From bb4d0f98658d8019ba1196f8dd6cff1cce059f1b Mon Sep 17 00:00:00 2001
From: Philippe WAUTELET <philippe.wautelet@aero.obs-mip.fr>
Date: Fri, 7 Jul 2023 16:21:56 +0200
Subject: [PATCH] Philippe 07/07/2023: sensors: add SEND_ALLOCATE and
 RECV_DEALLOCATE procedures

---
 src/MNH/aircraft_balloon.f90       | 121 +-------------------
 src/MNH/aircraft_balloon_evol.f90  |   7 +-
 src/MNH/modd_sensor.f90            | 174 ++++++++++++++++++++++++++---
 src/MNH/write_aircraft_balloon.f90 |  10 +-
 src/MNH/write_balloonn.f90         |   5 +-
 src/MNH/write_profilern.f90        |  28 +----
 src/MNH/write_stationn.f90         |  30 +----
 7 files changed, 186 insertions(+), 189 deletions(-)

diff --git a/src/MNH/aircraft_balloon.f90 b/src/MNH/aircraft_balloon.f90
index 90a129d20..800804710 100644
--- a/src/MNH/aircraft_balloon.f90
+++ b/src/MNH/aircraft_balloon.f90
@@ -25,8 +25,6 @@ PUBLIC :: AIRCRAFT_BALLOON
 
 PUBLIC :: AIRCRAFT_BALLOON_LONGTYPE_GET
 
-PUBLIC :: FLYER_RECV_AND_ALLOCATE, FLYER_SEND
-
 INTEGER, PARAMETER :: NTAG_NCUR = 145
 INTEGER, PARAMETER :: NTAG_PACK = 245
 
@@ -212,13 +210,13 @@ DEALLOCATE( IRANKNXT_AIRCRAFT_TMP )
 DO JI = 1, NAIRCRAFTS
   IF ( NRANKNXT_AIRCRAFT(JI) /= NRANKCUR_AIRCRAFT(JI) ) THEN
     IF ( ISP == NRANKCUR_AIRCRAFT(JI) ) THEN
-      CALL FLYER_SEND_AND_DEALLOCATE( TAIRCRAFTS(JI)%TAIRCRAFT, NRANKNXT_AIRCRAFT(JI) )
+      CALL TAIRCRAFTS(JI)%TAIRCRAFT%SEND_DEALLOCATE( KTO = NRANKNXT_AIRCRAFT(JI), OSEND_SIZE_TO_RECEIVER = .TRUE. )
       DEALLOCATE( TAIRCRAFTS(JI)%TAIRCRAFT )
     ELSE IF ( ISP == NRANKNXT_AIRCRAFT(JI) ) THEN
       IF ( ASSOCIATED( TAIRCRAFTS(JI)%TAIRCRAFT ) ) &
         call Print_msg( NVERB_FATAL, 'GEN', 'AIRCRAFT_BALLOON', 'aircraft already associated' )
       ALLOCATE( TAIRCRAFTS(JI)%TAIRCRAFT )
-      CALL FLYER_RECV_AND_ALLOCATE( TAIRCRAFTS(JI)%TAIRCRAFT, NRANKCUR_AIRCRAFT(JI) )
+      CALL TAIRCRAFTS(JI)%TAIRCRAFT%RECV_ALLOCATE( KFROM = NRANKCUR_AIRCRAFT(JI), ORECV_SIZE_FROM_OWNER = .TRUE. )
     END IF
   END IF
 END DO
@@ -297,11 +295,11 @@ DEALLOCATE( IRANKNXT_BALLOON_TMP )
 DO JI = 1, NBALLOONS
   IF ( NRANKNXT_BALLOON(JI) /= NRANKCUR_BALLOON(JI) ) THEN
     IF ( ISP == NRANKCUR_BALLOON(JI) ) THEN
-      CALL FLYER_SEND_AND_DEALLOCATE( TBALLOONS(JI)%TBALLOON, NRANKNXT_BALLOON(JI) )
+      CALL TBALLOONS(JI)%TBALLOON%SEND_DEALLOCATE( KTO = NRANKNXT_BALLOON(JI), OSEND_SIZE_TO_RECEIVER = .TRUE. )
       DEALLOCATE( TBALLOONS(JI)%TBALLOON )
     ELSE IF ( ISP == NRANKNXT_BALLOON(JI) ) THEN
       ALLOCATE( TBALLOONS(JI)%TBALLOON )
