Newer
Older

WAUTELET Philippe
committed
!MNH_LIC Copyright 2002-2023 CNRS, Meteo-France and Universite Paul Sabatier

WAUTELET Philippe
committed
!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.
!-----------------------------------------------------------------

WAUTELET Philippe
committed
! Authors:
! Misc: some of the code was taken from older subroutines/functions for stations

WAUTELET Philippe
committed
! P. Wautelet 08/04/2022
!-----------------------------------------------------------------
! Modifications:

WAUTELET Philippe
committed
! P. Wautelet 30/09/2022: bugfix: use XUNDEF from SURFEX for surface variables computed by SURFEX

WAUTELET Philippe
committed
! P. Wautelet 25/11/2022: rewrite STATPROF_INSTANT algorithm (does not depends on model timestep anymore => independent of model)

WAUTELET Philippe
committed
!-----------------------------------------------------------------
! ###################
MODULE MODE_STATPROF_TOOLS
! ###################

WAUTELET Philippe
committed

WAUTELET Philippe
committed
USE MODD_TYPE_STATPROF, ONLY: TPROFILERDATA, TSTATIONDATA, TSTATPROFDATA, TSTATPROFTIME

WAUTELET Philippe
committed

WAUTELET Philippe
committed
IMPLICIT NONE
PRIVATE

WAUTELET Philippe
committed
PUBLIC :: PROFILER_ALLOCATE, STATION_ALLOCATE
PUBLIC :: STATPROF_INI_INTERP
PUBLIC :: STATPROF_POSITION
PUBLIC :: PROFILER_ADD, STATION_ADD
PUBLIC :: STATPROF_INTERP_2D, STATPROF_INTERP_2D_U, STATPROF_INTERP_2D_V
PUBLIC :: STATPROF_INTERP_3D, STATPROF_INTERP_3D_U, STATPROF_INTERP_3D_V

WAUTELET Philippe
committed
PUBLIC :: STATPROF_INSTANT

WAUTELET Philippe
committed
CONTAINS

WAUTELET Philippe
committed
! ################################################
SUBROUTINE PROFILER_ALLOCATE( TPPROFILER, KSTORE )
! ################################################
! USE MODD_ALLSTATION_n, ONLY: LDIAG_SURFRAD
USE MODD_CONF_n, ONLY: NRR
USE MODD_DIAG_IN_RUN, ONLY: LDIAG_IN_RUN
USE MODD_DIM_n, ONLY: NKMAX
USE MODD_NSV, ONLY: NSV
USE MODD_PARAMETERS, ONLY: JPVEXT, XUNDEF
USE MODD_PARAM_n, ONLY: CCLOUD, CRAD, CTURB
USE MODD_RADIATIONS_n, ONLY: NAER

WAUTELET Philippe
committed
USE MODD_SURF_PAR, ONLY: XUNDEF_SFX => XUNDEF

