From bbaf5704ac941da6c56e9dcceb130eadf4e83398 Mon Sep 17 00:00:00 2001
From: Philippe WAUTELET <philippe.wautelet@aero.obs-mip.fr>
Date: Fri, 2 Dec 2022 10:39:07 +0100
Subject: [PATCH] Philippe 02/12/2022: aircraft_balloon_evol: first cleaning +
 better organisation of the source + correction of several bugs

---
 src/MNH/aircraft_balloon_evol.f90 | 2928 ++++++++++++-----------------
 1 file changed, 1216 insertions(+), 1712 deletions(-)

diff --git a/src/MNH/aircraft_balloon_evol.f90 b/src/MNH/aircraft_balloon_evol.f90
index 5b52ea22f..a246e4391 100644
--- a/src/MNH/aircraft_balloon_evol.f90
+++ b/src/MNH/aircraft_balloon_evol.f90
@@ -102,7 +102,7 @@ CONTAINS
 !          ------------
 !
 USE MODD_AIRCRAFT_BALLOON
-USE MODD_CONF
+USE MODD_CONF,             ONLY: LCARTESIAN
 USE MODD_CST
 USE MODD_DIAG_IN_RUN
 USE MODD_GRID
@@ -110,31 +110,8 @@ USE MODD_GRID_n
 USE MODD_IO,               ONLY: ISP
 USE MODD_LUNIT_n,          ONLY: TLUOUT
 USE MODD_NESTING
-USE MODD_NSV,              ONLY : NSV_LIMA_NI,NSV_LIMA_NR,NSV_LIMA_NC
 USE MODD_PARAMETERS
-USE MODD_PARAM_LIMA,       ONLY: XALPHAR_L=>XALPHAR,XNUR_L=>XNUR,XALPHAS_L=>XALPHAS,XNUS_L=>XNUS,&
-                                 XALPHAG_L=>XALPHAG,XNUG_L=>XNUG, XALPHAI_L=>XALPHAI,XNUI_L=>XNUI,&
-                                 XRTMIN_L=>XRTMIN,XALPHAC_L=>XALPHAC,XNUC_L=>XNUC
-USE MODD_PARAM_LIMA_COLD,  ONLY: XDI_L=>XDI,XLBEXI_L=>XLBEXI,XLBI_L=>XLBI,XAI_L=>XAI,XBI_L=>XBI,XC_I_L=>XC_I,&
-                                 XLBEXS_L=>XLBEXS,XLBS_L=>XLBS,XCCS_L=>XCCS,&
-                                 XAS_L=>XAS,XBS_L=>XBS,XCXS_L=>XCXS
-USE MODD_PARAM_LIMA_MIXED, ONLY: XDG_L=>XDG,XLBEXG_L=>XLBEXG,XLBG_L=>XLBG,XCCG_L=>XCCG,&
-                                 XAG_L=>XAG,XBG_L=>XBG,XCXG_L=>XCXG,XCG_L=>XCG
-USE MODD_PARAM_LIMA_WARM,  ONLY: XLBEXR_L=>XLBEXR,XLBR_L=>XLBR,XBR_L=>XBR,XAR_L=>XAR,&
-                                 XBC_L=>XBC,XAC_L=>XAC
 USE MODD_PARAM_n,          ONLY: CCLOUD, CSURF
-USE MODD_RAIN_ICE_DESCR,   ONLY: XALPHAR_I=>XALPHAR,XNUR_I=>XNUR,XLBEXR_I=>XLBEXR,&
-                                 XLBR_I=>XLBR,XCCR_I=>XCCR,XBR_I=>XBR,XAR_I=>XAR,&
-                                 XALPHAC_I=>XALPHAC,XNUC_I=>XNUC,&
-                                 XLBC_I=>XLBC,XBC_I=>XBC,XAC_I=>XAC,&
-                                 XALPHAC2_I=>XALPHAC2,XNUC2_I=>XNUC2,&
-                                 XALPHAS_I=>XALPHAS,XNUS_I=>XNUS,XLBEXS_I=>XLBEXS,&
-                                 XLBS_I=>XLBS,XCCS_I=>XCCS,XAS_I=>XAS,XBS_I=>XBS,XCXS_I=>XCXS,&
-                                 XALPHAG_I=>XALPHAG,XNUG_I=>XNUG,XDG_I=>XDG,XLBEXG_I=>XLBEXG,&
-                                 XLBG_I=>XLBG,XCCG_I=>XCCG,XAG_I=>XAG,XBG_I=>XBG,XCXG_I=>XCXG,XCG_I=>XCG,&
-                                 XALPHAI_I=>XALPHAI,XNUI_I=>XNUI,XDI_I=>XDI,XLBEXI_I=>XLBEXI,&
-                                 XLBI_I=>XLBI,XAI_I=>XAI,XBI_I=>XBI,XC_I_I=>XC_I,&
-                                 XRTMIN_I=>XRTMIN,XCONC_LAND,XCONC_SEA
 USE MODD_REF_n,            ONLY: XRHODREF
 USE MODD_TIME,             only: TDTSEG
 USE MODD_TIME_n,           only: tdtcur
@@ -145,11 +122,6 @@ USE MODE_FGAU,             ONLY: GAULAG
 USE MODE_FSCATTER,         ONLY: QEPSW,QEPSI,BHMIE,MOMG,MG
 USE MODE_GRIDPROJ
 USE MODE_ll
-USE MODE_POSITION_TOOLS,   ONLY: FIND_PROCESS_AND_MODEL_FROM_XY_POS
-USE MODE_STATPROF_TOOLS,   ONLY: STATPROF_INSTANT
-!
-USE MODI_GAMMA,            ONLY: GAMMA
-USE MODI_WATER_SUM
 !
 IMPLICIT NONE
 !
@@ -185,13 +157,7 @@ REAL, DIMENSION(:,:), OPTIONAL, INTENT(IN) :: PSEA
 INTEGER :: IMI        ! model index
 REAL    :: ZTHIS_PROC ! 1 if balloon is currently treated by this proc., else 0
 !
-INTEGER :: IIB        ! current process domain sizes
-INTEGER :: IJB
-INTEGER :: IIE
-INTEGER :: IJE
-INTEGER :: IIU
-INTEGER :: IJU
-INTEGER :: IKB
+INTEGER :: IKB        ! vertical domain sizes
 INTEGER :: IKE
 INTEGER :: IKU
 !
@@ -202,8 +168,6 @@ REAL, DIMENSION(2,2,SIZE(PZ,3))     :: ZZU    ! U points z coordinates
 REAL, DIMENSION(2,2,SIZE(PZ,3))     :: ZZV    ! V points z coordinates
 REAL, DIMENSION(2,2,SIZE(PZ,3))     :: ZWM    ! mass point wind
 !
-REAL, DIMENSION(2,2,SIZE(PTH,3))    :: ZTHV   ! virtual potential temperature
-REAL, DIMENSION(2,2,SIZE(PTH,3))    :: ZTV    ! virtual temperature
 REAL, DIMENSION(2,2,SIZE(PTH,3))    :: ZTEMP  ! temperature
 REAL, DIMENSION(2,2,SIZE(PTH,3))    :: ZEXN   ! Exner function
 REAL, DIMENSION(2,2,SIZE(PTH,3))    :: ZRHO   ! air density
@@ -212,7 +176,6 @@ REAL, DIMENSION(2,2,SIZE(PTH,3))    :: ZTHW_FLUX  !
 REAL, DIMENSION(2,2,SIZE(PTH,3))    :: ZRCW_FLUX  !
 REAL, DIMENSION(2,2,SIZE(PSV,3),SIZE(PSV,4))    :: ZSVW_FLUX
 !
-REAL    :: ZTDIST   ! time until launch (sec)
 LOGICAL :: GLAUNCH  ! launch/takeoff is effective at this time-step (if true)
 LOGICAL :: GSTORE   ! storage occurs at this time step
 !
@@ -262,43 +225,12 @@ REAL    :: ZV_BAL   ! horizontal wind speed at balloon location (along y)
 REAL    :: ZW_BAL   ! vertical   wind speed at balloon location (along z)
 REAL    :: ZMAP     ! map factor at balloon location
 REAL    :: ZGAM     ! rotation between meso-nh base and spherical lat-lon base.
-INTEGER :: IL       ! flight segment index
-REAL    :: ZSEG_FRAC! fraction of flight in the current segment
 REAL    :: ZRO_BAL  ! air density at balloon location
 !
 INTEGER :: IINFO_ll ! return code
-INTEGER :: ILUOUT   ! logical unit
-INTEGER :: IRESP    ! return code
-!
-! specific to cloud radar
-REAL, DIMENSION(SIZE(PR,3))    :: ZTEMPZ! vertical profile of temperature
-REAL, DIMENSION(SIZE(PR,3))    :: ZRHODREFZ ! vertical profile of dry air density of the reference state
-REAL, DIMENSION(SIZE(PR,3))    :: ZCIT     ! pristine ice concentration
-REAL, DIMENSION(SIZE(PR,3))    :: ZCCI,ZCCR,ZCCC     ! ICE,RAIN CLOUD concentration (LIMA)
-REAL, DIMENSION(SIZE(PR,1),SIZE(PR,2),SIZE(PR,3))    :: ZR
-REAL, DIMENSION(SIZE(PR,3),SIZE(PR,4)+1) :: ZRZ  ! vertical profile of hydrometeor mixing ratios
-REAL                           :: ZA,ZB,ZCC,ZCX,ZALPHA,ZNU,ZLB,ZLBEX,ZRHOHYD   ! generic microphysical parameters
-INTEGER                        :: JJ    ! loop counter for quadrature
-COMPLEX                        :: QMW,QMI,QM,QB,QEPSIW,QEPSWI   ! dielectric parameter
-REAL                           :: ZAETOT,ZAETMP,ZREFLOC,ZQSCA,ZQBACK,ZQEXT ! temporary scattering parameters
-REAL,DIMENSION(:),ALLOCATABLE  :: ZAELOC,ZZMZ ! temporary arrays
-INTEGER                        :: JPTS_GAULAG=7 ! number of points for Gauss-Laguerre quadrature
-REAL                           :: ZLBDA   ! slope distribution parameter
-REAL                           :: ZFRAC_ICE  ! ice water fraction
-REAL                           :: ZDELTA_EQUIV ! mass-equivalent Gauss-Laguerre point
-REAL                           :: ZFW ! liquid fraction
-REAL                           :: ZFPW ! weight for mixed-phase reflectivity
-REAL,DIMENSION(:),ALLOCATABLE  :: ZX,ZW ! Gauss-Laguerre points and weights
-REAL,DIMENSION(:),ALLOCATABLE  :: ZRTMIN ! local values for XRTMIN
-LOGICAL                        :: GCALC
 !
-INTEGER :: IRANK
 INTEGER :: IMODEL
-INTEGER :: IMODEL_OLD
-REAL    :: ZX_OLD, ZY_OLD
-REAL    :: ZDELTATIME
 REAL    :: ZTSTEP
-REAL    :: ZDIVTMP
 
 !----------------------------------------------------------------------------
 IKU = SIZE(PZ,3)
@@ -307,710 +239,56 @@ CALL GET_MODEL_NUMBER_ll(IMI)
 
 SELECT TYPE ( TPFLYER )
   CLASS IS ( TAIRCRAFTDATA)
-
     !Do the positioning only if model 1 (data will be available to others after)
-    MODEL1: IF ( IMI == 1 ) THEN
+    MODEL1AIR: IF ( IMI == 1 ) THEN
       !Do we have to store aircraft data?
-      CALL  STATPROF_INSTANT( TPFLYER%TFLYER_TIME, ISTORE )
-      IF ( ISTORE < 1 ) THEN
-        !No profiler storage at this time step
-        TPFLYER%LSTORE = .FALSE.
-        RETURN
-      ELSE
-        TPFLYER%LSTORE = .TRUE.
-      END IF
+      CALL FLYER_CHECK_STORESTEP( TPFLYER )
 
       ! Is the aircraft in flight ?
       IF ( TDTCUR >= TPFLYER%TLAUNCH .AND. TDTCUR <= TPFLYER%TLAND ) THEN
         TPFLYER%LFLY = .TRUE.
 
-        ! Find the flight segment
-        ZTDIST = TDTCUR - TPFLYER%TLAUNCH
-        IL = TPFLYER%NPOSCUR
-        DO WHILE ( ZTDIST > TPFLYER%XPOSTIME(IL+1) )
-          IL = IL + 1
-          IF ( IL > TPFLYER%NPOS-1 ) THEN
-            !Security (should not happen)
-            IL = TPFLYER%NPOS-1
-            EXIT
-          END IF
-        END DO
-        TPFLYER%NPOSCUR = IL
-
-        ! Compute the current position
-        ZSEG_FRAC = ( ZTDIST - TPFLYER%XPOSTIME(IL) ) / ( TPFLYER%XPOSTIME(IL+1) - TPFLYER%XPOSTIME(IL) )
-
-        TPFLYER%XX_CUR = (1.-ZSEG_FRAC) * TPFLYER%XPOSX(IL  ) &
-                       +     ZSEG_FRAC  * TPFLYER%XPOSX(IL+1)
-        TPFLYER%XY_CUR = (1.-ZSEG_FRAC) * TPFLYER%XPOSY(IL  ) &
-                       +     ZSEG_FRAC  * TPFLYER%XPOSY(IL+1)
-        IF (TPFLYER%LALTDEF) THEN
-          TPFLYER%XP_CUR = (1.-ZSEG_FRAC) * TPFLYER%XPOSP(IL  ) &
-                         +     ZSEG_FRAC  * TPFLYER%XPOSP(IL+1)
-        ELSE
-          TPFLYER%XZ_CUR = (1.-ZSEG_FRAC) * TPFLYER%XPOSZ(IL ) &
-                         +     ZSEG_FRAC  * TPFLYER%XPOSZ(IL +1 )
-        END IF
+        ! Compute current position
+        CALL AIRCRAFT_COMPUTE_POSITION( TDTCUR, TPFLYER )
 
         ! Get rank of the process where the aircraft is and the model number
-        IF ( TPFLYER%CMODEL == 'FIX' ) THEN
-          IMODEL = TPFLYER%NMODEL
-        ELSE
-          IMODEL = 0
-        END IF
-        CALL FIND_PROCESS_AND_MODEL_FROM_XY_POS( TPFLYER%XX_CUR, TPFLYER%XY_CUR, IRANK, IMODEL )
-        IF ( IRANK < 1 ) THEN
-          TPFLYER%NMODEL = 1 !Set to 1 because it is always a valid model (to prevent crash if NDAD(TPFLYER%NMODEL) )
-          TPFLYER%LCRASH = .TRUE.
-          TPFLYER%NCRASH = NCRASH_OUT_HORIZ
-          TPFLYER%LFLY   = .FALSE.
-        ELSE
-          TPFLYER%NMODEL = IMODEL
-          TPFLYER%LCRASH = .FALSE.
-          TPFLYER%NCRASH = NCRASH_NO
-          TPFLYER%NRANK_CUR = IRANK
-        END IF
+        CALL FLYER_GET_RANK_MODEL_ISCRASHED( TPFLYER )
       ELSE
         TPFLYER%LFLY = .FALSE.
-
       END IF
-    END IF MODEL1
+    END IF MODEL1AIR
 
-    IF ( IMI == TPFLYER%NMODEL .AND. TPFLYER%LFLY ) THEN
+    ! For aircrafts, data has only to be computed at store moments
+    IF ( IMI == TPFLYER%NMODEL .AND. TPFLYER%LFLY .AND. TPFLYER%LSTORE ) THEN
+      ISTORE = TPFLYER%TFLYER_TIME%N_CUR
       ! Check if it is the right moment to store data
-      IF ( TPFLYER%LSTORE ) THEN
-        ISTORE = TPFLYER%TFLYER_TIME%N_CUR
-        IF ( ABS( TDTCUR - TPFLYER%TFLYER_TIME%TPDATES(ISTORE) ) < 1e-10 ) THEN
-
-          ISOWNER: IF ( TPFLYER%NRANK_CUR == ISP ) THEN
-            ZTHIS_PROC = 1.
-            !
-            !*      2.   PRELIMINARIES-2
-            !            -------------
-            !
-            !*      2.1  Indices
-            !            -------
-            !
-            CALL GET_INDICE_ll (IIB,IJB,IIE,IJE)
-
-            IKB =   1   + JPVEXT
-            IKE = SIZE(PZ,3) - JPVEXT
-            !
-            !
-            !*      2.2  Interpolations of model variables to mass points
-            !            ------------------------------------------------
-            !
-            IIU=SIZE(XXHAT)
-            IJU=SIZE(XYHAT)
-            ! X position
-            II_U = COUNT( XXHAT (:) <= TPFLYER%XX_CUR )
-            II_M = COUNT( XXHATM(:) <= TPFLYER%XX_CUR )
-
-            ! Y position
-            IJ_V=COUNT( XYHAT (:)<=TPFLYER%XY_CUR )
-            IJ_M=COUNT( XYHATM(:)<=TPFLYER%XY_CUR )
-            !
-            !*      4.5  Interpolations of model variables to mass points
-            !            ------------------------------------------------
-            !
-            ZZM(:,:,1:IKU-1)=0.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,1:IKU-1)+0.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,2:IKU  )
-            ZZM(:,:,  IKU  )=1.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,  IKU-1)-0.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,  IKU-2)
-
-        IDU = II_U - II_M
-        ZZU(:,:,1:IKU-1)=0.25*PZ(IDU+II_M-1:IDU+II_M,  IJ_M  :IJ_M+1,1:IKU-1)+0.25*PZ(IDU+II_M-1:IDU+II_M  ,IJ_M  :IJ_M+1,2:IKU  ) &
-                      +0.25*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,1:IKU-1)+0.25*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,2:IKU  )
-        ZZU(:,:,  IKU  )=0.75*PZ(IDU+II_M-1:IDU+II_M  ,IJ_M  :IJ_M+1,  IKU-1)-0.25*PZ(IDU+II_M-1:IDU+II_M  ,IJ_M  :IJ_M+1,  IKU-2) &
-                      +0.75*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,  IKU-1)-0.25*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,  IKU-2)
-
-        IDV = IJ_V - IJ_M
-        ZZV(:,:,1:IKU-1)=0.25*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,1:IKU-1)+0.25*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,2:IKU  ) &
-                      +0.25*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,1:IKU-1)+0.25*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,2:IKU  )
-        ZZV(:,:,  IKU  )=0.75*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,  IKU-1)-0.25*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,  IKU-2) &
-                      +0.75*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,  IKU-1)-0.25*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,  IKU-2)
-
-            ZWM(:,:,1:IKU-1)=0.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,1:IKU-1)+0.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,2:IKU  )
-            ZWM(:,:,  IKU  )=1.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,  IKU-1)-0.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,  IKU-2)
-            !
-            !----------------------------------------------------------------------------
-            !
-            !*      5.   BALLOON/AIRCRAFT VERTICAL POSITION
-            !            ----------------------------------
-            !
-            !
-            !*      5.1  Density
-            !            -------
-            !
-            ZEXN(:,:,:    ) = (PP(II_M:II_M+1,IJ_M:IJ_M+1,:)/XP00)**(XRD/XCPD)
-            DO JK=IKB-1,1,-1
-              ZEXN(:,:,JK) = 1.5 * ZEXN(:,:,JK+1) - 0.5 * ZEXN(:,:,JK+2)
-            END DO
-            DO JK=IKE+1,IKU
-              ZEXN(:,:,JK) = 1.5 * ZEXN(:,:,JK-1) - 0.5 * ZEXN(:,:,JK-2)
-            END DO
-            !
-            ! IF ( TPFLYER%CTYPE == 'ISODEN' .OR. TPFLYER%CTYPE == 'CVBALL' .OR. TPFLYER%CTYPE == 'AIRCRA' ) THEN
-            ZTHV(:,:,:) = PTH(II_M:II_M+1,IJ_M:IJ_M+1,:)
-            IF (SIZE(PR,4)>0)                                                     &
-            ZTHV(:,:,:) = ZTHV(:,:,:) * ( 1. + XRV/XRD*PR(II_M:II_M+1,IJ_M:IJ_M+1,:,1) )  &
-                                      / ( 1. + WATER_SUM(PR(II_M:II_M+1,IJ_M:IJ_M+1,:,:)) )
-            !
-            ZTV (:,:,:) = ZTHV(:,:,:) * ZEXN(:,:,:)
-            ZRHO(:,:,:) = PP(II_M:II_M+1,IJ_M:IJ_M+1,:) / (XRD*ZTV(:,:,:))
-            DO JK=IKB-1,1,-1
-              ZRHO(:,:,JK) = 1.5 * ZRHO(:,:,JK+1) - 0.5 * ZRHO(:,:,JK+2)
-            END DO
-            DO JK=IKE+1,IKU
-              ZRHO(:,:,JK) = 1.5 * ZRHO(:,:,JK-1) - 0.5 * ZRHO(:,:,JK-2)
-            END DO
-            ZTHW_FLUX(:,:,:) = ZRHO(:,:,:)*XCPD *XTHW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:)
-            ZRCW_FLUX(:,:,:) = ZRHO(:,:,:)*XLVTT*XRCW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:)
-            ZSVW_FLUX(:,:,:,:) = XSVW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:,:)
-            ! END IF
-
-            ! Vertical position
-            IF ( TPFLYER%LALTDEF ) THEN
-              ZFLYER_EXN = (TPFLYER%XP_CUR/XP00)**(XRD/XCPD)
-              IK00 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,1,:)), 1)
-              IK01 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,2,:)), 1)
-              IK10 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,1,:)), 1)
-              IK11 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,2,:)), 1)
-            ELSE
-              IK00 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(1,1,:)), 1)
-              IK01 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(1,2,:)), 1)
-              IK10 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(2,1,:)), 1)
-              IK11 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(2,2,:)), 1)
-            END IF
+      IF ( ABS( TDTCUR - TPFLYER%TFLYER_TIME%TPDATES(ISTORE) ) < 1e-10 ) THEN
+        ISOWNERAIR: IF ( TPFLYER%NRANK_CUR == ISP ) THEN
+          ZTHIS_PROC = 1.
 
