13 const alglib::real_1d_array &eccentricities,
14 const alglib::real_1d_array &expected_semimajor_rate,
15 const alglib::real_1d_array &predicted_semimajor_rate,
16 const alglib::real_1d_array &expected_eccentricity_rate,
17 const alglib::real_1d_array &predicted_eccentricity_rate
20 std::cout << std::setw(25) <<
"eccentricity" 21 << std::setw(25) <<
"semimajor_rate" 22 << std::setw(25) <<
"expected_semimajor_rate" 23 << std::setw(25) <<
"eccentricity_rate" 24 << std::setw(25) <<
"expected_ecc_rate" 28 e_index < eccentricities.length();
31 std::cout << std::setw(25) << eccentricities[e_index]
33 << predicted_semimajor_rate[e_index]
35 << expected_semimajor_rate[e_index]
37 << predicted_eccentricity_rate[e_index]
39 << expected_eccentricity_rate[e_index]
47 int orbital_frequency_multiplier,
48 int spin_frequency_multiplier,
53 double e2 = std::pow(eccentricity, 2);
55 if(orbital_frequency_multiplier == 2 && spin_frequency_multiplier == 2)
56 return 1.0 - 5.0 * e2;
58 if(orbital_frequency_multiplier == 1 && spin_frequency_multiplier == 0)
59 return 3.0 / 4.0 * e2;
61 if(orbital_frequency_multiplier == 1 && spin_frequency_multiplier == 2)
62 return 1.0 / 8.0 * e2;
64 if(orbital_frequency_multiplier == 3 && spin_frequency_multiplier == 2)
65 return 147.0 / 8.0 * e2;
71 int orbital_frequency_multiplier,
72 int spin_frequency_multiplier
76 if(orbital_frequency_multiplier == 2 && spin_frequency_multiplier == 2)
79 if(orbital_frequency_multiplier == 1 && spin_frequency_multiplier == 0)
82 if(orbital_frequency_multiplier == 1 && spin_frequency_multiplier == 2)
85 if(orbital_frequency_multiplier == 3 && spin_frequency_multiplier == 2)
92 const alglib::real_1d_array& x,
93 const alglib::real_1d_array& y1,
94 const alglib::real_1d_array& y2,
95 unsigned agreement_order,
97 const std::string &description
100 alglib::real_1d_array difference;
101 difference.setlength(x.length());
102 double min_difference = Core::Inf,
103 max_difference = -Core::Inf,
105 for(
unsigned i = 0; i < x.length(); ++i) {
106 difference[i] = y2[i] - y1[i];
107 min_difference = std::min(difference[i], min_difference);
108 max_difference = std::max(difference[i], max_difference);
109 y_scale = std::max(y_scale,
110 std::max(std::abs(y1[i]), std::abs(y2[i])));
114 std::max(std::abs(max_difference), std::abs(min_difference))
119 alglib::ae_int_t fit_info;
120 alglib::barycentricinterpolant interp;
121 alglib::polynomialfitreport fit_report;
122 alglib::polynomialfit(x,
129 double max_allowed_residual = 1e-12 * (max_difference - min_difference);
131 std::ostringstream message;
132 message << description
133 <<
" too large residual from fit to difference: " 134 << fit_report.maxerror
136 << max_allowed_residual;
138 TEST_ASSERT_MSG(fit_report.maxerror <= max_allowed_residual,
139 message.str().c_str());
141 alglib::real_1d_array coefficients;
143 alglib::polynomialbar2pow(interp, coefficients);
145 double max_allowed_term = 0.0,
146 max_abs_x = std::max(std::abs(x[0]), x[x.length() - 1]);
147 for(
unsigned power = 0; power < coefficients.length(); ++power)
148 max_allowed_term = std::max(
150 std::abs(coefficients[power]) * std::pow(max_abs_x, power)
152 max_allowed_term *= 1e-8;
154 for(
unsigned power = 0; power <= agreement_order; ++power) {
155 double max_abs_term_value = (std::abs(coefficients[power])
157 std::pow(max_abs_x, power));
159 message << description
160 <<
" x^" << power <<
" coefficient too large: |" 161 << coefficients[power]
163 << max_abs_x <<
"^" << power
165 << max_abs_term_value
169 TEST_ASSERT_MSG(max_abs_term_value <= max_allowed_term,
170 message.str().c_str());
182 const double MAX_ECCENTRICITY = 0.1;
183 const unsigned NUM_ECCENTRICITIES = 100;
184 const double ECCENTRICITY_STEP = (
185 MAX_ECCENTRICITY / (NUM_ECCENTRICITIES - 1)
188 alglib::real_1d_array eccentricities,
189 expected_semimajor_rate,
190 predicted_semimajor_rate,
191 expected_eccentricity_rate,
192 predicted_eccentricity_rate;
193 eccentricities.setlength(NUM_ECCENTRICITIES);
194 expected_semimajor_rate.setlength(NUM_ECCENTRICITIES);
195 predicted_semimajor_rate.setlength(NUM_ECCENTRICITIES);
196 expected_eccentricity_rate.setlength(NUM_ECCENTRICITIES);
197 predicted_eccentricity_rate.setlength(NUM_ECCENTRICITIES);
199 eccentricities[0] = 0.0;
200 for(
unsigned e_index = 1; e_index < NUM_ECCENTRICITIES; ++e_index)
201 eccentricities[e_index] = (eccentricities[e_index - 1]
205 std::valarray<double> one_poly(1.0, 1);
207 int orbital_frequency_multiplier = 0;
208 orbital_frequency_multiplier <= 4;
209 ++orbital_frequency_multiplier
212 int spin_frequency_multiplier = 0;
213 spin_frequency_multiplier <= 4;
214 ++spin_frequency_multiplier
218 orbital_frequency_multiplier,
219 spin_frequency_multiplier,
230 std::valarray<double> parameters(0.0, 7);
231 std::valarray<double> evolution_rates(parameters.size());
232 parameters[0] = 10.0;
239 double common_rate_factor = (
251 for(
double semimajor = 2.0; semimajor <= 10.0; semimajor += 1.0) {
253 double mean_motion = std::sqrt(
262 double rate_factor = (
265 (mean_motion * std::pow(semimajor, 8))
268 double primary_spin_frequency = 0.0;
269 primary_spin_frequency <= 5.0 * mean_motion;
270 primary_spin_frequency += 0.2 * mean_motion
274 unsigned e_index = 0;
275 e_index < NUM_ECCENTRICITIES;
280 test_e = eccentricities[e_index];
281 parameters[0] = std::pow(semimajor, 6.5);
282 parameters[1] = test_e;
286 &(evolution_rates[0]));
287 expected_semimajor_rate[e_index] = (
288 6.5 * std::pow(semimajor, 6.5)
293 orbital_frequency_multiplier,
294 spin_frequency_multiplier,
298 expected_eccentricity_rate[e_index] = (
304 orbital_frequency_multiplier,
305 spin_frequency_multiplier
308 predicted_semimajor_rate[e_index] = evolution_rates[0];
309 predicted_eccentricity_rate[e_index] =
313 std::ostringstream message;
314 message <<
"orbital freq. mult. = " 315 << orbital_frequency_multiplier
316 <<
", spin freq. mult. = " 317 << spin_frequency_multiplier
318 <<
" for a = " << semimajor
319 <<
", W* = " << primary_spin_frequency;
320 std::cout << message.str() << std::endl;
323 expected_semimajor_rate,
324 predicted_semimajor_rate,
325 expected_eccentricity_rate,
326 predicted_eccentricity_rate);
359 const double MAX_ECCENTRICITY = 0.9;
360 const unsigned NUM_ECCENTRICITIES = 100;
361 const double ECCENTRICITY_STEP = (
362 MAX_ECCENTRICITY / (NUM_ECCENTRICITIES - 1)
364 const double a = 10.0;
365 const double age = 1.0;
368 StellarEvolution::make_no_evolution();
382 std::valarray<double> parameters(0.0, 10),
383 rough_rates(parameters.size()),
384 fine_rates(parameters.size());
394 std::cout << std::setw(25) <<
"e_order" 395 << std::setw(25) <<
"e" 396 << std::setw(25) <<
"rough_a_rate" 397 << std::setw(25) <<
"fine_a_rate" 398 << std::setw(25) <<
"rough_e_rate" 399 << std::setw(25) <<
"fine_e_rate" 400 << std::setw(25) <<
"rough_inc_rate" 401 << std::setw(25) <<
"fine_inc_rate" 402 << std::setw(25) <<
"rough_spin_rate" 403 << std::setw(25) <<
"fine_spin_rate" 407 for(
unsigned e_order = 5; e_order <= 100; e_order+=5) {
408 for(
double e = 0.0; e <= MAX_ECCENTRICITY; e += ECCENTRICITY_STEP) {
425 std::cout << std::setw(25) << e_order
426 << std::setw(25) << e
427 << std::setw(25) << rough_rates[0]
428 << std::setw(25) << fine_rates[0]
429 << std::setw(25) << rough_rates[1]
430 << std::setw(25) << fine_rates[1]
431 << std::setw(25) << rough_rates[2]
432 << std::setw(25) << fine_rates[2]
433 << std::setw(25) << rough_rates[7]
434 << std::setw(25) << fine_rates[7]
Implements a StellarEvolution based on polynomial evolution quantities.
const double MIN_AGE
Most tests start at this age in Gyr.
void detect_saturation()
Sets the saturation based on the currently configured spin frequency.
test_DifferentialEquations()
Create the test suite.
A skumanich wind body with a single zone dissipative to only a single tidal term. ...
double zahn77_semimajor_rate_coef(int orbital_frequency_multiplier, int spin_frequency_multiplier, double eccentricity) const
The Zahn (1977) coefficient for the semimajor evolution rate that corresponds to the given tidal term...
void test_aligned_equations()
Test the a & e differential equations for aligned orbit.
Single zone non-evolving planets with huge dissipation, so they always remain locked to the disk...
Evolve::DissipatingZone & zone(unsigned zone_index)
See Evolve::DissipatingBody::zone().
const double MAX_AGE
Most tests end at this age in Gyr.
Orientations of zones of bodies in a binary system.
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.
double mass() const
The mass of the body (constant with age).
const double solar_radius
Radius of the sun [m].
void check_agreement(const alglib::real_1d_array &x, const alglib::real_1d_array &y1, const alglib::real_1d_array &y2, unsigned agreement_order, unsigned max_order, const std::string &description)
Check if two given dependencies on x agree up to a given order in x.
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.
double zahn77_eccentricity_rate_coef(int orbital_frequency_multiplier, int spin_frequency_multiplier) const
Same as zahn77_semimajor_rate_coef() but for the eccentricity evolution.
Unit tests that check the differential equations for eccentricity and semimajor against analytic expr...
void test_error_estimate()
Test the error estimate of the differential equations.
virtual void change_expansion_order(unsigned new_expansion_order)
Change the tidal potential expansion order for all dissipative zones.
Star::InterpolatedEvolutionStar * make_const_lag_star(const StellarEvolution::Interpolator &evolution, double wind_strength, double wind_sat_freq, double coupling_timescale, double phase_lag)
Create a star with the given parameters with a constant phase lag.
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.
Describes a system of two bodies orbiting each other.
void output_rates(const alglib::real_1d_array &eccentricities, const alglib::real_1d_array &expected_semimajor_rate, const alglib::real_1d_array &predicted_semimajor_rate, const alglib::real_1d_array &expected_eccentricity_rate, const alglib::real_1d_array &predicted_eccentricity_rate) const
Output the predicted/expected semiamjor and eccentricity evolution rates to stdout.
const double G
Gravitational constant in SI.