Topic: Registry-generated state data definition and allocation

 

Summary

 

This page describes the generation of Fortran90 code that declares and dynamically allocates/deallocates state array fields in the derived data type TYPE(domain), which is defined in frame/module_domain.F in the WRF framework. The table below lists and describes the Registry-generated files:

 

Generated File:

Included by:

Generated by:

Description:

state_struct.inc

module_domain

tools/gen_defs.c: gen_state_struct.c

field declarations (simple data types)

state_subtypes.inc

module_domain

tools/gen_defs.c: gen_state_subtypes()

field declarations (derived data types)

core_allocs.inc

alloc_space_field in module_domain

tools/gen_allocs.c: gen_alloc()

core-specific field memory allocation

core_deallocs.inc

dealloc_space_field in module_domain

tools/gen_allocs.c: gen_dealloc()

core-specific field memory deallocation

 

The generation of these files is controlled by dimspec and state entries of the Registry database.

 

Click for Registry Reference Manual in PDF.

 

 

1                     state_struct.inc

 

State_struct.inc contains the declarations of fields that make up TYPE(domain) in the WRF framework. In WRF, this Fortran90 derived datatype is used to represent the state data for each domain. Each field is either a scalar, a pointer to a dynamically allocated deferred shape array, or a derived data type. Registry-generated derived data types are discussed in the next section.

1.1                   Usage:                                                               

 

Included in frame/module_domain.F as part of the TYPE(domain) declaration:

 

   TYPE domain

 

#include <state_struct.inc>

 

   END TYPE domain

 

1.2                   Generated code:

 

The code in state_struct.inc expands to:

 

   TYPE domain

   (scalar field declarations)

real                                     :: epsts

integer                                  :: step_number

   (pointers to core-specific deferred shape arrays)

real      ,DIMENSION(:,:)     ,POINTER   :: em_muu  ! 2-D, single time level

real      ,DIMENSION(:,:,:)   ,POINTER   :: em_u_1  ! 3-D, 1 of 2 time levels

real      ,DIMENSION(:,:,:)   ,POINTER   :: em_u_2  ! 3-D, 2 of 2 time levels

   (pointers to non-core-specific deferred shape arrays)

real      ,DIMENSION(:)       ,POINTER   :: fcx   ! 1-D

real      ,DIMENSION(:,:)     ,POINTER   :: psfc  ! 2-D

real      ,DIMENSION(:,:,:)   ,POINTER   :: div   ! 3-D

   (pointers to deferred-shape 4D arrays for tracers)

real      ,DIMENSION(:,:,:,:) ,POINTER   :: moist_1  ! 4-D, 1 of 2 time levels

real      ,DIMENSION(:,:,:,:) ,POINTER   :: moist_2  ! 4-D, 2 of 2 time levels

   END TYPE domain

 

1.3                   Registry specification:

 

For a given field, the code generated to state_struct.inc is based on dimspec and state entries within the Registry file.  The code shown above is generated from the following Registry entries:

 

#keyword  dim   order   definition            coord axis    dimension name

dimspec    i      1     standard_domain           x          west_east

dimspec    j      3     standard_domain           y          south_north

dimspec    k      2     standard_domain           z          bottom_top
dimspec    w      -     namelist=spec_bdy_width   c          spec_bdy_width

 

#keyword type    varname      dims   use      ntl  . . . description       

state    real    epsts        -      misc      -   . . . "leapfrog time filter constant"

state    integer step_number  -      misc      -   . . .                                                         

state    real    muu          ij     dyn_em    1   . . .

state    real    u            ikj    dyn_em    2   . . . "x-wind component"  "m s-1"

state    real    fcx          w      misc      -   . . . "RELAXATION TERM FOR BOUNDARY

state    real    psfc         ij     misc      1   . . . "SFC PRESSURE"      "Pa"

state    real    div          ikj    misc      1   . . . "DIVERGENCE"

state    real    qv           ikjft  moist     2   . . . "Water vapor mixing ratio" "kg kg-1"

 

