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(unsigned mp = 0; mp <= expansion_order() + 2; ++mp)
143  for(int m = -2; m <= 2; ++m)
144  result |= new LagForcingFrequencyBreakCondition(
145  *this,
146  this_body,
147  other_body,
148  mp,
149  m
150  );
151  }
152 
153  void BrokenPowerlawPhaseLagZone::print_configuration(std::ostream &out_stream)
154  {
155  return;
156  out_stream << "Tidal breaks: ";
157  for(
158  std::vector<double>::const_iterator
159  i = __tidal_frequency_breaks.begin();
160  i != __tidal_frequency_breaks.end();
161  ++i
162  )
163  out_stream << *i << " ";
164  out_stream << std::endl;
165 
166  out_stream << "Tidal powers: ";
167  for(
168  std::vector<double>::const_iterator
169  i = __tidal_frequency_powers.begin();
170  i != __tidal_frequency_powers.end();
171  ++i
172  )
173  out_stream << *i << " ";
174  out_stream << std::endl;
175 
176  out_stream << "Spin breaks: ";
177  for(
178  std::vector<double>::const_iterator
179  i = __spin_frequency_breaks.begin();
180  i != __spin_frequency_breaks.end();
181  ++i
182  )
183  out_stream << *i << " ";
184  out_stream << std::endl;
185 
186  out_stream << "Spin powers: ";
187  for(
188  std::vector<double>::const_iterator
189  i = __spin_frequency_powers.begin();
190  i != __spin_frequency_powers.end();
191  ++i
192  )
193  out_stream << *i << " ";
194  out_stream << std::endl;
195 
196  out_stream << "Break lags: ";
197  for(
198  std::vector<double>::const_iterator
199  i = __break_phase_lags.begin();
200  i != __break_phase_lags.end();
201  ++i
202  )
203  out_stream << *i << " ";
204  out_stream << std::endl;
205  }
206 
208  const std::vector<double> &tidal_frequency_breaks,
209  const std::vector<double> &spin_frequency_breaks,
210  const std::vector<double> &tidal_frequency_powers,
211  const std::vector<double> &spin_frequency_powers,
212  double reference_phase_lag,
213  double inertial_mode_enhancement,
214  double inertial_mode_sharpness
215  )
216  {
217  reset();
218  assert(__spin_frequency_breaks.size() == 0);
219  assert(__tidal_frequency_breaks.size() == 0);
220  assert(__spin_frequency_breaks.size() == 0);
221  assert(__spin_frequency_powers.size() == 0);
222  assert(__break_phase_lags.size() == 0);
223  assert(tidal_frequency_powers.size()
224  ==
225  tidal_frequency_breaks.size() + 1);
226  assert(spin_frequency_powers.size()
227  ==
228  spin_frequency_breaks.size() + 1);
229  assert(tidal_frequency_breaks.size() > 0
230  ||
231  tidal_frequency_powers.front() == 0);
232  assert(spin_frequency_breaks.size() > 0
233  ||
234  spin_frequency_powers.front() == 0);
235 
236  __dissipative = true;
237  __can_lock = tidal_frequency_powers.front() <= 0;
238 
239  __tidal_frequency_breaks = tidal_frequency_breaks;
240  __spin_frequency_breaks = spin_frequency_breaks;
241  __tidal_frequency_powers = tidal_frequency_powers;
242  __spin_frequency_powers = spin_frequency_powers;
243  __break_phase_lags.resize(
244  std::max(int(spin_frequency_breaks.size()), 1)
245  *
246  std::max(int(tidal_frequency_breaks.size()), 1)
247  );
248 
249  unsigned break_lag_i = 0;
250  for(
251  int spin_break_i = 0;
252  spin_break_i < std::max(int(spin_frequency_breaks.size()), 1);
253  ++spin_break_i
254  ) {
255  if(break_lag_i == 0)
256  __break_phase_lags[break_lag_i] = reference_phase_lag;
257  else
258  __break_phase_lags[break_lag_i] = (
260  break_lag_i - tidal_frequency_breaks.size()
261  ]
262  *
263  (
264  spin_frequency_powers[spin_break_i] == 0
265  ? 1.0
266  : std::pow(
267  (
268  spin_frequency_breaks[spin_break_i]
269  /
270  spin_frequency_breaks[spin_break_i - 1]
271  ),
272  spin_frequency_powers[spin_break_i]
273  )
274  )
275  );
276  ++break_lag_i;
277  for(
278  int tidal_break_i = 1;
279  tidal_break_i < std::max(int(tidal_frequency_breaks.size()),
280  1);
281  ++tidal_break_i
282  ) {
283  __break_phase_lags[break_lag_i] = (
284  __break_phase_lags[break_lag_i - 1]
285  *
286  (
287  tidal_frequency_powers[tidal_break_i] == 0
288  ? 1.0
289  : std::pow(
290  (
291  tidal_frequency_breaks[tidal_break_i]
292  /
293  tidal_frequency_breaks[tidal_break_i - 1]
294  ),
295  tidal_frequency_powers[tidal_break_i]
296  )
297  )
298  );
299  ++break_lag_i;
300  }
301  }
302 
303  __inertial_mode_enhancement = inertial_mode_enhancement;
304  __inertial_mode_sharpness = inertial_mode_sharpness;
305  if(__inertial_mode_enhancement != 1) {
308  "Inertial mode enhancement must be greater than 1."
309  );
312  "Sharpness parameter for inertial mode enhancement must be "
313  "strictly positive."
314  );
315  }
316 #ifndef NDEBUG
318 #endif
319  }//End BrokenPowerlawPhaseLagZone::BrokenPowerlawPhaseLagZone definition.
320 
322  bool initialize,
323  double age,
324  double orbital_frequency,
325  double eccentricity,
326  double orbital_angmom,
327  double spin,
328  double inclination,
329  double periapsis,
330  bool spin_is_frequency
331  )
332  {
333 
334  if(initialize && !std::isnan(orbital_frequency)) {
335  initializing(true);
336 
337 #ifndef NDEBUG
338  std::cerr << "Initializing broken powerlaw lag zone at t = "
339  << age
340  << (initialize ? " for the first time " : " ")
341  << "with Worb = " << orbital_frequency
342  << ", " << (spin_is_frequency ? "W" : "L") << "* = "
343  << spin
344  << ", e = " << eccentricity
345  << ", inclination = " << inclination
346  << ", periapsis = " << periapsis
347  << "."
348  << std::endl;
349 #endif
350 
351  configure_spin(spin, spin_is_frequency);
352 
353  set_spin_index();
354 
355  __tidal_indices.resize(5 * (expansion_order() + 3));
356 #ifndef NDEBUG
357  std::cerr << "__tidal_indices size = "
358  << __tidal_indices.size()
359  << std::endl;
360 #endif
361 
362  std::vector< std::vector<double>::size_type >::iterator
363  destination = __tidal_indices.begin();
364 
365  for(
366  int mp = 0;
367  mp <= static_cast<int>(expansion_order()) + 2;
368  ++mp
369  ) {
370  for(int m = -2; m <= 2; ++m) {
371  double abs_forcing_frequency = std::abs(
372  forcing_frequency(mp, m, orbital_frequency)
373  );
374  *destination = get_tidal_index(abs_forcing_frequency);
375  if(
376  *destination < __tidal_frequency_breaks.size()
377  &&
378  (
379  __tidal_frequency_breaks[*destination]
380  ==
381  abs_forcing_frequency
382  )
383  )
385  "Starting evolution from exactly a critical tidal "
386  "forcing frequency is not currently supported."
387  );
388  ++destination;
389  }
390  }
391 
392  initializing(false);
393  }
394 
395  DissipatingZone::configure(initialize,
396  age,
397  orbital_frequency,
398  eccentricity,
399  orbital_angmom,
400  spin,
401  inclination,
402  periapsis,
403  spin_is_frequency);
404  set_spin_index();
405 
406  }
407 
409  int orbital_frequency_multiplier,
410  int spin_frequency_multiplier,
411  double forcing_frequency,
412  Dissipation::QuantityEntry entry,
413  double &above_lock_value
414  ) const
415  {
416  if(
418  ||
419  entry == Dissipation::AGE
420  )
421  return 0;
422 
423  double abs_forcing_frequency = std::abs(forcing_frequency),
424  abs_spin_frequency = std::abs(spin_frequency());
425 
426  /*
427  std::vector<double>::size_type tidal_index
428  = __tidal_indices[tidal_term_index(orbital_frequency_multiplier,
429  spin_frequency_multiplier)];
430  */
431  std::vector<double>::size_type
432  tidal_index = get_tidal_index(abs_forcing_frequency);
433 
434  double tidal_power = __tidal_frequency_powers[tidal_index],
436 
437  std::vector<double>::size_type tidal_break_index = tidal_index,
438  spin_break_index = __spin_index;
439  if(
440  spin_break_index > 0
441  &&
442  spin_break_index >= __spin_frequency_breaks.size()
443  )
444  --spin_break_index;
445 
446  if(
447  tidal_break_index > 0
448  &&
449  tidal_break_index >= __tidal_frequency_breaks.size()
450  )
451  --tidal_break_index;
452 
453  std::vector<double>::size_type
454  lag_index = (spin_break_index * __tidal_frequency_breaks.size()
455  +
456  tidal_break_index);
457  double tidal_factor = (
458  tidal_power == 0
459  ? 1.0
460  : std::pow(abs_forcing_frequency
461  /
462  __tidal_frequency_breaks[tidal_break_index]
463  ,
464  tidal_power)
465  );
466  double spin_factor = (
467  spin_power == 0
468  ? 1.0
469  : std::pow(
470  (
471  abs_spin_frequency
472  /
473  __spin_frequency_breaks[spin_break_index]
474  ),
475  spin_power
476  )
477  );
478  double result = (__break_phase_lags[lag_index]
479  *
480  tidal_factor
481  *
482  spin_factor
483  *
484  get_inertial_mode_factor(forcing_frequency,
485  orbital_frequency_multiplier,
486  spin_frequency_multiplier));
487  switch(entry) {
489  result *= (
490  (spin_power ? spin_power / spin_frequency() : 0.0)
491  -
492  (
493  tidal_power
494  ? (spin_frequency_multiplier * tidal_power
495  /
497  : 0.0
498  )
499  +
500  get_inertial_mode_factor(forcing_frequency,
501  orbital_frequency_multiplier,
502  spin_frequency_multiplier,
504  );
505  break;
507  result *= (
508  (
509  tidal_power
510  ? (orbital_frequency_multiplier * tidal_power
511  /
513  : 0.0
514  )
515  +
516  get_inertial_mode_factor(forcing_frequency,
517  orbital_frequency_multiplier,
518  spin_frequency_multiplier,
520  );
521  break;
522  default :
523  assert(entry == Dissipation::NO_DERIV);
524  }
525 
526  if(forcing_frequency == 0) {
527  if(
528  tidal_power
529  &&
530  entry != Dissipation::NO_DERIV
531  ) {
532  assert(
534  ||
536  );
537  if(tidal_power == 1) {
538  result = (
539  (
541  ? spin_frequency_multiplier
542  : -orbital_frequency_multiplier
543  )
544  *
545  __break_phase_lags[lag_index]
546  *
547  spin_factor
548  /
549  __tidal_frequency_breaks[tidal_break_index]
550  );
551  } else {
552  assert(tidal_power > 1);
553  result = 0;
554  }
555  }
556  if(spin_frequency_multiplier >= 0) {
557  above_lock_value = -result;
558  return result;
559  } else {
560  above_lock_value = result;
561  return -result;
562  }
563  } else {
564  return (forcing_frequency > 0 ? result : -result);
565  }
566 
567  }//End BrokenPowerlawPhaseLagZone::modified_phase_lag definition.
568 
571  BinarySystem &system,
572  bool primary,
573  unsigned zone_index
574  )
575  {
576  CombinedStoppingCondition *result =
578  primary,
579  zone_index);
580  return result;
581 
582  if(system.evolution_mode() != Core::BINARY) return result;
583 
584  if(__spin_frequency_breaks.size() != 0) {
585  *result |= new LagSpinBreakCondition(
586  *this,
587  (primary ? system.primary() : system.secondary()),
588  (primary ? system.secondary() : system.primary()),
589  primary,
590  zone_index
591  );
592  }
593 
594  if(__tidal_frequency_breaks.size() != 0)
596  primary,
597  zone_index,
598  *result);
599 
600  return result;
601  }//End BrokenPowerlawPhaseLagZone::stopping_conditions definition.
602 
604  unsigned new_expansion_order,
605  BinarySystem &system,
606  bool primary,
607  unsigned zone_index
608  )
609  {
610  __tidal_indices.resize(5 * (new_expansion_order + 3));
611 
612  double orbital_frequency = get_orbital_frequency(system);
613 
614  std::vector< std::vector<double>::size_type >::iterator
615  destination = (__tidal_indices.begin()
616  +
617  5 * (expansion_order() + 3));
618  for(
619  int mp = static_cast<int>(expansion_order()) + 3;
620  mp <= static_cast<int>(new_expansion_order) + 2;
621  ++mp
622  ) {
623  for(int m = -2; m <= 2; ++m) {
624  *destination = get_tidal_index(
625  std::abs(forcing_frequency(mp, m, orbital_frequency))
626  );
627  ++destination;
628  }
629  }
630 
631  DissipatingZone::change_expansion_order(new_expansion_order,
632  system,
633  primary,
634  zone_index);
635  }
636 
637 } //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:917
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.
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).
virtual unsigned expansion_order() const
const DissipatingBody & secondary() const
Returns the secondary body in the system (const).
Definition: BinarySystem.h:920
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 void change_expansion_order(unsigned new_expansion_order, BinarySystem &system, bool primary, unsigned zone_index)
Changes the order of the eccentricity expansion performed.
virtual void change_expansion_order(unsigned new_expansion_order, BinarySystem &system, bool primary, unsigned zone_index)
Changes the order of the eccentricity expansion performed.
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().
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:933
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.
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:57
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...