FV3 Bundle
qg_obs_vectors.F90
Go to the documentation of this file.
1 ! (C) Copyright 2009-2016 ECMWF.
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 ! In applying this licence, ECMWF does not waive the privileges and immunities
6 ! granted to it by virtue of its status as an intergovernmental organisation nor
7 ! does it submit to any jurisdiction.
8 
9 !> Fortran module handling observation vectors
10 
12 
13 use iso_c_binding
15 use kinds
16 
17 implicit none
18 private
19 public :: obs_vect, obsvec_setup
20 public :: qg_obs_vect_registry
21 
22 ! ------------------------------------------------------------------------------
23 
24 !> Fortran derived type to represent an observation vector
26  integer :: nobs=0
27  integer :: ncol=0
28  real(kind=kind_real), allocatable :: values(:,:)
29 end type obs_vect
30 
31 #define LISTED_TYPE obs_vect
32 
33 !> Linked list interface - defines registry_t type
34 #include "oops/util/linkedList_i.f"
35 
36 !> Global registry
37 type(registry_t) :: qg_obs_vect_registry
38 
39 ! ------------------------------------------------------------------------------
40 contains
41 ! ------------------------------------------------------------------------------
42 !> Linked list implementation
43 #include "oops/util/linkedList_c.f"
44 
45 ! ------------------------------------------------------------------------------
46 
47 subroutine c_qg_obsvec_setup(c_key_self, ncol, nobs) bind(c,name='qg_obsvec_setup_f90')
48 implicit none
49 integer(c_int), intent(inout) :: c_key_self
50 integer(c_int), intent(in) :: ncol, nobs
51 type(obs_vect), pointer :: self
52 
53 call qg_obs_vect_registry%init()
54 call qg_obs_vect_registry%add(c_key_self)
55 call qg_obs_vect_registry%get(c_key_self,self)
56 call obsvec_setup(self, ncol, nobs)
57 
58 end subroutine c_qg_obsvec_setup
59 
60 ! ------------------------------------------------------------------------------
61 
62 subroutine obsvec_setup(self, nc, no)
63 implicit none
64 type(obs_vect), intent(inout) :: self
65 integer(c_int), intent(in) :: nc, no
66 
67 self%ncol=nc
68 self%nobs=no
69 if (allocated(self%values)) deallocate(self%values)
70 allocate(self%values(self%ncol,self%nobs))
71 
72 end subroutine obsvec_setup
73 
74 ! ------------------------------------------------------------------------------
75 
76 subroutine c_qg_obsvec_clone(c_key_self, c_key_other) bind(c,name='qg_obsvec_clone_f90')
77 implicit none
78 integer(c_int), intent(in) :: c_key_self
79 integer(c_int), intent(inout) :: c_key_other
80 type(obs_vect), pointer :: self, other
81 
82 call qg_obs_vect_registry%get(c_key_self,self)
83 call qg_obs_vect_registry%init()
84 call qg_obs_vect_registry%add(c_key_other)
85 call qg_obs_vect_registry%get(c_key_other,other)
86 other%ncol=self%ncol
87 other%nobs=self%nobs
88 allocate(other%values(other%ncol,other%nobs))
89 
90 end subroutine c_qg_obsvec_clone
91 
92 ! ------------------------------------------------------------------------------
93 
94 subroutine c_qg_obsvec_delete(c_key_self) bind(c,name='qg_obsvec_delete_f90')
95 implicit none
96 integer(c_int), intent(inout) :: c_key_self
97 type(obs_vect), pointer :: self
98 
99 call qg_obs_vect_registry%get(c_key_self,self)
100 deallocate(self%values)
101 call qg_obs_vect_registry%remove(c_key_self)
102 
103 end subroutine c_qg_obsvec_delete
104 
105 ! ------------------------------------------------------------------------------
106 subroutine c_qg_obsvec_assign(c_key_self, c_key_rhs) bind(c,name='qg_obsvec_assign_f90')
107 implicit none
108 integer(c_int), intent(in) :: c_key_self
109 integer(c_int), intent(in) :: c_key_rhs
110 type(obs_vect), pointer :: self, rhs
111 
112 call qg_obs_vect_registry%get(c_key_self,self)
113 call qg_obs_vect_registry%get(c_key_rhs,rhs)
114 if (rhs%ncol/=self%ncol .or. rhs%nobs/=self%nobs) then
115  deallocate(self%values)
116  self%ncol=rhs%ncol
117  self%nobs=rhs%nobs
118  allocate(self%values(self%ncol,self%nobs))
119 endif
120 self%values(:,:)=rhs%values(:,:)
121 
122 end subroutine c_qg_obsvec_assign
123 ! ------------------------------------------------------------------------------
124 subroutine c_qg_obsvec_zero(c_key_self) bind(c,name='qg_obsvec_zero_f90')
125 implicit none
126 integer(c_int), intent(in) :: c_key_self
127 type(obs_vect), pointer :: self
128 
129 call qg_obs_vect_registry%get(c_key_self,self)
130 self%values(:,:)=0.0_kind_real
131 
132 end subroutine c_qg_obsvec_zero
133 ! ------------------------------------------------------------------------------
134 subroutine c_qg_obsvec_mul_scal(c_key_self, zz) bind(c,name='qg_obsvec_mul_scal_f90')
135 implicit none
136 integer(c_int), intent(in) :: c_key_self
137 real(c_double), intent(in) :: zz
138 type(obs_vect), pointer :: self
139 
140 call qg_obs_vect_registry%get(c_key_self,self)
141 self%values(:,:)=zz*self%values(:,:)
142 
143 end subroutine c_qg_obsvec_mul_scal
144 ! ------------------------------------------------------------------------------
145 subroutine c_qg_obsvec_add(c_key_self, c_key_other) bind(c,name='qg_obsvec_add_f90')
146 implicit none
147 integer(c_int), intent(in) :: c_key_self
148 integer(c_int), intent(in) :: c_key_other
149 type(obs_vect), pointer :: self, other
150 
151 call qg_obs_vect_registry%get(c_key_self,self)
152 call qg_obs_vect_registry%get(c_key_other,other)
153 self%values(:,:)=self%values(:,:)+other%values(:,:)
154 
155 end subroutine c_qg_obsvec_add
156 ! ------------------------------------------------------------------------------
157 subroutine c_qg_obsvec_sub(c_key_self, c_key_other) bind(c,name='qg_obsvec_sub_f90')
158 implicit none
159 integer(c_int), intent(in) :: c_key_self
160 integer(c_int), intent(in) :: c_key_other
161 type(obs_vect), pointer :: self, other
162 
163 call qg_obs_vect_registry%get(c_key_self,self)
164 call qg_obs_vect_registry%get(c_key_other,other)
165 self%values(:,:)=self%values(:,:)-other%values(:,:)
166 
167 end subroutine c_qg_obsvec_sub
168 ! ------------------------------------------------------------------------------
169 subroutine c_qg_obsvec_mul(c_key_self, c_key_other) bind(c,name='qg_obsvec_mul_f90')
170 implicit none
171 integer(c_int), intent(in) :: c_key_self
172 integer(c_int), intent(in) :: c_key_other
173 type(obs_vect), pointer :: self, other
174 
175 call qg_obs_vect_registry%get(c_key_self,self)
176 call qg_obs_vect_registry%get(c_key_other,other)
177 self%values(:,:)=self%values(:,:)*other%values(:,:)
178 
179 end subroutine c_qg_obsvec_mul
180 ! ------------------------------------------------------------------------------
181 subroutine c_qg_obsvec_div(c_key_self, c_key_other) bind(c,name='qg_obsvec_div_f90')
182 implicit none
183 integer(c_int), intent(in) :: c_key_self
184 integer(c_int), intent(in) :: c_key_other
185 type(obs_vect), pointer :: self, other
186 
187 call qg_obs_vect_registry%get(c_key_self,self)
188 call qg_obs_vect_registry%get(c_key_other,other)
189 self%values(:,:)=self%values(:,:)/other%values(:,:)
190 
191 end subroutine c_qg_obsvec_div
192 ! ------------------------------------------------------------------------------
193 subroutine c_qg_obsvec_axpy(c_key_self, zz, c_key_other) bind(c,name='qg_obsvec_axpy_f90')
194 implicit none
195 integer(c_int), intent(in) :: c_key_self
196 real(c_double), intent(in) :: zz
197 integer(c_int), intent(in) :: c_key_other
198 type(obs_vect), pointer :: self, other
199 
200 call qg_obs_vect_registry%get(c_key_self,self)
201 call qg_obs_vect_registry%get(c_key_other,other)
202 self%values(:,:)=self%values(:,:)+zz*other%values(:,:)
203 
204 end subroutine c_qg_obsvec_axpy
205 ! ------------------------------------------------------------------------------
206 subroutine c_qg_obsvec_invert(c_key_self) bind(c,name='qg_obsvec_invert_f90')
207 implicit none
208 integer(c_int), intent(in) :: c_key_self
209 type(obs_vect), pointer :: self
210 
211 call qg_obs_vect_registry%get(c_key_self,self)
212 self%values(:,:)=1.0_kind_real/self%values(:,:)
213 
214 end subroutine c_qg_obsvec_invert
215 ! ------------------------------------------------------------------------------
216 subroutine c_qg_obsvec_random(c_key_self) bind(c,name='qg_obsvec_random_f90')
217 implicit none
218 integer(c_int), intent(in) :: c_key_self
219 type(obs_vect), pointer :: self
220 
221 call qg_obs_vect_registry%get(c_key_self,self)
222 call random_vector(self%values)
223 
224 end subroutine c_qg_obsvec_random
225 ! ------------------------------------------------------------------------------
226 subroutine c_qg_obsvec_dotprod(c_key_self, c_key_other, zz) bind(c,name='qg_obsvec_dotprod_f90')
227 implicit none
228 integer(c_int), intent(in) :: c_key_self
229 integer(c_int), intent(in) :: c_key_other
230 real(c_double), intent(inout) :: zz
231 type(obs_vect), pointer :: self, other
232 integer :: jc, jo
233 
234 zz=0.0_kind_real
235 call qg_obs_vect_registry%get(c_key_self,self)
236 call qg_obs_vect_registry%get(c_key_other,other)
237 do jo=1,self%nobs
238 do jc=1,self%ncol
239  zz = zz + self%values(jc,jo)*other%values(jc,jo)
240 enddo
241 enddo
242 
243 end subroutine c_qg_obsvec_dotprod
244 ! ------------------------------------------------------------------------------
245 subroutine c_qg_obsvec_minmaxavg(c_key_self, zmin, zmax, zavg) bind(c,name='qg_obsvec_minmaxavg_f90')
246 implicit none
247 integer(c_int), intent(in) :: c_key_self
248 real(c_double), intent(inout) :: zmin, zmax, zavg
249 type(obs_vect), pointer :: self
250 integer :: jc, jo
251 
252 call qg_obs_vect_registry%get(c_key_self,self)
253 if (self%nobs>0.and.self%ncol>0) then
254  if (.not.allocated(self%values)) call abor1_ftn("obsvec_minmax: obs vector not allocated")
255  zmin=self%values(1,1)
256  zmax=self%values(1,1)
257  zavg=0.0_kind_real
258  do jo=1,self%nobs
259  do jc=1,self%ncol
260  zmin=min(self%values(jc,jo),zmin)
261  zmax=max(self%values(jc,jo),zmax)
262  zavg=zavg+self%values(jc,jo)
263  enddo
264  enddo
265  zavg=zavg/real(self%ncol*self%nobs,kind_real)
266 else
267  zmin=0.0_kind_real
268  zmax=0.0_kind_real
269  zavg=0.0_kind_real
270 endif
271 
272 end subroutine c_qg_obsvec_minmaxavg
273 ! ------------------------------------------------------------------------------
274 subroutine c_qg_obsvec_nobs(c_key_self, kobs) bind(c,name='qg_obsvec_nobs_f90')
275 implicit none
276 integer(c_int), intent(in) :: c_key_self
277 integer(c_int), intent(inout) :: kobs
278 type(obs_vect), pointer :: self
279 
280 call qg_obs_vect_registry%get(c_key_self,self)
281 kobs=self%nobs*self%ncol
282 
283 end subroutine c_qg_obsvec_nobs
284 ! ------------------------------------------------------------------------------
285 
286 end module qg_obs_vectors
Fortran generic for generating random 1d, 2d and 3d arrays.
type(registry_t), public qg_obs_vect_registry
Linked list interface - defines registry_t type.
integer, parameter, public no
subroutine c_qg_obsvec_delete(c_key_self)
subroutine c_qg_obsvec_mul(c_key_self, c_key_other)
subroutine c_qg_obsvec_assign(c_key_self, c_key_rhs)
subroutine c_qg_obsvec_invert(c_key_self)
subroutine c_qg_obsvec_zero(c_key_self)
subroutine c_qg_obsvec_add(c_key_self, c_key_other)
subroutine c_qg_obsvec_div(c_key_self, c_key_other)
subroutine c_qg_obsvec_mul_scal(c_key_self, zz)
subroutine c_qg_obsvec_setup(c_key_self, ncol, nobs)
Linked list implementation.
subroutine c_qg_obsvec_random(c_key_self)
subroutine c_qg_obsvec_dotprod(c_key_self, c_key_other, zz)
subroutine c_qg_obsvec_minmaxavg(c_key_self, zmin, zmax, zavg)
subroutine, public obsvec_setup(self, nc, no)
subroutine c_qg_obsvec_nobs(c_key_self, kobs)
Fortran module for generating random vectors.
subroutine c_qg_obsvec_axpy(c_key_self, zz, c_key_other)
#define max(a, b)
Definition: mosaic_util.h:33
subroutine c_qg_obsvec_clone(c_key_self, c_key_other)
#define min(a, b)
Definition: mosaic_util.h:32
subroutine c_qg_obsvec_sub(c_key_self, c_key_other)
Fortran module handling observation vectors.
Fortran derived type to represent an observation vector.