The dimspec entries define the dimension descriptors that are used in the dims field of the state entry. For the purpose of generating the state_struct.inc file, in which the declarations are pointers to deferred shape arrays, it is sufficient to know only the number of dimensions. Most of the information in the dimspec entries is used later, in the Registry-generated code to allocate the fields.

 

The type field of the state arrays is self-explanatory.

 

With the exception of qv, the varname field provides the base name of the field to be declared in state_struct.inc. Qv is a tracer in a four-dimensional tracer array (as indicated by the special descriptor ‘f’ in the dims field). These will be discussed shortly. For the other varnames:

 

  1. If the variable is single time-level and non-core-associated, the base name of the field may be used as-is. Single time-level variables are indicated with a ‘-’  or  a ‘1’ in the ntl field.  Examples: epsts, step_number.
  2. If a variable has more than 2 or 3 time-levels, multiple declarations are generated to the state_struct.inc file, one for each time level. The time-level of the declaration is indicated with by appending an underscore and the time level to the variable name in the declaration. Examples: u and moist.
  3. If a variable is core-associated, it will have dyn_core in the use field of the state entry. In this case, core and an underscore are prepended to the variable name in the declaration. Examples: u and muu.

                                                                                                                                

In the case of tracers, such as Qv, the base name of the variable declared in state_struct.inc is the name of the four-dimensional array that will contain the tracers, not the tracer names themselves (rather, these are indexed over the fourth dimension of the array). The base name for tracers is given in the use field of the state entry. As above, multiple time level suffixed declarations will be generated if ntl is 2 or 3. Four-dimensional arrays are never core-associated.

1.4                   Generated by:

 

The code that generates state_struct.inc is the subroutine gen_state_struct() defined in tools/gen_defs.c  in the WRF source code distribution.

 

 

2                     state_subtypes.inc

 

The derived data types defined in state_subtypes may be used to declare state fields in the TYPE(domain) or to declare variables of the derived data type in code that USEs module_domain of the framework. Registry-generated derived data types are used in WRF 3DVAR. The WRF model itself does not define or use Registry-generated derived data types at this time.

2.1                   Usage:

 

Included in frame/module_domain.F prior to the main TYPE(domain) declaration. 

 

#include <state_subtypes.inc>

 

(Note, the link to the file may not contain any generated code since it links back to the WRF model, which does not use derived data types).

2.2                   Registry specification:

 

Registry entries for derived data types look like state declarations except that instead of the keyword state they begin with the keyword typedef followed by the name of the type being defined. Fields of a type are declared in the order the entries appear. The third element of a typedef entry is the type of the field, which may be a simple type or a previously defined derived type.

                                                                                                                                                                                                              

    (Registry definition of a derived data type)

typedef vp_type real    v1                      ijk      -         1        -       -

typedef vp_type real    v2                      ijk      -         1        -       -

typedef vp_type real    v3                      ijk      -         1        -       -

typedef vp_type real    v4                      ijk      -         1        -       -

typedef vp_type real    v5                      ijk      -         1        -       -

 

Once defined, a derived type may be used to define state entries in the Registry:

 

    (Registry declaration of a state variable using derived data type)

state           vp_type vv - -

 

2.3                   Generated code:

 

The Registry program generates the following declarations in state_subtypes.inc from the typedefs shown above.

 

   (Registry-generated declaration of a derived data type in state_subtypes.inc)

TYPE vp_type

real      ,DIMENSION(:,:,:)   ,POINTER   :: v1

real      ,DIMENSION(:,:,:)   ,POINTER   :: v2

real      ,DIMENSION(:,:,:)   ,POINTER   :: v3

real      ,DIMENSION(:,:,:)   ,POINTER   :: v4

real      ,DIMENSION(:,:,:)   ,POINTER   :: v5

END TYPE vp_type

 

The above example of a state declaration that uses the derived type results in the following being generated to state_struct.inc:

 

  (Registry-generated declaration using the derived data type in state_struct.inc)

TYPE(vp_type)                               :: vv

 

2.4                   Generated by:

 

The code that generates state_struct.inc is the subroutine gen_state_subtypes() defined in tools/gen_defs.c  in the WRF source code distribution.

 

 