-            IF ( ANY( [ IK00, IK01, IK10, IK11 ] < IKB ) ) THEN
-              !Minimum altitude is on the ground at IKB (no crash if too low)
-              IK00 = MAX ( IK00, IKB )
-              IK01 = MAX ( IK01, IKB )
-              IK10 = MAX ( IK10, IKB )
-              IK11 = MAX ( IK11, IKB )
-
-              CMNHMSG(1) = 'flyer ' // TRIM( TPFLYER%CTITLE ) // ' is near the ground'
-              WRITE( CMNHMSG(2), "( 'at ', I2, '/', I2, '/', I4, ' ', F18.12, 's' )" ) &
-                     TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
-              CALL PRINT_MSG( NVERB_INFO, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
-            END IF
+          CALL FLYER_INTERP_TO_MASSPOINTS()
 
-            IF (IK00 >= IKE .OR. IK01 >= IKE .OR. IK10 >= IKE .OR. IK11 >= IKE  ) THEN
-              TPFLYER%LCRASH = .TRUE.
-              TPFLYER%NCRASH = NCRASH_OUT_HIGH
-            END IF
-            !
-            !*      6.   INITIALIZATIONS FOR INTERPOLATIONS
-            !            ----------------------------------
-            !
-            !*      6.1  Interpolation coefficient for X
-            !            -------------------------------
-            !
-            ZXCOEF = (TPFLYER%XX_CUR - XXHATM(II_M)) / (XXHATM(II_M+1) - XXHATM(II_M))
-            ZXCOEF = MAX (0.,MIN(ZXCOEF,1.))
-            !
-            !
-            !*      6.2  Interpolation coefficient for y
-            !            -------------------------------
-            !
-            ZYCOEF = (TPFLYER%XY_CUR - XYHATM(IJ_M)) / (XYHATM(IJ_M+1) - XYHATM(IJ_M))
-            ZYCOEF = MAX (0.,MIN(ZYCOEF,1.))
-            !
-            !
-            !*      6.3  Interpolation coefficients for the 4 suroundings verticals
-            !            ----------------------------------------------------------
-            !
-            !       SELECT TYPE ( TPFLYER )
-            !         CLASS IS ( TBALLOONDATA)
-            !           IF ( TPFLYER%CTYPE == 'ISODEN' ) THEN
-            !             ZZCOEF00 = (TPFLYER%XRHO - ZRHO(1,1,IK00)) / ( ZRHO(1,1,IK00+1) - ZRHO(1,1,IK00) )
-            !             ZZCOEF01 = (TPFLYER%XRHO - ZRHO(1,2,IK01)) / ( ZRHO(1,2,IK01+1) - ZRHO(1,2,IK01) )
-            !             ZZCOEF10 = (TPFLYER%XRHO - ZRHO(2,1,IK10)) / ( ZRHO(2,1,IK10+1) - ZRHO(2,1,IK10) )
-            !             ZZCOEF11 = (TPFLYER%XRHO - ZRHO(2,2,IK11)) / ( ZRHO(2,2,IK11+1) - ZRHO(2,2,IK11) )
-            !             TPFLYER%XZ_CUR = FLYER_INTERP(ZZM)
-            !           ELSE IF ( TPFLYER%CTYPE == 'RADIOS' .OR. TPFLYER%CTYPE == 'CVBALL' ) THEN
-            !             ZZCOEF00 = (TPFLYER%XZ_CUR - ZZM(1,1,IK00)) / ( ZZM(1,1,IK00+1) - ZZM(1,1,IK00) )
-            !             ZZCOEF01 = (TPFLYER%XZ_CUR - ZZM(1,2,IK01)) / ( ZZM(1,2,IK01+1) - ZZM(1,2,IK01) )
-            !             ZZCOEF10 = (TPFLYER%XZ_CUR - ZZM(2,1,IK10)) / ( ZZM(2,1,IK10+1) - ZZM(2,1,IK10) )
-            !             ZZCOEF11 = (TPFLYER%XZ_CUR - ZZM(2,2,IK11)) / ( ZZM(2,2,IK11+1) - ZZM(2,2,IK11) )
-            !           END IF
-            !
-            !         CLASS IS ( TAIRCRAFTDATA)
-            IF ( TPFLYER%LALTDEF ) THEN
-              ZZCOEF00 = (ZFLYER_EXN - ZEXN(1,1,IK00)) / ( ZEXN(1,1,IK00+1) - ZEXN(1,1,IK00) )
-              ZZCOEF01 = (ZFLYER_EXN - ZEXN(1,2,IK01)) / ( ZEXN(1,2,IK01+1) - ZEXN(1,2,IK01) )
-              ZZCOEF10 = (ZFLYER_EXN - ZEXN(2,1,IK10)) / ( ZEXN(2,1,IK10+1) - ZEXN(2,1,IK10) )
-              ZZCOEF11 = (ZFLYER_EXN - ZEXN(2,2,IK11)) / ( ZEXN(2,2,IK11+1) - ZEXN(2,2,IK11) )
-              TPFLYER%XZ_CUR = FLYER_INTERP(ZZM)
-            ELSE
-              ZZCOEF00 = (TPFLYER%XZ_CUR - ZZM(1,1,IK00)) / ( ZZM(1,1,IK00+1) - ZZM(1,1,IK00) )
-              ZZCOEF01 = (TPFLYER%XZ_CUR - ZZM(1,2,IK01)) / ( ZZM(1,2,IK01+1) - ZZM(1,2,IK01) )
-              ZZCOEF10 = (TPFLYER%XZ_CUR - ZZM(2,1,IK10)) / ( ZZM(2,1,IK10+1) - ZZM(2,1,IK10) )
-              ZZCOEF11 = (TPFLYER%XZ_CUR - ZZM(2,2,IK11)) / ( ZZM(2,2,IK11+1) - ZZM(2,2,IK11) )
-              TPFLYER%XP_CUR = FLYER_INTERP(PP)
-            END IF
-            ! END SELECT
-            !
-            !----------------------------------------------------------------------------
-            !
-            !*      7.   INITIALIZATIONS FOR INTERPOLATIONS OF U AND V
-            !            ---------------------------------------------
-            !
-            !*      7.1  Interpolation coefficient for X (for U)
-            !            -------------------------------
-            !
-            ZUCOEF = (TPFLYER%XX_CUR - XXHAT(II_U)) / (XXHAT(II_U+1) - XXHAT(II_U))
-            ZUCOEF = MAX(0.,MIN(ZUCOEF,1.))
-            !
-            !
-            !*      7.2  Interpolation coefficient for y (for V)
-            !            -------------------------------
-            !
-            ZVCOEF = (TPFLYER%XY_CUR - XYHAT(IJ_V)) / (XYHAT(IJ_V+1) - XYHAT(IJ_V))
-            ZVCOEF = MAX(0.,MIN(ZVCOEF,1.))
-            !
-            !
-            !*      7.3  Interpolation coefficients for the 4 suroundings verticals (for U)
-            !            ----------------------------------------------------------
-            !
-            IU00 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(1,1,:)), 1)
-            IU01 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(1,2,:)), 1)
-            IU10 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(2,1,:)), 1)
-            IU11 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(2,2,:)), 1)
-            ZUCOEF00 = (TPFLYER%XZ_CUR - ZZU(1,1,IU00)) / ( ZZU(1,1,IU00+1) - ZZU(1,1,IU00) )
-            ZUCOEF01 = (TPFLYER%XZ_CUR - ZZU(1,2,IU01)) / ( ZZU(1,2,IU01+1) - ZZU(1,2,IU01) )
-            ZUCOEF10 = (TPFLYER%XZ_CUR - ZZU(2,1,IU10)) / ( ZZU(2,1,IU10+1) - ZZU(2,1,IU10) )
-            ZUCOEF11 = (TPFLYER%XZ_CUR - ZZU(2,2,IU11)) / ( ZZU(2,2,IU11+1) - ZZU(2,2,IU11) )
-            !
-            !
-            !*      7.4  Interpolation coefficients for the 4 suroundings verticals (for V)
-            !            ----------------------------------------------------------
-            !
-            IV00 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(1,1,:)), 1)
-            IV01 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(1,2,:)), 1)
-            IV10 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(2,1,:)), 1)
-            IV11 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(2,2,:)), 1)
-            ZVCOEF00 = (TPFLYER%XZ_CUR - ZZV(1,1,IV00)) / ( ZZV(1,1,IV00+1) - ZZV(1,1,IV00) )
-            ZVCOEF01 = (TPFLYER%XZ_CUR - ZZV(1,2,IV01)) / ( ZZV(1,2,IV01+1) - ZZV(1,2,IV01) )
-            ZVCOEF10 = (TPFLYER%XZ_CUR - ZZV(2,1,IV10)) / ( ZZV(2,1,IV10+1) - ZZV(2,1,IV10) )
-            ZVCOEF11 = (TPFLYER%XZ_CUR - ZZV(2,2,IV11)) / ( ZZV(2,2,IV11+1) - ZZV(2,2,IV11) )
-            !
-            !
-            !*      8.   DATA RECORDING
-            !            --------------
-            !
-            TPFLYER%NMODELHIST(ISTORE) = TPFLYER%NMODEL
-            TPFLYER%XX   (ISTORE) = TPFLYER%XX_CUR
-            TPFLYER%XY   (ISTORE) = TPFLYER%XY_CUR
-            TPFLYER%XZ   (ISTORE) = TPFLYER%XZ_CUR
-            !
-            CALL SM_LATLON(PLATOR,PLONOR,          &
-                        TPFLYER%XX_CUR, TPFLYER%XY_CUR,       &
-                        TPFLYER%XLAT(ISTORE), TPFLYER%XLON(ISTORE)  )
-            !
-            ZU_BAL = FLYER_INTERP_U(PU)
-            ZV_BAL = FLYER_INTERP_V(PV)
-            ZGAM   = (XRPK * (TPFLYER%XLON(ISTORE) - XLON0) - XBETA)*(XPI/180.)
-            TPFLYER%XZON (ISTORE) = ZU_BAL * COS(ZGAM) + ZV_BAL * SIN(ZGAM)
-            TPFLYER%XMER (ISTORE) = - ZU_BAL * SIN(ZGAM) + ZV_BAL * COS(ZGAM)
-            !
-            TPFLYER%XW   (ISTORE) = FLYER_INTERP(ZWM)
-            TPFLYER%XTH  (ISTORE) = FLYER_INTERP(PTH)
-            !
-            ZFLYER_EXN = FLYER_INTERP(ZEXN)
-            TPFLYER%XP   (ISTORE) = XP00 * ZFLYER_EXN**(XCPD/XRD)
-
-            ZR(:,:,:) = 0.
-            DO JLOOP=1,SIZE(PR,4)
-              TPFLYER%XR   (ISTORE,JLOOP) = FLYER_INTERP(PR(:,:,:,JLOOP))
-              IF (JLOOP>=2) ZR(:,:,:) = ZR(:,:,:) + PR(:,:,:,JLOOP)
-            END DO
-            DO JLOOP=1,SIZE(PSV,4)
-              TPFLYER%XSV  (ISTORE,JLOOP) = FLYER_INTERP(PSV(:,:,:,JLOOP))
-            END DO
-            TPFLYER%XRTZ  (ISTORE,:) = FLYER_INTERPZ(ZR(:,:,:))
-            DO JLOOP=1,SIZE(PR,4)
-              TPFLYER%XRZ  (ISTORE,:,JLOOP) = FLYER_INTERPZ(PR(:,:,:,JLOOP))
-            END DO
-            ! Fin Modifs ON
-            TPFLYER%XFFZ  (ISTORE,:) = FLYER_INTERPZ(SQRT(PU**2+PV**2))
-            IF (CCLOUD=="LIMA") THEN
-              TPFLYER%XCIZ  (ISTORE,:) = FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NI))
-              TPFLYER%XCCZ  (ISTORE,:) = FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NC))
-              TPFLYER%XCRZ  (ISTORE,:) = FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NR))
-            ELSE IF ( CCLOUD=="ICE3" .OR. CCLOUD=="ICE4" ) THEN
-              TPFLYER%XCIZ  (ISTORE,:) = FLYER_INTERPZ(PCIT(:,:,:))
-            ENDIF
-            ! initialization CRARE and CRARE_ATT + LWC and IWC
-            TPFLYER%XCRARE(ISTORE,:) = 0.
-            TPFLYER%XCRARE_ATT(ISTORE,:) = 0.
-            TPFLYER%XLWCZ  (ISTORE,:) = 0.
-            TPFLYER%XIWCZ  (ISTORE,:) = 0.
-            IF (CCLOUD=="LIMA" .OR. CCLOUD=="ICE3" ) THEN ! only for ICE3 and LIMA
-              TPFLYER%XLWCZ  (ISTORE,:) = FLYER_INTERPZ((PR(:,:,:,2)+PR(:,:,:,3))*PRHODREF(:,:,:))
-              TPFLYER%XIWCZ  (ISTORE,:) = FLYER_INTERPZ((PR(:,:,:,4)+PR(:,:,:,5)+PR(:,:,:,6))*PRHODREF(:,:,:))
-              ZTEMPZ(:)=FLYER_INTERPZ(PTH(II_M:II_M+1,IJ_M:IJ_M+1,:) * ZEXN(:,:,:))
-              ZRHODREFZ(:)=FLYER_INTERPZ(PRHODREF(:,:,:))
-              IF (CCLOUD=="LIMA") THEN
-                ZCCI(:)=FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NI))
-                ZCCR(:)=FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NR))
-                ZCCC(:)=FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NC))
-              ELSE
-                ZCIT(:)=FLYER_INTERPZ(PCIT(:,:,:))
-              ENDIF
-              DO JLOOP=3,6
-                ZRZ(:,JLOOP)=FLYER_INTERPZ(PR(:,:,:,JLOOP))
-              END DO
-              if ( csurf == 'EXTE' ) then
-                DO JK=1,IKU
-                  ZRZ(JK,2)=FLYER_INTERP_2D(PR(:,:,JK,2)*PSEA(:,:))       ! becomes cloud mixing ratio over sea
-                  ZRZ(JK,7)=FLYER_INTERP_2D(PR(:,:,JK,2)*(1.-PSEA(:,:)))  ! becomes cloud mixing ratio over land
-                END DO
-              else
-                !if csurf/='EXTE', psea is not allocated
-                DO JK=1,IKU
-                  ZRZ(JK,2)=FLYER_INTERP_2D(PR(:,:,JK,2))
-                  ZRZ(JK,7) = 0.
-                END DO
-              end if
-              ALLOCATE(ZAELOC(IKU))
-              !
-              ZAELOC(:)=0.
-              ! initialization of quadrature points and weights
-              ALLOCATE(ZX(JPTS_GAULAG),ZW(JPTS_GAULAG))
-              CALL GAULAG(JPTS_GAULAG,ZX,ZW) ! for integration over diameters
-              ! initialize minimum values
-              ALLOCATE(ZRTMIN(SIZE(PR,4)+1))
-              IF (CCLOUD == 'LIMA') THEN
-                ZRTMIN(2)=XRTMIN_L(2) ! cloud water over sea
-                ZRTMIN(3)=XRTMIN_L(3)
-                ZRTMIN(4)=XRTMIN_L(4)
-                ZRTMIN(5)=1E-10
-                ZRTMIN(6)=XRTMIN_L(6)
-                ZRTMIN(7)=XRTMIN_L(2) ! cloud water over land
-              ELSE
-                ZRTMIN(2)=XRTMIN_I(2) ! cloud water over sea
-                ZRTMIN(3)=XRTMIN_I(3)
-                ZRTMIN(4)=XRTMIN_I(4)
-                ZRTMIN(5)=1E-10
-                ZRTMIN(6)=XRTMIN_I(6)
-                ZRTMIN(7)=XRTMIN_I(2) ! cloud water over land
-              ENDIF
-              ! compute cloud radar reflectivity from vertical profiles of temperature and mixing ratios
-              DO JK=1,IKU
-                QMW=SQRT(QEPSW(ZTEMPZ(JK),XLIGHTSPEED/XLAM_CRAD))
-                QMI=SQRT(QEPSI(ZTEMPZ(JK),XLIGHTSPEED/XLAM_CRAD))
-                DO JLOOP=2,7
-                  IF (CCLOUD == 'LIMA') THEN
-                    GCALC=(ZRZ(JK,JLOOP)>ZRTMIN(JLOOP).AND.(JLOOP.NE.4.OR.ZCCI(JK)>0.).AND.&
-                          (JLOOP.NE.3.OR.ZCCR(JK)>0.).AND.((JLOOP.NE.2.AND. JLOOP.NE.7).OR.ZCCC(JK)>0.))
-                  ELSE
-                    GCALC=(ZRZ(JK,JLOOP)>ZRTMIN(JLOOP).AND.(JLOOP.NE.4.OR.ZCIT(JK)>0.))
-                  ENDIF
-                  IF(GCALC) THEN
-                    SELECT CASE(JLOOP)
-                      CASE(2) ! cloud water over sea
-                        IF (CCLOUD == 'LIMA') THEN
-                          ZA=XAC_L
-                          ZB=XBC_L
-                          ZCC=ZCCC(JK)*ZRHODREFZ(JK)
-                          ZCX=0.
-                          ZALPHA=XALPHAC_L
-                          ZNU=XNUC_L
-                          ZLBEX=1.0/(ZCX-ZB)
-                          ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                        ELSE
-                          ZA=XAC_I
-                          ZB=XBC_I
-                          ZCC=XCONC_SEA
-                          ZCX=0.
-                          ZALPHA=XALPHAC2_I
-                          ZNU=XNUC2_I
-                          ZLBEX=1.0/(ZCX-ZB)
-                          ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                        ENDIF
-                      CASE(3) ! rain water
-                        IF (CCLOUD == 'LIMA') THEN
-                          ZA=XAR_L
-                          ZB=XBR_L
-                          ZCC=ZCCR(JK)*ZRHODREFZ(JK)
-                          ZCX=0.
-                          ZALPHA=XALPHAR_L
-                          ZNU=XNUR_L
-                          ZLBEX=1.0/(ZCX-ZB)
-                          ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                        ELSE
-                          ZA=XAR_I
-                          ZB=XBR_I
-                          ZCC=XCCR_I
-                          ZCX=-1.
-                          ZALPHA=XALPHAR_I
-                          ZNU=XNUR_I
-                          ZLB=XLBR_I
-                          ZLBEX=XLBEXR_I
-                        ENDIF
-                      CASE(4) ! pristine ice
-                        IF (CCLOUD == 'LIMA') THEN
-                          ZA=XAI_L
-                          ZB=XBI_L
-                          ZCC=ZCCI(JK)*ZRHODREFZ(JK)
-                          ZCX=0.
-                          ZALPHA=XALPHAI_L
-                          ZNU=XNUI_L
-                          ZLBEX=1.0/(ZCX-ZB)
-                          ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX) ! because ZCC not included in XLBI
-                          ZFW=0
-                        ELSE
-                          ZA=XAI_I
-                          ZB=XBI_I
-                          ZCC=ZCIT(JK)
-                          ZCX=0.
-                          ZALPHA=XALPHAI_I
-                          ZNU=XNUI_I
-                          ZLBEX=XLBEXI_I
-                          ZLB=XLBI_I*ZCC**(-ZLBEX) ! because ZCC not included in XLBI
-                          ZFW=0
-                        ENDIF
-                      CASE(5) ! snow
-                        IF (CCLOUD == 'LIMA') THEN
-                          ZA=XAS_L
-                          ZB=XBS_L
-                          ZCC=XCCS_L
-                          ZCX=XCXS_L
-                          ZALPHA=XALPHAS_L
-                          ZNU=XNUS_L
-                          ZLB=XLBS_L
-                          ZLBEX=XLBEXS_L
-                          ZFW=0
-                        ELSE
-                          ZA=XAS_I
-                          ZB=XBS_I
-                          ZCC=XCCS_I
-                          ZCX=XCXS_I
-                          ZALPHA=XALPHAS_I
-                          ZNU=XNUS_I
-                          ZLB=XLBS_I
-                          ZLBEX=XLBEXS_I
-                          ZFW=0
-                        ENDIF
-                      CASE(6) ! graupel
-                        !If temperature between -10 and 10°C and Mr and Mg over min threshold: melting graupel
-                        ! with liquid water fraction Fw=Mr/(Mr+Mg) else dry graupel (Fw=0)
-                        IF( ZTEMPZ(JK) > XTT-10 .AND. ZTEMPZ(JK) < XTT+10 &
-                          .AND. ZRZ(JK,3) > ZRTMIN(3) ) THEN
-                          ZFW=ZRZ(JK,3)/(ZRZ(JK,3)+ZRZ(JK,JLOOP))
-                        ELSE
-                          ZFW=0
-                        ENDIF
-                        IF (CCLOUD == 'LIMA') THEN
-                          ZA=XAG_L
-                          ZB=XBG_L
-                          ZCC=XCCG_L
-                          ZCX=XCXG_L
-                          ZALPHA=XALPHAG_L
-                          ZNU=XNUG_L
-                          ZLB=XLBG_L
-                          ZLBEX=XLBEXG_L
-                        ELSE
-                          ZA=XAG_I
-                          ZB=XBG_I
-                          ZCC=XCCG_I
-                          ZCX=XCXG_I
-                          ZALPHA=XALPHAG_I
-                          ZNU=XNUG_I
-                          ZLB=XLBG_I
-                          ZLBEX=XLBEXG_I
-                        ENDIF
-                      CASE(7) ! cloud water over land
-                        IF (CCLOUD == 'LIMA') THEN
-                          ZA=XAC_L
-                          ZB=XBC_L
-                          ZCC=ZCCC(JK)*ZRHODREFZ(JK)
-                          ZCX=0.
-                          ZALPHA=XALPHAC_L
-                          ZNU=XNUC_L
-                          ZLBEX=1.0/(ZCX-ZB)
-                          ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                        ELSE
-                          ZA=XAC_I
-                          ZB=XBC_I
-                          ZCC=XCONC_LAND
-                          ZCX=0.
-                          ZALPHA=XALPHAC_I
-                          ZNU=XNUC_I
-                          ZLBEX=1.0/(ZCX-ZB)
-                          ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                        ENDIF
-                    END SELECT
-                    ZLBDA=ZLB*(ZRHODREFZ(JK)*ZRZ(JK,JLOOP))**ZLBEX
-                    ZREFLOC=0.
-                    ZAETMP=0.
-                    DO JJ=1,JPTS_GAULAG ! Gauss-Laguerre quadrature
-                      ZDELTA_EQUIV=ZX(JJ)**(1./ZALPHA)/ZLBDA
-                      SELECT CASE(JLOOP)
-                        CASE(2,3,7)
-                          QM=QMW
-                        CASE(4,5,6)
-                          ! pristine ice, snow, dry graupel
-                          ZRHOHYD=MIN(6.*ZA*ZDELTA_EQUIV**(ZB-3.)/XPI,.92*XRHOLW)
-                          QM=sqrt(MG(QMI**2,CMPLX(1,0),ZRHOHYD/.92/XRHOLW))
-
-                          ! water inclusions in ice in air
-                          QEPSWI=MG(QMW**2,QM**2,ZFW)
-                          ! ice in air inclusions in water
-                          QEPSIW=MG(QM**2,QMW**2,1.-ZFW)
-
-                          !MG weighted rule (Matrosov 2008)
-                          IF(ZFW .LT. 0.37) THEN
-                            ZFPW=0
-                          ELSE IF(ZFW .GT. 0.63) THEN
-                            ZFPW=1
-                          ELSE
-                            ZFPW=(ZFW-0.37)/(0.63-0.37)
-                          ENDIF
-                          QM=sqrt(QEPSWI*(1.-ZFPW)+QEPSIW*ZFPW)
-                      END SELECT
-                      CALL BHMIE(XPI/XLAM_CRAD*ZDELTA_EQUIV,QM,ZQEXT,ZQSCA,ZQBACK)
-                      ZREFLOC=ZREFLOC+ZQBACK*ZX(JJ)**(ZNU-1)*ZDELTA_EQUIV**2*ZW(JJ)
-                      ZAETMP =ZAETMP +ZQEXT *ZX(JJ)**(ZNU-1)*ZDELTA_EQUIV**2*ZW(JJ)
-                    END DO
-                    ZREFLOC=ZREFLOC*(XLAM_CRAD/XPI)**4*ZCC*ZLBDA**ZCX/(4.*GAMMA(ZNU)*.93)
-                    ZAETMP=ZAETMP  *           XPI    *ZCC*ZLBDA**ZCX/(4.*GAMMA(ZNU))
-                    TPFLYER%XCRARE(ISTORE,JK)=TPFLYER%XCRARE(ISTORE,JK)+ZREFLOC
-                    ZAELOC(JK)=ZAELOC(JK)+ZAETMP
-                  END IF
-                END DO
-              END DO
-
-              ! apply attenuation
-              ALLOCATE(ZZMZ(IKU))
-              ZZMZ(:)=FLYER_INTERPZ(ZZM(:,:,:))
-              ! nadir
-              ZAETOT=1.
-              DO JK=COUNT(TPFLYER%XZ_CUR >= ZZMZ(:)),1,-1
-                IF(JK.EQ.COUNT(TPFLYER%XZ_CUR >= ZZMZ(:))) THEN
-                  IF(TPFLYER%XZ_CUR<=ZZMZ(JK)+.5*(ZZMZ(JK+1)-ZZMZ(JK))) THEN
-                    ! only attenuation from ZAELOC(JK)
-                    ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK)*(TPFLYER%XZ_CUR-ZZMZ(JK))))
-                  ELSE
-                    ! attenuation from ZAELOC(JK) and ZAELOC(JK+1)
-                    ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK+1)*(TPFLYER%XZ_CUR-.5*(ZZMZ(JK+1)+ZZMZ(JK))) &
-                      +ZAELOC(JK)*.5*(ZZMZ(JK+1)-ZZMZ(JK))))
-                  END IF
-                ELSE
-                  ! attenuation from ZAELOC(JK) and ZAELOC(JK+1)
-                  ZAETOT=ZAETOT*EXP(-(ZAELOC(JK+1)+ZAELOC(JK))*(ZZMZ(JK+1)-ZZMZ(JK)))
-                END IF
-                TPFLYER%XCRARE_ATT(ISTORE,JK)=TPFLYER%XCRARE(ISTORE,JK)*ZAETOT
-              END DO
-              ! zenith
-              ZAETOT=1.
-              DO JK = MAX(COUNT(TPFLYER%XZ_CUR >= ZZMZ(:)),1)+1,IKU
-                IF ( JK .EQ. (MAX(COUNT(TPFLYER%XZ_CUR >= ZZMZ(:)),1)+1) ) THEN
-                  IF(TPFLYER%XZ_CUR>=ZZMZ(JK)-.5*(ZZMZ(JK)-ZZMZ(JK-1))) THEN
-                    ! only attenuation from ZAELOC(JK)
-                    ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK)*(ZZMZ(JK)-TPFLYER%XZ_CUR)))
-                  ELSE
-                    ! attenuation from ZAELOC(JK) and ZAELOC(JK-1)
-                    ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK-1)*(.5*(ZZMZ(JK)+ZZMZ(JK-1))-TPFLYER%XZ_CUR) &
-                      +ZAELOC(JK)*.5*(ZZMZ(JK)-ZZMZ(JK-1))))
-                  END IF
-                ELSE
-                  ! attenuation from ZAELOC(JK) and ZAELOC(JK-1)
-                  ZAETOT=ZAETOT*EXP(-(ZAELOC(JK-1)+ZAELOC(JK))*(ZZMZ(JK)-ZZMZ(JK-1)))
-                END IF
-                TPFLYER%XCRARE_ATT(ISTORE,JK)=TPFLYER%XCRARE(ISTORE,JK)*ZAETOT
-              END DO
-              TPFLYER%XZZ  (ISTORE,:) = ZZMZ(:)
-              DEALLOCATE(ZZMZ,ZAELOC)
-              ! m^3 → mm^6/m^3 → dBZ
-              WHERE(TPFLYER%XCRARE(ISTORE,:)>0)
-                TPFLYER%XCRARE(ISTORE,:)=10.*LOG10(1.E18*TPFLYER%XCRARE(ISTORE,:))
-              ELSEWHERE
-                TPFLYER%XCRARE(ISTORE,:)=XUNDEF
-              END WHERE
-              WHERE(TPFLYER%XCRARE_ATT(ISTORE,:)>0)
-                TPFLYER%XCRARE_ATT(ISTORE,:)=10.*LOG10(1.E18*TPFLYER%XCRARE_ATT(ISTORE,:))
-              ELSEWHERE
-                TPFLYER%XCRARE_ATT(ISTORE,:)=XUNDEF
-              END WHERE
-              DEALLOCATE(ZX,ZW,ZRTMIN)
-            END IF ! end LOOP ICE3
-            ! vertical wind
-            TPFLYER%XWZ  (ISTORE,:) = FLYER_INTERPZ(ZWM(:,:,:))
-            IF (SIZE(PTKE)>0) TPFLYER%XTKE  (ISTORE)    = FLYER_INTERP(PTKE)
-            IF (SIZE(PTS) >0) TPFLYER%XTSRAD(ISTORE)    = FLYER_INTERP_2D(PTS)
-            IF (LDIAG_IN_RUN) TPFLYER%XTKE_DISS(ISTORE) = FLYER_INTERP(XCURRENT_TKE_DISS)
-            TPFLYER%XZS(ISTORE)  = FLYER_INTERP_2D(PZ(:,:,1+JPVEXT))
-            TPFLYER%XTHW_FLUX(ISTORE) = FLYER_INTERP(ZTHW_FLUX)
-            TPFLYER%XRCW_FLUX(ISTORE) = FLYER_INTERP(ZRCW_FLUX)
-            DO JLOOP=1,SIZE(PSV,4)
-            TPFLYER%XSVW_FLUX(ISTORE,JLOOP) = FLYER_INTERP(ZSVW_FLUX(:,:,:,JLOOP))
-            END DO
-
-          ELSE ISOWNER
-
-            ZTHIS_PROC = 0.
-
-          END IF ISOWNER
+          ZEXN(:,:,:) = FLYER_COMPUTE_EXNER( )
+          ZRHO(:,:,:) = FLYER_COMPUTE_RHO( )
 
