00001
00019
00020
00021
00022
00023
00024
00025 #include "sdyn3.h"
00026
00027 #ifndef TOOLBOX
00028
00029 #define UNPERTURBED_DIAG false
00030 #define PRECISION 12
00031
00032 local void restore_pos_and_vel(kepler& inner, kepler& outer, real time,
00033 int n_transform,
00034 sdyn3* b1, sdyn3* b2, sdyn3* b3,
00035 vector& cmpos, vector& cmvel)
00036 {
00037 inner.transform_to_time(time);
00038 if (n_transform == 2) outer.transform_to_time(time);
00039
00040
00041
00042
00043
00044 kepler_pair_to_triple(inner, outer, b1, b2, b3);
00045
00046 for_all_daughters(sdyn3, b1->get_parent(), bb) {
00047 bb->inc_pos(cmpos);
00048 bb->inc_vel(cmvel);
00049 bb->store_old_into_new();
00050 }
00051 }
00052
00053 local real total_energy(sdyn3* b)
00054 {
00055 real k = 0, u = 0, dissipation = 0;
00056
00057 for_all_daughters(sdyn3, b, bi) {
00058 k += bi->get_mass() * bi->get_vel() * bi->get_vel();
00059 dissipation += bi->get_energy_dissipation();
00060 for (sdyn3 * bj = bi->get_younger_sister(); bj != NULL;
00061 bj = bj->get_younger_sister())
00062 u -= bi->get_mass() * bj->get_mass()
00063 / abs(bi->get_pos() - bj->get_pos());
00064 }
00065
00066 return 0.5*k + u + dissipation;
00067 }
00068
00069 static int save_flag = 1;
00070 static real last_error = 0, last_test3 = 0;
00071
00072 local void print_unperturbed_diag(sdyn3* b, sdyn3* b1, sdyn3* b2, sdyn3* b3,
00073 kepler& inner, kepler& outer,
00074 char* header)
00075 {
00076 if (UNPERTURBED_DIAG) {
00077
00078 int p = cerr.precision(PRECISION);
00079
00080 if (header) cerr << header << endl;
00081
00082 cerr << " inner binary:"
00083 << " time = "
00084 << inner.get_time() + (real)b->get_time_offset()
00085 << " t_peri = " << inner.get_time_of_periastron_passage()
00086 + (real)b->get_time_offset() << endl
00087 << " r = " << inner.get_separation()
00088 << " a = " << inner.get_semi_major_axis()
00089 << " e = " << inner.get_eccentricity() << endl
00090 << " mass = " << inner.get_total_mass() << endl
00091 << " pos = " << inner.get_rel_pos() << endl
00092 << " vel = " << inner.get_rel_vel() << endl
00093 << " th = " << inner.get_true_anomaly() << endl
00094 << " l = " << inner.get_longitudinal_unit_vector() << endl
00095 << " n = " << inner.get_normal_unit_vector() << endl;
00096
00097 cerr << " energy test 1: " << inner.get_energy()
00098 << " ?= " << 0.5 * square(b1->get_vel() - b2->get_vel())
00099 - (b1->get_mass() + b2->get_mass())
00100 / abs(b1->get_pos() - b2->get_pos()) << endl;
00101
00102 cerr << " outer binary:"
00103 << " R = " << outer.get_separation()
00104 << " a = " << outer.get_semi_major_axis()
00105 << " e = " << outer.get_eccentricity() << endl
00106 << " mass = " << outer.get_total_mass() << endl
00107 << " pos = " << outer.get_rel_pos() << endl
00108 << " vel = " << outer.get_rel_vel() << endl
00109 << " th = " << outer.get_true_anomaly() << endl
00110 << " l = " << outer.get_longitudinal_unit_vector() << endl
00111 << " n = " << outer.get_normal_unit_vector() << endl;
00112
00113 vector bcm_pos = (b1->get_mass() * b1->get_pos()
00114 + b2->get_mass() * b2->get_pos())
00115 / (b1->get_mass() + b2->get_mass());
00116 vector bcm_vel = (b1->get_mass() * b1->get_vel()
00117 + b2->get_mass() * b2->get_vel())
00118 / (b1->get_mass() + b2->get_mass());
00119
00120 cerr << " energy test 2: " << outer.get_energy()
00121 << " ?= " << 0.5 * square(b3->get_vel() - bcm_vel)
00122 - (b1->get_mass() + b2->get_mass() + b3->get_mass())
00123 / abs(b3->get_pos() - bcm_pos) << endl;
00124
00125 real r = inner.get_separation();
00126 real R = outer.get_separation();
00127 cerr << " check r: " << r << " ?= "
00128 << abs(b2->get_pos() - b1->get_pos()) << endl;
00129 cerr << " check R: " << R << " ?= "
00130 << abs(b3->get_pos() - bcm_pos) << endl;
00131
00132
00133
00134
00135 real m1 = b1->get_mass();
00136 real m2 = b2->get_mass();
00137 real m3 = b3->get_mass();
00138 real test3 = - m1*m3 / abs(b3->get_pos() - b1->get_pos())
00139 - m2*m3 / abs(b3->get_pos() - b2->get_pos())
00140 + (m1+m2)*m3 / outer.get_separation();
00141
00142 real coeff = (m1*m2/(m1+m2)) * (0.5*m3/pow(R,3));
00143 real term1 = coeff * r*r;
00144 real term2 = coeff * (-3) * pow(inner.get_rel_pos()
00145 * outer.get_rel_pos() / R, 2);
00146
00147 cerr << " energy test 3: " << test3
00148 << " =? " << term1 + term2 << endl;
00149
00150 real error = total_energy(b) - b->get_e_tot_init();
00151 cerr << " energy error = " << error << endl;
00152
00153 if (save_flag) {
00154 last_test3 = test3;
00155 last_error = error;
00156 } else {
00157 cerr << " delta(test3) = "
00158 << test3 - last_test3 << endl;
00159 cerr << " delta(error) = "
00160 << error - last_error << endl;
00161 }
00162
00163 save_flag = 1 - save_flag;
00164 cerr.precision(p);
00165
00166 cerr << flush;
00167 }
00168 }
00169
00170 local void print_perturbed_error(kepler& inner, kepler& outer,
00171 sdyn3* b1, real dt)
00172 {
00173
00174
00175
00176 cerr << " inner, outer time = " << inner.get_time()
00177 << " " << outer.get_time() << endl;
00178
00179
00180
00181
00182 outer.transform_to_time(outer.get_time() - 0.5*dt);
00183
00184 real M = outer.get_total_mass() - inner.get_total_mass();
00185 real R = abs(outer.get_separation());
00186 real X = outer.get_rel_pos() * inner.get_longitudinal_unit_vector();
00187 real Y = outer.get_rel_pos() * inner.get_transverse_unit_vector();
00188 real Z = outer.get_rel_pos() * inner.get_normal_unit_vector();
00189
00190
00191
00192 real E = inner.get_energy();
00193 real e = inner.get_eccentricity();
00194
00195 if (E >= 0 || e <= 0 || e >= 1) return;
00196
00197 real a = inner.get_semi_major_axis();
00198 real h = inner.get_angular_momentum();
00199 real r = inner.get_separation();
00200 real th = inner.get_true_anomaly();
00201
00202 real rp = a * (1 - e);
00203 real ra = a * (1 + e);
00204
00205
00206
00207 real red_mass = b1->get_mass()
00208 * (1 - b1->get_mass()/inner.get_total_mass());
00209 real coeff = 6*red_mass*M*X*Y/pow(R,5);
00210
00211
00212
00213 real mu = cos(th);
00214 real I1 = a*a*pow(1-e*e,2) *
00215 (-sin(th) * (2 - e*e + mu*e*(3-2*e*e))
00216 / (e*(1-e*e)*pow(1+mu*e,2))
00217 + (asin((mu+e)/(1+mu*e))-M_PI/2)
00218 * (2-3*e*e) / (e*e*pow(1-e*e,1.5))
00219 + 2*th / (e*e));
00220
00221 real f1 = pow(a*e,2) - pow(a-r,2);
00222 real f2 = atan((r-a*(1-e*e))/sqrt((1-e*e)*f1)) - M_PI/2;
00223 real f3 = asin((a-r)/(a*e)) - M_PI/2;
00224 real I2 = (h/(e*e*sqrt(2*abs(E)))) *
00225 ((e*e-2)*sqrt(f1) + 2*a*pow(1-e*e,1.5)*f2 - a*f3*(2-3*e*e));
00226
00227 cerr << " predicted potential change = "
00228 << coeff * r*r * cos(th) * sin(th)
00229 << endl;
00230 cerr << " predicted error = " << coeff * (I1 + I2) << "\n";
00231 cerr << " terms: I1, I2 = " << I1 << " " << I2 << endl;
00232
00233
00234
00235 real j0 = asin((a-r)/(a*e)) - M_PI/2;
00236 real term1 = 1.5*a*a*e*e * j0;
00237 real term2 = (a*(0.5+e*e)+0.5*r) * sqrt(a*a*e*e-(a-r)*(a-r));
00238 real I = (term1 + term2) / (e*sqrt(2*abs(E)));
00239 real coeffdv = -2*M/pow(R,5) * I;
00240
00241 vector dv = coeffdv * (-(R*R - 3*X*X) * inner.get_longitudinal_unit_vector()
00242 - 3*X*Y * inner.get_transverse_unit_vector()
00243 - 3*X*Z * inner.get_normal_unit_vector());
00244
00245
00246
00247
00248 cerr << " predicted dv = " << dv << endl;
00249 cerr << " associated dE = " << red_mass*dv*inner.get_rel_vel() << endl;
00250 cerr << " terms: " << term1 << " " << term2 << endl;
00251 }
00252
00253 static real tol_23 = -1;
00254
00255 local bool unperturbed_step(sdyn3* b,
00256 real tidal_tolerance,
00257 real& true_dt,
00258 int& collision_flag)
00259 {
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 if (tidal_tolerance <= 0) return FALSE;
00277
00278 sdyn3* bi = b->get_oldest_daughter();
00279 sdyn3* bj = bi->get_younger_sister();
00280 sdyn3* bk = bj->get_younger_sister();
00281
00282 real min_sep_sq = min(min(bi->get_nn_dr2(), bj->get_nn_dr2()),
00283 bk->get_nn_dr2());
00284 real max_sep_sq = max(max(bi->get_nn_dr2(), bj->get_nn_dr2()),
00285 bk->get_nn_dr2());
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 if (tol_23 < 0) {
00296 real total_mass = bi->get_mass() + bj->get_mass() + bk->get_mass();
00297 real max_mass = max(max(bi->get_mass(), bj->get_mass()),
00298 bk->get_mass());
00299 tol_23 = pow((1 - max_mass/total_mass) * tidal_tolerance, 0.6666667);
00300 }
00301
00302 if (min_sep_sq > max_sep_sq * tol_23) return FALSE;
00303
00304
00305
00306
00307
00308
00309
00310 sdyn3 *b1, *b2, *b3;
00311
00312
00313
00314 if (min_sep_sq == bi->get_nn_dr2())
00315 b1 = bi;
00316 else if (min_sep_sq == bj->get_nn_dr2())
00317 b1 = bj;
00318 else
00319 b1 = bk;
00320
00321
00322
00323 b2 = (sdyn3*)b1->get_nn();
00324 if (!b2) return FALSE;
00325
00326
00327
00328 if (bi != b1 && bi != b2)
00329 b3 = bi;
00330 else if (bj != b1 && bj != b2)
00331 b3 = bj;
00332 else
00333 b3 = bk;
00334
00335
00336
00337 vector r = b2->get_pos() - b1->get_pos();
00338
00339 if (r * (b2->get_vel() - b1->get_vel()) >= 0) return FALSE;
00340
00341
00342
00343
00344 real m12 = b1->get_mass() + b2->get_mass();
00345 real m123 = m12 + b3->get_mass();
00346
00347
00348
00349 vector binary_cmpos = (b1->get_mass() * b1->get_pos()
00350 + b2->get_mass() * b2->get_pos()) / m12;
00351
00352 vector R = b3->get_pos() - binary_cmpos;
00353
00354 real true_tol_23 = pow((m12/m123) * tidal_tolerance, 0.6666667);
00355 if (square(r) > square(R) * true_tol_23) return FALSE;
00356
00357
00358
00359
00360
00361 vector system_cmpos = (m12 * binary_cmpos
00362 + b3->get_mass() * b3->get_pos()) / m123;
00363
00364
00365
00366 vector binary_cmvel = (b1->get_mass() * b1->get_vel()
00367 + b2->get_mass() * b2->get_vel()) / m12;
00368
00369 vector system_cmvel = (m12 * binary_cmvel
00370 + b3->get_mass() * b3->get_vel()) / m123;
00371
00372
00373
00374 kepler inner, outer;
00375
00376
00377
00378 set_kepler_from_sdyn3(inner, b1, b2);
00379
00380
00381
00382 outer.set_time(b3->get_time());
00383 outer.set_total_mass(m123);
00384 outer.set_rel_pos(R);
00385 outer.set_rel_vel(b3->get_vel() - binary_cmvel);
00386
00387 outer.initialize_from_pos_and_vel();
00388
00389 real t_init = inner.get_time();
00390 real t_peri = inner.get_time_of_periastron_passage();
00391
00392
00393
00394
00395 real peri_sq = inner.get_periastron() * inner.get_periastron();
00396 b1->set_nn_dr2(min(b1->get_nn_dr2(), peri_sq));
00397 b2->set_nn_dr2(min(b2->get_nn_dr2(), peri_sq));
00398 b1->set_min_nn_dr2(min(b1->get_min_nn_dr2(), peri_sq));
00399 b2->set_min_nn_dr2(min(b2->get_min_nn_dr2(), peri_sq));
00400
00401 print_unperturbed_diag(b, b1, b2, b3,
00402 inner, outer,
00403 "Beginning unperturbed motion");
00404
00405
00406
00407 if (inner.get_periastron() <= b1->get_radius() + b2->get_radius()) {
00408
00409
00410
00411 restore_pos_and_vel(inner, outer, t_peri, 2,
00412 b1, b2, b3,
00413 system_cmpos, system_cmvel);
00414 collision_flag = 1;
00415 true_dt = t_peri - t_init;
00416
00417 return TRUE;
00418 }
00419
00420 real dt = 2*(t_peri - t_init);
00421
00422
00423
00424
00425 outer.transform_to_time(t_init + dt);
00426
00427 real sep = outer.get_separation();
00428 if (square(r) > sep * sep * true_tol_23) {
00429
00430
00431
00432 if (UNPERTURBED_DIAG)
00433 cerr <<
00434 "unperturbed_step: failed unperturbed test after unperturbed step!\n";
00435
00436 restore_pos_and_vel(inner, outer, t_init, 2, b1, b2, b3,
00437 system_cmpos, system_cmvel);
00438
00439 save_flag = 1;
00440 return FALSE;
00441 }
00442
00443 if (UNPERTURBED_DIAG) print_perturbed_error(inner, outer, b1, dt);
00444
00445
00446
00447
00448 restore_pos_and_vel(inner, outer, t_init + dt, 1, b1, b2, b3,
00449 system_cmpos, system_cmvel);
00450 true_dt = dt;
00451
00452 print_unperturbed_diag(b, b1, b2, b3,
00453 inner, outer,
00454 "Ending unperturbed motion");
00455
00456
00457
00458 return TRUE;
00459 }
00460
00461 local void predict(sdyn3* b,
00462 real dt)
00463 {
00464
00465
00466 if(b->get_oldest_daughter() !=NULL)
00467 for_all_daughters(sdyn3, b, bb)
00468 predict(bb, dt);
00469 else
00470 b->taylor_pred_new_pos_and_vel(dt);
00471 }
00472
00473 local void correct(sdyn3* b,
00474 real new_dt,
00475 real prev_new_dt)
00476 {
00477
00478
00479 if(b->get_oldest_daughter() !=NULL)
00480 for_all_daughters(sdyn3, b, bb)
00481 correct(bb, new_dt, prev_new_dt);
00482 else {
00483 b->correct_new_acc_and_jerk(new_dt, prev_new_dt);
00484 b->correct_new_pos_and_vel(new_dt);
00485 }
00486 }
00487
00488 local void calculate_energy(sdyn3* b, real& ekin, real& epot)
00489 {
00490 ekin = epot = 0;
00491 for_all_daughters(sdyn3, b, bb) {
00492 epot += bb->get_mass() * bb->get_pot();
00493 ekin += 0.5 * bb->get_mass() * (bb->get_vel() * bb->get_vel());
00494 }
00495 epot *= 0.5;
00496 }
00497
00498 typedef real (*tfp)(sdyn3*, real);
00499
00500 local bool step(sdyn3* b,
00501 real& t,
00502 real eps,
00503 real eta,
00504 real dt,
00505 real max_dt,
00506 int& end_flag,
00507 tfp the_tfp,
00508 int n_iter,
00509 int x_flag,
00510 int s_flag)
00511 {
00512
00513
00514
00515 bool unpert_flag = FALSE;
00516
00517 real true_dt = dt;
00518 int collision_flag = 0;
00519
00520 if (eps > 0 ||
00521 !(unpert_flag = unperturbed_step(b, DEFAULT_TIDAL_TOL_FACTOR,
00522 true_dt, collision_flag))) {
00523
00524
00525
00526 predict(b, dt);
00527
00528 real new_dt = dt;
00529 for (int i = 0; i <= n_iter; i++) {
00530
00531
00532
00533 b->calculate_new_acc_and_jerk_from_new(b, eps*eps,
00534 n_iter - i,
00535 collision_flag);
00536
00537 real prev_new_dt = new_dt;
00538 if (s_flag && i < n_iter) {
00539
00540
00541
00542 real end_point_dt = the_tfp(b, eta);
00543
00544
00545
00546 new_dt = 0.5 * (dt + end_point_dt);
00547 new_dt = dt + 0.5 * (end_point_dt - dt) * (new_dt/prev_new_dt);
00548
00549
00550
00551 if (x_flag) {
00552 if (new_dt >= max_dt) {
00553 end_flag = 1;
00554 new_dt = max_dt;
00555 } else
00556 end_flag = 0;
00557 }
00558 }
00559
00560
00561
00562 correct(b, new_dt, prev_new_dt);
00563 }
00564
00565 true_dt = new_dt;
00566
00567 } else
00568
00569 if (!collision_flag)
00570 b->calculate_new_acc_and_jerk_from_new(b, eps*eps,
00571 0, collision_flag);
00572
00573
00574
00575 for_all_daughters(sdyn3, b, bb) bb->store_new_into_old();
00576 t += true_dt;
00577
00578 if (collision_flag) end_flag = 1;
00579
00580 return unpert_flag;
00581 }
00582
00583 local void initialize(sdyn3* b,
00584 real eps)
00585 {
00586 predict(b, 0);
00587
00588 int collision_flag;
00589 b->calculate_new_acc_and_jerk_from_new(b, eps*eps, 1, collision_flag);
00590
00591 for_all_daughters(sdyn3, b, bb)
00592 bb->store_new_into_old();
00593 }
00594
00595
00596
00597
00598 real constant_timestep(sdyn3* b, real eta)
00599 {
00600 if (b == NULL) eta = 0;
00601 return eta;
00602 }
00603
00604 real dynamic_timestep(sdyn3* b, real eta)
00605 {
00606 real global_min_encounter_time_sq = VERY_LARGE_NUMBER;
00607 real global_min_free_fall_time_sq = VERY_LARGE_NUMBER;
00608
00609 for_all_daughters(sdyn3, b, bb) {
00610 global_min_encounter_time_sq =
00611 min(global_min_encounter_time_sq, bb->get_min_encounter_time_sq());
00612 global_min_free_fall_time_sq =
00613 min(global_min_free_fall_time_sq, bb->get_min_free_fall_time_sq());
00614 }
00615
00616 return eta *
00617 sqrt(min(global_min_encounter_time_sq, global_min_free_fall_time_sq));
00618 }
00619
00620 local tfp get_timestep_function_ptr(char* timestep_name)
00621 {
00622 if (streq(timestep_name, "constant_timestep"))
00623 return constant_timestep;
00624 else if (streq(timestep_name, "dynamic_timestep"))
00625 return dynamic_timestep;
00626 else {
00627 cerr << "get_timestep_function_ptr: no timestep function implemented"
00628 << " with name `" << timestep_name << "'" << endl;
00629 exit(1);
00630 }
00631 return (tfp)NULL;
00632 }
00633
00634 local void start_up(sdyn3* b, real& n_steps)
00635 {
00636 if (b->get_oldest_daughter() !=NULL) {
00637
00638 if ((n_steps = b->get_n_steps()) == 0)
00639 b->prepare_root();
00640
00641 for_all_daughters(sdyn3, b, bb)
00642 start_up(bb, n_steps);
00643
00644 } else
00645 if (n_steps == 0) b->prepare_branch();
00646 }
00647
00648 local void clean_up(sdyn3 * b, real n)
00649 {
00650 b->set_n_steps(n);
00651 }
00652
00653 int system_in_cube(sdyn3* b, real cube_size)
00654 {
00655 for_all_daughters(sdyn3, b, bb)
00656 for (int k = 0; k < 3; k++)
00657 if (abs(bb->get_pos()[k]) > cube_size) return 0;
00658 return 1;
00659 }
00660
00661 #define N_STEP_CHECK 1000 // Interval for checking CPU time
00662
00663 #define PERT_OUTPUT 2
00664 real last_unpert = -VERY_LARGE_NUMBER;
00665
00666 void low_n3_evolve(sdyn3* b,
00667 real delta_t,
00668 real dt_out,
00669 real dt_snap,
00670 real snap_cube_size,
00671 real eps,
00672 real eta,
00673 int x_flag,
00674 char* timestep_name,
00675 int s_flag,
00676 int n_iter,
00677 real n_max,
00678 real cpu_time_check,
00679 real dt_print,
00680 sdyn3_print_fp
00681 print)
00682 {
00683 real t = b->get_time();
00684
00685 real t_end = t + delta_t;
00686 real t_out = t + dt_out;
00687 real t_snap = t + dt_snap;
00688 real t_print = t + dt_print;
00689
00690 bool unpert;
00691
00692 real n_steps;
00693 int count_steps = 0;
00694 real cpu_init = cpu_time();
00695 real cpu_save = cpu_init;
00696
00697 tfp the_tfp = get_timestep_function_ptr(timestep_name);
00698
00699 start_up(b, n_steps);
00700 initialize(b, eps);
00701
00702 int p = cerr.precision(PRECISION);
00703
00704 real ekin, epot;
00705 calculate_energy(b, ekin, epot);
00706
00707 if (t_out <= t_end && n_steps == 0) {
00708 cerr << "Time = " << t + (real)b->get_time_offset()
00709 << " n_steps = " << n_steps
00710 << " Etot = " << ekin + epot << endl;
00711 }
00712
00713 if (b->get_n_steps() == 0) {
00714
00715 b->set_e_tot_init(ekin + epot);
00716 b->clear_de_tot_abs_max();
00717 }
00718
00719 int end_flag = 0;
00720 while (t < t_end && !end_flag) {
00721
00722 real max_dt = t_end - t;
00723 real dt = the_tfp(b, eta);
00724
00725 end_flag = 0;
00726 if (dt > max_dt && x_flag) {
00727 end_flag = 1;
00728 dt = max_dt;
00729 }
00730
00731 unpert = step(b, t, eps, eta, dt, max_dt, end_flag, the_tfp, n_iter,
00732 x_flag, s_flag);
00733
00734
00735
00736 b->set_system_time(b->get_system_time()+dt);
00737
00738 b->set_time(t);
00739 for_all_daughters(sdyn3, b, bi)
00740 bi->set_time(t);
00741
00742 n_steps += 1;
00743 count_steps++;
00744
00745 if (unpert) last_unpert = n_steps;
00746
00747
00748
00749 if (t >= t_out
00750 || (UNPERTURBED_DIAG && n_steps - last_unpert < PERT_OUTPUT)) {
00751 calculate_energy(b, ekin, epot);
00752 int pp = cerr.precision(PRECISION);
00753 cerr << "Time = " << t + (real)b->get_time_offset()
00754 << " n_steps = " << n_steps
00755 << " dE = " << ekin + epot - b->get_e_tot_init() << endl;
00756 while (t >= t_out) t_out += dt_out;
00757 cerr.precision(pp);
00758 }
00759
00760
00761
00762 if (print && t >= t_print) {
00763 (*print)(b);
00764 t_print += dt_print;
00765 }
00766
00767
00768
00769 if (n_max > 0 && n_steps >= n_max) end_flag = 1;
00770
00771 if (end_flag || t >= t_snap) {
00772 if ((t >= t_snap) && system_in_cube(b, snap_cube_size)) {
00773 put_node(cout, *b);
00774 cout << flush;
00775 t_snap += dt_snap;
00776 }
00777 }
00778
00779
00780
00781
00782
00783 if (count_steps >= N_STEP_CHECK) {
00784
00785 count_steps = 0;
00786
00787 if (b->get_n_steps() > MAX_N_STEPS) return;
00788
00789 if (cpu_time() - cpu_save > cpu_time_check) {
00790 cpu_save = cpu_time();
00791 calculate_energy(b, ekin, epot);
00792 int p = cerr.precision(STD_PRECISION);
00793 cerr << "low_n3_evolve: CPU time = " << cpu_save - cpu_init;
00794 cerr.precision(PRECISION);
00795 cerr << " time = " << t + (real)b->get_time_offset();
00796 cerr.precision(STD_PRECISION);
00797 cerr << " offset = " << b->get_time_offset() << endl;
00798 cerr << " n_steps = " << n_steps
00799 << " Etot = " << ekin + epot
00800 << " dt = " << dt
00801 << endl << flush;
00802 cerr.precision(p);
00803 }
00804 }
00805 }
00806
00807 cerr.precision(p);
00808 clean_up(b, n_steps);
00809 }
00810
00811 #else
00812
00813 main(int argc, char **argv)
00814 {
00815 sdyn3* b;
00816 int n_iter = 0;
00817 real n_max = -1;
00818
00819 real delta_t = 1;
00820 real eta = 0.02;
00821
00822
00823
00824 real dt_out = VERY_LARGE_NUMBER;
00825
00826 real dt_snap = VERY_LARGE_NUMBER;
00827
00828 real snap_cube_size = 10;
00829
00830 real cpu_time_check = 3600;
00831
00832 real eps = 0.05;
00833 char* timestep_name = "constant_timestep";
00834
00835 check_help();
00836
00837 extern char *poptarg;
00838 int c;
00839 char* param_string = "A:c:C:d:D:e:f:n:qr:st:xz:";
00840
00841 bool a_flag = FALSE;
00842 bool d_flag = FALSE;
00843 bool D_flag = FALSE;
00844 bool e_flag = FALSE;
00845 bool f_flag = FALSE;
00846 bool n_flag = FALSE;
00847 bool q_flag = FALSE;
00848 bool r_flag = FALSE;
00849 bool s_flag = FALSE;
00850 bool t_flag = FALSE;
00851 bool x_flag = FALSE;
00852
00853
00854
00855
00856
00857
00858 bool z_flag = FALSE;
00859
00860 while ((c = pgetopt(argc, argv, param_string)) != -1)
00861 switch(c) {
00862 case 'A': a_flag = TRUE;
00863 eta = atof(poptarg);
00864 break;
00865 case 'c': cpu_time_check = atof(poptarg);
00866 break;
00867 case 'C': snap_cube_size = atof(poptarg);
00868 break;
00869 case 'd': d_flag = TRUE;
00870 dt_out = atof(poptarg);
00871 break;
00872 case 'D': D_flag = TRUE;
00873 dt_snap = atof(poptarg);
00874 break;
00875 case 'e': e_flag = TRUE;
00876 eps = atof(poptarg);
00877 break;
00878 case 'f': f_flag = TRUE;
00879 timestep_name = poptarg;
00880 break;
00881 case 'n': n_flag = TRUE;
00882 n_iter = atoi(poptarg);
00883 break;
00884 case 'q': q_flag = TRUE;
00885 break;
00886 case 's': s_flag = TRUE;
00887 break;
00888 case 't': t_flag = TRUE;
00889 delta_t = atof(poptarg);
00890 break;
00891 case 'x': x_flag = TRUE;
00892 break;
00893 case 'z': z_flag = TRUE;
00894 n_max = atof(poptarg);
00895 break;
00896 case '?': params_to_usage(cerr, argv[0], param_string);
00897 get_help();
00898 }
00899
00900 if (!q_flag) {
00901
00902
00903
00904 if (!t_flag) cerr << "default delta_t = " << delta_t << "\n";
00905 if (!a_flag) cerr << "default eta = " << eta << "\n";
00906 if (!d_flag) cerr << "default dt_out = " << dt_out << "\n";
00907 if (!e_flag) cerr << "default eps = " << eps << "\n";
00908 if (!f_flag) cerr << "default timestep_name = " << timestep_name
00909 << "\n";
00910 if (!n_flag) cerr << "default n_iter = " << n_iter << "\n";
00911 if (!s_flag) cerr << "s_flag (symmetric timestep ?) = FALSE" << "\n";
00912 if (!x_flag) cerr << "default termination: not at exact t_end" << "\n";
00913 if (!z_flag) cerr << "default n_max = " << n_max << "\n";
00914 }
00915
00916 if (!D_flag) dt_snap = delta_t;
00917
00918 b = get_sdyn3(cin);
00919 b->log_history(argc, argv);
00920 cpu_init();
00921
00922 low_n3_evolve(b, delta_t, dt_out, dt_snap, eps, eta, snap_cube_size,
00923 x_flag, timestep_name, s_flag, n_iter, n_max,
00924 cpu_time_check);
00925 }
00926
00927 #endif