-      CALL FLYER_RECV_AND_ALLOCATE( TBALLOONS(JI)%TBALLOON, NRANKCUR_BALLOON(JI) )
+      CALL TBALLOONS(JI)%TBALLOON%RECV_ALLOCATE( KFROM = NRANKCUR_BALLOON(JI), ORECV_SIZE_FROM_OWNER = .TRUE. )
     END IF
   END IF
 END DO
@@ -352,115 +350,4 @@ END SUBROUTINE AIRCRAFT_BALLOON_LONGTYPE_GET
 !----------------------------------------------------------------------------
 !----------------------------------------------------------------------------
 
-SUBROUTINE FLYER_SEND( TPFLYER, KTO )
-
-USE MODD_AIRCRAFT_BALLOON, ONLY: TFLYERDATA
-USE MODD_IO,               ONLY: ISP
-USE MODD_PARAMETERS,       ONLY: JPVEXT
-
-IMPLICIT NONE
-
-CLASS(TFLYERDATA), INTENT(INOUT) :: TPFLYER
-INTEGER,           INTENT(IN)    :: KTO     ! Process to which to send flyer data
-
-CHARACTER(LEN=10) :: YFROM, YTO
-INTEGER :: IPACKSIZE ! Size of the ZPACK buffer
-INTEGER :: IPOS      ! Position in the ZPACK buffer
-INTEGER :: ISTORE_CUR
-REAL,    DIMENSION(:), ALLOCATABLE :: ZPACK        ! Buffer to store raw data of a profiler (used for MPI communication)
-
-WRITE( YFROM, '( I10 )' ) ISP
-WRITE( YTO,   '( I10 )' ) KTO
-CALL PRINT_MSG( NVERB_DEBUG, 'GEN', 'FLYER_SEND', 'send flyer '//TRIM(TPFLYER%CNAME)//': '//TRIM(YFROM)//'->'//TRIM(YTO), &
-                OLOCAL = .TRUE. )
-
-ISTORE_CUR = TPFLYER%TFLYER_TIME%N_CUR
-
-
-IPACKSIZE = TPFLYER%BUFFER_SIZE_COMPUTE( ISTORE_CUR )
-
-CALL TPFLYER%BUFFER_SIZE_SEND( ISTORE_CUR, IPACKSIZE, KTO )
-
-ALLOCATE( ZPACK(IPACKSIZE) )
-
-IPOS = 1
-CALL TPFLYER%BUFFER_PACK( ZPACK, IPOS, ISTORE_CUR )
-
-IF ( IPOS-1 /= IPACKSIZE ) &
-  call Print_msg( NVERB_ERROR, 'IO', 'FLYER_SEND', 'IPOS-1 /= IPACKSIZE (sender side)', OLOCAL = .TRUE. )
-
-CALL TPFLYER%BUFFER_SEND( ZPACK, KTO )
-
-DEALLOCATE( ZPACK )
-
-END SUBROUTINE FLYER_SEND
-!----------------------------------------------------------------------------
-!----------------------------------------------------------------------------
-SUBROUTINE FLYER_SEND_AND_DEALLOCATE( TPFLYER, KTO )
-
-USE MODD_AIRCRAFT_BALLOON,     ONLY: TFLYERDATA
-USE MODD_IO,               ONLY: ISP
-
-IMPLICIT NONE
-
-CLASS(TFLYERDATA), INTENT(INOUT) :: TPFLYER
-INTEGER,           INTENT(IN)    :: KTO     ! Process to which to send flyer data
-
-CHARACTER(LEN=10) :: YFROM, YTO
-
-WRITE( YFROM, '( I10 )' ) ISP
-WRITE( YTO,   '( I10 )' ) KTO
-CALL PRINT_MSG( NVERB_DEBUG, 'GEN', 'FLYER_SEND_AND_DEALLOCATE', &
-                'send flyer '//TRIM(TPFLYER%CNAME)//': '//TRIM(YFROM)//'->'//TRIM(YTO), OLOCAL = .TRUE. )
-
-CALL FLYER_SEND( TPFLYER, KTO )
-
-! Free flyer data (dynamically allocated), scalar data has to be freed outside this subroutine
-CALL TPFLYER%DATA_ARRAYS_DEALLOCATE()
-
-END SUBROUTINE FLYER_SEND_AND_DEALLOCATE
-!----------------------------------------------------------------------------
-!----------------------------------------------------------------------------
-SUBROUTINE FLYER_RECV_AND_ALLOCATE( TPFLYER, KFROM )
-
-USE MODD_AIRCRAFT_BALLOON, ONLY: TFLYERDATA
-! USE MODD_IO,               ONLY: ISP
-
-IMPLICIT NONE
-
-CLASS(TFLYERDATA), INTENT(INOUT) :: TPFLYER
-INTEGER,           INTENT(IN)    :: KFROM   ! Process from which to receive flyer data
-
-! CHARACTER(LEN=10) :: YFROM, YTO
-INTEGER :: ISTORE_CUR
-INTEGER :: ISTORE_TOT
-INTEGER :: IPACKSIZE ! Size of the ZPACK buffer
-INTEGER :: IPOS      ! Position in the ZPACK buffer
-REAL,    DIMENSION(:), ALLOCATABLE :: ZPACK        ! Buffer to store raw data of a profiler (used for MPI communication)
-
-! WRITE( YFROM, '( I10 )' ) KFROM
-! WRITE( YTO,   '( I10 )' ) ISP
-! CALL PRINT_MSG( NVERB_DEBUG, 'GEN', 'FLYER_RECV_AND_ALLOCATE', &
-!                 'receive flyer (name not yet known): '//TRIM(YFROM)//'->'//TRIM(YTO), OLOCAL = .TRUE. )
-
-CALL TPFLYER%BUFFER_SIZE_RECV( ISTORE_CUR, ISTORE_TOT, IPACKSIZE, KFROM )
-
-! Allocate receive buffer
-ALLOCATE( ZPACK(IPACKSIZE) )
-
-! Allocation of flyer must be done only once number of stores is known
-CALL TPFLYER%DATA_ARRAYS_ALLOCATE( ISTORE_TOT )
-
-CALL TPFLYER%BUFFER_RECV( ZPACK, KFROM )
-
-IPOS = 1
-CALL TPFLYER%BUFFER_UNPACK( ZPACK, IPOS, ISTORE_CUR )
-
-IF ( IPOS-1 /= IPACKSIZE ) &
-  call Print_msg( NVERB_ERROR, 'IO', 'FLYER_RECV_AND_ALLOCATE', 'IPOS-1 /= IPACKSIZE (receiver side)', OLOCAL = .TRUE. )
-
-END SUBROUTINE FLYER_RECV_AND_ALLOCATE
-!----------------------------------------------------------------------------
-!----------------------------------------------------------------------------
-
 END MODULE MODE_AIRCRAFT_BALLOON
diff --git a/src/MNH/aircraft_balloon_evol.f90 b/src/MNH/aircraft_balloon_evol.f90
index 9d5be44c4..e0d7e555b 100644
--- a/src/MNH/aircraft_balloon_evol.f90
+++ b/src/MNH/aircraft_balloon_evol.f90
@@ -207,9 +207,12 @@ SELECT TYPE ( TPFLYER )
     END IF TAKEOFF
 
     !Do we have to store aircraft data?
-    IF ( IMI == TPFLYER%NMODEL ) TPFLYER%LSTORE = TPFLYER%TFLYER_TIME%STORESTEP_CHECK_AND_SET( ISTORE )
+    IF ( IMI == TPFLYER%NMODEL ) THEN
+      TPFLYER%LSTORE = TPFLYER%TFLYER_TIME%STORESTEP_CHECK_AND_SET( ISTORE )
+      IF ( TPFLYER%LSTORE ) TPFLYER%NSTORE_CUR = ISTORE
+    END IF
+
 
-    IF ( TPFLYER%LSTORE ) TPFLYER%NSTORE_CUR = ISTORE
     ! For aircrafts, data has only to be computed at store moments
     IF ( IMI == TPFLYER%NMODEL .AND. TPFLYER%LFLY .AND. TPFLYER%LSTORE ) THEN
       ! Check if it is the right moment to store data
diff --git a/src/MNH/modd_sensor.f90 b/src/MNH/modd_sensor.f90
index b0296e02c..be0672788 100644
--- a/src/MNH/modd_sensor.f90
+++ b/src/MNH/modd_sensor.f90
@@ -132,6 +132,9 @@ MODULE MODD_SENSOR
       PROCEDURE, NON_OVERRIDABLE               :: BUFFER_SIZE_RECV
       PROCEDURE, NON_OVERRIDABLE               :: BUFFER_SEND
       PROCEDURE, NON_OVERRIDABLE               :: BUFFER_RECV
+      PROCEDURE, NON_OVERRIDABLE               :: SEND            => SENSOR_COMM_SEND
+      PROCEDURE, NON_OVERRIDABLE               :: SEND_DEALLOCATE => SENSOR_COMM_SEND_DEALLOCATE
+      PROCEDURE, NON_OVERRIDABLE               :: RECV_ALLOCATE   => SENSOR_COMM_RECV_ALLOCATE
 
       GENERIC :: INTERP_HOR_FROM_MASSPOINT => INTERP_HOR_FROM_MASSPOINT_0D, INTERP_HOR_FROM_MASSPOINT_1D
       GENERIC :: INTERP_HOR_FROM_UPOINT    => INTERP_HOR_FROM_UPOINT_0D,    INTERP_HOR_FROM_UPOINT_1D
@@ -1157,23 +1160,168 @@ MODULE MODD_SENSOR
     END SUBROUTINE BUFFER_SEND
 
 
-      ! ################################################
-      SUBROUTINE BUFFER_RECV( TPSENSOR, PBUFFER, KFROM )
-      ! ################################################
+    ! ################################################
+    SUBROUTINE BUFFER_RECV( TPSENSOR, PBUFFER, KFROM )
+    ! ################################################
 
-        USE MODD_MPIF,      ONLY: MPI_RECV, MPI_STATUS_IGNORE
-        USE MODD_PRECISION, ONLY: MNHREAL_MPI
-        USE MODD_VAR_LL,    ONLY: NMNH_COMM_WORLD
+      USE MODD_MPIF,      ONLY: MPI_RECV, MPI_STATUS_IGNORE
+      USE MODD_PRECISION, ONLY: MNHREAL_MPI
+      USE MODD_VAR_LL,    ONLY: NMNH_COMM_WORLD
+
+      CLASS(TSENSOR),     INTENT(IN)  :: TPSENSOR
+      REAL, DIMENSION(:), INTENT(OUT) :: PBUFFER
+      INTEGER,            INTENT(IN)  :: KFROM    ! Process from which to receive buffer
+
+      INTEGER :: IERR
+
+      ! Receive packed data
+      CALL MPI_RECV( PBUFFER, SIZE( PBUFFER ), MNHREAL_MPI, KFROM-1, NTAG_PACK, NMNH_COMM_WORLD, MPI_STATUS_IGNORE, IERR )
+
+    END SUBROUTINE BUFFER_RECV
+
+    ! ##################################################################
+    SUBROUTINE SENSOR_COMM_SEND( TPSENSOR, KTO, OSEND_SIZE_TO_RECEIVER )
+    ! ##################################################################
+
+      USE MODD_IO, ONLY: ISP
+
+      USE MODE_MSG
+
+      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
+
+      CHARACTER(LEN=10) :: YFROM, YTO
+      INTEGER           :: IPACKSIZE
+      INTEGER           :: IPOS
+      LOGICAL           :: GSEND_SIZE_TO_RECEIVER
+      REAL,    DIMENSION(:), ALLOCATABLE :: ZPACK ! buffer to store raw data of the sensor
+
+      WRITE( YFROM, '( i10 )' ) ISP
+      WRITE( YTO,   '( i10 )' ) KTO
+      CALL PRINT_MSG( NVERB_DEBUG, 'GEN', 'Sensor_comm_send', &
+                      'send sensor ' // TRIM(TPSENSOR%CNAME) // ': ' // TRIM(YFROM) // '->' // TRIM(YTO), OLOCAL = .TRUE. )
+
+      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 ( GSEND_SIZE_TO_RECEIVER ) CALL TPSENSOR%BUFFER_SIZE_SEND( TPSENSOR%NSTORE_CUR, IPACKSIZE, KTO )
+
+      ALLOCATE( ZPACK(IPACKSIZE) )
+
+      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. )
+
+      CALL TPSENSOR%BUFFER_SEND( ZPACK, KTO )
+
+      DEALLOCATE( ZPACK )
+
+    END SUBROUTINE SENSOR_COMM_SEND
+
+    ! #############################################################################
+    SUBROUTINE SENSOR_COMM_SEND_DEALLOCATE( TPSENSOR, KTO, OSEND_SIZE_TO_RECEIVER )
+    ! #############################################################################
+
+      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
+
+      CALL SENSOR_COMM_SEND( TPSENSOR, KTO, OSEND_SIZE_TO_RECEIVER )
+
+      ! Deallocate sensor data once not needed anymore
+      IF ( TPSENSOR%NSTORE_MAX >= 0 ) CALL TPSENSOR%DATA_ARRAYS_DEALLOCATE( )
+
+    END SUBROUTINE SENSOR_COMM_SEND_DEALLOCATE
+
+    ! ####################################################################################################
+    SUBROUTINE SENSOR_COMM_RECV_ALLOCATE( TPSENSOR, KFROM, KSTORE_CUR, KSTORE_MAX, ORECV_SIZE_FROM_OWNER )
+    ! ####################################################################################################
+
+      USE MODD_IO, ONLY: ISP
+
+      USE MODE_MSG
+
+      CLASS(TSENSOR),           INTENT(INOUT) :: TPSENSOR
+      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
+
+      CHARACTER(LEN=10) :: YFROM, YTO
+      INTEGER           :: IPACKSIZE
+      INTEGER           :: IPOS
+      INTEGER           :: ISTORE_CUR
+      INTEGER           :: ISTORE_MAX
+      LOGICAL           :: GRECV_SIZE_FROM_OWNER
+      REAL,    DIMENSION(:), ALLOCATABLE :: ZPACK ! buffer to store raw data of the sensor
+
+      WRITE( YFROM, '( i10 )' ) KFROM
+      WRITE( YTO,   '( i10 )' ) ISP
+      CALL PRINT_MSG( NVERB_DEBUG, 'GEN', 'Sensor_comm_recv_allocate', &
+                      'receive sensor (name not yet known): ' // TRIM(YFROM) // '->' // TRIM(YTO), OLOCAL = .TRUE. )
+
+      IF ( PRESENT( ORECV_SIZE_FROM_OWNER ) ) THEN
+        GRECV_SIZE_FROM_OWNER = ORECV_SIZE_FROM_OWNER
+      ELSE
+        GRECV_SIZE_FROM_OWNER = .FALSE.
+       END IF
+
+      IF ( PRESENT( KSTORE_CUR ) ) THEN
+        IF ( GRECV_SIZE_FROM_OWNER )                                                                       &
+          CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_recv_allocate',                                 &
+                          'kstore_cur may not be provided if size is received from owner', OLOCAL = .TRUE. )
+        ISTORE_CUR = KSTORE_CUR
+      ELSE
+        IF ( .NOT. GRECV_SIZE_FROM_OWNER )                                                                  &
+          CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_recv_allocate',                                  &
+                          'kstore_cur must be provided if size is not received from owner', OLOCAL = .TRUE. )
+        ! istore_cur will be received from owner
+        ISTORE_CUR = 0
+      END IF
+
+      IF ( PRESENT( KSTORE_MAX ) ) THEN
+        IF ( GRECV_SIZE_FROM_OWNER )                                                                       &
+          CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_recv_allocate',                                 &
+                          'kstore_max may not be provided if size is received from owner', OLOCAL = .TRUE. )
+        ISTORE_MAX = KSTORE_MAX
+      ELSE
+        IF ( .NOT. GRECV_SIZE_FROM_OWNER )                                                                  &
+          CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_recv_allocate',                                  &
+                          'kstore_max must be provided if size is not received from owner', OLOCAL = .TRUE. )
+
+        ! istore_max will be received from owner
+        ISTORE_MAX = 0
+      END IF
+
+      IF ( GRECV_SIZE_FROM_OWNER ) THEN
+        CALL TPSENSOR%BUFFER_SIZE_RECV( ISTORE_CUR, ISTORE_MAX, IPACKSIZE, KFROM )
+      ELSE
+        IPACKSIZE = TPSENSOR%BUFFER_SIZE_COMPUTE( ISTORE_CUR )
+      END IF
+
+      ! 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 )
 
