diff --git a/src/LIB/SURCOUCHE/src/mode_io_write_nc4.f90 b/src/LIB/SURCOUCHE/src/mode_io_write_nc4.f90 index a86fe8d36973710430362abb4e16d3ee8cfd3cb7..3ba78f506ce4189182277df320f15622373dfe4c 100644 --- a/src/LIB/SURCOUCHE/src/mode_io_write_nc4.f90 +++ b/src/LIB/SURCOUCHE/src/mode_io_write_nc4.f90 @@ -2279,12 +2279,16 @@ subroutine Write_flyer_time_coord( tpflyer ) use NETCDF use modd_aircraft_balloon - use modd_parameters, only: XUNDEF + use modd_parameters, only: NBUNAMELGTMAX, XUNDEF + + use modi_aircraft_balloon, only: Aircraft_balloon_longtype_get type(flyer), intent(in) :: tpflyer + character(len=NBUNAMELGTMAX) :: ytype integer :: istatus integer(kind=CDFINT) :: icatid + integer(kind=CDFINT) :: isubcatid integer(kind=CDFINT) :: idimid type(tdimnc), pointer :: tzdim @@ -2300,7 +2304,14 @@ subroutine Write_flyer_time_coord( tpflyer ) Trim( tpfile%cname ) // ': group Flyers not found' ) end if - istatus = NF90_INQ_NCID( icatid, Trim( tpflyer%title ), incid ) + call Aircraft_balloon_longtype_get( tpflyer, ytype ) + istatus = NF90_INQ_NCID( icatid, Trim( ytype ), isubcatid ) + if ( istatus /= NF90_NOERR ) then + call Print_msg( NVERB_ERROR, 'IO', 'Write_flyer_time_coord', & + Trim( tpfile%cname ) // ': group ' // Trim( ytype ) // ' not found' ) + end if + + istatus = NF90_INQ_NCID( isubcatid, Trim( tpflyer%title ), incid ) if ( istatus /= NF90_NOERR ) then call Print_msg( NVERB_ERROR, 'IO', 'Write_flyer_time_coord', & Trim( tpfile%cname ) // ': group '// Trim( tpflyer%title ) // ' not found' ) @@ -2321,7 +2332,7 @@ subroutine Write_flyer_time_coord( tpflyer ) !Group with flyer title suffixed by Z - istatus = NF90_INQ_NCID( icatid, Trim( tpflyer%title ) // 'Z' , incid ) + istatus = NF90_INQ_NCID( isubcatid, Trim( tpflyer%title ) // 'Z' , incid ) if ( istatus /= NF90_NOERR ) then call Print_msg( NVERB_ERROR, 'IO', 'Write_flyer_time_coord', & Trim( tpfile%cname ) // ': group '// Trim( tpflyer%title ) // 'Z not found' ) diff --git a/src/MNH/write_diachro.f90 b/src/MNH/write_diachro.f90 index 35bc5a584553e5b2c84f22ece752a819e5a7dbac..746440e232a37fe9a1ace5ad2826580789543e0d 100644 --- a/src/MNH/write_diachro.f90 +++ b/src/MNH/write_diachro.f90 @@ -712,22 +712,39 @@ end subroutine Write_diachro_lfi !----------------------------------------------------------------------------- subroutine Write_diachro_nc4( tpdiafile, tpbudiachro, tpfields, pvar, osplit, tpflyer ) -use NETCDF, only: NF90_DEF_DIM, NF90_DEF_GRP, NF90_DEF_VAR, NF90_INQ_NCID, NF90_PUT_ATT, NF90_PUT_VAR, & - NF90_GLOBAL, NF90_NOERR, NF90_STRERROR +use NETCDF, only: NF90_DEF_DIM, NF90_NOERR use modd_aircraft_balloon, only: flyer -use modd_budget, only: nbutshift, nbusubwrite, tbudiachrometadata +use modd_budget, only: CNOTSET, nbutshift, nbusubwrite, tbudiachrometadata use modd_conf, only: lcartesian use modd_field use modd_io, only: isp, tfiledata use modd_les, only: cbl_height_def, cles_norm_type, nles_masks, xles_temp_sampling -use modd_parameters, only: jphext +use modd_parameters, only: jphext, NBUNAMELGTMAX, NCOMMENTLGTMAX use modd_precision, only: CDFINT, MNHREAL_NF90 use modd_type_date, only: date_time use mode_io_field_write, only: IO_Field_create, IO_Field_write, IO_Field_write_box use mode_io_tools_nc4, only: IO_Err_handle_nc4 +integer, parameter :: NMAXLEVELS = 7 +integer, parameter :: NLVL_ROOT = 0 +integer, parameter :: NLVL_CATEGORY = 1 +integer, parameter :: NLVL_SUBCATEGORY = 2 +integer, parameter :: NLVL_GROUP = 3 +integer, parameter :: NLVL_SHAPE = 4 +integer, parameter :: NLVL_TIMEAVG = 5 +integer, parameter :: NLVL_NORM = 6 +integer, parameter :: NLVL_MASK = 7 +character(len=*), dimension(NMAXLEVELS), parameter :: CNCGROUPNAMES = [ & + 'category ', & !Name of the different type of groups/levels in the netCDF file + 'subcategory', & + 'group ', & + 'shape ', & + 'timeavg ', & + 'norm ', & + 'mask ' ] + type(tfiledata), intent(in) :: tpdiafile ! File to write type(tbudiachrometadata), intent(in) :: tpbudiachro class(tfield_metadata_base), dimension(:), intent(in) :: tpfields @@ -736,28 +753,32 @@ logical, intent(in), optional :: osp type(flyer), intent(in), optional :: tpflyer character(len=:), allocatable :: ycategory -character(len=:), allocatable :: ycategcomment !Comment for category in the netCDF file -character(len=:), allocatable :: ycategnc !Name of the group for category in the netCDF file +character(len=:), allocatable :: ylevelname +character(len=:), allocatable :: ylevels character(len=:), allocatable :: yshape character(len=:), allocatable :: ygroup character(len=:), allocatable :: ystdnameprefix -integer :: iil, iih, ijl, ijh, ikl, ikh -integer :: idims -integer :: icount -integer :: icorr -integer :: ji -integer :: jp -integer(kind=CDFINT) :: isavencid -integer(kind=CDFINT) :: idimid -integer(kind=CDFINT) :: icatid -integer(kind=CDFINT) :: igrpid -integer(kind=CDFINT) :: istatus -logical :: gdistributed -logical :: gcategdefined -logical :: ggroupdefined -logical :: gsplit -type(tfielddata) :: tzfield -type(tfiledata) :: tzfile +character(len=NBUNAMELGTMAX), dimension(NMAXLEVELS) :: ylevelnames !Name of the different groups/levels in the netCDF file +character(len=NCOMMENTLGTMAX), dimension(NMAXLEVELS) :: ylevelcomments !Comments for the different groups/levels in the netCDF file +integer :: iil, iih, ijl, ijh, ikl, ikh +integer :: idims +integer :: icount +integer :: icorr +integer :: ji +integer :: jl +integer :: jp +integer(kind=CDFINT) :: idimid +integer(kind=CDFINT) :: istatus +integer(kind=CDFINT) :: ilevelid +integer(kind=CDFINT), dimension(0:NMAXLEVELS) :: ilevelids ! ids of the different groups/levels in the netCDF file +logical :: gdistributed +logical :: gsplit +logical(kind=CDFINT), dimension(NMAXLEVELS) :: gleveluse ! Are the different groups/levels in the netCDF file used? +logical(kind=CDFINT), dimension(0:NMAXLEVELS) :: gleveldefined ! Are the different groups/levels already defined in the netCDF file +type(tfielddata) :: tzfield +type(tfiledata) :: tzfile + +call Print_msg( NVERB_DEBUG, 'BUD', 'Write_diachro_nc4', 'called' ) tzfile = tpdiafile @@ -790,230 +811,321 @@ else end if MASTER: if ( isp == tzfile%nmaster_rank) then - gcategdefined = .false. - ggroupdefined = .false. + ilevelids(NLVL_ROOT) = tzfile%nncid + + gleveldefined(NLVL_ROOT) = .false. + + gleveldefined(NLVL_CATEGORY) = .false. + gleveldefined(NLVL_SUBCATEGORY) = .false. + gleveldefined(NLVL_GROUP) = .false. + gleveldefined(NLVL_SHAPE) = .false. + gleveldefined(NLVL_TIMEAVG) = .false. + gleveldefined(NLVL_NORM) = .false. + gleveldefined(NLVL_MASK) = .false. + + ylevelnames(:) = '' + ylevelcomments(:) = '' select case ( ycategory ) case ( 'budget' ) - ycategnc = 'Budgets' - ycategcomment = 'Group for the different budgets' + gleveluse(NLVL_CATEGORY) = .true. + ylevelnames(NLVL_CATEGORY) = 'Budgets' + ylevelcomments(NLVL_CATEGORY) = 'Group for the different budgets' + + gleveluse(NLVL_SUBCATEGORY) = .false. + + gleveluse(NLVL_GROUP) = .true. + ylevelnames(NLVL_GROUP) = Trim( tpbudiachro%cgroupname ) + + gleveluse(NLVL_SHAPE) = .false. + ylevelnames(NLVL_SHAPE) = Trim( tpbudiachro%cshape ) + + gleveluse(NLVL_TIMEAVG) = .false. + if ( tpbudiachro%ltcompress ) then + ylevelnames(NLVL_TIMEAVG) = 'time averaged' + else + ylevelnames(NLVL_TIMEAVG) = 'not time averaged' + end if + + gleveluse(NLVL_NORM) = .false. + if ( tpbudiachro%lnorm ) then + ylevelnames(NLVL_NORM) = 'normalized' + else + ylevelnames(NLVL_NORM) = 'not normalized' + end if + + gleveluse(NLVL_MASK) = .false. + ylevelnames(NLVL_MASK) = tpbudiachro%cmask case ( 'LES' ) - ycategnc = 'LES budgets' - ycategcomment = 'Group for the different LES budgets' + gleveluse(NLVL_CATEGORY) = .true. + ylevelnames(NLVL_CATEGORY) = 'LES budgets' + ylevelcomments(NLVL_CATEGORY) = 'Group for the different LES budgets' + + gleveluse(NLVL_SUBCATEGORY) = .false. + gleveluse(NLVL_GROUP) = .false. + + gleveluse(NLVL_SHAPE) = .true. + ylevelnames(NLVL_SHAPE) = Trim( tpbudiachro%cshape ) + + gleveluse(NLVL_TIMEAVG) = .true. + if ( tpbudiachro%ltcompress ) then + ylevelnames(NLVL_TIMEAVG) = 'time averaged' + else + ylevelnames(NLVL_TIMEAVG) = 'not time averaged' + end if + + gleveluse(NLVL_NORM) = .true. + if ( tpbudiachro%lnorm ) then + ylevelnames(NLVL_NORM) = 'normalized' + else + ylevelnames(NLVL_NORM) = 'not normalized' + end if + + if ( tpbudiachro%cshape == 'cartesian' ) then + if ( tpbudiachro%cmask == CNOTSET ) then + call Print_msg( NVERB_WARNING, 'IO', 'Write_diachro_nc4', 'mask not set for ' // ygroup ) + gleveluse(NLVL_MASK) = .false. + else + gleveluse(NLVL_MASK) = .true. + ylevelnames(NLVL_MASK) = tpbudiachro%cmask + end if + else + gleveluse(NLVL_MASK) = .false. + end if case ( 'profiler' ) - ycategnc = 'Profilers' - ycategcomment = 'Group for the different vertical profilers' + gleveluse(NLVL_CATEGORY) = .true. + ylevelnames(NLVL_CATEGORY) = 'Profilers' + ylevelcomments(NLVL_CATEGORY) = 'Group for the different vertical profilers' + + gleveluse(NLVL_SUBCATEGORY) = .false. + + gleveluse(NLVL_GROUP) = .true. + ylevelnames(NLVL_GROUP) = Trim( tpbudiachro%cgroupname ) + + gleveluse(NLVL_SHAPE) = .false. + ylevelnames(NLVL_SHAPE) = Trim( tpbudiachro%cshape ) + + gleveluse(NLVL_TIMEAVG) = .false. + gleveluse(NLVL_NORM) = .false. + gleveluse(NLVL_MASK) = .false. case ( 'station' ) - ycategnc = 'Stations' - ycategcomment = 'Group for the different stations' + gleveluse(NLVL_CATEGORY) = .true. + ylevelnames(NLVL_CATEGORY) = 'Stations' + ylevelcomments(NLVL_CATEGORY) = 'Group for the different stations' + + gleveluse(NLVL_SUBCATEGORY) = .false. + + gleveluse(NLVL_GROUP) = .true. + ylevelnames(NLVL_GROUP) = Trim( tpbudiachro%cgroupname ) + + gleveluse(NLVL_SHAPE) = .false. + ylevelnames(NLVL_SHAPE) = Trim( tpbudiachro%cshape ) + + gleveluse(NLVL_TIMEAVG) = .false. + gleveluse(NLVL_NORM) = .false. + gleveluse(NLVL_MASK) = .false. case( 'aircraft', 'radiosonde balloon', 'iso-density balloon', 'constant volume balloon' ) - ycategnc = 'Flyers' - ycategcomment = 'Group for the different flyers (aircrafts and balloons)' + gleveluse(NLVL_CATEGORY) = .true. + ylevelnames(NLVL_CATEGORY) = 'Flyers' + ylevelcomments(NLVL_CATEGORY) = 'Group for the different flyers (aircrafts and balloons)' + + gleveluse(NLVL_SUBCATEGORY) = .true. + ylevelnames(NLVL_SUBCATEGORY) = ycategory + ylevelcomments(NLVL_SUBCATEGORY) = 'Group for the different ' // Trim( ycategory ) // 's' + + gleveluse(NLVL_GROUP) = .true. + ylevelnames(NLVL_GROUP) = Trim( tpbudiachro%cgroupname ) + + gleveluse(NLVL_SHAPE) = .true. + ylevelnames(NLVL_SHAPE) = Trim( tpbudiachro%cshape ) + + gleveluse(NLVL_TIMEAVG) = .false. + + gleveluse(NLVL_NORM) = .false. + + gleveluse(NLVL_MASK) = .false. case ( 'time series' ) - ycategnc = 'Time series' - ycategcomment = 'Group for the different time series' + gleveluse(NLVL_CATEGORY) = .true. + ylevelnames(NLVL_CATEGORY) = 'Time series' + ylevelcomments(NLVL_CATEGORY) = 'Group for the different time series' + + gleveluse(NLVL_SUBCATEGORY) = .false. + + gleveluse(NLVL_GROUP) = .true. + ylevelnames(NLVL_GROUP) = Trim( tpbudiachro%cgroupname ) + + gleveluse(NLVL_SHAPE) = .false. + ylevelnames(NLVL_SHAPE) = Trim( tpbudiachro%cshape ) + + gleveluse(NLVL_TIMEAVG) = .false. + gleveluse(NLVL_NORM) = .false. + + if ( Trim( tpbudiachro%cgroupname ) == 'TSERIES' .or. Trim( tpbudiachro%cgroupname ) == 'ZTSERIES' ) then + gleveluse(NLVL_MASK) = .true. + ylevelnames(NLVL_MASK) = tpbudiachro%cmask + else + gleveluse(NLVL_MASK) = .false. + end if case default call Print_msg( NVERB_ERROR, 'IO', 'Write_diachro_nc4', 'unknown category ' // ycategory // ' for group ' // ygroup ) return end select - istatus = NF90_INQ_NCID( tzfile%nncid, ycategnc, icatid ) - if ( istatus == NF90_NOERR ) then - gcategdefined = .true. - else - istatus = NF90_DEF_GRP( tzfile%nncid, ycategnc, icatid ) - if ( istatus /= NF90_NOERR ) & - call IO_Err_handle_nc4( istatus, 'Write_diachro_nc4', 'NF90_DEF_GRP', 'for ' // ycategnc // ' category' ) - end if + do jl = 1, NMAXLEVELS + call Move_to_next_level( ilevelids(jl-1), gleveldefined(jl-1), gleveluse(jl), & + ylevelnames(jl), gleveldefined(jl), ilevelids(jl) ) + end do - istatus = NF90_INQ_NCID( icatid, ygroup, igrpid ) - if ( istatus == NF90_NOERR ) then - ggroupdefined = .true. - if ( .not. gsplit ) then - call Print_msg( NVERB_WARNING, 'IO', 'Write_diachro_nc4', trim(tzfile%cname) // ': group ' // ygroup // ' already defined' ) + tzfile%nncid = ilevelids(NLVL_MASK) + + ylevels = '' + + do jl = NMAXLEVELS, 1, -1 + ylevels = Trim( CNCGROUPNAMES(jl) ) // ' ' // ylevels + if ( gleveluse(jl) ) then + call Att_write( ylevelnames(jl), ilevelids(jl), 'levels', Trim( ylevels ) ) + ylevels = '' end if - else - istatus = NF90_DEF_GRP( icatid, ygroup, igrpid ) - if ( istatus /= NF90_NOERR ) & - call IO_Err_handle_nc4( istatus, 'Write_diachro_nc4', 'NF90_DEF_GRP', 'for ' // ygroup // ' group' ) - end if + end do + + if ( .not. gleveldefined(NLVL_CATEGORY) ) then + ylevelname = ylevelnames(NLVL_CATEGORY) + ilevelid = ilevelids (NLVL_CATEGORY) + + call Att_write( ylevelname, ilevelid, 'category', ylevelname ) + if ( gleveluse(NLVL_CATEGORY) .and. Len_trim( ylevelcomments(NLVL_CATEGORY) ) > 0 ) & + call Att_write( ylevelname, ilevelid, 'comment', ylevelcomments(NLVL_CATEGORY) ) - !Save id of the file root group ('/' group) - isavencid = tzfile%nncid - tzfile%nncid = igrpid - - - if ( .not. gcategdefined ) then - call Att_write( ygroup, icatid, 'name', ycategnc ) - call Att_write( ygroup, icatid, 'comment', ycategcomment ) - if ( ycategnc /= 'Flyers' ) & - call Att_write( ygroup, icatid, 'category', ycategory ) - if ( ycategory /= 'LES' ) & - call Att_write( ygroup, icatid, 'shape', yshape ) - call Att_write( ygroup, icatid, 'moving', Merge( 'yes', 'no ', tpbudiachro%lmobile ) ) - call Att_write( ygroup, icatid, 'time averaged', Merge( 'yes', 'no ', tpbudiachro%ltcompress ) ) - call Att_write( ygroup, icatid, 'normalized', Merge( 'yes', 'no ', tpbudiachro%lnorm ) ) if ( ycategory == 'LES' ) & - call Att_write( ygroup, icatid, 'temporal sampling frequency', xles_temp_sampling ) + call Att_write( ylevelname, ilevelid, 'temporal sampling frequency', xles_temp_sampling ) + end if - if ( ycategory == 'budget' .and. yshape == 'cartesian' ) then - call Att_write( ygroup, icatid, 'min I index in physical domain', iil ) - call Att_write( ygroup, icatid, 'max I index in physical domain', iih ) - call Att_write( ygroup, icatid, 'min J index in physical domain', ijl ) - call Att_write( ygroup, icatid, 'max J index in physical domain', ijh ) - call Att_write( ygroup, icatid, 'min K index in physical domain', ikl ) - call Att_write( ygroup, icatid, 'max K index in physical domain', ikh ) + if ( .not. gleveldefined(NLVL_SUBCATEGORY) ) then + ylevelname = ylevelnames(NLVL_SUBCATEGORY) + ilevelid = ilevelids (NLVL_SUBCATEGORY) - call Att_write( ygroup, icatid, 'averaged in the I direction', Merge( 'yes', 'no ', tpbudiachro%licompress ) ) - call Att_write( ygroup, icatid, 'averaged in the J direction', Merge( 'yes', 'no ', tpbudiachro%ljcompress ) ) - call Att_write( ygroup, icatid, 'averaged in the K direction', Merge( 'yes', 'no ', tpbudiachro%lkcompress ) ) + call Att_write( ylevelname, ilevelid, 'subcategory', ylevelname ) + if ( gleveluse(NLVL_SUBCATEGORY) .and. Len_trim( ylevelcomments(NLVL_SUBCATEGORY) ) > 0 ) & + call Att_write( ylevelname, ilevelid, 'comment', ylevelcomments(NLVL_SUBCATEGORY) ) + end if - else if ( ycategory == 'budget' .and. yshape == 'mask' ) then - call Att_write( ygroup, icatid, 'masks are stored in variable', 'MASKS' ) - call Att_write( ygroup, icatid, 'averaged in the K direction', Merge( 1, 0, tpbudiachro%lkcompress ) ) + if ( .not. gleveldefined(NLVL_GROUP) ) then + ylevelname = ylevelnames(NLVL_GROUP) + ilevelid = ilevelids (NLVL_GROUP) - else if ( ycategory == 'LES' ) then - call Att_write( ygroup, icatid, 'min I index in physical domain', iil ) - call Att_write( ygroup, icatid, 'max I index in physical domain', iih ) - call Att_write( ygroup, icatid, 'min J index in physical domain', ijl ) - call Att_write( ygroup, icatid, 'max J index in physical domain', ijh ) + call Att_write( ylevelname, ilevelid, 'group', ylevelname ) + if ( gleveluse(NLVL_GROUP) .and. Len_trim( ylevelcomments(NLVL_GROUP) ) > 0 ) & + call Att_write( ylevelname, ilevelid, 'comment', ylevelcomments(NLVL_GROUP) ) + end if - else if ( ycategory == 'profiler' .and. yshape == 'vertical profile' ) then + if ( .not. gleveldefined(NLVL_SHAPE) ) then + ylevelname = ylevelnames(NLVL_SHAPE) + ilevelid = ilevelids (NLVL_SHAPE) + + call Att_write( ylevelname, ilevelid, 'shape', ylevelname ) + if ( gleveluse(NLVL_SHAPE) .and. Len_trim( ylevelcomments(NLVL_SHAPE) ) > 0 ) & + call Att_write( ylevelname, ilevelid, 'comment', ylevelcomments(NLVL_SHAPE) ) + + call Att_write( ylevelname, ilevelid, 'moving', Merge( 'yes', 'no ', tpbudiachro%lmobile ) ) + + if ( ( ycategory == 'budget' .and. yshape == 'cartesian' ) & + .or. ycategory == 'LES' & + .or. tpbudiachro%cgroupname == 'TSERIES' & + .or. tpbudiachro%cgroupname == 'ZTSERIES' & + .or. tpbudiachro%cgroupname(1:8) == 'XTSERIES' ) then + call Att_write( ylevelname, ilevelid, 'min I index in physical domain', iil ) + call Att_write( ylevelname, ilevelid, 'max I index in physical domain', iih ) + call Att_write( ylevelname, ilevelid, 'min J index in physical domain', ijl ) + call Att_write( ylevelname, ilevelid, 'max J index in physical domain', ijh ) + end if - else if ( ycategory == 'station' .and. yshape == 'point' ) then + if ( ( ycategory == 'budget' .and. yshape == 'cartesian' ) & + .or. tpbudiachro%cgroupname == 'TSERIES' & + .or. tpbudiachro%cgroupname == 'ZTSERIES' & + .or. tpbudiachro%cgroupname(1:8) == 'XTSERIES' ) then + call Att_write( ylevelname, ilevelid, 'min K index in physical domain', ikl ) + call Att_write( ylevelname, ilevelid, 'max K index in physical domain', ikh ) + end if - else if ( ycategory == 'time series' ) then + if ( ( ycategory == 'budget' .and. yshape == 'cartesian' ) & + .or. ( ycategory == 'LES' .and. yshape == 'cartesian' ) & + .or. tpbudiachro%cgroupname == 'TSERIES' & + .or. tpbudiachro%cgroupname == 'ZTSERIES' & + .or. tpbudiachro%cgroupname(1:8) == 'XTSERIES' ) then + call Att_write( ylevelname, ilevelid, & + 'averaged in the I direction', Merge( 'yes', 'no ', tpbudiachro%licompress ) ) + call Att_write( ylevelname, ilevelid, & + 'averaged in the J direction', Merge( 'yes', 'no ', tpbudiachro%ljcompress ) ) + call Att_write( ylevelname, ilevelid, & + 'averaged in the K direction', Merge( 'yes', 'no ', tpbudiachro%lkcompress ) ) end if end if - if ( .not. ggroupdefined ) then - call Att_write( ygroup, igrpid, 'name', tpbudiachro%cname ) - call Att_write( ygroup, igrpid, 'comment', tpbudiachro%ccomment ) + if ( .not. gleveldefined(NLVL_TIMEAVG) ) then + ylevelname = ylevelnames(NLVL_TIMEAVG) + ilevelid = ilevelids (NLVL_TIMEAVG) - if ( ycategory == 'budget' .and. yshape == 'cartesian' ) then + if ( gleveluse(NLVL_TIMEAVG) .and. Len_trim( ylevelcomments(NLVL_TIMEAVG) ) > 0 ) & + call Att_write( ylevelname, ilevelid, 'comment', ylevelcomments(NLVL_TIMEAVG) ) + call Att_write( ylevelname, ilevelid, 'time averaged', Merge( 'yes', 'no ', tpbudiachro%ltcompress ) ) + end if - else if ( ycategory == 'budget' .and. yshape == 'mask' ) then + if ( .not. gleveldefined(NLVL_NORM) ) then + ylevelname = ylevelnames(NLVL_NORM) + ilevelid = ilevelids (NLVL_NORM) - else if ( ycategory == 'LES' .and. yshape == 'cartesian' ) then - call Att_write( ygroup, igrpid, 'shape', yshape ) + if ( gleveluse(NLVL_NORM) .and. Len_trim( ylevelcomments(NLVL_NORM) ) > 0 ) & + call Att_write( ylevelname, ilevelid, 'comment', ylevelcomments(NLVL_NORM) ) - call Att_write( ygroup, igrpid, 'averaged in the I direction', Merge( 'yes', 'no ', tpbudiachro%licompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the J direction', Merge( 'yes', 'no ', tpbudiachro%ljcompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the K direction', Merge( 'yes', 'no ', tpbudiachro%lkcompress ) ) + call Att_write( ylevelname, ilevelid, 'normalized', Merge( 'yes', 'no ', tpbudiachro%lnorm ) ) + if ( ycategory == 'LES' .and. yshape == 'cartesian' ) then if ( tpbudiachro%lnorm ) then if ( cles_norm_type == 'NONE' ) then - call Att_write( ygroup, igrpid, 'normalization', 'none' ) + call Att_write( ylevelname, ilevelid, 'normalization', 'none' ) else if ( cles_norm_type == 'CONV' ) then - call Att_write( ygroup, igrpid, 'normalization', 'convective' ) + call Att_write( ylevelname, ilevelid, 'normalization', 'convective' ) ! cbl_height_def determines how the boundary layer height is computed, which is used in this normalization - call Att_write( ygroup, igrpid, 'definition of boundary layer height', cbl_height_def ) + call Att_write( ylevelname, ilevelid, 'definition of boundary layer height', cbl_height_def ) else if ( cles_norm_type == 'EKMA' ) then - call Att_write( ygroup, igrpid, 'normalization', 'Ekman' ) + call Att_write( ylevelname, ilevelid, 'normalization', 'Ekman' ) ! cbl_height_def determines how the boundary layer height is computed, which is used in this normalization - call Att_write( ygroup, igrpid, 'definition of boundary layer height', cbl_height_def ) + call Att_write( ylevelname, ilevelid, 'definition of boundary layer height', cbl_height_def ) else if ( cles_norm_type == 'MOBU' ) then - call Att_write( ygroup, igrpid, 'normalization', 'Monin-Obukhov' ) + call Att_write( ylevelname, ilevelid, 'normalization', 'Monin-Obukhov' ) else call Print_msg( NVERB_WARNING, 'IO', 'Write_diachro_nc4', Trim( tzfile%cname ) // & ': group ' // Trim( ygroup ) // ': unknown normalization' ) - call Att_write( ygroup, igrpid, 'normalization', 'unknown' ) + call Att_write( ylevelname, ilevelid, 'normalization', 'unknown' ) end if else - call Att_write( ygroup, igrpid, 'normalization', 'none' ) + call Att_write( ylevelname, ilevelid, 'normalization', 'none' ) end if + end if + end if - else if ( ycategory == 'LES' .and. yshape == '2-point correlation' ) then - call Att_write( ygroup, igrpid, 'shape', yshape ) - - call Att_write( ygroup, igrpid, 'direction of 2-point correlation', tpbudiachro%cdirection ) - - - else if ( ycategory == 'LES' .and. yshape == 'spectrum' ) then - call Att_write( ygroup, igrpid, 'shape', yshape ) - - call Att_write( ygroup, igrpid, 'direction of spectrum', tpbudiachro%cdirection ) - - - else if ( ( ycategory == 'aircraft' & - .or. ycategory == 'radiosonde balloon' & - .or. ycategory == 'iso-density balloon' & - .or. ycategory == 'constant volume balloon' ) & - .and. yshape == 'point' ) then - call Att_write( ygroup, igrpid, 'category', ycategory ) - else if ( ( ycategory == 'aircraft' & - .or. ycategory == 'radiosonde balloon' & - .or. ycategory == 'iso-density balloon' & - .or. ycategory == 'constant volume balloon' ) & - .and. yshape == 'vertical profile' ) then - call Att_write( ygroup, igrpid, 'category', ycategory ) - - - else if ( ycategory == 'profiler' .and. yshape == 'vertical profile' ) then - - else if ( ycategory == 'station' .and. yshape == 'point' ) then - - else if ( tpbudiachro%cgroupname == 'TSERIES' ) then - call Att_write( ygroup, igrpid, 'min I index in physical domain', iil ) - call Att_write( ygroup, igrpid, 'max I index in physical domain', iih ) - call Att_write( ygroup, igrpid, 'min J index in physical domain', ijl ) - call Att_write( ygroup, igrpid, 'max J index in physical domain', ijh ) - call Att_write( ygroup, igrpid, 'min K index in physical domain', ikl ) - call Att_write( ygroup, igrpid, 'max K index in physical domain', ikh ) - - call Att_write( ygroup, igrpid, 'averaged in the I direction', Merge( 'yes', 'no ', tpbudiachro%licompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the J direction', Merge( 'yes', 'no ', tpbudiachro%ljcompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the K direction', Merge( 'yes', 'no ', tpbudiachro%lkcompress ) ) - - else if ( tpbudiachro%cgroupname == 'ZTSERIES' ) then - call Att_write( ygroup, igrpid, 'min I index in physical domain', iil ) - call Att_write( ygroup, igrpid, 'max I index in physical domain', iih ) - call Att_write( ygroup, igrpid, 'min J index in physical domain', ijl ) - call Att_write( ygroup, igrpid, 'max J index in physical domain', ijh ) - call Att_write( ygroup, igrpid, 'min K index in physical domain', ikl ) - call Att_write( ygroup, igrpid, 'max K index in physical domain', ikh ) + if ( .not. gleveldefined(NLVL_MASK) ) then + ylevelname = ylevelnames(NLVL_MASK) + ilevelid = ilevelids (NLVL_MASK) - call Att_write( ygroup, igrpid, 'averaged in the I direction', Merge( 'yes', 'no ', tpbudiachro%licompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the J direction', Merge( 'yes', 'no ', tpbudiachro%ljcompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the K direction', Merge( 'yes', 'no ', tpbudiachro%lkcompress ) ) + call Att_write( ylevelname, ilevelid, 'mask', ylevelname ) + if ( gleveluse(NLVL_MASK) .and. Len_trim( ylevelcomments(NLVL_MASK) ) > 0 ) & + call Att_write( ylevelname, ilevelid, 'comment', ylevelcomments(NLVL_MASK) ) - else if ( tpbudiachro%cgroupname(1:8) == 'XTSERIES' ) then - call Att_write( ygroup, igrpid, 'min I index in physical domain', iil ) - call Att_write( ygroup, igrpid, 'max I index in physical domain', iih ) - call Att_write( ygroup, igrpid, 'min J index in physical domain', ijl ) - call Att_write( ygroup, igrpid, 'max J index in physical domain', ijh ) - call Att_write( ygroup, igrpid, 'min K index in physical domain', ikl ) - call Att_write( ygroup, igrpid, 'max K index in physical domain', ikh ) + if ( ycategory == 'budget' .and. yshape == 'mask' ) & + call Att_write( ylevelname, ilevelid, 'masks are stored in variable', tpbudiachro%cmask ) + end if - call Att_write( ygroup, igrpid, 'averaged in the I direction', Merge( 'yes', 'no ', tpbudiachro%licompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the J direction', Merge( 'yes', 'no ', tpbudiachro%ljcompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the K direction', Merge( 'yes', 'no ', tpbudiachro%lkcompress ) ) - else - call Print_msg( NVERB_WARNING, 'IO', 'Write_diachro_nc4', & - 'unknown group definition for ' // Trim( tpbudiachro%cname ) // ': using default behavior' ) - - call Att_write( ygroup, igrpid, 'min I index in physical domain', iil ) - call Att_write( ygroup, igrpid, 'max I index in physical domain', iih ) - call Att_write( ygroup, igrpid, 'min J index in physical domain', ijl ) - call Att_write( ygroup, igrpid, 'max J index in physical domain', ijh ) - call Att_write( ygroup, igrpid, 'min K index in physical domain', ikl ) - call Att_write( ygroup, igrpid, 'max K index in physical domain', ikh ) - - call Att_write( ygroup, igrpid, 'averaged in the I direction', Merge( 'yes', 'no ', tpbudiachro%licompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the J direction', Merge( 'yes', 'no ', tpbudiachro%ljcompress ) ) - call Att_write( ygroup, igrpid, 'averaged in the K direction', Merge( 'yes', 'no ', tpbudiachro%lkcompress ) ) - end if - end if end if MASTER @@ -1184,7 +1296,7 @@ select case ( idims ) !Correspond to FLYER_DIACHRO !Create local time dimension if ( isp == tzfile%nmaster_rank) then - istatus = NF90_DEF_DIM( igrpid, 'time_flyer', Int( Size( pvar, 4), kind = CDFINT ), idimid ) + istatus = NF90_DEF_DIM( ilevelids(NLVL_GROUP), 'time_flyer', Int( Size( pvar, 4), kind = CDFINT ), idimid ) if ( istatus /= NF90_NOERR ) & call IO_Err_handle_nc4( istatus, 'Write_diachro_nc4', 'NF90_DEF_DIM', Trim( tpfields(1)%cmnhname ) ) end if @@ -1315,7 +1427,7 @@ select case ( idims ) !Correspond to FLYER_DIACHRO !Create local time dimension if ( isp == tzfile%nmaster_rank) then - istatus = NF90_DEF_DIM( igrpid, 'time_flyer', Int( Size( pvar, 4), kind = CDFINT ), idimid ) + istatus = NF90_DEF_DIM( ilevelids(NLVL_GROUP), 'time_flyer', Int( Size( pvar, 4), kind = CDFINT ), idimid ) if ( istatus /= NF90_NOERR ) & call IO_Err_handle_nc4( istatus, 'Write_diachro_nc4', 'NF90_DEF_DIM', Trim( tpfields(1)%cmnhname ) ) end if @@ -1484,10 +1596,7 @@ end if -! -!Restore id of the file root group ('/' group) -tzfile%nncid = isavencid end subroutine Write_diachro_nc4 @@ -1956,6 +2065,42 @@ if (istatus /= NF90_NOERR ) & call IO_Err_handle_nc4( istatus, 'Write_diachro_nc4', 'NF90_PUT_ATT', Trim( hattname ) // ' for '// Trim( hlevel ) // ' group' ) end subroutine Att_write_x0 + + +subroutine Move_to_next_level( kpreviouslevelid, gpreviousleveldefined, oleveluse, hlevelname, gleveldefined, klevelid ) +use NETCDF, only: NF90_DEF_GRP, NF90_INQ_NCID, NF90_NOERR + +use modd_precision, only: CDFINT + +use mode_io_tools_nc4, only: IO_Err_handle_nc4 + +integer(kind=CDFINT), intent(in) :: kpreviouslevelid +logical, intent(in) :: gpreviousleveldefined +logical, intent(in) :: oleveluse +character(len=*), intent(inout) :: hlevelname +logical, intent(out) :: gleveldefined +integer(kind=CDFINT), intent(out) :: klevelid + +integer(kind=CDFINT) :: istatus + + +if ( oleveluse ) then + istatus = NF90_INQ_NCID( kpreviouslevelid, Trim( hlevelname ), klevelid ) + if ( istatus == NF90_NOERR ) then + gleveldefined = .true. + else + gleveldefined = .false. + istatus = NF90_DEF_GRP( kpreviouslevelid, Trim( hlevelname ), klevelid ) + if ( istatus /= NF90_NOERR ) & + call IO_Err_handle_nc4( istatus, 'Move_to_next_level', 'NF90_DEF_GRP', 'for ' // Trim( hlevelname ) ) + end if +else + gleveldefined = gpreviousleveldefined + if ( Len_trim( hlevelname ) == 0 ) hlevelname = '(unused)' + klevelid = kpreviouslevelid +end if + +end subroutine Move_to_next_level #endif end module mode_write_diachro