WAUTELET Philippe
committed
IMPLICIT NONE
TYPE(TPROFILERDATA), INTENT(INOUT) :: TPPROFILER
INTEGER, INTENT(IN) :: KSTORE ! number of moments to store
INTEGER :: IKU
IKU = NKMAX + 2 * JPVEXT
ALLOCATE( TPPROFILER%XZON (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XMER (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XFF (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XDD (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XW (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XP (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XZZ (KSTORE, IKU) )
IF ( CTURB == 'TKEL' ) THEN
ALLOCATE( TPPROFILER%XTKE (KSTORE, IKU) )
ELSE
ALLOCATE( TPPROFILER%XTKE (0, 0) )
END IF
ALLOCATE( TPPROFILER%XTH (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XTHV (KSTORE, IKU) )

WAUTELET Philippe
committed
IF ( CCLOUD == 'C2R2' .OR. CCLOUD == 'KHKO' ) THEN
ALLOCATE( TPPROFILER%XVISIGUL (KSTORE, IKU) )
ELSE
ALLOCATE( TPPROFILER%XVISIGUL (0, 0) )
END IF
IF ( CCLOUD /= 'NONE' .AND. CCLOUD /= 'REVE' ) THEN
ALLOCATE( TPPROFILER%XVISIKUN (KSTORE, IKU) )
ELSE
ALLOCATE( TPPROFILER%XVISIKUN (0, 0) )
END IF

WAUTELET Philippe
committed
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
ALLOCATE( TPPROFILER%XCRARE (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XCRARE_ATT(KSTORE, IKU) )
IF ( CCLOUD == 'ICE3' .OR. CCLOUD == 'ICE4' ) THEN
ALLOCATE( TPPROFILER%XCIZ (KSTORE, IKU) )
ELSE
ALLOCATE( TPPROFILER%XCIZ (0, 0) )
END IF
ALLOCATE( TPPROFILER%XLWCZ (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XIWCZ (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XRHOD (KSTORE, IKU) )
ALLOCATE( TPPROFILER%XR (KSTORE, IKU, NRR) )
ALLOCATE( TPPROFILER%XSV (KSTORE, IKU, NSV) )
ALLOCATE( TPPROFILER%XAER (KSTORE, IKU, NAER) )
ALLOCATE( TPPROFILER%XIWV(KSTORE) )
ALLOCATE( TPPROFILER%XZTD(KSTORE) )
ALLOCATE( TPPROFILER%XZWD(KSTORE) )
ALLOCATE( TPPROFILER%XZHD(KSTORE) )
! IF ( LDIAG_IN_RUN ) THEN
ALLOCATE( TPPROFILER%XT2M (KSTORE) )
ALLOCATE( TPPROFILER%XQ2M (KSTORE) )
ALLOCATE( TPPROFILER%XHU2M (KSTORE) )
ALLOCATE( TPPROFILER%XZON10M(KSTORE) )
ALLOCATE( TPPROFILER%XMER10M(KSTORE) )
ALLOCATE( TPPROFILER%XRN (KSTORE) )
ALLOCATE( TPPROFILER%XH (KSTORE) )
ALLOCATE( TPPROFILER%XLE (KSTORE) )
ALLOCATE( TPPROFILER%XLEI (KSTORE) )
ALLOCATE( TPPROFILER%XGFLUX (KSTORE) )
IF ( CRAD /= 'NONE' ) THEN
ALLOCATE( TPPROFILER%XSWD (KSTORE) )
ALLOCATE( TPPROFILER%XSWU (KSTORE) )
ALLOCATE( TPPROFILER%XLWD (KSTORE) )
ALLOCATE( TPPROFILER%XLWU (KSTORE) )
END IF
ALLOCATE( TPPROFILER%XTKE_DISS(KSTORE, IKU) )
! END IF
TPPROFILER%XZON (:,:) = XUNDEF
TPPROFILER%XMER (:,:) = XUNDEF
TPPROFILER%XFF (:,:) = XUNDEF
TPPROFILER%XDD (:,:) = XUNDEF
TPPROFILER%XW (:,:) = XUNDEF
TPPROFILER%XP (:,:) = XUNDEF
TPPROFILER%XZZ (:,:) = XUNDEF
IF ( CTURB == 'TKEL' ) TPPROFILER%XTKE(:,:) = XUNDEF
TPPROFILER%XTH (:,:) = XUNDEF
TPPROFILER%XTHV (:,:) = XUNDEF

WAUTELET Philippe
committed
IF ( CCLOUD == 'C2R2' .OR. CCLOUD == 'KHKO' ) TPPROFILER%XVISIGUL(:,:) = XUNDEF
IF ( CCLOUD /= 'NONE' .AND. CCLOUD /= 'REVE' ) TPPROFILER%XVISIKUN(:,:) = XUNDEF

WAUTELET Philippe
committed
TPPROFILER%XCRARE (:,:) = XUNDEF
TPPROFILER%XCRARE_ATT(:,:) = XUNDEF
IF ( CCLOUD == 'ICE3' .OR. CCLOUD == 'ICE4' ) TPPROFILER%XCIZ (:,:) = XUNDEF
TPPROFILER%XLWCZ (:,:) = XUNDEF
TPPROFILER%XIWCZ (:,:) = XUNDEF
TPPROFILER%XRHOD (:,:) = XUNDEF
TPPROFILER%XR (:,:,:) = XUNDEF
TPPROFILER%XSV (:,:,:) = XUNDEF
TPPROFILER%XAER (:,:,:) = XUNDEF
TPPROFILER%XIWV(:) = XUNDEF
TPPROFILER%XZTD(:) = XUNDEF
TPPROFILER%XZWD(:) = XUNDEF
TPPROFILER%XZHD(:) = XUNDEF
! IF ( LDIAG_IN_RUN ) THEN

WAUTELET Philippe
committed
TPPROFILER%XT2M (:) = XUNDEF_SFX
TPPROFILER%XQ2M (:) = XUNDEF_SFX
TPPROFILER%XHU2M (:) = XUNDEF_SFX
TPPROFILER%XZON10M(:) = XUNDEF_SFX
TPPROFILER%XMER10M(:) = XUNDEF_SFX
TPPROFILER%XRN (:) = XUNDEF_SFX
TPPROFILER%XH (:) = XUNDEF_SFX
TPPROFILER%XLE (:) = XUNDEF_SFX
TPPROFILER%XLEI (:) = XUNDEF_SFX
TPPROFILER%XGFLUX (:) = XUNDEF_SFX

WAUTELET Philippe
committed
IF ( CRAD /= 'NONE' ) THEN
TPPROFILER%XSWD (:) = XUNDEF
TPPROFILER%XSWU (:) = XUNDEF
TPPROFILER%XLWD (:) = XUNDEF
TPPROFILER%XLWU (:) = XUNDEF
END IF
TPPROFILER%XTKE_DISS(:,:) = XUNDEF
! END IF
END SUBROUTINE PROFILER_ALLOCATE

WAUTELET Philippe
committed
! ##############################################
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

WAUTELET Philippe
committed
USE MODD_SURF_PAR, ONLY: XUNDEF_SFX => XUNDEF

WAUTELET Philippe
committed
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
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

WAUTELET Philippe
committed
TPSTATION%XT2M(:) = XUNDEF_SFX
TPSTATION%XQ2M(:) = XUNDEF_SFX
TPSTATION%XHU2M(:) = XUNDEF_SFX
TPSTATION%XZON10M(:) = XUNDEF_SFX
TPSTATION%XMER10M(:) = XUNDEF_SFX
TPSTATION%XRN(:) = XUNDEF_SFX
TPSTATION%XH(:) = XUNDEF_SFX
TPSTATION%XLE(:) = XUNDEF_SFX
TPSTATION%XLEI(:) = XUNDEF_SFX
TPSTATION%XGFLUX(:) = XUNDEF_SFX

WAUTELET Philippe
committed
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

WAUTELET Philippe
committed
TPSTATION%XSFCO2(:) = XUNDEF_SFX

WAUTELET Philippe
committed
END IF
END SUBROUTINE STATION_ALLOCATE

WAUTELET Philippe
committed
! ##########################################
SUBROUTINE STATPROF_INI_INTERP( TPSTATPROF )
! ##########################################

WAUTELET Philippe
committed
USE MODD_GRID, ONLY: XLATORI, XLONORI
USE MODD_PARAMETERS, ONLY: XUNDEF
USE MODE_GRIDPROJ, ONLY: SM_XYHAT
USE MODE_MSG
IMPLICIT NONE

WAUTELET Philippe
committed
CLASS(TSTATPROFDATA), INTENT(INOUT) :: TPSTATPROF

WAUTELET Philippe
committed

WAUTELET Philippe
committed
IF ( TPSTATPROF%XLAT == XUNDEF .OR. TPSTATPROF%XLON == XUNDEF ) THEN
CMNHMSG(1) = 'Error in station or profiler position'

WAUTELET Philippe
committed
CMNHMSG(2) = 'either LATitude or LONgitude segment'
CMNHMSG(3) = 'or I and J segment'
CMNHMSG(4) = 'definition is not complete.'

WAUTELET Philippe
committed
CALL PRINT_MSG( NVERB_FATAL, 'GEN', 'STATPROF_INI_INTERP' )

WAUTELET Philippe
committed
END IF

WAUTELET Philippe
committed
CALL SM_XYHAT( XLATORI, XLONORI, &
TPSTATPROF%XLAT, TPSTATPROF%XLON, &
TPSTATPROF%XX, TPSTATPROF%XY )

WAUTELET Philippe
committed

WAUTELET Philippe
committed
END SUBROUTINE STATPROF_INI_INTERP

WAUTELET Philippe
committed
! ###########################################################
SUBROUTINE STATPROF_POSITION( TPSTATPROF, OINSIDE, OPRESENT )
! ###########################################################

WAUTELET Philippe
committed
! Subroutine to determine the position of a station/profiler on the model grid

WAUTELET Philippe
committed
! and set the useful coefficients for data interpolation

WAUTELET Philippe
committed

WAUTELET Philippe
committed
USE MODD_CONF, ONLY: L1D
USE MODD_GRID_n, ONLY: NPHYS_XMIN, NPHYS_XMAX, NPHYS_YMIN, NPHYS_YMAX, XHAT_BOUND, XHATM_BOUND, &
XXHAT, XYHAT, XXHATM, XYHATM, XZZ

WAUTELET Philippe
committed
USE MODD_PARAMETERS, ONLY: JPHEXT, JPVEXT

WAUTELET Philippe
committed

WAUTELET Philippe
committed
USE MODE_MSG
USE MODE_NEST_LL, ONLY: GET_MODEL_NUMBER_ll
USE MODE_TOOLS_ll, ONLY: GET_INDICE_ll

WAUTELET Philippe
committed
IMPLICIT NONE

WAUTELET Philippe
committed
CLASS(TSTATPROFDATA), INTENT(INOUT) :: TPSTATPROF
LOGICAL, INTENT(OUT) :: OINSIDE ! True if station/profiler is inside physical domain of model
LOGICAL, INTENT(OUT) :: OPRESENT ! True if station/profiler is present on the current process

WAUTELET Philippe
committed
INTEGER :: IIB ! domain sizes of current process
INTEGER :: IJB !
INTEGER :: IIE !
INTEGER :: IJE !

WAUTELET Philippe
committed
INTEGER :: IMI
INTEGER :: JK
REAL :: ZLOW, ZHIGH

WAUTELET Philippe
committed

WAUTELET Philippe
committed
OPRESENT = .FALSE.
OINSIDE = .FALSE.

WAUTELET Philippe
committed

WAUTELET Philippe
committed
CALL GET_INDICE_ll( IIB, IJB, IIE, IJE )

WAUTELET Philippe
committed
IF ( TPSTATPROF%XX >= XHAT_BOUND(NPHYS_XMIN) .AND. TPSTATPROF%XX <= XHAT_BOUND(NPHYS_XMAX) &
.AND. TPSTATPROF%XY >= XHAT_BOUND(NPHYS_YMIN) .AND. TPSTATPROF%XY <= XHAT_BOUND(NPHYS_YMAX) ) THEN

WAUTELET Philippe
committed
OINSIDE = .TRUE.
ELSE
CALL GET_MODEL_NUMBER_ll(IMI)

WAUTELET Philippe
committed
WRITE( CMNHMSG(1), "( 'station or profiler ', A, ' is outside of physical domain of model', I3 )" ) TRIM(TPSTATPROF%CNAME), IMI
CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'STATPROF_POSITION' )

WAUTELET Philippe
committed
END IF

WAUTELET Philippe
committed
! X position

WAUTELET Philippe
committed
TPSTATPROF%NI_U = COUNT( XXHAT (:) <= TPSTATPROF%XX )
TPSTATPROF%NI_M = COUNT( XXHATM(:) <= TPSTATPROF%XX )

WAUTELET Philippe
committed
! Y position

WAUTELET Philippe
committed
TPSTATPROF%NJ_V = COUNT( XYHAT (:) <= TPSTATPROF%XY )
TPSTATPROF%NJ_M = COUNT( XYHATM(:) <= TPSTATPROF%XY )

WAUTELET Philippe
committed

WAUTELET Philippe
committed
! Position of station/profiler according to process
IF ( TPSTATPROF%NI_U >= IIB .AND. TPSTATPROF%NI_U <= IIE &
.AND. TPSTATPROF%NJ_V >= IJB .AND. TPSTATPROF%NJ_V <= IJE ) OPRESENT = .TRUE.

WAUTELET Philippe
committed
IF ( L1D ) OPRESENT = .TRUE.

WAUTELET Philippe
committed
! Check if station/profiler is too near of physical domain border (outside of physical domain for mass points)

WAUTELET Philippe
committed
IF ( OINSIDE .AND. .NOT. L1D ) THEN
IF ( TPSTATPROF%XX < XHATM_BOUND(NPHYS_XMIN) .OR. TPSTATPROF%XX > XHATM_BOUND(NPHYS_XMAX) &
.OR. TPSTATPROF%XY < XHATM_BOUND(NPHYS_YMIN) .OR. TPSTATPROF%XY > XHATM_BOUND(NPHYS_YMAX) ) THEN

WAUTELET Philippe
committed
CALL GET_MODEL_NUMBER_ll(IMI)

WAUTELET Philippe
committed
WRITE( CMNHMSG(1), "( 'station or profiler ', A, ' is outside of mass-points physical domain of model', I3 )" ) &
TRIM(TPSTATPROF%CNAME), IMI

WAUTELET Philippe
committed
CMNHMSG(2) = 'but is inside of flux-points physical domain.'

WAUTELET Philippe
committed
CMNHMSG(3) = 'Meaning: station or profiler is too close to the boundaries of physical domain.'
CMNHMSG(4) = '=> station or profiler disabled (not computed)'
CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'STATPROF_POSITION' )

WAUTELET Philippe
committed
OPRESENT = .FALSE.
OINSIDE = .FALSE.
END IF
END IF

WAUTELET Philippe
committed
! Computations only on correct process

WAUTELET Philippe
committed
IF ( OPRESENT .AND. .NOT. L1D ) THEN

WAUTELET Philippe
committed
! Interpolation coefficient for X (mass-point)
TPSTATPROF%XXMCOEF = ( TPSTATPROF%XX - XXHATM(TPSTATPROF%NI_M) ) / ( XXHATM(TPSTATPROF%NI_M+1) - XXHATM(TPSTATPROF%NI_M) )

WAUTELET Philippe
committed
! Interpolation coefficient for Y (mass-point)
TPSTATPROF%XYMCOEF = ( TPSTATPROF%XY - XYHATM(TPSTATPROF%NJ_M) ) / ( XYHATM(TPSTATPROF%NJ_M+1) - XYHATM(TPSTATPROF%NJ_M) )

WAUTELET Philippe
committed
! Interpolation coefficient for X (U-point)

WAUTELET Philippe
committed
TPSTATPROF%XXUCOEF = ( TPSTATPROF%XX - XXHAT(TPSTATPROF%NI_U) ) / ( XXHAT(TPSTATPROF%NI_U+1) - XXHAT(TPSTATPROF%NI_U) )

WAUTELET Philippe
committed
! Interpolation coefficient for Y (V-point)

WAUTELET Philippe
committed
TPSTATPROF%XYVCOEF = ( TPSTATPROF%XY - XYHAT(TPSTATPROF%NJ_V) ) / ( XYHAT(TPSTATPROF%NJ_V+1) - XYHAT(TPSTATPROF%NJ_V) )

WAUTELET Philippe
committed
END IF

WAUTELET Philippe
committed
IF ( OPRESENT ) THEN

WAUTELET Philippe
committed
SELECT TYPE( TPSTATPROF )
TYPE IS( TPROFILERDATA )
! Nothing to do
TYPE IS( TSTATIONDATA )
! The closest K-level to the station altitude is chosen
JK = JPVEXT + 1
DO WHILE ( ( STATPROF_INTERP_2D( TPSTATPROF, XZZ(:,:,JK) ) - STATPROF_INTERP_2D( TPSTATPROF, XZZ(:,:,JPVEXT+1) ) ) &
< TPSTATPROF%XZ)
JK = JK + 1
END DO
ZLOW = STATPROF_INTERP_2D( TPSTATPROF, XZZ(:,:,JK-1) ) - STATPROF_INTERP_2D( TPSTATPROF, XZZ(:,:,JPVEXT+1) )
ZHIGH = STATPROF_INTERP_2D( TPSTATPROF, XZZ(:,:,JK ) ) - STATPROF_INTERP_2D( TPSTATPROF, XZZ(:,:,JPVEXT+1) )
!If the station/profiler is nearer from the lower level, select it
IF ( ( ZHIGH - TPSTATPROF%XZ ) > ( TPSTATPROF%XZ - ZLOW ) ) JK = JK - 1
TPSTATPROF%NK = JK
CLASS DEFAULT

WAUTELET Philippe
committed
CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATPROF_POSITION', 'unknown type for TPSTATPROF', OLOCAL = .TRUE. )

WAUTELET Philippe
committed
END SELECT

WAUTELET Philippe
committed
END IF

WAUTELET Philippe
committed
END SUBROUTINE STATPROF_POSITION
! ###################################
SUBROUTINE PROFILER_ADD( TPPROFILER )
! ###################################
! Subroutine to add a station to the local list of profilers
USE MODD_PROFILER_n, ONLY: NUMBPROFILER_LOC, TPROFILERS
IMPLICIT NONE

WAUTELET Philippe
committed
CLASS(TPROFILERDATA), INTENT(IN) :: TPPROFILER

WAUTELET Philippe
committed
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
INTEGER :: JS
TYPE(TPROFILERDATA), DIMENSION(:), POINTER :: TZPROFILERS
NUMBPROFILER_LOC = NUMBPROFILER_LOC + 1
ALLOCATE( TZPROFILERS( NUMBPROFILER_LOC ) )
DO JS = 1, NUMBPROFILER_LOC - 1
TZPROFILERS(JS) = TPROFILERS(JS)
END DO
!Copy fields available in TSTATPROFDATA
!other fields are not yet set
TZPROFILERS(NUMBPROFILER_LOC)%CNAME = TPPROFILER%CNAME
TZPROFILERS(NUMBPROFILER_LOC)%NID = TPPROFILER%NID
TZPROFILERS(NUMBPROFILER_LOC)%XX = TPPROFILER%XX
TZPROFILERS(NUMBPROFILER_LOC)%XY = TPPROFILER%XY
TZPROFILERS(NUMBPROFILER_LOC)%XZ = TPPROFILER%XZ
TZPROFILERS(NUMBPROFILER_LOC)%XLON = TPPROFILER%XLON
TZPROFILERS(NUMBPROFILER_LOC)%XLAT = TPPROFILER%XLAT
TZPROFILERS(NUMBPROFILER_LOC)%NI_M = TPPROFILER%NI_M
TZPROFILERS(NUMBPROFILER_LOC)%NJ_M = TPPROFILER%NJ_M
TZPROFILERS(NUMBPROFILER_LOC)%NI_U = TPPROFILER%NI_U
TZPROFILERS(NUMBPROFILER_LOC)%NJ_V = TPPROFILER%NJ_V
TZPROFILERS(NUMBPROFILER_LOC)%XXMCOEF = TPPROFILER%XXMCOEF
TZPROFILERS(NUMBPROFILER_LOC)%XYMCOEF = TPPROFILER%XYMCOEF
TZPROFILERS(NUMBPROFILER_LOC)%XXUCOEF = TPPROFILER%XXUCOEF
TZPROFILERS(NUMBPROFILER_LOC)%XYVCOEF = TPPROFILER%XYVCOEF

WAUTELET Philippe
committed
TZPROFILERS(NUMBPROFILER_LOC)%CTYPE = TPPROFILER%CTYPE

WAUTELET Philippe
committed
IF ( ASSOCIATED( TPROFILERS ) ) DEALLOCATE( TPROFILERS ) !Can be done without memory leak because allocatable arrays were
!not yet allocated (will be done in PROFILER_ALLOCATE)
TPROFILERS => TZPROFILERS
END SUBROUTINE PROFILER_ADD

WAUTELET Philippe
committed

WAUTELET Philippe
committed
! #################################
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

WAUTELET Philippe
committed
CLASS(TSTATIONDATA), INTENT(IN) :: TPSTATION

WAUTELET Philippe
committed
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

WAUTELET Philippe
committed
!Copy fields available in TSTATPROFDATA
!other fields are not yet set
TZSTATIONS(NUMBSTAT_LOC)%CNAME = TPSTATION%CNAME
TZSTATIONS(NUMBSTAT_LOC)%NID = TPSTATION%NID
TZSTATIONS(NUMBSTAT_LOC)%XX = TPSTATION%XX
TZSTATIONS(NUMBSTAT_LOC)%XY = TPSTATION%XY
TZSTATIONS(NUMBSTAT_LOC)%XZ = TPSTATION%XZ
TZSTATIONS(NUMBSTAT_LOC)%XLON = TPSTATION%XLON
TZSTATIONS(NUMBSTAT_LOC)%XLAT = TPSTATION%XLAT
TZSTATIONS(NUMBSTAT_LOC)%NI_M = TPSTATION%NI_M
TZSTATIONS(NUMBSTAT_LOC)%NJ_M = TPSTATION%NJ_M
TZSTATIONS(NUMBSTAT_LOC)%NI_U = TPSTATION%NI_U
TZSTATIONS(NUMBSTAT_LOC)%NJ_V = TPSTATION%NJ_V
TZSTATIONS(NUMBSTAT_LOC)%XXMCOEF = TPSTATION%XXMCOEF
TZSTATIONS(NUMBSTAT_LOC)%XYMCOEF = TPSTATION%XYMCOEF
TZSTATIONS(NUMBSTAT_LOC)%XXUCOEF = TPSTATION%XXUCOEF
TZSTATIONS(NUMBSTAT_LOC)%XYVCOEF = TPSTATION%XYVCOEF

WAUTELET Philippe
committed
TZSTATIONS(NUMBSTAT_LOC)%NK = TPSTATION%NK

WAUTELET Philippe
committed

WAUTELET Philippe
committed
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

WAUTELET Philippe
committed
! ########################################################
FUNCTION STATPROF_INTERP_2D( TPSTATPROF, PA ) RESULT( PB )
! ########################################################
USE MODD_CONF, ONLY: L1D
USE MODD_PARAMETERS, ONLY: XUNDEF

WAUTELET Philippe
committed
USE MODE_MSG
IMPLICIT NONE

WAUTELET Philippe
committed
CLASS(TSTATPROFDATA), INTENT(IN) :: TPSTATPROF

WAUTELET Philippe
committed
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

WAUTELET Philippe
committed
JI = TPSTATPROF%NI_M
JJ = TPSTATPROF%NJ_M

WAUTELET Philippe
committed
END IF
IF ( JI >= 1 .AND. JI < SIZE( PA, 1 ) &
.AND. JJ >= 1 .AND. JJ < SIZE( PA, 2 ) ) THEN

WAUTELET Philippe
committed
PB = (1.-TPSTATPROF%XXMCOEF) * (1.-TPSTATPROF%XYMCOEF) * PA(JI, JJ ) + &
( TPSTATPROF%XXMCOEF) * (1.-TPSTATPROF%XYMCOEF) * PA(JI+1, JJ ) + &
(1.-TPSTATPROF%XXMCOEF) * ( TPSTATPROF%XYMCOEF) * PA(JI, JJ+1) + &
( TPSTATPROF%XXMCOEF) * ( TPSTATPROF%XYMCOEF) * PA(JI+1, JJ+1)

WAUTELET Philippe
committed
ELSE

WAUTELET Philippe
committed
CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATPROF_INTERP_2D', 'value can not be interpolated', OLOCAL = .TRUE. )

WAUTELET Philippe
committed
PB = XUNDEF

WAUTELET Philippe
committed
END IF

WAUTELET Philippe
committed
END FUNCTION STATPROF_INTERP_2D

WAUTELET Philippe
committed

WAUTELET Philippe
committed
! ##########################################################
FUNCTION STATPROF_INTERP_2D_U( TPSTATPROF, PA ) RESULT( PB )
! ##########################################################
USE MODD_CONF, ONLY: L1D
USE MODD_PARAMETERS, ONLY: XUNDEF

WAUTELET Philippe
committed
USE MODE_MSG
IMPLICIT NONE

WAUTELET Philippe
committed
CLASS(TSTATPROFDATA), INTENT(IN) :: TPSTATPROF

WAUTELET Philippe
committed
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

WAUTELET Philippe
committed
JI = TPSTATPROF%NI_U
JJ = TPSTATPROF%NJ_M

WAUTELET Philippe
committed
END IF
IF ( JI >= 1 .AND. JI < SIZE( PA, 1 ) &
.AND. JJ >= 1 .AND. JJ < SIZE( PA, 2 ) ) THEN

WAUTELET Philippe
committed
PB = (1.-TPSTATPROF%XXUCOEF) * (1.-TPSTATPROF%XYMCOEF) * PA(JI, JJ ) + &
( TPSTATPROF%XXUCOEF) * (1.-TPSTATPROF%XYMCOEF) * PA(JI+1, JJ ) + &
(1.-TPSTATPROF%XXUCOEF) * ( TPSTATPROF%XYMCOEF) * PA(JI, JJ+1) + &
( TPSTATPROF%XXUCOEF) * ( TPSTATPROF%XYMCOEF) * PA(JI+1, JJ+1)

WAUTELET Philippe
committed
ELSE

WAUTELET Philippe
committed
CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATPROF_INTERP_2D_U', 'value can not be interpolated', OLOCAL = .TRUE. )

WAUTELET Philippe
committed
PB = XUNDEF

WAUTELET Philippe
committed
END IF

WAUTELET Philippe
committed
END FUNCTION STATPROF_INTERP_2D_U

WAUTELET Philippe
committed

WAUTELET Philippe
committed
! ##########################################################
FUNCTION STATPROF_INTERP_2D_V( TPSTATPROF, PA ) RESULT( PB )
! ##########################################################
USE MODD_CONF, ONLY: L1D
USE MODD_PARAMETERS, ONLY: XUNDEF

WAUTELET Philippe
committed
USE MODE_MSG
IMPLICIT NONE

WAUTELET Philippe
committed
CLASS(TSTATPROFDATA), INTENT(IN) :: TPSTATPROF

WAUTELET Philippe
committed
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

WAUTELET Philippe
committed
JI = TPSTATPROF%NI_M
JJ = TPSTATPROF%NJ_V

WAUTELET Philippe
committed
END IF
IF ( JI >= 1 .AND. JI < SIZE( PA, 1 ) &
.AND. JJ >= 1 .AND. JJ < SIZE( PA, 2 ) ) THEN

WAUTELET Philippe
committed
PB = (1.-TPSTATPROF%XXMCOEF) * (1.-TPSTATPROF%XYVCOEF) * PA(JI, JJ ) + &
( TPSTATPROF%XXMCOEF) * (1.-TPSTATPROF%XYVCOEF) * PA(JI+1, JJ ) + &
(1.-TPSTATPROF%XXMCOEF) * ( TPSTATPROF%XYVCOEF) * PA(JI, JJ+1) + &
( TPSTATPROF%XXMCOEF) * ( TPSTATPROF%XYVCOEF) * PA(JI+1, JJ+1)

WAUTELET Philippe
committed
ELSE

WAUTELET Philippe
committed
CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATPROF_INTERP_2D_V', 'value can not be interpolated', OLOCAL = .TRUE. )

WAUTELET Philippe
committed
PB = XUNDEF

WAUTELET Philippe
committed
END IF

WAUTELET Philippe
committed
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
END FUNCTION STATPROF_INTERP_2D_V
! ########################################################
FUNCTION STATPROF_INTERP_3D( TPSTATPROF, PA ) RESULT( PB )
! ########################################################
USE MODD_CONF, ONLY: L1D
USE MODD_PARAMETERS, ONLY: XUNDEF
USE MODE_MSG
IMPLICIT NONE
CLASS(TSTATPROFDATA), INTENT(IN) :: TPSTATPROF
REAL, DIMENSION(:,:,:), INTENT(IN) :: PA
REAL, DIMENSION(SIZE(PA,3)) :: PB
INTEGER :: JI, JJ, JK
IF ( SIZE( PA, 1 ) == 2 ) THEN
JI = 1
JJ = 1
ELSE IF ( L1D ) THEN
JI = 2
JJ = 2
ELSE
JI = TPSTATPROF%NI_M
JJ = TPSTATPROF%NJ_M
END IF
IF ( JI >= 1 .AND. JI < SIZE( PA, 1 ) &
.AND. JJ >= 1 .AND. JJ < SIZE( PA, 2 ) ) THEN
DO JK = 1, SIZE( PA, 3 )
IF ( PA(JI, JJ, JK) /= XUNDEF .AND. PA(JI+1, JJ, JK) /= XUNDEF .AND. &
PA(JI, JJ+1, JK) /= XUNDEF .AND. PA(JI+1, JJ+1, JK) /= XUNDEF ) THEN
PB(JK) = (1.-TPSTATPROF%XXMCOEF) * (1.-TPSTATPROF%XYMCOEF) * PA(JI, JJ, JK) + &
( TPSTATPROF%XXMCOEF) * (1.-TPSTATPROF%XYMCOEF) * PA(JI+1, JJ, JK) + &
(1.-TPSTATPROF%XXMCOEF) * ( TPSTATPROF%XYMCOEF) * PA(JI, JJ+1, JK) + &
( TPSTATPROF%XXMCOEF) * ( TPSTATPROF%XYMCOEF) * PA(JI+1, JJ+1, JK)
ELSE
PB(JK) = XUNDEF
END IF
END DO
ELSE

WAUTELET Philippe
committed
CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATPROF_INTERP_3D', 'value can not be interpolated', OLOCAL = .TRUE. )

WAUTELET Philippe
committed
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
PB(:) = XUNDEF
END IF
END FUNCTION STATPROF_INTERP_3D
! ##########################################################
FUNCTION STATPROF_INTERP_3D_U( TPSTATPROF, PA ) RESULT( PB )
! ##########################################################
USE MODD_CONF, ONLY: L1D
USE MODD_PARAMETERS, ONLY: XUNDEF
USE MODE_MSG
IMPLICIT NONE
CLASS(TSTATPROFDATA), INTENT(IN) :: TPSTATPROF
REAL, DIMENSION(:,:,:), INTENT(IN) :: PA
REAL, DIMENSION(SIZE(PA,3)) :: PB
INTEGER :: JI, JJ
IF ( SIZE( PA, 1 ) == 2 ) THEN
JI = 1
JJ = 1
ELSE IF ( L1D ) THEN
JI = 2
JJ = 2
ELSE
JI = TPSTATPROF%NI_U
JJ = TPSTATPROF%NJ_M
END IF
IF ( JI >= 1 .AND. JI < SIZE( PA, 1 ) &
.AND. JJ >= 1 .AND. JJ < SIZE( PA, 2 ) ) THEN
PB(:) = (1.-TPSTATPROF%XXUCOEF) * (1.-TPSTATPROF%XYMCOEF) * PA(JI, JJ, :) + &
( TPSTATPROF%XXUCOEF) * (1.-TPSTATPROF%XYMCOEF) * PA(JI+1, JJ, :) + &
(1.-TPSTATPROF%XXUCOEF) * ( TPSTATPROF%XYMCOEF) * PA(JI, JJ+1, :) + &
( TPSTATPROF%XXUCOEF) * ( TPSTATPROF%XYMCOEF) * PA(JI+1, JJ+1, :)
ELSE

WAUTELET Philippe
committed
CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATPROF_INTERP_3D_U', 'value can not be interpolated', OLOCAL = .TRUE. )

WAUTELET Philippe
committed
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
PB = XUNDEF
END IF
END FUNCTION STATPROF_INTERP_3D_U
! ##########################################################
FUNCTION STATPROF_INTERP_3D_V( TPSTATPROF, PA ) RESULT( PB )
! ##########################################################
USE MODD_CONF, ONLY: L1D
USE MODD_PARAMETERS, ONLY: XUNDEF
USE MODE_MSG
IMPLICIT NONE
CLASS(TSTATPROFDATA), INTENT(IN) :: TPSTATPROF
REAL, DIMENSION(:,:,:), INTENT(IN) :: PA
REAL, DIMENSION(SIZE(PA,3)) :: PB
INTEGER :: JI, JJ
IF ( SIZE( PA, 1 ) == 2 ) THEN
JI = 1
JJ = 1
ELSE IF ( L1D ) THEN
JI = 2
JJ = 2
ELSE
JI = TPSTATPROF%NI_M
JJ = TPSTATPROF%NJ_V
END IF
IF ( JI >= 1 .AND. JI < SIZE( PA, 1 ) &
.AND. JJ >= 1 .AND. JJ < SIZE( PA, 2 ) ) THEN
PB(:) = (1.-TPSTATPROF%XXMCOEF) * (1.-TPSTATPROF%XYVCOEF) * PA(JI, JJ, :) + &
( TPSTATPROF%XXMCOEF) * (1.-TPSTATPROF%XYVCOEF) * PA(JI+1, JJ, :) + &
(1.-TPSTATPROF%XXMCOEF) * ( TPSTATPROF%XYVCOEF) * PA(JI, JJ+1, :) + &
( TPSTATPROF%XXMCOEF) * ( TPSTATPROF%XYVCOEF) * PA(JI+1, JJ+1, :)
ELSE

WAUTELET Philippe
committed
CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATPROF_INTERP_3D_V', 'value can not be interpolated', OLOCAL = .TRUE. )

WAUTELET Philippe
committed
PB = XUNDEF
END IF
END FUNCTION STATPROF_INTERP_3D_V

WAUTELET Philippe
committed
! #################################################
SUBROUTINE STATPROF_INSTANT( TPSTATPROF_TIME, KIN )
! #################################################
USE MODD_TIME_n, ONLY: TDTCUR

WAUTELET Philippe
committed
USE MODE_DATETIME

WAUTELET Philippe
committed
USE MODE_MSG
IMPLICIT NONE
TYPE(TSTATPROFTIME), INTENT(INOUT) :: TPSTATPROF_TIME
INTEGER, INTENT(OUT) :: KIN ! Current step of storage

WAUTELET Philippe
committed
IF ( TPSTATPROF_TIME%N_CUR == 0 ) THEN
! First store
TPSTATPROF_TIME%N_CUR = 1
TPSTATPROF_TIME%TPDATES(1) = TDTCUR
KIN = 1
ELSE
IF ( TDTCUR - TPSTATPROF_TIME%TPDATES(TPSTATPROF_TIME%N_CUR) >= TPSTATPROF_TIME%XTSTEP - 1.E-6 ) THEN
TPSTATPROF_TIME%N_CUR = TPSTATPROF_TIME%N_CUR + 1
KIN = TPSTATPROF_TIME%N_CUR

WAUTELET Philippe
committed

WAUTELET Philippe
committed
IF ( KIN < 1 .OR. KIN > SIZE( TPSTATPROF_TIME%TPDATES ) ) THEN
CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'STATPROF_INSTANT', 'problem with step of storage' )
KIN = -2
ELSE
TPSTATPROF_TIME%TPDATES(KIN) = TDTCUR
END IF

WAUTELET Philippe
committed
ELSE

WAUTELET Philippe
committed
! Return an invalid step number
KIN = -1

WAUTELET Philippe
committed
END IF
END IF
END SUBROUTINE STATPROF_INSTANT

WAUTELET Philippe
committed
END MODULE MODE_STATPROF_TOOLS