00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "node.h"
00039
00040 #define MAXIMUM_ZAMS_MASS 100
00041 #define SEED_STRING_LENGTH 256
00042 static char tmp_string[SEED_STRING_LENGTH];
00043
00044 #ifndef TOOLBOX
00045
00046
00047
00048 local real mf_Miller_Scalo(real m_lower, real m_upper) {
00049
00050 real m, rnd;
00051 do {
00052 rnd = randinter(0,1);
00053 m = 0.19*rnd
00054 / (pow(1-rnd, 0.75) + 0.032*pow(1-rnd, 0.25));
00055 }
00056 while(m_lower>m || m>m_upper);
00057 return m;
00058 }
00059
00060
00061
00062 local real tapered_power_law(real m,
00063 const real x1 = -1.35,
00064 const real x2 = 2.4,
00065 const real mbreak = 0.25) {
00066
00067 real dNdm = pow(m, x1)*(1-pow(exp(-m/mbreak), x2));
00068 return dNdm;
00069 }
00070
00071 local real mf_GdeMarchi(real m_lower, real m_upper) {
00072
00073
00074
00075
00076 real x1 = -2.35;
00077 real x2 = 2.40;
00078 real mbreak = 0.15;
00079 real dNdm_min = tapered_power_law(m_lower, x1, x2, mbreak);
00080 real dNdm_max = tapered_power_law(m_upper, x1, x2, mbreak);
00081
00082 real m, rnd;
00083 real dNdm_try, dNdm;
00084 do {
00085 rnd = randinter(0,1);
00086 m = m_lower + rnd*(m_upper-m_lower);
00087 dNdm_try = randinter(dNdm_min,dNdm_max);
00088 dNdm = tapered_power_law(m, x1, x2, mbreak);
00089 }
00090 while(dNdm_try>dNdm);
00091 return m;
00092 }
00093
00094
00095
00096
00097
00098 local real mf_Scalo(real m_lower, real m_upper) {
00099 real m, rnd;
00100 do {
00101 rnd = randinter(0,1);
00102 m = 0.3*rnd
00103 / pow(1-rnd, 0.55);
00104 }
00105 while(m_lower>m || m>m_upper);
00106 return m;
00107 }
00108
00109 local real Kroupa_Tout_Gilmore(real m_lower, real m_upper) {
00110
00111 real m, rnd;
00112 do {
00113 rnd = randinter(0,1);
00114 m = 0.08 + (0.19*pow(rnd, 1.55) + 0.05*pow(rnd, 0.6))
00115 / pow(1-rnd, 0.58);
00116 }
00117 while(m_lower>m || m>m_upper);
00118 return m;
00119 }
00120
00121 real get_random_stellar_mass(real m_lower, real m_upper,
00122 mass_function mf, real exponent) {
00123
00124 real m;
00125 switch(mf) {
00126 case Equal_Mass:
00127 if (m_lower==0) {
00128 cerr << "get_random_stellar_mass:"<<endl;
00129 cerr << "unambiguous choise of Equal_Mass."<<endl;
00130 cerr << "Use -m option to set fixed stellar mass."<<endl;
00131 exit(1);
00132 }
00133 m = m_lower;
00134 break;
00135 case mf_Power_Law:
00136 m = general_power_law(m_lower, m_upper, exponent);
00137 break;
00138 case Miller_Scalo:
00139 m = mf_Miller_Scalo(m_lower, m_upper);
00140 break;
00141 case Scalo:
00142 m = mf_Scalo(m_lower, m_upper);
00143 break;
00144 case Kroupa:
00145 m = Kroupa_Tout_Gilmore(m_lower, m_upper);
00146 break;
00147 case Tapered_Power_Law:
00148 m = mf_GdeMarchi(m_lower, m_upper);
00149 break;
00150 default:
00151 cerr << "WARNING: \n"
00152 << " real get_random_stellar_mass:\n"
00153 << " Mass function parameters not properly defined.\n";
00154 exit(1);
00155 }
00156
00157 return m;
00158 }
00159
00160 char* type_string(mass_function mf) {
00161
00162 local char mf_name[SEED_STRING_LENGTH];
00163 switch(mf) {
00164
00165 case Equal_Mass:
00166 sprintf(mf_name, "Equal_Mass");
00167 break;
00168 case mf_Power_Law:
00169 sprintf(mf_name, "Power_Law");
00170 break;
00171 case Miller_Scalo:
00172 sprintf(mf_name, "Miller_Scalo");
00173 break;
00174 case Scalo:
00175 sprintf(mf_name, "Scalo");
00176 break;
00177 case Kroupa:
00178 sprintf(mf_name, "Kroupa");
00179 break;
00180 case Tapered_Power_Law:
00181 sprintf(mf_name, "Tapered_Power_Law");
00182 break;
00183 default:
00184 sprintf(mf_name, "Unknown");
00185 break;
00186 }
00187 return mf_name;
00188 }
00189
00190 mass_function extract_mass_function_type_string(char* type_string) {
00191
00192 mass_function type = Unknown_MF;
00193
00194 if (!strcmp(type_string, "Equal_Mass"))
00195 type = Equal_Mass;
00196 else if (!strcmp(type_string, "Power_Law"))
00197 type = mf_Power_Law;
00198 else if (!strcmp(type_string, "Miller_Scalo"))
00199 type = Miller_Scalo;
00200 else if (!strcmp(type_string, "Scalo"))
00201 type = Scalo;
00202 else if (!strcmp(type_string, "Kroupa"))
00203 type = Kroupa;
00204 else if (!strcmp(type_string, "Tapered_Power_Law"))
00205 type = Tapered_Power_Law;
00206 else if (!strcmp(type_string, "Unknown"))
00207 type = Unknown_MF;
00208 else {
00209 cerr << "No proper mass function indicated in mkmass."<<endl;
00210 exit(-1);
00211 }
00212
00213 return type;
00214 }
00215
00216 real general_power_law(real lowerl, real upperl, real exponent) {
00217
00218 real x, norm;
00219
00220
00221 if (exponent == -1)
00222 norm = log(upperl/lowerl);
00223 else
00224 norm = pow(upperl/lowerl, 1+exponent) - 1;
00225
00226 if (exponent == -1)
00227 x = lowerl*exp(norm*randinter(0,1));
00228 else
00229 x = lowerl*pow(norm*randinter(0,1) + 1, 1/(1+exponent));
00230
00231 return x;
00232 }
00233
00234 #else
00235
00236 typedef struct
00237 {
00238 node* str;
00239 real mass;
00240 } nm_pair, *nm_pair_ptr;
00241
00242
00243
00244
00245
00246 local int compare_mass(const void * pi, const void * pj)
00247 {
00248 if (((nm_pair_ptr) pi)->mass < ((nm_pair_ptr) pj)->mass)
00249 return(1);
00250 else if (((nm_pair_ptr)pi)->mass > ((nm_pair_ptr)pj)->mass)
00251 return(-1);
00252 else
00253 return(0);
00254 }
00255
00256 local void mkmass(node* b, mass_function mf,
00257 real m_lower, real m_upper,
00258 real exponent, real total_mass, bool renumber_stars) {
00259
00260 real m, m_sum = 0;
00261 int n=0;
00262 for_all_daughters(node, b, bi) {
00263 m = get_random_stellar_mass(m_lower, m_upper, mf, exponent);
00264 n++;
00265 bi->set_mass(m);
00266 m_sum += bi->get_mass();
00267 }
00268
00269 b->set_mass(m_sum);
00270
00271
00272
00273 if (renumber_stars) {
00274 int istart = 1;
00275 bool M_flag = true;
00276 renumber(b, istart, M_flag);
00277 }
00278
00279 #if 0
00280 nm_pair_ptr nm_table = new nm_pair[n];
00281 if (nm_table == NULL) {
00282 cerr << "mkmass: "
00283 << "not enough memory left for nm_table\n";
00284 return;
00285 }
00286
00287 int i=0;
00288 for_all_daughters(node, b, bi) {
00289 nm_table[i].str = bi;
00290 nm_table[i].mass = bi->get_mass();
00291 i++;
00292 }
00293
00294 qsort((void *)nm_table, (size_t)n, sizeof(nm_pair), compare_mass);
00295
00296 for (i=0; i<n; i++) {
00297 nm_table[i].str->set_index(i+1);
00298 }
00299
00300 delete []nm_table;
00301 }
00302 #endif
00303
00304 if (total_mass > 0) {
00305 real m_factor = total_mass/m_sum;
00306 for_all_daughters(node, b, bi)
00307 bi->set_mass(m_factor*bi->get_mass());
00308 b->set_mass(total_mass);
00309 }
00310
00311 if(m_lower>=m_upper)
00312 sprintf(tmp_string,
00313 " %s mass function, total mass = %8.2f",
00314 type_string(Equal_Mass), m_sum);
00315 else
00316 sprintf(tmp_string,
00317 " %s mass function, total mass = %8.2f Solar",
00318 type_string(mf), m_sum);
00319 b->log_comment(tmp_string);
00320 cerr << "Mass function is " << type_string(mf) <<endl;
00321
00322 }
00323
00324 void main(int argc, char ** argv)
00325 {
00326 bool F_flag = false;
00327 mass_function mf = mf_Power_Law;
00328 char *mfc = new char[64];
00329 real m_lower = 1, m_upper = 1;
00330 bool x_flag = false;
00331 real exponent = -2.35;
00332
00333
00334 real m_total = -1;
00335
00336 bool renumber_stars = false;
00337
00338
00339 int random_seed = 0;
00340 char seedlog[64];
00341
00342 check_help();
00343
00344 extern char *poptarg;
00345 int c;
00346 char* param_string = "E:e:iF:f:L:l:M:m:s:U:u:X:x:";
00347
00348 while ((c = pgetopt(argc, argv, param_string)) != -1)
00349 switch(c) {
00350
00351 case 'F': F_flag = true;
00352 mfc = poptarg;
00353 break;
00354 case 'f': mf = (mass_function)atoi(poptarg);
00355 break;
00356 case 'i': renumber_stars = true;
00357 break;
00358 case 'E':
00359 case 'e':
00360 case 'X':
00361 case 'x': x_flag = true;
00362 exponent = atof(poptarg);
00363 break;
00364 case 'L':
00365 case 'l': m_lower = atof(poptarg);
00366 break;
00367 case 'M':
00368 case 'm': m_total = atof(poptarg);
00369 break;
00370 case 's': random_seed = atoi(poptarg);
00371 break;
00372 case 'U':
00373 case 'u': m_upper = atof(poptarg);
00374 break;
00375 case '?': params_to_usage(cerr, argv[0], param_string);
00376 get_help();
00377 exit(1);
00378 }
00379
00380 if (m_lower <= 0 ||
00381 m_upper <= 0 ||
00382 m_lower > m_upper)
00383 err_exit("mkmass: Illegal mass limits");
00384
00385 if (F_flag)
00386 mf = extract_mass_function_type_string(mfc);
00387 delete mfc;
00388
00389 node* b;
00390 b = get_node(cin);
00391
00392 b->log_history(argc, argv);
00393
00394 int actual_seed = srandinter(random_seed);
00395
00396 sprintf(seedlog, " random number generator seed = %d",actual_seed);
00397 b->log_comment(seedlog);
00398
00399 mkmass(b, mf, m_lower, m_upper, exponent, m_total, renumber_stars);
00400 real initial_mass = getrq(b->get_log_story(), "initial_mass");
00401
00402 if (initial_mass > -VERY_LARGE_NUMBER)
00403 putrq(b->get_log_story(), "initial_mass", b->get_mass(),
00404 HIGH_PRECISION);
00405
00406
00407
00408 real m_sum = b->get_mass();
00409 real old_mtot = b->get_starbase()->conv_m_dyn_to_star(1);
00410 if(old_mtot<=0) {
00411 real old_r_vir= b->get_starbase()->conv_r_star_to_dyn(1);
00412 real old_t_vir= b->get_starbase()->conv_t_star_to_dyn(1);
00413 b->get_starbase()->set_stellar_evolution_scaling(m_sum,
00414 old_r_vir,
00415 old_t_vir);
00416 }
00417 put_node(cout, *b);
00418 rmtree(b);
00419
00420 }
00421 #endif
00422