1 #include "PolynomialEvolution.h" 7 if(__deriv_x < __xmin || __deriv_x >
__xmax) {
8 std::ostringstream msg;
9 msg << (
"Attempt to evaluate a PolynomialEvolutionQuantity " 13 std::cout << msg.str() << std::endl;
17 double xn = 1, result = 0;
18 for(
size_t n = deriv_order; n <
__poly_coef.size(); ++n) {
20 for(
size_t i = 0; i < deriv_order; ++i) coef_mod *= (n-i);
29 const std::valarray< std::valarray<double> > &R,
30 const std::valarray< std::valarray<double> > &Iconv,
31 const std::valarray< std::valarray<double> > &Irad,
32 const std::valarray< std::valarray<double> > &Rcore,
33 const std::valarray< std::valarray<double> > &Mcore,
34 const std::valarray< std::valarray<double> > &Lum
42 __core_formation_age(core_formation_age)
52 if(core_formation_age > 0) {
62 std::valarray<double>(0.0,
63 std::max(
__Mcore[0].size(),
size_t(2)))
66 std::valarray<double>(
__Iconv[0].size()));
68 for(
size_t mass_i = 0; mass_i <
__Mcore.size(); ++mass_i)
69 for(
size_t age_i = 0; age_i <
__Mcore[mass_i].size(); ++age_i)
81 case RADIUS:
return exact_track(
__R, mass);
83 case LUM:
return exact_track(
__Lum, mass);
97 std::valarray< std::valarray<double> >(
98 std::valarray<double>(Rstar, 1),
101 std::valarray< std::valarray<double> >(
102 std::valarray<double>(Iconv, 1),
105 std::valarray< std::valarray<double> >(
106 std::valarray<double>(1.0, 1),
109 std::valarray< std::valarray<double> >(
110 std::valarray<double>(1.0, 1),
113 std::valarray< std::valarray<double> >(
114 std::valarray<double>(1.0, 1),
117 std::valarray< std::valarray<double> >(
118 std::valarray<double>(1.0, 1),
128 std::valarray< std::valarray<double> >(
129 std::valarray<double>(1.0, 1),
132 std::valarray< std::valarray<double> >(
133 std::valarray<double>(1.0, 1),
136 std::valarray< std::valarray<double> >(
137 std::valarray<double>(1.0, 1),
140 std::valarray< std::valarray<double> >(
141 std::valarray<double>(1.0, 1),
144 std::valarray< std::valarray<double> >(
145 std::valarray<double>(1.0, 1),
148 std::valarray< std::valarray<double> >(
149 std::valarray<double>(1.0, 1),
158 StarData::StarData() :
159 num_stars_created(0),
162 evolution_masses(100),
170 for (
size_t age_ind=0; age_ind < evolution_ages.size(); age_ind++) {
171 evolution_ages[age_ind] = (
174 age_ind * (max_age -
MIN_AGE) / evolution_ages.size()
180 mass_ind < evolution_masses.size();
183 evolution_masses[mass_ind] = (
188 (max_stellar_mass - min_stellar_mass)
190 evolution_masses.size()
196 StarData::~StarData()
198 if(Lrad_track)
delete Lrad_track;
199 if(Lconv_track)
delete Lconv_track;
204 mass =
rand_value(min_stellar_mass, max_stellar_mass);
207 radius = (
rand_value(0.9, 1.1)) * eval_poly(r_coef, mass, age);
210 tidal_Q = std::pow(10.0,
rand_value(5.0,10.0));
214 disk_lock_time = evolution_ages[
rand_value(0, evolution_ages.size()-1)];
224 (*star) =
new Star(mass,
233 Lconv.resize(evolution_ages.size());
234 Lconv = tabulate_track(Lconv_track, evolution_ages);
235 Lrad.resize(evolution_ages.size());
236 Lrad = tabulate_track(Lrad_track, evolution_ages);
237 Iconv.resize(evolution_ages.size());
238 Iconv = tabulate_track(exact_track(Iconv_coef, mass), evolution_ages);
239 std::valarray<double> Itot =
240 tabulate_track(exact_track(Itot_coef, mass), evolution_ages);
242 std::list<double> Irad_list;
243 for (
size_t i=0; i < evolution_ages.size(); i++)
244 Irad_list.push_back(Itot[i]-Iconv[i]);
245 Irad = list_to_valarray(Irad_list);
247 Mrad_deriv = tabulate_track(exact_track(Mrad_coef, mass),
249 Lconv_deriv = tabulate_track(Lconv_track, evolution_ages, 1);
250 Lrad_deriv = tabulate_track(Lrad_track, evolution_ages, 1);
251 Rrad = tabulate_track(exact_track(Rcore_coef, mass), evolution_ages);
252 all_radii = tabulate_track(exact_track(r_coef, mass), evolution_ages);
254 std::valarray<double> fake_derivs;
255 (*star)->set_angular_momentum_evolution(evolution_ages,
256 tabulate_track(Lrad_track, evolution_ages),
257 tabulate_track(Lrad_track, evolution_ages, 1), radiative);
258 (*star)->set_angular_momentum_evolution(evolution_ages,
259 tabulate_track(Lconv_track, evolution_ages),
260 tabulate_track(Lconv_track, evolution_ages, 1), convective);
264 void PlanetData::create_random_planet(
Planet** planet)
266 mass =
rand_value(min_planet_mass, max_planet_mass);
267 radius =
rand_value(min_planet_radius, max_planet_radius);
269 std::list<double> semis;
270 std::list<double> ages;
271 for (
double age=0; age < 3; age += 0.1) {
273 semis.push_back(get_semi(age));
275 this->ages.resize(ages.size());
276 this->ages = list_to_valarray(ages);
277 this->semis.resize(semis.size());
278 this->semis = list_to_valarray(semis);
280 std::valarray<double> fakeDerivs;
281 double curr_semi = get_semi(star->age());
282 (*planet) =
new Planet(*star, mass, radius, curr_semi);
283 (*planet)->set_semimajor_evolution(this->ages,
284 this->semis, fakeDerivs);
287 double PlanetData::get_semi(
double age)
289 return (-age*age*age + 1.5*age*age + 2*age + 3)/50;
292 PlanetData::~PlanetData()
295 if(star)
delete star;
298 std::ostream &operator<<(std::ostream &os,
299 const PolynomialEvolutionTrack &track)
302 for(
size_t p=0; p<track.poly_coef.size(); p++) {
303 os << track.poly_coef[p];
305 if(p>1) os <<
"^" << p;
306 if(p<track.poly_coef.size()-1) os <<
" + ";
308 os <<
", " << track.xmin <<
" < x < " << track.xmax;
316 const std::valarray< std::valarray<double> > &poly_coef,
318 double low_mass_age_scaling,
319 double high_mass_age_scaling,
323 if(std::isnan(scale_mass)) scale_mass=mass;
324 std::valarray<double> age_poly_coeff(poly_coef.size());
325 double age_scaling=(mass <=
MAX_LOW_MASS ? low_mass_age_scaling
326 : high_mass_age_scaling);
327 for(
size_t age_i = 0; age_i < poly_coef.size(); ++age_i) {
329 age_poly_coeff[age_i]=0.0;
330 for(
size_t mass_i=0; mass_i<poly_coef[age_i].size(); mass_i++) {
331 age_poly_coeff[age_i]+=mass_pow*poly_coef[age_i][mass_i];
334 age_poly_coeff[age_i]*=std::pow(scale_mass, age_scaling*age_i);
339 std::numeric_limits<double>::max()
346 double eval_poly(
const std::valarray< std::valarray<double> > &poly_coef,
347 double mass,
double age,
double low_mass_age_scaling,
348 double high_mass_age_scaling,
double scale_mass)
350 if(std::isnan(scale_mass)) scale_mass=mass;
351 double age_scaling=(mass<=max_low_mass ? low_mass_age_scaling :
352 high_mass_age_scaling), result=0.0, age_pow=1.0;
353 for(
size_t age_i=0; age_i<poly_coef.size(); age_i++) {
354 double mass_pow=1.0, mass_result=0.0;
355 for(
size_t mass_i=0; mass_i<poly_coef[age_i].size(); mass_i++) {
356 mass_result+=mass_pow*poly_coef[age_i][mass_i];
359 result+=mass_result*age_pow*std::pow(scale_mass, age_scaling*age_i);
366 std::valarray<double> ages,
unsigned deriv_order)
368 std::valarray<double> data(ages.size());
369 for(
unsigned a=0; a<ages.size(); a++) {
371 data[a]=track->
order(deriv_order);
376 PolynomialStellarEvolution::PolynomialStellarEvolution(
377 const std::valarray<double> &masses,
378 const std::valarray<double> &ages,
379 const std::valarray< std::valarray<double> > &r_coef,
380 const std::valarray< std::valarray<double> > &Iconv_coef,
381 const std::valarray< std::valarray<double> > &Itot_coef,
382 const std::valarray< std::valarray<double> > &Mrad_coef,
383 const std::valarray< std::valarray<double> > &Rcore_coef,
384 double low_mass_age_scaling,
double high_mass_age_scaling)
386 std::list< std::valarray<double> > r_data, Iconv_data, Irad_data,
387 Mrad_data, Rcore_data;
389 for(
unsigned i=0; i<masses.size(); i++) {
390 track=exact_track(r_coef, masses[i], low_mass_age_scaling,
391 high_mass_age_scaling);
392 r_data.push_back(tabulate_track(track, ages));
394 track=exact_track(Iconv_coef, masses[i],
395 low_mass_age_scaling, high_mass_age_scaling);
396 Iconv_data.push_back(tabulate_track(track, ages));
398 track=exact_track(Itot_coef-Iconv_coef, masses[i],
399 low_mass_age_scaling, high_mass_age_scaling);
400 Irad_data.push_back(tabulate_track(track, ages));
402 track=exact_track(Mrad_coef, masses[i],
403 low_mass_age_scaling, high_mass_age_scaling);
404 Mrad_data.push_back(tabulate_track(track, ages));
406 track=exact_track(Rcore_coef, masses[i],
407 low_mass_age_scaling, high_mass_age_scaling);
408 Rcore_data.push_back(tabulate_track(track, ages));
411 interpolate_from(masses,
412 std::list< std::valarray<double> >(masses.size(), ages),
413 r_data, Iconv_data, Irad_data, Mrad_data, Rcore_data, NaN, NaN,
414 NaN, NaN, NaN, 0, 0, 0, 0, 0,
415 std::list< std::valarray<double> >(), 0,
416 max_low_mass, low_mass_age_scaling, high_mass_age_scaling);
422 if(deriv_order == 0)
return (*
this)(__deriv_x);
424 double result = (__scale
426 std::pow(__rate, static_cast<int>(deriv_order))
428 std::exp(__rate * __deriv_x)
430 offset_deriv->
order(deriv_order));
437 if(deriv_order == 0)
return (*
this)(__deriv_x);
438 const FunctionDerivatives *f1_deriv = __f1->deriv(__deriv_x),
439 *f2_deriv = __f2->deriv(__deriv_x);
440 double result = (f1_deriv->order(deriv_order)
442 f2_deriv->order(deriv_order));
450 const std::list<const OneArgumentDiffFunction *> &pieces,
454 __range_low(
Core::Inf),
455 __range_high(-
Core::Inf),
459 std::list<const OneArgumentDiffFunction *>::const_iterator
460 piece_i = __pieces.begin();
461 piece_i!=__pieces.end();
464 if((*piece_i)->range_low() < __range_low)
465 __range_low = (*piece_i)->range_low();
466 if((*piece_i)->range_high()>__range_high)
467 __range_high = (*piece_i)->range_high();
473 __pieces.push_back(piece);
474 if(piece->range_low() < __range_low)
475 __range_low = piece->range_low();
476 if(piece->range_high() > __range_high)
477 __range_high = piece->range_high();
482 double deriv_x = __deriv_x;
484 double result =
order(0);
492 if(std::isnan(__deriv_x))
return Core::NaN;
494 std::list<const OneArgumentDiffFunction *>::const_iterator
495 fi = __pieces.begin();
496 fi != __pieces.end();
500 __deriv_x >= (*fi)->range_low()
502 __deriv_x < (*fi)->range_high()
504 if(deriv_order == 0)
return (**fi)(__deriv_x);
505 const FunctionDerivatives *df = (*fi)->deriv(__deriv_x);
506 double result = df->order(deriv_order);
512 if(__deriv_x == __pieces.back()->range_high()) {
513 if(deriv_order == 0)
return (*(__pieces.back()))(__deriv_x);
514 const FunctionDerivatives *df = __pieces.back()->deriv(__deriv_x);
515 double result = df->order(deriv_order);
519 std::ostringstream msg;
520 msg <<
"Requested derivative or function value at age=" 522 <<
", outside the range of any piece in PiecewiseFunction::order.";
529 return (*
this)(__deriv_x);
531 const FunctionDerivatives *df1 = __f1->deriv(__deriv_x),
532 *df2 = __f2->deriv(__deriv_x);
536 df1->order(1) / df2->order(0)
538 df1->order(0) * df2->order(1) / std::pow(df2->order(0), 2)
540 else if(deriv_order == 2)
542 df1->order(2) / df2->order(0)
545 2.0 * df1->order(1) * df2->order(1)
547 std::pow(df2->order(0), 2)
550 df1->order(0) * df2->order(2) / std::pow(df2->order(0), 2)
553 df1->order(0) * std::pow(df2->order(1), 2)
555 std::pow(df2->order(0), 3)
560 "Function ratio derivatives are only implemneted up to and " 572 return (*
this)(__deriv_x);
574 const FunctionDerivatives *df = __f->deriv(__deriv_x);
579 std::pow(df->order(0), __power-1)
582 else if(deriv_order == 2)
589 std::pow(df->order(0), __power-2)
591 std::pow(df->order(1), 2)
593 std::pow(df->order(0), __power - 1) * df->order(2)
598 "Function to power derivatives are only implemneted up to " 599 "and including order 2." 608 if(deriv_order == 0)
return (*
this)(__deriv_x);
609 const FunctionDerivatives *f_deriv = __f->deriv(__deriv_x);
610 double result = __scale*f_deriv->order(deriv_order);
617 if(deriv_order == 0)
return (*
this)(__deriv_x);
619 const FunctionDerivatives *f_deriv=__f->deriv(__deriv_x);
622 result = f_deriv->order(1) / f_deriv->order(0);
623 else if(deriv_order == 2)
624 result = (f_deriv->order(2) / f_deriv->order(0)
626 std::pow(f_deriv->order(1) / f_deriv->order(0), 2));
629 "Log(Function) derivatives are only implemneted up to and " 639 if(deriv_order == 0)
return (*
this)(__deriv_x);
641 const FunctionDerivatives *f_deriv=__f->deriv(__deriv_x);
644 result = - std::sin(f_deriv->order(0)) * f_deriv->order(1);
645 else if(deriv_order == 2)
647 std::cos(f_deriv->order(0)) * std::pow(f_deriv->order(1), 2)
649 std::sin(f_deriv->order(1)) * f_deriv->order(2)
653 "Cos(Function) derivatives are only implemneted up to and " 661 double solve(
double guess_x,
662 double abs_precision,
663 double rel_precision,
664 double (*f)(
double x,
void *params),
665 double (*df) (
double x,
void *params),
666 void (*fdf) (
double x,
void *params,
double *f,
double *df),
671 const gsl_root_fdfsolver_type *T;
672 gsl_root_fdfsolver *s;
673 double x0, x = guess_x;
674 gsl_function_fdf FDF;
681 T = gsl_root_fdfsolver_newton;
682 s = gsl_root_fdfsolver_alloc (T);
683 gsl_root_fdfsolver_set (s, &FDF, x);
687 status = gsl_root_fdfsolver_iterate (s);
689 x = gsl_root_fdfsolver_root (s);
690 status = gsl_root_test_delta (x, x0, abs_precision, rel_precision);
691 }
while (status == GSL_CONTINUE);
693 gsl_root_fdfsolver_free (s);
Implements a StellarEvolution based on polynomial evolution quantities.
const double MIN_AGE
Most tests start at this age in Gyr.
std::valarray< std::valarray< double > > __Irad
The polynomial coefficients of the radiative zone moment of inertia dependence on stellar mass and ag...
std::valarray< std::valarray< double > > __Lum
The polynomial coefficients of the luminosity dependence on stellar mass and age. ...
const double MAX_LOW_MASS
The boundary between high and low mass stars in .
Function arguments do not satisfy some requirement.
RADIUS
The derivative w.r.t. the radius of the body in .
double core_formation_age(const EvolvingStar *star)
The age at which the core of a star forms.
std::valarray< std::valarray< double > > __Menv
The polynomial coefficients of the envelope mass dependence on stellar mass and age.
double order(unsigned deriv_order=1) const
For a derivative object returns the derivative of the given order.
double operator()(double x) const
Evaluates the function at the given x.
double rand_value(double min, double max)
A uniform random real value in the given range.
std::valarray< std::valarray< double > > __Iconv
The polynomial coefficients of the convective zone moment of inertia dependence on stellar mass and a...
const int LUM
Identifier for the stellar luminosity as an interpolation quantity.
double order(unsigned deriv_order=1) const
For a derivative object returns the derivative of the given order.
double order(unsigned deriv_order=1) const
For a derivative object returns the derivative of the given order.
double order(unsigned deriv_order=1) const
For a derivative object returns the derivative of the given order.
double __core_formation_age
The age in Gyr at which the core forms.
A class for stellar properties that depend on age.
virtual double order(unsigned deriv_order=1) const =0
Derivative of the given order of the function with respect to its argument.
MockStellarEvolution(double core_formation_age=Core::NaN, const std::valarray< std::valarray< double > > &R=std::valarray< std::valarray< double > >(), const std::valarray< std::valarray< double > > &Iconv=std::valarray< std::valarray< double > >(), const std::valarray< std::valarray< double > > &Irad=std::valarray< std::valarray< double > >(), const std::valarray< std::valarray< double > > &Rcore=std::valarray< std::valarray< double > >(), const std::valarray< std::valarray< double > > &Mcore=std::valarray< std::valarray< double > >(), const std::valarray< std::valarray< double > > &Lum=std::valarray< std::valarray< double > >())
Uses the given values and polynomials for the quantities.
void rand_poly_coef(std::valarray< std::valarray< double > > &poly_coef, double max_mass=-1)
Fills the given valarray with a random set of polynomial coefficients.
double order(unsigned deriv_order=1) const
Return the given order-th derivative at x set by previous call to deriv().
An EvolvingStellar quantity that uses a polynomial instead of interpolating.
double __xmax
The upper limit of the age at which this quantity can be evaluated.
double order(unsigned deriv_order=1) const
The order-th derivative.
std::valarray< std::valarray< double > > __Itot
The polynomial coefficients of total stellar moment of inertia dependence on stellar mass and age...
std::valarray< std::valarray< double > > __Rcore
The polynomial coefficients of the core radius dependence on stellar mass and age.
double order(unsigned deriv_order=1) const
For a derivative object returns the derivative of the given order.
A class representing arbitrary order derivatives of a function.
EvolvingStellarQuantity * operator()(QuantityID quantity, double mass, double feh) const
See StellarEvolutino::Interpolator::operator()()
Moment of inertia of the radiative zone of the star (low mass stars only) in .
std::valarray< std::valarray< double > > __R
The polynomial coefficients of the radius dependence on mass and age.
double __xmin
The lower limit of the age at which this quantity can be evaluated.
std::valarray< double > __poly_coef
The coefficients of the polynomial giving the evolution.
std::valarray< std::valarray< double > > __Mcore
The polynomial coefficients of the core mass dependence on stellar mass and age.
Moment of inertia of the convective zone of the star (low mass stars only) in .
Several functions stiched together.
QuantityID
Defines the quantities tracked by stellar evolution and their order.
PiecewiseFunction(const std::list< const OneArgumentDiffFunction *> &pieces=std::list< const OneArgumentDiffFunction *>(), double deriv_x=Core::NaN)
Create the function.
Radius of the stellar core in (low mass stars only).
std::valarray< std::valarray< double > > offset_age(const std::valarray< std::valarray< double > > &poly_coef, double age_offset)
Returns new polynomial coefficienst such that output polynomial(mass, age+age_offset)=input polynomia...
void add_piece(const OneArgumentDiffFunction *piece)
Adds another piece of the function, where it applies is defined by its range.
double order(unsigned deriv_order=1) const
For a derivative returns the given order.
Mass of the stellar core in (low mass stars only).
double __deriv_x
The location at which the derivative has been requested.
double order(unsigned deriv_order=1) const
For a derivative object returns the derivative of the given order.