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