Changes between Initial Version and Version 1 of OMI_observation_modules_PDAF23


Ignore:
Timestamp:
Jun 3, 2025, 12:56:43 PM (3 days ago)
Author:
lnerger
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • OMI_observation_modules_PDAF23

    v1 v1  
     1= PDAF-OMI Observation Modules =
     2
     3{{{
     4#!html
     5<div class="wiki-toc">
     6<h4>PDAF-OMI Guide</h4>
     7<ol><li><a href="PDAF_OMI_Overview">Overview</a></li>
     8<li><a href="OMI_Callback_obs_pdafomi">callback_obs_pdafomi.F90</a></li>
     9<li>Observation Modules</li>
     10<li><a href="OMI_observation_operators">Observation operators</a></li>
     11<li><a href="OMI_error_checking">Checking error status</a></li>
     12<li><a href="OMI_debugging">Debugging functionality</a></li>
     13<li><a href="OMI_ImplementationofAnalysisStep">Implementing the analysis step with OMI</a></li>
     14<ol>
     15<li> <a href="ImplementFilterAnalysisOverview"> General overview for ensemble filters</a></li>
     16<ol>
     17<li><a href="ImplementAnalysisGlobal">Implementation for Global Filters</a></li>
     18<li><a href="ImplementAnalysisLocal">Implementation for Local Filters</a></li>
     19<li><a href="ImplementAnalysislenkfOmi">Implementation for LEnKF</a></li>
     20</ol>
     21<li> <a href="Implement3DVarAnalysisOverview"> General overview for 3D-Var methods</a></li>
     22<ol>
     23<li><a href="ImplementAnalysis_3DVar">Implementation for 3D-Var</a></li>
     24<li><a href="ImplementAnalysis_3DEnVar">Implementation for 3D Ensemble Var</a></li>
     25<li><a href="ImplementAnalysis_Hyb3DVar">Implementation for Hybrid 3D-Var</a></li>
     26</ol>
     27</ol>
     28<li><a href="OMI_nondiagonal_observation_error_covariance_matrices">Using nondiagonal R-matrices</a></li>
     29<li><a href="Porting_to_OMI">Porting an existing implemention to OMI</a></li>
     30<li><a href="PDAFomi_additional_functionality">Additional OMI Functionality</a></li>
     31</ol>
     32</div>
     33}}}
     34
     35[[PageOutline(2-3,Contents of this page)]]
     36
     37== Overview ==
     38
     39The implementation of the observations with OMI is done in observation modules (obs-modules). For each observation type a separate module should be created.
     40
     41Each obs-module contains four routines (where 'TYPE' will be replaced by the name of the observation):
     42
     43 - `init_dim_obs_OBSTYPE` initializes all variables holding the information about one observation type. The information about the observation type is stored in a data structure (Fortran derived type).
     44 - `obs_op_OBSTYPE` applies the observation operator to a state vector. One can call an observation operator routine provided by PDAF, or one can to implement a new operator.
     45 - `init_dim_obs_l_OBSTYPE` calls a PDAF-OMI routine to initialize the observation information corresponding to a local analysis domain. One can set localization parameters, like the localization radius, for each observation type.
     46 - `localize_covar_OBSTYPE` calls a PDAF-OMI routine to apply covariance localization. One can set localization parameters, like the localization radius, for each observation type.
     47
     48The template file `obs_OBSTYPE_pdafomi_TEMPLATE.F90` shows the different steps needed when implementing these routines. The main work is to implement `init_dim_obs`, while the other routines mainly call a subroutine provided by PDAF-OMI.
     49
     50In the obs-module the subroutines are named according to the observation type. The template file uses generic names which can be replaced by the user. Having distinct names for each observation type is relevant to include the subroutine from the module in the call-back routine with ‘use’. In the header of each obs-module, the user can declare further variables, e.g. assim_OBSTYPE as a flag to control whether the observation type should be assimilated.
     51
     52'''Note:''' In contrast to the 'classical' implementation of observation routines for PDAF, the global and local filters use the same routines `init_dim_obs` and `obs_op`. PDAF-OMI recognizes whether a global or local filter is used and does the necessary operations by itself.
     53
     54== Data type obs_f ==
     55
     56To ensure the functionality within each obs-module, we rely on a derived data type called `obs_f` that contains all information about the observation. One instance of this data type is allocated in each obs-module with the generic variable name `thisobs`. A few of the elements of `obs_f` are initialized by the user when the observation information is initialized on `init_dim_obs_f`. Further variables is set in a call to the routine `PDAFomi_gather_obs`. This information is then used by all other routines in the obs-module. The template file `obs_OBSTYPE_pdafomi_TEMPLATE.F90` shows the different steps needed to initialize `thisobs`.
     57
     58The '''mandatory variables''' in `obs_f` that need to be set by the user are:
     59{{{
     60  TYPE obs_f
     61     ! ---- Mandatory variables to be set in INIT_DIM_OBS ----
     62     INTEGER :: doassim=0                 !< Whether to assimilate this observation type
     63     INTEGER :: disttype                  !< Type of distance computation to use for localization
     64                                          !   (0) Cartesian, (1) Cartesian periodic
     65                                          !   (2) simplified geographic, (3) geographic haversine function
     66                                          !   (10) Cartesian 2+1D factorized, (11) Cartesian periodic 2+1D factorized
     67                                          !   (12) simplified geographic 2+1D factorized
     68                                          ! (13) geographic haversine function  2+1D factorized
     69     INTEGER :: ncoord                    !< Number of coordinates use for distnce computation
     70     INTEGER, ALLOCATABLE :: id_obs_p(:,:) !< Indices of process-local observed field in state vector
     71     ...
     72  END TYPE obs_f
     73}}}
     74
     75In addition there are '''optional variables''' that the be used:
     76{{{
     77  TYPE obs_f
     78     ...
     79     ! ---- Optional variables - they can be set in INIT_DIM_OBS ----
     80     REAL, ALLOCATABLE :: icoeff_p(:,:)   !< Interpolation coefficients for obs. operator (optional)
     81     REAL, ALLOCATABLE :: domainsize(:)   !< Size of domain for periodicity (<=0 for no periodicity) (optional)
     82
     83     ! ---- Variables with predefined values - they can be changed in INIT_DIM_OBS  ----
     84     INTEGER :: obs_err_type=0            !< Type of observation error: (0) Gauss, (1) Laplace
     85     INTEGER :: use_global_obs=1          !< Whether to use (1) global full obs.
     86                                          !< or (0) obs. restricted to those relevant for a process domain
     87     ...
     88  END TYPE obs_f
     89}}}
     90
     91Apart from these variables, there is a number of variables that are set internally when the routine `PDAFomi_gather_obs` is called. The full data type can be seen on the [wiki:OMI_debugging page on OMI debugging].
     92
     93
     94Next to the derived data type `obs_f`, there is a derived type `obs_l` for localization. This is only used internally. It will be filled in the routine `init_dim_obs_l` when calling `PDAFomi_init_dim_obs_l`.
     95
     96== `init_dim_obs_OBSTYPE` ==
     97
     98This is the main routine to initialize observation information.
     99
     100||= Please see the template file `templates/omi/obs_OBSTYPE_pdafomi_TEMPLATE.F90`[[br]] for a step-by-step description of the implementation steps. =||
     101
     102Each observation module uses the generic name '''thisobs''' for the variable with observation type `obs_f`. Elements of `thisobs` are accessed like
     103`thisobs%doassim`.
     104
     105The main variables that the filled in this routine are
     106 1. [wiki:OMI_observation_modules#thisobsdoassim thisobs%doassim]: Specify whether this observation type is assimilated
     107 1. [wiki:OMI_observation_modules#thisobsdisttype thisobs%disttype]: Specify the type of distance computation
     108 1. [wiki:OMI_observation_modules#thisobsncoord thisobs%ncoord]: Specify the number of dimensions used to compute distances
     109 1. [wiki:OMI_observation_modules#dim_obs_p dim_obs_p]: Count the number of available observations
     110 1. [wiki:OMI_observation_modules#obs_p obs_p]: Fill the vector of observations
     111 1. [wiki:OMI_observation_modules#ocoord_p ocoord_p]: store the coordinates of the observations (only actually used in case of localization)
     112 1. [wiki:OMI_observation_modules#ivar_obs_p ivar_obs_p]: store the inverse error variance of each observation for the default mode of OMI, which assumes a diagonal observation error covariance matrix
     113 1. [wiki:OMI_observation_modules#thisobsid_obs_p thisobs%id_obs_p]: store the indices of state vector elements that correspond to an observation (A single value for observation at grid points, or multiple values for derived quantities or interpolation; this is only used in the OMI-provided observation operators)
     114
     115When the observation operator performs interpolation, one further needs to initialize an array of interpolation coefficients ([wiki:OMI_observation_modules#thisobsicoeff_p thisobs%icoeff_p]). For Cartesian distance computation with periodicity one also needs to set [wiki:OMI_observation_modules#thisobsdomainsize thisobs%domainsize].
     116
     117Here one can also activate the [wiki:PDAFomi_additional_functionality#Omittingobservationsthatarepotentialoutliers omission of observations that are too different from the ensemble mean]. This is activated by setting `thisobs%inno_omit>0.0`
     118
     119When parallel model with domain decomposition is used, the variables with suffix `_p` need to describe the observation information for a particular process domain. The following routine will perform the necessary operations to ensure that the parallelization is taken into account by PDAF.
     120
     121After these variables are filled, one calls
     122{{{
     123    CALL PDAFomi_gather_obs(thisobs, dim_obs_p, obs_p, ivar_obs_p, ocoord_p, &
     124         thisobs%ncoord, cradius, dim_obs)
     125}}}
     126This routine will complete all required initializations for OMI. As such it is mandatory to call the routine.
     127
     128The routine `PDAFomi_gather_obs` returns the number of observations `dim_obs` which is the return variable for PDAF. 
     129
     130Notes:
     131 * The value is `cradius` is only used if [wiki:OMI_observation_modules#thisobsuse_global_obs thisobs%use_global_obs=0].
     132 * `cradius` is always a single value. It should be set of the largest radius of the directions in which the process domain is split by parallelization. It defines the radius within which observations from neighboring process domains are taken into account.
     133
     134
     135== `obs_op_OBSTYPE` ==
     136
     137This routine applies the observation operator to a state vector. It returns the observed state vector to PDAF. The routine is used by all filters.
     138
     139PDAF-OMI provides several observation operators. For example the observation operator for observations that are grid point values is called as:
     140{{{
     141    CALL PDAFomi_obs_op_gridpoint(thisobs, state_p, ostate)
     142}}}
     143
     144Here, `state_p` is the state vector and `ostate` is the observed state vector.
     145
     146For more information on the available observation operators and on how to implement your own observation operator see the [wiki:OMI_observation_operators documentation of observation operators for OMI].
     147
     148
     149== `init_dim_obs_l_OBSTYPE` ==
     150
     151This routine initializes local observation information. The routine is only used by the domain-localized filters (LESTKF, LETKF, LSEIK, LNETF, LKNETF).
     152
     153For the initialization the following routine is called:
     154{{{
     155    CALL PDAFomi_init_dim_obs_l(thisobs_l, thisobs, coords_l, &
     156         locweight, cradius, sradius, dim_obs_l)
     157}}}
     158
     159Here, `thisobs` and `thisobs_l` are the data-type variables `obs_f` and `obs_l`. `dim_obs_l`, the local size of the observation vector, is the direct output of the routine.
     160
     161''Implementation steps:''
     162 - Ensure that `coords_l` is filled in `init_dim_l_pdaf` and that the unit of `coords_l` is the same as that used fo rthe observation coordinates.
     163 - Specify the localization variables (These variables are usually set in `init_pdaf` and included with `use mod_assimilation`)
     164   - `locweight`: Type of localization (see table below)
     165   - `cradius`: The localization radius or directional radii (cut-off radius for the observations, weight is always =0 for distances > cradius)
     166   - `sradius`: The support radius (or directional redii) of the localization weight function
     167Note, that starting with PDAF V2.2.1 these three variables can be either scalar values - for isotropic localization-, or arrays - for non-isotropic localization and for additionally choose separate weights functions for the horizontal and vertical directions (see the notes below for more information)
     168
     169The setting of `locweight` influences the weight function for the localization. The choices are standardized as follows
     170
     171||= '''locweight''' =||= '''0''' =||= '''1''' =||= '''2''' =||= '''3''' =||= '''4''' =||
     172||= function =|| unit weight ||  exponential  ||  5-th order[[BR]]polynomial  ||  5-th order[[BR]]polynomial  ||  5-th order[[BR]]polynomial  ||
     173||= regulation =||  -  ||  -  ||  -  ||  regulation using[[BR]]mean variance  ||  regulation using variance[[BR]]of single observation point  ||
     174||= '''cradius''' =||||||||||||  weight=0 if distance > cradius  ||
     175||= '''sradius''' =||  no impact  ||  weight = exp(-d / sradius)  ||||||||  weight = 0 if d >= sradius[[BR]] else[[BR]] weight = f(sradius, distance)  ||
     176
     177Here, 'regulation' refers to the regulated localization introduced in Nerger, L., Janjić, T., Schröter, J., Hiller, W. (2012). A regulated localization scheme for ensemble-based Kalman filters. Quarterly Journal of the Royal Meteorological Society, 138, 802-812. ​[https://doi.org/10.1002/qj.945 doi:10.1002/qj.945].
     178
     179**Notes:**
     180- **isotropic localization**: If `cradius` and `sradius` are scalar values, the localization is isotropic. Thus, it uses the same `cradius` in all directions. If different localization scales should be applied e.g. in the vertical compared to the horizonal one needs to scale the vertical coordinates.
     181- **non-isotropic localization**: Nonisotropic localization was introduced with PDAF V2.2: `cradius` and `sradius` can be declared as vectors of length `thisobs%ncoords` and each element can get a different value. In this case, the values define a non-isotropic localization according to the values specified in `cradius` and `sradius`. PDAF-OMI will use these values to compute a directional localization radius.
     182- **2D+1D factorized non-isotropic localization**: With PDAF V2.2.1 a factorized 2D+1D localization can be specified (see [wiki:OMI_observation_modules#thisobsdisttype explanation of disttype]. If the non-isotropic localization is used one can specify different weight functions for the vertical and horizontal directions. This is achieved by declaring `loweight` as a vector of size 2. Now the first element specifies the weight function (according to the table above) for the horizontal direction and the second element specified the wieght function for the vertical direction. When 'locweight' is used as a scalar variable, it specified the weight function in the horizontal direction while the weight function in the vertical dircetion is a constant value of one.
     183- A common choice is to use `locweight=2` or `locweight=4` in combination with `cradius=sradius`. Choosing `sradius>cradius` is possible, but `sradius<cradius` should be avoided (one would set the weights of distant observation to zero, but would still assimilate them).
     184
     185== `localize_covar_OBSTYPE` ==
     186
     187This routine initializes local observation information. The routine is only used by the local EnKF (LEnKF).
     188
     189For the initialization the following routine is called:
     190{{{
     191    CALL PDAFomi_localize_covar(thisobs, dim_p, locweight, cradius, sradius, &
     192         coords_p, HP_p, HPH)
     193}}}
     194
     195Here, `thisobs` is the data-type variable `obs_f`. `HP_p` and `HPH` are the covariance matrices projected onto the observations. The localization will be applied to these variables.
     196
     197''Implementation steps:''
     198 - Ensure that `coords_p` is filled in `localize_covar_pdafomi`
     199 - Specify the localization variables (These variables are usually set in `init_pdaf` and included with `use mod_assimilation`)
     200   - `locweight`: Type of localization (see table above)
     201   - `cradius`: The localization radius (cut-off radius for the observations, weight is always =0 for distances > cradius)
     202   - `sradius`: The support radius of the localization weight function
     203Note, that starting with PDAF V2.2.1 these three variables can be either scalar values - for isotropic localization-, or arrays - for non-isotropic localization and for additionally choose separate weights functions for the horizontal and vertical directions (see the notes below for more information)
     204
     205**Notes:**
     206- **isotropic localization**: If `cradius` and `sradius` are scalar values, the localization is isotropic. Thus, it uses the same `cradius` in all directions. If different localization scales should be applied e.g. in the vertical compared to the horizonal one needs to scale the vertical coordinates.
     207- **non-isotropic localization**: Nonisotropic localization was introduced with PDAF V2.2: `cradius` and `sradius` can declared as vectors of length `thisobs%ncoords` and each element can get a different value. In this case, the values defined a non-isotropic localization according to the values specified in `cradius` and `sradius`.
     208- **non-isotropic localization**: Nonisotropic localization was introduced with PDAF V2.2: `cradius` and `sradius` can be declared as vectors of length `thisobs%ncoords` and each element can get a different value. In this case, the values define a non-isotropic localization according to the values specified in `cradius` and `sradius`. PDAF-OMI will use these values to compute a directional localization radius.
     209- **2D+1D factorized non-isotropic localization**: With PDAF V2.2.1 a factorized 2D+1D localization can be specified (see [wiki:OMI_observation_modules#thisobsdisttype explanation of disttype]. If the non-isotropic localization is used one can specify different weight functions for the vertical and horizontal directions. This is achieved by declaring `loweight` as a vector of size 2. Now the first element specifies the weight function (according to the table above) for the horizontal direction and the second element specified the wieght function for the vertical direction. When 'locweight' is used as a scalar variable, it specified the weight function in the horizontal direction while the weight function in the vertical dircetion is a constant value of one.
     210- A common choice for the localization is to use `locweight=2` or `locweight=4` in combination with `cradius=sradius`. Choosing `sradius>cradius` is possible, but `sradius<cradius` should be avoided (one would set the weights of distant observation to zero, but would still assimilate them).
     211- Particular for the LEnKF: When choosing `locweight=1` (exponential decrease) with a finite value of `cradius` if might be that the localized covariance matrices are no longer positive semidefinite. Mathematically consistent for `locweight=1` would be to set `cradius` so that the full model domain is covered. The width of the localization weight function is then defined by `sradius`. For `locweight>1` one should set `cradius=sradius`.
     212
     213== Additional routines for 3D-Var ==
     214
     215For the 3D-Var methods added with PDAF V2.0 two more routines are required in the observation module.
     216
     217=== `obs_op_lin_OBSTYPE` ===
     218
     219This routine applies the linearized observation operator to a state vector. It returns the observed state vector to PDAF. The routine is used only by the 3D-Var methods.
     220
     221'''Note:''' A separate routine for `obs_op_lin_OBSTYPE` is only required if the full observation operator in `obs_op_OBSTYPE` is nonlinear. If `obs_op_OBSTYPE` is linear, one can just insert calls to this operator in the routine `obs_op_lin_pdafomi` in `callback_obs_pdafomi.F90`.
     222
     223PDAF-OMI provides several linear observation operators. For example the observation operator for observations that are grid point values is called as:
     224{{{
     225    CALL PDAFomi_obs_op_gridpoint(thisobs, state_p, ostate)
     226}}}
     227
     228Here, `state_p` is the state vector and `ostate` is the observed state vector.
     229
     230For more information on the available observation operators and on how to implement your own observation operator see the [wiki:OMI_observation_operators documentation of observation operators for OMI].
     231
     232=== `obs_op_adj_OBSTYPE` ===
     233
     234This routine applies the adjoint observation operator to an observation vector. It returns the state vector to PDAF. The routine is used only by the 3D-Var methods.
     235
     236PDAF-OMI provides consistent pairs of linear observation operators. For example the adjoint observation operator for observations that are grid point values is called as:
     237{{{
     238    CALL PDAFomi_obs_op_adj_gridpoint(thisobs, ostate, state_p)
     239}}}
     240
     241Here, `ostate` is the observation vector and `state_p` is the state vector.
     242
     243For more information on the available observation operators and on how to implement your own observation operator see the [wiki:OMI_observation_operators documentation of observation operators for OMI].
     244
     245
     246== Implementing a new observation type ==
     247
     248To implement a new observation type, the approach is generally as follows:
     2491.      Create a copy of `obs_OBSTYPE_pdafomi_TEMPLATE.F90`
     2501.      Rename the module and its subroutines according to the observation (replacing ‘OBSTYPE’ by name of observation).
     2511.      Implement `init_dim_obs` for the observation type following the instructions in the template
     2521.      Adapt `obs_op` for the observation type
     2531.      Adapt `init_dim_obs_l` for the observation type (if using a domain_localized filter)
     2541.      Adapt `localize_covar` for the observation type (if using a the local EnKF)
     2551.      Add subroutine calls for the new observation type into the routines in `callback_obs_pdafomi.F90`
     256
     257
     258== Implementation hints for init_dim_obs ==
     259
     260=== `thisobs%doassim` ===
     261
     262Set this variable to 1 to let the filter assimilate this observation. The setting is usually conditional on the value of `assim_OBSTYPE` which is set in `init_pdaf`:
     263{{{
     264   IF (assim_OBSTYPE) thisobs%doassim = 1
     265}}}
     266
     267Starting with PDAF V2.3.1 one can also use
     268{{{
     269   IF (assim_OBSTYPE) CALL PDAFomi_set_doassim(thisobs, 1)
     270}}}
     271
     272=== `thisobs%ncoord` ===
     273
     274This variable specifies the dimension of the distance computations. Thus thisobs%ncoord=2 will lead to distance computations in 2 dimensions.
     275
     276This variable can either be set directly in the code, or, starting with PDAF V2.3.1 by calling [wiki:PDAFomi_set_ncoord].
     277
     278
     279=== `thisobs%disttype` ===
     280
     281This variable specifies the type of distance computation. Possible choices are
     282 - 0: Cartesian distance in ncoord dimension
     283 - 1: Cartesian distance in ncoord dimensions with periodicity (Needs specification of thisobs%domainsize(ncoord))
     284 - 2: Approximate geographic distance in meters with horizontal coordinates in radians (latitude: -pi/2 to +pi/2; longitude -pi/+pi or 0 to 2pi)
     285 - 3: Geographic distance computation in meters using haversine formula with horizontal coordinates in radians (latitude: -pi/2 to +pi/2; longitude -pi/+pi or 0 to 2pi)
     286With PDAF V2.2.1, a **2D+1D factorized localization** was introduced for 3-dimensional applications. With the factorized localization, the horizontal distance (components 1 and 2) is treated separately from the vertical direction (3rd component). This is available for both isoptropic and non-isotropic localization and activated using the choices
     287 - 10: Cartesian distance 2D+1D factorized in 3 dimensions
     288 - 11: Cartesian distance 2D+1D factorized in 3 dimensions with periodicity (Needs specification of thisobs%domainsize(ncoord))
     289 - 12: Approximate geographic distance 2D+1D factorized in meters with horizontal coordinates in radians (latitude: -pi/2 to +pi/2; longitude -pi/+pi or 0 to 2pi) and vertical in unit chosen by the user.
     290 - 13: Geographic distance computation 2D+1D factorized in meters using haversine formula with horizontal coordinates in radians (latitude: -pi/2 to +pi/2; longitude -pi/+pi or 0 to 2pi) and vertical in unit as chosen by the user.
     291
     292**Notes:**
     293- When disttype>=10 is specified with isotropic localization the weight function for the vertical direction is constant with a valu eof one. For non-isotropic localization, the weight functions can be separately specified for the vertical and horizontal directions. (see the [wiki:OMI_observation_modules#init_dim_obs_l_OBSTYPE description of init_dim_obs_l_OBSTYPE] for information on how to specify the ono-isotropic localization.
     294- For 0 and 1 (likewise 10, 11) any distance unit can be used. The computed distance will be in the same unit. For 2 and 3 the horizontal input coordinates are in radians and the distance is computed in meters. Essential is that the grid point coordinates and observation coordinates use the same unit.
     295- For 3-dimensional localization, the unit of the vertical direction can be chosen by the user. However, for geographic ditances, the unit should be chosen to be 'compatible' with the unit in the horizontal (meter). When isotropic localization is used, the unit for the vertical direction can be scaled do that the length scales in the vertical and horizontal directions are the same  (this, e.g., allows to use pressure as the distance measure in the vertical in atmospheric models). For non-isotropic localization, the units can differ without scaling. In ccase of the factorized 2D+1D localization (disttype>=10), the units in the horizontal and vertical directions are independent.
     296
     297See `/models/lorenz96/` for an example using case 1 with periodicity in one dimension.
     298
     299This variable can either be set directly in the code, or, starting with PDAF V2.3.1 by calling [wiki:PDAFomi_set_disttype].
     300
     301
     302=== `dim_obs_p` ===
     303
     304This is a single integer value giving the number of observations. With a parallel model using domain-decomposition this will be the number of observations  for the process sub-domain. For observation files holding all observations one can read these and then check which observation redice within the process sub-domain. `dim_obs_p` will be used to allocate further arrays and as input argument to `PDAFomi_gather_obs`.
     305
     306=== `obs_p` ===
     307
     308This should be a vector of real values. It will be used as an argument to `PDAFomi_gather_obs`. The order of the entries has to be consistent in the arrays `thisobs%id_obs_p`, `obs_p`, `ivar_obs_p`, and `ocoord_p`.
     309
     310
     311=== `ocoord_p` ===
     312
     313This should be a rank-2 array of real values with size (thisobs%ncoord, dim_obs_p). It will be used as an argument to `PDAFomi_gather_obs`. The order of the entries has to be consistent in the arrays `thisobs%id_obs_p`, `obs_p`, `ivar_obs_p`, and `ocoord_p`.
     314
     315The coordinates of the observation with index `k` are given by `ocoord_p(:,k)`.
     316
     317'''Note:''' The observation coordinate values  will only be used in case of the local filters or for computing interpolation coefficients. The array has always to be allocated because it is used in the call to PDAFomi_gather_obs.
     318
     319'''Note:''' The unit of `ocoord_p` and `coords_l` (in `init_dim_obs_l`) has to be the same. For geographic coordinate computations (thisobs%disttype=2 or =3) the unit used by PDAF-OMI is radian.
     320
     321
     322=== `ivar_obs_p` ===
     323
     324The default mode of PDAF-OMI uses a **diagonal observation error covariance matrix R**. The observation error variances can vary. `ivar_obs_p` is used to specify the inverse observation error variances.
     325This should be a vector of real values. It will be used as an argument to `PDAFomi_gather_obs`. The order of the entries has to be consistent in the arrays `thisobs%id_obs_p`, `obs_p`, `ivar_obs_p`, and `ocoord_p`.
     326
     327If **non-diagonal observation error covariance matrices** are used, which is supported from PDAF 2.3, `ivar_obs_p` still has to be allocated and initialized. However, since the handling of **R** is ddone in a call-back routine if **R** is non-diagonal, it is up to the user whether this information is used. For more information see the **[wiki:OMI_nondiagonal_observation_error_covariance_matrices page on using non-diagonal R-matrices with OMI]**.
     328
     329
     330=== `thisobs%id_obs_p` ===
     331
     332This array is allocated as
     333{{{
     334   ALLOCATE(thisobs%id_obs_p(NROWS, dim_obs_p))
     335}}}
     336For a fixed value of the second index the NROWS are the indices of the elements of the state vector that are treated in the observation operator.
     337The value of NROWS depends on the observation operator used for an observation. Examples:
     338 - Using observations that are grid points values:
     339   - NROWS=1
     340   - The entry is the index of a single element of the state vector
     341 - Using observations that are determined by bi-linear interpolation of 4 grid points:
     342   - NROWS=4
     343   - The entries are the indices of four elements of the state vector
     344
     345'''Notes:'''
     346 * This array is only used in the observation operators provided by PDAF-OMI. If you don't use these observation operators, you might not need this array.
     347
     348||Starting from PDAF V2.3.1 one can also call [wiki:PDAFomi_set_id_obs_p] to initialize thisobs%id_obs_p. One provides a user-specified array of indices. The routine then allocates thisobs%id_obs_p and fills it with the provided indices. This should be particularly usable when not using Fortran. ||
     349
     350=== `thisobs%domainsize` ===
     351
     352This array has to be allocated as
     353{{{
     354   ALLOCATE(thisobs%domainsize(thisobs%ncoord))
     355}}}
     356Here one has to specify the size of the domain in each of its thisobs%ncoord dimensions. The information is used to compute the Cartesian distance with periodicity.
     357
     358Setting one dimension to 0 or a negative value indicates that there is no periodicity in this direction.
     359
     360|| '''Note:''' Starting from PDAF V2.3.1 one can also call [wiki:PDAFomi_set_domainsize] to initialize thisobs%domainsize. One provides a user-specified array of domain sizes. The routine then allocates thisobs%domainsize and fills it with the provided values. This should be particularly usable when not using Fortran. ||
     361
     362
     363=== `thisobs%icoeff_p` ===
     364
     365This array is allocate the in same way as `thisobs%id_obs_p`:
     366
     367{{{
     368   ALLOCATE(thisobs%icoeff_p(NROWS, dim_obs_p))
     369}}}
     370The value of NROWS has to be the same as for `thisobs%id_obs_p`. For a fixed value of the second index the NROWS of the array hold the interpolation coefficients corresponding to the indices specified in `thisobs%id_obs_p`.
     371
     372Please see the [wiki:OMI_observation_operators documentation of OMI observation operators] for information on how to initialize the array `thisobs%icoeff_p` using functions provided by PDAF-OMI.
     373
     374||Starting from PDAF V2.3.1 one can also call [wiki:PDAFomi_set_icoeff_p] to initialize thisobs%icoeff_p. One provides a user-specified array of interpolation coefficients. The routine then allocates thisobs%icoeff_p and fills it with the provided coefficients. This should be particularly usable when not using Fortran. ||
     375
     376
     377=== `thisobs%obs_err_type` ===
     378
     379The particle filter methods NETF, LNETF and PF can handle observations with non-Gaussian errors. PDAF-OMI supports the following two choices:
     380 - 0: Gaussian errors (''default value'')
     381 - 1: double-exponential (Laplace) errors
     382
     383This variable can either be set directly in the code, or, starting with PDAF V2.3.1 by calling [wiki:PDAFomi_set_obs_err_type].
     384
     385
     386=== `thisobs%use_global_obs` ===
     387
     388In the domain-localized filters (LESTK, LETKF, LSEIK, LNETF) observations are assimilated that are located within the localization around some grid point. When a model uses parallelization with domain-decomposition some of these observations might belong to a different process-domain. In the default mode (`thisobs%use_global_obs`=1) PDAF-OMI gathers all globally available observations so that each process has access to all observations. It can be more efficient to limit the observations on a process-domain to those observations that are located inside the domain or within the localization radius around it. Then, in the local analyses less observations have to be checked for their distance. Setting `thisobs%use_global_obs=0` activates this feature. However, it needs additional preparations to make PDAF-OMI aware of the limiting coordinates of a process sub-domain.
     389
     390This variable can either be set directly in the code, or, starting with PDAF V2.3.1 by calling [wiki:PDAFomi_set_use_global_obs].
     391
     392The use of this feature is described in the [wiki:OMI_use_global_obs documentation on using domain-limited observations].
     393
     394
     395
     396=== `thisobs%inno_omit` ===
     397
     398Setting this variable to a value > 0.0 activates the functionality that observations are omitted (made irrelevant) from the analysis update if the difference of their value and the ensemble mean to too large. For more information see the [wiki:PDAFomi_additional_functionality#Omittingobservationsthatarepotentialoutliers page on additional OMI functionality].
     399
     400This variable can either be set directly in the code, or, starting with PDAF V2.3.1 by calling [wiki:PDAFomi_set_inno_omit].
     401