Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

hydro_leapfrog.C

Go to the documentation of this file.
00001 //
00002 // hydro_leapfrog.C
00003 // 
00004 
00005 #include "dyn.h"
00006 #include "hydro.h"
00007 
00008 #ifdef TOOLBOX
00009 
00010 void accumulate_acceleration(dyn& bj,           // target body reference
00011                              dyn& bi,           // body whose force is required
00012                              real eps_squared,  // softening length squared
00013                              dyn *& bm)         // if non-null, merger has
00014                                                 // happened between bi and bm
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;                // merger has happened, go back to merge
00023         }                              // and recalculate all accelerations
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;                // merger has happened, go back to merge
00034                 }                      // and recalculate all accelerations
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,           // n-body system pointer
00049                             real eps_squared,   // softening length squared
00050                             dyn *& bm1,        // if non-null, merger has
00051                             dyn *& bm2)        // happened between bm1 and 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;                             // points to potential merger
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,          // n-body system pointer
00074                   real dt)  // timestep
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,          // n-body system pointer
00088                   real dt)  // timestep
00089 {
00090 
00091     //full recursive implementation
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,          // n-body system pointer
00104                   real dt)  // timestep
00105 {
00106 
00107 // non full-recursive implementation
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 // delete_node_from_general_tree
00120 // delete node b. Do not check if the parent has more than 2 remaining
00121 // daughters or not.
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     // check if b is head without parent or sisters
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 // add_node
00156 // insert b into the tree as the oldest_daughter of the
00157 // parent. The ex-oldest node of the parent becomes the
00158 // younger sister of b.
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     // set the pointers of ex-oldest-daughter of parent
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,         // stellar radius proportional to mass
00186            dyn * bm2,         // i.e.  R_bm = R_bm1 + R_bm2
00187            real t)            // time
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,           // n-body system pointer
00218                              real eps_squared,   // softening length squared
00219                              real t)             // time
00220     {
00221     dyn * bm1;           // if non-null, merger has
00222     dyn * bm2;           // happened between bm1 and 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); //recalculate acc
00230         }
00231     }
00232 
00233 void step(real& t,        // time                         
00234           dyn* b,        // dyn array                   
00235           real dt,        // time step of the integration 
00236           real eps)       // softening length             
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,        // time                         
00246             dyn* b,         // dyn array                   
00247             real delta_t,   // time span of the integration 
00248             real dt,        // time step of the integration 
00249             real dt_out,    // output time interval
00250             real dt_snap,   // snapshot output interval
00251             real eps)       // softening length             
00252 {
00253     real t_end = t + delta_t;      // final time, at the end of the integration
00254     real t_out = t + dt_out;       // time of next diagnostic output
00255     real t_snap = t + dt_snap;     // time of next snapshot;
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 //      Check for (trivial) output to cerr.
00265 
00266         if (t >= t_out) {
00267             cerr << "Time = " << t << "  steps = " << steps << endl;
00268             t_out += dt_out;
00269         }
00270 
00271 //      Output a snapshot at the scheduled time or at the end of the run.
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;             // pointer to the nbody system
00285     real  t = 0;         // time
00286 
00287     real  delta_t = 1;   // time span of the integration
00288     real  dt = 0.02;     // time step of the integration
00289     real  dt_out;        // diagnostic output time interval
00290     real  dt_snap;       // snap output interval
00291     real  eps = 0.05;    // softening length               
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         // Check input arguments and echo defaults.
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

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