-        CLASS(TSENSOR),     INTENT(IN)  :: TPSENSOR
-        REAL, DIMENSION(:), INTENT(OUT) :: PBUFFER
-        INTEGER,            INTENT(IN)  :: KFROM    ! Process from which to receive buffer
+      CALL TPSENSOR%BUFFER_RECV( ZPACK, KFROM )
 
-        INTEGER :: IERR
+      IPOS = 1
+      CALL TPSENSOR%BUFFER_UNPACK( ZPACK, IPOS, ISTORE_CUR )
 
-        ! Receive packed data
-        CALL MPI_RECV( PBUFFER, SIZE( PBUFFER ), MNHREAL_MPI, KFROM-1, NTAG_PACK, NMNH_COMM_WORLD, MPI_STATUS_IGNORE, IERR )
+      IF ( IPOS-1 /= IPACKSIZE ) &
+        CALL PRINT_MSG( NVERB_ERROR, 'GEN', 'Sensor_comm_recv_allocate', 'IPOS-1 /= IPACKSIZE', OLOCAL = .TRUE. )
 
-      END SUBROUTINE BUFFER_RECV
+    END SUBROUTINE SENSOR_COMM_RECV_ALLOCATE
 
 END MODULE MODD_SENSOR
diff --git a/src/MNH/write_aircraft_balloon.f90 b/src/MNH/write_aircraft_balloon.f90
index 3ad7fafc5..2e6fc331d 100644
--- a/src/MNH/write_aircraft_balloon.f90
+++ b/src/MNH/write_aircraft_balloon.f90
@@ -85,8 +85,6 @@ SUBROUTINE WRITE_AIRCRAFT_BALLOON(TPDIAFILE)
 USE MODD_AIRCRAFT_BALLOON
 USE MODD_IO,               ONLY: ISP, TFILEDATA
 !
