Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

compute_mcom.C

Go to the documentation of this file.
00001 
00013 
00014 #include "dyn.h"
00015 
00016 #ifndef TOOLBOX
00017 
00018 typedef  struct
00019 {
00020     real r2;
00021     dyn  *p;
00022 } rp_pair, *rp_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 (((rp_pair_ptr) pi)->r2 > ((rp_pair_ptr) pj)->r2)
00031         return +1;
00032     else if (((rp_pair_ptr)pi)->r2 < ((rp_pair_ptr)pj)->r2)
00033         return -1;
00034     else
00035         return 0;
00036 }
00037 
00038 void compute_mcom(dyn *b,
00039                   vector& pos, vector& vel,
00040                   real f,                       // default = 0.9
00041                   int n_iter)                   // default = 2
00042 {
00043     // See if mcom_pos is already defined and up to date, with the
00044     // same value of f.
00045 
00046     if (find_qmatch(b->get_dyn_story(), "mcom_pos")
00047         && getrq(b->get_dyn_story(), "mcom_f") == f
00048         && getrq(b->get_dyn_story(), "mcom_time") == b->get_system_time()) {
00049         pos = getvq(b->get_dyn_story(), "mcom_pos");
00050         vel = getvq(b->get_dyn_story(), "mcom_vel");
00051         return;
00052     }
00053 
00054     // See if com_pos is already defined and up to date, or compute it.
00055 
00056     if (find_qmatch(b->get_dyn_story(), "com_pos")
00057         && getrq(b->get_dyn_story(), "com_time") == b->get_system_time()) {
00058         pos = getvq(b->get_dyn_story(), "com_pos");
00059         vel = getvq(b->get_dyn_story(), "com_vel");
00060     } else
00061         compute_com(b, pos, vel);
00062 
00063     // Use pos and vel as the starting point for computing the modified com.
00064 
00065     int n = 0;
00066     for_all_daughters(dyn, b, bb) n++;
00067     rp_pair *rp = new rp_pair[n];
00068 
00069     if (rp == NULL) {
00070         cerr << "compute_mcom: "
00071              << "not enough memory to store rp_pair array\n";
00072         return;
00073     }
00074 
00075     bool loop;
00076     int count = n_iter;
00077 
00078     if (f > 1) f = 1;
00079     if (f == 1) count = 0;
00080 
00081     do {
00082         loop = false;
00083 
00084         // Set up an array of radii.
00085 
00086         int i = 0;
00087         for_all_daughters(dyn, b, bi) {
00088             rp[i].r2 = square(bi->get_pos() - pos);
00089             rp[i].p = bi;
00090             i++;
00091         }
00092 
00093         // Sort the array by radius.
00094 
00095         qsort((void *)rp, (size_t)i, sizeof(rp_pair), compare_radii);
00096 
00097         // Compute mpos and mvel by removing outliers.
00098 
00099         // Currently, apply mass independent weighting to all stars, but
00100         // let the weighting function go smoothly to zero at the cutoff.
00101 
00102         real r_max2i = 1/rp[(int)(f*n)].r2;
00103         real weighted_mass = 0;
00104         vector new_pos = 0, new_vel = 0;
00105 
00106         for (i = 0; i < f*n; i++) {
00107             dyn *bi = rp[i].p;
00108             real weight = bi->get_mass() * max(0.0, 1 - rp[i].r2*r_max2i);
00109             weighted_mass += weight;
00110             new_pos += weight * bi->get_pos();
00111             new_vel += weight * bi->get_vel();
00112         }
00113 
00114         if (weighted_mass > 0) {
00115             pos = new_pos / weighted_mass;
00116             vel = new_vel / weighted_mass;
00117             if (count-- > 0) loop = true;
00118         }
00119 
00120     } while (loop);
00121 
00122     putrq(b->get_dyn_story(), "mcom_time", b->get_system_time());
00123     putvq(b->get_dyn_story(), "mcom_pos", pos);
00124     putvq(b->get_dyn_story(), "mcom_vel", vel);
00125     putrq(b->get_dyn_story(), "mcom_f", f);
00126     putiq(b->get_dyn_story(), "mcom_n_iter", n_iter);
00127 }
00128 
00129 void compute_mcom(dyn *b,
00130                   real f,                       // default = 0.9
00131                   int n_iter)                   // default = 2
00132 {
00133     vector pos, vel;
00134     compute_mcom(b, pos, vel, f, n_iter);
00135 }
00136 
00137 #else
00138 
00139 //-----------------------------------------------------------------------------
00140 //  main  --  driver to use compute_mcom() as a tool
00141 //-----------------------------------------------------------------------------
00142 
00143 main(int argc, char ** argv)
00144 {
00145     char  *comment;
00146     dyn * b;
00147     bool  c_flag = FALSE;       // if TRUE: a comment given on command line
00148 
00149     check_help();
00150 
00151     extern char *poptarg;
00152     int c;
00153     real f = 0.9;
00154     char* param_string = "c:f:";
00155 
00156     while ((c = pgetopt(argc, argv, param_string)) != -1)
00157         switch(c) {
00158 
00159             case 'c': c_flag = TRUE;
00160                       comment = poptarg;
00161                       break;
00162             case 'f': f = atof(poptarg);
00163                       break;
00164             case '?': params_to_usage(cerr, argv[0], param_string);
00165                       get_help();
00166                       exit(1);
00167         }            
00168 
00169     if ((b = get_dyn(cin)) == NULL)
00170        err_exit("compute_mcom: No N-body system on standard input");
00171 
00172     while (b) {
00173 
00174         if (c_flag == TRUE)
00175             b->log_comment(comment);
00176         b->log_history(argc, argv);
00177 
00178         compute_mcom(b, f);
00179 
00180         // Write system to stdout and get next system (if any).
00181 
00182         put_dyn(cout, *b);
00183         rmtree(b);
00184         b = get_dyn(cin);
00185     }
00186 }
00187 
00188 #endif
00189 
00190 // endof: compute_mcom.C

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