#!/bin/bash
####################################################
#               COMPILATION JOB                    #
####################################################
#
# This script assumes default compilation options, to
# change those options : 
# it can either 
# 1. be  edited to add your own options
# 2. take environment variables
# 3. take argument variables
#
# CROCO_SRC : sources for CROCO
#
# CROCO_NETCDFLIB      : netcdf library
# CROCO_NETCDFINC      : netcdf include 
# CROCO_PRISM_ROOT_DIR : OASIS-MCT directory 
# CROCO_XIOS_ROOT_DIR  : XIOS directory
#
# CROCO_CFT1           : compiler
# CROCO_FFLAGS1        : compilation options
# NPROCS               : number of process at compilation
#
# Note that environment or commande line
# variables overwrite hard-coded options
#

####################################################
# BEGIN OF USER'S MODIFICATIONS
####################################################
#
# set source
#
source myenv_mypath.sh
MYSRCDIR=./MY_SRC/

SOURCE1=/ccc/work/cont003/gen6035/jourdain/models/croco-v2.1.0/OCEAN

#
# determine operating system
#
OS=`uname`
echo "OPERATING SYSTEM IS: $OS"

#
# compiler options
#
FC=$FC

#
# set MPI directories if needed
#
MPIF90="mpif90"
MPILIB=""
MPIINC=""

#
# set NETCDF directories
#
#NETCDFLIB=$(nf-config --flibs)
#NETCDFINC=-I$(nf-config --includedir)
NETCDFINC='-I$(NETCDFFORTRAN_ROOT)/include -I$(NETCDF_ROOT)/include'
NETCDFLIB='-L$(NETCDFFORTRAN_LIBDIR) -lnetcdff -L$(NETCDF_ROOT)/lib -lnetcdf'

#
# set OASIS-MCT (or OASIS3) directories if needed
#
PRISM_ROOT_DIR=../../../oasis3-mct/compile_oa3-mct

#
# set XIOS directory if needed
#
# if coupling with OASIS3-MCT is activated :
# => you need to use XIOS compiled with the "--use_oasis oasis3_mct" flag
#-----------------------------------------------------------
XIOS_ROOT_DIR=$HOME/xios

####################################################
# END OF USER'S MODIFICATIONS
####################################################

# EDIT ALL WHAT FOLLOWS AT YOUR OWN RISKS

# Function to display help
function show_help() {
   echo "-----------------------------------------------------------------"
   echo "JOBCOMP script to compile CROCO on OS = Linux or Darwin (Mac OS)"
   echo "-----------------------------------------------------------------"
   echo "Usage: $0 [OPTIONS]"
   echo "Options:"
   echo "  -h, --help                  Show this help message and exit."
   echo "  --src <path>                Specify the CROCO source directory (default: ../croco/OCEAN)."
   echo "  --fc <compiler>             Specify the Fortran compiler (default: gfortran)."
   echo "                              Available = gfortran, ifort, ifc, nvfortran, pgfortran"
   echo "  --mpif90 <compiler>         Specify the MPI Fortran compiler (default: mpif90)."
   echo "  --fflags <flags>            Specify the compilation flags "
   echo "                              (default: if fc=ifort or ifx : '-O2 -mcmodel=medium -fno-alias -i4 -r8 -fp-model precise' )."
   echo "                              (default: if fc=gfortran : '-O2 -mcmodel=medium -fdefault-real-8 -fdefault-double-8 -std=legacy' )."
   echo "                              (default: if fc=nvfortran or pgfortran : '-g -fast -r8 -i4 -mcmodel=medium -Mbackslash' )."
   echo "  --jobs <flags>              Number of processes for compilation (default: 1)"
   echo "  --netcdf-inc <path>         Specify the NetCDF include directory. (default: nf-config --includedir)"
   echo "  --netcdf-lib <path>         Specify the NetCDF library directory. (default: nf-config --flibs)"
   echo "  --xios-dir <path>           Specify the XIOS root directory. (default: $HOME/xios)"
   echo "  --prism-dir <path>          Specify the OASIS-MCT root directory. (default: ../../../oasis3-mct/compile_oa3-mct)"
}