-USE MODE_AIRCRAFT_BALLOON, ONLY: FLYER_RECV_AND_ALLOCATE, FLYER_SEND
-!
 IMPLICIT NONE
 !
 !
@@ -107,7 +105,7 @@ DO JI = 1, NBALLOONS
 
   ! Send data from owner to writer if necessary
   IF ( ISP == NRANKCUR_BALLOON(JI) .AND. NRANKCUR_BALLOON(JI) /= TPDIAFILE%NMASTER_RANK ) THEN
-    CALL FLYER_SEND( TBALLOONS(JI)%TBALLOON, TPDIAFILE%NMASTER_RANK )
+    CALL TBALLOONS(JI)%TBALLOON%SEND( KTO = TPDIAFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .TRUE. )
   END IF
 
   IF ( ISP == TPDIAFILE%NMASTER_RANK ) THEN
@@ -116,7 +114,7 @@ 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 FLYER_RECV_AND_ALLOCATE( TBALLOONS(JI)%TBALLOON, NRANKCUR_BALLOON(JI) )
+      CALL TBALLOONS(JI)%TBALLOON%RECV_ALLOCATE( KFROM = NRANKCUR_BALLOON(JI), ORECV_SIZE_FROM_OWNER = .TRUE. )
     END IF
 
     ! Write data