-!----------------------------------------------------------------------------
-          !
-          !*     11.   EXCHANGE OF INFORMATION BETWEEN PROCESSES
-          !            -----------------------------------------
-          !
-          !*     11.1  current position
-          !            ----------------
-          !
-          !
-          !*     11.2  data stored
-          !            -----------
-          !
-          ! IF ( GSTORE ) THEN
-          CALL DISTRIBUTE_FLYER_N(TPFLYER%NMODELHIST(ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XX  (ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XY  (ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XZ  (ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XLON(ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XLAT(ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XZON(ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XMER(ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XW  (ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XP  (ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XTH (ISTORE))
-          DO JLOOP=1,SIZE(PR,4)
-            CALL DISTRIBUTE_FLYER(TPFLYER%XR   (ISTORE,JLOOP))
-          END DO
-          DO JLOOP=1,SIZE(PSV,4)
-            CALL DISTRIBUTE_FLYER(TPFLYER%XSV  (ISTORE,JLOOP))
-          END DO
-          DO JLOOP=1,IKU
-            CALL DISTRIBUTE_FLYER(TPFLYER%XRTZ (ISTORE,JLOOP))
-            DO JLOOP2=1,SIZE(PR,4)
-              CALL DISTRIBUTE_FLYER(TPFLYER%XRZ (ISTORE,JLOOP,JLOOP2))
-            ENDDO
-            CALL DISTRIBUTE_FLYER(TPFLYER%XFFZ (ISTORE,JLOOP))
-            CALL DISTRIBUTE_FLYER(TPFLYER%XCIZ (ISTORE,JLOOP))
-            IF (CCLOUD== 'LIMA' ) THEN
-              CALL DISTRIBUTE_FLYER(TPFLYER%XCRZ (ISTORE,JLOOP))
-              CALL DISTRIBUTE_FLYER(TPFLYER%XCCZ (ISTORE,JLOOP))
-            ENDIF
-            CALL DISTRIBUTE_FLYER(TPFLYER%XIWCZ (ISTORE,JLOOP))
-            CALL DISTRIBUTE_FLYER(TPFLYER%XLWCZ (ISTORE,JLOOP))
-            CALL DISTRIBUTE_FLYER(TPFLYER%XCRARE (ISTORE,JLOOP))
-            CALL DISTRIBUTE_FLYER(TPFLYER%XCRARE_ATT (ISTORE,JLOOP))
-            CALL DISTRIBUTE_FLYER(TPFLYER%XWZ (ISTORE,JLOOP))
-            CALL DISTRIBUTE_FLYER(TPFLYER%XZZ (ISTORE,JLOOP))
-          END DO
-          IF (SIZE(PTKE)>0) CALL DISTRIBUTE_FLYER(TPFLYER%XTKE  (ISTORE))
-          IF (SIZE(PTS) >0) CALL DISTRIBUTE_FLYER(TPFLYER%XTSRAD(ISTORE))
-          IF (LDIAG_IN_RUN) CALL DISTRIBUTE_FLYER(TPFLYER%XTKE_DISS(ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XZS  (ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XTHW_FLUX(ISTORE))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XRCW_FLUX(ISTORE))
-          DO JLOOP=1,SIZE(PSV,4)
-            CALL DISTRIBUTE_FLYER(TPFLYER%XSVW_FLUX(ISTORE,JLOOP))
-          END DO
-        END IF
+          ZTHW_FLUX(:,:,:) = ZRHO(:,:,:)*XCPD *XTHW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:)
+          ZRCW_FLUX(:,:,:) = ZRHO(:,:,:)*XLVTT*XRCW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:)
+          ZSVW_FLUX(:,:,:,:) = XSVW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:,:)
+
+          ! Compute coefficents for horizontal interpolations
+          CALL FLYER_COMPUTE_INTERP_COEFF_HOR_STAGE1( )
+          ! Compute coefficents for vertical interpolations
+          CALL FLYER_COMPUTE_INTERP_COEFF_VER( )
+          ! Compute coefficents for horizontal interpolations
+          CALL FLYER_COMPUTE_INTERP_COEFF_HOR_STAGE2( )
+
+          CALL FLYER_RECORD_DATA( )
+        ELSE ISOWNERAIR
+          !Not owner branch
+          ZTHIS_PROC = 0.
+        END IF ISOWNERAIR
+
+        CALL FLYER_COMMUNICATE_DATA( )
       END IF
     END IF
 
@@ -1023,30 +301,16 @@ SELECT TYPE ( TPFLYER )
     ! (XXHAT_ll of all models are needed by FIND_PROCESS_AND_MODEL_FROM_XY_POS)
     IF ( .NOT. TPFLYER%LFLY .AND. .NOT. TPFLYER%LCRASH .AND. TPFLYER%NRANK_CUR < 0 ) THEN
       ! Get rank of the process where the balloon is and the model number
-      IF ( TPFLYER%CMODEL == 'FIX' ) THEN
-        IMODEL = TPFLYER%NMODEL
-      ELSE
-        IMODEL = 0
-      END IF
-      CALL FIND_PROCESS_AND_MODEL_FROM_XY_POS( TPFLYER%XXLAUNCH, TPFLYER%XYLAUNCH, IRANK, IMODEL )
-
-      IF ( IRANK < 1 ) THEN
-        TPFLYER%NMODEL = 1 !Set to 1 because it is always a valid model (to prevent crash if NDAD(TPFLYER%NMODEL) )
-        TPFLYER%LCRASH = .TRUE.
-        TPFLYER%NCRASH = NCRASH_OUT_HORIZ
-        TPFLYER%LFLY   = .FALSE.
+      CALL FLYER_GET_RANK_MODEL_ISCRASHED( TPFLYER, PX = TPFLYER%XXLAUNCH, PY = TPFLYER%XYLAUNCH )
+      IF ( TPFLYER%LCRASH ) THEN
         CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', 'balloon ' // TRIM( TPFLYER%CTITLE ) &
                         // ': launch coordinates are outside of horizontal physical domain' )
-      ELSE
-        TPFLYER%NMODEL = IMODEL
-        TPFLYER%LCRASH = .FALSE.
-        TPFLYER%NCRASH = NCRASH_NO
-        TPFLYER%NRANK_CUR = IRANK
       END IF
     END IF
 
     ! 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
         TPFLYER%LFLY = .TRUE.
         GLAUNCH = .TRUE.
@@ -1054,890 +318,74 @@ SELECT TYPE ( TPFLYER )
         TPFLYER%XX_CUR = TPFLYER%XXLAUNCH
         TPFLYER%XY_CUR = TPFLYER%XYLAUNCH
         TPFLYER%TPOS_CUR = TDTCUR
+
         ! Get rank of the process where the balloon is and the model number
-        IF ( TPFLYER%CMODEL == 'FIX' ) THEN
-          IMODEL = TPFLYER%NMODEL
-        ELSE
-          IMODEL = 0
-        END IF
-        CALL FIND_PROCESS_AND_MODEL_FROM_XY_POS( TPFLYER%XX_CUR, TPFLYER%XY_CUR, IRANK, IMODEL )
-        IF ( IRANK < 1 ) THEN
-          TPFLYER%NMODEL = 1 !Set to 1 because it is always a valid model (to prevent crash if NDAD(TPFLYER%NMODEL) )
-          TPFLYER%LCRASH = .TRUE.
-          TPFLYER%NCRASH = NCRASH_OUT_HORIZ
-          TPFLYER%LFLY   = .FALSE.
+        CALL FLYER_GET_RANK_MODEL_ISCRASHED( TPFLYER )
+        IF ( TPFLYER%LCRASH ) THEN
           WRITE( CMNHMSG(1), "( 'Balloon ', A, ' crashed the ', I2, '/', I2, '/', I4, ' at ', F18.12, &
                               's (out of the horizontal boundaries)' )" ) &
              TRIM( TPFLYER%CTITLE ), TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
           CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL' )
-        ELSE
-          TPFLYER%NMODEL = IMODEL
-          TPFLYER%LCRASH = .FALSE.
-          TPFLYER%NCRASH = NCRASH_NO
-          TPFLYER%NRANK_CUR = IRANK
         END IF
       END IF LAUNCHTIME
     END IF LAUNCH
 
-    MODEL1BAL: IF ( TPFLYER%NMODEL == IMI .AND. &
+    ! 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
       !Do we have to store balloon data?
-      CALL  STATPROF_INSTANT( TPFLYER%TFLYER_TIME, ISTORE )
-      IF ( ISTORE < 1 ) THEN
-        !No profiler storage at this time step
-        TPFLYER%LSTORE = .FALSE.
-      ELSE
-        TPFLYER%LSTORE = .TRUE.
-      END IF
-    END IF MODEL1BAL
+      CALL FLYER_CHECK_STORESTEP( TPFLYER )
+    END IF
 
     ! In flight
     INFLIGHTONMODEL: IF ( TPFLYER%LFLY .AND. .NOT. TPFLYER%LCRASH .AND. TPFLYER%NMODEL == IMI &
                           .AND. ABS( TPFLYER%TPOS_CUR - TDTCUR ) < 1.e-8 ) THEN
-
       ISOWNERBAL: IF ( TPFLYER%NRANK_CUR == ISP ) THEN
         ZTHIS_PROC = 1.
-        !
-        !*      2.   PRELIMINARIES-2
-        !            -------------
-        !
-        !*      2.1  Indices
-        !            -------
-        !
-        CALL GET_INDICE_ll (IIB,IJB,IIE,IJE)
-        IKB =   1   + JPVEXT
-        IKE = SIZE(PZ,3) - JPVEXT
-        !
-        !
-        !*      2.2  Interpolations of model variables to mass points
-        !            ------------------------------------------------
-        !
-        IIU=SIZE(XXHAT)
-        IJU=SIZE(XYHAT)
-        ! X position
-        II_U = COUNT( XXHAT (:) <= TPFLYER%XX_CUR )
-        II_M = COUNT( XXHATM(:) <= TPFLYER%XX_CUR )
-
-        ! Y position
-        IJ_V=COUNT( XYHAT (:)<=TPFLYER%XY_CUR )
-        IJ_M=COUNT( XYHATM(:)<=TPFLYER%XY_CUR )
-        !
-        !*      4.5  Interpolations of model variables to mass points
-        !            ------------------------------------------------
-        !
-        ZZM(:,:,1:IKU-1)=0.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,1:IKU-1)+0.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,2:IKU  )
-        ZZM(:,:,  IKU  )=1.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,  IKU-1)-0.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,  IKU-2)
-
-        IDU = II_U - II_M
-        ZZU(:,:,1:IKU-1)=0.25*PZ(IDU+II_M-1:IDU+II_M,  IJ_M  :IJ_M+1,1:IKU-1)+0.25*PZ(IDU+II_M-1:IDU+II_M  ,IJ_M  :IJ_M+1,2:IKU  ) &
-                      +0.25*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,1:IKU-1)+0.25*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,2:IKU  )
-        ZZU(:,:,  IKU  )=0.75*PZ(IDU+II_M-1:IDU+II_M  ,IJ_M  :IJ_M+1,  IKU-1)-0.25*PZ(IDU+II_M-1:IDU+II_M  ,IJ_M  :IJ_M+1,  IKU-2) &
-                      +0.75*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,  IKU-1)-0.25*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,  IKU-2)
-
-        IDV = IJ_V - IJ_M
-        ZZV(:,:,1:IKU-1)=0.25*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,1:IKU-1)+0.25*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,2:IKU  ) &
-                      +0.25*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,1:IKU-1)+0.25*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,2:IKU  )
-        ZZV(:,:,  IKU  )=0.75*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,  IKU-1)-0.25*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,  IKU-2) &
-                      +0.75*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,  IKU-1)-0.25*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,  IKU-2)
-
-        ZWM(:,:,1:IKU-1)=0.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,1:IKU-1)+0.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,2:IKU  )
-        ZWM(:,:,  IKU  )=1.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,  IKU-1)-0.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,  IKU-2)
-        !
-        !----------------------------------------------------------------------------
-        !
-        !*      5.   BALLOON/AIRCRAFT VERTICAL POSITION
-        !            ----------------------------------
-        !
-        !
-        !*      5.1  Density
-        !            -------
-        !
-        ZEXN(:,:,:    ) = (PP(II_M:II_M+1,IJ_M:IJ_M+1,:)/XP00)**(XRD/XCPD)
-        DO JK=IKB-1,1,-1
-          ZEXN(:,:,JK) = 1.5 * ZEXN(:,:,JK+1) - 0.5 * ZEXN(:,:,JK+2)
-        END DO
-        DO JK=IKE+1,IKU
-          ZEXN(:,:,JK) = 1.5 * ZEXN(:,:,JK-1) - 0.5 * ZEXN(:,:,JK-2)
-        END DO
-        !
-        IF ( TPFLYER%CTYPE == 'ISODEN' .OR. TPFLYER%CTYPE == 'CVBALL' .OR. TPFLYER%CTYPE == 'AIRCRA' ) THEN
-          ZTHV(:,:,:) = PTH(II_M:II_M+1,IJ_M:IJ_M+1,:)
-          IF (SIZE(PR,4)>0)                                                     &
-          ZTHV(:,:,:) = ZTHV(:,:,:) * ( 1. + XRV/XRD*PR(II_M:II_M+1,IJ_M:IJ_M+1,:,1) )  &
-                                    / ( 1. + WATER_SUM(PR(II_M:II_M+1,IJ_M:IJ_M+1,:,:)) )
-          !
-          ZTV (:,:,:) = ZTHV(:,:,:) * ZEXN(:,:,:)
-          ZRHO(:,:,:) = PP(II_M:II_M+1,IJ_M:IJ_M+1,:) / (XRD*ZTV(:,:,:))
-          DO JK=IKB-1,1,-1
-            ZRHO(:,:,JK) = 1.5 * ZRHO(:,:,JK+1) - 0.5 * ZRHO(:,:,JK+2)
-          END DO
-          DO JK=IKE+1,IKU
-            ZRHO(:,:,JK) = 1.5 * ZRHO(:,:,JK-1) - 0.5 * ZRHO(:,:,JK-2)
-          END DO
-          ZTHW_FLUX(:,:,:) = ZRHO(:,:,:)*XCPD *XTHW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:)
-          ZRCW_FLUX(:,:,:) = ZRHO(:,:,:)*XLVTT*XRCW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:)
-          ZSVW_FLUX(:,:,:,:) = XSVW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:,:)
-        END IF
-          SELECT CASE ( TPFLYER%CTYPE )
-            !
-            !*      5.2.1 Iso-density balloon
-            !
-            CASE ( 'ISODEN' )
-              ZXCOEF = (TPFLYER%XX_CUR - XXHATM(II_M)) / (XXHATM(II_M+1) - XXHATM(II_M))
-              ZXCOEF = MAX (0.,MIN(ZXCOEF,1.))
-              ZYCOEF = (TPFLYER%XY_CUR - XYHATM(IJ_M)) / (XYHATM(IJ_M+1) - XYHATM(IJ_M))
-              ZYCOEF = MAX (0.,MIN(ZYCOEF,1.))
-              IF ( TPFLYER%XALTLAUNCH /= XNEGUNDEF ) THEN
-                IK00 = MAX ( COUNT (TPFLYER%XALTLAUNCH >= ZZM(1,1,:)), 1)
-                IK01 = MAX ( COUNT (TPFLYER%XALTLAUNCH >= ZZM(1,2,:)), 1)
-                IK10 = MAX ( COUNT (TPFLYER%XALTLAUNCH >= ZZM(2,1,:)), 1)
-                IK11 = MAX ( COUNT (TPFLYER%XALTLAUNCH >= ZZM(2,2,:)), 1)
-                ZZCOEF00 = (TPFLYER%XALTLAUNCH - ZZM(1,1,IK00)) / ( ZZM(1,1,IK00+1) - ZZM(1,1,IK00))
-                ZZCOEF01 = (TPFLYER%XALTLAUNCH - ZZM(1,2,IK01)) / ( ZZM(1,2,IK01+1) - ZZM(1,2,IK01))
-                ZZCOEF10 = (TPFLYER%XALTLAUNCH - ZZM(2,1,IK10)) / ( ZZM(2,1,IK10+1) - ZZM(2,1,IK10))
-                ZZCOEF11 = (TPFLYER%XALTLAUNCH - ZZM(2,2,IK11)) / ( ZZM(2,2,IK11+1) - ZZM(2,2,IK11))
-                TPFLYER%XRHO = FLYER_INTERP(ZRHO)
-              ELSE IF ( TPFLYER%XPRES /= XNEGUNDEF ) THEN
-                ZFLYER_EXN = (TPFLYER%XPRES/XP00)**(XRD/XCPD)
-                IK00 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,1,:)), 1)
-                IK01 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,2,:)), 1)
-                IK10 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,1,:)), 1)
-                IK11 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,2,:)), 1)
-                ZZCOEF00 = (ZFLYER_EXN - ZEXN(1,1,IK00)) / ( ZEXN(1,1,IK00+1) - ZEXN(1,1,IK00))
-                ZZCOEF01 = (ZFLYER_EXN - ZEXN(1,2,IK01)) / ( ZEXN(1,2,IK01+1) - ZEXN(1,2,IK01))
-                ZZCOEF10 = (ZFLYER_EXN - ZEXN(2,1,IK10)) / ( ZEXN(2,1,IK10+1) - ZEXN(2,1,IK10))
-                ZZCOEF11 = (ZFLYER_EXN - ZEXN(2,2,IK11)) / ( ZEXN(2,2,IK11+1) - ZEXN(2,2,IK11))
-                TPFLYER%XRHO = FLYER_INTERP(ZRHO)
-              ELSE
-                CMNHMSG(1) = 'Error in balloon initial position (balloon ' // TRIM(TPFLYER%CTITLE) // ' )'
-                CMNHMSG(2) = 'neither initial ALTITUDE or PRESsure is given'
-                CMNHMSG(3) = 'Check your INI_BALLOON routine'
-                CALL PRINT_MSG( NVERB_FATAL, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
-              END IF
-            !
-            !*      5.2.2 Radiosounding balloon
-            !
-            CASE ( 'RADIOS' )
-              TPFLYER%XZ_CUR = TPFLYER%XALTLAUNCH
-              TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(1,1,IKB) )
-              TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(2,1,IKB) )
-              TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(1,2,IKB) )
-              TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(2,2,IKB) )
-            !
-            !*      5.2.4 Constant Volume Balloon
-            !
-            CASE ( 'CVBALL' )
-              ZXCOEF = (TPFLYER%XX_CUR - XXHATM(II_M)) / (XXHATM(II_M+1) - XXHATM(II_M))
-              ZXCOEF = MAX (0.,MIN(ZXCOEF,1.))
-              ZYCOEF = (TPFLYER%XY_CUR - XYHATM(IJ_M)) / (XYHATM(IJ_M+1) - XYHATM(IJ_M))
-              ZYCOEF = MAX (0.,MIN(ZYCOEF,1.))
-              IF ( TPFLYER%XALTLAUNCH /= XNEGUNDEF ) THEN
-                IK00 = MAX ( COUNT (TPFLYER%XALTLAUNCH >= ZZM(1,1,:)), 1)
-                IK01 = MAX ( COUNT (TPFLYER%XALTLAUNCH >= ZZM(1,2,:)), 1)
-                IK10 = MAX ( COUNT (TPFLYER%XALTLAUNCH >= ZZM(2,1,:)), 1)
-                IK11 = MAX ( COUNT (TPFLYER%XALTLAUNCH >= ZZM(2,2,:)), 1)
-                IF (IK00*IK01*IK10*IK11 .EQ. 0) THEN
-                  TPFLYER%XZ_CUR = TPFLYER%XALTLAUNCH
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(1,1,IKB) )
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(2,1,IKB) )
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(1,2,IKB) )
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(2,2,IKB) )
-                ELSE
-                  ZZCOEF00 = (TPFLYER%XALTLAUNCH - ZZM(1,1,IK00)) / ( ZZM(1,1,IK00+1) - ZZM(1,1,IK00))
-                  ZZCOEF01 = (TPFLYER%XALTLAUNCH - ZZM(1,2,IK01)) / ( ZZM(1,2,IK01+1) - ZZM(1,2,IK01))
-                  ZZCOEF10 = (TPFLYER%XALTLAUNCH - ZZM(2,1,IK10)) / ( ZZM(2,1,IK10+1) - ZZM(2,1,IK10))
-                  ZZCOEF11 = (TPFLYER%XALTLAUNCH - ZZM(2,2,IK11)) / ( ZZM(2,2,IK11+1) - ZZM(2,2,IK11))
-                  TPFLYER%XRHO = FLYER_INTERP(ZRHO)
-                  TPFLYER%XZ_CUR = FLYER_INTERP(ZZM)
-                END IF
-              ELSE IF ( TPFLYER%XPRES /= XNEGUNDEF ) THEN
-                ZFLYER_EXN = (TPFLYER%XPRES/XP00)**(XRD/XCPD)
-                IK00 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,1,:)), 1)
-                IK01 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,2,:)), 1)
-                IK10 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,1,:)), 1)
-                IK11 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,2,:)), 1)
-                IF (IK00*IK01*IK10*IK11 .EQ. 0) THEN
-                  TPFLYER%XZ_CUR = ZZM(1,1,IKB)
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(2,1,IKB) )
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(1,2,IKB) )
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(2,2,IKB) )
-                ELSE
-                  ZZCOEF00 = (ZFLYER_EXN - ZEXN(1,1,IK00)) / ( ZEXN(1,1,IK00+1) - ZEXN(1,1,IK00))
-                  ZZCOEF01 = (ZFLYER_EXN - ZEXN(1,2,IK01)) / ( ZEXN(1,2,IK01+1) - ZEXN(1,2,IK01))
-                  ZZCOEF10 = (ZFLYER_EXN - ZEXN(2,1,IK10)) / ( ZEXN(2,1,IK10+1) - ZEXN(2,1,IK10))
-                  ZZCOEF11 = (ZFLYER_EXN - ZEXN(2,2,IK11)) / ( ZEXN(2,2,IK11+1) - ZEXN(2,2,IK11))
-                  TPFLYER%XRHO = FLYER_INTERP(ZRHO)
-                  TPFLYER%XZ_CUR = FLYER_INTERP(ZZM)
-                END IF
-              ELSE
-                TPFLYER%XRHO = TPFLYER%XMASS / TPFLYER%XVOLUME
-                IK00 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(1,1,:)), 1)
-                IK01 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(1,2,:)), 1)
-                IK10 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(2,1,:)), 1)
-                IK11 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(2,2,:)), 1)
-                IF (IK00*IK01*IK10*IK11 .EQ. 0) THEN
-                  TPFLYER%XZ_CUR = ZZM(1,1,IKB)
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(2,1,IKB) )
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(1,2,IKB) )
-                  TPFLYER%XZ_CUR = MAX ( TPFLYER%XZ_CUR , ZZM(2,2,IKB) )
-                ELSE
-                  ZZCOEF00 = (TPFLYER%XRHO - ZRHO(1,1,IK00)) / ( ZRHO(1,1,IK00+1) - ZRHO(1,1,IK00))
-                  ZZCOEF01 = (TPFLYER%XRHO - ZRHO(1,2,IK01)) / ( ZRHO(1,2,IK01+1) - ZRHO(1,2,IK01))
-                  ZZCOEF10 = (TPFLYER%XRHO - ZRHO(2,1,IK10)) / ( ZRHO(2,1,IK10+1) - ZRHO(2,1,IK10))
-                  ZZCOEF11 = (TPFLYER%XRHO - ZRHO(2,2,IK11)) / ( ZRHO(2,2,IK11+1) - ZRHO(2,2,IK11))
-                  TPFLYER%XZ_CUR = FLYER_INTERP(ZZM)
-                END IF
-              END IF
-          END SELECT
-        END IF LAUNCHVERTPOS
-        !
-        !
-        !
-        !*      5.3  Vertical position
-        !            -----------------
-!
-        IF ( TPFLYER%CTYPE == 'ISODEN' ) THEN
-          IK00 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(1,1,:)), 1)
-          IK01 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(1,2,:)), 1)
-          IK10 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(2,1,:)), 1)
-          IK11 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(2,2,:)), 1)
-        ELSE IF ( TPFLYER%CTYPE == 'RADIOS' .OR. TPFLYER%CTYPE == 'CVBALL' ) THEN
-          IK00 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(1,1,:)), 1)
-          IK01 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(1,2,:)), 1)
-          IK10 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(2,1,:)), 1)
-          IK11 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(2,2,:)), 1)
-        END IF
 
