/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2016 Matthieu Schaller (schaller@strw.leidenuniv.nl).
* 2018 Jacob Kegerreis (jacob.kegerreis@durham.ac.uk).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
******************************************************************************/
#ifndef SWIFT_TILLOTSON_EQUATION_OF_STATE_H
#define SWIFT_TILLOTSON_EQUATION_OF_STATE_H
/**
* @file equation_of_state/planetary/tillotson.h
*
* Contains the Tillotson EOS functions for
* equation_of_state/planetary/equation_of_state.h
*
*/
/* Some standard headers. */
#include
/* Local headers. */
#include "adiabatic_index.h"
#include "common_io.h"
#include "equation_of_state.h"
#include "inline.h"
#include "physical_constants.h"
#include "units.h"
// Tillotson parameters
struct Til_params {
float rho_0, a, b, A, B, u_0, u_iv, u_cv, alpha, beta, eta_min, eta_zero,
P_min;
enum eos_planetary_material_id mat_id;
};
// Parameter values for each material (SI units)
INLINE static void set_Til_iron(struct Til_params *mat,
enum eos_planetary_material_id mat_id) {
mat->mat_id = mat_id;
mat->rho_0 = 7800.0f;
mat->a = 0.5f;
mat->b = 1.5f;
mat->A = 1.28e11f;
mat->B = 1.05e11f;
mat->u_0 = 9.5e6f;
mat->u_iv = 2.4e6f;
mat->u_cv = 8.67e6f;
mat->alpha = 5.0f;
mat->beta = 5.0f;
mat->eta_min = 0.0f;
mat->eta_zero = 0.0f;
mat->P_min = 0.0f;
}
INLINE static void set_Til_granite(struct Til_params *mat,
enum eos_planetary_material_id mat_id) {
mat->mat_id = mat_id;
mat->rho_0 = 2680.0f;
mat->a = 0.5f;
mat->b = 1.3f;
mat->A = 1.8e10f;
mat->B = 1.8e10f;
mat->u_0 = 1.6e7f;
mat->u_iv = 3.5e6f;
mat->u_cv = 1.8e7f;
mat->alpha = 5.0f;
mat->beta = 5.0f;
mat->eta_min = 0.0f;
mat->eta_zero = 0.0f;
mat->P_min = 0.0f;
}
INLINE static void set_Til_basalt(struct Til_params *mat,
enum eos_planetary_material_id mat_id) {
mat->mat_id = mat_id;
mat->rho_0 = 2700.0f;
mat->a = 0.5f;
mat->b = 1.5f;
mat->A = 2.67e10f;
mat->B = 2.67e10f;
mat->u_0 = 4.87e8f;
mat->u_iv = 4.72e6f;
mat->u_cv = 1.82e7f;
mat->alpha = 5.0f;
mat->beta = 5.0f;
mat->eta_min = 0.0f;
mat->eta_zero = 0.0f;
mat->P_min = 0.0f;
}
INLINE static void set_Til_water(struct Til_params *mat,
enum eos_planetary_material_id mat_id) {
mat->mat_id = mat_id;
mat->rho_0 = 998.0f;
mat->a = 0.7f;
mat->b = 0.15f;
mat->A = 2.18e9f;
mat->B = 1.325e10f;
mat->u_0 = 7.0e6f;
mat->u_iv = 4.19e5f;
mat->u_cv = 2.69e6f;
mat->alpha = 10.0f;
mat->beta = 5.0f;
mat->eta_min = 0.925f;
mat->eta_zero = 0.875f;
mat->P_min = 0.0f;
}
// Convert to internal units
INLINE static void convert_units_Til(struct Til_params *mat,
const struct unit_system *us) {
struct unit_system si;
units_init_si(&si);
// SI to cgs
mat->rho_0 *= units_cgs_conversion_factor(&si, UNIT_CONV_DENSITY);
mat->A *= units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE);
mat->B *= units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE);
mat->u_0 *= units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS);
mat->u_iv *= units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS);
mat->u_cv *= units_cgs_conversion_factor(&si, UNIT_CONV_ENERGY_PER_UNIT_MASS);
mat->P_min *= units_cgs_conversion_factor(&si, UNIT_CONV_PRESSURE);
// cgs to internal
mat->rho_0 /= units_cgs_conversion_factor(us, UNIT_CONV_DENSITY);
mat->A /= units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
mat->B /= units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
mat->u_0 /= units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
mat->u_iv /= units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
mat->u_cv /= units_cgs_conversion_factor(us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
mat->P_min /= units_cgs_conversion_factor(us, UNIT_CONV_PRESSURE);
}
// gas_internal_energy_from_entropy
INLINE static float Til_internal_energy_from_entropy(
float density, float entropy, const struct Til_params *mat) {
error("This EOS function is not yet implemented!");
return 0.f;
}
// gas_pressure_from_entropy
INLINE static float Til_pressure_from_entropy(float density, float entropy,
const struct Til_params *mat) {
error("This EOS function is not yet implemented!");
return 0.f;
}
// gas_entropy_from_pressure
INLINE static float Til_entropy_from_pressure(float density, float pressure,
const struct Til_params *mat) {
error("This EOS function is not yet implemented!");
return 0.f;
}
// gas_soundspeed_from_entropy
INLINE static float Til_soundspeed_from_entropy(float density, float entropy,
const struct Til_params *mat) {
error("This EOS function is not yet implemented!");
return 0.f;
}
// gas_entropy_from_internal_energy
INLINE static float Til_entropy_from_internal_energy(
float density, float u, const struct Til_params *mat) {
return 0.f;
}
// gas_pressure_from_internal_energy
INLINE static float Til_pressure_from_internal_energy(
float density, float u, const struct Til_params *mat) {
const float eta = density / mat->rho_0;
const float eta_sq = eta * eta;
const float mu = eta - 1.f;
const float nu = 1.f / eta - 1.f;
const float w = u / (mat->u_0 * eta_sq) + 1.f;
const float w_inv = 1.f / w;
float P_c, P_e, P;
// Condensed or cold
P_c =
(mat->a + mat->b * w_inv) * density * u + mat->A * mu + mat->B * mu * mu;
if (eta < mat->eta_zero) {
P_c = 0.f;
} else if (eta < mat->eta_min) {
P_c *= (eta - mat->eta_zero) / (mat->eta_min - mat->eta_zero);
}
// Expanded and hot
P_e = mat->a * density * u +
(mat->b * density * u * w_inv + mat->A * mu * expf(-mat->beta * nu)) *
expf(-mat->alpha * nu * nu);
// Condensed or cold state
if ((1.f < eta) || (u < mat->u_iv)) {
P = P_c;
}
// Expanded and hot state
else if ((eta < 1.f) && (mat->u_cv < u)) {
P = P_e;
}
// Hybrid state
else {
P = ((u - mat->u_iv) * P_e + (mat->u_cv - u) * P_c) /
(mat->u_cv - mat->u_iv);
}
// Minimum pressure
if (P < mat->P_min) {
P = mat->P_min;
}
return P;
}
// gas_internal_energy_from_pressure
INLINE static float Til_internal_energy_from_pressure(
float density, float P, const struct Til_params *mat) {
error("This EOS function is not yet implemented!");
return 0.f;
}
// gas_soundspeed_from_internal_energy
INLINE static float Til_soundspeed_from_internal_energy(
float density, float u, const struct Til_params *mat) {
const float rho_0_inv = 1.f / mat->rho_0;
const float eta = density * rho_0_inv;
const float rho_inv = 1.f / density;
const float eta_sq = eta * eta;
const float mu = eta - 1.f;
const float nu = 1.f / eta - 1.f;
const float w = u / (mat->u_0 * eta_sq) + 1.f;
const float w_inv = 1.f / w;
const float w_inv_sq = w_inv * w_inv;
const float exp_beta = expf(-mat->beta * nu);
const float exp_alpha = expf(-mat->alpha * nu * nu);
float P_c, P_e, c_sq_c, c_sq_e, c_sq;
// Condensed or cold
P_c =
(mat->a + mat->b * w_inv) * density * u + mat->A * mu + mat->B * mu * mu;
if (eta < mat->eta_zero) {
P_c = 0.f;
} else if (eta < mat->eta_min) {
P_c *= (eta - mat->eta_zero) / (mat->eta_min - mat->eta_zero);
}
c_sq_c = P_c * rho_inv * (1.f + mat->a + mat->b * w_inv) +
mat->b * (w - 1.f) * w_inv_sq * (2.f * u - P_c * rho_inv) +
rho_inv * (mat->A + mat->B * (eta_sq - 1.f));
// Expanded and hot
P_e = mat->a * density * u +
(mat->b * density * u * w_inv + mat->A * mu * exp_beta) * exp_alpha;
c_sq_e =
P_e * rho_inv * (1.f + mat->a + mat->b * w_inv * exp_alpha) +
(mat->b * density * u * w_inv_sq / eta_sq *
(rho_inv / mat->u_0 * (2.f * u - P_e * rho_inv) +
2.f * mat->alpha * nu * w * rho_0_inv) +
mat->A * rho_0_inv *
(1.f + mu / eta_sq * (mat->beta + 2.f * mat->alpha * nu - eta)) *
exp_beta) *
exp_alpha;
// Condensed or cold state
if ((1.f < eta) || (u < mat->u_iv)) {
c_sq = c_sq_c;
}
// Expanded and hot state
else if ((eta < 1.f) && (mat->u_cv < u)) {
c_sq = c_sq_e;
}
// Hybrid state
else {
c_sq = ((u - mat->u_iv) * c_sq_e + (mat->u_cv - u) * c_sq_c) /
(mat->u_cv - mat->u_iv);
}
c_sq = fmaxf(c_sq, mat->A * rho_0_inv);
return sqrtf(c_sq);
}
// gas_soundspeed_from_pressure
INLINE static float Til_soundspeed_from_pressure(float density, float P,
const struct Til_params *mat) {
error("This EOS function is not yet implemented!");
return 0.f;
}
#endif /* SWIFT_TILLOTSON_EQUATION_OF_STATE_H */