Skip to content

Latest commit

 

History

History
791 lines (567 loc) · 32.6 KB

obs_def_mod.rst

File metadata and controls

791 lines (567 loc) · 32.6 KB

MODULE obs_def_mod

Overview

The DART Fortran90 derived type obs_def provide an abstraction of the definition of an observation. An observation sequence obs_seq at a higher level is composed of observation definitions associated with observed values. For now, the basic operations required to implement an observation definition are an ability to compute a forward operator given the model state vector, the ability to read/write the observation definition from/to a file, and a capability to do a standard input driven interactive definition of the observation definition.

DART makes a distinction between specific observation types and generic observation quantities. The role of the various obs_def input files is to define the mapping between the types and quantities, and optionally to provide type-specific processing routines.

A single obs_def output module is created by the program preprocess from two kinds of input files. First, a DEFAULT obs_def module (normally called DEFAULT_obs_def_mod.F90 and documented in this directory) is used as a template into which the preprocessor incorporates information from zero or more special obs_def modules (such as obs_def_1d_state_mod.f90 or obs_def_reanalysis_bufr_mod.f90, also documented in this directory). If no special obs_def files are included in the preprocessor namelist, a minimal obs_def_mod.f90 is created which can only support identity forward observation operators.

New Observation Types

To add a new observation type which does not fit into any of the already-defined obs_def files, a new file should be created in the obs_def directory. These files are usually named according the the pattern obs_def_X_mod.f90, where the X is either an instrument name, a data source, or a class of observations. See the existing filenames in that directory for ideas. Then this new filename must be listed in the input.nml namelist for the model, in the &preprocess_nml section, in the obs_type_files variable. This variable is a string list type which can contain multiple filenames. Running the preprocess program will then use the contents of the new file to generate the needed output files for use in linking to the rest of the DART system.

Simple observations

If the new observation type can be directly interpolated by a model_mod interpolation routine, and has no additional observation-specific code for reading, writing, or initializing the observation, then the entire contents of the new file is:

! BEGIN DART PREPROCESS TYPE DEFINITIONS
! type, quantity, COMMON_CODE
! (repeat lines for each type)
! END DART PREPROCESS TYPE DEFINITIONS

DART will automatically generate all interface code needed for these new observation types. For example, here is a real list:

! BEGIN DART PREPROCESS TYPE DEFINITIONS
!VELOCITY,                     QTY_VELOCITY,              COMMON_CODE
!TRACER_CONCENTRATION,         QTY_TRACER_CONCENTRATION,  COMMON_CODE
!TRACER_SOURCE,                QTY_TRACER_SOURCE,         COMMON_CODE
!MEAN_SOURCE,                  QTY_MEAN_SOURCE,           COMMON_CODE
!SOURCE_PHASE,                 QTY_SOURCE_PHASE,          COMMON_CODE
! END DART PREPROCESS TYPE DEFINITIONS

The first column is the specific observation type and should be unique. The second column is the generic observation quantity. The quantities available to DART are defined at compile time by preprocess via the option 'quantity_files' in the preprocess_nml namelist. The third column must be the keyword COMMON_CODE which tells the preprocess program to automatically generate all necessary interface code for this type.

Observations needing special handling

For observation types which have observation-specific routines, must interpolate using a combination of other generic quantities, or require additional observation-specific data to be stored, the following format is used:

! BEGIN DART PREPROCESS TYPE DEFINITIONS
! type, quantity
! (repeat lines for each type/quantity pair)
! END DART PREPROCESS TYPE DEFINITIONS

DART will need user-supplied interface code for each of the listed types. For example, here is a real list:

! BEGIN DART PREPROCESS TYPE DEFINITIONS
! DOPPLER_RADIAL_VELOCITY, QTY_VELOCITY
! RADAR_REFLECTIVITY,      QTY_RADAR_REFLECTIVITY
! END DART PREPROCESS TYPE DEFINITIONS

