Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

chydro_leapfrog.C

Go to the documentation of this file.
00001 //
00002 // chydro_leapfrog.C   [ as hydro_leapfrog, for now, just for testing chydro ]
00003 // 
00004 
00005 //    Here the core masses are simply added, as well as the core radii,
00006 //      and similarly for the total mass and effective radii.
00007 //    This should be replaced by more realistic recipees.
00008 
00009 #include "dyn.h"
00010 #include "chydro.h"
00011 
00012 #ifdef TOOLBOX
00013 
00014 void accumulate_acceleration(dyn& bj,           // target body reference
00015                              dyn& bi,           // body whose force is required
00016                              real eps_squared,  // softening length squared
00017                              dyn *& bm)         // if non-null, merger has
00018                                                 // happened between bi and bm
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;                // merger has happened, go back to merge
00027         }                              // and recalculate all accelerations
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;                // merger has happened, go back to merge
00038                 }                      // and recalculate all accelerations
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,           // n-body system pointer
00053                             real eps_squared,   // softening length squared
00054                             dyn *& bm1,        // if non-null, merger has
00055                             dyn *& bm2)        // happened between bm1 and 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;                             // points to potential merger
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,          // n-body system pointer
00078                   real dt)  // timestep
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,          // n-body system pointer
00092                   real dt)  // timestep
00093 {
00094 
00095     //full recursive implementation
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,          // n-body system pointer
00108                   real dt)  // timestep
00109 {
00110 
00111 // non full-recursive implementation
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 // detach_node_from_general_tree
00124 // delete node b. Do not check if the parent has more than 2 remaining
00125 // daughters or not.
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     // check if b is head without parent or sisters
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 // add_node
00160 // insert b into the tree as the oldest_daughter of the
00161 // parent. The ex-oldest node of the parent becomes the
00162 // younger sister of b.
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     // set the pointers of ex-oldest-daughter of parent
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,         // stellar radius proportional to mass
00190            dyn * bm2,         // i.e.  R_bm = R_bm1 + R_bm2
00191            real t)             // time
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,           // n-body system pointer
00225                              real eps_squared,   // softening length squared
00226                              real t)             // time
00227     {
00228     dyn * bm1;           // if non-null, merger has
00229     dyn * bm2;           // happened between bm1 and 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); //recalculate acc
00237         }
00238     }
00239 
00240 void step(real& t,        // time                         
00241           dyn* b,        // dyn array                   
00242           real dt,        // time step of the integration 
00243           real eps)       // softening length             
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,        // time                         
00255             dyn* b,         // dyn array                   
00256             real delta_t,   // time span of the integration 
00257             real dt,        // time step of the integration 
00258             real dt_out,    // output time interval
00259             real dt_snap,   // snapshot output interval
00260             real eps)       // softening length             
00261 {
00262     real t_end = t + delta_t;      // final time, at the end of the integration
00263     real t_out = t + dt_out;       // time of next diagnostic output
00264     real t_snap = t + dt_snap;     // time of next snapshot;
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 //      Check for (trivial) output to cerr.
00274 
00275         if (t >= t_out) {
00276             cerr << "Time = " << t << "  steps = " << steps << endl;
00277             t_out += dt_out;
00278         }
00279 
00280 //      Output a snapshot at the scheduled time or at the end of the run.
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;             // pointer to the nbody system
00294     real  t = 0;         // time
00295 
00296     real  delta_t = 1;   // time span of the integration
00297     real  dt = 0.02;     // time step of the integration
00298     real  dt_out;        // diagnostic output time interval
00299     real  dt_snap;       // snap output interval
00300     real  eps = 0.05;    // softening length               
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         // Check input arguments and echo defaults.
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

Generated at Sun Feb 24 09:56:55 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001