#!/bin/bash
#
# v4? - 27/02/2020 (+Coupling with NEMO through OASIS)
#
# NAME
#
#   Compile.x - Compile NESTOR, MAR or MAPOST on a machine
#
# SYNOPSIS
#
#   Compile.x  code  [compilor set]
#
# OPERANDS
#
#   code            name of the code to compile                    [NST/MAR/PMP]
#                   (e.g.: './Compile.x NST' compiles NESTOR)
# [ compilor set    integer number refeering to an appropriate machine
#                   listed in the table hereunder.
#                   (e.g.: './COMPILE MAR 3' compiles MAR for the machine 3) ]
#
# DESCRIPTION
#
#   The Compile.x script compiles NESTOR, MAR or MAPOST. It must be located in
#   the directory with the sources to compile.
#   You can set your own preferences in the 'User's paremeters' area (only!).
#
#   The 'compilor set' argument is optional. If specified, it replaces the
#   compilor set which is used by default by the Compile.x script and which is
#   defined with the 'set_foc' variable hereunder. Especially useful for the
#   distinction between rhodes and uqbar on the IDRIS cluster.
#

#*******************************************************************************
# User's parameters
#

#general

. INI.ctr
. FUNCTIONS

#computation precision

MAR_DP=n          #MAR, NESTOR (NST), MAPOST (PMP) in simple precision [n]
NST_DP=n          #                                or double precision [y]
PMP_DP=n          #MAPOST always in simple precision

#compilor set

set_foc=1         #compilor set (foc=FOrtran Compilor)
#     (see further for detailed compiling and linking options)

# set_foc  machine                           Fortran compilor
#
# 1        linux      Linux x86_64           ifort

#MAR (only) compilation specifications

#The next XXvariables are adapted when the script 'CODE' calls 'Compile.x',
#but you can set them by hand if you want to use manually this script.

runnam=XXrunnam   #run name (MAR executable will be MAR_$runnam.exe) (e.g. a04)
domain=XXdomain   #domain name                                       (e.g. EUa)
CODEdir=XXCODEdir #code directory for the above-specified run
STKcod=XXSTKcod   #directory on the stock where to save the code + executable
#(usually: [stock:]MAR/EUa/a04/code)
VE=XXVE       #[T|F]   T: vectorized code,  F: scalar code
RT=XXRT       #[M|E] Morcrette (M) or ecRad (E) radiative transfer scheme (JFG)
#        (existing radCEP_*.d*_* or libecrad.a => no compilation)
CA=XXCA       #[-|b|E] no/Bechtold/Emanuel convective adjustment
#        (existing cvamnh.o      => no compilation)
MP=XXMP       #[T|F] Open-MP

AO=XXAO       #[T|F] AO

ISO=XXISO     #[T|F] ISO

debug=XXdebug #[T|F] debug compilation options (ifort)

#
# End of User's parameters
#*******************************************************************************

#===============================================================================
# Compilors set
#===============================================================================

#[ ${#2} -ne 0 ]         && set_foc=$2
[ $cluster == "foehn" ] && set_foc=3
[ $cluster == "froggy" ] && set_foc=3

#foc = Fortran compilor
#opX = compilation and linking options
#lnk = linking options
#netcdf = NetCDF library

# MAR don't work with ifort 11.1.080, 12.0.5, 11.0, 10.0, 12.1, 13.x,
#           work      ifort 11.1.056, 12.0.2, 10.1,

