Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

dyn_story.C

Go to the documentation of this file.
00001 
00002        //=======================================================//    _\|/_
00003       //  __  _____           ___                    ___       //      /|\ ~
00004      //  /      |      ^     |   \  |         ^     |   \     //          _\|/_
00005     //   \__    |     / \    |___/  |        / \    |___/    //            /|\ ~
00006    //       \   |    /___\   |  \   |       /___\   |   \   // _\|/_
00007   //     ___/   |   /     \  |   \  |____  /     \  |___/  //   /|\ ~
00008  //                                                       //            _\|/_
00009 //=======================================================//              /|\ ~
00010 
00011 // dyn_story.C:  initialization of system parameters from input snapshots.
00012 //
00013 // Externally visible functions:
00014 //
00015 //      real get_initial_mass           // functions get_initial_mass and
00016 //      real get_initial_virial_radius  // get_initial_virial radius are
00017 //                                      // essentially identical
00018 //
00019 //      real get_initial_jacobi_radius  // similar to the above in general
00020 //                                      // approach, but more complex logic
00021 //
00022 //      void set_tidal_params           // set tidal parameters from the
00023 //                                      // input story
00024 //      void test_tidal_params          // check consistency of disk fields
00025 //
00026 //      void check_set_tidal            // check and set tidal parameters
00027 //      void check_set_plummer          // check and set Plummer parameters
00028 //      void check_set_power_law        // check and set power-law parameters
00029 //
00030 //      void check_set_external         // check and set all external fields
00031 
00032 // Created Aug/Sep 2001, Steve McMillan
00033 
00034 #include "dyn.h"
00035 
00036 // Require that all systems have known initial mass and initial virial
00037 // radius.  These may be set by the make_* functions or by the function
00038 // scale.  In general, kira or other applications should *not* compute
00039 // these quantities -- better to determine them in advance.
00040 
00041 // get_initial_mass:  Read the initial_mass variable from the log story.
00042 //                    If not specified, use the input value, if any.
00043 //                    Otherwise, use a default.
00044 //
00045 //                    Write the new variable to the log story in the latter
00046 //                    two cases.
00047 
00048 static bool mass_msg = true;
00049 
00050 real get_initial_mass(dyn* b,
00051                       bool verbose,                     // default = false
00052                       bool mass_set,                    // default = false
00053                       real input_mass)                  // default = 0
00054 {
00055     real initial_mass = getrq(b->get_log_story(), "initial_mass");
00056 
00057     if (initial_mass > 0) {
00058 
00059         // The input snapshot has the information needed.  Snapshot
00060         // data OVERRIDES any input value.
00061 
00062         if (verbose && mass_msg)
00063             cerr << "read initial_mass = " << initial_mass
00064                  << " from input snapshot" << endl;
00065 
00066     } else {
00067 
00068         // See if input_mass exists, or use a default.
00069 
00070         if (mass_set) {
00071 
00072             if (verbose && mass_msg) {
00073 
00074                 cerr << "setting initial mass = " << input_mass << endl;
00075 
00076                 if (b->get_system_time() > 0)
00077                     cerr << endl
00078                          << "warning: setting initial mass with time > 0"
00079                          << endl;
00080             }
00081 
00082             initial_mass = input_mass;
00083 
00084         } else {
00085 
00086             if (b->get_system_time() <= 0)
00087 
00088                 // Simply compute the mass if t <= 0.
00089 
00090                 initial_mass = total_mass(b);
00091 
00092             else {
00093 
00094                 // Two options here:
00095                 //
00096                 //      1. Return a negative number, requiring the user
00097                 //         to provide the necessary data.
00098                 //
00099                 //      2. Adopt a default mass of 1, printing a message
00100                 //         so the user can use "make..." or "scale" to do
00101                 //         this properly.
00102                 //
00103                 // Choose (1) for now.
00104 
00105 #if 1
00106                 initial_mass = -1;
00107 
00108                 if (verbose && mass_msg)
00109                     cerr << "get_initial_mass:  initial_mass unknown"
00110                          << " (set with scale)" << endl;
00111 #else
00112                 initial_mass = 1;
00113 
00114                 if (verbose && mass_msg)
00115                     cerr << "adopting default initial_mass = "
00116                          << initial_mass << endl;
00117 #endif
00118             }
00119         }
00120 
00121         // Write the initial mass to the log story.
00122 
00123         if (initial_mass > 0)
00124             putrq(b->get_log_story(), "initial_mass", initial_mass,
00125                   HIGH_PRECISION);
00126     }
00127 
00128     mass_msg = false;
00129     return initial_mass;
00130 }
00131 
00132 // get_initial_virial_radius:  Read the initial_virial_radius variable from
00133 //                             the log story.
00134 //                             If not specified, use the input value, if any.
00135 //                             Otherwise, use a default.
00136 //
00137 //                             Write the new variable to the log story in the
00138 //                             latter two cases.
00139 
00140 static bool rvir_msg = true;
00141 
00142 real get_initial_virial_radius(dyn* b,
00143                                bool verbose,            // default = false
00144                                bool r_virial_set,       // default = false
00145                                real input_r_virial)     // default = 0
00146 {
00147     real r_virial = getrq(b->get_log_story(), "initial_rvirial");
00148 
00149     if (r_virial > 0) {
00150 
00151         // The input snapshot has the information needed.  Snapshot
00152         // data OVERRIDES any input value.
00153 
00154         if (verbose && rvir_msg)
00155             cerr << "read initial r_virial = " << r_virial
00156                  << " from input snapshot" << endl;
00157 
00158     } else {
00159 
00160         // See if input_r_virial exists, or use a default.
00161 
00162         if (r_virial_set) {
00163 
00164             if (verbose && rvir_msg) {
00165 
00166                 cerr << "setting initial r_virial = " << input_r_virial << endl;
00167 
00168                 if (b->get_system_time() > 0)
00169                     cerr << endl
00170                          << "warning: setting initial r_virial with time > 0"
00171                          << endl;
00172             }
00173 
00174             r_virial = input_r_virial;
00175 
00176         } else {
00177 
00178             // Two options here:
00179             //
00180             //  1. Return a negative number, requiring the user
00181             //     to provide the necessary data.
00182             //
00183             //  2. Adopt a default radius of 1, printing a message
00184             //     so the user can use "make..." or "scale" to do
00185             //     this properly.
00186             //
00187             // Choose (1) for now.
00188 
00189 #if 1
00190             r_virial = -1;
00191 
00192             if (verbose && rvir_msg)
00193                 cerr << "get_initial_virial_radius:  "
00194                      << "initial_rvirial unknown (set with scale)" << endl;
00195 #else
00196             r_virial = 1;
00197 
00198             if (verbose && rvir_msg)
00199                 cerr << "adopting default initial_rvirial = "
00200                      << r_virial << endl;
00201 #endif
00202         }
00203 
00204         // Write the virial radius to the log story.
00205 
00206         if (r_virial > 0)
00207             putrq(b->get_log_story(), "initial_rvirial", r_virial);
00208     }
00209 
00210     rvir_msg = false;
00211     return r_virial;
00212 }
00213 
00214 // get_initial_jacobi_radius:  Read the initial_jacobi_radius variable from
00215 //                             the log story.
00216 //                             If not specified, use the input value, if any,
00217 //                             modified in various ways.  There is no default.
00218 //
00219 //                             For use by kira, if specified, the variable
00220 //                             kira_initial_jacobi_radius takes precedence
00221 //                             over all other possibilities.
00222 //
00223 //                             Write the new variable to the log story if
00224 //                             a value can be determined.
00225 
00226 real get_initial_jacobi_radius(dyn* b,
00227                                real r_virial,
00228                                bool verbose,            // default = false
00229                                bool r_jacobi_set,       // default = false
00230                                real input_r_jacobi)     // default = 0
00231 {
00232     real initial_r_jacobi = -1;
00233 
00234     // Determine the initial Jacobi radius of the system.  This radius
00235     // may be input as an argument, or it may be derived from the
00236     // information in the input snapshot.  Unlike r_virial, the input
00237     // value takes precedence over initial data found in the input
00238     // snapshot, although it is superceded by any "kira" data found
00239     // in that file.  The convention is such that, if a non-kira
00240     // version of initial_r_jacobi is found in the input snapshot, the
00241     // input value will *scale* that number.  A kira version is used
00242     // as is.  Otherwise, the input value scales the virial radius
00243     // (hence the two tests of r_jacobi_set below).
00244     //
00245     // (Messy logic actually makes it possible to control the
00246     //  Jacobi radius in a fairly natural way...)
00247 
00248     // See if a kira_initial_jacobi_radius exists in the input file.
00249     // If it does, it TAKES PRECEDENCE over any other setting.
00250 
00251     if (find_qmatch(b->get_log_story(), "kira_initial_jacobi_radius")) {
00252 
00253         real kira_initial_jacobi_radius
00254             = getrq(b->get_log_story(), "kira_initial_jacobi_radius");
00255 
00256         if (kira_initial_jacobi_radius > 0) {
00257 
00258             initial_r_jacobi = kira_initial_jacobi_radius;
00259 
00260             if (verbose) {
00261                 cerr << "using initial Jacobi radius ";
00262                 PRL(kira_initial_jacobi_radius);
00263                 cerr << "    from input snapshot" << endl;
00264 
00265                 if (r_jacobi_set)
00266                     cerr << "ignoring input value " << input_r_jacobi << endl;
00267             }
00268 
00269         } else {
00270 
00271             if (verbose)
00272                 cerr << "warning: error reading "
00273                      << "kira_initial_jacobi_radius "
00274                      << "from input snapshot"
00275                      << endl;
00276             else
00277                 err_exit(
00278                 "Error reading kira_initial_jacobi_radius from input snapshot");
00279 
00280         }
00281     }
00282 
00283     if (initial_r_jacobi < 0) {
00284 
00285         // No kira Jacobi radius known.  See if we can determine the
00286         // system's initial Jacobi radius from the input snapshot.
00287 
00288         if (find_qmatch(b->get_log_story(), "initial_rtidal_over_rvirial")) {
00289 
00290             // The input snapshot contains an initial "tidal" radius.  Most
00291             // likely the initial model is a King profile and this is the
00292             // King radius (misnamed for historical reasons -- it may or
00293             // may not have anything to do with a tidal cutoff).
00294             // Alternatively, the ratio may have been set by add_tidal.
00295 
00296             real r_jacobi_over_r_virial = getrq(b->get_log_story(),
00297                                                 "initial_rtidal_over_rvirial");
00298 
00299             if (r_jacobi_over_r_virial > 0) {
00300 
00301                 initial_r_jacobi = r_jacobi_over_r_virial * r_virial;
00302 
00303                 if (verbose) {
00304                     cerr << "got r_jacobi_over_r_virial = "
00305                          << r_jacobi_over_r_virial
00306                          << " from input snapshot"
00307                          << endl;
00308                     if (initial_r_jacobi > 0) {
00309                         cerr << "    setting ";
00310                         PRL(initial_r_jacobi);
00311                     }
00312                 }
00313 
00314             } else {
00315 
00316                 if (verbose)
00317                     cerr << "warning: error reading "
00318                          << "initial_rtidal_over_rvirial from input snapshot"
00319                          << endl;
00320                 else
00321                     err_exit(
00322               "Error reading initial_rtidal_over_rvirial from input snapshot");
00323             }
00324         }
00325 
00326         // See if there was any input value, and resolve any conflicts.
00327 
00328         if (r_jacobi_set) {
00329 
00330             // An input value was specified.
00331 
00332             if (initial_r_jacobi > 0) {
00333 
00334                 // The Jacobi radius has been specified both in the input file
00335                 // and as an input argument.  If the model is an anisotropic
00336                 // King model, we must use the snapshot data and ignore the
00337                 // argument.  Otherwise, use the input argument to scale the
00338                 // "known" value.
00339 
00340                 // The variable alpha3_over_alpha1 is set *only* by
00341                 // make_aniso_king.
00342 
00343                 if (find_qmatch(b->get_log_story(), "alpha3_over_alpha1")) {
00344 
00345                     if (verbose)
00346                         cerr << "ignoring input Jacobi radius ("
00347                              << input_r_jacobi << ") for anisotropic King model"
00348                              << endl;
00349 
00350                 } else {
00351 
00352                     if (verbose)
00353                         cerr << "input Jacobi radius ("
00354                              << input_r_jacobi << ") scales initial value "
00355                              << initial_r_jacobi
00356                              << endl
00357                              << "    from input snapshot"
00358                              << endl;
00359 
00360                     initial_r_jacobi *= input_r_jacobi;
00361 
00362                 }
00363 
00364             } else {
00365 
00366                 // Use the input data to scale the virial radius.
00367 
00368                 if (verbose)
00369                     cerr << "input Jacobi radius ("
00370                          << input_r_jacobi << ") scales initial virial radius "
00371                          << r_virial << endl;
00372 
00373                 initial_r_jacobi = input_r_jacobi * r_virial;
00374 
00375             }
00376         }
00377 
00378         // Save the kira Jacobi radius for restart.
00379 
00380         if (initial_r_jacobi > 0)
00381             putrq(b->get_log_story(), "kira_initial_jacobi_radius",
00382                   initial_r_jacobi);
00383 
00384     }
00385 
00386     return initial_r_jacobi;
00387 }
00388 
00389 #define MATCH_TOL 0.001
00390 
00391 local bool matches(real r, real v)
00392 {
00393     return (abs(r/v - 1) < MATCH_TOL);
00394 }
00395 
00396 static char* tidal_type[5] = {"none",
00397                               "point-mass",
00398                               "isothermal",
00399                               "disk",
00400                               "custom"};
00401 
00402 // Express Galactic parameters in "Stellar" units (see Mihalas 1968):
00403 //
00404 //      G               =  1
00405 //      length unit     =  1 pc
00406 //      velocity unit   =  1 km/s
00407 //
00408 // ==>  time unit       =  0.978 Myr
00409 //      mass unit       =  232 Msun
00410 
00411 #define OORT_A  (0.0144)        // km/s/pc
00412 #define OORT_B  (-0.012)        // km/s/pc
00413 #define RHO_G   (0.11/232)      // (232 Msun)/pc^3
00414 
00415 #define Rsun_pc 2.255e-8        // R_sun/1 parsec = 6.960e+10/3.086e+18;
00416 
00417 #define OORT_ALPHA_RATIO \
00418         ((4*M_PI*RHO_G + 2*(OORT_A*OORT_A - OORT_B*OORT_B)) \
00419                          / (-4*OORT_A*(OORT_A-OORT_B)))
00420 
00421 local void tidal_msg(int i, real alpha3_over_alpha1)
00422 {
00423     cerr << "forcing tidal_field_type = " << i
00424          << " for anisotropic King model "
00425          << endl
00426          << "    with alpha3_over_alpha1 = "
00427          << alpha3_over_alpha1
00428          << endl;
00429 }
00430 
00431 void set_tidal_params(dyn* b,
00432                       bool verbose,
00433                       real initial_r_jacobi,
00434                       real initial_mass,
00435                       int& tidal_field_type)
00436 {
00437     // Set the tidal parameters for the system.
00438     //
00439     // Procedure:
00440     //          kira_tidal_field_type = 0 suppresses tidal fields
00441     //          if no type can be determined, suppress tidal field
00442     //          initial_mass and initial_r_jacobi set the value of alpha1
00443     //          tidal_field_type then sets the value of alpha3
00444     //
00445     // NOTE that tidal_field_type = 3, the field is intended to
00446     // model the Galactic field in the solar neighborhood, for
00447     // which alpha1 and alpha3 are actually determined directly by
00448     // the local Oort constants.  The resultant field may thus *not*
00449     // be consistent with the choice of radius used later in
00450     // establishing physical scales -- see test_tidal_params().
00451     //
00452     // Tidal field type (kira_tidal_field_type) or anisotropic King model
00453     // initial info (alpha3_over_alpha1) in the input snapshot OVERRIDE
00454     // the input data, if any.
00455     //
00456     // Thus, to decipher the tidal parameters, we need one of:
00457     //
00458     //          kira_tidal_field_type  ==> sets tidal_field_type directly and
00459     //                                     hence a standard alpha3_over_alpha1
00460     //  or      alpha3_over_alpha1     ==> allows inference of tidal_field_type
00461     //
00462     // Then the tidal parameters are set from the mass and Jacobi radius.
00463     // To determine the Jacobi radius, we need:
00464     //
00465     //          kira_initial_jacobi_radius
00466     //  or      initial_r_virial  and  initial_rtidal_over_rvirial
00467     //
00468     // These come from make_*, make_king, make_aniso_king, add_tidal,
00469     // and scale.
00470 
00471     int kira_tidal_field_type = -1;
00472 
00473     if (find_qmatch(b->get_log_story(), "kira_tidal_field_type")) {
00474 
00475         kira_tidal_field_type
00476             = getiq(b->get_log_story(), "kira_tidal_field_type");
00477 
00478         if (kira_tidal_field_type == 0)
00479 
00480             return;                                     // take no action
00481 
00482         else if (kira_tidal_field_type > 0) {
00483 
00484             if (verbose) {
00485                 cerr << "using tidal_field_type = " << kira_tidal_field_type
00486                      << " (" << tidal_type[kira_tidal_field_type]
00487                      << ") from input snapshot" << endl;
00488 
00489                 if (tidal_field_type > 0)
00490                     cerr << "ignoring input tidal_field_type"
00491                          << tidal_field_type << endl;
00492             }
00493 
00494             tidal_field_type = kira_tidal_field_type;
00495 
00496         } else {
00497 
00498             if (verbose)
00499                 cerr << "warning: error reading "
00500                      << "kira_tidal_field_type "
00501                      << "from input snapshot"
00502                      << endl;
00503             else
00504                 err_exit(
00505              "Error reading kira_tidal_field_type from input snapshot");
00506 
00507         }
00508 
00509     } else if (find_qmatch(b->get_log_story(), "alpha3_over_alpha1")) {
00510 
00511         // Try to infer tidal_field_type from alpha3_over_alpha1.
00512 
00513         real alpha3_over_alpha1
00514             = getrq(b->get_log_story(), "alpha3_over_alpha1");
00515 
00516         if (alpha3_over_alpha1 < 0
00517             && alpha3_over_alpha1 > -VERY_LARGE_NUMBER) {
00518 
00519             // See if the input ratio matches any of the standard types.
00520             // If it does, use that type; if not, flag a warning and use
00521             // the input type or the default.
00522 
00523             if (matches(alpha3_over_alpha1, -1.0/3)) {
00524                 if (tidal_field_type != 1) {
00525                     tidal_field_type = 1;
00526                     if (verbose)
00527                         tidal_msg(tidal_field_type, alpha3_over_alpha1);
00528                 }
00529             } else if (matches(alpha3_over_alpha1, -1.0/2)) {
00530                 if (tidal_field_type != 2) {
00531                     tidal_field_type = 2;
00532                     if (verbose)
00533                         tidal_msg(tidal_field_type, alpha3_over_alpha1);
00534                 }
00535             }  else if (matches(alpha3_over_alpha1, OORT_ALPHA_RATIO)) {
00536                 if (tidal_field_type != 3) {
00537                     tidal_field_type = 3;
00538                     if (verbose)
00539                         tidal_msg(tidal_field_type, alpha3_over_alpha1);
00540                 }
00541             } else {
00542                 cerr << "warning: snapshot alpha3_over_alpha1 = "
00543                      << alpha3_over_alpha1
00544                      << " does not match any standard value"
00545                      << endl;
00546             }
00547 
00548         } else {
00549 
00550             if (verbose)
00551                 cerr << "warning: error reading "
00552                      << "alpha3_over_alpha1 "
00553                      << "from input snapshot"
00554                      << endl;
00555 
00556         }
00557     }
00558 
00559     if (tidal_field_type > 4)
00560         err_exit("Unknown tidal field type");
00561 
00562     if (verbose) {
00563 
00564         if (tidal_field_type <= 0)
00565 
00566             cerr << "Unable to determine tidal field type." << endl;
00567 
00568         else {
00569 
00570             cerr << "using ";
00571 
00572             if (tidal_field_type <= 1) {
00573 
00574                 cerr << tidal_type[1] << " ";
00575                 if (tidal_field_type <= 0) cerr << "(default) ";
00576 
00577             } else
00578                 cerr << tidal_type[tidal_field_type] << " ";
00579 
00580             cerr << "tidal field; "
00581                  << "initial Jacobi radius = " << initial_r_jacobi
00582                  << endl;
00583         }
00584     }
00585 
00586     // Set up the dynamical tidal parameters.
00587 
00588     real alpha1, alpha3, omega;
00589     if (tidal_field_type > 0)
00590         alpha1 = -initial_mass / pow(initial_r_jacobi, 3.0);    // (definition)
00591 
00592     // Note that we don't use alpha3_over_alpha1, even if it is stored
00593     // in the snapshot.  We use the "standard" ratios, or rederive the
00594     // ratio from the stored Oort constants.
00595 
00596     if (tidal_field_type == 1) {
00597 
00598         // Point-mass field (see Binney & Tremaine, p. 452).
00599 
00600         alpha3 = -alpha1/3;
00601         omega = sqrt(alpha3);
00602 
00603     } else if (tidal_field_type == 2) {
00604 
00605         // Isothermal halo.
00606 
00607         alpha3 = -alpha1/2;
00608         omega = sqrt(alpha3);
00609         
00610     } else if (tidal_field_type == 3) {
00611 
00612         // Disk field.  Use the local Oort constants (defined above).
00613         // Conversion between Oort constants and alpha1/3 is taken
00614         // from Heggie & Ramamani (MNRAS 272, 317, 1995):
00615         //
00616         //      alpha1 = -4 A (A - B)
00617         //      alpha3 = 4 PI G RHO_G + 2 (A^2 - B^2)
00618         //
00619         // and recall that G = 1 by our above choice of units.
00620 
00621         alpha3 = alpha1 * OORT_ALPHA_RATIO;
00622 
00623         // Get omega from the definition of A and B:
00624         //
00625         //      A =  (1/2) (Vc/R - dVc/dR)
00626         //      B = -(1/2) (Vc/R + dVc/dR)
00627         //
00628         // ==>  omega = Vc/R = A - B,  dVc/dR = A + B
00629         //
00630         // so   alpha1 = -2 omega (omega - dVc/dR)
00631         //             = -2 omega^2 (1 - (A + B)/(A - B))
00632         //             =  4 omega^2 B / (A - B)
00633 
00634         omega = sqrt(0.25 * alpha1 * (OORT_A/OORT_B - 1));
00635 
00636     } else if (tidal_field_type == 4) {
00637 
00638         // Custom tidal field.  Require that the original physical
00639         // parameters be saved in the input snapshot.
00640 
00641         real Oort_A = 0;
00642         real Oort_B = 0;
00643         real rho_G = 0;
00644 
00645         if (find_qmatch(b->get_log_story(), "Oort_A_constant"))
00646             Oort_A = getrq(b->get_log_story(), "Oort_A_constant");
00647         else
00648             err_exit("Oort A constant not specified");
00649 
00650         if (find_qmatch(b->get_log_story(), "Oort_B_constant"))
00651             Oort_B = getrq(b->get_log_story(), "Oort_B_constant");      
00652         else
00653             err_exit("Oort B constant not specified");
00654 
00655         if (find_qmatch(b->get_log_story(), "local_mass_density"))
00656             rho_G = getrq(b->get_log_story(), "local_mass_density");
00657         else
00658             err_exit("rho_G not specified");
00659 
00660         cerr << "create custom tidal field from " << endl;
00661         PRI(4);PRC(Oort_A);PRC(Oort_B);PRL(rho_G);
00662 
00663         if (Oort_A != 0 && Oort_B != 0 && rho_G != 0) {
00664 
00665             // alpha1 = -4*Oort_A*(Oort_A-Oort_B);      // no!
00666 
00667             real alpha3_over_alpha1 =
00668                 (4*M_PI*rho_G + 2*(pow(Oort_A, 2) - pow(Oort_B, 2)))
00669                     / (-4*Oort_A*(Oort_A - Oort_B));
00670 
00671             alpha3 = alpha1 * alpha3_over_alpha1;
00672             omega = sqrt(0.25*alpha1 * (Oort_A/Oort_B - 1));
00673         }
00674         else
00675           err_exit("Insufficient information to reconstruct tidal field");
00676     }
00677 
00678     if (verbose && tidal_field_type > 0) {
00679         PRI(4); PRC(alpha1); PRC(alpha3); PRL(omega);
00680     }
00681 
00682     if (tidal_field_type > 0) {
00683         b->set_tidal_field(tidal_field_type);
00684         b->set_omega(omega);
00685         b->set_alpha(alpha1, alpha3);
00686     }
00687 
00688     // Save the field type information in the root log story, if necessary.
00689 
00690     if (kira_tidal_field_type <= 0)
00691         putiq(b->get_log_story(), "kira_tidal_field_type",
00692               tidal_field_type);
00693 
00694 }
00695 
00696 void test_tidal_params(dyn* b,
00697                        bool verbose,
00698                        real initial_r_jacobi,
00699                        real initial_r_virial,
00700                        real initial_mass)
00701 {
00702     cerr << endl << "comparing initial parameters for disk tidal field:"
00703          << endl;
00704 
00705     fprintf(stderr, "    model r_virial = %.3f, r_jacobi = %.3f",
00706             initial_r_virial, initial_r_jacobi);
00707     fprintf(stderr, ", ratio = %.3f\n", initial_r_jacobi/initial_r_virial);
00708 
00709     // Convert initial mass and virial radius using conversion factors.
00710     // Compute Jacobi radius from Oort constants.
00711 
00712     initial_mass
00713         = b->get_starbase()->conv_m_dyn_to_star(initial_mass);      // Msun
00714     initial_r_virial
00715         = b->get_starbase()->conv_r_dyn_to_star(initial_r_virial)
00716             * Rsun_pc;                                              // pc
00717 
00718     initial_r_jacobi = pow((initial_mass/232)
00719                             / (4*OORT_A*(OORT_A-OORT_B)), 1.0/3);   // pc
00720 
00721     fprintf(stderr, "    real  r_virial = %.3f, r_jacobi = %.3f",
00722             initial_r_virial, initial_r_jacobi);
00723     fprintf(stderr, ", ratio = %.3f\n", initial_r_jacobi/initial_r_virial);
00724 }
00725 
00726 int check_set_tidal(dyn *b,
00727                     bool verbose)               // default = false
00728 {
00729     int tidal_field_type = 0;
00730     b->set_tidal_field(tidal_field_type);
00731 
00732     real initial_mass = get_initial_mass(b, verbose);
00733     real initial_r_virial = get_initial_virial_radius(b, verbose);
00734     real initial_r_jacobi = get_initial_jacobi_radius(b, initial_r_virial,
00735                                                       verbose);
00736     if (initial_r_jacobi > 0)
00737         set_tidal_params(b, verbose,
00738                          initial_r_jacobi,
00739                          initial_mass,
00740                          tidal_field_type);
00741 
00742     return tidal_field_type;
00743 }
00744 
00745 void check_set_plummer(dyn *b,
00746                        bool verbose)            // default = false
00747 {
00748     // Check for Plummer-field data in the input snapshot, and
00749     // set kira parameters accordingly.  No coordination with the
00750     // command line because these parameters can *only* be set via
00751     // the input snapshot.  (Steve, 7/01)
00752     //
00753     // Expected fields in the input file are
00754     //
00755     //          kira_plummer_mass       =  M
00756     //          kira_plummer_scale      =  R
00757     //          kira_plummer_center     =  x y z
00758 
00759      if (find_qmatch(b->get_log_story(), "kira_plummer_mass")
00760          && find_qmatch(b->get_log_story(), "kira_plummer_scale")) {
00761 
00762          b->set_plummer();
00763 
00764          b->set_p_mass(getrq(b->get_log_story(), "kira_plummer_mass"));
00765          b->set_p_scale_sq(pow(getrq(b->get_log_story(),
00766                                      "kira_plummer_scale"), 2));
00767 
00768          vector center = 0;
00769          if (find_qmatch(b->get_log_story(), "kira_plummer_center"))
00770              center = getvq(b->get_log_story(), "kira_plummer_center");
00771          b->set_p_center(center);
00772 
00773          if (verbose) {
00774              real M = b->get_p_mass();
00775              real a = sqrt(b->get_p_scale_sq());
00776              vector center = b->get_p_center();
00777              cerr << "check_set_plummer:  "; PRC(M); PRC(a); PRL(center);
00778          }
00779      }
00780 }
00781 
00782 void check_set_power_law(dyn *b,
00783                          bool verbose)          // default = false
00784 {
00785     // Check for power-law-field data in the input snapshot, and
00786     // set kira parameters accordingly.  No coordination with the
00787     // command line because these parameters can *only* be set via
00788     // the input snapshot.  (Steve, 8/01)
00789     //
00790     // Expected fields in the input file are
00791     //
00792     //          kira_pl_coeff           =  A
00793     //          kira_pl_scale           =  R
00794     //          kira_pl_exponent        =  e
00795     //          kira_pl_center          =  x y z
00796     //          kira_pl_cutoff          =  C
00797     //          kira_pl_mass            =  M
00798     //          kira_pl_softening       =  eps
00799 
00800      if (find_qmatch(b->get_log_story(), "kira_pl_coeff")
00801          && find_qmatch(b->get_log_story(), "kira_pl_scale")) {
00802 
00803          b->set_pl();
00804 
00805          b->set_pl_coeff(getrq(b->get_log_story(), "kira_pl_coeff"));
00806          b->set_pl_scale_sq(pow(getrq(b->get_log_story(),
00807                                       "kira_pl_scale"), 2));
00808 
00809          real exponent = 0;
00810          if (find_qmatch(b->get_log_story(), "kira_pl_exponent"))
00811              exponent = getrq(b->get_log_story(), "kira_pl_exponent");
00812          b->set_pl_exponent(exponent);
00813 
00814          vector center = 0;
00815          if (find_qmatch(b->get_log_story(), "kira_pl_center"))
00816              center = getvq(b->get_log_story(), "kira_pl_center");
00817          b->set_pl_center(center);
00818 
00819          real cutoff = 0;
00820          if (find_qmatch(b->get_log_story(), "kira_pl_cutoff"))
00821              cutoff = getrq(b->get_log_story(), "kira_pl_cutoff");
00822          b->set_pl_cutoff(cutoff);
00823 
00824          real mass = 0;
00825          if (find_qmatch(b->get_log_story(), "kira_pl_mass"))
00826              mass = getrq(b->get_log_story(), "kira_pl_mass");
00827          b->set_pl_mass(mass);
00828 
00829          real softening = 0;
00830          if (find_qmatch(b->get_log_story(), "kira_pl_softening"))
00831              softening = getrq(b->get_log_story(), "kira_pl_softening");
00832          b->set_pl_softening_sq(softening*softening);
00833 
00834          if (verbose) {
00835              real A = b->get_pl_coeff();
00836              real a = sqrt(b->get_pl_scale_sq());
00837              real x = b->get_pl_exponent();
00838              vector center = b->get_pl_center();
00839              real C = b->get_pl_cutoff();
00840              real M = b->get_pl_mass();
00841              real eps2 = b->get_pl_softening_sq();
00842              cerr << "check_set_power_law:  ";
00843              PRC(A); PRC(a); PRC(x); PRL(center);
00844              PRI(22); PRC(C); PRC(M); PRL(eps2);
00845          }
00846      }
00847 }
00848 
00849 void check_set_external(dyn *b,
00850                         bool verbose)           // default = false
00851 {
00852     // Check for and set parameters for all known external fields.
00853 
00854     check_set_tidal(b, verbose);
00855     check_set_plummer(b, verbose);
00856     check_set_power_law(b, verbose);
00857 }
00858 
00859 void check_set_ignore_internal(dyn *b,
00860                                bool verbose)            // default = false
00861 {
00862     // Check for and set flag to skip internal interactions.
00863 
00864     bool ignore_internal = false;
00865     if (find_qmatch(b->get_log_story(), "ignore_internal")
00866         && getiq(b->get_log_story(), "ignore_internal") == 1)
00867         ignore_internal = true;
00868 
00869     b->set_ignore_internal(ignore_internal);
00870 }

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