SUBROUTINE RELSPE(LDOPT)

!**** *RELSPE*

!     PURPOSE.
!     --------

!        This routine calculates a spectral orography from an orography on
!     a grid. The new orography minimizes a cost function which is not
!     uniform over the region.

!**   INTERFACE.
!     ----------

!    *CALL* *RELSPE (LDOPT)*

!       *LDOPT*       - Key for optimizing the spectral orography

!     METHOD.
!     -------

!       The function to minimize is the weighted average of the square differenc
!     between the actual (grid point) and the spectrally expanded orography.
!       This routine calls the minimization subroutine *M1QN3* which uses the
!     gradient of the function with respect to the spectral coefficients.

!     EXTERNALS.
!     ----------

!        APLM1G
!        EREESPE
!        ESPEREE
!        REESPE
!        SIMREL
!        SPEREE
!        SPREORD

!     AUTHOR.
!     -------

!         Y. BOUTELOUP and M. DEQUE   1 FEB 91.
!         Modified by R. EL Khatib : 94-03-08 comdeck PTRSPOR
!         Modified by L. Isaksen   : 95-06-06  Reordering of spectral arrays
!         Modified : 95-12-22 M.Hamrud    Change of XREV,XPDS layout
!         98-03-17: R. EL KHATIB : SPREORD
!         Modified by P. Le Moigne : 98-09-29 , minimization parallelized.
!         Modified 98-08-10 by K. YESSAD: removal of LRPOLE option.
!          - removal of one dummy argument in 'CALL SPEREESM'.
!         Modified 99-07-21 by D. Giard : diagnostics for modified envelope
!         Modified 99-09-27 by V. Ivanovici : two way diagnostics for modified envelope
!         Modified 99-11-17 by D. Giard : new spectral transforms
!         Modified 00-09-15 by D. Giard : message passing
!         03-04-07: C. Fischer - use control_vector type (phasing for CY26)
!         Modified 02-11-25 by D. Giard : cleaning for minimization
!         Modified 02-12-16 by D. Giard : LNEWORO3 -> LNEWENV
!         Modified 04-01-07 by D. Giard : ARPEGE-ALADIN consistency for spectral
!                                         fit (with the help of J. Woyciechowska)
!         Modified 05-04-04 by D. Giard : update and merge with ERELSPE
!     ------------------------------------------------------------------

USE PARKIND1  ,ONLY : JPIM     ,JPRB
USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK

USE YOMCT0   , ONLY : LELAM
USE YOMLUN   , ONLY : NULOUT
USE YOMDIM   , ONLY : NSEFRE   ,NSPEC2, NSMAX
USE PTRSPOR  , ONLY : XRNM     ,XSNM     ,XREV
USE YOMGEM   , ONLY : NGPTOT
USE YOMMPG   , ONLY : NDIM0G
USE YOMCLA   , ONLY : LSPSMORO
USE YEMDIM   , ONLY : NISMAX

IMPLICIT NONE

LOGICAL,INTENT(INOUT)    :: LDOPT

REAL(KIND=JPRB) :: ZRNM(NSPEC2), ZREV(NGPTOT)
REAL(KIND=JPRB) :: ZXRNM(NSEFRE), ZXSNM(NSEFRE)
REAL(KIND=JPRB) :: ZDF1, ZF, ZRXMIN, ZFACT
REAL(KIND=JPRB) :: ZHOOK_HANDLE

INTEGER(KIND=JPIM) :: IMODE, INDC, IRZ, ITER, JM, JN, ISP

#include "aplm1g.intfb.h"
#include "ereespe.intfb.h"
#include "esperee.intfb.h"
#include "reespe.intfb.h"
#include "simrel.intfb.h"
#include "speree.intfb.h"
#include "spreord.intfb.h"

IF (LHOOK) CALL DR_HOOK('RELSPE',0,ZHOOK_HANDLE)

!     ------------------------------------------------------------------

!*    1. SAVING THE ACTUAL OROGRAPHY
!        ---------------------------

ZREV(:)=XREV(:)

!     ------------------------------------------------------------------

!*    2. COMPUTING THE REFERENCE SPECTRAL OROGRAPHY
!        ------------------------------------------

!     Spectral coefficients
IF (LELAM) THEN
  CALL EREESPE(1,1,ZRNM,ZREV)
ELSE
  CALL REESPE(1,1,ZRNM,ZREV)
ENDIF
!     ------------------------------------------------------------------
!*    2.5 SMOOTH THE OROGRAPHY WITH A 5del16 operator

IF(LSPSMORO) THEN
  DO JN=0,NSMAX
    DO JM=0,NISMAX(JN)
      ZFACT=(REAL(JM*JM+JN*JN)/(NSMAX*NSMAX))**8
      ZFACT=1._JPRB/(1._JPRB+4._JPRB*ZFACT)
      ISP=NDIM0G(JM)+4*JN
      ZRNM(ISP:ISP+3)=ZRNM(ISP:ISP+3)*ZFACT
    ENDDO
  ENDDO
  LDOPT=.FALSE.
ENDIF

!     Reordering
CALL SPREORD(1,XRNM,ZRNM,.FALSE.)


!*    3. OPTIMIZING THE SPECTRAL OROGRAPHY IF REQUIRED
!        ---------------------------------------------

IF (LDOPT) THEN

!     Calculation of the function for the initial argument
  ZF   = 0.0_JPRB
  INDC = 0
  ITER = 0
  ZXRNM(:)= XRNM(:)
  ZXSNM(:)= XSNM(:)
  CALL SIMREL(INDC,NSEFRE,ZXRNM,ZF,ZXSNM,ITER)
  XRNM(:)= ZXRNM(:)
  XSNM(:)= ZXSNM (:)
  WRITE(NULOUT,9001) ZF

!     Minimisation
  ZRXMIN = 3.E-5_JPRB
  ZDF1   = ZF
  IMODE  = 1
  ITER   = 600
!  IRZ = 4*NSEFRE+NSEFRE*(NSEFRE+1)/2+1000
!  IF (IRZ > 1000000) IRZ = 6*NSEFRE+1000
  IRZ = 6*NSEFRE+1000

  CALL APLM1G(ZF,ZRXMIN,ZDF1,IMODE,ITER,IRZ)

!     Reordering
  CALL SPREORD(1,XRNM,ZRNM,.TRUE.)

ENDIF 

!     ------------------------------------------------------------------

!*    4. RETURNING TO GRIDPOINT SPACE
!        ----------------------------

IF (LELAM) THEN
  CALL ESPEREE(1,1,ZRNM,XREV)
ELSE
  CALL SPEREE(1,1,ZRNM,XREV)
ENDIF 

!     ------------------------------------------------------------------

9001 FORMAT(' INITIAL VALUE ',E12.5)

IF (LHOOK) CALL DR_HOOK('RELSPE',1,ZHOOK_HANDLE)
END SUBROUTINE RELSPE
