Contact: Isaac Held, Peter Phillipps
Reviewers:
A package of routines for spectral transforms
and manipulation of spherical coefficients.
Supports domain decomposition for running on
distributed memory machines.
This transforms module provides the ability to transform spectral
spherical harmonics fields to a transform grid (and vice-versa)
to differentiate in the spectral domain, to compute vorticity and
divergence from a velocity field (and vice-versa) and a variety
of related operations.
Arrays of both gridded data and spherical coefficients are
distributed across processors. This domain decomposition is
done in the meridional direction only, the domain of each processor
retains all vertical levels and all longitudes.
Except where indicated, all arrays appearing as arguments to
public routines must have horizontal dimensions equal to the
extents on the local processor. These extents are denoted as follows:
is:ie -- the lower and upper limits of the longitude index of gridded data arrays
Currently, is=1 and je=(global number of longitude points) for any decomposition.
js:je -- the lower and upper limits of the latitude index of gridded data arrays
ms:me -- the lower and upper limits of zonal wavenumber of spectral data arrays
ns:ne -- the lower and upper limits of meridional wavenumber of spectral data arrays
The number of processors must be less than or equal to the
number of fourier waves and must divide evenly into half the
number of latitude rows.
A tutorial program is available which provides
a way of learning how to use this module.
mpp_mod
mpp_domains_mod
spec_mpp_mod
fms_mod
spherical_fourier_mod
grid_fourier_mod
use transforms_mod [,only: transforms_init,
transforms_are_initialized,
reset_num_lon_in_transform,
trans_spherical_to_grid,
trans_grid_to_spherical,
divide_by_cos,
divide_by_cos2,
trans_filter,
vor_div_from_uv_grid,
uv_grid_from_vor_div,
horizontal_advection,
area_weighted_global_mean,
get_lat_max,
get_triang_trunc,
get_num_fourier,
get_fourier_inc,
get_num_spherical,
get_grid_boundaries,
spherical_fourier_init,
trans_spherical_to_fourier,
trans_fourier_to_spherical,
get_south_to_north,
get_sin_lat,
get_cos_lat,
get_cosm_lat,
get_cosm2_lat,
get_deg_lat,
get_wts_lat,
grid_fourier_init,
trans_grid_to_fourier,
trans_fourier_to_grid,
get_lon_max,
get_longitude_origin,
get_deg_lon,
spherical_init,
compute_lon_deriv_cos,
compute_lat_deriv_cos,
compute_laplacian,
compute_vor,
compute_div,
get_spherical_wave,
get_fourier_wave,
get_eigen_laplacian,
compute_gradient_cos,
compute_ucos_vcos,
compute_vor_div,
triangular_truncation,
rhomboidal_truncation,
compute_legendre,
compute_gaussian,
spec_mpp_init,
get_grid_domain,
get_spec_domain,
grid_domain,
spectral_domain,
grid_fourier_end,
spherical_end,
spherical_fourier_end,
transforms_end,
---------------------------------------------------------------------------
type(domain2d) :: grid_domain
Derived-type variable that containing information related
to the decomposition of grid data arrays amoung processors.
Example of its use:
call set_domain(grid_domain)
call read_data(unit,grid_data)
call write_data(unit,grid_data)
Note that read_data and write_data are public routines of fms_mod
---------------------------------------------------------------------------
type(domain2d) :: spectral_domain
Derived-type variable that contains information related to the
decomposition of spherical coefficent arrays amoung processors.
Example of its use:
call set_domain(spectral_domain)
call read_data(unit,spectral_data)
call write_data(unit,spectral_data)
---------------------------------------------------------------------------
subroutine transforms_init
function transforms_are_initialized
subroutine get_grid_domain
subroutine get_spec_domain
subroutine trans_spherical_to_grid
subroutine trans_grid_to_spherical
subroutine divide_by_cos
subroutine divide_by_cos2
subroutine get_lat_max
subroutine get_triang_trunc
subroutine get_num_fourier
subroutine get_fourier_inc
subroutine get_num_spherical
subroutine get_grid_boundaries
subroutine vor_div_from_uv_grid
subroutine uv_grid_from_vor_div
subroutine horizontal_advection
function area_weighted_global_mean
subroutine reset_num_lon_in_transform
subroutine trans_filter
subroutine spherical_fourier_init
subroutine trans_spherical_to_fourier
subroutine trans_fourier_to_spherical
subroutine get_south_to_north
subroutine get_sin_lat
subroutine get_cos_lat
subroutine get_cosm_lat
subroutine get_cosm2_lat
subroutine get_deg_lat
subroutine get_wts_lat
subroutine grid_fourier_init
function trans_grid_to_fourier
function trans_fourier_to_grid
subroutine get_lon_max
subroutine get_longitude_origin
subroutine get_deg_lon
subroutine spherical_init
function compute_lon_deriv_cos
function compute_lat_deriv_cos
function compute_laplacian
function compute_vor
function compute_div
subroutine get_spherical_wave
subroutine get_fourier_wave
subroutine get_eigen_laplacian
subroutine compute_gradient_cos
subroutine compute_ucos_vcos
subroutine compute_vor_div
subroutine triangular_truncation
subroutine rhomboidal_truncation
subroutine compute_legendre
subroutine compute_gaussian
subroutine spec_mpp_init
subroutine grid_fourier_end
subroutine spherical_end
subroutine spherical_fourier_end
subroutine transforms_end
subroutine transforms_init(radius, &
lat_max, &
lon_max, &
num_fourier, &
fourier_inc, &
num_spherical, &
south_to_north, &
triang_trunc, &
longitude_origin)
input
real :: radius -- radius of the sphere
integer :: lat_max -- number of latitude points in transform grid
integer :: lon_max -- number of longitude points in transform grid
integer :: num_fourier --
the fourier wavenumbers in the truncation are set equal to
fourier_inc*m, where m = 0, num_fourier
therefore, the total number of fourier modes is num_fourier +1
integer :: fourier_inc -- the wavenumber increment (see num_fourier above)
integer :: num_spherical -- the maximum meridional wavenumber
Retained meridional wavewnumbers are n = 0,num_spherical
The total spherical wavenumber is L = n+m
optional:
logical :: south_to_north --
.true. -- the latitudinal dimension of
grid and fourier fields runs from south to north
.false. -- the latitudinal dimension of
grid and fourier fields runs from north to south
default is .true.
logical :: triang_trunc --
.true. -- subroutines trans_grid_to_spherical and vor_div_from_uv_grid
will triangularly truncate their output, except that
subroutine trans_grid_to_spherical can optionally
skip this step.
.false. -- as above, except rhomboidal truncation is done.
default = .true.
real :: longitude_origin --
the longitude of the first longitude point (radians)
default = 0.0
longitude_origin has no function within the transform
package itself. It is included to facilitate the correct
alignment of model data to the transform grid.
----------------------------------------------------------------------------
function transforms_are_initialized()
Returns .true. if transforms_init has been called, .false. if not.
----------------------------------------------------------------------------
subroutine get_grid_domain(is, ie, js, je)
intent(out):
is, ie, js, je = starting and endding indices within the global horizontal
domain of a gridded field's processor local data.
Example of the use of these indices:
A field dimensioned (lon_max, lat_max, num_levels) in the global domain
could be dimensioned on each processor as (is:ie, js:je, num_levels)
or as (ie-is+1, je-js+1, num_levels)
---------------------------------------------------------------------------
subroutine get_spec_domain(ms, me, ns, ne)
intent(out):
ms, me, ns, ne = starting and endding indices within the global horizontal
domain of a spectral coefficient field's processor local data.
Example of the use of these indices:
A field dimensioned (0:num_fourier, 0:num_spherical, num_levels) in the global domain
could be dimensioned on each processor as (ms:me, ns:ne, num_levels)
or as (me-ms+1, ne-ns+1, num_levels)
---------------------------------------------------------------------------
subroutine trans_spherical_to_grid(spherical, grid)
transforms either 2D or 3D spherical harmonics field to grid field
intent (in):
complex, dimension(ms:me, ns:ne, num_levels) :: spherical
or
complex, dimension(ms:me, ns:ne) :: spherical
intent (out):
real, dimension(is:ie, js:je, num_levels) :: grid
or
real, dimension(is:ie, js:je) :: grid
----------------------------------------------------------------------------
subroutine trans_grid_to_spherical(grid, spherical, do_truncation)
transforms either 2D or 3D grid field to spherical harmonics field
intent (in):
real, dimension(is:ie, js:je, num_levels) :: grid
or
real, dimension(is:ie, js:je) :: grid
intent (out):
complex, dimension(ms:me, ns:ne, num_levels) :: spherical
or
complex, dimension(ms:me, ns:ne) :: spherical
optional:
logical :: do_truncation --
.true. -- truncation of spherical field is performed
.false. -- truncation of spherical field is not performed
default = .true.
---------------------------------------------------------------------------
subroutine divide_by_cos(grid)
divides grid by cos(lat)
intent (in/out):
real, dimension(is:ie, js:je, num_levels) :: grid
or
real, dimension(is:ie, js:je) :: grid
---------------------------------------------------------------------------
subroutine divide_by_cos2(grid)
divides grid by cos(lat)*cos(lat)
intent (in/out):
real, dimension(is:ie, js:je, num_levels) :: grid
or
real, dimension(is:ie, js:je) :: grid
---------------------------------------------------------------------------
subroutine get_lon_max(lon_max)
Returns the number of longitude points in the transform grid.
lon_max is specified at initialization.
See subroutine transforms_init
integer, intent(out) :: lon_max
---------------------------------------------------------------------------
subroutine get_lat_max(lat_max)
Returns the number of latitude rows in the transform grid.
lat_max is specified at initialization.
See subroutine transforms_init
integer, intent (out) :: lat_max
---------------------------------------------------------------------------
subroutine get_longitude_origin(longitude_origin)
Returns longitude of the first longitude point
longitude_origin is specified at initialization.
See subroutine transforms_init
real, intent (out) :: longitude_origin
---------------------------------------------------------------------------
subroutine get_triang_trunc(triang_trunc)
Returns .true. if truncation is triangular
Returns .false. if truncation is rhomboidal
triang_trunc is specified at initialization.
See subroutine transforms_init
intent (out):
logical :: triang_trunc
---------------------------------------------------------------------------
subroutine get_num_fourier(num_fourier)
Returns the number of retained zonal wavenumbers.
num_fourier is specified at initialization.
See subroutine transforms_init
intent (out):
integer :: num_fourier
---------------------------------------------------------------------------
subroutine get_fourier_inc(fourier_inc)
Returns the zonal wavenumber increment.
fourier_inc is specified at initialization.
See subroutine transforms_init
intent (out):
integer :: fourier_inc
---------------------------------------------------------------------------
subroutine get_num_spherical(num_spherical)
Returns the number of meridional wavenumbers.
num_spherical is specified at initialization.
See subroutine transforms_init
intent (out):
integer :: num_spherical
---------------------------------------------------------------------------
subroutine get_grid_boundaries(lon_boundaries, lat_boundaries, global)
Returns the coordinates of the boundaries of the transform grid boxes. (radians)
intent (out):
real, dimension(is:ie+1) :: lon_boundaries
real, dimension(js:je+1) :: lat_boundaries
or
real, dimension(lon_max+1) :: lon_boundaries
real, dimension(lat_max+1) :: lat_boundaries
optional:
logical :: global --
.true. -- Returns boundaries of global grid
.false. -- Returns boundaries of grid local to processor
default = .false.
---------------------------------------------------------------------------
subroutine vor_div_from_uv_grid(ug, vg, vors, divs, triang)
Returns spectral coefficients of vorticity and
divergence given grid fields of velocity.
(Inverse of uv_grid_from_vor_div)
Both 2d and 3d interfaces exist.
intent (in):
real, dimension(is:ie, js:je, num_levels) :: ug, vg
or
real, dimension(is:ie, js:je) :: ug, vg
intent (out):
complex, dimension(ms:me, ns:me, num_levels) :: vors, divs
or
complex, dimension(ms:me, ns:me) :: vors, divs
optional:
logical :: triang -- determines triangular or rhomboidal truncation.
If not present then does triangular truncation.
---------------------------------------------------------------------------
subroutine uv_grid_from_vor_div(vors, divs, ug, vg)
Returns grid fields of velocity given spectral
coefficients of vorticity and divergence.
(Inverse of vor_div_from_uv_grid)
Both 2d and 3d interfaces exist.
intent (in):
complex, dimension(ms:me, ns:me, num_levels) :: vors, divs
or
complex, dimension(ms:me, ns:me) :: vors, divs
intent (out):
real, dimension(is:ie, js:je, num_levels) :: ug, vg
or
real, dimension(is:ie, js:je) :: ug, vg
---------------------------------------------------------------------------
subroutine horizontal_advection(field_spec, ug, vg, tendency)
Adds the tendency of "field_spec" due to
horizontal advection to the input tendency.
Both 2d and 3d interfaces exist.
intent (in):
complex, dimension(is:ie, js:je, num_levels) :: field_spec
or
complex, dimension(is:ie, js:je) :: field_spec
real, dimension(is:ie, js:je, num_levels) :: ug, vg
or
real, dimension(is:ie, js:je) :: ug, vg
intent(inout):
real, dimension(is:ie, js:je, num_levels) :: tendency
or
real, dimension(is:ie, js:je) :: tendency
---------------------------------------------------------------------------
function area_weighted_global_mean(field)
Returns the area weighted global mean of a 2-d field
Input is a field of values local to the processor.
intent (in):
real, dimension(is:ie, js:je) :: field
---------------------------------------------------------------------------
subroutine reset_num_lon_in_transform(num_lon, trunc_fourier, longitude_origin)
intent (in):
integer :: num_lon -- the number of longitudes to which the
transforms module is reset
integer :: trunc_fourier -- the fourier wavenumbers to be
used by the fft are (0:trunc_fourier)
must be less than or equal to num_fourier
optional:
real :: longitude_origin --
the longitude of the first longitude point (radians)
default = 0.0
---------------------------------------------------------------------------
subroutine trans_filter(grid, filter)
Transforms grid to spectral harmonics field,
multiplies by filter, then transforms back.
intent (inout):
real, dimension(is:ie, js:je, num_levels) :: grid
or
real, dimension(is:ie, js:je) :: grid
optional:
real, dimension (ms:me, ns:ne) :: filter
if filter is not present, then filter is assumed = 1
---------------------------------------------------------------------------
subroutine spherical_fourier_init(lat_max, num_fourier, &
fourier_inc, num_spherical, &
south_to_north=south_to_north)
&transforms_nml
check_fourier_imag = .true. : A check that the imaginary part of wavenumber zero
is zero is done when trans_fourier_to_grid is called.
= .false.: No such check is done.
default = .false.
Numerous error checks exist. All error messages are self explanatory so far as possible.