In this case, DART needs additional information for how to process these types. They include code sections delimited by precisely formatted comments, and possibly module code sections:

  1. ! BEGIN DART PREPROCESS USE OF SPECIAL OBS_DEF MODULE
    ! END DART PREPROCESS USE OF SPECIAL OBS_DEF MODULE
    Any fortran use statements for public subroutines or variables from other modules should be placed between these lines, with comment characters in the first column.
    For example, if the forward operator code includes a module with public routines then a "use" statement like:
    use obs_def_1d_state_mod, only : write_1d_integral, read_1d_integral, &
                                     interactive_1d_integral, get_expected_1d_integral

    needs to be added to the obs_def_mod so the listed subroutines are available to be called. This would look like:

    ! BEGIN DART PREPROCESS USE OF SPECIAL OBS_DEF MODULE
    ! use obs_def_1d_state_mod, only : write_1d_integral, read_1d_integral, &
    !                                  interactive_1d_integral, get_expected_1d_integral
    ! END DART PREPROCESS USE OF SPECIAL OBS_DEF MODULE
  2. ! BEGIN DART PREPROCESS GET_EXPECTED_OBS_FROM_DEF
    ! END DART PREPROCESS GET_EXPECTED_OBS_FROM_DEF
    These comments must enclose a case statement for each defined type that returns the expected observation value based on the current values of the state vector. The code must be in comments, with the comment character in the first column.
    The variables available to be passed to subroutines or used in this section of code are:
    state the entire model state vector
    state_time the time of the state data
    ens_index the ensemble member number
    location the observation location
    obs_kind_ind the index of the specific observation type
    obs_time the time of the observation
    error_val the observation error variance

    The routine must fill in the values of these variables:
    obs_val the computed forward operator value
    istatus return code: 0=ok, >0 is error, <0 reserved for system use

    To call a model_mod interpolate routine directly, the argument list must match exactly:
    interpolate(state, location, QTY_xxx, obs_val, istatus)

    This can be useful if the forward operator needs to retrieve values for fields which are typically found in a model and then compute a derived value from them.

  3. ! BEGIN DART PREPROCESS READ_OBS_DEF
    ! END DART PREPROCESS READ_OBS_DEF
    These comments must enclose a case statement for each defined type that reads any additional data associated with a single observation. If there is no information beyond that for the basic obs_def type, the case statement must still be provided, but the code can simply be continue. The code must be in comments, with the comment character in the first column.
    The variables available to be passed to subroutines or used in this section of code are:
    ifile the open unit number positioned ready to read, read-only
    obs_def the rest of the obs_def derived type for this obs, read-write
    key the index observation number in this sequence, read-only
    obs_val the observation value, if needed. in general should not be changed
    is_ascii logical to indicate how the file was opened, formatted or unformatted

    The usual use of this routine is to read in additional metadata per observation and to set the private key in the obs_def to indicate which index to use for this observation to look up the corresponding metadata in arrays or derived types. Do not confuse the key in the obs_def with the key argument to this routine; the latter is the global observation sequence number for this observation.
  4. ! BEGIN DART PREPROCESS WRITE_OBS_DEF
    ! END DART PREPROCESS WRITE_OBS_DEF
    These comments must enclose a case statement for each defined type that writes any additional data associated with a single observation. If there is no information beyond that for the basic obs_def type, the case statement must still be provided, but the code can simply be continue. The code must be in comments, with the comment character in the first column.
    The variables available to be passed to subroutines or used in this section of code are:
    ifile the open unit number positioned ready to write, read-only
    obs_def the rest of the obs_def derived type for this obs, read-only
    key the index observation number in this sequence, read-only
    is_ascii logical to indicate how the file was opened, formatted or unformatted

    The usual use of this routine is to write the additional metadata for this observation based on the private key in the obs_def. Do not confuse this with the key in the subroutine call which is the observation number relative to the entire observation sequence file.
  5. ! BEGIN DART PREPROCESS INTERACTIVE_OBS_DEF
    ! END DART PREPROCESS INTERACTIVE_OBS_DEF
    These comments must enclose a case statement for each defined type that prompts the user for any additional data associated with a single observation. If there is no information beyond that for the basic obs_def type, the case statement must still be provided, but the code can simply be continue. The code must be in comments, with the comment character in the first column.
    The variables available to be passed to subroutines or used in this section of code are:
    obs_def the rest of the obs_def derived type for this obs, read-write
    key the index observation number in this sequence, read-only

    The DART code will prompt for the rest of the obs_def values (location, type, value, error) but any additional metadata needed by this observation type should be prompted to, and read from, the console (e.g. write(*,*), and read(*, *)). The code will generally set the obs_def%key value as part of setting the metadata.
  6. ! BEGIN DART PREPROCESS MODULE CODE
    ! END DART PREPROCESS MODULE CODE
    If the code to process this observation requires module data and/or subroutines, then these comments must surround the module definitions. Unlike all the other sections, this comment pair is optional, and if used, the code must not be in comments; it will be copied verbatim over to the output file.
    Generally the code for a forward operator should be defined inside a module, to keep module variables and other private subroutines from colliding with unrelated routines and variables in other forward operator files.

