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