case $set_foc in
    1) #OpenSuse Linux 12.3 (ifort)
        export inf="OpenSuse/RedHat Linux (tested with ifort 21 and ifx 24)"
        export foc="ifort" # ifx
        export arch="core-avx2"
        if [ $debug == "T" ]; then
            export opt="-w -init=zero -init=arrays -static -vec_report0 -mp1 -check all -traceback"
        else
            export opt="-w -init=zero -init=arrays -static -vec_report0 -mp1 -ipo -O3 -march=$arch -align array64byte -traceback" # -132
        fi
        export lnk="-lnetcdf_ifort" # -lnetcdf_ifx
        export netcdf="/usr/include/netcdf.inc"

        if [ $cluster == "nasa" ]; then
            export lnk="-L /discover/nobackup/eunoble/model/MAR_Libs -lnetcdf_ifort"
            export netcdf="/discover/nobackup/eunoble/model/MAR_Libs/netcdf.inc"
        fi

        if [ $cluster == "obelix" ]; then
            # Linux -static compilation
            export LDIR="$MARdir/lib"
            export lnk="-I${LDIR}/include -L${LDIR}/lib -lnetcdff -lnetcdf -L${LDIR}/lib -lhdf5_hl -lhdf5 -L${LDIR} -lz -lcurl -lm"
            export netcdf="/usr/include/netcdf.inc"
        fi

        [ ${#MARstatic} -eq 1 ] && [ "${MARstatic}" == "n" ] && export opt="-w -init=zero -init=arrays -vec_report0 -mp1 -ipo -O3 -march=$arch -traceback"
        ;;

    2) #OpenSuse Linux (gfortran)
        export inf="OpenSuse Linux 15.5 (gfortran 11-12-13)"
        export foc="gfortran-11"
        export opt="-w -march=native -Ofast "
        export lnk="-lnetcdff -lnetcdf"
        export netcdf="/usr/include/netcdf.inc"
        ;;

    3) # foehn.ujf-grenoble.fr
        export inf="foehn.ujf-grenoble.fr"
        export foc="ifort"
        export opt="-w -init=zero -init=arrays -vec_report0 -O3 -xSSE4.2 -mp1 -ipo -traceback"
        export lnk="-lnetcdf_ifort"
        export netcdf="$HOME/MAR/lib/netcdf/netcdf.inc"
        ;;

    *) #UNDEFINED!!! -> exit
        echo '@&?%! '"compilor error: set_foc undefined [$set_foc]" && exit ;;
esac

[ -f $MARdir/lib/netcdf/netcdf.inc ] && netcdf="$MARdir/lib/netcdf/netcdf.inc"

[ ! -f $netcdf ] && echo "$netcdf not found" && exit

echo $inf >Compile.info
echo $foc >>Compile.info
type $foc >>Compile.info
echo $opt >>Compile.info
echo $lnk >>Compile.info
echo $netcdf >>Compile.info

#===============================================================================
# HELP
#===============================================================================

model=$1

