1 #define BUILDING_LIBRARY 8 double orbital_frequency)
10 double torque_norm = (
11 std::pow(companion_mass / std::pow(semimajor, 3), 2)
25 double dangular_velocity_da = -1.5 * orbital_frequency / semimajor;
26 for(
unsigned zone_index = 0; zone_index <
number_zones(); ++zone_index) {
85 no_deriv_ind = invalid_ind,
86 orbital_freq_deriv_ind = invalid_ind,
87 radius_deriv_ind = invalid_ind,
88 semimajor_deriv_ind = invalid_ind;
100 unsigned zone_index = 0;
109 unsigned deriv_ind = 0;
137 tidal_torque[Dissipation::NO_DERIV],
161 unsigned correction_index = 0;
162 for(
unsigned zone_index=0; zone_index<
number_zones(); ++zone_index)
183 Eigen::Vector3d &outer_angmom_gain,
184 Eigen::Vector3d &inner_angmom_gain,
185 Dissipation::QuantityEntry deriv,
186 bool with_respect_to_outer
196 lost_spin = (dm_dt >= 0
207 outer_angmom_gain[0] = outer_angmom_gain[1] = 0;
214 Eigen::Vector3d(0, 0, angmom_transfer),
216 with_respect_to_outer
219 inner_angmom_gain[0] = inner_angmom_gain[1] = 0;
226 Eigen::Vector3d(0, 0, angmom_transfer),
228 !with_respect_to_outer
235 Dissipation::QuantityEntry deriv,
236 bool with_respect_to_outer
239 assert(zone_index > 0);
242 &zone_above =
zone(zone_index - 1);
243 double scaling = Core::NaN,
261 (with_respect_to_outer && dm_dt <= 0)
263 (!with_respect_to_outer && dm_dt>=0)
265 return Eigen::Vector3d(0, 0, 0);
267 scaling = 1.0 / (with_respect_to_outer
268 ? zone_above.spin_frequency()
271 scaling = -1.0 / (with_respect_to_outer
272 ? zone_above.moment_of_inertia()
274 else scaling = 1.0 / (with_respect_to_outer
275 ? zone_above.angular_momentum()
283 return Eigen::Vector3d(0, 0, 0);
285 Eigen::Vector3d dummy, result;
291 with_respect_to_outer);
301 Dissipation::QuantityEntry deriv,
302 bool with_respect_to_inner
308 &zone_below =
zone(zone_index + 1);
309 double scaling = Core::NaN,
310 dm_dt = zone_below.outer_mass(1);
315 2.0 * zone_below.outer_radius(1) / zone_below.outer_radius(0)
317 zone_below.outer_mass(2) / dm_dt
327 (with_respect_to_inner && dm_dt >= 0)
329 (!with_respect_to_inner && dm_dt <= 0)
331 return Eigen::Vector3d(0, 0, 0);
333 scaling = 1.0 / (with_respect_to_inner
334 ? zone_below.spin_frequency()
337 scaling = -1.0 / (with_respect_to_inner
338 ? zone_below.moment_of_inertia()
340 else scaling = 1.0 / (with_respect_to_inner
341 ? zone_below.angular_momentum()
349 return Eigen::Vector3d(0, 0, 0);
351 Eigen::Vector3d dummy, result;
357 !with_respect_to_inner);
367 Dissipation::QuantityEntry deriv,
382 return Eigen::Vector3d(0,0,0);
383 Eigen::Vector3d result(0, 0, 0);
431 Eigen::VectorXd &above_lock_fractions_age_deriv,
432 Eigen::VectorXd &above_lock_fractions_semimajor_deriv,
433 Eigen::VectorXd &above_lock_fractions_eccentricity_deriv,
434 Eigen::VectorXd &above_lock_fractions_radius_deriv
437 unsigned correction_index = 0;
439 unsigned zone_index = 0;
444 unsigned locked_zone_index = (
453 unsigned entry_ind = 0;
457 Dissipation::QuantityEntry entry = (
472 double frac_deriv = Core::NaN;
474 frac_deriv = (above_lock_fractions_age_deriv
475 [locked_zone_index]);
478 above_lock_fractions_semimajor_deriv
485 above_lock_fractions_eccentricity_deriv
491 frac_deriv = (above_lock_fractions_radius_deriv
492 [locked_zone_index]);
494 frac_deriv = (above_lock_fractions_semimajor_deriv
495 [locked_zone_index]);
512 std::valarray<Eigen::VectorXd> &above_lock_fractions
516 unsigned correction_index = 0;
518 unsigned zone_index = 0;
523 unsigned locked_zone_index = (
529 entry_int < Dissipation::NUM_ENTRIES;
532 Dissipation::QuantityEntry entry = (
533 static_cast<Dissipation::QuantityEntry
>(entry_int)
535 Eigen::Vector3d correction = (
568 static_cast<Dissipation::QuantityEntry>(
577 above_lock_fractions[entry][locked_zone_index]
589 double companion_mass,
592 const double *spin_angmom,
593 const double *inclination,
594 const double *periapsis,
596 bool zero_outer_inclination,
597 bool zero_outer_periapsis)
599 double orbital_angmom=Core::orbital_angular_momentum(
621 std::cerr <<
"Initializing DissipatingBody" << std::endl;
628 unsigned angmom_offset = (locked_surface ? 1 : 0);
630 unsigned zone_index = 0;
635 double zone_inclination, zone_periapsis, zone_spin;
637 zone_inclination = 0;
638 else if(zero_outer_inclination)
639 zone_inclination = (zone_index
640 ? inclination[zone_index - 1]
643 zone_inclination = inclination[zone_index];
646 else if(zero_outer_periapsis)
647 zone_periapsis = (zone_index ? periapsis[zone_index-1] : 0);
649 zone_periapsis = periapsis[zone_index];
650 if(locked_surface && zone_index == 0)
652 else if(current_zone.
locked() && !initialize) {
653 zone_spin = Core::NaN;
656 zone_spin = spin_angmom[zone_index - angmom_offset];
658 std::cerr <<
"Configuring zone " << zone_index << std::endl;
668 locked_surface && zone_index == 0);
671 unsigned zone_index = 0;
680 zone(zone_index + 1),
690 tidal_torque.resize(Dissipation::NUM_ENTRIES);
696 Dissipation::QuantityEntry entry = (
697 static_cast<Dissipation::QuantityEntry
>(torque_ind)
715 !std::isnan(tidal_torque[entry].sum())
731 Dissipation::QuantityEntry deriv,
737 assert(static_cast<int>(zone_index) + deriv_zone >= 0);
738 assert(static_cast<int>(zone_index) + deriv_zone
742 Eigen::Vector3d result(0, 0, 0);
743 if(zone_index == 0 && deriv_zone == 0)
751 (!zone_specific(deriv) || deriv_zone >= 0)
759 (!zone_specific(deriv) || deriv_zone<=0)
774 zone(zone_index - 1),
786 Dissipation::QuantityEntry entry)
const 815 std::valarray<Eigen::VectorXd> &above_lock_fractions
837 Dissipation::QuantityEntry entry,
838 unsigned deriv_zone_index,
839 const Eigen::VectorXd &above_lock_fraction_deriv
843 double result = Core::NaN;
845 !zone_specific(entry)
851 if(zone_specific(entry)) {
852 result =
tidal_power(deriv_zone_index,
false, entry);
875 assert(above_lock_fraction_deriv.size()
879 unsigned correction_index = 0;
880 for(
unsigned zone_index = 0; zone_index <
number_zones(); ++zone_index)
883 above_lock_fraction_deriv
894 Dissipation::QuantityEntry entry,
895 unsigned deriv_zone_index,
896 const Eigen::VectorXd &above_lock_fraction_deriv
899 if(zone_specific(entry) && deriv_zone_index != 0) {
918 assert(above_lock_fraction_deriv.size()
922 unsigned correction_index = 0;
924 unsigned zone_index = 0;
930 above_lock_fraction_deriv[
960 [Dissipation::NO_DERIV]
974 Dissipation::QuantityEntry entry,
975 unsigned deriv_zone_index,
976 const Eigen::VectorXd &above_lock_fraction_deriv
979 Eigen::Vector3d result;
985 above_lock_fraction_deriv)
996 deriv_zone_index == 0
998 &
zone(deriv_zone_index) == &reference_zone
1005 deriv_zone_index==0);
1012 for(
unsigned zone_ind = 0; zone_ind <
number_zones(); ++zone_ind)
1018 for(
unsigned zone_ind = 0; zone_ind <
number_zones(); ++zone_ind)
1024 for(
unsigned zone_ind = 0; zone_ind <
number_zones(); ++zone_ind)
1034 for(
unsigned zone_ind = 0; zone_ind <
number_zones(); ++zone_ind)
1045 for(
unsigned zone_ind = 0; zone_ind <
number_zones(); ++zone_ind)
double __power_norm
The coefficient used to normalize tidal power.
double tidal_power(bool above, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV) const
The dimensionless tidal power or one of its derivatives.
unsigned locked_zone_index() const
The index of this zone in the list of locked zones (valid only if locked).
std::valarray< std::valarray< Eigen::Vector3d > > __angular_momentum_transfer
The rate of angular momentum transfer between two neighboring zones due to zone boundaries moving...
virtual void rewind_evolution(unsigned nsteps)
Discards the last steps from the evolution.
virtual void reset_evolution()
Discards all evolution.
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.
virtual void add_to_evolution()
Appends the state defined by last configure(), to the evolution.
double angular_momentum() const
The angular momentum of the given zone in .
void set_above_lock_fractions(std::valarray< Eigen::VectorXd > &above_lock_fractions)
Corrects the tidal orbit energy gain and angular momentum gain for locked zones.
Eigen::Vector3d angular_momentum_transfer_from_bottom(unsigned zone_index, Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV, bool with_respect_to_inner=false) const
Rate of angular momentum transfer (or its derivatives) to a zone due to its bottom boundary moving...
SPIN_FREQUENCY
The derivative w.r.t. the spin frequency of a dissipating zone.
DissipatingBody()
Some initializations for new objects.
double tidal_power(unsigned zone_index, bool above, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV) const
Tidal power dissipated in the given zone.
Eigen::Vector3d angular_momentum_transfer_from_top(unsigned zone_index, Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV, bool with_respect_to_outer=false) const
Rate of angular momentum transfer (or its derivatives) to a zone due to its top boundary moving...
virtual Eigen::Vector3d angular_momentum_coupling(unsigned top_zone_index, Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV, bool with_respect_to_top=false) const =0
Coupling torque for two neighboring zones in the coordinate system of the top zone.
virtual void add_to_evolution()
Appends the state defined by last configure(), to the evolution.
virtual const DissipatingZone & zone(unsigned zone_index) const =0
A modifiable reference to one of the body's zones.
SEMIMAJOR
The derivative w.r.t. the semimajor axis in AU.
Eigen::Vector3d zone_to_zone_transform(const ZoneOrientation &from_zone, const ZoneOrientation &to_zone, const Eigen::Vector3d &vector, Dissipation::QuantityEntry deriv, bool with_respect_to_from)
Transforms a vector betwen the coordinates systems of two zones.
double surface_lock_frequency() const
Angular velocity of the surface zone when locked (assumed constant).
Orientations of zones of bodies in a binary system.
double tidal_torque_y(bool above, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV) const
The dimensionless torque along y.
NUM_DERIVATIVES
The total number of derivatives supported.
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...
double mass() const
The mass of the body (constant with age).
void calculate_orbit_rate_corrections()
Calculates the correction the orbital energy gain and torque due to switching locked zones from fully...
virtual void configure(bool initialize, double age, double companion_mass, double semimajor, double eccentricity, const double *spin_angmom, const double *inclination=NULL, const double *periapsis=NULL, bool locked_surface=false, bool zero_outer_inclination=false, bool zero_outer_periapsis=false)
Defines the orbit this body is in.
virtual CombinedStoppingCondition * stopping_conditions(BinarySystem &system, bool primary)
Conditions detecting the next possible discontinuities in the evolution due to this body...
double __dorbital_frequency_da
The derivative of the orbital frequency w.r.t. semimajor axis.
double radius(int deriv_order=0) const
The current radius or its derivative with age of the body.
Eigen::Vector3d nontidal_torque(unsigned zone_index, Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV, int deriv_zone=0) const
External torque acting on a single zone (last calculate_torques_power()).
const double solar_radius
Radius of the sun [m].
A layer of a system body for which the tidal bulge is not exactly in phase with the tidal potential...
virtual void reset_evolution()
Discards all evolution.
double __orbital_frequency
The mean angular velocity with which the orbit is traversed.
double normalize_torques(double companion_mass, double semimajor, double orbital_frequency)
Scales the dimensionless torques as appropriate and corrects the relevant derivatives returning the n...
std::valarray< std::valarray< Eigen::Vector3d > > __tidal_torques_below
Tidal torques and their derivatives on each zone for spin frequency approaching potential lock from b...
virtual double outer_mass(int deriv_order=0) const =0
Mass coordinate of the zone's outer ouboundary or its derivative.
void correct_orbit_torque(std::valarray< Eigen::VectorXd > &above_lock_fractions)
Corrects __orbit_torque for zone locks.
ECCENTRICITY
The derivative w.r.t. the eccentricity.
const double solar_mass
Mass of the sun [kg].
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's radius and the moments of iner...
std::vector< Eigen::Vector3d > __orbit_torque_correction
Corrections to __orbit_torque_below (undifferentiated) if single zones switch to above.
virtual double angular_momentum_loss(Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV) const =0
Rate of angular momentum loss by the top zone of the body and its derivatives.
void angular_momentum_transfer(const DissipatingZone &outer_zone, const DissipatingZone &inner_zone, Eigen::Vector3d &outer_angmom_gain, Eigen::Vector3d &inner_angmom_gain, Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV, bool with_respect_to_outer=false) const
Angular momentum transfer between two neighboring zones due to moving zone boundaries.
virtual CombinedStoppingCondition * stopping_conditions(BinarySystem &system, bool primary, unsigned zone_index)
Conditions detecting the next possible discontinuities in the evolution due to this zone...
virtual bool locked(int orbital_frequency_multiplier, int spin_frequency_multiplier) const
Should return true iff the given term is presently locked.
NO_DERIV
The quantity itself, undifferentiated.
Declares the DissipatingBody class.
ORBITAL_FREQUENCY
The derivative w.r.t. the orbital frequency.
double tidal_torque_z(bool above, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV) const
The dimensionless tidal torque along z.
std::vector< Dissipation::QuantityEntry > __orbit_entries
The quantities w.r.t. which derivatives of the orbit energy gain and torque are pre-calculated.
SPIN_ANGMOM
The derivative w.r.t. the spin angular momentum in .
double tidal_orbit_power(Dissipation::QuantityEntry entry=Dissipation::NO_DERIV, unsigned deriv_zone_index=0, const Eigen::VectorXd &above_lock_fraction_deriv=Eigen::VectorXd()) const
Rate of increase of the orbital energy due to tides in this body (last calculate_torques_power()).
virtual void rewind_evolution(unsigned nsteps)
Discards the last steps from the evolution.
const Eigen::Vector3d & tidal_torque(unsigned zone_index, bool above, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV) const
Tidal torque acting on the given zone (last calculate_torques_power()).
Eigen::Vector3d angular_momentum_transfer_to_zone(unsigned zone_index, Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV, int deriv_zone=0) const
Rate of angular momentum transfer (or its derivatives) to a zone due to moving zone boundaries...
void collect_orbit_rates(double orbital_frequency, double torque_norm)
Calcuates the total energy and angular momentum loss rates for the orbit due to this body's tidal dis...
std::valarray< std::valarray< Eigen::Vector3d > > __tidal_torques_above
Tidal torques and their derivatives on each zone for spin frequency approaching potential lock from a...
A class combining the the outputs of multiple stopping conditions.
void correct_orbit_power(Eigen::VectorXd &above_lock_fractions_age_deriv, Eigen::VectorXd &above_lock_fractions_semimajor_deriv, Eigen::VectorXd &above_lock_fractions_eccentricity_deriv, Eigen::VectorXd &above_lock_fractions_radius_deriv)
Corrects __orbit_power for zone locks.
std::vector< Eigen::Vector3d > __orbit_torque
Torque on the orbit (and its derivatives and error) due to tides on this body.
virtual bool dissipative() const =0
Should return true iff the zone has some non-zero dissipation.
std::valarray< Eigen::VectorXd > __above_lock_fractions
The fractional contribution of the above the lock rates for locked zones and their derivatives...
unsigned __num_locked_zones
The number of zones currently in a spin-orbit lock.
double tidal_torque_x(bool above, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV) const
The dimensionless tidal torque along x.
Describes a system of two bodies orbiting each other.
std::valarray< double > __orbit_power
Total tidal power (and derivatives and error) gained by the orbit from this body. ...
virtual void change_expansion_order(unsigned new_expansion_order, BinarySystem &system, bool primary)
Change the eccentricity expansion order for all dissipative zones.
std::valarray< double > __orbit_power_correction
Corrections to __orbit_power_below (undifferentiated) if single zones switch to above.
Eigen::Vector3d tidal_orbit_torque(Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV, unsigned deriv_zone_index=0, const Eigen::VectorXd &above_lock_fraction_deriv=Eigen::VectorXd()) const
The torque on the orbit due to tidal dissipation in the body.
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 surface spin freuqency of the body.
double spin_frequency() const
The spin frequency of the given zone.
const double G
Gravitational constant in SI.
virtual unsigned number_zones() const =0
The number of zones the body consists of.