Planetary Orbital Evolution due to Tides
Orbital evolution of two objects experiencing tides
DissipatingZone.cpp
1 #define BUILDING_LIBRARY
2 #include "DissipatingZone.h"
3 #include "BinarySystem.h"
4 
5 namespace Evolve {
6 
7  std::ostream &operator<<(std::ostream &os,
8  const ZoneEvolutionQuantities &evol_var)
9  {
10  switch(evol_var) {
11  case ANGULAR_MOMENTUM : os << "ANGULAR_MOMENTUM"; break;
12  case ANGULAR_MOMENTUM_DERIV : os << "ANGULAR_MOMENTUM_DERIV"; break;
13  case INCLINATION : os << "INCLINATION"; break;
14  case INCLINATION_DERIV : os << "INCLINATION_DERIV"; break;
15  case PERIAPSIS : os << "PERIAPSIS"; break;
16  case PERIAPSIS_DERIV : os << "PERIAPSIS_DERIV"; break;
17  case MOMENT_OF_INERTIA : os << "MOMENT_OF_INERTIA"; break;
19  os << "DMOMENT_OF_INERTIA_DT"; break;
21  os << "D2MOMENT_OF_INERTIA_DT2"; break;
22  case OUTER_RADIUS : os << "OUTER_RADIUS"; break;
23  case OUTER_RADIUS_FIRST_DERIV : os << "DOUTER_RADIUS_DT"; break;
24  case OUTER_RADIUS_SECOND_DERIV : os << "D2OUTER_RADIUS_DT2"; break;
25  case OUTER_MASS : os << "OUTER_MASS"; break;
26  case OUTER_MASS_DERIV : os << "DOUTER_MASS_DT"; break;
27  case E_ORDER : os << "E_ORDER"; break;
28  case ORBITAL_FREQ_MULTIPLIER : os << "ORBITAL_FREQ_MULTIPLIER";
29  break;
30  case SPIN_FREQ_MULTIPLIER : os << "SPIN_FREQ_MULTIPLIER"; break;
31  default : assert(false);
32  };
33  return os;
34  }
35 
36  const double DissipatingZone::__torque_x_plus_coef[]={1.0,
37  std::sqrt(1.5),
38  std::sqrt(1.5),
39  1.0,
40  0.0};
41 
42  const double DissipatingZone::__torque_x_minus_coef[]={0.0, //m=-2
43  1.0, //m=-1
44  std::sqrt(1.5),//m=0
45  std::sqrt(1.5),//m=1
46  1.0}; //m=2
47 
49  const SpinOrbitLockInfo &limit,
50  int orbital_frequency_multiplier,
51  int spin_frequency_multiplier,
52  double &forcing_frequency
53  ) const
54  {
55  if(__initializing || !can_lock()) return;
56  assert(limit.spin_frequency_multiplier() == 1
57  ||
58  limit.spin_frequency_multiplier() == 2);
59 
60  if(
61  limit.term(orbital_frequency_multiplier,
62  spin_frequency_multiplier)
63  ) {
64  if(
65  spin_frequency_multiplier
66  *
67  limit.lock_direction()
68  *
69  forcing_frequency
70  >
71  0
72  )
73  forcing_frequency = (
74  (
75  spin_frequency_multiplier*limit.lock_direction() > 0
76  ? -1
77  : 1
78  )
79  *
80  std::numeric_limits<double>::epsilon()
81  );
82  return;
83  }
84  int expected_sign = boost::math::sign(
86  *
87  (
88  orbital_frequency_multiplier
89  *
91  -
93  *
94  spin_frequency_multiplier
95  )
96  );
97  if(
98  expected_sign * limit.lock_direction() * spin_frequency_multiplier
99  >
100  0
101  ) return;
102  if(forcing_frequency * expected_sign > 0) return;
103 
104  assert(limit.lock_direction());
105 
106  forcing_frequency = (
107  std::numeric_limits<double>::epsilon()
108  *
109  expected_sign
110  );
111  }
112 
114  {
115 #ifndef NDEBUG
116  std::cerr << "Checking lock consistency for __lock: "
117  << __lock
118  << ", __other_lock: "
119  << __other_lock
120  << ", zone "
121  << (can_lock() ? "can": "cannot")
122  << " lock"
123  << std::endl;
124 #endif
125  if(__initializing || !can_lock()) return;
126  int max_abs_orb_mult = static_cast<int>(__expansion_order);
127  if(
128  (!__lock)
129  &&
131  ) {
132  throw Core::Error::Runtime(
133  "Inconsistent lock state encountered for a zone. Likely related "
134  "to initial conditions with a tidal term too close to zero."
135  );
136  }
137  assert(__lock.spin_frequency_multiplier() == 1
138  ||
141  &&
143  if(__lock) return;
144  return;//<++>
145  assert(
146  (
148  *
150  *
152  +
153  1.0e-5 * __orbital_frequency
154  )
155  >=
156  (
158  *
160  *
162  )
163  );
165  assert(
166  (
168  *
170  *
172  )
173  >
174  (
176  *
178  *
180  )
181  );
182  } else assert(
184  >
185  0
186  );
187  }
188 
190  SpinOrbitLockInfo &lock
191  )
192  {
193  assert(lock.lock_direction());
195  if(
196  static_cast<unsigned>(std::abs(lock.orbital_frequency_multiplier()))
197  >
199  &&
200  lock.spin_frequency_multiplier()==2
201  )
202  lock.set_lock(
203  (
205  -
206  lock.lock_direction()
207  )/2,
208  1,
209  lock.lock_direction()
210  );
211 
212  if(
214  >
215  static_cast<int>(__expansion_order)
216  ) {
217  if(lock.lock_direction() > 0)
218  lock.set_lock(__expansion_order, 1, 1);
219  else
220  lock.set_lock(1, 0, -1);
221  } else if(
223  <
224  -static_cast<int>(__expansion_order)
225  ) {
226  if(lock.lock_direction() > 0)
227  lock.set_lock(-1, 0, 1);
228  else
229  lock.set_lock(-static_cast<int>(__expansion_order), 1, -1);
230  }
232  }
233 
235  {
236  if(!can_lock()) {
237  __lock.set_lock(-1, 0, 1);
238  __other_lock.set_lock(1, 0, -1);
239  return;
240  }
241 #ifndef NDEBUG
242 // std::cerr << "Initializing locks for Worb = "
243 // << __orbital_frequency
244 // << ", W* = "
245 // << __spin_frequency
246 // << "." << std::endl;
247 #endif
248  int below_orb_mult = std::floor(2.0
249  *
251  /
253  max_abs_orb_mult=static_cast<int>(__expansion_order);
254  if(below_orb_mult % 2) {
255  if(
256  std::abs(below_orb_mult)
257  <=
258  max_abs_orb_mult
259  ) {
260  __lock.set_lock(below_orb_mult, 2, 1);
261  __other_lock.set_lock((below_orb_mult + 1) / 2, 1, -1);
262  } else if(
263  std::abs((below_orb_mult - 1) / 2)
264  <=
265  max_abs_orb_mult
266  ) {
267  __lock.set_lock((below_orb_mult - 1) / 2, 1, 1);
268  if((below_orb_mult + 1) / 2 > max_abs_orb_mult)
269  __other_lock.set_lock(1, 0, -1);
270  else
271  __other_lock.set_lock((below_orb_mult + 1) / 2, 1, -1);
272  } else {
273  if(__spin_frequency > 0) {
274  __lock.set_lock(max_abs_orb_mult, 1, 1);
275  __other_lock.set_lock(1, 0, -1);
276  } else {
277  __lock.set_lock(-max_abs_orb_mult, 1, -1);
278  __other_lock.set_lock(-1, 0, 1);
279  }
280  }
281  } else if(std::abs(below_orb_mult / 2) <= max_abs_orb_mult) {
282  __lock.set_lock(below_orb_mult / 2, 1, 1);
283  if(std::abs(below_orb_mult + 1) <= max_abs_orb_mult)
284  __other_lock.set_lock(below_orb_mult + 1, 2, -1);
285  else if(std::abs(below_orb_mult / 2 + 1) <= max_abs_orb_mult)
286  __other_lock.set_lock(below_orb_mult / 2 + 1, 1, -1);
287  else
288  __other_lock.set_lock(1, 0, -1);
289  } else {
290  if(__spin_frequency > 0) {
291  __lock.set_lock(max_abs_orb_mult, 1, 1);
292  __other_lock.set_lock(1, 0, -1);
293  } else {
294  __lock.set_lock(-max_abs_orb_mult, 1, -1);
295  __other_lock.set_lock(-1, 0, 1);
296  }
297 
298  }
300  }
301 
303  int mp,
304  double tidal_frequency,
305  const TidalTermTriplet &U_value,
306  const TidalTermTriplet &U_i_deriv,
307  const TidalTermTriplet &U_e_deriv)
308  {
309  int m_ind = m + 2;
310 
311  bool locked_term = locked(mp, m);
312 
313  for(
314  int deriv = Dissipation::NO_DERIV;
315  (
316  (m != 0 || mp != 0)
317  &&
319  );
320  ++deriv
321  ) {
322  Dissipation::QuantityEntry phase_lag_deriv = (
324  ? static_cast<Dissipation::QuantityEntry>(deriv)
326  );
327  double mod_phase_lag_above,
328  mod_phase_lag_below = modified_phase_lag(
329  mp,
330  m,
331  tidal_frequency,
332  phase_lag_deriv,
333  mod_phase_lag_above
334  ),
335  love_coef = love_coefficient(
336  mp,
337  m,
338  (
339  phase_lag_deriv == Dissipation::AGE
342  )
343  );
344 
347  U = U_value;
348  else if(deriv == Dissipation::INCLINATION)
349  U = U_i_deriv;
350  else
351  U = U_e_deriv;
352 
353  double U_mmp_squared = std::pow(U.m, 2),
354  term_power = U_mmp_squared * mp,
355  term_torque_z = U_mmp_squared * m,
356  term_torque_x = U.m * (
358  +
360  );
361  if(
362  !locked_term
363  &&
364  (tidal_frequency != 0 || __lock.lock_direction() < 0)
365  )
366  mod_phase_lag_above = mod_phase_lag_below;
367  else if(
368  !locked_term
369  &&
370  tidal_frequency == 0
371  &&
372  __lock.lock_direction() > 0
373  )
374  mod_phase_lag_below = mod_phase_lag_above;
375  int deriv_ind = 2 * deriv;
376  __power[deriv_ind] += term_power * mod_phase_lag_below;
377  __torque_z[deriv_ind] += (term_torque_z
378  *
379  mod_phase_lag_below);
380  __torque_x[deriv_ind] += (term_torque_x
381  *
382  mod_phase_lag_below);
383  __torque_y[deriv_ind + 1] = -(
384  __torque_y[deriv_ind] -= term_torque_x * love_coef
385  );
386  __power[deriv_ind + 1] += term_power * mod_phase_lag_above;
387  __torque_z[deriv_ind + 1] += (term_torque_z
388  *
389  mod_phase_lag_above);
390  __torque_x[deriv_ind + 1] += (term_torque_x
391  *
392  mod_phase_lag_above);
393  //TODO: revive eccentricity derivative check
394  if(deriv != Dissipation::ECCENTRICITY) {
395  assert(!std::isnan(__torque_x[deriv_ind]));
396  assert(!std::isnan(__torque_x[deriv_ind + 1]));
397  assert(!std::isnan(__torque_y[deriv_ind]));
398  assert(!std::isnan(__torque_y[deriv_ind + 1]));
399  assert(!std::isnan(__torque_z[deriv_ind]));
400  assert(!std::isnan(__torque_z[deriv_ind + 1]));
401  }
402 #if 0
403  if(deriv == Dissipation::NO_DERIV)
404  std::cerr << ", Wzone = "
405  << spin_frequency()
406  << ", U(" << m << ", " << mp << ") = "
407  << U.m
408  << ", term_power="
409  << term_power
410  << ", mod_phase_lag(above="
411  << mod_phase_lag_above
412  << ", below="
413  << mod_phase_lag_below
414  << ")";
415 #endif
416  }
417  }
418 
420  bool spin_is_frequency)
421  {
422  if(spin_is_frequency) {
424  __spin_frequency = spin;
425  } else {
426  __angular_momentum = spin;
427  if(spin == 0 && moment_of_inertia() == 0) __spin_frequency = 0;
428  else __spin_frequency = spin / moment_of_inertia();
429  }
430  }
431 
432  DissipatingZone::DissipatingZone() :
440  __initializing(false)
441  {}
442 
443  void DissipatingZone::configure(bool initialize,
444  double
445 #ifndef NDEBUG
446  age
447 #endif
448  ,
449  double orbital_frequency,
450  double eccentricity,
451  double orbital_angmom,
452  double spin,
453  double inclination,
454  double periapsis,
455  bool spin_is_frequency)
456  {
457  assert(age >= 0);
458 
459  if(initialize) {
460  __initializing = true;
461 #ifndef NDEBUG
462  std::cerr << "Initializing DissipatingZone" << std::endl;
463 #endif
464  }
465 #ifndef NDEBUG
466  std::cerr << "At t = " << age << ", configuring "
467  << (!dissipative() ? "non-" : "")
468  << "dissipative zone with w = "
469  << spin / (spin_is_frequency ? 1.0 : moment_of_inertia())
470  << ", L = "
471  << spin * (spin_is_frequency ? moment_of_inertia() : 1.0)
472  << ", inclination = " << inclination
473  << ", periapsis = " << periapsis
474  << std::endl;
475 
476 #endif
477  ZoneOrientation::configure(inclination, periapsis);
478  __orbital_angmom = orbital_angmom;
479  __orbital_frequency = orbital_frequency;
480  if(__lock && !initialize) {
481  __spin_frequency = __lock.spin(orbital_frequency);
483  } else
484  configure_spin(spin, spin_is_frequency);
485 
486  if(initialize) {
488  __initializing = false;
489  }
490  if(std::isnan(orbital_frequency)) return;
491 
492  __potential_term.configure(inclination, periapsis);
493  __power = 0;
494  __torque_x = 0;
495  __torque_y = 0;
496  __torque_z = 0;
497 
498  if(!dissipative()) return;
499 
500  for(
501  int mp = -static_cast<int>(__expansion_order);
502  mp <= static_cast<int>(__expansion_order);
503  ++mp
504  ) {
505  TidalTermTriplet U_value,
506  U_i_deriv,
507  U_e_deriv;
508  __potential_term(eccentricity,
509  -2,
510  mp,
511  U_value.m_plus_one,
512  U_i_deriv.m_plus_one,
513  U_e_deriv.m_plus_one);
514 
515  for(int m = -2; m <= 2; ++m) {
516 #if 0
517  std::cerr << "Term: m' = "
518  << mp
519  << ", m = "
520  << m;
521 #endif
522 
523  U_value.m = U_value.m_plus_one;
524  U_i_deriv.m = U_i_deriv.m_plus_one;
525  U_e_deriv.m = U_e_deriv.m_plus_one;
526  if(m < 2) {
527  __potential_term(eccentricity,
528  m + 1,
529  mp,
530  U_value.m_plus_one,
531  U_i_deriv.m_plus_one,
532  U_e_deriv.m_plus_one);
533  } else {
534  U_value.m_plus_one = 0;
535  U_i_deriv.m_plus_one = 0;
536  U_e_deriv.m_plus_one = 0;
537  }
538 
540  m,
541  mp,
542  forcing_frequency(mp, m, orbital_frequency),
543  U_value,
544  U_i_deriv,
545  U_e_deriv
546  );
547 
548  U_value.m_minus_one = U_value.m;
549  U_i_deriv.m_minus_one = U_i_deriv.m;
550  U_e_deriv.m_minus_one = U_e_deriv.m;
551 #ifdef VERBOSE_DEBUG
552  std::cerr << std::endl;
553 #endif
554  }
555  }
556  }
557 
559  int orbital_frequency_multiplier,
560  int spin_frequency_multiplier,
561  double orbital_frequency
562  ) const
563  {
564  if(
566  ||
568 
569  )
571  if(__lock(orbital_frequency_multiplier, spin_frequency_multiplier))
572  return 0;
573  double forcing_freq = (
574  orbital_frequency_multiplier * orbital_frequency
575  -
576  spin_frequency_multiplier * spin_frequency()
577  );
578  assert(!std::isnan(forcing_freq));
579 
580 #ifdef VERBOSE_DEBUG
581 // std::cerr << "Worb = " << orbital_frequency << ", "
582 // << "Wspin = " << spin_frequency() << " -> "
583 // << "Wtide = " << forcing_freq << " -> ";
584 #endif
585 
586  if(
588  ||
590 
591  )
593  orbital_frequency_multiplier,
594  spin_frequency_multiplier,
595  forcing_freq);
598  orbital_frequency_multiplier,
599  spin_frequency_multiplier,
600  forcing_freq);
601 #ifdef VERBOSE_DEBUG
602 // std::cerr << forcing_freq << std::endl;
603 #endif
604  return forcing_freq;
605  }
606 
607 
608 
610  const Eigen::Vector3d &orbit_torque,
611  const Eigen::Vector3d &zone_torque,
612  Dissipation::QuantityEntry entry,
613  const Eigen::Vector3d &orbit_torque_deriv,
614  const Eigen::Vector3d &zone_torque_deriv
615  )
616  {
617  double sin_inc = std::sin(inclination()),
618  cos_inc = std::cos(inclination()),
619  zone_y_torque,
620  orbit_y_torque;
621  if(entry == Dissipation::NO_DERIV) {
622  orbit_y_torque = orbit_torque[1];
623  zone_y_torque = zone_torque[1];
624  } else {
625  orbit_y_torque = orbit_torque_deriv[1];
626  zone_y_torque = zone_torque_deriv[1];
627  }
628 #ifndef NDEBUG
629  if(sin_inc == 0) {
630  assert(orbit_y_torque == 0 || std::isnan(orbit_y_torque));
631  assert(zone_y_torque == 0 || std::isnan(zone_y_torque));
632  } else {
633  assert(!std::isnan(orbit_y_torque));
634  assert(!std::isnan(zone_y_torque));
635  }
636 #endif
637  double result = (
638  sin_inc == 0
639  ? 0
640  : (
641  -orbit_y_torque * cos_inc / (__orbital_angmom * sin_inc)
642  +
643  zone_y_torque / (__angular_momentum * sin_inc)
644  )
645  );
646  assert(!std::isnan(result));
647 
648  if(
649  entry == Dissipation::NO_DERIV
650  ||
651  entry == Dissipation::AGE
652  ||
654  ||
655  entry == Dissipation::PERIAPSIS
656  ||
657  entry == Dissipation::RADIUS
658  ||
660  ||
661  entry == Dissipation::SEMIMAJOR
662  )
663  return result;
664  else if(
666  ||
667  entry == Dissipation::SPIN_ANGMOM
668  ) {
669  if(sin_inc == 0) return 0.0;
670  else return (
671  result
672  -
673  zone_torque[1]
674  /
675  (std::pow(__angular_momentum, 2) * sin_inc)
676  *
678  );
679  } else if(entry == Dissipation::INCLINATION) {
680  if(sin_inc == 0) return 0.0;
681  else return (
682  result
683  -
684  (
685  orbit_torque[1] / __orbital_angmom
686  +
687  zone_torque[1] * cos_inc / __angular_momentum
688  )
689  /
690  std::pow(sin_inc, 2)
691  );
692  } else {
693  assert(false);
694  }
695 
696  return Core::NaN;
697  }
698 
700  const Eigen::Vector3d &orbit_torque,
701  const Eigen::Vector3d &zone_torque,
702  Dissipation::QuantityEntry entry,
703  const Eigen::Vector3d &orbit_torque_deriv,
704  const Eigen::Vector3d &zone_torque_deriv)
705  {
706  double sin_inc = std::sin(inclination()),
707  cos_inc = std::cos(inclination()),
708  zone_x_torque,
709  orbit_x_torque,
710  orbit_z_torque;
711  assert(!std::isnan(orbit_torque[0]));
712  assert(!std::isnan(orbit_torque[2]));
713  assert(!std::isnan(zone_torque[0]));
714  if(entry == Dissipation::NO_DERIV) {
715  orbit_x_torque = orbit_torque[0];
716  orbit_z_torque = orbit_torque[2];
717  zone_x_torque = zone_torque[0];
718  } else {
719  orbit_x_torque = orbit_torque_deriv[0];
720  orbit_z_torque = orbit_torque_deriv[2];
721  zone_x_torque = zone_torque_deriv[0];
722  }
723 
724  double result;
725  if(orbit_x_torque == 0 && orbit_z_torque == 0)
726  result = 0.0;
727  else
728  result = ((orbit_x_torque * cos_inc - orbit_z_torque * sin_inc)
729  /
731 
732  if(zone_x_torque != 0 && moment_of_inertia() != 0)
733  result -= zone_x_torque / __angular_momentum;
734 
735  assert(!std::isnan(result));
736 
737  if(
738  entry == Dissipation::NO_DERIV
739  ||
740  entry == Dissipation::AGE
741  ||
743  ||
744  entry == Dissipation::PERIAPSIS
745  ||
746  entry == Dissipation::RADIUS
747  ||
749  ||
750  entry == Dissipation::SEMIMAJOR
751  ) {
752  return result;
753  } else if(
755  ||
756  entry == Dissipation::SPIN_ANGMOM
757  ) {
758  assert(std::abs(__angular_momentum) > 0);
759  return (
760  result
761  +
762  zone_torque[0] / std::pow(__angular_momentum, 2)
763  *
765  );
766  } else if(entry == Dissipation::INCLINATION) {
767  assert(std::abs(__angular_momentum) > 0);
768  return (result
769  +
770  (orbit_torque[2] * cos_inc + orbit_torque[0] * sin_inc)
771  /
773  } else
774  assert(false);
775  return Core::NaN;
776  }
777 
779  {
780  assert(can_lock());
781  if(__lock.spin_frequency_multiplier() == 2) {
782  assert(__lock.orbital_frequency_multiplier() % 2 == 1);
785  1,
786  -1
787  );
790  1,
791  -1
792  );
793  }
796  if(__lock.spin_frequency_multiplier() == 0) {
798  __other_lock.set_lock(1, 0, 1);
799  }
800  }
801 
802  void DissipatingZone::release_lock(short direction)
803  {
804  assert(can_lock());
805  assert(__lock);
806  assert(direction == 1 || direction == -1);
807  assert(
809  ||
811  );
812  __lock.lock_direction(direction);
813  int orbit_mult = (
814  (__lock.spin_frequency_multiplier() == 2 ? 1 : 2)
815  *
817  +
818  direction
819  );
820  if(orbit_mult % 2) __other_lock.set_lock(orbit_mult, 2, -direction);
821  else __other_lock.set_lock(orbit_mult/2, 1, -direction);
823  }
824 
826  unsigned new_expansion_order,
827  BinarySystem &,
828  bool ,
829  unsigned
830  )
831  {
832 
833 #ifndef NDEBUG
834  std::cerr << "Changing eccentricity order to "
835  << new_expansion_order
836  << std::endl;
837 #endif
838  if(__lock.spin_frequency_multiplier() == 0) {
839  __expansion_order = new_expansion_order;
840 #ifdef VERBOSE_DEBUG
841  std::cerr << "No lock defined, simple e-order change." << std::endl;
842 #endif
843  return;
844  }
845 #ifdef VERBOSE_DEBUG
846  std::cerr << "Lock(s) defined, updating." << std::endl;
847 #endif
848  if(__lock) {
849  __expansion_order = new_expansion_order;
850  if(
852  >
853  static_cast<int>(__expansion_order)
854  )
855  release_lock();
856  return;
857  }
859 
860  __expansion_order = new_expansion_order;
862 
864  }
865 
867  {
871  );
872 
875 
876  __evolution_real[PERIAPSIS].push_back(periapsis());
877  __evolution_real[PERIAPSIS_DERIV].push_back(periapsis(true));
878 
880 
883  );
884 
887  );
888 
890 
892 
894 
895  __evolution_real[OUTER_MASS].push_back(outer_mass());
896 
898 
901  );
902 
903  if(__lock) {
905  .push_back(__lock.orbital_frequency_multiplier());
907  .push_back(__lock.spin_frequency_multiplier());
908  } else {
910  .push_back(0);
912  .push_back(0);
913  }
914  }
915 
917  {
918  for(unsigned i = 0; i < __evolution_real.size(); ++i)
919  __evolution_real[i].clear();
920  for(unsigned i = 0; i < __evolution_integer.size(); ++i)
921  __evolution_integer[i].clear();
922  }
923 
924  void DissipatingZone::rewind_evolution(unsigned nsteps)
925  {
926  for(unsigned i = 0; i < nsteps; ++i) {
927  for(unsigned i = 0; i < __evolution_real.size(); ++i)
928  __evolution_real[i].pop_back();
929  for(unsigned i = 0; i < __evolution_integer.size(); ++i)
930  __evolution_integer[i].pop_back();
931  }
932  }
933 
935  BinarySystem &system,
936  bool primary,
937  unsigned zone_index
938  )
939  {
941  if(!can_lock()) return result;
942  if(__lock)
943  (*result) |= new BreakLockCondition(system, __locked_zone_index);
944  else if(system.evolution_mode() == Core::BINARY) {
945  (*result) |= new SynchronizedCondition(__lock,
946  primary,
947  zone_index,
948  system);
949  (*result) |= new SynchronizedCondition(__other_lock,
950  primary,
951  zone_index,
952  system);
953  }
954  return result;
955  }
956 
957 } //End Evolve namespace.
ZoneEvolutionQuantities
IDs for quantities saved as part of the evolution.
double m
The (m, m&#39;) coefficient.
Age derivative of MOMENT_OF_INERTIA.
unsigned __locked_zone_index
If this zone is locked, this is its index in the list of locked zones in the system.
RADIUS
The derivative w.r.t. the radius of the body in .
virtual void configure(bool initialize, double age, double orbital_frequency, double eccentricity, double orbital_angmom, double spin, double inclination, double periapsis, bool spin_is_frequency)
Defines the current orbit, triggering re-calculation of all quantities.
END_PHASE_LAG_DERIV
The above derivatives exist for modified phase lags, below do not.
Inclination of the zone.
The rate at which periapsis changes.
Satisfied when some multiples of the orbit and stellar rotation are synchronized. ...
std::valarray< double > __power
The dimensionless tidal power and its derivatives.
Declares a class representing one zone of a body dissipative to tidal distortions.
The total number of quantities whose evolution is tracked.
SPIN_FREQUENCY
The derivative w.r.t. the spin frequency of a dissipating zone.
void add_tidal_term(int m, int mp, double tidal_frequency, const TidalTermTriplet &U_value, const TidalTermTriplet &U_i_deriv, const TidalTermTriplet &U_e_deriv)
Add a term to the tidal torque and power arrays.
double __spin_frequency
The current spin frequency of the zone.
std::ostream & operator<<(std::ostream &os, const ZoneEvolutionQuantities &evol_var)
More civilized output for EvolVarType variables.
int orbital_frequency_multiplier() const
The multiplier in front of the orbital frequency in the lock.
virtual void add_to_evolution()
Appends the state defined by last configure(), to the evolution.
unsigned __expansion_order
The tidal potential expansion order to use.
double periapsis(bool evolution_rate=false) const
The argument of periapsis of this zone minus the reference zone&#39;s.
Satisfied when the maximum tidal torque that the planet can exert on the star is no longer sufficient...
The rate at which the the inclination changes.
SEMIMAJOR
The derivative w.r.t. the semimajor axis in AU.
static const double __torque_x_plus_coef[]
as a function of .
std::vector< std::list< double > > __evolution_real
The floating point quantities whose evolution is tracked.
Outer radius boundary of the zone.
MOMENT_OF_INERTIA
virtual double modified_phase_lag(int orbital_frequency_multiplier, int spin_frequency_multiplier, double forcing_frequency, Dissipation::QuantityEntry entry, double &above_lock_value) const =0
Should return the tidal phase lag times the love number for the given tidal term (or one of its deriv...
virtual double love_coefficient(int orbital_frequency_multiplier, int spin_frequency_multiplier, Dissipation::QuantityEntry entry) const =0
Should return the corresponding component of the love coefficient (Lai 2012 Equation 24)...
Any runtime error.
Definition: Error.h:61
Orientations of zones of bodies in a binary system.
double spin(double orbital_frequency) const
Spin frequency at exactly the lock that corresponds to the given orbital frequency.
Number of real values evolution quantities.
Eccentricity expansion order.
void release_lock()
Update the zone as necessary when the held lock disappears from the expansion.
First age derivative of OUTER_MASS.
virtual double moment_of_inertia(int deriv_order=0) const =0
Moment of inertia of the zone or its age derivative at the age of last configure() call...
std::valarray< double > __torque_x
The dimensionless tidal torque in the x direction and its derivatives.
double __angular_momentum_evolution_rate
The current rate of angular momentum evolution of the zone.
double m_minus_one
The (m-1, m&#39;) coefficient.
Periapsis of the zone.
int spin_frequency_multiplier() const
The multiplier in front of the spin frequency in the lock.
void configure(double inclination, double arg_of_periapsis=0)
Set the inclination relative to the orbit.
virtual void reset_evolution()
Discards all evolution.
double __orbital_frequency
The orbital frequency (rad/day).
double m_plus_one
The (m+1, m&#39;) coefficient.
void configure(double inclination, double periapsis)
Changes the zone orientation.
TidalPotentialTerms __potential_term
The expansion of the tidal potential in series.
SpinOrbitLockInfo __other_lock
The term closest matched by the current spin-orbit ratio in the other direction from __lock...
double __angular_momentum
The current angular momentum of the zone.
virtual double outer_mass(int deriv_order=0) const =0
Mass coordinate of the zone&#39;s outer ouboundary or its derivative.
double periapsis_evolution(const Eigen::Vector3d &orbit_torque, const Eigen::Vector3d &zone_torque, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV, const Eigen::Vector3d &orbit_torque_deriv=Eigen::Vector3d(), const Eigen::Vector3d &zone_torque_deriv=Eigen::Vector3d())
The rate at which the periapsis of the orbit/reference zone in this zone&#39;s equatorial plane is changi...
ECCENTRICITY
The derivative w.r.t. the eccentricity.
For locked zones this is the orbital frequency multiple of the lock.
END_DIMENSIONLESS_DERIV
void fix_forcing_frequency(const SpinOrbitLockInfo &limit, int orbital_frequency_multiplier, int spin_frequency_multiplier, double &forcing_frequency) const
Ensure the forcing frequency has the correct sign per the given constraint.
Moment of inertia of the zone.
virtual void change_expansion_order(unsigned new_expansion_order, BinarySystem &system, bool primary, unsigned zone_index)
Changes the order of the eccentricity expansion performed.
AGE
The derivative w.r.t. age, excluding the dependence through the body&#39;s radius and the moments of iner...
Defines the BinarySystem class.
Core::EvolModeType evolution_mode()
The evolution mode of last call to configure().
virtual CombinedStoppingCondition * stopping_conditions(BinarySystem &system, bool primary, unsigned zone_index)
Conditions detecting the next possible discontinuities in the evolution due to this zone...
double inclination(bool evolution_rate=false) const
The angle between the angular momenta of the zone and the orbit.
Outer mass boundary of the zone.
NO_DERIV
The quantity itself, undifferentiated.
SpinOrbitLockInfo __lock
The lock the zone is currently held at (disabled if not locked).
Second age deriv of OUTER_RADIUS.
std::vector< std::list< int > > __evolution_integer
The integer quantities whose evolution is tracked.
bool term(int orbital_freq_mult, int spin_freq_mult) const
Angular momentum of the zone.
SPIN_ANGMOM
The derivative w.r.t. the spin angular momentum in .
double inclination_evolution(const Eigen::Vector3d &orbit_torque, const Eigen::Vector3d &zone_torque, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV, const Eigen::Vector3d &orbit_torque_deriv=Eigen::Vector3d(), const Eigen::Vector3d &zone_torque_deriv=Eigen::Vector3d())
The rate at which the inclination between this zone and the orbit is changing.
static const double __torque_x_minus_coef[]
as a function of .
virtual void rewind_evolution(unsigned nsteps)
Discards the last steps from the evolution.
First age deriv of OUTER_RADIUS.
void configure_spin(double spin, bool spin_is_frequency)
Configures only the spin of the zone.
void update_lock_to_lower_expansion_order(SpinOrbitLockInfo &lock)
Updates a SpinOrbitLockInfo variable as appropriate when decreasing the eccentricity expansion order...
Age second deriv of MOMENT_OF_INERTIA.
std::valarray< double > __torque_y
The dimensionless tidal torque in the y direction and its derivatives.
double forcing_frequency(int orbital_frequency_multiplier, int spin_frequency_multiplier, double orbital_frequency) const
The tidal forcing frequency for the given term and orbital frequency.
std::valarray< double > __torque_z
The dimensionless tidal torque in the z direction and its derivatives.
The rate at which angular momentum changes.
A class combining the the outputs of multiple stopping conditions.
void select_locks_to_monitor()
Initializes the locks the first time the zone is configure() -ed.
virtual bool dissipative() const =0
Should return true iff the zone has some non-zero dissipation.
bool __initializing
Is the zone in the middle of initializing (disable lock check)?
virtual bool can_lock() const =0
Should return true iff the zone&#39;s dissipation is discontinuous at zero frequency. ...
For locked zones this is the spin frequency multiple of the lock.
double __orbital_angmom
The absolute value of the angular momentum of the orbit.
virtual bool locked() const
Should return true iff any tidal term is locked.
Describes a system of two bodies orbiting each other.
Definition: BinarySystem.h:57
void set_lock(int orbital_freq_mult, int spin_freq_mult, short lock_direction=0)
Define which tidal dissipation term is in a lock.
virtual double outer_radius(int deriv_order=0) const =0
Outer radius of the zone or its derivative (per last.
double spin_frequency() const
The spin frequency of the given zone.
virtual void check_locks_consistency() const
Runs a bunch of asserts to check the consistency of __lock and __other_lock.
Defines a lock between the spin of a dissipating body and the orbit.