Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

lagrad.C

Go to the documentation of this file.
00001 
00016 
00017 //-----------------------------------------------------------------------------
00018 //   version 1:  May 1989   Piet Hut               email: piet@iassns.BITNET
00019 //                           Institute for Advanced Study, Princeton, NJ, USA
00020 //   version 2:  Dec 1992   Piet Hut  --  adopted to the new C++-based starlab
00021 //   version 3:  Jul 1996   Steve McMillan & Jun Makino
00022 //.............................................................................
00023 //   non-local functions: 
00024 //      compute_general_mass_radii
00025 //      compute_mass_radii_quartiles
00026 //      compute_mass_radii_percentiles
00027 //-----------------------------------------------------------------------------
00028 
00029 #include "dyn.h"
00030 
00031 #ifndef TOOLBOX
00032 
00033 typedef  struct
00034 {
00035     real  radius;
00036     real  mass;
00037 } rm_pair, *rm_pair_ptr;
00038 
00039 //-----------------------------------------------------------------------------
00040 //  compare_radii  --  compare the radii of two particles
00041 //-----------------------------------------------------------------------------
00042 
00043 local int compare_radii(const void * pi, const void * pj)  // increasing radius
00044 {
00045     if (((rm_pair_ptr) pi)->radius > ((rm_pair_ptr) pj)->radius)
00046         return +1;
00047     else if (((rm_pair_ptr)pi)->radius < ((rm_pair_ptr)pj)->radius)
00048         return -1;
00049     else
00050         return 0;
00051 }
00052 
00053 //-----------------------------------------------------------------------------
00054 //  compute_general_mass_radii  --  Get the massradii for all particles.
00055 //-----------------------------------------------------------------------------
00056 
00057 static real nonlin_masses[9] = {0.005, 0.01, 0.02, 0.05, 0.1,
00058                                 0.25, 0.5, 0.75, 0.9};
00059 
00060 void compute_general_mass_radii(dyn * b, int nzones,
00061                                 bool nonlin,
00062                                 boolfn bf)
00063 {
00064     if (nzones < 2) return;
00065     if (nonlin && nzones != 10) return;         // Special case
00066 
00067     // Note: nzones specifies the number of radial zones to consider.
00068     //       However, we only store radii corresponding to the nzones-1 
00069     //       interior zone boundaries.
00070 
00071     char lagr_string[64] = "geometric center";
00072 
00073     int n = 0;
00074     if (bf == NULL)
00075         n = b->n_daughters();
00076     else {
00077         for_all_daughters(dyn, b, bb)
00078             if ((*bf)(bb)) n++;
00079     }
00080 
00081     // Use the density center if known and up to date (preferred).
00082     // Otherwise, use modified center of mass, if known and up to date.
00083 
00084     vector lagr_pos, lagr_vel;
00085     int which = get_std_center(b, lagr_pos, lagr_vel);
00086     if (which == 1)
00087         strcpy(lagr_string, "density center");
00088     else
00089         strcpy(lagr_string, "modified center of mass");
00090 
00091     rm_pair_ptr rm_table = new rm_pair[n];
00092 
00093     if (rm_table == NULL) {
00094         cerr << "compute_general_mass_radii: "
00095              << "not enough memory left for rm_table\n";
00096         return;
00097     }
00098 
00099     // Set up an array of (radius, mass) pairs.  Also find the total
00100     // mass of all nodes under consideration.
00101 
00102     real total_mass = 0;
00103     int i = 0;
00104 
00105     for_all_daughters(dyn, b, bi) {
00106         if (bf == NULL || (*bf)(bi)) {
00107             total_mass += bi->get_mass();
00108             rm_table[i].radius = abs(bi->get_pos() - lagr_pos);
00109             rm_table[i].mass = bi->get_mass();
00110             i++;
00111         }
00112     }
00113 
00114     // Sort the array by radius.  (Slightly wasteful, as get_std_center
00115     // will also sort the data if compute_mcom is called.)
00116 
00117     qsort((void *)rm_table, (size_t)i, sizeof(rm_pair), compare_radii);
00118 
00119     // Determine the Lagrangian radii.
00120 
00121     // cerr << "Determining Lagrangian radii 1" << endl << flush;
00122 
00123     real* mass_percent = new real[nzones-1];
00124     if (mass_percent == NULL) {
00125         cerr << "compute_general_mass_radii: "
00126              << "not enough memory left for mass_percent\n";
00127         return;
00128     }
00129 
00130     int k;
00131     for (k = 0; k < nzones-1; k++) {
00132         if (!nonlin) 
00133             mass_percent[k] = ((k + 1) / (real)nzones) * total_mass;
00134         else
00135             mass_percent[k] = nonlin_masses[k] * total_mass;
00136     }
00137 
00138     real *rlagr = new real[nzones-1];
00139     real cumulative_mass = 0.0;
00140     i = 0;
00141 
00142     // cerr << "Determining Lagrangian radii 2" << endl << flush;
00143 
00144     for (k = 0; k < nzones-1; k++) {
00145 
00146         while (cumulative_mass < mass_percent[k])
00147             cumulative_mass += rm_table[i++].mass;
00148 
00149         rlagr[k] = rm_table[i-1].radius;
00150     }
00151 
00152     // cerr << "writing stories" << endl << flush;
00153 
00154     // Place the data in the root dyn story.
00155 
00156     if (bf == NULL)
00157         putiq(b->get_dyn_story(), "boolfn", 0);
00158     else
00159         putiq(b->get_dyn_story(), "boolfn", 1);
00160 
00161     putiq(b->get_dyn_story(), "n_nodes", n);
00162     putrq(b->get_dyn_story(), "lagr_time", b->get_system_time());
00163     putvq(b->get_dyn_story(), "lagr_pos", lagr_pos);
00164     putvq(b->get_dyn_story(), "lagr_vel", lagr_vel);
00165     putsq(b->get_dyn_story(), "pos_type", lagr_string);
00166     putiq(b->get_dyn_story(), "n_lagr", nzones-1);
00167     putra(b->get_dyn_story(), "r_lagr", rlagr, nzones-1);
00168 
00169     delete [] mass_percent;
00170     delete [] rm_table;
00171     delete [] rlagr;
00172 }
00173 
00174 // Convenient synonyms:
00175 
00176 void  compute_mass_radii_quartiles(dyn * b)
00177 {
00178     compute_general_mass_radii(b, 4);
00179 }
00180 
00181 void  compute_mass_radii_percentiles(dyn * b)
00182 {
00183     compute_general_mass_radii(b, 10);
00184 }
00185 
00186 #else
00187 
00188 //-----------------------------------------------------------------------------
00189 //  main  --  driver to use  compute_mass_radii() as a tool
00190 //-----------------------------------------------------------------------------
00191 
00192 main(int argc, char ** argv)
00193 {
00194     char  *comment;
00195     int n = 0;
00196     bool  c_flag = false;      // if TRUE: a comment given on command line
00197     bool  t_flag = false;      // if TRUE: percentiles rather than quartiles
00198     bool  nonlin = false;
00199 
00200     check_help();
00201 
00202     extern char *poptarg;
00203     int c;
00204     char* param_string = "c:n:st";
00205 
00206     while ((c = pgetopt(argc, argv, param_string)) != -1)
00207         switch(c)
00208             {
00209             case 'c': c_flag = true;
00210                       comment = poptarg;
00211                       break;
00212             case 'n': n = atoi(poptarg);
00213                       break;
00214             case 's': n = 10;
00215                       nonlin = true;
00216             case 't': t_flag = true;
00217                       break;
00218             case '?': params_to_usage(cerr, argv[0], param_string);
00219                       get_help();
00220                       exit(1);
00221             }            
00222 
00223     dyn *b;
00224 
00225     while (b = get_dyn(cin)) {
00226 
00227         if (c_flag == TRUE)
00228             b->log_comment(comment);
00229 
00230         b->log_history(argc, argv);
00231 
00232         if (t_flag)
00233             compute_mass_radii_percentiles(b);
00234         else {
00235             if (n <= 1)
00236                 compute_mass_radii_quartiles(b);
00237             else
00238                 compute_general_mass_radii(b, n, nonlin);
00239         }
00240 
00241         // Print out radii in case of quartiles only.
00242 
00243         if (find_qmatch(b->get_dyn_story(), "n_lagr")) {
00244 
00245             int n_lagr = getiq(b->get_dyn_story(), "n_lagr");
00246             real *r_lagr = new real[n_lagr];
00247             getra(b->get_dyn_story(), "r_lagr", r_lagr, n_lagr);
00248             cerr << "r_lagr =";
00249             for (int i = 0; i < n_lagr; i++) cerr << " " << r_lagr[i];
00250             cerr << endl;
00251 
00252         }
00253 
00254         put_dyn(cout, *b);      
00255         delete b;
00256     }
00257 }
00258 
00259 #endif
00260 
00261 // endof: lagrad.C

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