Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

kira_ev.C

Go to the documentation of this file.
00001 
00002        //=======================================================//    _\|/_
00003       //  __  _____           ___                    ___       //      /|\ ~
00004      //  /      |      ^     |   \  |         ^     |   \     //          _\|/_
00005     //   \__    |     / \    |___/  |        / \    |___/    //            /|\ ~
00006    //       \   |    /___\   |  \   |       /___\   |   \   // _\|/_
00007   //     ___/   |   /     \  |   \  |____  /     \  |___/  //   /|\ ~
00008  //                                                       //            _\|/_
00009 //=======================================================//              /|\ ~
00010 
00011 // Functions associated with integration within kira.
00012 //
00013 // Externally visible functions:
00014 //
00015 //      void calculate_acc_and_jerk_for_list
00016 //      void calculate_acc_and_jerk_on_all_top_level_nodes
00017 //      void initialize_system_phase2
00018 //      void clean_up_kira_ev
00019 
00020 #include "hdyn.h"
00021 
00022 // Set TIME_INTERNAL to perform timing of force-evaluation functions
00023 // in calculate_acc_and_jerk_for_list().
00024 
00025 //#define TIME_INTERNAL
00026 
00027 void calculate_acc_and_jerk_for_list(hdyn *b,
00028                                      hdyn **next_nodes,
00029                                      int  n_next,
00030                                      xreal time,
00031                                      bool exact,
00032                                      bool tree_changed,
00033                                      bool &reset_force_correction, // no longer
00034                                                                    // used...
00035                                      bool &restart_grape)
00036 {
00037     // Note that this function uses the same function calls as
00038     // calculate_acc_and_jerk_on_top_level_node, but in a different
00039     // order: all prologue calls are performed first, then all
00040     // top-level (i.e. GRAPE) force calculations, then all epilogue
00041     // calls.
00042 
00043     bool ignore_internal = next_nodes[0]->get_ignore_internal();
00044 
00045 #ifdef TIME_INTERNAL
00046 
00047     // Code to time specific force-calculation operations:
00048 
00049     real cpu0, cpu1, cpu2, cpu3, cpu4;
00050     int kmax = 1;
00051 
00052         for (int k = 0; k < n_next; k++) {
00053             hdyn* bi = next_nodes[k];
00054 
00055             if (bi->name_is("13a")
00056                 && bi->get_kepler() == NULL
00057                 && bi->get_time() > 6.6
00058                 && bi->find_perturber_node()
00059                 && bi->find_perturber_node()->get_n_perturbers() > 0
00060                 ) {
00061 
00062                 // Found the particle.  Clean up the rest of the list.
00063 
00064                 for (int kk = 0; kk < n_next; kk++)
00065                     if (kk != k)
00066                         next_nodes[kk]->set_timestep(VERY_LARGE_NUMBER);
00067                 n_next = 1;
00068                 next_nodes[0] = bi;
00069 
00070                 int p = cerr.precision(HIGH_PRECISION);
00071                 cerr << endl << "timing " << bi->format_label()
00072                      << " at time " << bi->get_system_time() << endl;
00073                 if (bi->is_low_level_node()) {
00074                     PRL(bi->get_top_level_node()->format_label());
00075                     if (bi->find_perturber_node()) {
00076                         PRL(bi->find_perturber_node()->format_label());
00077                         PRL(bi->find_perturber_node()->get_n_perturbers());
00078                     }
00079                 }
00080                 cerr.precision(p);
00081 
00082                 kmax = 25000;
00083                 cpu0 = cpu_time();
00084             }
00085         }
00086     }
00087 
00088     for (int k = 0; k < kmax; k++) {
00089 
00090 #endif
00091 
00092     xreal sys_t = next_nodes[0]->get_system_time();
00093 
00094     for (int i = 0; i < n_next; i++) {
00095 
00096         hdyn *bi = next_nodes[i];
00097 
00098         // Predict the entire clump containing node bi (Steve, 8/98):
00099 
00100         predict_loworder_all(bi->get_top_level_node(), sys_t);
00101 
00102         if (bi->is_top_level_node()) {
00103             bi->clear_interaction();
00104             bi->top_level_node_prologue_for_force_calculation(exact);
00105         }
00106     }
00107 
00108 #ifdef TIME_INTERNAL
00109     }
00110     if (kmax > 1) cpu1 = cpu_time();
00111 #endif
00112 
00113     if (tree_changed)
00114         restart_grape = true;
00115 
00116 #ifdef TIME_INTERNAL
00117     for (int k = 0; k < kmax; k++) {
00118 #endif
00119 
00120     if (!exact) {
00121 
00122         if (!ignore_internal)
00123             kira_calculate_top_level_acc_and_jerk(next_nodes, n_next,
00124                                                   time, restart_grape);
00125 
00126         // (Uses grape_calculate_acc_and_jerk or
00127         //  top_level_node_real_force_calculation, as appropriate.)
00128 
00129         int n = get_n_top_level();
00130 
00131         for (int i = 0; i < n_next; i++) {
00132             hdyn *bi = next_nodes[i];
00133 
00134             if (ignore_internal) {
00135                 bi->set_nn(bi);
00136                 bi->set_coll(bi);
00137                 bi->set_d_nn_sq(VERY_LARGE_NUMBER);
00138             }
00139 
00140             if (bi->is_top_level_node()) {
00141 
00142                 bi->inc_direct_force(n-1);      // direct force counter
00143 
00144                 bi->top_level_node_epilogue_force_calculation();
00145             }
00146         }
00147     }
00148 
00149 #ifdef TIME_INTERNAL
00150     }
00151     if (kmax > 1) cpu2 = cpu_time();
00152 #endif
00153 
00154     kira_diag *kd = next_nodes[0]->get_kira_diag();
00155 
00156 #ifdef TIME_INTERNAL
00157     for (int k = 0; k < kmax; k++) {
00158 #endif
00159 
00160     for (int i = 0; i < n_next; i++) {
00161         hdyn *bi = next_nodes[i];
00162 
00163         // Compute forces on low-level nodes.
00164 
00165         if (bi->is_low_level_node() && bi->get_kepler() == NULL) {
00166 
00167             if (kd->kira_ev) {
00168                 cerr << "\nComputing force on low-level node "
00169                      << bi->format_label() << endl;
00170             }
00171 
00172             bi->clear_interaction();
00173             bi->calculate_acc_and_jerk(exact);
00174 
00175             if (kd->kira_ev) {
00176                 PRL(bi->get_acc());
00177                 PRL(bi->get_binary_sister()->get_acc());
00178                 PRL(bi->get_pos());
00179                 PRL(bi->get_binary_sister()->get_pos());
00180             }
00181         }
00182 
00183         // Update all step counters (direct force counters are
00184         // incremented above; indirect force counters are handled
00185         // in hdyn_ev.C)
00186 
00187 #ifdef TIME_INTERNAL
00188         if (k == 0)
00189 #endif
00190 
00191         bi->inc_steps();
00192     }
00193 
00194 #ifdef TIME_INTERNAL
00195     }
00196     if (kmax > 1) cpu3 = cpu_time();
00197 #endif
00198 
00199     // Complete calculation of accs and jerks by correcting for C.M.
00200     // interactions.
00201 
00202     kira_options *ko = next_nodes[0]->get_kira_options();
00203 
00204 #ifdef TIME_INTERNAL
00205     for (int k = 0; k < kmax; k++) {
00206 #endif
00207 
00208     if (!exact) {
00209 
00210         // Note: correct_acc_and_jerk() now checks list membership to
00211         // determine if correction is needed.
00212 
00213         // The new version of correct_acc_and_jerk appears to work, but
00214         // retain the possibility of reverting to the old version until we
00215         // are sure there are no problems.  Results of the two versions
00216         // are similar, but *not* identical.
00217 
00218         // On_integration_list flags are for use by correct_acc_and_jerk(),
00219         // to ensure that we only correct interactions between objects on
00220         // the list.
00221 
00222         for (int i = 0; i < n_next; i++)
00223             next_nodes[i]->set_on_integration_list();
00224 
00225         if (ko->use_old_correct_acc_and_jerk || !ko->use_perturbed_list)
00226 
00227             correct_acc_and_jerk(b,                     // old version
00228                                  reset_force_correction);
00229         else
00230 
00231             correct_acc_and_jerk(next_nodes, n_next);   // new version
00232 
00233         // Cautiously unset the "on_integration_list" flags...
00234 
00235         for (int i = 0; i < n_next; i++) {
00236             hdyn *n = next_nodes[i];
00237             if (n && n->is_valid())
00238                 n->clear_on_integration_list();
00239         }
00240 
00241     }
00242 
00243 #ifdef TIME_INTERNAL
00244     }
00245     if (kmax > 1) cpu4 = cpu_time();
00246 
00247     for (int k = 0; k < kmax; k++) {
00248 #endif
00249 
00250     if (b->get_external_field() > 0) {
00251 
00252         // Add external forces.
00253 
00254         for (int i = 0; i < n_next; i++)
00255             if (next_nodes[i]->is_top_level_node()) {
00256                 hdyn *bb = next_nodes[i];
00257                 real pot;
00258                 vector acc, jerk;
00259                 get_external_acc(bb, bb->get_pred_pos(), bb->get_pred_vel(),
00260                                  pot, acc, jerk);
00261                 bb->inc_pot(pot);
00262                 bb->inc_acc(acc);
00263                 bb->inc_jerk(jerk);
00264             }
00265     }
00266 
00267 #ifdef TIME_INTERNAL
00268     }
00269     if (kmax > 1) {
00270         cerr << "CPU times:  "
00271              << (cpu1-cpu0)/kmax << "  "
00272              << (cpu2-cpu1)/kmax << "  "
00273              << (cpu3-cpu2)/kmax << "  "
00274              << (cpu4-cpu3)/kmax << "  "
00275              << (cpu_time()-cpu4)/kmax << endl;
00276         exit(0);
00277     }
00278 #endif
00279 }
00280 
00281 void calculate_acc_and_jerk_on_all_top_level_nodes(hdyn * b)
00282 {
00283     int n_top = b->n_daughters();
00284     hdynptr * list = new hdynptr[n_top];
00285 
00286     int i_top = 0;
00287     for_all_daughters(hdyn, b, bb)
00288         list[i_top++] = bb;
00289 
00290     bool reset_force_correction = true;         // (no longer used)
00291     bool restart_grape = true;
00292 
00293     calculate_acc_and_jerk_for_list(b, list, n_top,
00294                                     b->get_system_time(),
00295                                     false,      // usually what we want...
00296                                     false,      // called before tree changes
00297                                     reset_force_correction, // no longer used
00298                                     restart_grape);
00299 
00300     delete [] list;
00301 }
00302 
00303 
00304 
00305 // initialize_system_phase2:  Calculate acc, jerk, timestep, etc for all nodes.
00306 
00307 // System should be synchronized prior to calling this function.
00308 
00309 // Static data:
00310 
00311 static int work_size = 0;
00312 static hdyn ** nodes = NULL;
00313 static int nnodes = -1;
00314 
00315 // Allow possibility of cleaning up if necessary:
00316 
00317 void clean_up_kira_ev() {if (nodes) delete [] nodes;}
00318 
00319 void initialize_system_phase2(hdyn * b,
00320                               int call_id,      // default = 0
00321                               bool set_dt)      // default = true
00322 {
00323 //    cerr << "initialize_system_phase2: "; PRL(call_id);
00324 
00325     dbg_message("initialize_system_phase2", b);
00326 
00327     if (!b->is_root()) {
00328         err_exit("initialize_system_phase2 called with non-root");
00329     }
00330 
00331     int n = 0;
00332     for_all_nodes(hdyn, b, b1) n++ ;
00333 
00334     if  (work_size < n) {
00335         if (!nodes) delete [] nodes;
00336         work_size = n + 10;
00337         nodes = new hdynptr[work_size];
00338     }
00339 
00340     // (New variable names necessary here because of DEC C++...)
00341 
00342     for_all_nodes(hdyn, b, b2) {
00343         if (!b2->get_kepler() && (b2->get_unperturbed_timestep() > 0)) {
00344 
00345             // When is this necessary? (SLWM 3/98)
00346 
00347             int p = cerr.precision(HIGH_PRECISION);
00348             cerr << endl
00349                  << "initialize_system_phase2: "
00350                  << "creating kepler for unperturbed binary"
00351                  << endl
00352                  << "    " << b2->get_parent()->format_label()
00353                  << " at system time " << b->get_system_time()
00354                  << "  call_id = " << call_id
00355                  << endl;
00356             cerr.precision(p);
00357 
00358             b2->update_kepler_from_hdyn();
00359 
00360         }
00361     }
00362 
00363     // Make a list of all nodes except unperturbed binary components.
00364 
00365     n = 0;
00366     for_all_nodes(hdyn, b, b3) {
00367         if ((b3 != b) && (!b3->get_kepler())) {
00368             nodes[n] = b3;
00369             n++ ;
00370         }
00371     }
00372 
00373     xreal time = nodes[0]->get_system_time();
00374 
00375     bool tree_changed = true;
00376     bool reset_force_correction = true; // no longer used
00377     bool restart_grape = true;
00378     bool exact = false;
00379 
00380     calculate_acc_and_jerk_for_list(b, nodes, n, time,
00381                                     exact,
00382                                     tree_changed,
00383                                     reset_force_correction,  // no longer used
00384                                     restart_grape);
00385 
00386     // (All perturber lists have been redetermined...)
00387 
00388     real min_dt = VERY_LARGE_NUMBER;
00389 
00390     for_all_nodes(hdyn, b, b4) {
00391         if ((b4 != b) && (!b4->get_kepler())) {
00392             b4->store_old_force();
00393             if (set_dt || (b4->get_time() <= 0 || b4->get_timestep() <= 0) ) {
00394                 b4->set_first_timestep();
00395 
00396                 if (b4->get_time() + b4->get_timestep()
00397                     < b->get_system_time()) {
00398 
00399                     // Note from Steve and Simon, 26Feb, 1999:
00400 
00401                     // This bug can only occur if the function is
00402                     // improperly called.
00403 
00404                     cerr << endl << "warning: initialize_system_phase2: "
00405                          << "time will go backwards!" << endl;
00406                     cerr << "function should not be called with "
00407                          << "unsynchronized system." << endl << endl;
00408                     pp3(b4);
00409 
00410                     // Fix would be to force timestep to go past system
00411                     // time, but this is not in general possible while
00412                     // maintaining the block step structure.  Could
00413                     // simply terminate here, but for now we let the
00414                     // code die in kira.C.
00415 
00416                 }
00417 
00418             }
00419 
00420             min_dt = min(min_dt, b4->get_timestep());
00421         }
00422     }
00423 
00424     // Check for perturbed binaries in the input data...
00425 
00426     if (set_dt && b->get_system_time() <= 0) {
00427         for_all_nodes(hdyn, b, b5) {
00428             if ((b5 != b) && (!b5->get_kepler())) {
00429                 if (b5->is_parent()
00430                     && b5->get_oldest_daughter()
00431                          ->get_perturbation_squared() > 1)
00432                     b5->set_timestep(min_dt);
00433             }
00434         }
00435     }
00436 
00437     // cerr << "leaving initialize_system_phase2()\n\n";
00438 }

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