00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "scatter3.h"
00015
00016
00017
00018
00019
00020
00021 local void set_orientation(kepler &k, phase3 &p)
00022 {
00023 real mu = p.cos_theta;
00024 real sin_theta = sqrt(1 - mu * mu);
00025
00026
00027
00028 vector n = vector(sin_theta*cos(p.phi), sin_theta*sin(p.phi), mu);
00029
00030
00031
00032 vector temp = vector(1, 0, 0);
00033 if (abs(n[0]) > .5) temp = vector(0, 1, 0);
00034 if (n[2] < 0) temp = -temp;
00035
00036 vector b = n ^ temp;
00037 b /= abs(b);
00038 vector a = b ^ n;
00039 if (n[2] < 0) a = -a;
00040
00041
00042
00043
00044 vector l = cos(p.psi)*a + sin(p.psi)*b;
00045 vector t = n ^ l;
00046
00047 k.set_orientation(l, t, n);
00048 k.initialize_from_shape_and_phase();
00049 }
00050
00051 local real potential_energy(sdyn3 * b)
00052 {
00053 real u = 0;
00054
00055 for_all_daughters(sdyn3, b, bi) {
00056 for (sdyn3 * bj = bi->get_younger_sister(); bj != NULL;
00057 bj = bj->get_younger_sister())
00058 u -= bi->get_mass() * bj->get_mass()
00059 / abs(bi->get_pos() - bj->get_pos());
00060 }
00061
00062 return u;
00063 }
00064
00065 local real energy(sdyn3 * b)
00066 {
00067 real k = 0, u = 0, dissipation = 0;
00068
00069 for_all_daughters(sdyn3, b, bi) {
00070 k += bi->get_mass() * bi->get_vel() * bi->get_vel();
00071 dissipation += bi->get_energy_dissipation();
00072 for (sdyn3 * bj = bi->get_younger_sister(); bj != NULL;
00073 bj = bj->get_younger_sister())
00074 u -= bi->get_mass() * bj->get_mass()
00075 / abs(bi->get_pos() - bj->get_pos());
00076 }
00077
00078 return 0.5*k + u + dissipation;
00079 }
00080
00081 local void kepler_pair_to_triple(kepler & k1,
00082 kepler & k3,
00083 sdyn3 * b1, sdyn3 * b2, sdyn3 * b3)
00084
00085
00086
00087
00088 {
00089
00090
00091
00092
00093
00094 real m1 = b1->get_mass();
00095 real m2 = b2->get_mass();
00096 real m3 = b3->get_mass();
00097
00098 real m12 = m1 + m2;
00099 real m123 = m12 + m3;
00100
00101
00102
00103 b3->set_pos(m12 * k3.get_rel_pos() / m123);
00104 b3->set_vel(m12 * k3.get_rel_vel() / m123);
00105
00106 b1->set_pos(-m3 * k3.get_rel_pos() / m123);
00107 b1->set_vel(-m3 * k3.get_rel_vel() / m123);
00108
00109 b2->set_pos(b1->get_pos());
00110 b2->set_vel(b1->get_vel());
00111
00112
00113
00114 b1->inc_pos(-m2 * k1.get_rel_pos() / m12);
00115 b1->inc_vel(-m2 * k1.get_rel_vel() / m12);
00116
00117 b2->inc_pos( m1 * k1.get_rel_pos() / m12);
00118 b2->inc_vel( m1 * k1.get_rel_vel() / m12);
00119
00120 }
00121
00122 local sdyn3 * set_up_dynamics(real m2,
00123 real m3,
00124 kepler & k1,
00125 kepler & k3)
00126 {
00127
00128
00129 sdyn3 * b = mksdyn3(3);
00130
00131
00132
00133 b->set_time(k3.get_time());
00134 for_all_daughters(sdyn3, b, bb)
00135 bb->set_time(k3.get_time());
00136
00137 sdyn3 * b1 = b->get_oldest_daughter();
00138 sdyn3 * b2 = b1->get_younger_sister();
00139 sdyn3 * b3 = b2->get_younger_sister();
00140
00141 b1->set_label(1);
00142 b2->set_label(2);
00143 b3->set_label(3);
00144
00145 b->set_mass(1 + m3);
00146 b1->set_mass(1 - m2);
00147 b2->set_mass(m2);
00148 b3->set_mass(m3);
00149
00150 kepler_pair_to_triple(k1, k3, b1, b2, b3);
00151
00152 return b;
00153 }
00154
00155
00156
00157 local sdyn3 * init_to_sdyn3(initial_state3 & init, final_state3 & final)
00158 {
00159 set_kepler_tolerance(2);
00160
00161 kepler k1;
00162
00163 real peri = 1;
00164 if (init.ecc == 1) peri = 0;
00165
00166 make_standard_kepler(k1, 0, 1, -0.5 / init.sma, init.ecc,
00167 peri, init.phase.mean_anomaly);
00168
00169
00170
00171
00172
00173
00174 real m2 = init.m2;
00175 real m3 = init.m3;
00176 real mtotal = 1 + m3;
00177 real v_inf = init.v_inf * sqrt( (1 - m2) * m2 * mtotal / m3 );
00178
00179 real energy3 = .5 * v_inf * v_inf;
00180 real ang_mom3 = init.rho * v_inf;
00181
00182 real ecc3 = (energy3 == 0 ? 1
00183 : sqrt( 1 + 2 * energy3
00184 * pow(ang_mom3/mtotal, 2)));
00185
00186
00187
00188 real virial_ratio = init.rho;
00189
00190 kepler k3;
00191
00192 make_standard_kepler(k3, 0, mtotal, energy3, ecc3, virial_ratio, 0);
00193
00194
00195
00196 real r_unp = (init.sma + init.r3)
00197 * pow(TIDAL_TOL_FACTOR / mtotal, -1/3.0);
00198
00199 if (r_unp <= k3.get_periastron()) {
00200 final.descriptor = preservation;
00201 final.sma = k1.get_semi_major_axis();
00202 final.ecc = k1.get_eccentricity();
00203 final.outer_separation = k3.get_periastron();
00204 final.escaper = 3;
00205 final.error = 0;
00206 final.time = 0;
00207 final.n_steps = 0;
00208 final.virial_ratio = k3.get_energy() * k3.get_periastron()
00209 / k3.get_total_mass() - 1;
00210
00211
00212
00213
00214
00215 if (k1.get_periastron() < init.r1 + init.r2) {
00216 final.descriptor = merger_escape_3;
00217 final.sma = final.ecc = -1;
00218 }
00219
00220 return NULL;
00221 }
00222
00223 init.r_init = max(init.r_init_min, min(init.r_init_max, r_unp));
00224
00225 k1.transform_to_time(k3.return_to_radius(init.r_init));
00226
00227 set_orientation(k3, init.phase);
00228
00229
00230
00231
00232 sdyn3 * b;
00233 b = set_up_dynamics(m2, m3, k1, k3);
00234
00235
00236
00237 sdyn3 * bb = b->get_oldest_daughter();
00238 bb->set_radius(init.r1);
00239 bb = bb->get_younger_sister();
00240 bb->set_radius(init.r2);
00241 bb = bb->get_younger_sister();
00242 bb->set_radius(init.r3);
00243
00244 return b;
00245 }
00246
00247 local void extend_orbits(sdyn3 * b1, sdyn3 * b2, sdyn3 * b3)
00248
00249
00250
00251 {
00252 if ( (b1->get_time() != b2->get_time())
00253 || (b1->get_time() != b3->get_time()) )
00254 err_exit("extend_orbits: inconsistent times");
00255
00256 real time = b3->get_time();
00257
00258 kepler inner, outer;
00259
00260 set_kepler_from_sdyn3(inner, b1, b2);
00261
00262 real m1 = b1->get_mass();
00263 real m2 = b2->get_mass();
00264 real m3 = b3->get_mass();
00265 real m12 = m1 + m2;
00266 real m123 = m12 + m3;
00267
00268 outer.set_time(time);
00269 outer.set_total_mass(m123);
00270
00271
00272
00273 vector cmr = (m1 * b1->get_pos() + m2 * b2->get_pos()) / m12;
00274 vector cmv = (m1 * b1->get_vel() + m2 * b2->get_vel()) / m12;
00275
00276 outer.set_rel_pos(b3->get_pos() - cmr);
00277 outer.set_rel_vel(b3->get_vel() - cmv);
00278
00279 outer.initialize_from_pos_and_vel();
00280
00281
00282
00283
00284 int inner_orbits = 2 * (int) ((outer.pred_advance_to_apastron() - time)
00285 / inner.get_period() + 0.5);
00286 time += inner_orbits * inner.get_period();
00287 outer.transform_to_time(time);
00288
00289
00290
00291
00292 inner.set_time(time);
00293
00294
00295
00296 b1->get_parent()->set_time(time);
00297 b1->set_time(time);
00298 b2->set_time(time);
00299 b3->set_time(time);
00300
00301 kepler_pair_to_triple(inner, outer, b1, b2, b3);
00302
00303
00304
00305
00306
00307
00308
00309 }
00310
00311 local int escape(sdyn3 * bi, sdyn3 * bj, sdyn3 * bk,
00312 real ejk,
00313 real r_stop,
00314 intermediate_state3 & inter,
00315 final_state3 & final)
00316
00317
00318
00319
00320
00321 {
00322 final.descriptor = unknown_final;
00323 if (ejk >= 0) return 0;
00324
00325 real mi = bi->get_mass();
00326 real mj = bj->get_mass();
00327 real mk = bk->get_mass();
00328 real mjk = mj + mk;
00329
00330
00331
00332 vector cmr = (mj * bj->get_pos() + mk * bk->get_pos()) / mjk;
00333 vector cmv = (mj * bj->get_vel() + mk * bk->get_vel()) / mjk;
00334
00335
00336
00337 vector dv = bi->get_vel() - cmv;
00338 vector dr = bi->get_pos() - cmr;
00339
00340 if (dr*dv <= 0) return 0;
00341
00342 real sep = abs(dr);
00343 real virial_ratio = .5 * dv * dv * sep / (mi + mj + mk);
00344
00345 if (sep > r_stop) {
00346
00347 real ajk = 0.5 * mjk / abs(ejk);
00348
00349 final.descriptor = stopped;
00350
00351 final.sma = ajk;
00352 real ang_mom = abs((bk->get_pos() - bj->get_pos())
00353 ^ (bk->get_vel() - bj->get_vel()));
00354
00355 real ecc2 = 1 - ang_mom * ang_mom / (mjk * ajk);
00356 if (ecc2 < 1.e-10) {
00357
00358
00359
00360 kepler k;
00361 set_kepler_from_sdyn3(k, bj, bk);
00362 final.ecc = k.get_eccentricity();
00363
00364 } else
00365 final.ecc = sqrt(ecc2);
00366
00367 final.escaper = bi->get_index();
00368 final.virial_ratio = virial_ratio;
00369 final.outer_separation = sep;
00370
00371 return 1;
00372 }
00373
00374
00375
00376 real ajk = 0.5 * mjk / abs(ejk);
00377
00378
00379
00380
00381
00382 real rlimit = (ajk + bi->get_radius())
00383 * pow(TIDAL_TOL_FACTOR * mjk / (mi + mjk), -1/3.0);
00384
00385 if (sep < rlimit) return 0;
00386
00387
00388
00389
00390 real scaled_safety_factor = ENERGY_SAFETY_FACTOR * rlimit / sep;
00391
00392
00393
00394
00395
00396
00397
00398 if (abs(virial_ratio - 1) < scaled_safety_factor) return 0;
00399
00400
00401
00402 if (virial_ratio > 1) {
00403
00404
00405
00406 if (bi->get_index() == 1)
00407 final.descriptor = exchange_1;
00408 else if (bi->get_index() == 2)
00409 final.descriptor = exchange_2;
00410 else if (bi->get_index() == 3)
00411 final.descriptor = preservation;
00412 else
00413 final.descriptor = unknown_final;
00414
00415 final.sma = ajk;
00416 real ang_mom = abs((bk->get_pos() - bj->get_pos())
00417 ^ (bk->get_vel() - bj->get_vel()));
00418
00419 real ecc2 = 1 - ang_mom * ang_mom / (mjk * ajk);
00420 if (ecc2 < 1.e-10) {
00421
00422
00423
00424 kepler k;
00425 set_kepler_from_sdyn3(k, bj, bk);
00426 final.ecc = k.get_eccentricity();
00427
00428 } else
00429 final.ecc = sqrt(ecc2);
00430
00431 final.escaper = bi->get_index();
00432 final.virial_ratio = virial_ratio;
00433 final.outer_separation = sep;
00434
00435 return 1;
00436
00437 } else {
00438
00439
00440
00441
00442
00443
00444 extend_orbits(bj, bk, bi);
00445 inter.n_kepler++;
00446
00447
00448
00449 }
00450
00451 return 0;
00452 }
00453
00454
00455
00456 void set_merger_mass_and_radius(sdyn3 * bn, sdyn3 * bi, sdyn3 * bj)
00457 {
00458 bn->set_mass(bi->get_mass() + bj->get_mass());
00459 bn->set_radius(bi->get_radius() + bj->get_radius());
00460 }
00461
00462
00463
00464
00465 void set_merger_dyn(sdyn3 * bn, sdyn3 * bi, sdyn3 * bj)
00466 {
00467 real mi = bi->get_mass();
00468 real mj = bj->get_mass();
00469 real m_inv = 1/(mi + mj);
00470
00471 bn->set_pos((mi*bi->get_pos() + mj*bj->get_pos())*m_inv);
00472 bn->set_vel((mi*bi->get_vel() + mj*bj->get_vel())*m_inv);
00473 bn->set_acc((mi*bi->get_acc() + mj*bj->get_acc())*m_inv);
00474 bn->set_jerk((mi*bi->get_jerk() + mj*bj->get_jerk())*m_inv);
00475
00476 vector d_pos = bi->get_pos() - bj->get_pos();
00477 real rij = sqrt(d_pos*d_pos);
00478
00479 vector d_vel = bi->get_vel() - bj->get_vel();
00480 real vij2 = d_vel*d_vel;
00481
00482 real eij_pot = -mi * mj / rij;
00483 real eij_kin = 0.5 * mi * mj * m_inv * vij2;
00484
00485
00486
00487 sdyn3 * b = bi->get_parent();
00488 sdyn3 * bk = NULL;
00489
00490 for_all_daughters(sdyn3, b, bb)
00491 if (bb != bi && bb != bj) bk = bb;
00492
00493 real tidal_pot = 0;
00494 if (bk)
00495 {
00496 real mn = mi + mj;
00497 real mk = bk->get_mass();
00498 tidal_pot = -mn * mk / abs(bn->get_pos() - bk->get_pos())
00499 + mi * mk / abs(bi->get_pos() - bk->get_pos())
00500 + mj * mk / abs(bj->get_pos() - bk->get_pos());
00501 }
00502
00503 bn->set_energy_dissipation(bi->get_energy_dissipation()
00504 + bj->get_energy_dissipation()
00505 + eij_pot + eij_kin
00506 - tidal_pot);
00507
00508 }
00509
00510
00511
00512 void merge(sdyn3 * bi, sdyn3 * bj)
00513 {
00514 sdyn3 * b = bi->get_parent();
00515 if (b != bj->get_parent()) err_exit("merge: parent conflict...");
00516
00517
00518
00519 sdyn3 * bn = new sdyn3();
00520
00521
00522
00523
00524
00525
00526
00527
00528 set_merger_mass_and_radius(bn, bi, bj);
00529 set_merger_dyn(bn, bi, bj);
00530 bn->set_time(bi->get_time());
00531
00532 int max_index = 0;
00533 for_all_daughters(sdyn3, b, bb)
00534 if (max_index < bb->get_index())
00535 max_index = bb->get_index();
00536
00537 bn->set_label(max_index+1);
00538
00539 detach_node_from_general_tree(*bi);
00540 detach_node_from_general_tree(*bj);
00541
00542 add_node(*bn, *b);
00543 }
00544
00545
00546
00547 local void merge_collisions(sdyn3 * b)
00548 {
00549 int coll = 1;
00550 while (coll)
00551 {
00552 coll = 0;
00553 for_all_daughters(sdyn3, b, bi)
00554 {
00555 if (coll) break;
00556 for (sdyn3 * bj = bi->get_younger_sister(); bj != NULL;
00557 bj = bj->get_younger_sister())
00558 {
00559 if ( abs(bi->get_pos() - bj->get_pos())
00560 < (bi->get_radius() + bj->get_radius()) )
00561 {
00562 merge(bi, bj);
00563 coll = 1;
00564 break;
00565 }
00566 }
00567 }
00568 }
00569 }
00570
00571
00572
00573
00574
00575 local int triple_escape(real e12, real r3, real m12, real m3)
00576 {
00577 if (e12 < 0) return 0;
00578
00579 real a12 = 0.5 * m12 / e12;
00580
00581
00582
00583 if (r3 > a12 * pow(TIDAL_TOL_FACTOR * m12 / (m3 + m12), -1/3.0))
00584 return 1;
00585 else
00586 return 0;
00587 }
00588
00589 local int extend_or_end_scatter3(sdyn3 * b, real r_stop,
00590 intermediate_state3 & inter,
00591 final_state3 & final)
00592 {
00593
00594 b->to_com();
00595
00596 sdyn3 * b1 = b->get_oldest_daughter();
00597 sdyn3 * b2 = b1->get_younger_sister();
00598 sdyn3 * b3 = b2->get_younger_sister();
00599
00600 real r12 = abs(b1->get_pos() - b2->get_pos());
00601 real r23 = abs(b2->get_pos() - b3->get_pos());
00602 real r31 = abs(b3->get_pos() - b1->get_pos());
00603
00604 real m1 = b1->get_mass();
00605 real m2 = b2->get_mass();
00606 real m3 = b3->get_mass();
00607
00608 real k1 = 0.5 * m1 * b1->get_vel() * b1->get_vel();
00609 real k2 = 0.5 * m2 * b2->get_vel() * b2->get_vel();
00610 real k3 = 0.5 * m3 * b3->get_vel() * b3->get_vel();
00611
00612 real phi12 = m1 * m2 / r12;
00613 real phi23 = m2 * m3 / r23;
00614 real phi31 = m3 * m1 / r31;
00615
00616 real mu12 = m1 * m2 / (m1 + m2);
00617 real mu23 = m2 * m3 / (m2 + m3);
00618 real mu31 = m3 * m1 / (m3 + m1);
00619
00620 vector dv = b2->get_vel() - b1->get_vel();
00621 real k12 = 0.5 * mu12 * dv * dv;
00622 real vr12 = dv * (b2->get_pos() - b1->get_pos());
00623
00624 dv = b3->get_vel() - b2->get_vel();
00625 real k23 = 0.5 * mu23 * dv * dv;
00626 real vr23 = dv * (b3->get_pos() - b2->get_pos());
00627
00628 dv = b1->get_vel() - b3->get_vel();
00629 real k31 = 0.5 * mu31 * dv * dv;
00630 real vr31 = dv * (b1->get_pos() - b3->get_pos());
00631
00632
00633
00634 if (k1 + k2 + k3 >= phi12 + phi23 + phi31
00635 && r12 > LARGE_SEPARATION
00636 && r23 > LARGE_SEPARATION
00637 && r31 > LARGE_SEPARATION
00638 && k12 > phi12 && k23 > phi23 && k31 > phi31
00639 && vr12 > 0 && vr23 > 0 && vr31 > 0
00640 && triple_escape(k12 - phi12, min(r23, r31), m1 + m2, m3)
00641 && triple_escape(k23 - phi23, min(r31, r12), m2 + m3, m1)
00642 && triple_escape(k31 - phi31, min(r12, r23), m3 + m1, m2)) {
00643
00644 final.descriptor = ionization;
00645 final.virial_ratio = min(min(k12/phi12, k23/phi23), k31/phi31);
00646 final.outer_separation = -1;
00647 final.escaper = -1;
00648 return 1;
00649 }
00650
00651
00652
00653
00654
00655
00656
00657 if (r12 * LARGE_SEPARATION_FACTOR < (r23 + r31))
00658 return escape(b3, b1, b2, (k12 - phi12)/mu12, r_stop, inter, final);
00659
00660 if (r23 * LARGE_SEPARATION_FACTOR < (r31 + r12))
00661 return escape(b1, b2, b3, (k23 - phi23)/mu23, r_stop, inter, final);
00662
00663 if (r31 * LARGE_SEPARATION_FACTOR < (r12 + r23))
00664 return escape(b2, b3, b1, (k31 - phi31)/mu31, r_stop, inter, final);
00665
00666 return 0;
00667 }
00668
00669 local int extend_or_end_scatter2(sdyn3 * b, final_state3 & final)
00670 {
00671 sdyn3 * d1 = b->get_oldest_daughter();
00672 sdyn3 * d2 = d1->get_younger_sister();
00673 kepler k;
00674
00675 sdyn3 * merger = NULL;
00676 sdyn3 * single = NULL;
00677
00678 if (d1->get_index() > 3)
00679 {
00680 merger = d1;
00681 single = d2;
00682 }
00683 else
00684 {
00685 merger = d2;
00686 single = d1;
00687 }
00688
00689 set_kepler_from_sdyn3(k, d1, d2);
00690
00691 real closest_approach = k.get_periastron();
00692 if (k.get_energy() >= 0
00693 && (d1->get_pos() - d2->get_pos())
00694 * (d1->get_vel() - d2->get_vel()) > 0)
00695 closest_approach = k.get_separation();
00696
00697 if (closest_approach < d1->get_radius() + d2->get_radius()) {
00698
00699 merge(d1, d2);
00700 d1 = b->get_oldest_daughter();
00701
00702 final.descriptor = triple_merger;
00703 final.escaper = 0;
00704 final.outer_separation = 0;
00705 final.virial_ratio = -1;
00706
00707 } else {
00708
00709 real closest_approach_squared = closest_approach * closest_approach;
00710
00711 merger->set_min_nn_dr2(closest_approach_squared);
00712 merger->set_min_nn_label(single->get_index());
00713
00714 if (closest_approach_squared < single->get_min_nn_dr2())
00715 {
00716 single->set_min_nn_dr2(closest_approach_squared);
00717 single->set_min_nn_label(merger->get_index());
00718 }
00719
00720
00721 if (k.get_energy() < 0) {
00722
00723 if (single->get_index() == 1)
00724 final.descriptor = merger_binary_1;
00725 else if (single->get_index() == 2)
00726 final.descriptor = merger_binary_2;
00727 else if (single->get_index() == 3)
00728 final.descriptor = merger_binary_3;
00729 else
00730 final.descriptor = unknown_final;
00731
00732 final.sma = k.get_semi_major_axis();
00733 final.ecc = k.get_eccentricity();
00734 final.outer_separation = -1;
00735 final.escaper = 0;
00736 final.virial_ratio = -1;
00737
00738 } else {
00739
00740 if (single->get_index() == 1)
00741 final.descriptor = merger_escape_1;
00742 else if (single->get_index() == 2)
00743 final.descriptor = merger_escape_2;
00744 else if (single->get_index() == 3)
00745 final.descriptor = merger_escape_3;
00746 else
00747 final.descriptor = unknown_final;
00748
00749 final.outer_separation = k.get_separation();
00750 final.escaper = single->get_index();
00751 final.virial_ratio = k.get_energy() * k.get_separation()
00752 / k.get_total_mass() - 1;
00753 }
00754 }
00755
00756 return 1;
00757 }
00758
00759 local int extend_or_end_scatter1(final_state3 & final)
00760 {
00761 final.descriptor = triple_merger;
00762 final.escaper = 0;
00763 final.outer_separation = 0;
00764 final.virial_ratio = -1;
00765
00766 return 1;
00767 }
00768
00769
00770
00771
00772
00773 local int extend_or_end_scatter(sdyn3 * b, real r_stop,
00774 intermediate_state3 & inter,
00775 final_state3 & final)
00776 {
00777
00778
00779 if (b->get_n_steps() > MAX_N_STEPS) {
00780 final.descriptor = stopped;
00781 return 1;
00782 }
00783
00784 int n = 0;
00785 for_all_daughters(sdyn3, b, bb) n++;
00786
00787
00788
00789 final.sma = -1;
00790 final.ecc = -1;
00791
00792 if (n == 3)
00793 return extend_or_end_scatter3(b, r_stop, inter, final);
00794 else if (n == 2)
00795 return extend_or_end_scatter2(b, final);
00796 else if (n == 1)
00797 return extend_or_end_scatter1(final);
00798 else {
00799 cerr << "extend_or_end_scatter: n = " << n << endl;
00800 exit(1);
00801 }
00802 return 0;
00803 }
00804
00805
00806
00807 local void check_init(initial_state3 & init)
00808 {
00809 if (init.m2 > 1) err_exit("check_init: m1 < 0");
00810 if (init.m2 < 0) err_exit("check_init: m2 < 0");
00811 if (init.m3 < 0) err_exit("check_init: m3 < 0");
00812 if (init.sma <= 0) err_exit("check_init: semi-major axis <= 0");
00813 if (init.ecc < 0) err_exit("check_init: eccentricity < 0");
00814 if (init.ecc > 1) err_exit("check_init: eccentricity > 1");
00815 if (init.r1 < 0) err_exit("check_init: r1 < 0");
00816 if (init.r2 < 0) err_exit("check_init: r2 < 0");
00817 if (init.r3 < 0) err_exit("check_init: r3 < 0");
00818 if (init.v_inf < 0) err_exit("check_init: v_inf < 0");
00819 if (init.rho < 0) err_exit("check_init: rho < 0");
00820 if (init.eta <= 0) err_exit("check_init: eta <= 0");
00821 }
00822
00823
00824
00825 local void sdyn3_to_system(sdyn3 * root, body * system)
00826 {
00827 int n = 0;
00828 for_all_daughters(sdyn3, root, bb) {
00829 system[n].index = bb->get_index();
00830 system[n].mass = bb->get_mass();
00831 for (int kp = 0; kp < 3; kp++) system[n].pos[kp] = bb->get_pos()[kp];
00832 for (int kv = 0; kv < 3; kv++) system[n].vel[kv] = bb->get_vel()[kv];
00833 n++;
00834 }
00835 }
00836
00837
00838
00839
00840 void scatter3(initial_state3 & init,
00841 intermediate_state3 & inter,
00842 final_state3 & final,
00843 real cpu_time_check,
00844 real dt_out,
00845 real dt_snap,
00846 real snap_cube_size,
00847 real dt_print,
00848 sdyn3_print_fp p)
00849 {
00850 static int count = 0;
00851
00852 check_init(init);
00853 sdyn3 * b = init_to_sdyn3(init, final);
00854
00855
00856
00857
00858
00859
00860
00861 sdyn3* b1 = b->get_oldest_daughter();
00862 sdyn3* b2 = b1->get_younger_sister();
00863 sdyn3* b3 = b2->get_younger_sister();
00864
00865
00866
00867 vector dx = b1->get_pos() - b2->get_pos();
00868 cout << ++count
00869 << " " << 180*atan2(dx[1], dx[0])/PI
00870 << " " << dx[2]/abs(dx);
00871
00872
00873
00874 vector cm = (b1->get_mass()*b1->get_pos()
00875 + b2->get_mass()*b2->get_pos())
00876 / (b1->get_mass() + b2->get_mass());
00877 dx = b3->get_pos() - cm;
00878
00879 cout << " " << 180*atan2(dx[1], dx[0])/PI
00880 << " " << dx[2]/abs(dx);
00881
00882 cout << endl;
00883
00884
00885
00886
00887
00888
00889
00890 sdyn3 * bi = b->get_oldest_daughter();
00891 while (bi) {
00892 sdyn3 * tmp = bi->get_younger_sister();
00893 delete bi;
00894 bi = tmp;
00895 }
00896 delete b;
00897 }
00898
00899 main(int argc, char **argv)
00900 {
00901
00902 initial_state3 init;
00903 make_standard_init(init);
00904
00905 int seed = 0;
00906 int n_rand = 0;
00907
00908 int n_experiments = 1;
00909 real dt_out =
00910 VERY_LARGE_NUMBER;
00911 real dt_snap =
00912 VERY_LARGE_NUMBER;
00913
00914 real cpu_time_check = 3600;
00915 real snap_cube_size = 10;
00916
00917 int planar_flag = 0;
00918
00919 bool b_flag = FALSE;
00920 bool q_flag = FALSE;
00921 bool Q_flag = FALSE;
00922
00923 extern char *poptarg;
00924 int pgetopt(int, char **, char *), c;
00925
00926 while ((c = pgetopt(argc, argv,
00927 "A:bc:C:d:D:e:L:m:M:n:N:pPqQr:R:s:S:U:v:x:y:z:")) != -1)
00928 switch(c)
00929 {
00930 case 'A': init.eta = atof(poptarg);
00931 break;
00932 case 'b': b_flag = 1 - b_flag;
00933 break;
00934 case 'c': cpu_time_check = 3600*atof(poptarg);
00935 break;
00936 case 'C': snap_cube_size = atof(poptarg);
00937 break;
00938 case 'd': dt_out = atof(poptarg);
00939 break;
00940 case 'D': dt_snap = atof(poptarg);
00941 break;
00942 case 'e': init.ecc = atof(poptarg);
00943 break;
00944 case 'L': init.r_init_min = atof(poptarg);
00945 break;
00946 case 'm': init.m2 = atof(poptarg);
00947 break;
00948 case 'M': init.m3 = atof(poptarg);
00949 break;
00950 case 'n': n_experiments = atoi(poptarg);
00951 break;
00952 case 'N': n_rand = atoi(poptarg);
00953 break;
00954 case 'p': planar_flag = 1;
00955 break;
00956 case 'P': planar_flag = -1;
00957 break;
00958 case 'q': q_flag = 1 - q_flag;
00959 break;
00960 case 'Q': Q_flag = 1 - Q_flag;
00961 break;
00962 case 'r': init.rho = atof(poptarg);
00963 break;
00964 case 'R': init.r_stop = init.r_init_min
00965 = init.r_init_max
00966 = atof(poptarg);
00967 break;
00968 case 's': seed = atoi(poptarg);
00969 break;
00970 case 'S': init.r_stop = atof(poptarg);
00971 break;
00972 case 'U': init.r_init_max = atof(poptarg);
00973 break;
00974 case 'v': init.v_inf = atof(poptarg);
00975 break;
00976 case 'x': init.r1 = atof(poptarg);
00977 break;
00978 case 'y': init.r2 = atof(poptarg);
00979 break;
00980 case 'z': init.r3 = atof(poptarg);
00981 break;
00982 case '?': cerr <<
00983 "usage: scatter3 [-A #] [-b] [-c #] [-C #] [-d #] [-D #] "
00984 << "[-e #] [-L #] [-m #] [-M #] [-n #] [-N #] [-p] "
00985 << "[-P] [-q] [-Q] [-r #] [-R #] [-s #] "
00986 << "[-S #] [-U #] [-v #] [-x #] [-y #] [-z #]" << endl;
00987 exit(1);
00988 }
00989
00990 if (Q_flag) q_flag = TRUE;
00991
00992 if (init.m2 > 1)
00993 {
00994 cerr << "sigma3: init.m2 = " << init.m2 << " > 1" << endl;
00995 exit(1);
00996 }
00997
00998 cpu_init();
00999 int random_seed = srandinter(seed, n_rand);
01000
01001 while (n_experiments--) {
01002
01003
01004
01005
01006 randomize_angles(init.phase);
01007
01008 if (planar_flag == 1)
01009 init.phase.cos_theta = 1;
01010 else if (planar_flag == -1)
01011 init.phase.cos_theta = -1;
01012
01013 intermediate_state3 inter;
01014 final_state3 final;
01015
01016 real cpu = cpu_time();
01017 scatter3(init, inter, final, cpu_time_check,
01018 dt_out, dt_snap, snap_cube_size);
01019 }
01020 }