-        IF ( ANY( [ IK00, IK01, IK10, IK11 ] < IKB ) ) THEN
-          !Minimum altitude is on the ground at IKB (no crash if too low)
-          IK00 = MAX ( IK00, IKB )
-          IK01 = MAX ( IK01, IKB )
-          IK10 = MAX ( IK10, IKB )
-          IK11 = MAX ( IK11, IKB )
-
-          CMNHMSG(1) = 'flyer ' // TRIM( TPFLYER%CTITLE ) // ' is near the ground'
-          WRITE( CMNHMSG(2), "( 'at ', I2, '/', I2, '/', I4, ' ', F18.12, 's' )" ) &
-                TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
-          CALL PRINT_MSG( NVERB_INFO, 'GEN', 'AIRCRAFT_BALLOON_EVOL' , OLOCAL = .TRUE.)
-        END IF
+        CALL FLYER_INTERP_TO_MASSPOINTS()
+
+        ZEXN(:,:,:) = FLYER_COMPUTE_EXNER( )
+        ZRHO(:,:,:) = FLYER_COMPUTE_RHO( )
+
+        ZTHW_FLUX(:,:,:) = ZRHO(:,:,:)*XCPD *XTHW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:)
+        ZRCW_FLUX(:,:,:) = ZRHO(:,:,:)*XLVTT*XRCW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:)
+        ZSVW_FLUX(:,:,:,:) = XSVW_FLUX(II_M:II_M+1,IJ_M:IJ_M+1,:,:)
+
+        ! Compute coefficents for horizontal interpolations
+        CALL FLYER_COMPUTE_INTERP_COEFF_HOR_STAGE1( )
+
+        IF ( GLAUNCH ) CALL BALLOON_COMPUTE_INITIAL_VERTICAL_POSITION( TPFLYER )
+
+        ! Compute coefficents for vertical interpolations
+        CALL FLYER_COMPUTE_INTERP_COEFF_VER( )
 
-        !
-        !
-        !*      5.4  Crash of the balloon
-        !            --------------------
-        !
-        !
-        IF (IK00 <  IKB .OR. IK01 <  IKB .OR. IK10 <  IKB .OR. IK11 <  IKB ) THEN
-          TPFLYER%LCRASH = .TRUE.
-          TPFLYER%NCRASH = NCRASH_OUT_LOW
-        END IF
-        IF (IK00 >= IKE .OR. IK01 >= IKE .OR. IK10 >= IKE .OR. IK11 >= IKE  ) THEN
-          TPFLYER%LCRASH = .TRUE.
-          TPFLYER%NCRASH = NCRASH_OUT_HIGH
-        END IF
         CRASH_VERT: IF ( TPFLYER%LCRASH ) THEN
           TPFLYER%LFLY = .FALSE.
-        WRITE( CMNHMSG(1), "( 'Balloon ', A, ' crashed the ', I2, '/', I2, '/', I4, ' at ', F18.12, 's (too low or too high)' )" ) &
-               TRIM( TPFLYER%CTITLE ), TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
-        CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
+          WRITE( CMNHMSG(1), "( 'Balloon ', A, ' crashed the ', I2, '/', I2, '/', I4, ' at ', F18.12, &
+                                's (too low or too high)' )" )                                        &
+                 TRIM( TPFLYER%CTITLE ), TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
+          CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
         ELSE CRASH_VERT
           !No vertical crash
-          !
-          !*      6.   INITIALIZATIONS FOR INTERPOLATIONS
-          !            ----------------------------------
-          !
-          !*      6.1  Interpolation coefficient for X
-          !            -------------------------------
-          !
-          ZXCOEF = (TPFLYER%XX_CUR - XXHATM(II_M)) / (XXHATM(II_M+1) - XXHATM(II_M))
-          ZXCOEF = MAX (0.,MIN(ZXCOEF,1.))
-          !
-          !
-          !*      6.2  Interpolation coefficient for y
-          !            -------------------------------
-          !
-          ZYCOEF = (TPFLYER%XY_CUR - XYHATM(IJ_M)) / (XYHATM(IJ_M+1) - XYHATM(IJ_M))
-          ZYCOEF = MAX (0.,MIN(ZYCOEF,1.))
-          !
-          !
-          !*      6.3  Interpolation coefficients for the 4 suroundings verticals
-          !            ----------------------------------------------------------
-          !
-          !       SELECT TYPE ( TPFLYER )
-          !         CLASS IS ( TBALLOONDATA)
-          IF ( TPFLYER%CTYPE == 'ISODEN' ) THEN
-            ZZCOEF00 = (TPFLYER%XRHO - ZRHO(1,1,IK00)) / ( ZRHO(1,1,IK00+1) - ZRHO(1,1,IK00) )
-            ZZCOEF01 = (TPFLYER%XRHO - ZRHO(1,2,IK01)) / ( ZRHO(1,2,IK01+1) - ZRHO(1,2,IK01) )
-            ZZCOEF10 = (TPFLYER%XRHO - ZRHO(2,1,IK10)) / ( ZRHO(2,1,IK10+1) - ZRHO(2,1,IK10) )
-            ZZCOEF11 = (TPFLYER%XRHO - ZRHO(2,2,IK11)) / ( ZRHO(2,2,IK11+1) - ZRHO(2,2,IK11) )
-            TPFLYER%XZ_CUR = FLYER_INTERP(ZZM)
-          ELSE IF ( TPFLYER%CTYPE == 'RADIOS' .OR. TPFLYER%CTYPE == 'CVBALL' ) THEN
-            ZZCOEF00 = (TPFLYER%XZ_CUR - ZZM(1,1,IK00)) / ( ZZM(1,1,IK00+1) - ZZM(1,1,IK00) )
-            ZZCOEF01 = (TPFLYER%XZ_CUR - ZZM(1,2,IK01)) / ( ZZM(1,2,IK01+1) - ZZM(1,2,IK01) )
-            ZZCOEF10 = (TPFLYER%XZ_CUR - ZZM(2,1,IK10)) / ( ZZM(2,1,IK10+1) - ZZM(2,1,IK10) )
-            ZZCOEF11 = (TPFLYER%XZ_CUR - ZZM(2,2,IK11)) / ( ZZM(2,2,IK11+1) - ZZM(2,2,IK11) )
-          END IF
-          !----------------------------------------------------------------------------
-          !
-          !*      7.   INITIALIZATIONS FOR INTERPOLATIONS OF U AND V
-          !            ---------------------------------------------
-          !
-          !*      7.1  Interpolation coefficient for X (for U)
-          !            -------------------------------
-          !
-          ZUCOEF = (TPFLYER%XX_CUR - XXHAT(II_U)) / (XXHAT(II_U+1) - XXHAT(II_U))
-          ZUCOEF = MAX(0.,MIN(ZUCOEF,1.))
-          !
-          !
-          !*      7.2  Interpolation coefficient for y (for V)
-          !            -------------------------------
-          !
-          ZVCOEF = (TPFLYER%XY_CUR - XYHAT(IJ_V)) / (XYHAT(IJ_V+1) - XYHAT(IJ_V))
-          ZVCOEF = MAX(0.,MIN(ZVCOEF,1.))
-          !
-          !
-          !*      7.3  Interpolation coefficients for the 4 suroundings verticals (for U)
-          !            ----------------------------------------------------------
-          !
-          IU00 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(1,1,:)), 1)
-          IU01 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(1,2,:)), 1)
-          IU10 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(2,1,:)), 1)
-          IU11 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(2,2,:)), 1)
-          ZUCOEF00 = (TPFLYER%XZ_CUR - ZZU(1,1,IU00)) / ( ZZU(1,1,IU00+1) - ZZU(1,1,IU00) )
-          ZUCOEF01 = (TPFLYER%XZ_CUR - ZZU(1,2,IU01)) / ( ZZU(1,2,IU01+1) - ZZU(1,2,IU01) )
-          ZUCOEF10 = (TPFLYER%XZ_CUR - ZZU(2,1,IU10)) / ( ZZU(2,1,IU10+1) - ZZU(2,1,IU10) )
-          ZUCOEF11 = (TPFLYER%XZ_CUR - ZZU(2,2,IU11)) / ( ZZU(2,2,IU11+1) - ZZU(2,2,IU11) )
-          !
-          !
-          !*      7.4  Interpolation coefficients for the 4 suroundings verticals (for V)
-          !            ----------------------------------------------------------
-          !
-          IV00 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(1,1,:)), 1)
-          IV01 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(1,2,:)), 1)
-          IV10 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(2,1,:)), 1)
-          IV11 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(2,2,:)), 1)
-          ZVCOEF00 = (TPFLYER%XZ_CUR - ZZV(1,1,IV00)) / ( ZZV(1,1,IV00+1) - ZZV(1,1,IV00) )
-          ZVCOEF01 = (TPFLYER%XZ_CUR - ZZV(1,2,IV01)) / ( ZZV(1,2,IV01+1) - ZZV(1,2,IV01) )
-          ZVCOEF10 = (TPFLYER%XZ_CUR - ZZV(2,1,IV10)) / ( ZZV(2,1,IV10+1) - ZZV(2,1,IV10) )
-          ZVCOEF11 = (TPFLYER%XZ_CUR - ZZV(2,2,IV11)) / ( ZZV(2,2,IV11+1) - ZZV(2,2,IV11) )
+
+          ! Compute coefficents for horizontal interpolations
+          CALL FLYER_COMPUTE_INTERP_COEFF_HOR_STAGE2( )
 
           ! Check if it is the right moment to store data
           IF ( TPFLYER%LSTORE ) THEN
             ISTORE = TPFLYER%TFLYER_TIME%N_CUR
             IF ( ABS( TDTCUR - TPFLYER%TFLYER_TIME%TPDATES(ISTORE) ) < 1e-10 ) THEN