@@ -133,7 +131,7 @@ 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 FLYER_SEND( TAIRCRAFTS(JI)%TAIRCRAFT, TPDIAFILE%NMASTER_RANK )
+    CALL TAIRCRAFTS(JI)%TAIRCRAFT%SEND( KTO = TPDIAFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .TRUE. )
   END IF
 
   IF ( ISP == TPDIAFILE%NMASTER_RANK ) THEN
@@ -142,7 +140,7 @@ 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 FLYER_RECV_AND_ALLOCATE( TAIRCRAFTS(JI)%TAIRCRAFT, NRANKCUR_AIRCRAFT(JI) )
+      CALL TAIRCRAFTS(JI)%TAIRCRAFT%RECV_ALLOCATE( KFROM = NRANKCUR_AIRCRAFT(JI), ORECV_SIZE_FROM_OWNER = .TRUE. )
     END IF
 
     ! Write data
diff --git a/src/MNH/write_balloonn.f90 b/src/MNH/write_balloonn.f90
index 7604e0de0..4c0e7d02b 100644
--- a/src/MNH/write_balloonn.f90
+++ b/src/MNH/write_balloonn.f90
@@ -60,7 +60,6 @@ CONTAINS
 USE MODD_AIRCRAFT_BALLOON, only: NBALLOONS, NRANKCUR_BALLOON, TBALLOONS
 USE MODD_IO,               ONLY: GSMONOPROC, ISP, TFILEDATA
 !
