8 #define BUILDING_LIBRARY 16 for(
short body_ind = 0; body_ind < 2; ++body_ind) {
19 unsigned zone_ind = 0;
35 lock_scenario_type result;
37 for(
unsigned short body_ind = 0; body_ind < 2; ++body_ind) {
40 unsigned zone_ind = 0;
48 bool other_lock=
false;
49 unsigned scenario_zone_i = (zone_ind
79 std::get<0>(result.back()) == scenario_zone_i);
80 other_lock = !other_lock;
88 const lock_scenario_type &lock_scenario
93 std::cerr <<
"Setting lock scenario: " << std::endl;
96 std::vector<bool>(lock_scenario.size(),
false),
105 std::vector<double>::iterator
106 angmom_dest = angmom.begin(),
107 inclination_dest = inclinations.begin(),
108 periapsis_dest = periapses.begin();
109 lock_scenario_type::const_iterator
110 scenario_zone_iter = lock_scenario.begin();
112 unsigned scenario_zone;
113 short scenario_lock_dir;
114 double scenario_angmom, zone_angmom;
115 std::tie(scenario_zone,
117 scenario_angmom) = *scenario_zone_iter;
119 for(
short body_i = 0; body_i < 2; ++body_i) {
121 for(
unsigned zone_i = 0; zone_i < body.
number_zones(); ++zone_i) {
129 zone_angmom = scenario_angmom;
138 std::cerr <<
"Unlocking " 139 << (body_i == 0 ?
"primary" :
"secondary")
140 <<
" zone " << zone_i
141 <<
"(overall zone " << scenario_zone
152 std::cerr <<
"Locking " 153 << (body_i == 0 ?
"primary" :
"secondary")
154 <<
" zone " << zone_i
155 <<
"(overall zone " << scenario_zone
160 if(scenario_lock_dir != 0) {
162 std::cerr <<
"Unlocking " 163 << (body_i == 0 ?
"primary" :
"secondary")
164 <<
" zone " << zone_i
165 <<
"(overall zone " << scenario_zone
176 std::cerr << (body_i == 0 ?
"Primary" :
"Secondary")
177 <<
" zone " << zone_i
178 <<
"(overall zone " << scenario_zone
179 <<
") already matches scenario." 183 ++scenario_zone_iter;
184 if(scenario_zone_iter != lock_scenario.end())
185 std::tie(scenario_zone,
187 scenario_angmom) = *scenario_zone_iter;
194 *angmom_dest++ = zone_angmom;
211 const std::vector<short> &unlock_directions,
212 const std::vector<double> &original_angmom
219 unsigned locked_i = 0;
220 for(
unsigned config_i = 0; config_i <
number_zones(); ++config_i) {
224 unsigned body_zone_i = (
231 config_inclinations[config_i] = zone.
inclination();
233 config_periapses[config_i - 1] = zone.
periapsis();
236 config_angmom[config_i] = (original_angmom.size()
237 ? original_angmom[locked_i]
240 unlock_directions[locked_i]);
249 config_angmom.data(),
250 config_inclinations.data(),
251 config_periapses.data(),
258 unsigned body_zone_ind = (primary_zone
268 std::valarray<double> orbit;
270 std::valarray<double> derivatives(orbit.size());
276 std::valarray<double> check_cond_deriv;
288 assert(check_cond_deriv.size() == 1);
291 <<
"for zone " << test_zone_ind
292 <<
" (condition deriv: " << check_cond_deriv[0]
304 const lock_scenario_type &lock_scenario,
305 const std::vector<bool> passed,
309 lock_scenario_type::const_iterator
310 scenario_zone_i = lock_scenario.begin();
311 std::vector<bool>::const_iterator passed_i = passed.begin();
312 unsigned test_zone_ind;
313 short lock_direction;
314 std::tie(test_zone_ind, lock_direction, std::ignore) = *scenario_zone_i;
327 for(
short body_i = 0; body_i < 2; ++body_i) {
329 for(
unsigned zone_i = 0; zone_i < body.
number_zones(); ++zone_i) {
339 if(lock_direction == 0)
341 else if(lock_direction > 0)
344 <<
" (" << (*passed_i ?
"V" :
"X") <<
")";
346 if(scenario_zone_i != lock_scenario.end())
347 std::tie(test_zone_ind,
349 std::ignore) = *scenario_zone_i;
363 const lock_scenario_type &lock_scenario
365 ,
bool first_scenario
374 std::vector<bool> passed(lock_scenario.size());
375 std::vector<bool>::iterator passed_i = passed.begin();
379 lock_scenario_type::const_iterator
380 scenario_zone_iter = lock_scenario.begin();
381 scenario_zone_iter != lock_scenario.end();
384 unsigned test_zone_ind;
385 short lock_direction;
386 std::tie(test_zone_ind,
388 std::ignore) = *scenario_zone_iter;
389 if(lock_direction == 0) {
391 std::cerr <<
"Lock for zone " << test_zone_ind <<
" will ";
395 *above_lock_fraction_p > 0
397 *above_lock_fraction_p < 1
411 else *passed_i++ =
true;
414 std::cerr <<
"hold (above lock frac: " 415 << *above_lock_fraction_p
418 ++above_lock_fraction_p;
428 else *passed_i++ =
true;
435 first_scenario ||
true);
443 lock_scenario_type::const_iterator next_synchronized_zone,
444 unsigned num_synchronized_zones,
445 lock_scenario_type &lock_scenario
447 ,
bool first_scenario
452 if(lock_scenario.size() == num_synchronized_zones) {
456 std::cerr <<
"Selected lock scenario: " << std::endl;
460 std::vector<bool>(lock_scenario.size(),
true),
466 std::vector<bool>(lock_scenario.size(),
true),
478 assert(lock_scenario.size() < num_synchronized_zones);
480 lock_scenario.push_back(*next_synchronized_zone);
481 short &scenario_dir = std::get<1>(lock_scenario.back());
482 short orig_lock_direction = std::get<1>(*next_synchronized_zone);
486 ++next_synchronized_zone;
487 for(scenario_dir = -1; scenario_dir <= 1; ++scenario_dir) {
490 next_synchronized_zone,
491 num_synchronized_zones,
506 first_scenario =
false;
509 lock_scenario.pop_back();
519 double *evolution_rates
529 unsigned zone_index = 1;
538 evolution_rates[zone_index - 1],
550 #ifdef ENABLE_DERIVATIVES 551 void BinarySystem::locked_surface_jacobian(
double *param_derivs,
552 double *age_derivs)
const 558 for(
unsigned row = 0; row < num_param; ++row) {
559 double dIbelow_dt = 0;
572 if(row < num_param - 1) {
621 for(
unsigned col = 0; col < num_param; ++col) {
622 double &dest = *(param_derivs + row * num_param + col);
623 if(std::abs(static_cast<int>(row) -
static_cast<int>(col)) < 1)
648 double *evolution_rates
653 *inclination_evol = evolution_rates,
654 *periapsis_evol = evolution_rates + (nzones - 1),
655 *angmom_evol = periapsis_evol+(nzones - 1);
657 Eigen::Vector3d reference_torque;
658 for(
unsigned zone_index = 0; zone_index < nzones; ++zone_index) {
660 angmom_evol[zone_index] = torque[2];
677 }
else reference_torque = torque;
680 angmom_evol[zone_index],
681 (zone_index ? inclination_evol[zone_index - 1] : 0.0),
682 (zone_index ? periapsis_evol[zone_index -1] : 0.0)
686 std::cerr <<
"rates: ";
687 for(
unsigned i = 0; i < 3 * nzones - 2; ++i) {
688 if(i) std::cerr <<
", ";
689 std::cerr << evolution_rates[i];
691 std::cerr << std::endl;
696 #ifdef ENABLE_DERIVATIVES 697 void BinarySystem::fill_single_body_jacobian(
698 double *inclination_param_derivs,
699 double *periapsis_param_derivs,
700 double *angmom_param_derivs,
701 double *inclination_age_derivs,
702 double *periapsis_age_derivs,
703 double *angmom_age_derivs
734 unsigned deriv_zone_ind = 0;
735 deriv_zone_ind < nzones;
738 angmom_param_derivs[deriv_zone_ind - 1] =
739 (deriv_zone_ind == 1 ? dref_torque_dincl[2] : 0);
740 angmom_param_derivs[nzones+deriv_zone_ind - 2] =
741 (deriv_zone_ind == 1 ? dref_torque_dperi[2] : 0);
742 double &angmom_angmom_deriv =
743 angmom_param_derivs[2 * nzones+deriv_zone_ind - 2];
744 if(deriv_zone_ind==0) angmom_angmom_deriv = dref_torque_dangmom0[2];
745 else if(deriv_zone_ind == 1)
746 angmom_angmom_deriv = dref_torque_dangmom1[2];
747 else angmom_angmom_deriv = 0;
749 angmom_age_derivs[0] = dref_torque_dage[2];
751 for(
unsigned zone_ind = 1; zone_ind < nzones; ++zone_ind) {
764 inclination_age_derivs[zone_ind - 1] =
768 ref_torque_age_deriv,
769 zone_torque_age_deriv);
770 periapsis_age_derivs[zone_ind - 1] =
774 ref_torque_age_deriv,
775 zone_torque_age_deriv);
776 angmom_age_derivs[zone_ind] = zone_torque_age_deriv[2];
778 unsigned quantity_ind = 0;
779 quantity_ind < nparams;
782 unsigned offset = (zone_ind - 1) * nparams + quantity_ind;
783 double &inclination_dest = inclination_param_derivs[offset],
784 &periapsis_dest = periapsis_param_derivs[offset],
785 &angmom_dest = angmom_param_derivs[offset+nparams];
786 unsigned quantity_zone = quantity_ind;
787 Dissipation::QuantityEntry with_respect_to;
788 Eigen::Vector3d ref_torque_deriv(0, 0, 0);
789 if(quantity_ind > 2 * nzones - 2) {
790 quantity_zone -= 2 * nzones - 2;
792 if(quantity_zone == 0)
793 ref_torque_deriv = dref_torque_dangmom0;
794 else if(quantity_zone == 1)
795 ref_torque_deriv = dref_torque_dangmom1;
796 if(quantity_zone <= 1)
803 if(quantity_ind >= nzones - 1) {
804 quantity_zone -= nzones - 2;
806 if(quantity_zone == 1)
807 ref_torque_deriv = dref_torque_dperi;
811 if(quantity_zone == 1)
812 ref_torque_deriv = dref_torque_dincl;
814 if(quantity_zone == 1)
825 Eigen::Vector3d zone_torque_deriv;
826 if(quantity_zone == zone_ind) {
843 if(std::abs(static_cast<int>(quantity_zone-zone_ind)) == 1) {
847 quantity_zone - zone_ind
849 }
else zone_torque_deriv = zero3d;
857 angmom_dest = zone_torque_deriv[2];
862 void BinarySystem::single_body_jacobian(
double *param_derivs,
863 double *age_derivs)
const 867 fill_single_body_jacobian(param_derivs,
868 param_derivs + (nzones - 1) * nparams,
869 param_derivs + 2 * (nzones - 1) * nparams,
871 age_derivs + (nzones - 1),
872 age_derivs + 2 * (nzones - 1));
878 double orbit_power_deriv
881 if(std::isnan(orbit_power_deriv))
882 return (orbit_power == 0
886 else if(orbit_power == 0 && orbit_power_deriv == 0)
900 double orbit_angmom_gain,
901 double orbit_power_deriv,
902 double orbit_angmom_gain_deriv,
903 bool semimajor_deriv)
const 909 if(std::isnan(orbit_power_deriv))
913 else if(semimajor_deriv)
927 2.0 * orbit_angmom_gain_deriv
955 Dissipation::QuantityEntry entry,
957 Eigen::MatrixXd &matrix,
961 unsigned deriv_zone_index = (body1_deriv
979 unsigned locked_ind = 0;
982 unsigned zone_ind = 0;
983 zone_ind < body->number_zones();
999 if(body->zone(zone_ind).locked()) {
1000 matrix.col(locked_ind).array() += (
1004 body->tidal_power(zone_ind,
true)
1006 body->tidal_power(zone_ind,
false)
1019 }
else if(deriv_zone.
locked()) {
1030 matrix(deriv_zone_index, deriv_zone_index) -=(
1035 rhs(deriv_zone_index) -= (
1041 rhs(deriv_zone_index) -= (
1051 Eigen::VectorXd &fractions,
1052 Dissipation::QuantityEntry entry,
1062 std::cerr <<
"Setting " 1064 <<
" above lock fractions " 1069 if(num_locked_zones == 0) {
1070 fractions.resize(0);
1073 std::valarray<double> nontidal_torque(num_locked_zones),
1074 tidal_torque_z_above(num_locked_zones),
1075 tidal_torque_z_below(num_locked_zones),
1076 tidal_power_difference(num_locked_zones);
1077 unsigned locked_zone_ind = 0;
1088 nontidal_torque[locked_zone_ind] =
1090 tidal_torque_z_above[locked_zone_ind] =
1092 tidal_torque_z_below[locked_zone_ind] =
1094 if(!zone_specific(entry) || *zi == 0) {
1095 tidal_power_difference[locked_zone_ind] = (
1103 Eigen::MatrixXd matrix(num_locked_zones, num_locked_zones);
1104 Eigen::VectorXd rhs(num_locked_zones);
1116 std::list<unsigned>::const_iterator
1121 if(!zone_specific(entry) || *zi == 0)
1122 matrix.col(i).setConstant(1.5
1124 tidal_power_difference[i]
1127 else matrix.col(i).setZero();
1132 (tidal_torque_z_above[i] - tidal_torque_z_below[i])
1144 rhs(i) -= ((nontidal_torque[i] + tidal_torque_z_below[i])
1161 Dissipation::QuantityEntry entry,
1163 unsigned zone_index)
1172 assert(zone_index > 0 || &body == &
__body2);
1179 if(num_locked_zones == 0)
return Eigen::VectorXd();
1181 unsigned locked_zone_index=(&body == &
__body1 1184 Eigen::VectorXd rhs;
1185 for(
unsigned i = 0; i < zone_index; ++i)
1186 if(body.
zone(i).
locked()) ++locked_zone_index;
1187 if(deriv_zone.
locked()) {
1192 -1.5 * (above_frac*body.
tidal_power(zone_index,
true, entry)
1200 rhs(locked_zone_index) -=
1201 above_frac*body.
tidal_torque(zone_index,
true, entry)[2]
1207 rhs(locked_zone_index) -= (
1213 rhs(locked_zone_index) += (
1223 rhs.setConstant(num_locked_zones,
1224 -1.5 * body.
tidal_power(zone_index,
false, entry));
1226 if(zone_index > 0 && body.
zone(zone_index - 1).
locked())
1255 unsigned body_zone_ind = 0;
1256 for(
unsigned zone_ind = 1; zone_ind < num_zones; ++zone_ind) {
1283 std::valarray<Eigen::VectorXd>
1292 static_cast<Dissipation::QuantityEntry>(deriv)
1294 if(!zone_specific(static_cast < Dissipation::QuantityEntry>(deriv)))
1297 body2_above_lock_fractions[deriv],
1298 static_cast<Dissipation::QuantityEntry>(deriv),
1339 double *inclination_rates = differential_equations + 2,
1340 *periapsis_rates = inclination_rates + num_total_zones,
1341 *angmom_rates = periapsis_rates + num_total_zones - 1;
1342 unsigned angmom_skipped = 0;
1343 double reference_periapsis_rate = Core::NaN;
1344 for(
unsigned zone_ind = 0; zone_ind < num_total_zones; ++zone_ind) {
1348 unsigned body_zone_ind = zone_ind;
1349 if(zone_ind >= num_body1_zones)
1350 body_zone_ind -= num_body1_zones;
1352 Eigen::Vector3d zone_orbit_torque,
1356 zone_orbit_torque = (zone_ind
1367 total_zone_torque += (
1377 }
else total_zone_torque += body.
tidal_torque(body_zone_ind,
1385 assert(!std::isnan(inclination_rates[zone_ind]));
1391 ) - reference_periapsis_rate;
1392 assert(!std::isnan(periapsis_rates[zone_ind - 1]));
1399 assert(!std::isnan(reference_periapsis_rate));
1403 angmom_rates[zone_ind - angmom_skipped] = total_zone_torque[2];
1404 assert(!std::isnan(angmom_rates[zone_ind - angmom_skipped]));
1408 total_zone_torque[2],
1409 inclination_rates[zone_ind],
1410 (zone_ind ? periapsis_rates[zone_ind - 1] : 0.0)
1413 #ifdef VERBOSE_DEBUG 1414 std::cerr <<
"Zone " << zone_ind
1415 <<
" torque: " << total_zone_torque
1416 <<
" inclination rate";
1417 std::cerr <<
": " << inclination_rates[zone_ind];
1419 std::cerr <<
" periapsis rate: " 1420 << periapsis_rates[zone_ind - 1];
1422 std::cerr << std::endl;
1424 assert(!std::isnan(total_zone_torque.sum()));
1435 differential_equations[0] *= 6.5 * std::pow(
__semimajor, 5.5);
1437 #ifdef VERBOSE_DEBUG 1438 std::cerr <<
"rates: ";
1444 if(i) std::cerr <<
", ";
1445 std::cerr << differential_equations[i];
1447 std::cerr << std::endl;
1453 template<
typename VALUE_TYPE>
1458 const Eigen::VectorXd &)
const,
1459 std::valarray<VALUE_TYPE> &orbit_rate_deriv,
1464 num_param = orbit_rate_deriv.size() - 1;
1471 orbit_rate_deriv[num_param] += (
1479 for(
unsigned zone_ind = 0; zone_ind < body.
number_zones(); ++zone_ind) {
1480 orbit_rate_deriv[zone_ind+2+offset] =
1486 if(zone_ind+offset > 0)
1487 orbit_rate_deriv[zone_ind + 1 + num_zones + offset] =
1494 if(zone.
locked()) ++locked_zone_count;
1495 else orbit_rate_deriv[
1496 zone_ind + 1 + 2 * num_zones - locked_zone_count
1502 orbit_rate_deriv[num_param] += (
1515 std::valarray<double> &orbit_power_deriv)
const 1517 orbit_power_deriv[0] = 0;
1518 orbit_power_deriv[1] = 0;
1519 orbit_power_deriv[orbit_power_deriv.size() - 1] = 0;
1530 std::valarray<double> &orbit_angmom_gain_deriv
1533 std::valarray<Eigen::Vector3d>
1534 body1_orbit_torque_deriv(orbit_angmom_gain_deriv.size()),
1535 body2_orbit_torque_deriv(orbit_angmom_gain_deriv.size());
1536 body1_orbit_torque_deriv[0] =
1537 body1_orbit_torque_deriv[1] =
1538 body2_orbit_torque_deriv[0] =
1539 body2_orbit_torque_deriv[1] = Eigen::Vector3d(0, 0, 0);
1542 body1_orbit_torque_deriv,
1545 body2_orbit_torque_deriv,
1551 for(
unsigned i = 0; i < orbit_angmom_gain_deriv.size(); ++i)
1552 orbit_angmom_gain_deriv[i] = (
1553 body1_sin_inc * body1_orbit_torque_deriv[i][0]
1555 body1_cos_inc * body1_orbit_torque_deriv[i][2]
1557 body2_sin_inc * body2_orbit_torque_deriv[i][0]
1559 body2_cos_inc * body2_orbit_torque_deriv[i][2]
1563 orbit_angmom_gain_deriv[2] +=(body1_cos_inc * body1_orbit_torque[0]
1565 body1_sin_inc * body1_orbit_torque[2]
1567 body2_cos_inc * body2_orbit_torque[0]
1569 body2_sin_inc * body2_orbit_torque[2]);
1572 #ifdef ENABLE_DERIVATIVES 1573 void BinarySystem::semimajor_jacobian(
1574 const std::valarray<double> &orbit_power_deriv,
1576 double *param_derivs,
1581 orbit_power_deriv[0]);
1582 if(a6p5) param_derivs[0] +=
1585 for(; i < orbit_power_deriv.size() - 1; ++i)
1590 void BinarySystem::eccentricity_jacobian(
1591 const std::valarray<double> &orbit_power_deriv,
1592 const std::valarray<double> &orbit_angmom_gain_deriv,
1594 double *param_derivs,
1600 orbit_power_deriv[0],
1601 orbit_angmom_gain_deriv[0],
1603 if(a6p5) param_derivs[0] /= 6.5 * std::pow(
__semimajor, 5.5);
1606 orbit_power_deriv[1],
1607 orbit_angmom_gain_deriv[1],
1610 for(; i < orbit_power_deriv.size() - 1; ++i)
1612 orbit_angmom_gain_deriv[i]);
1614 orbit_angmom_gain_deriv[i]);
1621 unsigned locked_zone_ind,
1622 double &inclination,
1623 double &periapsis)
const 1628 Eigen::Vector3d orbit_torque_age_deriv = (
1638 unsigned body_zone_ind = 0,
1641 unsigned other_zone_ind = 0;
1642 other_zone_ind<num_zones;
1645 orbit_torque_age_deriv += (
1661 periapsis = (orbit_torque_age_deriv[1]
1666 inclination = (orbit_torque_age_deriv[0] * cos_inc
1674 double above_frac_deriv =
1691 inclination += to_add[0];
1692 periapsis -= to_add[1] / sin_inc;
1695 void BinarySystem::angle_evolution_orbit_deriv(Dissipation::QuantityEntry entry,
1696 double angmom_deriv,
1701 unsigned locked_zone_ind,
1702 double &inclination,
1703 double &periapsis)
const 1713 orbit_torque_deriv = (
1718 inclination = (orbit_torque_deriv[0] * cos_inc
1720 orbit_torque_deriv[2] * sin_inc
1722 (orbit_torque[0] * cos_inc - orbit_torque[2] * sin_inc)
1731 orbit_torque_deriv[1]
1759 }
else to_add -= body.
tidal_torque(zone_ind,
false, entry);
1761 inclination += to_add[0];
1762 periapsis -= to_add[1] / sin_inc;
1765 void BinarySystem::fill_orbit_torque_deriv(
1766 Dissipation::QuantityEntry entry,
1769 std::valarray<Eigen::Vector3d> &orbit_torque_deriv
1779 assert(orbit_torque_deriv.size()
1783 unsigned body_deriv_zone_ind = 0,
1784 num_zones = orbit_torque_deriv.size();
1786 const std::valarray<Eigen::VectorXd> *above_frac_deriv;
1798 unsigned deriv_zone_ind = 0;
1799 deriv_zone_ind < num_zones;
1802 orbit_torque_deriv[deriv_zone_ind] =
1806 body_deriv_zone_ind,
1807 (*above_frac_deriv)[deriv_zone_ind]
1818 zone_ind == body_deriv_zone_ind
1823 orbit_torque_deriv[deriv_zone_ind] +=
1830 ++body_deriv_zone_ind;
1831 if(body_deriv_zone_ind == deriv_body->
number_zones()) {
1832 body_deriv_zone_ind = 0;
1838 void BinarySystem::fill_zone_torque_deriv(
1839 Dissipation::QuantityEntry entry,
1842 std::valarray<Eigen::Vector3d> &zone_torque_deriv
1847 assert(zone_torque_deriv.size() == 4);
1849 assert(zone_torque_deriv.size() == 3);
1852 zone_torque_deriv[0] = (zone_ind == 0
1853 ? Eigen::Vector3d::Zero()
1858 zone_torque_deriv[1] = (nontidal_torque
1861 zone_torque_deriv[2] = (zone_ind < body.
number_zones() - 1
1863 : Eigen::Vector3d::Zero());
1865 zone_torque_deriv[3] = (nontidal_torque
1870 void BinarySystem::inclination_evolution_zone_derivs(
1871 Dissipation::QuantityEntry entry,
1874 double zone_x_torque_above,
1875 double zone_x_torque_below,
1876 const std::valarray<Eigen::Vector3d> &zone_torque_deriv,
1877 const Eigen::Vector3d &orbit_torque,
1878 const std::valarray<Eigen::Vector3d> &orbit_torque_deriv,
1879 const std::valarray<Eigen::VectorXd> &above_frac_deriv,
1882 unsigned locked_zone_ind,
1891 assert(orbit_torque_deriv.size()
1896 unsigned num_zones = orbit_torque_deriv.size();
1897 unsigned global_zone_ind = zone_ind;
1905 deriv_zone_ind < num_zones;
1909 ? result[deriv_zone_ind - 1]
1910 : result[deriv_zone_ind]);
1912 orbit_torque_deriv[deriv_zone_ind][0] * cos_inc
1914 orbit_torque_deriv[deriv_zone_ind][2] * sin_inc
1917 dest -= (above_frac_deriv[deriv_zone_ind][locked_zone_ind]
1919 (zone_x_torque_above - zone_x_torque_below)
1921 zone.angular_momentum());
1922 if(std::abs(static_cast<int>(deriv_zone_ind - global_zone_ind)) <= 1) {
1923 double torque_deriv=
1924 zone_torque_deriv[deriv_zone_ind + 1 - global_zone_ind][0];
1925 if(zone.locked() && deriv_zone_ind == global_zone_ind) {
1927 above_frac * zone_torque_deriv[3][0]
1929 (1.0 - above_frac) * torque_deriv
1930 ) / zone.angular_momentum();
1931 }
else dest -= torque_deriv / zone.angular_momentum();
1935 result[global_zone_ind] -= (
1936 orbit_torque[0] * sin_inc
1938 orbit_torque[2] * cos_inc
1941 result[global_zone_ind] += (
1943 ? (above_frac * zone_x_torque_above
1945 (1.0 - above_frac) * zone_x_torque_below)
1946 : zone_x_torque_below
1947 ) / std::pow(zone.angular_momentum(), 2);
1950 void BinarySystem::periapsis_evolution_zone_derivs(
1951 Dissipation::QuantityEntry entry,
1954 double zone_y_torque_above,
1955 double zone_y_torque_below,
1956 const std::valarray<Eigen::Vector3d> &zone_torque_deriv,
1957 double orbit_y_torque,
1958 const std::valarray<Eigen::Vector3d> &orbit_torque_deriv,
1959 const std::valarray<Eigen::VectorXd> &above_frac_deriv,
1962 unsigned locked_zone_ind,
1973 assert(orbit_torque_deriv.size()
1978 unsigned num_zones = orbit_torque_deriv.size();
1979 unsigned global_zone_ind = zone_ind;
1986 unsigned deriv_zone_ind = 0;
1987 deriv_zone_ind < num_zones;
1992 ? result[deriv_zone_ind - 1]
1993 : result[deriv_zone_ind]);
1994 dest = (-orbit_torque_deriv[deriv_zone_ind][1]
2000 dest += (above_frac_deriv[deriv_zone_ind][locked_zone_ind]
2002 (zone_y_torque_above - zone_y_torque_below)
2004 (sin_inc * zone.angular_momentum()));
2006 std::abs(static_cast<int>(deriv_zone_ind - global_zone_ind))
2010 double torque_deriv =
2011 zone_torque_deriv[deriv_zone_ind + 1 - global_zone_ind][1];
2012 if(zone.locked() && deriv_zone_ind == global_zone_ind) {
2014 above_frac * zone_torque_deriv[3][1]
2016 (1.0 - above_frac) * torque_deriv
2017 ) / (sin_inc * zone.angular_momentum());
2018 }
else dest += (torque_deriv
2020 (sin_inc * zone.angular_momentum()));
2024 if(zone.locked()) zone_torque = (above_frac*zone_y_torque_above
2028 zone_y_torque_below);
2029 else zone_torque = zone_y_torque_below;
2031 result[global_zone_ind] += (
2036 (zone.angular_momentum() * std::pow(sin_inc, 2))
2039 result[global_zone_ind] -=
2040 zone_torque / (std::pow(zone.angular_momentum(), 2) * sin_inc);
2043 void BinarySystem::spin_angmom_evolution_zone_derivs(
2044 Dissipation::QuantityEntry entry,
2047 double zone_z_torque_above,
2048 double zone_z_torque_below,
2049 const std::valarray<Eigen::Vector3d> &zone_torque_deriv,
2050 const std::valarray<Eigen::VectorXd> &above_frac_deriv,
2051 unsigned locked_zone_ind,
2055 unsigned global_zone_ind = zone_ind,
2060 bool zone_is_locked = body.
zone(zone_ind).
locked();
2062 unsigned deriv_zone_ind = 0;
2063 deriv_zone_ind<num_zones;
2067 ? result[deriv_zone_ind - 1]
2068 : result[deriv_zone_ind]);
2070 dest = (above_frac_deriv[deriv_zone_ind][locked_zone_ind]
2072 (zone_z_torque_above - zone_z_torque_below));
2074 if(std::abs(static_cast<int>(deriv_zone_ind
2076 global_zone_ind)) <= 1) {
2077 double torque_deriv =
2078 zone_torque_deriv[deriv_zone_ind + 1 - global_zone_ind][2];
2079 if(zone_is_locked) dest += (above_frac * zone_torque_deriv[3][2]
2081 (1.0 - above_frac) * torque_deriv);
2082 else dest += torque_deriv;
2087 void BinarySystem::binary_jacobian(
double *param_derivs,
2088 double *age_derivs)
const 2095 num_param = 1 + 6 * num_zones - num_locked_zones;
2102 std::valarray<double> orbit_power_deriv(num_param + 1),
2103 orbit_angmom_gain_deriv(num_param + 1);
2106 semimajor_jacobian(orbit_power_deriv,
2107 num_locked_zones == 0,
2110 eccentricity_jacobian(orbit_power_deriv,
2111 orbit_angmom_gain_deriv,
2112 num_locked_zones == 0,
2113 param_derivs + num_param,
2115 unsigned locked_zone_ind = 0;
2117 unsigned body_zone_ind = 0;
2118 static Dissipation::QuantityEntry zone_deriv_list[]={
2123 std::valarray<double> reference_periapsis_param_deriv(num_param);
2124 double reference_periapsis_age_deriv;
2125 const std::valarray<Eigen::VectorXd> *above_frac_deriv[] = {
2130 for(
unsigned zone_ind = 0; zone_ind < num_zones; ++zone_ind) {
2134 double &periapsis_age_deriv = (
2136 ? reference_periapsis_age_deriv
2137 : age_derivs[1 + num_zones + zone_ind]
2139 angle_evolution_age_deriv(*body,
2144 age_derivs[2 + zone_ind],
2145 periapsis_age_deriv);
2147 double *periapsis_row = (
2149 ? &reference_periapsis_param_deriv[0]
2150 : param_derivs+(1 + zone_ind+num_zones) * num_param
2160 param_derivs[(2 + zone_ind) * num_param],
2162 angle_evolution_orbit_deriv(
2169 param_derivs[(2 + zone_ind) * num_param + 1],
2174 zone_torque_below = zone_torque_above,
2176 zone_torque_above += body->
tidal_torque(zone_ind,
true);
2177 zone_torque_below += body->
tidal_torque(zone_ind,
false);
2178 std::valarray<Eigen::Vector3d>
2179 zone_torque_deriv(zone.
locked() ? 4 : 3),
2180 orbit_torque_deriv(num_zones);
2181 unsigned param_offset = (2 + zone_ind) * num_param + 2;
2182 for(
unsigned deriv_ind = 0; deriv_ind < 3; ++deriv_ind) {
2183 Dissipation::QuantityEntry deriv = zone_deriv_list[deriv_ind];
2184 fill_zone_torque_deriv(deriv,
2188 fill_orbit_torque_deriv(deriv,
2190 orbit_torque_deriv);
2191 inclination_evolution_zone_derivs(deriv,
2193 zone_torque_above[0],
2194 zone_torque_below[0],
2198 *(above_frac_deriv[deriv_ind]),
2202 param_derivs + param_offset);
2203 periapsis_evolution_zone_derivs(deriv,
2206 zone_torque_above[1],
2207 zone_torque_below[1],
2211 *(above_frac_deriv[deriv_ind]),
2216 spin_angmom_evolution_zone_derivs(
2220 zone_torque_above[2],
2221 zone_torque_below[2],
2223 *(above_frac_deriv[deriv_ind]),
2225 param_derivs + param_offset + 2 * num_zones - 1
2232 if(zone.
locked()) ++locked_zone_ind;
2239 periapsis_age_deriv -= reference_periapsis_age_deriv;
2240 for(
unsigned i = 0; i < num_param; ++i)
2241 periapsis_row[i] -= reference_periapsis_param_deriv[i];
2249 std::valarray<double> &orbit
2275 unsigned inclination_ind = 2,
2278 for(
short body_ind = 0; body_ind < 2; ++body_ind) {
2281 unsigned zone_ind = 0;
2287 if(body_ind || zone_ind)
2288 orbit[periapsis_ind++] = zone.
periapsis();
2305 unsigned inclination_ind = 0,
2309 unsigned zone_ind = 0;
2314 if(zone_ind) orbit[inclination_ind++] = zone.
inclination();
2315 if(zone_ind) orbit[periapsis_ind++] = zone.
periapsis();
2325 const double *spin_angmom,
2326 const double *inclination,
2327 const double *periapsis,
2332 std::cerr <<
"Initializing BinarySystem." << std::endl;
2333 if(evolution_mode != Core::BINARY) {
2334 assert(std::isnan(semimajor));
2335 assert(std::isnan(eccentricity));
2337 if(evolution_mode == Core::LOCKED_SURFACE_SPIN) {
2338 assert(inclination == NULL);
2339 assert(periapsis == NULL);
2342 std::cerr <<
"Configuring binary with a = " << semimajor
2343 <<
", e = " << eccentricity
2344 <<
" in " << evolution_mode <<
" mode" 2349 evolution_mode == Core::BINARY
2373 std::cerr <<
"Configuring primary." << std::endl;
2383 evolution_mode == Core::LOCKED_SURFACE_SPIN,
2384 evolution_mode != Core::BINARY,
2388 if(evolution_mode == Core::BINARY) {
2391 std::cerr <<
"Configuring secondary." << std::endl;
2399 inclination + offset,
2400 periapsis + offset - 1);
2416 const double *parameters,
2421 const double *spin_angmom, *inclination, *periapsis;
2423 if(evolution_mode == Core::BINARY) {
2424 if(parameters[0] < 0) {
2426 std::cerr <<
"At t = " << age <<
" param: ";
2432 if(i) std::cerr <<
", ";
2433 std::cerr << parameters[i];
2435 std::cerr << std::endl;
2440 semimajor = parameters[0];
2442 semimajor = std::pow(parameters[0], 1.0 / 6.5);
2443 eccentricity = parameters[1];
2444 inclination = parameters+2;
2446 semimajor = eccentricity=Core::NaN;
2447 if(evolution_mode == Core::SINGLE) inclination = parameters;
2448 else inclination = NULL;
2451 if(evolution_mode == Core::LOCKED_SURFACE_SPIN) {
2453 spin_angmom = parameters;
2455 assert(inclination != NULL);
2457 periapsis = inclination+num_zones;
2458 if(evolution_mode == Core::SINGLE) --periapsis;
2459 spin_angmom = periapsis + num_zones - 1;
2472 std::valarray<double> &orbit
2483 Dissipation::QuantityEntry entry,
2484 unsigned deriv_zone_index,
2485 bool secondary_radius)
2487 if(zone_specific(entry)) {
2498 [locked_zone_index];
2501 [locked_zone_index];
2504 [locked_zone_index];
2506 [locked_zone_index];
2516 const double *parameters,
2521 std::cerr <<
"Finding differential equations at t = " << age
2522 <<
" in " << evolution_mode
2523 <<
" mode, with orbit[0] = " << parameters[0]
2526 int status =
configure(
false, age, parameters, evolution_mode);
2527 if(status != GSL_SUCCESS)
return status;
2529 switch(evolution_mode) {
2530 case Core::LOCKED_SURFACE_SPIN :
2532 differential_equations
2536 differential_equations
2542 "Evolution mode other than LOCKED_SURFACE_SPIN, SINGLE or " 2543 "BINARY encountered in " 2544 "BinarySystem::differential_equations!" 2549 #ifdef ENABLE_DERIVATIVES 2550 int BinarySystem::jacobian(
double age,
2551 const double *parameters,
2553 double *param_derivs,
2556 configure(
false, age, parameters, evolution_mode);
2557 switch(evolution_mode) {
2558 case Core::LOCKED_SURFACE_SPIN :
2559 locked_surface_jacobian(param_derivs, age_derivs);
2561 case Core::SINGLE : single_body_jacobian(param_derivs, age_derivs);
2563 case Core::BINARY : binary_jacobian(param_derivs, age_derivs);
2566 "Evolution mode other than LOCKED_SURFACE_SPIN, " 2567 "SINGLE or BINARY encountered in " 2568 "BinarySystem::jacobian!" 2579 if(lock_candidates.empty())
2582 lock_scenario_type lock_scenario;
2584 lock_candidates.size(),
2588 std::cerr <<
"Setting lock scenario: " << std::endl;
2601 unsigned short body_index,
2602 unsigned zone_index,
2607 assert(body_index <= 1);
2609 assert(spin_freq_mult);
2612 body.
lock_zone_spin(zone_index, orbital_freq_mult, spin_freq_mult);
2615 locked_zone_ind = 0;
2616 std::vector<double> spin_angmom(num_zones - num_locked_zones),
2617 inclinations(num_zones),
2618 periapses(num_zones);
2619 for(
unsigned zone_ind = 0; zone_ind < num_zones; ++zone_ind) {
2625 if(zone.
locked()) ++locked_zone_ind;
2626 else spin_angmom[zone_ind-locked_zone_ind] = (
2630 if(zone_ind) periapses[zone_ind - 1] = zone.
periapsis();
2632 assert(locked_zone_ind == num_locked_zones);
2646 std::cerr <<
"Holding lock requires above lock fraction of: " 2647 << above_lock_fraction
2650 if(above_lock_fraction > 0 && above_lock_fraction < 1)
return;
2651 std::vector<double>::iterator check_zone_dest = (
2662 spin_angmom.insert(check_zone_dest, original_angmom);
2665 "Crossing spin-orbit synchronization with unspecified direction!" 2704 std::cerr <<
"Handling secondary death!" << std::endl;
2707 std::valarray<double> spin_angmom(num_zones),
2708 inclination(num_zones - 1),
2709 periapsis(num_zones - 1);
2711 double old_surface_inclination = old_surface_zone.
inclination(),
2712 sin_inc = std::sin(old_surface_inclination),
2713 cos_inc = std::cos(old_surface_inclination),
2725 spin_angmom[0] = angmom;
2728 for(
unsigned zone_ind = 1; zone_ind < num_zones; ++zone_ind) {
2731 inclination[zone_ind - 1]=std::abs(zone.
inclination()
2733 old_surface_inclination
2735 new_surface_inclination);
2736 periapsis[zone_ind - 1] = 0;
2757 unsigned zone_ind = 0;
2768 unsigned zone_ind = 0;
2771 if(locked_zone_index == 0)
break;
2772 else --locked_zone_index;
2805 for(
unsigned i = 0; i < nsteps; ++i) {
2846 unsigned zone_ind = 0;
2856 assert(static_cast<unsigned>(result)
2872 "System contains no dissipative zones! " 2873 "Run as single objects instead!" virtual void add_to_evolution()
Appends the state defined by last configure(), to the evolution.
double __age
The present age of the stellar system in Gyrs.
unsigned locked_zone_index() const
The index of this zone in the list of locked zones (valid only if locked).
void initialize_locks(double sync_precision)
Identify and lock all zones within precision of a lock that can hold the lock at the current configur...
virtual void rewind_evolution(unsigned nsteps)
Discards the last steps from the evolution.
virtual void reset_evolution()
Discards all evolution.
int single_body_differential_equations(double *evolution_rates) const
Differential equations for the rotation of the zones of body 0 if no other body is present...
Eigen::VectorXd __above_lock_fractions_body2_radius_deriv
The derivative of the above lock fractions w.r.t. to the radius of the secondardy.
Function arguments do not satisfy some requirement.
RADIUS
The derivative w.r.t. the radius of the body in .
const std::list< double > & eccentricity_evolution() const
The tabulated evolution of the eccentricity so far.
virtual void add_to_evolution()
Appends the state defined by last configure(), to the evolution.
Eigen::Vector3d __orbit_torque
The torque on the orbit in the coordinate system of the outermost zone of the first body...
const SpinOrbitLockInfo & lock_monitored(bool other=false) const
Return either of the locks being monitored.
void find_locked_zones()
Fills the __locked_zones list.
double angular_momentum() const
The angular momentum of the given zone in .
double __semimajor_rate
The current rate at which the semiamjor axis is changing.
unsigned number_locked_zones() const
The number of zones currently in a spin-orbit lock.
Satisfied when some multiples of the orbit and stellar rotation are synchronized. ...
virtual unsigned expansion_order() const
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.
int binary_differential_equations(double *differential_equations) const
The differential equations for a system with both bodies present.
std::list< double > __eccentricity_evolution
The evolution of the eccentricity recorded by add_to_evolution() so far.
void set_lock_scenario(const lock_scenario_type &lock_scenario)
Lock exactly the specified zones and configure the system.
SPIN_FREQUENCY
The derivative w.r.t. the spin frequency of a dissipating zone.
std::list< double > __semimajor_evolution
The evolution of the semimajor axis recorded by add_to_evolution() so far.
A base class for any body contributing to tidal dissipation.
double tidal_power(unsigned zone_index, bool above, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV) const
Tidal power dissipated in the given zone.
virtual double minimum_separation(bool deriv=false) const
Smallest semimajor axis at which the secondary can survive for the latest system configuration.
int orbital_frequency_multiplier() const
The multiplier in front of the orbital frequency in the lock.
int locked_surface_differential_equations(double *evolution_rates) const
Differential equations for the rotation of the zones of body 0 with the topmost zone rotating with a ...
void fill_above_lock_fractions_deriv()
Fills the __above_lock_fractinos_*_deriv members.
double periapsis(bool evolution_rate=false) const
The argument of periapsis of this zone minus the reference zone's.
virtual const DissipatingZone & zone(unsigned zone_index) const =0
A modifiable reference to one of the body's zones.
double __semimajor
The current semimajor axis.
void check_for_lock(int orbital_freq_mult, int spin_freq_mult, unsigned short body_index, unsigned zone_index, short direction)
Check if a spin-orbit lock can be held and updates the system as necessary to calculate subsequent ev...
void swap_monitored_locks()
std::valarray< Eigen::VectorXd > __above_lock_fractions
The above lock fractinos for the locked zones and their derivatives.
SEMIMAJOR
The derivative w.r.t. the semimajor axis in AU.
void unlock_zone_spin(unsigned zone_index, short direction)
Releases the given zone from a spin-orbit lock.
virtual void reached_critical_age(double)
Change the body as necessary at the given age.
virtual double next_stop_age() const
The next age when the evolution needs to be stopped for a system change.
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 above_lock_fraction(unsigned locked_zone_index, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV, unsigned deriv_zone_index=0, bool secondary_radius=false)
The fraction of an infinitesimal timestep that a zone spends spinning faster than the lock it is in...
Orientations of zones of bodies in a binary system.
const std::list< double > & semimajor_evolution() const
The tabulated evolution of the semimajor axis so far.
lock_scenario_type __selected_lock_scenario
The lock/unlock configuration selected by the last call to.
bool test_synchronized_unlocked_zone(unsigned test_zone_ind)
NUM_DERIVATIVES
The total number of derivatives supported.
double __orbit_power
The rate at which the orbit gains energy due to tides.
void fill_orbit_angmom_gain_deriv(std::valarray< double > &orbit_angmom_gain_deriv) const
Computes the derivatives w.r.t. the evolution quantities of the orbit angular momentum gain...
int differential_equations(double age, const double *parameters, Core::EvolModeType evolution_mode, double *differential_equations)
The differential equation and jacobian for the evolution of the system.
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...
virtual void reset_evolution()
Resets the evolution of the system.
double mass() const
The mass of the body (constant with age).
void add_body_rate_deriv(const DissipatingBody &body, VALUE_TYPE(DissipatingBody::*func)(Dissipation::QuantityEntry, unsigned, const Eigen::VectorXd &) const, std::valarray< VALUE_TYPE > &orbit_rate_deriv, unsigned offset) const
Adds the derivatives of a rate by which the orbit is changing due to tidal interactions with a single...
double age() const
Returns the present age of the system in Gyr.
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...
void fill_locked_surface_orbit(std::valarray< double > &orbit) const
Implements fill_orbit() for LOCKED_SURFACE_SPIN evolution mode.
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()).
virtual void spin_jumped()
Notifies the body that its spin just discontinously jumped.
A layer of a system body for which the tidal bulge is not exactly in phase with the tidal potential...
int spin_frequency_multiplier() const
The multiplier in front of the spin frequency in the lock.
virtual unsigned expansion_order() const
std::valarray< Eigen::VectorXd > __above_lock_fractions_angmom_deriv
The derivatives of the above lock fractions w.r.t. the angular momenta of the zones.
unsigned number_locked_zones() const
How many zones on either body are currently locked.
std::list< double > __semimajor_rate_evolution
The rate at which the semimajor axis evolved at each.
DissipatingBody & __body2
The second body in the system.
virtual void reached_critical_age(double age)
Change the system as necessary at the given age.
short lock_direction() const
void calculate_above_lock_fractions(Eigen::VectorXd &fractions, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV, bool body1_deriv=true)
Calculates the fraction of a timestep above spin-orbit lock for all locked zones. ...
double __eccentricity
The current eccentricity.
virtual double next_stop_age() const
The next age when the evolution needs to be stopped for a change in one of the bodies.
void fill_binary_orbit(std::valarray< double > &orbit) const
Implements fill_orbit() for BINARY evolution mode.
Satisfied when the planet enters below either the roche sphere or the stellar photosphere.
std::list< unsigned > __locked_zones
A list of indices of locked zones.
double __orbit_angmom_gain
The rate at which the orbit gains angular momentum due to tides.
void fill_single_orbit(std::valarray< double > &orbit) const
Implements fill_orbit() for SINGLE evolution mode.
std::list< double > __eccentricity_rate_evolution
The rate at which the eccentricity evolved at each.
Core::EvolModeType __evolution_mode
The evolution mode from the last call to configure();.
virtual void secondary_died()
Update the system to account for the death of the secondary.
Eigen::ColPivHouseholderQR< Eigen::MatrixXd > __above_lock_fractions_decomp
The matrix that defines the problem to solve for __above_lock_fractions.
bool test_lock_scenario(const lock_scenario_type &lock_scenario, bool first_scenario)
Return true iff all locks in the given scenario will be maintained and synchronized unlocked zones wi...
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.
double orbital_frequency(bool semimajor_deriv=false) const
The current orbital frequency [Rad/day] (calculated from the semimajor axis).
void set_evolution_rates(double angular_momentum, double inclination, double periapsis)
Set evolution rates for this zone's properties for storing in the eveloution.
void set_reference_zone_angmom(double reference_angmom)
Defines the angular momentum of the reference zone for single body evolution.
std::valarray< Eigen::VectorXd > __above_lock_fractions_inclination_deriv
The derivatives of the above lock fractions w.r.t. the inclinations of the zones. ...
AGE
The derivative w.r.t. age, excluding the dependence through the body's radius and the moments of iner...
void fill_orbit_power_deriv(std::valarray< double > &orbit_power_deriv) const
Computes the derivatives w.r.t. the evolution quantities of the orbit energy gain.
Defines the BinarySystem class.
virtual void rewind_evolution(unsigned nsteps)
Discards the last steps from the evolution.
lock_scenario_type find_synchronized_zones(double precision)
Return a list of the zone indices that are spin-orbit synchronized with some tidal term (locked or un...
Core::EvolModeType evolution_mode()
The evolution mode of last call to configure().
void update_above_lock_fractions()
Solves for and sets the above lock fractions and their derivatives.
virtual bool locked(int orbital_frequency_multiplier, int spin_frequency_multiplier) const
Should return true iff the given term is presently locked.
double inclination(bool evolution_rate=false) const
The angle between the angular momenta of the zone and the orbit.
NO_DERIV
The quantity itself, undifferentiated.
EvolModeType
The various evolution modes.
ORBITAL_FREQUENCY
The derivative w.r.t. the orbital frequency.
bool explore_lock_scenarios(lock_scenario_type::const_iterator next_synchronized_zone, unsigned num_synchronized_zones, lock_scenario_type &lock_scenario, bool first_scenario=true)
Iterate over all possible lock scenarios until a valid one is found.
std::valarray< Eigen::VectorXd > __above_lock_fractions_inertia_deriv
The derivatives of the above lock fractions w.r.t. the moments of inertia of the zones.
void lock_zone_spin(unsigned zone_index, int orbital_frequency_multiplier, int spin_frequency_multiplier)
double semimajor() const
The current semimajor axis of the system.
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.
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()).
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()).
DissipatingBody & __body1
The first body in the system.
Eigen::VectorXd above_lock_fractions_deriv(Dissipation::QuantityEntry entry, DissipatingBody &body, unsigned zone_index)
Calculates derivatives of the above lock fractions w.r.t. quantities of non-surface zones...
std::valarray< Eigen::VectorXd > __above_lock_fractions_periapsis_deriv
The derivatives of the above lock fractions w.r.t. the periapses of the zones.
A class combining the the outputs of multiple stopping conditions.
double __eccentricity_rate
The current rate at which the eccentricity is changing.
virtual bool dissipative() const =0
Should return true iff the zone has some non-zero dissipation.
unsigned number_zones() const
The total number of zones in both system bodies.
void above_lock_problem_deriv_correction(Dissipation::QuantityEntry entry, bool body1_deriv, Eigen::MatrixXd &matrix, Eigen::VectorXd &rhs) const
Makes corrections to the matrix and RHS to accomodate the given derivative for the linear problem tha...
virtual bool can_lock() const =0
Should return true iff the zone's dissipation is discontinuous at zero frequency. ...
virtual void release_lock(unsigned locked_zone_index, short direction)
Releases the lock to one of the locked zones.
void unlock_all_zones(const std::vector< short > &unlock_directions, const std::vector< double > &original_angmom=std::vector< double >())
Unlock all zones, restoring their original spins if known.
double __orbital_angmom
The current orbital angular momentum.
double eccentricity() const
The current eccentricity of the system.
virtual CombinedStoppingCondition * stopping_conditions()
Conditions detecting the next possible doscontinuity in the evolution.
virtual int configure(bool initialize, double age, double semimajor, double eccentricity, const double *spin_angmom, const double *inclination, const double *periapsis, Core::EvolModeType evolution_mode)
Sets the current state of the system.
double __orbital_energy
The current orbital energy.
void fill_orbit_torque_and_power()
Update the values of ::__orbit_power, ::__orbit_torque, and ::__orbit_angmom_gain.
void describe_lock_scenario(std::ostream &os, const lock_scenario_type &lock_scenario, const std::vector< bool > passed, bool add_header=false)
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.
Core::EvolModeType fill_orbit(std::valarray< double > &orbit) const
Fills an array with the parameters expected by differential_equations() and jacobian(), returning the evolution mode.
double spin_frequency() const
The spin frequency of the given zone.
Defines a lock between the spin of a dissipating body and the orbit.
virtual unsigned number_zones() const =0
The number of zones the body consists of.