3                     core_allocs.inc

 

Core_allocs.inc includes Fortran90 ALLOCATE statements and related code for dynamically allocating memory for fields that are pointers to deferred shape arrays in TYPE(domain) in frame/module_dm.F that are associated with the dynamic core core. In addition to ALLOCATE statements for multi-dimensional fields, core­_allocs includes to set the array and scalar fields of TYPE(domain) to an initial value, the value for which is declared as the real initial_data_value and defined in the including routine. For other integer fields, the initial value is zero. For logical the initial value is .FALSE.

3.1                   Usage:

 

In the WRF framework, core­­_allocs.inc files (e.g. em_allocs.inc) are included inside a conditional in the routine alloc_space_field, also in frame/module_dm.F.

3.2                   Registry specification:

 

The registry specification is the same as Section 1.3 above. For a given field, the code generated to state_struct.inc is based on dimspec and state entries within the Registry file. The logic is more complicated, however, since in addition to knowing the number of dimensions, we also must generate the correct extents for each dimension.

3.3                   Generated code:

 

The following code is generated to a file em_allocs.inc for the example Registry entries in Section 1.3 above. For readability, some comments and spacing have been added between entries, and the base names of the variables are highlighted in blue:

 

                  (scalars; first a real then an integer. neither is core associated.)

IF ( setinitval .EQ. 3 ) grid%epsts=initial_data_value

IF ( setinitval .EQ. 3 ) grid%step_number=0

 

  (an em core-associated variable)

