00001
00002 #include "../evolve/sigma.h"
00003 #ifndef TOOLBOX
00004
00005 #define DEFAULT_MASS_RATIO 1
00006 #define DEFAULT_ECC 0
00007 #define DEFAULT_SMA 1
00008 #define SMA_REDUCE 10
00009 #define DEFAULT_R1 0
00010 #define DEFAULT_R2 0
00011 #define TIDAL_TOL_FACTOR 1e-6
00012
00013
00014 local void pp(sdyn* b, ostream & s, int level = 0) {
00015
00016 s.precision(4);
00017
00018 for (int i = 0; i < 2*level; i++) s << " ";
00019
00020 b->pretty_print_node(s);
00021 s << " \t"<< b->get_mass() << " \t"
00022 << b->get_pos() << " "
00023 << b->get_vel() <<endl;
00024
00025 for (sdyn * daughter = b->get_oldest_daughter();
00026 daughter != NULL;
00027 daughter = daughter->get_younger_sister())
00028 pp(daughter, s, level + 1);
00029 }
00030
00031
00032
00033
00034
00035
00036 local void initialize_root(sdyn* root, real v_inf,
00037 real rho_sq_min, real rho_sq_max, real peri,
00038 real r_init,
00039 real projectile_mass, real projectile_radius) {
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 real target_mass = 1;
00050 real target_sma = 1;
00051
00052 real m_total = target_mass + projectile_mass;
00053 root->set_mass(m_total);
00054 root->set_pos(vector(0,0,0));
00055 root->set_vel(vector(0,0,0));
00056
00057 sdyn* target = root->get_oldest_daughter();
00058 target->set_mass(target_mass);
00059 target->set_radius(target_sma);
00060
00061 sdyn* projectile = target->get_younger_sister();
00062 projectile->set_mass(projectile_mass);
00063 projectile->set_radius(projectile_radius);
00064
00065
00066
00067 v_inf *= sqrt(0.5*m_total);
00068
00069
00070 if (rho_sq_max*peri > 0) err_exit("Inconsistent initial conditions.");
00071
00072 if(rho_sq_min<0)
00073 rho_sq_min = 0;
00074
00075 real rho_max = -1;
00076 if(rho_sq_max>0)
00077 rho_max = sqrt(rho_sq_max);
00078
00079
00080
00081 if (peri > 0) {
00082 if (v_inf > 0)
00083 rho_max = peri * sqrt(1 + 2*m_total/(peri*v_inf*v_inf));
00084 else
00085 rho_max = peri;
00086 }
00087
00088
00089
00090 real rho = sqrt(randinter(rho_sq_min, pow(rho_max, 2)));
00091
00092
00093
00094
00095 real energy = .5 * v_inf * v_inf;
00096 real ang_mom = rho * v_inf;
00097
00098
00099
00100
00101 real ecc = (energy == 0 ? 1 : sqrt( 1 + 2 * energy
00102 * pow(ang_mom/m_total, 2)));
00103
00104
00105
00106 real virial_ratio = rho;
00107
00108 kepler k;
00109
00110
00111
00112
00113 make_standard_kepler(k, 0, m_total, energy, ecc, virial_ratio, -0.001, 1);
00114
00115
00116
00117 real r_unp = (target_sma + projectile_radius)
00118 * pow(TIDAL_TOL_FACTOR / m_total, -1/3.0);
00119
00120 real r_start = min(r_init, r_unp);
00121 if (k.get_separation() < r_start)
00122 k.return_to_radius(r_start);
00123 else
00124 k.advance_to_radius(r_start);
00125
00126
00127
00128 root->set_time(k.get_time());
00129 target->set_time(k.get_time());
00130 projectile->set_time(k.get_time());
00131
00132 target->set_pos(-projectile_mass * k.get_rel_pos() / m_total);
00133 target->set_vel(-projectile_mass * k.get_rel_vel() / m_total);
00134
00135 projectile->set_pos(target_mass * k.get_rel_pos() / m_total);
00136 projectile->set_vel(target_mass * k.get_rel_vel() / m_total);
00137
00138
00139
00140
00141
00142
00143
00144
00145 }
00146
00147
00148
00149
00150
00151
00152 local void split_particle(sdyn* current, real ecc, real sma, int planar,
00153 real mass_ratio, real r1, real r2) {
00154
00155 if (current->get_oldest_daughter() != NULL)
00156 err_exit("Can't split a binary node!");
00157
00158
00159
00160 sdyn* d1 = new sdyn;
00161 sdyn* d2 = new sdyn;
00162
00163 current->set_oldest_daughter(d1);
00164
00165 d1->set_parent(current);
00166 d2->set_parent(current);
00167
00168 d1->set_younger_sister(d2);
00169 d2->set_elder_sister(d1);
00170
00171
00172
00173 real m_total = current->get_mass();
00174 real m1 = m_total / (1 + mass_ratio);
00175 real m2 = m1 * mass_ratio;
00176
00177
00178
00179 if (m1 < m2) {
00180 real temp = m1;
00181 m1 = m2;
00182 m2 = temp;
00183 }
00184
00185 d1->set_mass(m1);
00186 d2->set_mass(m2);
00187
00188
00189 d1->set_radius(r1);
00190 d2->set_radius(r2);
00191
00192
00193 d2->get_parent()->set_radius(0);
00194
00195
00196
00197 kepler k;
00198
00199 if (sma < 0) {
00200 sma = DEFAULT_SMA;
00201 for (int i = 1; i < strlen(current->get_name()); i++)
00202 sma /= SMA_REDUCE;
00203 }
00204
00205 if (ecc < 0 || ecc >= 1) {
00206
00207
00208 real peri_min = 2*max(d1->get_radius(), d2->get_radius());
00209 real e_max = 1 - peri_min/sma;
00210
00211 if(e_max<0)
00212 err_exit("initial eccentricity out of bounds in split_particle(...)");
00213
00214
00215 if(STABILITY)
00216 ecc = sqrt(randinter(0, e_max*e_max));
00217 else
00218 ecc = sqrt(randinter(0,1));
00219 }
00220
00221
00222
00223
00224
00225 real peri = 1;
00226 if (ecc == 1) peri = 0;
00227
00228
00229
00230 real mean_anomaly = randinter(-PI, PI);
00231
00232 make_standard_kepler(k, 0, m_total, -0.5 * m_total / sma, ecc,
00233 peri, mean_anomaly);
00234
00235 set_random_orientation(k, planar);
00236
00237 d1->set_time(current->get_time());
00238 d2->set_time(current->get_time());
00239
00240 d1->set_pos(-m2 * k.get_rel_pos() / m_total);
00241 d1->set_vel(-m2 * k.get_rel_vel() / m_total);
00242
00243 d2->set_pos(m1 * k.get_rel_pos() / m_total);
00244 d2->set_vel(m1 * k.get_rel_vel() / m_total);
00245
00246
00247
00248 d1->set_name(current->get_name());
00249 d2->set_name(current->get_name());
00250 strcat(d1->get_name(), "1");
00251 strcat(d2->get_name(), "2");
00252
00253
00254
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 #include <string.h>
00266 local sdyn* locate_label_and_set_defaults(sdyn* root, char* label, int planar) {
00267
00268 sdyn* b = root;
00269
00270 for (int i = 0; i < strlen(label); i++) {
00271
00272 char* name = strdup(label);
00273 name[i+1] = '\0';
00274
00275 sdyn* node = NULL;
00276
00277
00278
00279 while (node == NULL) {
00280 for_all_daughters(sdyn, b, bb)
00281 if (strcmp(bb->get_name(), name) == 0) node = bb;
00282 if (node == NULL) {
00283 if (b->get_oldest_daughter() != NULL) return NULL;
00284
00285
00286
00287 split_particle(b, DEFAULT_ECC, -1, planar,
00288 DEFAULT_MASS_RATIO, DEFAULT_R1, DEFAULT_R2);
00289 }
00290
00291
00292 }
00293 b = node;
00294 }
00295 return b;
00296 }
00297
00298
00299
00300
00301 sdyn* first_leaf(sdyn* b)
00302 {
00303 while (b->get_oldest_daughter()) b = b->get_oldest_daughter();
00304 return b;
00305 }
00306
00307
00308
00309 sdyn* next_leaf(sdyn* b)
00310 {
00311 if (b == NULL)
00312
00313 return NULL;
00314
00315 else if (b->get_oldest_daughter())
00316
00317 return first_leaf(b);
00318
00319 else
00320
00321 while (b != NULL && b->get_younger_sister() == NULL)
00322 b = b->get_parent();
00323
00324 return (b == NULL ? (sdyn*)NULL : first_leaf(b->get_younger_sister()));
00325 }
00326
00327 sdyn* mkscat(int argc, char **argv, sigma_input &input) {
00328
00329
00330
00331 sdyn* root = mksdyn(2);
00332 root->set_name("r");
00333 root->set_index(-1);
00334
00335 sdyn* target = root->get_oldest_daughter();
00336 target->set_name("t");
00337 target->set_index(-1);
00338
00339 sdyn* projectile = target->get_younger_sister();
00340 projectile->set_name("p");
00341 projectile->set_index(-1);
00342
00343 sdyn* current = root;
00344
00345
00346
00347 real projectile_mass = 1;
00348 real projectile_radius = 0;
00349 real v_inf = 1;
00350 real rho = 0;
00351 real peri = -1;
00352 real initial_separation = VERY_LARGE_NUMBER;
00353
00354 real mass_ratio = DEFAULT_MASS_RATIO;
00355 real ecc = DEFAULT_ECC;
00356 real sma = DEFAULT_SMA;
00357 real r1 = DEFAULT_R1;
00358 real r2 = DEFAULT_R2;
00359
00360 int planar = 0;
00361 bool debug = FALSE;
00362
00363
00364
00365 int seed = 0;
00366 int i = 0;
00367 int random_seed;
00368 while (++i < argc)
00369 if (argv[i][0] == '-' && argv[i][1] == 's') {
00370 seed = atoi(argv[++i]);
00371 if(seed!=0)
00372 random_seed = srandinter(seed);
00373 else
00374 cerr << "Seed not re-initialized" << endl;
00375 seed = -1;
00376 }
00377 if(seed>0)
00378 random_seed = srandinter(seed);
00379
00380
00381
00382 i = 0;
00383 while (++i < argc) if (argv[i][0] == '-')
00384 switch (argv[i][1]) {
00385
00386
00387
00388 case 'M': if (current != root) cerr <<
00389 "Too late to initialize projectile mass!\n";
00390 projectile_mass = atof(argv[++i]);
00391 input.pmass = projectile_mass;
00392 break;
00393 case 'R': projectile_radius = atof(argv[++i]);
00394 break;
00395 case 'r': switch(argv[i][2]) {
00396 case '\0': if (current != root) cerr <<
00397 "Too late to initialize impact parameter!\n";
00398 if(input.rho_sq_max<0 && input.peri<0) {
00399 rho = atof(argv[++i]);
00400 peri = -1;
00401 input.rho_sq_max = rho*rho;
00402 input.peri = -1;
00403 }
00404 break;
00405 case 'm': if (current != root) cerr <<
00406 "Too late to initialize pericenter!\n";
00407 if(input.rho_sq_max<0 && input.peri<0) {
00408 peri = atof(argv[++i]);
00409 rho = -1;
00410 input.peri = peri;
00411 input.rho_sq_max = rho;
00412 }
00413 break;
00414 case '1': r1 = atof(argv[++i]);
00415 break;
00416 case '2': r2 = atof(argv[++i]);
00417 break;
00418 default: cerr << "Incorrect 'r' flag ignored\n";
00419 break;
00420 }
00421 break;
00422 case 'S': initial_separation = atof(argv[++i]);
00423 break;
00424 case 'v': if (current != root) cerr <<
00425 "Too late to initialize velocity at infinity!\n";
00426 if(input.rho_sq_max<0 && input.peri<0) {
00427 v_inf = atof(argv[++i]);
00428 input.v_inf = v_inf;
00429 }
00430 break;
00431
00432
00433
00434 case 'p':
00435 case 't': if (current == root)
00436 initialize_root(root, input.v_inf,
00437 input.rho_sq_min, input.rho_sq_max,
00438 input.peri,
00439 initial_separation,
00440 projectile_mass, projectile_radius);
00441 else
00442 split_particle(current, ecc, sma, planar,
00443 mass_ratio, r1, r2);
00444
00445 current = locate_label_and_set_defaults(root,
00446 &argv[i][1],
00447 planar);
00448 if (current == NULL) err_exit("Illegal node name.");
00449
00450
00451
00452 mass_ratio = DEFAULT_MASS_RATIO;
00453
00454
00455 ecc = -1;
00456 sma = -1;
00457 r1 = DEFAULT_R1;
00458 r2 = DEFAULT_R2;
00459
00460 break;
00461
00462
00463
00464 case 'a': sma = atof(argv[++i]);
00465 break;
00466 case 'e': ecc = atof(argv[++i]);
00467 break;
00468 case 'q': mass_ratio = atof(argv[++i]);
00469 break;
00470
00471 case 'P': switch(argv[i][2]) {
00472 case '-': planar = -1;
00473 break;
00474 case '0': planar = 0;
00475 break;
00476 case '+': planar = 1;
00477 break;
00478 case '\0': if (planar == 0)
00479 planar = 1;
00480 else
00481 planar = 0;
00482 break;
00483 default: cerr << "Incorrect 'P' flag ignored\n";
00484 break;
00485 }
00486 break;
00487
00488 case 'd': debug = 1 - debug;
00489 break;
00490 case 's': break;
00491
00492 default: cerr << "usage: mkscat [-d] [-s #]"
00493 << " [-M #] [-r #] [-rm #] [-v #] [-R #] [-S #]"
00494 << " [ -t/p... [-a #] [-e #] [-q #] [-P[+/-]"
00495 << " [-r1 #] [-r2 #] ] [-t/p... ...]"
00496 << endl;
00497 exit(1);
00498 }
00499
00500
00501
00502 if (current == root)
00503 initialize_root(root, input.v_inf, input.rho_sq_min, input.rho_sq_max,
00504 input.peri,
00505 initial_separation,
00506 projectile_mass, projectile_radius);
00507 else
00508 split_particle(current, ecc, sma, planar,
00509 mass_ratio, r1, r2);
00510
00511
00512
00513
00514 int id = 0;
00515 sdyn* b = first_leaf(root);
00516 while (b) {
00517 b->set_index(++id);
00518 b = next_leaf(b);
00519 }
00520
00521
00522
00523 root->log_history(argc, argv);
00524
00525 char seedlog[80];
00526 sprintf(seedlog, " random seed = %d",
00527 random_seed);
00528 root->log_comment(seedlog);
00529
00530 if (0) {
00531 cerr << "mkscat: pretty-print system (seed = "
00532 << random_seed << "):\n";
00533 pp(root, cerr);
00534 }
00535
00536 return root;
00537 }
00538
00539 #define MAX_ARGS 256
00540 #define TEXT_BUFFER_SIZE 1024
00541
00542 static char temp[TEXT_BUFFER_SIZE];
00543 static char* name = "parse_string";
00544
00545
00546
00547
00548
00549 void parse_string(char* s, int& argc, char* argv[]) {
00550
00551 int length = strlen(s);
00552 if (length >= TEXT_BUFFER_SIZE) err_exit("String too long.");
00553
00554 argv[0] = name;
00555 argc = 1;
00556
00557 int first = 0, last = -1;
00558
00559 for (int i = 0; i <= length; i++) {
00560 temp[i] = s[i];
00561 if (temp[i] == ' ' || i == length) {
00562 if (last >= 0) {
00563 temp[i] = '\0';
00564 argv[argc++] = temp + first;
00565 }
00566 last = -1;
00567 } else {
00568 if (last < 0) first = i;
00569 last = i;
00570 }
00571 }
00572 }
00573
00574
00575 sdyn* mkscat(char* s, sigma_input &input) {
00576
00577 int argc;
00578 char* argv[MAX_ARGS];
00579
00580 parse_string(s, argc, argv);
00581 if (argc > MAX_ARGS) err_exit("Too many arguments.");
00582
00583 return mkscat(argc, argv, input);
00584 }
00585
00586 #endif