It is possible to mix automatic code types and user-supplied code types in the same list. Simply add the COMMON_CODE keyword on the lines which need no special data or interfaces. For example, here is an extract from the 1d state obs_def module, where the raw state variable needs only autogenerated code, but the 1d integral has user-supplied processing code:

! BEGIN DART PREPROCESS TYPE LIST
! RAW_STATE_VARIABLE,    QTY_STATE_VARIABLE, COMMON_CODE
! RAW_STATE_1D_INTEGRAL, QTY_1D_INTEGRAL
! END DART PREPROCESS TYPE LIST


! BEGIN DART PREPROCESS USE OF SPECIAL OBS_DEF MODULE
!   use obs_def_1d_state_mod, only : write_1d_integral, read_1d_integral, &
!                                    interactive_1d_integral, get_expected_1d_integral
! END DART PREPROCESS USE OF SPECIAL OBS_DEF MODULE

! BEGIN DART PREPROCESS GET_EXPECTED_OBS_FROM_DEF
!         case(RAW_STATE_1D_INTEGRAL)
!            call get_expected_1d_integral(state, location, obs_def%key, obs_val, istatus)
! END DART PREPROCESS GET_EXPECTED_OBS_FROM_DEF

! BEGIN DART PREPROCESS READ_OBS_DEF
!      case(RAW_STATE_1D_INTEGRAL)
!         call read_1d_integral(obs_def%key, ifile, fileformat)
! END DART PREPROCESS READ_OBS_DEF

! BEGIN DART PREPROCESS WRITE_OBS_DEF
!      case(RAW_STATE_1D_INTEGRAL)
!         call write_1d_integral(obs_def%key, ifile, fileformat)
! END DART PREPROCESS WRITE_OBS_DEF

! BEGIN DART PREPROCESS INTERACTIVE_OBS_DEF
!      case(RAW_STATE_1D_INTEGRAL)
!         call interactive_1d_integral(obs_def%key)
! END DART PREPROCESS INTERACTIVE_OBS_DEF

! BEGIN DART PREPROCESS MODULE CODE
module obs_def_1d_state_mod

use        types_mod, only : r8
use    utilities_mod, only : register_module, error_handler, E_ERR, E_MSG
use     location_mod, only : location_type, set_location, get_location
use  assim_model_mod, only : interpolate
use   cov_cutoff_mod, only : comp_cov_factor

implicit none

public :: write_1d_integral, read_1d_integral, interactive_1d_integral, &
          get_expected_1d_integral

...  (module code here)

end module obs_def_1d_state_mod
! END DART PREPROCESS MODULE CODE
See the ./obs_def_1d_state_mod documentation for more details and examples of each section. Also see obs_def_wind_speed_mod.f90 for an example of a 3D geophysical forward operator.
In addition to collecting and managing any additional observation type-specific code, this module provides the definition of the obs_def_type derived type, and a collection of subroutines for creating, accessing, and updating this type. The remainder of this document describes the subroutines provided by this module.

Other modules used

types_mod
utilities_mod
location_mod (depends on model choice)
time_manager_mod
assim_model_mod
obs_kind_mod
Other special obs_def_kind modules as required

Public interfaces

