UFO
ufo_gnssroonedvarcheck_pen_mod.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! (C) British Crown Copyright 2020 Met Office
3 !
4 ! This software is licensed under the terms of the Apache Licence Version 2.0
5 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6 !-------------------------------------------------------------------------------
7 
8 !> Calculates GPSRO penalty.
9 
11 
12 use kinds, only: kind_real
13 use missing_values_mod, only: missing_value
14 
15 private
16 public :: ops_gpsro_pen
17 
18 contains
19 
20 SUBROUTINE ops_gpsro_pen (Nstate, & ! size of state vec.
21  Nobs, & ! size of obs vec.
22  x, & ! current estimate of soltution
23  xb, & ! background
24  yobs, & ! observed values
25  ycalc, & ! y(x)
26  bm1, & ! inverse .of bsck cov matrix
27  om1, & ! inv. of obs+forw cov matrix
28  pen_ob, & ! obs penalty
29  pen_back, & ! back penalty
30  pen_func) ! total penalty
31 
32 
33 IMPLICIT NONE
34 
35 ! Subroutine arguments:
36 INTEGER, INTENT(IN) :: nstate
37 INTEGER, INTENT(IN) :: nobs
38 REAL(kind_real), INTENT(IN) :: x(:)
39 REAL(kind_real), INTENT(IN) :: xb(:)
40 REAL(kind_real), INTENT(IN) :: yobs(:)
41 REAL(kind_real), INTENT(IN) :: ycalc(:)
42 REAL(kind_real), INTENT(IN) :: bm1(:,:)
43 REAL(kind_real), INTENT(IN) :: om1(:,:)
44 REAL(kind_real), INTENT(OUT) :: pen_ob
45 REAL(kind_real), INTENT(OUT) :: pen_back
46 REAL(kind_real), INTENT(OUT) :: pen_func
47 
48 ! Local declarations:
49 REAL(kind_real) :: dx(nstate)
50 REAL(kind_real) :: dy(nobs)
51 REAL(kind_real) :: bdx(nstate)
52 REAL(kind_real) :: ody(nobs)
53 REAL(kind_real) :: j_back
54 REAL(kind_real) :: j_obs
55 CHARACTER(len=*), PARAMETER :: routinename = "Ops_GPSRO_pen"
56 
57 ! deviation from background
58 
59 dx(:) = x(:) - xb(:)
60 
61 ! calc. Bdx matrix ie B^-1(x-xb)
62 
63 bdx(:) = matmul(bm1(:,:), dx(:))
64 
65 ! background term (scalar)
66 
67 j_back = dot_product(dx(:), bdx(:))
68 
69 ! obs. meas-calc
70 
71 dy(:) = yobs(:) - ycalc(:)
72 
73 !make sure missing data is not included
74 WHERE (ycalc(:) == missing_value(ycalc(1)) .OR. &
75  yobs(:) == missing_value(yobs(1)))
76 
77  dy(:) = 0.0
78 END WHERE
79 
80 ! Ody O^-1 (ymeas-ycalc)
81 
82 ody(:) = matmul(om1(:,:), dy(:))
83 
84 ! observation term. (scalar)
85 
86 j_obs = dot_product(dy(:), ody(:))
87 
88 ! SCALAR value required
89 
90 pen_func = 0.5 * (j_back + j_obs)
91 
92 pen_ob = 0.5 * j_obs
93 pen_back = 0.5 * j_back
94 
95 END SUBROUTINE ops_gpsro_pen
96 
subroutine, public ops_gpsro_pen(Nstate, Nobs, x, xb, yobs, ycalc, BM1, OM1, pen_ob, pen_back, pen_func)