9 | | As mentioned in the OMI introduction, the routines are mainly pass-through routines. Thus, one typically includes the observation-specific routine with ‘use’ and then calls this routine. However, the is small additional functionality in the different routines which has to be handles when implementing the routine or adding an observation type |
| 9 | The routines are mainly pass-through routines. Thus, one typically includes the observation-specific routine with ‘use’ and then calls this routine. However, there is small additional functionality in the different routines which has to be handled when implementing the routine or adding an observation type. |
| 10 | |
| 11 | In the descriptions below we use 'TYPE' as a generic label for an observation type. When implemeting an observation type, one replace this by an actual name. For example for sea surface temperature (sst) observations, one could replace TYPE by 'sst' and write e.g. `init_dim_obs_sst`. |
| 23 | As an example, in `tutorial/online_2D_serialmodel_omi/` we have three observations, named A, B, and C. In `init_dim_obs_pdafomi` we find the lines |
| 24 | {{{ |
| 25 | USE obs_A_pdafomi, ONLY: assim_A, init_dim_obs_A |
| 26 | USE obs_B_pdafomi, ONLY: assim_B, init_dim_obs_B |
| 27 | USE obs_C_pdafomi, ONLY: assim_C, init_dim_obs_C |
| 28 | |
| 29 | INTEGER :: dim_obs_A ! Observation dimensions |
| 30 | INTEGER :: dim_obs_B ! Observation dimensions |
| 31 | INTEGER :: dim_obs_C ! Observation dimensions |
| 32 | |
| 33 | dim_obs_A = 0 |
| 34 | dim_obs_B = 0 |
| 35 | dim_obs_C = 0 |
| 36 | |
| 37 | IF (assim_A) CALL init_dim_obs_A(step, dim_obs_A) |
| 38 | IF (assim_B) CALL init_dim_obs_B(step, dim_obs_B) |
| 39 | IF (assim_C) CALL init_dim_obs_C(step, dim_obs_C) |
| 40 | }}} |
| 41 | |
| 42 | |
33 | | 1. Add a call to the observation-specific routine obs_op_TYPE |
| 55 | 1. Add a call to the observation-specific routine `obs_op_TYPEz |
| 56 | |
| 57 | As an example, in `tutorial/online_2D_serialmodel_omi/` we have |
| 58 | {{{ |
| 59 | USE obs_A_pdafomi, ONLY: obs_op_A |
| 60 | USE obs_B_pdafomi, ONLY: obs_op_B |
| 61 | USE obs_C_pdafomi, ONLY: obs_op_C |
| 62 | |
| 63 | CALL obs_op_A(dim_p, dim_obs, state_p, ostate) |
| 64 | CALL obs_op_B(dim_p, dim_obs, state_p, ostate) |
| 65 | CALL obs_op_C(dim_p, dim_obs, state_p, ostate) |
| 66 | }}} |
| 81 | As an example, in `tutorial/online_2D_serialmodel_omi/` we have |
| 82 | {{{ |
| 83 | USE obs_A_pdafomi, ONLY: init_dim_obs_l_A |
| 84 | USE obs_B_pdafomi, ONLY: init_dim_obs_l_B |
| 85 | USE obs_C_pdafomi, ONLY: init_dim_obs_l_C |
| 86 | |
| 87 | CALL init_dim_obs_l_A(domain_p, step, dim_obs, dim_obs_l) |
| 88 | CALL init_dim_obs_l_B(domain_p, step, dim_obs, dim_obs_l) |
| 89 | CALL init_dim_obs_l_C(domain_p, step, dim_obs, dim_obs_l) |
| 90 | }}} |
| 91 | |
| 92 | Notes: |
| 93 | - The order of the calls to `init_dim_obs_l_TYPE` defines the order in which the observations are stored in the local observation vector. The calling order does not need to be the same as in the other routines, but it's good practive to keep the order of the calls consistent. |
| 104 | As an example, in `tutorial/online_2D_serialmodel_omi/` we have |
| 105 | {{{ |
| 106 | USE obs_A_pdafomi, ONLY: localize_covar_A |
| 107 | USE obs_B_pdafomi, ONLY: localize_covar_B |
| 108 | USE obs_C_pdafomi, ONLY: localize_covar_C |
| 109 | |
| 110 | REAL, ALLOCATABLE :: coords_p(:,:) ! Coordinates of PE-local state vector entries |
| 111 | |
| 112 | ALLOCATE(coords_p(2, dim_p)) |
| 113 | coords_p = ... ! Initialize coords_p |
| 114 | |
| 115 | |
| 116 | CALL localize_covar_A(dim_p, dim_obs, HP_p, HPH, coords_p) |
| 117 | CALL localize_covar_B(dim_p, dim_obs, HP_p, HPH, coords_p) |
| 118 | CALL localize_covar_C(dim_p, dim_obs, HP_p, HPH, coords_p) |
| 119 | |
| 120 | DEALLOCATE(coords_p) |
| 121 | }}} |
| 122 | |
| 123 | Notes: |
| 124 | - Instead of allocating and filling the coordinate array `coords_p` in this routine one could also do it once in `init_pdaf` and declare the array in the module `mod_assimilation`. |
| 125 | - The order of the calls to `obs_op_TYPE` is not relevant because the setup of the overall full observation vector is defined by the order of the calls in init_dim_obs_pdafomi. Anyway, it's good practice to keep the order of the calls consistent. |
| 135 | |
| 136 | As an example, in `tutorial/online_2D_serialmodel_omi/` we have |
| 137 | {{{ |
| 138 | USE PDAFomi, ONLY: PDAFomi_deallocate_obs |
| 139 | USE obs_A_pdafomi, ONLY: obs_A => thisobs |
| 140 | USE obs_B_pdafomi, ONLY: obs_B => thisobs |
| 141 | USE obs_C_pdafomi, ONLY: obs_C => thisobs |
| 142 | |
| 143 | CALL PDAFomi_deallocate_obs(obs_A) |
| 144 | CALL PDAFomi_deallocate_obs(obs_B) |
| 145 | CALL PDAFomi_deallocate_obs(obs_C) |
| 146 | }}} |