13 use fckit_mpi_module,
only: fckit_mpi_comm, fckit_mpi_sum
32 real(kind_real),
allocatable :: vals(:,:)
76 integer,
intent(in) :: nobs
84 allocate(self%geovals(self%nvar))
85 do ivar = 1, self%nvar
86 self%geovals(ivar)%nobs = nobs
87 self%geovals(ivar)%nval = 0
101 do ivar = 1, self%nvar
102 deallocate(self%geovals(ivar)%vals)
106 if (self%lalloc)
then 107 deallocate(self%geovals)
108 self%lalloc = .false.
120 character(MAXVARLEN),
intent(in) :: varname
121 type(
ufo_geoval),
pointer,
intent(inout) :: geoval
122 integer,
optional,
intent(out) :: status
124 integer :: ivar, status_
128 if (.not. self%lalloc .or. .not. self%linit)
then 137 geoval => self%geovals(ivar)
141 if(
present(status))
then 153 if (.not. self%lalloc)
then 154 call abor1_ftn(
"ufo_geovals_zero: geovals not allocated")
157 do ivar = 1,self%nvar
158 self%geovals(ivar)%nval = 1
159 allocate(self%geovals(ivar)%vals(1,self%nobs))
172 if (.not. self%lalloc)
then 173 call abor1_ftn(
"ufo_geovals_zero: geovals not allocated")
175 if (.not. self%linit)
then 176 call abor1_ftn(
"ufo_geovals_zero: geovals not initialized")
178 do ivar = 1, self%nvar
179 self%geovals(ivar)%vals(:,:) = 0.0
191 if (.not. self%lalloc)
then 192 call abor1_ftn(
"ufo_geovals_abs: geovals not allocated")
194 if (.not. self%linit)
then 195 call abor1_ftn(
"ufo_geovals_abs: geovals not initialized")
197 do ivar = 1, self%nvar
198 self%geovals(ivar)%vals = abs(self%geovals(ivar)%vals)
208 real(kind_real),
intent(inout) :: vrms
212 if (.not. self%lalloc)
then 213 call abor1_ftn(
"ufo_geovals_rms: geovals not allocated")
215 if (.not. self%linit)
then 216 call abor1_ftn(
"ufo_geovals_rms: geovals not initialized")
222 vrms = vrms + sum(self%geovals(jv)%vals(:,jo)**2)
223 n=n+self%geovals(jv)%nval
239 if (.not. self%lalloc)
then 240 call abor1_ftn(
"ufo_geovals_random: geovals not allocated")
242 if (.not. self%linit)
then 243 call abor1_ftn(
"ufo_geovals_random: geovals not initialized")
245 do ivar = 1, self%nvar
256 real(kind_real),
intent(in) :: zz
257 integer :: jv, jo, jz
259 if (.not. self%lalloc .or. .not. self%linit)
then 260 call abor1_ftn(
"ufo_geovals_scalmult: geovals not allocated")
265 do jz = 1, self%geovals(jv)%nval
266 self%geovals(jv)%vals(jz,jo) = zz * self%geovals(jv)%vals(jz,jo)
279 integer :: jv, jo, jz
281 character(max_string) :: err_msg
283 if (.not. self%lalloc .or. .not. self%linit)
then 284 call abor1_ftn(
"ufo_geovals_scalmult: geovals not allocated")
286 if (.not. rhs%lalloc .or. .not. rhs%linit)
then 287 call abor1_ftn(
"ufo_geovals_scalmult: geovals not allocated")
290 if (self%nobs /= rhs%nobs)
then 291 call abor1_ftn(
"ufo_geovals_assign: nobs different between lhs and rhs")
297 write(err_msg,*)
'ufo_geovals_assign: var ', trim(self%variables%fldnames(jv)),
' doesnt exist in rhs' 298 call abor1_ftn(trim(err_msg))
300 if (self%geovals(jv)%nval /= rhs%geovals(iv)%nval)
then 301 write(err_msg,*)
'ufo_geovals_assign: nvals for var ', trim(self%variables%fldnames(jv)),
' are different in lhs and rhs' 302 call abor1_ftn(trim(err_msg))
305 do jz = 1, self%geovals(jv)%nval
306 self%geovals(jv)%vals(jz,jo) = rhs%geovals(iv)%vals(jz,jo)
320 integer :: jv, jo, jz
322 character(max_string) :: err_msg
324 if (.not. self%lalloc .or. .not. self%linit)
then 325 call abor1_ftn(
"ufo_geovals_add: geovals not allocated")
327 if (.not. other%lalloc .or. .not. other%linit)
then 328 call abor1_ftn(
"ufo_geovals_add: geovals not allocated")
331 if (self%nobs /= other%nobs)
then 332 call abor1_ftn(
"ufo_geovals_assign: nobs different between lhs and rhs")
338 if (self%geovals(jv)%nval /= other%geovals(iv)%nval)
then 339 write(err_msg,*)
'ufo_geovals_assign: nvals for var ', trim(self%variables%fldnames(jv)),
' are different in lhs and rhs' 340 call abor1_ftn(trim(err_msg))
343 do jz = 1, self%geovals(jv)%nval
344 self%geovals(jv)%vals(jz,jo) = self%geovals(jv)%vals(jz,jo) + other%geovals(iv)%vals(jz,jo)
359 integer :: jv, jo, jz
361 character(max_string) :: err_msg
363 if (.not. self%lalloc .or. .not. self%linit)
then 364 call abor1_ftn(
"ufo_geovals_diff: geovals not allocated")
366 if (.not. other%lalloc .or. .not. other%linit)
then 367 call abor1_ftn(
"ufo_geovals_diff: geovals not allocated")
370 if (self%nobs /= other%nobs)
then 371 call abor1_ftn(
"ufo_geovals_assign: nobs different between lhs and rhs")
377 if (self%geovals(jv)%nval /= other%geovals(iv)%nval)
then 378 write(err_msg,*)
'ufo_geovals_assign: nvals for var ', trim(self%variables%fldnames(jv)),
' are different in lhs and rhs' 379 call abor1_ftn(trim(err_msg))
382 do jz = 1, self%geovals(jv)%nval
383 self%geovals(jv)%vals(jz,jo) = self%geovals(jv)%vals(jz,jo) - other%geovals(iv)%vals(jz,jo)
401 if (.not. self%lalloc .or. .not. self%linit)
then 402 call abor1_ftn(
"ufo_geovals_copy: geovals not defined")
409 other%nobs = self%nobs
410 other%nvar = self%nvar
412 allocate(other%geovals(other%nvar))
413 do jv = 1, other%nvar
414 other%geovals(jv)%nval = self%geovals(jv)%nval
415 other%geovals(jv)%nobs = self%geovals(jv)%nobs
416 allocate(other%geovals(jv)%vals(other%geovals(jv)%nval, other%geovals(jv)%nobs))
417 other%geovals(jv)%vals(:,:) = self%geovals(jv)%vals(:,:)
420 other%lalloc = .true.
462 character(*),
intent(in) :: ic
464 real(kind_real) ::
pi = acos(-1.0_kind_real)
465 real(kind_real) :: deg_to_rad,rlat, rlon
466 real(kind_real) :: p0, kz, u0, v0, w0, t0, phis0, ps0, rho0, hum0
467 real(kind_real) :: q1, q2, q3, q4
468 integer :: ivar, iloc, ival
470 if (.not. self%lalloc .or. .not. self%linit)
then 471 call abor1_ftn(
"ufo_geovals_analytic_init: geovals not defined")
476 if (trim(self%variables%fldnames(self%nvar)) /= trim(
var_prsl))
then 477 call abor1_ftn(
"ufo_geovals_analytic_init: pressure coordinate not defined")
480 deg_to_rad =
pi/180.0_kind_real
482 do ivar = 1, self%nvar-1
484 do iloc = 1, self%geovals(ivar)%nobs
487 rlat = deg_to_rad * locs%lat(iloc)
488 rlon = deg_to_rad*modulo(locs%lon(iloc)+180.0_kind_real,360.0_kind_real) -
pi 490 do ival = 1, self%geovals(ivar)%nval
495 p0 = exp(self%geovals(self%nvar)%vals(ival,iloc))*1.0e3_kind_real
497 init_option:
select case (trim(ic))
499 case (
"dcmip-test-1-1")
502 t0,phis0,ps0,rho0,hum0,q1,q2,q3,q4)
504 case (
"dcmip-test-1-2")
507 t0,phis0,ps0,rho0,hum0,q1)
509 case (
"dcmip-test-3-1")
512 t0,phis0,ps0,rho0,hum0)
514 case (
"dcmip-test-4-0")
516 call test4_baroclinic_wave(0,1.0_kind_real,rlon,rlat,p0,kz,0,u0,v0,w0,&
517 t0,phis0,ps0,rho0,hum0,q1,q2)
521 call abor1_ftn(
"ufo_geovals_analytic_init: invalid analytic_init")
523 end select init_option
526 if (trim(self%variables%fldnames(ivar)) == trim(
var_tv))
then 529 self%geovals(ivar)%vals(ival,iloc) = t0
558 integer :: jv, jo, jz
559 real(kind_real) :: over_nloc, vrms, norm
561 if (.not. self%lalloc .or. .not. self%linit)
then 562 call abor1_ftn(
"ufo_geovals_normalize: geovals not allocated")
564 if (.not. other%lalloc .or. .not. other%linit)
then 565 call abor1_ftn(
"ufo_geovals_normalize: geovals not allocated")
567 if (self%nvar /= other%nvar)
then 568 call abor1_ftn(
"ufo_geovals_normalize: reference geovals object must have the same variables as the original")
578 over_nloc = 1.0_kind_real / &
582 do jo = 1, other%nobs
583 do jz = 1, other%geovals(jv)%nval
584 vrms = vrms + other%geovals(jv)%vals(jz,jo)**2
588 if (vrms > 0.0_kind_real)
then 589 norm = 1.0_kind_real / sqrt(vrms*over_nloc)
596 do jz = 1, self%geovals(jv)%nval
597 self%geovals(jv)%vals(jz,jo) = norm*self%geovals(jv)%vals(jz,jo)
608 real(kind_real),
intent(inout) :: gprod
610 integer :: ivar, iobs, ival, nval
611 real(kind_real) :: prod
613 type(fckit_mpi_comm) :: f_comm
615 f_comm = fckit_mpi_comm()
617 if (.not. self%lalloc .or. .not. self%linit)
then 618 call abor1_ftn(
"ufo_geovals_dotprod: geovals not allocated")
621 if (.not. other%lalloc .or. .not. other%linit)
then 622 call abor1_ftn(
"ufo_geovals_dotprod: geovals not allocated")
627 do ivar = 1, self%nvar
628 nval = self%geovals(ivar)%nval
630 do iobs = 1, self%nobs
631 prod = prod + self%geovals(ivar)%vals(ival,iobs) * &
632 other%geovals(ivar)%vals(ival,iobs)
638 call f_comm%allreduce(prod,gprod,fckit_mpi_sum())
646 integer,
intent(inout) :: kobs
647 real(kind_real),
intent(inout) :: pmin, pmax, prms
651 pmin=minval(self%geovals(1)%vals)
652 pmax=maxval(self%geovals(1)%vals)
668 real(kind_real),
intent(inout) :: mxval
669 integer,
intent(inout) :: iobs, ivar
672 real(kind_real) :: vrms
673 integer :: jv, jo, jz
675 if (.not. self%lalloc .or. .not. self%linit)
then 676 call abor1_ftn(
"ufo_geovals_maxloc: geovals not allocated")
679 mxval = 0.0_kind_real
687 do jz = 1, self%geovals(jv)%nval
688 vrms = vrms + self%geovals(jv)%vals(jz,jo)**2
690 vrms = sqrt(vrms/
real(self%geovals(jv)%nval,
kind_real))
691 if (vrms > mxval)
then 705 USE netcdf,
ONLY: nf90_float, nf90_double, nf90_int
708 use nc_diag_read_mod,
only: nc_diag_read_get_var_dims, nc_diag_read_check_var
716 character(max_string),
intent(in) :: filename
719 integer :: iunit, ivar, nobs, nval, fvlen
720 integer :: nvardim, vartype
721 integer,
allocatable,
dimension(:) :: vardims
723 real(kind_real),
allocatable :: fieldr2d(:,:), fieldr1d(:)
724 real,
allocatable :: fieldf2d(:,:), fieldf1d(:)
725 integer,
allocatable :: fieldi2d(:,:), fieldi1d(:)
727 character(max_string) :: err_msg
730 integer,
allocatable,
dimension(:) :: dist_indx
734 if (
allocated(vardims))
deallocate(vardims)
735 call nc_diag_read_get_var_dims(iunit, vars%fldnames(1), nvardim, vardims)
736 if (nvardim .eq. 1)
then 745 nobs=distribution%nobs_pe()
751 if (nc_diag_read_check_var(iunit,
"virtual_temperature"))
then 753 nobs =
size(dist_indx)
755 allocate(dist_indx(nobs))
756 dist_indx = distribution%indx
764 if (.not. nc_diag_read_check_var(iunit, vars%fldnames(ivar)))
then 765 write(err_msg,*)
'ufo_geovals_read_netcdf: var ', trim(vars%fldnames(ivar)),
' doesnt exist' 766 call abor1_ftn(trim(err_msg))
769 if (
allocated(vardims))
deallocate(vardims)
770 call nc_diag_read_get_var_dims(iunit, vars%fldnames(ivar), nvardim, vardims)
772 vartype = nc_diag_read_get_var_type(iunit, vars%fldnames(ivar))
774 if (nvardim == 1)
then 775 if (vardims(1) /= fvlen)
call abor1_ftn(
'ufo_geovals_read_netcdf: var dim /= fvlen')
779 self%geovals(ivar)%nval = nval
780 allocate(self%geovals(ivar)%vals(nval,nobs))
782 if (vartype == nf90_double)
then 783 allocate(fieldr1d(vardims(1)))
784 call nc_diag_read_get_var(iunit, vars%fldnames(ivar), fieldr1d)
785 self%geovals(ivar)%vals(1,:) = fieldr1d(dist_indx)
787 elseif (vartype == nf90_float)
then 788 allocate(fieldf1d(vardims(1)))
789 call nc_diag_read_get_var(iunit, vars%fldnames(ivar), fieldf1d)
790 self%geovals(ivar)%vals(1,:) = dble(fieldf1d(dist_indx))
792 elseif (vartype == nf90_int)
then 793 allocate(fieldi1d(vardims(1)))
794 call nc_diag_read_get_var(iunit, vars%fldnames(ivar), fieldi1d)
795 self%geovals(ivar)%vals(1,:) = fieldi1d(dist_indx)
798 call abor1_ftn(
'ufo_geovals_read_netcdf: can only read double, float and int')
801 elseif (nvardim == 2)
then 802 if (vardims(2) /= fvlen)
call abor1_ftn(
'ufo_geovals_read_netcdf: var dim /= fvlen')
806 self%geovals(ivar)%nval = nval
807 allocate(self%geovals(ivar)%vals(nval,nobs))
809 if (vartype == nf90_double)
then 810 allocate(fieldr2d(vardims(1), vardims(2)))
811 call nc_diag_read_get_var(iunit, vars%fldnames(ivar), fieldr2d)
812 self%geovals(ivar)%vals = fieldr2d(:,dist_indx)
814 elseif (vartype == nf90_float)
then 815 allocate(fieldf2d(vardims(1), vardims(2)))
816 call nc_diag_read_get_var(iunit, vars%fldnames(ivar), fieldf2d)
817 self%geovals(ivar)%vals = dble(fieldf2d(:,dist_indx))
819 elseif (vartype == nf90_int)
then 820 allocate(fieldi2d(vardims(1), vardims(2)))
821 call nc_diag_read_get_var(iunit, vars%fldnames(ivar), fieldi2d)
822 self%geovals(ivar)%vals = fieldi2d(:,dist_indx)
825 call abor1_ftn(
'ufo_geovals_read_netcdf: can only read double, float and int')
829 call abor1_ftn(
'ufo_geovals_read_netcdf: can only read 1d and 2d fields')
844 integer,
intent(in) :: iobs
847 character(MAXVARLEN) :: varname
850 do ivar = 1, self%nvar
851 varname = self%variables%fldnames(ivar)
853 if (
associated(geoval))
then 854 print *,
'geoval test: ', trim(varname), geoval%nval, geoval%vals(:,iobs)
856 print *,
'geoval test: ', trim(varname),
' doesnt exist' Fortran generic for generating random 1d, 2d and 3d arrays.
subroutine, public ufo_geovals_get_var(self, varname, geoval, status)
subroutine, public ufo_geovals_delete(self)
subroutine, public ufo_geovals_minmaxavg(self, kobs, pmin, pmax, prms)
subroutine, public ufo_geovals_add(self, other)
Sum of two GeoVaLs objects.
subroutine, public ufo_geovals_analytic_init(self, locs, ic)
Initialize a GeoVaLs object based on an analytic state.
Fortran derived type to hold observation locations.
integer function, public ufo_vars_getindex(self, varname)
subroutine, public ufo_geovals_init(self)
subroutine, public ufo_geovals_read_netcdf(self, filename, vars)
subroutine, public ufo_geovals_diff(self, other)
Difference between two GeoVaLs objects.
integer, parameter max_string
subroutine, public ufo_geovals_rms(self, vrms)
subroutine test1_advection_deformation(lon, lat, p, z, zcoords, u, v, w, t, phis, ps, rho, q, q1, q2, q3, q4)
subroutine test4_baroclinic_wave(moist, X, lon, lat, p, z, zcoords, u, v, w, t, phis, ps, rho, q, q1, q2)
subroutine, public ufo_geovals_dotprod(self, other, gprod)
Fortran derived type to represent model variables.
Fortran module containing IODA utility programs.
subroutine, public ufo_geovals_abs(self)
subroutine, public ufo_geovals_random(self)
subroutine, public ufo_geovals_zero(self)
subroutine, public ufo_geovals_allocone(self)
subroutine, public ufo_geovals_normalize(self, other)
Normalization of one GeoVaLs object by another.
character(len=maxvarlen), public var_prsl
subroutine, public ufo_geovals_maxloc(self, mxval, iobs, ivar)
Location where the summed geovals value is maximum.
type to hold interpolated fields required by the obs operators
Fortran module for generating random vectors.
subroutine test1_advection_hadley(lon, lat, p, z, zcoords, u, v, w, t, phis, ps, rho, q, q1)
subroutine nc_diag_read_close(filename, file_ncdr_id, from_pop)
subroutine test3_gravity_wave(lon, lat, p, z, zcoords, u, v, w, t, phis, ps, rho, q)
subroutine, public ufo_geovals_setup(self, vars, nobs)
Fortran module handling observation locations.
integer, parameter, public kind_real
character(len=maxvarlen), public var_tv
subroutine, public ioda_deselect_missing_values(ncid, vname, in_index, out_index)
subroutine, public ufo_geovals_print(self, iobs)
subroutine, public ufo_geovals_assign(self, rhs)
subroutine nc_diag_read_init(filename, file_ncdr_id, from_push)
subroutine, public ufo_geovals_scalmult(self, zz)
subroutine, public ufo_geovals_copy(self, other)
Copy one GeoVaLs object into another.
subroutine, public ufo_vars_clone(self, other)
type to hold interpolated field for one variable, one observation
real(fp), parameter, public pi