-              !
-              !*      2.   PRELIMINARIES-2
-              !            -------------
-              !
-              !*      2.1  Indices
-              !            -------
-              !
-              CALL GET_INDICE_ll (IIB,IJB,IIE,IJE)
-
-              IKB =   1   + JPVEXT
-              IKE = SIZE(PZ,3) - JPVEXT
-              !
-              !
-              !*      2.2  Interpolations of model variables to mass points
-              !            ------------------------------------------------
-              !
-              IIU=SIZE(XXHAT)
-              IJU=SIZE(XYHAT)
-
-              TPFLYER%NMODELHIST(ISTORE) = TPFLYER%NMODEL
-              TPFLYER%XX   (ISTORE) = TPFLYER%XX_CUR
-              TPFLYER%XY   (ISTORE) = TPFLYER%XY_CUR
-              TPFLYER%XZ   (ISTORE) = TPFLYER%XZ_CUR
-              !
-              CALL SM_LATLON(PLATOR,PLONOR,          &
-                          TPFLYER%XX_CUR, TPFLYER%XY_CUR,       &
-                          TPFLYER%XLAT(ISTORE), TPFLYER%XLON(ISTORE)  )
-              !
-              ZU_BAL = FLYER_INTERP_U(PU)
-              ZV_BAL = FLYER_INTERP_V(PV)
-              ZGAM   = (XRPK * (TPFLYER%XLON(ISTORE) - XLON0) - XBETA)*(XPI/180.)
-              TPFLYER%XZON (ISTORE) = ZU_BAL * COS(ZGAM) + ZV_BAL * SIN(ZGAM)
-              TPFLYER%XMER (ISTORE) = - ZU_BAL * SIN(ZGAM) + ZV_BAL * COS(ZGAM)
-              !
-              TPFLYER%XW   (ISTORE) = FLYER_INTERP(ZWM)
-              TPFLYER%XTH  (ISTORE) = FLYER_INTERP(PTH)
-              !
-              ZFLYER_EXN = FLYER_INTERP(ZEXN)
-              TPFLYER%XP   (ISTORE) = XP00 * ZFLYER_EXN**(XCPD/XRD)
-              !
-              ZR(:,:,:) = 0.
-              DO JLOOP=1,SIZE(PR,4)
-                TPFLYER%XR   (ISTORE,JLOOP) = FLYER_INTERP(PR(:,:,:,JLOOP))
-                IF (JLOOP>=2) ZR(:,:,:) = ZR(:,:,:) + PR(:,:,:,JLOOP)
-              END DO
-              DO JLOOP=1,SIZE(PSV,4)
-                TPFLYER%XSV  (ISTORE,JLOOP) = FLYER_INTERP(PSV(:,:,:,JLOOP))
-              END DO
-              TPFLYER%XRTZ  (ISTORE,:) = FLYER_INTERPZ(ZR(:,:,:))
-              DO JLOOP=1,SIZE(PR,4)
-                TPFLYER%XRZ  (ISTORE,:,JLOOP) = FLYER_INTERPZ(PR(:,:,:,JLOOP))
-              END DO
-              ! Fin Modifs ON
-              TPFLYER%XFFZ  (ISTORE,:) = FLYER_INTERPZ(SQRT(PU**2+PV**2))
-              IF (CCLOUD=="LIMA") THEN
-                TPFLYER%XCIZ  (ISTORE,:) = FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NI))
-                TPFLYER%XCCZ  (ISTORE,:) = FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NC))
-                TPFLYER%XCRZ  (ISTORE,:) = FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NR))
-              ELSE IF ( CCLOUD=="ICE3" .OR. CCLOUD=="ICE4" ) THEN
-                TPFLYER%XCIZ  (ISTORE,:) = FLYER_INTERPZ(PCIT(:,:,:))
-              ENDIF
-              ! initialization CRARE and CRARE_ATT + LWC and IWC
-              TPFLYER%XCRARE(ISTORE,:) = 0.
-              TPFLYER%XCRARE_ATT(ISTORE,:) = 0.
-              TPFLYER%XLWCZ  (ISTORE,:) = 0.
-              TPFLYER%XIWCZ  (ISTORE,:) = 0.
-              IF (CCLOUD=="LIMA" .OR. CCLOUD=="ICE3" ) THEN ! only for ICE3 and LIMA
-                TPFLYER%XLWCZ  (ISTORE,:) = FLYER_INTERPZ((PR(:,:,:,2)+PR(:,:,:,3))*PRHODREF(:,:,:))
-                TPFLYER%XIWCZ  (ISTORE,:) = FLYER_INTERPZ((PR(:,:,:,4)+PR(:,:,:,5)+PR(:,:,:,6))*PRHODREF(:,:,:))
-                ZTEMPZ(:)=FLYER_INTERPZ(PTH(II_M:II_M+1,IJ_M:IJ_M+1,:) * ZEXN(:,:,:))
-                ZRHODREFZ(:)=FLYER_INTERPZ(PRHODREF(:,:,:))
-                IF (CCLOUD=="LIMA") THEN
-                  ZCCI(:)=FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NI))
-                  ZCCR(:)=FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NR))
-                  ZCCC(:)=FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NC))
-                ELSE
-                  ZCIT(:)=FLYER_INTERPZ(PCIT(:,:,:))
-                ENDIF
-                DO JLOOP=3,6
-                  ZRZ(:,JLOOP)=FLYER_INTERPZ(PR(:,:,:,JLOOP))
-                END DO
-                if ( csurf == 'EXTE' ) then
-                  DO JK=1,IKU
-                    ZRZ(JK,2)=FLYER_INTERP_2D(PR(:,:,JK,2)*PSEA(:,:))       ! becomes cloud mixing ratio over sea
-                    ZRZ(JK,7)=FLYER_INTERP_2D(PR(:,:,JK,2)*(1.-PSEA(:,:)))  ! becomes cloud mixing ratio over land
-                  END DO
-                else
-                  !if csurf/='EXTE', psea is not allocated
-                  DO JK=1,IKU
-                    ZRZ(JK,2)=FLYER_INTERP_2D(PR(:,:,JK,2))
-                    ZRZ(JK,7) = 0.
-                  END DO
-                end if
-                ALLOCATE(ZAELOC(IKU))
-                !
-                ZAELOC(:)=0.
-                ! initialization of quadrature points and weights
-                ALLOCATE(ZX(JPTS_GAULAG),ZW(JPTS_GAULAG))
-                CALL GAULAG(JPTS_GAULAG,ZX,ZW) ! for integration over diameters
-                ! initialize minimum values
-                ALLOCATE(ZRTMIN(SIZE(PR,4)+1))
-                IF (CCLOUD == 'LIMA') THEN
-                  ZRTMIN(2)=XRTMIN_L(2) ! cloud water over sea
-                  ZRTMIN(3)=XRTMIN_L(3)
-                  ZRTMIN(4)=XRTMIN_L(4)
-                  ZRTMIN(5)=1E-10
-                  ZRTMIN(6)=XRTMIN_L(6)
-                  ZRTMIN(7)=XRTMIN_L(2) ! cloud water over land
-                ELSE
-                  ZRTMIN(2)=XRTMIN_I(2) ! cloud water over sea
-                  ZRTMIN(3)=XRTMIN_I(3)
-                  ZRTMIN(4)=XRTMIN_I(4)
-                  ZRTMIN(5)=1E-10
-                  ZRTMIN(6)=XRTMIN_I(6)
-                  ZRTMIN(7)=XRTMIN_I(2) ! cloud water over land
-                ENDIF
-                ! compute cloud radar reflectivity from vertical profiles of temperature and mixing ratios
-                DO JK=1,IKU
-                  QMW=SQRT(QEPSW(ZTEMPZ(JK),XLIGHTSPEED/XLAM_CRAD))
-                  QMI=SQRT(QEPSI(ZTEMPZ(JK),XLIGHTSPEED/XLAM_CRAD))
-                  DO JLOOP=2,7
-                    IF (CCLOUD == 'LIMA') THEN
-                      GCALC=(ZRZ(JK,JLOOP)>ZRTMIN(JLOOP).AND.(JLOOP.NE.4.OR.ZCCI(JK)>0.).AND.&
-                            (JLOOP.NE.3.OR.ZCCR(JK)>0.).AND.((JLOOP.NE.2.AND. JLOOP.NE.7).OR.ZCCC(JK)>0.))
-                    ELSE
-                      GCALC=(ZRZ(JK,JLOOP)>ZRTMIN(JLOOP).AND.(JLOOP.NE.4.OR.ZCIT(JK)>0.))
-                    ENDIF
-                    IF(GCALC) THEN
-                      SELECT CASE(JLOOP)
-                        CASE(2) ! cloud water over sea
-                          IF (CCLOUD == 'LIMA') THEN
-                            ZA=XAC_L
-                            ZB=XBC_L
-                            ZCC=ZCCC(JK)*ZRHODREFZ(JK)
-                            ZCX=0.
-                            ZALPHA=XALPHAC_L
-                            ZNU=XNUC_L
-                            ZLBEX=1.0/(ZCX-ZB)
-                            ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                          ELSE
-                            ZA=XAC_I
-                            ZB=XBC_I
-                            ZCC=XCONC_SEA
-                            ZCX=0.
-                            ZALPHA=XALPHAC2_I
-                            ZNU=XNUC2_I
-                            ZLBEX=1.0/(ZCX-ZB)
-                            ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                          ENDIF
-                        CASE(3) ! rain water
-                          IF (CCLOUD == 'LIMA') THEN
-                            ZA=XAR_L
-                            ZB=XBR_L
-                            ZCC=ZCCR(JK)*ZRHODREFZ(JK)
-                            ZCX=0.
-                            ZALPHA=XALPHAR_L
-                            ZNU=XNUR_L
-                            ZLBEX=1.0/(ZCX-ZB)
-                            ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                          ELSE
-                            ZA=XAR_I
-                            ZB=XBR_I
-                            ZCC=XCCR_I
-                            ZCX=-1.
-                            ZALPHA=XALPHAR_I
-                            ZNU=XNUR_I
-                            ZLB=XLBR_I
-                            ZLBEX=XLBEXR_I
-                          ENDIF
-                        CASE(4) ! pristine ice
-                          IF (CCLOUD == 'LIMA') THEN
-                            ZA=XAI_L
-                            ZB=XBI_L
-                            ZCC=ZCCI(JK)*ZRHODREFZ(JK)
-                            ZCX=0.
-                            ZALPHA=XALPHAI_L
-                            ZNU=XNUI_L
-                            ZLBEX=1.0/(ZCX-ZB)
-                            ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX) ! because ZCC not included in XLBI
-                            ZFW=0
-                          ELSE
-                            ZA=XAI_I
-                            ZB=XBI_I
-                            ZCC=ZCIT(JK)
-                            ZCX=0.
-                            ZALPHA=XALPHAI_I
-                            ZNU=XNUI_I
-                            ZLBEX=XLBEXI_I
-                            ZLB=XLBI_I*ZCC**(-ZLBEX) ! because ZCC not included in XLBI
-                            ZFW=0
-                          ENDIF
-                        CASE(5) ! snow
-                          IF (CCLOUD == 'LIMA') THEN
-                            ZA=XAS_L
-                            ZB=XBS_L
-                            ZCC=XCCS_L
-                            ZCX=XCXS_L
-                            ZALPHA=XALPHAS_L
-                            ZNU=XNUS_L
-                            ZLB=XLBS_L
-                            ZLBEX=XLBEXS_L
-                            ZFW=0
-                          ELSE
-                            ZA=XAS_I
-                            ZB=XBS_I
-                            ZCC=XCCS_I
-                            ZCX=XCXS_I
-                            ZALPHA=XALPHAS_I
-                            ZNU=XNUS_I
-                            ZLB=XLBS_I
-                            ZLBEX=XLBEXS_I
-                            ZFW=0
-                          ENDIF
-                        CASE(6) ! graupel
-                          !If temperature between -10 and 10°C and Mr and Mg over min threshold: melting graupel
-                          ! with liquid water fraction Fw=Mr/(Mr+Mg) else dry graupel (Fw=0)
-                          IF( ZTEMPZ(JK) > XTT-10 .AND. ZTEMPZ(JK) < XTT+10 &
-                            .AND. ZRZ(JK,3) > ZRTMIN(3) ) THEN
-                            ZFW=ZRZ(JK,3)/(ZRZ(JK,3)+ZRZ(JK,JLOOP))
-                          ELSE
-                            ZFW=0
-                          ENDIF
-                          IF (CCLOUD == 'LIMA') THEN
-                            ZA=XAG_L
-                            ZB=XBG_L
-                            ZCC=XCCG_L
-                            ZCX=XCXG_L
-                            ZALPHA=XALPHAG_L
-                            ZNU=XNUG_L
-                            ZLB=XLBG_L
-                            ZLBEX=XLBEXG_L
-                          ELSE
-                            ZA=XAG_I
-                            ZB=XBG_I
-                            ZCC=XCCG_I
-                            ZCX=XCXG_I
-                            ZALPHA=XALPHAG_I
-                            ZNU=XNUG_I
-                            ZLB=XLBG_I
-                            ZLBEX=XLBEXG_I
-                          ENDIF
-                        CASE(7) ! cloud water over land
-                          IF (CCLOUD == 'LIMA') THEN
-                            ZA=XAC_L
-                            ZB=XBC_L
-                            ZCC=ZCCC(JK)*ZRHODREFZ(JK)
-                            ZCX=0.
-                            ZALPHA=XALPHAC_L
-                            ZNU=XNUC_L
-                            ZLBEX=1.0/(ZCX-ZB)
-                            ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                          ELSE
-                            ZA=XAC_I
-                            ZB=XBC_I
-                            ZCC=XCONC_LAND
-                            ZCX=0.
-                            ZALPHA=XALPHAC_I
-                            ZNU=XNUC_I
-                            ZLBEX=1.0/(ZCX-ZB)
-                            ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
-                          ENDIF
-                      END SELECT
-                      ZLBDA=ZLB*(ZRHODREFZ(JK)*ZRZ(JK,JLOOP))**ZLBEX
-                      ZREFLOC=0.
-                      ZAETMP=0.
-                      DO JJ=1,JPTS_GAULAG ! Gauss-Laguerre quadrature
-                        ZDELTA_EQUIV=ZX(JJ)**(1./ZALPHA)/ZLBDA
-                        SELECT CASE(JLOOP)
-                          CASE(2,3,7)
-                            QM=QMW
-                          CASE(4,5,6)
-                            ! pristine ice, snow, dry graupel
-                            ZRHOHYD=MIN(6.*ZA*ZDELTA_EQUIV**(ZB-3.)/XPI,.92*XRHOLW)
-                            QM=sqrt(MG(QMI**2,CMPLX(1,0),ZRHOHYD/.92/XRHOLW))
-
-                            ! water inclusions in ice in air
-                            QEPSWI=MG(QMW**2,QM**2,ZFW)
-                            ! ice in air inclusions in water
-                            QEPSIW=MG(QM**2,QMW**2,1.-ZFW)
-
-                            !MG weighted rule (Matrosov 2008)
-                            IF(ZFW .LT. 0.37) THEN
-                              ZFPW=0
-                            ELSE IF(ZFW .GT. 0.63) THEN
-                              ZFPW=1
-                            ELSE
-                              ZFPW=(ZFW-0.37)/(0.63-0.37)
-                            ENDIF
-                            QM=sqrt(QEPSWI*(1.-ZFPW)+QEPSIW*ZFPW)
-                        END SELECT
-                        CALL BHMIE(XPI/XLAM_CRAD*ZDELTA_EQUIV,QM,ZQEXT,ZQSCA,ZQBACK)
-                        ZREFLOC=ZREFLOC+ZQBACK*ZX(JJ)**(ZNU-1)*ZDELTA_EQUIV**2*ZW(JJ)
-                        ZAETMP =ZAETMP +ZQEXT *ZX(JJ)**(ZNU-1)*ZDELTA_EQUIV**2*ZW(JJ)
-                      END DO
-                      ZREFLOC=ZREFLOC*(XLAM_CRAD/XPI)**4*ZCC*ZLBDA**ZCX/(4.*GAMMA(ZNU)*.93)
-                      ZAETMP=ZAETMP  *           XPI    *ZCC*ZLBDA**ZCX/(4.*GAMMA(ZNU))
-                      TPFLYER%XCRARE(ISTORE,JK)=TPFLYER%XCRARE(ISTORE,JK)+ZREFLOC
-                      ZAELOC(JK)=ZAELOC(JK)+ZAETMP
-                    END IF
-                  END DO
-                END DO
-
-                ! apply attenuation
-                ALLOCATE(ZZMZ(IKU))
-                ZZMZ(:)=FLYER_INTERPZ(ZZM(:,:,:))
-                ! nadir
-                ZAETOT=1.
-                DO JK=COUNT(TPFLYER%XZ_CUR >= ZZMZ(:)),1,-1
-                  IF(JK.EQ.COUNT(TPFLYER%XZ_CUR >= ZZMZ(:))) THEN
-                    IF(TPFLYER%XZ_CUR<=ZZMZ(JK)+.5*(ZZMZ(JK+1)-ZZMZ(JK))) THEN
-                      ! only attenuation from ZAELOC(JK)
-                      ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK)*(TPFLYER%XZ_CUR-ZZMZ(JK))))
-                    ELSE
-                      ! attenuation from ZAELOC(JK) and ZAELOC(JK+1)
-                      ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK+1)*(TPFLYER%XZ_CUR-.5*(ZZMZ(JK+1)+ZZMZ(JK))) &
-                        +ZAELOC(JK)*.5*(ZZMZ(JK+1)-ZZMZ(JK))))
-                    END IF
-                  ELSE
-                    ! attenuation from ZAELOC(JK) and ZAELOC(JK+1)
-                    ZAETOT=ZAETOT*EXP(-(ZAELOC(JK+1)+ZAELOC(JK))*(ZZMZ(JK+1)-ZZMZ(JK)))
-                  END IF
-                  TPFLYER%XCRARE_ATT(ISTORE,JK)=TPFLYER%XCRARE(ISTORE,JK)*ZAETOT
-                END DO
-                ! zenith
-                ZAETOT=1.
-                DO JK = MAX(COUNT(TPFLYER%XZ_CUR >= ZZMZ(:)),1)+1,IKU
-                  IF ( JK .EQ. (MAX(COUNT(TPFLYER%XZ_CUR >= ZZMZ(:)),1)+1) ) THEN
-                    IF(TPFLYER%XZ_CUR>=ZZMZ(JK)-.5*(ZZMZ(JK)-ZZMZ(JK-1))) THEN
-                      ! only attenuation from ZAELOC(JK)
-                      ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK)*(ZZMZ(JK)-TPFLYER%XZ_CUR)))
-                    ELSE
-                      ! attenuation from ZAELOC(JK) and ZAELOC(JK-1)
-                      ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK-1)*(.5*(ZZMZ(JK)+ZZMZ(JK-1))-TPFLYER%XZ_CUR) &
-                        +ZAELOC(JK)*.5*(ZZMZ(JK)-ZZMZ(JK-1))))
-                    END IF
-                  ELSE
-                    ! attenuation from ZAELOC(JK) and ZAELOC(JK-1)
-                    ZAETOT=ZAETOT*EXP(-(ZAELOC(JK-1)+ZAELOC(JK))*(ZZMZ(JK)-ZZMZ(JK-1)))
-                  END IF
-                  TPFLYER%XCRARE_ATT(ISTORE,JK)=TPFLYER%XCRARE(ISTORE,JK)*ZAETOT
-                END DO
-                TPFLYER%XZZ  (ISTORE,:) = ZZMZ(:)
-                DEALLOCATE(ZZMZ,ZAELOC)
-                ! m^3 → mm^6/m^3 → dBZ
-                WHERE(TPFLYER%XCRARE(ISTORE,:)>0)
-                  TPFLYER%XCRARE(ISTORE,:)=10.*LOG10(1.E18*TPFLYER%XCRARE(ISTORE,:))
-                ELSEWHERE
-                  TPFLYER%XCRARE(ISTORE,:)=XUNDEF
-                END WHERE
-                WHERE(TPFLYER%XCRARE_ATT(ISTORE,:)>0)
-                  TPFLYER%XCRARE_ATT(ISTORE,:)=10.*LOG10(1.E18*TPFLYER%XCRARE_ATT(ISTORE,:))
-                ELSEWHERE
-                  TPFLYER%XCRARE_ATT(ISTORE,:)=XUNDEF
-                END WHERE
-                DEALLOCATE(ZX,ZW,ZRTMIN)
-              END IF ! end LOOP ICE3
-              ! vertical wind
-              TPFLYER%XWZ  (ISTORE,:) = FLYER_INTERPZ(ZWM(:,:,:))
-              IF (SIZE(PTKE)>0) TPFLYER%XTKE  (ISTORE)    = FLYER_INTERP(PTKE)
-              IF (SIZE(PTS) >0) TPFLYER%XTSRAD(ISTORE)    = FLYER_INTERP_2D(PTS)
-              IF (LDIAG_IN_RUN) TPFLYER%XTKE_DISS(ISTORE) = FLYER_INTERP(XCURRENT_TKE_DISS)
-              TPFLYER%XZS(ISTORE)  = FLYER_INTERP_2D(PZ(:,:,1+JPVEXT))
-              TPFLYER%XTHW_FLUX(ISTORE) = FLYER_INTERP(ZTHW_FLUX)
-              TPFLYER%XRCW_FLUX(ISTORE) = FLYER_INTERP(ZRCW_FLUX)
-              DO JLOOP=1,SIZE(PSV,4)
-              TPFLYER%XSVW_FLUX(ISTORE,JLOOP) = FLYER_INTERP(ZSVW_FLUX(:,:,:,JLOOP))
-              END DO
-            END IF
-          END IF
-          !
-          !----------------------------------------------------------------------------
-          !
-          !*      9.   BALLOON ADVECTION
-          !            -----------------
-          !
-          !       SELECT TYPE ( TPFLYER )
-          !         CLASS IS ( TBALLOONDATA)
-          ZTSTEP = PTSTEP
-
-          IF ( TPFLYER%CTYPE == 'RADIOS' .OR. TPFLYER%CTYPE == 'ISODEN' .OR. TPFLYER%CTYPE == 'CVBALL' ) THEN
-            ZU_BAL = FLYER_INTERP_U(PU)
-            ZV_BAL = FLYER_INTERP_V(PV)
-            if ( .not. lcartesian ) then
-              ZMAP = FLYER_INTERP_2D(PMAP)
-            else
-              ZMAP = 1.
-            end if
-            !
-            ZX_OLD = TPFLYER%XX_CUR
-            ZY_OLD = TPFLYER%XY_CUR
-
-            TPFLYER%XX_CUR = TPFLYER%XX_CUR + ZU_BAL * ZTSTEP * ZMAP
-            TPFLYER%XY_CUR = TPFLYER%XY_CUR + ZV_BAL * ZTSTEP * ZMAP
-          END IF
-          !
-          !Compute rank and model for next position
-          !This is done here because we need to check if there is a change of model (for 'MOB' balloons)
-          !because position has to be adapted to the timestep of a coarser model (if necessary)
-          IMODEL_OLD = TPFLYER%NMODEL
-          ! Get rank of the process where the balloon is and the model number
-          IF ( TPFLYER%CMODEL == 'FIX' ) THEN
-            IMODEL = TPFLYER%NMODEL
-          ELSE
-            IMODEL = 0
-          END IF
-          CALL FIND_PROCESS_AND_MODEL_FROM_XY_POS( TPFLYER%XX_CUR, TPFLYER%XY_CUR, IRANK, IMODEL )
-          IF ( IRANK < 1 ) THEN
-            TPFLYER%NMODEL = 1 !Set to 1 because it is always a valid model (to prevent crash if NDAD(TPFLYER%NMODEL) )
-            TPFLYER%LCRASH = .TRUE.
-            TPFLYER%NCRASH = NCRASH_OUT_HORIZ
-            TPFLYER%LFLY   = .FALSE.
-            WRITE( CMNHMSG(1), "( 'Balloon ', A, ' crashed the ', I2, '/', I2, '/', I4, ' at ', F18.12, &
-                                's (out of the horizontal boundaries)' )" ) &
-              TRIM( TPFLYER%CTITLE ), TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
-            CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
-          ELSE
-            TPFLYER%NMODEL = IMODEL
-            TPFLYER%LCRASH = .FALSE.
-            TPFLYER%NCRASH = NCRASH_NO
-            TPFLYER%NRANK_CUR = IRANK
-          END IF
-          IF ( TPFLYER%NMODEL /= IMODEL_OLD .AND. .NOT. TPFLYER%LCRASH ) THEN
-            IF ( NDAD(TPFLYER%NMODEL ) == IMODEL_OLD ) THEN
-              !Nothing special to do
-            ELSE IF ( TPFLYER%NMODEL == NDAD(IMODEL_OLD) ) THEN
-              !Recompute position to be compatible with parent timestep
-
-              !Determine step compatible with parent model at next parent timestep
-              ZDELTATIME = TDTCUR - TDTSEG
-              ZDIVTMP = ZDELTATIME / ( PTSTEP * NDTRATIO(IMODEL_OLD) )
-              IF ( ABS( ZDIVTMP - NINT( ZDIVTMP ) ) < 1E-6 * PTSTEP * NDTRATIO(IMODEL_OLD) ) THEN
-                ZTSTEP = ZTSTEP * NDTRATIO(IMODEL_OLD)
-              ELSE
-                ZTSTEP = ZTSTEP * ( 1 + NDTRATIO(IMODEL_OLD) )
-                ! Detect if we need to skip a store (if time of next position is after time of next store)
-                ! This can happen when a ballon goes to its parent model
-                IF ( TDTCUR + ZTSTEP > &
-                     TPFLYER%TFLYER_TIME%TPDATES(TPFLYER%TFLYER_TIME%N_CUR) + TPFLYER%TFLYER_TIME%XTSTEP + 1e-6 ) THEN
-                  TPFLYER%TFLYER_TIME%N_CUR = TPFLYER%TFLYER_TIME%N_CUR + 1
-                  ISTORE = TPFLYER%TFLYER_TIME%N_CUR
-                  !Remark: by construction here, ISTORE is always > 1 => no risk with ISTORE-1 value
-                  TPFLYER%TFLYER_TIME%TPDATES(ISTORE) = TPFLYER%TFLYER_TIME%TPDATES(ISTORE-1) + TPFLYER%TFLYER_TIME%XTSTEP
-
-                  !Force a dummy store (nothing is computed, therefore default/initial values will be stored)
-                  TPFLYER%LSTORE = .TRUE.
-
-                  WRITE( CMNHMSG(1), "( 'Balloon ', A, ': store skipped at ', I2, '/', I2, '/', I4, ' at ', F18.12, 's' )" ) &
-                         TRIM( TPFLYER%CTITLE ),                                                                             &
-                         TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%NDAY,  TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%NMONTH,              &
-                         TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%NYEAR, TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%XTIME
-                  CMNHMSG(2) = 'due to change of model (child to its parent)'
-                  CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
-                END IF
-              END IF
-
-              TPFLYER%XX_CUR = TPFLYER%XX_CUR + ZU_BAL * ZTSTEP * ZMAP
-              TPFLYER%XY_CUR = TPFLYER%XY_CUR + ZV_BAL * ZTSTEP * ZMAP
-
-              ! Model number is now imposed
-              IMODEL = TPFLYER%NMODEL
-              CALL FIND_PROCESS_AND_MODEL_FROM_XY_POS( TPFLYER%XX_CUR, TPFLYER%XY_CUR, IRANK, IMODEL )
-              IF ( IRANK < 1 ) THEN
-                TPFLYER%NMODEL = 1 !Set to 1 because it is always a valid model (to prevent crash if NDAD(TPFLYER%NMODEL) )
-                TPFLYER%LCRASH = .TRUE.
-                TPFLYER%NCRASH = NCRASH_OUT_HORIZ
-                TPFLYER%LFLY   = .FALSE.
-                WRITE( CMNHMSG(1), "( 'Balloon ', A, ' crashed the ', I2, '/', I2, '/', I4, ' at ', F18.12, &
-                       's (out of the horizontal boundaries)' )" )                                          &
-                       TRIM( TPFLYER%CTITLE ), TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
-                CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
-              ELSE
-                !TPFLYER%NMODEL = IMODEL !Do not change model because we are in transition to parent
-                TPFLYER%LCRASH = .FALSE.
-                TPFLYER%NCRASH = NCRASH_NO
-                TPFLYER%NRANK_CUR = IRANK
-              END IF
-            ELSE
-              !Special case not-managed (different dads, change of several models in 1 step (going to grand parent)...)
-              CMNHMSG(1) = 'unmanaged change of model for ballon ' // TPFLYER%CTITLE
-              CMNHMSG(2) = 'its trajectory might be wrong'
-              CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
+              CALL FLYER_RECORD_DATA( )
             END IF
           END IF
 
-          IF ( TPFLYER%CTYPE == 'RADIOS' ) THEN
-            ZW_BAL = FLYER_INTERP(ZWM)
-            TPFLYER%XZ_CUR = TPFLYER%XZ_CUR + ( ZW_BAL + TPFLYER%XWASCENT ) * ZTSTEP
-          END IF
-          !
-          IF ( TPFLYER%CTYPE == 'CVBALL' ) THEN
-            ZW_BAL = FLYER_INTERP(ZWM)
-            ZRO_BAL = FLYER_INTERP(ZRHO)
-            ! calculation with a time step of 1 second or less
-            IF (INT(ZTSTEP) .GT. 1 ) THEN
-              DO JK=1,INT(ZTSTEP)
-                TPFLYER%XWASCENT = TPFLYER%XWASCENT &
-                  -  ( 1. / (1. + TPFLYER%XINDDRAG ) ) * 1. * &
-                     ( XG * ( ( TPFLYER%XMASS / TPFLYER%XVOLUME ) - ZRO_BAL ) / ( TPFLYER%XMASS / TPFLYER%XVOLUME ) &
-                        + TPFLYER%XWASCENT * ABS ( TPFLYER%XWASCENT ) * &
-                          TPFLYER%XDIAMETER * TPFLYER%XAERODRAG / ( 2. * TPFLYER%XVOLUME ) &
-                      )
-                TPFLYER%XZ_CUR = TPFLYER%XZ_CUR + ( ZW_BAL + TPFLYER%XWASCENT ) * 1.
-              END DO
-            END IF
-            IF (ZTSTEP .GT. INT(ZTSTEP)) THEN
-              TPFLYER%XWASCENT = TPFLYER%XWASCENT &
-                -  ( 1. / (1. + TPFLYER%XINDDRAG ) ) * (ZTSTEP-INT(ZTSTEP)) * &
-                   ( XG * ( ( TPFLYER%XMASS / TPFLYER%XVOLUME ) - ZRO_BAL ) / ( TPFLYER%XMASS / TPFLYER%XVOLUME ) &
-                      + TPFLYER%XWASCENT * ABS ( TPFLYER%XWASCENT ) * &
-                        TPFLYER%XDIAMETER * TPFLYER%XAERODRAG / ( 2. * TPFLYER%XVOLUME ) &
-                    )
-              TPFLYER%XZ_CUR = TPFLYER%XZ_CUR + ( ZW_BAL + TPFLYER%XWASCENT ) * (ZTSTEP-INT(ZTSTEP))
-            END IF
-          END IF
+          ! Compute next horizontal position (balloon advection)
+          CALL BALLOON_ADVECTION_HOR( TPFLYER )
+
+          ! Compute next vertical position (balloon advection)
+          CALL BALLOON_ADVECTION_VER( TPFLYER )
 
           TPFLYER%TPOS_CUR = TDTCUR + ZTSTEP
         END IF CRASH_VERT !end of no vertical crash branch
@@ -1945,99 +393,1022 @@ SELECT TYPE ( TPFLYER )
         !The balloon is not present on this MPI process
         ZTHIS_PROC = 0.
       END IF ISOWNERBAL
-      !----------------------------------------------------------------------------
-      !
-      !*     11.   EXCHANGE OF INFORMATION BETWEEN PROCESSES
-      !            -----------------------------------------
-      !
-      !*     11.1  current position
-      !            ----------------
-      !
-      IF ( TPFLYER%CMODEL == 'MOB' ) THEN
-        CALL DISTRIBUTE_FLYER_N(TPFLYER%NMODEL)
+
+      CALL FLYER_COMMUNICATE_DATA( )
+    END IF INFLIGHTONMODEL
+
+END SELECT
+
+
+CONTAINS
+!
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE BALLOON_COMPUTE_INITIAL_VERTICAL_POSITION( TPBALLOON )
+
+IMPLICIT NONE
+
+CLASS(TBALLOONDATA), INTENT(INOUT) :: TPBALLOON
+
+SELECT CASE ( TPBALLOON%CTYPE )
+  !
+  ! Iso-density balloon
+  !
+  CASE ( 'ISODEN' )
+    IF ( TPBALLOON%XALTLAUNCH /= XNEGUNDEF ) THEN
+      IK00 = MAX ( COUNT (TPBALLOON%XALTLAUNCH >= ZZM(1,1,:)), 1)
+      IK01 = MAX ( COUNT (TPBALLOON%XALTLAUNCH >= ZZM(1,2,:)), 1)
+      IK10 = MAX ( COUNT (TPBALLOON%XALTLAUNCH >= ZZM(2,1,:)), 1)
+      IK11 = MAX ( COUNT (TPBALLOON%XALTLAUNCH >= ZZM(2,2,:)), 1)
+      ZZCOEF00 = (TPBALLOON%XALTLAUNCH - ZZM(1,1,IK00)) / ( ZZM(1,1,IK00+1) - ZZM(1,1,IK00))
+      ZZCOEF01 = (TPBALLOON%XALTLAUNCH - ZZM(1,2,IK01)) / ( ZZM(1,2,IK01+1) - ZZM(1,2,IK01))
+      ZZCOEF10 = (TPBALLOON%XALTLAUNCH - ZZM(2,1,IK10)) / ( ZZM(2,1,IK10+1) - ZZM(2,1,IK10))
+      ZZCOEF11 = (TPBALLOON%XALTLAUNCH - ZZM(2,2,IK11)) / ( ZZM(2,2,IK11+1) - ZZM(2,2,IK11))
+      TPBALLOON%XRHO = FLYER_INTERP(ZRHO)
+    ELSE IF ( TPBALLOON%XPRES /= XNEGUNDEF ) THEN
+      ZFLYER_EXN = (TPBALLOON%XPRES/XP00)**(XRD/XCPD)
+      IK00 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,1,:)), 1)
+      IK01 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,2,:)), 1)
+      IK10 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,1,:)), 1)
+      IK11 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,2,:)), 1)
+      ZZCOEF00 = (ZFLYER_EXN - ZEXN(1,1,IK00)) / ( ZEXN(1,1,IK00+1) - ZEXN(1,1,IK00))
+      ZZCOEF01 = (ZFLYER_EXN - ZEXN(1,2,IK01)) / ( ZEXN(1,2,IK01+1) - ZEXN(1,2,IK01))
+      ZZCOEF10 = (ZFLYER_EXN - ZEXN(2,1,IK10)) / ( ZEXN(2,1,IK10+1) - ZEXN(2,1,IK10))
+      ZZCOEF11 = (ZFLYER_EXN - ZEXN(2,2,IK11)) / ( ZEXN(2,2,IK11+1) - ZEXN(2,2,IK11))
+      TPBALLOON%XRHO = FLYER_INTERP(ZRHO)
+    ELSE
+      CMNHMSG(1) = 'Error in balloon initial position (balloon ' // TRIM(TPBALLOON%CTITLE) // ' )'
+      CMNHMSG(2) = 'neither initial ALTITUDE or PRESsure is given'
+      CMNHMSG(3) = 'Check your INI_BALLOON routine'
+      CALL PRINT_MSG( NVERB_FATAL, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
+    END IF
+  !
+  ! Radiosounding balloon
+  !
+  CASE ( 'RADIOS' )
+    TPBALLOON%XZ_CUR = TPBALLOON%XALTLAUNCH
+    TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(1,1,IKB) )
+    TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(2,1,IKB) )
+    TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(1,2,IKB) )
+    TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(2,2,IKB) )
+  !
+  ! Constant Volume Balloon
+  !
+  CASE ( 'CVBALL' )
+    IF ( TPBALLOON%XALTLAUNCH /= XNEGUNDEF ) THEN
+      IK00 = MAX ( COUNT (TPBALLOON%XALTLAUNCH >= ZZM(1,1,:)), 1)
+      IK01 = MAX ( COUNT (TPBALLOON%XALTLAUNCH >= ZZM(1,2,:)), 1)
+      IK10 = MAX ( COUNT (TPBALLOON%XALTLAUNCH >= ZZM(2,1,:)), 1)
+      IK11 = MAX ( COUNT (TPBALLOON%XALTLAUNCH >= ZZM(2,2,:)), 1)
+      IF (IK00*IK01*IK10*IK11 .EQ. 0) THEN
+        TPBALLOON%XZ_CUR = TPBALLOON%XALTLAUNCH
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(1,1,IKB) )
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(2,1,IKB) )
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(1,2,IKB) )
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(2,2,IKB) )
+      ELSE
+        ZZCOEF00 = (TPBALLOON%XALTLAUNCH - ZZM(1,1,IK00)) / ( ZZM(1,1,IK00+1) - ZZM(1,1,IK00))
+        ZZCOEF01 = (TPBALLOON%XALTLAUNCH - ZZM(1,2,IK01)) / ( ZZM(1,2,IK01+1) - ZZM(1,2,IK01))
+        ZZCOEF10 = (TPBALLOON%XALTLAUNCH - ZZM(2,1,IK10)) / ( ZZM(2,1,IK10+1) - ZZM(2,1,IK10))
+        ZZCOEF11 = (TPBALLOON%XALTLAUNCH - ZZM(2,2,IK11)) / ( ZZM(2,2,IK11+1) - ZZM(2,2,IK11))
+        TPBALLOON%XRHO = FLYER_INTERP(ZRHO)
+        TPBALLOON%XZ_CUR = FLYER_INTERP(ZZM)
+      END IF
+    ELSE IF ( TPBALLOON%XPRES /= XNEGUNDEF ) THEN
+      ZFLYER_EXN = (TPBALLOON%XPRES/XP00)**(XRD/XCPD)
+      IK00 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,1,:)), 1)
+      IK01 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,2,:)), 1)
+      IK10 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,1,:)), 1)
+      IK11 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,2,:)), 1)
+      IF (IK00*IK01*IK10*IK11 .EQ. 0) THEN
+        TPBALLOON%XZ_CUR = ZZM(1,1,IKB)
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(2,1,IKB) )
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(1,2,IKB) )
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(2,2,IKB) )
+      ELSE
+        ZZCOEF00 = (ZFLYER_EXN - ZEXN(1,1,IK00)) / ( ZEXN(1,1,IK00+1) - ZEXN(1,1,IK00))
+        ZZCOEF01 = (ZFLYER_EXN - ZEXN(1,2,IK01)) / ( ZEXN(1,2,IK01+1) - ZEXN(1,2,IK01))
+        ZZCOEF10 = (ZFLYER_EXN - ZEXN(2,1,IK10)) / ( ZEXN(2,1,IK10+1) - ZEXN(2,1,IK10))
+        ZZCOEF11 = (ZFLYER_EXN - ZEXN(2,2,IK11)) / ( ZEXN(2,2,IK11+1) - ZEXN(2,2,IK11))
+        TPBALLOON%XRHO = FLYER_INTERP(ZRHO)
+        TPBALLOON%XZ_CUR = FLYER_INTERP(ZZM)
       END IF
