From 488baaf1adbb7f14b8298971463f13809f3e517e Mon Sep 17 00:00:00 2001 From: Philippe WAUTELET <philippe.wautelet@aero.obs-mip.fr> Date: Wed, 20 Apr 2022 11:35:49 +0200 Subject: [PATCH] Philippe 20/04/2022: stations: optimise stations (less communications, less memory...) Interpolation was not correct for U and V (did not use correct position indices) --- src/MNH/default_desfmn.f90 | 3 +- src/MNH/ini_modeln.f90 | 6 +- src/MNH/ini_surfstationn.f90 | 295 +++++++++----------------- src/MNH/modd_allstationn.f90 | 16 +- src/MNH/modd_stationn.f90 | 18 +- src/MNH/modd_type_station.f90 | 12 +- src/MNH/modn_stationn.f90 | 10 +- src/MNH/station_reader.f90 | 162 ++++++++------- src/MNH/station_tools.f90 | 376 ++++++++++++++++++++++++++++++---- src/MNH/stationn.f90 | 351 ++++++------------------------- src/MNH/write_stationn.f90 | 228 +++++++++++++++++++-- 11 files changed, 819 insertions(+), 658 deletions(-) diff --git a/src/MNH/default_desfmn.f90 b/src/MNH/default_desfmn.f90 index c1be2c51e..c9f530786 100644 --- a/src/MNH/default_desfmn.f90 +++ b/src/MNH/default_desfmn.f90 @@ -1,4 +1,4 @@ -!MNH_LIC Copyright 1994-2021 CNRS, Meteo-France and Universite Paul Sabatier +!MNH_LIC Copyright 1994-2022 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. @@ -603,7 +603,6 @@ XZ_STAT(:) = XUNDEF XLAT_STAT(:) = XUNDEF XLON_STAT(:) = XUNDEF CNAME_STAT(:) = '' -CTYPE_STAT(:) = '' CFILE_STAT = 'NO_INPUT_CSV' LDIAG_SURFRAD = .TRUE. ! diff --git a/src/MNH/ini_modeln.f90 b/src/MNH/ini_modeln.f90 index 718f11ce6..6ee23d80a 100644 --- a/src/MNH/ini_modeln.f90 +++ b/src/MNH/ini_modeln.f90 @@ -1,4 +1,4 @@ -!MNH_LIC Copyright 1994-2021 CNRS, Meteo-France and Universite Paul Sabatier +!MNH_LIC Copyright 1994-2022 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. @@ -2565,9 +2565,7 @@ CALL INI_AIRCRAFT_BALLOON(TPINIFILE,XTSTEP, TDTSEG, XSEGLEN, NRR, NSV, & !* 24. STATION initializations ! ----------------------- ! -CALL INI_SURFSTATION_n(XTSTEP, XSEGLEN, NRR, NSV, & - CTURB=="TKEL" , KMI, & - XLATORI, XLONORI ) +CALL INI_SURFSTATION_n( ) ! !------------------------------------------------------------------------------- ! diff --git a/src/MNH/ini_surfstationn.f90 b/src/MNH/ini_surfstationn.f90 index 3cde34d16..ebd004817 100644 --- a/src/MNH/ini_surfstationn.f90 +++ b/src/MNH/ini_surfstationn.f90 @@ -9,21 +9,7 @@ MODULE MODI_INI_SURFSTATION_n ! INTERFACE ! - SUBROUTINE INI_SURFSTATION_n(PTSTEP, PSEGLEN, & - KRR, KSV, OUSETKE, KMI, & - PLATOR, PLONOR ) -! -USE MODD_TYPE_DATE -REAL, INTENT(IN) :: PTSTEP ! time step -REAL, INTENT(IN) :: PSEGLEN ! segment length -INTEGER, INTENT(IN) :: KRR ! number of moist variables -INTEGER, INTENT(IN) :: KSV ! number of scalar variables -LOGICAL, INTENT(IN) :: OUSETKE ! flag to use tke -REAL, INTENT(IN) :: PLATOR ! latitude of origine point -REAL, INTENT(IN) :: PLONOR ! longitude of origine point -INTEGER, INTENT(IN) :: KMI ! MODEL NUMBER -! -!------------------------------------------------------------------------------- + SUBROUTINE INI_SURFSTATION_n( ) ! END SUBROUTINE INI_SURFSTATION_n ! @@ -31,11 +17,9 @@ END INTERFACE ! END MODULE MODI_INI_SURFSTATION_n ! -! ######################################################## - SUBROUTINE INI_SURFSTATION_n(PTSTEP, PSEGLEN, & - KRR, KSV, OUSETKE, KMI, & - PLATOR, PLONOR ) -! ######################################################## +! ############################### + SUBROUTINE INI_SURFSTATION_n( ) +! ############################### ! ! !!**** *INI_SURFSTATION_n* - @@ -69,222 +53,143 @@ END MODULE MODI_INI_SURFSTATION_n ! P. Wautelet 13/09/2019: budget: simplify and modernize date/time management ! R. Schoetter 11/2019: work for cartesian coordinates + parallel. ! E.Jezequel 02/2021: read stations from CVS file -! P. Wautelet 07/04/2022: rewrite types for stations +! P. Wautelet 04/2022: restructure stations for better performance, reduce memory usage and correct some problems/bugs ! -------------------------------------------------------------------------- ! !* 0. DECLARATIONS ! ------------ ! USE MODD_ALLSTATION_n -USE MODD_CONF -USE MODD_DIM_n -USE MODD_DYN_n -USE MODD_GRID -USE MODD_GRID_n -USE MODD_NESTING -USE MODD_PARAMETERS -USE MODD_SHADOWS_n +USE MODD_CONF, ONLY: LCARTESIAN +USE MODD_DYN, ONLY: XSEGLEN +USE MODD_DYN_n, ONLY: DYN_MODEL, XTSTEP +USE MODD_GRID_n, ONLY: XXHAT, XYHAT +USE MODD_PARAMETERS, ONLY: JPHEXT, JPVEXT USE MODD_STATION_n -USE MODD_TYPE_DATE -USE MODD_VAR_ll, ONLY: IP +USE MODD_TYPE_STATION ! -USE MODE_GATHER_ll -USE MODE_GRIDPROJ -USE MODE_ll USE MODE_MSG -! -USE MODI_INI_STATION_N +USE MODE_STATION_READER +USE MODE_STATION_TOOLS, ONLY: STATION_ADD, STATION_ALLOCATE, STATION_INI_INTERP, STATION_POSITION +USE MODE_ALLOCBUFFER_ll, ONLY: ALLOCBUFFER_ll +USE MODE_GATHER_ll, ONLY: GATHERALL_FIELD_ll ! IMPLICIT NONE ! ! !* 0.1 declarations of arguments ! -! -REAL, INTENT(IN) :: PTSTEP ! time step -REAL, INTENT(IN) :: PSEGLEN ! segment length -INTEGER, INTENT(IN) :: KRR ! number of moist variables -INTEGER, INTENT(IN) :: KSV ! number of scalar variables -LOGICAL, INTENT(IN) :: OUSETKE ! flag to use tke -REAL, INTENT(IN) :: PLATOR ! latitude of origine point -REAL, INTENT(IN) :: PLONOR ! longitude of origine point -INTEGER, INTENT(IN) :: KMI ! MODEL NUMBER +! NONE ! !------------------------------------------------------------------------------- ! ! 0.2 declaration of local variables ! -INTEGER :: ISTORE ! number of storage instants -INTEGER :: IIU_ll,IJU_ll,IRESP +INTEGER :: IERR +INTEGER :: IIU +INTEGER :: IJU +INTEGER :: ISTORE ! number of storage instants INTEGER :: JI +LOGICAL :: GALLOCX, GALLOCY +LOGICAL :: GINSIDE ! True if station is inside physical domain of model +LOGICAL :: GPRESENT ! True if station is present on the current process +REAL :: ZXHATM_PHYS_MIN, ZYHATM_PHYS_MIN ! Minimum X coordinate of mass points in the physical domain +REAL :: ZXHATM_PHYS_MAX, ZYHATM_PHYS_MAX ! Minimum X coordinate of mass points in the physical domain +REAL, DIMENSION(SIZE(XXHAT)) :: ZXHATM ! mass point coordinates +REAL, DIMENSION(SIZE(XYHAT)) :: ZYHATM ! mass point coordinates +REAL, DIMENSION(:), POINTER :: ZXHAT_GLOB +REAL, DIMENSION(:), POINTER :: ZYHAT_GLOB +TYPE(TSTATIONDATA) :: TZSTATION ! !---------------------------------------------------------------------------- -! -!* 1. Default values -! -------------- -! -NUMBSTAT = 0 -TSTATIONS_TIME%XTSTEP = XTSTEP -! -! -!* 3. Stations initialization -! ----------------------- -! -IF (CFILE_STAT=="NO_INPUT_CSV") THEN -! -!* 1. Namelist -! -------- - NUMBSTAT = NNUMB_STAT - IF (NUMBSTAT > 0) THEN - ALLOCATE( TSTATIONS(NUMBSTAT) ) +TSTATIONS_TIME%XTSTEP = XSTEP_STAT - IF (LCARTESIAN) THEN - DO JI=1,NUMBSTAT - TSTATIONS(JI)%XX = XX_STAT(JI) - TSTATIONS(JI)%XY = XY_STAT(JI) - TSTATIONS(JI)%XZ = XZ_STAT(JI) - TSTATIONS(JI)%CNAME = CNAME_STAT(JI) - TSTATIONS(JI)%CTYPE = CTYPE_STAT(JI) - END DO - ELSE - DO JI=1,NUMBSTAT - TSTATIONS(JI)%XLAT = XLAT_STAT(JI) - TSTATIONS(JI)%XLON = XLON_STAT(JI) - TSTATIONS(JI)%XZ = XZ_STAT(JI) - TSTATIONS(JI)%CNAME = CNAME_STAT(JI) - TSTATIONS(JI)%CTYPE = CTYPE_STAT(JI) - END DO - END IF - END IF -ELSE -! -!* 2. CSV DATA -! - CALL READ_CSV_STATION( CFILE_STAT, TSTATIONS, LCARTESIAN ) -END IF +if ( tstations_time%xtstep < xtstep ) then + call Print_msg( NVERB_WARNING, 'GEN', 'INI_SURFSTATION_n', 'Timestep for stations was smaller than model timestep' ) + tstations_time%xtstep = xtstep +end if -TSTATIONS_TIME%XTSTEP = XSTEP_STAT +ISTORE = NINT ( ( XSEGLEN - DYN_MODEL(1)%XTSTEP ) / TSTATIONS_TIME%XTSTEP ) + 1 -LSTATION = (NUMBSTAT>0) -! -!---------------------------------------------------------------------------- +allocate( tstations_time%tpdates(istore) ) ! -!* 4. Allocations of storage arrays -! ----------------------------- +! Prepare positioning data ! -IF(NUMBSTAT>0) THEN - CALL ALLOCATE_STATION_n() - IF (.NOT. LCARTESIAN) CALL INI_INTERP_STATION_n() -ENDIF -!---------------------------------------------------------------------------- +IF ( CFILE_STAT /= "NO_INPUT_CSV" .OR. NNUMB_STAT > 0 ) THEN + IIU = SIZE( XXHAT ) + IJU = SIZE( XYHAT ) + + ! Get global XHAT and YHAT (needed by STATION_POSITION) + CALL ALLOCBUFFER_ll( ZXHAT_GLOB, XXHAT, 'XX', GALLOCX ) + CALL ALLOCBUFFER_ll( ZYHAT_GLOB, XYHAT, 'YY', GALLOCY ) + CALL GATHERALL_FIELD_ll( 'XX', XXHAT, ZXHAT_GLOB, IERR ) + CALL GATHERALL_FIELD_ll( 'YY', XYHAT, ZYHAT_GLOB, IERR ) + + ! Interpolations of model variables to mass points + ZXHATM(1:IIU-1) = 0.5 * XXHAT(1:IIU-1) + 0.5 * XXHAT(2:IIU ) + ZXHATM( IIU ) = 1.5 * XXHAT( IIU ) - 0.5 * XXHAT( IIU-1) + + ZYHATM(1:IJU-1) = 0.5 * XYHAT(1:IJU-1) + 0.5 * XYHAT(2:IJU ) + ZYHATM( IJU ) = 1.5 * XYHAT( IJU ) - 0.5 * XYHAT( IJU-1) + + ZXHATM_PHYS_MIN = 0.5 * ( ZXHAT_GLOB(1+JPHEXT) + ZXHAT_GLOB(2+JPHEXT) ) + ZXHATM_PHYS_MAX = 0.5 * ( ZXHAT_GLOB(UBOUND(ZXHAT_GLOB,1)-JPHEXT) + ZXHAT_GLOB(UBOUND(ZXHAT_GLOB,1)-JPHEXT+1) ) + ZYHATM_PHYS_MIN = 0.5 * ( ZYHAT_GLOB(1+JPHEXT) + ZYHAT_GLOB(2+JPHEXT) ) + ZYHATM_PHYS_MAX = 0.5 * ( ZYHAT_GLOB(UBOUND(ZYHAT_GLOB,1)-JPHEXT) + ZYHAT_GLOB(UBOUND(ZYHAT_GLOB,1)-JPHEXT+1) ) +END IF ! -CONTAINS +! Stations initialization ! -!---------------------------------------------------------------------------- -SUBROUTINE ALLOCATE_STATION_n() +NUMBSTAT_LOC = 0 -INTEGER :: JI - -if ( tstations_time%xtstep < xtstep ) then - call Print_msg( NVERB_WARNING, 'GEN', 'INI_SURFSTATION_n', 'Timestep for stations was smaller than model timestep' ) - tstations_time%xtstep = xtstep -end if +IF (CFILE_STAT=="NO_INPUT_CSV") THEN + ! Treat namelist + NUMBSTAT = 0 + IF ( NNUMB_STAT > 0 ) THEN + DO JI = 1, NNUMB_STAT + IF ( LCARTESIAN ) THEN + TZSTATION%XX = XX_STAT(JI) + TZSTATION%XY = XY_STAT(JI) + ELSE + TZSTATION%XLAT = XLAT_STAT(JI) + TZSTATION%XLON = XLON_STAT(JI) + CALL STATION_INI_INTERP( TZSTATION ) + END IF + TZSTATION%XZ = XZ_STAT(JI) + TZSTATION%CNAME = CNAME_STAT(JI) -ISTORE = NINT ( ( PSEGLEN - DYN_MODEL(1)%XTSTEP ) / TSTATIONS_TIME%XTSTEP ) + 1 + CALL STATION_POSITION( TZSTATION, ZXHAT_GLOB, ZYHAT_GLOB, ZXHATM, ZYHATM, & + ZXHATM_PHYS_MIN, ZXHATM_PHYS_MAX, ZYHATM_PHYS_MIN, ZYHATM_PHYS_MAX, & + GINSIDE, GPRESENT ) -allocate( tstations_time%tpdates(istore) ) + IF ( GINSIDE ) THEN + NUMBSTAT = NUMBSTAT + 1 + TZSTATION%NID = NUMBSTAT + END IF -DO JI = 1, NUMBSTAT - ALLOCATE(TSTATIONS(JI)%XZON (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XMER (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XW (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XP (ISTORE)) - IF (OUSETKE) THEN - ALLOCATE(TSTATIONS(JI)%XTKE (ISTORE)) - ELSE - ALLOCATE(TSTATIONS(JI)%XTKE (0)) + IF ( GPRESENT ) CALL STATION_ADD( TZSTATION ) + END DO END IF - ALLOCATE(TSTATIONS(JI)%XTH (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XR (ISTORE,KRR)) - ALLOCATE(TSTATIONS(JI)%XSV (ISTORE,KSV)) - ALLOCATE(TSTATIONS(JI)%XTSRAD (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XT2M (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XQ2M (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XHU2M (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XZON10M(ISTORE)) - ALLOCATE(TSTATIONS(JI)%XMER10M(ISTORE)) - ALLOCATE(TSTATIONS(JI)%XRN (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XH (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XLE (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XLEI (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XGFLUX (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XSWD (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XSWU (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XLWD (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XLWU (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XSWDIR (ISTORE)) - ALLOCATE(TSTATIONS(JI)%XSWDIFF(ISTORE)) - ALLOCATE(TSTATIONS(JI)%XDSTAOD(ISTORE)) - ALLOCATE(TSTATIONS(JI)%XSFCO2 (ISTORE)) +ELSE + !Treat CSV datafile + CALL READ_CSV_STATION( CFILE_STAT, ZXHAT_GLOB, ZYHAT_GLOB, ZXHATM, ZYHATM, & + ZXHATM_PHYS_MIN, ZXHATM_PHYS_MAX,ZYHATM_PHYS_MIN, ZYHATM_PHYS_MAX ) +END IF - TSTATIONS(JI)%XZON(:) = XUNDEF - TSTATIONS(JI)%XMER(:) = XUNDEF - TSTATIONS(JI)%XW(:) = XUNDEF - TSTATIONS(JI)%XP(:) = XUNDEF - TSTATIONS(JI)%XTKE(:) = XUNDEF - TSTATIONS(JI)%XTH(:) = XUNDEF - TSTATIONS(JI)%XR(:,:) = XUNDEF - TSTATIONS(JI)%XSV(:,:) = XUNDEF - TSTATIONS(JI)%XTSRAD(:) = XUNDEF - TSTATIONS(JI)%XT2M(:) = XUNDEF - TSTATIONS(JI)%XQ2M(:) = XUNDEF - TSTATIONS(JI)%XHU2M(:) = XUNDEF - TSTATIONS(JI)%XZON10M(:) = XUNDEF - TSTATIONS(JI)%XMER10M(:) = XUNDEF - TSTATIONS(JI)%XRN(:) = XUNDEF - TSTATIONS(JI)%XH(:) = XUNDEF - TSTATIONS(JI)%XLE(:) = XUNDEF - TSTATIONS(JI)%XLEI(:) = XUNDEF - TSTATIONS(JI)%XGFLUX(:) = XUNDEF - TSTATIONS(JI)%XSWD(:) = XUNDEF - TSTATIONS(JI)%XSWU(:) = XUNDEF - TSTATIONS(JI)%XLWD(:) = XUNDEF - TSTATIONS(JI)%XLWU(:) = XUNDEF - TSTATIONS(JI)%XSWDIR(:) = XUNDEF - TSTATIONS(JI)%XSWDIFF(:) = XUNDEF - TSTATIONS(JI)%XDSTAOD(:) = XUNDEF - TSTATIONS(JI)%XSFCO2(:) = XUNDEF -END DO +LSTATION = ( NUMBSTAT > 0 ) -END SUBROUTINE ALLOCATE_STATION_n -!---------------------------------------------------------------------------- -!---------------------------------------------------------------------------- -SUBROUTINE INI_INTERP_STATION_n() +DO JI = 1, NUMBSTAT_LOC + CALL STATION_ALLOCATE( TSTATIONS(JI), ISTORE ) +END DO ! -USE MODE_STATION_TOOLS, ONLY: STATION_POSITION - -INTEGER :: JII -INTEGER :: IIU, IJU +! Clean positioning data ! -IF ( ALL(TSTATIONS(:)%XLAT /= XUNDEF) .AND. ALL(TSTATIONS(:)%XLON /= XUNDEF) ) THEN - DO JII = 1, NUMBSTAT - CALL GET_DIM_EXT_ll ('B',IIU,IJU) - CALL SM_XYHAT(PLATOR,PLONOR, & - TSTATIONS(JII)%XLAT, TSTATIONS(JII)%XLON, & - TSTATIONS(JII)%XX, TSTATIONS(JII)%XY ) - CALL STATION_POSITION( TSTATIONS(JII) ) - END DO -ELSE - CMNHMSG(1) = 'Error in station position' - CMNHMSG(1) = 'either LATitude or LONgitude segment' - CMNHMSG(1) = 'or I and J segment' - CMNHMSG(1) = 'definition is not complete.' - CALL PRINT_MSG( NVERB_FATAL, 'GEN', 'INI_SURFSTATION_n' ) +IF ( CFILE_STAT /= "NO_INPUT_CSV" .OR. NNUMB_STAT > 0 ) THEN + IF ( GALLOCX ) DEALLOCATE( ZXHAT_GLOB ) + IF ( GALLOCY ) DEALLOCATE( ZYHAT_GLOB ) END IF -END SUBROUTINE INI_INTERP_STATION_n !---------------------------------------------------------------------------- -!---------------------------------------------------------------------------- -! + END SUBROUTINE INI_SURFSTATION_n diff --git a/src/MNH/modd_allstationn.f90 b/src/MNH/modd_allstationn.f90 index 933c16571..4229177e4 100644 --- a/src/MNH/modd_allstationn.f90 +++ b/src/MNH/modd_allstationn.f90 @@ -1,4 +1,4 @@ -!MNH_LIC Copyright 2021-2021 CNRS, Meteo-France and Universite Paul Sabatier +!MNH_LIC Copyright 2021-2022 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. @@ -29,6 +29,7 @@ !! MODIFICATIONS !! ------------- !! Original 01/06/21 +! P. Wautelet 04/2022: restructure stations for better performance, reduce memory usage and correct some problems/bugs !------------------------------------------------------------------------------- ! !* 0. DECLARATIONS @@ -36,11 +37,16 @@ ! ! USE MODD_PARAMETERS, ONLY: JPMODELMAX -USE MODD_STATION_n -USE MODD_TYPE_STATION IMPLICIT NONE +PRIVATE + +PUBLIC :: NNUMB_STAT, XSTEP_STAT, XX_STAT, XY_STAT, XLAT_STAT, XLON_STAT, XZ_STAT +PUBLIC :: CNAME_STAT, CFILE_STAT, LDIAG_SURFRAD + +PUBLIC :: ALLSTATION_GOTO_MODEL + TYPE ALLSTATION_t ! !------------------------------------------------------------------------------------------- @@ -48,7 +54,7 @@ TYPE ALLSTATION_t ! INTEGER :: NNUMB_STAT !Number of stations as defined in namelist REAL, DIMENSION(100) :: XX_STAT, XY_STAT, XZ_STAT, XLAT_STAT, XLON_STAT - CHARACTER(LEN=7), DIMENSION(100) :: CNAME_STAT, CTYPE_STAT + CHARACTER(LEN=7), DIMENSION(100) :: CNAME_STAT CHARACTER(LEN=20) :: CFILE_STAT REAL :: XSTEP_STAT LOGICAL :: LDIAG_SURFRAD @@ -66,7 +72,6 @@ REAL, DIMENSION(:), POINTER :: XLAT_STAT=>NULL() REAL, DIMENSION(:), POINTER :: XLON_STAT=>NULL() REAL, DIMENSION(:), POINTER :: XZ_STAT=>NULL() CHARACTER (LEN=7),DIMENSION(:), POINTER :: CNAME_STAT=>NULL() -CHARACTER (LEN=7),DIMENSION(:), POINTER :: CTYPE_STAT=>NULL() CHARACTER (LEN=20),POINTER :: CFILE_STAT=>NULL() LOGICAL, POINTER :: LDIAG_SURFRAD=>NULL() CONTAINS @@ -86,7 +91,6 @@ XZ_STAT =>ALLSTATION_MODEL(KTO)%XZ_STAT XLAT_STAT =>ALLSTATION_MODEL(KTO)%XLAT_STAT XLON_STAT =>ALLSTATION_MODEL(KTO)%XLON_STAT CNAME_STAT =>ALLSTATION_MODEL(KTO)%CNAME_STAT -CTYPE_STAT =>ALLSTATION_MODEL(KTO)%CTYPE_STAT CFILE_STAT =>ALLSTATION_MODEL(KTO)%CFILE_STAT LDIAG_SURFRAD =>ALLSTATION_MODEL(KTO)%LDIAG_SURFRAD END SUBROUTINE ALLSTATION_GOTO_MODEL diff --git a/src/MNH/modd_stationn.f90 b/src/MNH/modd_stationn.f90 index ff5351dee..6017c0f98 100644 --- a/src/MNH/modd_stationn.f90 +++ b/src/MNH/modd_stationn.f90 @@ -29,25 +29,31 @@ !! MODIFICATIONS !! ------------- !! Original 15/01/02 -! P. Wautelet 07/04/2022: rewrite types for stations +! P. Wautelet 04/2022: restructure stations for better performance, reduce memory usage and correct some problems/bugs !------------------------------------------------------------------------------- ! !* 0. DECLARATIONS ! ------------ ! ! -USE MODD_PARAMETERS, ONLY: JPMODELMAX -USE MODD_TYPE_STATION +USE MODD_PARAMETERS, ONLY: JPMODELMAX +USE MODD_TYPE_STATION, ONLY: TSTATIONDATA, TSTATIONTIME IMPLICIT NONE +PRIVATE + +PUBLIC :: LSTATION, NUMBSTAT, NUMBSTAT_LOC, TSTATIONS_TIME, TSTATIONS + +PUBLIC :: STATION_GOTO_MODEL + TYPE STATION_t ! !------------------------------------------------------------------------------------------- ! LOGICAL :: LSTATION ! flag to use stations INTEGER :: NUMBSTAT ! number of stations - LOGICAL :: LSTATLAT ! positioning in lat/lon + INTEGER :: NUMBSTAT_LOC = 0 ! number of stations on this process ! TYPE(TSTATIONTIME) :: TSTATIONS_TIME TYPE(TSTATIONDATA), DIMENSION(:), POINTER :: TSTATIONS ! characteristics and records of the stations @@ -58,7 +64,7 @@ TYPE(STATION_t), DIMENSION(JPMODELMAX), TARGET, SAVE :: STATION_MODEL LOGICAL, POINTER :: LSTATION=>NULL() INTEGER, POINTER :: NUMBSTAT=>NULL() -LOGICAL, POINTER :: LSTATLAT=>NULL() +INTEGER, POINTER :: NUMBSTAT_LOC=>NULL() TYPE(TSTATIONTIME), POINTER :: TSTATIONS_TIME => NULL() TYPE(TSTATIONDATA), DIMENSION(:), POINTER :: TSTATIONS => NULL() @@ -73,7 +79,7 @@ STATION_MODEL(KFROM)%TSTATIONS => TSTATIONS ! Current model is set to model KTO LSTATION => STATION_MODEL(KTO)%LSTATION NUMBSTAT => STATION_MODEL(KTO)%NUMBSTAT -LSTATLAT => STATION_MODEL(KTO)%LSTATLAT +NUMBSTAT_LOC => STATION_MODEL(KTO)%NUMBSTAT_LOC TSTATIONS_TIME => STATION_MODEL(KTO)%TSTATIONS_TIME TSTATIONS => STATION_MODEL(KTO)%TSTATIONS diff --git a/src/MNH/modd_type_station.f90 b/src/MNH/modd_type_station.f90 index ac0134eab..8d34883fa 100644 --- a/src/MNH/modd_type_station.f90 +++ b/src/MNH/modd_type_station.f90 @@ -30,14 +30,14 @@ !! ------------- !! Original 15/01/02 ! P. Wautelet 13/09/2019: budget: simplify and modernize date/time management -! P. Wautelet 07/04/2022: rewrite types for stations +! P. Wautelet 04/2022: restructure stations for better performance, reduce memory usage and correct some problems/bugs !------------------------------------------------------------------------------- ! !* 0. DECLARATIONS ! ------------ ! use modd_type_date, only: date_time -use modd_parameters, only: NNEGUNDEF, NUNDEF, XUNDEF +use modd_parameters, only: NNEGUNDEF, XUNDEF implicit none @@ -54,10 +54,10 @@ END TYPE TSTATIONTIME TYPE TSTATIONDATA ! Type to store all the data of 1 station + CHARACTER(LEN=8) :: CNAME = '' ! station name -CHARACTER(LEN=8) :: CTYPE = '' ! station type (currently not used) -LOGICAL :: LERROR = .FALSE. ! -LOGICAL :: LPRESENT = .FALSE. ! If true, this station is situated on this process + +INTEGER :: NID = 0 ! Global identification number of the station (from 1 to total number of stations of the model) REAL :: XX = XUNDEF ! X(n) REAL :: XY = XUNDEF ! Y(n) @@ -78,7 +78,7 @@ REAL :: XYMCOEF = XUNDEF ! Interpolation coefficient for Y (mass-point) REAL :: XXUCOEF = XUNDEF ! Interpolation coefficient for X (U-point) REAL :: XYVCOEF = XUNDEF ! Interpolation coefficient for Y (V-point) -INTEGER :: NK = NUNDEF ! Model level for altitude comparisons +INTEGER :: NK = NNEGUNDEF ! Model level for altitude comparisons REAL, DIMENSION(:), ALLOCATABLE :: XZON ! zonal wind(n) REAL, DIMENSION(:), ALLOCATABLE :: XMER ! meridian wind(n) diff --git a/src/MNH/modn_stationn.f90 b/src/MNH/modn_stationn.f90 index f388061e7..ab6013ee2 100644 --- a/src/MNH/modn_stationn.f90 +++ b/src/MNH/modn_stationn.f90 @@ -1,4 +1,4 @@ -!MNH_LIC Copyright 2020-2021 CNRS, Meteo-France and Universite Paul Sabatier +!MNH_LIC Copyright 2020-2022 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. @@ -21,6 +21,7 @@ !! MODIFICATIONS !! ------------- !! Original 10/03/20 +! P. Wautelet 04/2022: restructure stations for better performance, reduce memory usage and correct some problems/bugs !! !! IMPLICIT ARGUMENTS !! ------------------ @@ -34,7 +35,6 @@ USE MODD_ALLSTATION_n, ONLY:& XLON_STAT_n =>XLON_STAT ,& XZ_STAT_n =>XZ_STAT ,& CNAME_STAT_n =>CNAME_STAT ,& - CTYPE_STAT_n =>CTYPE_STAT ,& CFILE_STAT_n =>CFILE_STAT ,& LDIAG_SURFRAD_n =>LDIAG_SURFRAD !! @@ -46,7 +46,7 @@ IMPLICIT NONE INTEGER ,SAVE:: NNUMB_STAT REAL ,SAVE:: XSTEP_STAT REAL, DIMENSION(100) ,SAVE:: XX_STAT, XY_STAT, XZ_STAT, XLAT_STAT, XLON_STAT -CHARACTER (LEN=7), DIMENSION(100),SAVE:: CNAME_STAT, CTYPE_STAT +CHARACTER (LEN=7), DIMENSION(100),SAVE:: CNAME_STAT CHARACTER (LEN=20) ,SAVE:: CFILE_STAT !filename LOGICAL ,SAVE:: LDIAG_SURFRAD @@ -54,7 +54,7 @@ NAMELIST /NAM_STATIONn/ & NNUMB_STAT, XSTEP_STAT, & XX_STAT,XY_STAT,XZ_STAT,& XLON_STAT,XLAT_STAT,& - CNAME_STAT,CTYPE_STAT,& + CNAME_STAT,& CFILE_STAT,LDIAG_SURFRAD ! @@ -69,7 +69,6 @@ SUBROUTINE INIT_NAM_STATIONn XLON_STAT = XLON_STAT_n XZ_STAT = XZ_STAT_n CNAME_STAT = CNAME_STAT_n - CTYPE_STAT = CTYPE_STAT_n CFILE_STAT = CFILE_STAT_n LDIAG_SURFRAD= LDIAG_SURFRAD_n END SUBROUTINE INIT_NAM_STATIONn @@ -83,7 +82,6 @@ SUBROUTINE UPDATE_NAM_STATIONn XLON_STAT_n = XLON_STAT XZ_STAT_n = XZ_STAT CNAME_STAT_n = CNAME_STAT - CTYPE_STAT_n = CTYPE_STAT CFILE_STAT_n = CFILE_STAT LDIAG_SURFRAD_n= LDIAG_SURFRAD END SUBROUTINE UPDATE_NAM_STATIONn diff --git a/src/MNH/station_reader.f90 b/src/MNH/station_reader.f90 index 3e7741e8b..1a72bfe1a 100644 --- a/src/MNH/station_reader.f90 +++ b/src/MNH/station_reader.f90 @@ -4,21 +4,18 @@ !MNH_LIC for details. version 1. !----------------------------------------------------------------- ! ####################### - MODULE MODI_STATION_READER + MODULE MODE_STATION_READER ! ####################### -! -INTERFACE -! -SUBROUTINE READ_CSV_STATION( HFILE, TPSTATIONS, OCARTESIAN ) -USE MODD_STATION_n -CHARACTER(LEN=*), INTENT(IN) :: HFILE ! file to read -TYPE(TSTATIONDATA), DIMENSION(:), POINTER, INTENT(INOUT) :: TPSTATIONS -LOGICAL, INTENT(IN) :: OCARTESIAN -END SUBROUTINE READ_CSV_STATION -! -END INTERFACE -! -END MODULE MODI_STATION_READER + +IMPLICIT NONE + +PRIVATE + +PUBLIC :: READ_CSV_STATION + +INTEGER, PARAMETER :: NMAXLINELGT = 400 + +CONTAINS !------------------------------------------------------------------- ! !!**** *READ_CSV_STATION* - @@ -34,85 +31,85 @@ END MODULE MODI_STATION_READER !! MODIFICATIONS !! ------------- !! 03/2020 Original -! P. Wautelet 07/04/2022: rewrite types for stations +! P. Wautelet 04/2022: restructure stations for better performance, reduce memory usage and correct some problems/bugs !--------------------------------------------------------------- ! -!######################################################### -SUBROUTINE READ_CSV_STATION( HFILE, TPSTATIONS, OCARTESIAN ) -USE MODD_ALLSTATION_n -USE MODD_STATION_n -USE MODD_PARAMETERS -USE MODD_TYPE_STATION -USE MODI_INI_SURFSTATION_n +!############################################################################################### +SUBROUTINE READ_CSV_STATION( HFILE, PXHAT_GLOB, PYHAT_GLOB, PXHATM, PYHATM, & + PXHATM_PHYS_MIN, PXHATM_PHYS_MAX,PYHATM_PHYS_MIN, PYHATM_PHYS_MAX ) +!############################################################################################### +USE MODD_CONF, ONLY: LCARTESIAN +USE MODD_STATION_n, ONLY: NUMBSTAT +USE MODD_TYPE_STATION, ONLY: TSTATIONDATA + +USE MODE_MSG +USE MODE_STATION_TOOLS, ONLY: STATION_ADD, STATION_INI_INTERP, STATION_POSITION + +CHARACTER(LEN=*), INTENT(IN) :: HFILE ! file to read +REAL, DIMENSION(:), INTENT(IN) :: PXHAT_GLOB +REAL, DIMENSION(:), INTENT(IN) :: PYHAT_GLOB +REAL, DIMENSION(:), INTENT(IN) :: PXHATM ! mass point coordinates +REAL, DIMENSION(:), INTENT(IN) :: PYHATM ! mass point coordinates +REAL, INTENT(IN) :: PXHATM_PHYS_MIN, PYHATM_PHYS_MIN ! Minimum X coordinate of mass points in the physical domain +REAL, INTENT(IN) :: PXHATM_PHYS_MAX, PYHATM_PHYS_MAX ! Minimum X coordinate of mass points in the physical domain ! -CHARACTER(LEN=*), INTENT(IN) :: HFILE ! file to read -TYPE(TSTATIONDATA), DIMENSION(:), POINTER, INTENT(INOUT) :: TPSTATIONS -LOGICAL, INTENT(IN) :: OCARTESIAN -! -INTEGER :: INBLINE ! Nb of line in csv file -! -CHARACTER(LEN=80) :: YERROR -CHARACTER(LEN=400) :: YSTRING -INTEGER :: ILU ! logical unit of the file -! +CHARACTER(LEN=NMAXLINELGT) :: YSTRING +INTEGER :: ILU ! logical unit of the file +INTEGER :: INBLINE ! Nb of lines in csv file +INTEGER :: JI +LOGICAL :: GINSIDE ! True if station is inside physical domain of model +LOGICAL :: GPRESENT ! True if station is present on the current process +TYPE(TSTATIONDATA) :: TZSTATION + +INBLINE = 0 !Number of stations found in the file +NUMBSTAT = 0 !Number of stations found in the file AND inside the model domain ! Open file -OPEN(NEWUNIT=ILU,FILE=HFILE, FORM='formatted') -! Count lines -REWIND(ILU) -INBLINE=0 +OPEN( NEWUNIT = ILU, FILE = HFILE, FORM = 'formatted' ) + +READ( ILU, END = 101, FMT = '(A)' ) YSTRING ! Reading of header (skip it) + DO - READ(ILU,END=101,FMT='(A400)') YSTRING -!* analyses if the record has been written in French convention - CALL FRENCH_TO_ENGLISH(YSTRING) ! analyse de convention fr ou eng - IF (LEN_TRIM(YSTRING) > 0) THEN + ! Read station coordinates + READ( ILU, END = 101, FMT = '(A)' ) YSTRING + + ! Check if record is written in French convention + CALL FRENCH_TO_ENGLISH( YSTRING ) + + IF ( LCARTESIAN ) THEN + READ( YSTRING, * ) TZSTATION%CNAME, TZSTATION%XX, TZSTATION%XY, TZSTATION%XZ + ELSE + READ( YSTRING, * ) TZSTATION%CNAME, TZSTATION%XLAT, TZSTATION%XLON, TZSTATION%XZ + END IF + + IF ( .NOT. LCARTESIAN ) CALL STATION_INI_INTERP( TZSTATION ) + CALL STATION_POSITION( TZSTATION, PXHAT_GLOB, PYHAT_GLOB, PXHATM, PYHATM, & + PXHATM_PHYS_MIN, PXHATM_PHYS_MAX, PYHATM_PHYS_MIN, PYHATM_PHYS_MAX, & + GINSIDE, GPRESENT ) + + IF ( GINSIDE ) THEN + NUMBSTAT = NUMBSTAT + 1 + TZSTATION%NID = NUMBSTAT + END IF + + IF ( GPRESENT ) CALL STATION_ADD( TZSTATION ) + INBLINE = INBLINE + 1 - END IF END DO -! + 101 CONTINUE - IF (INBLINE == 0) THEN - YERROR = 'Data not found in file : '//TRIM(HFILE) - PRINT*, YERROR - ELSE - ! Save number of stations - NUMBSTAT = INBLINE - 1 - - ALLOCATE( TPSTATIONS(NUMBSTAT) ) - - ! New reading - REWIND(ILU) - READ(ILU,FMT='(A400)') YSTRING ! Reading of header - ! - ! Save the data - IF (OCARTESIAN) THEN - INBLINE = 1 - DO INBLINE=1, NUMBSTAT - READ(ILU,FMT='(A400)') YSTRING - READ(YSTRING,*) TPSTATIONS(INBLINE)%CNAME, & !TPSTATIONS(INBLINE)%CTYPE,& - TPSTATIONS(INBLINE)%XX, TPSTATIONS(INBLINE)%XY, TPSTATIONS(INBLINE)%XZ - END DO - REWIND(ILU) - CLOSE(ILU) - RETURN - ELSE - INBLINE = 1 - DO INBLINE=1, NUMBSTAT - READ(ILU,FMT='(A400)') YSTRING - READ(YSTRING,*) TPSTATIONS(INBLINE)%CNAME, & !TPSTATIONS(INBLINE)%CTYPE,& - TPSTATIONS(INBLINE)%XLAT, TPSTATIONS(INBLINE)%XLON, TPSTATIONS(INBLINE)%XZ - END DO - REWIND(ILU) - CLOSE(ILU) - RETURN - END IF - END IF -! + +CLOSE( ILU ) + +IF ( INBLINE == 0 ) CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'READ_CSV_STATION', 'Data not found in file ' // TRIM( HFILE ) ) + END SUBROUTINE READ_CSV_STATION + !######################################################### SUBROUTINE FRENCH_TO_ENGLISH(HSTRING) -CHARACTER(LEN=400), INTENT(INOUT) :: HSTRING ! csv record +CHARACTER(LEN=NMAXLINELGT), INTENT(INOUT) :: HSTRING ! csv record + INTEGER :: JL LOGICAL :: GFRENCH ! @@ -120,13 +117,13 @@ GFRENCH = .FALSE. !* analyses if the record has been written in French convention ! French convention (separator is ; decimal symbol is ,) ! or English convention (separator is , decimal symbol is .) -DO JL=1,400 +DO JL = 1, NMAXLINELGT IF (HSTRING(JL:JL)==';') GFRENCH=.TRUE. END DO ! ! If French convention is used in the file, transforms it in English convention IF (GFRENCH) THEN - DO JL=1,400 + DO JL = 1, NMAXLINELGT IF (HSTRING(JL:JL)==',') HSTRING(JL:JL)='.' IF (HSTRING(JL:JL)==';') HSTRING(JL:JL)=',' END DO @@ -134,3 +131,4 @@ END IF ! END SUBROUTINE FRENCH_TO_ENGLISH +END MODULE MODE_STATION_READER diff --git a/src/MNH/station_tools.f90 b/src/MNH/station_tools.f90 index 1aa02f68e..10b3c1ee3 100644 --- a/src/MNH/station_tools.f90 +++ b/src/MNH/station_tools.f90 @@ -1,9 +1,10 @@ -!MNH_LIC Copyright 2022-2022 CNRS, Meteo-France and Universite Paul Sabatier +!MNH_LIC Copyright 2002-2022 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. !----------------------------------------------------------------- -! Author: +! Authors: +! Misc: some of the code was taken from older subroutines/functions for stations ! P. Wautelet 08/04/2022 !----------------------------------------------------------------- ! Modifications: @@ -12,84 +13,381 @@ MODULE MODE_STATION_TOOLS ! ################## +USE MODD_TYPE_STATION, ONLY: TSTATIONDATA + IMPLICIT NONE PRIVATE +PUBLIC :: STATION_ALLOCATE +PUBLIC :: STATION_INI_INTERP PUBLIC :: STATION_POSITION +PUBLIC :: STATION_ADD +PUBLIC :: STATION_INTERP_2D, STATION_INTERP_2D_U, STATION_INTERP_2D_V CONTAINS -! ###################################### -SUBROUTINE STATION_POSITION( TPSTATION ) -! ###################################### +! ############################################## +SUBROUTINE STATION_ALLOCATE( TPSTATION, KSTORE ) +! ############################################## + + USE MODD_ALLSTATION_n, ONLY: LDIAG_SURFRAD + USE MODD_CONF_n, ONLY: NRR + USE MODD_NSV, ONLY: NSV + USE MODD_PARAMETERS, ONLY: XUNDEF + USE MODD_PARAM_n, ONLY: CRAD, CTURB + + IMPLICIT NONE + + TYPE(TSTATIONDATA), INTENT(INOUT) :: TPSTATION + INTEGER, INTENT(IN) :: KSTORE ! number of moments to store + + ALLOCATE( TPSTATION%XZON(KSTORE) ) + ALLOCATE( TPSTATION%XMER(KSTORE) ) + ALLOCATE( TPSTATION%XW (KSTORE) ) + ALLOCATE( TPSTATION%XP (KSTORE) ) + IF ( CTURB == 'TKEL' ) THEN + ALLOCATE( TPSTATION%XTKE(KSTORE) ) + ELSE + ALLOCATE( TPSTATION%XTKE(0) ) + END IF + ALLOCATE( TPSTATION%XTH(KSTORE) ) + ALLOCATE( TPSTATION%XR (KSTORE, NRR) ) + ALLOCATE( TPSTATION%XSV(KSTORE, NSV) ) + IF ( CRAD /= 'NONE' ) THEN + ALLOCATE( TPSTATION%XTSRAD(KSTORE) ) + ELSE + ALLOCATE( TPSTATION%XTSRAD(0) ) + END IF + IF ( LDIAG_SURFRAD ) THEN + ALLOCATE( TPSTATION%XT2M (KSTORE) ) + ALLOCATE( TPSTATION%XQ2M (KSTORE) ) + ALLOCATE( TPSTATION%XHU2M (KSTORE) ) + ALLOCATE( TPSTATION%XZON10M(KSTORE) ) + ALLOCATE( TPSTATION%XMER10M(KSTORE) ) + ALLOCATE( TPSTATION%XRN (KSTORE) ) + ALLOCATE( TPSTATION%XH (KSTORE) ) + ALLOCATE( TPSTATION%XLE (KSTORE) ) + ALLOCATE( TPSTATION%XLEI (KSTORE) ) + ALLOCATE( TPSTATION%XGFLUX (KSTORE) ) + IF ( CRAD /= 'NONE' ) THEN + ALLOCATE( TPSTATION%XSWD (KSTORE) ) + ALLOCATE( TPSTATION%XSWU (KSTORE) ) + ALLOCATE( TPSTATION%XLWD (KSTORE) ) + ALLOCATE( TPSTATION%XLWU (KSTORE) ) + ALLOCATE( TPSTATION%XSWDIR (KSTORE) ) + ALLOCATE( TPSTATION%XSWDIFF(KSTORE) ) + ALLOCATE( TPSTATION%XDSTAOD(KSTORE) ) + END IF + ALLOCATE( TPSTATION%XSFCO2(KSTORE) ) + END IF + + TPSTATION%XZON(:) = XUNDEF + TPSTATION%XMER(:) = XUNDEF + TPSTATION%XW(:) = XUNDEF + TPSTATION%XP(:) = XUNDEF + TPSTATION%XTKE(:) = XUNDEF + TPSTATION%XTH(:) = XUNDEF + TPSTATION%XR(:,:) = XUNDEF + TPSTATION%XSV(:,:) = XUNDEF + TPSTATION%XTSRAD(:) = XUNDEF + IF ( LDIAG_SURFRAD ) THEN + TPSTATION%XT2M(:) = XUNDEF + TPSTATION%XQ2M(:) = XUNDEF + TPSTATION%XHU2M(:) = XUNDEF + TPSTATION%XZON10M(:) = XUNDEF + TPSTATION%XMER10M(:) = XUNDEF + TPSTATION%XRN(:) = XUNDEF + TPSTATION%XH(:) = XUNDEF + TPSTATION%XLE(:) = XUNDEF + TPSTATION%XLEI(:) = XUNDEF + TPSTATION%XGFLUX(:) = XUNDEF + IF ( CRAD /= 'NONE' ) THEN + TPSTATION%XSWD(:) = XUNDEF + TPSTATION%XSWU(:) = XUNDEF + TPSTATION%XLWD(:) = XUNDEF + TPSTATION%XLWU(:) = XUNDEF + TPSTATION%XSWDIR(:) = XUNDEF + TPSTATION%XSWDIFF(:) = XUNDEF + TPSTATION%XDSTAOD(:) = XUNDEF + END IF + TPSTATION%XSFCO2(:) = XUNDEF + END IF + +END SUBROUTINE STATION_ALLOCATE + +! ######################################## +SUBROUTINE STATION_INI_INTERP( TPSTATION ) +! ######################################## + + USE MODD_GRID, ONLY: XLATORI, XLONORI + USE MODD_PARAMETERS, ONLY: XUNDEF + + USE MODE_GRIDPROJ, ONLY: SM_XYHAT + USE MODE_MSG + + IMPLICIT NONE + + TYPE(TSTATIONDATA), INTENT(INOUT) :: TPSTATION + + IF ( TPSTATION%XLAT == XUNDEF .OR. TPSTATION%XLON == XUNDEF ) THEN + CMNHMSG(1) = 'Error in station position' + CMNHMSG(2) = 'either LATitude or LONgitude segment' + CMNHMSG(3) = 'or I and J segment' + CMNHMSG(4) = 'definition is not complete.' + CALL PRINT_MSG( NVERB_FATAL, 'GEN', 'STATION_INI_INTERP' ) + END IF + + CALL SM_XYHAT( XLATORI, XLONORI, & + TPSTATION%XLAT, TPSTATION%XLON, & + TPSTATION%XX, TPSTATION%XY ) + +END SUBROUTINE STATION_INI_INTERP + +! ############################################################################################### +SUBROUTINE STATION_POSITION( TPSTATION, PXHAT_GLOB, PYHAT_GLOB, PXHATM, PYHATM, & + PXHATM_PHYS_MIN, PXHATM_PHYS_MAX,PYHATM_PHYS_MIN, PYHATM_PHYS_MAX, & + OINSIDE, OPRESENT ) +! ############################################################################################### ! Subroutine to determine the position of a station on the model grid -! and set the useful coefficient for data interpolation +! and set the useful coefficients for data interpolation - USE MODD_CONF, ONLY: L1D - USE MODD_GRID_n, ONLY: XXHAT, XYHAT - USE MODD_TYPE_STATION, ONLY: TSTATIONDATA + USE MODD_CONF, ONLY: L1D + USE MODD_GRID_n, ONLY: XXHAT, XYHAT, XZZ + USE MODD_PARAMETERS, ONLY: JPHEXT, JPVEXT - USE MODE_TOOLS_ll, ONLY: GET_INDICE_ll, LWEST_ll, LEAST_ll, LNORTH_ll, LSOUTH_ll + USE MODE_MSG + USE MODE_NEST_LL, ONLY: GET_MODEL_NUMBER_ll + USE MODE_TOOLS_ll, ONLY: GET_INDICE_ll IMPLICIT NONE TYPE(TSTATIONDATA), INTENT(INOUT) :: TPSTATION + REAL, DIMENSION(:), INTENT(IN) :: PXHAT_GLOB + REAL, DIMENSION(:), INTENT(IN) :: PYHAT_GLOB + REAL, DIMENSION(:), INTENT(IN) :: PXHATM ! mass point coordinates + REAL, DIMENSION(:), INTENT(IN) :: PYHATM ! mass point coordinates + REAL, INTENT(IN) :: PXHATM_PHYS_MIN, PYHATM_PHYS_MIN ! Minimum X coordinate of mass points in the physical domain + REAL, INTENT(IN) :: PXHATM_PHYS_MAX, PYHATM_PHYS_MAX ! Minimum X coordinate of mass points in the physical domain + LOGICAL, INTENT(OUT) :: OINSIDE ! True if station is inside physical domain of model + LOGICAL, INTENT(OUT) :: OPRESENT ! True if station is present on the current process INTEGER :: IIB ! domain sizes of current process INTEGER :: IJB ! INTEGER :: IIE ! INTEGER :: IJE ! - INTEGER :: IIU ! - INTEGER :: IJU ! - REAL, DIMENSION(SIZE(XXHAT)) :: ZXHATM ! mass point coordinates - REAL, DIMENSION(SIZE(XYHAT)) :: ZYHATM ! mass point coordinates - - IIU = SIZE( XXHAT ) - IJU = SIZE( XYHAT ) + INTEGER :: IMI + INTEGER :: JK + REAL :: ZLOW, ZHIGH - CALL GET_INDICE_ll (IIB, IJB, IIE, IJE ) + OPRESENT = .FALSE. + OINSIDE = .FALSE. - ! Interpolations of model variables to mass points - ZXHATM(1:IIU-1) = 0.5 * XXHAT(1:IIU-1) + 0.5 * XXHAT(2:IIU ) - ZXHATM( IIU ) = 1.5 * XXHAT( IIU ) - 0.5 * XXHAT( IIU-1) + CALL GET_INDICE_ll( IIB, IJB, IIE, IJE ) - ZYHATM(1:IJU-1) = 0.5 * XYHAT(1:IJU-1) + 0.5 * XYHAT(2:IJU ) - ZYHATM( IJU ) = 1.5 * XYHAT( IJU ) - 0.5 * XYHAT( IJU-1) - - TPSTATION%LPRESENT = .FALSE. + IF ( TPSTATION%XX >= PXHAT_GLOB(JPHEXT+1) .AND. TPSTATION%XX <= PXHAT_GLOB(UBOUND(PXHAT_GLOB,1)-JPHEXT+1) & + .AND. TPSTATION%XY >= PYHAT_GLOB(JPHEXT+1) .AND. TPSTATION%XY <= PYHAT_GLOB(UBOUND(PYHAT_GLOB,1)-JPHEXT+1) ) THEN + OINSIDE = .TRUE. + ELSE + CALL GET_MODEL_NUMBER_ll(IMI) + WRITE( CMNHMSG(1), "( 'station ', A, ' is outside of physical domain of model', I3 )" ) TRIM(TPSTATION%CNAME), IMI + CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'STATION_POSITION' ) + END IF ! X position TPSTATION%NI_U = COUNT( XXHAT (:) <= TPSTATION%XX ) - TPSTATION%NI_M = COUNT( ZXHATM(:) <= TPSTATION%XX ) - - IF ( TPSTATION%NI_M<=IIB-1 .AND. LWEST_ll() .AND. .NOT. L1D ) TPSTATION%LERROR = .TRUE. - IF ( TPSTATION%NI_M>=IIE .AND. LEAST_ll() .AND. .NOT. L1D ) TPSTATION%LERROR = .TRUE. + TPSTATION%NI_M = COUNT( PXHATM(:) <= TPSTATION%XX ) ! Y position TPSTATION%NJ_V = COUNT( XYHAT (:) <= TPSTATION%XY ) - TPSTATION%NJ_M = COUNT( ZYHATM(:) <= TPSTATION%XY ) + TPSTATION%NJ_M = COUNT( PYHATM(:) <= TPSTATION%XY ) - IF ( TPSTATION%NJ_M<=IJB-1 .AND. LSOUTH_ll() .AND. .NOT. L1D ) TPSTATION%LERROR = .TRUE. - IF ( TPSTATION%NJ_M>=IJE .AND. LNORTH_ll() .AND. .NOT. L1D ) TPSTATION%LERROR = .TRUE. - - ! Position of station according to processes + ! Position of station according to process IF ( TPSTATION%NI_U >= IIB .AND. TPSTATION%NI_U <= IIE & - .AND. TPSTATION%NJ_V >= IJB .AND. TPSTATION%NJ_V <= IJE ) TPSTATION%LPRESENT = .TRUE. - IF ( L1D ) TPSTATION%LPRESENT = .TRUE. + .AND. TPSTATION%NJ_V >= IJB .AND. TPSTATION%NJ_V <= IJE ) OPRESENT = .TRUE. + IF ( L1D ) OPRESENT = .TRUE. + + ! Check if station is too near of physical domain border (outside of physical domain for mass points) + IF ( OINSIDE .AND. .NOT. L1D ) THEN + IF ( TPSTATION%XX < PXHATM_PHYS_MIN .OR. TPSTATION%XX > PXHATM_PHYS_MAX & + .OR. TPSTATION%XY < PYHATM_PHYS_MIN .OR. TPSTATION%XY > PYHATM_PHYS_MAX ) THEN + CALL GET_MODEL_NUMBER_ll(IMI) + WRITE( CMNHMSG(1), "( 'station ', A, ' is outside of mass-points physical domain of model', I3 )" ) & + TRIM(TPSTATION%CNAME), IMI + CMNHMSG(2) = 'but is inside of flux-points physical domain.' + CMNHMSG(3) = 'Meaning: station is too close to the boundaries of physical domain.' + CMNHMSG(4) = '=> station disabled (not computed)' + CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'STATION_POSITION' ) + OPRESENT = .FALSE. + OINSIDE = .FALSE. + END IF + END IF ! Computations only on correct process - IF ( TPSTATION%LPRESENT .AND. .NOT. L1D ) THEN + IF ( OPRESENT .AND. .NOT. L1D ) THEN ! Interpolation coefficient for X (mass-point) - TPSTATION%XXMCOEF = ( TPSTATION%XX - ZXHATM(TPSTATION%NI_M) ) / ( ZXHATM(TPSTATION%NI_M+1) - ZXHATM(TPSTATION%NI_M) ) + TPSTATION%XXMCOEF = ( TPSTATION%XX - PXHATM(TPSTATION%NI_M) ) / ( PXHATM(TPSTATION%NI_M+1) - PXHATM(TPSTATION%NI_M) ) ! Interpolation coefficient for Y (mass-point) - TPSTATION%XYMCOEF = ( TPSTATION%XY - ZYHATM(TPSTATION%NJ_M) ) / ( ZYHATM(TPSTATION%NJ_M+1) - ZYHATM(TPSTATION%NJ_M) ) + TPSTATION%XYMCOEF = ( TPSTATION%XY - PYHATM(TPSTATION%NJ_M) ) / ( PYHATM(TPSTATION%NJ_M+1) - PYHATM(TPSTATION%NJ_M) ) ! Interpolation coefficient for X (U-point) TPSTATION%XXUCOEF = ( TPSTATION%XX - XXHAT(TPSTATION%NI_U) ) / ( XXHAT(TPSTATION%NI_U+1) - XXHAT(TPSTATION%NI_U) ) ! Interpolation coefficient for Y (V-point) TPSTATION%XYVCOEF = ( TPSTATION%XY - XYHAT(TPSTATION%NJ_V) ) / ( XYHAT(TPSTATION%NJ_V+1) - XYHAT(TPSTATION%NJ_V) ) END IF + IF ( OPRESENT ) THEN + ! The closest K-level to the station altitude is chosen + JK = JPVEXT + 1 + DO WHILE ( ( STATION_INTERP_2D( TPSTATION, XZZ(:,:,JK) ) - STATION_INTERP_2D( TPSTATION, XZZ(:,:,JPVEXT+1) ) ) < TPSTATION%XZ) + JK = JK + 1 + END DO + ZLOW = STATION_INTERP_2D( TPSTATION, XZZ(:,:,JK-1) ) - STATION_INTERP_2D( TPSTATION, XZZ(:,:,JPVEXT+1) ) + ZHIGH = STATION_INTERP_2D( TPSTATION, XZZ(:,:,JK ) ) - STATION_INTERP_2D( TPSTATION, XZZ(:,:,JPVEXT+1) ) + !If the station is nearer from the lower level, select it + IF ( ( ZHIGH - TPSTATION%XZ ) > ( TPSTATION%XZ - ZLOW ) ) JK = JK - 1 + TPSTATION%NK = JK + END IF + END SUBROUTINE STATION_POSITION +! ################################# +SUBROUTINE STATION_ADD( TPSTATION ) +! ################################# +! Subroutine to add a station to the local list of stations + USE MODD_STATION_n, ONLY: NUMBSTAT_LOC, TSTATIONS + + IMPLICIT NONE + + TYPE(TSTATIONDATA), INTENT(IN) :: TPSTATION + + INTEGER :: JS + TYPE(TSTATIONDATA), DIMENSION(:), POINTER :: TZSTATIONS + + NUMBSTAT_LOC = NUMBSTAT_LOC + 1 + + ALLOCATE( TZSTATIONS( NUMBSTAT_LOC ) ) + DO JS = 1, NUMBSTAT_LOC - 1 + TZSTATIONS(JS) = TSTATIONS(JS) + END DO + TZSTATIONS(NUMBSTAT_LOC) = TPSTATION + IF ( ASSOCIATED( TSTATIONS ) ) DEALLOCATE( TSTATIONS ) !Can be done without memory leak because allocatable arrays were + !not yet allocated (will be done in STATION_ALLOCATE) + TSTATIONS => TZSTATIONS + +END SUBROUTINE STATION_ADD +! +! ###################################################### +FUNCTION STATION_INTERP_2D( TPSTATION, PA ) RESULT( PB ) +! ###################################################### + USE MODD_CONF, ONLY: L1D + + USE MODE_MSG + + IMPLICIT NONE + + TYPE(TSTATIONDATA), INTENT(IN) :: TPSTATION + REAL, DIMENSION(:,:), INTENT(IN) :: PA + REAL :: PB + + INTEGER :: JI, JJ + + IF ( SIZE( PA, 1 ) == 2 ) THEN + JI = 1 + JJ = 1 + ELSE IF ( L1D ) THEN + JI = 2 + JJ = 2 + ELSE + JI = TPSTATION%NI_M + JJ = TPSTATION%NJ_M + END IF + + IF ( JI >= 1 .AND. JI < SIZE( PA, 1 ) & + .AND. JJ >= 1 .AND. JJ < SIZE( PA, 2 ) ) THEN + PB = (1.-TPSTATION%XXMCOEF) * (1.-TPSTATION%XYMCOEF) * PA(JI,JJ) + & + ( TPSTATION%XXMCOEF) * (1.-TPSTATION%XYMCOEF) * PA(JI+1,JJ) + & + (1.-TPSTATION%XXMCOEF) * ( TPSTATION%XYMCOEF) * PA(JI,JJ+1) + & + ( TPSTATION%XXMCOEF) * ( TPSTATION%XYMCOEF) * PA(JI+1,JJ+1) + ELSE + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATION_INTERP_2D', 'value can not be interpolated' ) + END IF + +END FUNCTION STATION_INTERP_2D + +! ######################################################## +FUNCTION STATION_INTERP_2D_U( TPSTATION, PA ) RESULT( PB ) +! ######################################################## + USE MODD_CONF, ONLY: L1D + + USE MODE_MSG + + IMPLICIT NONE + + TYPE(TSTATIONDATA), INTENT(IN) :: TPSTATION + REAL, DIMENSION(:,:), INTENT(IN) :: PA + REAL :: PB + + INTEGER :: JI, JJ + + IF ( SIZE( PA, 1 ) == 2 ) THEN + JI = 1 + JJ = 1 + ELSE IF ( L1D ) THEN + JI = 2 + JJ = 2 + ELSE + JI = TPSTATION%NI_U + JJ = TPSTATION%NJ_M + END IF + + IF ( JI >= 1 .AND. JI < SIZE( PA, 1 ) & + .AND. JJ >= 1 .AND. JJ < SIZE( PA, 2 ) ) THEN + PB = (1.-TPSTATION%XXUCOEF) * (1.-TPSTATION%XYMCOEF) * PA(JI,JJ) + & + ( TPSTATION%XXUCOEF) * (1.-TPSTATION%XYMCOEF) * PA(JI+1,JJ) + & + (1.-TPSTATION%XXUCOEF) * ( TPSTATION%XYMCOEF) * PA(JI,JJ+1) + & + ( TPSTATION%XXUCOEF) * ( TPSTATION%XYMCOEF) * PA(JI+1,JJ+1) + ELSE + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATION_INTERP_2D_U', 'value can not be interpolated' ) + END IF + +END FUNCTION STATION_INTERP_2D_U + +! ######################################################## +FUNCTION STATION_INTERP_2D_V( TPSTATION, PA ) RESULT( PB ) +! ######################################################## + USE MODD_CONF, ONLY: L1D + + USE MODE_MSG + + IMPLICIT NONE + + TYPE(TSTATIONDATA), INTENT(IN) :: TPSTATION + REAL, DIMENSION(:,:), INTENT(IN) :: PA + REAL :: PB + + INTEGER :: JI, JJ + + IF ( SIZE( PA, 1 ) == 2 ) THEN + JI = 1 + JJ = 1 + ELSE IF ( L1D ) THEN + JI = 2 + JJ = 2 + ELSE + JI = TPSTATION%NI_M + JJ = TPSTATION%NJ_V + END IF + + IF ( JI >= 1 .AND. JI < SIZE( PA, 1 ) & + .AND. JJ >= 1 .AND. JJ < SIZE( PA, 2 ) ) THEN + PB = (1.-TPSTATION%XXMCOEF) * (1.-TPSTATION%XYVCOEF) * PA(JI,JJ) + & + ( TPSTATION%XXMCOEF) * (1.-TPSTATION%XYVCOEF) * PA(JI+1,JJ) + & + (1.-TPSTATION%XXMCOEF) * ( TPSTATION%XYVCOEF) * PA(JI,JJ+1) + & + ( TPSTATION%XXMCOEF) * ( TPSTATION%XYVCOEF) * PA(JI+1,JJ+1) + ELSE + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATION_INTERP_2D_V', 'value can not be interpolated' ) + END IF + +END FUNCTION STATION_INTERP_2D_V + END MODULE MODE_STATION_TOOLS diff --git a/src/MNH/stationn.f90 b/src/MNH/stationn.f90 index dcb38f6d3..0343d9da3 100644 --- a/src/MNH/stationn.f90 +++ b/src/MNH/stationn.f90 @@ -75,33 +75,29 @@ END MODULE MODI_STATION_n ! A. Lemonsu 19/11/2002 ! P. Aumond 01/07/2011: add model levels ! C. Lac 04/2013: correction on the vertical levels -! C. Lac 04/2013: add I/J positioning +! C. Lac 04/2013: add I/JK positioning ! P. Wautelet 28/03/2018: replace TEMPORAL_DIST by DATETIME_DISTANCE ! P. Wautelet 05/2016-04/2018: new data structures and calls for I/O ! P. Wautelet 13/09/2019: budget: simplify and modernize date/time management ! R. Schoetter 11/2019: use LCARTESIAN instead of LSTATLAT for multiproc in cartesian -! P. Wautelet 07/04/2022: rewrite types for stations +! P. Wautelet 04/2022: restructure stations for better performance, reduce memory usage and correct some problems/bugs ! ! -------------------------------------------------------------------------- ! !* 0. DECLARATIONS ! ------------ ! -USE MODD_CONF -USE MODD_CST +USE MODD_CONF, ONLY: LCARTESIAN +USE MODD_CST, ONLY: XPI USE MODD_DIAG_IN_RUN -USE MODD_GRID -USE MODD_PARAMETERS +USE MODD_GRID, ONLY: XBETA, XLON0, XRPK +USE MODD_PARAMETERS, ONLY: JPVEXT, XUNDEF USE MODD_PARAM_n, ONLY: CRAD USE MODD_STATION_n USE MODD_ALLSTATION_n, ONLY: LDIAG_SURFRAD -USE MODD_TIME, ONLY: tdtexp USE MODD_TIME_n, ONLY: tdtcur ! -USE MODE_ll -! -USE MODI_WATER_SUM -! +USE MODE_STATION_TOOLS, ONLY: STATION_INTERP_2D, STATION_INTERP_2D_U, STATION_INTERP_2D_V ! ! IMPLICIT NONE @@ -129,21 +125,6 @@ REAL, DIMENSION(:,:,:), INTENT(IN) :: PP ! pressure ! 0.2 declaration of local variables ! ! -INTEGER :: IIB ! current processor domain sizes -INTEGER :: IJB ! -INTEGER :: IIE ! -INTEGER :: IJE ! -INTEGER :: IIU ! -INTEGER :: IJU ! -! -REAL, DIMENSION(SIZE(PXHAT)) :: ZXHATM ! mass point coordinates -REAL, DIMENSION(SIZE(PYHAT)) :: ZYHATM ! mass point coordinates -! -REAL, DIMENSION(SIZE(PSV,1),SIZE(PSV,2),SIZE(PSV,3),SIZE(PSV,4)) :: ZWORK ! -! -LOGICAL :: GSTORE ! storage occurs at this time step -! -! INTEGER :: IN ! time index INTEGER :: JSV ! loop counter ! @@ -151,33 +132,8 @@ REAL :: ZU_STAT ! horizontal wind speed at station location (along x) REAL :: ZV_STAT ! horizontal wind speed at station location (along y) REAL :: ZGAM ! rotation between meso-nh base and spherical lat-lon base. ! -INTEGER :: IRESP ! return code -INTEGER :: I ! loop for stations -INTEGER :: J ! loop for levels - -! -!---------------------------------------------------------------------------- -! -!* 2. PRELIMINARIES -! ------------- -! -!* 2.1 Indices -! ------- -! -CALL GET_INDICE_ll (IIB,IJB,IIE,IJE) -! -! -!* 2.2 Interpolations of model variables to mass points -! ------------------------------------------------ -! -IIU=SIZE(PXHAT) -IJU=SIZE(PYHAT) -! -ZXHATM(1:IIU-1)=0.5*PXHAT(1:IIU-1)+0.5*PXHAT(2:IIU ) -ZXHATM( IIU )=1.5*PXHAT( IIU )-0.5*PXHAT( IIU-1) -! -ZYHATM(1:IJU-1)=0.5*PYHAT(1:IJU-1)+0.5*PYHAT(2:IJU ) -ZYHATM( IJU )=1.5*PYHAT( IJU )-0.5*PYHAT( IJU-1) +INTEGER :: JS ! loop for stations +INTEGER :: JK ! loop for levels ! !---------------------------------------------------------------------------- ! @@ -189,260 +145,73 @@ IF ( TSTATIONS_TIME%XTIME_CUR == XUNDEF ) TSTATIONS_TIME%XTIME_CUR = TSTATIONS_T TSTATIONS_TIME%XTIME_CUR = TSTATIONS_TIME%XTIME_CUR + PTSTEP ! IF ( TSTATIONS_TIME%XTIME_CUR >= TSTATIONS_TIME%XTSTEP - 1.E-10 ) THEN - GSTORE = .TRUE. - TSTATIONS_TIME%XTIME_CUR = TSTATIONS_TIME%XTIME_CUR - TSTATIONS_TIME%XTSTEP - TSTATIONS_TIME%N_CUR = TSTATIONS_TIME%N_CUR + 1 - IN = TSTATIONS_TIME%N_CUR -ELSE - GSTORE = .FALSE. -END IF -! -IF (GSTORE) THEN -#if 0 - tstations_time%tpdates(in)%date%year = tdtexp%date%year - tstations_time%tpdates(in)%date%month = tdtexp%date%month - tstations_time%tpdates(in)%date%day = tdtexp%date%day - tstations_time%tpdates(in)%xtime = tdtexp%xtime + ( in - 1 ) * tstation%step -#else + TSTATIONS_TIME%XTIME_CUR = TSTATIONS_TIME%XTIME_CUR - TSTATIONS_TIME%XTSTEP + TSTATIONS_TIME%N_CUR = TSTATIONS_TIME%N_CUR + 1 + IN = TSTATIONS_TIME%N_CUR tstations_time%tpdates(in) = tdtcur -#endif +ELSE + !No station storage at this time step + RETURN END IF ! -! !---------------------------------------------------------------------------- ! !* 8. DATA RECORDING ! -------------- ! -IF (GSTORE) THEN - DO I=1,NUMBSTAT - ! - IF ( TSTATIONS(I)%LPRESENT .AND. .NOT. TSTATIONS(I)%LERROR ) THEN - IF (TSTATIONS(I)%NK/= XUNDEF) THEN - J = TSTATIONS(I)%NK - ELSE ! suppose TSTATIONS(I)%XZ /= XUNDEF - J=1 - DO WHILE ((STATION_INTERP_2D(PZ(:,:,J))-STATION_INTERP_2D(PZ(:,:,2))) & - < TSTATIONS(I)%XZ) - J = J + 1 - END DO - IF (((STATION_INTERP_2D(PZ(:,:,J))-STATION_INTERP_2D(PZ(:,:,2)))-TSTATIONS(I)%XZ)>& - (TSTATIONS(I)%XZ-(STATION_INTERP_2D(PZ(:,:,J-1))-STATION_INTERP_2D(PZ(:,:,2))))) THEN - J=J-1 - ENDIF - END IF - ! - IF (LCARTESIAN) THEN - TSTATIONS(I)%XZON (IN) = STATION_INTERP_2D_U(PU(:,:,J)) - TSTATIONS(I)%XMER (IN) = STATION_INTERP_2D_V(PV(:,:,J)) - ELSE - ZU_STAT = STATION_INTERP_2D_U(PU(:,:,J)) - ZV_STAT = STATION_INTERP_2D_V(PV(:,:,J)) - ZGAM = (XRPK * (TSTATIONS(I)%XLON - XLON0) - XBETA)*(XPI/180.) - TSTATIONS(I)%XZON (IN) = ZU_STAT * COS(ZGAM) + ZV_STAT * SIN(ZGAM) - TSTATIONS(I)%XMER (IN) = - ZU_STAT * SIN(ZGAM) + ZV_STAT * COS(ZGAM) - ENDIF - TSTATIONS(I)%XW (IN) = STATION_INTERP_2D(PW(:,:,J)) - TSTATIONS(I)%XTH (IN) = STATION_INTERP_2D(PTH(:,:,J)) - TSTATIONS(I)%XP (IN) = STATION_INTERP_2D(PP(:,:,J)) - ! - DO JSV=1,SIZE(PR,4) - TSTATIONS(I)%XR (IN,JSV) = STATION_INTERP_2D(PR(:,:,J,JSV)) - END DO - ! - DO JSV=1,SIZE(PSV,4) - TSTATIONS(I)%XSV (IN,JSV) = STATION_INTERP_2D(PSV(:,:,J,JSV)) - END DO - ! - IF (SIZE(PTKE)>0) TSTATIONS(I)%XTKE (IN) = STATION_INTERP_2D(PTKE(:,:,J)) - IF (SIZE(PTS) >0) TSTATIONS(I)%XTSRAD(IN) = STATION_INTERP_2D(PTS) - TSTATIONS(I)%XZS = STATION_INTERP_2D(PZ(:,:,1+JPVEXT)) - ! - IF (LDIAG_SURFRAD) THEN - TSTATIONS(I)%XZON10M(IN) = STATION_INTERP_2D(XCURRENT_ZON10M) - TSTATIONS(I)%XMER10M(IN) = STATION_INTERP_2D(XCURRENT_MER10M) - TSTATIONS(I)%XT2M (IN) = STATION_INTERP_2D(XCURRENT_T2M ) - TSTATIONS(I)%XQ2M (IN) = STATION_INTERP_2D(XCURRENT_Q2M ) - TSTATIONS(I)%XHU2M (IN) = STATION_INTERP_2D(XCURRENT_HU2M ) - TSTATIONS(I)%XRN (IN) = STATION_INTERP_2D(XCURRENT_RN ) - TSTATIONS(I)%XH (IN) = STATION_INTERP_2D(XCURRENT_H ) - TSTATIONS(I)%XLE (IN) = STATION_INTERP_2D(XCURRENT_LE ) - TSTATIONS(I)%XLEI (IN) = STATION_INTERP_2D(XCURRENT_LEI ) - TSTATIONS(I)%XGFLUX (IN) = STATION_INTERP_2D(XCURRENT_GFLUX ) - IF (CRAD /= 'NONE') THEN - TSTATIONS(I)%XSWD (IN) = STATION_INTERP_2D(XCURRENT_SWD ) - TSTATIONS(I)%XSWU (IN) = STATION_INTERP_2D(XCURRENT_SWU ) - TSTATIONS(I)%XLWD (IN) = STATION_INTERP_2D(XCURRENT_LWD ) - TSTATIONS(I)%XLWU (IN) = STATION_INTERP_2D(XCURRENT_LWU ) - TSTATIONS(I)%XSWDIR (IN) = STATION_INTERP_2D(XCURRENT_SWDIR ) - TSTATIONS(I)%XSWDIFF(IN) = STATION_INTERP_2D(XCURRENT_SWDIFF) - TSTATIONS(I)%XDSTAOD(IN) = STATION_INTERP_2D(XCURRENT_DSTAOD) - ENDIF - TSTATIONS(I)%XSFCO2 (IN) = STATION_INTERP_2D(XCURRENT_SFCO2 ) - ENDIF +STATION: DO JS = 1,NUMBSTAT_LOC + JK = TSTATIONS(JS)%NK + + IF (LCARTESIAN) THEN + TSTATIONS(JS)%XZON(IN) = STATION_INTERP_2D_U( TSTATIONS(JS), PU(:,:,JK) ) + TSTATIONS(JS)%XMER(IN) = STATION_INTERP_2D_V( TSTATIONS(JS), PV(:,:,JK) ) + ELSE + ZU_STAT = STATION_INTERP_2D_U( TSTATIONS(JS), PU(:,:,JK) ) + ZV_STAT = STATION_INTERP_2D_V( TSTATIONS(JS), PV(:,:,JK) ) + ZGAM = (XRPK * (TSTATIONS(JS)%XLON - XLON0) - XBETA)*(XPI/180.) + TSTATIONS(JS)%XZON(IN) = ZU_STAT * COS(ZGAM) + ZV_STAT * SIN(ZGAM) + TSTATIONS(JS)%XMER(IN) = - ZU_STAT * SIN(ZGAM) + ZV_STAT * COS(ZGAM) + END IF + TSTATIONS(JS)%XW (IN) = STATION_INTERP_2D( TSTATIONS(JS), PW(:,:,JK) ) + TSTATIONS(JS)%XTH(IN) = STATION_INTERP_2D( TSTATIONS(JS), PTH(:,:,JK) ) + TSTATIONS(JS)%XP (IN) = STATION_INTERP_2D( TSTATIONS(JS), PP(:,:,JK) ) - ! - END IF -! -!---------------------------------------------------------------------------- -! -!* 11. EXCHANGE OF INFORMATION BETWEEN PROCESSORS -! ------------------------------------------ -! -!* 11.2 data stored -! ----------- -! - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XX ) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XY ) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XZ ) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XLON ) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XLAT ) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XZON (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XMER (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XW (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XP (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XTH (IN)) DO JSV=1,SIZE(PR,4) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XR (IN,JSV)) + TSTATIONS(JS)%XR(IN,JSV) = STATION_INTERP_2D( TSTATIONS(JS), PR(:,:,JK,JSV) ) END DO + DO JSV=1,SIZE(PSV,4) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XSV (IN,JSV)) + TSTATIONS(JS)%XSV(IN,JSV) = STATION_INTERP_2D( TSTATIONS(JS), PSV(:,:,JK,JSV) ) END DO - IF (SIZE(PTKE)>0) CALL DISTRIBUTE_STATION(TSTATIONS(I)%XTKE (IN)) - IF (SIZE(PTS) >0) CALL DISTRIBUTE_STATION(TSTATIONS(I)%XTSRAD(IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XZS ) - IF (LDIAG_SURFRAD) THEN - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XT2M (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XQ2M (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XHU2M (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XZON10M (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XMER10M (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XRN (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XH (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XLE (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XLEI (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XGFLUX (IN)) - IF (CRAD /= 'NONE') THEN - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XSWD (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XSWU (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XLWD (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XLWU (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XSWDIR (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XSWDIFF (IN)) - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XDSTAOD (IN)) - END IF - CALL DISTRIBUTE_STATION(TSTATIONS(I)%XSFCO2 (IN)) - ENDIF - ENDDO - ! -END IF -! -!---------------------------------------------------------------------------- -!---------------------------------------------------------------------------- -! -CONTAINS -! -!---------------------------------------------------------------------------- -!---------------------------------------------------------------------------- -! -FUNCTION STATION_INTERP_2D(PA) RESULT(PB) -! -REAL, DIMENSION(:,:), INTENT(IN) :: PA -REAL :: PB -! -INTEGER :: JI, JJ -! -IF (SIZE(PA,1)==2) THEN - JI=1 - JJ=1 -ELSEIF (L1D) THEN - JI=2 - JJ=2 -ELSE - JI=TSTATIONS(I)%NI_M - JJ=TSTATIONS(I)%NJ_M -END IF -! -! -IF ((JI .GE. 1).AND. (JI .LE. SIZE(PA,1)) .AND. & - (JJ .GE. 1).AND. (JJ .LE. SIZE(PA,2))) & -PB = (1.-TSTATIONS(I)%XYMCOEF) * (1.-TSTATIONS(I)%XXMCOEF) * PA(JI,JJ) + & - (1.-TSTATIONS(I)%XYMCOEF) * (TSTATIONS(I)%XXMCOEF) * PA(JI+1,JJ) + & - ( TSTATIONS(I)%XYMCOEF) * (1.-TSTATIONS(I)%XXMCOEF) * PA(JI,JJ+1) + & - ( TSTATIONS(I)%XYMCOEF) * (TSTATIONS(I)%XXMCOEF) * PA(JI+1,JJ+1) -! -END FUNCTION STATION_INTERP_2D -!---------------------------------------------------------------------------- -!---------------------------------------------------------------------------- -! MODIFS -FUNCTION STATION_INTERP_2D_U(PA) RESULT(PB) -! -REAL, DIMENSION(:,:), INTENT(IN) :: PA -REAL :: PB -! -INTEGER :: JI, JJ -! -IF (SIZE(PA,1)==2) THEN - JI=1 - JJ=1 -ELSEIF (L1D) THEN - JI=2 - JJ=2 -ELSE - JI=TSTATIONS(I)%NI_M - JJ=TSTATIONS(I)%NJ_M -END IF -! -IF ((JI .GE. 1).AND. (JI .LE. SIZE(PA,1)) .AND. & - (JJ .GE. 1).AND. (JJ .LE. SIZE(PA,2))) & -PB = (1.- TSTATIONS(I)%XYMCOEF) * (1.-TSTATIONS(I)%XXUCOEF) * PA(JI ,JJ ) & - + (1.- TSTATIONS(I)%XYMCOEF) * ( TSTATIONS(I)%XXUCOEF) * PA(JI+1,JJ ) & - + ( TSTATIONS(I)%XYMCOEF) * (1.-TSTATIONS(I)%XXUCOEF) * PA(JI ,JJ+1) & - + ( TSTATIONS(I)%XYMCOEF) * ( TSTATIONS(I)%XXUCOEF) * PA(JI+1,JJ+1) -! -END FUNCTION STATION_INTERP_2D_U -!---------------------------------------------------------------------------- -!---------------------------------------------------------------------------- -! MODIFS -FUNCTION STATION_INTERP_2D_V(PA) RESULT(PB) -! -REAL, DIMENSION(:,:), INTENT(IN) :: PA -REAL :: PB -! -INTEGER :: JI, JJ -! -IF (SIZE(PA,1)==2) THEN - JI=1 - JJ=1 -ELSEIF (L1D) THEN - JI=2 - JJ=2 -ELSE - JI=TSTATIONS(I)%NI_M - JJ=TSTATIONS(I)%NJ_M -END IF -! -IF ((JI .GT. 0).AND. (JI .LT. SIZE(PA,1)) .AND. & - (JJ .GT. 0).AND. (JJ .LT. SIZE(PA,2))) & -PB = (1.- TSTATIONS(I)%XYVCOEF) * (1.-TSTATIONS(I)%XXMCOEF) * PA(JI ,JJ ) & - + (1.- TSTATIONS(I)%XYVCOEF) * ( TSTATIONS(I)%XXMCOEF) * PA(JI+1,JJ ) & - + ( TSTATIONS(I)%XYVCOEF) * (1.-TSTATIONS(I)%XXMCOEF) * PA(JI ,JJ+1) & - + ( TSTATIONS(I)%XYVCOEF) * ( TSTATIONS(I)%XXMCOEF) * PA(JI+1,JJ+1) -! -END FUNCTION STATION_INTERP_2D_V -!---------------------------------------------------------------------------- -!---------------------------------------------------------------------------- -SUBROUTINE DISTRIBUTE_STATION(PAS) -! -REAL, INTENT(INOUT) :: PAS -! -INTEGER :: IINFO_ll ! return code + IF (SIZE(PTKE)>0) TSTATIONS(JS)%XTKE(IN) = STATION_INTERP_2D( TSTATIONS(JS), PTKE(:,:,JK) ) + IF ( CRAD /= 'NONE' ) TSTATIONS(JS)%XTSRAD(IN) = STATION_INTERP_2D( TSTATIONS(JS), PTS ) + TSTATIONS(JS)%XZS = STATION_INTERP_2D( TSTATIONS(JS), PZ(:,:,1+JPVEXT)) -IF ( .NOT. TSTATIONS(I)%LPRESENT ) PAS = 0. -CALL REDUCESUM_ll(PAS,IINFO_ll) + IF ( LDIAG_SURFRAD ) THEN + TSTATIONS(JS)%XZON10M(IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_ZON10M ) + TSTATIONS(JS)%XMER10M(IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_MER10M ) + TSTATIONS(JS)%XT2M (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_T2M ) + TSTATIONS(JS)%XQ2M (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_Q2M ) + TSTATIONS(JS)%XHU2M (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_HU2M ) + TSTATIONS(JS)%XRN (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_RN ) + TSTATIONS(JS)%XH (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_H ) + TSTATIONS(JS)%XLE (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_LE ) + TSTATIONS(JS)%XLEI (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_LEI ) + TSTATIONS(JS)%XGFLUX (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_GFLUX ) + IF ( CRAD /= 'NONE' ) THEN + TSTATIONS(JS)%XSWD (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_SWD ) + TSTATIONS(JS)%XSWU (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_SWU ) + TSTATIONS(JS)%XLWD (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_LWD ) + TSTATIONS(JS)%XLWU (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_LWU ) + TSTATIONS(JS)%XSWDIR (IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_SWDIR ) + TSTATIONS(JS)%XSWDIFF(IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_SWDIFF ) + TSTATIONS(JS)%XDSTAOD(IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_DSTAOD ) + END IF + TSTATIONS(JS)%XSFCO2(IN) = STATION_INTERP_2D( TSTATIONS(JS), XCURRENT_SFCO2 ) + END IF +END DO STATION ! -END SUBROUTINE DISTRIBUTE_STATION !---------------------------------------------------------------------------- ! END SUBROUTINE STATION_n diff --git a/src/MNH/write_stationn.f90 b/src/MNH/write_stationn.f90 index 0746c64d2..9f65f84e1 100644 --- a/src/MNH/write_stationn.f90 +++ b/src/MNH/write_stationn.f90 @@ -61,7 +61,7 @@ END MODULE MODI_WRITE_STATION_n ! P. Wautelet 09/10/2020: Write_diachro: use new datatype tpfields ! P. Wautelet 03/03/2021: budgets: add tbudiachrometadata type (useful to pass more information to Write_diachro) ! P. Wautelet 04/02/2022: use TSVLIST to manage metadata of scalar variables -! P. Wautelet 07/04/2022: rewrite types for stations +! P. Wautelet 04/2022: restructure stations for better performance, reduce memory usage and correct some problems/bugs ! -------------------------------------------------------------------------- ! !* 0. DECLARATIONS @@ -70,17 +70,22 @@ END MODULE MODI_WRITE_STATION_n USE MODD_ALLSTATION_n, ONLY: LDIAG_SURFRAD use MODD_BUDGET, ONLY: tbudiachrometadata USE MODD_CONF, ONLY: LCARTESIAN +USE MODD_CONF_n, ONLY: NRR USE MODD_CST, ONLY: XRV -USE MODD_IO, ONLY: TFILEDATA +USE MODD_IO, ONLY: ISNPROC, ISP, TFILEDATA +USE MODD_MPIF USE MODD_NSV, ONLY: tsvlist, nsv, nsv_aer, nsv_aerbeg, nsv_aerend, & nsv_dst, nsv_dstbeg, nsv_dstend, nsv_slt, nsv_sltbeg, nsv_sltend -USE MODD_PARAM_n, ONLY: CRAD, CSURF +USE MODD_PARAM_n, ONLY: CRAD, CSURF, CTURB USE MODD_PARAMETERS, ONLY: XUNDEF -USE MODD_STATION_n, only: NUMBSTAT, TSTATIONS +USE MODD_PRECISION, ONLY: MNHINT_MPI, MNHREAL_MPI +USE MODD_STATION_n, only: NUMBSTAT_LOC, TSTATIONS, tstations_time +USE MODD_TYPE_STATION, ONLY: TSTATIONDATA ! USE MODE_AERO_PSD USE MODE_DUST_PSD USE MODE_SALT_PSD +USE MODE_STATION_TOOLS, ONLY: STATION_ALLOCATE use MODE_WRITE_DIACHRO, ONLY: Write_diachro ! IMPLICIT NONE @@ -94,13 +99,199 @@ TYPE(TFILEDATA), INTENT(IN) :: TPDIAFILE ! diachronic file to write ! ! 0.2 declaration of local variables ! -INTEGER :: II ! loop +INTEGER, PARAMETER :: ITAG = 100 +INTEGER :: IERR +INTEGER :: JP, JS +INTEGER :: IDX +INTEGER :: INUMSTAT ! Total number of stations (for the current model) +INTEGER :: IPACKSIZE ! Size of the ZPACK buffer +INTEGER :: IPOS ! Position in the ZPACK buffer +INTEGER :: ISTORE +INTEGER, DIMENSION(:), ALLOCATABLE :: INSTATPRC ! Array to store the number of stations per process (for the current model) +INTEGER, DIMENSION(:), ALLOCATABLE :: ISTATIDS ! Intermediate array for MPI communication +INTEGER, DIMENSION(:), ALLOCATABLE :: ISTATPRCRANK ! Array to store the ranks of the processes where the stations are +INTEGER, DIMENSION(:), ALLOCATABLE :: IDS ! Array to store the station number to send +INTEGER, DIMENSION(:), ALLOCATABLE :: IDISP ! Array to store the displacements for MPI communications +REAL, DIMENSION(:), ALLOCATABLE :: ZPACK ! Buffer to store raw data of a station (used for MPI communication) +TYPE(TSTATIONDATA) :: TZSTATION ! !---------------------------------------------------------------------------- -! -DO II = 1, NUMBSTAT - CALL STATION_DIACHRO_n( TSTATIONS(II) ) -ENDDO + +ALLOCATE( INSTATPRC(ISNPROC) ) +ALLOCATE( IDS(NUMBSTAT_LOC) ) + +!Gather number of station present on each process +CALL MPI_ALLGATHER( NUMBSTAT_LOC, 1, MNHINT_MPI, INSTATPRC, 1, MNHINT_MPI, TPDIAFILE%NMPICOMM, IERR ) + +!Store the identification number of local stations (these numbers are globals) +DO JS = 1, NUMBSTAT_LOC + IDS(JS) = TSTATIONS(JS)%NID +END DO + +ALLOCATE( IDISP(ISNPROC) ) +IDISP(1) = 0 +DO JP = 2, ISNPROC + IDISP(JP) = IDISP(JP-1) + INSTATPRC(JP-1) +END DO + +INUMSTAT = SUM( INSTATPRC(:) ) +ALLOCATE( ISTATIDS(INUMSTAT) ) +ALLOCATE( ISTATPRCRANK(INUMSTAT) ) + +!Gather the list of all the stations of all processes +CALL MPI_ALLGATHERV( IDS(:), NUMBSTAT_LOC, MNHINT_MPI, ISTATIDS(:), INSTATPRC(:), & + IDISP(:), MNHINT_MPI, TPDIAFILE%NMPICOMM, IERR ) + +!Store the rank of each process corresponding to a given station +IDX = 1 +ISTATPRCRANK(:) = -1 +DO JP = 1, ISNPROC + DO JS = 1, INSTATPRC(JP) + ISTATPRCRANK(ISTATIDS(IDX)) = JP + IDX = IDX + 1 + END DO +END DO + +CALL STATION_ALLOCATE( TZSTATION, SIZE( tstations_time%tpdates ) ) + +!Determine the size of the ZPACK buffer used to transfer station data in 1 MPI communication +IF ( ISNPROC > 1 ) THEN + ISTORE = SIZE( TSTATIONS_TIME%TPDATES ) + IPACKSIZE = 7 + IPACKSIZE = IPACKSIZE + ISTORE * ( 5 + NRR + NSV ) + IF ( CTURB == 'TKEL') IPACKSIZE = IPACKSIZE + ISTORE !Tke term + IF ( CRAD /= 'NONE' ) IPACKSIZE = IPACKSIZE + ISTORE !XTSRAD term + IF (LDIAG_SURFRAD) THEN + IF ( CSURF == 'EXTE' ) IPACKSIZE = IPACKSIZE + ISTORE * 10 + IF ( CRAD /= 'NONE' ) IPACKSIZE = IPACKSIZE + ISTORE * 7 + IPACKSIZE = IPACKSIZE + ISTORE !XSFCO2 term + END IF + + ALLOCATE( ZPACK(IPACKSIZE) ) +END IF + +IDX = 1 + +STATION: DO JS = 1, INUMSTAT + IF ( ISTATPRCRANK(JS) == TPDIAFILE%NMASTER_RANK ) THEN + !No communication necessary, the station data is already on the writer process + IF ( ISP == TPDIAFILE%NMASTER_RANK ) THEN + TZSTATION = TSTATIONS(IDX) + IDX = IDX + 1 + END IF + ELSE + !The station data is not on the writer process + IF ( ISP == ISTATPRCRANK(JS) ) THEN + ! This process has the data and needs to send it to the writer process + IPOS = 1 + ZPACK(IPOS) = TSTATIONS(IDX)%NID; IPOS = IPOS + 1 + ZPACK(IPOS) = TSTATIONS(IDX)%XX; IPOS = IPOS + 1 + ZPACK(IPOS) = TSTATIONS(IDX)%XY; IPOS = IPOS + 1 + ZPACK(IPOS) = TSTATIONS(IDX)%XZ; IPOS = IPOS + 1 + ZPACK(IPOS) = TSTATIONS(IDX)%XLON; IPOS = IPOS + 1 + ZPACK(IPOS) = TSTATIONS(IDX)%XLAT; IPOS = IPOS + 1 + ZPACK(IPOS) = TSTATIONS(IDX)%XZS; IPOS = IPOS + 1 + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XZON(:); IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XMER(:); IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XW(:); IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XP(:); IPOS = IPOS + ISTORE + IF ( CTURB == 'TKEL') THEN + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XTKE(:); IPOS = IPOS + ISTORE + END IF + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XTH(:); IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE*NRR-1) = RESHAPE( TSTATIONS(IDX)%XR(:,:), [ISTORE*NRR] ); IPOS = IPOS + ISTORE * NRR + ZPACK(IPOS:IPOS+ISTORE*NSV-1) = RESHAPE( TSTATIONS(IDX)%XSV(:,:), [ISTORE*NSV] ); IPOS = IPOS + ISTORE * NSV + IF ( CRAD /= 'NONE' ) THEN + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XTSRAD(:); IPOS = IPOS + ISTORE + END IF + IF (LDIAG_SURFRAD) THEN + IF ( CSURF == 'EXTE') THEN + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XT2M; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XQ2M; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XHU2M; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XZON10M; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XMER10M; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XRN; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XH; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XLE; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XGFLUX; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XLEI; IPOS = IPOS + ISTORE + END IF + IF ( CRAD /= 'NONE' ) THEN + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XSWD; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XSWU; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XLWD; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XLWU; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XSWDIR; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XSWDIFF; IPOS = IPOS + ISTORE + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XDSTAOD; IPOS = IPOS + ISTORE + END IF + ZPACK(IPOS:IPOS+ISTORE-1) = TSTATIONS(IDX)%XSFCO2; IPOS = IPOS + ISTORE + END IF + + CALL MPI_SEND( TSTATIONS(IDX)%CNAME, LEN(TSTATIONS(IDX)%CNAME), MPI_CHARACTER, TPDIAFILE%NMASTER_RANK - 1, & + ITAG, TPDIAFILE%NMPICOMM, IERR ) + CALL MPI_SEND( ZPACK, IPACKSIZE, MNHREAL_MPI, TPDIAFILE%NMASTER_RANK - 1, ITAG, TPDIAFILE%NMPICOMM, IERR ) + + IDX = IDX + 1 + + ELSE IF ( ISP == TPDIAFILE%NMASTER_RANK ) THEN + ! This process is the writer and will receive the station data from its owner + CALL MPI_RECV( TZSTATION%CNAME, LEN(TZSTATION%CNAME), MPI_CHARACTER, & + ISTATPRCRANK(JS) - 1, ITAG, TPDIAFILE%NMPICOMM, MPI_STATUS_IGNORE, IERR ) + CALL MPI_RECV( ZPACK, IPACKSIZE, MNHREAL_MPI, ISTATPRCRANK(JS) - 1, ITAG, TPDIAFILE%NMPICOMM, MPI_STATUS_IGNORE, IERR ) + + IPOS = 1 + TZSTATION%NID = NINT( ZPACK(IPOS) ); IPOS = IPOS + 1 + TZSTATION%XX = ZPACK(IPOS); IPOS = IPOS + 1 + TZSTATION%XY = ZPACK(IPOS); IPOS = IPOS + 1 + TZSTATION%XZ = ZPACK(IPOS); IPOS = IPOS + 1 + TZSTATION%XLON = ZPACK(IPOS); IPOS = IPOS + 1 + TZSTATION%XLAT = ZPACK(IPOS); IPOS = IPOS + 1 + TZSTATION%XZS = ZPACK(IPOS); IPOS = IPOS + 1 + TZSTATION%XZON(:) = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XMER(:) = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XW(:) = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XP(:) = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + IF ( CTURB == 'TKEL') THEN + TZSTATION%XTKE(:) = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + END IF + TZSTATION%XTH(:) = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XR(:,:) = RESHAPE( ZPACK(IPOS:IPOS+ISTORE*NRR-1), [ ISTORE, NRR ] ); IPOS = IPOS + ISTORE * NRR + TZSTATION%XSV(:,:) = RESHAPE( ZPACK(IPOS:IPOS+ISTORE*NSV-1), [ ISTORE, NSV ] ); IPOS = IPOS + ISTORE * NSV + IF ( CRAD /= 'NONE' ) THEN + TZSTATION%XTSRAD(:) = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + END IF + IF (LDIAG_SURFRAD) THEN + IF ( CSURF == 'EXTE' ) THEN + TZSTATION%XT2M = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XQ2M = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XHU2M = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XZON10M = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XMER10M = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XRN = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XH = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XLE = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XGFLUX = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XLEI = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + END IF + IF ( CRAD /= 'NONE' ) THEN + TZSTATION%XSWD = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XSWU = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XLWD = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XLWU = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XSWDIR = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XSWDIFF = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + TZSTATION%XDSTAOD = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + END IF + TZSTATION%XSFCO2 = ZPACK(IPOS:IPOS+ISTORE-1); IPOS = IPOS + ISTORE + END IF + END IF + END IF + + CALL STATION_DIACHRO_n( TZSTATION ) + +END DO STATION ! !---------------------------------------------------------------------------- !---------------------------------------------------------------------------- @@ -145,13 +336,10 @@ type(tbudiachrometadata) :: tzbudiachro type(tfieldmetadata_base), dimension(:), allocatable :: tzfields ! !---------------------------------------------------------------------------- -IF (TPSTATION%XX==XUNDEF) RETURN -IF (TPSTATION%XY==XUNDEF) RETURN ! IPROC = 8 + SIZE(TPSTATION%XR,2) + SIZE(TPSTATION%XSV,2) -IF (TPSTATION%XX==XUNDEF) IPROC = IPROC + 2 -IF (SIZE(TPSTATION%XTKE )>0) IPROC = IPROC + 1 +IF ( CTURB == 'TKEL' ) IPROC = IPROC + 1 IF (LDIAG_SURFRAD) THEN IF(CSURF=="EXTE") IPROC = IPROC + 10 IF(CRAD/="NONE") IPROC = IPROC + 7 @@ -159,8 +347,8 @@ END IF IF (LORILAM) IPROC = IPROC + JPMODE*(3+NSOA+NCARB+NSP) IF (LDUST) IPROC = IPROC + NMODE_DST*3 IF (LSALT) IPROC = IPROC + NMODE_SLT*3 -IF (ANY(TPSTATION%XTSRAD(:)/=XUNDEF)) IPROC = IPROC + 1 -IF (ANY(TPSTATION%XSFCO2(:)/=XUNDEF)) IPROC = IPROC + 1 +IF ( CRAD /= 'NONE' ) IPROC = IPROC + 1 +IPROC = IPROC + 1 ! XSFCO2 term ! ALLOCATE (ZWORK6(1,1,1,SIZE(tstations_time%tpdates),1,IPROC)) ALLOCATE (YCOMMENT(IPROC)) @@ -390,7 +578,7 @@ DO JRR=1,SIZE(TPSTATION%XR,2) END IF END DO ! -IF (SIZE(TPSTATION%XTKE,1)>0) THEN +IF ( CTURB == 'TKEL' ) THEN JPROC = JPROC+1 YTITLE (JPROC) = 'Tke' YUNIT (JPROC) = 'm2 s-2' @@ -642,7 +830,7 @@ IF (SIZE(TPSTATION%XSV,2)>=1) THEN END IF END IF -IF (ANY(TPSTATION%XTSRAD(:)/=XUNDEF)) THEN +IF ( CRAD /= 'NONE' ) THEN JPROC = JPROC+1 YTITLE (JPROC) = 'Tsrad' YUNIT (JPROC) = 'K' @@ -650,13 +838,13 @@ IF (ANY(TPSTATION%XTSRAD(:)/=XUNDEF)) THEN ZWORK6 (1,1,1,:,1,JPROC) = TPSTATION%XTSRAD(:) END IF ! -IF (ANY(TPSTATION%XSFCO2(:)/=XUNDEF)) THEN +! IF (ANY(TPSTATION%XSFCO2(:)/=XUNDEF)) THEN JPROC = JPROC+1 YTITLE (JPROC) = 'SFCO2' YUNIT (JPROC) = 'mg m-2 s-1' YCOMMENT (JPROC) = 'CO2 Surface Flux' ZWORK6 (1,1,1,:,1,JPROC) = TPSTATION%XSFCO2(:) -END IF +! END IF ! !---------------------------------------------------------------------------- ! @@ -739,7 +927,5 @@ DEALLOCATE (YUNIT ) DEALLOCATE (IGRID ) !---------------------------------------------------------------------------- END SUBROUTINE STATION_DIACHRO_n -!---------------------------------------------------------------------------- -!---------------------------------------------------------------------------- ! END SUBROUTINE WRITE_STATION_n -- GitLab