Skip to content

Commit

Permalink
Merge pull request #29 from metno/icon
Browse files Browse the repository at this point in the history
Extending snap and snappy to work with DWD/Icon meteorological data
  • Loading branch information
heikoklein authored May 6, 2020
2 parents 2820551 + 7bc9233 commit 253e498
Show file tree
Hide file tree
Showing 18 changed files with 1,005 additions and 273 deletions.
268 changes: 268 additions & 0 deletions src/common/filesort_fi.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
! SNAP: Servere Nuclear Accident Programme
! Copyright (C) 1992-2020 Norwegian Meteorological Institute

! This file is part of SNAP. SNAP is free software: you can
! redistribute it and/or modify it under the terms of the
! GNU General Public License as published by the
! Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.

! This program is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! GNU General Public License for more details.

! You should have received a copy of the GNU General Public License
! along with this program. If not, see <https://www.gnu.org/licenses/>.

module filesort_fiML
implicit none
private

public filesort_fi

contains

!> check and sort netcdf file contents
subroutine filesort_fi(fimex_type, fimex_config)
USE iso_fortran_env, only: error_unit, real64, int64, int32
use Fimex, only: FimexIO, AXIS_GeoZ, &
AXIS_Pressure, AXIS_Height, AXIS_Realization, AXIS_Time
USE readfield_fiML, only: check
USE DateCalc, only: epochToDate
USE Utils, only: itoa
USE ieee_arithmetic, only: ieee_is_nan
USE snapfilML, only: iavail, kavail, itimer, navail, nfilef, filef
USE snapfldML, only: enspos
USE snapmetML, ONLY: met_params
USE snapdebug, only: iulog, idebug
USE snapdimML, only: nx, ny, mavail
USE milibML, only: vtime
!> filetype of all input-files, e.g. ncml, netcdf, grib
character(len=1024), intent(in) :: fimex_type
!> optional config-file
character(len=1024), intent(in) :: fimex_config

TYPE(FimexIO) :: fio
integer(int32), dimension(:), allocatable :: start, length, atypes
character(len=1024) :: time_var, varname
integer :: i, j, t, ndims, nf, tsize, ierror
real(real64), allocatable, target :: times(:)
real(real64), allocatable, target :: field(:)
integer :: zeroHour, status, count_nan
integer :: dateTime(6)

! position in iavail
navail = 0
! loop over all file-names
do nf = 1, nfilef
! get the time steps from the files "time" variable
status = fio%open (filef(nf), fimex_config, fimex_type)
if (status /= 0) then
write (error_unit, *) "cannot open ", trim(filef(nf))
write (iulog, *) "cannot open ", trim(filef(nf))
cycle
endif