use obs_def_mod, only : obs_def_type
init_obs_def
get_obs_def_location
get_obs_def_type_of_obs
get_obs_def_time
get_obs_def_error_variance
get_obs_def_key
set_obs_def_location
set_obs_def_type_of_obs
set_obs_def_time
set_obs_def_error_variance
set_obs_def_key
interactive_obs_def
write_obs_def
read_obs_def
get_expected_obs_from_def
destroy_obs_def
copy_obs_def
assignment(=)
get_name_for_type_of_obs

A note about documentation style. Optional arguments are enclosed in brackets [like this].

type obs_def_type
   private
   type(location_type)  :: location
   integer              :: kind
   type(time_type)      :: time
   real(r8)             :: error_variance
   integer              :: key
end type obs_def_type

Models all that is known about an observation except for actual values. Includes a location, type, time and error variance.

Component Description
location Location of the observation.
kind Despite the name, the specific type of the observation.
time Time of the observation.
error_variance Error variance of the observation.
key Unique identifier for observations of a particular type.

call init_obs_def(obs_def, location, kind, time, error_variance) :

type(obs_def_type),  intent(out) :: obs_def
type(location_type), intent(in)  :: location
integer,             intent(in)  :: kind
type(time_type),     intent(in)  :: time
real(r8),            intent(in)  :: error_variance

Creates an obs_def type with location, type, time and error_variance specified.

obs_def The obs_def that is created
location Location for this obs_def
kind Observation type for obs_def
time Time for obs_def
error_variance Error variance of this observation

call copy_obs_def(obs_def1, obs_def2) :

type(obs_def_type), intent(out) :: obs_def1
type(obs_def_type), intent(in)  :: obs_def2

Copies obs_def2 to obs_def1, overloaded as assignment (=).

obs_def1 obs_def to be copied into
obs_def2 obs_def to be copied from

var = get_obs_def_key(obs_def) :

integer                        :: get_obs_def_key
type(obs_def_type), intent(in) :: obs_def

Returns key from an observation definition.

var Returns key from an obs_def
obs_def An obs_def

var = get_obs_def_error_variance(obs_def) :

real(r8)                       :: get_obs_def_error_variance
type(obs_def_type), intent(in) :: obs_def

Returns error variance from an observation definition.

var Error variance from an obs_def
obs_def An obs_def

var = get_obs_def_location(obs_def) :

type(location_type)              :: get_obs_def_location
type(obs_def_type), intent(in)   :: obs_def

Returns the location from an observation definition.

var Returns location from an obs_def
obs_def An obs_def

var = get_obs_def_type_of_obs(obs_def) :

integer                         :: get_obs_def_type_of_obs
type(obs_def_type),  intent(in) :: obs_def

Returns an observation type from an observation definition.

var Returns the observation type from an obs_def
obs_def An obs_def

var = get_obs_def_time(obs_def) :

type(time_type)                :: get_obs_def_time
type(obs_def_type), intent(in) :: obs_def

Returns time from an observation definition.

var Returns time from an obs_def
obs_def An obs_def

obs_name = get_name_for_type_of_obs(obs_kind_ind) :

character(len = 32)            :: get_name_for_type_of_obs
integer, intent(in)            :: obs_kind_ind

Returns an observation name from an observation type.

var Returns name from an observation type
obs_kind_ind An observation type

call set_obs_def_location(obs_def, location) :

type(obs_def_type),  intent(inout) :: obs_def
type(location_type), intent(in)    :: location

Set the location in an observation definition.

obs_def An obs_def
location A location

call set_obs_def_error_variance(obs_def, error_variance) :

type(obs_def_type), intent(inout) :: obs_def
real(r8), intent(in)              :: error_variance

Set error variance for an observation definition.

obs_def An obs_def
error_variance Error variance

call set_obs_def_key(obs_def, key) :

type(obs_def_type), intent(inout) :: obs_def
integer,            intent(in)    :: key

Set the key for an observation definition.

obs_def An obs_def
key Unique identifier for this observation

call set_obs_def_type_of_obs(obs_def, kind) :

type(obs_def_type), intent(inout) :: obs_def
integer,            intent(in)    :: kind

