Appearance
adam_flume_cooling_library
ADAM, FLUME optically thin radiative cooling, Townsend's exact integration (issue #93, M11).
Every routine is pure, takes explicit-size dummies and is tagged !$acc routine seq + !$omp declare target, as in adam_flume_euler_library: the CPU loops and the FNL device kernels call the same source.
The cooling law is d(rho e)/dt = -n^2 Lambda(T) at fixed density and momentum, n = rho / m (m the particle mass) and T = p / (rho R). Lambda is the piecewise power law through the nodes (T_k, Lambda_k), k = 1..N: Lambda = Lambda_k (T / T_k)^alpha_k on [T_k, T_k+1], alpha_k = ln(Lambda_k+1 / Lambda_k) / ln(T_k+1 / T_k); above T_N the last segment continues; below T_1 there is no cooling (the floor).
Isochoric, dT/dt = -(gamma - 1) n^2 Lambda(T) / (rho R). Townsend (2009, ApJS 181, 391, section 2) writes it through the temporal evolution function
Y(T) = (Lambda_N / T_N) int_T^T_N dT' / Lambda(T'),
Y(T) = Y_k + (Lambda_N / Lambda_k) (T_k / T_N) [1 - (T / T_k)^(1 - alpha_k)] / (1 - alpha_k) on segment k,Y_N = 0, decreasing in T (the alpha_k = 1 limit is the logarithm). Along the cooling dY/dt is the constant (gamma - 1) n^2 Lambda_N / (rho R T_N), so one step is exact for any dt: Y_new = Y(T) + dt dY/dt, then T_new = Y^-1(Y_new) on the segment that holds Y_new, and T_new = T_1 exactly when Y_new >= Y_1.
Near alpha_k = 1 both forms lose digits ((1 - x^eps) / eps with eps small); they are evaluated through expm1 and log1p, written here as series where the argument is small, so every alpha_k keeps full precision.
Source: src/app/flume/common/adam_flume_cooling_library.F90
Contents
- cooling_function
- cooling_evolution
- cooling_segment_y
- cooled_temperature
- cooled_internal_energy
- segment_of_temperature
- expm1_over
- log1p_over
Variables
| Name | Type | Attributes | Description |
|---|---|---|---|
SERIES_THRESHOLD | real(kind=R8P) | parameter | Below it, expm1 and log1p are summed as series (above, 1e-14 relative). |
Functions
cooling_function
Return Lambda(T), zero below the first node.
Attributes: pure
Returns: real(kind=R8P)
fortran
function cooling_function(n_nodes, t_nodes, l_nodes, alpha, temperature) result(lambda)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
n_nodes | integer(kind=I4P) | in | Nodes number, N >= 2. | |
t_nodes | real(kind=R8P) | in | Node temperatures, increasing. | |
l_nodes | real(kind=R8P) | in | Node values of Lambda. | |
alpha | real(kind=R8P) | in | Segment exponents, alpha(k) on [T_k, T_k+1] (alpha(N) unused). | |
temperature | real(kind=R8P) | in | Temperature. |
Call graph
cooling_evolution
Return the temporal evolution function Y(T), T > T_1.
Attributes: pure
Returns: real(kind=R8P)
fortran
function cooling_evolution(n_nodes, t_nodes, l_nodes, alpha, y_nodes, temperature) result(y)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
n_nodes | integer(kind=I4P) | in | Nodes number, N >= 2. | |
t_nodes | real(kind=R8P) | in | Node temperatures, increasing. | |
l_nodes | real(kind=R8P) | in | Node values of Lambda. | |
alpha | real(kind=R8P) | in | Segment exponents. | |
y_nodes | real(kind=R8P) | in | Y at the nodes, Y_N = 0. | |
temperature | real(kind=R8P) | in | Temperature. |
Call graph
cooling_segment_y
Return Y(T) - Y_k along the power law of segment k (also beyond its end: the node values Y_k are built from it, and above T_N the last segment continues).
Attributes: pure
Returns: real(kind=R8P)
fortran
function cooling_segment_y(n_nodes, t_nodes, l_nodes, alpha, k, temperature) result(y)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
n_nodes | integer(kind=I4P) | in | Nodes number, N >= 2. | |
t_nodes | real(kind=R8P) | in | Node temperatures, increasing. | |
l_nodes | real(kind=R8P) | in | Node values of Lambda. | |
alpha | real(kind=R8P) | in | Segment exponents. | |
k | integer(kind=I4P) | in | Segment. | |
temperature | real(kind=R8P) | in | Temperature. |
Call graph
cooled_temperature
Return the temperature after an isochoric cooling step that raises Y by dy >= 0; T <= T_1 is not cooled.
Attributes: pure
Returns: real(kind=R8P)
fortran
function cooled_temperature(n_nodes, t_nodes, l_nodes, alpha, y_nodes, temperature, dy) result(t_new)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
n_nodes | integer(kind=I4P) | in | Nodes number, N >= 2. | |
t_nodes | real(kind=R8P) | in | Node temperatures, increasing. | |
l_nodes | real(kind=R8P) | in | Node values of Lambda. | |
alpha | real(kind=R8P) | in | Segment exponents. | |
y_nodes | real(kind=R8P) | in | Y at the nodes, Y_N = 0. | |
temperature | real(kind=R8P) | in | Temperature before the step. | |
dy | real(kind=R8P) | in | Increment of Y over the step. |
Call graph
cooled_internal_energy
Return the internal energy density of a cell after an isochoric cooling step dt; a cell at or below the floor, or with e <= 0, keeps its value bit for bit (no round trip through the temperature).
Attributes: pure
Returns: real(kind=R8P)
fortran
function cooled_internal_energy(n_nodes, t_nodes, l_nodes, alpha, y_nodes, gamma, R, dy_rate, dt, rho, e) result(e_new)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
n_nodes | integer(kind=I4P) | in | Nodes number, N >= 2. | |
t_nodes | real(kind=R8P) | in | Node temperatures, increasing. | |
l_nodes | real(kind=R8P) | in | Node values of Lambda. | |
alpha | real(kind=R8P) | in | Segment exponents. | |
y_nodes | real(kind=R8P) | in | Y at the nodes, Y_N = 0. | |
gamma | real(kind=R8P) | in | Specific heats ratio. | |
R | real(kind=R8P) | in | Gas constant. | |
dy_rate | real(kind=R8P) | in | (gamma - 1) Lambda_N / (m^2 R T_N). | |
dt | real(kind=R8P) | in | Time step. | |
rho | real(kind=R8P) | in | Density. | |
e | real(kind=R8P) | in | Internal energy density, rho e. |
Call graph
segment_of_temperature
Return the segment of a temperature T > T_1: T_k <= T < T_k+1, N - 1 from T_N - 1 up.
Attributes: pure
Returns: integer(kind=I4P)
fortran
function segment_of_temperature(n_nodes, t_nodes, temperature) result(k)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
n_nodes | integer(kind=I4P) | in | Nodes number. | |
t_nodes | real(kind=R8P) | in | Node temperatures, increasing. | |
temperature | real(kind=R8P) | in | Temperature. |
Call graph
expm1_over
Return (exp(eps x) - 1) / eps, x if eps = 0, to full precision for any eps.
Attributes: pure
Returns: real(kind=R8P)
fortran
function expm1_over(eps, x) result(f)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
eps | real(kind=R8P) | in | Exponent factor. | |
x | real(kind=R8P) | in | Argument. |
Call graph
log1p_over
Return log(1 + eps z) / eps, z if eps = 0, to full precision for any eps (1 + eps z > 0).
Attributes: pure
Returns: real(kind=R8P)
fortran
function log1p_over(eps, z) result(f)Arguments
| Name | Type | Intent | Attributes | Description |
|---|---|---|---|---|
eps | real(kind=R8P) | in | Factor. | |
z | real(kind=R8P) | in | Argument. |
Call graph