Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

grow_black_hole.C

Go to the documentation of this file.
00001 
00008 
00009 //                 Simon Portegies Zwart, MIT June 2000
00010 
00011 #include "dyn.h"
00012 
00013 #define  SEED_STRING_LENGTH  256
00014 char  tmp_string[SEED_STRING_LENGTH];
00015 
00016 #ifdef TOOLBOX
00017 
00018 typedef  struct
00019 {
00020     real  radius;
00021     real  mass;
00022 } rm_pair, *rm_pair_ptr;
00023 
00024 //-----------------------------------------------------------------------------
00025 //  compare_radii  --  compare the radii of two particles
00026 //-----------------------------------------------------------------------------
00027 
00028 local int compare_radii(const void * pi, const void * pj)  // increasing radius
00029 {
00030     if (((rm_pair_ptr) pi)->radius > ((rm_pair_ptr) pj)->radius)
00031         return +1;
00032     else if (((rm_pair_ptr)pi)->radius < ((rm_pair_ptr)pj)->radius)
00033         return -1;
00034     else
00035         return 0;
00036 }
00037 
00038 //-----------------------------------------------------------------------------
00039 //  radius_containting_mass  --  Get the massradii for all particles.
00040 //-----------------------------------------------------------------------------
00041 
00042 real radius_containting_mass(dyn * b, real mass) {
00043 
00044     char lagr_string[64] = "central black hole";
00045 
00046     int n = b->n_daughters();
00047 
00048     // Use the density center if known and up to date (preferred).
00049     // Otherwise, use modified center of mass, if known and up to date.
00050     // Otherwise, use the geometric center.
00051 
00052     vector lagr_pos = 0, lagr_vel = 0;
00053     bool try_com = true;
00054     bool modify_com = false;
00055 
00056 #if 0
00057     if (find_qmatch(b->get_dyn_story(), "density_center_pos")) {
00058 
00059         if (getrq(b->get_dyn_story(), "density_center_time")
00060                 != b->get_system_time())
00061             warning("lagrad: neglecting out-of-date density center");
00062         else {
00063             lagr_pos = getvq(b->get_dyn_story(), "density_center_pos");
00064             strcpy(lagr_string, "density center");
00065             try_com = false;
00066 
00067             // Assume that density_center_vel exists if density_center_pos
00068             // is OK.
00069 
00070             lagr_vel = getvq(b->get_dyn_story(), "density_center_vel");
00071         }
00072     }
00073 
00074     if (try_com && find_qmatch(b->get_dyn_story(), "com_pos")) {
00075 
00076         if (getrq(b->get_dyn_story(), "com_time")
00077                 != b->get_system_time()) {
00078             warning("lagrad: neglecting out-of-date center of mass");
00079         } else {
00080             lagr_pos = getvq(b->get_dyn_story(), "com_pos");
00081             lagr_vel = getvq(b->get_dyn_story(), "com_vel");
00082             strcpy(lagr_string, "center of mass");
00083             modify_com = true;
00084         }
00085     }
00086 #endif
00087 
00088     rm_pair_ptr rm_table = new rm_pair[n];
00089 
00090     if (rm_table == NULL) {
00091         cerr << "radius_containing_mass: "
00092              << "not enough memory left for rm_table\n";
00093         return -1;
00094     }
00095 
00096     // Set up an array of (radius, mass) pairs.  Also find the total
00097     // mass of all nodes under consideration.
00098 
00099     real total_mass = 0;
00100     int i = 0;
00101 
00102     for_all_daughters(dyn, b, bi) {
00103       total_mass += bi->get_mass();
00104       rm_table[i].radius = abs(bi->get_pos() - lagr_pos);
00105       rm_table[i].mass = bi->get_mass();
00106       i++;
00107     }
00108 
00109     // Sort the array by radius.
00110     qsort((void *)rm_table, (size_t)i, sizeof(rm_pair), compare_radii);
00111     
00112     real rlagr = 0;
00113     real cumulative_mass = 0.0;
00114     
00115     // cerr << "Determining Lagrangian radii 2" << endl << flush;
00116     
00117     i=0;
00118     while (cumulative_mass < mass)
00119       cumulative_mass += rm_table[i++].mass;
00120 
00121     rlagr = rm_table[i-1].radius;
00122 
00123     delete [] rm_table;
00124 
00125     PRL(rlagr);
00126     return rlagr;
00127 }
00128 
00129 void merge_bh_with_coll(dyn * bh, dyn * bcoll) {
00130 
00131     detach_node_from_general_tree(*bcoll);
00132     bcoll->set_younger_sister(NULL);
00133     bcoll->set_elder_sister(NULL);
00134 
00135     real mass = bh->get_mass() + bcoll->get_mass();
00136 
00137     real f1 = bh->get_mass() / mass;
00138     real f2 = bcoll->get_mass() / mass;
00139     vector pos = f1 * bh->get_pos() + f2 * bcoll->get_pos();
00140     vector vel = f1 * bh->get_vel() + f2 * bcoll->get_vel();
00141     vector acc = f1 * bh->get_acc() + f2 * bcoll->get_acc();
00142 
00143     // Set up the physical coordinates of the daughters.
00144 
00145     bh->set_mass(mass);
00146     bh->set_pos(bh->get_pos() - pos);
00147     bh->set_vel(bh->get_vel() - vel);
00148     bh->set_acc(bh->get_acc() - acc);
00149 
00150     bcoll->set_pos(bcoll->get_pos() - pos);
00151     bcoll->set_vel(bcoll->get_vel() - vel);
00152     bcoll->set_acc(bcoll->get_acc() - acc);
00153   }
00154 
00155 
00156 local void grow_black_hole(dyn* b, real m_bh) {
00157 
00158     PRL(m_bh);
00159     if(m_bh<=1) {
00160         cerr << "fractional bh mass" << endl;
00161         m_bh *= b->get_mass();
00162         PRL(m_bh);
00163     }
00164 
00165     real bh_radius = radius_containting_mass(b, m_bh);
00166     PRL(bh_radius);
00167 
00168 
00169     real sum = 0;
00170 
00171     int ibh = 0;
00172     dyn *bh = NULL;
00173     int n = b->n_daughters();
00174     do {
00175       for_all_daughters(dyn, b, bi) {
00176         if(abs(bi->get_pos())<=bh_radius) {
00177           ibh++;
00178           if (bh==NULL) 
00179             bh = bi;
00180           else if(bh!=bi) {
00181 //          cerr << "merge bh with " << bi->format_label() << endl;
00182             merge_bh_with_coll(bh, bi);
00183 //          PRL(bh->get_mass());
00184 //          put_dyn(cerr, *bh);
00185             break;
00186           }
00187         }
00188       }
00189     }
00190     while(bh->get_mass()<m_bh);
00191 
00192     putiq(bh->get_log_story(), "black_hole", 1);
00193   }
00194 
00195 void main(int argc, char ** argv) {
00196 
00197     real m_bh = 0;
00198 
00199     check_help();
00200 
00201     extern char *poptarg;
00202     int c;
00203     char* param_string = "M:";
00204 
00205     while ((c = pgetopt(argc, argv, param_string)) != -1)
00206         switch(c) {
00207             case 'M': m_bh = atof(poptarg);
00208                       break;
00209             case '?': params_to_usage(cerr, argv[0], param_string);
00210                       exit(1);
00211         }
00212 
00213 
00214     dyn* b;
00215     b = get_dyn(cin);
00216     b->log_history(argc, argv);
00217 
00218     grow_black_hole(b, m_bh);
00219 
00220     put_dyn(cout, *b);
00221     rmtree(b);
00222 
00223 }
00224 #endif

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