Skip to content

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 ​

Variables ​

NameTypeAttributesDescription
SERIES_THRESHOLDreal(kind=R8P)parameterBelow 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

NameTypeIntentAttributesDescription
n_nodesinteger(kind=I4P)inNodes number, N >= 2.
t_nodesreal(kind=R8P)inNode temperatures, increasing.
l_nodesreal(kind=R8P)inNode values of Lambda.
alphareal(kind=R8P)inSegment exponents, alpha(k) on [T_k, T_k+1] (alpha(N) unused).
temperaturereal(kind=R8P)inTemperature.

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

NameTypeIntentAttributesDescription
n_nodesinteger(kind=I4P)inNodes number, N >= 2.
t_nodesreal(kind=R8P)inNode temperatures, increasing.
l_nodesreal(kind=R8P)inNode values of Lambda.
alphareal(kind=R8P)inSegment exponents.
y_nodesreal(kind=R8P)inY at the nodes, Y_N = 0.
temperaturereal(kind=R8P)inTemperature.

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

NameTypeIntentAttributesDescription
n_nodesinteger(kind=I4P)inNodes number, N >= 2.
t_nodesreal(kind=R8P)inNode temperatures, increasing.
l_nodesreal(kind=R8P)inNode values of Lambda.
alphareal(kind=R8P)inSegment exponents.
kinteger(kind=I4P)inSegment.
temperaturereal(kind=R8P)inTemperature.

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

NameTypeIntentAttributesDescription
n_nodesinteger(kind=I4P)inNodes number, N >= 2.
t_nodesreal(kind=R8P)inNode temperatures, increasing.
l_nodesreal(kind=R8P)inNode values of Lambda.
alphareal(kind=R8P)inSegment exponents.
y_nodesreal(kind=R8P)inY at the nodes, Y_N = 0.
temperaturereal(kind=R8P)inTemperature before the step.
dyreal(kind=R8P)inIncrement 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

NameTypeIntentAttributesDescription
n_nodesinteger(kind=I4P)inNodes number, N >= 2.
t_nodesreal(kind=R8P)inNode temperatures, increasing.
l_nodesreal(kind=R8P)inNode values of Lambda.
alphareal(kind=R8P)inSegment exponents.
y_nodesreal(kind=R8P)inY at the nodes, Y_N = 0.
gammareal(kind=R8P)inSpecific heats ratio.
Rreal(kind=R8P)inGas constant.
dy_ratereal(kind=R8P)in(gamma - 1) Lambda_N / (m^2 R T_N).
dtreal(kind=R8P)inTime step.
rhoreal(kind=R8P)inDensity.
ereal(kind=R8P)inInternal 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

NameTypeIntentAttributesDescription
n_nodesinteger(kind=I4P)inNodes number.
t_nodesreal(kind=R8P)inNode temperatures, increasing.
temperaturereal(kind=R8P)inTemperature.

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

NameTypeIntentAttributesDescription
epsreal(kind=R8P)inExponent factor.
xreal(kind=R8P)inArgument.

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

NameTypeIntentAttributesDescription
epsreal(kind=R8P)inFactor.
zreal(kind=R8P)inArgument.

Call graph