-USE MODE_AIRCRAFT_BALLOON,     ONLY: FLYER_RECV_AND_ALLOCATE, FLYER_SEND
 USE MODE_MODELN_HANDLER,       ONLY: GET_CURRENT_MODEL_INDEX
 !
 IMPLICIT NONE
@@ -88,14 +87,14 @@ 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 FLYER_SEND( TBALLOONS(JI)%TBALLOON, TPFILE%NMASTER_RANK )
+    CALL TBALLOONS(JI)%TBALLOON%SEND( KTO = TPFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .TRUE. )
   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 FLYER_RECV_AND_ALLOCATE( TBALLOONS(JI)%TBALLOON, NRANKCUR_BALLOON(JI) )
+      CALL TBALLOONS(JI)%TBALLOON%RECV_ALLOCATE( KFROM = NRANKCUR_BALLOON(JI), ORECV_SIZE_FROM_OWNER = .TRUE. )
     END IF
 
     ! Write data (only if flyer is on the current model)
diff --git a/src/MNH/write_profilern.f90 b/src/MNH/write_profilern.f90
index 46fe8d327..5cd2e0c04 100644
--- a/src/MNH/write_profilern.f90
+++ b/src/MNH/write_profilern.f90
@@ -74,15 +74,12 @@ INTEGER :: IERR
 INTEGER :: JP, JS
 INTEGER :: IDX
 INTEGER :: INUMPROF  ! Total number of profilers (for the current model)