backup=y
[ ${#1} -eq 0 ] && model=MAR && backup=n

[ ${#1} -ne 0 ] && [ $1 != "NST" -a $1 != "MAR" -a $1 != "PMP" ] && head -31 $0 && exit 99

#===============================================================================
# 1 - INITIALISATION
#===============================================================================

Ferror() { echo "  ${1} [KO]"; }
Fgoon() { echo "  ${1} [OK]"; }

#===============================================================================
#  COMPILATION OF NESTOR, MAR OR MAPOST
#===============================================================================

case $model in
    NST)
        #-----------------------------------------------------------------------------
        # NESTOR
        #-----------------------------------------------------------------------------
        [ $foc == "ifort" ] && opt="-w -init=zero -init=arrays -static -vec_report0 -O3 -traceback"
        [ $foc == "ifx" ]   && opt="-w -init=zero -init=arrays -static -vec_report0 -O3 -traceback"
        [ ${#MARstatic} -eq 1 ] && [ "${MARstatic}" == "n" ] && opt="-w -init=zero -init=arrays -vec_report0 -O3 -traceback"
        # NESTOR version
        tmp=$(grep "C |  NESTOR" NESTOR.f | awk '{print($4",",$7,$8,$9)}')
        echo "NESTOR code version     : $tmp"
        echo "Informatic platform     : $inf"
        echo "Fortran compilor        : $foc"
        echo "Options, compil. & link.: $opt"
        echo "Options,           link.: $lnk"
        echo
        # librairy NetCDF
        rm -f NetCDF.inc &>/dev/null
        cp -f $netcdf NetCDF.inc
        # simple/double precision
        [ $NST_DP = "y" ] && ln -s MARout.f.DP MARout.f
        # COMPILATION
        rm -f *.o
        for file in *.f *.f90; do
            if [ -f $file ]; then
                $foc -c $opt $file
                if [ $? -ne 0 ]; then
                    Ferror "$file"
                    DAMNED "compilation error"
                else
                    Fgoon "$file"
                fi
            fi
        done
        # LINKING
        rm -f ../NESTOR.exe
        $foc $opt *.o -o ../NESTOR.exe $lnk
        # END
        echo
        if [ -f ../NESTOR.exe -o -f ../NESTOR_DP.exe ]; then
            Fgoon "NESTOR compilation"
        else
            Ferror "NESTOR compilation"
        fi
        # END OF NESTOR COMPILATION-LINKING
        ;;

    PMP)
        #-----------------------------------------------------------------------------
        # MAPOST
        #-----------------------------------------------------------------------------
        # MAPOST version
        tmp=$(grep "C | MAPOST" MAPOST.f | awk '{print($7,$8)}')
        echo "MAPOST code version     : $tmp"
        echo "Informatic platform     : $inf"
        echo "Fortran compilor        : $foc"
        echo "Options, compil. & link.: $opt"
        echo "Options,           link.: $lnk"
        # librairy NetCDF
        rm -f NetCDF.inc &>/dev/null
        cp -f $netcdf NetCDF.inc
        # COMPILATION
        rm -f *.o
        for file in *.f; do
            $foc -c $opt $file
            if [ $? -ne 0 ]; then
                Ferror "$file"
                DAMNED "compilation error"
            else
                Fgoon "$file"
            fi
        done
        # LINKING
        rm -f ../MAPOST.exe
        $foc $opt *.o -o ../MAPOST.exe $lnk
        # END
        echo
        if [ -f ../MAPOST.exe ]; then
            Fgoon "MAPOST compilation"
        else
            Ferror "MAPOST compilation"
        fi
        echo
        # END OF MAPOST COMPILATION-LINKING
        ;;

    MAR)
        #-----------------------------------------------------------------------------
        # MAR
        #-----------------------------------------------------------------------------
        [ -f $PWD/mar.f   ] && CODEdir=$PWD
        [ -f $PWD/mar.f90 ] && CODEdir=$PWD

        # MAR version
        tmp=$(grep MARv3 mar.f90 | head -1 | awk '{print $4}')
        echo "MAR code version        : $tmp"
        echo "Informatic platform     : $inf"
        echo "Fortran compilator      : $foc ($(type $foc))"
        echo "                version : $($foc -v)"
        echo "Options, compil. & link.: $opt"
        echo "Options,           link.: $lnk"
        echo "CODEdir                 : $CODEdir"
        export openmp=
        if [ $foc == "ifort" ] ||  [ $foc == "ifx" ]; then
            $foc -v &>~/tmp.txt
            ifortV=$(cat ~/tmp.txt)
            ifortV=${ifortV##*\ }
            ifortV=${ifortV%%\.*}
            rm -f ~/tmp.txt
            [ $MP = "T" ] && export openmp=" -openmp"
            [ $ifortV -ge 16 ] && [ $MP = "T" ] && export openmp="-qopenmp"
            [ $foc == "mpiifort" ] && export openmp="-qopenmp"
        fi
        [ $MP = "T" ] && [ "${foc:0:8}" == "gfortran" ] && export openmp="-fopenmp"
        #
        # compile and link
        #
        rm -f NetCDF.inc &>/dev/null
        cp -f $netcdf NetCDF.inc
        # mzabso # done in CODE90
        #  sed "s/mzhyd\=mzabso/mzhyd\=mzabso-1/g"  MARdim.inc > MARdim2.inc
        #  grep "mzabso-1-"                         MARdim2.inc &>/dev/null ; err1=$?
        #  grep "mzabso-1+"                         MARdim2.inc &>/dev/null ; err2=$?
        #  [ $err1 -ne 0 ] && [ $err2 -ne 0 ] && mv MARdim2.inc  MARdim.inc
        #  chmod go+r *.inc  &> /dev/null
        #  rm -f MARdim2.inc &> /dev/null
        echo
        REMARK "compilation"
        echo
        # compilation: cvamnh.f90
        [ $MAR_DP = "T" ] && tmp="-r8" || tmp=""
        file="cvamnh.f90"
        if [ $CA = "b" ]; then
            if [ $debug == "T" ]; then
                Fgoon "$foc $openmp $opt -c $file"
                $foc $openmp $opt -c $file
            elif [ $foc == "ifort" ] || [ $foc == "ifx" ] ; then
                Fgoon "$foc $openmp $tmp -init=zero -init=arrays -w -O3 -march=$arch -traceback -c $file"
                $foc $openmp $tmp -init=zero -init=arrays -w -O3 -march=$arch -traceback -c $file -o cvamnh.o &
                sleep 1
            else
                $foc $openmp $opt $tmp -c $file -o cvamnh.o
            fi
            if [ $? -ne 0 ]; then
                Ferror "$file"
                DAMNED "compilation error"
                exit
            #else
            #    Fgoon "$foc $openmp $opt  -c $file"
            fi
        fi
        echo ""
        # compilation: modules
        modules1="mardim_mod mar_sv_mod"
        # need modules1
        modules2="mardsv_mod marssn_mod"
        # for mar_module
        modules3="mar_ge_mod marphy_mod mar_ao_mod"
        # other modules
        modules4="libUN_mod mar0sv_mod mar_bs_mod mar_ca_mod marctr_mod \
      mar_cu_mod marcdp_mod mar_dy_mod mar_ew_mod mar_fi_mod margrd_mod mar_hy_mod \
      mar_ib_mod mar_io_mod mar_lb_mod marlsv_mod marmagic_mod \
      mar_pb_mod mar_po_mod marqqm_mod mar_ra_mod marsib_mod mar_sl_mod marsnd_mod \
      mar_te_mod mar_tu_mod mar_tv_mod mar_ub_mod mar_vb_mod marvec_mod mar_wk_mod \
      marxsv_mod marysv_mod"
        # JFG: the MAR module with additional variables for using the 
        # radiative transfer scheme varies with the selected scheme.
        if [ $RT == "E" ]; then
            modules4="${modules4} mar_ecrad_mod"
        elif [ $RT == "M" ]; then
            modules4="${modules4} radcep_mod"
        fi
        modules5="marpen_mod mar_tc_mod mar_nh_mod mar_ol_mod" # not used
        modules_optional="trackwind_mod trackwater_mod"
        [[ "$ISO" == "T" ]] && modules_iso="mariso_mod mariso_init mariso_routines mariso_io" || modules_iso=""
        # compilation: all the other *.f90 files
        subroutines="advbot_4 cva_filtering cvagen_mnh dynadv_dlf \
  dynadv_hor dynadv_lfb dynadv_lfb_2p dynadv_sal dynadv_ver dynadv_verq \
  dyndgz dyndps dynfil_1d dynfil_3d dynfil_3d_mp dynfil_3d_mp2 dyngpo \
  dynloa dynqqm dynrho dynwww filatmo grdgeo grdmar grdsig grdstr \
  hydadv_ver hydgen hydmic iniglf inilbc iniphy inisic inisnd inisnd_th \
  inisnd_vl iniubc interp_subpix lbcnud_000 lbcnud_atm lbcnud_ini \
  lbcnud_par lbcnud_srf libUN mar_allocate margau margxyz matinv out_nc outgks outice \
  outsav pbltop phy_sisvat phymar phyrad_top qsat0d qsat2d qsat3d qse_0d \
  sbcnew sisvat sisvat_bsn sisvat_gsn sisvat_ini sisvat_qsn sisvat_qso \
  sisvat_qvg sisvat_sic sisvat_sno_albedo sisvat_sno_filtering sisvat_tso \
  sisvat_tvg sisvat_vgt_albedo sisvat_weq sisvat_zag sisvat_zcr sisvat_zsn \
  sisvatesbl sspray stereosouth svasav timcor timcur time_steps timgeo \
  tlat turabl turhor_dyn turhor_kh turtke_advh turtke_advv turtke_difh \
  turtke_difv turtke_gen"

        for file in $modules1 $modules2 $modules3 $modules4 $modules_iso; do
            Fgoon "$foc $openmp $opt  -c $file"
            $foc $openmp $opt -c $file.f90
            if [ $? -ne 0 ]; then
                Ferror "$file"
                DAMNED "compilation error"
                exit
            fi
        done
        # modules added in f90
        for file in $modules_optional ; do
          if [[ -f $file.f90 ]]; then
            Fgoon "$foc $openmp $opt -c $file.f90"
            $foc $openmp $opt -c $file.f90
            if [ $? -ne 0 ]; then
                Ferror "$file"
                DAMNED "compilation error"
                exit
            fi
          fi
        done

        radCEPo="" # Needed for linking radCEP (see below)
        # compilation: ecRad (ECMWF radiative scheme)
        if [ $RT == "E" ]; then
            if [ ! -f $CODEdir/libecrad.a ]; then
                cd $CODEdir/ecRad
                [ "${foc:0:8}" == "gfortran" ] && ln -sf Makefile-gfortran Makefile
                [ "${foc:0:8}" == "ifx"      ] && ln -sf Makefile-ifx      Makefile
                make # Makefile for ecRad automatically builds everything into an archive libecrad.a
                mv $CODEdir/ecRad/libecrad.a $CODEdir/
                cd $CODEdir
            fi
            if [ -f $CODEdir/ecRad/libecrad.a ] ; then
             mv $CODEdir/ecRad/libecrad.a $CODEdir/
            fi
        # compilation: radCEP.d
        elif [ $RT == "M" ]; then
            radmz=$(grep "mz = " mardim_mod.f90 | cut -d'=' -f2)
            radmz=0$(echo $radmz)
            if [ ! -d radCEP.d/radCEP_${radmz}.d${foc} ]; then
                echo "It takes around 2 hours to compile the ECMWF radiative scheme..."
                #      radvec=256 # faster with ifort
                radvec=1
                [ $MP = "T" ] && radvec=1
                cd $CODEdir/radCEP.d
                time bash radCEP.bash $radvec $radmz
                cd $CODEdir
            fi
            radCEPo="radCEP.d/radCEP_${radmz}.d${foc}/*.o"
            Fgoon "radCEP.d/radCEP_${radmz}.d${foc}"
            #cp -fp  radCEP.d/radCEP_${radmz}.d${foc}/radCEP.inc  $CODEdir/
        fi

        if [ $AO = "T" ]; then
            # compilation: *.f* that need OASIS mod
            for file in mar_module.f90 mar_2_oasis.f90 oasis_2_mar.f90 mar.f90 inigen.f90; do
                $foc $openmp $opt -I$ARCHDIR_INC -Mmpi=mpich -c $file
                if [ $? -ne 0 ]; then
                    Ferror "$file"
                    DAMNED "compilation error"
                    exit
                else
                    Fgoon "$foc $openmp $opt $LIBPSMILE  -c $file"
                fi
            done
        else
            for file in mar.f90 inigen.f90; do
                if [ -f $file ]; then
                    $foc $openmp $opt -c $file
                    if [ $? -ne 0 ]; then
                        Ferror "$file"
                        DAMNED "compilation error"
                        exit
                    else
                        Fgoon "$foc $openmp $opt  -c $file"
                    fi
                fi
            done
        fi
        for file in $subroutines; do
            $foc $openmp $opt -c $file.f90
            if [ $? -ne 0 ]; then
                Ferror "$file"
                DAMNED "compilation error"
                exit
            else
                Fgoon "$foc $openmp $opt  -c $file"
            fi
        done
      
        [ $RT == "E" ] && file=phyrad_ecrad_in.f90 
        [ $RT == "M" ] && file=phyrad_cep_in.f90 

        if [ $debug == "T" ]; then
            Fgoon "$foc $openmp $opt -c $file"
            $foc $openmp $opt -c $file
        elif [ $foc == "ifort" ] || [ $foc == "mpiifort" ] || [ $foc == "ifx" ] ; then
            Fgoon "$foc $openmp -init=zero -init=arrays -w -mp1 -O3 -march=$arch -traceback -c $file"
            $foc $openmp -init=zero -init=arrays -w -mp1 -O3 -march=$arch -traceback -c $file &
            wait
        else
            Fgoon "$foc $openmp $opt -c $file"
            $foc $openmp $opt -c $file
        fi

        # linking
        echo
        REMARK "linking"
        
        # Linking the radiative transfer scheme
        archiveRad=""
        if [ $RT == "E" ]; then
            rm -f ecRad.a &>/dev/null
            cp libecrad.a ecRad.a
            ar r ecRad.a phyrad_ecrad_in.o cvamnh.o
            archiveRad="ecRad.a"
        elif [ $RT == "M" ]; then
            rm -f radCEP.a &>/dev/null
            ar -cq radCEP.a ${radCEPo} phyrad_cep_in.o cvamnh.o
            archiveRad="radCEP.a"
        fi
        rm -f phyrad_cep_in.o phyrad_ecrad_in.o cvamnh.o
       
        if [ $AO = "T" ]; then
            Fgoon "$foc $openmp $opt *.o -o MAR_$runnam.exe $archiveRad $LIBPSMILE -lmpi $lnk"
            $foc $openmp $opt *.o -o MAR_$runnam.exe $archiveRad $LIBPSMILE -lmpi $lnk
        else
            Fgoon "$foc $openmp  $opt  *.o  -o MAR_$runnam.exe $archiveRad $lnk"
            $foc $openmp $opt *.o -o MAR_$runnam.exe $archiveRad $lnk
        fi
        tmp=$?
        [ $backup == "n" ] && exit
        # exit # to uncomment if MAR is recompiled
        #
        # Backup: code and executable if successful compilation
        #
        echo

        if [ $tmp -eq 0 -a -f MAR_$runnam.exe ]; then
            Fgoon "MAR compilation"
            end=yes
        else
            Ferror "MAR compilation"
            end=no
        fi
        [ $cluster == "obelix" ] && end=no
        echo

        if [ $end = "yes" ]; then
            # put the MAR executable on stock
            REMARK "MAR_$runnam.exe stored on stock"
            echo
            smput "$CODEdir" "MAR_$runnam.exe" "$STKcod"
            if [ $? -eq 0 ]; then
                rm -f $CODEdir/MAR_$runnam.exe
                tmp=0
            else
                tmp=1
            fi
            echo
            # save the code directory on stock also
            REMARK "source code for $runnam stored on stock"
            echo
            cd $CODEdir
            if [ $tmp -eq 0 ]; then
                rm -f *.o *.L
                rm -rf $CODEdir/src
                tarX "$CODEdir" "*" "compilink"
                gzip compilink.tar
                smput "$CODEdir" "compilink.tar.gz" "$STKcod"
                cd $CODEdir
                mv $CODEdir/Compile.* ..
                rm -rf $CODEdir/*
                mv ../Compile.* $CODEdir/
            else
                echo "an error occurred, nothing saved on the stock"
            fi
            echo
        else
            if [ $cluster == "obelix" ]; then
                cd $STKcod
                ln -s $CODEdir/MAR_$runnam.exe .
                cd $CODEdir
            fi
        fi

        #END OF MAR COMPILATION-LINKING
        ;;
esac

#-------------------------------------------------------------------------------
#  X - END OF TROUBLES :o)
#-------------------------------------------------------------------------------
