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 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)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
&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.