-INTEGER :: IPACKSIZE ! Size of the ZPACK buffer
-INTEGER :: IPOS      ! Position in the ZPACK buffer
 INTEGER :: ISTORE
 INTEGER, DIMENSION(:), ALLOCATABLE :: INPROFPRC    ! Array to store the number of profilers per process (for the current model)
 INTEGER, DIMENSION(:), ALLOCATABLE :: IPROFIDS     ! Intermediate array for MPI communication
 INTEGER, DIMENSION(:), ALLOCATABLE :: IPROFPRCRANK ! Array to store the ranks of the processes where the profilers are
 INTEGER, DIMENSION(:), ALLOCATABLE :: IDS          ! Array to store the profiler 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 profiler (used for MPI communication)
 TYPE(TPROFILERDATA) :: TZPROFILER
 !
 !----------------------------------------------------------------------------
@@ -127,13 +124,6 @@ ISTORE = SIZE( TPROFILERS_TIME%TPDATES )
 
 CALL TZPROFILER%DATA_ARRAYS_ALLOCATE( ISTORE )
 
-!Determine the size of the ZPACK buffer used to transfer profiler data in 1 MPI communication
-IF ( ISNPROC > 1 ) THEN
-  IPACKSIZE = TZPROFILER%BUFFER_SIZE_COMPUTE( ISTORE )
-
-  ALLOCATE( ZPACK(IPACKSIZE) )
-END IF
-
 IDX = 1
 
 PROFILER: DO JS = 1, INUMPROF
@@ -147,24 +137,12 @@ PROFILER: DO JS = 1, INUMPROF
     !The profiler data is not on the writer process
     IF ( ISP == IPROFPRCRANK(JS) ) THEN
       ! This process has the data and needs to send it to the writer process
-      IPOS = 1
-      CALL TPROFILERS(IDX)%BUFFER_PACK( ZPACK, IPOS, ISTORE )
-
-      IF ( IPOS-1 /= IPACKSIZE ) &
-        call Print_msg( NVERB_ERROR, 'IO', 'WRITE_PROFILER_n', 'IPOS-1 /= IPACKSIZE (sender side)', OLOCAL = .TRUE. )
-
-      CALL TPROFILERS(IDX)%BUFFER_SEND( ZPACK, TPDIAFILE%NMASTER_RANK )
+      CALL TPROFILERS(IDX)%SEND_DEALLOCATE( KTO = TPDIAFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .FALSE. )
 
       IDX = IDX + 1
     ELSE IF ( ISP == TPDIAFILE%NMASTER_RANK ) THEN
       ! This process is the writer and will receive the profiler data from its owner