-      CALL DISTRIBUTE_FLYER_N(TPFLYER%NRANK_CUR)
-      CALL DISTRIBUTE_FLYER_L(TPFLYER%LFLY)
-      CALL DISTRIBUTE_FLYER_L(TPFLYER%LCRASH)
-      CALL DISTRIBUTE_FLYER_L(TPFLYER%LSTORE)
-      CALL DISTRIBUTE_FLYER(TPFLYER%XX_CUR)
-      CALL DISTRIBUTE_FLYER(TPFLYER%XY_CUR)
-      CALL DISTRIBUTE_FLYER_N(TPFLYER%TPOS_CUR%NYEAR)
-      CALL DISTRIBUTE_FLYER_N(TPFLYER%TPOS_CUR%NMONTH)
-      CALL DISTRIBUTE_FLYER_N(TPFLYER%TPOS_CUR%NDAY)
-      CALL DISTRIBUTE_FLYER  (TPFLYER%TPOS_CUR%XTIME)
-
-      CALL DISTRIBUTE_FLYER_N(TPFLYER%TFLYER_TIME%N_CUR)
-
-      ! SELECT TYPE ( TPFLYER )
-      !   CLASS IS ( TBALLOONDATA )
-      IF ( TPFLYER%CTYPE == 'CVBALL' ) THEN
-        CALL DISTRIBUTE_FLYER(TPFLYER%XZ_CUR)
-        CALL DISTRIBUTE_FLYER(TPFLYER%XWASCENT)
-      ELSE IF ( TPFLYER%CTYPE == 'RADIOS' ) THEN
-        CALL DISTRIBUTE_FLYER(TPFLYER%XZ_CUR)
-      ELSE IF ( TPFLYER%CTYPE == 'ISODEN' ) THEN
-        CALL DISTRIBUTE_FLYER(TPFLYER%XRHO)
+    ELSE
+      TPBALLOON%XRHO = TPBALLOON%XMASS / TPBALLOON%XVOLUME
+      IK00 = MAX ( COUNT (TPBALLOON%XRHO <= ZRHO(1,1,:)), 1)
+      IK01 = MAX ( COUNT (TPBALLOON%XRHO <= ZRHO(1,2,:)), 1)
+      IK10 = MAX ( COUNT (TPBALLOON%XRHO <= ZRHO(2,1,:)), 1)
+      IK11 = MAX ( COUNT (TPBALLOON%XRHO <= ZRHO(2,2,:)), 1)
+      IF (IK00*IK01*IK10*IK11 .EQ. 0) THEN
+        TPBALLOON%XZ_CUR = ZZM(1,1,IKB)
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(2,1,IKB) )
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(1,2,IKB) )
+        TPBALLOON%XZ_CUR = MAX ( TPBALLOON%XZ_CUR , ZZM(2,2,IKB) )
+      ELSE
+        ZZCOEF00 = (TPBALLOON%XRHO - ZRHO(1,1,IK00)) / ( ZRHO(1,1,IK00+1) - ZRHO(1,1,IK00))
+        ZZCOEF01 = (TPBALLOON%XRHO - ZRHO(1,2,IK01)) / ( ZRHO(1,2,IK01+1) - ZRHO(1,2,IK01))
+        ZZCOEF10 = (TPBALLOON%XRHO - ZRHO(2,1,IK10)) / ( ZRHO(2,1,IK10+1) - ZRHO(2,1,IK10))
+        ZZCOEF11 = (TPBALLOON%XRHO - ZRHO(2,2,IK11)) / ( ZRHO(2,2,IK11+1) - ZRHO(2,2,IK11))
+        TPBALLOON%XZ_CUR = FLYER_INTERP(ZZM)
       END IF
+    END IF
+END SELECT
 
-      IF ( TPFLYER%LSTORE ) THEN
-        CALL DISTRIBUTE_FLYER_N(TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%NYEAR)
-        CALL DISTRIBUTE_FLYER_N(TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%NMONTH)
-        CALL DISTRIBUTE_FLYER_N(TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%NDAY)
-        CALL DISTRIBUTE_FLYER  (TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%XTIME)
-
-        CALL DISTRIBUTE_FLYER_N(TPFLYER%NMODELHIST(ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XX  (ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XY  (ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XZ  (ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XLON(ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XLAT(ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XZON(ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XMER(ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XW  (ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XP  (ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XTH (ISTORE))
-        DO JLOOP=1,SIZE(PR,4)
-          CALL DISTRIBUTE_FLYER(TPFLYER%XR   (ISTORE,JLOOP))
-        END DO
-        DO JLOOP=1,SIZE(PSV,4)
-          CALL DISTRIBUTE_FLYER(TPFLYER%XSV  (ISTORE,JLOOP))
-        END DO
-        DO JLOOP=1,IKU
-          CALL DISTRIBUTE_FLYER(TPFLYER%XRTZ (ISTORE,JLOOP))
-          DO JLOOP2=1,SIZE(PR,4)
-            CALL DISTRIBUTE_FLYER(TPFLYER%XRZ (ISTORE,JLOOP,JLOOP2))
-          ENDDO
-          CALL DISTRIBUTE_FLYER(TPFLYER%XFFZ (ISTORE,JLOOP))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XCIZ (ISTORE,JLOOP))
-          IF (CCLOUD== 'LIMA' ) THEN
-            CALL DISTRIBUTE_FLYER(TPFLYER%XCRZ (ISTORE,JLOOP))
-            CALL DISTRIBUTE_FLYER(TPFLYER%XCCZ (ISTORE,JLOOP))
-          ENDIF
-          CALL DISTRIBUTE_FLYER(TPFLYER%XIWCZ (ISTORE,JLOOP))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XLWCZ (ISTORE,JLOOP))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XCRARE (ISTORE,JLOOP))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XCRARE_ATT (ISTORE,JLOOP))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XWZ (ISTORE,JLOOP))
-          CALL DISTRIBUTE_FLYER(TPFLYER%XZZ (ISTORE,JLOOP))
-        END DO
-        IF (SIZE(PTKE)>0) CALL DISTRIBUTE_FLYER(TPFLYER%XTKE  (ISTORE))
-        IF (SIZE(PTS) >0) CALL DISTRIBUTE_FLYER(TPFLYER%XTSRAD(ISTORE))
-        IF (LDIAG_IN_RUN) CALL DISTRIBUTE_FLYER(TPFLYER%XTKE_DISS(ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XZS  (ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XTHW_FLUX(ISTORE))
-        CALL DISTRIBUTE_FLYER(TPFLYER%XRCW_FLUX(ISTORE))
-        DO JLOOP=1,SIZE(PSV,4)
-          CALL DISTRIBUTE_FLYER(TPFLYER%XSVW_FLUX(ISTORE,JLOOP))
-        END DO
+END SUBROUTINE BALLOON_COMPUTE_INITIAL_VERTICAL_POSITION
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE BALLOON_ADVECTION_HOR( TPBALLOON )
+
+USE MODD_AIRCRAFT_BALLOON, ONLY: TBALLOONDATA
+
+IMPLICIT NONE
+
+CLASS(TBALLOONDATA), INTENT(INOUT) :: TPBALLOON
+
+INTEGER :: IMODEL_OLD
+REAL    :: ZX_OLD, ZY_OLD
+REAL    :: ZDELTATIME
+REAL    :: ZDIVTMP
+
+ZTSTEP = PTSTEP
+
+ZU_BAL = FLYER_INTERP_U(PU)
+ZV_BAL = FLYER_INTERP_V(PV)
+if ( .not. lcartesian ) then
+  ZMAP = FLYER_INTERP_2D(PMAP)
+else
+  ZMAP = 1.
+end if
+!
+ZX_OLD = TPBALLOON%XX_CUR
+ZY_OLD = TPBALLOON%XY_CUR
+
+TPBALLOON%XX_CUR = TPBALLOON%XX_CUR + ZU_BAL * ZTSTEP * ZMAP
+TPBALLOON%XY_CUR = TPBALLOON%XY_CUR + ZV_BAL * ZTSTEP * ZMAP
+
+! Compute rank and model for next position
+! This is done here because we need to check if there is a change of model (for 'MOB' balloons)
+! because position has to be adapted to the timestep of a coarser model (if necessary)
+IMODEL_OLD = TPBALLOON%NMODEL
+
+! Get rank of the process where the balloon is and the model number
+CALL FLYER_GET_RANK_MODEL_ISCRASHED( TPBALLOON )
+
+IF ( TPBALLOON%LCRASH ) THEN
+  WRITE( CMNHMSG(1), "( 'Balloon ', A, ' crashed the ', I2, '/', I2, '/', I4, ' at ', F18.12, &
+                      's (out of the horizontal boundaries)' )" ) &
+    TRIM( TPBALLOON%CTITLE ), TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
+  CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
+END IF
+
+IF ( TPBALLOON%NMODEL /= IMODEL_OLD .AND. .NOT. TPBALLOON%LCRASH ) THEN
+  ! Balloon has changed of model
+  IF ( NDAD(TPBALLOON%NMODEL ) == IMODEL_OLD ) THEN
+    ! Nothing special to do when going to child model
+  ELSE IF ( TPBALLOON%NMODEL == NDAD(IMODEL_OLD) ) THEN
+    ! Balloon go to parent model
+    ! Recompute position to be compatible with parent timestep
+    ! Parent timestep could be bigger (factor NDTRATIO) and therefore next position is not the one computed just before
+
+    ! Determine step compatible with parent model at next parent timestep
+    ZDELTATIME = TDTCUR - TDTSEG
+    ZDIVTMP = ZDELTATIME / ( PTSTEP * NDTRATIO(IMODEL_OLD) )
+    IF ( ABS( ZDIVTMP - NINT( ZDIVTMP ) ) < 1E-6 * PTSTEP * NDTRATIO(IMODEL_OLD) ) THEN
+      ! Current time is a multiple of parent timestep => next position is parent timestep
+      ZTSTEP = ZTSTEP * NDTRATIO(IMODEL_OLD)
+    ELSE
+      ! Current time is not a multiple of parent timestep
+      ! Next position must be a multiple of parent timestep
+      ! NINT( NDTRATIO(IMODEL_OLD) * ( 1 - ( ZDIVTMP - INT( ZDIVTMP ) ) ) ) corresponds to the number
+      ! of child timesteps to go to the next parent timestep
+      ! We skip one timestep (+NDTRATIO(IMODEL_OLD)) because it has already been computed for the parent model
+      ZTSTEP = ZTSTEP * ( NINT( NDTRATIO(IMODEL_OLD) * ( 1 - ( ZDIVTMP - INT( ZDIVTMP ) ) ) ) + NDTRATIO(IMODEL_OLD) )
+
+      ! Detect if we need to skip a store (if time of next position is after time of next store)
+      ! This can happen when a ballon goes to its parent model
+      IF ( TDTCUR + ZTSTEP > TPBALLOON%TFLYER_TIME%TPDATES(TPBALLOON%TFLYER_TIME%N_CUR) + TPBALLOON%TFLYER_TIME%XTSTEP + 1e-6 ) THEN
+        !Force a dummy store (nothing is computed, therefore default/initial values will be stored)
+        TPBALLOON%LSTORE = .TRUE.
+
+        TPBALLOON%TFLYER_TIME%N_CUR = TPBALLOON%TFLYER_TIME%N_CUR + 1
+        ISTORE = TPBALLOON%TFLYER_TIME%N_CUR
+
+        !Remark: by construction here, ISTORE is always > 1 => no risk with ISTORE-1 value
+        TPBALLOON%TFLYER_TIME%TPDATES(ISTORE) = TPBALLOON%TFLYER_TIME%TPDATES(ISTORE-1) + TPBALLOON%TFLYER_TIME%XTSTEP
+
+        WRITE( CMNHMSG(1), "( 'Balloon ', A, ': store skipped at ', I2, '/', I2, '/', I4, ' at ', F18.12, 's' )" ) &
+               TRIM( TPBALLOON%CTITLE ),                                                                             &
+               TPBALLOON%TFLYER_TIME%TPDATES(ISTORE)%NDAY,  TPBALLOON%TFLYER_TIME%TPDATES(ISTORE)%NMONTH,              &
+               TPBALLOON%TFLYER_TIME%TPDATES(ISTORE)%NYEAR, TPBALLOON%TFLYER_TIME%TPDATES(ISTORE)%XTIME
+        CMNHMSG(2) = 'due to change of model (child to its parent)'
+        CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
       END IF
-    END IF INFLIGHTONMODEL
+    END IF
+
+    ! Compute new horizontal position
+    TPBALLOON%XX_CUR = TPBALLOON%XX_CUR + ZU_BAL * ZTSTEP * ZMAP
+    TPBALLOON%XY_CUR = TPBALLOON%XY_CUR + ZV_BAL * ZTSTEP * ZMAP
+
+    ! Get rank of the process where the balloon is and the model number
+    ! Model number is now imposed
+    IMODEL = TPBALLOON%NMODEL
+    CALL FLYER_GET_RANK_MODEL_ISCRASHED( TPBALLOON, KMODEL = IMODEL )
+    IF ( TPBALLOON%LCRASH ) THEN
+      WRITE( CMNHMSG(1), "( 'Balloon ', A, ' crashed the ', I2, '/', I2, '/', I4, ' at ', F18.12, &
+                         's (out of the horizontal boundaries)' )" ) &
+        TRIM( TPBALLOON%CTITLE ), TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
+      CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
+    END IF
+  ELSE
+    ! Special case not-managed (different dads, change of several models in 1 step (going to grand parent/grand children)...)
+    ! This situation should be very infrequent => reasonable risk, error on the trajectory should be relatively small in most cases
+    CMNHMSG(1) = 'unmanaged change of model for ballon ' // TPBALLOON%CTITLE
+    CMNHMSG(2) = 'its trajectory might be wrong'
+    CALL PRINT_MSG( NVERB_WARNING, 'GEN', 'AIRCRAFT_BALLOON_EVOL', OLOCAL = .TRUE. )
+  END IF
+END IF
+
+END SUBROUTINE BALLOON_ADVECTION_HOR
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE BALLOON_ADVECTION_VER( TPBALLOON )
+
+USE MODD_AIRCRAFT_BALLOON, ONLY: TBALLOONDATA
+
+IMPLICIT NONE
+
+CLASS(TBALLOONDATA), INTENT(INOUT) :: TPBALLOON
+
+IF ( TPBALLOON%CTYPE == 'RADIOS' ) THEN
+  ZW_BAL = FLYER_INTERP(ZWM)
+  TPBALLOON%XZ_CUR = TPBALLOON%XZ_CUR + ( ZW_BAL + TPBALLOON%XWASCENT ) * ZTSTEP
+END IF
+
+IF ( TPBALLOON%CTYPE == 'CVBALL' ) THEN
+  ZW_BAL = FLYER_INTERP(ZWM)
+  ZRO_BAL = FLYER_INTERP(ZRHO)
+  ! calculation with a time step of 1 second or less
+  IF (INT(ZTSTEP) .GT. 1 ) THEN
+    DO JK=1,INT(ZTSTEP)
+      TPBALLOON%XWASCENT = TPBALLOON%XWASCENT &
+        -  ( 1. / (1. + TPBALLOON%XINDDRAG ) ) * 1. * &
+           ( XG * ( ( TPBALLOON%XMASS / TPBALLOON%XVOLUME ) - ZRO_BAL ) / ( TPBALLOON%XMASS / TPBALLOON%XVOLUME ) &
+              + TPBALLOON%XWASCENT * ABS ( TPBALLOON%XWASCENT ) * &
+                TPBALLOON%XDIAMETER * TPBALLOON%XAERODRAG / ( 2. * TPBALLOON%XVOLUME ) &
+            )
+      TPBALLOON%XZ_CUR = TPBALLOON%XZ_CUR + ( ZW_BAL + TPBALLOON%XWASCENT ) * 1.
+    END DO
+  END IF
+  IF (ZTSTEP .GT. INT(ZTSTEP)) THEN
+    TPBALLOON%XWASCENT = TPBALLOON%XWASCENT &
+      -  ( 1. / (1. + TPBALLOON%XINDDRAG ) ) * (ZTSTEP-INT(ZTSTEP)) * &
+         ( XG * ( ( TPBALLOON%XMASS / TPBALLOON%XVOLUME ) - ZRO_BAL ) / ( TPBALLOON%XMASS / TPBALLOON%XVOLUME ) &
+            + TPBALLOON%XWASCENT * ABS ( TPBALLOON%XWASCENT ) * &
+              TPBALLOON%XDIAMETER * TPBALLOON%XAERODRAG / ( 2. * TPBALLOON%XVOLUME ) &
+          )
+    TPBALLOON%XZ_CUR = TPBALLOON%XZ_CUR + ( ZW_BAL + TPBALLOON%XWASCENT ) * (ZTSTEP-INT(ZTSTEP))
+  END IF
+END IF
+
+END SUBROUTINE BALLOON_ADVECTION_VER
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE FLYER_INTERP_TO_MASSPOINTS()
+
+IMPLICIT NONE
+
+! Indices
+IKB =   1   + JPVEXT
+IKE = SIZE(PZ,3) - JPVEXT
+
+! Interpolations of model variables to mass points
+! ------------------------------------------------
+
+! X position
+II_U = COUNT( XXHAT (:) <= TPFLYER%XX_CUR )
+II_M = COUNT( XXHATM(:) <= TPFLYER%XX_CUR )
+
+! Y position
+IJ_V=COUNT( XYHAT (:)<=TPFLYER%XY_CUR )
+IJ_M=COUNT( XYHATM(:)<=TPFLYER%XY_CUR )
+ZZM(:,:,1:IKU-1)=0.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,1:IKU-1)+0.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,2:IKU  )
+ZZM(:,:,  IKU  )=1.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,  IKU-1)-0.5 *PZ(II_M  :II_M+1,IJ_M  :IJ_M+1,  IKU-2)
+
+IDU = II_U - II_M
+ZZU(:,:,1:IKU-1)=0.25*PZ(IDU+II_M-1:IDU+II_M,  IJ_M  :IJ_M+1,1:IKU-1)+0.25*PZ(IDU+II_M-1:IDU+II_M  ,IJ_M  :IJ_M+1,2:IKU  ) &
+                +0.25*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,1:IKU-1)+0.25*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,2:IKU  )
+ZZU(:,:,  IKU  )=0.75*PZ(IDU+II_M-1:IDU+II_M  ,IJ_M  :IJ_M+1,  IKU-1)-0.25*PZ(IDU+II_M-1:IDU+II_M  ,IJ_M  :IJ_M+1,  IKU-2) &
+                +0.75*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,  IKU-1)-0.25*PZ(IDU+II_M  :IDU+II_M+1,IJ_M  :IJ_M+1,  IKU-2)
+
+IDV = IJ_V - IJ_M
+ZZV(:,:,1:IKU-1)=0.25*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,1:IKU-1)+0.25*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,2:IKU  ) &
+                +0.25*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,1:IKU-1)+0.25*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,2:IKU  )
+ZZV(:,:,  IKU  )=0.75*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,  IKU-1)-0.25*PZ(II_M  :II_M+1,IDV+IJ_M-1:IDV+IJ_M  ,  IKU-2) &
+                +0.75*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,  IKU-1)-0.25*PZ(II_M  :II_M+1,IDV+IJ_M  :IDV+IJ_M+1,  IKU-2)
+
+ZWM(:,:,1:IKU-1)=0.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,1:IKU-1)+0.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,2:IKU  )
+ZWM(:,:,  IKU  )=1.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,  IKU-1)-0.5*PW(II_M:II_M+1,IJ_M:IJ_M+1,  IKU-2)
+
+END SUBROUTINE FLYER_INTERP_TO_MASSPOINTS
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+PURE FUNCTION FLYER_COMPUTE_EXNER( ) RESULT( PEXN )
+
+IMPLICIT NONE
+
+REAL, DIMENSION(2,2,SIZE(PTH,3)) :: PEXN
+
+INTEGER :: JK
+
+PEXN(:,:,:) = ( PP(II_M:II_M+1, IJ_M:IJ_M+1, :) / XP00) ** ( XRD / XCPD )
+DO JK = IKB-1, 1, -1
+  PEXN(:,:,JK) = 1.5 * PEXN(:,:,JK+1) - 0.5 * PEXN(:,:,JK+2)
+END DO
+DO JK = IKE+1, IKU
+  PEXN(:,:,JK) = 1.5 * PEXN(:,:,JK-1) - 0.5 * PEXN(:,:,JK-2)
+END DO
+
+END FUNCTION FLYER_COMPUTE_EXNER
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+PURE FUNCTION FLYER_COMPUTE_RHO( ) RESULT( PRHO )
+
+USE MODI_WATER_SUM
+
+IMPLICIT NONE
+
+REAL, DIMENSION(2,2,SIZE(PTH,3)) :: PRHO
+
+INTEGER                          :: JK
+REAL, DIMENSION(2,2,SIZE(PTH,3)) :: ZTHV ! virtual potential temperature
+
+ZTHV(:,:,:) = PTH(II_M:II_M+1, IJ_M:IJ_M+1, :)
+IF ( SIZE( PR, 4 ) > 0 )                                                              &
+  ZTHV(:,:,:) = ZTHV(:,:,:) * ( 1. + XRV / XRD * PR(II_M:II_M+1, IJ_M:IJ_M+1, :, 1) ) &
+                            / ( 1. + WATER_SUM( PR(II_M:II_M+1, IJ_M:IJ_M+1, :, :)) )
+!
+PRHO(:,:,:) = PP(II_M:II_M+1, IJ_M:IJ_M+1, :) / ( XRD * ZTHV(:,:,:) * ZEXN(:,:,:) )
+DO JK = IKB-1, 1, -1
+  PRHO(:,:,JK) = 1.5 * PRHO(:,:,JK+1) - 0.5 * PRHO(:,:,JK+2)
+END DO
+DO JK = IKE+1, IKU
+  PRHO(:,:,JK) = 1.5 * PRHO(:,:,JK-1) - 0.5 * PRHO(:,:,JK-2)
+END DO
+
+END FUNCTION FLYER_COMPUTE_RHO
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE FLYER_COMPUTE_INTERP_COEFF_HOR_STAGE1( )
+! Compute coefficents for horizontal interpolations (1st stage)
+
+IMPLICIT NONE
+
+! Interpolation coefficient for X
+ZXCOEF = (TPFLYER%XX_CUR - XXHATM(II_M)) / (XXHATM(II_M+1) - XXHATM(II_M))
+ZXCOEF = MAX (0.,MIN(ZXCOEF,1.))
+
+! Interpolation coefficient for y
+ZYCOEF = (TPFLYER%XY_CUR - XYHATM(IJ_M)) / (XYHATM(IJ_M+1) - XYHATM(IJ_M))
+ZYCOEF = MAX (0.,MIN(ZYCOEF,1.))
+
+! Interpolation coefficient for X (for U)
+ZUCOEF = (TPFLYER%XX_CUR - XXHAT(II_U)) / (XXHAT(II_U+1) - XXHAT(II_U))
+ZUCOEF = MAX(0.,MIN(ZUCOEF,1.))
+
+! Interpolation coefficient for y (for V)
+ZVCOEF = (TPFLYER%XY_CUR - XYHAT(IJ_V)) / (XYHAT(IJ_V+1) - XYHAT(IJ_V))
+ZVCOEF = MAX(0.,MIN(ZVCOEF,1.))
+
+END SUBROUTINE FLYER_COMPUTE_INTERP_COEFF_HOR_STAGE1
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE FLYER_COMPUTE_INTERP_COEFF_VER( )
+! Compute coefficent for vertical interpolations
+
+IMPLICIT NONE
+
+! Find indices surrounding the vertical box where the flyer is
+SELECT TYPE ( TPFLYER )
+  CLASS IS ( TAIRCRAFTDATA)
+    IF ( TPFLYER%LALTDEF ) THEN
+      ZFLYER_EXN = (TPFLYER%XP_CUR/XP00)**(XRD/XCPD)
+      IK00 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,1,:)), 1)
+      IK01 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(1,2,:)), 1)
+      IK10 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,1,:)), 1)
+      IK11 = MAX ( COUNT (ZFLYER_EXN <= ZEXN(2,2,:)), 1)
+    ELSE
+      IK00 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(1,1,:)), 1)
+      IK01 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(1,2,:)), 1)
+      IK10 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(2,1,:)), 1)
+      IK11 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(2,2,:)), 1)
+    END IF
+
+  CLASS IS ( TBALLOONDATA)
+    IF ( TPFLYER%CTYPE == 'ISODEN' ) THEN
+      IK00 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(1,1,:)), 1)
+      IK01 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(1,2,:)), 1)
+      IK10 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(2,1,:)), 1)
+      IK11 = MAX ( COUNT (TPFLYER%XRHO <= ZRHO(2,2,:)), 1)
+    ELSE IF ( TPFLYER%CTYPE == 'RADIOS' .OR. TPFLYER%CTYPE == 'CVBALL' ) THEN
+      IK00 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(1,1,:)), 1)
+      IK01 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(1,2,:)), 1)
+      IK10 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(2,1,:)), 1)
+      IK11 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZM(2,2,:)), 1)
+    END IF
 
 END SELECT
 
