Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

sdyn_ev.C

Go to the documentation of this file.
00001 
00002 // sdyn_ev.C
00003 // member functions for the sdyn class that are related to orbit integration.
00004 //
00005 
00006 #include "sdyn.h"
00007 
00008 local int code_collision_flag(sdyn *bi, sdyn *bj) {
00009 
00010 #if 0
00011   if(bi==bj) {
00012     cerr << "bi==bj in code_collision_flag()" << endl;
00013     exit(-1);
00014   }
00015 
00016   //  cerr << "Collision occured between " << bi->get_index() 
00017   //       <<  " and " << bj->get_index() << endl;
00018   real r = abs(bi->get_pos() - bj->get_pos());
00019   //  PRC(r);PRC(bi->get_radius());PRC(bj->get_radius());
00020   //  cerr << "At time = " << bi->get_system_time() << endl;
00021 
00022   int imin = min(bi->get_index(), bj->get_index());
00023   int imax = max(bi->get_index(), bj->get_index());
00024   if(imin==imax) {
00025     cerr << "imin==imax in code_collision_flag()"<< endl;
00026     exit(-1);
00027   }
00028 
00029   int ci = -1;
00030   switch(imin) {
00031   case 1: if(imax==2)      ci = 1;
00032           else if(imax==3) ci = 2;
00033           else             ci = 3;
00034           break;
00035   case 2: if(imax==3)      ci = 4;
00036           else             ci = 5;
00037     break;
00038   case 3:                  ci = 6;
00039     break;
00040   default:  cerr << "No default value in code_collision_flag()" << endl;
00041     exit(-1);
00042   };
00043 
00044 #endif  
00045   int ci = 2;
00046   return ci;
00047 }
00048 
00049 
00050 local void pp(sdyn* b, ostream & s, int level = 0) {
00051 
00052     s.precision(4);
00053 
00054     for (int i = 0; i < 2*level; i++) s << " ";
00055 
00056     b->pretty_print_node(s);
00057     s << " \t"<< b->get_mass() << " \t"
00058       << b->get_pos() << "   "
00059       << b->get_vel() <<endl;
00060 
00061     for (sdyn * daughter = b->get_oldest_daughter();
00062          daughter != NULL;
00063          daughter = daughter->get_younger_sister())
00064         pp(daughter, s, level + 1);     
00065 }
00066 
00067 void sdyn::accumulate_new_acc_and_jerk_from_new(
00068                         sdyn * bj,                  // n-body system pointer
00069                         real eps2,                  // softening length squared
00070                         int no_diag_flag,    // if true, intermediate iteration
00071                         int & collision_flag)
00072     {
00073     if(bj->get_oldest_daughter() != NULL)
00074         for_all_daughters(sdyn, bj, bb)
00075             accumulate_new_acc_and_jerk_from_new(bb, eps2,
00076                                                  no_diag_flag, collision_flag);
00077     else
00078         if(this != bj)
00079             {
00080             vector d_pos = new_pos - bj->get_new_pos();
00081             vector d_vel = new_vel - bj->get_new_vel();
00082             real r2 = d_pos*d_pos;
00083             if (r2 < (radius + bj->get_radius()) 
00084                    * (radius + bj->get_radius())) {
00085                 collision_flag = code_collision_flag(this, bj);
00086                 //cerr << "Collision occured" << endl;
00087                 //PRC(sqrt(r2));PRC(radius);PRC(bj->get_radius());
00088                 //PRL(radius + bj->get_radius());
00089             }
00090 
00091             real r2inv = 1.0/(r2 + eps2);
00092             real a3 = -3.0*(d_pos*d_vel)*r2inv;
00093             real rinv = sqrt(r2inv);
00094             real mrinv = bj->get_mass() * rinv;
00095             new_pot -= mrinv;
00096             real mr3inv = mrinv * r2inv;
00097             new_acc -= mr3inv*d_pos;
00098             new_jerk -= mr3inv*(d_vel + a3*d_pos);
00099 
00100             if (! no_diag_flag)
00101                 {
00102                 if (nn_dr2 > r2)
00103                     {
00104                     nn_dr2 = r2;
00105                     nn_label = bj->get_index();
00106                     }
00107                 if (min_nn_dr2 > r2)
00108                     {
00109                     min_nn_dr2 = r2;
00110                     min_nn_label = bj->get_index();
00111                     }
00112                 }
00113 
00114             real encounter_time_squared = 1 / (r2inv * d_vel * d_vel);
00115             if (min_encounter_time_sq > encounter_time_squared)
00116                 min_encounter_time_sq = encounter_time_squared;
00117 
00118             real inverse_free_fall_time_squared = 
00119                 r2inv * rinv * (mass + bj->get_mass());
00120             if (min_free_fall_time_sq == VERY_LARGE_NUMBER ||
00121                 min_free_fall_time_sq * inverse_free_fall_time_squared > 1)
00122                 min_free_fall_time_sq = 1/inverse_free_fall_time_squared;
00123             }
00124     }
00125 
00126 void sdyn::calculate_new_acc_and_jerk_from_new(sdyn * b, real eps_squared,
00127                                                int  no_diag_flag,
00128                                                int  & collision_flag) {
00129 
00130     if(oldest_daughter != NULL)
00131         {
00132         collision_flag = 0;
00133 
00134         if (! no_diag_flag)
00135             {
00136             nn_label = 0;
00137             for_all_daughters(sdyn, this, c)
00138                 c->set_nn_dr2(VERY_LARGE_NUMBER);
00139             }
00140 
00141         for_all_daughters(sdyn, this, bb)
00142             bb->calculate_new_acc_and_jerk_from_new(b, eps_squared,
00143                                                     no_diag_flag,
00144                                                     collision_flag);
00145         if (! no_diag_flag)
00146             {
00147             for_all_daughters(sdyn, this, d)
00148                 {
00149                 if (d->get_init_nn_label() <= 0)
00150                     d->set_init_nn_label(d->get_nn_label());
00151                 if (d->get_init_nn_label() != d->get_nn_label())
00152                         d->set_nn_change_flag(1);
00153                 }
00154 
00155             real e_tot = 0;
00156             for_all_daughters(sdyn, this, bbb)
00157                 e_tot += 0.5 * bbb->get_mass() * (bbb->get_new_pot()
00158                                     + bbb->get_new_vel() * bbb->get_new_vel());
00159             if (de_tot_abs_max < abs(e_tot - e_tot_init))
00160                 de_tot_abs_max = abs(e_tot - e_tot_init);
00161             }
00162         }
00163     else
00164         {
00165         new_pot = 0;
00166         new_acc = new_jerk = 0;
00167         min_encounter_time_sq = min_free_fall_time_sq = VERY_LARGE_NUMBER;
00168         accumulate_new_acc_and_jerk_from_new(b, eps_squared, no_diag_flag,
00169                                              collision_flag);
00170         }
00171     }
00172 
00173 void  sdyn::taylor_pred_new_pos_and_vel(const real dt)
00174     {
00175     taylor_pred_new_pos(dt);
00176     taylor_pred_new_vel(dt);
00177     }
00178 
00179 void  sdyn::correct_new_acc_and_jerk(const real new_dt, const real prev_new_dt)
00180     {
00181     if (new_dt == prev_new_dt)
00182         return;
00183 
00184     real dt_off = new_dt - 0.5 * prev_new_dt;
00185                                     // offset from midpoint of prev_new_dt step
00186     real theta = 0.5 * prev_new_dt;
00187     real tau = dt_off / theta;          // equals 1 if new_dt = prev_new_dt
00188 
00189     real inv_theta = 1 / theta;
00190     real tau2 = tau * tau;
00191     real tau3 = tau2 * tau;
00192     vector prev_new_acc = new_acc;
00193     vector prev_new_jerk = new_jerk;
00194 
00195     new_acc = 0.25 * (
00196                       acc * (2 - 3 * tau + tau3)
00197                       + prev_new_acc * (2 + 3 * tau - tau3)
00198                       + jerk * theta * (1 - tau - tau2 + tau3)
00199                       + prev_new_jerk * theta * (-1 - tau + tau2 + tau3)
00200                       );
00201 
00202     new_jerk = 0.25 * (
00203                        acc * inv_theta * 3 * (-1 + tau2)
00204                        + prev_new_acc * inv_theta * 3 * (1 - tau2)
00205                        + jerk * (-1 - 2*tau + 3*tau2)
00206                        + prev_new_jerk * (-1 + 2*tau + 3*tau2)
00207                        );
00208     }
00209 
00210 void  sdyn::correct_new_pos_and_vel(const real new_dt)  // timestep
00211     {
00212     real new_dt2 = new_dt * new_dt;
00213     real new_dt3 = new_dt2 * new_dt;
00214 
00215     new_vel = vel + new_dt * (new_acc + acc)/2
00216                  - new_dt2 * (new_jerk - jerk)/12;
00217 
00218     new_pos = pos + new_dt * (new_vel + vel)/2 
00219                   - new_dt2 * (new_acc - acc)/12;          // alpha = -5/3
00220     }
00221 
00222 

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