Planetary Orbital Evolution due to Tides
Orbital evolution of two objects experiencing tides
BrokenPowerlawPhaseLagZone.cpp
1 #define BUILDING_LIBRARY
3 #include <iostream>
4 
5 namespace Evolve {
6 
8  const BinarySystem &system
9  ) const
10  {
11  return Core::orbital_angular_velocity(
12  system.primary().mass(),
13  system.secondary().mass(),
14  system.semimajor()
15  );
16  }
17 
19  double forcing_frequency,
20  int orbital_frequency_multiplier,
21  int spin_frequency_multiplier,
22  Dissipation::QuantityEntry entry
23  ) const
24  {
26  if(entry == Dissipation::NO_DERIV)
27  return 1.0;
28  return 0.0;
29  }
30 
31  double abs_spin_frequency = std::abs(spin_frequency()),
32  abs_forcing_frequency = std::abs(forcing_frequency);
33  if(entry == Dissipation::NO_DERIV)
34  return (
35  abs_forcing_frequency > 2.0 * abs_spin_frequency
36  ? 1.0
37  : std::min(
38  std::pow(
39  2.0 * abs_spin_frequency / abs_forcing_frequency,
41  ),
43  )
44  );
45 
46  if(
47  abs_forcing_frequency > 2.0 * abs_spin_frequency
48  ||
49  (
50  std::pow(
51  2.0 * abs_spin_frequency / abs_forcing_frequency,
53  )
54  >
56  )
57  )
58  return 0.0;
59 
61  return -(__inertial_mode_sharpness * orbital_frequency_multiplier
62  /
64 
65  if(entry == Dissipation::SPIN_FREQUENCY)
66  return __inertial_mode_sharpness * (
67  1.0 / spin_frequency()
68  +
69  spin_frequency_multiplier / forcing_frequency
70  );
71  return 0.0;
72  }
73 
75  {
80  __break_phase_lags.clear();
81  }
82 
84  {
85  if(__spin_frequency_breaks.size() != 0) {
86  double abs_spin_frequency = std::abs(spin_frequency());
87  __spin_index = (
88  std::lower_bound(
91  abs_spin_frequency
92  )
93  -
95  );
96  if(
98  &&
99  __spin_frequency_breaks[__spin_index] == abs_spin_frequency
100  )
102  "Starting evolution from exactly a critical spin "
103  "frequency is not currently supported."
104  );
105  } else
106  __spin_index = 0;
107 
108 
109  }
110 
111  std::vector<double>::size_type
113  double abs_forcing_frequency
114  ) const
115  {
116  assert(abs_forcing_frequency >= 0);
117  if(__tidal_frequency_breaks.size() != 0)
118  return (
119  std::lower_bound(
120  __tidal_frequency_breaks.begin(),
122  abs_forcing_frequency
123  )
124  -
126  );
127  else
128  return 0;
129  }
130 
132  BinarySystem &system,
133  bool primary,
134  unsigned,
136  )
137  {
138  const DissipatingBody
139  &this_body = (primary ? system.primary() : system.secondary()),
140  &other_body = (primary ? system.secondary() : system.primary());
141 
142  for(
143  int e_order = 0;
144  e_order <= static_cast<int>(eccentricity_order());
145  ++e_order
146  )
147  {
148 
149  int mp_step = (e_order == 0 ? 1 : 4 + 2 * e_order);
150 
151  for(int mp = 0; mp <= e_order + 2; mp += mp_step)
152  for(int m = -2; m <= 2; ++m)
153  result |= new LagForcingFrequencyBreakCondition(
154  *this,
155  this_body,
156  other_body,
157  mp,
158  m
159  );
160  }
161 
162  }
163 
164  void BrokenPowerlawPhaseLagZone::print_configuration(std::ostream &out_stream)
165  {
166  return;
167  out_stream << "Tidal breaks: ";
168  for(
169  std::vector<double>::const_iterator
170  i = __tidal_frequency_breaks.begin();
171  i != __tidal_frequency_breaks.end();
172  ++i
173  )
174  out_stream << *i << " ";
175  out_stream << std::endl;
176 
177  out_stream << "Tidal powers: ";
178  for(
179  std::vector<double>::const_iterator
180  i = __tidal_frequency_powers.begin();
181  i != __tidal_frequency_powers.end();
182  ++i
183  )
184  out_stream << *i << " ";
185  out_stream << std::endl;
186 
187  out_stream << "Spin breaks: ";
188  for(
189  std::vector<double>::const_iterator
190  i = __spin_frequency_breaks.begin();
191  i != __spin_frequency_breaks.end();
192  ++i
193  )
194  out_stream << *i << " ";
195  out_stream << std::endl;
196 
197  out_stream << "Spin powers: ";
198  for(
199  std::vector<double>::const_iterator
200  i = __spin_frequency_powers.begin();
201  i != __spin_frequency_powers.end();
202  ++i
203  )
204  out_stream << *i << " ";
205  out_stream << std::endl;
206 
207  out_stream << "Break lags: ";
208  for(
209  std::vector<double>::const_iterator
210  i = __break_phase_lags.begin();
211  i != __break_phase_lags.end();
212  ++i
213  )
214  out_stream << *i << " ";
215  out_stream << std::endl;
216  }
217 
219  const std::vector<double> &tidal_frequency_breaks,
220  const std::vector<double> &spin_frequency_breaks,
221  const std::vector<double> &tidal_frequency_powers,
222  const std::vector<double> &spin_frequency_powers,
223  double reference_phase_lag,
224  double inertial_mode_enhancement,
225  double inertial_mode_sharpness
226  )
227  {
228  reset();
229  assert(__spin_frequency_breaks.size() == 0);
230  assert(__tidal_frequency_breaks.size() == 0);
231  assert(__spin_frequency_breaks.size() == 0);
232  assert(__spin_frequency_powers.size() == 0);
233  assert(__break_phase_lags.size() == 0);
234  assert(tidal_frequency_powers.size()
235  ==
236  tidal_frequency_breaks.size() + 1);
237  assert(spin_frequency_powers.size()
238  ==
239  spin_frequency_breaks.size() + 1);
240  assert(tidal_frequency_breaks.size() > 0
241  ||
242  tidal_frequency_powers.front() == 0);
243  assert(spin_frequency_breaks.size() > 0
244  ||
245  spin_frequency_powers.front() == 0);
246 
247  __dissipative = true;
248  __can_lock = tidal_frequency_powers.front() <= 0;
249 
250  __tidal_frequency_breaks = tidal_frequency_breaks;
251  __spin_frequency_breaks = spin_frequency_breaks;
252  __tidal_frequency_powers = tidal_frequency_powers;
253  __spin_frequency_powers = spin_frequency_powers;
254  __break_phase_lags.resize(
255  std::max(int(spin_frequency_breaks.size()), 1)
256  *
257  std::max(int(tidal_frequency_breaks.size()), 1)
258  );
259 
260  unsigned break_lag_i = 0;
261  for(
262  int spin_break_i = 0;
263  spin_break_i < std::max(int(spin_frequency_breaks.size()), 1);
264  ++spin_break_i
265  ) {
266  if(break_lag_i == 0)
267  __break_phase_lags[break_lag_i] = reference_phase_lag;
268  else
269  __break_phase_lags[break_lag_i] = (
271  break_lag_i - tidal_frequency_breaks.size()
272  ]
273  *
274  (
275  spin_frequency_powers[spin_break_i] == 0
276  ? 1.0
277  : std::pow(
278  (
279  spin_frequency_breaks[spin_break_i]
280  /
281  spin_frequency_breaks[spin_break_i - 1]
282  ),
283  spin_frequency_powers[spin_break_i]
284  )
285  )
286  );
287  ++break_lag_i;
288  for(
289  int tidal_break_i = 1;
290  tidal_break_i < std::max(int(tidal_frequency_breaks.size()),
291  1);
292  ++tidal_break_i
293  ) {
294  __break_phase_lags[break_lag_i] = (
295  __break_phase_lags[break_lag_i - 1]
296  *
297  (
298  tidal_frequency_powers[tidal_break_i] == 0
299  ? 1.0
300  : std::pow(
301  (
302  tidal_frequency_breaks[tidal_break_i]
303  /
304  tidal_frequency_breaks[tidal_break_i - 1]
305  ),
306  tidal_frequency_powers[tidal_break_i]
307  )
308  )
309  );
310  ++break_lag_i;
311  }
312  }
313 
314  __inertial_mode_enhancement = inertial_mode_enhancement;
315  __inertial_mode_sharpness = inertial_mode_sharpness;
316  if(__inertial_mode_enhancement != 1) {
319  "Inertial mode enhancement must be greater than 1."
320  );
323  "Sharpness parameter for inertial mode enhancement must be "
324  "strictly positive."
325  );
326  }
327 #ifndef NDEBUG
329 #endif
330  }//End BrokenPowerlawPhaseLagZone::BrokenPowerlawPhaseLagZone definition.
331 
333  bool initialize,
334  double age,
335  double orbital_frequency,
336  double eccentricity,
337  double orbital_angmom,
338  double spin,
339  double inclination,
340  double periapsis,
341  bool spin_is_frequency
342  )
343  {
344 
345  if(initialize && !std::isnan(orbital_frequency)) {
346  initializing(true);
347 
348 #ifndef NDEBUG
349  std::cerr << "Initializing broken powerlaw lag zone at t = "
350  << age
351  << (initialize ? " for the first time " : " ")
352  << "with Worb = " << orbital_frequency
353  << ", " << (spin_is_frequency ? "W" : "L") << "* = "
354  << spin
355  << ", e = " << eccentricity
356  << ", inclination = " << inclination
357  << ", periapsis = " << periapsis
358  << "."
359  << std::endl;
360 #endif
361 
362  configure_spin(spin, spin_is_frequency);
363 
364  set_spin_index();
365 
366  __tidal_indices.resize(5 * (eccentricity_order() + 3));
367 #ifndef NDEBUG
368  std::cerr << "__tidal_indices size = "
369  << __tidal_indices.size()
370  << std::endl;
371 #endif
372 
373  std::vector< std::vector<double>::size_type >::iterator
374  destination = __tidal_indices.begin();
375 
376  for(
377  int mp = 0;
378  mp <= static_cast<int>(eccentricity_order()) + 2;
379  ++mp
380  ) {
381  for(int m = -2; m <= 2; ++m) {
382  double abs_forcing_frequency = std::abs(
383  forcing_frequency(mp, m, orbital_frequency)
384  );
385  *destination = get_tidal_index(abs_forcing_frequency);
386  if(
387  *destination < __tidal_frequency_breaks.size()
388  &&
389  (
390  __tidal_frequency_breaks[*destination]
391  ==
392  abs_forcing_frequency
393  )
394  )
396  "Starting evolution from exactly a critical tidal "
397  "forcing frequency is not currently supported."
398  );
399  ++destination;
400  }
401  }
402 
403  initializing(false);
404  }
405 
406  DissipatingZone::configure(initialize,
407  age,
408  orbital_frequency,
409  eccentricity,
410  orbital_angmom,
411  spin,
412  inclination,
413  periapsis,
414  spin_is_frequency);
415  set_spin_index();
416 
417  }
418 
420  int orbital_frequency_multiplier,
421  int spin_frequency_multiplier,
422  double forcing_frequency,
423  Dissipation::QuantityEntry entry,
424  double &above_lock_value
425  ) const
426  {
427  if(
429  ||
430  entry == Dissipation::AGE
431  ||
433  )
434  return 0;
435 
436  double abs_forcing_frequency = std::abs(forcing_frequency),
437  abs_spin_frequency = std::abs(spin_frequency());
438 
439  /*
440  std::vector<double>::size_type tidal_index
441  = __tidal_indices[tidal_term_index(orbital_frequency_multiplier,
442  spin_frequency_multiplier)];
443  */
444  std::vector<double>::size_type
445  tidal_index = get_tidal_index(abs_forcing_frequency);
446 
447  double tidal_power = __tidal_frequency_powers[tidal_index],
449 
450  std::vector<double>::size_type tidal_break_index = tidal_index,
451  spin_break_index = __spin_index;
452  if(
453  spin_break_index > 0
454  &&
455  spin_break_index >= __spin_frequency_breaks.size()
456  )
457  --spin_break_index;
458 
459  if(
460  tidal_break_index > 0
461  &&
462  tidal_break_index >= __tidal_frequency_breaks.size()
463  )
464  --tidal_break_index;
465 
466  std::vector<double>::size_type
467  lag_index = (spin_break_index * __tidal_frequency_breaks.size()
468  +
469  tidal_break_index);
470  double tidal_factor = (
471  tidal_power == 0
472  ? 1.0
473  : std::pow(abs_forcing_frequency
474  /
475  __tidal_frequency_breaks[tidal_break_index]
476  ,
477  tidal_power)
478  );
479  double spin_factor = (
480  spin_power == 0
481  ? 1.0
482  : std::pow(
483  (
484  abs_spin_frequency
485  /
486  __spin_frequency_breaks[spin_break_index]
487  ),
488  spin_power
489  )
490  );
491  double result = (__break_phase_lags[lag_index]
492  *
493  tidal_factor
494  *
495  spin_factor
496  *
497  get_inertial_mode_factor(forcing_frequency,
498  orbital_frequency_multiplier,
499  spin_frequency_multiplier));
500  switch(entry) {
502  result *= (
503  (spin_power ? spin_power / spin_frequency() : 0.0)
504  -
505  (
506  tidal_power
507  ? (spin_frequency_multiplier * tidal_power
508  /
510  : 0.0
511  )
512  +
513  get_inertial_mode_factor(forcing_frequency,
514  orbital_frequency_multiplier,
515  spin_frequency_multiplier,
517  );
518  break;
520  result *= (
521  (
522  tidal_power
523  ? (orbital_frequency_multiplier * tidal_power
524  /
526  : 0.0
527  )
528  +
529  get_inertial_mode_factor(forcing_frequency,
530  orbital_frequency_multiplier,
531  spin_frequency_multiplier,
533  );
534  break;
535  default :
536  assert(entry == Dissipation::NO_DERIV);
537  }
538 
539  if(forcing_frequency == 0) {
540  if(
541  tidal_power
542  &&
543  entry != Dissipation::NO_DERIV
544  ) {
545  assert(
547  ||
549  );
550  if(tidal_power == 1) {
551  result = (
552  (
554  ? spin_frequency_multiplier
555  : -orbital_frequency_multiplier
556  )
557  *
558  __break_phase_lags[lag_index]
559  *
560  spin_factor
561  /
562  __tidal_frequency_breaks[tidal_break_index]
563  );
564  } else {
565  assert(tidal_power > 1);
566  result = 0;
567  }
568  }
569  if(spin_frequency_multiplier >= 0) {
570  above_lock_value = -result;
571  return result;
572  } else {
573  above_lock_value = result;
574  return -result;
575  }
576  } else {
577  return (forcing_frequency > 0 ? result : -result);
578  }
579 
580  }//End BrokenPowerlawPhaseLagZone::modified_phase_lag definition.
581 
584  BinarySystem &system,
585  bool primary,
586  unsigned zone_index
587  )
588  {
589  CombinedStoppingCondition *result =
591  primary,
592  zone_index);
593  return result;
594 
595  if(system.evolution_mode() != Core::BINARY) return result;
596 
597  if(__spin_frequency_breaks.size() != 0) {
598  *result |= new LagSpinBreakCondition(
599  *this,
600  (primary ? system.primary() : system.secondary()),
601  (primary ? system.secondary() : system.primary()),
602  primary,
603  zone_index
604  );
605  }
606 
607  if(__tidal_frequency_breaks.size() != 0)
609  primary,
610  zone_index,
611  *result);
612 
613  return result;
614  }//End BrokenPowerlawPhaseLagZone::stopping_conditions definition.
615 
617  unsigned new_e_order,
618  BinarySystem &system,
619  bool primary,
620  unsigned zone_index
621  )
622  {
623  __tidal_indices.resize(5 * (new_e_order + 3));
624 
625  double orbital_frequency = get_orbital_frequency(system);
626 
627  std::vector< std::vector<double>::size_type >::iterator
628  destination = (__tidal_indices.begin()
629  +
630  5 * (eccentricity_order() + 3));
631  for(
632  int mp = static_cast<int>(eccentricity_order()) + 3;
633  mp <= static_cast<int>(new_e_order) + 2;
634  ++mp
635  ) {
636  for(int m = -2; m <= 2; ++m) {
637  *destination = get_tidal_index(
638  std::abs(forcing_frequency(mp, m, orbital_frequency))
639  );
640  ++destination;
641  }
642  }
643 
645  system,
646  primary,
647  zone_index);
648  }
649 
650 } //End BinarySystem namespace.
void set_spin_index()
Properly set the value of __spin_index per the current spin of the zone.
double tidal_power(bool above, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV) const
The dimensionless tidal power or one of its derivatives.
std::vector< std::vector< double >::size_type > __tidal_indices
The indices within __tidal_frequency_powers of the powerlaw now in effect for each active tidal term...
Function arguments do not satisfy some requirement.
Definition: Error.h:73
virtual void configure(bool initialize, double age, double orbital_frequency, double eccentricity, double orbital_angmom, double spin, double inclination, double periapsis, bool spin_is_frequency)
Defines the current orbit, triggering re-calculation of all quantities.
void print_configuration(std::ostream &out_stream=std::clog)
Print the configuration of the zone to stdlog.
const DissipatingBody & primary() const
Returns the primary body in the system (const).
Definition: BinarySystem.h:836
SPIN_FREQUENCY
The derivative w.r.t. the spin frequency of a dissipating zone.
std::vector< double >::size_type __spin_index
The index within __spin_frequency_powers of the powerlaw now in effect.
A base class for any body contributing to tidal dissipation.
std::vector< double >::size_type get_tidal_index(double abs_forcing_frequency) const
The index within __tidal_frequency_powers to use for the given forcing frequency. ...
std::vector< double > __spin_frequency_powers
The powerlaw indices for the spin frequency dependence.
double get_orbital_frequency(const BinarySystem &system) const
Return the current orbital frequency of the given system.
virtual void change_e_order(unsigned new_e_order, BinarySystem &system, bool primary, unsigned zone_index)
Changes the order of the eccentricity expansion performed.
double periapsis(bool evolution_rate=false) const
The argument of periapsis of this zone minus the reference zone&#39;s.
virtual double modified_phase_lag(int orbital_frequency_multiplier, int spin_frequency_multiplier, double forcing_frequency, Dissipation::QuantityEntry entry, double &above_lock_value) const
Should return the tidal phase lag times the love number for the given tidal term (or one of its deriv...
bool __dissipative
Is the zone dissipative.
Orientations of zones of bodies in a binary system.
void initializing(bool flag)
Notify the zone that it is in the process of initializing or not.
double mass() const
The mass of the body (constant with age).
const DissipatingBody & secondary() const
Returns the secondary body in the system (const).
Definition: BinarySystem.h:839
virtual void configure(bool initialize, double age, double orbital_frequency, double eccentricity, double orbital_angmom, double spin, double inclination, double periapsis, bool spin_is_frequency)
See DissipatingZone::configure().
virtual unsigned eccentricity_order() const
AGE
The derivative w.r.t. age, excluding the dependence through the body&#39;s radius and the moments of iner...
void add_tidal_frequency_conditions(BinarySystem &system, bool primary, unsigned zone_index, CombinedStoppingCondition &result)
Make sure that the entries in __tidal_frequency_conditions are appropriate for the current eccentrici...
Core::EvolModeType evolution_mode()
The evolution mode of last call to configure().
Definition: BinarySystem.h:996
std::vector< double > __break_phase_lags
The phase lags at the tidal/spin frequency breaks.
virtual CombinedStoppingCondition * stopping_conditions(BinarySystem &system, bool primary, unsigned zone_index)
Conditions detecting the next possible discontinuities in the evolution due to this zone...
double inclination(bool evolution_rate=false) const
The angle between the angular momenta of the zone and the orbit.
NO_DERIV
The quantity itself, undifferentiated.
std::vector< double > __spin_frequency_breaks
The locations of the breaks in spin frequency in rad/day.
double get_inertial_mode_factor(double abs_forcing_frequency, int orbital_frequency_multiplier, int spin_frequency_multiplier, Dissipation::QuantityEntry entry=Dissipation::NO_DERIV) const
Calculate the factor by which dissipation is enhanced due to inertial modes or one of its logarithmic...
ORBITAL_FREQUENCY
The derivative w.r.t. the orbital frequency.
double semimajor() const
The current semimajor axis of the system.
Definition: BinarySystem.h:852
Declares the class that provides the phase lag function to DissipatingZone objects.
void configure_spin(double spin, bool spin_is_frequency)
Configures only the spin of the zone.
double forcing_frequency(int orbital_frequency_multiplier, int spin_frequency_multiplier, double orbital_frequency) const
The tidal forcing frequency for the given term and orbital frequency.
virtual void change_e_order(unsigned new_e_order, BinarySystem &system, bool primary, unsigned zone_index)
Changes the order of the eccentricity expansion performed.
std::vector< double > __tidal_frequency_powers
The powerlaw indices for the tidal frequency dependence.
A class combining the the outputs of multiple stopping conditions.
std::vector< double > __tidal_frequency_breaks
The locations of the breaks in tidal frequency in rad/day.
virtual CombinedStoppingCondition * stopping_conditions(BinarySystem &system, bool primary, unsigned zone_index)
Conditions detecting the next possible discontinuities in the evolution due to this zone...
satisfied when a forcing frequency reaches a critical value.
Describes a system of two bodies orbiting each other.
Definition: BinarySystem.h:56
double spin_frequency() const
The spin frequency of the given zone.
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...