From f687f3e1f3780c2ca162a666983b6d79e2989234 Mon Sep 17 00:00:00 2001 From: Philippe WAUTELET <philippe.wautelet@aero.obs-mip.fr> Date: Thu, 14 Jan 2021 15:39:48 +0100 Subject: [PATCH] Philippe 14/01/2021: IO: add IO_Field_write_byname_N4 and IO_Field_write_byfield_N4 subroutines --- src/LIB/SURCOUCHE/src/mode_io_field_write.f90 | 227 +++++++++++++++++- 1 file changed, 223 insertions(+), 4 deletions(-) diff --git a/src/LIB/SURCOUCHE/src/mode_io_field_write.f90 b/src/LIB/SURCOUCHE/src/mode_io_field_write.f90 index 16670f0c1..387a900a9 100644 --- a/src/LIB/SURCOUCHE/src/mode_io_field_write.f90 +++ b/src/LIB/SURCOUCHE/src/mode_io_field_write.f90 @@ -1,4 +1,4 @@ -!MNH_LIC Copyright 1994-2020 CNRS, Meteo-France and Universite Paul Sabatier +!MNH_LIC Copyright 1994-2021 CNRS, Meteo-France and Universite Paul Sabatier !MNH_LIC This is part of the Meso-NH software governed by the CeCILL-C licence !MNH_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt !MNH_LIC for details. version 1. @@ -18,6 +18,7 @@ ! P. Wautelet 30/09/2020: add IO_Field_write_box_byfield_X3 and IO_Field_write_error_check subroutines ! P. Wautelet 04/12/2020: add IO_Field_create and IO_Ndimlist_reduce subroutines ! P. Wautelet 07/12/2020: add support for partial write of fields (optional argument: koffset, not all subroutines, no LFI spport) +! P. Wautelet 14/01/2021: add IO_Field_write_byname_N4 and IO_Field_write_byfield_N4 subroutines !----------------------------------------------------------------- #define MNH_SCALARS_IN_SPLITFILES 0 @@ -52,6 +53,7 @@ MODULE MODE_IO_FIELD_WRITE IO_Field_write_byname_X6, & IO_Field_write_byname_N0, IO_Field_write_byname_N1, & IO_Field_write_byname_N2, IO_Field_write_byname_N3, & + IO_Field_write_byname_N4, & IO_Field_write_byname_L0, IO_Field_write_byname_L1, & IO_Field_write_byname_C0, IO_Field_write_byname_C1, & IO_Field_write_byname_T0, IO_Field_write_byname_T1, & @@ -61,6 +63,7 @@ MODULE MODE_IO_FIELD_WRITE IO_Field_write_byfield_X6, & IO_Field_write_byfield_N0,IO_Field_write_byfield_N1, & IO_Field_write_byfield_N2,IO_Field_write_byfield_N3, & + IO_Field_write_byfield_N4, & IO_Field_write_byfield_L0,IO_Field_write_byfield_L1, & IO_Field_write_byfield_C0,IO_Field_write_byfield_C1, & IO_Field_write_byfield_T0,IO_Field_write_byfield_T1 @@ -394,7 +397,7 @@ subroutine IO_Field_create( tpfile, tpfield ) case ( 4 ) NDIMS if ( tzfield%ntype /= TYPEREAL ) then call Print_msg( NVERB_ERROR, 'IO', 'IO_Field_create', Trim( tpfile%cname ) // ': ' & - // Trim( tzfield%cmnhname ) // ': invalid ntype for 2D field' ) + // Trim( tzfield%cmnhname ) // ': invalid ntype for 4D field' ) return end if @@ -403,7 +406,7 @@ subroutine IO_Field_create( tpfile, tpfield ) case ( 5 ) NDIMS if ( tzfield%ntype /= TYPEREAL ) then call Print_msg( NVERB_ERROR, 'IO', 'IO_Field_create', Trim( tpfile%cname ) // ': ' & - // Trim( tzfield%cmnhname ) // ': invalid ntype for 2D field' ) + // Trim( tzfield%cmnhname ) // ': invalid ntype for 5D field' ) return end if @@ -412,7 +415,7 @@ subroutine IO_Field_create( tpfile, tpfield ) case ( 6 ) NDIMS if ( tzfield%ntype /= TYPEREAL ) then call Print_msg( NVERB_ERROR, 'IO', 'IO_Field_create', Trim( tpfile%cname ) // ': ' & - // Trim( tzfield%cmnhname ) // ': invalid ntype for 2D field' ) + // Trim( tzfield%cmnhname ) // ': invalid ntype for 6D field' ) return end if @@ -2501,6 +2504,222 @@ end subroutine IO_Ndimlist_reduce END SUBROUTINE IO_Field_write_byfield_N3 + SUBROUTINE IO_Field_write_byname_N4( TPFILE, HNAME, KFIELD, KRESP, koffset ) + ! + !* 0.1 Declarations of arguments + ! + TYPE(TFILEDATA), INTENT(IN) :: TPFILE + CHARACTER(LEN=*), INTENT(IN) :: HNAME ! name of the field to write + INTEGER,DIMENSION(:,:,:,:), INTENT(IN) :: KFIELD ! array containing the data field + INTEGER, OPTIONAL, INTENT(OUT) :: KRESP ! return-code + integer, dimension(4), optional, intent(in) :: koffset + ! + !* 0.2 Declarations of local variables + ! + INTEGER :: ID ! Index of the field + INTEGER :: IRESP ! return_code + ! + CALL PRINT_MSG(NVERB_DEBUG,'IO','IO_Field_write_byname_N4',TRIM(TPFILE%CNAME)//': writing '//TRIM(HNAME)) + ! + CALL FIND_FIELD_ID_FROM_MNHNAME(HNAME,ID,IRESP) + ! + if( iresp == 0 ) call IO_Field_write( tpfile, tfieldlist(id), kfield, iresp, koffset ) + ! + IF (PRESENT(KRESP)) KRESP = IRESP + ! + END SUBROUTINE IO_Field_write_byname_N4 + + + SUBROUTINE IO_Field_write_byfield_N4( TPFILE, TPFIELD, KFIELD, KRESP, koffset ) + use modd_field, only: NMNHDIM_UNKNOWN, NMNHDIM_ONE, NMNHDIM_UNUSED + USE MODD_IO, ONLY: GSMONOPROC, ISP, L1D, L2D, LPACK + USE MODD_PARAMETERS_ll, ONLY: JPHEXT + USE MODD_TIMEZ, ONLY: TIMEZ + ! + USE MODE_ALLOCBUFFER_ll + USE MODE_GATHER_ll + USE MODE_IO_TOOLS, ONLY: IO_Level2filenumber_get + USE MODE_MNH_TIMING, ONLY: SECOND_MNH2 + USE MODD_VAR_ll, ONLY: MNH_STATUSES_IGNORE + ! + ! + !* 0.1 Declarations of arguments + ! + TYPE(TFILEDATA), INTENT(IN) :: TPFILE + TYPE(TFIELDDATA), INTENT(IN) :: TPFIELD + INTEGER,DIMENSION(:,:,:,:),TARGET, INTENT(IN) :: KFIELD ! array containing the data field + INTEGER, OPTIONAL, INTENT(OUT) :: KRESP ! return-code + integer, dimension(4), optional, intent(in) :: koffset + ! + !* 0.2 Declarations of local variables + ! + CHARACTER(LEN=28) :: YFILEM ! FM-file name + CHARACTER(LEN=NMNHNAMELGTMAX) :: YRECFM ! name of the article to write + CHARACTER(LEN=2) :: YDIR ! field form + INTEGER :: IERR + INTEGER :: ISIZEMAX + integer :: iresp, iresp_lfi, iresp_nc4, iresp_glob + integer, dimension(2) :: ioffset2d + integer, dimension(3) :: ioffset3d + integer, dimension(:,:), pointer :: ifieldp2d + integer, dimension(:,:,:), pointer :: ifieldp3d + integer, dimension(:,:,:,:), pointer :: ifieldp + LOGICAL :: GALLOC + LOGICAL :: GLFI, GNC4 + INTEGER :: IHEXTOT + CHARACTER(LEN=:),ALLOCATABLE :: YMSG + CHARACTER(LEN=6) :: YRESP + type(tfielddata) :: tzfield + ! + YFILEM = TPFILE%CNAME + YRECFM = TPFIELD%CMNHNAME + YDIR = TPFIELD%CDIR + ! + iresp = 0 + iresp_lfi = 0 + iresp_nc4 = 0 + GALLOC = .FALSE. + ! + IHEXTOT = 2*JPHEXT+1 + ! + CALL PRINT_MSG(NVERB_DEBUG,'IO','IO_Field_write_byfield_N4',TRIM(YFILEM)//': writing '//TRIM(YRECFM)) + ! + CALL IO_Field_metadata_check(TPFIELD,TYPEINT,4,'IO_Field_write_byfield_N4') + ! + CALL IO_File_write_check(TPFILE,'IO_Field_write_byfield_N4',IRESP) + ! + CALL IO_Format_write_select(TPFILE,GLFI,GNC4) + ! + if ( Present( koffset ) .and. glfi ) then + call Print_msg( NVERB_ERROR, 'IO', 'IO_Field_partial_write_byfield_N4', Trim( tpfile%cname ) // ': LFI format not supported' ) + glfi = .false. + end if + + IF (IRESP==0) THEN + IF (GSMONOPROC) THEN ! sequential execution + ! IF (LPACK .AND. L1D .AND. YDIR=='XY') THEN + IF (LPACK .AND. L1D .AND. SIZE(KFIELD,1)==IHEXTOT .AND. SIZE(KFIELD,2)==IHEXTOT) THEN + if ( tpfile%ldimreduced ) then + tzfield = tpfield + tzfield%ndims = tzfield%ndims - 2 + if ( tzfield%ndimlist(1) /= NMNHDIM_UNKNOWN ) then + tzfield%ndimlist(1) = tzfield%ndimlist(3) + tzfield%ndimlist(2) = tzfield%ndimlist(4) + tzfield%ndimlist(3) = tzfield%ndimlist(5) !Necessary if time dimension + tzfield%ndimlist(4:) = NMNHDIM_UNUSED + end if + ifieldp2d => kfield(jphext + 1, jphext + 1, :, :) + if ( Present( koffset ) ) then + ioffset2d(1) = koffset(3) + ioffset2d(2) = koffset(4) + !if ( glfi ) call IO_Field_partial_write_lfi( tpfile, tzfield, ifieldp2d, ioffset2d, iresp_lfi ) + if ( gnc4 ) call IO_Field_partial_write_nc4( tpfile, tzfield, ifieldp2d, ioffset2d, iresp_nc4 ) + else + if ( glfi ) call IO_Field_write_lfi( tpfile, tzfield, ifieldp2d, iresp_lfi ) + if ( gnc4 ) call IO_Field_write_nc4( tpfile, tzfield, ifieldp2d, iresp_nc4 ) + end if + else + tzfield = tpfield + if ( tzfield%ndimlist(1) /= NMNHDIM_UNKNOWN ) then + tzfield%ndimlist(1:2) = NMNHDIM_ONE + end if + ifieldp => kfield(jphext + 1 : jphext + 1, jphext + 1 : jphext + 1, :, :) + if ( Present( koffset ) ) then + !if ( glfi ) call IO_Field_partial_write_lfi( tpfile, tzfield, ifieldp, koffset, iresp_lfi ) + if ( gnc4 ) call IO_Field_partial_write_nc4( tpfile, tzfield, ifieldp, koffset, iresp_nc4 ) + else + if ( glfi ) call IO_Field_write_lfi( tpfile, tzfield, ifieldp, iresp_lfi ) + if ( gnc4 ) call IO_Field_write_nc4( tpfile, tzfield, ifieldp, iresp_nc4 ) + end if + endif + ! ELSE IF (LPACK .AND. L2D .AND. YDIR=='XY') THEN + ELSEIF (LPACK .AND. L2D .AND. SIZE(KFIELD,2)==IHEXTOT) THEN + if ( tpfile%ldimreduced ) then + tzfield = tpfield + tzfield%ndims = tzfield%ndims - 1 + if ( tzfield%ndimlist(1) /= NMNHDIM_UNKNOWN ) then + tzfield%ndimlist(2) = tzfield%ndimlist(3) + tzfield%ndimlist(3) = tzfield%ndimlist(4) + tzfield%ndimlist(4) = tzfield%ndimlist(5) !Necessary if time dimension + tzfield%ndimlist(5:) = NMNHDIM_UNUSED + end if + ifieldp3d => kfield(:, jphext + 1, :, :) + if ( Present( koffset ) ) then + ioffset3d(1) = koffset(1) + ioffset3d(2) = koffset(3) + ioffset3d(3) = koffset(4) + !if ( glfi ) call IO_Field_partial_write_lfi( tpfile, tzfield, ifieldp3d, ioffset3d, iresp_lfi ) + if ( gnc4 ) call IO_Field_partial_write_nc4( tpfile, tzfield, ifieldp3d, ioffset3d, iresp_nc4 ) + else + if ( glfi ) call IO_Field_write_lfi( tpfile, tzfield, ifieldp3d, iresp_lfi ) + if ( gnc4 ) call IO_Field_write_nc4( tpfile, tzfield, ifieldp3d, iresp_nc4 ) + end if + else + tzfield = tpfield + if ( tzfield%ndimlist(2) /= NMNHDIM_UNKNOWN ) tzfield%ndimlist(2) = NMNHDIM_ONE + ifieldp => kfield(:, jphext + 1 : jphext + 1, :, :) + if ( Present( koffset ) ) then + !if ( glfi ) call IO_Field_partial_write_lfi( tpfile, tzfield, ifieldp, koffset, iresp_lfi ) + if ( gnc4 ) call IO_Field_partial_write_nc4( tpfile, tzfield, ifieldp, koffset, iresp_nc4 ) + else + if ( glfi ) call IO_Field_write_lfi( tpfile, tzfield, ifieldp, iresp_lfi ) + if ( gnc4 ) call IO_Field_write_nc4( tpfile, tzfield, ifieldp, iresp_nc4 ) + end if + endif + ELSE + if ( Present( koffset ) ) then + !if ( glfi ) call IO_Field_partial_write_lfi( tpfile, tpfield, kfield, koffset, iresp_lfi ) + if ( gnc4 ) call IO_Field_partial_write_nc4( tpfile, tpfield, kfield, koffset, iresp_nc4 ) + else + if ( glfi ) call IO_Field_write_lfi( tpfile, tpfield, kfield, iresp_lfi ) + if ( gnc4 ) call IO_Field_write_nc4( tpfile, tpfield, kfield, iresp_nc4 ) + end if + END IF + ELSE + CALL MPI_ALLREDUCE(SIZE(KFIELD),ISIZEMAX,1,MNHINT_MPI,MPI_MAX,TPFILE%NMPICOMM,IERR) + IF (ISIZEMAX==0) THEN + CALL PRINT_MSG(NVERB_INFO,'IO','IO_Field_write_byfield_N4','ignoring variable with a zero size ('//TRIM(YRECFM)//')') + IF (PRESENT(KRESP)) KRESP=0 + RETURN + END IF + + IF (ISP == TPFILE%NMASTER_RANK) THEN + CALL ALLOCBUFFER_ll(IFIELDP,KFIELD,YDIR,GALLOC) + ELSE + ALLOCATE(IFIELDP(0,0,0,0)) + GALLOC = .TRUE. + END IF + ! + IF (YDIR == 'XX' .OR. YDIR =='YY') THEN + CALL GATHER_XXFIELD(YDIR,KFIELD,IFIELDP,TPFILE%NMASTER_RANK,TPFILE%NMPICOMM) + ELSEIF (YDIR == 'XY') THEN + IF (LPACK .AND. L2D) THEN + call Print_msg( NVERB_FATAL, 'GEN', 'IO_Field_write_byfield_N4', '2D not (yet) allowed for parallel execution' ) + CALL GATHER_XXFIELD('XX',KFIELD(:,JPHEXT+1,:,:),IFIELDP(:,1,:,:),TPFILE%NMASTER_RANK,TPFILE%NMPICOMM) + ELSE + CALL GATHER_XYFIELD(KFIELD,IFIELDP,TPFILE%NMASTER_RANK,TPFILE%NMPICOMM) + END IF + END IF + ! + IF (ISP == TPFILE%NMASTER_RANK) THEN + if ( Present( koffset ) ) then + !if ( glfi ) call IO_Field_partial_write_lfi( tpfile, tpfield, ifieldp, koffset, iresp_lfi ) + if ( gnc4 ) call IO_Field_partial_write_nc4( tpfile, tpfield, ifieldp, koffset, iresp_nc4 ) + else + if ( glfi ) call IO_Field_write_lfi( tpfile, tpfield, ifieldp, iresp_lfi ) + if ( gnc4 ) call IO_Field_write_nc4( tpfile, tpfield, ifieldp, iresp_nc4 ) + end if + END IF + END IF ! multiprocess execution + END IF + + call IO_Field_write_error_check( tpfile, tpfield, 'IO_Field_write_byfield_N4', iresp, iresp_lfi, iresp_nc4, iresp_glob ) + if ( Present( kresp ) ) kresp = iresp_glob + + IF (GALLOC) DEALLOCATE(IFIELDP) + END SUBROUTINE IO_Field_write_byfield_N4 + + SUBROUTINE IO_Field_write_byname_L0(TPFILE,HNAME,OFIELD,KRESP) ! !* 0.1 Declarations of arguments -- GitLab