14 use fckit_log_module,
only : fckit_log
42 integer,
allocatable :: dist_indx(:)
44 character(len=max_string) :: obstype
46 character(len=max_string) :: filename
48 character(len=max_string) :: fileout
52 real(kind=c_double),
allocatable :: odb_data(:,:)
60 subroutine ioda_obsdb_setup(self, fvlen, nobs, dist_indx, nlocs, nvars, filename, fileout, obstype)
70 integer,
intent(in) :: fvlen
71 integer,
intent(in) :: nobs
72 integer,
intent(in) :: dist_indx(:)
73 integer,
intent(in) :: nlocs
74 integer,
intent(in) :: nvars
75 character(len=*),
intent(in) :: filename
76 character(len=*),
intent(in) :: fileout
77 character(len=*),
intent(in) :: obstype
79 integer :: input_file_type
81 character(len=:),
allocatable :: var_list(:)
82 logical,
allocatable :: var_select(:)
84 integer :: var_list_item_len
86 integer(selected_int_kind(8)),
allocatable :: dim_sizes(:)
91 allocate(self%dist_indx(nobs))
92 self%dist_indx = dist_indx
95 self%filename = filename
96 self%fileout = fileout
97 self%obstype = obstype
98 call self%obsvars%setup()
101 select case (input_file_type)
108 call nc_diag_read_init(self%filename, iunit)
111 allocate(
character(var_list_item_len)::var_list(file_nvars))
114 allocate(var_select(file_nvars))
118 var_select(i) = (
size(dim_sizes) .eq. 1) .and. (dim_sizes(1) .eq. fvlen)
119 deallocate(dim_sizes)
127 var_list_item_len = 80
128 allocate(
character(var_list_item_len)::var_list(file_nvars))
129 allocate(var_select(file_nvars))
131 var_list(1) =
"latitude" 132 var_list(2) =
"longitude" 135 var_select(1) = .true.
136 var_select(2) = .true.
137 var_select(2) = .true.
145 if (var_select(i))
then 151 deallocate(var_select)
165 if (
allocated(self%dist_indx))
deallocate(self%dist_indx)
171 call self%obsvars%delete()
184 type(datetime),
intent(in) :: t1, t2
186 character(len=*),
parameter:: myname =
"ioda_obsdb_getlocs" 187 character(len=255) :: record
192 integer,
dimension(:),
allocatable :: indx
193 real(kind_real),
dimension(:),
allocatable :: time, lon, lat
194 type(duration),
dimension(:),
allocatable :: dt
195 type(datetime),
dimension(:),
allocatable :: t
196 type(datetime) :: reftime
198 character(21) :: tstr, tstr2
203 istep = self%nobs / self%nlocs
206 allocate(time(self%nlocs), lon(self%nlocs), lat(self%nlocs))
207 allocate(indx(self%nlocs))
219 allocate(dt(self%nlocs), t(self%nlocs))
224 call datetime_create(
"2018-04-15T00:00:00Z", reftime)
226 call datetime_to_string(reftime, tstr)
229 dt(i) = int(3600*time(i))
231 call datetime_update(t(i), dt(i))
234 call datetime_to_string(t1,tstr)
235 call datetime_to_string(t2,tstr2)
240 if (t(i) > t1 .and. t(i) <= t2)
then 243 call datetime_to_string(t(i),tstr)
252 locs%lon(i) = lon(indx(i))
253 locs%lat(i) = lat(indx(i))
254 locs%time(i) = time(indx(i))
256 locs%indx = indx(1:ilocs)
258 deallocate(time, lon, lat)
261 write(record,*) myname,
': allocated/assinged obs-data' 262 call fckit_log%info(record)
273 use mpi,
only: mpi_comm_rank, mpi_comm_size, mpi_comm_world, mpi_init, mpi_finalize
277 use netcdf,
only: nf90_float, nf90_double, nf90_int
288 type(ioda_obsdb),
intent(in) :: self
289 character(len=*),
intent(in) :: vname
290 type(ioda_obs_var),
pointer :: vptr
293 character(len=max_string) :: err_msg
298 integer,
allocatable :: dimsizes(:)
299 real,
allocatable :: field1d_sngl(:)
300 real,
allocatable :: field2d_sngl(:,:)
301 integer,
allocatable :: field1d_int(:)
302 integer,
allocatable :: field2d_int(:,:)
303 real(kind_real),
allocatable :: field1d_dbl(:)
304 real(kind_real),
allocatable :: field2d_dbl(:,:)
305 integer :: input_file_type
312 call self%obsvars%get_node(vname, vptr)
313 if (.not.
associated(vptr))
then 314 call self%obsvars%add_node(vname, vptr)
317 select case (input_file_type)
321 call nc_diag_read_init(self%filename, iunit)
324 if (.not.nc_diag_read_check_var(iunit, vname))
then 325 write(err_msg,*)
'ioda_obsdb_getvar: var ', trim(vname),
' does not exist' 326 call abor1_ftn(trim(err_msg))
331 call nc_diag_read_get_var_dims(iunit, vname, ndims, dimsizes)
334 vartype = nc_diag_read_get_var_type(iunit, vname)
336 if (ndims .gt. 1)
then 337 write(err_msg,*)
'ioda_obsdb_getvar: var ', trim(vname),
' must have rank = 1' 338 call abor1_ftn(trim(err_msg))
341 if (dimsizes(1) .ne. self%fvlen)
then 342 write(err_msg,*)
'ioda_obsdb_getvar: var ', trim(vname),
' size (', dimsizes(1),
') must equal fvlen (', self%fvlen,
')' 343 call abor1_ftn(trim(err_msg))
347 vptr%nobs = self%nobs
348 allocate(vptr%vals(vptr%nobs))
350 if (vartype == nf90_double)
then 351 allocate(field1d_dbl(dimsizes(1)))
352 call nc_diag_read_get_var(iunit, vname, field1d_dbl)
353 vptr%vals = field1d_dbl(self%dist_indx)
354 deallocate(field1d_dbl)
355 elseif (vartype == nf90_float)
then 356 allocate(field1d_sngl(dimsizes(1)))
357 call nc_diag_read_get_var(iunit, vname, field1d_sngl)
358 vptr%vals = field1d_sngl(self%dist_indx)
359 deallocate(field1d_sngl)
360 elseif (vartype == nf90_int)
then 361 allocate(field1d_int(dimsizes(1)))
362 call nc_diag_read_get_var(iunit, vname, field1d_int)
363 vptr%vals = field1d_int(self%dist_indx)
364 deallocate(field1d_int)
376 call get_vars (self % filename, [
"lat"],
"entryno = 1", field2d_dbl)
378 call get_vars (self % filename, [
"lon"],
"entryno = 1", field2d_dbl)
380 call get_vars (self % filename, [
"time"],
"entryno = 1", field2d_dbl)
382 vptr%nobs =
size(field2d_dbl,dim=2)
383 allocate(vptr%vals(vptr%nobs))
384 vptr % vals(:) = field2d_dbl(1,:)
404 character(len=*),
intent(in) :: vname
405 real(kind_real),
intent(out) :: vdata(:)
407 character(len=*),
parameter:: myname =
"ioda_obsdb_get_vec" 408 character(len=255) :: record
424 character(len=*),
intent(in) :: vname
425 real(kind_real),
intent(in) :: vdata(:)
428 character(len=*),
parameter :: myname =
"ioda_obsdb_put_vec" 429 character(len=255) :: record
431 call self%obsvars%get_node(vname, vptr)
432 if (.not.
associated(vptr))
then 433 call self%obsvars%add_node(vname, vptr)
434 vptr%nobs = self%nobs
435 allocate(vptr%vals(vptr%nobs))
438 write(record,*) myname,
' var= ', trim(vname),
':this column already exists' 439 call abor1_ftn(record)
446 subroutine ioda_obsdb_generate(self, fvlen, nobs, dist_indx, nlocs, nvars, obstype, lat, lon1, lon2)
449 integer,
intent(in) :: fvlen
450 integer,
intent(in) :: nobs
451 integer,
intent(in) :: dist_indx(:)
452 integer,
intent(in) :: nlocs
453 integer,
intent(in) :: nvars
454 character(len=*) :: obstype
455 real,
intent(in) :: lat, lon1, lon2
457 character(len=*),
parameter :: myname =
"ioda_obsdb_generate" 460 character(len=max_string) :: vname
463 call ioda_obsdb_setup(self, fvlen, nobs, dist_indx, nlocs, nvars,
"",
"", obstype)
467 call self%obsvars%get_node(vname, vptr)
468 if (.not.
associated(vptr))
then 469 call self%obsvars%add_node(vname, vptr)
471 vptr%nobs = self%nobs
475 call self%obsvars%get_node(vname, vptr)
476 if (.not.
associated(vptr))
then 477 call self%obsvars%add_node(vname, vptr)
479 vptr%nobs = self%nobs
481 vptr%vals(i) = lon1 + (i-1)*(lon2-lon1)/(nobs-1)
492 real(kind=kind_real),
intent(inout) :: ovec(:)
493 character(len=*),
intent(in) :: vname
495 character(len=*),
parameter:: myname =
"ioda_obsdb_var_to_ovec" 496 character(len=255) :: record
501 ovec(:) = vptr%vals(:)
511 type(ioda_obsdb),
intent(in) :: self
513 type(ioda_obs_var),
pointer :: vptr
514 character(len=*),
parameter :: myname =
"ioda_obsdb_write" 515 character(len=255) :: record
516 integer :: i,ncid,dimid_1d(1),dimid_nobs
517 integer,
allocatable :: ncid_var(:)
521 if (self%fileout(len_trim(self%fileout)-3:len_trim(self%fileout)) ==
".nc4" .or. &
522 self%fileout(len_trim(self%fileout)-3:len_trim(self%fileout)) ==
".nc")
then 524 write(record,*) myname,
':write diag in netcdf, filename=', trim(self%fileout)
525 call fckit_log%info(record)
527 call check(
'nf90_create', nf90_create(trim(self%fileout),nf90_hdf5,ncid))
528 call check(
'nf90_def_dim', nf90_def_dim(ncid,trim(self%obstype)//
'_nobs',self%nobs, dimid_nobs))
529 dimid_1d = (/ dimid_nobs /)
532 allocate(ncid_var(self%obsvars%n_nodes))
533 vptr => self%obsvars%head
534 do while (
associated(vptr))
536 call check(
'nf90_def_var', nf90_def_var(ncid,trim(vptr%vname)//
'_'//trim(self%obstype),nf90_double,dimid_1d,ncid_var(i)))
540 call check(
'nf90_enddef', nf90_enddef(ncid))
543 vptr => self%obsvars%head
544 do while (
associated(vptr))
546 call check(
'nf90_put_var', nf90_put_var(ncid,ncid_var(i),vptr%vals))
550 call check(
'nf90_close', nf90_close(ncid))
553 else if (self%fileout(len_trim(self%fileout)-3:len_trim(self%fileout)) ==
".odb")
then 555 write(record,*) myname,
':write diag in odb2, filename=', trim(self%fileout)
556 call fckit_log%info(record)
560 write(record,*) myname,
':no output' 561 call fckit_log%info(record)
572 type(ioda_obsdb),
intent(in) :: self
574 type(ioda_obs_var),
pointer :: vptr
576 print*,
"DEBUG: ioda_obsdb_dump: fvlen: ", self%fvlen
577 print*,
"DEBUG: ioda_obsdb_dump: nobs: ", self%nobs
578 print*,
"DEBUG: ioda_obsdb_dump: nlocs: ", self%nlocs
579 print*,
"DEBUG: ioda_obsdb_dump: nvars: ", self%nvars
580 print*,
"DEBUG: ioda_obsdb_dump: obstype: ", trim(self%obstype)
581 print*,
"DEBUG: ioda_obsdb_dump: filename: ", trim(self%filename)
583 print*,
"DEBUG: ioda_obsdb_dump: count: ", self%obsvars%n_nodes
585 vptr => self%obsvars%head
586 do while (
associated(vptr))
587 print*,
"DEBUG: ioda_obsdb_dump: vname: ", trim(vptr%vname)
588 print*,
"DEBUG: ioda_obsdb_dump: shape, size: ", shape(vptr%vals),
size(vptr%vals)
589 print*,
"DEBUG: ioda_obsdb_dump: vals (first 5): ", vptr%vals(1:5)
590 print*,
"DEBUG: ioda_obsdb_dump: vals (last 5): ", vptr%vals(vptr%nobs-4:vptr%nobs)
595 print*,
"DEBUG: ioda_obsdb_dump:" 600 subroutine check(action, status)
602 use netcdf,
only: nf90_noerr, nf90_strerror
606 integer,
intent (in) :: status
607 character (len=*),
intent (in) :: action
609 if(status /= nf90_noerr)
then 610 print *,
"During action: ", trim(action),
", received error: ", trim(nf90_strerror(status))
620 character(len=*),
intent(in) :: fname
627 if (fname(len_trim(fname)-3:len_trim(fname)) ==
".nc4" .or. &
628 fname(len_trim(fname)-2:len_trim(fname)) ==
".nc")
then 630 elseif (fname(len_trim(fname)-3:len_trim(fname)) ==
".odb")
then subroutine count_query_results(filename, query, num_results)
subroutine ioda_obsdb_dump(self)
Fortran derived type to hold a set of observation variables.
subroutine, public ioda_obsdb_setup(self, fvlen, nobs, dist_indx, nlocs, nvars, filename, fileout, obstype)
subroutine ioda_obsdb_getvar(self, vname, vptr)
subroutine check(action, status)
Fortran derived type to hold observation locations.
Fortran module handling radiosonde observation space.
subroutine, public ioda_obsdb_get_vec(self, vname, vdata)
integer function, public ioda_obsdb_get_ftype(fname)
subroutine, public ioda_obsdb_delete(self)
Fortran module with ODB API utility routines.
subroutine get_vars(filename, columns, filter, data)
subroutine, public ioda_obsdb_getlocs(self, locs, t1, t2)
subroutine, public ioda_obsdb_put_vec(self, vname, vdata)
subroutine nc_diag_read_close(filename, file_ncdr_id, from_pop)
subroutine, public ioda_obsdb_var_to_ovec(self, ovec, vname)
Fortran module handling observation locations.
subroutine ioda_obsdb_write(self)
integer, parameter max_string
subroutine, public ioda_obsdb_generate(self, fvlen, nobs, dist_indx, nlocs, nvars, obstype, lat, lon1, lon2)
subroutine, public ioda_locs_setup(self, nlocs)
subroutine nc_diag_read_init(filename, file_ncdr_id, from_push)