ALLOCATE(grid%em_muu(sm31:em31,sm33:em33),STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to allocate grid%em_muu(sm31:em31,sm33:em33). ')

 endif

  IF ( setinitval .EQ. 1 .OR. setinitval .EQ. 3 ) grid%em_muu=initial_data_value

 

  (first and second time levels of the em core-associated variable u)

ALLOCATE(grid%em_u_1(sm31:em31,sm32:em32,sm33:em33),STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to allocate grid%em_u_1(sm31:em31,sm32:em32,sm33:em33). ')

 endif

  IF ( setinitval .EQ. 1 .OR. setinitval .EQ. 3 ) grid%em_u_1=initial_data_value

ALLOCATE(grid%em_u_2(sm31:em31,sm32:em32,sm33:em33),STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to allocate grid%em_u_2(sm31:em31,sm32:em32,sm33:em33). ')

 endif

  IF ( setinitval .EQ. 1 .OR. setinitval .EQ. 3 ) grid%em_u_2=initial_data_value

 

  (non core-associated arrays of various dimensions)

ALLOCATE(grid%fcx(model_config_rec%spec_bdy_width),STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to allocate grid%fcx(model_config_rec%spec_bdy_width). ')

 endif

  IF ( setinitval .EQ. 1 .OR. setinitval .EQ. 3 ) grid%fcx=initial_data_value

 

ALLOCATE(grid%psfc(sm31:em31,sm33:em33),STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to allocate grid%psfc(sm31:em31,sm33:em33). ')

 endif

  IF ( setinitval .EQ. 1 .OR. setinitval .EQ. 3 ) grid%psfc=initial_data_value

 

ALLOCATE(grid%div(sm31:em31,sm32:em32,sm33:em33),STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to allocate grid%div(sm31:em31,sm32:em32,sm33:em33). ')

 endif

  IF ( setinitval .EQ. 1 .OR. setinitval .EQ. 3 ) grid%div=initial_data_value

 

  (first and second time levels of the 4d array of 3d moisture tracers)

ALLOCATE(grid%moist_1(sm31:em31,sm32:em32,sm33:em33,num_moist),STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to allocate grid%moist_1(sm31:em31,sm32:em32,sm33:em33,num_moist). ')

 endif

  IF ( setinitval .EQ. 1 .OR. setinitval .EQ. 3 ) grid%moist_1=initial_data_value

ALLOCATE(grid%moist_2(sm31:em31,sm32:em32,sm33:em33,num_moist),STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to allocate grid%moist_2(sm31:em31,sm32:em32,sm33:em33,num_moist). ')

 endif

  IF ( setinitval .EQ. 1 .OR. setinitval .EQ. 3 ) grid%moist_2=initial_data_value

 

Notes:

 

  1. Whether a variable is initialized or not depends on the value of setinitval. 1=initialize arrays, 2=initialize scalars, and 3=initialize both.
  2. Error checking code is generated to test the status variable, ierr, from each ALLOCATE statement and generate a fatal error if it is non-zero.
  3. For 3-dimensional arrays where each of dimspec entry used in dims is defined standard_domain, the generated dimensions for the ALLOCATE statement are sm31:em31,sm32:em32,sm33:em33 which, in framework nomenclature, mean the starts and ends of the first second and third “standard” memory dimensions.  Standard memory dimensions mean that they are associated with the X, Y, and Z coordinates of the domain.
  4. For 4-dimensional arrays of 3-dimensional tracers, the fourth dimension is provided as num_basename.  This is declarated in another Registry-generated module: module_state_description.
  5. Also for 4-dimensional arrays of 3-dimensional tracers, the base name of the array is found in the use field of the Registry entries for the tracers (e.g. “moist”). It is not the names of the individual tracers themselves.
  6. For 2-dimensional arrays were each of the two dimspec entries used in dims is defined  standard_domain, the order and meaning of the dimensions is important – it’s necessary to know which dimension to leave out. This is where the dim and  order elements of the dimspec entries are important. Since the dims field of the 2-d arrays is defined as ij in the Registry, and since ‘i’ is given order ‘1’ and j is given order ‘3’, sm31:em31 are used for the first dimension in the allocate statement and sm33:em33 are used for the second dimension.
  7. Certain other dimspecs are not defined standard_domain . For example, the dimspec “w” is define as being the value of a variable that is defined in the namelist, namelist=spec_bdy_width  .  In the case the state entry for fcx, which has “w” in the dims element, the dimension generated for the ALLOCATE statement is model_config_rec%spec_bdy_width.
  8. In the case of derived data types, the application program assumes responsibility for allocating fields contained in the derived data type. The Registry does not generate code for this at this time.

 

3.4                   Generated by:

 

The code that generates core_allocs.inc is the subroutine gen_alloc() defined in tools/gen_allocs.c  in the WRF source code distribution.

 

 

4                     core_deallocs.inc

                                                         

Core­_deallocs.inc is relatively simple to generate, since it does require information about dimensionality of the fields being deallocated (except to check that the field is not a scalar).

 

4.1                   Usage:

                                                                                

In the WRF framework, core­­_deallocs.inc files (e.g. em_deallocs.inc) are included inside a conditional in the routine dealloc_space_field, also in frame/module_dm.F.

4.2                   Generated code:

 

DEALLOCATE(grid%em_muu,STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to dallocate grid%em_muu. ')

 endif

DEALLOCATE(grid%em_u_1,STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to dallocate grid%em_u_1. ')

 endif

DEALLOCATE(grid%em_u_2,STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to dallocate grid%em_u_2. ')

 endif

DEALLOCATE(grid%fcx,STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to dallocate grid%fcx. ')

 endif

DEALLOCATE(grid%psfc,STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to dallocate grid%psfc. ')

 endif

DEALLOCATE(grid%div,STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to dallocate grid%div. ')

 endif

DEALLOCATE(grid%moist_1,STAT=ierr)

 if (ierr.ne.0) then

 CALL wrf_error_fatal ( &

'frame/module_domain.f: Failed to dallocate grid%moist_1. ')

 endif

 

4.3                   Registry specification:

 

The registry specification is the same as Section 1.3 above. For a given field, the code generated to state_struct.inc is based on dimspec and state entries within the Registry file. The logic is more complicated, however, since in addition to knowing the number of dimensions, we also must generate the correct extents for each dimension.

4.4                   Generated by:

 

The code that generates core_deallocs.inc is the subroutine gen_dealloc() defined in tools/gen_allocs.c  in the WRF source code distribution.

 

 

 

 

Page created: March 14, 2005, John Michalakes