UFO
ufo_adt_tlad_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 2017-2018 UCAR
2 !
3 ! This software is licensed under the terms of the Apache Licence Version 2.0
4 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5 
6 !> Fortran adt module for tl/ad observation operator
7 
9 
10  use fckit_configuration_module, only: fckit_configuration
11  use iso_c_binding
12  use kinds
13 
16  use ufo_vars_mod
17  use obsspace_mod
18  use missing_values_mod
19 
20  implicit none
21  private
22 
23  integer, parameter :: max_string=800
24 
25  !> Fortran derived type for the tl/ad observation operator
26  type, extends(ufo_basis_tlad), public :: ufo_adt_tlad
27  private
28  integer :: nlocs !< Local number of obs
29  real(c_double) :: r_miss_val !< Missing value flag
30  type(ufo_geoval) :: geoval_adt !< adt (traj)
31  contains
32  procedure :: setup => ufo_adt_tlad_setup
33  procedure :: delete => ufo_adt_tlad_delete
34  procedure :: settraj => ufo_adt_tlad_settraj
35  procedure :: simobs_tl => ufo_adt_simobs_tl
36  procedure :: simobs_ad => ufo_adt_simobs_ad
37  end type ufo_adt_tlad
38 
39 contains
40 
41 ! ------------------------------------------------------------------------------
42 subroutine ufo_adt_tlad_setup(self, f_conf)
43 implicit none
44 class(ufo_adt_tlad), intent(inout) :: self
45 type(fckit_configuration), intent(in) :: f_conf
46 
47 end subroutine ufo_adt_tlad_setup
48 
49 ! ------------------------------------------------------------------------------
50 subroutine ufo_adt_tlad_delete(self)
51 implicit none
52 class(ufo_adt_tlad), intent(inout) :: self
53 
54 self%ltraj = .false.
55 
56 end subroutine ufo_adt_tlad_delete
57 
58 ! ------------------------------------------------------------------------------
59 subroutine ufo_adt_tlad_settraj(self, geovals, obss)
60 implicit none
61 class(ufo_adt_tlad), intent(inout) :: self
62 type(ufo_geovals), intent(in) :: geovals
63 type(c_ptr), value, intent(in) :: obss
64 
65 character(len=*), parameter :: myname_="ufo_adt_tlad_settraj"
66 type(ufo_geoval), pointer :: geoval_adt
67 
68 self%nlocs = obsspace_get_nlocs(obss)
69 
70 ! check if adt variables is in geovals and get it
71 call ufo_geovals_get_var(geovals, var_abs_topo, geoval_adt)
72 
73 self%geoval_adt = geoval_adt
74 self%ltraj = .true.
75 
76 ! Set missing flag
77 self%r_miss_val = missing_value(self%r_miss_val)
78 
79 end subroutine ufo_adt_tlad_settraj
80 
81 ! ------------------------------------------------------------------------------
82 subroutine ufo_adt_simobs_tl(self, geovals, hofx, obss)
83 use fckit_mpi_module, only: fckit_mpi_comm, fckit_mpi_sum
84 implicit none
85 class(ufo_adt_tlad), intent(in) :: self
86 type(ufo_geovals), intent(in) :: geovals
87 real(c_double), intent(inout) :: hofx(:)
88 type(c_ptr), value, intent(in) :: obss
89 
90 character(len=*), parameter :: myname_="ufo_adt_simobs_tl"
91 character(max_string) :: err_msg
92 integer :: iobs, nlocs, cnt, cnt_glb
93 type(ufo_geoval), pointer :: geoval_adt
94 real(kind_real) :: offset_hofx, pe_offset_hofx
95 type(fckit_mpi_comm) :: f_comm
96 
97 call obsspace_get_comm(obss, f_comm)
98 
99 ! check if trajectory was set
100 if (.not. self%ltraj) then
101  write(err_msg,*) myname_, ' trajectory wasnt set!'
102  call abor1_ftn(err_msg)
103 endif
104 
105 ! check if nlocs is consistent in geovals & hofx
106 nlocs = self%nlocs
107 
108 if (geovals%nlocs /= nlocs) then
109  write(err_msg,*) myname_, ' error: nlocs inconsistent!'
110  call abor1_ftn(err_msg)
111 endif
112 
113 ! check if adt variable is in geovals and get it
114 call ufo_geovals_get_var(geovals, var_abs_topo, geoval_adt)
115 
116 ! Local offset
117 pe_offset_hofx = 0.0
118 cnt = 0
119 do iobs = 1, self%nlocs
120  if (hofx(iobs)/=self%r_miss_val) then
121  pe_offset_hofx = pe_offset_hofx + geoval_adt%vals(1,iobs)
122  cnt = cnt + 1
123  end if
124 end do
125 
126 ! Global offset
127 call f_comm%allreduce(pe_offset_hofx, offset_hofx, fckit_mpi_sum())
128 call f_comm%allreduce(cnt, cnt_glb, fckit_mpi_sum())
129 offset_hofx = offset_hofx/cnt_glb
130 
131 ! adt obs operator
132 hofx = 0.0
133 do iobs = 1, self%nlocs
134  hofx(iobs) = geoval_adt%vals(1,iobs) - offset_hofx
135 enddo
136 
137 end subroutine ufo_adt_simobs_tl
138 
139 ! ------------------------------------------------------------------------------
140 subroutine ufo_adt_simobs_ad(self, geovals, hofx, obss)
141 use fckit_mpi_module, only: fckit_mpi_comm, fckit_mpi_sum
142 implicit none
143 class(ufo_adt_tlad), intent(in) :: self
144 type(ufo_geovals), intent(inout) :: geovals
145 real(c_double), intent(in) :: hofx(:)
146 type(c_ptr), value, intent(in) :: obss
147 
148 character(len=*), parameter :: myname_="ufo_adt_simobs_ad"
149 character(max_string) :: err_msg
150 
151 integer :: iobs, nlocs, cnt, cnt_glb
152 type(ufo_geoval), pointer :: geoval_adt
153 real(kind_real) :: offset_hofx, pe_offset_hofx
154 type(fckit_mpi_comm) :: f_comm
155 
156 call obsspace_get_comm(obss, f_comm)
157 
158 ! check if trajectory was set
159 if (.not. self%ltraj) then
160  write(err_msg,*) myname_, ' trajectory wasnt set!'
161  call abor1_ftn(err_msg)
162 endif
163 
164 ! check if nlocs is consistent in geovals & hofx
165 nlocs = self%nlocs
166 if (geovals%nlocs /= nlocs) then
167  write(err_msg,*) myname_, ' error: nlocs inconsistent!'
168  call abor1_ftn(err_msg)
169 endif
170 
171 if (.not. geovals%linit ) geovals%linit=.true.
172 
173 ! check if adt variable is in geovals and get it
174 call ufo_geovals_get_var(geovals, var_abs_topo, geoval_adt)
175 
176 ! Local offset
177 pe_offset_hofx = 0.0
178 cnt = 0
179 do iobs = 1, self%nlocs
180  if (hofx(iobs)/=self%r_miss_val) then
181  pe_offset_hofx = pe_offset_hofx + hofx(iobs)
182  cnt = cnt + 1
183  end if
184 end do
185 
186 ! Global offset
187 call f_comm%allreduce(pe_offset_hofx, offset_hofx, fckit_mpi_sum())
188 call f_comm%allreduce(cnt, cnt_glb, fckit_mpi_sum())
189 offset_hofx = offset_hofx/cnt_glb
190 
191 do iobs = 1, nlocs
192  if (hofx(iobs)/=self%r_miss_val) then
193  geoval_adt%vals(1,iobs) = geoval_adt%vals(1,iobs) + hofx(iobs) - offset_hofx
194  end if
195 enddo
196 
197 end subroutine ufo_adt_simobs_ad
198 
199 end module ufo_adt_tlad_mod
Fortran adt module for tl/ad observation operator.
subroutine ufo_adt_simobs_ad(self, geovals, hofx, obss)
subroutine ufo_adt_tlad_delete(self)
integer, parameter max_string
subroutine ufo_adt_tlad_setup(self, f_conf)
subroutine ufo_adt_tlad_settraj(self, geovals, obss)
subroutine ufo_adt_simobs_tl(self, geovals, hofx, obss)
subroutine, public ufo_geovals_get_var(self, varname, geoval)
character(len=maxvarlen), public var_abs_topo
Fortran derived type for the tl/ad observation operator.
type to hold interpolated field for one variable, one observation
type to hold interpolated fields required by the obs operators