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