diff --git a/A-INSTALL b/A-INSTALL index a85c1f96f701ce78a3f7b88147e605ccd536bb48..14ef158756ed91d741f6384f049c749be1b371b5 100644 --- a/A-INSTALL +++ b/A-INSTALL @@ -1,7 +1,7 @@ # # Version of PACKAGE MESONH "Open distribution" # PACK-MNH-V5-6-1 -# DATE : 05/09/2023 +# DATE : 25/09/2023 # VERSION : MESONH MASDEV5_6 + BUG-1 # # MAP diff --git a/src/LIB/SURCOUCHE/src/mode_io_write_nc4.f90 b/src/LIB/SURCOUCHE/src/mode_io_write_nc4.f90 index 3f5860da56c6be4bf8b67fbd5b0dd7409779490c..9559f6b17ca0dcaa3816b5dcb764b2db48b8a678 100644 --- a/src/LIB/SURCOUCHE/src/mode_io_write_nc4.f90 +++ b/src/LIB/SURCOUCHE/src/mode_io_write_nc4.f90 @@ -2301,7 +2301,9 @@ subroutine Write_flyer_time_coord( tpflyer ) type(tdimnc), pointer :: tzdim !Do it only if correct model level and has really flown - if ( tpflyer%nmodel == imi .and. Count( tpflyer%xx /= XUNDEF) > 1 ) then + if ( tpflyer%nmodel == imi ) then + ! Do the second if only if the first one is OK (if not, xx may be not allocated) + if ( Count( tpflyer%xx /= XUNDEF) > 1 ) then Allocate( tzdim ) istatus = NF90_INQ_NCID( tpfile%nncid, 'Flyers', icatid ) @@ -2342,6 +2344,7 @@ subroutine Write_flyer_time_coord( tpflyer ) !Restore file identifier to root group incid = tpfile%nncid end if + end if end subroutine Write_flyer_time_coord diff --git a/src/MNH/aeroopt_get.f90 b/src/MNH/aeroopt_get.f90 index d8ec58193f7c308daba8bf8ad069ab21f2e7a976..994608c3da4bbb2bcab4f8ad5382131f9e67adc8 100644 --- a/src/MNH/aeroopt_get.f90 +++ b/src/MNH/aeroopt_get.f90 @@ -132,8 +132,9 @@ REAL, DIMENSION(size(ZMASS,1),size(ZMASS,2),size(ZMASS,3)) :: VEXTR COMPLEX, DIMENSION(size(ZMASS,1),size(ZMASS,2),size(ZMASS,3),6)::Req ! Equivalent refractive index REAL, PARAMETER :: EPSILON=1.d-8 ![um] a small number used to avoid zero - - INTEGER ::JJJ, JI, JSV + REAL,DIMENSION(NSP+NCARB+NSOA) :: ZFAC + REAL,DIMENSION(NSP+NCARB+NSOA) :: ZRHOI + INTEGER ::JJJ, JI, JSV, JJ !------------------------------------------------------------------------- !------------------------------------------------------------------------- @@ -212,25 +213,33 @@ NMODE_AER=JPMODE ! in case of ORILAM ! VDDST(:,:,:)=0. ! ENDIF - - VOC(:,:,:)=(ZMASS(:,:,:,JP_AER_OC,JMDE))/XFAC(JP_AER_OC) - VH2O(:,:,:)=(ZMASS(:,:,:,JP_AER_H2O,JMDE))/XFAC(JP_AER_H2O) - VAM(:,:,:)=(ZMASS(:,:,:,JP_AER_NH3,JMDE))/XFAC(JP_AER_NH3) - VSU(:,:,:)=(ZMASS(:,:,:,JP_AER_SO4,JMDE))/XFAC(JP_AER_SO4) - VNI(:,:,:)=(ZMASS(:,:,:,JP_AER_NO3,JMDE))/XFAC(JP_AER_NO3) - VBC(:,:,:)=(ZMASS(:,:,:,JP_AER_BC,JMDE))/XFAC(JP_AER_BC) - VDDST(:,:,:)=(ZMASS(:,:,:,JP_AER_DST,JMDE))/XFAC(JP_AER_DST) +! Cf Ackermann (all to black carbon except water) +!Set molecular weightn g/mol +ZRHOI(:) = 1.8e3 +ZRHOI(JP_AER_H2O) = 1.0e3 ! water +ZRHOI(JP_AER_DST) = XDENSITY_DUST ! dusts +DO JJ=1,NSP+NCARB+NSOA + ZFAC(JJ)=(4./3.)*XPI*ZRHOI(JJ)*1.e-9 +ENDDO + + VOC(:,:,:)=(ZMASS(:,:,:,JP_AER_OC,JMDE))/ZFAC(JP_AER_OC) + VH2O(:,:,:)=(ZMASS(:,:,:,JP_AER_H2O,JMDE))/ZFAC(JP_AER_H2O) + VAM(:,:,:)=(ZMASS(:,:,:,JP_AER_NH3,JMDE))/ZFAC(JP_AER_NH3) + VSU(:,:,:)=(ZMASS(:,:,:,JP_AER_SO4,JMDE))/ZFAC(JP_AER_SO4) + VNI(:,:,:)=(ZMASS(:,:,:,JP_AER_NO3,JMDE))/ZFAC(JP_AER_NO3) + VBC(:,:,:)=(ZMASS(:,:,:,JP_AER_BC,JMDE))/ZFAC(JP_AER_BC) + VDDST(:,:,:)=(ZMASS(:,:,:,JP_AER_DST,JMDE))/ZFAC(JP_AER_DST) IF (NSOA .EQ. 10) THEN - VSOA1(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA1,JMDE))/XFAC(JP_AER_SOA1) - VSOA2(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA2,JMDE))/XFAC(JP_AER_SOA2) - VSOA3(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA3,JMDE))/XFAC(JP_AER_SOA3) - VSOA4(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA4,JMDE))/XFAC(JP_AER_SOA4) - VSOA5(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA5,JMDE))/XFAC(JP_AER_SOA5) - VSOA6(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA6,JMDE))/XFAC(JP_AER_SOA6) - VSOA7(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA7,JMDE))/XFAC(JP_AER_SOA7) - VSOA8(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA8,JMDE))/XFAC(JP_AER_SOA8) - VSOA9(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA9,JMDE))/XFAC(JP_AER_SOA9) - VSOA10(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA10,JMDE))/XFAC(JP_AER_SOA10) + VSOA1(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA1,JMDE))/ZFAC(JP_AER_SOA1) + VSOA2(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA2,JMDE))/ZFAC(JP_AER_SOA2) + VSOA3(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA3,JMDE))/ZFAC(JP_AER_SOA3) + VSOA4(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA4,JMDE))/ZFAC(JP_AER_SOA4) + VSOA5(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA5,JMDE))/ZFAC(JP_AER_SOA5) + VSOA6(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA6,JMDE))/ZFAC(JP_AER_SOA6) + VSOA7(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA7,JMDE))/ZFAC(JP_AER_SOA7) + VSOA8(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA8,JMDE))/ZFAC(JP_AER_SOA8) + VSOA9(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA9,JMDE))/ZFAC(JP_AER_SOA9) + VSOA10(:,:,:)=(ZMASS(:,:,:,JP_AER_SOA10,JMDE))/ZFAC(JP_AER_SOA10) VSOA(:,:,:)=VSOA1(:,:,:)+VSOA2(:,:,:)+VSOA3(:,:,:)+VSOA4(:,:,:)+& VSOA5(:,:,:)+VSOA6(:,:,:)+VSOA7(:,:,:)+VSOA8(:,:,:)+& VSOA9(:,:,:)+VSOA10(:,:,:) diff --git a/src/MNH/aircraft_balloon_evol.f90 b/src/MNH/aircraft_balloon_evol.f90 index e37f97c5b71fa08247d3449f6c8c8923c4296cdf..dcbdd6349d012cb4ceea2734c75146d1c55a5c4b 100644 --- a/src/MNH/aircraft_balloon_evol.f90 +++ b/src/MNH/aircraft_balloon_evol.f90 @@ -31,6 +31,8 @@ MODULE MODE_AIRCRAFT_BALLOON_EVOL ! ########################## +USE MODD_PRECISION, ONLY: MNHREAL + USE MODE_MSG IMPLICIT NONE @@ -43,6 +45,8 @@ PUBLIC :: AIRCRAFT_COMPUTE_POSITION PUBLIC :: FLYER_GET_RANK_MODEL_ISCRASHED +REAL, PARAMETER :: XTIMETHRESH = 1.E-8_MNHREAL + CONTAINS ! ######################################################## SUBROUTINE AIRCRAFT_BALLOON_EVOL(PTSTEP, & @@ -299,7 +303,7 @@ SELECT TYPE ( TPFLYER ) ! Launch? LAUNCH: IF ( .NOT. TPFLYER%LFLY .AND. .NOT. TPFLYER%LCRASH .AND. TPFLYER%NMODEL == IMI ) THEN ! Check if it is launchtime - LAUNCHTIME: IF ( ( TDTCUR - TPFLYER%TLAUNCH ) >= -1.e-10 ) THEN + LAUNCHTIME: IF ( ( TDTCUR - TPFLYER%TLAUNCH ) >= -XTIMETHRESH ) THEN TPFLYER%LFLY = .TRUE. GLAUNCH = .TRUE. @@ -315,15 +319,16 @@ SELECT TYPE ( TPFLYER ) ! Check if it is time to store data. This has also to be checked if the balloon ! is not yet launched or is crashed (data is also written in these cases, but with default values) IF ( TPFLYER%NMODEL == IMI .AND. & - ( .NOT. TPFLYER%LFLY .OR. TPFLYER%LCRASH .OR. ABS( TPFLYER%TPOS_CUR - TDTCUR ) < 1.e-8 ) ) THEN + ( .NOT. TPFLYER%LFLY .OR. TPFLYER%LCRASH .OR. ABS( TPFLYER%TPOS_CUR - TDTCUR ) < XTIMETHRESH ) ) THEN !Do we have to store balloon data? TPFLYER%LSTORE = TPFLYER%TFLYER_TIME%STORESTEP_CHECK_AND_SET( ISTORE ) IF ( TPFLYER%LSTORE ) TPFLYER%NSTORE_CUR = ISTORE END IF ! In flight + ! The condition "ABS( TPFLYER%TPOS_CUR - TDTCUR ) < XTIMETHRESH" is necessary if the balloon changes of model INFLIGHTONMODEL: IF ( TPFLYER%LFLY .AND. .NOT. TPFLYER%LCRASH .AND. TPFLYER%NMODEL == IMI & - .AND. ABS( TPFLYER%TPOS_CUR - TDTCUR ) < 1.e-8 ) THEN + .AND. ABS( TPFLYER%TPOS_CUR - TDTCUR ) < XTIMETHRESH ) THEN ISOWNERBAL: IF ( TPFLYER%NRANK_CUR == ISP ) THEN CALL FLYER_INTERP_TO_MASSPOINTS() diff --git a/src/MNH/ini_aircraft.f90 b/src/MNH/ini_aircraft.f90 index 40be297467af3fdff58183479da32c89a667975a..64e39beb3c82047dd42ed9f19ccd5d9c94f2a434 100644 --- a/src/MNH/ini_aircraft.f90 +++ b/src/MNH/ini_aircraft.f90 @@ -54,6 +54,8 @@ DO JI = 1, NAIRCRAFTS TZAIRCRAFT%NID = JI + TZAIRCRAFT%LFIX = .FALSE. + IF ( CTITLE(JI) == '' ) THEN WRITE( CTITLE(JI), FMT = '( A, I3.3) ') TRIM( CTYPE(JI) ), JI diff --git a/src/MNH/ini_aircraft_balloon.f90 b/src/MNH/ini_aircraft_balloon.f90 index 7dc6567036e01f7619912a665cd1b99b452486e7..f31a5584a3f4d9018367801a666ac2644e9098a0 100644 --- a/src/MNH/ini_aircraft_balloon.f90 +++ b/src/MNH/ini_aircraft_balloon.f90 @@ -67,10 +67,11 @@ CONTAINS ! ------------ ! USE MODD_AIRCRAFT_BALLOON -USE MODD_CONF, ONLY: CPROGRAM +USE MODD_CONF, ONLY: CPROGRAM, NMODEL USE MODD_DYN_n, ONLY: DYN_MODEL USE MODD_IO, ONLY: ISP, TFILEDATA USE MODD_PARAMETERS, ONLY: NUNDEF +USE MODD_PARAM_n, ONLY: PARAM_MODEL ! USE MODE_GRIDPROJ, ONLY: SM_XYHAT USE MODE_INI_AIRCRAFT, ONLY: INI_AIRCRAFT @@ -92,6 +93,7 @@ REAL, INTENT(IN) :: PLONOR ! longitude of origine point ! INTEGER :: IMI ! current model index INTEGER :: JI +LOGICAL :: GCHECK ! !---------------------------------------------------------------------------- @@ -99,12 +101,12 @@ IF ( CPROGRAM == 'DIAG ') RETURN IF ( NAIRCRAFTS > 0 .OR. NBALLOONS > 0 ) LFLYER = .TRUE. +IMI = GET_CURRENT_MODEL_INDEX() + !---------------------------------------------------------------------------- ! !* 2. Balloon initialization ! ---------------------- -IMI=GET_CURRENT_MODEL_INDEX() - IF ( IMI == 1 ) THEN ALLOCATE( NRANKCUR_BALLOON (NBALLOONS) ); NRANKCUR_BALLOON = NFLYER_DEFAULT_RANK ALLOCATE( NRANKNXT_BALLOON (NBALLOONS) ); NRANKNXT_BALLOON = NFLYER_DEFAULT_RANK @@ -147,13 +149,50 @@ END IF !* 4. Allocations of storage arrays ! ----------------------------- ! -IF ( IMI == 1 .AND. ISP == NFLYER_DEFAULT_RANK ) THEN +! Check that CCLOUD, CRAD and CTURB are the same for all models if some flyers have CMODEL='MOB' +! This is necessary because we need to allocate and compute the same data on every model if the flyer is allowed to change model +! This check is only done once (on MODEL IMI=1) +! This check has to be done AFTER the calls to INI_AIRCRAFT and INI_BALLOON +IF ( IMI == 1 .AND. NMODEL > 1 .AND. ISP == NFLYER_DEFAULT_RANK ) THEN + GCHECK = .FALSE. + + DO JI = 1, NBALLOONS + IF ( TBALLOONS(JI)%TBALLOON%CMODEL == 'MOB' ) THEN + GCHECK = .TRUE. + EXIT + END IF + END DO + + DO JI = 1, NAIRCRAFTS + IF ( TAIRCRAFTS(JI)%TAIRCRAFT%CMODEL == 'MOB' ) THEN + GCHECK = .TRUE. + EXIT + END IF + END DO + + IF ( GCHECK ) THEN + DO JI = 2, NMODEL + IF ( PARAM_MODEL(JI)%CCLOUD /= PARAM_MODEL(1)%CCLOUD ) & + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'INI_AIRCRAFT_BALLOON', & + 'CCLOUD must be the same on all nested domains if aircraft/balloon has CMODEL="MOB"' ) + IF ( PARAM_MODEL(JI)%CRAD /= PARAM_MODEL(1)%CRAD ) & + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'INI_AIRCRAFT_BALLOON', & + 'CRAD must be the same on all nested domains if aircraft/balloon has CMODEL="MOB"' ) + IF ( PARAM_MODEL(JI)%CTURB /= PARAM_MODEL(1)%CTURB ) & + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'INI_AIRCRAFT_BALLOON', & + 'CTURB must be the same on all nested domains if aircraft/balloon has CMODEL="MOB"' ) + END DO + END IF +END IF + +! Allocate data arrays of flyers +IF ( ISP == NFLYER_DEFAULT_RANK ) THEN DO JI = 1, NBALLOONS - CALL TBALLOONS(JI)%TBALLOON%DATA_ARRAYS_ALLOCATE() + IF ( TBALLOONS(JI)%TBALLOON%NMODEL == IMI ) CALL TBALLOONS(JI)%TBALLOON%DATA_ARRAYS_ALLOCATE() END DO DO JI = 1, NAIRCRAFTS - CALL TAIRCRAFTS(JI)%TAIRCRAFT%DATA_ARRAYS_ALLOCATE() + IF ( TAIRCRAFTS(JI)%TAIRCRAFT%NMODEL == IMI ) CALL TAIRCRAFTS(JI)%TAIRCRAFT%DATA_ARRAYS_ALLOCATE() END DO END IF ! @@ -208,6 +247,7 @@ CALL SM_XYHAT( PLATOR, PLONOR, TPFLYER%XLATLAUNCH, TPFLYER%XLONLAUNCH, TPFLYER%X IF ( CPROGRAM == 'MESONH' .OR. CPROGRAM == 'SPAWN ' .OR. CPROGRAM == 'REAL ' ) THEN ! Read the current location in the synchronous file + ! Remark: if the balloon is not yet in flight or is crashed, position is not available in file IF ( TPINIFILE%CFORMAT == 'LFI' & .OR. ( TPINIFILE%CFORMAT == 'NETCDF4' .AND. & diff --git a/src/MNH/ini_balloon.f90 b/src/MNH/ini_balloon.f90 index bbcaa9abad8b08aa5af220fc8fc9cc6055de02b5..e3ca63c57f4548453f78fef314f1cf78e9f11ed2 100644 --- a/src/MNH/ini_balloon.f90 +++ b/src/MNH/ini_balloon.f90 @@ -48,6 +48,8 @@ DO JI = 1, NBALLOONS TZBALLOON%NID = JI + TZBALLOON%LFIX = .FALSE. + IF ( CTITLE(JI) == '' ) THEN WRITE( CTITLE(JI), FMT = '( A, I3.3) ') TRIM( CTYPE(JI) ), JI diff --git a/src/MNH/ini_posprofilern.f90 b/src/MNH/ini_posprofilern.f90 index 4ce19c1558c9b1b90c8c30c16ab0631bd4037214..6a50b045d044f43e3a1ae420c44edadfc66d488c 100644 --- a/src/MNH/ini_posprofilern.f90 +++ b/src/MNH/ini_posprofilern.f90 @@ -141,6 +141,7 @@ END IF LPROFILER = ( INUMBPROF > 0 ) DO JI = 1, NUMBPROFILER_LOC + TPROFILERS(JI)%LFIX = .TRUE. CALL TPROFILERS(JI)%DATA_ARRAYS_ALLOCATE( ISTORE ) END DO !---------------------------------------------------------------------------- diff --git a/src/MNH/ini_surfstationn.f90 b/src/MNH/ini_surfstationn.f90 index c1eb1a20dab4975e5cb9021e1154403505ed7996..a14cc771c37a1852a1ff9cd1991400cfb71795d7 100644 --- a/src/MNH/ini_surfstationn.f90 +++ b/src/MNH/ini_surfstationn.f90 @@ -142,6 +142,7 @@ END IF LSTATION = ( INUMBSTAT > 0 ) DO JI = 1, NUMBSTAT_LOC + TSTATIONS(JI)%LFIX = .TRUE. CALL TSTATIONS(JI)%DATA_ARRAYS_ALLOCATE( ISTORE ) END DO diff --git a/src/MNH/modd_sensor.f90 b/src/MNH/modd_sensor.f90 index 18ca64c27d6941aaa3a87a398614b0900f1867ae..b780c39137fc86ee7ed5d63c5a9af8921b9b8c04 100644 --- a/src/MNH/modd_sensor.f90 +++ b/src/MNH/modd_sensor.f90 @@ -21,6 +21,8 @@ MODULE MODD_SENSOR INTEGER, PARAMETER :: NTAG_NCUR = 145 INTEGER, PARAMETER :: NTAG_PACK = 245 + + INTEGER, PARAMETER :: NEMPTYDATA = -1 ! Size to communicate if exchange of no sensor data TYPE :: TSENSORTIME INTEGER :: N_CUR = 0 ! current step of storage REAL :: XTSTEP = 60. ! storage time step (default reset later) @@ -71,6 +73,7 @@ MODULE MODD_SENSOR INTEGER :: NV01 = NNEGUNDEF ! Z position for ni_m , nj_v+1 INTEGER :: NV10 = NNEGUNDEF ! Z position for ni_m+1, nj_v INTEGER :: NV11 = NNEGUNDEF ! Z position for ni_m+1, nj_v+1 + ! Coefficient to interpolate values (sensors are usually not exactly on mesh points) REAL :: XXMCOEF = XUNDEF ! Interpolation coefficient for X (mass-point) REAL :: XYMCOEF = XUNDEF ! Interpolation coefficient for Y (mass-point) @@ -380,7 +383,6 @@ MODULE MODD_SENSOR INTEGER :: IK00, IK01, IK10, IK11 INTEGER :: IKB, IKE, IKU INTEGER :: JI, JJ - LOGICAL :: GCHANGE ! set to true if at least an index has been forced to change LOGICAL :: GDONE ! set to true if coefficient computation has been done LOGICAL :: GDONOLOWCRASH REAL :: ZZCOEF00, ZZCOEF01, ZZCOEF10, ZZCOEF11 @@ -388,7 +390,6 @@ MODULE MODD_SENSOR OLOW = .FALSE. OHIGH = .FALSE. - GCHANGE = .FALSE. GDONE = .FALSE. IKB = 1 + JPVEXT @@ -419,9 +420,9 @@ MODULE MODD_SENSOR IF ( ANY( [ IK00, IK01, IK10, IK11 ] < IKB ) ) THEN ! Sensor is low (too near the ground or below it) OLOW = .TRUE. + IF ( GDONOLOWCRASH ) THEN ! Do not allow crash on the ground: set position on the ground if too low - GCHANGE = .TRUE. !Minimum altitude is on the ground at ikb (no crash if too low) IK00 = MAX ( IK00, IKB ) IK01 = MAX ( IK01, IKB ) @@ -454,25 +455,20 @@ MODULE MODD_SENSOR OHIGH = .TRUE. ! Limit ik?? indices to prevent out of bound accesses - IF ( IK00 > IKU-1) THEN - IK00 = IKU-1 - GCHANGE = .TRUE. - END IF - IF ( IK01 > IKU-1) THEN - IK01 = IKU-1 - GCHANGE = .TRUE. - END IF - IF ( IK10 > IKU-1) THEN - IK10 = IKU-1 - GCHANGE = .TRUE. - END IF - IF ( IK11 > IKU-1) THEN - IK11 = IKU-1 - GCHANGE = .TRUE. - END IF + IK00 = MIN( IK00, IKE ) + IK01 = MIN( IK01, IKE ) + IK10 = MIN( IK10, IKE ) + IK11 = MIN( IK11, IKE ) CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'Compute_vertical_interp_coeff', & 'sensor ' // TRIM( TPSENSOR%CNAME ) // ' is too high', OLOCAL = .TRUE. ) + + ZZCOEF00 = XUNDEF + ZZCOEF01 = XUNDEF + ZZCOEF10 = XUNDEF + ZZCOEF11 = XUNDEF + + GDONE = .TRUE. END IF IF ( .NOT. GDONE ) THEN @@ -1258,9 +1254,9 @@ MODULE MODD_SENSOR END SUBROUTINE BUFFER_RECV - ! ################################################################## - SUBROUTINE SENSOR_COMM_SEND( TPSENSOR, KTO, OSEND_SIZE_TO_RECEIVER ) - ! ################################################################## + ! ############################################################################## + SUBROUTINE SENSOR_COMM_SEND( TPSENSOR, KTO, OSEND_SIZE_TO_RECEIVER, OEMPTYSEND ) + ! ############################################################################## USE MODD_IO, ONLY: ISP @@ -1269,10 +1265,12 @@ MODULE MODD_SENSOR CLASS(TSENSOR), INTENT(INOUT) :: TPSENSOR INTEGER, INTENT(IN) :: KTO ! Process to which to send data LOGICAL, OPTIONAL, INTENT(IN) :: OSEND_SIZE_TO_RECEIVER ! If the buffer size has to be send to the receiver + LOGICAL, OPTIONAL, INTENT(IN) :: OEMPTYSEND ! True if the sensor data has not to be sent CHARACTER(LEN=10) :: YFROM, YTO INTEGER :: IPACKSIZE INTEGER :: IPOS + LOGICAL :: GEMPTYSEND LOGICAL :: GSEND_SIZE_TO_RECEIVER REAL, DIMENSION(:), ALLOCATABLE :: ZPACK ! buffer to store raw data of the sensor @@ -1281,27 +1279,45 @@ MODULE MODD_SENSOR CALL PRINT_MSG( NVERB_DEBUG, 'GEN', 'Sensor_comm_send', & 'send sensor ' // TRIM(TPSENSOR%CNAME) // ': ' // TRIM(YFROM) // '->' // TRIM(YTO), OLOCAL = .TRUE. ) + IF ( PRESENT( OEMPTYSEND ) ) THEN + GEMPTYSEND = OEMPTYSEND + ELSE + GEMPTYSEND = .FALSE. + END IF + IF ( PRESENT( OSEND_SIZE_TO_RECEIVER ) ) THEN GSEND_SIZE_TO_RECEIVER = OSEND_SIZE_TO_RECEIVER ELSE GSEND_SIZE_TO_RECEIVER = .FALSE. END IF - IPACKSIZE = TPSENSOR%BUFFER_SIZE_COMPUTE( TPSENSOR%NSTORE_CUR ) + IF ( GEMPTYSEND .AND. .NOT.GSEND_SIZE_TO_RECEIVER ) & + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_send', & + 'incompatible options: gemptysend=T and gsend_size_to_receiver=F', OLOCAL = .TRUE. ) + + IF ( GEMPTYSEND ) THEN + ! If 'empty send', ipacksize is set to NEMPTYDATA + ! This will allow the receiver to know that no sensor data will be sent + IPACKSIZE = NEMPTYDATA + ELSE + IPACKSIZE = TPSENSOR%BUFFER_SIZE_COMPUTE( TPSENSOR%NSTORE_CUR ) + END IF IF ( GSEND_SIZE_TO_RECEIVER ) CALL TPSENSOR%BUFFER_SIZE_SEND( TPSENSOR%NSTORE_CUR, IPACKSIZE, KTO ) - ALLOCATE( ZPACK(IPACKSIZE) ) + IF ( .NOT. GEMPTYSEND ) THEN + ALLOCATE( ZPACK(IPACKSIZE) ) - IPOS = 1 - CALL TPSENSOR%BUFFER_PACK( ZPACK, IPOS, TPSENSOR%NSTORE_CUR ) + IPOS = 1 + CALL TPSENSOR%BUFFER_PACK( ZPACK, IPOS, TPSENSOR%NSTORE_CUR ) - IF ( IPOS-1 /= IPACKSIZE ) & - CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_send', 'IPOS-1 /= IPACKSIZE', OLOCAL = .TRUE. ) + IF ( IPOS-1 /= IPACKSIZE ) & + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_send', 'IPOS-1 /= IPACKSIZE', OLOCAL = .TRUE. ) - CALL TPSENSOR%BUFFER_SEND( ZPACK, KTO ) + CALL TPSENSOR%BUFFER_SEND( ZPACK, KTO ) - DEALLOCATE( ZPACK ) + DEALLOCATE( ZPACK ) + END IF END SUBROUTINE SENSOR_COMM_SEND @@ -1320,26 +1336,28 @@ MODULE MODD_SENSOR END SUBROUTINE SENSOR_COMM_SEND_DEALLOCATE - ! #################################################################################################### - SUBROUTINE SENSOR_COMM_RECV_ALLOCATE( TPSENSOR, KFROM, KSTORE_CUR, KSTORE_MAX, ORECV_SIZE_FROM_OWNER ) - ! #################################################################################################### + ! ################################################################################################################ + SUBROUTINE SENSOR_COMM_RECV_ALLOCATE( TPSENSOR, KFROM, KSTORE_CUR, KSTORE_MAX, ORECV_SIZE_FROM_OWNER, OEMPTYRECV ) + ! ################################################################################################################ USE MODD_IO, ONLY: ISP USE MODE_MSG CLASS(TSENSOR), INTENT(INOUT) :: TPSENSOR - INTEGER, INTENT(IN) :: KFROM ! Process from which to receive data + INTEGER, INTENT(IN) :: KFROM ! Process from which to receive data INTEGER, OPTIONAL, INTENT(IN) :: KSTORE_CUR ! Number of storage steps to receive INTEGER, OPTIONAL, INTENT(IN) :: KSTORE_MAX ! Maximum number of storage steps to store in sensor ! (if not provided, kstore_* size must be given by the sender) LOGICAL, OPTIONAL, INTENT(IN) :: ORECV_SIZE_FROM_OWNER ! If the buffer size has to be send to the receiver + LOGICAL, OPTIONAL, INTENT(OUT) :: OEMPTYRECV ! True if the sensor data has not been received CHARACTER(LEN=10) :: YFROM, YTO INTEGER :: IPACKSIZE INTEGER :: IPOS INTEGER :: ISTORE_CUR INTEGER :: ISTORE_MAX + LOGICAL :: GEMPTYRECV LOGICAL :: GRECV_SIZE_FROM_OWNER REAL, DIMENSION(:), ALLOCATABLE :: ZPACK ! buffer to store raw data of the sensor @@ -1348,6 +1366,8 @@ MODULE MODD_SENSOR CALL PRINT_MSG( NVERB_DEBUG, 'GEN', 'Sensor_comm_recv_allocate', & 'receive sensor (name not yet known): ' // TRIM(YFROM) // '->' // TRIM(YTO), OLOCAL = .TRUE. ) + GEMPTYRECV = .FALSE. + IF ( PRESENT( ORECV_SIZE_FROM_OWNER ) ) THEN GRECV_SIZE_FROM_OWNER = ORECV_SIZE_FROM_OWNER ELSE @@ -1387,19 +1407,29 @@ MODULE MODD_SENSOR IPACKSIZE = TPSENSOR%BUFFER_SIZE_COMPUTE( ISTORE_CUR ) END IF - ! Allocate receive buffer - ALLOCATE( ZPACK(IPACKSIZE) ) + IF ( IPACKSIZE == NEMPTYDATA ) THEN + GEMPTYRECV = .TRUE. + !call Print_msg( NVERB_DEBUG, 'GEN', 'Sensor_comm_recv_allocate', 'empty receive', olocal = .true. ) + IF ( .NOT. PRESENT( OEMPTYRECV) ) & + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_recv_allocate', & + 'optional dummy argument oemptyrecv must be provided in case of empty communication', OLOCAL = .TRUE. ) + ELSE + ! Allocate receive buffer + ALLOCATE( ZPACK(IPACKSIZE) ) - ! Allocation of sensor must be done only once the total number of stores is known (and only if not yet allocated) - IF (TPSENSOR%NSTORE_MAX < 0 ) CALL TPSENSOR%DATA_ARRAYS_ALLOCATE( ISTORE_MAX ) + ! Allocation of sensor must be done only once the total number of stores is known (and only if not yet allocated) + IF (TPSENSOR%NSTORE_MAX < 0 ) CALL TPSENSOR%DATA_ARRAYS_ALLOCATE( ISTORE_MAX ) - CALL TPSENSOR%BUFFER_RECV( ZPACK, KFROM ) + CALL TPSENSOR%BUFFER_RECV( ZPACK, KFROM ) - IPOS = 1 - CALL TPSENSOR%BUFFER_UNPACK( ZPACK, IPOS, ISTORE_CUR ) + IPOS = 1 + CALL TPSENSOR%BUFFER_UNPACK( ZPACK, IPOS, ISTORE_CUR ) + + IF ( IPOS-1 /= IPACKSIZE ) & + CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_recv_allocate', 'IPOS-1 /= IPACKSIZE', OLOCAL = .TRUE. ) + END IF - IF ( IPOS-1 /= IPACKSIZE ) & - CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_recv_allocate', 'IPOS-1 /= IPACKSIZE', OLOCAL = .TRUE. ) + IF ( PRESENT( OEMPTYRECV) ) OEMPTYRECV = GEMPTYRECV END SUBROUTINE SENSOR_COMM_RECV_ALLOCATE diff --git a/src/MNH/mode_sensor.f90 b/src/MNH/mode_sensor.f90 index bd6c86b3b6ee45c674bba2638188b766f3cd947b..e3ff8bea07f207702737b2803eb8b33bbcb380fa 100644 --- a/src/MNH/mode_sensor.f90 +++ b/src/MNH/mode_sensor.f90 @@ -54,6 +54,7 @@ CONTAINS TPSENSOR%XLWCZ(:,KSTORE_ID) = 0. TPSENSOR%XIWCZ(:,KSTORE_ID) = 0. + !TODO: add ICE4? IF ( CCLOUD == "LIMA" .OR. CCLOUD=="ICE3" ) THEN TPSENSOR%XLWCZ(:,KSTORE_ID) = TPSENSOR%INTERP_HOR_FROM_MASSPOINT( (PR(:,:,:,2)+PR(:,:,:,3) ) * PRHODREF(:,:,:) ) TPSENSOR%XIWCZ(:,KSTORE_ID) = TPSENSOR%INTERP_HOR_FROM_MASSPOINT( (PR(:,:,:,4)+PR(:,:,:,5)+PR(:,:,:,6)) * PRHODREF(:,:,:) ) @@ -136,6 +137,7 @@ CONTAINS TPSENSOR%XCRARE (:,KSTORE_ID) = 0. TPSENSOR%XCRARE_ATT(:,KSTORE_ID) = 0. + !TODO: add ICE4? IF ( CCLOUD == "LIMA" .OR. CCLOUD=="ICE3" ) THEN ZTEMPZ(:) = TPSENSOR%INTERP_HOR_FROM_MASSPOINT( PTH_EXN(:,:,:) ) ZRHODREFZ(:) = TPSENSOR%INTERP_HOR_FROM_MASSPOINT( PRHODREF(:,:,:) ) @@ -519,7 +521,6 @@ CONTAINS SUBROUTINE ADD_ORILAM_DATA( TPSENSOR, KLEVEL, KSTORE ) USE MODD_CH_AEROSOL USE MODD_CONF_N, ONLY: NRR - USE MODD_CH_AEROSOL, ONLY: NCARB, NSOA, NSP USE MODD_CST, ONLY: XP00, XCPD, XRD, XRV USE MODD_NSV, ONLY: NSV_AER, NSV_AERBEG, NSV_AEREND diff --git a/src/MNH/write_aircraft_balloon.f90 b/src/MNH/write_aircraft_balloon.f90 index 61be44dab866a3aeb3082d101aaf1cf9608bebd0..a1b978be286734a3a65d09439ffd0d0792e0300c 100644 --- a/src/MNH/write_aircraft_balloon.f90 +++ b/src/MNH/write_aircraft_balloon.f90 @@ -78,7 +78,9 @@ SUBROUTINE WRITE_AIRCRAFT_BALLOON(TPDIAFILE) ! USE MODD_AIRCRAFT_BALLOON USE MODD_IO, ONLY: ISP, TFILEDATA -! + +USE MODE_MODELN_HANDLER, ONLY: GET_CURRENT_MODEL_INDEX + IMPLICIT NONE ! ! @@ -90,16 +92,21 @@ TYPE(TFILEDATA), INTENT(IN) :: TPDIAFILE ! file to write ! ! 0.2 declaration of local variables ! +INTEGER :: IMI INTEGER :: JI +LOGICAL :: GEMPTYCOMM ! if TRUE, the communication is empty (no data is exchanged) ! !---------------------------------------------------------------------------- +IMI = GET_CURRENT_MODEL_INDEX() + DO JI = 1, NBALLOONS ! The balloon data is only available on the process where it is physically located => transfer it if necessary ! Send data from owner to writer if necessary IF ( ISP == NRANKCUR_BALLOON(JI) .AND. NRANKCUR_BALLOON(JI) /= TPDIAFILE%NMASTER_RANK ) THEN - CALL TBALLOONS(JI)%TBALLOON%SEND( KTO = TPDIAFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .TRUE. ) + GEMPTYCOMM = ( TBALLOONS(JI)%TBALLOON%NMODEL /= IMI ) + CALL TBALLOONS(JI)%TBALLOON%SEND( KTO = TPDIAFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .TRUE., OEMPTYSEND = GEMPTYCOMM ) END IF IF ( ISP == TPDIAFILE%NMASTER_RANK ) THEN @@ -108,11 +115,12 @@ DO JI = 1, NBALLOONS IF ( ASSOCIATED( TBALLOONS(JI)%TBALLOON ) ) & call Print_msg( NVERB_FATAL, 'GEN', 'WRITE_AIRCRAFT_BALLOON', 'balloon already associated' ) ALLOCATE( TBALLOONS(JI)%TBALLOON ) - CALL TBALLOONS(JI)%TBALLOON%RECV_ALLOCATE( KFROM = NRANKCUR_BALLOON(JI), ORECV_SIZE_FROM_OWNER = .TRUE. ) + CALL TBALLOONS(JI)%TBALLOON%RECV_ALLOCATE( KFROM = NRANKCUR_BALLOON(JI), ORECV_SIZE_FROM_OWNER = .TRUE., & + OEMPTYRECV = GEMPTYCOMM ) END IF - ! Write data - CALL FLYER_DIACHRO( TPDIAFILE, TBALLOONS(JI)%TBALLOON ) + ! Write data (if balloon is on this model (GEMPTYCOMM=F)) + IF ( .NOT. GEMPTYCOMM ) CALL FLYER_DIACHRO( TPDIAFILE, TBALLOONS(JI)%TBALLOON ) ! Remark: release of memory is done later by a call to AIRCRAFT_BALLOON_FREE_NONLOCAL ! This call must be done after the file is closed because flyer data is needed on the @@ -125,7 +133,8 @@ DO JI = 1, NAIRCRAFTS ! Send data from owner to writer if necessary IF ( ISP == NRANKCUR_AIRCRAFT(JI) .AND. NRANKCUR_AIRCRAFT(JI) /= TPDIAFILE%NMASTER_RANK ) THEN - CALL TAIRCRAFTS(JI)%TAIRCRAFT%SEND( KTO = TPDIAFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .TRUE. ) + GEMPTYCOMM = ( TAIRCRAFTS(JI)%TAIRCRAFT%NMODEL /= IMI ) + CALL TAIRCRAFTS(JI)%TAIRCRAFT%SEND( KTO = TPDIAFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .TRUE., OEMPTYSEND = GEMPTYCOMM ) END IF IF ( ISP == TPDIAFILE%NMASTER_RANK ) THEN @@ -134,11 +143,12 @@ DO JI = 1, NAIRCRAFTS IF ( ASSOCIATED( TAIRCRAFTS(JI)%TAIRCRAFT ) ) & call Print_msg( NVERB_FATAL, 'GEN', 'WRITE_AIRCRAFT_BALLOON', 'aircraft already associated' ) ALLOCATE( TAIRCRAFTS(JI)%TAIRCRAFT ) - CALL TAIRCRAFTS(JI)%TAIRCRAFT%RECV_ALLOCATE( KFROM = NRANKCUR_AIRCRAFT(JI), ORECV_SIZE_FROM_OWNER = .TRUE. ) + CALL TAIRCRAFTS(JI)%TAIRCRAFT%RECV_ALLOCATE( KFROM = NRANKCUR_AIRCRAFT(JI), ORECV_SIZE_FROM_OWNER = .TRUE., & + OEMPTYRECV = GEMPTYCOMM ) END IF - ! Write data - CALL FLYER_DIACHRO( TPDIAFILE, TAIRCRAFTS(JI)%TAIRCRAFT ) + ! Write data (if aircraft is on this model (GEMPTYCOMM=F)) + IF ( .NOT. GEMPTYCOMM ) CALL FLYER_DIACHRO( TPDIAFILE, TAIRCRAFTS(JI)%TAIRCRAFT ) ! Remark: release of memory is done later by a call to AIRCRAFT_BALLOON_FREE_NONLOCAL ! This call must be done after the file is closed because flyer data is needed on the @@ -168,7 +178,7 @@ IF ( ISP == TPDIAFILE%NMASTER_RANK ) THEN DO JI = 1, NBALLOONS ! Free ballon data if it was not stored on this process IF ( NRANKCUR_BALLOON(JI) /= TPDIAFILE%NMASTER_RANK ) THEN - CALL TBALLOONS(JI)%TBALLOON%DATA_ARRAYS_DEALLOCATE() + IF ( TBALLOONS(JI)%TBALLOON%NSTORE_MAX >= 0 ) CALL TBALLOONS(JI)%TBALLOON%DATA_ARRAYS_DEALLOCATE() DEALLOCATE( TBALLOONS(JI)%TBALLOON ) END IF END DO @@ -176,7 +186,7 @@ IF ( ISP == TPDIAFILE%NMASTER_RANK ) THEN DO JI = 1, NAIRCRAFTS ! Free aircraft data if it was not stored on this process IF ( NRANKCUR_AIRCRAFT(JI) /= TPDIAFILE%NMASTER_RANK ) THEN - CALL TAIRCRAFTS(JI)%TAIRCRAFT%DATA_ARRAYS_DEALLOCATE() + IF ( TAIRCRAFTS(JI)%TAIRCRAFT%NSTORE_MAX >= 0 ) CALL TAIRCRAFTS(JI)%TAIRCRAFT%DATA_ARRAYS_DEALLOCATE() DEALLOCATE( TAIRCRAFTS(JI)%TAIRCRAFT ) END IF END DO @@ -239,10 +249,8 @@ IMI = GET_CURRENT_MODEL_INDEX() IRR = SIZE( tpflyer%xr, 3 ) -IF (TPFLYER%NMODEL==0) RETURN -IF (ALL(TPFLYER%XX==XUNDEF)) RETURN -IF (COUNT(TPFLYER%XX/=XUNDEF)<=1) RETURN IF ( IMI /= TPFLYER%NMODEL ) RETURN +IF ( ALL( TPFLYER%XX == XUNDEF ) ) RETURN ! IKU = SIZE(TPFLYER%XRTZ,1) !number of vertical levels ! diff --git a/src/MNH/write_balloonn.f90 b/src/MNH/write_balloonn.f90 index 4c0e7d02b4acb61d35441843c96319153e74a333..e519c2b99e0d289941727eb4106293c8abab8ac6 100644 --- a/src/MNH/write_balloonn.f90 +++ b/src/MNH/write_balloonn.f90 @@ -73,12 +73,13 @@ TYPE(TFILEDATA), INTENT(IN) :: TPFILE ! File characteristics ! INTEGER :: IMI INTEGER :: JI -LOGICAL :: OMONOPROC_SAVE ! Copy of true value of GSMONOPROC +LOGICAL :: GEMPTYCOMM ! if TRUE, the communication is empty (no data is exchanged) +LOGICAL :: GMONOPROC_SAVE ! Copy of true value of GSMONOPROC IMI = GET_CURRENT_MODEL_INDEX() ! Save GSMONOPROC value -OMONOPROC_SAVE = GSMONOPROC +GMONOPROC_SAVE = GSMONOPROC ! Force GSMONOPROC to true to allow IO_Field_write on only 1 process! (not very clean hack) GSMONOPROC = .TRUE. @@ -87,30 +88,33 @@ DO JI = 1, NBALLOONS ! Send data from owner to writer if necessary IF ( ISP == NRANKCUR_BALLOON(JI) .AND. NRANKCUR_BALLOON(JI) /= TPFILE%NMASTER_RANK ) THEN - CALL TBALLOONS(JI)%TBALLOON%SEND( KTO = TPFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .TRUE. ) + GEMPTYCOMM = ( TBALLOONS(JI)%TBALLOON%NMODEL /= IMI ) + CALL TBALLOONS(JI)%TBALLOON%SEND( KTO = TPFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .TRUE., OEMPTYSEND = GEMPTYCOMM ) END IF IF ( ISP == TPFILE%NMASTER_RANK ) THEN ! Receive data from owner if not available on the writer process IF ( NRANKCUR_BALLOON(JI) /= TPFILE%NMASTER_RANK ) THEN ALLOCATE( TBALLOONS(JI)%TBALLOON ) - CALL TBALLOONS(JI)%TBALLOON%RECV_ALLOCATE( KFROM = NRANKCUR_BALLOON(JI), ORECV_SIZE_FROM_OWNER = .TRUE. ) + CALL TBALLOONS(JI)%TBALLOON%RECV_ALLOCATE( KFROM = NRANKCUR_BALLOON(JI), ORECV_SIZE_FROM_OWNER = .TRUE., & + OEMPTYRECV = GEMPTYCOMM ) END IF ! Write data (only if flyer is on the current model) ! It will also be written in the ancestry model files - IF ( TBALLOONS(JI)%TBALLOON%NMODEL == IMI ) CALL WRITE_BALLOON_POSITION( TPFILE, TBALLOONS(JI)%TBALLOON ) + ! if GEMPTYCOMM=FALSE => flyer is on the current model (equivalent to TBALLOONS(JI)%TBALLOON%NMODEL==IMI) + IF ( .NOT. GEMPTYCOMM ) CALL WRITE_BALLOON_POSITION( TPFILE, TBALLOONS(JI)%TBALLOON ) ! Free ballon data if it was not stored on this process IF ( NRANKCUR_BALLOON(JI) /= TPFILE%NMASTER_RANK ) THEN - CALL TBALLOONS(JI)%TBALLOON%DATA_ARRAYS_DEALLOCATE() + IF ( TBALLOONS(JI)%TBALLOON%NSTORE_MAX >= 0 ) CALL TBALLOONS(JI)%TBALLOON%DATA_ARRAYS_DEALLOCATE() DEALLOCATE( TBALLOONS(JI)%TBALLOON ) END IF END IF END DO ! Restore correct value of GSMONOPROC -GSMONOPROC = OMONOPROC_SAVE +GSMONOPROC = GMONOPROC_SAVE END SUBROUTINE WRITE_BALLOON_n !------------------------------------------------------------------------------- @@ -151,7 +155,7 @@ REAL :: ZLON ! longitude of the balloon type(tfiledata) :: tzfile TYPE(TFIELDMETADATA) :: TZFIELD -! Do not write balloon position if not yet in fly or crashed +! Do not write balloon position if not yet in flight or crashed IF ( .NOT.TPFLYER%LFLY .OR. TPFLYER%LCRASH ) RETURN ! Check if current model time is the same as the time corresponding to the balloon position diff --git a/src/Makefile.MESONH.mk b/src/Makefile.MESONH.mk index 223dd4c2caca29b0eb051c92026de99e52859072..6c9420cecf939b753d843c54d177c914efe03376 100644 --- a/src/Makefile.MESONH.mk +++ b/src/Makefile.MESONH.mk @@ -342,7 +342,7 @@ INC_MPI = -I$(B)$(DIR_MPI) DIR_MASTER += $(DIR_MPI) OBJS_LISTE_MASTER += mpivide.o INC += $(INC_MPI) -mpivide.o : CPPFLAGS += -DMNH_INT=$(MNH_INT) -DMNH_REAL=$(MNH_REAL) \ +mpivide.o : CPPFLAGS_C += -DMNH_INT=$(MNH_INT) -DMNH_REAL=$(MNH_REAL) \ -I$(DIR_MPI)/include VPATH += $(DIR_MPI) endif