Set the type of observation in an observation definition.

obs_def An obs_def
kind An integer observation type

call set_obs_def_time(obs_def, time) :

type(obs_def_type), intent(inout) :: obs_def
type(time_type), intent(in)       :: time

Sets time for an observation definition.

obs_def An obs_def
time Time to set

call get_expected_obs_from_def(key, obs_def, obs_kind_ind, ens_index, state, state_time, obs_val, istatus, assimilate_this_ob, evaluate_this_ob) :

integer,            intent(in)  :: key
type(obs_def_type), intent(in)  :: obs_def
integer,            intent(in)  :: obs_kind_ind
integer,            intent(in)  :: ens_index
real(r8),           intent(in)  :: state(:)
type(time_type),    intent(in)  :: state_time
real(r8),           intent(out) :: obs_val
integer,            intent(out) :: istatus
logical,            intent(out) :: assimilate_this_ob
logical,            intent(out) :: evaluate_this_ob

Compute the observation (forward) operator for a particular obs definition.

key descriptor for observation type
obs_def The input obs_def
obs_kind_ind The obs type
ens_index The ensemble member number of this state vector
state Model state vector
state_time Time of the data in the model state vector
istatus Returned integer describing problems with applying forward operator (0 == OK, >0 == error, <0 reserved for sys use).
assimilate_this_ob Indicates whether to assimilate this obs or not
evaluate_this_ob Indicates whether to evaluate this obs or not

call read_obs_def(ifile, obs_def, key, obs_val [,fform]) :

integer,                    intent(in)    :: ifile
type(obs_def_type),         intent(inout) :: obs_def
integer,                    intent(in)    :: key
real(r8),                   intent(inout) :: obs_val
character(len=*), optional, intent(in)    :: fform

Reads an obs_def from file open on channel ifile. Uses format specified in fform or FORMATTED if fform is not present.

ifile File unit open to output file
obs_def Observation definition to be read
key Present if unique identifier key is needed by some obs type. Unused by default code.
obs_val Present if needed to perform operations based on value. Unused by default code.
fform File format specifier: FORMATTED or UNFORMATTED; default FORMATTED (FORMATTED in this case is the human readable/text option as opposed to UNFORMATTED which is binary.)

call interactive_obs_def(obs_def, key) :

type(obs_def_type), intent(inout) :: obs_def
integer,            intent(in)    :: key

Creates an obs_def via input from standard in.

obs_def An obs_def to be created
key Present if unique identifier key is needed by some obs type. Unused by default code.

call write_obs_def(ifile, obs_def, key [,fform]) :

integer,                    intent(in) :: ifile
type(obs_def_type),         intent(in) :: obs_def
integer,                    intent(in) :: key
character(len=*), optional, intent(in) :: fform

Writes an obs_def to file open on channel ifile. Uses format specified in fform or FORMATTED if fform is not present.

ifile File unit open to output file
obs_def Observation definition to be written
key Present if unique identifier key is needed by some obs type. Unused by default code.
fform File format specifier: FORMATTED or UNFORMATTED; default FORMATTED

call destroy_obs_def(obs_def) :

type(obs_def_type), intent(inout) :: obs_def

Releases all storage associated with an obs_def and its subcomponents.

obs_def An obs_def to be released.

Files

  • The read_obs_def() and write_obs_def() routines are passed an already-opened file channel/descriptor and read to or write from it.

References

  • none

Error codes and conditions

Routine Message Comment
get_expected_obs_from_def Attempt to evaluate undefined observation type An observation type for which no forward operator has been defined is an error.
read_obs_def Expected header "obdef" in input file The format of the input file is not consistent.
read_obs_def Expected kind header "kind " in input file The format of the input file is not consistent.
read_obs_def Attempt to read for undefined obs_kind index Reading for an observation type for which no forward operator has been defined is an error.
write_obs_def Attempt to write for undefined obs_kind index Writing for an observation type for which no forward operator has been defined is an error.
interactive_obs_def Attempt to interactively create undefined obs_kind index Creating an observation type for which no forward operator has been defined is an error.

Private components

N/A