Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

split_particle.C

Go to the documentation of this file.
00001 
00002 // split_particle.C: Split a specified particle into a binary.
00003 //
00004 //      Mostly stolen from sdyn/init/mkscat.C
00005 //
00006 //      Steve McMillan, August 1996
00007 
00008 #include "dyn.h"
00009 
00010 #ifdef TOOLBOX
00011 
00012 // split_particle: Split the specified node into a binary with the specified
00013 //                 parameters.  All unspecified orbit elements are chosen
00014 //               randomly.  Newly created nodes have names "n1" and "n2",
00015 //                 where "n" is the name of the node being split.
00016 
00017 local bool split_particle(dyn* bi, real ecc, real sma, real mass_ratio)
00018 {
00019     if (bi->get_oldest_daughter() != NULL) {
00020         cerr << "Can't split a binary node!\n";
00021         return false;
00022     } else if (sma <= 0) {
00023         cerr << "Must specify semi-major axis > 0.\n";
00024         return false;
00025     } else if (ecc < 0 || ecc >= 1) {
00026         cerr << "Must specify eccentricity in [0,1).\n";
00027         return false;
00028     } else if (mass_ratio <= 0 || mass_ratio > 1) {
00029         cerr << "Must specify mass ratio in (0,1]!\n";
00030         return false;
00031     }
00032 
00033     // Update the binary tree structure:
00034 
00035     dyn* d1 = new dyn;
00036     dyn* d2 = new dyn;
00037 
00038     bi->set_oldest_daughter(d1);
00039 
00040     d1->set_parent(bi);
00041     d2->set_parent(bi);
00042 
00043     d1->set_younger_sister(d2);
00044     d2->set_elder_sister(d1);
00045 
00046     // Set new masses and radii:
00047 
00048     real m_total = bi->get_mass();
00049     real m1 = m_total / (1 + mass_ratio);
00050     real m2 = m1 * mass_ratio;
00051 
00052     // By convention, the first component has larger mass.
00053 
00054     if (m1 < m2) {
00055         real temp = m1;
00056         m1 = m2;
00057         m2 = temp;
00058     }
00059 
00060     d1->set_mass(m1);
00061     d2->set_mass(m2);
00062 
00063     // Set internal orbital elements:
00064 
00065     kepler k;
00066 
00067     real peri = 1; // Default value (unimportant unless ecc = 1).
00068     if (ecc == 1) peri = 0;
00069 
00070     // For now, binary phase is random.
00071 
00072     real mean_anomaly = randinter(-PI, PI);
00073 
00074     make_standard_kepler(k, 0, m_total, -0.5 * m_total / sma, ecc,
00075                          peri, mean_anomaly);
00076 
00077     set_random_orientation(k);
00078 
00079     d1->set_pos(-m2 * k.get_rel_pos() / m_total);
00080     d1->set_vel(-m2 * k.get_rel_vel() / m_total);
00081 
00082     d2->set_pos(m1 * k.get_rel_pos() / m_total);
00083     d2->set_vel(m1 * k.get_rel_vel() / m_total);
00084 
00085     // Naming convention:
00086 
00087     if (bi->get_name() == NULL)
00088         if (bi->get_index() >= 0) {
00089             char tmp[64];
00090             sprintf(tmp, "%d", bi->get_index());
00091             bi->set_name(tmp);
00092         }
00093 
00094     d1->set_name(bi->get_name());
00095     d2->set_name(bi->get_name());
00096     strcat(d1->get_name(), "a");
00097     strcat(d2->get_name(), "b");
00098 
00099     return true;
00100 }
00101 
00102 // leaf_with_label: Return a pointer to the leaf with the specified name.
00103 
00104 #include <string.h>
00105 
00106 local dyn* leaf_with_label(dyn* b, char* label)
00107 {
00108     for_all_leaves(dyn, b, bi) {
00109         if (bi->get_name() != NULL) {
00110             if (strcmp(bi->get_name(), label) == 0)
00111                 return bi;
00112         } else if (bi->get_index() >= 0) {
00113             char id[64];
00114             sprintf(id, "%d", bi->get_index());
00115             if (strcmp(id, label) == 0)
00116                 return bi;
00117         }
00118     }
00119     return NULL;
00120 }
00121 
00122 local void scale_energy(real energy, int N, real M, real E)
00123 {
00124     // Scale energy to kT = -(2/3) E/N.
00125 
00126     energy *= (-E / (1.5*N));
00127 }
00128 
00129 //----------------------------------------------------------------------
00130 
00131 void main(int argc, char ** argv)
00132 {
00133     real energy = 0.0;
00134     real eccentricity = -1;
00135     real semi_major_axis = 0.1;
00136     real mass_ratio = 1.0;
00137     int random_seed = 0;
00138     char seedlog[64];
00139     char label[64];
00140 
00141     label[0] = '\0';
00142 
00143     extern char *poptarg;
00144     int c;
00145     char* param_string = "a:e:E:l:s:o:";
00146 
00147     while ((c = pgetopt(argc, argv, param_string)) != -1)
00148         switch(c) {
00149 
00150             case 'a': semi_major_axis = atof(poptarg);
00151                       break;
00152             case 'e': eccentricity = atof(poptarg);
00153                       break;
00154             case 'E': energy = atof(poptarg);
00155                       break;
00156             case 'l': strcpy(label, poptarg);
00157                       break;
00158             case 'q': mass_ratio = atof(poptarg);
00159                       break;
00160             case 's': random_seed = atoi(poptarg);
00161                       break;
00162             case '?': params_to_usage(cerr, argv[0], param_string);
00163                       exit(1);
00164         }
00165 
00166     if (label[0] == '\0')
00167         err_exit("must specify a particle label");
00168 
00169     dyn* b;
00170     b = get_dyn(cin);
00171 
00172     // Bookkeeping.
00173 
00174     b->log_history(argc, argv);
00175 
00176     int actual_seed = srandinter(random_seed);
00177 
00178     sprintf(seedlog,
00179             "       random number generator seed = %d",actual_seed);
00180     b->log_comment(seedlog);
00181 
00182     if (eccentricity < 0)
00183         eccentricity = sqrt(randinter(0,1));    // Thermal distribution
00184 
00185     if (energy < 0) {
00186 
00187         // Working with energy, rather than semi-major axis.
00188 
00189         // Look in the dyn story to see if a total system energy is known.
00190         // If it is, scale 'energy' accordingly.
00191 
00192         // Thus, if the total system energy is known, 'energy' is specified
00193         // in "kT" units.  If not, 'energy' is the binary kinetic energy.
00194 
00195         char* energy_string = "initial_total_energy";
00196 
00197         if (find_qmatch(b->get_dyn_story(), energy_string))
00198             scale_energy(energy, b->n_daughters(), b->get_mass(),
00199                          getrq(b->get_dyn_story(), energy_string));
00200         else
00201             cerr << "split_particle: Using unscaled energy limits.\n";
00202 
00203     }
00204 
00205     // Locate the particle to be split.
00206 
00207     dyn* bi = leaf_with_label(b, label);
00208 
00209     if (bi == NULL) {
00210 
00211         // Do nothing in this case, but don't stop the flow of data.
00212 
00213         cerr << "Warning: particle " << label << " not found.\n";
00214         put_dyn(cout, *b);
00215 
00216     } else {
00217 
00218         // Determine the semi-major axis if necessary.
00219 
00220         if (energy < 0)
00221             semi_major_axis = (1 - mass_ratio) * bi->get_mass()
00222                                 * mass_ratio * bi->get_mass()
00223                                         / (-2 * energy);
00224 
00225         // If a real error occurs, terminate the data flow.
00226 
00227         if (split_particle(bi, eccentricity, semi_major_axis, mass_ratio))
00228             put_dyn(cout, *b);
00229     }
00230 }
00231 
00232 #endif

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