%	smalldyn.s
%
%	Purpose:	Small part of HIRLAM DYN specification for testing
%	Copyright:	R.A. van Engelen, Leiden University, 1997

include vecalg, arakawa.

% Dimensions

SomeDim := _G207699.
Time := "s".
Temperature := "K".
Distance := "m".
Pressure := "Pa".
DimLess := "1".
Velocity := Distance / Time.
Accelleration := Distance / Time ^ 2.
PressureTendency := Pressure / Time.
TemperatureTendency := Temperature / Time.

% Constants and parameters

r :: real ~ Distance := 6371 ~ "km".
	% radius of earth
R_d :: real ~ "J/kg/K" := 287.04 ~ "J/kg/K".
% gas constant for dry air
R_v :: real ~ "J/kg/K" := 461.51 ~ "J/kg/K".
% gas constant for water vapour
c_pd :: real ~ "J/kg/K" := 1004.64 ~ "J/kg/K".
% specific heat for dry air at constant pressure
c_pv :: real ~ "J/kg/K" := 1869.46 ~ "J/kg/K".
% specific heat for moist air at constant pressure

[delta, epsilon, kappa] isa parameter_var.

delta :: real := c_pv / c_pd.
epsilon :: real := R_d / R_v.
kappa :: real := R_d / c_pd.

% Grid size

natural := integer(1 .. infinity).

[nlon, nlat, nlev] isa parameter_var.

nlon :: natural.
nlat :: natural.
nlev :: integer(2 .. infinity).

% Vertical grid consists of at least 2 grid points.
% This constraint allows stronger optimization of vertical boundary conditions
% imposed on the eta_p field

% Computational domains

longitudinal := i = 1 .. nlon.
latitudinal := j = 1 .. nlat.
horizontal := longitudinal by latitudinal.
vertical := k = 1 .. nlev.
global := horizontal by vertical.
atmosphere := k = 2 .. nlev.

% Metric coefficients for the HIRLAM coordinate system

[h_x, h_y] isa parameter_var.
h_x :: real field (x, y).
h_y :: real field (x, y).

h_x is abstraction_of(grid, choices = (hxv, hxu, hxt)).
h_y is abstraction_of(grid, choices = (hyu, hyv, hyt)).

[hxu, hxv, hxt] isa parameter_var.
hxu :: real field (x(half), y(grid)) on horizontal.
hxv :: real field (x(grid), y(half)) on horizontal.
hxt :: real field (x(grid), y(grid)) on horizontal.
hxu has latex_name("h_{x,u}").
hxv has latex_name("h_{x,v}").
hxt has latex_name("h_{x,t}").

[hyu, hyv, hyt] isa parameter_var.
hyu :: real field (x(half), y(grid)) on horizontal.
hyv :: real field (x(grid), y(half)) on horizontal.
hyt :: real field (x(grid), y(grid)) on horizontal.
hyu has latex_name("h_{y,u}").
hyv has latex_name("h_{y,v}").
hyt has latex_name("h_{y,t}").

H := [h_x, h_y].

% Use the chain-rule for symbolic differentiation and integration

include diff.

mode(diff, chain).

coordinates := [x, y].
coefficients := H.

eta := z ~ "1".
eta(N) := N.

% Grid-point distances for finite differences

rdlam isa parameter_var.
rdth isa parameter_var.
rdlam :: real(0 .. 1).
rdth :: real(0 .. 1).

delta x :: real := r / rdlam.
delta y :: real := r / rdth.
delta z :: real := 1.

% Override LaTeX descriptions of vertical finite differences

df_g(Expr, z) latex precedence(300); "\Delta^+_z", Expr.
df_h(Expr, z) latex precedence(300); "\Delta^-_z", Expr.

% Pressure

A isa parameter_var.
B isa parameter_var.
A :: real(0 .. 107000) ~ Pressure field z(grid) on vertical.
B :: real(0 .. 1) ~ DimLess field z(grid) on vertical.
p_s :: real(10000 .. 107000) ~ Pressure field ( x(grid)
, y(grid)
) on horizontal.
p :: (real(0 .. 107000) ~ Pressure field ( x(grid)
, y(grid)
, z(grid)
) monotonic k(+) on global :=
A + B * p_s
).
% Horizontal wind velocity vector u :: real ~ Velocity field ( x(half)
, y(grid)
, z(half)
) on global.
v :: real ~ Velocity field ( x(grid)
, y(half)
, z(half)
) on global.
V_h := [u, v]. % Auxiliary horizontal wind velocity vector u_aux :: (real ~ (Pressure * Velocity) field ( x(half)
, y(grid)
, z(half)
) on
global
).
v_aux :: (real ~ (Pressure * Velocity) field ( x(grid)
, y(half)
, z(half)
) on
global
).
V := [u_aux, v_aux]. V = V_h * d p / d eta. % Temperature (virtual) T :: (real(0 .. infinity) ~ Temperature field ( x(grid)
, y(grid)
, z(half)
) on
global
).
ltvir :: boolean. ltvir := false. T_v := T * (1 + (1 / epsilon - 1) * q) if ltvir \\ T otherwise. % Surface pressure tendency p_s_t :: (real ~ PressureTendency field ( x(grid)
, y(grid)
, z(grid)
) on
horizontal
).
p_s_t = - integrate(nabla .* V, eta = eta(1) .. eta(nlev + 1)). % Subroutine declaration subroutine(smalldyn, [V_h, T], [p_s_t]). % Fortran stuff A has fortran_name(AHYB). B has fortran_name(BHYB). p_s has fortran_name(PS). u has fortran_name(PUZ). v has fortran_name(PVZ). T has fortran_name(PTZ). q has fortran_name(PQZ). p_s_t has fortran_name(PDPSDT). T_t has fortran_name(PDTDT).