00001 
00002 
00003 
00004 
00005 #include "dyn.h"
00006 #include "hydro.h"
00007 
00008 #ifdef TOOLBOX
00009 
00010 void accumulate_acceleration(dyn& bj,           
00011                              dyn& bi,           
00012                              real eps_squared,  
00013                              dyn *& bm)         
00014                                                 
00015 {
00016     bm = NULL;    
00017     if(bj.get_oldest_daughter() != NULL){
00018         for(dyn * bb = bj.get_oldest_daughter();bb != NULL;
00019             bb = bb->get_younger_sister()){
00020             accumulate_acceleration(*bb,bi,eps_squared, bm);
00021             if (bm != NULL)
00022                 return;                
00023         }                              
00024     }else{
00025         if(&bi != &bj){
00026             vector  d_pos = bi.get_pos() - bj.get_pos();
00027             real  d_pos_squared = d_pos * d_pos;
00028             real  sum_of_stellar_r_eff =
00029                     get_effective_radius(&bi) + get_effective_radius(&bj);
00030             if (sum_of_stellar_r_eff * sum_of_stellar_r_eff > d_pos_squared)
00031                 {
00032                 bm = &bj;
00033                 return;                
00034                 }                      
00035 
00036             real soft_d_pos_squared = d_pos_squared + eps_squared;
00037 
00038             real inverse_d_pos_cubed =
00039             1 / ( soft_d_pos_squared * sqrt( soft_d_pos_squared ));      
00040 
00041             bi.inc_acc(-inverse_d_pos_cubed * bj.get_mass() * d_pos);
00042         }
00043     }
00044 }
00045 
00046 
00047 void calculate_acceleration(dyn & bj,
00048                             dyn & b,           
00049                             real eps_squared,   
00050                             dyn *& bm1,        
00051                             dyn *& bm2)        
00052 {
00053     bm1 = bm2 = NULL;
00054     if(b.get_oldest_daughter() != NULL){
00055         for(dyn * bb = b.get_oldest_daughter();bb != NULL;
00056             bb = bb->get_younger_sister()){
00057             calculate_acceleration(bj,*bb,eps_squared, bm1, bm2);
00058             if (bm1 != NULL)
00059                 return;
00060         }
00061     }else{
00062         b.clear_acc();
00063         dyn * bm;                             
00064         accumulate_acceleration(bj,b,eps_squared, bm);
00065         if (bm != NULL)
00066             {
00067             bm1 = &b;
00068             bm2 = bm;
00069             }
00070     }
00071 }
00072 
00073 void predict_step(   dyn &b,          
00074                   real dt)  
00075 {
00076     if(b.get_oldest_daughter() !=NULL){
00077         for(dyn * bb = b.get_oldest_daughter();bb != NULL;
00078             bb = bb->get_younger_sister()){
00079             predict_step(*bb,dt);
00080         }
00081     }else{
00082         b.inc_vel( 0.5 * dt * b.get_acc() );
00083         b.inc_pos( dt * b.get_vel() );
00084     }
00085 }
00086 
00087 void old_correct_step(   dyn &b,          
00088                   real dt)  
00089 {
00090 
00091     
00092     
00093     if(b.get_oldest_daughter() != NULL){
00094         old_correct_step(*b.get_oldest_daughter(),dt);
00095     }else{
00096         b.inc_vel( 0.5 * dt * b.get_acc() );
00097     }
00098     if(b.get_younger_sister() != NULL){
00099         old_correct_step(*b.get_younger_sister(),dt);
00100     }
00101 }
00102 
00103 void correct_step(   dyn &b,          
00104                   real dt)  
00105 {
00106 
00107 
00108     
00109     if(b.get_oldest_daughter() !=NULL){
00110         for(dyn * bb = b.get_oldest_daughter();bb != NULL;
00111             bb = bb->get_younger_sister()){
00112             correct_step(*bb,dt);
00113         }
00114     }else{
00115         b.inc_vel( 0.5 * dt * b.get_acc() );
00116     }
00117 }
00118 
00119 
00120 
00121 
00122 
00123 void delete_node_from_general_tree(dyn & b)
00124 {
00125     if(&b == NULL){
00126         cerr << "Warning: delete_node_from_general_tree, b is null\n";
00127         return;
00128     }
00129 
00130     dyn *  parent = b.get_parent();
00131     
00132     
00133     if(parent == NULL){
00134         cerr << "Warning: delete_node_from_general_tree, b has no parent\n";
00135         return;
00136     }
00137 
00138     b.set_parent(NULL);
00139 
00140     dyn *  elder_sister = b.get_elder_sister();
00141     dyn *  younger_sister = b.get_younger_sister();
00142 
00143     if (parent->get_oldest_daughter() == &b){
00144         parent->set_oldest_daughter(younger_sister);
00145     }
00146 
00147     if(elder_sister != NULL){
00148         elder_sister->set_younger_sister(younger_sister);
00149     }
00150     if(younger_sister != NULL){
00151         younger_sister->set_elder_sister(elder_sister);
00152     }
00153 }
00154 
00155 
00156 
00157 
00158 
00159 
00160 void add_node(dyn &b, dyn & parent)
00161 {
00162     if(&b == NULL){
00163         cerr << "Warning:add_node, b is null\n";
00164         return;
00165     }
00166 
00167     if(&parent == NULL){
00168         cerr << "Warning:add_node, parent is null\n";
00169         return;
00170     }
00171 
00172     
00173     dyn *  ex = parent.get_oldest_daughter();
00174     if(ex != NULL){
00175         ex->set_elder_sister(&b);
00176     }
00177 
00178     parent.set_oldest_daughter(&b);
00179 
00180     b.set_elder_sister(NULL);
00181     b.set_younger_sister(ex);
00182     b.set_parent(&parent);
00183 }
00184 
00185 void merge(dyn * bm1,         
00186            dyn * bm2,         
00187            real t)            
00188     {
00189     dyn * bm = new dyn();
00190 
00191 cerr << "entering merge(" << bm1->get_index() << ", " << bm2->get_index()
00192      << ") with r1 = " << bm1->get_pos() << "\n                     "
00193      << " and r2 = " << bm2->get_pos()   << "\n                     "
00194      << "   at t = " << t << endl;
00195 
00196     real  m1 = bm1->get_mass();
00197     real  m2 = bm2->get_mass();
00198     real  m_tot = m1 + m2;
00199     
00200     bm->set_mass(m_tot);
00201     bm->set_pos((m1*bm1->get_pos() + m2*bm2->get_pos())/m_tot);
00202     bm->set_vel((m1*bm1->get_vel() + m2*bm2->get_vel())/m_tot);
00203 
00204     real  new_r_eff = get_effective_radius(bm1) + get_effective_radius(bm2);
00205     
00206     addhydro(bm, new_r_eff);
00207     
00208     dyn * root = bm1->get_parent(); 
00209 
00210     delete_node_from_general_tree(*bm1);
00211     delete_node_from_general_tree(*bm2);
00212   
00213     add_node(*bm, *root);
00214     }
00215 
00216 void calculate_acc_and_merge(dyn & bj,
00217                              dyn & b,           
00218                              real eps_squared,   
00219                              real t)             
00220     {
00221     dyn * bm1;           
00222     dyn * bm2;           
00223 
00224     calculate_acceleration(bj, b, eps_squared, bm1, bm2);
00225 
00226     while (bm1 != NULL)
00227         {
00228         merge(bm1, bm2, t);
00229         calculate_acceleration(bj, b, eps_squared, bm1, bm2); 
00230         }
00231     }
00232 
00233 void step(real& t,        
00234           dyn* b,        
00235           real dt,        
00236           real eps)       
00237 {
00238     t += dt;
00239     
00240     predict_step(*b,dt);
00241     calculate_acc_and_merge(*b,*b, eps*eps, t);
00242     correct_step(*b,dt);
00243 }
00244 
00245 void evolve(real& t,        
00246             dyn* b,         
00247             real delta_t,   
00248             real dt,        
00249             real dt_out,    
00250             real dt_snap,   
00251             real eps)       
00252 {
00253     real t_end = t + delta_t;      
00254     real t_out = t + dt_out;       
00255     real t_snap = t + dt_snap;     
00256     int  steps = 0;
00257  
00258     calculate_acc_and_merge(*b, *b, eps*eps, t);
00259     
00260     while (t < t_end){
00261         step(t, b, dt, eps);
00262         steps++;
00263 
00264 
00265 
00266         if (t >= t_out) {
00267             cerr << "Time = " << t << "  steps = " << steps << endl;
00268             t_out += dt_out;
00269         }
00270 
00271 
00272 
00273         if (t >= t_snap || t >= t_end) {
00274             cerr<<"time = "<<t<<endl;
00275             put_node(cout, *b);
00276             cout << flush;
00277             t_snap += dt_snap;
00278         }
00279     }
00280 }
00281 
00282 main(int argc, char **argv)
00283 {
00284     dyn*  b;             
00285     real  t = 0;         
00286 
00287     real  delta_t = 1;   
00288     real  dt = 0.02;     
00289     real  dt_out;        
00290     real  dt_snap;       
00291     real  eps = 0.05;    
00292     char  *comment;
00293 
00294     extern char *poptarg;
00295     int  pgetopt(int, char **, char *), c;
00296 
00297     bool  a_flag = FALSE;
00298     bool  c_flag = FALSE;
00299     bool  d_flag = FALSE;
00300     bool  D_flag = FALSE;
00301     bool  e_flag = FALSE;
00302     bool  q_flag = FALSE;
00303     bool  t_flag = FALSE;
00304     
00305     while ((c = pgetopt(argc, argv, "a:c:d:D:e:qt:")) != -1)
00306         switch(c)
00307             {
00308             case 'a': a_flag = TRUE;
00309                       dt = atof(poptarg);
00310                       break;
00311             case 'c': c_flag = TRUE;
00312                       comment = poptarg;
00313                       break;
00314             case 'd': d_flag = TRUE;
00315                       dt_out = atof(poptarg);
00316                       break;
00317             case 'D': D_flag = TRUE;
00318                       dt_snap = atof(poptarg);
00319                       break;
00320             case 'e': e_flag = TRUE;
00321                       eps = atof(poptarg);
00322                       break;
00323             case 'q': q_flag = TRUE;
00324                       break;
00325             case 't': t_flag = TRUE;
00326                       delta_t = atof(poptarg);
00327                       break;
00328             case '?': cerr <<
00329                       "usage: hydro_leapfrog -t # -a # -e # -D # -d # " <<
00330                       "[-c \"..\"]\n" <<
00331                       "for t (time span), a (time step length), " <<
00332                       "d (output interval) D (snapshot output interval) " <<
00333                       "and e (softening length)\n";
00334                       exit(1);
00335             }            
00336 
00337     if (!q_flag) {
00338 
00339         
00340 
00341         if (!t_flag) cerr << "default delta_t = " << delta_t << "\n";
00342         if (!a_flag) cerr << "default dt = " << dt << "\n";
00343         if (!d_flag) cerr << "default dt_out = " << dt_out << "\n";
00344         if (!e_flag) cerr << "default eps = " << eps << "\n";
00345     }
00346 
00347     if (!D_flag) dt_snap = delta_t;
00348 
00349     b = get_dyn(cin, new_hydro);
00350     
00351     if (c_flag == TRUE) b->log_comment(comment);
00352     b->log_history(argc, argv);
00353 
00354     evolve(t, b, delta_t, dt, dt_out, dt_snap, eps);
00355 }
00356 
00357 #endif