diff --git a/src/LIB/SURCOUCHE/src/mode_io_field_write.f90 b/src/LIB/SURCOUCHE/src/mode_io_field_write.f90 index baa7fcc4f58de937e0709753defdc2af2b3fb0e3..357aa7998fb18fcb70750c2930c76532b644d997 100644 --- a/src/LIB/SURCOUCHE/src/mode_io_field_write.f90 +++ b/src/LIB/SURCOUCHE/src/mode_io_field_write.f90 @@ -3946,6 +3946,11 @@ IF ( NOUT_NBOXES > 0 ) THEN CALL IO_Fieldlist_1field_write( TZOUTPUT, IMI, TFIELDLIST(NOUT_FIELDLIST(JI)), TOUT_BOXES(JBOX) ) END DO + ! Write box-specific fields + DO JI = 1, SIZE( TOUT_BOXES(JBOX)%NFIELDLIST_SUPP ) + CALL IO_Fieldlist_1field_write( TZOUTPUT, IMI, TFIELDLIST(TOUT_BOXES(JBOX)%NFIELDLIST_SUPP(JI)), TOUT_BOXES(JBOX) ) + END DO + ! Restore the root group (not really necessary but cleaner) IF ( ISP == TZOUTPUT%NMASTER_RANK ) TZOUTPUT%NNCID = IGROUPID_ROOT END DO diff --git a/src/LIB/SURCOUCHE/src/mode_io_manage_struct.f90 b/src/LIB/SURCOUCHE/src/mode_io_manage_struct.f90 index 2e27e733a0a905f4698b90abbd5470adfc6c5f53..9c5a0a6f3136270426c6cf20ea05a7ec6306847e 100644 --- a/src/LIB/SURCOUCHE/src/mode_io_manage_struct.f90 +++ b/src/LIB/SURCOUCHE/src/mode_io_manage_struct.f90 @@ -65,8 +65,6 @@ USE MODD_SUB_MODEL_N, ONLY: NFILE_BACKUP_CURRENT, NFILE_OUTPUT_CURRENT, SUB_MODE USE MODD_OUT_n, ONLY: OUT_GOTO_MODEL, OUT_MODEL, TOUT_BOXES USE MODD_VAR_ll, ONLY: IP -use mode_field, only: Find_field_id_from_mnhname - USE MODN_BACKUP, ONLY: BACKUP_NML_DEALLOCATE USE MODN_OUTPUT, ONLY: OUTPUT_NML_DEALLOCATE @@ -79,10 +77,9 @@ INTEGER :: IBAK_NUM INTEGER :: IOUT_NUM INTEGER :: IMI ! Model number for loop INTEGER :: IERR_LVL ! Level of error message -INTEGER :: IVAR ! Number of variables INTEGER :: ISTEP INTEGER :: ISTEP_MAX ! Number of timesteps -INTEGER :: IPOS,IFIELD ! Indices +INTEGER :: IPOS ! Index INTEGER :: JOUT,IDX ! Loop indices INTEGER :: JI INTEGER :: IRESP @@ -497,37 +494,14 @@ DO IMI = 1, NMODEL CALL PRINT_MSG( IERR_LVL, 'IO', 'IO_Bakout_struct_prepare', 'no (valid) backup time' ) END IF - !Determine the list of the fields to write in each output IF ( OUT_MODEL(IMI)%NOUT_NUMB > 0 ) THEN - !Count the number of fields to output - IVAR = 0 - DO IPOS = 1,JPOUTVARMAX - IF (COUT_VAR(IMI,IPOS)/='') IVAR = IVAR + 1 - END DO - IF (IVAR==0) CALL PRINT_MSG(NVERB_WARNING,'IO','IO_Bakout_struct_prepare','no fields chosen for output') - ALLOCATE( OUT_MODEL(IMI)%NOUT_FIELDLIST(IVAR) ) - - IF ( IVAR > 0 ) THEN - !Determine the list of the outputs to do (by field number) - IVAR = 0 - DO IPOS = 1,JPOUTVARMAX - IF (COUT_VAR(IMI,IPOS)/='') THEN - IVAR=IVAR+1 - CALL FIND_FIELD_ID_FROM_MNHNAME(COUT_VAR(IMI,IPOS),IFIELD,IRESP) - OUT_MODEL(IMI)%NOUT_FIELDLIST(IVAR) = IFIELD - IF (IRESP/=0) THEN - CALL PRINT_MSG(NVERB_FATAL,'IO','IO_Bakout_struct_prepare','unknown field for output: '//TRIM(COUT_VAR(IMI,IPOS))) - !MNH is killed to prevent problems with wrong values in NOUT_FIELDLIST - END IF - ! - END IF - END DO - END IF + !Determine the list of the fields to write in each output + CALL IO_OUT_FIELDLIST_FILL( COUT_VAR(IMI,:), .TRUE., OUT_MODEL(IMI)%NOUT_FIELDLIST ) + + ! Treat the boxes (sub-domains) for output files + CALL IO_BOX_PREPARE( IMI ) END IF ! - ! Treat the boxes (sub-domains) for output files - IF ( OUT_MODEL(IMI)%NOUT_NUMB > 0 ) CALL IO_BOX_PREPARE( IMI ) - ! IF ( IP == 1 ) THEN ! Backup information WRITE( *, '( "-------------------------------------------------" )' ) @@ -559,9 +533,9 @@ DO IMI = 1, NMODEL IF (OUT_MODEL(IMI)%NOUT_STEPFREQ > 0 ) THEN WRITE( *, '( " Regular: ", I9 )' ) & ( ISTEP_MAX - OUT_MODEL(IMI)%NOUT_STEPFREQFIRST ) / OUT_MODEL(IMI)%NOUT_STEPFREQ + 1 - WRITE( *, '( " Frequency: ", I9, " timesteps (", F12.3, "s)" )' ) & + WRITE( *, '( " Frequency: every ", I9, " timesteps (", F12.3, "s)" )' ) & OUT_MODEL(IMI)%NOUT_STEPFREQ, OUT_MODEL(IMI)%NOUT_STEPFREQ * DYN_MODEL(IMI)%XTSTEP - WRITE( *, '( " First: ", I9, " timesteps (", F12.3, "s)" )' ) & + WRITE( *, '( " First at timestep ", I9, " (", F12.3, "s)" )' ) & OUT_MODEL(IMI)%NOUT_STEPFREQFIRST, ( OUT_MODEL(IMI)%NOUT_STEPFREQFIRST - 1 ) * DYN_MODEL(IMI)%XTSTEP ELSE WRITE( *, '( " Regular: ", I9 )' ) 0 @@ -588,6 +562,13 @@ DO IMI = 1, NMODEL WRITE( *, '( " List of boxes:" )' ) DO JI = 1, OUT_MODEL(IMI)%NOUT_NBOXES WRITE(*, '( " ", A )' ) TRIM(OUT_MODEL(IMI)%TOUT_BOXES(JI)%CNAME) + IF ( SIZE( OUT_MODEL(IMI)%TOUT_BOXES(JI)%NFIELDLIST_SUPP ) > 0 ) THEN + WRITE( *, '( " Specific fields:" )' ) + DO JOUT = 1, SIZE( OUT_MODEL(IMI)%TOUT_BOXES(JI)%NFIELDLIST_SUPP ) + IDX = OUT_MODEL(IMI)%TOUT_BOXES(JI)%NFIELDLIST_SUPP(JOUT) + WRITE(*, '( " ", A )' ) TRIM(TFIELDLIST(IDX)%CMNHNAME) + END DO + END IF END DO END IF END IF @@ -734,6 +715,78 @@ SUBROUTINE SORT_ENTRIES(KNUMB,KSTEPS) END DO END SUBROUTINE SORT_ENTRIES ! +!######################################################################### +SUBROUTINE IO_OUT_FIELDLIST_FILL( HVARLIST, OMAINBOX, KFIELDLIST ) +!######################################################################### + use mode_field, only: Find_field_id_from_mnhname + + CHARACTER(LEN=NMNHNAMELGTMAX), DIMENSION(:), INTENT(IN) :: HVARLIST + LOGICAL, INTENT(IN) :: OMAINBOX + INTEGER, DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: KFIELDLIST + + INTEGER :: IFIELD + INTEGER :: IVAR ! Number of variables + INTEGER :: JIDX + INTEGER, DIMENSION(:), ALLOCATABLE :: ICOMPACTFIELDLIST + + !Count the number of fields to output + IVAR = 0 + DO IPOS = 1, SIZE(HVARLIST) + IF ( HVARLIST(IPOS) /= '' ) IVAR = IVAR + 1 + END DO + + ! Print warning message only if the main box has to be written + IF ( IVAR == 0 .AND. OMAINBOX .AND. ( NOUT_BOXES(IMI) == 0 .OR. LOUT_MAINDOMAIN_WRITE(IMI) ) ) & + CALL PRINT_MSG( NVERB_WARNING, 'IO', 'IO_OUT_FIELDLIST_FILL', 'no fields chosen for output' ) + + ALLOCATE( KFIELDLIST(IVAR) ) + + IF ( IVAR > 0 ) THEN + !Determine the list of the outputs to do (by field number) + IVAR = 0 + DO IPOS = 1, SIZE(HVARLIST) + IF ( HVARLIST(IPOS) /= '' ) THEN + IVAR = IVAR + 1 + CALL FIND_FIELD_ID_FROM_MNHNAME( HVARLIST(IPOS), IFIELD, IRESP ) + KFIELDLIST(IVAR) = IFIELD + IF ( IRESP /= 0 ) THEN + CALL PRINT_MSG( NVERB_FATAL, 'IO', 'IO_OUT_FIELDLIST_FILL', 'unknown field for output: ' // TRIM(HVARLIST(IPOS)) ) + !MNH is killed to prevent problems with wrong values in fieldlist + END IF + ! + END IF + END DO + END IF + + !Find and remove duplicated entries + DO IPOS = 1, SIZE( KFIELDLIST ) + IFIELD = KFIELDLIST(IPOS) + IF ( IFIELD == -1 ) CYCLE + DO JIDX = IPOS + 1, SIZE( KFIELDLIST ) + IF ( KFIELDLIST(JIDX) == IFIELD ) THEN + KFIELDLIST(JIDX) = -1 + IVAR = IVAR - 1 + END IF + END DO + END DO + + ! Compact the fieldlist (if some entries were duplicated and removed) + IF ( IVAR < SIZE( KFIELDLIST ) ) THEN + CALL PRINT_MSG( NVERB_WARNING, 'IO', 'IO_OUT_FIELDLIST_FILL', 'some output variable entries were duplicated => removed' ) + + ALLOCATE( ICOMPACTFIELDLIST(IVAR) ) + JIDX = 1 + DO IPOS = 1, SIZE( KFIELDLIST ) + IF ( KFIELDLIST(IPOS) /= -1 ) THEN + ICOMPACTFIELDLIST(JIDX) = KFIELDLIST(IPOS) + JIDX = JIDX + 1 + END IF + END DO + CALL MOVE_ALLOC( FROM = ICOMPACTFIELDLIST, TO = KFIELDLIST ) + END IF + +END SUBROUTINE IO_OUT_FIELDLIST_FILL + !######################################################################### SUBROUTINE IO_BOX_PREPARE( KMI ) !######################################################################### @@ -742,6 +795,11 @@ SUBROUTINE IO_BOX_PREPARE( KMI ) INTEGER, INTENT(IN) :: KMI + INTEGER :: IFIELD + INTEGER :: IVAR + INTEGER :: JIDX1, JIDX2 + INTEGER, DIMENSION(:), ALLOCATABLE :: ICOMPACTFIELDLIST + ! Force the writing of the main domain if there are no boxes ! Remark: default value of LOUT_MAINDOMAIN_WRITE is .FALSE. IF ( NOUT_BOXES(IMI) == 0 ) LOUT_MAINDOMAIN_WRITE(IMI) = .TRUE. @@ -792,6 +850,28 @@ SUBROUTINE IO_BOX_PREPARE( KMI ) IF ( TOUT_BOXES(JI)%NKSUP > NKMAX ) CALL Print_msg( NVERB_ERROR, 'GEN', 'IO_BOX_PREPARE', 'NOUT_BOX_KSUP too large (>NKMAX)' ) IF ( TOUT_BOXES(JI)%NKSUP < TOUT_BOXES(JI)%NKINF ) & CALL Print_msg( NVERB_ERROR, 'GEN', 'INI_LES_n', 'NOUT_BOX_KSUP < NOUT_BOX_KINF' ) + + ! Field the list of variables to write for each box (in addition to the NOUTFIELDLIST which is common to all the boxes) + CALL IO_OUT_FIELDLIST_FILL( COUT_BOX_VAR_SUPP(IMI,JI,:), .FALSE., TOUT_BOXES(JI)%NFIELDLIST_SUPP ) + + ! Check for duplicated entries between the general list and the box-specific one + IVAR = SIZE( TOUT_BOXES(JI)%NFIELDLIST_SUPP ) + DO JIDX1 = 1, SIZE( OUT_MODEL(IMI)%NOUT_FIELDLIST ) + IFIELD = OUT_MODEL(IMI)%NOUT_FIELDLIST(JIDX1) + DO JIDX2 = 1, SIZE( TOUT_BOXES(JI)%NFIELDLIST_SUPP ) + IF ( TOUT_BOXES(JI)%NFIELDLIST_SUPP(JIDX2) == IFIELD ) THEN + TOUT_BOXES(JI)%NFIELDLIST_SUPP(JIDX2) = TOUT_BOXES(JI)%NFIELDLIST_SUPP(SIZE(TOUT_BOXES(JI)%NFIELDLIST_SUPP)) + IVAR = IVAR - 1 + END IF + END DO + END DO + + ! Compact the fieldlist (if some entries were duplicated and removed) + IF ( IVAR < SIZE( TOUT_BOXES(JI)%NFIELDLIST_SUPP ) ) THEN + CALL Print_msg( NVERB_WARNING, 'IO', 'IO_BOX_PREPARE', 'some box-specific output variables already in main list => removed' ) + ICOMPACTFIELDLIST = TOUT_BOXES(JI)%NFIELDLIST_SUPP(1:IVAR) + CALL MOVE_ALLOC( FROM = ICOMPACTFIELDLIST, TO = TOUT_BOXES(JI)%NFIELDLIST_SUPP ) + END IF END DO END SUBROUTINE IO_BOX_PREPARE diff --git a/src/MNH/modd_bakout.f90 b/src/MNH/modd_bakout.f90 index 4fd225d6b7a6160156adaa0f953a17114c27f416..28fe4a0ca45bdbc0b651cc80d4b9212134cfdc0b 100644 --- a/src/MNH/modd_bakout.f90 +++ b/src/MNH/modd_bakout.f90 @@ -95,6 +95,8 @@ CHARACTER(LEN=NDIRNAMELGTMAX) :: CBAK_DIR='', COUT_DIR='' ! Boxes (subdomains) for outputs INTEGER, DIMENSION(JPMODELMAX) :: NOUT_BOXES = 0 ! Number of sub-boxes inside each modelgrid CHARACTER(LEN=NMNHNAMELGTMAX), DIMENSION(:,:), ALLOCATABLE :: COUT_BOX_NAME ! Names of the boxes +CHARACTER(LEN=NMNHNAMELGTMAX), DIMENSION(:,:,:), ALLOCATABLE :: COUT_BOX_VAR_SUPP ! Name of the fields to output separately + ! in the different boxes (added to the COUT_VAR) LOGICAL, DIMENSION(JPMODELMAX) :: LOUT_MAINDOMAIN_WRITE = .FALSE. ! True to write the main domain ! (automatically forced to .TRUE. if NOUT_BOXES=0) diff --git a/src/MNH/modd_outn.f90 b/src/MNH/modd_outn.f90 index 932f5c133abc0bf32f68993d133338614e71ad5a..a4258e395987f52c678d88cb74f3f29782d4a07b 100644 --- a/src/MNH/modd_outn.f90 +++ b/src/MNH/modd_outn.f90 @@ -48,6 +48,7 @@ SAVE TYPE TOUTBOXMETADATA CHARACTER(LEN=NMNHNAMELGTMAX):: CNAME = '' ! Name of the box + INTEGER, DIMENSION(:), ALLOCATABLE :: NFIELDLIST_SUPP ! Lists of fields to write (added to the NOUT_FIELDLIST) INTEGER :: NIINF = NNEGUNDEF ! Box coordinates in physical domain INTEGER :: NISUP = NNEGUNDEF INTEGER :: NJINF = NNEGUNDEF diff --git a/src/MNH/modn_output.f90 b/src/MNH/modn_output.f90 index 1c4cb31494970b64e58d86943d70c6b4bf37b911..e1db16f4a51aa44817648b7f8852c5410162300c 100644 --- a/src/MNH/modn_output.f90 +++ b/src/MNH/modn_output.f90 @@ -54,7 +54,7 @@ NAMELIST/NAM_OUTPUT/LOUT_BEG,LOUT_END,& LOUT_COMPRESS, NOUT_COMPRESS_LEVEL,& LOUT_COMPRESS_LOSSY, COUT_COMPRESS_LOSSY_ALGO, NOUT_COMPRESS_LOSSY_NSD, & COUT_DIR, & - NOUT_BOXES, COUT_BOX_NAME, LOUT_MAINDOMAIN_WRITE, & + NOUT_BOXES, COUT_BOX_NAME, COUT_BOX_VAR_SUPP, LOUT_MAINDOMAIN_WRITE, & NOUT_BOX_IINF, NOUT_BOX_ISUP, NOUT_BOX_JINF, NOUT_BOX_JSUP, NOUT_BOX_KINF, NOUT_BOX_KSUP LOGICAL, SAVE, PRIVATE :: LOUTPUT_NML_ALLOCATED = .FALSE. @@ -81,6 +81,8 @@ SUBROUTINE OUTPUT_NML_ALLOCATE( ) ALLOCATE( COUT_BOX_NAME(NMODEL, NOUT_BOXMAX) ) + ALLOCATE( COUT_BOX_VAR_SUPP(NMODEL, NOUT_BOXMAX, JPOUTVARMAX ) ) + ALLOCATE( NOUT_BOX_IINF(NMODEL, NOUT_BOXMAX) ) ALLOCATE( NOUT_BOX_ISUP(NMODEL, NOUT_BOXMAX) ) ALLOCATE( NOUT_BOX_JINF(NMODEL, NOUT_BOXMAX) ) @@ -94,6 +96,8 @@ SUBROUTINE OUTPUT_NML_ALLOCATE( ) COUT_BOX_NAME(:,:) = '' + COUT_BOX_VAR_SUPP(:,:,:) = '' + NOUT_BOX_IINF(:,:) = NNEGUNDEF NOUT_BOX_ISUP(:,:) = NNEGUNDEF NOUT_BOX_JINF(:,:) = NNEGUNDEF