# Parse command-line arguments
while [[ $# -gt 0 ]]; do
   case "$1" in
        -h|--help)
            show_help
            exit 0
            ;;
        --src)
            CROCO_SRC="$2"
            shift 2
            ;;
        --fc)
            CROCO_CFT1="$2"
            shift 2
            ;;
        --mpif90)
            CROCO_MPIF90="$2"
            shift 2
            ;;
        --fflags)
            CROCO_FFLAGS1="$2"
            shift 2
            ;;
        --xios-dir)
            CROCO_XIOS_ROOT_DIR="$2"
            shift 2
            ;;
        --prism-dir)
            CROCO_PRISM_ROOT_DIR="$2"
            shift 2
            ;;
        --netcdf-inc)
            CROCO_NETCDFINC="$2"
            shift 2
            ;;
        --netcdf-lib)
            CROCO_NETCDFLIB="$2"
            shift 2
            ;;
         --jobs)
            NPROCS="$2"
            shift 2
            ;;
        *)
            echo "Unknown option: $1"
            show_help
            exit 1
            ;;
    esac
done


NPROCS=${NPROCS:-1}
SOURCE=${CROCO_SRC-$SOURCE1}
SCRDIR=./Compile
RUNDIR=`pwd`
ROOT_DIR=$SOURCE/..

MPIF90=${CROCO_MPIF90-$MPIF90}

#
# Use GNU Make command, else make
#
MAKE=gmake
which $MAKE > /dev/null 2>&1 || MAKE=make

#
# clean scratch area
#
rm -rf $SCRDIR
mkdir $SCRDIR

#
# AGRIF sources directory
#
AGRIF_SRC=${ROOT_DIR}/AGRIF

#
# copy SOURCE code
#