varname = met_params%xwindv
ndims = fio%get_dimensions(varname)
if (ndims <= 0) &
call check(ndims, "can't make slicebuilder for "//TRIM(varname))

if (allocated(start)) deallocate (start)
allocate (start(ndims))
if (allocated(length)) deallocate (length)
allocate (length(ndims))
if (allocated(atypes)) deallocate (atypes)
allocate (atypes(ndims))
call check(fio%get_dimension_start_size(start, length), "reading dim-sizes for "//TRIM(varname))
call check(fio%get_axistypes(atypes), "reading dim-types for "//TRIM(varname))

tsize = huge(tsize)
DO i = 1, ndims
SELECT CASE (atypes(i))
CASE (AXIS_Time) ! full x-range
tsize = length(i)
time_var = fio%get_dimname(i)
END SELECT
END DO

if (tsize > mavail) then
write (error_unit, *) "to many time-steps in ", filef(nf), ": ", tsize
error stop 1
end if

ndims = fio%get_dimensions(time_var)
if (allocated(times)) deallocate (times)
allocate (times(tsize))
call check(fio%read (time_var, times, "seconds since 1970-01-01 00:00:00 +00:00"), "reading time variable")

do t = 1, tsize
ndims = fio%get_dimensions(varname)
DO i = 1, ndims
SELECT CASE (atypes(i))
CASE (AXIS_Time)
call check(fio%reduce_dimension(fio%get_dimname(i), t - 1, 1), &
"reducing "//TRIM(fio%get_dimname(i))//" to "//itoa(t)//" for "//TRIM(varname))
CASE (AXIS_GeoZ, AXIS_Pressure, AXIS_Height)
call check(fio%reduce_dimension(fio%get_dimname(i), 0, 1), &
"reducing "//TRIM(fio%get_dimname(i))//" to 0 for "//TRIM(varname))
CASE (AXIS_Realization)
call check(fio%reduce_dimension(fio%get_dimname(i), enspos - 1, 1), &
"reducing "//TRIM(fio%get_dimname(i))//" to 0 for "//TRIM(varname))
END SELECT
END DO
if (.not. allocated(field)) allocate (field(nx*ny))
status = fio%read (varname, field)

! test 4 arbitrary values in field
count_nan = 0
do j = 1, 4
if (ieee_is_nan(field(j*j))) count_nan = count_nan + 1
end do
if (count_nan == 4) then
write (error_unit, *) met_params%xwindv, " at time ", i, " undefined, skipping"
CYCLE
end if
navail = navail + 1
if (navail >= mavail) then
if (navail == mavail) then
write (iulog, *) 'WARNING : TOO MANY AVAILABLE TIME STEPS'
write (iulog, *) ' no.,max(MAVAIL): ', navail, mavail
write (iulog, *) ' CONTINUING WITH RECORDED DATA'
write (error_unit, *) 'WARNING : TOO MANY AVAILABLE TIME STEPS'
write (error_unit, *) ' max (MAVAIL): ', mavail
write (error_unit, *) ' CONTINUING WITH RECORDED DATA'
end if
navail = mavail
end if
dateTime = epochToDate(int(times(t), kind=int64))
iavail(navail)%aYear = dateTime(6)
iavail(navail)%aMonth = dateTime(5)
iavail(navail)%aDay = dateTime(4)
iavail(navail)%aHour = dateTime(3)
! iavail(n)%fcHour: forecast hour
iavail(navail)%fcHour = 0
iavail(navail)%fileNo = nf
! iavail(n)%fileType: 1=model level 2=surface 3=both
! currently not used
iavail(navail)%fileType = 3
! in nc-mode: time-postion in file
iavail(navail)%timePos = t
! iavail(n)%oHour: offset in hours from first (sorted) timestep
! but currently used to store the hours since 1970-01-01
iavail(navail)%oHour = int(times(t)/3600)
! iavail(n)%nAvail: pointer to next forward (time) data
! iavail(n)%pAvail: pointer to next backward (time) data
! still to be set
iavail(navail)%nAvail = 0
iavail(navail)%pAvail = 0
end do
end do

! sorting time-steps, setting iavail 9, 10, kavail(1) and kavail(2)
! drop double occurances of time, using latest in input-list
kavail(1) = 1
kavail(2) = 1
iavail(1)%pAvail = 0
iavail(1)%nAvail = 0
do i = 2, navail
! run back until time is >= existing time
j = kavail(2)
do while (j > 0 .AND. iavail(i)%oHour < iavail(j)%oHour)
j = iavail(j)%pAvail
end do
if (j == kavail(2)) kavail(2) = i

if (j == 0) then
! insert at beginning
iavail(kavail(1))%pAvail = i
iavail(i)%nAvail = kavail(1)
iavail(i)%pAvail = 0
kavail(1) = i
else
if (iavail(i)%oHour == iavail(j)%oHour) then
! replace position j with i (newer)
if (iavail(i)%timePos == 1 .AND. iavail(j)%timePos > 1) then
! exception, i is analysis time, j isn't so: keep j
! ignore this timestep if possible, but give next and previous
iavail(i)%nAvail = iavail(j)%nAvail
iavail(i)%pAvail = j
! reset first and last elements to j
if (kavail(1) == i) kavail(1) = j
if (kavail(2) == i) kavail(2) = j
else
! replace j with i
iavail(i)%nAvail = iavail(j)%nAvail
iavail(i)%pAvail = iavail(j)%pAvail
! set next of previous if previous exists
if (iavail(j)%pAvail /= 0) then
iavail(iavail(j)%pAvail)%nAvail = i
endif
! set previous of next if next exists
if (iavail(j)%nAvail /= 0) then
iavail(iavail(j)%nAvail)%pAvail = i
endif
! reset first and last elements to i
if (kavail(1) == j) kavail(1) = i
if (kavail(2) == j) kavail(2) = i
end if
else
! insert i as successor to j
iavail(i)%nAvail = iavail(j)%nAvail
iavail(j)%nAvail = i
iavail(i)%pAvail = j
if (iavail(i)%nAvail /= 0) then
iavail(iavail(i)%nAvail)%pAvail = i
endif
if (kavail(2) == j) kavail(2) = i
end if
end if
end do

!..time range

do i = 1, 2
itimer(1, i) = iavail(kavail(i))%aYear
itimer(2, i) = iavail(kavail(i))%aMonth
itimer(3, i) = iavail(kavail(i))%aDay
itimer(4, i) = iavail(kavail(i))%aHour
itimer(5, i) = iavail(kavail(i))%fcHour
end do

!..get valid time (with forecast=0)
call vtime(itimer(1, 1), ierror)
call vtime(itimer(1, 2), ierror)

!..adjust hours to hours since first available time
zeroHour = iavail(kavail(1))%oHour
do i = 1, navail
iavail(i)%oHour = iavail(i)%oHour - zeroHour
end do

if (idebug == 1) then
write (iulog, *)
write (iulog, *) 'FILESORT------------------------------------------'
!..debug message of forward list
j = kavail(1)
do while (j > 0)
write (iulog, *) "file info forward", j, ": ", iavail(j)%aYear, &
iavail(j)%aMonth, &
iavail(j)%aDay, iavail(j)%aHour, trim(filef(iavail(j)%fileNo))
j = iavail(j)%nAvail
end do

write (iulog, *)
write (iulog, *) 'FILESORT--backward--------------------------------'
j = kavail(2)
do while (j > 0)
write (iulog, *) "file info backward", j, ": ", iavail(j)%aYear, &
iavail(j)%aMonth, &
iavail(j)%aDay, iavail(j)%aHour, trim(filef(iavail(j)%fileNo))
j = iavail(j)%pAvail
end do
end if

RETURN
end subroutine filesort_fi
end module filesort_fiML
2 changes: 1 addition & 1 deletion src/common/filesort_nc.f90
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ subroutine filesort_nc
CYCLE
end if
navail = navail + 1
if(navail > mavail) then
if(navail >= mavail) then
if (navail == mavail) then
write(iulog,*) 'WARNING : TOO MANY AVAILABLE TIME STEPS'
write(iulog,*) ' no.,max(MAVAIL): ',navail,mavail
Expand Down
14 changes: 10 additions & 4 deletions src/common/snap.F90
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ PROGRAM bsnap
USE readfield_ncML, only: readfield_nc
#if defined(FIMEX)
USE readfield_fiML, only: fi_init, readfield_fi
USE filesort_fiML, only: filesort_fi
#endif
USE releasefileML, only: releasefile
USE filesort_ncML, only: filesort_nc
Expand Down Expand Up @@ -380,8 +381,12 @@ PROGRAM bsnap

!..check input FELT files and make sorted lists of available data
!..make main list based on x wind comp. (u) in upper used level
if (ftype == "netcdf" .or. ftype == "fimex") then
if (ftype == "netcdf") then
call filesort_nc ! (iunitf, ierror)
else if (ftype == "fimex") then
#if defined(FIMEX)
call filesort_fi(fimex_type, fimex_config)
#endif
else
call filesort(iunitf, ierror)
end if
Expand Down Expand Up @@ -647,7 +652,7 @@ PROGRAM bsnap
! b END
#endif

! reset readfield_nc (eventually, traj will rerun this loop)
! reset readfield_nc (eventually, traj will rerun this loop)
if (ftype == "netcdf") then
call readfield_nc(-1, nhleft, itimei, ihr1, ihr2, &
time_file, ierror)
Expand Down Expand Up @@ -1857,7 +1862,7 @@ subroutine read_inputfile(snapinput_unit)
if (.not. has_value) goto 12
read (cinput(pname_start:pname_end), *, err=12) maxhfc
case ('field.type')
!..field.type felt or netcdf
!..field.type felt, netcdf or fimex
if (.not. has_value) goto 12
read (cinput(pname_start:pname_end), *, err=12) ftype
case ('fimex.config')
Expand All @@ -1869,7 +1874,7 @@ subroutine read_inputfile(snapinput_unit)
if (.not. has_value) then
fimex_config = ""
else
read (cinput(pname_start:pname_end), *, err=12) fimex_config
fimex_config = cinput(pname_start:pname_end)
endif
case ('fimex.file_type')
!..fimex.file_type grib,netcdf,felt,ncml (known fimex filetypes), only used when ftype=fimex
Expand Down Expand Up @@ -1983,6 +1988,7 @@ subroutine read_inputfile(snapinput_unit)
end if
nlevel = size(klevel)
nk = nlevel
write (error_unit, *) "autodetection of grid-param: ", gparam
case ('end')
!..end
#if defined(TRAJ)
Expand Down
4 changes: 3 additions & 1 deletion src/common/snap.mk
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ else
endif
ifdef FIMEXLIB
F77FLAGS += -DFIMEX
MODELOBJ += readfield_fi.o find_parameters_fi.o fimex.o
MODELOBJ += readfield_fi.o filesort_fi.o find_parameters_fi.o fimex.o
endif


Expand Down Expand Up @@ -85,6 +85,8 @@ readfield_fi.o: ../common/readfield_fi.f90 particleML.o snapfilML.o snapgrdML.o
${F77} -c ${F77FLAGS} $(INCLUDES) $<
filesort_nc.o: ../common/filesort_nc.f90 dateCalc.o snapfilML.o snapdimML.o snapgrdML.o snapfldML.o snapmetML.o snapdebugML.o readfield_nc.o
${F77} -c ${F77FLAGS} $(INCLUDES) $<
filesort_fi.o: ../common/filesort_fi.f90 dateCalc.o snapfilML.o snapdimML.o snapgrdML.o snapfldML.o snapmetML.o snapdebugML.o readfield_fi.o
${F77} -c ${F77FLAGS} $(INCLUDES) $<
find_parameters.o: ../common/find_parameters.f90 snapmetML.o
${F77} -c ${F77FLAGS} $(INCLUDES) $<
find_parameters_fi.o: ../common/find_parameters_fi.f90 snapmetML.o fimex.o
Expand Down
1 change: 1 addition & 0 deletions src/common/snapmetML.f90
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ subroutine init_meteo_params(nctype, ierr)
met_params%precconaccumv = 'lwe_thickness_of_convective_precipitation_amount_acc'
met_params%precstrativrt = ''
met_params%precconvrt = ''
!..get grid parameters from field identification
case('SLIM')
met_params%manual_level_selection = .true.
met_params%has_dummy_dim = .true.
Expand Down
Loading

0 comments on commit 253e498

Please sign in to comment.