+! Do not allow crash on the ground: set position on the ground if too low
+IF ( ANY( [ IK00, IK01, IK10, IK11 ] < IKB ) ) THEN
+  !Minimum altitude is on the ground at IKB (no crash if too low)
+  IK00 = MAX ( IK00, IKB )
+  IK01 = MAX ( IK01, IKB )
+  IK10 = MAX ( IK10, IKB )
+  IK11 = MAX ( IK11, IKB )
+
+  CMNHMSG(1) = 'flyer ' // TRIM( TPFLYER%CTITLE ) // ' is near the ground'
+  WRITE( CMNHMSG(2), "( 'at ', I2, '/', I2, '/', I4, ' ', F18.12, 's' )" ) &
+         TDTCUR%NDAY, TDTCUR%NMONTH, TDTCUR%NYEAR, TDTCUR%XTIME
+  CALL PRINT_MSG( NVERB_INFO, 'GEN', 'FLYER_COMPUTE_INTERP_COEFF_VER', OLOCAL = .TRUE. )
+END IF
 
-CONTAINS
+! ! Check if the flyer crashed vertically (lower bound)
+! IF (IK00 <  IKB .OR. IK01 <  IKB .OR. IK10 <  IKB .OR. IK11 <  IKB ) THEN
+!   TPFLYER%LCRASH = .TRUE.
+!   TPFLYER%NCRASH = NCRASH_OUT_LOW
+! END IF
+
+! Check if the flyer crashed vertically (higher bound)
+IF (IK00 >= IKE .OR. IK01 >= IKE .OR. IK10 >= IKE .OR. IK11 >= IKE  ) THEN
+  TPFLYER%LCRASH = .TRUE.
+  TPFLYER%NCRASH = NCRASH_OUT_HIGH
+END IF
+
+SELECT TYPE ( TPFLYER )
+  CLASS IS ( TBALLOONDATA)
+    IF ( TPFLYER%LCRASH ) RETURN
+END SELECT
+
+! Interpolation coefficients for the 4 suroundings verticals
+SELECT TYPE ( TPFLYER )
+  CLASS IS ( TAIRCRAFTDATA)
+    IF ( TPFLYER%LALTDEF ) THEN
+      ZZCOEF00 = (ZFLYER_EXN - ZEXN(1,1,IK00)) / ( ZEXN(1,1,IK00+1) - ZEXN(1,1,IK00) )
+      ZZCOEF01 = (ZFLYER_EXN - ZEXN(1,2,IK01)) / ( ZEXN(1,2,IK01+1) - ZEXN(1,2,IK01) )
+      ZZCOEF10 = (ZFLYER_EXN - ZEXN(2,1,IK10)) / ( ZEXN(2,1,IK10+1) - ZEXN(2,1,IK10) )
+      ZZCOEF11 = (ZFLYER_EXN - ZEXN(2,2,IK11)) / ( ZEXN(2,2,IK11+1) - ZEXN(2,2,IK11) )
+      TPFLYER%XZ_CUR = FLYER_INTERP(ZZM)
+    ELSE
+      ZZCOEF00 = (TPFLYER%XZ_CUR - ZZM(1,1,IK00)) / ( ZZM(1,1,IK00+1) - ZZM(1,1,IK00) )
+      ZZCOEF01 = (TPFLYER%XZ_CUR - ZZM(1,2,IK01)) / ( ZZM(1,2,IK01+1) - ZZM(1,2,IK01) )
+      ZZCOEF10 = (TPFLYER%XZ_CUR - ZZM(2,1,IK10)) / ( ZZM(2,1,IK10+1) - ZZM(2,1,IK10) )
+      ZZCOEF11 = (TPFLYER%XZ_CUR - ZZM(2,2,IK11)) / ( ZZM(2,2,IK11+1) - ZZM(2,2,IK11) )
+      TPFLYER%XP_CUR = FLYER_INTERP(PP)
+    END IF
+
+  CLASS IS ( TBALLOONDATA)
+    IF ( TPFLYER%CTYPE == 'ISODEN' ) THEN
+      ZZCOEF00 = (TPFLYER%XRHO - ZRHO(1,1,IK00)) / ( ZRHO(1,1,IK00+1) - ZRHO(1,1,IK00) )
+      ZZCOEF01 = (TPFLYER%XRHO - ZRHO(1,2,IK01)) / ( ZRHO(1,2,IK01+1) - ZRHO(1,2,IK01) )
+      ZZCOEF10 = (TPFLYER%XRHO - ZRHO(2,1,IK10)) / ( ZRHO(2,1,IK10+1) - ZRHO(2,1,IK10) )
+      ZZCOEF11 = (TPFLYER%XRHO - ZRHO(2,2,IK11)) / ( ZRHO(2,2,IK11+1) - ZRHO(2,2,IK11) )
+      TPFLYER%XZ_CUR = FLYER_INTERP(ZZM)
+    ELSE IF ( TPFLYER%CTYPE == 'RADIOS' .OR. TPFLYER%CTYPE == 'CVBALL' ) THEN
+      ZZCOEF00 = (TPFLYER%XZ_CUR - ZZM(1,1,IK00)) / ( ZZM(1,1,IK00+1) - ZZM(1,1,IK00) )
+      ZZCOEF01 = (TPFLYER%XZ_CUR - ZZM(1,2,IK01)) / ( ZZM(1,2,IK01+1) - ZZM(1,2,IK01) )
+      ZZCOEF10 = (TPFLYER%XZ_CUR - ZZM(2,1,IK10)) / ( ZZM(2,1,IK10+1) - ZZM(2,1,IK10) )
+      ZZCOEF11 = (TPFLYER%XZ_CUR - ZZM(2,2,IK11)) / ( ZZM(2,2,IK11+1) - ZZM(2,2,IK11) )
+    END IF
+
+END SELECT
+
+END SUBROUTINE FLYER_COMPUTE_INTERP_COEFF_VER
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE FLYER_COMPUTE_INTERP_COEFF_HOR_STAGE2( )
+! Compute coefficents for horizontal interpolations (2nd stage)
+! This stage must be done after FLYER_COMPUTE_INTERP_COEFF_VER because we should need XZ_CUR computed in it
+
+IMPLICIT NONE
+
+! Interpolation coefficients for the 4 suroundings verticals (for U)
+IU00 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(1,1,:)), 1)
+IU01 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(1,2,:)), 1)
+IU10 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(2,1,:)), 1)
+IU11 = MAX( COUNT (TPFLYER%XZ_CUR >= ZZU(2,2,:)), 1)
+ZUCOEF00 = (TPFLYER%XZ_CUR - ZZU(1,1,IU00)) / ( ZZU(1,1,IU00+1) - ZZU(1,1,IU00) )
+ZUCOEF01 = (TPFLYER%XZ_CUR - ZZU(1,2,IU01)) / ( ZZU(1,2,IU01+1) - ZZU(1,2,IU01) )
+ZUCOEF10 = (TPFLYER%XZ_CUR - ZZU(2,1,IU10)) / ( ZZU(2,1,IU10+1) - ZZU(2,1,IU10) )
+ZUCOEF11 = (TPFLYER%XZ_CUR - ZZU(2,2,IU11)) / ( ZZU(2,2,IU11+1) - ZZU(2,2,IU11) )
+
+! Interpolation coefficients for the 4 suroundings verticals (for V)
+IV00 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(1,1,:)), 1)
+IV01 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(1,2,:)), 1)
+IV10 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(2,1,:)), 1)
+IV11 = MAX ( COUNT (TPFLYER%XZ_CUR >= ZZV(2,2,:)), 1)
+ZVCOEF00 = (TPFLYER%XZ_CUR - ZZV(1,1,IV00)) / ( ZZV(1,1,IV00+1) - ZZV(1,1,IV00) )
+ZVCOEF01 = (TPFLYER%XZ_CUR - ZZV(1,2,IV01)) / ( ZZV(1,2,IV01+1) - ZZV(1,2,IV01) )
+ZVCOEF10 = (TPFLYER%XZ_CUR - ZZV(2,1,IV10)) / ( ZZV(2,1,IV10+1) - ZZV(2,1,IV10) )
+ZVCOEF11 = (TPFLYER%XZ_CUR - ZZV(2,2,IV11)) / ( ZZV(2,2,IV11+1) - ZZV(2,2,IV11) )
+
+END SUBROUTINE FLYER_COMPUTE_INTERP_COEFF_HOR_STAGE2
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE FLYER_RECORD_DATA( )
+
+USE MODD_NSV,              ONLY: NSV_LIMA_NC, NSV_LIMA_NR, NSV_LIMA_NI
+USE MODD_PARAM_LIMA,       ONLY: XALPHAR_L => XALPHAR, XNUR_L => XNUR, XALPHAS_L => XALPHAS, XNUS_L => XNUS, &
+                                 XALPHAG_L => XALPHAG, XNUG_L => XNUG, XALPHAI_L => XALPHAI, XNUI_L => XNUI, &
+                                 XRTMIN_L => XRTMIN, XALPHAC_L => XALPHAC, XNUC_L => XNUC
+USE MODD_PARAM_LIMA_COLD,  ONLY: XAI_L => XAI, XBI_L => XBI, XLBEXS_L => XLBEXS,XLBS_L => XLBS,XCCS_L => XCCS,&
+                                 XAS_L => XAS, XBS_L => XBS, XCXS_L => XCXS
+USE MODD_PARAM_LIMA_MIXED, ONLY: XLBEXG_L => XLBEXG, XLBG_L => XLBG, XCCG_L => XCCG, XAG_L => XAG, XBG_L => XBG, XCXG_L => XCXG
+USE MODD_PARAM_LIMA_WARM,  ONLY: XAC_L => XAC, XAR_L => XAR, XBC_L => XBC, XBR_L => XBR
+USE MODD_RAIN_ICE_DESCR,   ONLY: XALPHAR_I => XALPHAR, XNUR_I => XNUR, XLBEXR_I => XLBEXR,                   &
+                                 XLBR_I => XLBR, XCCR_I => XCCR, XBR_I => XBR, XAR_I => XAR,                 &
+                                 XALPHAC_I => XALPHAC, XNUC_I => XNUC, XBC_I => XBC, XAC_I => XAC,           &
+                                 XALPHAC2_I => XALPHAC2, XNUC2_I => XNUC2,                                   &
+                                 XALPHAS_I => XALPHAS, XNUS_I => XNUS, XLBEXS_I => XLBEXS,                   &
+                                 XLBS_I => XLBS, XCCS_I => XCCS, XAS_I => XAS, XBS_I => XBS, XCXS_I => XCXS, &
+                                 XALPHAG_I => XALPHAG, XNUG_I => XNUG, XLBEXG_I => XLBEXG,                   &
+                                 XLBG_I => XLBG, XCCG_I => XCCG, XAG_I => XAG, XBG_I => XBG, XCXG_I => XCXG, &
+                                 XALPHAI_I => XALPHAI, XNUI_I => XNUI, XLBEXI_I => XLBEXI,                   &
+                                 XLBI_I => XLBI, XAI_I => XAI, XBI_I => XBI,                                 &
+                                 XRTMIN_I => XRTMIN, XCONC_LAND, XCONC_SEA
+
+USE MODI_GAMMA,            ONLY: GAMMA
+
+IMPLICIT NONE
+
+INTEGER, PARAMETER :: JPTS_GAULAG = 7 ! number of points for Gauss-Laguerre quadrature
+
+REAL, DIMENSION(SIZE(PR,3))    :: ZTEMPZ! vertical profile of temperature
+REAL, DIMENSION(SIZE(PR,3))    :: ZRHODREFZ ! vertical profile of dry air density of the reference state
+REAL, DIMENSION(SIZE(PR,3))    :: ZCIT     ! pristine ice concentration
+REAL, DIMENSION(SIZE(PR,3))    :: ZCCI,ZCCR,ZCCC     ! ICE,RAIN CLOUD concentration (LIMA)
+REAL, DIMENSION(SIZE(PR,1),SIZE(PR,2),SIZE(PR,3))    :: ZR
+REAL, DIMENSION(SIZE(PR,3),SIZE(PR,4)+1) :: ZRZ  ! vertical profile of hydrometeor mixing ratios
+REAL                           :: ZA,ZB,ZCC,ZCX,ZALPHA,ZNU,ZLB,ZLBEX,ZRHOHYD   ! generic microphysical parameters
+INTEGER                        :: JJ    ! loop counter for quadrature
+COMPLEX                        :: QMW,QMI,QM,QEPSIW,QEPSWI   ! dielectric parameter
+REAL                           :: ZAETOT,ZAETMP,ZREFLOC,ZQSCA,ZQBACK,ZQEXT ! temporary scattering parameters
+REAL,DIMENSION(:),ALLOCATABLE  :: ZAELOC,ZZMZ ! temporary arrays
+REAL                           :: ZLBDA   ! slope distribution parameter
+REAL                           :: ZDELTA_EQUIV ! mass-equivalent Gauss-Laguerre point
+REAL                           :: ZFW ! liquid fraction
+REAL                           :: ZFPW ! weight for mixed-phase reflectivity
+REAL,DIMENSION(:),ALLOCATABLE  :: ZX,ZW ! Gauss-Laguerre points and weights
+REAL,DIMENSION(:),ALLOCATABLE  :: ZRTMIN ! local values for XRTMIN
+LOGICAL                        :: GCALC
+
+TPFLYER%NMODELHIST(ISTORE) = TPFLYER%NMODEL
+
+TPFLYER%XX(ISTORE) = TPFLYER%XX_CUR
+TPFLYER%XY(ISTORE) = TPFLYER%XY_CUR
+TPFLYER%XZ(ISTORE) = TPFLYER%XZ_CUR
+!
+CALL SM_LATLON(PLATOR,PLONOR,          &
+            TPFLYER%XX_CUR, TPFLYER%XY_CUR,       &
+            TPFLYER%XLAT(ISTORE), TPFLYER%XLON(ISTORE)  )
 !
