15 use fckit_configuration_module,
only: fckit_configuration
16 use fckit_log_module,
only: fckit_log
38 character(len=50) :: colname
41 real(kind_real),
allocatable :: values(:,:)
45 character(len=50) :: grpname
48 type(datetime),
allocatable :: times(:)
54 character(len=1024) :: filein
55 character(len=1024) :: fileout
59 #define LISTED_TYPE qg_obsdb
62 #include "oops/util/linkedList_i.f"
72 #include "oops/util/linkedList_c.f"
82 type(fckit_configuration),
intent(in) :: f_conf
83 type(datetime),
intent(in) :: winbgn
84 type(datetime),
intent(in) :: winend
87 character(len=1024) :: fin,fout
88 character(len=:),
allocatable :: str
91 if (f_conf%has(
"obsdatain"))
then
92 call f_conf%get_or_die(
"obsdatain.obsfile",str)
97 call fckit_log%info(
'qg_obsdb_setup: file in = '//trim(fin))
100 if (f_conf%has(
"obsdataout"))
then
101 call f_conf%get_or_die(
"obsdataout.obsfile",str)
102 call swap_name_member(f_conf, str)
105 call fckit_log%info(
'qg_obsdb_setup: file out = '//trim(fout))
126 type(
qg_obsdb),
intent(inout) :: self
137 do while (
associated(self%grphead))
139 self%grphead => jgrp%next
141 call datetime_delete(jgrp%times(jobs))
143 deallocate(jgrp%times)
144 do while (
associated(jgrp%colhead))
146 jgrp%colhead => jcol%next
147 deallocate(jcol%values)
162 character(len=*),
intent(in) :: grp
163 character(len=*),
intent(in) :: col
165 logical,
intent(in) :: local
166 integer,
intent(in),
optional :: idx(:)
174 call fckit_log%debug(
'qg_obsdb_get: grp = '//trim(grp))
175 call fckit_log%debug(
'qg_obsdb_get: col = '//trim(col))
179 if (.not.
associated(jgrp))
then
181 do while (
associated(jgrp))
182 call fckit_log%info(
'qg_obsdb_get: group '//trim(jgrp%grpname)//
' exists')
185 call fckit_log%error(
'qg_obsdb_get: cannot find '//trim(grp))
186 call abor1_ftn(
'qg_obsdb_get: obs group not found')
191 if (.not.
associated(jcol))
call abor1_ftn(
'qg_obsdb_get: obs column not found')
194 if (
allocated(ovec%values))
deallocate(ovec%values)
195 ovec%nlev = jcol%nlev
198 if ( .not.
present(idx))
then
201 ovec%nobs =
size(idx)
205 allocate(ovec%values(ovec%nlev,ovec%nobs))
208 ovec%values(jlev,jobs) = jcol%values(jlev,idx(jobs)+1)
213 ovec%nobs = jgrp%nobs
214 allocate(ovec%values(ovec%nlev,ovec%nobs))
217 ovec%values(jlev,jobs) = jcol%values(jlev,jobs)
230 type(
qg_obsdb),
intent(inout) :: self
231 character(len=*),
intent(in) :: grp
232 character(len=*),
intent(in) :: col
242 if (.not.
associated(jgrp))
then
244 do while (
associated(jgrp))
245 call fckit_log%info(
'qg_obsdb_put: group '//trim(jgrp%grpname)//
' exists')
248 call fckit_log%error(
'qg_obsdb_put: cannot find '//trim(grp))
249 call abor1_ftn(
'qg_obsdb_put: obs group not found')
254 if (.not.
associated(jcol))
then
255 if (.not.
associated(jgrp%colhead))
call abor1_ftn(
'qg_obsdb_put: no locations')
257 do while (
associated(jcol%next))
263 jcol%nlev = ovec%nlev
264 allocate(jcol%values(jcol%nlev,jgrp%nobs))
268 if (ovec%nobs/=jgrp%nobs)
call abor1_ftn(
'qg_obsdb_put: error obs number')
269 if (ovec%nlev/=jcol%nlev)
call abor1_ftn(
'qg_obsdb_put: error col number')
272 jcol%values(jlev,jobs) = ovec%values(jlev,jobs)
285 character(len=*),
intent(in) :: grp
286 character(len=*),
intent(in) :: col
287 integer,
intent(out) ::
has
298 if (
associated(jgrp))
then
301 if (
associated(jcol))
has = 1
313 character(len=*),
intent(in) :: grp
314 type(datetime),
intent(in) :: t1
315 type(datetime),
intent(in) :: t2
316 type(atlas_fieldset),
intent(inout) :: fields
317 type(c_ptr),
intent(in),
value :: c_times
321 integer,
allocatable :: indx(:)
322 character(len=8),
parameter :: col =
'Location'
325 type(atlas_field) :: field_z, field_lonlat
326 real(kind_real),
pointer :: z(:), lonlat(:,:)
330 allocate(indx(nlocs))
335 if (.not.
associated(jgrp))
call abor1_ftn(
'qg_obsdb_locations: obs group not found')
339 if (.not.
associated(jcol))
call abor1_ftn(
'qg_obsdb_locations: obs column not found')
343 field_lonlat = atlas_field(name=
"lonlat", kind=atlas_real(kind_real), shape=[2,nlocs])
344 field_z = atlas_field(name=
"altitude", kind=atlas_real(kind_real), shape=[nlocs])
346 call field_lonlat%data(lonlat)
351 lonlat(1,jo) = jcol%values(1,indx(jo))
352 lonlat(2,jo) = jcol%values(2,indx(jo))
353 z(jo) = jcol%values(3,indx(jo))
354 call f_c_push_to_datetime_vector(c_times, jgrp%times(indx(jo)))
357 call fields%add(field_lonlat)
358 call fields%add(field_z)
361 call field_lonlat%final()
374 type(
qg_obsdb),
intent(inout) :: self
375 character(len=*),
intent(in) :: grp
376 type(fckit_configuration),
intent(in) :: f_conf
377 type(datetime),
intent(in) :: bgn
378 type(duration),
intent(in) :: step
379 integer,
intent(in) :: ktimes
380 integer,
intent(inout) :: kobs
383 integer :: nlev,nlocs
384 real(kind_real) :: err
385 type(datetime),
allocatable :: times(:)
389 call f_conf%get_or_die(
"obs_density",nlocs)
393 allocate(times(kobs))
402 call f_conf%get_or_die(
"obs_error",err)
403 call f_conf%get_or_die(
"nval",nlev)
405 obserr%values(:,:) = err
410 deallocate(obsloc%values)
411 deallocate(obserr%values)
422 character(len=*),
intent(in) :: grp
423 integer,
intent(inout) :: kobs
432 if (
associated(jgrp))
then
448 type(
qg_obsdb),
intent(inout) :: self
449 type(datetime),
intent(in) :: winbgn
450 type(datetime),
intent(in) :: winend
453 integer :: igrp,icol,iobs,ncol,nobsfile,jobs
454 integer :: ncid,grpname_id,ngrp_id,nobs_id,ncol_id,times_id,nlev_id,colname_id,values_id
457 character(len=6) :: igrpchar
458 character(len=50) :: stime
459 character(len=1024) :: record
460 logical,
allocatable :: inwindow(:)
461 type(datetime) :: tobs
462 type(datetime),
allocatable :: alltimes(:)
463 real(kind_real),
allocatable :: readbuf(:,:)
466 call ncerr(nf90_open(trim(self%filein),nf90_nowrite,ncid))
469 call ncerr(nf90_inq_dimid(ncid,
'ngrp',ngrp_id))
472 call ncerr(nf90_inquire_dimension(ncid,ngrp_id,len=self%ngrp))
475 call ncerr(nf90_inq_varid(ncid,
'grpname',grpname_id))
480 allocate(self%grphead)
486 write(igrpchar,
'(i6.6)') igrp
489 call ncerr(nf90_get_var(ncid,grpname_id,jgrp%grpname,(/1,igrp/),(/50,1/)))
492 call ncerr(nf90_inq_dimid(ncid,
'nobs_'//igrpchar,nobs_id))
493 call ncerr(nf90_inq_dimid(ncid,
'ncol_'//igrpchar,ncol_id))
496 call ncerr(nf90_inquire_dimension(ncid,nobs_id,len=nobsfile))
497 call ncerr(nf90_inquire_dimension(ncid,ncol_id,len=ncol))
498 write(record,*)
'qg_obsdb_read: reading ',nobsfile,
' ',jgrp%grpname,
' observations'
499 call fckit_log%info(record)
502 call ncerr(nf90_inq_varid(ncid,
'times_'//igrpchar,times_id))
503 call ncerr(nf90_inq_varid(ncid,
'nlev_'//igrpchar,nlev_id))
504 call ncerr(nf90_inq_varid(ncid,
'colname_'//igrpchar,colname_id))
505 call ncerr(nf90_inq_varid(ncid,
'values_'//igrpchar,values_id))
508 allocate(inwindow(nobsfile))
509 allocate(alltimes(nobsfile))
512 call ncerr(nf90_get_var(ncid,grpname_id,jgrp%grpname,(/1,igrp/),(/50,1/)))
515 call ncerr(nf90_get_var(ncid,times_id,stime,(/1,iobs/),(/50,1/)))
516 call datetime_create(stime,tobs)
517 if (tobs > winbgn .and. tobs <= winend)
then
518 inwindow(iobs) = .true.
519 alltimes(iobs) = tobs
520 jgrp%nobs = jgrp%nobs + 1
522 inwindow(iobs) = .false.
525 write(record,*)
'qg_obsdb_read: keeping ',jgrp%nobs,
' ',jgrp%grpname,
' observations'
526 call fckit_log%info(record)
528 allocate(jgrp%times(jgrp%nobs))
531 if (inwindow(iobs))
then
533 jgrp%times(jobs) = alltimes(iobs)
537 write(record,*)
'qg_obsdb_read: ',jgrp%grpname,
' after times ',jgrp%nobs
538 call fckit_log%info(record)
544 allocate(jgrp%colhead)
552 call ncerr(nf90_get_var(ncid,nlev_id,jcol%nlev,(/icol/)))
553 call ncerr(nf90_get_var(ncid,colname_id,jcol%colname,(/1,icol/),(/50,1/)))
554 write(record,*)
'qg_obsdb_read: ',jgrp%grpname,
' after get var ',jgrp%nobs
555 call fckit_log%info(record)
558 allocate(readbuf(jcol%nlev,nobsfile))
559 allocate(jcol%values(jcol%nlev,jgrp%nobs))
562 call ncerr(nf90_get_var(ncid,values_id,readbuf(1:jcol%nlev,:),(/1,icol,1/),(/jcol%nlev,1,nobsfile/)))
563 write(record,*)
'qg_obsdb_read: ',jgrp%grpname,
' after get values ',jgrp%nobs
564 call fckit_log%info(record)
568 if (inwindow(iobs))
then
570 jcol%values(:,jobs) = readbuf(:,iobs)
574 write(record,*)
'qg_obsdb_read: ',jgrp%grpname,
' after readbuf ',jgrp%nobs, jobs
575 call fckit_log%info(record)
578 write(record,*)
'qg_obsdb_read: ',jgrp%grpname,
' done ',jgrp%nobs
579 call fckit_log%info(record)
582 write(record,*)
'qg_obsdb_read: closing file'
583 call fckit_log%info(record)
585 call ncerr(nf90_close(ncid))
598 integer :: igrp,icol,iobs,ncol,nlevmax
599 integer :: ncid,nstrmax_id,grpname_id,ngrp_id,nobs_id,ncol_id,nlevmax_id,times_id,nlev_id,colname_id,values_id
602 character(len=6) :: igrpchar
603 character(len=50) :: stime
606 call ncerr(nf90_create(trim(self%fileout),or(nf90_clobber,nf90_64bit_offset),ncid))
609 call ncerr(nf90_def_dim(ncid,
'nstrmax',50,nstrmax_id))
610 call ncerr(nf90_def_dim(ncid,
'ngrp',self%ngrp,ngrp_id))
613 call ncerr(nf90_def_var(ncid,
'grpname',nf90_char,(/nstrmax_id,ngrp_id/),grpname_id))
616 call ncerr(nf90_enddef(ncid))
621 do while (
associated(jgrp))
623 if (jgrp%nobs > 0)
then
624 write(igrpchar,
'(i6.6)') igrp
626 call ncerr(nf90_redef(ncid))
632 do while (
associated(jcol))
634 nlevmax = max(jcol%nlev,nlevmax)
639 call ncerr(nf90_def_dim(ncid,
'nobs_'//igrpchar,jgrp%nobs,nobs_id))
640 call ncerr(nf90_def_dim(ncid,
'ncol_'//igrpchar,ncol,ncol_id))
641 call ncerr(nf90_def_dim(ncid,
'nlevmax_'//igrpchar,nlevmax,nlevmax_id))
644 call ncerr(nf90_def_var(ncid,
'times_'//igrpchar,nf90_char,(/nstrmax_id,nobs_id/),times_id))
645 call ncerr(nf90_def_var(ncid,
'nlev_'//igrpchar,nf90_int,(/ncol_id/),nlev_id))
646 call ncerr(nf90_def_var(ncid,
'colname_'//igrpchar,nf90_char,(/nstrmax_id,ncol_id/),colname_id))
647 call ncerr(nf90_def_var(ncid,
'values_'//igrpchar,nf90_double,(/nlevmax_id,ncol_id,nobs_id/),values_id))
650 call ncerr(nf90_enddef(ncid))
653 call ncerr(nf90_put_var(ncid,grpname_id,jgrp%grpname,(/1,igrp/),(/50,1/)))
655 call datetime_to_string(jgrp%times(iobs),stime)
656 call ncerr(nf90_put_var(ncid,times_id,stime,(/1,iobs/),(/50,1/)))
662 do while (
associated(jcol))
666 call ncerr(nf90_put_var(ncid,nlev_id,jcol%nlev,(/icol/)))
667 call ncerr(nf90_put_var(ncid,colname_id,jcol%colname,(/1,icol/),(/50,1/)))
668 call ncerr(nf90_put_var(ncid,values_id,jcol%values(1:jcol%nlev,:),(/1,icol,1/),(/jcol%nlev,1,jgrp%nobs/)))
679 call ncerr(nf90_close(ncid))
690 character(len=*),
intent(in) :: grp
691 type(
group_data),
pointer,
intent(inout) :: find
697 do while (
associated(find))
698 if (find%grpname==grp)
exit
711 character(len=*),
intent(in) :: col
718 do while (
associated(find))
719 if (find%colname==col)
exit
731 integer,
intent(in) :: nlocs
732 integer,
intent(in) :: ntimes
733 type(datetime),
intent(in) :: bgn
734 type(duration),
intent(in) :: step
735 type(datetime),
intent(inout) :: times(nlocs*ntimes)
739 integer :: jobs,iobs,jstep
740 real(kind_real) :: x(nlocs),y(nlocs),z(nlocs),lon(nlocs),lat(nlocs)
741 type(datetime) :: now
763 obsloc%values(:,iobs) = (/lon(jobs),lat(jobs),z(jobs)/)
765 call datetime_update(now,step)
769 call datetime_delete(now)
779 type(
qg_obsdb),
intent(inout) :: self
780 character(len=*),
intent(in) :: grp
781 type(datetime),
intent(in) :: times(:)
790 if (
associated(igrp))
call abor1_ftn(
'qg_obsdb_create: obs group already exists')
791 if (
associated(self%grphead))
then
793 do while (
associated(igrp%next))
799 allocate(self%grphead)
805 igrp%nobs =
size(times)
806 allocate(igrp%times(igrp%nobs))
807 igrp%times(:) = times(:)
808 allocate(igrp%colhead)
809 igrp%colhead%colname =
'Location'
810 igrp%colhead%nlev = 3
811 allocate(igrp%colhead%values(3,igrp%nobs))
812 if (locs%nlev/=3)
call abor1_ftn(
'qg_obsdb_create: error locations not 3D')
813 if (locs%nobs/=igrp%nobs)
call abor1_ftn(
'qg_obsdb_create: error locations number')
816 igrp%colhead%values(jlev,jobs) = locs%values(jlev,jobs)
819 self%ngrp = self%ngrp+1
830 character(len=*),
intent(in) :: grp
831 type(datetime),
intent(in) :: t1
832 type(datetime),
intent(in) :: t2
833 integer,
intent(inout) :: kobs
841 if (.not.
associated(jgrp))
call abor1_ftn(
'qg_obsdb_count_time: obs group not found')
846 if ((t1<jgrp%times(jobs)).and.(jgrp%times(jobs)<=t2)) kobs = kobs+1
858 character(len=*),
intent(in) :: grp
859 type(datetime),
intent(in) :: t1
860 type(datetime),
intent(in) :: t2
861 integer,
intent(inout) :: indx(:)
869 if (.not.
associated(jgrp))
call abor1_ftn(
'qg_obsdb_count_indx: obs group not found')
874 if ((t1<jgrp%times(jobs)).and.(jgrp%times(jobs)<=t2))
then