-      CALL TZPROFILER%BUFFER_RECV( ZPACK, IPROFPRCRANK(JS) )
-
-      IPOS = 1
-      CALL TZPROFILER%BUFFER_UNPACK( ZPACK, IPOS, ISTORE )
-
-      IF ( IPOS-1 /= IPACKSIZE ) &
-        call Print_msg( NVERB_ERROR, 'IO', 'WRITE_PROFILER_n', 'IPOS-1 /= IPACKSIZE (receiver side)', OLOCAL = .TRUE. )
+      CALL TZPROFILER%RECV_ALLOCATE( KFROM = IPROFPRCRANK(JS), KSTORE_CUR = ISTORE, KSTORE_MAX = ISTORE )
     END IF
   END IF
 
@@ -172,6 +150,8 @@ PROFILER: DO JS = 1, INUMPROF
 
 END DO PROFILER
 
+! Deallocate arrays (if still allocated)
+IF ( TZPROFILER%NSTORE_MAX >= 0 ) CALL TZPROFILER%DATA_ARRAYS_DEALLOCATE( )
 
 END SUBROUTINE WRITE_PROFILER_n
 
diff --git a/src/MNH/write_stationn.f90 b/src/MNH/write_stationn.f90
index 3279e3175..ecdc90dfd 100644
--- a/src/MNH/write_stationn.f90
+++ b/src/MNH/write_stationn.f90
@@ -67,15 +67,12 @@ 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
 !
 !----------------------------------------------------------------------------
@@ -119,13 +116,6 @@ ISTORE = SIZE( TSTATIONS_TIME%TPDATES )
 
 CALL TZSTATION%DATA_ARRAYS_ALLOCATE( ISTORE )
 
-!Determine the size of the ZPACK buffer used to transfer station data in 1 MPI communication
-IF ( ISNPROC > 1 ) THEN
-  IPACKSIZE = TZSTATION%BUFFER_SIZE_COMPUTE( ISTORE )
-
-  ALLOCATE( ZPACK(IPACKSIZE) )
-END IF
-
 IDX = 1
 
 STATION: DO JS = 1, INUMSTAT
@@ -139,24 +129,13 @@ STATION: DO JS = 1, INUMSTAT
     !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
-      CALL TSTATIONS(IDX)%BUFFER_PACK( ZPACK, IPOS, ISTORE )
-
-      IF ( IPOS-1 /= IPACKSIZE ) &
-        call Print_msg( NVERB_ERROR, 'IO', 'WRITE_STATION_n', 'IPOS-1 /= IPACKSIZE (sender side)', OLOCAL = .TRUE. )
-
-      CALL TSTATIONS(IDX)%BUFFER_SEND( ZPACK, TPDIAFILE%NMASTER_RANK )
+      CALL TSTATIONS(IDX)%SEND_DEALLOCATE( KTO = TPDIAFILE%NMASTER_RANK, OSEND_SIZE_TO_RECEIVER = .FALSE. )
 
       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 TZSTATION%BUFFER_RECV( ZPACK, ISTATPRCRANK(JS) )
-
-      IPOS = 1
-      CALL TZSTATION%BUFFER_UNPACK( ZPACK, IPOS, ISTORE )
-
-      IF ( IPOS-1 /= IPACKSIZE ) &
-        call Print_msg( NVERB_WARNING, 'IO', 'WRITE_STATION_n', 'IPOS-1 /= IPACKSIZE (receiver side)', OLOCAL = .TRUE. )
+      ! Remark: allocation is already done and will be skipped in RECV_ALLOCATE
+      CALL TZSTATION%RECV_ALLOCATE( KFROM = ISTATPRCRANK(JS), KSTORE_CUR = ISTORE, KSTORE_MAX = ISTORE )
     END IF
   END IF
 
@@ -164,6 +143,9 @@ STATION: DO JS = 1, INUMSTAT
 
 END DO STATION
 
+! Deallocate arrays (if still allocated)
+IF ( TZSTATION%NSTORE_MAX >= 0 ) CALL TZSTATION%DATA_ARRAYS_DEALLOCATE( )
+
 END SUBROUTINE WRITE_STATION_n
 
 ! ##################################################
-- 
GitLab