+ZU_BAL = FLYER_INTERP_U(PU)
+ZV_BAL = FLYER_INTERP_V(PV)
+ZGAM   = (XRPK * (TPFLYER%XLON(ISTORE) - XLON0) - XBETA)*(XPI/180.)
+TPFLYER%XZON (ISTORE) = ZU_BAL * COS(ZGAM) + ZV_BAL * SIN(ZGAM)
+TPFLYER%XMER (ISTORE) = - ZU_BAL * SIN(ZGAM) + ZV_BAL * COS(ZGAM)
+!
+TPFLYER%XW   (ISTORE) = FLYER_INTERP(ZWM)
+TPFLYER%XTH  (ISTORE) = FLYER_INTERP(PTH)
+!
+ZFLYER_EXN = FLYER_INTERP(ZEXN)
+TPFLYER%XP   (ISTORE) = XP00 * ZFLYER_EXN**(XCPD/XRD)
+
+ZR(:,:,:) = 0.
+DO JLOOP=1,SIZE(PR,4)
+  TPFLYER%XR   (ISTORE,JLOOP) = FLYER_INTERP(PR(:,:,:,JLOOP))
+  IF (JLOOP>=2) ZR(:,:,:) = ZR(:,:,:) + PR(:,:,:,JLOOP)
+END DO
+DO JLOOP=1,SIZE(PSV,4)
+  TPFLYER%XSV  (ISTORE,JLOOP) = FLYER_INTERP(PSV(:,:,:,JLOOP))
+END DO
+TPFLYER%XRTZ  (ISTORE,:) = FLYER_INTERPZ(ZR(:,:,:))
+DO JLOOP=1,SIZE(PR,4)
+  TPFLYER%XRZ  (ISTORE,:,JLOOP) = FLYER_INTERPZ(PR(:,:,:,JLOOP))
+END DO
+
+TPFLYER%XFFZ  (ISTORE,:) = FLYER_INTERPZ(SQRT(PU**2+PV**2))
+
+IF (CCLOUD=="LIMA") THEN
+  TPFLYER%XCIZ  (ISTORE,:) = FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NI))
+  TPFLYER%XCCZ  (ISTORE,:) = FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NC))
+  TPFLYER%XCRZ  (ISTORE,:) = FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NR))
+ELSE IF ( CCLOUD=="ICE3" .OR. CCLOUD=="ICE4" ) THEN
+  TPFLYER%XCIZ  (ISTORE,:) = FLYER_INTERPZ(PCIT(:,:,:))
+END IF
+! initialization CRARE and CRARE_ATT + LWC and IWC
+TPFLYER%XCRARE(ISTORE,:) = 0.
+TPFLYER%XCRARE_ATT(ISTORE,:) = 0.
+TPFLYER%XLWCZ  (ISTORE,:) = 0.
+TPFLYER%XIWCZ  (ISTORE,:) = 0.
+IF (CCLOUD=="LIMA" .OR. CCLOUD=="ICE3" ) THEN ! only for ICE3 and LIMA
+  TPFLYER%XLWCZ  (ISTORE,:) = FLYER_INTERPZ((PR(:,:,:,2)+PR(:,:,:,3))*PRHODREF(:,:,:))
+  TPFLYER%XIWCZ  (ISTORE,:) = FLYER_INTERPZ((PR(:,:,:,4)+PR(:,:,:,5)+PR(:,:,:,6))*PRHODREF(:,:,:))
+  ZTEMPZ(:)=FLYER_INTERPZ(PTH(II_M:II_M+1,IJ_M:IJ_M+1,:) * ZEXN(:,:,:))
+  ZRHODREFZ(:)=FLYER_INTERPZ(PRHODREF(:,:,:))
+  IF (CCLOUD=="LIMA") THEN
+    ZCCI(:)=FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NI))
+    ZCCR(:)=FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NR))
+    ZCCC(:)=FLYER_INTERPZ(PSV(:,:,:,NSV_LIMA_NC))
+  ELSE
+    ZCIT(:)=FLYER_INTERPZ(PCIT(:,:,:))
+  ENDIF
+  DO JLOOP=3,6
+    ZRZ(:,JLOOP)=FLYER_INTERPZ(PR(:,:,:,JLOOP))
+  END DO
+  if ( csurf == 'EXTE' ) then
+    DO JK=1,IKU
+      ZRZ(JK,2)=FLYER_INTERP_2D(PR(:,:,JK,2)*PSEA(:,:))       ! becomes cloud mixing ratio over sea
+      ZRZ(JK,7)=FLYER_INTERP_2D(PR(:,:,JK,2)*(1.-PSEA(:,:)))  ! becomes cloud mixing ratio over land
+    END DO
+  else
+    !if csurf/='EXTE', psea is not allocated
+    DO JK=1,IKU
+      ZRZ(JK,2)=FLYER_INTERP_2D(PR(:,:,JK,2))
+      ZRZ(JK,7) = 0.
+    END DO
+  end if
+  ALLOCATE(ZAELOC(IKU))
+  !
+  ZAELOC(:)=0.
+  ! initialization of quadrature points and weights
+  ALLOCATE(ZX(JPTS_GAULAG),ZW(JPTS_GAULAG))
+  CALL GAULAG(JPTS_GAULAG,ZX,ZW) ! for integration over diameters
+  ! initialize minimum values
+  ALLOCATE(ZRTMIN(SIZE(PR,4)+1))
+  IF (CCLOUD == 'LIMA') THEN
+    ZRTMIN(2)=XRTMIN_L(2) ! cloud water over sea
+    ZRTMIN(3)=XRTMIN_L(3)
+    ZRTMIN(4)=XRTMIN_L(4)
+    ZRTMIN(5)=1E-10
+    ZRTMIN(6)=XRTMIN_L(6)
+    ZRTMIN(7)=XRTMIN_L(2) ! cloud water over land
+  ELSE
+    ZRTMIN(2)=XRTMIN_I(2) ! cloud water over sea
+    ZRTMIN(3)=XRTMIN_I(3)
+    ZRTMIN(4)=XRTMIN_I(4)
+    ZRTMIN(5)=1E-10
+    ZRTMIN(6)=XRTMIN_I(6)
+    ZRTMIN(7)=XRTMIN_I(2) ! cloud water over land
+  ENDIF
+  ! compute cloud radar reflectivity from vertical profiles of temperature and mixing ratios
+  DO JK=1,IKU
+    QMW=SQRT(QEPSW(ZTEMPZ(JK),XLIGHTSPEED/XLAM_CRAD))
+    QMI=SQRT(QEPSI(ZTEMPZ(JK),XLIGHTSPEED/XLAM_CRAD))
+    DO JLOOP=2,7
+      IF (CCLOUD == 'LIMA') THEN
+        GCALC=(ZRZ(JK,JLOOP)>ZRTMIN(JLOOP).AND.(JLOOP.NE.4.OR.ZCCI(JK)>0.).AND.&
+              (JLOOP.NE.3.OR.ZCCR(JK)>0.).AND.((JLOOP.NE.2.AND. JLOOP.NE.7).OR.ZCCC(JK)>0.))
+      ELSE
+        GCALC=(ZRZ(JK,JLOOP)>ZRTMIN(JLOOP).AND.(JLOOP.NE.4.OR.ZCIT(JK)>0.))
+      ENDIF
+      IF(GCALC) THEN
+        SELECT CASE(JLOOP)
+          CASE(2) ! cloud water over sea
+            IF (CCLOUD == 'LIMA') THEN
+              ZA=XAC_L
+              ZB=XBC_L
+              ZCC=ZCCC(JK)*ZRHODREFZ(JK)
+              ZCX=0.
+              ZALPHA=XALPHAC_L
+              ZNU=XNUC_L
+              ZLBEX=1.0/(ZCX-ZB)
+              ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
+            ELSE
+              ZA=XAC_I
+              ZB=XBC_I
+              ZCC=XCONC_SEA
+              ZCX=0.
+              ZALPHA=XALPHAC2_I
+              ZNU=XNUC2_I
+              ZLBEX=1.0/(ZCX-ZB)
+              ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
+            ENDIF
+          CASE(3) ! rain water
+            IF (CCLOUD == 'LIMA') THEN
+              ZA=XAR_L
+              ZB=XBR_L
+              ZCC=ZCCR(JK)*ZRHODREFZ(JK)
+              ZCX=0.
+              ZALPHA=XALPHAR_L
+              ZNU=XNUR_L
+              ZLBEX=1.0/(ZCX-ZB)
+              ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
+            ELSE
+              ZA=XAR_I
+              ZB=XBR_I
+              ZCC=XCCR_I
+              ZCX=-1.
+              ZALPHA=XALPHAR_I
+              ZNU=XNUR_I
+              ZLB=XLBR_I
+              ZLBEX=XLBEXR_I
+            ENDIF
+          CASE(4) ! pristine ice
+            IF (CCLOUD == 'LIMA') THEN
+              ZA=XAI_L
+              ZB=XBI_L
+              ZCC=ZCCI(JK)*ZRHODREFZ(JK)
+              ZCX=0.
+              ZALPHA=XALPHAI_L
+              ZNU=XNUI_L
+              ZLBEX=1.0/(ZCX-ZB)
+              ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX) ! because ZCC not included in XLBI
+              ZFW=0
+            ELSE
+              ZA=XAI_I
+              ZB=XBI_I
+              ZCC=ZCIT(JK)
+              ZCX=0.
+              ZALPHA=XALPHAI_I
+              ZNU=XNUI_I
+              ZLBEX=XLBEXI_I
+              ZLB=XLBI_I*ZCC**(-ZLBEX) ! because ZCC not included in XLBI
+              ZFW=0
+            ENDIF
+          CASE(5) ! snow
+            IF (CCLOUD == 'LIMA') THEN
+              ZA=XAS_L
+              ZB=XBS_L
+              ZCC=XCCS_L
+              ZCX=XCXS_L
+              ZALPHA=XALPHAS_L
+              ZNU=XNUS_L
+              ZLB=XLBS_L
+              ZLBEX=XLBEXS_L
+              ZFW=0
+            ELSE
+              ZA=XAS_I
+              ZB=XBS_I
+              ZCC=XCCS_I
+              ZCX=XCXS_I
+              ZALPHA=XALPHAS_I
+              ZNU=XNUS_I
+              ZLB=XLBS_I
+              ZLBEX=XLBEXS_I
+              ZFW=0
+            ENDIF
+          CASE(6) ! graupel
+            !If temperature between -10 and 10°C and Mr and Mg over min threshold: melting graupel
+            ! with liquid water fraction Fw=Mr/(Mr+Mg) else dry graupel (Fw=0)
+            IF( ZTEMPZ(JK) > XTT-10 .AND. ZTEMPZ(JK) < XTT+10 &
+              .AND. ZRZ(JK,3) > ZRTMIN(3) ) THEN
+              ZFW=ZRZ(JK,3)/(ZRZ(JK,3)+ZRZ(JK,JLOOP))
+            ELSE
+              ZFW=0
+            ENDIF
+            IF (CCLOUD == 'LIMA') THEN
+              ZA=XAG_L
+              ZB=XBG_L
+              ZCC=XCCG_L
+              ZCX=XCXG_L
+              ZALPHA=XALPHAG_L
+              ZNU=XNUG_L
+              ZLB=XLBG_L
+              ZLBEX=XLBEXG_L
+            ELSE
+              ZA=XAG_I
+              ZB=XBG_I
+              ZCC=XCCG_I
+              ZCX=XCXG_I
+              ZALPHA=XALPHAG_I
+              ZNU=XNUG_I
+              ZLB=XLBG_I
+              ZLBEX=XLBEXG_I
+            ENDIF
+          CASE(7) ! cloud water over land
+            IF (CCLOUD == 'LIMA') THEN
+              ZA=XAC_L
+              ZB=XBC_L
+              ZCC=ZCCC(JK)*ZRHODREFZ(JK)
+              ZCX=0.
+              ZALPHA=XALPHAC_L
+              ZNU=XNUC_L
+              ZLBEX=1.0/(ZCX-ZB)
+              ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
+            ELSE
+              ZA=XAC_I
+              ZB=XBC_I
+              ZCC=XCONC_LAND
+              ZCX=0.
+              ZALPHA=XALPHAC_I
+              ZNU=XNUC_I
+              ZLBEX=1.0/(ZCX-ZB)
+              ZLB=( ZA*ZCC*MOMG(ZALPHA,ZNU,ZB) )**(-ZLBEX)
+            ENDIF
+        END SELECT
+        ZLBDA=ZLB*(ZRHODREFZ(JK)*ZRZ(JK,JLOOP))**ZLBEX
+        ZREFLOC=0.
+        ZAETMP=0.
+        DO JJ=1,JPTS_GAULAG ! Gauss-Laguerre quadrature
+          ZDELTA_EQUIV=ZX(JJ)**(1./ZALPHA)/ZLBDA
+          SELECT CASE(JLOOP)
+            CASE(2,3,7)
+              QM=QMW
+            CASE(4,5,6)
+              ! pristine ice, snow, dry graupel
+              ZRHOHYD=MIN(6.*ZA*ZDELTA_EQUIV**(ZB-3.)/XPI,.92*XRHOLW)
+              QM=sqrt(MG(QMI**2,CMPLX(1,0),ZRHOHYD/.92/XRHOLW))
+
+              ! water inclusions in ice in air
+              QEPSWI=MG(QMW**2,QM**2,ZFW)
+              ! ice in air inclusions in water
+              QEPSIW=MG(QM**2,QMW**2,1.-ZFW)
+
+              !MG weighted rule (Matrosov 2008)
+              IF(ZFW .LT. 0.37) THEN
+                ZFPW=0
+              ELSE IF(ZFW .GT. 0.63) THEN
+                ZFPW=1
+              ELSE
+                ZFPW=(ZFW-0.37)/(0.63-0.37)
+              ENDIF
+              QM=sqrt(QEPSWI*(1.-ZFPW)+QEPSIW*ZFPW)
+          END SELECT
+          CALL BHMIE(XPI/XLAM_CRAD*ZDELTA_EQUIV,QM,ZQEXT,ZQSCA,ZQBACK)
+          ZREFLOC=ZREFLOC+ZQBACK*ZX(JJ)**(ZNU-1)*ZDELTA_EQUIV**2*ZW(JJ)
+          ZAETMP =ZAETMP +ZQEXT *ZX(JJ)**(ZNU-1)*ZDELTA_EQUIV**2*ZW(JJ)
+        END DO
+        ZREFLOC=ZREFLOC*(XLAM_CRAD/XPI)**4*ZCC*ZLBDA**ZCX/(4.*GAMMA(ZNU)*.93)
+        ZAETMP=ZAETMP  *           XPI    *ZCC*ZLBDA**ZCX/(4.*GAMMA(ZNU))
+        TPFLYER%XCRARE(ISTORE,JK)=TPFLYER%XCRARE(ISTORE,JK)+ZREFLOC
+        ZAELOC(JK)=ZAELOC(JK)+ZAETMP
+      END IF
+    END DO
+  END DO
+
+  ! apply attenuation
+  ALLOCATE(ZZMZ(IKU))
+  ZZMZ(:)=FLYER_INTERPZ(ZZM(:,:,:))
+  ! nadir
+  ZAETOT=1.
+  DO JK=COUNT(TPFLYER%XZ_CUR >= ZZMZ(:)),1,-1
+    IF(JK.EQ.COUNT(TPFLYER%XZ_CUR >= ZZMZ(:))) THEN
+      IF(TPFLYER%XZ_CUR<=ZZMZ(JK)+.5*(ZZMZ(JK+1)-ZZMZ(JK))) THEN
+        ! only attenuation from ZAELOC(JK)
+        ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK)*(TPFLYER%XZ_CUR-ZZMZ(JK))))
+      ELSE
+        ! attenuation from ZAELOC(JK) and ZAELOC(JK+1)
+        ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK+1)*(TPFLYER%XZ_CUR-.5*(ZZMZ(JK+1)+ZZMZ(JK))) &
+          +ZAELOC(JK)*.5*(ZZMZ(JK+1)-ZZMZ(JK))))
+      END IF
+    ELSE
+      ! attenuation from ZAELOC(JK) and ZAELOC(JK+1)
+      ZAETOT=ZAETOT*EXP(-(ZAELOC(JK+1)+ZAELOC(JK))*(ZZMZ(JK+1)-ZZMZ(JK)))
+    END IF
+    TPFLYER%XCRARE_ATT(ISTORE,JK)=TPFLYER%XCRARE(ISTORE,JK)*ZAETOT
+  END DO
+  ! zenith
+  ZAETOT=1.
+  DO JK = MAX(COUNT(TPFLYER%XZ_CUR >= ZZMZ(:)),1)+1,IKU
+    IF ( JK .EQ. (MAX(COUNT(TPFLYER%XZ_CUR >= ZZMZ(:)),1)+1) ) THEN
+      IF(TPFLYER%XZ_CUR>=ZZMZ(JK)-.5*(ZZMZ(JK)-ZZMZ(JK-1))) THEN
+        ! only attenuation from ZAELOC(JK)
+        ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK)*(ZZMZ(JK)-TPFLYER%XZ_CUR)))
+      ELSE
+        ! attenuation from ZAELOC(JK) and ZAELOC(JK-1)
+        ZAETOT=ZAETOT*EXP(-2.*(ZAELOC(JK-1)*(.5*(ZZMZ(JK)+ZZMZ(JK-1))-TPFLYER%XZ_CUR) &
+          +ZAELOC(JK)*.5*(ZZMZ(JK)-ZZMZ(JK-1))))
+      END IF
+    ELSE
+      ! attenuation from ZAELOC(JK) and ZAELOC(JK-1)
+      ZAETOT=ZAETOT*EXP(-(ZAELOC(JK-1)+ZAELOC(JK))*(ZZMZ(JK)-ZZMZ(JK-1)))
+    END IF
+    TPFLYER%XCRARE_ATT(ISTORE,JK)=TPFLYER%XCRARE(ISTORE,JK)*ZAETOT
+  END DO
+
+  TPFLYER%XZZ  (ISTORE,:) = ZZMZ(:)
+  DEALLOCATE(ZZMZ,ZAELOC)
+  ! m^3 → mm^6/m^3 → dBZ
+  WHERE(TPFLYER%XCRARE(ISTORE,:)>0)
+    TPFLYER%XCRARE(ISTORE,:)=10.*LOG10(1.E18*TPFLYER%XCRARE(ISTORE,:))
+  ELSEWHERE
+    TPFLYER%XCRARE(ISTORE,:)=XUNDEF
+  END WHERE
+  WHERE(TPFLYER%XCRARE_ATT(ISTORE,:)>0)
+    TPFLYER%XCRARE_ATT(ISTORE,:)=10.*LOG10(1.E18*TPFLYER%XCRARE_ATT(ISTORE,:))
+  ELSEWHERE
+    TPFLYER%XCRARE_ATT(ISTORE,:)=XUNDEF
+  END WHERE
+  DEALLOCATE(ZX,ZW,ZRTMIN)
+END IF ! end LOOP ICE3
+! vertical wind
+TPFLYER%XWZ  (ISTORE,:) = FLYER_INTERPZ(ZWM(:,:,:))
+IF (SIZE(PTKE)>0) TPFLYER%XTKE  (ISTORE)    = FLYER_INTERP(PTKE)
+IF (SIZE(PTS) >0) TPFLYER%XTSRAD(ISTORE)    = FLYER_INTERP_2D(PTS)
+IF (LDIAG_IN_RUN) TPFLYER%XTKE_DISS(ISTORE) = FLYER_INTERP(XCURRENT_TKE_DISS)
+TPFLYER%XZS(ISTORE)  = FLYER_INTERP_2D(PZ(:,:,1+JPVEXT))
+TPFLYER%XTHW_FLUX(ISTORE) = FLYER_INTERP(ZTHW_FLUX)
+TPFLYER%XRCW_FLUX(ISTORE) = FLYER_INTERP(ZRCW_FLUX)
+DO JLOOP=1,SIZE(PSV,4)
+TPFLYER%XSVW_FLUX(ISTORE,JLOOP) = FLYER_INTERP(ZSVW_FLUX(:,:,:,JLOOP))
+END DO
+
+END SUBROUTINE FLYER_RECORD_DATA
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE FLYER_COMMUNICATE_DATA( )
+! Exchange of information between processes
+
+IMPLICIT NONE
+
+SELECT TYPE ( TPFLYER )
+  CLASS IS ( TBALLOONDATA)
+    IF ( TPFLYER%CMODEL == 'MOB' ) THEN
+      CALL DISTRIBUTE_FLYER_N(TPFLYER%NMODEL)
+    END IF
+    CALL DISTRIBUTE_FLYER_N(TPFLYER%NRANK_CUR)
+    CALL DISTRIBUTE_FLYER_L(TPFLYER%LFLY)
+    CALL DISTRIBUTE_FLYER_L(TPFLYER%LCRASH)
+    CALL DISTRIBUTE_FLYER_L(TPFLYER%LSTORE)
+    CALL DISTRIBUTE_FLYER(TPFLYER%XX_CUR)
+    CALL DISTRIBUTE_FLYER(TPFLYER%XY_CUR)
+    CALL DISTRIBUTE_FLYER_N(TPFLYER%TPOS_CUR%NYEAR)
+    CALL DISTRIBUTE_FLYER_N(TPFLYER%TPOS_CUR%NMONTH)
+    CALL DISTRIBUTE_FLYER_N(TPFLYER%TPOS_CUR%NDAY)
+    CALL DISTRIBUTE_FLYER  (TPFLYER%TPOS_CUR%XTIME)
+
+    CALL DISTRIBUTE_FLYER_N(TPFLYER%TFLYER_TIME%N_CUR)
+
+    IF ( TPFLYER%CTYPE == 'CVBALL' ) THEN
+      CALL DISTRIBUTE_FLYER(TPFLYER%XZ_CUR)
+      CALL DISTRIBUTE_FLYER(TPFLYER%XWASCENT)
+    ELSE IF ( TPFLYER%CTYPE == 'RADIOS' ) THEN
+      CALL DISTRIBUTE_FLYER(TPFLYER%XZ_CUR)
+    ELSE IF ( TPFLYER%CTYPE == 'ISODEN' ) THEN
+      CALL DISTRIBUTE_FLYER(TPFLYER%XRHO)
+    END IF
+
+END SELECT
+
+IF ( TPFLYER%LSTORE ) THEN
+  ! Data stored
+  ISTORE = TPFLYER%TFLYER_TIME%N_CUR
+
+  SELECT TYPE ( TPFLYER )
+    CLASS IS ( TBALLOONDATA)
+      CALL DISTRIBUTE_FLYER_N(TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%NYEAR)
+      CALL DISTRIBUTE_FLYER_N(TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%NMONTH)
+      CALL DISTRIBUTE_FLYER_N(TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%NDAY)
+      CALL DISTRIBUTE_FLYER  (TPFLYER%TFLYER_TIME%TPDATES(ISTORE)%XTIME)
+  END SELECT
+
+  CALL DISTRIBUTE_FLYER_N(TPFLYER%NMODELHIST(ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XX  (ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XY  (ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XZ  (ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XLON(ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XLAT(ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XZON(ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XMER(ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XW  (ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XP  (ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XTH (ISTORE))
+  DO JLOOP=1,SIZE(PR,4)
+    CALL DISTRIBUTE_FLYER(TPFLYER%XR   (ISTORE,JLOOP))
+  END DO
+  DO JLOOP=1,SIZE(PSV,4)
+    CALL DISTRIBUTE_FLYER(TPFLYER%XSV  (ISTORE,JLOOP))
+  END DO
+  DO JLOOP=1,IKU
+    CALL DISTRIBUTE_FLYER(TPFLYER%XRTZ (ISTORE,JLOOP))
+    DO JLOOP2=1,SIZE(PR,4)
+      CALL DISTRIBUTE_FLYER(TPFLYER%XRZ (ISTORE,JLOOP,JLOOP2))
+    END DO
+    CALL DISTRIBUTE_FLYER(TPFLYER%XFFZ (ISTORE,JLOOP))
+    CALL DISTRIBUTE_FLYER(TPFLYER%XCIZ (ISTORE,JLOOP))
+    IF (CCLOUD== 'LIMA' ) THEN
+      CALL DISTRIBUTE_FLYER(TPFLYER%XCRZ (ISTORE,JLOOP))
+      CALL DISTRIBUTE_FLYER(TPFLYER%XCCZ (ISTORE,JLOOP))
+    END IF
+    CALL DISTRIBUTE_FLYER(TPFLYER%XIWCZ (ISTORE,JLOOP))
+    CALL DISTRIBUTE_FLYER(TPFLYER%XLWCZ (ISTORE,JLOOP))
+    CALL DISTRIBUTE_FLYER(TPFLYER%XCRARE (ISTORE,JLOOP))
+    CALL DISTRIBUTE_FLYER(TPFLYER%XCRARE_ATT (ISTORE,JLOOP))
+    CALL DISTRIBUTE_FLYER(TPFLYER%XWZ (ISTORE,JLOOP))
+    CALL DISTRIBUTE_FLYER(TPFLYER%XZZ (ISTORE,JLOOP))
+  END DO
+  IF (SIZE(PTKE)>0) CALL DISTRIBUTE_FLYER(TPFLYER%XTKE  (ISTORE))
+  IF (SIZE(PTS) >0) CALL DISTRIBUTE_FLYER(TPFLYER%XTSRAD(ISTORE))
+  IF (LDIAG_IN_RUN) CALL DISTRIBUTE_FLYER(TPFLYER%XTKE_DISS(ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XZS  (ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XTHW_FLUX(ISTORE))
+  CALL DISTRIBUTE_FLYER(TPFLYER%XRCW_FLUX(ISTORE))
+  DO JLOOP=1,SIZE(PSV,4)
+    CALL DISTRIBUTE_FLYER(TPFLYER%XSVW_FLUX(ISTORE,JLOOP))
+  END DO
+END IF
+
+END SUBROUTINE FLYER_COMMUNICATE_DATA
 !----------------------------------------------------------------------------
 !----------------------------------------------------------------------------
 FUNCTION FLYER_INTERP(PA) RESULT(PB)
@@ -2062,6 +1433,7 @@ PB = (1.- ZYCOEF) * (1.-ZXCOEF) * ( (1.-ZZCOEF00) * PA(JI  ,JJ  ,IK00) + ZZCOEF0
 !
 END FUNCTION FLYER_INTERP
 !----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
 FUNCTION FLYER_INTERPZ(PA) RESULT(PB)
 !
 REAL, DIMENSION(:,:,:), INTENT(IN) :: PA
@@ -2208,5 +1580,137 @@ END SUBROUTINE DISTRIBUTE_FLYER_L
 
 END SUBROUTINE AIRCRAFT_BALLOON_EVOL
 !----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE AIRCRAFT_COMPUTE_POSITION( TPDATE, TPAIRCRAFT )
+
+USE MODD_AIRCRAFT_BALLOON, ONLY: TAIRCRAFTDATA
+USE MODD_TYPE_DATE,        ONLY: DATE_TIME
+
+USE MODE_DATETIME
+USE MODE_POSITION_TOOLS,   ONLY: FIND_PROCESS_AND_MODEL_FROM_XY_POS
+
+IMPLICIT NONE
+
+TYPE(DATE_TIME),      INTENT(IN)    :: TPDATE
+CLASS(TAIRCRAFTDATA), INTENT(INOUT) :: TPAIRCRAFT !aircraft
+
+INTEGER :: IL        ! flight segment index
+REAL    :: ZTDIST    ! time since launch (sec)
+REAL    :: ZSEG_FRAC ! fraction of flight in the current segment
+
+! Find the flight segment
+ZTDIST = TPDATE - TPAIRCRAFT%TLAUNCH
+IL = TPAIRCRAFT%NPOSCUR
+DO WHILE ( ZTDIST > TPAIRCRAFT%XPOSTIME(IL+1) )
+  IL = IL + 1
+  IF ( IL > TPAIRCRAFT%NPOS-1 ) THEN
+    !Security (should not happen)
+    IL = TPAIRCRAFT%NPOS-1
+    EXIT
+  END IF
+END DO
+TPAIRCRAFT%NPOSCUR = IL
+
+! Compute the current position
+ZSEG_FRAC = ( ZTDIST - TPAIRCRAFT%XPOSTIME(IL) ) / ( TPAIRCRAFT%XPOSTIME(IL+1) - TPAIRCRAFT%XPOSTIME(IL) )
+
+TPAIRCRAFT%XX_CUR = (1.-ZSEG_FRAC) * TPAIRCRAFT%XPOSX(IL  ) &
+               +     ZSEG_FRAC  * TPAIRCRAFT%XPOSX(IL+1)
+TPAIRCRAFT%XY_CUR = (1.-ZSEG_FRAC) * TPAIRCRAFT%XPOSY(IL  ) &
+               +     ZSEG_FRAC  * TPAIRCRAFT%XPOSY(IL+1)
+
+IF (TPAIRCRAFT%LALTDEF) THEN
+  TPAIRCRAFT%XP_CUR = (1.-ZSEG_FRAC) * TPAIRCRAFT%XPOSP(IL  ) &
+                 +     ZSEG_FRAC  * TPAIRCRAFT%XPOSP(IL+1)
+ELSE
+  TPAIRCRAFT%XZ_CUR = (1.-ZSEG_FRAC) * TPAIRCRAFT%XPOSZ(IL ) &
+                 +     ZSEG_FRAC  * TPAIRCRAFT%XPOSZ(IL +1)
+END IF
+
+END SUBROUTINE AIRCRAFT_COMPUTE_POSITION
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE FLYER_GET_RANK_MODEL_ISCRASHED( TPFLYER, PX, PY, KMODEL )
+
+USE MODD_AIRCRAFT_BALLOON, ONLY: NCRASH_NO, NCRASH_OUT_HORIZ, TFLYERDATA
+
+USE MODE_POSITION_TOOLS,   ONLY: FIND_PROCESS_AND_MODEL_FROM_XY_POS
+
+IMPLICIT NONE
+
+CLASS(TFLYERDATA), INTENT(INOUT) :: TPFLYER ! balloon/aircraft
+REAL,    OPTIONAL, INTENT(IN)    :: PX      ! X position (if not provided, takes current flyer position)
+REAL,    OPTIONAL, INTENT(IN)    :: PY      ! Y position (if not provided, takes current flyer position)
+INTEGER, OPTIONAL, INTENT(IN)    :: KMODEL  ! if provided, model number is imposed (if not 0)
+
+INTEGER :: IMODEL
+INTEGER :: IRANK
+REAL    :: ZX, ZY
+
+IF ( PRESENT( KMODEL ) ) THEN
+  IMODEL = KMODEL
+ELSE
+  IF ( TPFLYER%CMODEL == 'FIX' ) THEN
+    IMODEL = TPFLYER%NMODEL
+  ELSE
+    IMODEL = 0
+  END IF
+END IF
+
+IF ( PRESENT( PX ) ) THEN
+  ZX = PX
+ELSE
+  ZX = TPFLYER%XX_CUR
+END IF
+
+IF ( PRESENT( PY ) ) THEN
+  ZY = PY
+ELSE
+  ZY = TPFLYER%XY_CUR
+END IF
+
+CALL FIND_PROCESS_AND_MODEL_FROM_XY_POS( ZX, ZY, IRANK, IMODEL )
+
+IF ( IRANK < 1 ) THEN
+  ! Flyer is outside of horizontal domain
+  TPFLYER%NMODEL    = 1 !Set to 1 because it is always a valid model (to prevent crash if NDAD(TPFLYER%NMODEL) )
+  TPFLYER%LCRASH    = .TRUE.
+  TPFLYER%NCRASH    = NCRASH_OUT_HORIZ
+  TPFLYER%LFLY      = .FALSE.
+ELSE
+  TPFLYER%NMODEL    = IMODEL
+  TPFLYER%LCRASH    = .FALSE.
+  TPFLYER%NCRASH    = NCRASH_NO
+  !TPFLYER%LFLY      = !Do not touch LFLY (flyer could be in flight or not)
+  TPFLYER%NRANK_CUR = IRANK
+END IF
+
+END SUBROUTINE FLYER_GET_RANK_MODEL_ISCRASHED
+!----------------------------------------------------------------------------
+!----------------------------------------------------------------------------
+SUBROUTINE FLYER_CHECK_STORESTEP( TPFLYER )
+
+USE MODD_AIRCRAFT_BALLOON, ONLY: TFLYERDATA
+
+USE MODE_STATPROF_TOOLS,   ONLY: STATPROF_INSTANT
+
+IMPLICIT NONE
+
+CLASS(TFLYERDATA), INTENT(INOUT) :: TPFLYER ! balloon/aircraft
+
+INTEGER :: ISTORE
+
+!Remark: TPFLYER%TFLYER_TIME%N_CUR and %TPDATES are updated in STATPROF_INSTANT
+CALL  STATPROF_INSTANT( TPFLYER%TFLYER_TIME, ISTORE )
+
+IF ( ISTORE < 1 ) THEN
+  !No profiler storage at this time step
+  TPFLYER%LSTORE = .FALSE.
+ELSE
+  TPFLYER%LSTORE = .TRUE.
+END IF
+
+END SUBROUTINE FLYER_CHECK_STORESTEP
+!----------------------------------------------------------------------------
 
 END MODULE MODE_AIRCRAFT_BALLOON_EVOL
-- 
GitLab