Planetary Orbital Evolution due to Tides
Orbital evolution of two objects experiencing tides
testOrbitSolver.cpp
Go to the documentation of this file.
1 
9 #include "testOrbitSolver.h"
10 
11 namespace Evolve {
12 
13  const double TSTART = 2.0 * MIN_AGE;
14  const double zero = 0.0;
15  const double one = 1.0;
16 
17  const double Mjup_to_Msun = (Core::AstroConst::jupiter_mass
18  /
20 
21  const double Rjup_to_Rsun = (Core::AstroConst::jupiter_radius
22  /
24 
25  std::ostream &operator<<(std::ostream &os,
27  {
28  switch(q) {
29  case SEMIMAJOR :
30  os << "SEMIMAJOR"; break;
31  case ECCENTRICITY:
32  os << "ECCENTRICITY"; break;
33  case CONV_INCLINATION:
34  os << "CONV_INCLINATION"; break;
35  case RAD_INCLINATION:
36  os << "RAD_INCLINATION"; break;
37  case CONV_PERIAPSIS:
38  os << "CONV_PERIAPSIS"; break;
39  case RAD_PERIAPSIS:
40  os << "RAD_PERIAPSIS"; break;
41  case CONV_ANGMOM:
42  os << "CONV_ANGMOM"; break;
43  case RAD_ANGMOM:
44  os << "RAD_ANGMOM"; break;
45  case AGE:
46  os << "AGE"; break;
47  default :
48  assert(false);
49  }
50  return os;
51  }
52 
53 
55  std::valarray<double>(Core::NaN, 2),
56  TSTART,
57  MAX_AGE
58  );
59 
61  std::valarray<double>(),
62  TSTART,
63  MAX_AGE
64  );
65 
67  std::valarray<double>(1.0, 1),
68  TSTART,
69  MAX_AGE
70  );
71 
73  std::valarray<double>(2.0, 1),
74  TSTART,
75  MAX_AGE
76  );
77 
79  std::valarray<double>(200.0, 1),
80  TSTART,
81  MAX_AGE
82  );
83 
85  double min_frequency,
86  double max_frequency,
87  double decay_scale,
88  double phase_lag
89  )
90  {
91  //phase lag(min_frequency - decay_scale)
92  //=
93  //phase lag(max_frequency + decay_scale)
94  //=
95  //suppression_factor * phase_lag
96  const double suppression_factor = 0.01;
97 
98  std::vector<double> breaks(2);
99  breaks[0] = min_frequency;
100  breaks[1] = max_frequency;
101 
102  std::vector<double> powerlaw_indices(3);
103  powerlaw_indices[0] = (
104  std::log(suppression_factor)
105  /
106  std::log(1.0 - decay_scale / min_frequency)
107  );
108  powerlaw_indices[1] = 0.0;
109  powerlaw_indices[2] = (
110  std::log(suppression_factor)
111  /
112  std::log(1.0 + decay_scale / max_frequency)
113  );
114 
116 
117  if(__star) {
118  assert(__primary_planet == NULL);
119  zone = &(__star->envelope());
120  } else {
121  assert(__primary_planet);
122  zone = &(__primary_planet->zone());
123  }
124 
125  zone->setup(breaks,
126  std::vector<double>(),
127  powerlaw_indices,
128  std::vector<double>(1, 0.0),
129  phase_lag);
130  }
131 
133  const StellarEvolution::Interpolator &evolution,
134  double wind_strength,
135  double wind_sat_freq,
136  double coupling_timescale,
137  double min_frequency,
138  double max_frequency,
139  double decay_scale,
140  double phase_lag
141  )
142  {
143  __star = new Star::InterpolatedEvolutionStar(1.0,//mass
144  0.0,//feh
145  wind_strength,
146  wind_sat_freq,
147  coupling_timescale,
148  evolution);
149  set_single_component_dissipation(min_frequency,
150  max_frequency,
151  decay_scale,
152  phase_lag);
153 
154  }
155 
156  void test_OrbitSolver::evolve(double wdisk,
157  double tdisk,
158  double initial_a,
159  const double *initial_Lstar,
160  double initial_incl,
161  double secondary_mass,
162  double tsecondary,
163  double max_age,
164  double secondary_radius,
165  double precision,
166  double max_step_factor,
167  const std::list<double> required_ages)
168  {
169  Evolve::DissipatingBody *primary;
170  if(__star)
171  primary = __star;
172  else
173  primary = __primary_planet;
174 
175  secondary_mass *= Mjup_to_Msun;
176  secondary_radius *= Rjup_to_Rsun;
177 
178  if(std::isnan(tsecondary)) tsecondary = tdisk;
179 
180  Planet::Planet secondary(secondary_mass,
181  (secondary_mass ? secondary_radius : 0.0));
182  secondary.configure(true, //init
183  tsecondary, //age
184  primary->mass(), //mass
185  initial_a, //semimajor
186  0.0, //eccentricity
187  &zero, //spin angmom
188  NULL, //inclination
189  NULL, //periapsis
190  false, //locked surface
191  true, //zero outer inclination
192  true);//zero outer periapsis
193 
195  *primary,
196  secondary,
197  initial_a, //semimajor
198  0.0, //eccentricity
199  initial_incl, //inclination
200  wdisk, //Wdisk
201  tdisk, //disk dissipation age
202  tsecondary //secondary formation age
203  );
204  double zeros[] = {0.0, 0.0};
205  if(__star) {
206  if(tdisk <= TSTART) {
207  if(tsecondary <= TSTART) {
208  __system->configure(true, //init
209  TSTART,
210  initial_a, //semimajor
211  0.0, //eccentricity
212  initial_Lstar, //spin angmom
213  zeros, //inclination
214  zeros, //periapsis
215  Core::BINARY);
216  } else {
217  __system->configure(true, //init
218  TSTART,
219  Core::NaN, //semimajor
220  Core::NaN, //eccentricity
221  initial_Lstar, //spin angmom
222  zeros, //inclination
223  zeros, //periapsis
224  Core::SINGLE);
225  }
226  } else {
227  __system->configure(true, //init
228  TSTART,
229  Core::NaN, //semimajor
230  Core::NaN, //eccentricity
231  initial_Lstar, //spin angmom
232  NULL, //inclination
233  NULL, //periapsis
234  Core::LOCKED_SURFACE_SPIN);
235  }
237  } else {
238  double initial_inclinations[] = {initial_incl, 0.0, 0.0};
239  __system->configure(true, //init
240  tsecondary,
241  initial_a, //semimajor
242  0.0, //eccentricity
243  initial_Lstar, //spin angmom
244  initial_inclinations, //inclination
245  zeros, //periapsis
246  Core::BINARY);
247  }
248  __solver = new Evolve::OrbitSolver(max_age, precision);
249  (*__solver)(*__system,
250  (max_age - __system->age()) * max_step_factor,//time step
251  required_ages); //no required ages
252  }
253 
254  std::vector< const std::list<double> *> test_OrbitSolver::get_evolution()
255  const
256  {
257  std::vector< const std::list<double> *>
258  tabulated_real_quantities(NUM_REAL_QUANTITIES);
259 
260  tabulated_real_quantities[AGE] = &(__solver->evolution_ages());
261 
262  tabulated_real_quantities[SEMIMAJOR] =
264 
265  tabulated_real_quantities[ECCENTRICITY] =
267 
268  Evolve::DissipatingZone *primary_envelope;
269 
270  if(__star) {
271  tabulated_real_quantities[RAD_INCLINATION] =
273 
274  tabulated_real_quantities[RAD_PERIAPSIS] =
276 
277  tabulated_real_quantities[RAD_ANGMOM] = &(
279  );
280  primary_envelope = &(__star->envelope());
281  } else {
282  tabulated_real_quantities[RAD_INCLINATION] = NULL;
283  tabulated_real_quantities[RAD_PERIAPSIS] = NULL;
284  tabulated_real_quantities[RAD_ANGMOM] = NULL;
285  primary_envelope = &(__primary_planet->zone());
286  }
287 
288  tabulated_real_quantities[CONV_INCLINATION] = &(
289  primary_envelope->get_evolution_real(Evolve::INCLINATION)
290  );
291 
292  tabulated_real_quantities[CONV_PERIAPSIS] = &(
293  primary_envelope->get_evolution_real(Evolve::PERIAPSIS)
294  );
295 
296  tabulated_real_quantities[CONV_ANGMOM] = &(
297  primary_envelope->get_evolution_real(
299  )
300  );
301  return tabulated_real_quantities;
302  }
303 
305  const std::vector< const std::list<double> * > &
306  tabulated_real_quantities,
307  std::vector<const Core::OneArgumentDiffFunction *>
308  expected_real_quantities,
309  const ExpectedEvolutionMode<Core::EvolModeType> &expected_evol_mode,
310  const ExpectedEvolutionMode<bool> &expected_wind_mode,
311  double min_age,
312  double max_age,
313  bool debug_mode
314  )
315  {
316  const std::list<Core::EvolModeType> &tabulated_modes =
318 
319  const std::list<bool> *tabulated_wind_sat =
320  (__star ? &(__star->wind_saturation_evolution()) : NULL);
321 
322  unsigned num_ages = tabulated_real_quantities[AGE]->size();
323 
324  std::ostringstream msg_start;
325  std::ostringstream msg;
326  msg.precision(16);
327  msg.setf(std::ios_base::scientific);
328  msg_start.precision(16);
329  msg_start.setf(std::ios_base::scientific);
330  msg << msg_start.str()
331  << num_ages
332  << " tabulated ages, ";
333  bool all_same_size = true;
334 
335  for(unsigned q = 0; q < AGE; ++q) {
336  if(tabulated_real_quantities[q]) {
337  msg << tabulated_real_quantities[q]->size()
338  << " tabulated "
339  << static_cast<RealEvolutionQuantity>(q)
340  << ", ";
341  all_same_size = (
342  all_same_size
343  &&
344  tabulated_real_quantities[q]->size() == num_ages
345  );
346  }
347  }
348 
349  msg << tabulated_modes.size() << " tabulated modes";
350 
351  all_same_size = (all_same_size
352  &&
353  tabulated_modes.size() == num_ages);
354  if(__star) {
355  msg << ", "
356  << tabulated_wind_sat->size()
357  << " tabulated wind saturations";
358  all_same_size = (all_same_size
359  &&
360  tabulated_wind_sat->size() == num_ages);
361  }
362 
363 
364  if(debug_mode) std::cout << msg.str() << std::endl;
365  TEST_ASSERT_MSG(all_same_size, msg.str().c_str());
366 
367  msg.str("");
368  msg << "Expected age range: " << min_age << " to " << max_age
369  << ", actual age range: " << tabulated_real_quantities[AGE]->front()
370  << " to " << tabulated_real_quantities[AGE]->back();
371  if(debug_mode) std::cout << msg.str() << std::endl;
372  TEST_ASSERT_MSG(
373  (
374  tabulated_real_quantities[AGE]->front() == min_age
375  &&
376  tabulated_real_quantities[AGE]->back() == max_age
377  ),
378  msg.str().c_str()
379  );
380 
381  std::vector< std::list<double>::const_iterator >
382  real_tabulated_iter(AGE);
383  for(unsigned q = 0; q < AGE; ++q)
384  if(tabulated_real_quantities[q])
385  real_tabulated_iter[q] = tabulated_real_quantities[q]->begin();
386  std::list<Core::EvolModeType>::const_iterator
387  tabulated_mode_iter = tabulated_modes.begin();
388  std::list<bool>::const_iterator tabulated_wind_sat_iter;
389  if(__star)
390  tabulated_wind_sat_iter = tabulated_wind_sat->begin();
391  double last_checked_age = Core::NaN;
392 
393  for(
394  std::list<double>::const_iterator
395  age_i = tabulated_real_quantities[AGE]->begin();
396  age_i != tabulated_real_quantities[AGE]->end();
397  ++age_i
398  ) {
399  std::vector<double> expected_real_values(AGE);
400  for(unsigned q = 0; q < AGE; ++q) {
401  expected_real_values[q] =
402  (*(expected_real_quantities[q]))(*age_i);
403  }
404  Core::EvolModeType expected_mode = expected_evol_mode(*age_i);
405  bool expected_wind_sat = expected_wind_mode(*age_i);
406 
407  std::ostringstream age_msg_start;
408  age_msg_start.precision(16);
409  age_msg_start.setf(std::ios_base::scientific);
410  age_msg_start << msg_start.str()
411  << "age = " << *age_i
412  << ", mode = " << *tabulated_mode_iter;
413  if(__star) {
414  age_msg_start << ", wind is ";
415  if(!(*tabulated_wind_sat_iter)) age_msg_start << " not ";
416  age_msg_start << "saturated";
417  }
418  for(unsigned q = 0; q < AGE; ++q)
419  if(tabulated_real_quantities[q])
420  age_msg_start << ", "
421  << static_cast<RealEvolutionQuantity>(q)
422  << " = "
423  << *real_tabulated_iter[q];
424 
425  msg.str("");
426  msg << age_msg_start.str() << " age is out of range.";
427  TEST_ASSERT_MSG(*age_i >= min_age && *age_i <= max_age,
428  msg.str().c_str());
429 
430  std::list<double>::const_iterator next_age_i = age_i;
431  ++next_age_i;
432  bool
433  can_skip = (
434  next_age_i != tabulated_real_quantities[AGE]->end()
435  &&
436  std::abs(*next_age_i - *age_i) < 1e-5
437  &&
438  expected_evol_mode.near_break(*age_i)
439  &&
440  expected_evol_mode.near_break(*next_age_i)
441  ),
442  skipped = (*age_i == last_checked_age);
443 
444  msg.str("");
445  msg << age_msg_start.str() << ": mode is not "
446  << expected_mode << ", but " << *tabulated_mode_iter;
447 
448  if(debug_mode) std::cout << msg.str() << std::endl;
449  if(!skipped && expected_mode != *tabulated_mode_iter) {
450  if(can_skip) skipped = true;
451  else TEST_ASSERT_MSG(false, msg.str().c_str());
452  }
453 
454  if(__star) {
455  msg.str("");
456  msg << age_msg_start.str() << ": wind is ";
457  if(!(*tabulated_wind_sat_iter)) msg << " not ";
458  msg << "saturated, but should";
459  if(!expected_wind_sat) msg << " not ";
460  msg << "be.";
461  if(debug_mode) std::cout << msg.str() << std::endl;
462  if(!skipped && expected_wind_sat != *tabulated_wind_sat_iter) {
463  if(can_skip) skipped = true;
464  else TEST_ASSERT_MSG(false, msg.str().c_str());
465  }
466  }
467 /* TEST_ASSERT_MSG(
468  (
469  skipped
470  ||
471  expected_wind_sat == *tabulated_wind_sat_iter
472  ||
473  expected_wind_mode.near_break(*age_i)
474  ),
475  msg.str().c_str()
476  );*/
477 
478  for(unsigned q = 0; q < AGE; ++q) {
479  if(!tabulated_real_quantities[q]) continue;
480  msg.str("");
481  msg << age_msg_start.str() << ": "
482  << static_cast<RealEvolutionQuantity>(q)
483  << " is not "
484  << expected_real_values[q]
485  << " but "
486  << *real_tabulated_iter[q]
487  << ", difference = "
488  << (*real_tabulated_iter[q]) - expected_real_values[q];
489  if(debug_mode) std::cout << msg.str() << std::endl;
490  if(
491  !skipped
492  &&
493  !check_diff((*real_tabulated_iter[q]),
494  expected_real_values[q],
495  1.2e-5,
496  0.0)
497  ) {
498  if(can_skip) {
499  skipped = true;
500  break;
501  }
502  TEST_ASSERT_MSG(false, msg.str().c_str());
503  }
504  }
505  if(!skipped)
506  last_checked_age = *age_i;
507  else if(debug_mode)
508  std::cerr << "Skipped checks for t = " << *age_i
509  << std::endl;
510  for(unsigned q = 0; q < AGE; ++q)
511  if(tabulated_real_quantities[q])
512  ++(real_tabulated_iter[q]);
513  if(__star) ++tabulated_wind_sat_iter;
514  ++tabulated_mode_iter;
515  }
516  }
517 
519  const StellarEvolution::Interpolator &stellar_evol,
520  double *initial_Lstar,
521  double windK,
522  double wind_sat_freq,
523  double core_env_coupling_time,
524  std::vector<const Core::OneArgumentDiffFunction *>
525  &expected_real_quantities,
526  const ExpectedEvolutionMode<bool> &expected_wind_mode,
527  double max_age,
528  bool debug_mode
529  ) {
531  binary_mode;
532  single_mode.add_break(TSTART, Core::SINGLE);
533  binary_mode.add_break(TSTART, Core::BINARY);
534 
535  __star = make_const_lag_star(stellar_evol,
536  windK,
537  wind_sat_freq,
538  core_env_coupling_time,
539  1.0);//phase lag
540  evolve(0.0,//Wdisk
541  0.0,//tdisk
542  1.0,//initial semimajor
543  initial_Lstar,
544  0.0,//initial inclination
545  1.0,//planet mass
546  max_age,//planet formation age.
547  max_age);//end evolution age
548  expected_real_quantities[SEMIMAJOR] = &nan_func;
549  expected_real_quantities[ECCENTRICITY] = &nan_func;
550  expected_real_quantities[CONV_INCLINATION] = &zero_func;
551  expected_real_quantities[RAD_INCLINATION] = &zero_func;
552  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
553  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
554 
556  expected_real_quantities,
557  single_mode,
558  expected_wind_mode,
559  TSTART,
560  max_age,
561  debug_mode);
562 
563  if(initial_Lstar[0] == 0) return;
564 
565  for(double phase_lag = 0.0; phase_lag < 1.5; phase_lag += 1.0)
566  for(
567  double mplanet = 0.0;
568  mplanet < 1.5 - phase_lag;
569  mplanet += 1.0
570  ) {
571  delete __star;
572  delete __system;
573  delete __solver;
574 
575  __star = make_const_lag_star(stellar_evol,
576  windK,
577  wind_sat_freq,
578  core_env_coupling_time,
579  phase_lag);
580  evolve(0.0,//Wdisk
581  0.0,//tdisk
582  1.0,//initial semimajor
583  initial_Lstar,
584  0.0,//initial inclination
585  mplanet,//planet mass
586  TSTART,//planet formation age.
587  max_age);//end evolution age
588 
589  expected_real_quantities[SEMIMAJOR] = &one_func;
590  expected_real_quantities[ECCENTRICITY] = &zero_func;
592  expected_real_quantities,
593  binary_mode,
594  expected_wind_mode,
595  TSTART,
596  max_age,
597  debug_mode);
598  delete __system;
599  delete __solver;
600 
601  evolve(0.0,//Wdisk
602  0.0,//tdisk
603  200.0,//initial semimajor
604  initial_Lstar,
605  0.0,//initial inclination
606  mplanet,//planet mass
607  TSTART,//planet formation age.
608  max_age);//end evolution age
609 
610  expected_real_quantities[SEMIMAJOR] = &two_hundred_func;
612  expected_real_quantities,
613  binary_mode,
614  expected_wind_mode,
615  TSTART,
616  max_age,
617  debug_mode);
618 
619  }
620  delete __star;
621  __star = NULL;
622  delete __system;
623  __system = NULL;
624  delete __solver;
625  __solver = NULL;
626 
627  }
628 
629  std::vector<const Core::OneArgumentDiffFunction *>
631  double phase_lag,
632  double secondary_mass,
633  bool decaying
634  )
635  {
636  std::vector<const Core::OneArgumentDiffFunction *>
637  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
638 
639  double msecondary_si = (secondary_mass
640  *
642  mprimary_si = Core::AstroConst::solar_mass,
643  alpha = (
644  2.4 * M_PI
645  *
646  std::sqrt(
647  Core::AstroConst::G * (msecondary_si + mprimary_si)
648  /
650  )
651  *
652  msecondary_si / mprimary_si
653  *
654  phase_lag * Core::AstroConst::Gyr
655  /
657  ),
658  a6p5_offset,
659  a0,
660  Lscale = (
661  -msecondary_si
662  /
663  std::pow(Core::AstroConst::solar_radius, 1.5)
664  *
665  std::sqrt(
667  /
668  (msecondary_si + Core::AstroConst::solar_mass)
669  )
670  *
672  );
673 
674  if(decaying) {
675  a6p5_offset = std::pow(2.0, 6.5) + 6.5 * alpha;
676  a0 = std::pow(a6p5_offset, 1.0 / 6.5);
677  } else {
678  a0 = 2.6;
679  a6p5_offset = std::pow(a0, 6.5);
680  }
681 
682  std::valarray<double> a6p5_poly_coef(2);
683  a6p5_poly_coef[0] = a6p5_offset;
684  a6p5_poly_coef[1] = (decaying ? -1.0 : 1.0) * 6.5 * alpha;
687  a6p5_poly_coef,
688  TSTART,
689  1.0
690  )
691  );
692  __temp_functions.push_back(a6p5_evol);
693 
694  FunctionToPower *sqrta_evol = new FunctionToPower(a6p5_evol, 1.0/13.0);
695  __temp_functions.push_back(sqrta_evol);
696 
697 
698  ExponentialPlusFunc *Lconv_unscaled = new ExponentialPlusFunc(
699  sqrta_evol,
700  (decaying ? 0.0 : -1e5) - std::sqrt(a0),
701  0
702  );
703  __temp_functions.push_back(Lconv_unscaled);
704 
705  expected_real_quantities[SEMIMAJOR] = new FunctionToPower(
706  a6p5_evol,
707  1.0 / 6.5
708  );
709  __temp_functions.push_back(expected_real_quantities[SEMIMAJOR]);
710 
711  expected_real_quantities[ECCENTRICITY] = &zero_func;
712  expected_real_quantities[CONV_INCLINATION] = &zero_func;
713  expected_real_quantities[RAD_INCLINATION] = &zero_func;
714  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
715  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
716  expected_real_quantities[CONV_ANGMOM] = new ScaledFunction(
717  Lconv_unscaled,
718  Lscale
719  );
720  __temp_functions.push_back(expected_real_quantities[CONV_ANGMOM]);
721  expected_real_quantities[RAD_ANGMOM] = &zero_func;
722 
723  return expected_real_quantities;
724 
725  }
726 
727  std::vector<const Core::OneArgumentDiffFunction *>
728  test_OrbitSolver::calculate_expected_disklocked_to_fast_to_locked(
729  double lgQ,
730  double tdisk,
731  double async,
732  double tsync,
733  double tend,
734  bool include_disk_lock
735  )
736  {
737  const double Q = std::pow(10.0, lgQ),
738  alpha = (
739  -4.5
740  *
741  std::sqrt(
743  /
744  (
746  *
748  )
749  )
750  *
752  *
754  /
756  ),
757  Lscale = (
759  /
760  std::pow(Core::AstroConst::solar_radius, 1.5)
761  *
762  std::sqrt(Core::AstroConst::G
763  /
764  (
766  +
767  Core::AstroConst::solar_mass
768  )
769  )
770  *
772  ),
773  beta = (
774  std::sqrt(
776  *
777  (
778  Core::AstroConst::solar_mass
779  +
781  )
782  )
783  *
785  /
786  std::pow(Core::AstroConst::solar_radius, 1.5)
787  ),
788  a6p5_offset = (std::pow(async, 6.5)
789  -
790  6.5 * alpha * tsync),
791  a_formation=std::pow(
792  a6p5_offset + 6.5 * alpha * tdisk,
793  1.0 / 6.5
794  ),
795  Ic = (
796  Lscale
797  *
798  (std::sqrt(a_formation) - std::sqrt(async))
799  /
800  (beta * (std::pow(async, -1.5)
801  -
802  0.5 * std::pow(a_formation, -1.5)))
803  ),
804  wdisk = (
805  0.5 * beta / std::pow(a_formation, 1.5)
806  *
807  (
808  1.0
809  +
810  10.0 * std::numeric_limits<double>::epsilon()
811  )
812  ),
813  wlocked = beta / std::pow(async, 1.5);
814 
815  std::valarray<double> a6p5_poly_coef(2);
816  a6p5_poly_coef[0] = a6p5_offset;
817  a6p5_poly_coef[1] = 6.5 * alpha;
820  a6p5_poly_coef,
821  tdisk,
822  tsync
823  ),
825  std::valarray<double>(Ic * wdisk, 1),
826  TSTART,
827  tdisk
828  ),
830  std::valarray<double>(Ic * wlocked, 1),
831  tsync,
832  tend
833  ),
835  std::valarray<double>(Core::NaN, 2),
836  TSTART,
837  tdisk
838  ),
840  std::valarray<double>(async, 1),
841  tsync,
842  tend
843  ),
845  std::valarray<double>(),
846  TSTART,
847  tend
848  ),
850  std::valarray<double>(),
851  tdisk,
852  tend
853  );
854  __temp_functions.push_back(a6p5_evol);
855  __temp_functions.push_back(Lconv_disk);
856  __temp_functions.push_back(Lconv_locked);
857  __temp_functions.push_back(nan_disk);
858  __temp_functions.push_back(a_locked);
859  __temp_functions.push_back(Lrad_evol);
860  __temp_functions.push_back(zero_e);
861 
862  FunctionToPower *a_fast = new FunctionToPower(a6p5_evol,
863  1.0 / 6.5),
864  *sqrta_evol = new FunctionToPower(a6p5_evol,
865  1.0 / 13.0);
866  __temp_functions.push_back(a_fast);
867  __temp_functions.push_back(sqrta_evol);
868 
869  ExponentialPlusFunc *Lconv_unscaled = new ExponentialPlusFunc(
870  sqrta_evol,
871  -Ic * wdisk / Lscale - std::sqrt(a_formation), 0
872  );
873  __temp_functions.push_back(Lconv_unscaled);
874 
875  ScaledFunction *Lconv_fast = new ScaledFunction(Lconv_unscaled,
876  -Lscale);
877  __temp_functions.push_back(Lconv_fast);
878 
879  PiecewiseFunction *a_evol = new PiecewiseFunction,
880  *e_evol = new PiecewiseFunction,
881  *Lconv_evol = new PiecewiseFunction;
882  __temp_functions.push_back(a_evol);
883  __temp_functions.push_back(e_evol);
884  __temp_functions.push_back(Lconv_evol);
885 
887 
888  if(include_disk_lock) {
889  a_evol->add_piece(nan_disk);
890  e_evol->add_piece(nan_disk);
891  Lconv_evol->add_piece(Lconv_disk);
892  zero_quantity = &zero_func;
893  } else {
894  zero_quantity = zero_e;
895  }
896 
897  a_evol->add_piece(a_fast);
898  a_evol->add_piece(a_locked);
899 
900  e_evol->add_piece(zero_e);
901 
902  Lconv_evol->add_piece(Lconv_fast);
903  Lconv_evol->add_piece(Lconv_locked);
904 
905  std::vector<const Core::OneArgumentDiffFunction *>
906  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
907 
908  expected_real_quantities[SEMIMAJOR] = a_evol;
909  expected_real_quantities[ECCENTRICITY] = e_evol;
910  expected_real_quantities[CONV_INCLINATION] = zero_quantity;
911  expected_real_quantities[RAD_INCLINATION] = zero_quantity;
912  expected_real_quantities[CONV_PERIAPSIS] = zero_quantity;
913  expected_real_quantities[RAD_PERIAPSIS] = zero_quantity;
914  expected_real_quantities[CONV_ANGMOM] = Lconv_evol;
915  expected_real_quantities[RAD_ANGMOM] = zero_quantity;
916 
917  return expected_real_quantities;
918  }
919 
920  std::vector<const Core::OneArgumentDiffFunction *>
921  test_OrbitSolver::calculate_expected_polar_1_0(double tdisk,
922  double wstar,
923  double worb)
924 
925  {
926  double aorb = std::pow(
927  (
929  *
930  (
932  +
934  )
935  )
936  /
937  std::pow(
938  worb / Core::AstroConst::day,
939  2
940  ),
941  1.0 / 3.0
943 
946  std::valarray<double>(Core::NaN, 1),
947  TSTART,
948  tdisk
949  ),
951  std::valarray<double>(aorb, 1),
952  tdisk,
953  MAX_AGE
954  ),
956  std::valarray<double>(),
957  tdisk,
958  MAX_AGE
959  ),
960  *disk_zero_evol = new StellarEvolution::PolynomialEvolutionQuantity(
961  std::valarray<double>(),
962  TSTART,
963  tdisk
964  ),
966  std::valarray<double>(M_PI / 2.0, 1),
967  tdisk,
968  MAX_AGE
969  );
970  __temp_functions.push_back(disk_nan_evol);
971  __temp_functions.push_back(fixed_a_evol);
972  __temp_functions.push_back(fixed_e_evol);
973  __temp_functions.push_back(disk_zero_evol);
974  __temp_functions.push_back(halfpi_evol);
975 
976  PiecewiseFunction *a_evol = new PiecewiseFunction,
977  *e_evol = new PiecewiseFunction,
978  *conv_incl_evol = new PiecewiseFunction,
979  *rad_incl_evol = new PiecewiseFunction;
980  __temp_functions.push_back(a_evol);
981  __temp_functions.push_back(e_evol);
982  __temp_functions.push_back(conv_incl_evol);
983  __temp_functions.push_back(rad_incl_evol);
984 
985  a_evol->add_piece(disk_nan_evol);
986  a_evol->add_piece(fixed_a_evol);
987 
988  e_evol->add_piece(disk_nan_evol);
989  e_evol->add_piece(fixed_e_evol);
990 
991  conv_incl_evol->add_piece(disk_zero_evol);
992  conv_incl_evol->add_piece(halfpi_evol);
993 
994  rad_incl_evol->add_piece(disk_zero_evol);
995  rad_incl_evol->add_piece(halfpi_evol);
996 
997  std::vector<const Core::OneArgumentDiffFunction *>
998  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
999 
1000  expected_real_quantities[SEMIMAJOR] = a_evol;
1001  expected_real_quantities[ECCENTRICITY] = e_evol;
1002  expected_real_quantities[CONV_INCLINATION] = conv_incl_evol;
1003  expected_real_quantities[RAD_INCLINATION] = rad_incl_evol;
1004  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1005  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1006  expected_real_quantities[CONV_ANGMOM] =
1008  std::valarray<double>(wstar, 1),
1009  TSTART,
1010  MAX_AGE
1011  );
1012  __temp_functions.push_back(
1013  expected_real_quantities[CONV_ANGMOM]
1014  );
1015  expected_real_quantities[RAD_ANGMOM] = &one_func;
1016 
1017  return expected_real_quantities;
1018  }
1019 
1020  std::vector<const Core::OneArgumentDiffFunction *>
1021  test_OrbitSolver::calculate_expected_polar_2_0(double tdisk,
1022  double wstar,
1023  double worb,
1024  double phase_lag,
1025  double &lconv_decay_rate,
1026  double &semimajor)
1027  {
1028  semimajor = std::pow(
1029  (
1031  *
1032  (
1034  +
1036  )
1037  )
1038  /
1039  std::pow(
1040  worb / Core::AstroConst::day,
1041  2
1042  ),
1043  1.0 / 3.0
1045  lconv_decay_rate = (
1046  0.3 * M_PI
1047  *
1048  (
1050  *
1051  std::pow(
1052  (
1054  /
1055  std::pow(
1056  semimajor * Core::AstroConst::solar_radius,
1057  3
1058  )
1059  ),
1060  2
1061  )
1062  *
1063  std::pow(Core::AstroConst::solar_radius, 5)
1064  )
1065  /
1066  (
1068  *
1069  std::pow(Core::AstroConst::solar_radius, 2)
1070  )
1071  *
1073  *
1075  *
1076  phase_lag
1077  );
1078  double lorb = (
1079  (
1081  /
1083  )
1084  /
1085  (
1086  1.0
1087  +
1089  /
1091  )
1092  *
1093  semimajor * semimajor
1094  *
1095  worb
1096  );
1097  double lconv_offset = lconv_decay_rate * tdisk;
1098 
1099  std::valarray<double> spindown_coef(2);
1100  spindown_coef[0] = wstar + lconv_decay_rate * tdisk;
1101  spindown_coef[1] = - lconv_decay_rate;
1102 
1103  std::valarray<double> conv_cosinc_numer_coef(3),
1104  conv_cosinc_denom_coef(2),
1105  rad_cosinc_numer_coef(3),
1106  rad_cosinc_denom_coef(3);
1107  conv_cosinc_numer_coef[0] = - (
1108  (2.0 * wstar + lconv_offset) * lconv_offset
1109  );
1110  conv_cosinc_numer_coef[1] = 2.0 * wstar * lconv_decay_rate;
1111  conv_cosinc_numer_coef[2] = -std::pow(lconv_decay_rate, 2);
1112 
1113  conv_cosinc_denom_coef[0] = 2.0 * lorb * (wstar + lconv_offset);
1114  conv_cosinc_denom_coef[1] = -2.0 * lconv_decay_rate * lorb;
1115 
1116  conv_cosinc_numer_coef[0] += conv_cosinc_denom_coef[0];
1117  conv_cosinc_numer_coef[1] += conv_cosinc_denom_coef[1];
1118 
1119  rad_cosinc_numer_coef[0] = - 2.0 * lorb * lconv_decay_rate * tdisk;
1120  rad_cosinc_numer_coef[1] = 2.0 * lorb * lconv_decay_rate;
1121 
1122  rad_cosinc_denom_coef[0] = (2.0 * lorb * lorb
1123  -
1124  2.0 * wstar * lconv_decay_rate * tdisk
1125  -
1126  std::pow(lconv_decay_rate * tdisk, 2));
1127  rad_cosinc_denom_coef[1] =
1128  2.0 * lconv_decay_rate * (worb + lconv_decay_rate * tdisk);
1129  rad_cosinc_denom_coef[2] = - std::pow(lconv_decay_rate, 2);
1130 
1131  rad_cosinc_numer_coef += rad_cosinc_denom_coef;
1132 
1134  *disk_nan_evol =
1136  std::valarray<double>(Core::NaN, 1),
1137  TSTART,
1138  tdisk
1139  ),
1140  *fixed_a_evol =
1142  std::valarray<double>(semimajor, 1),
1143  tdisk,
1144  MAX_AGE
1145  ),
1146  *fixed_e_evol
1148  std::valarray<double>(),
1149  tdisk,
1150  MAX_AGE
1151  ),
1152  *disk_cosinc_evol =
1154  std::valarray<double>(2.0, 1),
1155  TSTART,
1156  tdisk
1157  ),
1158  *conv_cosinc_binary_numer =
1160  conv_cosinc_numer_coef,
1161  tdisk, MAX_AGE
1162  ),
1163  *conv_cosinc_binary_denom =
1165  conv_cosinc_denom_coef,
1166  tdisk,
1167  MAX_AGE
1168  ),
1169  *rad_cosinc_binary_numer =
1171  rad_cosinc_numer_coef,
1172  tdisk,
1173  MAX_AGE
1174  ),
1175  *rad_cosinc_binary_denom =
1177  rad_cosinc_denom_coef,
1178  tdisk,
1179  MAX_AGE
1180  ),
1181  *lconv_disk =
1183  std::valarray<double>(wstar, 1),
1184  TSTART,
1185  tdisk
1186  ),
1187  *lconv_spindown =
1189  spindown_coef,
1190  tdisk,
1191  MAX_AGE
1192  );
1193  __temp_functions.push_back(disk_nan_evol);
1194  __temp_functions.push_back(fixed_a_evol);
1195  __temp_functions.push_back(fixed_e_evol);
1196  __temp_functions.push_back(disk_cosinc_evol);
1197  __temp_functions.push_back(conv_cosinc_binary_numer);
1198  __temp_functions.push_back(conv_cosinc_binary_denom);
1199  __temp_functions.push_back(rad_cosinc_binary_numer);
1200  __temp_functions.push_back(rad_cosinc_binary_denom);
1201  __temp_functions.push_back(lconv_disk);
1202  __temp_functions.push_back(lconv_spindown);
1203 
1204  FunctionRatio *conv_cosinc_binary = new FunctionRatio(
1205  conv_cosinc_binary_numer,
1206  conv_cosinc_binary_denom
1207  );
1208  __temp_functions.push_back(conv_cosinc_binary);
1209  FunctionRatio *rad_cosinc_binary = new FunctionRatio(
1210  rad_cosinc_binary_numer,
1211  rad_cosinc_binary_denom
1212  );
1213  __temp_functions.push_back(rad_cosinc_binary);
1214 
1215  PiecewiseFunction *a_evol = new PiecewiseFunction,
1216  *e_evol = new PiecewiseFunction,
1217  *conv_cosinc_evol = new PiecewiseFunction,
1218  *rad_cosinc_evol = new PiecewiseFunction,
1219  *lconv_evol = new PiecewiseFunction;
1220  __temp_functions.push_back(a_evol);
1221  __temp_functions.push_back(e_evol);
1222  __temp_functions.push_back(conv_cosinc_evol);
1223  __temp_functions.push_back(rad_cosinc_evol);
1224  __temp_functions.push_back(lconv_evol);
1225 
1226  a_evol->add_piece(disk_nan_evol);
1227  a_evol->add_piece(fixed_a_evol);
1228 
1229  e_evol->add_piece(disk_nan_evol);
1230  e_evol->add_piece(fixed_e_evol);
1231 
1232  conv_cosinc_evol->add_piece(disk_cosinc_evol);
1233  conv_cosinc_evol->add_piece(conv_cosinc_binary);
1234 
1235  rad_cosinc_evol->add_piece(disk_cosinc_evol);
1236  rad_cosinc_evol->add_piece(rad_cosinc_binary);
1237 
1238  lconv_evol->add_piece(lconv_disk);
1239  lconv_evol->add_piece(lconv_spindown);
1240 
1241  std::vector<const Core::OneArgumentDiffFunction *>
1242  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1243 
1244  expected_real_quantities[SEMIMAJOR] = a_evol;
1245  expected_real_quantities[ECCENTRICITY] = e_evol;
1246  expected_real_quantities[CONV_INCLINATION] = conv_cosinc_evol;
1247  expected_real_quantities[RAD_INCLINATION] = rad_cosinc_evol;
1248  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1249  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1250  expected_real_quantities[CONV_ANGMOM] = lconv_evol;
1251  expected_real_quantities[RAD_ANGMOM] = &one_func;
1252 
1253  return expected_real_quantities;
1254  }
1255 
1256  std::vector<const Core::OneArgumentDiffFunction *>
1257  test_OrbitSolver::calculate_expected_oblique_m_0(
1258  unsigned m,
1259  double tdisk,
1260  double worb,
1261  double initial_inc,
1262  double initial_wstar,
1263  double phase_lag,
1264  double &min_wstar
1265  )
1266  {
1267  assert(m == 1 || m == 2);
1268  double aorb = std::pow(
1269  (
1271  *
1272  (
1274  +
1276  )
1277  )
1278  /
1279  std::pow(
1280  worb / Core::AstroConst::day,
1281  2
1282  ),
1283  1.0 / 3.0
1285  double lorb = (Mjup_to_Msun
1286  /
1287  (1.0 + Mjup_to_Msun)
1288  *
1289  aorb * aorb
1290  *
1291  worb);
1292 
1293  double ltot = std::sqrt(
1294  std::pow(initial_wstar, 2)
1295  +
1296  2.0 * initial_wstar * lorb * std::cos(initial_inc)
1297  +
1298  std::pow(lorb, 2)
1299  );
1300 
1301  min_wstar = ltot - lorb;
1302 
1303  double linear_quantity_rate = (
1304  0.6 * M_PI
1305  *
1306  (
1308  *
1309  std::pow(
1310  (
1312  /
1313  std::pow(
1315  3
1316  )
1317  ),
1318  2
1319  )
1320  *
1321  std::pow(Core::AstroConst::solar_radius, 5)
1322  )
1323  /
1324  (
1326  *
1327  std::pow(Core::AstroConst::solar_radius, 2)
1328  )
1329  *
1331  *
1333  *
1334  phase_lag
1335  );
1336 
1339  std::valarray<double>(Core::NaN, 1),
1340  TSTART,
1341  tdisk
1342  );
1343  __temp_functions.push_back(disk_nan_evol);
1344 
1347  std::valarray<double>(aorb, 1),
1348  tdisk,
1349  MAX_AGE
1350  );
1351  __temp_functions.push_back(fixed_a_evol);
1352 
1355  std::valarray<double>(),
1356  tdisk,
1357  MAX_AGE
1358  );
1359  __temp_functions.push_back(fixed_e_evol);
1360 
1361  PiecewiseFunction *a_evol = new PiecewiseFunction,
1362  *e_evol = new PiecewiseFunction;
1363  __temp_functions.push_back(a_evol);
1364  __temp_functions.push_back(e_evol);
1365 
1366  a_evol->add_piece(disk_nan_evol);
1367  a_evol->add_piece(fixed_a_evol);
1368 
1369  e_evol->add_piece(disk_nan_evol);
1370  e_evol->add_piece(fixed_e_evol);
1371 
1372  Core::OneArgumentDiffFunction *lconv_evol;
1373  if(m == 1)
1374  lconv_evol =
1376  tdisk,
1377  ltot,
1378  lorb,
1379  initial_wstar,
1380  linear_quantity_rate
1381  );
1382  else
1383  lconv_evol =
1385  tdisk,
1386  ltot,
1387  lorb,
1388  initial_wstar,
1389  linear_quantity_rate / 2.0
1390  );
1391  __temp_functions.push_back(lconv_evol);
1392 
1393  ConservedLEConvObliquityEvolution *conv_obliq_evol =
1394  new ConservedLEConvObliquityEvolution(*lconv_evol,
1395  lorb,
1396  ltot,
1397  tdisk);
1398  __temp_functions.push_back(conv_obliq_evol);
1399 
1400  ConservedLERadObliquityEvolution *rad_obliq_evol =
1401  new ConservedLERadObliquityEvolution(*lconv_evol,
1402  *conv_obliq_evol,
1403  lorb,
1404  tdisk);
1405  __temp_functions.push_back(rad_obliq_evol);
1406 
1407  std::vector<const Core::OneArgumentDiffFunction *>
1408  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1409  expected_real_quantities[SEMIMAJOR] = a_evol;
1410  expected_real_quantities[ECCENTRICITY] = e_evol;
1411  expected_real_quantities[CONV_INCLINATION] = conv_obliq_evol;
1412  expected_real_quantities[RAD_INCLINATION] = rad_obliq_evol;
1413  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1414  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1415  expected_real_quantities[CONV_ANGMOM] = lconv_evol;
1416  expected_real_quantities[RAD_ANGMOM] = &one_func;
1417 
1418  return expected_real_quantities;
1419  }
1420 
1421  void test_OrbitSolver::test_disk_locked_no_stellar_evolution()
1422  {
1423  try {
1425  StellarEvolution::make_no_evolution();
1426  __star = make_const_lag_star(*no_evol,
1427  1.0,
1428  1.0,
1429  1.0);
1430 
1431  ExpectedEvolutionMode<Core::EvolModeType> expected_evol_mode;
1432  expected_evol_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
1433 
1434  ExpectedEvolutionMode<bool> expected_wind_mode;
1435  expected_wind_mode.add_break(TSTART, false);
1436 
1437  std::vector<const Core::OneArgumentDiffFunction *>
1438  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1439  expected_real_quantities[SEMIMAJOR] = &nan_func;
1440  expected_real_quantities[ECCENTRICITY] = &nan_func;
1441  expected_real_quantities[CONV_INCLINATION] = &zero_func;
1442  expected_real_quantities[RAD_INCLINATION] = &zero_func;
1443  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1444  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1445  expected_real_quantities[CONV_ANGMOM] = &one_func;
1446  expected_real_quantities[RAD_ANGMOM] = &one_func;
1447 
1448  evolve(1.0, MAX_AGE, 1.0, &one);
1450  expected_real_quantities,
1451  expected_evol_mode,
1452  expected_wind_mode,
1453  TSTART,
1454  MAX_AGE);
1455 
1456  delete __solver;
1457  delete __system;
1458 
1459  evolve(1.0, MAX_AGE, 1.0, &zero);
1460  expected_real_quantities[RAD_ANGMOM] = new ExponentialPlusFunc(
1461  &one_func,
1462  -std::exp(TSTART/2.0),
1463  -0.5
1464  );
1466  expected_real_quantities,
1467  expected_evol_mode,
1468  expected_wind_mode,
1469  TSTART,
1470  MAX_AGE);
1471 
1472  delete expected_real_quantities[RAD_ANGMOM];
1473  delete no_evol;
1474  } catch (Core::Error::General &ex) {
1475  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")+
1476  ex.what()+": "+ex.get_message()).c_str());
1477  } catch (std::exception &ex) {
1478  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")+
1479  ex.what()).c_str());
1480  }
1481  }
1482 
1483  void test_OrbitSolver::test_disk_locked_with_stellar_evolution()
1484  {
1485  try {
1487  StellarEvolution::make_linear_I_evolution();
1488 
1489  __star = make_const_lag_star(*evol1, 1.0, 1.0, 1.0);
1490 
1491  ExpectedEvolutionMode<Core::EvolModeType> expected_evol_mode;
1492  expected_evol_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
1493 
1494  ExpectedEvolutionMode<bool> expected_wind_mode;
1495  expected_wind_mode.add_break(TSTART, false);
1496 
1497  std::valarray<double> temp_array=std::valarray<double>(1.0, 2);
1498  temp_array[0] = -1;
1501  TSTART,
1502  MAX_AGE);
1503 
1504  std::vector<const Core::OneArgumentDiffFunction *>
1505  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1506  expected_real_quantities[SEMIMAJOR] = &nan_func;
1507  expected_real_quantities[ECCENTRICITY] = &nan_func;
1508  expected_real_quantities[CONV_INCLINATION] = &zero_func;
1509  expected_real_quantities[RAD_INCLINATION] = &zero_func;
1510  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1511  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1512  expected_real_quantities[CONV_ANGMOM] =
1514  std::valarray<double>(1.0, 2),
1515  TSTART,
1516  MAX_AGE
1517  );
1518  expected_real_quantities[RAD_ANGMOM] =
1519  new ExponentialPlusFunc(temp_poly, 1, -0.5);
1520 
1521  double initial_Lrad = TSTART - 1 + std::exp(-TSTART / 2.0);
1522  evolve(1.0,
1523  MAX_AGE,
1524  1.0,
1525  &initial_Lrad);
1527  expected_real_quantities,
1528  expected_evol_mode,
1529  expected_wind_mode,
1530  TSTART,
1531  MAX_AGE);
1532 
1533  delete expected_real_quantities[CONV_ANGMOM];
1534  delete expected_real_quantities[RAD_ANGMOM];
1535  delete temp_poly;
1536  delete __solver;
1537  delete __system;
1538  delete __star;
1539  delete evol1;
1540 
1541  std::valarray< std::valarray<double> > Ic_arr(
1542  std::valarray<double>(1.0, 1),
1543  2
1544  );
1545  Ic_arr[1][0]=-1.0/6.0;
1547  -1,
1548  std::valarray< std::valarray<double> >(//R
1549  std::valarray<double>(1.0, 1),
1550  1
1551  ),
1552  Ic_arr, //Iconv
1553  std::valarray< std::valarray<double> >(//Irad
1554  std::valarray<double>(1.0/6.0, 1),
1555  2
1556  ),
1557  std::valarray< std::valarray<double> >(//Rcore
1558  std::valarray<double>(0.5, 1),
1559  1
1560  ),
1561  std::valarray< std::valarray<double> >(//Mcore
1562  std::valarray<double>(1.0, 1),
1563  2
1564  )
1565  );
1566 
1567  __star = make_const_lag_star(evol2, 1.0, 1.0, 1.0);
1568 
1569  std::valarray<double> Lc_coef(1.0, 2);
1570  Lc_coef[1]=-1.0/6.0;
1571  expected_real_quantities[SEMIMAJOR] = &nan_func;
1572  expected_real_quantities[ECCENTRICITY] = &nan_func;
1573  expected_real_quantities[CONV_INCLINATION] = &zero_func;
1574  expected_real_quantities[RAD_INCLINATION] = &zero_func;
1575  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
1576  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
1577  expected_real_quantities[CONV_ANGMOM] =
1579  TSTART,
1580  MAX_AGE);
1581  expected_real_quantities[RAD_ANGMOM] =
1583  std::valarray<double>(1.0/6.0, 2),
1584  TSTART,
1585  MAX_AGE
1586  );
1587  initial_Lrad = (TSTART / 2.0 + 1.0) / 6.0;
1588  evolve(1.0,
1589  MAX_AGE,
1590  1.0,
1591  &initial_Lrad);
1593  expected_real_quantities,
1594  expected_evol_mode,
1595  expected_wind_mode,
1596  TSTART,
1597  MAX_AGE);
1598 
1599  delete expected_real_quantities[CONV_ANGMOM];
1600  delete expected_real_quantities[RAD_ANGMOM];
1601  } catch (Core::Error::General &ex) {
1602  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")
1603  +
1604  ex.what()+": "+ex.get_message()).c_str());
1605  } catch (std::exception &ex) {
1606  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")
1607  +
1608  ex.what()).c_str());
1609  }
1610  }
1611 
1612  void test_OrbitSolver::test_no_planet_evolution()
1613  {
1614  try {
1615  const double rt2 = std::sqrt(2.0);
1616 
1618  *stellar_evol = StellarEvolution::make_no_evolution();
1619  double initial_Lstar[] = {0.0, 0.0};
1620 
1621  std::vector<const Core::OneArgumentDiffFunction *>
1622  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
1623  expected_real_quantities[CONV_ANGMOM] = &zero_func;
1624  expected_real_quantities[RAD_ANGMOM] = &zero_func;
1625  ExpectedEvolutionMode<bool> unsat_wind_mode, sat_wind_mode;
1626  unsat_wind_mode.add_break(TSTART, false);
1627  sat_wind_mode.add_break(TSTART, true);
1628 
1629  test_no_planet_scenario(*stellar_evol,
1630  initial_Lstar,
1631  1.0,//Wind K
1632  2.0,//wind sat freq.
1633  Core::Inf,//core-env coupling timescale
1634  expected_real_quantities,
1635  unsat_wind_mode);
1636 
1637  delete stellar_evol;
1638  stellar_evol = StellarEvolution::make_linear_I_evolution();
1639 
1640  initial_Lstar[0] = 1.0;
1641  expected_real_quantities[CONV_ANGMOM] = &one_func;
1642  test_no_planet_scenario(*stellar_evol,
1643  initial_Lstar,
1644  0.0,//Wind K
1645  2.0,//wind sat freq.
1646  Core::Inf,//core-env coupling timescale
1647  expected_real_quantities,
1648  unsat_wind_mode);
1649 
1650 
1651  initial_Lstar[0] = 0.5 * (1.0 + std::exp(-TSTART));
1652  initial_Lstar[1] = 0.5 * (1.0 - std::exp(-TSTART));
1653 
1655  std::valarray<double>(0.5, 1),
1656  TSTART,
1657  MAX_AGE
1658  );
1659  expected_real_quantities[CONV_ANGMOM] = new ExponentialPlusFunc(
1660  &half_func,
1661  0.5,
1662  -1.0
1663  );
1664  expected_real_quantities[RAD_ANGMOM] = new ExponentialPlusFunc(
1665  &half_func,
1666  -0.5,
1667  -1.0
1668  );
1669  test_no_planet_scenario(*stellar_evol,
1670  initial_Lstar,
1671  0.0,//Wind K
1672  1.0,//wind sat freq.
1673  1.0,//core-env coupling timescale
1674  expected_real_quantities,
1675  unsat_wind_mode);
1676 
1677  delete expected_real_quantities[CONV_ANGMOM];
1678  delete expected_real_quantities[RAD_ANGMOM];
1679 
1680  initial_Lstar[0] = 1.0/(1.0+TSTART);
1681  initial_Lstar[1] = 1.0;
1682 
1683  double wind_sat_age = std::pow(2.0, 0.25) - 1;
1684  std::valarray<double> late_denom_coef(3);
1685  late_denom_coef[0] = 2.0 * rt2 - 2.0;
1686  late_denom_coef[1] = 4.0 * rt2;
1687  late_denom_coef[2] = 2.0 * rt2;
1689  one_func_early(std::valarray<double>(1.0, 1),
1690  TSTART, wind_sat_age),
1691  one_plus_t(std::valarray<double>(1.0, 2), TSTART, MAX_AGE),
1692  late_denom2(late_denom_coef, wind_sat_age, MAX_AGE);
1693  FunctionToPower late_denom(&late_denom2, 0.5);
1694  FunctionRatio early_solution(&one_func_early, &one_plus_t),
1695  late_solution(&one_plus_t, &late_denom);
1696  PiecewiseFunction full_solution;
1697  full_solution.add_piece(&early_solution);
1698  full_solution.add_piece(&late_solution);
1699 
1700  expected_real_quantities[CONV_ANGMOM] = &full_solution;
1701  expected_real_quantities[RAD_ANGMOM] = &one_func;
1702  ExpectedEvolutionMode<bool> changing_wind_mode;
1703  changing_wind_mode.add_break(TSTART, true);
1704  changing_wind_mode.add_break(wind_sat_age, false);
1705 
1706  test_no_planet_scenario(*stellar_evol,
1707  initial_Lstar,
1708  2.0,//Wind K
1709  1.0 / rt2, //wind sat freq.
1710  Core::Inf,//core-env coupling timescale
1711  expected_real_quantities,
1712  changing_wind_mode);
1713 
1714  double b1 = (std::sqrt(2) - 1) / (2.0 * rt2),
1715  b2 = (std::sqrt(2) + 1) / (2.0 * rt2);
1716  initial_Lstar[0] = (b1 * std::exp(-TSTART / (2.0 + rt2))
1717  +
1718  b2 * std::exp(-TSTART / (2.0 - rt2)));
1719  initial_Lstar[1] = (
1720  0.5 / rt2 * std::exp(-1.0 / (2.0 + rt2) * (TSTART))
1721  -
1722  0.5 / rt2 * std::exp(-1.0 / (2.0 - rt2) * (TSTART))
1723  );
1724 
1726  Lc1(&zero_func, b1, -1.0 / (2.0 + rt2)),
1727  Lc2(&zero_func, b2, -1.0 / (2.0 - rt2)),
1728  Lr1(&zero_func, 0.5 / rt2, -1.0 / (2.0 + rt2)),
1729  Lr2(&zero_func, -0.5 / rt2, -1.0 / (2.0 - rt2));
1730 
1731  expected_real_quantities[CONV_ANGMOM] = new FuncPlusFunc(&Lc1,
1732  &Lc2);
1733  expected_real_quantities[RAD_ANGMOM] = new FuncPlusFunc(&Lr1,
1734  &Lr2);
1735  delete stellar_evol;
1736  stellar_evol = StellarEvolution::make_no_evolution();
1737  test_no_planet_scenario(*stellar_evol,
1738  initial_Lstar,
1739  100.0,//Wind K
1740  0.1,//wind sat freq.
1741  1.0,//core-env coupling timescale
1742  expected_real_quantities,
1743  sat_wind_mode,
1744  2.0);
1745  delete expected_real_quantities[CONV_ANGMOM];
1746  delete expected_real_quantities[RAD_ANGMOM];
1747 
1748  delete stellar_evol;
1749  } catch (Core::Error::General &ex) {
1750  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")+
1751  ex.what()+": "+ex.get_message()).c_str());
1752  } catch (std::exception &ex) {
1753  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")+
1754  ex.what()).c_str());
1755  }
1756  }
1757 
1758  void test_OrbitSolver::test_unlocked_evolution()
1759  {
1760  try {
1762  binary_mode.add_break(TSTART, Core::BINARY);
1763  ExpectedEvolutionMode<bool> unsat_wind_mode, sat_wind_mode;
1764  unsat_wind_mode.add_break(TSTART, false);
1765  sat_wind_mode.add_break(TSTART, true);
1766 
1768  *no_evol = StellarEvolution::make_no_evolution(1.0);
1769 
1770  const double mplanet = 100;
1771  double lag = 1e-8 / mplanet;
1772 
1773  std::vector<const Core::OneArgumentDiffFunction *>
1774  expected_real_quantities = calculate_expected_unlocked_evolution(
1775  lag,
1776  mplanet
1777  );
1778 
1779  __star = make_const_lag_star(*no_evol,
1780  0.0,//wind K
1781  100.0,//wsat
1782  Core::Inf,//tcoup
1783  lag);
1784 
1785  while(true) {
1786  double initial_a = (
1787  *expected_real_quantities[SEMIMAJOR]
1788  )(TSTART);
1789 
1790  std::valarray<double> initial_L(3);
1791  initial_L[0] = (*expected_real_quantities[CONV_ANGMOM])(
1792  TSTART
1793  );
1794  initial_L[1] = 0.0;
1795  initial_L[2] = 0.0;
1796 
1797  evolve(0.0,//wdisk
1798  TSTART,//tdisk
1799  initial_a,
1800  &(initial_L[0]),
1801  0.0,//initial inclination
1802  mplanet,//planet mass
1803  Core::NaN,//tplanet
1804  1.0,//stop evolution age
1805  0.0001);//Rplanet
1807  expected_real_quantities,
1808  binary_mode,
1809  unsat_wind_mode,
1810  TSTART,
1811  1.0);
1812 
1813  delete __system;
1814  delete __solver;
1815 
1816  expected_real_quantities =
1818  lag,
1819  mplanet,
1820  false
1821  );
1822 
1823  initial_a = (*expected_real_quantities[SEMIMAJOR])(TSTART);
1824  initial_L[0] = (*expected_real_quantities[CONV_ANGMOM])(TSTART);
1825 
1826  evolve(0.0,//wdisk
1827  TSTART,//tdisk
1828  initial_a,
1829  &(initial_L[0]),
1830  0.0,//initial inclination
1831  mplanet,//planet mass
1832  Core::NaN,//tplanet
1833  1.0,//stop evolution age
1834  0.0001);//Rplanet
1836  expected_real_quantities,
1837  binary_mode,
1838  sat_wind_mode,
1839  TSTART,
1840  1.0);
1841 
1842  if(__star) {
1843  delete __star;
1844  __star = NULL;
1845 
1846  __primary_planet = new Planet::Planet(1.0, 1.0, 1.0);
1847  __primary_planet->zone().setup(
1848  std::vector<double>(),//Wtide breaks
1849  std::vector<double>(),//W* breaks
1850  std::vector<double>(1, 0.0),//Wtide pow.
1851  std::vector<double>(1, 0.0),//W* pow.
1852  lag
1853  );
1854  } else
1855  break;
1856  }
1857 
1858  delete no_evol;
1859  } catch (Core::Error::General &ex) {
1860  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")
1861  +
1862  ex.what()+": "+ex.get_message()).c_str());
1863  } catch (std::exception &ex) {
1864  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")
1865  +
1866  ex.what()).c_str());
1867  }
1868  }
1869 
1874  double locked_unsat_eq(double a, void *params)
1875  {
1876  double *dbl_par = static_cast<double *>(params);
1877  double alpha = dbl_par[0],
1878  beta = dbl_par[1],
1879  kappa = dbl_par[2],
1880  c = dbl_par[3],
1881  t = dbl_par[4];
1882  return (
1883  0.1 * alpha * std::pow(a, 5)
1884  -
1885  0.5 * beta * std::pow(a, 3)
1886  +
1887  kappa*t
1888  -
1889  c
1890  );
1891  }
1892 
1897  double locked_sat_eq(double a, void *params)
1898  {
1899  double *dbl_par = static_cast<double *>(params);
1900  double alpha = dbl_par[0],
1901  beta = dbl_par[1],
1902  kappa = dbl_par[2],
1903  c = dbl_par[3],
1904  t = dbl_par[4];
1905  return (
1906  alpha * a * a / 4.0
1907  -
1908  1.5 * beta * std::log(a)
1909  +
1910  kappa * t
1911  -
1912  c
1913  );
1914  }
1915 
1921  double locked_unsat_deriv(double a, void *params)
1922  {
1923  double *dbl_par = static_cast<double *>(params);
1924  double alpha = dbl_par[0],
1925  beta = dbl_par[1];
1926  return 0.5 * alpha * std::pow(a, 4) - 1.5 * beta * std::pow(a, 2);
1927  }
1928 
1934  double locked_sat_deriv(double a, void *params)
1935  {
1936  double *dbl_par = static_cast<double *>(params);
1937  double alpha = dbl_par[0],
1938  beta = dbl_par[1];
1939  return alpha * a / 2.0 - 1.5 * beta / a;
1940  }
1941 
1947  void locked_unsat_eq_deriv(double a, void *params, double *f, double *df)
1948  {
1949  double *dbl_par = static_cast<double *>(params);
1950  double alpha = dbl_par[0],
1951  beta = dbl_par[1],
1952  kappa = dbl_par[2],
1953  c = dbl_par[3],
1954  t = dbl_par[4];
1955  *f = (
1956  0.1 * alpha * std::pow(a, 5)
1957  -
1958  0.5 * beta * std::pow(a, 3)
1959  +
1960  kappa * t
1961  -
1962  c
1963  );
1964  *df = (0.5 * alpha * std::pow(a, 4)
1965  -
1966  1.5 * beta * std::pow(a, 2));
1967  }
1968 
1974  void locked_sat_eq_deriv(double a, void *params, double *f, double *df)
1975  {
1976  double *dbl_par = static_cast<double *>(params);
1977  double alpha = dbl_par[0],
1978  beta = dbl_par[1],
1979  kappa = dbl_par[2],
1980  c = dbl_par[3],
1981  t = dbl_par[4];
1982  *f = (
1983  alpha * a * a / 4.0
1984  -
1985  1.5 * beta * std::log(a)
1986  +
1987  kappa * t
1988  -
1989  c
1990  );
1991  *df = alpha * a / 2.0 - 1.5 * beta / a;
1992  }
1993 
1994  void test_OrbitSolver::test_locked_evolution()
1995  {
1996  try {
1998  expected_mode.add_break(TSTART, Core::BINARY);
1999  ExpectedEvolutionMode<bool> expected_wind_mode;
2000  expected_wind_mode.add_break(TSTART, false);
2001  const double Ic = 0.001, Kwind = 1e-3, Kwind_s = 1;
2003  no_evol = StellarEvolution::make_no_evolution(1.0, Ic);
2004 
2005  double a1 = 3,
2007  /
2008  std::pow(Core::AstroConst::solar_radius, 1.5)
2009  *
2010  std::sqrt(
2012  /
2014  +
2016  )
2017  *
2019  beta = (
2020  Ic * std::sqrt(
2022  *
2023  (
2025  +
2027  )
2028  )
2029  *
2031  /
2032  std::pow(Core::AstroConst::solar_radius, 1.5)
2033  ),
2034  wsat_s = 0.1, //Must be adjusted if a1 is adjusted
2035 // wsat = Core::Inf,
2036  kappa=(
2037  Kwind
2038  *
2039  std::pow(
2040  (
2042  *
2043  (
2045  +
2047  )
2048  /
2049  std::pow(Core::AstroConst::solar_radius, 3)
2050  ),
2051  1.5
2052  )
2053  *
2054  std::pow(Core::AstroConst::day, 3)
2055  ),
2056  kappa_s = (
2057  Kwind_s * wsat_s * wsat_s *
2058  std::sqrt(
2060  *
2061  (
2063  +
2065  )
2066  /
2067  std::pow(Core::AstroConst::solar_radius, 3)
2068  )
2069  *
2071  ),
2072  int_const = (Lscale / 10.0 * std::pow(a1, 5)
2073  -
2074  beta / 2.0 * std::pow(a1, 3)
2075  +
2076  kappa),
2077  int_const_s = (Lscale / 4.0 * std::pow(a1, 2)
2078  -
2079  3.0 * beta / 2.0 * std::log(a1)
2080  +
2081  kappa_s);
2082 /* double solver_params[] = {Lscale, beta, kappa, int_const, 0.0};
2083  double a0 = solve(a1,
2084  0.0,
2085  1e-9,
2086  &locked_unsat_eq,
2087  &locked_unsat_deriv,
2088  &locked_unsat_eq_deriv,
2089  static_cast<void*>(solver_params));
2090  solver_params[4] = TSTART;
2091  double astart = solve(a0,
2092  0.0,
2093  1e-9,
2094  &locked_unsat_eq,
2095  &locked_unsat_deriv,
2096  &locked_unsat_eq_deriv,
2097  static_cast<void*>(solver_params));
2098  solver_params[2] = kappa_s;
2099  solver_params[3] = int_const_s;
2100  solver_params[4] = 0;
2101  double a0_s = solve(a1,
2102  0.0,
2103  1e-9,
2104  &locked_sat_eq,
2105  &locked_sat_deriv,
2106  &locked_sat_eq_deriv,
2107  static_cast<void*>(solver_params));
2108  solver_params[4] = TSTART;
2109  double astart_s = solve(a1,
2110  0.0,
2111  1e-9,
2112  &locked_sat_eq,
2113  &locked_sat_deriv,
2114  &locked_sat_eq_deriv,
2115  static_cast<void*>(solver_params));
2116  solver_params[4] = 1.0;
2117 
2118  double w0=std::sqrt(
2119  AstroConst::G*
2120  (AstroConst::solar_mass+AstroConst::jupiter_mass)/
2121  std::pow(a0*AstroConst::solar_radius, 3))*
2122  AstroConst::day,
2123  w0_s=std::sqrt(
2124  AstroConst::G*
2125  (AstroConst::solar_mass+AstroConst::jupiter_mass)/
2126  std::pow(a0_s*AstroConst::solar_radius, 3))*
2127  AstroConst::day,
2128  w1=std::sqrt(
2129  AstroConst::G*
2130  (AstroConst::solar_mass+AstroConst::jupiter_mass)/
2131  std::pow(a1_check*AstroConst::solar_radius, 3))*
2132  AstroConst::day,
2133  w1_s=std::sqrt(
2134  AstroConst::G*
2135  (AstroConst::solar_mass+AstroConst::jupiter_mass)/
2136  std::pow(a1_check_s*AstroConst::solar_radius, 3))*
2137  AstroConst::day;*/
2138  std::valarray<double> a_transform_coef(0.0, 6),
2139  t_coef(2),
2140  t_coef_s(2);
2141  a_transform_coef[5] = Lscale / 10.0;
2142  a_transform_coef[3] = -beta / 2.0;
2143  t_coef[0] = int_const;
2144  t_coef[1] = -kappa;
2145  t_coef_s[0] = int_const_s;
2146  t_coef_s[1] = -kappa_s;
2147  std::valarray<double> Lconv_term1_coef(0.0, 2),
2148  Lconv_term2_coef(0.0, 3),
2149  identity_coef(0.0, 2),
2150  a_term1_coef_s(0.0, 3),
2151  Lconv_term1_coef_s(0.0, 2),
2152  Lc_beta_coef_s(0.0, 2);
2153  Lconv_term1_coef[1] = 1.0 / beta * std::pow(10.0 / Lscale,
2154  3.0 / 10.0);
2155  Lconv_term2_coef[2] = -2.0 / std::pow(beta, 3);
2156  identity_coef[1] = 1;
2157  a_term1_coef_s[2] = Lscale / 4.0;
2158  Lconv_term1_coef_s[1] = 1.0 / beta * std::pow(4.0 / Lscale,
2159  3.0 / 4.0);
2160  Lc_beta_coef_s[1] = 1.0 / beta;
2161 
2163  a_transform(a_transform_coef, 0.0, Core::Inf),
2164  a_transform1_s(a_term1_coef_s, 0.0, Core::Inf),
2165  transformed_a_evol(t_coef, TSTART, 1.0),
2166  transformed_a_evol_s(t_coef_s, TSTART, 1.0),
2167  Lconv_term1_poly(Lconv_term1_coef, 0.0, Core::Inf),
2168  Lconv_term2_poly(Lconv_term2_coef, 0.0, Core::Inf),
2169  Lconv_term1_poly_s(Lconv_term1_coef_s, 0.0, Core::Inf),
2170  Lc_beta_s(Lc_beta_coef_s, 0.0, Core::Inf),
2171  identity(identity_coef, 0.0, Core::Inf);
2172  FunctionToPower L_transform1(&Lconv_term1_poly, -10.0 / 3.0),
2173  L_transform2(&Lconv_term2_poly, -1.0),
2174  L_transform1_s(&Lconv_term1_poly_s, -4.0 / 3.0);
2175  LogFunction log_a(&identity),
2176  log_Lc_beta_s(&Lc_beta_s);
2177  ScaledFunction a_transform2_s(&log_a, -1.5 * beta),
2178  L_transform2_s(&log_Lc_beta_s, beta);
2179  FuncPlusFunc L_transform(&L_transform1, &L_transform2),
2180  a_transform_s(&a_transform1_s, &a_transform2_s),
2181  L_transform_s(&L_transform1_s, &L_transform2_s);
2182 #if 0
2183  std::valarray<double> initial_orbit(2);
2184 
2185  initial_orbit[0]=astart;
2186  initial_orbit[1]=0.0;
2187  std::cout.precision(16);
2188  std::cout.setf(std::ios_base::scientific);
2189  Star star_not_saturated_wind_no_coupling(1.0, 0.0, Kwind, wsat, Inf,
2190  0.0, 0.0, 0.0, no_evol);
2191  Planet planet1(&star_not_saturated_wind_no_coupling, 1.0, 1.0, 1.0);
2192  StellarSystem system1(&star_not_saturated_wind_no_coupling, &planet1);
2193  OrbitSolver solver(tstart, 1.0, 1e-9);
2194  solver(system1, Inf, 0.0, a0, tstart, LOCKED_TO_PLANET, initial_orbit, true);
2195  TransformedSolution to_check(a_transform, L_transform, identity, -Inf);
2196  to_check(solver);
2197  test_solution(to_check, transformed_a_evol, transformed_a_evol,
2198  zero_func, tstart, 1.0, expected_mode);
2199 
2200  initial_orbit[0]=astart_s;
2201  initial_orbit[1]=0.0;
2202  Star star_saturated_wind_no_coupling(1.0, 0.0, Kwind_s, wsat_s, Inf,
2203  0.0, 0.0, 0.0, no_evol);
2204  Planet planet2(&star_saturated_wind_no_coupling, 1.0, 1.0, 1.0);
2205  StellarSystem system2(&star_saturated_wind_no_coupling, &planet2);
2206  solver(system2, Inf, 0.0, a0_s, tstart, LOCKED_TO_PLANET,
2207  initial_orbit, true);
2208  TransformedSolution to_check_s(a_transform_s, L_transform_s,
2209  identity, -Inf);
2210  to_check_s(solver);
2211  test_solution(to_check_s, transformed_a_evol_s, transformed_a_evol_s,
2212  zero_func, tstart, 1.0, expected_mode);
2213 #endif
2214  delete no_evol;
2215  } catch (Core::Error::General &ex) {
2216  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")
2217  +
2218  ex.what()+": "+ex.get_message()).c_str());
2219  } catch (std::exception &ex) {
2220  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")
2221  +
2222  ex.what()).c_str());
2223  }
2224  }
2225 
2226  void test_OrbitSolver::test_disklocked_to_locked_to_noplanet()
2227  {
2228  try {
2229  const double Ic = 0.001,
2230  Kwind = 2e-4,
2231  tdisk = 1,
2232  tfinal = 2;
2234  no_evol = StellarEvolution::make_no_evolution(1.0, Ic);
2235 
2236  double afinal = 1.75,
2238  /
2239  std::pow(Core::AstroConst::solar_radius, 1.5)
2240  *
2241  std::sqrt(
2243  /
2244  (
2246  +
2248  )
2249  )
2250  *
2252  beta = (
2253  Ic
2254  *
2255  std::sqrt(
2257  *
2258  (
2260  +
2262  )
2263  )
2264  *
2266  /
2267  std::pow(Core::AstroConst::solar_radius, 1.5)
2268  ),
2269  wsat = 1e100,
2270  kappa = (
2271  Kwind
2272  *
2273  std::pow(
2275  *
2276  (
2278  +
2280  )
2281  /
2282  std::pow(Core::AstroConst::solar_radius, 3),
2283  1.5
2284  )
2285  *
2286  std::pow(Core::AstroConst::day, 3)
2287  ),
2288  int_const = (Lscale / 10.0 * std::pow(afinal, 5)
2289  -
2290  beta / 2.0 * std::pow(afinal, 3)
2291  +
2292  kappa * tfinal);
2293  double solver_params[]={Lscale, beta, kappa, int_const, tdisk};
2294  double ainitial = solve(2.0 * afinal,
2295  0.0,
2296  1e-9,
2297  &locked_unsat_eq,
2300  static_cast<void*>(solver_params)),
2301  wdisk = (
2302  std::sqrt(
2304  *
2305  (
2307  +
2309  )
2310  /
2311  std::pow(ainitial * Core::AstroConst::solar_radius, 3)
2312  )
2313  *
2315  ) * (
2316  1.0
2317  +
2318  1e7 * std::numeric_limits<double>::epsilon()
2319  );
2320 
2322  *no_evol,
2323  Kwind,
2324  wsat,
2325  Core::Inf,//core-env coupling timescale
2327  /
2329  );
2330  Planet::Planet planet(Mjup_to_Msun, Rjup_to_Rsun);
2331  planet.configure(true, //init
2332  tdisk, //age
2333  __star->mass(), //mass
2334  ainitial * (1.0 - 1e-14),//planet formation semimajor
2335  0.0, //eccentricity
2336  &zero, //spin angmom
2337  NULL, //inclination
2338  NULL, //periapsis
2339  false, //locked surface
2340  true, //zero outer inclination
2341  true);//zero outer periapsis
2342 
2344  *__star,
2345  planet,
2346  ainitial * (1.0 - 1e-14), //semimajor
2347  0.0, //eccentricity
2348  0, //inclination
2349  wdisk, //Wdisk
2350  tdisk, //disk dissipation age
2351  tdisk //planet formation age
2352  );
2353 
2354  __system->configure(true, //init
2355  TSTART,
2356  Core::NaN, //semimajor
2357  Core::NaN, //eccentricity
2358  &zero, //spin angmom
2359  NULL, //inclination
2360  NULL, //periapsis
2361  Core::LOCKED_SURFACE_SPIN);
2362 
2363 
2364  double adestr = __system->minimum_separation(),
2365  tdestr = ((beta / 2.0 * std::pow(adestr, 3)
2366  +
2367  int_const
2368  -
2369  Lscale / 10.0 * std::pow(adestr, 5)) / kappa),
2370  Lc_at_destr = (beta / std::pow(adestr, 1.5)
2371  +
2372  Lscale * std::sqrt(adestr));
2373 
2374 
2375  std::valarray<double> a_transform_coef(0.0, 6), t_coef(2);
2376  a_transform_coef[5] = Lscale / 10.0;
2377  a_transform_coef[3] = -beta / 2.0;
2378  t_coef[0] = int_const;
2379  t_coef[1] = -kappa;
2380  std::valarray<double> Lconv_term1_coef(0.0, 2),
2381  Lconv_term2_coef(0.0, 3),
2382  identity_coef(0.0, 2),
2383  noplanet_Lconv_m2_coef(2);
2384  Lconv_term1_coef[1] = 1.0 / beta * std::pow(10.0 / Lscale, 0.3);
2385  Lconv_term2_coef[2] = -2.0 / std::pow(beta, 3);
2386  noplanet_Lconv_m2_coef[0] = (
2387  std::pow(Lc_at_destr, -2)
2388  -
2389  2.0 * Kwind * tdestr / std::pow(Ic, 3)
2390  );
2391  noplanet_Lconv_m2_coef[1] = 2.0 * Kwind / std::pow(Ic, 3);
2392  identity_coef[1] = 1;
2394  identity(identity_coef, -Core::Inf, Core::Inf),
2395  disk_nan_evol(std::valarray<double>(Core::NaN, 2),
2396  TSTART,
2397  tdisk),
2398  locked_a_transform(a_transform_coef, -Core::Inf, Core::Inf),
2399  locked_aLconv_evol(t_coef, tdisk, tdestr),
2400  locked_e_evol(std::valarray<double>(), tdisk, tdestr),
2401  noplanet_nan_evol(std::valarray<double>(Core::NaN, 2),
2402  tdestr,
2403  tfinal),
2404  disk_Lconv_evol(std::valarray<double>(wdisk * Ic, 1),
2405  TSTART,
2406  tdisk),
2407  noplanet_Lconv_m2_evol(noplanet_Lconv_m2_coef, tdestr, tfinal),
2408  Lconv_term1_poly(Lconv_term1_coef, -Core::Inf, Core::Inf),
2409  Lconv_term2_poly(Lconv_term2_coef, -Core::Inf, Core::Inf),
2410  Lrad_evol(std::valarray<double>(), TSTART, tfinal);
2411  FunctionToPower L_transform1(&Lconv_term1_poly, -10.0 / 3.0),
2412  L_transform2(&Lconv_term2_poly, -1.0),
2413  noplanet_Lconv_evol(&noplanet_Lconv_m2_evol, -0.5);
2414  LogFunction log_a(&identity);
2415  FuncPlusFunc locked_Lconv_transform(&L_transform1, &L_transform2);
2416  PiecewiseFunction a_evol, e_evol, Lconv_evol;
2417  a_evol.add_piece(&disk_nan_evol);
2418  a_evol.add_piece(&locked_aLconv_evol);
2419  a_evol.add_piece(&noplanet_nan_evol);
2420  e_evol.add_piece(&disk_nan_evol);
2421  e_evol.add_piece(&locked_e_evol);
2422  e_evol.add_piece(&noplanet_nan_evol);
2423  Lconv_evol.add_piece(&disk_Lconv_evol);
2424  Lconv_evol.add_piece(&locked_aLconv_evol);
2425  Lconv_evol.add_piece(&noplanet_Lconv_evol);
2426 
2427  std::vector< const Core::OneArgumentDiffFunction * >
2428  transformations(NUM_REAL_QUANTITIES - 1, &identity);
2429  TransformedSolution to_check(transformations, TSTART);
2430  transformations[SEMIMAJOR] = &locked_a_transform;
2431  transformations[CONV_ANGMOM] = &locked_Lconv_transform;
2432  to_check.add_transformation(transformations, tdisk);
2433  transformations[SEMIMAJOR] = &identity;
2434  transformations[CONV_ANGMOM] = &identity;
2435  to_check.add_transformation(transformations, tdestr);
2436 
2437  ExpectedEvolutionMode<Core::EvolModeType> expected_evol_mode;
2438  expected_evol_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
2439  expected_evol_mode.add_break(tdisk, Core::BINARY);
2440  expected_evol_mode.add_break(tdestr, Core::SINGLE);
2441 
2442  ExpectedEvolutionMode<bool> expected_wind_mode;
2443  expected_wind_mode.add_break(TSTART, false);
2444 
2446  __solver = new Evolve::OrbitSolver(tfinal, 1e-8);
2447  (*__solver)(*__system,
2448  (tfinal - __system->age()) / 10000.0, //time step
2449  std::list<double>()); //no required ages*/
2450 
2451  std::vector< const std::list<double> * >
2452  tabulated_evolution = get_evolution();
2453  const std::vector< const std::list<double> * > &
2454  transformed_evolution = to_check(tabulated_evolution);
2455 
2456  std::vector<const Core::OneArgumentDiffFunction *>
2457  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
2458  expected_real_quantities[SEMIMAJOR] = &a_evol;
2459  expected_real_quantities[ECCENTRICITY] = &e_evol;
2460  expected_real_quantities[CONV_INCLINATION] = &zero_func;
2461  expected_real_quantities[RAD_INCLINATION] = &zero_func;
2462  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
2463  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
2464  expected_real_quantities[CONV_ANGMOM] = &Lconv_evol;
2465  expected_real_quantities[RAD_ANGMOM] = &Lrad_evol;
2466 
2467  test_solution(transformed_evolution,
2468  expected_real_quantities,
2469  expected_evol_mode,
2470  expected_wind_mode,
2471  TSTART,
2472  tfinal);
2473  delete no_evol;
2474 
2475 #if 0
2476  Star star_not_saturated_wind_no_coupling(
2477  1.0,//M*
2478  1.0e-10,//Q*
2479  Kwind,
2480  wsat,
2481  Inf,//core-env coupling timescale
2482  0.0,//Q transition width
2483  wdisk,
2484  tdisk,
2485  no_evol);
2486  Planet planet1(&star_not_saturated_wind_no_coupling, 1.0, 1.0, 1.0);
2487  StellarSystem system1(&star_not_saturated_wind_no_coupling, &planet1);
2488  /* std::cout << std::endl << "alpha=" << Lscale
2489  << std::endl << "beta=" << beta
2490  << std::endl << "kappa=" << kappa
2491  << std::endl << "wdisk=" << wdisk << std::endl;
2492  std::cout << std::endl << "ainitial=" << ainitial << std::endl;
2493  std::cout << std::endl << "Destruction a=" << adestr
2494  << ", t=" << tdestr << ", " << ", Lc=" << Lc_at_destr
2495  << ", no planet time="
2496  << (Lscale*(std::pow(adestr, 5)-std::pow(afinal, 5))/10.0 -
2497  beta*(std::pow(adestr, 3)-std::pow(afinal, 3))/2.0)/kappa
2498  << std::endl;*/
2499 
2500  OrbitSolver solver(tstart, tfinal, 1e-8);
2501  solver(system1,
2502  Inf,//Max step
2503  0.0,//Planet formation age
2504  ainitial/AU_Rsun,//planet formation semimajor
2505  tstart);//Start age
2506 
2507  test_solution(to_check,
2508  a_evol,
2509  Lconv_evol,
2510  Lrad_evol,
2511  tstart,
2512  tfinal,
2513  expected_mode);
2514 #endif
2515  } catch (Core::Error::General &ex) {
2516  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")
2517  +
2518  ex.what()+": "+ex.get_message()).c_str());
2519  } catch (std::exception &ex) {
2520  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")
2521  +
2522  ex.what()).c_str());
2523  }
2524 
2525  }
2526 
2527  void test_OrbitSolver::test_disklocked_to_fast_to_noplanet()
2528  {
2529  try {
2530  const double TDISK = 1,
2531  TDESTR = 2,
2532  WDISK = 0.0,
2533  I_CONV = 1,
2534  L_SCALE = (
2536  /
2537  std::pow(Core::AstroConst::solar_radius, 1.5)
2538  *
2539  std::sqrt(
2541  /
2542  (
2544  +
2546  )
2547  )
2548  *
2550  );
2551 
2553  no_evol = StellarEvolution::make_no_evolution(1.0, I_CONV);
2554 
2555  double lgQ = 8,
2556  alpha = (
2557  -4.5
2558  *
2559  std::sqrt(
2561  /
2562  (
2564  *
2566  )
2567  )
2568  *
2569  Core::AstroConst::jupiter_mass / std::pow(10.0, lgQ)
2570  *
2572  );
2573 
2575  *no_evol,
2576  0.0,
2577  1.0,
2578  Core::Inf,
2579  lag_from_lgQ(lgQ,
2581  /
2582  Core::AstroConst::solar_mass))
2583  );
2584 
2585  double adestr = (
2586  2.44
2587  *
2588  std::pow(
2589  (
2590  __star->mass() * Core::AstroConst::solar_mass
2591  /
2593  ),
2594  1.0 / 3.0
2595  )
2596  *
2598  /
2600  );
2601  double a6p5_offset = (std::pow(adestr, 6.5)
2602  -
2603  6.5 * alpha * TDESTR),
2604  a_formation = std::pow(a6p5_offset + 6.5 * alpha * TDISK,
2605  1.0 / 6.5);
2606 
2607  evolve(WDISK,
2608  TDISK,
2609  a_formation,
2610  &zero);//Initial L*
2611 
2613  expected_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
2614  expected_mode.add_break(TDISK, Core::BINARY);
2615  expected_mode.add_break(TDESTR, Core::SINGLE);
2616 
2617  ExpectedEvolutionMode<bool> unsat_wind_mode;
2618  unsat_wind_mode.add_break(TSTART, false);
2619 
2620  std::valarray<double> a6p5_poly_coef(2);
2621  a6p5_poly_coef[0] = a6p5_offset;
2622  a6p5_poly_coef[1] = 6.5 * alpha;
2624  a6p5_evol(a6p5_poly_coef, TDISK, TDESTR),
2625  Lconv_disk(std::valarray<double>(I_CONV*WDISK, 1),
2626  TSTART,
2627  TDISK),
2628  Lconv_noplanet(
2629  std::valarray<double>(
2630  -L_SCALE * std::sqrt(a_formation) + I_CONV * WDISK,
2631  1
2632  ),
2633  TDESTR,
2634  MAX_AGE
2635  ),
2636  nan_disk(std::valarray<double>(Core::NaN, 2), TSTART, TDISK),
2637  nan_noplanet(std::valarray<double>(Core::NaN, 2),
2638  TDESTR,
2639  MAX_AGE),
2640  e_fast(std::valarray<double>(0.0, 1),
2641  TDISK,
2642  TDESTR),
2643  Lrad_evol(std::valarray<double>(), TSTART, MAX_AGE);
2644  FunctionToPower a_fast(&a6p5_evol, 1.0 / 6.5),
2645  sqrta_evol(&a6p5_evol, 1.0 / 13.0);
2646  ExponentialPlusFunc Lconv_unscaled(
2647  &sqrta_evol,
2648  I_CONV * WDISK / L_SCALE - std::sqrt(a_formation),
2649  0
2650  );
2651  ScaledFunction Lconv_fast(&Lconv_unscaled, L_SCALE);
2652 
2653  std::vector<const Core::OneArgumentDiffFunction *>
2654  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
2655 
2656  PiecewiseFunction a_evol, e_evol, conv_angmom_evol;
2657 
2658  a_evol.add_piece(&nan_disk);
2659  a_evol.add_piece(&a_fast);
2660  a_evol.add_piece(&nan_noplanet);
2661 
2662  e_evol.add_piece(&nan_disk);
2663  e_evol.add_piece(&e_fast);
2664  e_evol.add_piece(&nan_noplanet);
2665 
2666  conv_angmom_evol.add_piece(&Lconv_disk);
2667  conv_angmom_evol.add_piece(&Lconv_fast);
2668  conv_angmom_evol.add_piece(
2669  &Lconv_noplanet
2670  );
2671 
2672  expected_real_quantities[SEMIMAJOR] = &a_evol;
2673  expected_real_quantities[ECCENTRICITY] = &e_evol;
2674  expected_real_quantities[CONV_INCLINATION] = &zero_func;
2675  expected_real_quantities[RAD_INCLINATION] = &zero_func;
2676  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
2677  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
2678  expected_real_quantities[RAD_ANGMOM] = &zero_func;
2679  expected_real_quantities[CONV_ANGMOM] = &conv_angmom_evol;
2680  expected_real_quantities[RAD_ANGMOM] = &zero_func;
2681 
2683  expected_real_quantities,
2684  expected_mode,
2685  unsat_wind_mode,
2686  TSTART,
2687  MAX_AGE);
2688 
2689  delete no_evol;
2690  } catch (Core::Error::General &ex) {
2691  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")+
2692  ex.what()+": "+ex.get_message()).c_str());
2693  } catch (std::exception &ex) {
2694  TEST_ASSERT_MSG(false, (std::string("Unexpected exception thrown: ")+
2695  ex.what()).c_str());
2696  }
2697  }
2698 
2699  void test_OrbitSolver::test_disklocked_to_fast_to_locked()
2700  {
2701  try {
2702  const double lgQ = 8,
2703  tdisk = 1,
2704  async = 2.5,
2705  tsync = 2.0,
2706  tend = 3;
2707 
2708  std::vector<const Core::OneArgumentDiffFunction *>
2709  expected_real_quantities
2710  =
2711  calculate_expected_disklocked_to_fast_to_locked(
2712  lgQ,
2713  tdisk,
2714  async,
2715  tsync,
2716  tend
2717  );
2718 
2719  double wsync = Core::orbital_angular_velocity(1.0,
2720  Mjup_to_Msun,
2721  async),
2722  Lconv_sync = (*expected_real_quantities[CONV_ANGMOM])(
2723  (tsync + tend) / 2.0
2724  ),
2725  Iconv = Lconv_sync / wsync,
2726  Ldisk = (*expected_real_quantities[CONV_ANGMOM])(
2727  (TSTART + tdisk) / 2.0
2728  ),
2729  wdisk = Ldisk / Iconv,
2730  a_formation = (*expected_real_quantities[SEMIMAJOR])(tdisk),
2731  phase_lag = lag_from_lgQ(lgQ,
2733  /
2735 
2737  no_evol = StellarEvolution::make_no_evolution(1.0, Iconv);
2738 
2740  *no_evol,//evolution
2741  0.0,//Kwind
2742  100.0,//wsat
2743  Core::Inf,//tcoup
2744  phase_lag
2745  );
2746 
2747  ExpectedEvolutionMode<Core::EvolModeType> expected_evol_mode;
2748  expected_evol_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
2749  expected_evol_mode.add_break(tdisk, Core::BINARY);
2750 
2751  ExpectedEvolutionMode<bool> expected_wind_mode;
2752  expected_wind_mode.add_break(TSTART, false);
2753 
2754  while(true) {
2755  evolve(wdisk,//wdisk,
2756  tdisk,//tdisk
2757  a_formation,//initial semimajor
2758  (__star ? &zero : &Ldisk),//initial L*
2759  0.0,//initial inclination
2760  1.0,//planet_mass
2761  Core::NaN,//time of secondary formation
2762  tend,//max evolution age
2763  0.01,//planet radius
2764  1e-7,
2765  1e-3,
2766  std::list<double>(1, tsync));//precision
2767 
2769  expected_real_quantities,
2770  expected_evol_mode,
2771  expected_wind_mode,
2772  (__star ? TSTART : tdisk),
2773  tend);
2774  if(__star) {
2775  delete __star;
2776  __star = NULL;
2777 
2778  __primary_planet = new Planet::Planet(1.0, 1.0, Iconv);
2779  __primary_planet->zone().setup(
2780  std::vector<double>(),//Wtide breaks
2781  std::vector<double>(),//W* breaks
2782  std::vector<double>(1, 0.0),//Wtide pow.
2783  std::vector<double>(1, 0.0),//W* pow.
2784  phase_lag
2785  );
2786  } else
2787  break;
2788  }
2789  delete no_evol;
2790 
2791  } catch (Core::Error::General &ex) {
2792  TEST_ASSERT_MSG(
2793  false,
2794  (
2795  std::string("Unexpected exception thrown: ")
2796  +
2797  ex.what() + ": " + ex.get_message()).c_str()
2798  );
2799  } catch (std::exception &ex) {
2800  TEST_ASSERT_MSG(
2801  false,
2802  (
2803  std::string("Unexpected exception thrown: ")
2804  +
2805  ex.what()
2806  ).c_str()
2807  );
2808  }
2809  }
2810 
2811  void test_OrbitSolver::test_disklocked_to_locked_to_fast()
2812  {
2813  try {
2814  const double
2815  a0=3.2,
2816  abreak=3.0,
2817  adeath=2.0,
2818  tdisk=1,
2819  tbreak=2,
2820  tdeath=3,
2821  tend=4,
2822  Rp = (
2823  adeath
2824  *
2826  /
2828  /
2829  (
2830  2.44 * std::pow(Core::AstroConst::solar_mass
2831  /
2833  1.0 / 3.0)
2834  )
2835  ),
2836  beta = (
2837  std::sqrt(
2839  *
2840  (
2842  +
2844  )
2845  )
2846  *
2848  /
2849  std::pow(Core::AstroConst::solar_radius, 1.5)
2850  ),
2851  wdisk = beta / std::pow(a0, 1.5),
2852  gamma = (
2853  (std::pow(abreak, 6.5) - std::pow(adeath, 6.5))
2854  /
2855  (tdeath - tbreak)
2856  ),
2857  Q = (
2858  9.0 * 13.0 / 4.0
2859  *
2860  std::sqrt(Core::AstroConst::G
2861  /
2863  *
2865  *
2867  /
2868  (gamma * std::pow(Core::AstroConst::solar_radius, 1.5))
2869  ),
2870  alphaL = (
2872  /
2873  std::pow(Core::AstroConst::solar_radius, 1.5)
2874  *
2875  std::sqrt(Core::AstroConst::G
2876  /
2877  (
2879  +
2881  )
2882  )
2883  *
2885  ),
2886  Ic = (
2887  (
2888  (
2889  (std::pow(a0, 5) - std::pow(abreak, 5))
2890  *
2891  std::pow(abreak, 3.5)
2892  *
2893  6.5
2894  )
2895  -
2896  5.0 * gamma * abreak * abreak
2897  )
2898  /
2899  (
2900  (
2901  (std::pow(a0, 3) - std::pow(abreak, 3))
2902  *
2903  std::pow(abreak, 3.5) * 6.5
2904  )
2905  -
2906  3.0 * gamma
2907  )
2908  *
2909  alphaL
2910  /
2911  (5.0 * beta)
2912  ),
2913  kappa = (
2914  (std::pow(a0, 5) - std::pow(abreak, 5)) * alphaL / 10.0
2915  -
2916  (std::pow(a0, 3) - std::pow(abreak, 3)) * beta * Ic / 2.0
2917  ),
2918  Kwind = (
2919  kappa
2920  /
2921  std::pow(
2923  *
2924  (
2926  +
2928  )
2929  /
2930  std::pow(Core::AstroConst::solar_radius, 3),
2931  1.5
2932  )
2933  /
2934  std::pow(Core::AstroConst::day, 3)
2935  ),
2936  locked_a_int_const = (alphaL * std::pow(a0, 5) / 10.0
2937  -
2938  beta * Ic * std::pow(a0, 3) / 2.0
2939  +
2940  kappa * tdisk);
2941 
2943  no_evol = StellarEvolution::make_no_evolution(1.0, Ic);
2944 
2946  *no_evol,//evolution
2947  Kwind,//Kwind
2948  100.0,//wsat
2949  Core::Inf,//tcoup
2950  lag_from_lgQ(
2951  std::log10(Q),
2953  /
2955  )
2956  );
2957  evolve(wdisk,//wdisk,
2958  tdisk,//tdisk
2959  a0 * (1.0 + 1e-14),//initial semimajor
2960  &zero,//initial L*
2961  0.0,//initial inclination
2962  1.0,//planet_mass
2963  Core::NaN,//form the planet when disk dissipates
2964  tend,//max evolution age
2965  Rp);//planet radius
2966 
2967  ExpectedEvolutionMode<Core::EvolModeType> expected_evol_mode;
2968  expected_evol_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
2969  expected_evol_mode.add_break(tdisk, Core::BINARY);
2970  expected_evol_mode.add_break(tdeath, Core::SINGLE);
2971 
2972  ExpectedEvolutionMode<bool> expected_wind_mode;
2973  expected_wind_mode.add_break(TSTART, false);
2974 
2975  std::valarray<double> a_locked_transform_coef(0.0, 6),
2976  a_locked_evol_coef(2),
2977  identity_coef(0.0, 2),
2978  a6p5_fast_evol_coef(2),
2979  Lconv_locked_term1_coef(0.0, 2),
2980  Lconv_locked_term2_coef(0.0, 3);
2981  a_locked_transform_coef[5] = alphaL / 10.0;
2982  a_locked_transform_coef[3] = -beta * Ic / 2.0;
2983  a_locked_evol_coef[0] = locked_a_int_const;
2984  a_locked_evol_coef[1] = -kappa;
2985  identity_coef[1] = 1.0;
2986  a6p5_fast_evol_coef[0] = gamma * tbreak + std::pow(abreak, 6.5);
2987  a6p5_fast_evol_coef[1] = -gamma;
2988  Lconv_locked_term1_coef[1] = (1.0
2989  /
2990  (beta * Ic)
2991  *
2992  std::pow(10.0 / alphaL, 3.0 / 10.0));
2993  Lconv_locked_term2_coef[2] = -2.0 / std::pow(beta * Ic, 3);
2994 
2996  identity(identity_coef, -Core::Inf, Core::Inf),
2997  a_disk_transform = identity,
2998  nan_disk_evol(std::valarray<double>(Core::NaN, 2),
2999  TSTART,
3000  tdisk),
3001  a_locked_transform(a_locked_transform_coef,
3002  -Core::Inf,
3003  Core::Inf),
3004  a_locked_evol(a_locked_evol_coef, tdisk, tbreak),
3005  a_fast_transform = identity,
3006  a6p5_fast_evol(a6p5_fast_evol_coef, tbreak, tdeath),
3007  a_noplanet_transform = identity,
3008  nan_noplanet_evol(std::valarray<double>(Core::NaN, 2),
3009  tdeath,
3010  tend),
3011 
3012  Lconv_disk_transform = identity,
3013  Lconv_disk_evol(std::valarray<double>(wdisk * Ic, 1),
3014  TSTART,
3015  tdisk),
3016  Lconv_locked_term1_poly(Lconv_locked_term1_coef,
3017  -Core::Inf,
3018  Core::Inf),
3019  Lconv_locked_term2_poly(Lconv_locked_term2_coef,
3020  -Core::Inf,
3021  Core::Inf),
3022  Lconv_locked_evol = a_locked_evol,
3023  Lconv_fast_transform(std::valarray<double>(Core::NaN, 2),
3024  -Core::Inf,
3025  Core::Inf),
3026  Lconv_fast_evol(std::valarray<double>(Core::NaN, 2),
3027  tbreak,
3028  tdeath),
3029  Lconv_noplanet_transform(std::valarray<double>(Core::NaN, 2),
3030  -Core::Inf,
3031  Core::Inf),
3032  Lconv_noplanet_evol(std::valarray<double>(Core::NaN, 2),
3033  tdeath,
3034  tend),
3035  Lrad_transform = identity,
3036  Lrad_evol(std::valarray<double>(), TSTART, tend),
3037  zero_e(std::valarray<double>(), tdisk, tdeath);
3038 
3040  a_fast_evol(&a6p5_fast_evol, 1.0 / 6.5),
3041  Lconv_locked_transform1(&Lconv_locked_term1_poly,
3042  -10.0 / 3.0),
3043  Lconv_locked_transform2(&Lconv_locked_term2_poly, -1.0);
3044 
3045  FuncPlusFunc Lconv_locked_transform(&Lconv_locked_transform1,
3046  &Lconv_locked_transform2);
3047 
3048  PiecewiseFunction a_evol, e_evol, Lconv_evol;
3049 
3050  a_evol.add_piece(&nan_disk_evol);
3051  a_evol.add_piece(&a_locked_evol);
3052  a_evol.add_piece(&a_fast_evol);
3053  a_evol.add_piece(&nan_noplanet_evol);
3054 
3055  e_evol.add_piece(&nan_disk_evol);
3056  e_evol.add_piece(&zero_e);
3057  e_evol.add_piece(&nan_noplanet_evol);
3058 
3059  Lconv_evol.add_piece(&Lconv_disk_evol);
3060  Lconv_evol.add_piece(&Lconv_locked_evol);
3061  Lconv_evol.add_piece(&Lconv_fast_evol);
3062  Lconv_evol.add_piece(&Lconv_noplanet_evol);
3063 
3064  std::vector< const Core::OneArgumentDiffFunction * >
3065  transformations(NUM_REAL_QUANTITIES - 1, &identity);
3066  TransformedSolution to_check(transformations, TSTART);
3067 
3068  transformations[SEMIMAJOR] = &a_disk_transform;
3069  transformations[CONV_ANGMOM] = &Lconv_disk_transform;
3070  to_check.add_transformation(transformations, TSTART);
3071 
3072  transformations[SEMIMAJOR] = &a_locked_transform;
3073  transformations[CONV_ANGMOM] = &Lconv_locked_transform;
3074  to_check.add_transformation(transformations, tdisk);
3075 
3076  transformations[SEMIMAJOR] = &a_fast_transform;
3077  transformations[CONV_ANGMOM] = &Lconv_fast_transform;
3078  to_check.add_transformation(transformations, tbreak);
3079 
3080  transformations[SEMIMAJOR] = &a_fast_transform;
3081  transformations[CONV_ANGMOM] = &Lconv_fast_transform;
3082  to_check.add_transformation(transformations, tbreak);
3083 
3084  transformations[SEMIMAJOR] = &a_noplanet_transform;
3085  transformations[CONV_ANGMOM] = &Lconv_noplanet_transform;
3086  to_check.add_transformation(transformations, tdeath);
3087 
3088  std::vector<const Core::OneArgumentDiffFunction *>
3089  expected_real_quantities(NUM_REAL_QUANTITIES - 1);
3090 
3091  std::vector< const std::list<double> * >
3092  tabulated_evolution = get_evolution();
3093 
3094  const std::vector< const std::list<double> * > &
3095  transformed_evolution = to_check(tabulated_evolution);
3096 
3097  expected_real_quantities[SEMIMAJOR] = &a_evol;
3098  expected_real_quantities[ECCENTRICITY] = &e_evol;
3099  expected_real_quantities[CONV_INCLINATION] = &zero_func;
3100  expected_real_quantities[RAD_INCLINATION] = &zero_func;
3101  expected_real_quantities[CONV_PERIAPSIS] = &zero_func;
3102  expected_real_quantities[RAD_PERIAPSIS] = &zero_func;
3103  expected_real_quantities[CONV_ANGMOM] = &Lconv_evol;
3104  expected_real_quantities[RAD_ANGMOM] = &zero_func;
3105 
3106  test_solution(transformed_evolution,
3107  expected_real_quantities,
3108  expected_evol_mode,
3109  expected_wind_mode,
3110  TSTART,
3111  tend);
3112  delete no_evol;
3113  } catch (Core::Error::General &ex) {
3114  TEST_ASSERT_MSG(
3115  false,
3116  (
3117  std::string("Unexpected exception thrown: ")
3118  +
3119  ex.what()+": "+ex.get_message()
3120  ).c_str()
3121  );
3122  } catch (std::exception &ex) {
3123  TEST_ASSERT_MSG(
3124  false,
3125  (
3126  std::string("Unexpected exception thrown: ")
3127  +
3128  ex.what()
3129  ).c_str()
3130  );
3131  }
3132 
3133  }
3134 
3135  void test_OrbitSolver::test_polar_1_0_evolution()
3136  {
3138  no_evol = StellarEvolution::make_no_evolution();
3139 
3140  const double TDISK = 0.1,
3141  WSTAR = 0.01,
3142  WORB = 0.1;
3143  double initial_L = 1.0;
3144  std::vector<const Core::OneArgumentDiffFunction *>
3145  expected_real_quantities = calculate_expected_polar_1_0(
3146  TDISK,
3147  WSTAR,
3148  WORB
3149  );
3150  ExpectedEvolutionMode<Core::EvolModeType> expected_evol_mode;
3151  expected_evol_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
3152  expected_evol_mode.add_break(TDISK, Core::BINARY);
3153 
3154  ExpectedEvolutionMode<bool> expected_wind_mode;
3155  expected_wind_mode.add_break(TSTART, false);
3156 
3157  double semimajor = (*expected_real_quantities[SEMIMAJOR])(
3158  (TDISK + MAX_AGE) / 2.0
3159  );
3160 
3161  make_single_component_star(*no_evol,
3162  0.0,//Kw
3163  1.0,//Wsat
3164  Core::Inf,
3165  0.9 * WSTAR,
3166  1.1 * WSTAR,
3167  0.1 * WSTAR,
3168  1.0);//tcoup
3169 
3170  while(true) {
3171  evolve(WSTAR,//wdisk
3172  TDISK,//tdisk
3173  semimajor,//initial semimajor
3174  &initial_L,//initial L*
3175  M_PI / 2.0);//initial inclination
3176 
3178  expected_real_quantities,
3179  expected_evol_mode,
3180  expected_wind_mode,
3181  (__star ? TSTART : TDISK),
3182  MAX_AGE);
3183 
3184  if(__star) {
3185  delete __star;
3186  delete __system;
3187  delete __solver;
3188  __star = NULL;
3189  __system = NULL;
3190  __solver = NULL;
3191 
3192  __primary_planet = new Planet::Planet(1.0, 1.0, 1.0);
3194  0.9 * WSTAR,
3195  1.1 * WSTAR,
3196  0.1 * WSTAR,
3197  1.0
3198  );
3199  initial_L = WSTAR;
3200  } else
3201  break;
3202  }
3203 
3204  delete no_evol;
3205  }
3206 
3207  void test_OrbitSolver::test_polar_2_0_evolution()
3208  {
3210  no_evol = StellarEvolution::make_no_evolution();
3211 
3212  const double TDISK = 0.1,
3213  WSTAR = 0.01,
3214  WORB = 0.1,
3215  PHASE_LAG = 1e-2;
3216 
3217  double lconv_decay_rate, semimajor, initial_L = 1.0;
3218 
3219  std::vector<const Core::OneArgumentDiffFunction *>
3220  expected_real_quantities = calculate_expected_polar_2_0(TDISK,
3221  WSTAR,
3222  WORB,
3223  PHASE_LAG,
3224  lconv_decay_rate,
3225  semimajor);
3226 
3227 
3228  std::valarray<double> identity_coef(0.0, 2);
3229  identity_coef[1] = 1.0;
3231  identity(identity_coef, -Core::Inf, Core::Inf),
3232  one_func(std::valarray<double>(1.0, 1), -Core::Inf, Core::Inf);
3233 
3234  CosFunction cos_transform(&identity);
3235  FuncPlusFunc one_plus_cos_transform(&one_func,
3236  &cos_transform);
3237 
3238 
3240  *no_evol,
3241  0.0,//Kw
3242  1.0,//Wsat
3243  Core::Inf,//tcoup
3244  2.0 * (WSTAR - lconv_decay_rate * MAX_AGE),
3245  2.0 * (WSTAR + lconv_decay_rate * MAX_AGE),
3246  0.1 * WSTAR,
3247  PHASE_LAG
3248  );
3249 
3250  while(true) {
3251  evolve(WSTAR,//wdisk
3252  TDISK,//tdisk
3253  semimajor,//initial semimajor
3254  &initial_L,//initial L*
3255  M_PI / 2.0);//initial inclination
3256 
3257  std::vector< const Core::OneArgumentDiffFunction * >
3258  transformations(NUM_REAL_QUANTITIES - 1, &identity);
3259  transformations[CONV_INCLINATION] = &one_plus_cos_transform;
3260  transformations[RAD_INCLINATION] = &one_plus_cos_transform;
3261  TransformedSolution to_check(transformations, TSTART);
3262 
3263  std::vector< const std::list<double> * >
3264  tabulated_evolution = get_evolution();
3265  const std::vector< const std::list<double> * > &
3266  transformed_evolution = to_check(tabulated_evolution);
3267 
3268  ExpectedEvolutionMode<Core::EvolModeType> expected_evol_mode;
3269  expected_evol_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
3270  expected_evol_mode.add_break(TDISK, Core::BINARY);
3271 
3272  ExpectedEvolutionMode<bool> expected_wind_mode;
3273  expected_wind_mode.add_break(TSTART, false);
3274 
3275  test_solution(transformed_evolution,
3276  expected_real_quantities,
3277  expected_evol_mode,
3278  expected_wind_mode,
3279  (__star ? TSTART : TDISK),
3280  MAX_AGE);
3281 
3282  if(__star) {
3283  delete __star;
3284  delete __system;
3285  delete __solver;
3286  __star = NULL;
3287  __system = NULL;
3288  __solver = NULL;
3289 
3290  __primary_planet = new Planet::Planet(1.0, 1.0, 1.0);
3292  2.0 * (WSTAR - lconv_decay_rate * MAX_AGE),
3293  2.0 * (WSTAR + lconv_decay_rate * MAX_AGE),
3294  0.1 * WSTAR,
3295  PHASE_LAG
3296  );
3297  initial_L = WSTAR;
3298  } else
3299  break;
3300  }
3301 
3302  delete no_evol;
3303  }
3304  void test_OrbitSolver::test_oblique_1_0_evolution()
3305  {
3307  no_evol = StellarEvolution::make_no_evolution();
3308 
3309  const double PHASE_LAG = 0.1,
3310  TDISK = 0.1,
3311  WORB = 0.1,
3312  INITIAL_INC = 0.25 * M_PI,
3313  INITIAL_WSTAR = 0.01;
3314 
3315  double initial_angmom = 1.0,
3316  min_wstar;
3317 
3318  std::vector<const Core::OneArgumentDiffFunction *>
3319  expected_real_quantities = calculate_expected_oblique_m_0(
3320  1,
3321  TDISK,
3322  WORB,
3323  INITIAL_INC,
3324  INITIAL_WSTAR,
3325  PHASE_LAG,
3326  min_wstar
3327  );
3328 
3329  double wstar_tolerance = 0.01 * (INITIAL_WSTAR - min_wstar),
3330  semimajor = (*expected_real_quantities[SEMIMAJOR])(
3331  (TDISK + MAX_AGE) / 2.0
3332  );
3333 
3334  ExpectedEvolutionMode<Core::EvolModeType> expected_evol_mode;
3335  expected_evol_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
3336  expected_evol_mode.add_break(TDISK, Core::BINARY);
3337 
3338  ExpectedEvolutionMode<bool> expected_wind_mode;
3339  expected_wind_mode.add_break(TSTART, false);
3340 
3342  *no_evol,
3343  0.0,//Kw
3344  1.0,//Wsat
3345  Core::Inf,//tcoup
3346  min_wstar - wstar_tolerance,
3347  INITIAL_WSTAR + wstar_tolerance,
3348  0.1 * INITIAL_WSTAR,
3349  PHASE_LAG
3350  );
3351 
3352  while(true) {
3353  evolve(INITIAL_WSTAR,//wdisk
3354  TDISK,//tdisk
3355  semimajor,//initial semimajor
3356  &initial_angmom,//initial L*
3357  INITIAL_INC);//initial inclination
3358 
3360  expected_real_quantities,
3361  expected_evol_mode,
3362  expected_wind_mode,
3363  (__star ? TSTART : TDISK),
3364  MAX_AGE);
3365 
3366  if(__star) {
3367  delete __star;
3368  delete __system;
3369  delete __solver;
3370  __star = NULL;
3371  __system = NULL;
3372  __solver = NULL;
3373 
3374  __primary_planet = new Planet::Planet(1.0, 1.0, 1.0);
3376  min_wstar - wstar_tolerance,
3377  INITIAL_WSTAR + wstar_tolerance,
3378  0.1 * INITIAL_WSTAR,
3379  PHASE_LAG
3380  );
3381 
3382  initial_angmom = INITIAL_WSTAR;
3383  } else
3384  break;
3385  }
3386  }
3387 
3388  void test_OrbitSolver::test_oblique_2_0_evolution()
3389  {
3391  no_evol = StellarEvolution::make_no_evolution();
3392 
3393  const double PHASE_LAG = 0.1,
3394  TDISK = 0.1,
3395  WORB = 0.1,
3396  INITIAL_INC = 0.25 * M_PI,
3397  INITIAL_WSTAR = 0.01;
3398 
3399  double initial_angmom = 1.0,
3400  min_wstar;
3401 
3402  std::vector<const Core::OneArgumentDiffFunction *>
3403  expected_real_quantities = calculate_expected_oblique_m_0(
3404  2,
3405  TDISK,
3406  WORB,
3407  INITIAL_INC,
3408  INITIAL_WSTAR,
3409  PHASE_LAG,
3410  min_wstar
3411  );
3412 
3413  double wstar_tolerance = 0.01 * (INITIAL_WSTAR - min_wstar),
3414  semimajor = (*expected_real_quantities[SEMIMAJOR])(
3415  (TDISK + MAX_AGE) / 2.0
3416  );
3417 
3418  ExpectedEvolutionMode<Core::EvolModeType> expected_evol_mode;
3419  expected_evol_mode.add_break(TSTART, Core::LOCKED_SURFACE_SPIN);
3420  expected_evol_mode.add_break(TDISK, Core::BINARY);
3421 
3422  ExpectedEvolutionMode<bool> expected_wind_mode;
3423  expected_wind_mode.add_break(TSTART, false);
3424 
3426  *no_evol,
3427  0.0,//Kw
3428  1.0,//Wsat
3429  Core::Inf,//tcoup
3430  2.0 * min_wstar - wstar_tolerance,
3431  2.0 * INITIAL_WSTAR + wstar_tolerance,
3432  0.1 * INITIAL_WSTAR,
3433  PHASE_LAG
3434  );
3435 
3436  while(true) {
3437  evolve(INITIAL_WSTAR,//wdisk
3438  TDISK,//tdisk
3439  semimajor,//initial semimajor
3440  &initial_angmom,//initial L*
3441  INITIAL_INC);//initial inclination
3442 
3444  expected_real_quantities,
3445  expected_evol_mode,
3446  expected_wind_mode,
3447  (__star ? TSTART : TDISK),
3448  MAX_AGE);
3449  if(__star) {
3450  delete __star;
3451  delete __system;
3452  delete __solver;
3453  __star = NULL;
3454  __system = NULL;
3455  __solver = NULL;
3456 
3457  __primary_planet = new Planet::Planet(1.0, 1.0, 1.0);
3459  2.0 * min_wstar - wstar_tolerance,
3460  2.0 * INITIAL_WSTAR + wstar_tolerance,
3461  0.1 * INITIAL_WSTAR,
3462  PHASE_LAG
3463  );
3464 
3465  initial_angmom = INITIAL_WSTAR;
3466  } else
3467  break;
3468  }
3469 
3470  delete no_evol;
3471 
3472  }
3473 
3474  void test_OrbitSolver::setup()
3475  {
3476  assert(__star == NULL);
3477  assert(__primary_planet == NULL);
3478  assert(__system == NULL);
3479  assert(__solver == NULL);
3480  assert(__temp_functions.empty());
3481  }
3482 
3483  void test_OrbitSolver::tear_down()
3484  {
3485  if(__star) {
3486  std::cout << "Deleting star" << std::endl;
3487  delete __star;
3488  __star = NULL;
3489  }
3490  if(__primary_planet) {
3491  std::cout << "Deleting primary planet" << std::endl;
3492  delete __primary_planet;
3493  __primary_planet = NULL;
3494  }
3495  if(__system) {
3496  std::cout << "Deleting system" << std::endl;
3497  delete __system;
3498  __system = NULL;
3499  }
3500  if(__solver) {
3501  std::cout << "Deleting solver" << std::endl;
3502  delete __solver;
3503  __solver = NULL;
3504  }
3505  for(
3506  std::vector< const Core::OneArgumentDiffFunction* >::iterator
3507  temp_func_i = __temp_functions.begin();
3508  temp_func_i != __temp_functions.end();
3509  ++temp_func_i
3510  ) {
3511  std::cout << "Deleting function" << std::endl;
3512  delete *temp_func_i;
3513  }
3514  __temp_functions.clear();
3515  }
3516 
3517  test_OrbitSolver::test_OrbitSolver() :
3518  __solver(NULL),
3519  __system(NULL),
3520  __star(NULL),
3521  __primary_planet(NULL)
3522  {
3523  //Successfully passed
3524  TEST_ADD(test_OrbitSolver::test_disk_locked_no_stellar_evolution);
3525  TEST_ADD(test_OrbitSolver::test_disk_locked_with_stellar_evolution);
3526  TEST_ADD(test_OrbitSolver::test_no_planet_evolution);
3527  TEST_ADD(test_OrbitSolver::test_unlocked_evolution);
3528  TEST_ADD(test_OrbitSolver::test_disklocked_to_fast_to_noplanet);
3529  TEST_ADD(test_OrbitSolver::test_polar_1_0_evolution);
3530  TEST_ADD(test_OrbitSolver::test_polar_2_0_evolution);
3531  TEST_ADD(test_OrbitSolver::test_oblique_1_0_evolution);
3532  TEST_ADD(test_OrbitSolver::test_disklocked_to_fast_to_locked);
3533  TEST_ADD(test_OrbitSolver::test_disklocked_to_locked_to_fast);
3534  TEST_ADD(test_OrbitSolver::test_disklocked_to_locked_to_noplanet);
3535  TEST_ADD(test_OrbitSolver::test_locked_evolution);
3536 
3537  //NOT REVIVED!!!
3538  //TEST_ADD(test_OrbitSolver::test_oblique_2_0_evolution);
3539  }
3540 
3541 }//End Evolve namespace.
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.
Definition: Common.h:54
Age in Myr when disk dissipates.
Definition: IOColumns.h:62
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...
Inclination of the zone.
Declares the test suite that exercises the OrbitSolver class and some other clasess necessary to acco...
const std::string & get_message() const
Details about what caused the error.
Definition: Error.h:42
The orbital periapsis in the reference frame of the stellar radiative zone in radians.
Definition: IOColumns.h:186
void detect_saturation()
Sets the saturation based on the currently configured spin frequency.
The base class of all exceptions.
Definition: Error.h:27
const std::list< Core::EvolModeType > & mode_evolution() const
The tabulated evolution modes so far.
Definition: OrbitSolver.h:498
The orbital frequency in rad/day.
Definition: IOColumns.h:168
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.
Definition: Functions.h:104
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...
Definition: Planet.h:21
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.
Definition: IOColumns.h:178
const Evolve::DissipatingZone & zone(unsigned zone_index) const
Returns the only zone.
Definition: Planet.h:37
struct LIB_PUBLIC OrbitSolver
Opaque struct to cast to/from Evolve::OrbitSolver.
Definition: CInterface.h:38
The angle between the stellar surface spin and orbital angular momentum in radians.
Definition: IOColumns.h:174
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.
Definition: Common.h:57
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.
Definition: EvolvingStar.h:100
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.
Definition: CInterface.h:35
A class that interpolates among stellar evolution tracks.
Definition: Interpolator.h:42
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.
double lag_from_lgQ(double lgQ)
Converts lg(Q) to a tidal phase lag.
Definition: CInterface.cpp:17
Periapsis of the zone.
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.
Definition: IOColumns.h:57
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.
Definition: Error.h:39
const double Gyr
Gyr [s].
bool check_diff(double x, double y, double frac_tolerance, double abs_tolerance)
Returns true iff .
Definition: Common.cpp:3
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-8, double max_step_factor=1e-3, const std::list< double > required_ages=std::list< double >())
Add a planet to the given star and evolve, returning the solver.
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.
const double day
day [s]
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.
Definition: EvolvingStar.h:94
AGE
The derivative w.r.t. age, excluding the dependence through the body&#39;s radius and the moments of iner...
The minimum age to start evolution at in Gyr.
Definition: IOColumns.h:67
Several functions stiched together.
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.
Definition: Common.h:42
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...
Definition: OrbitSolver.h:115
Definition: Planet.h:15
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.
Definition: IOColumns.h:182
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.
Definition: MakeStar.cpp:10
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.
A class that can be passed to the solution testing function instead of the solver that transforms the...
const std::list< double > & evolution_ages() const
The ages at which evolution has been tabulated so far.
Definition: OrbitSolver.h:494
void add_transformation(const std::vector< const Core::OneArgumentDiffFunction *> &transforms, double change_age)
Add more pieces to the transformation.
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...