Changes between Initial Version and Version 1 of OMI_observation_operators_PDAF23


Ignore:
Timestamp:
Jun 3, 2025, 12:57:05 PM (4 days ago)
Author:
lnerger
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • OMI_observation_operators_PDAF23

    v1 v1  
     1= PDAF-OMI Observation Operators =
     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><a href="OMI_observation_modules">Observation Modules</a></li>
     10<li>Observation Operators</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
     37An observation operator routine is called for each observation type in the routine `obs_op_pdafomi` in the file `callback_obs_pdafomi.F90`.
     38
     39== Observation operators ==
     40
     41OMI currently provides 3 observation operators:
     42 - '''[wiki:PDAFomi_obs_op_gridpoint]'''[[br]]
     43  This observation operator is used for the case that observations are model variables located at grid points. Thus, the operation is to select single element from the state vector according to the index array `thisobs%id_obs_p` initialized in `init_dim_obs_OBSTYPE`.
     44 - '''[wiki:PDAFomi_obs_op_gridavg]'''[[br]]
     45  This observation operator is used for the case that observations are the average of model variables at grid points. The averages are computed according to the number of rows in the index array `thisobs%id_obs_p` initialized in `init_dim_obs_OBSTYPE`.
     46 - '''[wiki:PDAFomi_obs_op_interp_lin]'''[[br]]
     47  This observation operator computes the observation by linear interpolation. It uses the index array `thisobs%id_obs_p` and the array `thisobs%icoeff_p` holding interpolation coefficients initialized in `init_dim_obs_OBSTYPE`. To use this observation operator, one has to allocate and initialize `thisobs%icoeff_p` as described below.
     48
     49The arguments of the observation operators are
     50{{{
     51  SUBROUTINE PDAFomi_obs_op_X (thisobs,[nrows,] state_p, ostate)
     52
     53     TYPE(obs_f), INTENT(inout) :: thisobs  ! Data type with full observation
     54   [ INTEGER, INTENT(in) :: nrows           ! Number of values to be averaged ]
     55     REAL, INTENT(in)    :: state_p(:)      ! Process-local model state (provided by PDAF)
     56     REAL, INTENT(inout) :: obs_f_all(:)    ! Full observed state for all observation types (array provided by PDAF)
     57}}}
     58Where `thisobs` is the observation type variable, `state_p` is the input state vector provided by PDAF and `ostate` is the observed state that will be returned to PDAF. `nrows` only exists for the observation operators X=gridavg and X=interp_lin and specifies the number of grid points involved in the observation operation. For X=gridpoint, this argument does not exist.
     59
     60
     61== Initializing interpolation coefficients ==
     62
     63The observation operator `PDAFomi_obs_op_interp_lin` requires that the interpolation coefficients have been initialized in the array `thisobs%icoeff_p`. This initialization is performed in `init_dim_obs_OBSTYPE`. PDAF-OMI provides three routines for this task:
     64 - '''PDAFomi_get_interp_coeff_lin1D'''[[br]]
     65 Simplified initialization for 1-dimensional models
     66 - '''PDAFomi_get_interp_coeff_lin'''[[br]]
     67 Determine interpolation coefficients based on the coordinates of grid points and the observation for a rectangular grid in 1, 2, or 3 dimensions.
     68 - '''PDAFomi_get_interp_coeff_tri'''[[br]]
     69 Determine barycentric interpolation coefficients for triangular grids based on the coordinates of grid points and the observation
     70
     71An example of initializing interpolation coefficients with PDAFomi_get_interp_coeff_lin and of using PDAFomi_obs_op_interp_lin is provided in `tutorial/online_2D_serialmodel/obs_C_pdafomi.F90`.
     72
     73
     74=== PDAFomi_get_interp_coeff_lin ===
     75
     76This routine computes interpolation coefficients for a rectangular grid in 1, 2, or 3 dimensions.
     77
     78The call to this routine is
     79{{{
     80  CALL PDAFomi_get_interp_coeff_lin(num_gp, n_dim, gcoords, ocoord, icoeff)
     81
     82    INTEGER, INTENT(in) :: num_gp         ! Length of thisobs%icoeff_p(:,i)
     83    INTEGER, INTENT(in) :: n_dim          ! Number of dimensions in interpolation
     84    REAL, INTENT(in)    :: gcoords(:,:)   ! Coordinates of grid points
     85    REAL, INTENT(in)    :: ocoord(:)      ! Coordinates of observation (one column ocoord_p(:,i))
     86    REAL, INTENT(inout) :: icoeff(:)      ! Interpolation coefficients (one column thisobs%icoeff_p(:,i))
     87
     88}}}
     89Here it is required that num_gp=2 for n_dim=1; num_gp=4 for n_dim=2; num_gp=8 for n_dim=3.
     90
     91In the array `gcoords`, the first index specifies the grid point while the second specifies the coordinate. Thus, `gcoords(1,1)` is the first coordinate for grid point 1, `gcoords(1,2)` is the second coordiate for grid point 1, while `gcoords(2,1)` is the first coordiate for grid point 2. The coordinates need to be consistent with the indices specified in `thisobs%id_obs_p` since these specify the elements of the state vector that are interpolated. Only the first `n_dim` entries of ocoord will be used for the interpolation.
     92
     93`ocoord(:,i)` holds the list of the coordinates for the observation with index i (different from the use in `gcoords`)
     94
     95The order of the coordinates and coefficients is the following:
     96{{{
     97                       (7)------(8)
     98                       /|       /|    with
     99                     (5)+-----(6)|       - column 1
     100                      | |      | |       / column 2
     101                      |(3)-----+(4)      | column 3
     102                      |/       |/
     103                     (1) ---- (2)
     104
     105   thus gcoords(1,1)/=gcoords(2,1),        but  gcoords(1,1)=gcoords(3,1)=gcoords(5,1),
     106        gcoords(1,2)/=gcoords(3,2),             gcoords(1,2)=gcoords(2,2)=gcoords(5,2),
     107        gcoords(1,3)/=gcoords(5,3)              gcoords(1,3)=gcoords(2,3)=gcoords(3,3)
     108}}}
     109
     110'''Notes:'''
     111 - For 1D linear interpolation (n_dim=1) only the coordinates for grid points 1 and 2 are used to compute the coefficients
     112 - For bi-linear interpolation (n_dim=2) only the coordinates for grid points 1, 2, and 3 are used to compute the coefficients
     113 - For tri-linear interpolation (n_dim=3) only the coordinates for grid points 1, 2, 3, and 5 are used to compute the coefficients
     114
     115
     116=== PDAFomi_get_interp_coeff_lin1D ===
     117
     118This routine is a simplified variant of `PDAFomi_get_interp_coeff_lin`. It computes interpolation coefficients in 1 dimension only
     119
     120The call to this routine is
     121{{{
     122  CALL PDAFomi_get_interp_coeff_lin1D(gcoords, ocoord, icoeff)
     123
     124    REAL, INTENT(in)    :: gcoords(:)  ! Coordinates of grid points; dim=2
     125    REAL, INTENT(in)    :: ocoord      ! Coordinates of observation
     126    REAL, INTENT(inout) :: icoeff(:)   ! Interpolation coefficients; dim=2
     127}}}
     128
     129
     130
     131=== PDAFomi_get_interp_coeff_tri ===
     132
     133For triangular model grid interpolation coefficients are determined as barycentric coordinates. This is performed in this routine.
     134
     135The call to this routine is
     136{{{
     137  CALL PDAFomi_get_interp_coeff_tri(gcoords, ocoord, icoeff)
     138
     139    REAL, INTENT(in)    :: gcoords(:)      ! Coordinates of grid points; dim=(3,2)
     140    REAL, INTENT(in)    :: ocoord(:)       ! Coordinates of observation; dim=2
     141    REAL, INTENT(inout) :: icoeff(:)       ! Interpolation coefficients; dim=3
     142}}}
     143
     144'''Notes:'''
     145 - In the array `gcoords`, the first index specifies the grid point while the second specifies the coordinate, thus `gcoords(j,:)` is the list of coordinates for grid point j.
     146 - The order of the grid points in `gcoords` has to be consistent with the order of the indices specified in `thisobs%id_obs_p`
     147
     148
     149== Adjoint observation operators ==
     150
     151For the application of 3D-Var, adjoint observation operators are required. These perform the operation of the transposed linear observation operator.
     152
     153OMI provides the adjoint observation operators corresponding to the forward observation operators:
     154 - '''[wiki:PDAFomi_obs_op_adj_gridpoint]'''[[br]]
     155  This observation operator is used for the case that observations are model variables located at grid points. Thus, the operation is to select single element from the state vector according to the index array `thisobs%id_obs_p` initialized in `init_dim_obs_OBSTYPE`.
     156 - '''[wiki:PDAFomi_obs_op_adj_gridavg]'''[[br]]
     157  This observation operator is used for the case that observations are the average of model variables at grid points. The averages are computed according to the number of rows in the index array `thisobs%id_obs_p` initialized in `init_dim_obs_OBSTYPE`.
     158 - '''[wiki:PDAFomi_obs_op_adj_interp_lin]'''[[br]]
     159  This observation operator is used for the case of linear interpolation. It uses the index array `thisobs%id_obs_p` and the array `thisobs%icoeff_p` holding interpolation coefficients initialized in `init_dim_obs_OBSTYPE`. To use this observation operator, one has to allocate and initialize `thisobs%icoeff_p` as described below.
     160
     161The arguments of the observation operators are
     162{{{
     163  CALL PDAFomi_obs_op_adj_X (thisobs,[nrows,] state_p, ostate)
     164
     165     TYPE(obs_f), INTENT(inout) :: thisobs  ! Data type with full observation
     166     INTEGER, INTENT(in) :: nrows           ! Number of values to be averaged
     167     REAL, INTENT(in)    :: obs_f_all(:)    ! Full observed state for all observation types (array provided by PDAF)
     168     REAL, INTENT(inout) :: state_p(:)      ! Process-local model state (provided by PDAF)
     169}}}
     170Where `thisobs` is the observation type variable, `ostate` is the input vector in the observation space provided by PDAF and `state_p` is the output state vector that will be returned to PDAF. `nrows` only exists for the observation operators X=gridavg and X=interp_lin and specifies the number of grid points involved in the observation operation. For X=gridpoint, this argument does not exist.
     171
     172
     173== Implementing your own observation operator ==
     174
     175The current set of observation operators provided by PDAF-OMI is rather fundamental. However, there are also observation types which are not variables of state vector, but functions of several values. Likewise one might want to use a more sophisticated interpolation than the linear one or some interpolation that treats the horizontal and vertical directions separately. For these cases you can implement you own operators.
     176
     177|| The '''template observation operator''' in `/template/omi/ob_op_pdafomi_TEMPLATE.F90` can be used as the basis for the implementation. It describes the steps needs in the implementation. ||
     178
     179Each observation operator include the following functionality:
     180 1. Check whether `thisobs%doassim==1`, which indicates that the observation is assimilated
     181 2. initialize the observation vector `ostate_p` for the observation type for which the routine is called. For a parallel model this is done for for the process-local domain (for a model without parallelization this is the global domain)
     182 3. Call `PDAFomi_gather_obsstate` to gather the full observation vector `obs_f_all`. This call is mandatory even if the model is not parallelized. The interface is:
     183{{{
     184  SUBROUTINE PDAFomi_gather_obsstate(thisobs, ostate_p, obs_f_all)
     185
     186    TYPE(obs_f), INTENT(inout) :: thisobs  ! Data type with full observation
     187    REAL, INTENT(in) :: ostate_p(:)        ! Vector of process-local observed state
     188    REAL, INTENT(inout) :: obs_f_all(:)    ! Full observed vector for all types
     189}}}
     190
     191Generally one can implement any function that computes an observation from the elements of the state vector that is provided to the routine as `state_p`. The coordinate information is provided in `thisobs`. One can also modify the interface to the obsration operator routine if, e.g., additional information is required.
     192
     193Dependent on the complexity of an observation operator it might be useful to separate the functional computations from the interpolation. For this one could consider multi-step observation operators in separate routines.
     194
     195In the template we also included outputs for the [wiki:OMI_debugging debug functionality]. These should be adapted to a particular observation operator so that meaningful outputs are generated that help to check whether the operations in the routine are correct.
     196
     197||In case that you implement a new observation operator: The community of PDAF users would be grateful if you can help to advance PDAF-OMI by providing new observation operators for inclusion into PDAF-OMI under the LGPL license.||