00001
00035
00036
00037
00038
00039 #include "dyn.h"
00040
00041 #ifdef TOOLBOX
00042
00043 local void add_dynamics(dyn* cm, real ecc, real energy)
00044 {
00045 dyn* primary = cm->get_oldest_daughter();
00046 dyn* secondary = primary->get_younger_sister();
00047
00048 real m_total = cm->get_mass();
00049 real m1 = primary->get_mass();
00050 real m2 = secondary->get_mass();
00051
00052
00053
00054 kepler k;
00055
00056 real peri = 1;
00057 if (ecc == 1) peri = 0;
00058
00059
00060
00061 real mean_anomaly = randinter(-PI, PI);
00062
00063
00064
00065
00066 energy = -energy;
00067
00068 make_standard_kepler(k, 0, m_total, energy, ecc,
00069 peri, mean_anomaly);
00070
00071
00072
00073
00074 set_random_orientation(k);
00075
00076
00077
00078 primary->set_pos(-m2 * k.get_rel_pos() / m_total);
00079 primary->set_vel(-m2 * k.get_rel_vel() / m_total);
00080
00081 secondary->set_pos(m1 * k.get_rel_pos() / m_total);
00082 secondary->set_vel(m1 * k.get_rel_vel() / m_total);
00083 }
00084
00085 local real minimum_semi_major_axis(dyn* b1, dyn* b2)
00086 {
00087 real ms_prim = b1->get_starbase()->conv_m_dyn_to_star(b1->get_mass());
00088 real ms_sec = b2->get_starbase()->conv_m_dyn_to_star( b2->get_mass());
00089 real rs_prim = b1->get_starbase()->conv_r_star_to_dyn(ms_prim);
00090 real rs_sec = b2->get_starbase()->conv_r_star_to_dyn(ms_sec);
00091 real ms_tot = ms_prim + ms_sec;
00092
00093 real sma_prim = 2.2*rs_prim*pow(ms_tot/ms_prim, ONE_THIRD);
00094 real sma_sec = 2.2*rs_sec*pow(ms_tot/ms_sec, ONE_THIRD);
00095
00096
00097 return min(sma_prim, sma_sec);
00098 }
00099
00100 local void add_secondary(node* original, real mass_ratio)
00101 {
00102 node* primary = new node;
00103 node* secondary = new node;
00104
00105
00106
00107 original->set_oldest_daughter(primary);
00108
00109 primary->set_parent(original);
00110 secondary->set_parent(original);
00111
00112 primary->set_younger_sister(secondary);
00113 secondary->set_elder_sister(primary);
00114
00115
00116
00117 primary->set_mass(original->get_mass());
00118 secondary->set_mass(mass_ratio*original->get_mass());
00119 original->inc_mass(secondary->get_mass());
00120
00121
00122
00123 if (original->get_name() == NULL)
00124 if (original->get_index() >= 0) {
00125 char tmp[64];
00126 sprintf(tmp, "%d", original->get_index());
00127 original->set_name(tmp);
00128 }
00129
00130 if (original->get_name() != NULL) {
00131
00132
00133
00134 primary->set_name(original->get_name());
00135 secondary->set_name(original->get_name());
00136 strcat(primary->get_name(), "a");
00137 strcat(secondary->get_name(), "b");
00138
00139
00140
00141 char tmp[256];
00142 sprintf(tmp, "(%s,%s)", primary->get_name(), secondary->get_name());
00143 original->set_name(tmp);
00144 }
00145 }
00146
00147 local void mkbinary(dyn* b, real lower, real upper,
00148 int select, int option, real emax)
00149 {
00150
00151
00152
00153
00154 real frac = upper/lower;
00155
00156 for_all_daughters(dyn, b, bi)
00157 if(!bi->is_parent()) {
00158 add_secondary(bi, 0.0001);
00159 }
00160
00161 for_all_daughters(dyn, b, bi)
00162 if (bi->get_oldest_daughter()) {
00163
00164 dyn* primary = bi->get_oldest_daughter();
00165 dyn* secondary = primary->get_younger_sister();
00166 real m_total = bi->get_mass();
00167 real mu = primary->get_mass() * secondary->get_mass() / m_total;
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 real ecc, energy = 0;
00204
00205 if (select == 1) {
00206
00207 real l_const, sma, angular_momentum;
00208
00209 if (option == 2) {
00210 bool detached = false;
00211 real a_min = minimum_semi_major_axis(primary, secondary);
00212 if (pow(upper, 2) <= a_min*m_total*(1-pow(ecc, 2)))
00213 err_exit(
00214 "mkbinary: Illegal limits on angular momentum");
00215 do {
00216 ecc = sqrt(randinter(0,emax));
00217 l_const = log(upper) - log(lower);
00218 angular_momentum = lower * pow(frac, randinter(0,1));
00219 sma = pow(angular_momentum, 2)
00220 / (m_total*(1-pow(ecc, 2)));
00221 if (sma*(1-pow(ecc, 2)) > a_min) detached = true;
00222 }
00223 while(!detached);
00224 }
00225 else {
00226 ecc = sqrt(randinter(0,emax));
00227 l_const = log(upper) - log(lower);
00228 angular_momentum = lower * pow(frac, randinter(0,1));
00229 sma = pow(angular_momentum, 2) / (m_total*(1-pow(ecc, 2)));
00230 }
00231 energy = 0.5 * m_total / sma;
00232 }
00233
00234 else if (select == 2) {
00235
00236 real semi_major_axis, a_const;
00237
00238 if (option >= 2) {
00239 bool detached = false;
00240 real a_min = minimum_semi_major_axis(primary, secondary);
00241 if(upper<=a_min)
00242 err_exit(
00243 "mkbinary: Illegal limits on angular momentum");
00244
00245 if (option == 3) {
00246 real pericenter, apocenter;
00247 do {
00248 ecc = sqrt(randinter(0,emax));
00249 pericenter = lower*(1-ecc);
00250 apocenter = upper*(1+ecc);
00251 a_const = log(upper) - log(lower);
00252 semi_major_axis = lower*exp(randinter(0., a_const));
00253 if (semi_major_axis*(1-pow(ecc, 2)) > a_min &&
00254 (semi_major_axis > pericenter &&
00255 semi_major_axis < apocenter))
00256 detached = true;
00257 }
00258 while(!detached);
00259 }
00260 else {
00261
00262
00263
00264
00265
00266
00267 do {
00268 ecc = sqrt(randinter(0,emax));
00269 a_const = log(upper) - log(lower);
00270 semi_major_axis = lower*exp(randinter(0., a_const));
00271 if(semi_major_axis*(1-pow(ecc, 2))>a_min)
00272 detached = true;
00273 }
00274 while(!detached);
00275 }
00276 }
00277 else {
00278 ecc = sqrt(randinter(0,emax));
00279 a_const = log(upper) - log(lower);
00280 semi_major_axis = lower*exp(randinter(0., a_const));
00281 }
00282 energy = 0.5 * m_total / semi_major_axis;
00283 }
00284
00285 else {
00286
00287 ecc = sqrt(randinter(0,emax));
00288 energy = lower * pow(frac, randinter(0,1));
00289 if (option == 1)
00290 energy /= mu;
00291 else if (option == 3)
00292 energy *= m_total / mu;
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 add_dynamics(bi, ecc, energy);
00305 add_dynamics(bi, ecc, 2*energy);
00306 add_dynamics(bi, ecc, 4*energy);
00307 add_dynamics(bi, ecc, 8*energy);
00308 }
00309 }
00310
00311 local void scale_limits(real& e1, real& e2, int option,
00312 int N, real M, real E)
00313 {
00314 real scale = 1.0;
00315
00316 PRL(E);
00317 if (option == 3) {
00318
00319
00320
00321 scale = -E / M;
00322
00323 } else if (option != 2) {
00324
00325
00326
00327 scale = -E / (1.5*N);
00328 PRL(scale);
00329 }
00330
00331 e1 *= scale;
00332 e2 *= scale;
00333 }
00334
00335 void main(int argc, char ** argv)
00336 {
00337 real lower = 1.0, upper = 1.0;
00338 real emax = 1;
00339 int function_select = 3;
00340 int option = 1;
00341 int random_seed = 0;
00342 char seedlog[64];
00343
00344 check_help();
00345
00346 extern char *poptarg;
00347 int c;
00348 char* param_string = "f:l:s:o:u:e:";
00349
00350 while ((c = pgetopt(argc, argv, param_string)) != -1)
00351 switch(c) {
00352
00353 case 'f': function_select = atoi(poptarg);
00354 break;
00355 case 'l': lower = atof(poptarg);
00356 break;
00357 case 'o': option= atoi(poptarg);
00358 break;
00359 case 'e': emax = atof(poptarg);
00360 break;
00361 case 's': random_seed = atoi(poptarg);
00362 break;
00363 case 'u': upper = atof(poptarg);
00364 break;
00365 case '?': params_to_usage(cerr, argv[0], param_string);
00366 get_help();
00367 exit(1);
00368 }
00369
00370 if (lower <= 0 || upper <= 0 || lower > upper)
00371 err_exit("mkbinary: Illegal limits");
00372
00373 dyn* b;
00374 b = get_dyn(cin);
00375
00376 b->log_history(argc, argv);
00377
00378 int actual_seed = srandinter(random_seed);
00379
00380 sprintf(seedlog, " random number generator seed = %d",
00381 actual_seed);
00382 b->log_comment(seedlog);
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 char* energy_string = "initial_total_energy";
00393
00394 if (function_select == 1) {
00395 if (b->get_starbase()->get_stellar_evolution_scaling()) {
00396 real scale = sqrt(b->get_starbase()->conv_m_star_to_dyn(1)
00397 * b->get_starbase()->conv_r_star_to_dyn(1));
00398 lower *= scale;
00399 upper *= scale;
00400 }
00401 else
00402 cerr << "mkbinary: Using unscaled angular-momentum limits.\n";
00403 }
00404 else if (function_select == 2) {
00405 if (b->get_starbase()->conv_r_star_to_dyn(1)>0) {
00406 lower = b->get_starbase()->conv_r_star_to_dyn(lower);
00407 upper = b->get_starbase()->conv_r_star_to_dyn(upper);
00408 }
00409 else
00410 cerr << "mkbinary: Using unscaled semi-major axis limits.\n";
00411 }
00412 else if (function_select == 3) {
00413 if (find_qmatch(b->get_dyn_story(), energy_string))
00414 scale_limits(lower, upper, option,
00415 b->n_daughters(), b->get_mass(),
00416 getrq(b->get_dyn_story(), energy_string));
00417 else
00418 cerr << "mkbinary: Using unscaled energy limits.\n";
00419 }
00420
00421 mkbinary(b, lower, upper, function_select, option, emax);
00422
00423 put_dyn(cout, *b);
00424 rmtree(b);
00425
00426 }
00427 #endif