Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

update_node.C

Go to the documentation of this file.
00001 local INLINE void set_kepler_from_tdyn_pair(kepler *k, tdyn *b, tdyn *sis)
00002 {
00003     k->set_time(b->get_time());
00004     k->set_total_mass(b->get_mass() + sis->get_mass());
00005     k->set_rel_pos(sis->get_pos() - b->get_pos());
00006     k->set_rel_vel(sis->get_vel() - b->get_vel());
00007     k->initialize_from_pos_and_vel();
00008 }
00009 
00010 local INLINE void update_node(worldbundle *wb,
00011                               worldline *ww, real t,
00012                               tdyn *bb, tdyn *top, bool vel,
00013                               bool debug)
00014 {
00015     // Copy or interpolate all relevant quantities from the base node
00016     // bb on worldline ww to the node curr in the interpolated tree.
00017     // For convenience, top is the top-level node of bb.
00018 
00019     tdyn *b = find_event(ww, bb, t);                    // current event
00020 
00021     pdyn *curr = ww->get_tree_node();                   // current node in the
00022                                                         // interpolated tree
00023 
00024     if (debug) {
00025         cerr << "current node " << b << " "
00026              << b->get_time() << " "
00027              << b->format_label() << endl;
00028         cerr << "base node " << bb << " "
00029              << bb->get_time() << " "
00030              << bb->format_label() << endl;
00031     }
00032 
00033     //======================================================================
00034 
00035     // Preliminaries:
00036 
00037     if (NEW == 0) {
00038 
00039         //-----------------------------------------------------------------
00040         // The following "static" quantities should be constant within a
00041         // segment, and thus need only be set when node curr is created.
00042         // Should not be necessary to copy these data at each update.
00043         //
00044         //              name/index
00045         //              worldline index
00046         //-----------------------------------------------------------------
00047 
00048         // Moved to attach_new_node.C for NEW = 1 (Steve, 5/30/01):
00049 
00050         // Very helpful to attach the worldline ID as an index to the pdyn,
00051         // but then we lose the connection between the index seen by the
00052         // display program and the index in the original data.  Save both!
00053 
00054         // Index is the original index; worldline ID is worldline_index.
00055 
00056         if (b->get_name()) {
00057             curr->set_name(b->get_name());
00058             curr->set_index(atoi(b->get_name()));
00059         }
00060         if (b->get_index() >= 0)
00061             curr->set_index(b->get_index());
00062 
00063         // Cleanest way to get the worldline index:
00064 
00065         curr->set_worldline_index(wb->find_index(b));
00066     }
00067 
00068     // Allow possibility that mass may change along the worldline:
00069 
00070     curr->set_mass(b->get_mass());
00071 
00072     //======================================================================
00073 
00074     // See if we need to deal with unperturbed  or lightly perturbed
00075     // motion (most of the work of this function).
00076 
00077     // Variables which may be set and used later...
00078 
00079     tdyn *bbsis = NULL;
00080     worldline *wwsis = NULL;
00081     tdyn *sis = NULL;
00082 
00083     // The kepler flag (1) is attached once the motion is unperturbed,
00084     // but unperturbed motion doesn't start a new segment.
00085 
00086     // Assume that the unperturbed approximation is OK even if only
00087     // the start of the current section of the worldline (node b) is
00088     // flagged as unperturbed:
00089     //
00090     //              b              b->next
00091     //
00092     //          (unpert) -----x--- (unpert)     OK -- normal case
00093     //
00094     //          (unpert) -----x--- (pert)       OK -- motion became perturbed
00095     //                                          at the end of the step
00096     //
00097     //            (pert) -----x--- (unpert)     not OK -- perturbed motion
00098     //                                          throughout the step
00099     //            (pert) -----x--- (pert)       not OK -- perturbed motion
00100 
00101     if (b->get_kepler() == (kepler*)1) {        // 2 is reserved for lightly
00102                                                 // perturbed binary motion
00103 
00104         // If the kepler flag for b is set to 1, we have unperturbed
00105         // motion during this interval.  If curr has no kepler, create
00106         // one.  If a kepler does exist, there is still the possibility
00107         // that it refers to a previous kepler segment and that we have
00108         // skipped a perturbed interval.  Must check this and update the
00109         // kepler data if necessary.                    (Steve, 9/01)
00110 
00111         kepler *k = curr->get_kepler();
00112 
00113         if (!k) {
00114 
00115             // Default placeholder:
00116 
00117             curr->set_kepler((kepler*)1);
00118 
00119             if (NEW == 1) {
00120 
00121                 // Locate b's sister node.  Tree info is attached to the
00122                 // base nodes.  Compute a kepler only for the elder sister
00123                 // of a pair of nodes.  Younger sister just gets a "1".
00124 
00125                 if (!bb->get_elder_sister()) {
00126 
00127                     bbsis = bb->get_younger_sister();
00128                     wwsis = wb->find_worldline(bbsis);
00129                     sis = find_event(wwsis, bbsis, t);
00130 
00131                     // Check that sis has the same time and also has kep set.
00132 
00133                     if (sis->get_time() != b->get_time())
00134                         cerr << "warning: unsynchronized binary nodes" << endl;
00135 
00136                     if (!sis->get_kepler())
00137                         cerr << "warning: binary sister has kep = NULL" << endl;
00138 
00139                     // Create a real kepler structure.
00140 
00141                     // cerr << "creating new kepler for " << bb->format_label()
00142                     //      << " at time " << b->get_time() << endl;
00143 
00144                     k = new kepler;
00145 
00146                     k->set_circular_binary_limit(1.e-6);        // ~arbitrary
00147                     set_kepler_tolerance(2);                    // repetitious
00148 
00149                     set_kepler_from_tdyn_pair(k, b, sis);
00150                     curr->set_kepler(k);
00151 
00152                     if (debug)
00153                         cerr << "created kepler for " << curr->format_label()
00154                              << " at time " << b->get_time() << endl;
00155                 }
00156             }
00157 
00158         } else {
00159 
00160             if (NEW == 1) {
00161 
00162                 // A kepler structure already exists.  Check to see if it
00163                 // is consistent with the current pos and vel.  May be
00164                 // expensive to do this every step -- need a better way of
00165                 // verifying the consistency of the data.
00166 
00167                 if (!bb->get_elder_sister()) {
00168 
00169                     // Locate b's sister node.  Tree info is attached to the
00170                     // base nodes.  Code follows that above (kepler == NULL).
00171                     // Note that this isn't so expensive, as all these data
00172                     // should be used again below.
00173 
00174                     bbsis = bb->get_younger_sister();
00175                     wwsis = wb->find_worldline(bbsis);
00176                     sis = find_event(wwsis, bbsis, t);
00177 
00178                     // Check that sis has the same time and also has kep set.
00179 
00180                     if (sis->get_time() != b->get_time())
00181                         cerr << "warning: unsynchronized binary nodes" << endl;
00182 
00183                     if (!sis->get_kepler())
00184                         cerr << "warning: binary sister has kep = NULL" << endl;
00185 
00186                     // For now, use angular momentum as a check -- better than
00187                     // energy, which is likely to be nearly conserved during an
00188                     // intervening period of perturbed motion.
00189 
00190                     // m1r1 + m2r2 = 0
00191                     // r2 = -m1r1/m2
00192                     // r1 - r2 = r1 (1 + m1/m2)
00193                     // v1 - v2 = v1 (1 + m1/m2)
00194                     // (r1-r2)^(v1-v2) = (1+m1/m2)^2 r1^v1
00195 
00196                     // Hard to see how to avoid this cost...
00197 
00198                     vector ang_mom = square(1+b->get_mass()/sis->get_mass())
00199                                         * (b->get_pos() ^ b->get_vel());
00200 
00201 #define TWFAC 1.e-6
00202                     if (!twiddles(square(ang_mom),
00203                                   square(curr->get_kepler()
00204                                           ->get_angular_momentum()), TWFAC)) {
00205 
00206                         // Old and new orbits are inconsistent.  Redefine
00207                         // the orbital parameters.  Factor TWFAC comes from
00208                         // trial and error, but seems to work.
00209 
00210                         set_kepler_from_tdyn_pair(k, b, sis);
00211 
00212                         if (debug)
00213                             cerr << "recreated kepler for "
00214                                  << curr->format_label()
00215                                  << " at time " << b->get_time() << endl;
00216                     }
00217                 }
00218             }
00219         }
00220 
00221 #if 0           // turn this on to enable new kep2 stuff, but the new code
00222                 // is incompatible with the old buggy kira output format...
00223 
00224     // (thinking aloud...)
00225     //
00226     // What about lightly perturbed (lpert) binaries (kep = 2)?
00227     // Outcome is pretty simple:
00228     //
00229     //              b              b->next
00230     //
00231     //          (unpert) -----x--- (unpert)     unperturbed         (1 kepler)
00232     //          (unpert) -----x--- (lpert)      unperturbed
00233     //          (unpert) -----x--- (pert)       unperturbed
00234     //
00235     //           (lpert) -----x--- (unpert)     lightly perturbed   (2 keplers)
00236     //           (lpert) -----x--- (pert)       lightly perturbed
00237     //           (lpert) -----x--- (lpert)      lightly perturbed
00238     //
00239     //            (pert) -----x--- (unpert)     perturbed           (0 keplers)
00240     //            (pert) -----x--- (lpert)      perturbed
00241     //            (pert) -----x--- (pert)       perturbed
00242     //
00243     // i.e. only b matters.
00244     //
00245     // Now curr must keep track of 2 kepler pointers (b and next) in
00246     // some coherent and efficient way.  Interpolation will entail
00247     // interpolation between keplers at two different times.
00248     //
00249     //          kepler #1 is b,  kepler #2 is b->next
00250     //
00251     // As with unperturbed case, keep track of existing keplers, for
00252     // efficiency.  Need new data structure to hold 2 kepler pointers.
00253     // As of 9/01, the pdyn class contains two kepler pointers: kep and
00254     // kep2.                                            (Steve, 9/01)
00255     //
00256     // Curr has 0 keplers:      create 2
00257     //          1 kepler:       was unperturbed: check 1, create 1
00258     //          2 keplers:      already lightly perturbed; check 2
00259     //
00260     // We expect that both keplers may change from one step to the next,
00261     // and the "lightly perturbed" period will cover several steps, so
00262     // for now (maybe forever) just do the following:
00263     //
00264     //          - if 0 or 1 kepler exists, create two new ones
00265     //            (don't even bother checking to see if the unpert
00266     //             kepler is usable?)                   kep2 == NULL
00267     //
00268     //          - if 2 keplers exist, see if any can be used (same
00269     //            events, indicated by saving time or event address),
00270     //            and create new ones as necessary:     kep2 != NULL
00271 
00272     } else if (b->get_kepler() == (kepler*)2) {
00273 
00274         // Lightly perturbed motion.
00275 
00276         // Take action only if this is the elder sister of a binary.
00277         // Younger sister pointers are also set in the process.
00278 
00279         if (!bb->get_elder_sister()) {
00280 
00281             // Default action is to create two kepler structures.
00282 
00283             bool createkep = true, createkep2 = true;
00284             tdyn *next = b->get_next();
00285 
00286             if (curr->get_kepler2()) {
00287 
00288                 // Two keplers already exist (assume that kepler2 implies the
00289                 // existence of kepler).  See if either is still valid.
00290 
00291                 tdyn *event = curr->get_kepevent();
00292                 tdyn *event2 = curr->get_kepevent2();
00293 
00294                 if (event == b)
00295 
00296                     createkep = false;
00297 
00298                 else if (event == next) {
00299 
00300                     // Old event will become the new event2.
00301                     // Remove the old kep2 (event2 shouldn't be b!).
00302 
00303                     delete curr->get_kepler2();
00304 
00305                     // New kep2 is old kep.
00306 
00307                     curr->set_kepler2(curr->get_kepler());
00308                     pdyn *sister = curr->get_younger_sister();
00309                     sister->set_kepler2(curr->get_kepler());
00310 
00311                     curr->set_kepler(NULL);
00312                     sister->set_kepler(NULL);
00313 
00314                     createkep2 = false;
00315                 }
00316 
00317                 if (event2 == next)
00318 
00319                     createkep2 = false;
00320 
00321                 else if (event2 == b) {
00322 
00323                     // Old event2 will become the new event.
00324                     // Remove the old kep (event shouldn't be next!).
00325 
00326                     delete curr->get_kepler();
00327 
00328                     // New kep is old kep2.
00329 
00330                     curr->set_kepler(curr->get_kepler2());
00331                     pdyn *sister = curr->get_binary_sister();
00332                     sister->set_kepler(curr->get_kepler2());
00333 
00334                     curr->set_kepler2(NULL);
00335                     sister->set_kepler2(NULL);
00336 
00337                     createkep = false;
00338                 }
00339             }
00340 
00341             if (createkep || createkep2) {
00342 
00343                 // Must construct at least one kepler structure.
00344 
00345                 bbsis = bb->get_younger_sister();
00346                 wwsis = wb->find_worldline(bbsis);
00347                 sis = find_event(wwsis, bbsis, t);
00348 
00349                 // Check that sis has the same time and also has kep set.
00350                 // (Same check and output as above.)
00351 
00352                 if (sis->get_time() != b->get_time())
00353                     cerr << "warning: unsynchronized binary nodes" << endl;
00354 
00355                 if (!sis->get_kepler())
00356                     cerr << "warning: binary sister has kep = NULL" << endl;
00357 
00358                 if (createkep) {
00359                     curr->rmkepler();
00360                     kepler *k = new kepler;
00361                     set_kepler_from_tdyn_pair(k, b, sis);
00362                     curr->set_kepler(k);
00363                 }
00364                         
00365                 if (createkep2) {
00366                     curr->rmkepler2();
00367                     kepler *k = new kepler;
00368                     set_kepler_from_tdyn_pair(k, next, sis->get_next());
00369 
00370                     // sis->next should be OK...
00371 
00372                     curr->set_kepler2(k);
00373                 }
00374             }
00375 
00376             curr->set_kepevent(b);
00377             curr->set_kepevent2(next);  // don't bother setting sister pointers
00378         }
00379 
00380 #endif
00381 
00382     } else {                                            // unperturbed motion
00383 
00384         // Delete any old keplers (if real).
00385 
00386         if (curr->get_kepler() == (kepler*)2)           // shouldn't occur
00387             PRL(curr->get_kepler());
00388 
00389         if (curr->get_kepler()
00390              && curr->get_kepler() != (kepler*)1
00391              && curr->get_kepler() != (kepler*)2) {     // "2" shouldn't be
00392                                                         // needed, but...
00393             curr->rmkepler();
00394 
00395             if (debug && 
00396                 !bb->get_elder_sister())
00397                 cerr << "deleted kepler for " << curr->format_label()
00398                      << " at time " << t << " (" << b->get_time() << ")"
00399                      << endl;
00400         }
00401 
00402         if (curr->get_kepler2()) {
00403 
00404             curr->rmkepler2();
00405 
00406             if (debug && 
00407                 !bb->get_elder_sister())
00408                 cerr << "deleted kepler2 for " << curr->format_label()
00409                      << " at time " << t << " (" << b->get_time() << ")"
00410                      << endl;
00411         }
00412     }
00413 
00414     //======================================================================
00415 
00416     // Now actually do the interpolation.  Take advantage of the binary
00417     // tree structure, and do nothing for the younger sister of a pair.
00418 
00419     kepler *k = curr->get_kepler();
00420 
00421     if (!k || k == (kepler*)2) {                // *** still to be completed ***
00422 
00423         // This is a top-level node or a perturbed binary component.
00424         // New code: Take no action if this is the younger component
00425         // of a binary.
00426 
00427         if (NEW == 0 || bb == top || !bb->get_elder_sister())
00428 #ifndef NEW_INTERP
00429             curr->set_pos(interpolate_pos(b, t, bb));
00430 #else
00431             set_interpolated_pos(b, t, curr, bb);
00432 #endif
00433 
00434         // Need velocity information on low-level nodes, or if forced:
00435 
00436         if (vel || (bb != top && (NEW == 0 || !bb->get_elder_sister())))
00437             curr->set_vel(interpolate_vel(b, t, bb));
00438 
00439 #if 0
00440         if (!bb->get_elder_sister())
00441             print_binary_diagnostics(t, b, bb, curr);
00442 #endif
00443 
00444     } else if (k != (kepler*)1 && !bb->get_elder_sister()) {
00445 
00446         // This is the elder component of an unperturbed binary, and
00447         // has a real kepler attached (should happen only for NEW = 1)
00448 
00449         k->transform_to_time(t);
00450 
00451         // By construction, rel_pos runs from curr to the
00452         // other (younger) binary component.
00453 
00454         real mass_fac = 1 - curr->get_mass()/k->get_total_mass();
00455         curr->set_pos(-mass_fac * k->get_rel_pos());
00456         curr->set_vel(-mass_fac * k->get_rel_vel());
00457 
00458     } else
00459 
00460         if (NEW == 0) {
00461 
00462             // Default case (old code only):
00463 
00464             curr->set_pos(b->get_pos());
00465             curr->set_vel(b->get_vel());
00466         }
00467 
00468     //======================================================================
00469 
00470     pdyn *csis = NULL;
00471 
00472     if (NEW == 1) {
00473 
00474         // Update the younger component of a binary (perturbed or not).
00475 
00476         if (bb != top && !bb->get_elder_sister()) {
00477 
00478             // Find the sister node in the interpolated tree.
00479             // Check each pointer; none should be NULL.
00480 
00481             if (!bbsis) {
00482                 bbsis = bb->get_younger_sister();            // sister base node
00483                 wwsis = wb->find_worldline(bbsis);           // sister worldline
00484             }
00485 
00486             if (bbsis && wwsis) {
00487 
00488                 pdyn *csis = wwsis->get_tree_node();
00489 
00490                 if (csis) {
00491                     if (csis->get_mass() > 0) {
00492                         real mass_fac = -curr->get_mass()/csis->get_mass();
00493                         csis->set_pos(mass_fac*curr->get_pos());
00494                         csis->set_vel(mass_fac*curr->get_vel());
00495                     } else
00496                         cerr << "update_node: "
00497                              << "error: sister mass <= 0" << endl;
00498                 } else
00499                     cerr << "update_node: "
00500                          << "error: sister tree node NULL for "
00501                          << bbsis->format_label() << " at " << t << endl;
00502             } else
00503                 cerr << "update_node: "
00504                     << "error: sister base node sister NULL" << endl;
00505         }
00506     }
00507 
00508     //======================================================================
00509 
00510     // Clean up.
00511 
00512     curr->set_stellar_type(b->get_stellar_type());
00513     curr->set_temperature(b->get_temperature());
00514     curr->set_luminosity(b->get_luminosity());
00515 
00516     ww->set_t_curr(t);
00517     ww->set_current_event(b);                           // for find_event()
00518 
00519     if (bbsis) {
00520         if (!sis) sis = find_event(wwsis, bbsis, t);
00521         wwsis->set_t_curr(t);
00522         wwsis->set_current_event(sis);                  // for find_event()
00523         if (csis) {
00524             csis->set_stellar_type(sis->get_stellar_type());
00525             csis->set_temperature(sis->get_temperature());
00526             csis->set_luminosity(sis->get_luminosity());
00527         }
00528     }
00529 
00530     if (debug)
00531         cerr << "updated " << curr->format_label() << endl;
00532 }

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