Changes between Initial Version and Version 1 of OMI_debugging_PDAF23


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

--

Legend:

Unmodified
Added
Removed
Modified
  • OMI_debugging_PDAF23

    v1 v1  
     1= PDAF-OMI Debugging Information =
     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><a href="OMI_observation_operators">Observation Operators</a></li>
     11<li><a href="OMI_error_checking">Checking error status</a></li>
     12<li>Debugging functionality</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
     39When implementing an observation with PDAF, or when performing the very first implementation of PDAF with a new model, it is useful to check whether the inputs to the PDAF-routines are correctly used. For this purpose, PDAF-OMI provides a debugging functionality. It allows you to activate debugging output e.g. for a single local analysis domain on a single process of a complex application of a local filter like LETKF.
     40
     41Note: There is a separate debugging output functionality for PDAF itself. For details see the [wiki:PDAF_debugging documentation on PDAF debugging]. One can activate the debugging for PDAF and PDAF-OMI separately or can used both in combination.
     42
     43
     44== Activating Debugging Output ==
     45
     46Debugging output is activated by a call of the form
     47{{{
     48   USE PDAFomi, ONLY: PDAFomi_set_debug_flag
     49   INTEGER :: dbg_id  ! Debugging flag: >0 for debug output; =0 for no debug output
     50
     51   CALLOMI PDAFomi_set_debug_flag(dbg_id)
     52}}}
     53In particular this call can be inserted in any routines contained in `callback_obs_pdafomi.F90`. Setting the single argument of `PDAFomi_set_debug_flag` to a value larger 0 will active the output, while =0 will deactivate it. For the debugging it is useful to keep the number of observations low since for a large number of observations, the output will be very lengthy. This can particularly be the case when using the debugging output in `init_dim_obs_pdafomi` or `obs_op_pdafomi`. To this end, it can be useful to intentionally reduce the number of observations for the debugging. For the localized filters (LESTKF, LETKF, LNETF, LSEIK) it is recommended to only activate the debugging for a single local analysis domain as shown below. The particular domain index can be chosen e.g. based on the coordinates of the domain, which are usually determined in `init_dim_l_pdaf`.
     54
     55For example to activate debugging in `init_dim_obs_l_pdafomi` for the local analysis domain `domain_p=10` and filter process 0, one uses
     56{{{
     57SUBROUTINE init_dim_obs_l_pdafomi(domain_p, step, dim_obs, dim_obs_l)
     58
     59  USE PDAFomi, ONLY: PDAFomi_set_debug_flag
     60  USE mod_parallel_pdaf, ONLY: mype_filter
     61
     62  ...
     63
     64  IF (domain_p==10 .AND. mype_filter==0) THEN
     65    CALL PDAFomi_set_debug_flag(domain_p)
     66  ELSE
     67    CALL PDAFomi_set_debug_flag(0)
     68  ENDIF
     69
     70  ...
     71
     72}}}
     73
     74== Understanding the Debugging Output ==
     75
     76The debugging output mainly writes information about the different variables contained in the full data type `obs_f` allocated as `thisobs` and the local type `obs_l` allocate as `thisobs_l`. For reference we list the full declaration of these types. When reading the debugging output one can check for the meaning of the variables.
     77
     78{{{
     79  TYPE obs_f
     80     ! ---- Mandatory variables to be set in INIT_DIM_OBS ----
     81     INTEGER :: doassim=0                 !< Whether to assimilate this observation type
     82     INTEGER :: disttype                  !< Type of distance computation to use for localization
     83     INTEGER :: ncoord                    !< Number of coordinates use for distance computation
     84     INTEGER, ALLOCATABLE :: id_obs_p(:,:) !< Indices of process-local observed field in state vector
     85
     86     ! ---- Optional variables - they can be set in INIT_DIM_OBS ----
     87     REAL, ALLOCATABLE :: icoeff_p(:,:)   !< Interpolation coefficients for obs. operator (optional)
     88     REAL, ALLOCATABLE :: domainsize(:)   !< Size of domain for periodicity (<=0 for no periodicity) (optional)
     89
     90     ! ---- Variables with predefined values - they can be changed in INIT_DIM_OBS  ----
     91     INTEGER :: obs_err_type=0            !< Type of observation error: (0) Gauss, (1) Laplace
     92     INTEGER :: use_global_obs=1          !< Whether to use (1) global full obs.
     93                                          !< or (0) obs. restricted to those relevant for a process domain
     94     REAL :: inno_omit=0.0                !< Omit obs. if squared innovation larger this factor times
     95                                          !<     observation variance (only active for >0)
     96     REAL :: inno_omit_ivar=1.0e-12       !< Value of inverse variance to omit observation
     97                                          !<     (should be much larger than actual observation error variance)
     98
     99     ! ----  The following variables are set in the routine PDAFomi_gather_obs ---
     100     INTEGER :: dim_obs_p                 !< number of PE-local observations
     101     INTEGER :: dim_obs_f                 !< number of full observations
     102     INTEGER :: dim_obs_g                 !< global number of observations
     103     INTEGER :: off_obs_f                 !< Offset of this observation in overall full obs. vector
     104     INTEGER :: off_obs_g                 !< Offset of this observation in overall global obs. vector
     105     INTEGER :: obsid                     !< Index of observation over all assimilated observations
     106     REAL, ALLOCATABLE :: obs_f(:)        !< Full observed field
     107     REAL, ALLOCATABLE :: ocoord_f(:,:)   !< Coordinates of full observation vector
     108     REAL, ALLOCATABLE :: ivar_obs_f(:)   !< Inverse variance of full observations
     109     INTEGER, ALLOCATABLE :: id_obs_f_lim(:) !< Indices of domain-relevant full obs. in global vector of obs.
     110  END TYPE obs_f
     111}}}
     112
     113{{{
     114  TYPE obs_l
     115     INTEGER :: dim_obs_l                 !< number of local observations
     116     INTEGER :: off_obs_l                 !< Offset of this observation in overall local obs. vector
     117     INTEGER, ALLOCATABLE :: id_obs_l(:)  !< Indices of local observations in full obs. vector
     118     REAL, ALLOCATABLE :: distance_l(:)   !< Distances of local observations
     119     REAL, ALLOCATABLE :: cradius_l(:)    !< directional cut-off radii of local observations
     120     REAL, ALLOCATABLE :: sradius_l(:)    !< directional support radii of local observations
     121     REAL, ALLOCATABLE :: ivar_obs_l(:)   !< Inverse variance of local observations
     122     INTEGER :: locweight                 !< Specify localization function
     123     REAL, ALLOCATABLE :: cradius(:)      !< Localization cut-off radius (single value or vector)
     124     REAL, ALLOCATABLE :: sradius(:)      !< support radius for localization function (single value or vector)
     125  END TYPE obs_l
     126}}}
     127
     128=== Example output ===
     129
     130For illustration we insert the above call to PDAFomi_set_debug flag into the routine `init_dim_obs_l_pdafomi` the file `callback_obs_pdafomi.F90` in `tutorial/online_2D_serialmodel/`. Then we compile and execute the tutorial program with:
     131{{{
     132  mpirun -np 4 ./model_pdaf -dim_ens 4 -filtertype 7 -cradius 5 -locweight 2
     133}}}
     134
     135The first lines of the debugging output looks like this:
     136{{{
     137 ++ OMI-debug set_debug_flag: mype_filter           0 activate          10
     138 ++ OMI-debug:           10 PDAFomi_init_dim_obs_l -- START
     139 ++ OMI-debug:           10    PDAFomi_init_dim_obs_l -- count local observations
     140 ++ OMI-debug init_dim_obs_l:          10   Re-init dim_obs_l=0
     141 ++ OMI-debug init_dim_obs_l:          10   coords_l   1.0000000000000000        10.000000000000000     
     142 ++ OMI-debug init_dim_obs_l:          10   Note: Please ensure that coords_l and observation coordinates have the same unit
     143 ++ OMI-debug cnt_dim_obs_l:           10   thisobs%ncoord           2
     144 ++ OMI-debug cnt_dim_obs_l:           10   thisobs_l%cradius   5.0000000000000000     
     145 ++ OMI-debug cnt_dim_obs_l:           10   Check for observations within radius
     146 ++ OMI-debug comp_dist2:              10   compute Cartesian distance
     147 ++ OMI-debug cnt_dim_obs_l:           10   valid observation with coordinates   5.0000000000000000        8.0000000000000000     
     148 ++ OMI-debug cnt_dim_obs_l:           10   valid observation with coordinates   5.0000000000000000        12.000000000000000     
     149 ++ OMI-debug:           10    PDAFomi_init_dim_obs_l -- initialize local observation arrays
     150 ++ OMI-debug comp_dist2:              10   compute Cartesian distance
     151 ++ OMI-debug init_dim_obs_l:          10   thisobs_l%dim_obs_l           2
     152 ++ OMI-debug init_dim_obs_l:          10   thisobs_l%id_obs_l           2           3
     153 ++ OMI-debug init_dim_obs_l:          10   thisobs_l%distance_l   4.4721359549995796        4.4721359549995796     
     154 ++ OMI-debug:           10 PDAFomi_init_dim_obs_l -- END
     155}}}
     156
     157The first line
     158{{{
     159 ++ OMI-debug set_debug_flag: mype_filter           0 activate          10
     160}}}
     161is from PDAFomi_set_debug_flag showing that debugging is activates with value 10 (which is values fo `domain_p` specified in the call)
     162
     163The next lines are
     164{{{
     165 ++ OMI-debug:           10 PDAFomi_init_dim_obs_l -- START           
     166 ++ OMI-debug:           10    PDAFomi_init_dim_obs_l -- count local observations
     167 ++ OMI-debug init_dim_obs_l:          10   Re-init dim_obs_l=0
     168}}}
     169show that debugging output for PDAFomi_init_dim_obs_l is shown. Most routines show such a 'START' line. The second line shows that a segment of the routine started, the counting of local observations. The third line states that dim_obs_l=0 is set. This line, as many others shows the name of the subroutine in short form without `PDAFomi` at the beginning of the line.
     170
     171The following lines show variable values
     172{{{
     173 ++ OMI-debug init_dim_obs_l:          10   coords_l   1.0000000000000000        10.000000000000000     
     174 ++ OMI-debug cnt_dim_obs_l:           10   thisobs%ncoord           2
     175 ++ OMI-debug cnt_dim_obs_l:           10   thisobs_l%cradius   5.0000000000000000     
     176}}}
     177First, we see that the coordinates `coords_l` of the grid point corresponding to domain_p=10 are (1.0, 10.0). Further we have two dimensions (thisobs%ncoord=2) and the localization radius is set to 5.0.
     178In the following lines
     179{{{
     180 ++ OMI-debug cnt_dim_obs_l:           10   Check for observations within radius
     181 ++ OMI-debug comp_dist2:              10   compute Cartesian distance
     182 ++ OMI-debug cnt_dim_obs_l:           10   valid observation with coordinates   5.0000000000000000        8.0000000000000000     
     183 ++ OMI-debug cnt_dim_obs_l:           10   valid observation with coordinates   5.0000000000000000        12.000000000000000 
     184}}}
     185it is checked which observations lie within the distance thisobs_l%cradius=5.0 from coords_l=(1.0, 10.0). Two observations with coordinates (5.0, 8.0) and (5.0, 12.0) are found. The following lines
     186{{{
     187 ++ OMI-debug:           10    PDAFomi_init_dim_obs_l -- initialize local observation arrays
     188 ++ OMI-debug comp_dist2:              10   compute Cartesian distance
     189 ++ OMI-debug init_dim_obs_l:          10   thisobs_l%dim_obs_l           2
     190 ++ OMI-debug init_dim_obs_l:          10   thisobs_l%id_obs_l           2           3
     191 ++ OMI-debug init_dim_obs_l:          10   thisobs_l%distance_l   4.4721359549995796        4.4721359549995796     
     192}}}
     193show that observation arrays are initialized. A Cartesian distance is computrd. `thisobs_l%dim_obs_l` confirms that 2 local observation were found and they are the elements 2 and 3 of the full observation vector (thisobs_l%id_obs_l= (2, 3)) and the distances are thisobs_l%distance_l=(4.4721359549995796, 4.4721359549995796)
     194
     195One could now compare this with the input information. Are the values of coords_l correct? Are the coordinates shown those of the second and third observation?
     196
     197Later in the debugging output (not shown above) we find, for example,
     198{{{
     199 ++ OMI-debug:           10    PDAFomi_init_obs_l -- Get local vector of observations
     200 ++ OMI-debug g2l_obs:                 10   thisobs_l%id_obs_l           2           3
     201 ++ OMI-debug g2l_obs:                 10   obs_l -0.84588099999999999       -1.5201499999999999     
     202 ++ OMI-debug:           10    PDAFomi_init_obs_l -- Get local vector of inverse obs. variances
     203 ++ OMI-debug g2l_obs:                 10   thisobs_l%id_obs_l           2           3
     204 ++ OMI-debug g2l_obs:                 10   obs_l   4.0000000000000000        4.0000000000000000   
     205}}}
     206These lines are from the internal routine `PDAFomi_init_obs_l`, which initializes the local vector of observations. (This is functionality also existing in the 'traditional' form of implementing the observation handling. The documention page about [wiki:init_obs_l_pdaf init_obs_l_pdaf] explains what is done here.) Important is that not only the local observation vector (two values) is initialized, but also the inverse observation variance (4.0 in this example).
     207
     208Similarly
     209{{{
     210 ++ OMI-debug:           10 PDAFomi_g2l_obs -- START Get local observed ensemble member           1
     211 ++ OMI-debug g2l_obs:                 10   thisobs_l%id_obs_l           2           3
     212 ++ OMI-debug g2l_obs:                 10   obs_l -0.53940120224649080       0.56425243172725248     
     213 ++ OMI-debug:           10 PDAFomi_g2l_obs -- END
     214}}}
     215shows the localization of the observed ensemble member 1. This is performed in the internal routine `PDAFomi_g2l_obs` (see the page about [wiki:g2l_obs_pdaf g2l_obs_pdaf]). There is analogous output for all of the 4 ensemble states.
     216
     217