ls ${SOURCE}/*.F               > /dev/null  2>&1 && \cp ${SOURCE}/*.F   $SCRDIR
ls ${SOURCE}/*.F90             > /dev/null  2>&1 && \cp ${SOURCE}/*.F90 $SCRDIR
ls ${SOURCE}/*.h               > /dev/null  2>&1 && \cp ${SOURCE}/*.h   $SCRDIR
ls ${SOURCE}/*.py              > /dev/null  2>&1 && \cp ${SOURCE}/*.py   $SCRDIR
ls ${SOURCE}/Make*             > /dev/null  2>&1 && \cp ${SOURCE}/Make* $SCRDIR
ls ${SOURCE}/jobcomp           > /dev/null  2>&1 && \cp ${SOURCE}/jobcomp $SCRDIR
ls ${SOURCE}/amr.in            > /dev/null  2>&1 && \cp ${SOURCE}/amr.in $SCRDIR
ls ${AGRIF_SRC}                > /dev/null  2>&1 && \cp -r ${AGRIF_SRC} $SCRDIR
ls ${ROOT_DIR}/XIOS/*.F        > /dev/null  2>&1 && \cp ${ROOT_DIR}/XIOS/*.F $SCRDIR
ls ${ROOT_DIR}/PISCES/*        > /dev/null  2>&1 && \cp -r ${ROOT_DIR}/PISCES/* $SCRDIR
ls ${ROOT_DIR}/PISCES/LIB/*    > /dev/null  2>&1 && \cp -r ${ROOT_DIR}/PISCES/LIB/* $SCRDIR
ls ${ROOT_DIR}/PISCES/SED/*    > /dev/null  2>&1 && \cp ${ROOT_DIR}/PISCES/SED/* $SCRDIR
ls ${ROOT_DIR}/PISCES/kRGB61*  > /dev/null  2>&1 && \cp ${ROOT_DIR}/PISCES/kRGB61* $RUNDIR
ls ${ROOT_DIR}/MUSTANG/*       > /dev/null  2>&1 && \cp -r ${ROOT_DIR}/MUSTANG/* $SCRDIR
ls ${ROOT_DIR}/OBSTRUCTION/*   > /dev/null  2>&1 && \cp -r ${ROOT_DIR}/OBSTRUCTION/* $SCRDIR

if [[ -e "namelist_pisces_ref" ]] ; then
   echo "  file namelist_pisces exists in Run directory"
else
   \cp -f ${ROOT_DIR}/PISCES/namelist_pisces* $RUNDIR
   echo "  file namelist_pisces copied from source directory"
   \cp -f ${ROOT_DIR}/PISCES/SED/namelist_sediment* $RUNDIR
   echo "  file namelist_sediment copied from source directory"
fi

if [[ -d MUSTANG_NAMELIST ]]; then
   echo "  Mustang namelist directory MUSTANG_NAMELIST exists"
else
   mkdir -p $RUNDIR/MUSTANG_NAMELIST
   \cp -rf ${ROOT_DIR}/MUSTANG/MUSTANG_NAMELIST/*txt $RUNDIR/MUSTANG_NAMELIST/.
   echo "  file para*txt copied from source directory"
fi

#
# overwrite with local files
#

ls *.F90   > /dev/null  2>&1 && \cp -f *.F90 $SCRDIR
ls *.F     > /dev/null  2>&1 && \cp -f *.F $SCRDIR
ls *.h     > /dev/null  2>&1 && \cp -f *.h $SCRDIR
ls *.h90   > /dev/null  2>&1 && \cp -f *.h90 $SCRDIR
ls Make*   > /dev/null  2>&1 && \cp -f Make* $SCRDIR
ls jobcomp > /dev/null  2>&1 && \cp -f jobcomp $SCRDIR

## my files (overwrite it) ## = Guillaume's version
\cp -rf $MYSRCDIR/* $SCRDIR

# Change directory
#
cd $SCRDIR
#
# generates LDFLAGS1 according to users notifications
#
LDFLAGS1="${CROCO_NETCDFLIB-$NETCDFLIB}"
CPPFLAGS1="${CROCO_NETCDFINC-$NETCDFINC} -ICROCOFILES/AGRIF_INC"
#
# Set compilation options
#
if [[ $OS == Linux || $OS == Darwin ]] ; then           # ===== LINUX / MAC =====
   if [[ $FC == ifort || $FC == ifc ]] ; then
      CPP1="cpp -traditional -DLinux -DIfort"
      CFT1=ifort
      FFLAGS1="-O2 -mcmodel=medium -fno-alias -i4 -r8 -fp-model precise"
#                FFLAGS1="-O0 -g -i4 -r8 -traceback -check bounds \
#                       -check uninit -CA -CB -CS -ftrapuv -fpe1"
      LDFLAGS1="$LDFLAGS1"
   elif [[ $FC == gfortran ]] ; then
      CPP1="cpp -traditional -DLinux"
      CFT1=gfortran
      FFLAGS1="-O2 -mcmodel=medium -fdefault-real-8 -fdefault-double-8 -std=legacy"
#           FFLAGS1="-O0 -g -fdefault-real-8 -fdefault-double-8 -std=legacy -fbacktrace \
#                   -ffpe-trap=invalid,zero,overflow -fbounds-check -finit-real=nan -finit-integer=8888"
      LDFLAGS1="$LDFLAGS1"
   elif [[ $FC == pgfortran || $FC == nvfortran ]] ; then
       CPP1="cpp  -traditional -DLinux -DXLF"
       CFT1=$FC
       FFLAGS1="-g -fast -r8 -i4 -mcmodel=medium -Mbackslash"
   #FFLAGS1="-g -O0 -C -Kieee -r8 -i4 -traceback"
   if [[ $HOSTNAME == "jean-zay"* ]]; then
      CPP1=$CPP1" -DJEANZAY"
   fi
   else
      echo "Unknown Fortran Compiler"
      exit
   fi
else
   echo "Unknown Operating System"
   exit
fi
#
# Take environment variables for compiler and options
#
FFLAGS1=${CROCO_FFLAGS1-$FFLAGS1}
CFT1=${CROCO_CFT1-$CFT1}

# PISCES Business
if $($CPP1 testkeys.F | grep -i -q p2zisdefined) ; then
        echo "Simple version of PISCES is defined : copy the appropriate namelist"
        \cp -f $RUNDIR/namelist_pisces_cfg_p2z  $RUNDIR/namelist_pisces_cfg
        \cp -f $RUNDIR/namelist_pisces_cfg_p2z  $RUNDIR/namelist_pisces_cfg.1
fi
if $($CPP1 testkeys.F | grep -i -q p5zisdefined) ; then
        echo "Quota version of PISCES is defined : copy the appropriate namelist"
        \cp -f $RUNDIR/namelist_pisces_cfg_p5z  $RUNDIR/namelist_pisces_cfg
        \cp -f $RUNDIR/namelist_pisces_cfg_p5z  $RUNDIR/namelist_pisces_cfg.1
fi


# Netcdf for netcdf.mod in F90
FFLAGS1="$FFLAGS1 $NETCDFINC"
#
# determine if AGRIF compilation is required
#
unset COMPILEAGRIF
echo "Checking COMPILEAGRIF..."
if $($CPP1 testkeys.F | grep -i -q agrifisdefined) ; then
   echo " => AGRIF activated"
   COMPILEAGRIF=TRUE
   FFLAGS1="$FFLAGS1 -IAGRIF"
   LDFLAGS1="-LAGRIF -lagrif $LDFLAGS1"
# we use the AGRIF Makedefs.generic definition
   cp -f Makedefs.generic.AGRIF Makedefs.generic
fi

#
# determine if MPI compilation is required
#
unset COMPILEMPI
echo "Checking COMPILEMPI..."
if $($CPP1 testkeys.F | grep -i -q mpiisdefined) ; then
   echo " => MPI activated"
   COMPILEMPI=TRUE
   LDFLAGS1="$LDFLAGS1 $MPILIB"
   CPPFLAGS1="$CPPFLAGS1 $MPIINC"
   FFLAGS1="$FFLAGS1 $MPIINC"
   CFT1="${MPIF90}"
fi
#
# - Determine if XIOS librairies is required 
# - if it is the case :
#     => if XIOS compiled with oasis, add the OASIS inc. files and librairies
#     => pre-processing (using cpp) of the xml files required by XIOS 
#
unset COMPILEXIOS
echo "Checking COMPILEXIOS..."
XIOS_ROOT_DIR=${CROCO_XIOS_ROOT_DIR-$XIOS_ROOT_DIR}
if $($CPP1 testkeys.F | grep -i -q xiosisdefined) ; then
      echo " => XIOS activated"
      COMPILEXIOS=TRUE
      LDFLAGS1="$LDFLAGS1 $XIOS_ROOT_DIR/lib/libxios.a  -lstdc++ -lnetcdff -lnetcdf"
      CPPFLAGS1="$CPPFLAGS1 -I$XIOS_ROOT_DIR/inc"
      FFLAGS1="$FFLAGS1 -I$XIOS_ROOT_DIR/inc"

      ln -fs $XIOS_ROOT_DIR/bin/xios_server.exe $RUNDIR/.
fi

#
# determine if OASIS librairies are required
#
unset COMPILEOASIS
echo "Checking COMPILEOASIS..."
PRISM_ROOT_DIR=${CROCO_PRISM_ROOT_DIR-$PRISM_ROOT_DIR}
if $($CPP1 testkeys.F | grep -i -q oacplisdefined) ; then
   echo " => OASIS activated"
   CHAN=MPI1
   LIBPSMILE="${PRISM_ROOT_DIR}/lib/libpsmile.${CHAN}.a \
      ${PRISM_ROOT_DIR}/lib/libmct.a  \
      ${PRISM_ROOT_DIR}/lib/libmpeu.a \
      ${PRISM_ROOT_DIR}/lib/libscrip.a"
   PSMILE_INCDIR="-I${PRISM_ROOT_DIR}/build/lib/psmile.${CHAN} \
      -I${PRISM_ROOT_DIR}/build/lib/mct"
   COMPILEOASIS=TRUE
   LDFLAGS1="$LDFLAGS1 $LIBPSMILE $NETCDFLIB"
   CPPFLAGS1="$CPPFLAGS1 ${PSMILE_INCDIR} $NETCDFINC"
   FFLAGS1="$FFLAGS1 ${PSMILE_INCDIR} $NETCDFINC"
fi
#
# prepare and compile the library
#
if [[ $COMPILEAGRIF ]] ; then
    NPROCS=1   #compile on whar process only !
# Find the default C compiler
    CC1=$(echo -e 'dummy_target:\n\t@echo $(CC)' | $MAKE -f - dummy_target)
    CFLAGS1=$(echo -e 'dummy_target:\n\t@echo $(CFLAGS)' | $MAKE -f - dummy_target)
# Test if the C compiler is the GNU Compiler
# if True add '-fcommon' to CFLAGS
    if command -v "$CC1" >/dev/null && "$CC1" -v 2>&1 | grep -q "gcc version"; then
   echo "Using the GNU C compiler. Adding -fcommon to CFLAGS"
   CFLAGS1="$CFLAGS1 -fcommon"
    fi
#
# compile the AGRIF librairy
#
   if [[ $COMPILEMPI ]] ; then
      $MAKE -C AGRIF FC="$CFT1" CPP="$CPP1" CPPFLAGS="-DAGRIF_MPI $MPIINC" FFLAGS="$FFLAGS1" CFLAGS="$CFLAGS1"
   else
      $MAKE -C AGRIF FC="$CFT1" CPP="$CPP1" FFLAGS="$FFLAGS1" CFLAGS="$CFLAGS1"
   fi
   if [[ $OS == Darwin ]] ; then          # DARWIN
# run RANLIB on Darwin system
      ranlib AGRIF/libagrif.a
   fi
#
   mkdir CROCOFILES
   mkdir -p CROCOFILES/AGRIF_MODELFILES
   mkdir -p CROCOFILES/AGRIF_INC
   $CPP1 amr.in | grep -v -e ! -e '#' -e % -e '*' > CROCOFILES/amr.scrum
   mv AGRIF/conv CROCOFILES/.
   for i in *.h *.h90 ; do
      echo $i
      cat cppdefs.h $i | cpp -P | grep -v -e ! -e '#' -e % -e '*' > CROCOFILES/$i
   done
   mv -f CROCOFILES/private_scratch_AMR.h CROCOFILES/private_scratch.h
fi

#
# determine if OPENMP compilation is needed
#
unset COMPILEOMP
echo "Checking COMPILEOMP..."
if $($CPP1 testkeys.F | grep -i -q openmp) ; then
   COMPILEOMP=TRUE
   if [[ $OS == Linux || $OS == Darwin ]] ; then 
      if [[ $FC == gfortran ]] ; then
         FFLAGS1="$FFLAGS1 -fopenmp"
      elif [[ $FC == ifort || $FC == ifc ]] ; then
         INTEL_VERSION=$(ifort --version 2>&1 | grep -oP "(\d+)" | head -n1)
         # Compare the version with 18
         if [[ "$INTEL_VERSION" -gt 18 ]]; then
            FFLAGS1="$FFLAGS1 -qopenmp"
         else
            FFLAGS1="$FFLAGS1 -openmp"
         fi
      else
         FFLAGS1="$FFLAGS1 -openmp"
      fi
   fi
fi

#
# determine if OPENACC compilation is needed
#
unset COMPILEOPENACC
echo "Checking COMPILEOPENACC..."
if $($CPP1 testkeys.F | grep -i -q openaccisdefined) ; then
   COMPILEOPENACC=TRUE
   if [[ $FC == pgfortran || $FC == nvfortran ]] ; then
        FFLAGS1="$FFLAGS1 -acc -Minfo=accel"
   fi
fi

#
# rewrite Makedefs according to previous flags
# with openmp flags if needed
#
rm -f Makedefs
echo 's?$(FFLAGS1)?'$FFLAGS1'?g' > flags.tmp
echo 's?$(LDFLAGS1)?'$LDFLAGS1'?g' >> flags.tmp
echo 's?$(CPP1)?'$CPP1'?g' >> flags.tmp
echo 's?$(CFT1)?'$CFT1'?g' >> flags.tmp
echo 's?$(CPPFLAGS1)?'$CPPFLAGS1'?g' >> flags.tmp
sed -f flags.tmp Makedefs.generic > Makedefs
rm -f flags.tmp

#
# compile croco
#
$MAKE depend
$MAKE -j ${NPROCS} || exit 1


[[ -f croco  ]] && mv croco $RUNDIR
[[ -f partit ]] && mv partit $RUNDIR
[[ -f ncjoin ]] && mv ncjoin  $RUNDIR

cat $ROOT_DIR/OCEAN/croco_ascii.txt
echo CROCO is OK

#
