14 const double zero = 0.0;
15 const double one = 1.0;
30 os <<
"SEMIMAJOR";
break;
32 os <<
"ECCENTRICITY";
break;
34 os <<
"CONV_INCLINATION";
break;
36 os <<
"RAD_INCLINATION";
break;
38 os <<
"CONV_PERIAPSIS";
break;
40 os <<
"RAD_PERIAPSIS";
break;
42 os <<
"CONV_ANGMOM";
break;
44 os <<
"RAD_ANGMOM";
break;
55 std::valarray<double>(Core::NaN, 2),
61 std::valarray<double>(),
67 std::valarray<double>(1.0, 1),
73 std::valarray<double>(2.0, 1),
79 std::valarray<double>(200.0, 1),
96 const double suppression_factor = 0.01;
98 std::vector<double> breaks(2);
99 breaks[0] = min_frequency;
100 breaks[1] = max_frequency;
102 std::vector<double> powerlaw_indices(3);
103 powerlaw_indices[0] = (
104 std::log(suppression_factor)
106 std::log(1.0 - decay_scale / min_frequency)
108 powerlaw_indices[1] = 0.0;
109 powerlaw_indices[2] = (
110 std::log(suppression_factor)
112 std::log(1.0 + decay_scale / max_frequency)
126 std::vector<double>(),
128 std::vector<double>(1, 0.0),
134 double wind_strength,
135 double wind_sat_freq,
136 double coupling_timescale,
137 double min_frequency,
138 double max_frequency,
159 const double *initial_Lstar,
161 double secondary_mass,
164 double secondary_radius,
166 double max_step_factor)
174 secondary_mass *= Mjup_to_Msun;
175 secondary_radius *= Rjup_to_Rsun;
177 if(std::isnan(tsecondary)) tsecondary = tdisk;
180 (secondary_mass ? secondary_radius : 0.0));
203 double zeros[] = {0.0, 0.0};
205 if(tdisk <= TSTART) {
206 if(tsecondary <= TSTART) {
233 Core::LOCKED_SURFACE_SPIN);
237 double initial_inclinations[] = {initial_incl, 0.0, 0.0};
243 initial_inclinations,
249 (max_age - __system->age()) * max_step_factor,
250 std::list<double>());
256 std::vector< const std::list<double> *>
257 tabulated_real_quantities(NUM_REAL_QUANTITIES);
270 tabulated_real_quantities[RAD_INCLINATION] =
273 tabulated_real_quantities[RAD_PERIAPSIS] =
276 tabulated_real_quantities[RAD_ANGMOM] = &(
281 tabulated_real_quantities[RAD_INCLINATION] = NULL;
282 tabulated_real_quantities[RAD_PERIAPSIS] = NULL;
283 tabulated_real_quantities[RAD_ANGMOM] = NULL;
287 tabulated_real_quantities[CONV_INCLINATION] = &(
291 tabulated_real_quantities[CONV_PERIAPSIS] = &(
295 tabulated_real_quantities[CONV_ANGMOM] = &(
300 return tabulated_real_quantities;
304 const std::vector<
const std::list<double> * > &
305 tabulated_real_quantities,
306 std::vector<const Core::OneArgumentDiffFunction *>
307 expected_real_quantities,
315 const std::list<Core::EvolModeType> &tabulated_modes =
318 const std::list<bool> *tabulated_wind_sat =
321 unsigned num_ages = tabulated_real_quantities[
AGE]->size();
323 std::ostringstream msg_start;
324 std::ostringstream msg;
326 msg.setf(std::ios_base::scientific);
327 msg_start.precision(16);
328 msg_start.setf(std::ios_base::scientific);
329 msg << msg_start.str()
331 <<
" tabulated ages, ";
332 bool all_same_size =
true;
334 for(
unsigned q = 0; q <
AGE; ++q) {
335 if(tabulated_real_quantities[q]) {
336 msg << tabulated_real_quantities[q]->size()
343 tabulated_real_quantities[q]->size() == num_ages
348 msg << tabulated_modes.size() <<
" tabulated modes";
350 all_same_size = (all_same_size
352 tabulated_modes.size() == num_ages);
355 << tabulated_wind_sat->size()
356 <<
" tabulated wind saturations";
357 all_same_size = (all_same_size
359 tabulated_wind_sat->size() == num_ages);
363 if(debug_mode) std::cout << msg.str() << std::endl;
364 TEST_ASSERT_MSG(all_same_size, msg.str().c_str());
367 msg <<
"Expected age range: " << min_age <<
" to " << max_age
368 <<
", actual age range: " << tabulated_real_quantities[AGE]->front()
369 <<
" to " << tabulated_real_quantities[AGE]->back();
370 if(debug_mode) std::cout << msg.str() << std::endl;
373 tabulated_real_quantities[AGE]->front() == min_age
375 tabulated_real_quantities[AGE]->back() == max_age
380 std::vector< std::list<double>::const_iterator >
381 real_tabulated_iter(AGE);
382 for(
unsigned q = 0; q < AGE; ++q)
383 if(tabulated_real_quantities[q])
384 real_tabulated_iter[q] = tabulated_real_quantities[q]->begin();
385 std::list<Core::EvolModeType>::const_iterator
386 tabulated_mode_iter = tabulated_modes.begin();
387 std::list<bool>::const_iterator tabulated_wind_sat_iter;
389 tabulated_wind_sat_iter = tabulated_wind_sat->begin();
390 double last_checked_age = Core::NaN;
393 std::list<double>::const_iterator
394 age_i = tabulated_real_quantities[AGE]->begin();
395 age_i != tabulated_real_quantities[AGE]->end();
398 std::vector<double> expected_real_values(AGE);
399 for(
unsigned q = 0; q < AGE; ++q) {
400 expected_real_values[q] =
401 (*(expected_real_quantities[q]))(*age_i);
404 bool expected_wind_sat = expected_wind_mode(*age_i);
406 std::ostringstream age_msg_start;
407 age_msg_start.precision(16);
408 age_msg_start.setf(std::ios_base::scientific);
409 age_msg_start << msg_start.str()
410 <<
"age = " << *age_i
411 <<
", mode = " << *tabulated_mode_iter;
413 age_msg_start <<
", wind is ";
414 if(!(*tabulated_wind_sat_iter)) age_msg_start <<
" not ";
415 age_msg_start <<
"saturated";
417 for(
unsigned q = 0; q < AGE; ++q)
418 if(tabulated_real_quantities[q])
419 age_msg_start <<
", " 422 << *real_tabulated_iter[q];
425 msg << age_msg_start.str() <<
" age is out of range.";
426 TEST_ASSERT_MSG(*age_i >= min_age && *age_i <= max_age,
429 std::list<double>::const_iterator next_age_i = age_i;
433 next_age_i != tabulated_real_quantities[AGE]->end()
435 std::abs(*next_age_i - *age_i) < 1e-5
441 skipped = (*age_i == last_checked_age);
444 msg << age_msg_start.str() <<
": mode is not " 445 << expected_mode <<
", but " << *tabulated_mode_iter;
447 if(debug_mode) std::cout << msg.str() << std::endl;
448 if(!skipped && expected_mode != *tabulated_mode_iter) {
449 if(can_skip) skipped =
true;
450 else TEST_ASSERT_MSG(
false, msg.str().c_str());
455 msg << age_msg_start.str() <<
": wind is ";
456 if(!(*tabulated_wind_sat_iter)) msg <<
" not ";
457 msg <<
"saturated, but should";
458 if(!expected_wind_sat) msg <<
" not ";
460 if(debug_mode) std::cout << msg.str() << std::endl;
461 if(!skipped && expected_wind_sat != *tabulated_wind_sat_iter) {
462 if(can_skip) skipped =
true;
463 else TEST_ASSERT_MSG(
false, msg.str().c_str());
477 for(
unsigned q = 0; q < AGE; ++q) {
478 if(!tabulated_real_quantities[q])
continue;
480 msg << age_msg_start.str() <<
": " 483 << expected_real_values[q]
485 << *real_tabulated_iter[q]
487 << (*real_tabulated_iter[q]) - expected_real_values[q];
488 if(debug_mode) std::cout << msg.str() << std::endl;
493 expected_real_values[q],
501 TEST_ASSERT_MSG(
false, msg.str().c_str());
505 last_checked_age = *age_i;
507 std::cerr <<
"Skipped checks for t = " << *age_i
509 for(
unsigned q = 0; q < AGE; ++q)
510 if(tabulated_real_quantities[q])
511 ++(real_tabulated_iter[q]);
512 if(
__star) ++tabulated_wind_sat_iter;
513 ++tabulated_mode_iter;
519 double *initial_Lstar,
521 double wind_sat_freq,
522 double core_env_coupling_time,
523 std::vector<const Core::OneArgumentDiffFunction *>
524 &expected_real_quantities,
531 single_mode.
add_break(TSTART, Core::SINGLE);
532 binary_mode.
add_break(TSTART, Core::BINARY);
537 core_env_coupling_time,
547 expected_real_quantities[
SEMIMAJOR] = &nan_func;
549 expected_real_quantities[CONV_INCLINATION] = &zero_func;
550 expected_real_quantities[RAD_INCLINATION] = &zero_func;
551 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
552 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
555 expected_real_quantities,
562 if(initial_Lstar[0] == 0)
return;
564 for(
double phase_lag = 0.0; phase_lag < 1.5; phase_lag += 1.0)
566 double mplanet = 0.0;
567 mplanet < 1.5 - phase_lag;
577 core_env_coupling_time,
588 expected_real_quantities[
SEMIMAJOR] = &one_func;
591 expected_real_quantities,
609 expected_real_quantities[
SEMIMAJOR] = &two_hundred_func;
611 expected_real_quantities,
628 std::vector<const Core::OneArgumentDiffFunction *>
631 double secondary_mass,
635 std::vector<const Core::OneArgumentDiffFunction *>
636 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
638 double msecondary_si = (secondary_mass
651 msecondary_si / mprimary_si
674 a6p5_offset = std::pow(2.0, 6.5) + 6.5 * alpha;
675 a0 = std::pow(a6p5_offset, 1.0 / 6.5);
678 a6p5_offset = std::pow(a0, 6.5);
681 std::valarray<double> a6p5_poly_coef(2);
682 a6p5_poly_coef[0] = a6p5_offset;
683 a6p5_poly_coef[1] = (decaying ? -1.0 : 1.0) * 6.5 * alpha;
699 (decaying ? 0.0 : -1e5) - std::sqrt(a0),
711 expected_real_quantities[CONV_INCLINATION] = &zero_func;
712 expected_real_quantities[RAD_INCLINATION] = &zero_func;
713 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
714 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
720 expected_real_quantities[RAD_ANGMOM] = &zero_func;
722 return expected_real_quantities;
726 std::vector<const Core::OneArgumentDiffFunction *>
727 test_OrbitSolver::calculate_expected_disklocked_to_fast_to_locked(
733 bool include_disk_lock
736 const double Q = std::pow(10.0, lgQ),
766 Core::AstroConst::solar_mass
777 Core::AstroConst::solar_mass
787 a6p5_offset = (std::pow(async, 6.5)
789 6.5 * alpha * tsync),
790 a_formation=std::pow(
791 a6p5_offset + 6.5 * alpha * tdisk,
797 (std::sqrt(a_formation) - std::sqrt(async))
799 (beta * (std::pow(async, -1.5)
801 0.5 * std::pow(a_formation, -1.5)))
803 wdisk = 0.5 * beta / std::pow(a_formation, 1.5),
804 wlocked = beta / std::pow(async, 1.5);
806 std::valarray<double> a6p5_poly_coef(2);
807 a6p5_poly_coef[0] = a6p5_offset;
808 a6p5_poly_coef[1] = 6.5 * alpha;
816 std::valarray<double>(Ic * wdisk, 1),
821 std::valarray<double>(Ic * wlocked, 1),
826 std::valarray<double>(Core::NaN, 2),
831 std::valarray<double>(async, 1),
836 std::valarray<double>(),
841 std::valarray<double>(),
862 -Ic * wdisk / Lscale - std::sqrt(a_formation), 0
879 if(include_disk_lock) {
883 zero_quantity = &zero_func;
885 zero_quantity = zero_e;
896 std::vector<const Core::OneArgumentDiffFunction *>
897 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
899 expected_real_quantities[
SEMIMAJOR] = a_evol;
901 expected_real_quantities[CONV_INCLINATION] = zero_quantity;
902 expected_real_quantities[RAD_INCLINATION] = zero_quantity;
903 expected_real_quantities[CONV_PERIAPSIS] = zero_quantity;
904 expected_real_quantities[RAD_PERIAPSIS] = zero_quantity;
905 expected_real_quantities[CONV_ANGMOM] = Lconv_evol;
906 expected_real_quantities[RAD_ANGMOM] = zero_quantity;
908 return expected_real_quantities;
911 std::vector<const Core::OneArgumentDiffFunction *>
912 test_OrbitSolver::calculate_expected_polar_1_0(
double tdisk,
917 double aorb = std::pow(
937 std::valarray<double>(Core::NaN, 1),
942 std::valarray<double>(aorb, 1),
947 std::valarray<double>(),
952 std::valarray<double>(),
957 std::valarray<double>(M_PI / 2.0, 1),
982 conv_incl_evol->
add_piece(disk_zero_evol);
985 rad_incl_evol->
add_piece(disk_zero_evol);
988 std::vector<const Core::OneArgumentDiffFunction *>
989 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
991 expected_real_quantities[
SEMIMAJOR] = a_evol;
993 expected_real_quantities[CONV_INCLINATION] = conv_incl_evol;
994 expected_real_quantities[RAD_INCLINATION] = rad_incl_evol;
995 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
996 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
997 expected_real_quantities[CONV_ANGMOM] =
999 std::valarray<double>(wstar, 1),
1004 expected_real_quantities[CONV_ANGMOM]
1006 expected_real_quantities[RAD_ANGMOM] = &one_func;
1008 return expected_real_quantities;
1011 std::vector<const Core::OneArgumentDiffFunction *>
1012 test_OrbitSolver::calculate_expected_polar_2_0(
double tdisk,
1016 double &lconv_decay_rate,
1019 semimajor = std::pow(
1036 lconv_decay_rate = (
1054 std::pow(Core::AstroConst::solar_radius, 5)
1060 std::pow(Core::AstroConst::solar_radius, 2)
1084 semimajor * semimajor
1088 double lconv_offset = lconv_decay_rate * tdisk;
1090 std::valarray<double> spindown_coef(2);
1091 spindown_coef[0] = wstar + lconv_decay_rate * tdisk;
1092 spindown_coef[1] = - lconv_decay_rate;
1094 std::valarray<double> conv_cosinc_numer_coef(3),
1095 conv_cosinc_denom_coef(2),
1096 rad_cosinc_numer_coef(3),
1097 rad_cosinc_denom_coef(3);
1098 conv_cosinc_numer_coef[0] = - (
1099 (2.0 * wstar + lconv_offset) * lconv_offset
1101 conv_cosinc_numer_coef[1] = 2.0 * wstar * lconv_decay_rate;
1102 conv_cosinc_numer_coef[2] = -std::pow(lconv_decay_rate, 2);
1104 conv_cosinc_denom_coef[0] = 2.0 * lorb * (wstar + lconv_offset);
1105 conv_cosinc_denom_coef[1] = -2.0 * lconv_decay_rate * lorb;
1107 conv_cosinc_numer_coef[0] += conv_cosinc_denom_coef[0];
1108 conv_cosinc_numer_coef[1] += conv_cosinc_denom_coef[1];
1110 rad_cosinc_numer_coef[0] = - 2.0 * lorb * lconv_decay_rate * tdisk;
1111 rad_cosinc_numer_coef[1] = 2.0 * lorb * lconv_decay_rate;
1113 rad_cosinc_denom_coef[0] = (2.0 * lorb * lorb
1115 2.0 * wstar * lconv_decay_rate * tdisk
1117 std::pow(lconv_decay_rate * tdisk, 2));
1118 rad_cosinc_denom_coef[1] =
1119 2.0 * lconv_decay_rate * (worb + lconv_decay_rate * tdisk);
1120 rad_cosinc_denom_coef[2] = - std::pow(lconv_decay_rate, 2);
1122 rad_cosinc_numer_coef += rad_cosinc_denom_coef;
1127 std::valarray<double>(Core::NaN, 1),
1133 std::valarray<double>(semimajor, 1),
1139 std::valarray<double>(),
1145 std::valarray<double>(2.0, 1),
1149 *conv_cosinc_binary_numer =
1151 conv_cosinc_numer_coef,
1154 *conv_cosinc_binary_denom =
1156 conv_cosinc_denom_coef,
1160 *rad_cosinc_binary_numer =
1162 rad_cosinc_numer_coef,
1166 *rad_cosinc_binary_denom =
1168 rad_cosinc_denom_coef,
1174 std::valarray<double>(wstar, 1),
1196 conv_cosinc_binary_numer,
1197 conv_cosinc_binary_denom
1201 rad_cosinc_binary_numer,
1202 rad_cosinc_binary_denom
1223 conv_cosinc_evol->
add_piece(disk_cosinc_evol);
1224 conv_cosinc_evol->
add_piece(conv_cosinc_binary);
1226 rad_cosinc_evol->
add_piece(disk_cosinc_evol);
1227 rad_cosinc_evol->
add_piece(rad_cosinc_binary);
1232 std::vector<const Core::OneArgumentDiffFunction *>
1233 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1235 expected_real_quantities[
SEMIMAJOR] = a_evol;
1237 expected_real_quantities[CONV_INCLINATION] = conv_cosinc_evol;
1238 expected_real_quantities[RAD_INCLINATION] = rad_cosinc_evol;
1239 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1240 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1241 expected_real_quantities[CONV_ANGMOM] = lconv_evol;
1242 expected_real_quantities[RAD_ANGMOM] = &one_func;
1244 return expected_real_quantities;
1247 std::vector<const Core::OneArgumentDiffFunction *>
1248 test_OrbitSolver::calculate_expected_oblique_m_0(
1253 double initial_wstar,
1258 assert(m == 1 || m == 2);
1259 double aorb = std::pow(
1276 double lorb = (Mjup_to_Msun
1278 (1.0 + Mjup_to_Msun)
1284 double ltot = std::sqrt(
1285 std::pow(initial_wstar, 2)
1287 2.0 * initial_wstar * lorb * std::cos(initial_inc)
1292 min_wstar = ltot - lorb;
1294 double linear_quantity_rate = (
1312 std::pow(Core::AstroConst::solar_radius, 5)
1318 std::pow(Core::AstroConst::solar_radius, 2)
1330 std::valarray<double>(Core::NaN, 1),
1338 std::valarray<double>(aorb, 1),
1346 std::valarray<double>(),
1371 linear_quantity_rate
1380 linear_quantity_rate / 2.0
1398 std::vector<const Core::OneArgumentDiffFunction *>
1399 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1400 expected_real_quantities[
SEMIMAJOR] = a_evol;
1402 expected_real_quantities[CONV_INCLINATION] = conv_obliq_evol;
1403 expected_real_quantities[RAD_INCLINATION] = rad_obliq_evol;
1404 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1405 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1406 expected_real_quantities[CONV_ANGMOM] = lconv_evol;
1407 expected_real_quantities[RAD_ANGMOM] = &one_func;
1409 return expected_real_quantities;
1412 void test_OrbitSolver::test_disk_locked_no_stellar_evolution()
1416 StellarEvolution::make_no_evolution();
1423 expected_evol_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
1426 expected_wind_mode.
add_break(TSTART,
false);
1428 std::vector<const Core::OneArgumentDiffFunction *>
1429 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1430 expected_real_quantities[
SEMIMAJOR] = &nan_func;
1432 expected_real_quantities[CONV_INCLINATION] = &zero_func;
1433 expected_real_quantities[RAD_INCLINATION] = &zero_func;
1434 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1435 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1436 expected_real_quantities[CONV_ANGMOM] = &one_func;
1437 expected_real_quantities[RAD_ANGMOM] = &one_func;
1441 expected_real_quantities,
1453 -std::exp(TSTART/2.0),
1457 expected_real_quantities,
1463 delete expected_real_quantities[RAD_ANGMOM];
1466 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")+
1468 }
catch (std::exception &ex) {
1469 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")+
1470 ex.what()).c_str());
1474 void test_OrbitSolver::test_disk_locked_with_stellar_evolution()
1478 StellarEvolution::make_linear_I_evolution();
1483 expected_evol_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
1486 expected_wind_mode.
add_break(TSTART,
false);
1488 std::valarray<double> temp_array=std::valarray<double>(1.0, 2);
1495 std::vector<const Core::OneArgumentDiffFunction *>
1496 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1497 expected_real_quantities[
SEMIMAJOR] = &nan_func;
1499 expected_real_quantities[CONV_INCLINATION] = &zero_func;
1500 expected_real_quantities[RAD_INCLINATION] = &zero_func;
1501 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1502 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1503 expected_real_quantities[CONV_ANGMOM] =
1505 std::valarray<double>(1.0, 2),
1509 expected_real_quantities[RAD_ANGMOM] =
1512 double initial_Lrad = TSTART - 1 + std::exp(-TSTART / 2.0);
1518 expected_real_quantities,
1524 delete expected_real_quantities[CONV_ANGMOM];
1525 delete expected_real_quantities[RAD_ANGMOM];
1532 std::valarray< std::valarray<double> > Ic_arr(
1533 std::valarray<double>(1.0, 1),
1536 Ic_arr[1][0]=-1.0/6.0;
1539 std::valarray< std::valarray<double> >(
1540 std::valarray<double>(1.0, 1),
1544 std::valarray< std::valarray<double> >(
1545 std::valarray<double>(1.0/6.0, 1),
1548 std::valarray< std::valarray<double> >(
1549 std::valarray<double>(0.5, 1),
1552 std::valarray< std::valarray<double> >(
1553 std::valarray<double>(1.0, 1),
1560 std::valarray<double> Lc_coef(1.0, 2);
1561 Lc_coef[1]=-1.0/6.0;
1562 expected_real_quantities[
SEMIMAJOR] = &nan_func;
1564 expected_real_quantities[CONV_INCLINATION] = &zero_func;
1565 expected_real_quantities[RAD_INCLINATION] = &zero_func;
1566 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1567 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1568 expected_real_quantities[CONV_ANGMOM] =
1572 expected_real_quantities[RAD_ANGMOM] =
1574 std::valarray<double>(1.0/6.0, 2),
1578 initial_Lrad = (TSTART / 2.0 + 1.0) / 6.0;
1584 expected_real_quantities,
1590 delete expected_real_quantities[CONV_ANGMOM];
1591 delete expected_real_quantities[RAD_ANGMOM];
1593 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")
1596 }
catch (std::exception &ex) {
1597 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")
1599 ex.what()).c_str());
1603 void test_OrbitSolver::test_no_planet_evolution()
1606 const double rt2 = std::sqrt(2.0);
1609 *stellar_evol = StellarEvolution::make_no_evolution();
1610 double initial_Lstar[] = {0.0, 0.0};
1612 std::vector<const Core::OneArgumentDiffFunction *>
1613 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1614 expected_real_quantities[CONV_ANGMOM] = &zero_func;
1615 expected_real_quantities[RAD_ANGMOM] = &zero_func;
1617 unsat_wind_mode.
add_break(TSTART,
false);
1625 expected_real_quantities,
1628 delete stellar_evol;
1629 stellar_evol = StellarEvolution::make_linear_I_evolution();
1631 initial_Lstar[0] = 1.0;
1632 expected_real_quantities[CONV_ANGMOM] = &one_func;
1638 expected_real_quantities,
1642 initial_Lstar[0] = 0.5 * (1.0 + std::exp(-TSTART));
1643 initial_Lstar[1] = 0.5 * (1.0 - std::exp(-TSTART));
1646 std::valarray<double>(0.5, 1),
1665 expected_real_quantities,
1668 delete expected_real_quantities[CONV_ANGMOM];
1669 delete expected_real_quantities[RAD_ANGMOM];
1671 initial_Lstar[0] = 1.0/(1.0+TSTART);
1672 initial_Lstar[1] = 1.0;
1674 double wind_sat_age = std::pow(2.0, 0.25) - 1;
1675 std::valarray<double> late_denom_coef(3);
1676 late_denom_coef[0] = 2.0 * rt2 - 2.0;
1677 late_denom_coef[1] = 4.0 * rt2;
1678 late_denom_coef[2] = 2.0 * rt2;
1680 one_func_early(std::valarray<double>(1.0, 1),
1681 TSTART, wind_sat_age),
1682 one_plus_t(std::valarray<double>(1.0, 2), TSTART,
MAX_AGE),
1683 late_denom2(late_denom_coef, wind_sat_age,
MAX_AGE);
1686 late_solution(&one_plus_t, &late_denom);
1688 full_solution.
add_piece(&early_solution);
1689 full_solution.
add_piece(&late_solution);
1691 expected_real_quantities[CONV_ANGMOM] = &full_solution;
1692 expected_real_quantities[RAD_ANGMOM] = &one_func;
1694 changing_wind_mode.
add_break(TSTART,
true);
1695 changing_wind_mode.
add_break(wind_sat_age,
false);
1702 expected_real_quantities,
1703 changing_wind_mode);
1705 double b1 = (std::sqrt(2) - 1) / (2.0 * rt2),
1706 b2 = (std::sqrt(2) + 1) / (2.0 * rt2);
1707 initial_Lstar[0] = (b1 * std::exp(-TSTART / (2.0 + rt2))
1709 b2 * std::exp(-TSTART / (2.0 - rt2)));
1710 initial_Lstar[1] = (
1711 0.5 / rt2 * std::exp(-1.0 / (2.0 + rt2) * (TSTART))
1713 0.5 / rt2 * std::exp(-1.0 / (2.0 - rt2) * (TSTART))
1717 Lc1(&zero_func, b1, -1.0 / (2.0 + rt2)),
1718 Lc2(&zero_func, b2, -1.0 / (2.0 - rt2)),
1719 Lr1(&zero_func, 0.5 / rt2, -1.0 / (2.0 + rt2)),
1720 Lr2(&zero_func, -0.5 / rt2, -1.0 / (2.0 - rt2));
1722 expected_real_quantities[CONV_ANGMOM] =
new FuncPlusFunc(&Lc1,
1724 expected_real_quantities[RAD_ANGMOM] =
new FuncPlusFunc(&Lr1,
1726 delete stellar_evol;
1727 stellar_evol = StellarEvolution::make_no_evolution();
1733 expected_real_quantities,
1736 delete expected_real_quantities[CONV_ANGMOM];
1737 delete expected_real_quantities[RAD_ANGMOM];
1739 delete stellar_evol;
1741 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")+
1743 }
catch (std::exception &ex) {
1744 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")+
1745 ex.what()).c_str());
1749 void test_OrbitSolver::test_unlocked_evolution()
1753 binary_mode.
add_break(TSTART, Core::BINARY);
1755 unsat_wind_mode.
add_break(TSTART,
false);
1759 *no_evol = StellarEvolution::make_no_evolution(1.0);
1761 const double mplanet = 100;
1762 double lag = 1e-8 / mplanet;
1764 std::vector<const Core::OneArgumentDiffFunction *>
1777 double initial_a = (
1781 std::valarray<double> initial_L(3);
1782 initial_L[0] = (*expected_real_quantities[CONV_ANGMOM])(
1798 expected_real_quantities,
1807 expected_real_quantities =
1814 initial_a = (*expected_real_quantities[
SEMIMAJOR])(TSTART);
1815 initial_L[0] = (*expected_real_quantities[CONV_ANGMOM])(TSTART);
1827 expected_real_quantities,
1839 std::vector<double>(),
1840 std::vector<double>(),
1841 std::vector<double>(1, 0.0),
1842 std::vector<double>(1, 0.0),
1851 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")
1854 }
catch (std::exception &ex) {
1855 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")
1857 ex.what()).c_str());
1867 double *dbl_par =
static_cast<double *
>(params);
1868 double alpha = dbl_par[0],
1874 0.1 * alpha * std::pow(a, 5)
1876 0.5 * beta * std::pow(a, 3)
1890 double *dbl_par =
static_cast<double *
>(params);
1891 double alpha = dbl_par[0],
1899 1.5 * beta * std::log(a)
1914 double *dbl_par =
static_cast<double *
>(params);
1915 double alpha = dbl_par[0],
1917 return 0.5 * alpha * std::pow(a, 4) - 1.5 * beta * std::pow(a, 2);
1927 double *dbl_par =
static_cast<double *
>(params);
1928 double alpha = dbl_par[0],
1930 return alpha * a / 2.0 - 1.5 * beta / a;
1940 double *dbl_par =
static_cast<double *
>(params);
1941 double alpha = dbl_par[0],
1947 0.1 * alpha * std::pow(a, 5)
1949 0.5 * beta * std::pow(a, 3)
1955 *df = (0.5 * alpha * std::pow(a, 4)
1957 1.5 * beta * std::pow(a, 2));
1967 double *dbl_par =
static_cast<double *
>(params);
1968 double alpha = dbl_par[0],
1976 1.5 * beta * std::log(a)
1982 *df = alpha * a / 2.0 - 1.5 * beta / a;
1985 void test_OrbitSolver::test_locked_evolution()
1989 expected_mode.
add_break(TSTART, Core::BINARY);
1991 expected_wind_mode.
add_break(TSTART,
false);
1992 const double Ic = 0.001, Kwind = 1e-3, Kwind_s = 1;
1994 no_evol = StellarEvolution::make_no_evolution(1.0, Ic);
2048 Kwind_s * wsat_s * wsat_s *
2063 int_const = (Lscale / 10.0 * std::pow(a1, 5)
2065 beta / 2.0 * std::pow(a1, 3)
2068 int_const_s = (Lscale / 4.0 * std::pow(a1, 2)
2070 3.0 * beta / 2.0 * std::log(a1)
2129 std::valarray<double> a_transform_coef(0.0, 6),
2132 a_transform_coef[5] = Lscale / 10.0;
2133 a_transform_coef[3] = -beta / 2.0;
2134 t_coef[0] = int_const;
2136 t_coef_s[0] = int_const_s;
2137 t_coef_s[1] = -kappa_s;
2138 std::valarray<double> Lconv_term1_coef(0.0, 2),
2139 Lconv_term2_coef(0.0, 3),
2140 identity_coef(0.0, 2),
2141 a_term1_coef_s(0.0, 3),
2142 Lconv_term1_coef_s(0.0, 2),
2143 Lc_beta_coef_s(0.0, 2);
2144 Lconv_term1_coef[1] = 1.0 / beta * std::pow(10.0 / Lscale,
2146 Lconv_term2_coef[2] = -2.0 / std::pow(beta, 3);
2147 identity_coef[1] = 1;
2148 a_term1_coef_s[2] = Lscale / 4.0;
2149 Lconv_term1_coef_s[1] = 1.0 / beta * std::pow(4.0 / Lscale,
2151 Lc_beta_coef_s[1] = 1.0 / beta;
2154 a_transform(a_transform_coef, 0.0, Core::Inf),
2155 a_transform1_s(a_term1_coef_s, 0.0, Core::Inf),
2156 transformed_a_evol(t_coef, TSTART, 1.0),
2157 transformed_a_evol_s(t_coef_s, TSTART, 1.0),
2158 Lconv_term1_poly(Lconv_term1_coef, 0.0, Core::Inf),
2159 Lconv_term2_poly(Lconv_term2_coef, 0.0, Core::Inf),
2160 Lconv_term1_poly_s(Lconv_term1_coef_s, 0.0, Core::Inf),
2161 Lc_beta_s(Lc_beta_coef_s, 0.0, Core::Inf),
2162 identity(identity_coef, 0.0, Core::Inf);
2164 L_transform2(&Lconv_term2_poly, -1.0),
2165 L_transform1_s(&Lconv_term1_poly_s, -4.0 / 3.0);
2167 log_Lc_beta_s(&Lc_beta_s);
2169 L_transform2_s(&log_Lc_beta_s, beta);
2170 FuncPlusFunc L_transform(&L_transform1, &L_transform2),
2171 a_transform_s(&a_transform1_s, &a_transform2_s),
2172 L_transform_s(&L_transform1_s, &L_transform2_s);
2174 std::valarray<double> initial_orbit(2);
2176 initial_orbit[0]=astart;
2177 initial_orbit[1]=0.0;
2178 std::cout.precision(16);
2179 std::cout.setf(std::ios_base::scientific);
2180 Star star_not_saturated_wind_no_coupling(1.0, 0.0, Kwind, wsat, Inf,
2181 0.0, 0.0, 0.0, no_evol);
2182 Planet planet1(&star_not_saturated_wind_no_coupling, 1.0, 1.0, 1.0);
2183 StellarSystem system1(&star_not_saturated_wind_no_coupling, &planet1);
2185 solver(system1, Inf, 0.0, a0, tstart, LOCKED_TO_PLANET, initial_orbit,
true);
2188 test_solution(to_check, transformed_a_evol, transformed_a_evol,
2189 zero_func, tstart, 1.0, expected_mode);
2191 initial_orbit[0]=astart_s;
2192 initial_orbit[1]=0.0;
2193 Star star_saturated_wind_no_coupling(1.0, 0.0, Kwind_s, wsat_s, Inf,
2194 0.0, 0.0, 0.0, no_evol);
2195 Planet planet2(&star_saturated_wind_no_coupling, 1.0, 1.0, 1.0);
2196 StellarSystem system2(&star_saturated_wind_no_coupling, &planet2);
2197 solver(system2, Inf, 0.0, a0_s, tstart, LOCKED_TO_PLANET,
2198 initial_orbit,
true);
2202 test_solution(to_check_s, transformed_a_evol_s, transformed_a_evol_s,
2203 zero_func, tstart, 1.0, expected_mode);
2207 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")
2210 }
catch (std::exception &ex) {
2211 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")
2213 ex.what()).c_str());
2217 void test_OrbitSolver::test_disklocked_to_locked_to_noplanet()
2220 const double Ic = 0.001,
2225 no_evol = StellarEvolution::make_no_evolution(1.0, Ic);
2227 double afinal = 1.75,
2279 int_const = (Lscale / 10.0 * std::pow(afinal, 5)
2281 beta / 2.0 * std::pow(afinal, 3)
2284 double solver_params[]={Lscale, beta, kappa, int_const, tdisk};
2285 double ainitial = solve(2.0 * afinal,
2291 static_cast<void*>(solver_params)),
2321 ainitial * (1.0 - 1e-14),
2333 ainitial * (1.0 - 1e-14),
2348 Core::LOCKED_SURFACE_SPIN);
2352 tdestr = ((beta / 2.0 * std::pow(adestr, 3)
2356 Lscale / 10.0 * std::pow(adestr, 5)) / kappa),
2357 Lc_at_destr = (beta / std::pow(adestr, 1.5)
2359 Lscale * std::sqrt(adestr));
2362 std::valarray<double> a_transform_coef(0.0, 6), t_coef(2);
2363 a_transform_coef[5] = Lscale / 10.0;
2364 a_transform_coef[3] = -beta / 2.0;
2365 t_coef[0] = int_const;
2367 std::valarray<double> Lconv_term1_coef(0.0, 2),
2368 Lconv_term2_coef(0.0, 3),
2369 identity_coef(0.0, 2),
2370 noplanet_Lconv_m2_coef(2);
2371 Lconv_term1_coef[1] = 1.0 / beta * std::pow(10.0 / Lscale, 0.3);
2372 Lconv_term2_coef[2] = -2.0 / std::pow(beta, 3);
2373 noplanet_Lconv_m2_coef[0] = (
2374 std::pow(Lc_at_destr, -2)
2376 2.0 * Kwind * tdestr / std::pow(Ic, 3)
2378 noplanet_Lconv_m2_coef[1] = 2.0 * Kwind / std::pow(Ic, 3);
2379 identity_coef[1] = 1;
2381 identity(identity_coef, -Core::Inf, Core::Inf),
2382 disk_nan_evol(std::valarray<double>(Core::NaN, 2),
2385 locked_a_transform(a_transform_coef, -Core::Inf, Core::Inf),
2386 locked_aLconv_evol(t_coef, tdisk, tdestr),
2387 locked_e_evol(std::valarray<double>(), tdisk, tdestr),
2388 noplanet_nan_evol(std::valarray<double>(Core::NaN, 2),
2391 disk_Lconv_evol(std::valarray<double>(wdisk * Ic, 1),
2394 noplanet_Lconv_m2_evol(noplanet_Lconv_m2_coef, tdestr, tfinal),
2395 Lconv_term1_poly(Lconv_term1_coef, -Core::Inf, Core::Inf),
2396 Lconv_term2_poly(Lconv_term2_coef, -Core::Inf, Core::Inf),
2397 Lrad_evol(std::valarray<double>(), TSTART, tfinal);
2399 L_transform2(&Lconv_term2_poly, -1.0),
2400 noplanet_Lconv_evol(&noplanet_Lconv_m2_evol, -0.5);
2402 FuncPlusFunc locked_Lconv_transform(&L_transform1, &L_transform2);
2411 Lconv_evol.
add_piece(&locked_aLconv_evol);
2412 Lconv_evol.
add_piece(&noplanet_Lconv_evol);
2414 std::vector< const Core::OneArgumentDiffFunction * >
2415 transformations(NUM_REAL_QUANTITIES - 1, &identity);
2417 transformations[
SEMIMAJOR] = &locked_a_transform;
2418 transformations[CONV_ANGMOM] = &locked_Lconv_transform;
2421 transformations[CONV_ANGMOM] = &identity;
2425 expected_evol_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
2426 expected_evol_mode.
add_break(tdisk, Core::BINARY);
2427 expected_evol_mode.
add_break(tdestr, Core::SINGLE);
2430 expected_wind_mode.
add_break(TSTART,
false);
2435 (tfinal - __system->age()) / 10000.0,
2436 std::list<double>());
2438 std::vector< const std::list<double> * >
2440 const std::vector< const std::list<double> * > &
2441 transformed_evolution = to_check(tabulated_evolution);
2443 std::vector<const Core::OneArgumentDiffFunction *>
2444 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
2445 expected_real_quantities[
SEMIMAJOR] = &a_evol;
2447 expected_real_quantities[CONV_INCLINATION] = &zero_func;
2448 expected_real_quantities[RAD_INCLINATION] = &zero_func;
2449 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
2450 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
2451 expected_real_quantities[CONV_ANGMOM] = &Lconv_evol;
2452 expected_real_quantities[RAD_ANGMOM] = &Lrad_evol;
2455 expected_real_quantities,
2463 Star star_not_saturated_wind_no_coupling(
2473 Planet planet1(&star_not_saturated_wind_no_coupling, 1.0, 1.0, 1.0);
2474 StellarSystem system1(&star_not_saturated_wind_no_coupling, &planet1);
2503 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")
2506 }
catch (std::exception &ex) {
2507 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")
2509 ex.what()).c_str());
2514 void test_OrbitSolver::test_disklocked_to_fast_to_noplanet()
2517 const double TDISK = 1,
2540 no_evol = StellarEvolution::make_no_evolution(1.0, I_CONV);
2569 Core::AstroConst::solar_mass))
2577 __star->
mass() * Core::AstroConst::solar_mass
2588 double a6p5_offset = (std::pow(adestr, 6.5)
2590 6.5 * alpha * TDESTR),
2591 a_formation = std::pow(a6p5_offset + 6.5 * alpha * TDISK,
2600 expected_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
2601 expected_mode.
add_break(TDISK, Core::BINARY);
2602 expected_mode.
add_break(TDESTR, Core::SINGLE);
2605 unsat_wind_mode.
add_break(TSTART,
false);
2607 std::valarray<double> a6p5_poly_coef(2);
2608 a6p5_poly_coef[0] = a6p5_offset;
2609 a6p5_poly_coef[1] = 6.5 * alpha;
2611 a6p5_evol(a6p5_poly_coef, TDISK, TDESTR),
2612 Lconv_disk(std::valarray<double>(I_CONV*
WDISK, 1),
2616 std::valarray<double>(
2617 -L_SCALE * std::sqrt(a_formation) + I_CONV * WDISK,
2623 nan_disk(std::valarray<double>(Core::NaN, 2), TSTART, TDISK),
2624 nan_noplanet(std::valarray<double>(Core::NaN, 2),
2627 e_fast(std::valarray<double>(0.0, 1),
2630 Lrad_evol(std::valarray<double>(), TSTART,
MAX_AGE);
2632 sqrta_evol(&a6p5_evol, 1.0 / 13.0);
2635 I_CONV * WDISK / L_SCALE - std::sqrt(a_formation),
2640 std::vector<const Core::OneArgumentDiffFunction *>
2641 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
2653 conv_angmom_evol.
add_piece(&Lconv_disk);
2654 conv_angmom_evol.
add_piece(&Lconv_fast);
2659 expected_real_quantities[
SEMIMAJOR] = &a_evol;
2661 expected_real_quantities[CONV_INCLINATION] = &zero_func;
2662 expected_real_quantities[RAD_INCLINATION] = &zero_func;
2663 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
2664 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
2665 expected_real_quantities[RAD_ANGMOM] = &zero_func;
2666 expected_real_quantities[CONV_ANGMOM] = &conv_angmom_evol;
2667 expected_real_quantities[RAD_ANGMOM] = &zero_func;
2670 expected_real_quantities,
2678 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")+
2680 }
catch (std::exception &ex) {
2681 TEST_ASSERT_MSG(
false, (std::string(
"Unexpected exception thrown: ")+
2682 ex.what()).c_str());
2686 void test_OrbitSolver::test_disklocked_to_fast_to_locked()
2689 const double lgQ = 8,
2695 std::vector<const Core::OneArgumentDiffFunction *>
2696 expected_real_quantities
2698 calculate_expected_disklocked_to_fast_to_locked(
2706 double wsync = Core::orbital_angular_velocity(1.0,
2709 Lconv_sync = (*expected_real_quantities[CONV_ANGMOM])(
2710 (tsync + tend) / 2.0
2712 Iconv = Lconv_sync / wsync,
2713 Ldisk = (*expected_real_quantities[CONV_ANGMOM])(
2714 (TSTART + tdisk) / 2.0
2716 wdisk = Ldisk / Iconv,
2717 a_formation = (*expected_real_quantities[
SEMIMAJOR])(tdisk),
2724 no_evol = StellarEvolution::make_no_evolution(1.0, Iconv);
2735 expected_evol_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
2736 expected_evol_mode.
add_break(tdisk, Core::BINARY);
2739 expected_wind_mode.
add_break(TSTART,
false);
2745 (
__star ? &zero : &Ldisk),
2754 expected_real_quantities,
2757 (
__star ? TSTART : tdisk),
2765 std::vector<double>(),
2766 std::vector<double>(),
2767 std::vector<double>(1, 0.0),
2768 std::vector<double>(1, 0.0),
2780 std::string(
"Unexpected exception thrown: ")
2784 }
catch (std::exception &ex) {
2788 std::string(
"Unexpected exception thrown: ")
2796 void test_OrbitSolver::test_disklocked_to_locked_to_fast()
2836 wdisk = beta / std::pow(a0, 1.5),
2838 (std::pow(abreak, 6.5) - std::pow(adeath, 6.5))
2874 (std::pow(a0, 5) - std::pow(abreak, 5))
2876 std::pow(abreak, 3.5)
2881 5.0 * gamma * abreak * abreak
2886 (std::pow(a0, 3) - std::pow(abreak, 3))
2888 std::pow(abreak, 3.5) * 6.5
2899 (std::pow(a0, 5) - std::pow(abreak, 5)) * alphaL / 10.0
2901 (std::pow(a0, 3) - std::pow(abreak, 3)) * beta * Ic / 2.0
2921 locked_a_int_const = (alphaL * std::pow(a0, 5) / 10.0
2923 beta * Ic * std::pow(a0, 3) / 2.0
2928 no_evol = StellarEvolution::make_no_evolution(1.0, Ic);
2953 expected_evol_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
2954 expected_evol_mode.
add_break(tdisk, Core::BINARY);
2955 expected_evol_mode.
add_break(tdeath, Core::SINGLE);
2958 expected_wind_mode.
add_break(TSTART,
false);
2960 std::valarray<double> a_locked_transform_coef(0.0, 6),
2961 a_locked_evol_coef(2),
2962 identity_coef(0.0, 2),
2963 a6p5_fast_evol_coef(2),
2964 Lconv_locked_term1_coef(0.0, 2),
2965 Lconv_locked_term2_coef(0.0, 3);
2966 a_locked_transform_coef[5] = alphaL / 10.0;
2967 a_locked_transform_coef[3] = -beta * Ic / 2.0;
2968 a_locked_evol_coef[0] = locked_a_int_const;
2969 a_locked_evol_coef[1] = -kappa;
2970 identity_coef[1] = 1.0;
2971 a6p5_fast_evol_coef[0] = gamma * tbreak + std::pow(abreak, 6.5);
2972 a6p5_fast_evol_coef[1] = -gamma;
2973 Lconv_locked_term1_coef[1] = (1.0
2977 std::pow(10.0 / alphaL, 3.0 / 10.0));
2978 Lconv_locked_term2_coef[2] = -2.0 / std::pow(beta * Ic, 3);
2981 identity(identity_coef, -Core::Inf, Core::Inf),
2982 a_disk_transform = identity,
2983 nan_disk_evol(std::valarray<double>(Core::NaN, 2),
2986 a_locked_transform(a_locked_transform_coef,
2989 a_locked_evol(a_locked_evol_coef, tdisk, tbreak),
2990 a_fast_transform = identity,
2991 a6p5_fast_evol(a6p5_fast_evol_coef, tbreak, tdeath),
2992 a_noplanet_transform = identity,
2993 nan_noplanet_evol(std::valarray<double>(Core::NaN, 2),
2997 Lconv_disk_transform = identity,
2998 Lconv_disk_evol(std::valarray<double>(wdisk * Ic, 1),
3001 Lconv_locked_term1_poly(Lconv_locked_term1_coef,
3004 Lconv_locked_term2_poly(Lconv_locked_term2_coef,
3007 Lconv_locked_evol = a_locked_evol,
3008 Lconv_fast_transform(std::valarray<double>(Core::NaN, 2),
3011 Lconv_fast_evol(std::valarray<double>(Core::NaN, 2),
3014 Lconv_noplanet_transform(std::valarray<double>(Core::NaN, 2),
3017 Lconv_noplanet_evol(std::valarray<double>(Core::NaN, 2),
3020 Lrad_transform = identity,
3021 Lrad_evol(std::valarray<double>(), TSTART, tend),
3022 zero_e(std::valarray<double>(), tdisk, tdeath);
3025 a_fast_evol(&a6p5_fast_evol, 1.0 / 6.5),
3026 Lconv_locked_transform1(&Lconv_locked_term1_poly,
3028 Lconv_locked_transform2(&Lconv_locked_term2_poly, -1.0);
3030 FuncPlusFunc Lconv_locked_transform(&Lconv_locked_transform1,
3031 &Lconv_locked_transform2);
3045 Lconv_evol.
add_piece(&Lconv_locked_evol);
3047 Lconv_evol.
add_piece(&Lconv_noplanet_evol);
3049 std::vector< const Core::OneArgumentDiffFunction * >
3050 transformations(NUM_REAL_QUANTITIES - 1, &identity);
3053 transformations[
SEMIMAJOR] = &a_disk_transform;
3054 transformations[CONV_ANGMOM] = &Lconv_disk_transform;
3057 transformations[
SEMIMAJOR] = &a_locked_transform;
3058 transformations[CONV_ANGMOM] = &Lconv_locked_transform;
3061 transformations[
SEMIMAJOR] = &a_fast_transform;
3062 transformations[CONV_ANGMOM] = &Lconv_fast_transform;
3065 transformations[
SEMIMAJOR] = &a_fast_transform;
3066 transformations[CONV_ANGMOM] = &Lconv_fast_transform;
3069 transformations[
SEMIMAJOR] = &a_noplanet_transform;
3070 transformations[CONV_ANGMOM] = &Lconv_noplanet_transform;
3073 std::vector<const Core::OneArgumentDiffFunction *>
3074 expected_real_quantities(NUM_REAL_QUANTITIES - 1);
3076 std::vector< const std::list<double> * >
3079 const std::vector< const std::list<double> * > &
3080 transformed_evolution = to_check(tabulated_evolution);
3082 expected_real_quantities[
SEMIMAJOR] = &a_evol;
3084 expected_real_quantities[CONV_INCLINATION] = &zero_func;
3085 expected_real_quantities[RAD_INCLINATION] = &zero_func;
3086 expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
3087 expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
3088 expected_real_quantities[CONV_ANGMOM] = &Lconv_evol;
3089 expected_real_quantities[RAD_ANGMOM] = &zero_func;
3092 expected_real_quantities,
3102 std::string(
"Unexpected exception thrown: ")
3107 }
catch (std::exception &ex) {
3111 std::string(
"Unexpected exception thrown: ")
3120 void test_OrbitSolver::test_polar_1_0_evolution()
3123 no_evol = StellarEvolution::make_no_evolution();
3125 const double TDISK = 0.1,
3128 double initial_L = 1.0;
3129 std::vector<const Core::OneArgumentDiffFunction *>
3130 expected_real_quantities = calculate_expected_polar_1_0(
3136 expected_evol_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
3137 expected_evol_mode.
add_break(TDISK, Core::BINARY);
3140 expected_wind_mode.
add_break(TSTART,
false);
3142 double semimajor = (*expected_real_quantities[
SEMIMAJOR])(
3163 expected_real_quantities,
3166 (
__star ? TSTART : TDISK),
3192 void test_OrbitSolver::test_polar_2_0_evolution()
3195 no_evol = StellarEvolution::make_no_evolution();
3197 const double TDISK = 0.1,
3202 double lconv_decay_rate, semimajor, initial_L = 1.0;
3204 std::vector<const Core::OneArgumentDiffFunction *>
3205 expected_real_quantities = calculate_expected_polar_2_0(TDISK,
3213 std::valarray<double> identity_coef(0.0, 2);
3214 identity_coef[1] = 1.0;
3216 identity(identity_coef, -Core::Inf, Core::Inf),
3217 one_func(std::valarray<double>(1.0, 1), -Core::Inf, Core::Inf);
3229 2.0 * (WSTAR - lconv_decay_rate *
MAX_AGE),
3230 2.0 * (WSTAR + lconv_decay_rate * MAX_AGE),
3242 std::vector< const Core::OneArgumentDiffFunction * >
3243 transformations(NUM_REAL_QUANTITIES - 1, &identity);
3244 transformations[CONV_INCLINATION] = &one_plus_cos_transform;
3245 transformations[RAD_INCLINATION] = &one_plus_cos_transform;
3248 std::vector< const std::list<double> * >
3250 const std::vector< const std::list<double> * > &
3251 transformed_evolution = to_check(tabulated_evolution);
3254 expected_evol_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
3255 expected_evol_mode.
add_break(TDISK, Core::BINARY);
3258 expected_wind_mode.
add_break(TSTART,
false);
3261 expected_real_quantities,
3264 (
__star ? TSTART : TDISK),
3277 2.0 * (WSTAR - lconv_decay_rate * MAX_AGE),
3278 2.0 * (WSTAR + lconv_decay_rate * MAX_AGE),
3289 void test_OrbitSolver::test_oblique_1_0_evolution()
3292 no_evol = StellarEvolution::make_no_evolution();
3294 const double PHASE_LAG = 0.1,
3297 INITIAL_INC = 0.25 * M_PI,
3298 INITIAL_WSTAR = 0.01;
3300 double initial_angmom = 1.0,
3303 std::vector<const Core::OneArgumentDiffFunction *>
3304 expected_real_quantities = calculate_expected_oblique_m_0(
3314 double wstar_tolerance = 0.01 * (INITIAL_WSTAR - min_wstar),
3315 semimajor = (*expected_real_quantities[
SEMIMAJOR])(
3320 expected_evol_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
3324 expected_wind_mode.
add_break(TSTART,
false);
3331 min_wstar - wstar_tolerance,
3332 INITIAL_WSTAR + wstar_tolerance,
3333 0.1 * INITIAL_WSTAR,
3345 expected_real_quantities,
3361 min_wstar - wstar_tolerance,
3362 INITIAL_WSTAR + wstar_tolerance,
3363 0.1 * INITIAL_WSTAR,
3367 initial_angmom = INITIAL_WSTAR;
3373 void test_OrbitSolver::test_oblique_2_0_evolution()
3376 no_evol = StellarEvolution::make_no_evolution();
3378 const double PHASE_LAG = 0.1,
3381 INITIAL_INC = 0.25 * M_PI,
3382 INITIAL_WSTAR = 0.01;
3384 double initial_angmom = 1.0,
3387 std::vector<const Core::OneArgumentDiffFunction *>
3388 expected_real_quantities = calculate_expected_oblique_m_0(
3398 double wstar_tolerance = 0.01 * (INITIAL_WSTAR - min_wstar),
3399 semimajor = (*expected_real_quantities[
SEMIMAJOR])(
3404 expected_evol_mode.
add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
3408 expected_wind_mode.
add_break(TSTART,
false);
3415 2.0 * min_wstar - wstar_tolerance,
3416 2.0 * INITIAL_WSTAR + wstar_tolerance,
3417 0.1 * INITIAL_WSTAR,
3429 expected_real_quantities,
3444 2.0 * min_wstar - wstar_tolerance,
3445 2.0 * INITIAL_WSTAR + wstar_tolerance,
3446 0.1 * INITIAL_WSTAR,
3450 initial_angmom = INITIAL_WSTAR;
3459 void test_OrbitSolver::setup()
3468 void test_OrbitSolver::tear_down()
3471 std::cout <<
"Deleting star" << std::endl;
3476 std::cout <<
"Deleting primary planet" << std::endl;
3481 std::cout <<
"Deleting system" << std::endl;
3486 std::cout <<
"Deleting solver" << std::endl;
3491 std::vector< const Core::OneArgumentDiffFunction* >::iterator
3496 std::cout <<
"Deleting function" << std::endl;
3497 delete *temp_func_i;
3502 test_OrbitSolver::test_OrbitSolver() :
3508 TEST_ADD(test_OrbitSolver::test_disk_locked_no_stellar_evolution);
3509 TEST_ADD(test_OrbitSolver::test_disk_locked_with_stellar_evolution);
3510 TEST_ADD(test_OrbitSolver::test_no_planet_evolution);
3511 TEST_ADD(test_OrbitSolver::test_unlocked_evolution);
3513 TEST_ADD(test_OrbitSolver::test_disklocked_to_locked_to_noplanet);
3514 TEST_ADD(test_OrbitSolver::test_disklocked_to_fast_to_noplanet);
3515 TEST_ADD(test_OrbitSolver::test_disklocked_to_fast_to_locked);
3516 TEST_ADD(test_OrbitSolver::test_disklocked_to_locked_to_fast);
3517 TEST_ADD(test_OrbitSolver::test_polar_1_0_evolution);
3518 TEST_ADD(test_OrbitSolver::test_polar_2_0_evolution);
3519 TEST_ADD(test_OrbitSolver::test_oblique_1_0_evolution);
3520 TEST_ADD(test_OrbitSolver::test_oblique_2_0_evolution);
Implements a StellarEvolution based on polynomial evolution quantities.
Star::InterpolatedEvolutionStar * __star
The star used in the current test (NULL if primary is planet).
const double MIN_AGE
Most tests start at this age in Gyr.
Age in Myr when disk dissipates.
const std::list< double > & eccentricity_evolution() const
The tabulated evolution of the eccentricity so far.
double locked_sat_eq(double a, void *params)
The equation that should be solved in order to get the semimamjor axis at a given time for the locked...
Declares the test suite that exercises the OrbitSolver class and some other clasess necessary to acco...
The orbital periapsis in the reference frame of the stellar radiative zone in radians.
void detect_saturation()
Sets the saturation based on the currently configured spin frequency.
The base class of all exceptions.
const std::list< Core::EvolModeType > & mode_evolution() const
The tabulated evolution modes so far.
The orbital frequency in rad/day.
A function scaled by some constant.
std::ostream & operator<<(std::ostream &os, const ZoneEvolutionQuantities &evol_var)
More civilized output for EvolVarType variables.
A base class for any body contributing to tidal dissipation.
void locked_sat_eq_deriv(double a, void *params, double *f, double *df)
The equation and its derivative that should be solved in order to get the semimamjor axis at a given ...
virtual double minimum_separation(bool deriv=false) const
Smallest semimajor axis at which the secondary can survive for the latest system configuration.
A class representing a once differentiable function of a single argument.
SEMIMAJOR
The derivative w.r.t. the semimajor axis in AU.
Single zone non-evolving planets with huge dissipation, so they always remain locked to the disk...
void test_no_planet_scenario(const StellarEvolution::Interpolator &stellar_evol, double *initial_Lstar, double windK, double wind_sat_freq, double core_env_coupling_time, std::vector< const Core::OneArgumentDiffFunction *> &expected_evolution, const ExpectedEvolutionMode< bool > &expected_wind_mode, double max_age=MAX_AGE, bool debug_mode=false)
Test a planet-less scenario computed in 3 different ways: 1) withou a planet 2) without dissipation 3...
The angle between the stellar core spin and orbital angular momentum in radians.
const Evolve::DissipatingZone & zone(unsigned zone_index) const
Returns the only zone.
struct LIB_PUBLIC OrbitSolver
Opaque struct to cast to/from Evolve::OrbitSolver.
The angle between the stellar surface spin and orbital angular momentum in radians.
const double jupiter_mass
Mass of Jupiter [kg].
void make_single_component_star(const StellarEvolution::Interpolator &evolution, double wind_strength, double wind_sat_freq, double coupling_timescale, double min_frequency, double max_frequency, double decay_scale, double phase_lag=1.0e-5)
Create __star with constant dissipation in a range, quickly decaying outside of that.
Evolve::DiskBinarySystem * __system
The system being evolved by the current test.
const double MAX_AGE
Most tests end at this age in Gyr.
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.
const std::list< bool > & wind_saturation_evolution() const
The tabulated wind saturation states so far.
const EvolvingStellarCore & core() const
The core of the star.
Planet::Planet * __primary_planet
The primary planet in the current test (NULL if primary is star).
RealEvolutionQuantity
Define identifiers for the quantities whose evolution we check.
struct LIB_PUBLIC DiskBinarySystem
Opaque struct to cast to/from Evolve::DiskBinarySystem.
A class that interpolates among stellar evolution tracks.
Represents the sum of two functions and the derivative.
const double jupiter_radius
Radius of Jupiter [m].
double mass() const
The mass of the body (constant with age).
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.
void evolve(double wdisk, double tdisk, double initial_a, const double *initial_Lstar, double initial_incl=0.0, double secondary_mass=1.0, double tsecondary=Core::NaN, double max_age=MAX_AGE, double secondary_radius=1.0, double precision=1e-6, double max_step_factor=1e-3)
Add a planet to the given star and evolve, returning the solver.
double lag_from_lgQ(double lgQ)
Converts lg(Q) to a tidal phase lag.
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...
The cosine of a function.
An EvolvingStellar quantity that uses a polynomial instead of interpolating.
The natural logarithm of a function.
Stellar surface spin while disk is present in rad/day.
void set_single_component_dissipation(double min_frequency, double max_frequency, double decay_scale, double phase_lag=1.0e-5)
Set the dissipation of the primary to only a single tidal.
virtual const char * what() const
The type of error.
bool check_diff(double x, double y, double frac_tolerance, double abs_tolerance)
Returns true iff .
double locked_unsat_deriv(double a, void *params)
The derivative of the equation that should be solved in order to get the semimamjor axis at a given t...
ECCENTRICITY
The derivative w.r.t. the eccentricity.
std::vector< const Core::OneArgumentDiffFunction * > calculate_expected_unlocked_evolution(double phase_lag, double secondary_mass, bool decaying=true)
Calculate the predicted evolution for the test_unlocked_evolution() case.
const double solar_mass
Mass of the sun [kg].
const EvolvingStellarEnvelope & envelope() const
The envelope of the star - inmodifiable.
AGE
The derivative w.r.t. age, excluding the dependence through the body's radius and the moments of iner...
The minimum age to start evolution at in Gyr.
Several functions stiched together.
const std::string & get_message()
Details about what caused the error.
A DissipatingZone where the phase lag is described by a broken powerlaw.
bool near_break(double age) const
Is the given age close to a break (hence ambigous mode).
EvolModeType
The various evolution modes.
void test_solution(const std::vector< const std::list< double > * > &tabulated_real_quantities, std::vector< const Core::OneArgumentDiffFunction *> expected_real_quantities, const ExpectedEvolutionMode< Core::EvolModeType > &expected_evol_mode, const ExpectedEvolutionMode< bool > &expected_wind_mode, double min_age, double max_age, bool debug_mode=false)
Tests the latest evolution calculated by the solver against the given tracks.
const std::list< double > & get_evolution_real(ZoneEvolutionQuantities quantity) const
The tabulated evolution of a real valued quantity so far.
std::vector< const Core::OneArgumentDiffFunction *> __temp_functions
A list of functions allocated during a test to delete at the end.
Angular momentum of the zone.
void locked_unsat_eq_deriv(double a, void *params, double *f, double *df)
The equation and its derivative that should be solved in order to get the semimamjor axis at a given ...
Represents a function of the form offset + scale*exp(rate*x) as well as its derivative.
Solves the system of ODEs describing the evolution of a single planet around a single star...
Evolve::OrbitSolver * __solver
The solver used for the current test.
A function raised to some power.
double locked_unsat_eq(double a, void *params)
The equation that should be solved in order to get the semimamjor axis at a gien time.
The orbital periapsis in the reference frame of the stellar convective zone in radians.
void add_piece(const OneArgumentDiffFunction *piece)
Adds another piece of the function, where it applies is defined by its range.
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.
The ratio of two functions;.
std::vector< const std::list< double > * > get_evolution() const
Return the last calculated evolution.
double locked_sat_deriv(double a, void *params)
The derivative of the equation that should be solved in order to get the semimamjor axis at a gien ti...
void add_break(double age, MODE_TYPE mode)
Add an evolution mode that applies up to the given age.
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.
Some evolution mode that changes at specified ages.
const std::list< double > & evolution_ages() const
The ages at which evolution has been tabulated so far.
const double G
Gravitational constant in SI.
void setup(const std::vector< double > &tidal_frequency_breaks, const std::vector< double > &spin_frequency_breaks, const std::vector< double > &tidal_frequency_powers, const std::vector< double > &spin_frequency_powers, double reference_phase_lag, double inertial_mode_enhancement=1.0, double inertial_mode_sharpness=10.0)
Seup the zone with the given breaks/powers and inertial mode enhancement. Continuous accress all brea...