1 #define BUILDING_LIBRARY 15 case PERIAPSIS : os <<
"PERIAPSIS";
break;
19 os <<
"DMOMENT_OF_INERTIA_DT";
break;
21 os <<
"D2MOMENT_OF_INERTIA_DT2";
break;
27 case E_ORDER : os <<
"E_ORDER";
break;
31 default : assert(
false);
50 int orbital_frequency_multiplier,
51 int spin_frequency_multiplier,
52 double &forcing_frequency
61 limit.
term(orbital_frequency_multiplier,
62 spin_frequency_multiplier)
65 spin_frequency_multiplier
80 std::numeric_limits<double>::epsilon()
84 int expected_sign = boost::math::sign(
88 orbital_frequency_multiplier
94 spin_frequency_multiplier
102 if(forcing_frequency * expected_sign > 0)
return;
106 forcing_frequency = (
107 std::numeric_limits<double>::epsilon()
116 int max_abs_orb_mult =
static_cast<int>(
__e_order + 2);
123 "Inconsistent lock state encountered for a zone. Likely related " 124 "to initial conditions with a tidal term too close to zero." 230 std::cerr <<
"Initializing locks for Worb = " 236 int below_orb_mult = std::floor(2.0
241 max_abs_orb_mult=
static_cast<int>(
__e_order + 2);
242 if(below_orb_mult % 2) {
244 std::abs(below_orb_mult)
251 std::abs((below_orb_mult - 1) / 2)
256 if((below_orb_mult + 1) / 2 > max_abs_orb_mult)
269 }
else if(std::abs(below_orb_mult / 2) <= max_abs_orb_mult) {
271 if(std::abs(below_orb_mult + 1) <= max_abs_orb_mult)
273 else if(std::abs(below_orb_mult / 2 + 1) <= max_abs_orb_mult)
292 double tidal_frequency,
300 bool locked_term =
locked(mp, m);
302 bool has_error =
true;
313 Dissipation::QuantityEntry phase_lag_deriv = (
315 ?
static_cast<Dissipation::QuantityEntry
>(deriv)
318 double mod_phase_lag_above,
344 double U_mmp_squared = std::pow(U.
m, 2),
345 U_mmp_squared_error = (has_error
346 ? (2.0 * std::abs(U.
m * U_error.
m)
348 std::pow(U_error.
m, 2))
350 term_power = U_mmp_squared * mp,
351 term_power_error = U_mmp_squared_error * mp,
352 term_torque_z = U_mmp_squared * m,
353 term_torque_z_error = U_mmp_squared_error * m,
354 term_torque_x = U.
m * (
359 term_torque_x_error = 0.0;
361 double common_error_term = (
366 term_torque_x_error = (
369 ? U_error.
m * (term_torque_x / U.
m + common_error_term)
373 U.
m * common_error_term
381 mod_phase_lag_above = mod_phase_lag_below;
389 mod_phase_lag_below = mod_phase_lag_above;
390 int deriv_ind = 2 * deriv;
391 __power[deriv_ind] += term_power * mod_phase_lag_below;
394 mod_phase_lag_below);
397 mod_phase_lag_below);
399 __torque_y[deriv_ind] -= term_torque_x * love_coef
401 __power[deriv_ind + 1] += term_power * mod_phase_lag_above;
404 mod_phase_lag_above);
407 mod_phase_lag_above);
409 assert(!std::isnan(
__torque_x[deriv_ind + 1]));
411 assert(!std::isnan(
__torque_y[deriv_ind + 1]));
413 assert(!std::isnan(
__torque_z[deriv_ind + 1]));
417 __power[error_ind] += term_power_error * mod_phase_lag_below;
420 mod_phase_lag_below);
423 mod_phase_lag_below);
425 __torque_y[error_ind] -= term_torque_x_error * love_coef
427 __power[error_ind + 1] += (term_power_error
429 mod_phase_lag_above);
430 __torque_z[error_ind + 1] += (term_torque_z_error
432 mod_phase_lag_above);
433 __torque_x[error_ind + 1] += (term_torque_x_error
435 mod_phase_lag_above);
438 assert(!std::isnan(
__torque_x[error_ind + 1]));
440 assert(!std::isnan(
__torque_y[error_ind + 1]));
442 assert(!std::isnan(
__torque_z[error_ind + 1]));
445 if(deriv == Dissipation::NO_DERIV)
446 std::cerr <<
", Wzone = " 448 <<
", U(" << m <<
", " << mp <<
") = " 452 <<
", mod_phase_lag(above=" 453 << mod_phase_lag_above
455 << mod_phase_lag_below
462 bool spin_is_frequency)
464 if(spin_is_frequency) {
474 DissipatingZone::DissipatingZone() :
491 double orbital_frequency,
493 double orbital_angmom,
497 bool spin_is_frequency)
504 std::cerr <<
"Initializing DissipatingZone" << std::endl;
508 std::cerr <<
"At t = " << age <<
", configuring zone with " 509 << (spin_is_frequency ?
"w" :
"L") <<
" = " << spin
510 <<
", inclination = " << inclination
511 <<
", periapsis = " << periapsis
518 if(
__lock && !initialize) {
528 if(std::isnan(orbital_frequency))
return;
538 double esquared = std::pow(eccentricity, 2);
541 int mp = -static_cast<int>(
__e_order) - 2;
558 for(
int m = -2; m <= 2; ++m) {
560 std::cerr <<
"Term: m' = " 601 std::cerr << std::endl;
608 int orbital_frequency_multiplier,
609 int spin_frequency_multiplier,
610 double orbital_frequency
620 if(
__lock(orbital_frequency_multiplier, spin_frequency_multiplier))
622 double forcing_freq = (
623 orbital_frequency_multiplier * orbital_frequency
627 assert(!std::isnan(forcing_freq));
630 std::cerr <<
"Worb = " << orbital_frequency <<
", " 632 <<
"Wtide = " << forcing_freq <<
" -> ";
642 orbital_frequency_multiplier,
643 spin_frequency_multiplier,
647 orbital_frequency_multiplier,
648 spin_frequency_multiplier,
651 std::cerr << forcing_freq << std::endl;
659 const Eigen::Vector3d &orbit_torque,
660 const Eigen::Vector3d &zone_torque,
661 Dissipation::QuantityEntry entry,
662 const Eigen::Vector3d &orbit_torque_deriv,
663 const Eigen::Vector3d &zone_torque_deriv
671 orbit_y_torque = orbit_torque[1];
672 zone_y_torque = zone_torque[1];
678 std::abs(orbit_torque[1] * cos_inc
682 std::abs(zone_torque[1]
688 orbit_y_torque = orbit_torque_deriv[1];
689 zone_y_torque = zone_torque_deriv[1];
693 assert(orbit_y_torque == 0 || std::isnan(orbit_y_torque));
694 assert(zone_y_torque == 0 || std::isnan(zone_y_torque));
696 assert(!std::isnan(orbit_y_torque));
697 assert(!std::isnan(zone_y_torque));
709 assert(!std::isnan(result));
732 if(sin_inc == 0)
return 0.0;
743 if(sin_inc == 0)
return 0.0;
763 const Eigen::Vector3d &orbit_torque,
764 const Eigen::Vector3d &zone_torque,
765 Dissipation::QuantityEntry entry,
766 const Eigen::Vector3d &orbit_torque_deriv,
767 const Eigen::Vector3d &zone_torque_deriv)
774 assert(!std::isnan(orbit_torque[0]));
775 assert(!std::isnan(orbit_torque[2]));
776 assert(!std::isnan(zone_torque[0]));
778 orbit_x_torque = orbit_torque[0];
779 orbit_z_torque = orbit_torque[2];
780 zone_x_torque = zone_torque[0];
782 if(orbit_torque[0] == 0 && orbit_torque[2] == 0)
788 std::abs(orbit_torque[0] * cos_inc)
790 std::abs(orbit_torque[2] * sin_inc)
796 orbit_x_torque = orbit_torque_deriv[0];
797 orbit_z_torque = orbit_torque_deriv[2];
798 zone_x_torque = zone_torque_deriv[0];
802 if(orbit_x_torque == 0 && orbit_z_torque == 0)
805 result = ((orbit_x_torque * cos_inc - orbit_z_torque * sin_inc)
812 assert(!std::isnan(result));
847 (orbit_torque[2] * cos_inc + orbit_torque[0] * sin_inc)
883 assert(direction == 1 || direction == -1);
903 unsigned new_e_order,
910 std::cerr <<
"Changing eccentricity order to " 918 std::cerr <<
"No lock defined, simple e-order change." << std::endl;
923 std::cerr <<
"Lock(s) defined, updating." << std::endl;
1014 for(
unsigned i = 0; i < nsteps; ++i) {
ZoneEvolutionQuantities
IDs for quantities saved as part of the evolution.
double m
The (m, m') 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.
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 error and 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.
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.
double periapsis(bool evolution_rate=false) const
The argument of periapsis of this zone minus the reference zone'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.
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, const TidalTermTriplet &U_error)
Add a term to the tidal torque and power arrays.
static const double __torque_x_plus_coef[]
as a function of .
unsigned __e_order
The expansion order in eccentricity to use.
std::vector< std::list< double > > __evolution_real
The floating point quantities whose evolution is tracked.
void update_lock_to_lower_e_order(SpinOrbitLockInfo &lock)
Updates a SpinOrbitLockInfo variable as appropriate when decreasing the eccentricity expansion order...
Outer radius boundary of the zone.
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 time the love number for the given tidal term (or one of its deriva...
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)...
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') coefficient.
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).
short lock_direction() const
double m_plus_one
The (m+1, m') coefficient.
void configure(double inclination, double periapsis)
Changes the zone orientation.
TidalPotentialTerms __potential_term
The expansion of the tidal potential in series.
void change_e_order(unsigned new_e_order)
Change the eccentricity expansion order.
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'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'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.
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.
void initialize_locks()
Initializes the locks the first time the zone is configure() -ed.
AGE
The derivative w.r.t. age, excluding the dependence through the body'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.
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.
virtual void change_e_order(unsigned new_e_order, BinarySystem &system, bool primary, unsigned zone_index)
Changes the order of the eccentricity expansion performed.
The rate at which angular momentum changes.
A class combining the the outputs of multiple stopping conditions.
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'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.
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.