Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

kira_grape_include.C

Go to the documentation of this file.
00001 
00002        //=======================================================//    _\|/_
00003       //  __  _____           ___                    ___       //      /|\ ~
00004      //  /      |      ^     |   \  |         ^     |   \     //          _\|/_
00005     //   \__    |     / \    |___/  |        / \    |___/    //            /|\ ~
00006    //       \   |    /___\   |  \   |       /___\   |   \   // _\|/_
00007   //     ___/   |   /     \  |   \  |____  /     \  |___/  //   /|\ ~
00008  //                                                       //            _\|/_
00009 //=======================================================//              /|\ ~
00010 
00011 // kira_grape_include.C:  All conditional code that depends on GRAPE
00012 //                        availability.  Not compiled into any library,
00013 //                        but instead included directly into kira.C.
00014 //                        scale_grape.C, and the hdyn version of
00015 //                        sys_stats.C when the executable is built.
00016 //
00017 // Convenient to separate these functions from the rest of kira and
00018 // other code, both for identification and ease of reuse.
00019 //
00020 // USE_GRAPE should only be true during the building of kira_grape4/6,
00021 // scale_grape, and sys_stats_grape, and must be set in the appropriate
00022 // Makefile.
00023 //
00024 // Functions defined:
00025 //
00026 //      bool kira_use_grape
00027 //
00028 //      void kira_calculate_internal_energies
00029 //      void kira_calculate_energies
00030 //      void kira_top_level_energies
00031 //      void kira_calculate_top_level_acc_and_jerk
00032 //      void kira_compute_densities
00033 //      void kira_synchronize_tree
00034 //
00035 // The last six functions in effect act as switches to the appropriate
00036 // GRAPEx routines.  If USE_GRAPE is defined at build time, they cause
00037 // the GRAPE libraries to be loaded.
00038 //
00039 //      grape_calculate_energies
00040 //      grape_calculate_acc_and_jerk
00041 //      grape_calculate_densities
00042 
00043 // Note that these functions are declared in hdyn.h, so they are generally
00044 // accessible, but *only* if loaded by an executable including this file...
00045 
00046 bool kira_use_grape()
00047 {
00048 #if defined(USE_GRAPE)
00049     return true;
00050 #else
00051     return false;
00052 #endif
00053 }
00054 
00055 void kira_calculate_internal_energies(hdyn* b,
00056                                       real& epot, real& ekin, real& etot,
00057                                       bool cm,          // default = false
00058                                       bool use_grape)   // default = true
00059 {
00060     // Compute the total internal energy; also compute the "pot" class
00061     // datum.
00062 
00063     // Notes from Steve (8/99):
00064     //
00065     //  - grape_calculate_energies recomputes hdyn::pot, but does
00066     //    *not* include the tidal terms.
00067     //
00068     //  - new code uses the hdyn version of calculate_energies() (see
00069     //    ../util/hdyn_tt.C), which sets the hdyn::pot member data,
00070     //    and also omits the tidal terms.
00071     //
00072     // The cm flag specifies that we should use the center-of-mass
00073     // approximation, i.e. compute the top-level energies only.
00074     // This is what we want for scale.  Implemented for GRAPE by
00075     // Steve, 7/01.
00076 
00077     // This function is called by hdyn::merge_nodes() and kira routine
00078     // calculate_energies_with_external().  Note that use by a member
00079     // function apparently does *not* mean that all tools using hdyns
00080     // need to include this file...
00081 
00082 #if defined(USE_GRAPE)
00083 
00084     if (use_grape)                                      // tautology?
00085 
00086         grape_calculate_energies(b, epot, ekin, etot, cm);
00087 
00088     else
00089 
00090         calculate_energies(b, b->get_eps2(), epot, ekin, etot, cm);
00091 
00092 #else
00093 
00094     calculate_energies(b, b->get_eps2(), epot, ekin, etot, cm);
00095 
00096 #endif
00097 
00098 }
00099 
00100 void kira_calculate_energies(dyn* b, real eps2, 
00101                              real &potential, real &kinetic, real &total,
00102                              bool cm)
00103 {
00104     // Provide an hdyn function with a calling sequence that can be
00105     // substituted for the dyn function dyn::calculate_energies when
00106     // called by sys_stats...  Discard eps2 (--> 0).
00107 
00108     // Called by hdyn/evolve/kira_log.C (kira function print_statistics())
00109     // and hdyn/util/sys_stats.C (standalone tool), in each case as an
00110     // argument to the dyn version of sys_stats.
00111 
00112     kira_calculate_internal_energies((hdyn*)b, potential, kinetic, total, cm);
00113 }
00114 
00115 void kira_top_level_energies(dyn *b, real eps2,
00116                              real& potential_energy,
00117                              real& kinetic_energy)
00118 {
00119     // Another lookalike, this time to perform the operation of
00120     // dyn::get_top_level_energies() using the GRAPE if possible.
00121     // Used only in the standalone tool scale_grape.C as an argument
00122     // to the dyn function scale.
00123 
00124     real energy;
00125     kira_calculate_energies(b, eps2,
00126                             potential_energy, kinetic_energy, energy,
00127                             true);
00128 }
00129 
00130 void kira_calculate_top_level_acc_and_jerk(hdyn ** next_nodes,
00131                                            int n_next,
00132                                            xreal time,
00133                                            bool & restart_grape)
00134 {
00135     // Switch between GRAPE and non-GRAPE determination of the forces
00136     // on the particles in the specified list.  Called only by 
00137     // calculate_acc_and_jerk_for_list() in kira_ev.C.
00138 
00139 #if defined(USE_GRAPE)
00140 
00141     grape_calculate_acc_and_jerk(next_nodes, n_next,
00142                                  time, restart_grape);
00143     restart_grape = false;
00144 
00145 #else
00146 
00147     for (int i = 0; i < n_next; i++) {
00148         hdyn *bi = next_nodes[i];
00149         if (bi->is_top_level_node())
00150             bi->top_level_node_real_force_calculation();
00151     }
00152 
00153 #endif
00154 }
00155 
00156 void kira_compute_densities(hdyn* b, vector& cod_pos, vector& cod_vel)
00157 {
00158     // Density computation (currently limited to GRAPE systems).
00159     // Called only by log_output() in kira_log.C.
00160 
00161 #if defined(USE_GRAPE)
00162 
00163     cerr << "Computing densities using GRAPE..." << endl;
00164     real cpu0 = cpu_time();
00165 
00166     // The second argument determines the squared radius at which
00167     // particles are deemed to have zero densities.  This allows
00168     // discrimination against low-density particles, and also limits
00169     // costly repeat GRAPE calls.
00170 
00171     grape_calculate_densities(b, 0.1);          // (densities are saved in
00172                                                 //  particle dyn stories)
00173     real cpu1 = cpu_time();
00174     compute_mean_cod(b, cod_pos, cod_vel);
00175     real cpu2 = cpu_time();
00176 
00177     cerr << "CPU times:  density " << cpu1 - cpu0
00178          << "  cod " << cpu2 - cpu1
00179          << endl;
00180 
00181 #else
00182 
00183     // Skip as too expensive if no GRAPE is available...
00184 
00185     cerr << "Skipping density calculation..." << endl;
00186 
00187 #endif
00188 
00189 }
00190 
00191 void kira_synchronize_tree(hdyn *b)
00192 {
00193     // GRAPE replacement for synchronize_tree().  Synchronize all
00194     // top-level nodes.  Called from integrate_list() in kira.C and
00195     // hdyn::merge_nodes().  Somewhat more elaborate than other
00196     // functions in this file,/ as the entire algorithm is contained
00197     // here.
00198 
00199 #if defined(USE_GRAPE)
00200 
00201     // Code is similar to that in integrate_list(), but only top-level
00202     // nodes are considered and we don't check for errors in function
00203     // correct_and_update.  Possibly should merge this with (part of)
00204     // integrate_list() and drop synchronize_tree() completely.
00205     //                                                   (Steve, 1/02)
00206 
00207     // Make a list of top-level nodes in need of synchronization.
00208 
00209     xreal sys_t = b->get_system_time();
00210 
00211     cerr << endl
00212          << "synchronizing tree using GRAPE at time " << sys_t
00213          << endl << flush;
00214 
00215     int n_next = 0;
00216     for_all_daughters(hdyn, b, bi)
00217         if (bi->get_time() < sys_t) n_next++;
00218 
00219     hdyn **next_nodes = new hdynptr[n_next];
00220     n_next = 0;
00221     for_all_daughters(hdyn, b, bi)
00222         if (bi->get_time() < sys_t) next_nodes[n_next++] = bi;
00223 
00224     // Integrate all particles on the list.  Start by computing forces.
00225     // (Assume exact = false and ignore_internal = true.)
00226 
00227     for (int i = 0; i < n_next; i++) {
00228         hdyn *bi = next_nodes[i];
00229         predict_loworder_all(bi, sys_t);
00230         bi->clear_interaction();
00231         bi->top_level_node_prologue_for_force_calculation(false);
00232     }
00233 
00234     bool restart_grape = false;
00235     grape_calculate_acc_and_jerk(next_nodes, n_next, sys_t, restart_grape);
00236 
00237     int ntop = get_n_top_level();
00238     for (int i = 0; i < n_next; i++) {
00239         hdyn *bi = next_nodes[i];
00240         bi->inc_direct_force(ntop-1);
00241         bi->top_level_node_epilogue_force_calculation();
00242         bi->inc_steps();
00243     }
00244 
00245     // Complete calculation of accs and jerks by correcting for C.M.
00246     // interactions and applying external fields.
00247 
00248     kira_options *ko = b->get_kira_options();
00249 
00250     for (int i = 0; i < n_next; i++)
00251         next_nodes[i]->set_on_integration_list();
00252 
00253     if (ko->use_old_correct_acc_and_jerk || !ko->use_perturbed_list) {
00254         bool reset = false;
00255         correct_acc_and_jerk(b, reset);                 // old version
00256     } else
00257         correct_acc_and_jerk(next_nodes, n_next);       // new version
00258 
00259     for (int i = 0; i < n_next; i++)
00260         next_nodes[i]->clear_on_integration_list();
00261 
00262     if (b->get_external_field() > 0) {
00263 
00264         // Add external forces.
00265 
00266         for (int i = 0; i < n_next; i++) {
00267             hdyn *bi = next_nodes[i];
00268             real pot;
00269             vector acc, jerk;
00270             get_external_acc(bi, bi->get_pred_pos(), bi->get_pred_vel(),
00271                              pot, acc, jerk);
00272             bi->inc_pot(pot);
00273             bi->inc_acc(acc);
00274             bi->inc_jerk(jerk);
00275         }
00276     }
00277 
00278     // Apply corrector and redetermine timesteps.
00279 
00280     for (int i = 0; i < n_next; i++) {
00281         hdyn *bi = next_nodes[i];
00282         bi->correct_and_update();
00283         bi->init_pred();
00284         bi->store_old_force();
00285     }
00286 
00287     delete [] next_nodes;
00288 
00289     cerr << endl
00290          << "end of synchronization"
00291          << endl << flush;
00292 
00293 #else
00294 
00295     cerr << endl
00296          << "synchronizing tree without GRAPE at time " << b->get_system_time()
00297          << endl;
00298 
00299     synchronize_tree(b);
00300 
00301 #endif
00302 }

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