Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

hdyn_io.C

Go to the documentation of this file.
00001 
00002        //=======================================================//    _\|/_
00003       //  __  _____           ___                    ___       //      /|\ ~
00004      //  /      |      ^     |   \  |         ^     |   \     //          _\|/_
00005     //   \__    |     / \    |___/  |        / \    |___/    //            /|\ ~
00006    //       \   |    /___\   |  \   |       /___\   |   \   // _\|/_
00007   //     ___/   |   /     \  |   \  |____  /     \  |___/  //   /|\ ~
00008  //                                                       //            _\|/_
00009 //=======================================================//              /|\ ~
00010 
00011 // hdyn_io:  Starlab hdyn-specific I/O functions.
00012 
00013 #include "hdyn.h"
00014 #include "util_io.h"
00015 #include "../evolve/kira_defaults.h"
00016 
00017 #ifndef TOOLBOX
00018 
00019 // Initialize all static hdyn data here.
00020 
00021 kira_counters *hdyn::kc                         = NULL;
00022 kira_options *hdyn::options                     = NULL;
00023 kira_diag *hdyn::diag                           = NULL;
00024 
00025 bool hdyn::use_dstar                            = false;
00026 
00027 real hdyn::stellar_encounter_criterion_sq       = 0;
00028 real hdyn::stellar_merger_criterion_sq          = 0;
00029 real hdyn::stellar_capture_criterion_sq         = 0;
00030 
00031 hdyn** hdyn::perturbed_list                     = NULL;
00032 int  hdyn::n_perturbed                          = 0;
00033 
00034 real hdyn::eta                                  = DEFAULT_ETA;
00035 real hdyn::eps                                  = DEFAULT_EPS;
00036 real hdyn::eps2                                 = (DEFAULT_EPS*DEFAULT_EPS);
00037 
00038 real hdyn::d_min_fac                            = DEFAULT_D_MIN_FAC;
00039 real hdyn::d_min_sq                             = 0;    // compute at runtime
00040 real hdyn::lag_factor                           = DEFAULT_LAG_FACTOR;
00041 real hdyn::mbar                                 = 0;    // compute at runtime
00042 
00043 real hdyn::gamma2                               = DEFAULT_GAMMA;
00044 real hdyn::gamma23                              = VERY_LARGE_NUMBER;
00045 
00046 real hdyn::initial_step_limit                   = 0;
00047 real hdyn::step_limit                           = 0;
00048 real hdyn::unpert_step_limit                    = 1;
00049 
00050 real hdyn::scaled_stripping_radius              = -1;   // no value set
00051 
00052 int hdyn::max_slow_factor                       = DEFAULT_MAX_SLOW_FACTOR;
00053 real hdyn::max_slow_perturbation                = DEFAULT_MAX_SLOW_PERTURBATION;
00054 real hdyn::max_slow_perturbation_sq          = DEFAULT_MAX_SLOW_PERTURBATION_SQ;
00055 
00056 
00057 void check_sanity_of_timestep(xreal & time, real & timestep)
00058 {
00059     if (timestep > 0) {
00060 
00061         // Sanity check for timestep...
00062 
00063         if (fmod(time,  timestep) != 0.0) {
00064 
00065             cerr << " impossible timestep error \n";
00066 
00067             cerr.precision(HIGH_PRECISION);
00068             PRL(time);
00069             PRL(timestep);
00070             PRL(1.0/timestep);
00071             PRL(fmod(time,  timestep));
00072             cerr << " Perform correction... \n";
00073 
00074             real corrected_timestep = 1.0;
00075             while (corrected_timestep > timestep*1.1)
00076                 corrected_timestep *= 0.5;
00077 
00078             timestep = corrected_timestep;
00079             real  err;
00080             if ((err = fmod(time,  timestep)) != 0.0) {
00081                 time = time - err;
00082                 if (err > 0.5*timestep)
00083                     time += timestep;
00084             }
00085             PRL(time);
00086             PRL(timestep);
00087         }
00088     }
00089 }
00090 
00091 static bool read_xreal = false;
00092 
00093 void hdyn::print_static(ostream& s)             // default = cerr
00094 {
00095     _dyn:_:print_static(s);
00096 
00097     s << "kc = " << kc << endl;
00098     s << "options = " << options << endl;
00099     s << "diag = " << diag << endl;
00100 
00101     s << "use_dstar = " << use_dstar << endl;
00102 
00103     s << "stellar_encounter_criterion_sq = "
00104       << stellar_encounter_criterion_sq << endl;
00105     s << "stellar_merger_criterion_sq = "
00106       << stellar_merger_criterion_sq << endl;
00107     s << "stellar_capture_criterion_sq = "
00108       << stellar_capture_criterion_sq << endl;
00109 
00110     s << "perturbed_list = " << perturbed_list << endl;
00111     s << "n_perturbed = " << n_perturbed << endl;
00112 
00113     s << "eta = " << eta << endl;
00114     s << "eps = " << eps << endl;
00115     s << "eps2 = " << eps2 << endl;
00116 
00117     s << "d_min_fac = " << d_min_fac << endl;
00118     s << "d_min_sq = " << d_min_sq << endl;
00119     s << "lag_factor = " << lag_factor << endl;
00120     s << "mbar = " << mbar << endl;
00121 
00122     s << "gamma2 = " << gamma2 << endl;
00123     s << "gamma23 = " << gamma23 << endl;
00124 
00125     s << "initial_step_limit = " << initial_step_limit << endl;
00126     s << "step_limit = " << step_limit << endl;
00127     s << "unpert_step_limit = " << unpert_step_limit << endl;
00128 
00129     s << "scaled_stripping_radius = " << scaled_stripping_radius << endl;
00130   
00131     s << "max_slow_factor = " << max_slow_factor << endl;
00132     s << "max_slow_perturbation = " << max_slow_perturbation << endl;
00133     s << "max_slow_perturbation_sq = " << max_slow_perturbation_sq << endl;
00134 }
00135 
00136 istream & hdyn::scan_dyn_story(istream & s)
00137 {
00138     char input_line[MAX_INPUT_LINE_LENGTH];
00139     real last_real = false;
00140 
00141     while (get_line(s, input_line), strcmp(END_DYNAMICS, input_line)) {
00142 
00143         char keyword[MAX_INPUT_LINE_LENGTH];
00144         const char *val = getequals(input_line, keyword);
00145 
00146         // See xreal notes in dyn_io.C...
00147 
00148         if (!strcmp("real_system_time", keyword)) {
00149 
00150             read_xreal = true;
00151             last_real = true;
00152 
00153         } else if (!strcmp("system_time", keyword)) {
00154 
00155             // Check input format before reading.
00156 
00157             if (!last_real) read_xreal = false;
00158 
00159             if (read_xreal) {
00160 
00161                 //cerr << "hdyn::scan_dyn_story: input "
00162                 //     << "time data type is xreal"
00163                 //     << endl;
00164 
00165                 set_system_time(get_xreal_from_input_line(input_line));
00166 
00167             } else {
00168 
00169                 if (sizeof(xreal) != sizeof(real))      // crude test...
00170                     cerr << "hdyn::scan_dyn_story: input "
00171                          << "time data type is real"
00172                          << endl;
00173 
00174                 real_system_time = system_time = strtod(val, NULL);
00175 
00176             }
00177             // PRC(system_time); xprint(system_time);
00178 
00179         } else {
00180 
00181             last_real = false;
00182 
00183             if (!strcmp("t", keyword)) {
00184 
00185                 if (read_xreal)
00186                     time = get_xreal_from_input_line(input_line);
00187                 else
00188                     time = strtod(val, NULL);
00189 
00190             } else if (!strcmp("dt", keyword))
00191                 timestep = strtod(val, NULL);
00192             else if (!strcmp("m", keyword))
00193                 mass = strtod(val, NULL);
00194             else if (!strcmp("r", keyword))
00195                 set_vector_from_input_line(pos, input_line);
00196             else if (!strcmp("v", keyword)) {
00197                 set_vector_from_input_line(vel, input_line);
00198                 posvel = pos*vel;
00199             } else if (!strcmp("a", keyword))
00200                 set_vector_from_input_line(acc, input_line);
00201             else if (!strcmp("pot", keyword))
00202                 pot = strtod(val, NULL);
00203             else if (!strcmp("R_eff", keyword))
00204                 radius = strtod(val, NULL);
00205             else if (!strcmp("steps", keyword))
00206                 steps = strtod(val, NULL);
00207             else if (!strcmp("dir_f", keyword))
00208                 direct_force = strtod(val, NULL);
00209             else if (!strcmp("indir_f", keyword))
00210                 indirect_force = strtod(val, NULL);
00211 
00212             // NOTE:  Complete initialization of unperturbed and slow
00213             // binary structures requires knowledge of the tree structure
00214             // that is available only after the entire tree has been
00215             // read in.  The get_hdyn() macro completes the setup of
00216             // these parameters after the tree is known.
00217 
00218             // Unperturbed motion:
00219 
00220             else if (!strcmp("dt_u", keyword))
00221                 unperturbed_timestep = strtod(val, NULL);
00222             else if (!strcmp("full_u", keyword))
00223                 fully_unperturbed = strtol(val, NULL, 10);
00224 
00225             // Slow binary motion:
00226 
00227             else if (!strcmp("slow_kappa", keyword)) {
00228 
00229                 // Component of a slow binary.  The information needed to
00230                 // recognize and reconstruct the slow structure is attached
00231                 // to the ELDER sister only.
00232 
00233                 int k = strtol(val, NULL, 10);
00234 
00235                 if (k > 1) {
00236 
00237                     // Create the slow structure.  Note that we won't need
00238                     // to apply modifications to acc or the sister data.
00239 
00240                     slow = new slow_binary(k);
00241                     slow->set_dtau(timestep/k);
00242 
00243                     // t_init, t_apo, and tau will be set in due course...
00244 
00245                 }
00246 
00247             } else if (!strcmp("slow_t_init", keyword)) {
00248 
00249                 if (slow) {
00250                     slow->set_t_init( strtod(val,NULL) );
00251                 }
00252 
00253             } else if (!strcmp("slow_t_apo", keyword)) {
00254 
00255                 if (slow) {
00256                     slow->set_t_apo( strtod(val,NULL) );
00257                 }
00258 
00259             } else if (!strcmp("slow_tau", keyword)) {
00260 
00261                 if (slow) {
00262                     slow->set_tau( strtod(val,NULL) );
00263                     slow->init_tau_pred();
00264                 }
00265 
00266             } else
00267 
00268                 add_story_line(dyn_story, input_line);
00269         }
00270     }
00271 
00272     check_sanity_of_timestep(time, timestep);
00273 
00274     return s;
00275 }
00276 
00277 // Temporary flag to force unformatted output:
00278 
00279 static bool write_unformatted = false;
00280 
00281 // Accessors:
00282 
00283 void set_write_unformatted(bool u)      // default = true;
00284 {
00285     write_unformatted = u;
00286 }
00287 
00288 bool get_write_unformatted()
00289 {
00290     return write_unformatted;
00291 }
00292 
00293 // Another kludge -- we need to know if this print_dyn_story() is
00294 // part of a complete snapshot, or just a single node or subtree.
00295 // Set complete_system_dump before put_node, unset it afterward.
00296 
00297 static bool complete_system_dump = false;
00298 
00299 void set_complete_system_dump(bool d)                   // default = true
00300 {
00301     complete_system_dump = d;
00302 }
00303 
00304 ostream & hdyn::print_dyn_story(ostream & s,
00305                                 bool print_xreal,       // default = true
00306                                 int short_output)       // default = 0
00307 {
00308     // Modifications by Steve (5/01) to streamline output.
00309 
00310     int precision = 0;
00311     int use_floats = 0;
00312 
00313     // Two basic branches here:
00314     //
00315     //          1. short_output (full_dump mode)
00316     //          2. write_unformatted
00317     //
00318     // Note that write_unformatted is only relevant when short_output > 0.
00319     //
00320     // Short_output options (see also write_unformatted):
00321     //
00322     //          0:      normal (long) output
00323     //          1:      short output using current time, pos, ...
00324     //          2:      short output using current time, predicted pos, ...
00325     //          3:      as for 2, but mark as defunct
00326     //          4:      new (Steve, 7/01) to allow restart; combines hdyn
00327     //                  and tdyn...  Don't allow unformatted output.
00328     //
00329     // Short output is:  time, mass, pos, vel (options 1-3).
00330     //
00331     // Particle name is printed in node/util/tree_io.C
00332 
00333     bool short_short = (short_output && short_output != 4);
00334 
00335     if (write_unformatted && short_short) {
00336 
00337         // In this case, we have to do everything ourselves, and we
00338         // can't rely on the base class output functions to help us.
00339 
00340         // Note that short_output is implicit.
00341 
00342         if (is_root()) put_real_number(s, "  system_time  =  ",
00343                                        real_system_time);
00344 
00345         // Write time, mass, pos, and vel as unformatted data.
00346         // Allows significantly faster I/O, and converting doubles
00347         // to floats saves additional space.
00348 
00349         // *** Must coordinate with tdyn_io.C. ***
00350 
00351         vector putpos = pos;
00352         vector putvel = vel;
00353 
00354         if (short_output > 1) {
00355             putpos = pred_pos;
00356             putvel = pred_vel;
00357         }
00358 
00359         if (use_floats) {
00360 
00361             // Write floats.
00362 
00363             s << "t64mpv32 =" << endl;
00364             write_unformatted_real(s, system_time);
00365             write_unformatted32_real(s, mass);
00366             write_unformatted32_vector(s, putpos);
00367             write_unformatted32_vector(s, putvel);
00368 
00369         } else {
00370 
00371             // Write doubles.
00372 
00373             s << "tmpv =" << endl;
00374             write_unformatted_real(s, system_time);
00375             write_unformatted_real(s, mass);
00376             write_unformatted_vector(s, putpos);
00377             write_unformatted_vector(s, putvel);
00378         }
00379 
00380     } else {
00381 
00382         // For formatted output, we can rely on the _dyn_ output
00383         // functions to start us off as usual...
00384 
00385         _dyn_::print_dyn_story(s, print_xreal, short_output);
00386 
00387         if (!short_short) {
00388 
00389             put_real_number(s, "  steps  =  ", steps);
00390             put_real_number(s, "  dir_f  =  ", direct_force);
00391             put_real_number(s, "  indir_f  =  ", indirect_force);
00392 
00393             // Special cases for which only partial information is saved:
00394 
00395             if (kep) {
00396 
00397                 // Component of an unperturbed binary -- may be fully or
00398                 // partially unperturbed.  Store sufficient information for
00399                 // restart.  Other kepler data can be recomputed from hdyn.
00400                 //
00401                 // BOTH components carry full_u and dt_u information (no
00402                 // particular reason for this, but retain for consistency).
00403 
00404                 put_integer(s, "  full_u  =  ", fully_unperturbed);
00405                 put_real_number(s, "  dt_u  =  ", unperturbed_timestep);
00406             }
00407 
00408             if (slow) {
00409 
00410                 // Component of a slow binary.  The value of kappa serves
00411                 // as a flag for slow motion.  The information needed for
00412                 // restart is attached to the ELDER component only.
00413 
00414                 if (!elder_sister) {
00415                     put_integer(s, "  slow_kappa  =  ", get_kappa());
00416                     put_real_number(s, "  slow_t_init  =  ",
00417                                     slow->get_t_init());
00418                     put_real_number(s, "  slow_t_apo  =  ",
00419                                     slow->get_t_apo());
00420                     put_real_number(s, "  slow_tau  =  ", slow->get_tau());
00421                 }
00422             }
00423         }
00424     }
00425 
00426     if (short_output) {
00427 
00428         // Convenient to output Star quantities here too.
00429         // (Star output is now suppressed in tree_io in the
00430         // short_output case, and the tdyn input is simplest
00431         // when all relevant data are in Dyn.)
00432 
00433         if (use_sstar && sbase) {
00434 
00435             // Print out basic stellar information.
00436             // See inc/star/star_support.h for element_type.
00437 
00438             // put_string(s,      "  S  =  ",
00439             //            type_short_string(sbase->get_element_type()));
00440             put_integer(s,     "  S  =  ", (int)sbase->get_element_type());
00441 
00442             if (write_unformatted && short_short) {
00443 
00444                 // Always write floats for T and L.
00445 
00446                 s << "TL =" << endl;
00447                 write_unformatted32_real(s, sbase->temperature());
00448                 write_unformatted32_real(s, sbase->get_luminosity());
00449 
00450             } else {
00451                 put_real_number(s, "  T  =  ", sbase->temperature());
00452                 put_real_number(s, "  L  =  ", sbase->get_luminosity());
00453             }
00454         }
00455 
00456         // Use kep as a general-purpose flag here (careful!).
00457 
00458         if (kep)
00459             put_integer(s, "  kep  =  ", 1);
00460 #if 1
00461         else {
00462 
00463             // *** Hook for future treatment of lightly perturbed binaries.
00464             // *** Indicator is kep = 2; currently not used by tdyn.
00465 
00466             if (this != root                    // must check this...
00467                 && is_low_level_node()
00468                 && get_perturbation_squared() < SMALL_TDYN_PERT_SQ)
00469                 put_integer(s, "  kep  =  ", 2);
00470         }
00471 #endif
00472 
00473         // Defunct node:
00474         
00475         if (short_output == 3)
00476             put_integer(s, "  defunct  =  ", 1);
00477 
00478         // Add information on the system center to the root node.
00479         // Must do this explicitly here because story output is
00480         // suppressed in short_output mode.
00481 
00482         if (is_root()) {
00483 
00484             vector pos, vel;
00485             int which = get_std_center(this, pos, vel);
00486             put_real_vector(s, "  center_pos  =  ", pos);
00487             put_real_vector(s, "  center_vel  =  ", vel);
00488             put_integer(s, "  center_type  =  ", which);
00489 
00490             // Add extra information on other centers:
00491 
00492             if (get_external_field() > 0) {
00493                 refine_cluster_mass2(this);
00494                 if (find_qmatch(get_dyn_story(), "bound_center_pos")) {
00495                     vector bound_pos = getvq(get_dyn_story(),
00496                                              "bound_center_pos");
00497                     vector bound_vel = getvq(get_dyn_story(),
00498                                              "bound_center_vel");
00499                     put_real_vector(s, "  bound_center_pos  =  ", bound_pos);
00500                     put_real_vector(s, "  bound_center_vel  =  ", bound_vel);
00501                 }
00502             }
00503         }
00504 
00505         // Extra output for complete system dumps only.
00506 
00507         if (complete_system_dump) {
00508 
00509             if (external_field) {
00510 
00511                 // Not needed if short_output = 4, as the data are already
00512                 // contained in the dyn story...
00513 
00514                 if (short_output != 4) {
00515 
00516                     if (!is_root()) {
00517                         hdyn *top = get_top_level_node();
00518 
00519                         // The esc flag is probably redundant...
00520 
00521                         bool esc = false;
00522                         if (find_qmatch(top->get_dyn_story(), "esc"))
00523                             esc = getiq(top->get_dyn_story(), "esc");
00524                         put_integer(s, "  esc  =  ", esc);
00525 
00526                         if (find_qmatch(top->get_dyn_story(), "t_esc"))
00527                             put_real_number(s, "t_esc  =  ",
00528                                             getrq(top->get_dyn_story(),
00529                                                   "t_esc"));
00530                     }
00531                 }
00532             }
00533         }
00534     }
00535 
00536     return s;
00537 }
00538 
00539 typedef struct
00540 {
00541     hdyn* b;
00542     real  d;
00543 } bd_pair, *bd_pair_ptr;
00544 
00545 local int compare(const void * pi, const void * pj)
00546 {
00547     if (((bd_pair_ptr) pi)->d > ((bd_pair_ptr) pj)->d)
00548         return 1;
00549     else if (((bd_pair_ptr)pi)->d < ((bd_pair_ptr)pj)->d)
00550         return -1;
00551     else
00552         return 0;
00553 }
00554 
00555 void hdyn::print_perturber_list(ostream & s, char* pre)
00556 {
00557     // NOTE: 'this' is a binary center of mass.
00558 
00559     s << pre << "perturber list of " << format_label()
00560       << " [" << perturber_list << "]" << flush;
00561 
00562     if (!valid_perturbers || perturber_list == NULL) {
00563         s << " is invalid" << endl;
00564         return;
00565     }
00566 
00567     int np = n_perturbers;
00568 
00569     if (np <= 0) {
00570         s << " is empty (no perturbers)" << endl;
00571         return;
00572     }
00573 
00574     // Sort the perturbers by distance (between top-level nodes).
00575 
00576     hdyn* top = get_top_level_node();
00577 
00578     // s << "creating list" << endl << flush;
00579 
00580     bd_pair_ptr bd_list = new bd_pair[np];
00581     for (int i = 0; i < np; i++) {
00582         bd_list[i].b = perturber_list[i];
00583         if (perturber_list[i] && perturber_list[i]->is_valid()) {
00584             bd_list[i].d = square(perturber_list[i]
00585                                           ->get_top_level_node()->pos
00586                                   - top->pos);
00587         } else
00588             bd_list[i].d = VERY_LARGE_NUMBER;
00589     }
00590 
00591     // s << "sorting list" << endl << flush;
00592 
00593     qsort((void *)bd_list, (size_t)np, sizeof(bd_pair), compare);
00594 
00595     s << "  (" << np << " perturbers):";
00596     s << endl << pre << "    ";
00597     for (int i = 0; i < np; i++) {
00598         if (bd_list[i].b)
00599             bd_list[i].b->print_label(s);
00600         else
00601             s << "(null)";
00602         if ((i+1)%10 == 0) {
00603             if (i < np-1)
00604                 s << endl << pre << "    ";
00605         } else
00606             s << " ";
00607     }
00608     s << endl;
00609 
00610     delete [] bd_list;
00611 
00612     // s << "leaving print_perturber_list" << endl << flush;
00613 }
00614 
00615 void hdyn::find_print_perturber_list(ostream & s, char* pre)
00616 {
00617     s << pre << "perturber list node for " << format_label() << " is ";
00618 
00619     hdyn* pnode = find_perturber_node();
00620 
00621     if (!pnode) {
00622         s << "NULL" << endl;
00623         return;
00624     } else
00625         s << pnode->format_label() << endl;
00626 
00627     pnode->print_perturber_list(s, pre);
00628 }
00629 
00630 #else
00631 
00632 main(int argc, char** argv)
00633 {
00634     hdyn  * b;
00635     check_help();
00636 
00637     while (b = get_hdyn(cin)) {
00638         cout << "TESTING put_hdyn:" << endl;
00639         put_node(cout, *b);
00640         cout << "TESTING pp2()   :" << endl;
00641         pp2(b);
00642         delete b;
00643     }
00644     cerr << "Normal exit" << endl;
00645 }
00646 
00647 #endif

Generated at Sun Feb 24 09:57:03 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001