Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

compute_density.C

Go to the documentation of this file.
00001 
00010 
00011 //.............................................................................
00012 //    version 1:  May 1989   Piet Hut
00013 //    version 2:  Nov 1994   Piet Hut
00014 //.............................................................................
00015 //  non-local function: 
00016 //    compute_density
00017 //.............................................................................
00018 //  see also: density_center.C
00019 //.............................................................................
00020 
00021 
00022 // This program can be very slow, as it runs on the front end.
00023 // It should be made to use the GRAPE if available...
00024 
00025 #include "dyn.h"
00026 
00027 #ifndef TOOLBOX
00028 
00029 //-----------------------------------------------------------------------------
00030 //
00031 // compute_density  --  Compute the density for one or all particles.
00032 //               note:
00033 //                    the neighbor_dist_sq[q] array will contain the distances
00034 //                    to the q-th nearest neighbor (in the form of the squares 
00035 //                    thereof); therefore  neighbor_dist_sq[0] = 0.0  since
00036 //                    this indicates the distance of a particle to itself.
00037 //                    Including this trivial case simplifies the algorithm
00038 //                    below by making it more homogeneous.
00039 //-----------------------------------------------------------------------------
00040 //              Litt.:
00041 //                    Stefano Casertano and Piet Hut: Astroph.J. 298,80 (1985).
00042 //                    To use their recipe, k >= 2 is required.
00043 //-----------------------------------------------------------------------------
00044 
00045 void  compute_density(dyn * b,          // pointer to N-body system or node
00046                       int k,            // use kth nearest neighbor [12]
00047                       dyn ** list,      // list of neighbor nodes to work from
00048                       int n_list)       // number of nodes on the list
00049 
00050 // If list = NULL [default] or n_list = 0, use the entire system.
00051 
00052 {
00053     int  q, r;
00054     real *neighbor_dist_sq;
00055     real *neighbor_mass;
00056     real  delr_sq;
00057     
00058     if (k <= 1) {
00059         cerr << "compute_density: k = " << k << " <= 1" << endl;
00060         return;
00061     }
00062 
00063     if (list == NULL)
00064         n_list = 0;
00065     else if (n_list <= 0) {
00066         cerr << "compute_density: n_list = " << n_list << endl;
00067         return;
00068     }
00069 
00070     int nsys = b->n_leaves() - 1;
00071     if (n_list > 0)
00072         nsys = n_list;
00073 
00074     if (k > nsys) {                     // no k-th nearest neighbor exists
00075         cerr << "compute_density: k = " << k << " >= nsys = " << nsys << endl;
00076         return;
00077     }
00078 
00079     neighbor_dist_sq = new real[k+1];
00080     neighbor_mass = new real[k+1];
00081 
00082 
00083 
00084         // **** Problem with k = 12?? ****
00085 
00086 
00087 
00088     // Set first body d for which density is to be computed.
00089 
00090     // for_all_leaves(dyn, b, d) {      // The density is now defined
00091     // for_all_daughters(dyn, b, d) {   // ONLY for top-level nodes.
00092 
00093     dyn* d;
00094 
00095     if (list)
00096         d = b;
00097     else
00098         d = b->get_oldest_daughter();   // b is root in this case
00099 
00100     while (d) {
00101 
00102         neighbor_dist_sq[0] = 0.0;
00103         neighbor_mass[0] = d->get_mass();
00104         for (q = 1; q <= k; q++) {
00105             neighbor_dist_sq[q] = VERY_LARGE_NUMBER;
00106             neighbor_mass[q] = 0;
00107         }
00108 
00109         // Search bodies dd to find k-th nearest neighbor.
00110         // May be slow if the original list is long -- qsort should
00111         // perhaps be used.
00112 
00113         // for_all_leaves(dyn, b, dd) {
00114         // for_all_daughters(dyn, b, dd) {
00115 
00116         dyn* dd;
00117 
00118         if (list)
00119             dd = list[n_list-1];
00120         else
00121             dd = b->get_oldest_daughter();      // b is root
00122 
00123         while (dd) {
00124 
00125             if (d != dd) {
00126 
00127                 delr_sq = square(something_relative_to_root(d, &dyn::get_pos)
00128                               - something_relative_to_root(dd, &dyn::get_pos));
00129 
00130                 if (delr_sq < neighbor_dist_sq[k]) {
00131 
00132                     // Place dd on d's neighbor list.
00133 
00134                     for (q = k-1; q >= 0; q--) {
00135                         if (delr_sq > neighbor_dist_sq[q]) {
00136                             for (r = k; r > q+1; r--) {
00137                                 neighbor_dist_sq[r] = neighbor_dist_sq[r-1];
00138                                 neighbor_mass[r] = neighbor_mass[r-1];
00139                             }
00140                             neighbor_dist_sq[q+1] = delr_sq;
00141                             neighbor_mass[q+1] = dd->get_mass();
00142 
00143                             break;
00144                         }
00145                     }
00146                 }
00147             }
00148 
00149             // Get next dd.
00150 
00151             if (list) {
00152                 if (--n_list < 0)
00153                     dd = NULL;
00154                 else
00155                     dd = list[n_list];
00156             } else
00157                 dd = dd->get_younger_sister();
00158         }
00159             
00160         real density =  0;
00161 
00162         if (neighbor_dist_sq[k] > 0) {
00163             while (k > 0 && neighbor_dist_sq[k] >= VERY_LARGE_NUMBER)
00164                 k--;
00165             if (k > 1 && neighbor_dist_sq[k] > 0
00166                       && neighbor_dist_sq[k] < VERY_LARGE_NUMBER) {
00167                 real volume = (4.0/3.0) * PI * pow(neighbor_dist_sq[k], 1.5);
00168                 if (volume > 0) {
00169 //                  density = (k - 1) / volume;     // ApJ, 298, 80 (1985)
00170 
00171                     real mass = 0;   
00172                     for(int m=1; m<k; m++) // exclude seld and outer most stars.
00173                         mass += neighbor_mass[k]; 
00174                     density = mass/volume;    // ApJ, 298, 80 (1985)
00175                 }
00176             }
00177         }
00178 
00179         // Store the density in d's dyn story.
00180 
00181         putrq(d->get_dyn_story(), "density_time", b->get_system_time());
00182         putiq(d->get_dyn_story(), "density_k_level", k);
00183         putrq(d->get_dyn_story(), "density", density);
00184 
00185         // Get next d.
00186 
00187         if (list)
00188             d = NULL;
00189         else
00190             d = d->get_younger_sister();
00191     }
00192 
00193     // Timestamp the density computation if the entire system was involved.
00194 
00195     if (!list) {
00196         dyn* root = b->get_root();
00197         putrq(root->get_dyn_story(), "density_time", root->get_system_time());
00198     }
00199 
00200     // Clean up.
00201 
00202     delete neighbor_dist_sq;
00203     delete neighbor_mass;
00204 }
00205 
00206 #else
00207 
00208 main(int argc, char ** argv)
00209 {
00210     int  k = 12;                // default
00211 
00212     char *comment;
00213     bool c_flag = false;        // if true: a comment given on command line
00214     bool verbose = false;
00215 
00216     check_help();
00217 
00218     extern char *poptarg;
00219     int c;
00220     char* param_string = "c:k:v";
00221 
00222     while ((c = pgetopt(argc, argv, param_string)) != -1)
00223         switch(c) {
00224             case 'c': c_flag = true;
00225                       comment = poptarg;
00226                       break;
00227             case 'k': k = atoi(poptarg);
00228                       break;
00229             case 'v': verbose = !verbose;
00230                       break;
00231             case '?': params_to_usage(cerr, argv[0], param_string);
00232                       get_help();
00233                       exit(1);
00234         }
00235 
00236     // Loop over input until no more data remain.
00237 
00238     dyn *b;
00239     int i = 0;
00240     while (b = get_dyn(cin)) {
00241 
00242         if (verbose) cerr << "snap #" << ++i
00243                           << ", time = " << b->get_system_time() << endl;
00244 
00245         if (c_flag) b->log_comment(comment);
00246         b->log_history(argc, argv);
00247 
00248         compute_density(b, k);
00249 
00250         put_dyn(cout, *b);
00251         rmtree(b);
00252     }
00253 }
00254 
00255 #endif
00256 
00257 // endof: compute_density.C

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