Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

split_particles.C

Go to the documentation of this file.
00001 
00029 
00030 // Only the main routine and check_and_initialize (at end) differ
00031 // from the functions in split_particle.
00032 // The repeated functions will end up in a library someday...
00033 
00034 // Steve McMillan, August 1996
00035 
00036 #include "dyn.h"
00037 
00038 #ifdef TOOLBOX
00039 
00040 // split_particle: Split the specified node into a binary with the specified
00041 //                 parameters.  All unspecified orbit elements are chosen
00042 //               randomly.  Newly created leaves have names "na" and "nb",
00043 //                 where "n" is the name of the leaf being split.
00044 
00045 local bool split_particle(dyn* bi, real ecc, real sma, real mass_ratio)
00046 {
00047     if (bi->get_oldest_daughter() != NULL) {
00048         cerr << "Can't split a binary node!\n";
00049         return false;
00050     } else if (sma <= 0) {
00051         cerr << "Must specify semi-major axis > 0.\n";
00052         return false;
00053     } else if (ecc < 0 || ecc >= 1) {
00054         cerr << "Must specify eccentricity in [0,1).\n";
00055         return false;
00056     } else if (mass_ratio <= 0 || mass_ratio > 1) {
00057         cerr << "Must specify mass ratio in (0,1]!\n";
00058         return false;
00059     }
00060 
00061     // Update the binary tree structure:
00062 
00063     dyn* d1 = new dyn;
00064     dyn* d2 = new dyn;
00065 
00066     bi->set_oldest_daughter(d1);
00067 
00068     d1->set_parent(bi);
00069     d2->set_parent(bi);
00070 
00071     d1->set_younger_sister(d2);
00072     d2->set_elder_sister(d1);
00073 
00074     // Set new masses and radii:
00075 
00076     real m_total = bi->get_mass();
00077     real m1 = m_total / (1 + mass_ratio);
00078     real m2 = m1 * mass_ratio;
00079 
00080     // By convention, the first component has larger mass.
00081 
00082     if (m1 < m2) {
00083         real temp = m1;
00084         m1 = m2;
00085         m2 = temp;
00086     }
00087 
00088     d1->set_mass(m1);
00089     d2->set_mass(m2);
00090 
00091     // Set internal orbital elements:
00092 
00093     kepler k;
00094 
00095     real peri = 1; // Default value (unimportant unless ecc = 1).
00096     if (ecc == 1) peri = 0;
00097 
00098     // For now, binary phase is random.
00099 
00100     real mean_anomaly = randinter(-PI, PI);
00101 
00102     make_standard_kepler(k, 0, m_total, -0.5 * m_total / sma, ecc,
00103                          peri, mean_anomaly);
00104 
00105     set_random_orientation(k);
00106 
00107     d1->set_pos(-m2 * k.get_rel_pos() / m_total);
00108     d1->set_vel(-m2 * k.get_rel_vel() / m_total);
00109 
00110     d2->set_pos(m1 * k.get_rel_pos() / m_total);
00111     d2->set_vel(m1 * k.get_rel_vel() / m_total);
00112 
00113     // Naming convention:
00114 
00115     if (bi->get_name() == NULL)
00116         if (bi->get_index() >= 0) {
00117             char tmp[64];
00118             sprintf(tmp, "%d", bi->get_index());
00119             bi->set_name(tmp);
00120         }
00121 
00122     d1->set_name(bi->get_name());
00123     d2->set_name(bi->get_name());
00124     strcat(d1->get_name(), "a");
00125     strcat(d2->get_name(), "b");
00126 
00127     return true;
00128 }
00129 
00130 // leaf_with_label: Return a pointer to the leaf with the specified name.
00131 
00132 #include <string.h>
00133 
00134 local dyn* leaf_with_label(dyn* b, char* label)
00135 {
00136     for_all_leaves(dyn, b, bi) {
00137         if (bi->get_name() != NULL) {
00138             if (strcmp(bi->get_name(), label) == 0)
00139                 return bi;
00140         } else if (bi->get_index() >= 0) {
00141             char id[64];
00142             sprintf(id, "%d", bi->get_index());
00143             if (strcmp(id, label) == 0)
00144                 return bi;
00145         }
00146     }
00147     return NULL;
00148 }
00149 
00150 local void scale_energy(real energy, int N, real M, real E)
00151 {
00152     // Scale energy to kT = -(2/3) E/N.
00153 
00154     energy *= (-E / (1.5*N));
00155 }
00156 
00157 //----------------------------------------------------------------------
00158 
00159 local void check_and_initialize(dyn* b, char* label,
00160                                 real eccentricity, real energy,
00161                                 real semi_major_axis, real mass_ratio)
00162 {
00163     if (eccentricity < 0)
00164         eccentricity = sqrt(randinter(0,1));    // Thermal distribution
00165 
00166     if (energy < 0) {
00167 
00168         // Working with energy, rather than semi-major axis.
00169 
00170         // Look in the dyn story to see if a total system energy is known.
00171         // If it is, scale 'energy' accordingly.
00172 
00173         // Thus, if the total system energy is known, 'energy' is specified
00174         // in "kT" units.  If not, 'energy' is the binary kinetic energy.
00175 
00176         char* energy_string = "initial_total_energy";
00177 
00178         if (find_qmatch(b->get_dyn_story(), energy_string))
00179             scale_energy(energy, b->n_daughters(), b->get_mass(),
00180                          getrq(b->get_dyn_story(), energy_string));
00181         else
00182             cerr << "split_particle: Using unscaled energy limits.\n";
00183 
00184     }
00185 
00186     // Locate the particle to be split.
00187 
00188     dyn* bi = leaf_with_label(b, label);
00189 
00190     if (bi == NULL) {
00191 
00192         cerr << "Warning: particle \"" << label << "\" not found.\n";
00193 
00194     } else {
00195 
00196         // Determine the semi-major axis if necessary.
00197 
00198         if (energy < 0)
00199             semi_major_axis = (1 - mass_ratio) * bi->get_mass()
00200                                 * mass_ratio * bi->get_mass()
00201                                         / (-2 * energy);
00202 
00203         // If a real error occurs, terminate the data flow.
00204 
00205         if (!split_particle(bi, eccentricity, semi_major_axis, mass_ratio))
00206             err_exit("fatal error");
00207     }
00208 }
00209 
00210 #define DEFAULT_ENERGY           0.0
00211 #define DEFAULT_ECC             -1.0
00212 #define DEFAULT_SMA              0.1
00213 #define DEFAULT_Q                1.0
00214 
00215 void main(int argc, char ** argv)
00216 {
00217     real energy = DEFAULT_ENERGY;
00218     real eccentricity = DEFAULT_ECC;
00219     real semi_major_axis = DEFAULT_SMA;
00220     real mass_ratio = DEFAULT_Q;
00221 
00222     char label[64];
00223     label[0] = '\0';
00224     bool previous_label = false;
00225 
00226     int random_seed = 0;
00227     char seedlog[64];
00228 
00229     check_help();
00230 
00231     dyn* b;
00232     b = get_dyn(cin);
00233 
00234     b->log_history(argc, argv);
00235 
00236     // Parse the command line by hand, modifying the system as we go.
00237 
00238     int i = 0;
00239     while (++i < argc)
00240         if (argv[i][0] == '-')
00241             switch (argv[i][1]) {
00242 
00243                 case 'a': semi_major_axis = atof(argv[++i]);
00244                           break;
00245 
00246                 case 'e': eccentricity = atof(argv[++i]);
00247                           break;
00248 
00249                 case 'E': energy = atof(argv[++i]);
00250                           break;
00251 
00252                 case 'l': if (previous_label)
00253 
00254                               // Initialize the previous binary with the
00255                               // present parameters.
00256 
00257                               check_and_initialize(b, label,
00258                                                    eccentricity, energy,
00259                                                    semi_major_axis, mass_ratio);
00260 
00261                           strcpy(label, argv[++i]);
00262 
00263                           // Options: we can either reinitialize to defaults,
00264                           // or we can pick up the previously defined values...
00265                           // Do the former, at least for now.
00266 
00267                           energy = DEFAULT_ENERGY;
00268                           eccentricity = DEFAULT_ECC;
00269                           semi_major_axis = DEFAULT_SMA;
00270                           mass_ratio = DEFAULT_Q;
00271 
00272                           previous_label = true;
00273                           break;
00274 
00275                 case 'q': mass_ratio = atof(argv[++i]);
00276                           break;
00277 
00278                 case 's': {
00279                           random_seed = atoi(argv[++i]);
00280                           int actual_seed = srandinter(random_seed);
00281                           sprintf(seedlog,
00282                                   "       random number generator seed = %d",
00283                                   actual_seed);
00284                           b->log_comment(seedlog);
00285                           }
00286                           break;
00287 
00288                 default:  get_help();
00289                           exit(1);
00290             }
00291 
00292     if (previous_label)
00293         check_and_initialize(b, label,
00294                              eccentricity, energy,
00295                              semi_major_axis, mass_ratio);
00296 
00297     put_dyn(cout, *b);
00298 }
00299 
00300 #endif

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