UFO
ufo_geovals_mod.F90
Go to the documentation of this file.
1 !
2 ! (C) Copyright 2017-2018 UCAR
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 !
8 
9 use fckit_configuration_module, only: fckit_configuration
10 use iso_c_binding
11 use ufo_vars_mod
12 use kinds
13 use obsspace_mod
14 use missing_values_mod
15 
16 use fckit_mpi_module, only: fckit_mpi_comm, fckit_mpi_sum
17 
18 implicit none
19 private
20 integer, parameter :: max_string=800
21 
22 public :: ufo_geovals, ufo_geoval
26 public :: ufo_geovals_profmult
34 
36 
37 ! ------------------------------------------------------------------------------
38 
39 !> type to hold interpolated field for one variable, one observation
40 type :: ufo_geoval
41  real(kind_real), allocatable :: vals(:,:) !< values (nval, nlocs)
42  integer :: nval = 0 !< number of values in profile
43  integer :: nlocs = 0 !< number of observations
44 end type ufo_geoval
45 
46 !> type to hold interpolated fields required by the obs operators
47 type :: ufo_geovals
48  integer :: nlocs = 0 !< number of observations
49  integer :: nvar = 0 !< number of variables (supposed to be the
50  ! same for same obs operator
51 
52  type(ufo_geoval), allocatable :: geovals(:) !< array of interpolated
53  ! vertical profiles for all obs (nvar)
54 
55  character(len=MAXVARLEN), allocatable :: variables(:) !< variable list
56 
57  real(c_double) :: missing_value !< obsspace missing value mark
58 
59  logical :: linit = .false. !< .true. if all the ufo_geoval arrays inside geovals
60  ! were allocated and have data
61 end type ufo_geovals
62 
63 ! ------------------------------------------------------------------------------
64 contains
65 ! ------------------------------------------------------------------------------
66 
68 implicit none
69 type(ufo_geovals), intent(inout) :: self
70 
71 self%nlocs = 0
72 self%missing_value = missing_value(0.0)
73 self%nvar = 0
74 self%linit = .false.
75 
76 end subroutine ufo_geovals_default_constr
77 
78 
79 subroutine ufo_geovals_setup(self, vars, nlocs)
80 use oops_variables_mod
81 implicit none
82 type(ufo_geovals), intent(inout) :: self
83 type(oops_variables), intent(in) :: vars
84 integer, intent(in) :: nlocs
85 
86 integer :: ivar
87 type(fckit_configuration) :: f_vars
88 
89 call ufo_geovals_delete(self)
90 self%nlocs = nlocs
91 self%missing_value = missing_value(self%missing_value)
92 
93 self%nvar = vars%nvars()
94 allocate(self%geovals(self%nvar))
95 allocate(self%variables(self%nvar))
96 do ivar = 1, self%nvar
97  self%variables(ivar) = vars%variable(ivar)
98  self%geovals(ivar)%nlocs = nlocs
99  self%geovals(ivar)%nval = 0
100 enddo
101 
102 end subroutine ufo_geovals_setup
103 
104 ! ------------------------------------------------------------------------------
105 
106 subroutine ufo_geovals_delete(self)
107 implicit none
108 type(ufo_geovals), intent(inout) :: self
109 
110 integer :: ivar
111 
112 if (allocated(self%geovals)) then
113  do ivar = 1, self%nvar
114  if (allocated(self%geovals(ivar)%vals)) deallocate(self%geovals(ivar)%vals)
115  enddo
116  deallocate(self%geovals)
117  endif
118 if (allocated(self%variables)) deallocate(self%variables)
119 self%nvar = 0
120 self%nlocs = 0
121 self%linit = .false.
122 
123 end subroutine ufo_geovals_delete
124 
125 ! ------------------------------------------------------------------------------
126 
127 subroutine ufo_geovals_get_var(self, varname, geoval)
128 implicit none
129 type(ufo_geovals), target, intent(in) :: self
130 character(len=*), intent(in) :: varname
131 type(ufo_geoval), pointer, intent(inout) :: geoval
132 
133 character(len=*), parameter :: myname_="ufo_geovals_get_var"
134 
135 character(max_string) :: err_msg
136 integer :: ivar, jv
137 
138 geoval => null()
139 if (.not. self%linit) then
140  !return
141 endif
142 
143 ivar = ufo_vars_getindex(self%variables, varname)
144 
145 if (ivar < 0) then
146  write(0,*)'ufo_geovals_get_var looking for ',trim(varname),' in:'
147  do jv=1,self%nvar
148  write(0,*)'ufo_geovals_get_var ',jv,trim(self%variables(jv))
149  enddo
150  write(err_msg,*) myname_, " ", trim(varname), ' doesnt exist'
151  call abor1_ftn(err_msg)
152 else
153  geoval => self%geovals(ivar)
154 endif
155 
156 end subroutine ufo_geovals_get_var
157 
158 ! ------------------------------------------------------------------------------
159 
160 subroutine ufo_geovals_put_var(self, varname, geoval,k)
161 type(ufo_geovals),intent(inout) :: self
162 character(len=*), intent(in) :: varname
163 type(ufo_geoval), intent(in) :: geoval
164 integer, intent(in) :: k
165 
166 integer :: ivar
167 
168 ivar = ufo_vars_getindex(self%variables, varname)
169 self%geovals(ivar)%vals(k,:)=geoval%vals(k,:)
170 
171 end subroutine ufo_geovals_put_var
172 
173 ! ------------------------------------------------------------------------------
174 
175 subroutine ufo_geovals_zero(self)
176 implicit none
177 type(ufo_geovals), intent(inout) :: self
178 integer :: ivar
179 
180 if (.not. self%linit) then
181  call abor1_ftn("ufo_geovals_zero: geovals not initialized")
182 endif
183 do ivar = 1, self%nvar
184  self%geovals(ivar)%vals(:,:) = 0.0
185 enddo
186 
187 end subroutine ufo_geovals_zero
188 
189 ! ------------------------------------------------------------------------------
190 
191 subroutine ufo_geovals_abs(self)
192 implicit none
193 type(ufo_geovals), intent(inout) :: self
194 integer :: ivar
195 
196 if (.not. self%linit) then
197  call abor1_ftn("ufo_geovals_abs: geovals not initialized")
198 endif
199 do ivar = 1, self%nvar
200  self%geovals(ivar)%vals = abs(self%geovals(ivar)%vals)
201 enddo
202 
203 end subroutine ufo_geovals_abs
204 
205 ! ------------------------------------------------------------------------------
206 
207 subroutine ufo_geovals_rms(self,vrms)
208 implicit none
209 type(ufo_geovals), intent(in) :: self
210 real(kind_real), intent(inout) :: vrms
211 integer :: jv, jo
212 real(kind_real) :: n
213 
214 if (.not. self%linit) then
215  call abor1_ftn("ufo_geovals_rms: geovals not initialized")
216 endif
217 vrms=0.0_kind_real
218 n=0.0_kind_real
219 do jv = 1, self%nvar
220  do jo = 1, self%nlocs
221  vrms = vrms + sum(self%geovals(jv)%vals(:,jo)**2)
222  n=n+self%geovals(jv)%nval
223  enddo
224 enddo
225 
226 if ( n > 0) vrms = sqrt(vrms/n)
227 
228 end subroutine ufo_geovals_rms
229 
230 ! ------------------------------------------------------------------------------
231 
232 subroutine ufo_geovals_random(self)
233 use random_mod
234 implicit none
235 type(ufo_geovals), intent(inout) :: self
236 integer :: ivar
237 integer :: rseed = 7
238 
239 if (.not. self%linit) then
240  call abor1_ftn("ufo_geovals_random: geovals not initialized")
241 endif
242 do ivar = 1, self%nvar
243  call normal_distribution(self%geovals(ivar)%vals, 0.0_kind_real, 1.0_kind_real, rseed)
244 enddo
245 
246 end subroutine ufo_geovals_random
247 
248 ! ------------------------------------------------------------------------------
249 
250 subroutine ufo_geovals_scalmult(self, zz)
251 implicit none
252 type(ufo_geovals), intent(inout) :: self
253 real(kind_real), intent(in) :: zz
254 integer :: jv, jo, jz
255 
256 if (.not. self%linit) then
257  call abor1_ftn("ufo_geovals_scalmult: geovals not allocated")
258 endif
259 
260 do jv=1,self%nvar
261  do jo=1,self%nlocs
262  do jz = 1, self%geovals(jv)%nval
263  self%geovals(jv)%vals(jz,jo) = zz * self%geovals(jv)%vals(jz,jo)
264  enddo
265  enddo
266 enddo
267 
268 end subroutine ufo_geovals_scalmult
269 
270 ! ------------------------------------------------------------------------------
271 
272 subroutine ufo_geovals_profmult(self, nlocs, values)
273 implicit none
274 type(ufo_geovals), intent(inout) :: self
275 integer(c_int), intent(in) :: nlocs
276 real(c_float), intent(in) :: values(nlocs)
277 integer :: jv, jo
278 
279 if (.not. self%linit) then
280  call abor1_ftn("ufo_geovals_profmult: geovals not allocated")
281 endif
282 
283 do jv=1,self%nvar
284  do jo=1,self%nlocs
285  self%geovals(jv)%vals(:,jo) = values(jo) * self%geovals(jv)%vals(:,jo)
286  enddo
287 enddo
288 
289 end subroutine ufo_geovals_profmult
290 
291 ! ------------------------------------------------------------------------------
292 
293 
294 subroutine ufo_geovals_assign(self, rhs)
295 implicit none
296 type(ufo_geovals), intent(inout) :: self
297 type(ufo_geovals), intent(in) :: rhs
298 integer :: jv, jo, jz
299 integer :: iv
300 character(max_string) :: err_msg
301 
302 if (.not. self%linit) then
303  call abor1_ftn("ufo_geovals_scalmult: geovals not allocated")
304 endif
305 if (.not. rhs%linit) then
306  call abor1_ftn("ufo_geovals_scalmult: geovals not allocated")
307 endif
308 
309 if (self%nlocs /= rhs%nlocs) then
310  call abor1_ftn("ufo_geovals_assign: nlocs different between lhs and rhs")
311 endif
312 
313 do jv=1,self%nvar
314  iv = ufo_vars_getindex(rhs%variables, self%variables(jv))
315  if (iv < 0) then
316  write(err_msg,*) 'ufo_geovals_assign: var ', trim(self%variables(jv)), ' doesnt exist in rhs'
317  call abor1_ftn(trim(err_msg))
318  endif
319  if (self%geovals(jv)%nval /= rhs%geovals(iv)%nval) then
320  write(err_msg,*) 'ufo_geovals_assign: nvals for var ', trim(self%variables(jv)), ' are different in lhs and rhs'
321  call abor1_ftn(trim(err_msg))
322  endif
323  do jo=1,self%nlocs
324  do jz = 1, self%geovals(jv)%nval
325  self%geovals(jv)%vals(jz,jo) = rhs%geovals(iv)%vals(jz,jo)
326  enddo
327  enddo
328 enddo
329 
330 end subroutine ufo_geovals_assign
331 
332 ! ------------------------------------------------------------------------------
333 subroutine ufo_geovals_reorderzdir(self, varname, zdir)
334 implicit none
335 type(ufo_geovals),intent(inout) :: self
336 character(len=*), intent(in) :: varname
337 character(len=*), intent(in) :: zdir
338 
339 type(ufo_geovals) :: selfclone
340 type(ufo_geoval), pointer :: geoval
341 character(max_string) :: err_msg
342 integer:: iobs, ivar, ival, kval
343 logical :: do_flip = .false. !< .true. if all the ufo_geoval arrays inside geovals
344 
345 if (.not. self%linit) then
346  call abor1_ftn("ufo_geovals_reorderzdir: geovals not allocated")
347 endif
348 
349 ! Get vertical coordinate variable
350 call ufo_geovals_get_var(self, varname, geoval)
351 if (associated(geoval)) then
352  print *, 'ufo_geovals_reorderzdir: geoval vertical coordinate variable ', trim(varname), geoval%nval, geoval%nlocs
353 else
354  write(err_msg, *) 'ufo_geovals_reorderzdir: geoval vertical coordinate variable ', trim(varname), ' doesnt exist'
355 endif
356 
357 ! Check if reorder variables is necessary based on the direction defined by zdir
358 if ((zdir == "bottom2top" .and. geoval%vals(1,1) < geoval%vals(geoval%nval,1)) .or. &
359  (zdir == "top2bottom" .and. geoval%vals(1,1) > geoval%vals(geoval%nval,1))) then
360  do_flip = .true.
361  print *, 'ufo_geovals_reorderzdir: do_flip ', do_flip
362 else if (zdir /= "bottom2top" .or. zdir /= "top2bottom") then
363  write(err_msg, *) 'ufo_geovals_reorderzdir: z-coordinate direction ', trim(zdir), ' not defined'
364 else
365  print *, 'no need to reorder variables in vertical direction (zdir) do_flip ', do_flip
366  return
367 endif
368 
369 call ufo_geovals_copy(self, selfclone)
370 
371 if (do_flip) then
372  do ivar = 1, self%nvar
373  do ival = 1, self%geovals(ivar)%nval
374  kval = self%geovals(ivar)%nval - ival + 1
375  self%geovals(ivar)%vals(ival,:) = selfclone%geovals(ivar)%vals(kval,:)
376  enddo
377  enddo
378 endif
379 
380 call ufo_geovals_delete(selfclone)
381 
382 end subroutine ufo_geovals_reorderzdir
383 
384 ! ------------------------------------------------------------------------------
385 !> Sum of two GeoVaLs objects
386 
387 subroutine ufo_geovals_add(self, other)
388 implicit none
389 type(ufo_geovals), intent(inout) :: self
390 type(ufo_geovals), intent(in) :: other
391 integer :: jv, jo, jz
392 integer :: iv
393 character(max_string) :: err_msg
394 
395 if (.not. self%linit) then
396  call abor1_ftn("ufo_geovals_add: geovals not allocated")
397 endif
398 if (.not. other%linit) then
399  call abor1_ftn("ufo_geovals_add: geovals not allocated")
400 endif
401 
402 if (self%nlocs /= other%nlocs) then
403  call abor1_ftn("ufo_geovals_add: nlocs different between lhs and rhs")
404 endif
405 
406 do jv=1,self%nvar
407  iv = ufo_vars_getindex(other%variables, self%variables(jv))
408  if (iv .ne. -1) then !Only add if exists in RHS
409  if (self%geovals(jv)%nval /= other%geovals(iv)%nval) then
410  write(err_msg,*) 'ufo_geovals_add: nvals for var ', trim(self%variables(jv)), ' are different in lhs and rhs'
411  call abor1_ftn(trim(err_msg))
412  endif
413  do jo=1,self%nlocs
414  do jz = 1, self%geovals(jv)%nval
415  self%geovals(jv)%vals(jz,jo) = self%geovals(jv)%vals(jz,jo) + other%geovals(iv)%vals(jz,jo)
416  enddo
417  enddo
418  endif
419 enddo
420 
421 end subroutine ufo_geovals_add
422 
423 ! ------------------------------------------------------------------------------
424 !> Difference between two GeoVaLs objects
425 
426 subroutine ufo_geovals_diff(self, other)
427 implicit none
428 type(ufo_geovals), intent(inout) :: self
429 type(ufo_geovals), intent(in) :: other
430 integer :: jv, jo, jz
431 integer :: iv
432 character(max_string) :: err_msg
433 
434 if (.not. self%linit) then
435  call abor1_ftn("ufo_geovals_diff: geovals not allocated")
436 endif
437 if (.not. other%linit) then
438  call abor1_ftn("ufo_geovals_diff: geovals not allocated")
439 endif
440 
441 if (self%nlocs /= other%nlocs) then
442  call abor1_ftn("ufo_geovals_diff: nlocs different between lhs and rhs")
443 endif
444 
445 do jv=1,self%nvar
446  iv = ufo_vars_getindex(other%variables, self%variables(jv))
447  if (iv .ne. -1) then !Only subtract if exists in RHS
448  if (self%geovals(jv)%nval /= other%geovals(iv)%nval) then
449  write(err_msg,*) 'ufo_geovals_diff: nvals for var ', trim(self%variables(jv)), ' are different in lhs and rhs'
450  call abor1_ftn(trim(err_msg))
451  endif
452  do jo=1,self%nlocs
453  do jz = 1, self%geovals(jv)%nval
454  self%geovals(jv)%vals(jz,jo) = self%geovals(jv)%vals(jz,jo) - other%geovals(iv)%vals(jz,jo)
455  enddo
456  enddo
457  endif
458 enddo
459 
460 end subroutine ufo_geovals_diff
461 
462 ! ------------------------------------------------------------------------------
463 !> Schur product of two GeoVaLs objects
464 
465 subroutine ufo_geovals_schurmult(self, other)
466 implicit none
467 type(ufo_geovals), intent(inout) :: self
468 type(ufo_geovals), intent(in) :: other
469 integer :: jv, jo, jz
470 integer :: iv
471 character(max_string) :: err_msg
472 
473 if (.not. self%linit) then
474  call abor1_ftn("ufo_geovals_schurmult: geovals not allocated")
475 endif
476 if (.not. other%linit) then
477  call abor1_ftn("ufo_geovals_schurmult: geovals not allocated")
478 endif
479 
480 if (self%nlocs /= other%nlocs) then
481  call abor1_ftn("ufo_geovals_schurmult: nlocs different between lhs and rhs")
482 endif
483 
484 do jv=1,self%nvar
485  iv = ufo_vars_getindex(other%variables, self%variables(jv))
486  if (iv .ne. -1) then !Only mult if exists in RHS
487  if (self%geovals(jv)%nval /= other%geovals(iv)%nval) then
488  write(err_msg,*) 'ufo_geovals_schurmult: nvals for var ', trim(self%variables(jv)), ' are different in lhs and rhs'
489  call abor1_ftn(trim(err_msg))
490  endif
491  do jo=1,self%nlocs
492  do jz = 1, self%geovals(jv)%nval
493  self%geovals(jv)%vals(jz,jo) = self%geovals(jv)%vals(jz,jo) * other%geovals(iv)%vals(jz,jo)
494  enddo
495  enddo
496  endif
497 enddo
498 
499 end subroutine ufo_geovals_schurmult
500 
501 ! ------------------------------------------------------------------------------
502 !> Copy one GeoVaLs object into another
503 !!
504 
505 subroutine ufo_geovals_copy(self, other)
506 implicit none
507 type(ufo_geovals), intent(in) :: self
508 type(ufo_geovals), intent(inout) :: other
509 integer :: jv
510 
511 if (.not. self%linit) then
512  call abor1_ftn("ufo_geovals_copy: geovals not defined")
513 endif
514 
515 call ufo_geovals_delete(other)
516 
517 other%nlocs = self%nlocs
518 other%nvar = self%nvar
519 allocate(other%variables(other%nvar))
520 other%variables(:) = self%variables(:)
521 
522 allocate(other%geovals(other%nvar))
523 do jv = 1, other%nvar
524  other%geovals(jv)%nval = self%geovals(jv)%nval
525  other%geovals(jv)%nlocs = self%geovals(jv)%nlocs
526  allocate(other%geovals(jv)%vals(other%geovals(jv)%nval, other%geovals(jv)%nlocs))
527  other%geovals(jv)%vals(:,:) = self%geovals(jv)%vals(:,:)
528 enddo
529 
530 other%missing_value = self%missing_value
531 other%linit = .true.
532 
533 end subroutine ufo_geovals_copy
534 
535 ! ------------------------------------------------------------------------------
536 !> Copy one location from GeoVaLs into a new object
537 !!
538 
539 subroutine ufo_geovals_copy_one(self, other, loc_index)
540 implicit none
541 type(ufo_geovals), intent(inout) :: self !> GeoVaLs for one location
542 type(ufo_geovals), intent(in) :: other !> GeoVaLs for many location
543 integer, intent(in) :: loc_index !> Index of the location in the "other" geoval
544 integer :: jv
545 
546 if (.not. other%linit) then
547  call abor1_ftn("ufo_geovals_copy_one: geovals not defined")
548 endif
549 
550 call ufo_geovals_delete(self)
551 
552 self%nlocs = 1
553 self%nvar = other%nvar
554 allocate(self%variables(self%nvar))
555 self%variables(:) = other%variables(:)
556 
557 allocate(self%geovals(self%nvar))
558 do jv = 1, self%nvar
559  self%geovals(jv)%nval = other%geovals(jv)%nval
560  self%geovals(jv)%nlocs = 1
561  allocate(self%geovals(jv)%vals(self%geovals(jv)%nval, self%geovals(jv)%nlocs))
562  self%geovals(jv)%vals(:,self%nlocs) = other%geovals(jv)%vals(:,loc_index)
563 enddo
564 
565 self%missing_value = other%missing_value
566 self%linit = .true.
567 
568 end subroutine ufo_geovals_copy_one
569 
570 ! ------------------------------------------------------------------------------
571 !> Initialize a GeoVaLs object based on an analytic state
572 !!
573 !! \details **ufo_geovals_analytic_init_c()** takes an existing ufo::GeoVaLs object
574 !! and fills in values based on one of several analytic solutions. This initialization
575 !! is intended to be used with the **TestStateInterpolation()** test; see there for
576 !! further information.
577 !!
578 !! Currently implemented options for analytic_init include:
579 !! * dcmip-test-1-1: 3D deformational flow
580 !! * dcmip-test-1-2: 3D Hadley-like meridional circulation
581 !! * dcmip-test-3-1: Non-orographic gravity waves on a small planet
582 !! * dcmip-test-4-0: Baroclinic instability
583 !!
584 !! \warning Currently only temperature is implemented. For variables other than
585 !! temperature, the input GeoVaLs object is not changed. This effectively
586 !! disables the interpolation test for that variable by setting the normalized
587 !! error to zero.
588 !!
589 !! \warning Currently there is no conversion between temperature and virtual
590 !! temperature
591 !!
592 !! \date May, 2018: Created by M. Miesch (JCSDA)
593 !! \date June, 2018: Added dcmip-test-4.0 (M. Miesch, JCSDA)
594 !!
595 !! \sa test::TestStateInterpolation()
596 !!
597 
598 subroutine ufo_geovals_analytic_init(self, locs, ic)
599 use ufo_locs_mod, only : ufo_locs
600 use dcmip_initial_conditions_test_1_2_3, only : test1_advection_deformation, &
601  test1_advection_hadley, test3_gravity_wave
602 use dcmip_initial_conditions_test_4, only : test4_baroclinic_wave
603 
604 implicit none
605 type(ufo_geovals), intent(inout) :: self
606 type(ufo_locs), intent(in) :: locs
607 character(*), intent(in) :: ic
608 
609 real(kind_real) :: pi = acos(-1.0_kind_real)
610 real(kind_real) :: deg_to_rad,rlat, rlon
611 real(kind_real) :: p0, kz, u0, v0, w0, t0, phis0, ps0, rho0, hum0
612 real(kind_real) :: q1, q2, q3, q4
613 integer :: ivar, iloc, ival
614 
615 if (.not. self%linit) then
616  call abor1_ftn("ufo_geovals_analytic_init: geovals not defined")
617 endif
618 
619 ! The last variable should be the ln pressure coordinate. That's
620 ! where we get the height information for the analytic init
621 if (trim(self%variables(self%nvar)) /= trim(var_prs)) then
622  call abor1_ftn("ufo_geovals_analytic_init: pressure coordinate not defined")
623 endif
624 
625 deg_to_rad = pi/180.0_kind_real
626 
627 do ivar = 1, self%nvar-1
628 
629  do iloc = 1, self%geovals(ivar)%nlocs
630 
631  ! convert lat and lon to radians
632  rlat = deg_to_rad * locs%lat(iloc)
633  rlon = deg_to_rad*modulo(locs%lon(iloc)+180.0_kind_real,360.0_kind_real) - pi
634 
635  do ival = 1, self%geovals(ivar)%nval
636 
637  ! obtain height from the existing GeoVaLs object, which should be an
638  ! output of the State::getValues() method
639  ! should be delivered in units of Pa
640  p0 = self%geovals(self%nvar)%vals(ival,iloc)
641 
642  init_option: select case (trim(ic))
643 
644  case ("dcmip-test-1-1")
645 
646  call test1_advection_deformation(rlon,rlat,p0,kz,0,u0,v0,w0,&
647  t0,phis0,ps0,rho0,hum0,q1,q2,q3,q4)
648 
649  case ("dcmip-test-1-2")
650 
651  call test1_advection_hadley(rlon,rlat,p0,kz,0,u0,v0,w0,&
652  t0,phis0,ps0,rho0,hum0,q1)
653 
654  case ("dcmip-test-3-1")
655 
656  call test3_gravity_wave(rlon,rlat,p0,kz,0,u0,v0,w0,&
657  t0,phis0,ps0,rho0,hum0)
658 
659  case ("dcmip-test-4-0")
660 
661  call test4_baroclinic_wave(0,1.0_kind_real,rlon,rlat,p0,kz,0,u0,v0,w0,&
662  t0,phis0,ps0,rho0,hum0,q1,q2)
663 
664  case default
665 
666  call abor1_ftn("ufo_geovals_analytic_init: invalid analytic_init")
667 
668  end select init_option
669 
670  ! currently only temperture is implemented
671  if (trim(self%variables(ivar)) == trim(var_tv)) then
672  ! Warning: we may need a conversion from temperature to
673  ! virtual temperture here
674  self%geovals(ivar)%vals(ival,iloc) = t0
675  endif
676 
677  enddo
678  enddo
679 enddo
680 
681 end subroutine ufo_geovals_analytic_init
682 
683 ! ------------------------------------------------------------------------------
684 !> Normalization of one GeoVaLs object by another
685 !!
686 !! \details This is a normalization operator that first computes the normalization
687 !! factor for each variable based on the rms amplitude of that variable across
688 !! all locations in the reference GeoVaLs object (other). Then each element of
689 !! the input GeoVals object (self) is divided by these normalization factors.
690 !! The operation is done in place. So, after execution, the input GeoVaLs
691 !! object will be nondimensional.
692 !!
693 !! \warning If the reference variable is identially zero across all
694 !! locations, then the result of this operatution is set to zero for that
695 !! variable. This is to used to bypass variables that do not have a reference
696 !! value in the State interpolation test.
697 !!
698 
699 subroutine ufo_geovals_normalize(self, other)
700 implicit none
701 type(ufo_geovals), intent(inout) :: self !> Input GeoVaLs object (LHS)
702 type(ufo_geovals), intent(in) :: other !> Reference GeoVaLs object (RHS)
703 integer :: jv, jo, jz
704 real(kind_real) :: over_nloc, vrms, norm
705 
706 if (.not. self%linit) then
707  call abor1_ftn("ufo_geovals_normalize: geovals not allocated")
708 endif
709 if (.not. other%linit) then
710  call abor1_ftn("ufo_geovals_normalize: geovals not allocated")
711 endif
712 if (self%nvar /= other%nvar) then
713  call abor1_ftn("ufo_geovals_normalize: reference geovals object must have the same variables as the original")
714 endif
715 
716 
717 do jv=1,self%nvar
718 
719  !> Compute normalization factors for the errors based on the rms amplitude of
720  !! each variable across all of the selected locations. Use the "other" GeoVaLs
721  !! object as a reference, since this may be the exact analytic answer
722 
723  over_nloc = 1.0_kind_real / &
724  (real(other%nlocs,kind_real)*real(other%geovals(jv)%nval,kind_real))
725 
726  vrms = 0.0_kind_real
727  do jo = 1, other%nlocs
728  do jz = 1, other%geovals(jv)%nval
729  vrms = vrms + other%geovals(jv)%vals(jz,jo)**2
730  enddo
731  enddo
732 
733  if (vrms > 0.0_kind_real) then
734  norm = 1.0_kind_real / sqrt(vrms*over_nloc)
735  else
736  norm = 0.0_kind_real
737  endif
738 
739  ! Now loop through the LHS locations to compute the normalized value
740  do jo=1,self%nlocs
741  do jz = 1, self%geovals(jv)%nval
742  self%geovals(jv)%vals(jz,jo) = norm*self%geovals(jv)%vals(jz,jo)
743  enddo
744  enddo
745 enddo
746 
747 end subroutine ufo_geovals_normalize
748 
749 ! ------------------------------------------------------------------------------
750 
751 subroutine ufo_geovals_dotprod(self, other, gprod, f_comm)
752 implicit none
753 real(kind_real), intent(inout) :: gprod
754 type(ufo_geovals), intent(in) :: self, other
755 integer :: ivar, iobs, ival, nval
756 real(kind_real) :: prod
757 
758 type(fckit_mpi_comm), intent(in) :: f_comm
759 
760 if (.not. self%linit) then
761  call abor1_ftn("ufo_geovals_dotprod: geovals not allocated")
762 endif
763 
764 if (.not. other%linit) then
765  call abor1_ftn("ufo_geovals_dotprod: geovals not allocated")
766 endif
767 
768 ! just something to put in (dot product of the 1st var and 1st element in the profile
769 prod=0.0
770 do ivar = 1, self%nvar
771  nval = self%geovals(ivar)%nval
772  do ival = 1, nval
773  do iobs = 1, self%nlocs
774  if ((self%geovals(ivar)%vals(ival,iobs) .ne. self%missing_value) .and. &
775  (other%geovals(ivar)%vals(ival,iobs) .ne. self%missing_value)) then
776  prod = prod + self%geovals(ivar)%vals(ival,iobs) * &
777  other%geovals(ivar)%vals(ival,iobs)
778  endif
779  enddo
780  enddo
781 enddo
782 
783 !Get global dot product
784 call f_comm%allreduce(prod,gprod,fckit_mpi_sum())
785 
786 end subroutine ufo_geovals_dotprod
787 
788 !-------------------------------------------------------------------------------
789 subroutine ufo_geovals_reset_sec_arg(self, other, nlocs)
790 implicit none
791 type(ufo_geovals), intent(in) :: self
792 type(ufo_geovals), intent(inout) :: other
793 integer, intent(in) :: nlocs
794 integer :: ivar
795 
796 if (other%linit) call abor1_ftn("ufo_geovals_reset_sec_arg: other already have data")
797 
798 other%nlocs = nlocs
799 other%nvar = self%nvar
800 other%missing_value = self%missing_value
801 allocate(other%variables(self%nvar))
802 allocate(other%geovals(self%nvar))
803 do ivar = 1, self%nvar
804  other%variables(ivar) = self%variables(ivar)
805  other%geovals(ivar)%nlocs = nlocs
806  other%geovals(ivar)%nval = self%geovals(ivar)%nval
807  allocate(other%geovals(ivar)%vals(self%geovals(ivar)%nval, nlocs))
808  other%geovals(ivar)%vals(:,:) = 0.0
809 enddo
810 other%linit = .false.
811 
812 end subroutine ufo_geovals_reset_sec_arg
813 ! ------------------------------------------------------------------------------
814 
815 subroutine ufo_geovals_split(self, other1, other2)
816 implicit none
817 type(ufo_geovals), intent(in) :: self
818 type(ufo_geovals), intent(inout) :: other1
819 type(ufo_geovals), intent(inout) :: other2
820 
821 integer :: ivar, iobs
822 
823 if (.not. self%linit) &
824  call abor1_ftn("ufo_geovals_split: geovals self is not allocated or has no data")
825 
826 if (other1%linit .or. other2%linit) &
827  call abor1_ftn("ufo_geovals_split: geovals other1 or other2 already have data")
828 
829 call ufo_geovals_delete(other1)
830 call ufo_geovals_delete(other2)
831 call ufo_geovals_reset_sec_arg(self, other1, self%nlocs/2)
832 call ufo_geovals_reset_sec_arg(self, other2, self%nlocs - self%nlocs/2)
833 
834 do ivar = 1, self%nvar
835  do iobs = 1, self%nlocs/2
836  other1%geovals(ivar)%vals(:,iobs) = self%geovals(ivar)%vals(:,iobs)
837  enddo
838  do iobs = self%nlocs/2 + 1, self%nlocs
839  other2%geovals(ivar)%vals(:,iobs - self%nlocs/2) = self%geovals(ivar)%vals(:,iobs)
840  enddo
841 enddo
842 other1%linit = .true.
843 other2%linit = .true.
844 
845 end subroutine ufo_geovals_split
846 ! ------------------------------------------------------------------------------
847 
848 subroutine ufo_geovals_merge(self, other1, other2)
849 implicit none
850 type(ufo_geovals), intent(inout) :: self
851 type(ufo_geovals), intent(in) :: other1
852 type(ufo_geovals), intent(in) :: other2
853 
854 integer :: ivar, iobs
855 
856 if ((.not. other1%linit) .or. (.not. other2%linit)) &
857  call abor1_ftn("ufo_geovals_merge: geovals other1 or other2 is not allocated or has no data")
858 
859 call ufo_geovals_delete(self)
860 call ufo_geovals_reset_sec_arg(other1, self, other1%nlocs + other2%nlocs)
861 
862 do ivar = 1, self%nvar
863  do iobs = 1, other1%nlocs
864  self%geovals(ivar)%vals(:,iobs) = other1%geovals(ivar)%vals(:,iobs)
865  enddo
866  do iobs = other1%nlocs + 1, self%nlocs
867  self%geovals(ivar)%vals(:,iobs) = &
868  other2%geovals(ivar)%vals(:,iobs - other1%nlocs)
869  enddo
870 enddo
871 self%linit = .true.
872 
873 end subroutine ufo_geovals_merge
874 ! ------------------------------------------------------------------------------
875 
876 subroutine ufo_geovals_minmaxavg(self, kobs, kvar, pmin, pmax, prms)
877 implicit none
878 integer, intent(inout) :: kobs
879 integer, intent(in) :: kvar
880 real(kind_real), intent(inout) :: pmin, pmax, prms
881 type(ufo_geovals), intent(in) :: self
882 integer :: jo, jz, jv
883 
884 jv = kvar+1
885 kobs = 0
886 pmin = huge(pmin)
887 pmax = -huge(pmax)
888 prms = 0.0_kind_real
889 do jo = 1, self%nlocs
890  do jz = 1, self%geovals(jv)%nval
891  if (self%geovals(jv)%vals(jz,jo) .ne. self%missing_value) then
892  kobs = kobs + 1
893  if (self%geovals(jv)%vals(jz,jo) < pmin) pmin = self%geovals(jv)%vals(jz,jo)
894  if (self%geovals(jv)%vals(jz,jo) > pmax) pmax = self%geovals(jv)%vals(jz,jo)
895  prms = prms + self%geovals(jv)%vals(jz,jo) * self%geovals(jv)%vals(jz,jo)
896  endif
897  enddo
898 enddo
899 if (kobs > 0) prms = sqrt(prms/real(kobs,kind_real))
900 
901 end subroutine ufo_geovals_minmaxavg
902 
903 ! ------------------------------------------------------------------------------
904 !> Location where the summed geovals value is maximum
905 !!
906 !! \details This routine computes the rms value over the vertical profile for
907 !! each location and observation then returns the location number and the
908 !! variable number where this rms value is maximum. Intended for use with
909 !! the State interpotation test in which the input GeoVaLs object is a
910 !! nondimensional, positive-definite error measurement.
911 
912 subroutine ufo_geovals_maxloc(self, mxval, iobs, ivar)
913 implicit none
914 real(kind_real), intent(inout) :: mxval
915 integer, intent(inout) :: iobs, ivar
916 
917 type(ufo_geovals), intent(in) :: self
918 real(kind_real) :: vrms
919 integer :: jv, jo, jz
920 
921 if (.not. self%linit) then
922  call abor1_ftn("ufo_geovals_maxloc: geovals not allocated")
923 endif
924 
925 mxval = 0.0_kind_real
926 iobs = 1
927 ivar = 1
928 
929 do jv = 1,self%nvar
930  do jo = 1, self%nlocs
931 
932  vrms = 0.0_kind_real
933  do jz = 1, self%geovals(jv)%nval
934  vrms = vrms + self%geovals(jv)%vals(jz,jo)**2
935  enddo
936 
937  if ( self%geovals(jv)%nval > 0 ) then
938  vrms = sqrt(vrms/real(self%geovals(jv)%nval,kind_real))
939  end if
940 
941  if (vrms > mxval) then
942  mxval = vrms
943  iobs = jo
944  ivar = jv
945  endif
946 
947  enddo
948 enddo
949 
950 end subroutine ufo_geovals_maxloc
951 
952 ! ------------------------------------------------------------------------------
953 
954 subroutine ufo_geovals_read_netcdf(self, filename, loc_multiplier, c_obspace, vars)
955 use netcdf
956 use oops_variables_mod
957 implicit none
958 type(ufo_geovals), intent(inout) :: self
959 character(max_string), intent(in) :: filename
960 integer, intent(in) :: loc_multiplier
961 type(c_ptr), intent(in) :: c_obspace
962 type(oops_variables), intent(in) :: vars
963 
964 integer :: nlocs, gv_all_nlocs, nlocs_var
965 integer :: nval
966 integer :: obs_nlocs
967 integer :: obs_all_nlocs
968 integer :: iloc
969 integer :: jloc, jloc_start, jloc_end
970 integer :: iloc_new
971 
972 integer :: ncid, dimid, varid, vartype, ndims
973 integer, dimension(3) :: dimids
974 integer :: ivar
975 integer :: ierr
976 
977 character(max_string) :: err_msg
978 character(len=30) :: obs_nlocs_str
979 character(len=30) :: geo_nlocs_str
980 
981 integer(c_size_t), allocatable, dimension(:) :: dist_indx
982 integer(c_size_t), allocatable, dimension(:) :: obs_dist_indx
983 
984 real, allocatable :: field2d(:,:), field1d(:)
985 
986 ! open netcdf file
987 call check('nf90_open', nf90_open(trim(filename),nf90_nowrite,ncid))
988 
989 ! find how many locs are in the file
990 ierr = nf90_inq_dimid(ncid, "nlocs", dimid)
991 if(ierr /= nf90_noerr) then
992  write(err_msg,*) "Error: Dimension nlocs not found in ", trim(filename)
993  call abor1_ftn(err_msg)
994 endif
995 call check('nf90_inq_dimid', nf90_inq_dimid(ncid, "nlocs", dimid))
996 call check('nf90_inquire_dimension', nf90_inquire_dimension(ncid, dimid, len = gv_all_nlocs))
997 
998 !> round-robin distribute the observations to PEs
999 !> Calculate how many obs. on each PE
1000 obs_all_nlocs = obsspace_get_gnlocs(c_obspace)
1001 obs_nlocs = obsspace_get_nlocs(c_obspace)
1002 allocate(obs_dist_indx(obs_nlocs))
1003 call obsspace_get_index(c_obspace, obs_dist_indx)
1004 
1005 ! loc_multiplier specifies how many locations in the geovals file per
1006 ! single location in the obs file. There needs to be at least
1007 ! loc_multiplier * obs_all_nlocs locations in the geovals file.
1008 
1009 if (gv_all_nlocs .lt. (loc_multiplier * obs_all_nlocs)) then
1010  write(obs_nlocs_str, *) loc_multiplier * obs_all_nlocs
1011  write(geo_nlocs_str, *) gv_all_nlocs
1012  write(err_msg,'(7a)') &
1013  "Error: Number of locations in the geovals file (", &
1014  trim(adjustl(geo_nlocs_str)), ") must be greater than or equal to ", &
1015  "the product of loc_multiplier and number of locations in the ", &
1016  "obs file (", trim(adjustl(obs_nlocs_str)), ")"
1017  call abor1_ftn(err_msg)
1018 endif
1019 
1020 ! We have enough locations in the geovals file to cover the span of the
1021 ! number of locations in the obs file. Generate the dist_indx according
1022 ! to the loc_multiplier and obs_nlocs values.
1023 if (loc_multiplier >= 0) then
1024  nlocs = loc_multiplier * obs_nlocs
1025  allocate(dist_indx(nlocs))
1026  iloc_new = 1
1027  do iloc = 1,obs_nlocs
1028  jloc_start = ((obs_dist_indx(iloc) - 1) * loc_multiplier) + 1
1029  jloc_end = obs_dist_indx(iloc) * loc_multiplier
1030  do jloc = jloc_start, jloc_end
1031  dist_indx(iloc_new) = jloc
1032  iloc_new = iloc_new + 1
1033  enddo
1034  enddo
1035 else
1036  nlocs = - loc_multiplier * obs_nlocs
1037  allocate(dist_indx(nlocs))
1038  iloc_new = 1
1039  do jloc = 1, - loc_multiplier
1040  do iloc = 1, obs_nlocs
1041  dist_indx(iloc_new) = obs_dist_indx(iloc) + (jloc - 1) * obs_all_nlocs
1042  iloc_new = iloc_new + 1
1043  enddo
1044  enddo
1045 end if
1046 
1047 ! allocate geovals structure
1048 call ufo_geovals_setup(self, vars, nlocs)
1049 
1050 do ivar = 1, self%nvar
1051 
1052  ierr = nf90_inq_varid(ncid, self%variables(ivar), varid)
1053  if(ierr /= nf90_noerr) then
1054  write(err_msg,*) "Error: Variable ", trim(self%variables(ivar)), " not found in ", trim(filename)
1055  call abor1_ftn(err_msg)
1056  endif
1057 
1058  call check('nf90_inquire_variable', nf90_inquire_variable(ncid, varid, xtype = vartype, &
1059  ndims = ndims, dimids = dimids))
1060  !> read 1d variable
1061  if (ndims == 1) then
1062  call check('nf90_inquire_dimension', nf90_inquire_dimension(ncid, dimids(1), len = nlocs_var))
1063  if (nlocs_var /= gv_all_nlocs) then
1064  call abor1_ftn('ufo_geovals_read_netcdf: var dim /= gv_all_nlocs')
1065  endif
1066  nval = 1
1067  !> allocate geoval for this variable
1068  self%geovals(ivar)%nval = nval
1069  allocate(self%geovals(ivar)%vals(nval,nlocs))
1070 
1071  allocate(field1d(nlocs_var))
1072  call check('nf90_get_var', nf90_get_var(ncid, varid, field1d))
1073  self%geovals(ivar)%vals(1,:) = field1d(dist_indx)
1074  deallocate(field1d)
1075  !> read 2d variable
1076  elseif (ndims == 2) then
1077  call check('nf90_inquire_dimension', nf90_inquire_dimension(ncid, dimids(1), len = nval))
1078  call check('nf90_inquire_dimension', nf90_inquire_dimension(ncid, dimids(2), len = nlocs_var))
1079  if (nlocs_var /= gv_all_nlocs) then
1080  call abor1_ftn('ufo_geovals_read_netcdf: var dim /= gv_all_nlocs')
1081  endif
1082  !> allocate geoval for this variable
1083  self%geovals(ivar)%nval = nval
1084  allocate(self%geovals(ivar)%vals(nval,nlocs))
1085  allocate(field2d(nval, nlocs_var))
1086  call check('nf90_get_var', nf90_get_var(ncid, varid, field2d))
1087  self%geovals(ivar)%vals(:,:) = field2d(:,dist_indx)
1088  deallocate(field2d)
1089  !> only 1d & 2d vars
1090  else
1091  call abor1_ftn('ufo_geovals_read_netcdf: can only read 1d and 2d fields')
1092  endif
1093 
1094  ! set the missing value equal to IODA missing_value
1095  where (self%geovals(ivar)%vals > 1.0e08) self%geovals(ivar)%vals = self%missing_value
1096 
1097 enddo
1098 
1099 if (allocated(dist_indx)) deallocate(dist_indx)
1100 if (allocated(obs_dist_indx)) deallocate(obs_dist_indx)
1101 
1102 self%linit = .true.
1103 
1104 call check('nf90_close', nf90_close(ncid))
1105 
1106 end subroutine ufo_geovals_read_netcdf
1107 
1108 ! ------------------------------------------------------------------------------
1109 subroutine ufo_geovals_write_netcdf(self, filename)
1110 use netcdf
1111 implicit none
1112 type(ufo_geovals), intent(inout) :: self
1113 character(max_string), intent(in) :: filename
1114 
1115 integer :: i
1116 integer :: ncid, dimid_nlocs, dimid_nval, dims(2)
1117 integer, allocatable :: ncid_var(:)
1118 
1119 allocate(ncid_var(self%nvar))
1120 
1121 call check('nf90_create', nf90_create(trim(filename),nf90_hdf5,ncid))
1122 call check('nf90_def_dim', nf90_def_dim(ncid,'nlocs',self%nlocs, dimid_nlocs))
1123 dims(2) = dimid_nlocs
1124 
1125 do i = 1, self%nvar
1126  call check('nf90_def_dim', &
1127  nf90_def_dim(ncid,trim(self%variables(i))//"_nval",self%geovals(i)%nval, dimid_nval))
1128  dims(1) = dimid_nval
1129  call check('nf90_def_var', &
1130  nf90_def_var(ncid,trim(self%variables(i)),nf90_float,dims,ncid_var(i)))
1131 enddo
1132 
1133 call check('nf90_enddef', nf90_enddef(ncid))
1134 
1135 do i = 1, self%nvar
1136  call check('nf90_put_var', nf90_put_var(ncid,ncid_var(i),self%geovals(i)%vals(:,:)))
1137 enddo
1138 
1139 call check('nf90_close', nf90_close(ncid))
1140 deallocate(ncid_var)
1141 
1142 end subroutine ufo_geovals_write_netcdf
1143 
1144 ! ------------------------------------------------------------------------------
1145 subroutine check(action, status)
1146 use netcdf, only: nf90_noerr, nf90_strerror
1147 implicit none
1148 
1149 integer, intent (in) :: status
1150 character (len=*), intent (in) :: action
1151 character(max_string) :: err_msg
1152 
1153 if(status /= nf90_noerr) then
1154  write(err_msg,*) "During action: ", trim(action), ", received error: ", trim(nf90_strerror(status))
1155  call abor1_ftn(err_msg)
1156 end if
1157 
1158 end subroutine check
1159 
1160 ! ------------------------------------------------------------------------------
1161 
1162 subroutine ufo_geovals_print(self, iobs)
1163 implicit none
1164 type(ufo_geovals), intent(in) :: self
1165 integer, intent(in) :: iobs
1166 
1167 type(ufo_geoval), pointer :: geoval
1168 character(MAXVARLEN) :: varname
1169 integer :: ivar
1170 
1171 do ivar = 1, self%nvar
1172  varname = self%variables(ivar)
1173  call ufo_geovals_get_var(self, varname, geoval)
1174  if (associated(geoval)) then
1175  print *, 'geoval test: ', trim(varname), geoval%nval, geoval%vals(:,iobs)
1176  else
1177  print *, 'geoval test: ', trim(varname), ' doesnt exist'
1178  endif
1179 enddo
1180 
1181 end subroutine ufo_geovals_print
1182 
1183 ! ------------------------------------------------------------------------------
1184 
1185 end module ufo_geovals_mod
ufo_geovals_mod::ufo_geovals_add
subroutine, public ufo_geovals_add(self, other)
Sum of two GeoVaLs objects.
Definition: ufo_geovals_mod.F90:388
ufo_avgkernel_mod::max_string
integer, parameter max_string
Definition: ufo_avgkernel_mod.F90:17
ufo_geovals_mod::ufo_geovals_default_constr
subroutine, public ufo_geovals_default_constr(self)
Definition: ufo_geovals_mod.F90:68
ufo_geovals_mod::ufo_geovals_assign
subroutine, public ufo_geovals_assign(self, rhs)
Definition: ufo_geovals_mod.F90:295
ufo_geovals_mod::ufo_geovals_diff
subroutine, public ufo_geovals_diff(self, other)
Difference between two GeoVaLs objects.
Definition: ufo_geovals_mod.F90:427
ufo_geovals_mod::check
subroutine check(action, status)
Definition: ufo_geovals_mod.F90:1146
ufo_geovals_mod::ufo_geovals_delete
subroutine, public ufo_geovals_delete(self)
Definition: ufo_geovals_mod.F90:107
ufo_geovals_mod::ufo_geovals_setup
subroutine, public ufo_geovals_setup(self, vars, nlocs)
Definition: ufo_geovals_mod.F90:80
ufo_geovals_mod::ufo_geovals_scalmult
subroutine, public ufo_geovals_scalmult(self, zz)
Definition: ufo_geovals_mod.F90:251
ufo_geovals_mod::ufo_geovals_reset_sec_arg
subroutine, private ufo_geovals_reset_sec_arg(self, other, nlocs)
Definition: ufo_geovals_mod.F90:790
ufo_geovals_mod::ufo_geovals_rms
subroutine, public ufo_geovals_rms(self, vrms)
Definition: ufo_geovals_mod.F90:208
ufo_geovals_mod::ufo_geovals_zero
subroutine, public ufo_geovals_zero(self)
Definition: ufo_geovals_mod.F90:176
ufo_geovals_mod::ufo_geovals_merge
subroutine, public ufo_geovals_merge(self, other1, other2)
Definition: ufo_geovals_mod.F90:849
ufo_geovals_mod::ufo_geovals_copy_one
subroutine, public ufo_geovals_copy_one(self, other, loc_index)
Copy one location from GeoVaLs into a new object.
Definition: ufo_geovals_mod.F90:540
ufo_geovals_mod::ufo_geovals_print
subroutine, public ufo_geovals_print(self, iobs)
Definition: ufo_geovals_mod.F90:1163
ufo_geovals_mod::ufo_geovals_split
subroutine, public ufo_geovals_split(self, other1, other2)
Definition: ufo_geovals_mod.F90:816
ufo_geovals_mod::ufo_geovals_random
subroutine, public ufo_geovals_random(self)
Definition: ufo_geovals_mod.F90:233
ufo_vars_mod::ufo_vars_getindex
integer function, public ufo_vars_getindex(vars, varname)
Definition: ufo_variables_mod.F90:204
ufo_geovals_mod::ufo_geovals_normalize
subroutine, public ufo_geovals_normalize(self, other)
Normalization of one GeoVaLs object by another.
Definition: ufo_geovals_mod.F90:700
ufo_geovals_mod::ufo_geovals_abs
subroutine, public ufo_geovals_abs(self)
Definition: ufo_geovals_mod.F90:192
ufo_vars_mod::var_tv
character(len=maxvarlen), parameter, public var_tv
Definition: ufo_variables_mod.F90:18
ufo_geovals_mod::ufo_geovals_dotprod
subroutine, public ufo_geovals_dotprod(self, other, gprod, f_comm)
Definition: ufo_geovals_mod.F90:752
ufo_geovals_mod
Definition: ufo_geovals_mod.F90:7
ufo_geovals_mod::ufo_geovals_profmult
subroutine, public ufo_geovals_profmult(self, nlocs, values)
Definition: ufo_geovals_mod.F90:273
ufo_geovals_mod::ufo_geovals_analytic_init
subroutine, public ufo_geovals_analytic_init(self, locs, ic)
Initialize a GeoVaLs object based on an analytic state.
Definition: ufo_geovals_mod.F90:599
ufo_geovals_mod::ufo_geovals_read_netcdf
subroutine, public ufo_geovals_read_netcdf(self, filename, loc_multiplier, c_obspace, vars)
Definition: ufo_geovals_mod.F90:955
ufo_vars_mod
Definition: ufo_variables_mod.F90:8
ufo_geovals_mod::ufo_geovals_put_var
subroutine, public ufo_geovals_put_var(self, varname, geoval, k)
Definition: ufo_geovals_mod.F90:161
ufo_geovals_mod::ufo_geovals_schurmult
subroutine, public ufo_geovals_schurmult(self, other)
Schur product of two GeoVaLs objects.
Definition: ufo_geovals_mod.F90:466
ufo_geovals_mod::ufo_geovals_minmaxavg
subroutine, public ufo_geovals_minmaxavg(self, kobs, kvar, pmin, pmax, prms)
Definition: ufo_geovals_mod.F90:877
ufo_geovals_mod::ufo_geovals_get_var
subroutine, public ufo_geovals_get_var(self, varname, geoval)
Definition: ufo_geovals_mod.F90:128
ufo_geovals_mod::ufo_geovals_maxloc
subroutine, public ufo_geovals_maxloc(self, mxval, iobs, ivar)
Location where the summed geovals value is maximum.
Definition: ufo_geovals_mod.F90:913
ufo_geovals_mod::ufo_geovals_write_netcdf
subroutine, public ufo_geovals_write_netcdf(self, filename)
Definition: ufo_geovals_mod.F90:1110
ufo_locs_mod
Fortran module handling observation locations.
Definition: ufo_locs_mod.F90:9
ufo_geovals_mod::ufo_geovals
type to hold interpolated fields required by the obs operators
Definition: ufo_geovals_mod.F90:47
ufo_geovals_mod::ufo_geoval
type to hold interpolated field for one variable, one observation
Definition: ufo_geovals_mod.F90:40
ufo_locs_mod::ufo_locs
Fortran derived type to hold observation locations.
Definition: ufo_locs_mod.F90:25
ufo_vars_mod::var_prs
character(len=maxvarlen), parameter, public var_prs
Definition: ufo_variables_mod.F90:25
ufo_geovals_mod::ufo_geovals_reorderzdir
subroutine, public ufo_geovals_reorderzdir(self, varname, zdir)
Definition: ufo_geovals_mod.F90:334
ufo_geovals_mod::ufo_geovals_copy
subroutine, public ufo_geovals_copy(self, other)
Copy one GeoVaLs object into another.
Definition: ufo_geovals_mod.F90:506