Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

dyn_di.C

Go to the documentation of this file.
00001 //
00002 // dyn_di.C: dyn-specific diagnostic functions.
00003 //
00004 
00005 #include "dyn.h"
00006 
00007 void dbg_message(char* s, dyn* b) {
00008 #ifdef DEBUG    
00009     cerr << s << " ";
00010     b->pretty_print_node(cerr); cerr << "\n";
00011 #else
00012     char* dummy_char = s;       // to keep the compiler happy
00013     dyn* dummy = b;             // to keep the compiler happy
00014 #endif    
00015 }
00016 
00017 void dbg_message(char* s, dyn* bj, dyn *bi) {
00018 #ifdef DEBUG    
00019     cerr << s << " ";
00020     bj->pretty_print_node(cerr); cerr << "->";
00021     bi->pretty_print_node(cerr); cerr << "\n";
00022 #else
00023     char* dummy_char = s;       // to keep the compiler happy
00024     dyn* dummy_i = bi;          // to keep the compiler happy
00025     dyn* dummy_j = bj;          // to keep the compiler happy
00026 #endif    
00027 }
00028 
00029 local inline void accumulate_pot_on_work(real mass,
00030                                          vector d_pos,
00031 //                                       vector d_vel,  // not used
00032                                          real eps2,
00033                                          real & p) {
00034     real r2inv = 1.0 / (d_pos*d_pos + eps2);
00035     real mrinv = mass * sqrt(r2inv);
00036     p -= mrinv;
00037 
00038 //  silly trick to make the compiler shut up about "warning:  d_vel not used":
00039 //    vector dummy = d_vel;
00040 
00041 //    cout << "work p = " << p << " \n";    
00042 }
00043 
00044 local void tree_calculate_pot(dyn * bj,
00045                               dyn *mask,
00046                               dyn *bi,
00047                               vector offset_pos,
00048 //                            vector offset_vel,
00049                               real eps2,
00050                               real & p)
00051 {
00052     if (bj == mask) return;
00053 
00054     if (bj->get_oldest_daughter()) {
00055         for_all_daughters(dyn, bj, bb)
00056             tree_calculate_pot(bb, mask, bi,
00057                                offset_pos + bb->get_pos(),
00058 //                             offset_vel + bb->get_vel(),
00059                                eps2, p);                        // recursion
00060     } else {
00061         if (bj != bi)
00062             accumulate_pot_on_work(bj->get_mass(), offset_pos,
00063 //                                 offset_vel,
00064                                    eps2, p);
00065     }
00066 }
00067 
00068 
00069 local void calculate_pot_on_leaf(dyn * bj,
00070                                  dyn *mask,
00071                                  dyn *bi,
00072                                  real eps2,
00073                                  real & p)
00074 {
00075     // dbg_message("calculate_pot_on_leaf", bi);
00076 
00077     vector d_pos;
00078 //    vector d_vel;
00079     for(dyn * b = bi; b != bj; b = b->get_parent()){
00080         d_pos -= b->get_pos();
00081 //      d_vel -= b->get_vel();
00082     }
00083     tree_calculate_pot(bj, mask, bi,
00084                        d_pos,
00085 //                     d_vel,
00086                        eps2, p);
00087 }
00088 
00089 local real pot_on_node(dyn * bj,                // root node for computation
00090                        dyn * mask,              // exclude all nodes under mask
00091                        dyn * bi,                // compute potential on node bi
00092                        real eps2)               // softening parameter
00093 {
00094     // Compute the potential per unit mass on node bi due to all nodes
00095     // under node bj, excluding nodes under node mask.
00096 
00097     real p = 0;
00098     real mtot = 0;
00099 
00100     if (bi->get_oldest_daughter() == NULL) {
00101 
00102         calculate_pot_on_leaf(bj, mask, bi, eps2, p);
00103 
00104     } else {
00105 
00106         // Potential is sum of daughter potentials.
00107 
00108         real p_daughter;
00109         for_all_daughters(dyn, bi, bd) {
00110             real m_daughter = bd->get_mass();
00111             p_daughter = pot_on_node(bj, mask, bd, eps2);       // recursion
00112             p += m_daughter * p_daughter;
00113             mtot += m_daughter;
00114         }
00115 
00116         real minv = 1/mtot;
00117         p *= minv;
00118     }
00119     return p;
00120 }
00121 
00122 local real pot_on_low_level_node(dyn * bi, real eps2)
00123 {
00124     // Compute the potential on bi due to its binary sister only.
00125 
00126     dyn * parent = bi->get_parent();
00127 
00128     if (parent->get_oldest_daughter()
00129               ->get_younger_sister()->get_younger_sister())
00130         err_exit("pot_on_low_level_node: not a binary node!");
00131 
00132     dyn * sister = bi->get_elder_sister();
00133     if (sister == NULL) sister = bi->get_younger_sister();
00134     
00135     return pot_on_node(parent, bi, bi, eps2);
00136 }
00137 
00138 local inline real cm_pot_on_node(dyn * bj, dyn * bi, real eps2)
00139 {
00140     // Compute the potential per unit mass on node bi due to all daughters
00141     // of node bj, using the center of mass approximation throughout.
00142 
00143     real p = 0;
00144     for_all_daughters(dyn, bj, bb)
00145         if (bb != bi)
00146             accumulate_pot_on_work(bb->get_mass(),
00147                                    bb->get_pos() - bi->get_pos(),
00148 //                                 bb->get_vel() - bi->get_vel(),
00149                                    eps2, p);
00150     return p;
00151 }
00152 
00153 real pot_on_general_node(dyn * bj, dyn * bi, real eps2, bool cm = false)
00154 {
00155     // Calculate potential (per unit mass) on top-level node bi due to
00156     // all nodes under node bj, or the potential on low-level node bi due
00157     // to its binary sister.  If cm = true, then bj is the root node, bi
00158     // is a top-level node, and the center of mass approximation is to be
00159     // used.
00160 
00161     if (bi->is_top_level_node()) {
00162 
00163         // Silly to carry the cm flag through the many levels of recursion
00164         // used in the general case.  Just compute the CM pot as a special
00165         // case.  Do this here, rather than in accumulate_energies, because
00166         // the hdyn version of this function will want to set the value
00167         // of pot on return.
00168 
00169         if (cm)
00170             return cm_pot_on_node(bj, bi, eps2);
00171         else
00172             return pot_on_node(bj, bi, bi, eps2);
00173 
00174     } else
00175 
00176         return pot_on_low_level_node(bi, eps2);
00177 }
00178 
00179 local void accumulate_energies(dyn * root, dyn * b, real eps2,
00180                                real & epot, real & ekin, real & etot,
00181                                bool cm = false)
00182 {
00183     if (b->get_oldest_daughter()) {
00184 
00185         // Start/continue the recursion.  In the cm = true case,
00186         // expand daughters only if root really is root.
00187 
00188         if (!cm || b->is_root())
00189             for_all_daughters(dyn, b, bb)
00190                 accumulate_energies(root, bb, eps2, epot, ekin, etot, cm);
00191 
00192         etot = epot + ekin;
00193     }
00194 
00195     // Do the work.
00196 
00197     if (!b->is_root()) {
00198         real m2 = 0.5 * b->get_mass();
00199         epot += m2 * pot_on_general_node(root, b, eps2, cm);
00200         ekin += m2 * square(b->get_vel());
00201     }
00202 }
00203 
00204 void calculate_energies(dyn * root, real eps2,
00205                         real & epot, real & ekin, real & etot,
00206                         bool cm)        // default = false
00207 {
00208     epot = ekin = etot = 0;
00209     accumulate_energies(root, root, eps2, epot, ekin, etot, cm);
00210 }
00211 
00212 void print_recalculated_energies(dyn * b, int mode, real eps2, real e_corr)
00213 {
00214     real epot = 0;
00215     real ekin = 0;
00216     real etot = 0;
00217     static real initial_etot;
00218 
00219     if (!b->get_ignore_internal())
00220         accumulate_energies(b, b, eps2, epot, ekin, etot);
00221 
00222     cerr << "Energies: " << epot << " " << ekin << " " << etot
00223          << " " << initial_etot;
00224 
00225     if (mode) {
00226 
00227         // real de = (etot - e_corr - initial_etot) / epot;
00228 
00229         // The above normalization fails if many stars have escaped
00230         // the system with HUGE kicks...
00231 
00232         real de = (etot - e_corr - initial_etot) / initial_etot;
00233         cerr << " de = " << de << endl;
00234 
00235     } else {
00236         initial_etot = etot;
00237         cerr << "\n";
00238     }   
00239 }

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