#!/bin/bash
set -eu  # error on command failure, and on unset variables
export LC_ALL=C  # standardize awk format

###########################################################################
# Author : Laurent Fairhead et Frédéric Hourdin
# Usage  : install_lmdz.sh -help
#
# bash installation script of the LMDZ model on different computer types :
# Linux PC, "mesocentre" (IPSL-UPMC, IPSL-X), super-computer (IDRIS)
#
# The model is downloaded in the following directory tree
# $MODEL/modipsl/modeles/...
# using the "modipsl" infrastructure created by the "IPSL"
# for coupled (atmosphere/ocean/vegetation/chemistry) climate modeling
# activities.
# Here we only download atmospheric (LMDZ) and vegetation (ORCHIDEE)
# components.
#
# The sources of the models can be found in the "modeles" directory.
# In the present case, LMDZ, ORCHIDEE, and IOIPSL or XIOS (handling of
# input-outputs using the NetCDF library).
#
# The script downloads various source files (including a version of NetCDF)
# and utilities, compiles the model, and runs a test simulation in a
# minimal configuration.
#
# Prerequisites : gfortran, bash or ksh, wget, gunzip, tar, ...
#
# Modif 18/11/2011
#    changes for option real 8.
#      We compile with -r8 (or equivalent) and -DNC_DOUBLE for the GCM
#      but with -r4 for netcdf. Variable real must be set to
#      r4 or r8 at the beginning of the script below.
#
###########################################################################

### Functions

function myget {
  # Get a file from LMDZ repository, make it executable if .(ba)sh
  local url=$1

  local filename
  filename=$(basename "$url")

  wget --no-check-certificate -nv "http://lmdz.lmd.jussieu.fr/pub/$url"
  if [[ $filename =~ .*\.(ba)?sh ]]; then chmod +x "$filename"; fi
}

function set_default_params {
    # Valeur par défaut des parametres
    svn_lmdz=""
    version="20240508.CM7"

    netcdf=1
    bench=1
    SCM=0
    veget="none"
    grid_resolution="32x32x39"
    benchphysiq=""
    compphysiq="lmd"

    parallel="none"
    trusting="testing"
    MODEL=""

    with_xios=0
    opt_makelmdz_xios=""

    rad="rrtm"

    compile_with_fcm=1

    cosp="none"
    aerosols=0
    inlandsis=0

    make_j=8
    clean_install=1

    # Check if on a Mac /!\ Probably doesn't work anymore, to fix one day...
    if [[ $(uname) = "Darwin" ]]; then
        export MAKE="make"
    fi

    optim_debug=""
    arch="local"

    arch="local-gfortran"
    arch_dir=""

    jobcmd=""
}

function read_cmdline_args {
    while (($# > 0)); do
        case $1 in
            "-h") cat <<........fin
        $0 [ -v version ] [ -r svn_release ]
               [ -parallel PARA ] [ -d GRID_RESOLUTION ] [ -bench 0/1 ]
               [-name LOCAL_MODEL_NAME] [-rad RADIATIF]

        -v       "version" like 20150828.trunk, see http://www.lmd.jussieu.fr/~lmdz/Distrib/LISMOI.trunk (default <$version>)

        -r       "svn_release" : either the svn release number or "last" (default <$svn_lmdz>)

        -parallel parallel support: mpi, omp, mpi_omp (mpi with openMP) or none (default: <$parallel>)

        -d        "grid resolution": should be among the available benchs if -bench 1 (valid values: 48x36x19, 48x36x39) (default : <$grid_resolution>)

        -bench     activating the bench or not (0/1) (default: <$bench>)

        -unstable  use unstable tar instead of testing

        -name      name of the folder to install to (default <$MODEL>)

        -netcdf    0, 1 or PATH. 0: do not download NetCDF, look for it in standard locations (/usr);  1: download and compile NetCDF; PATH: full path to an existing installed NetCDF library (default: <$netcdf>)

        -xios      use (download and compile) the XIOS library (will compile the parallel NetCDF4-HDF5 library) (requires to also have -parallel mpi_omp)

        -cosp       to run with cospv1 or cospv2 [none/v1/v2] (default <$cosp>)

        -rad        radiative code: oldrad, rrtm or ecrad (default <$rad>)

        -nofcm      to compile without fcm

        -SCM        install 1D version automatically

        -debug      compile everything in debug mode

        -benchphysiq   to choose which physics.def package to use in the bench (default <$benchphysiq>)

        -compilephysiq   physics to compile the model with (default <$compphysiq>)

        -veget      surface/vegetation scheme treatment controlled by the single variable veget which can have the following values: none: bucket scheme (default); CMIP6 | veget2.0: orchidee version used in CMIP exercise, rev 5661; veget2.2: orchidee branch 2.2, rev 8529 (bundled); number: orchidee version number  [only orch>2.0] (default $veget)

        -spla       activate interactive aerosols

        -inlandsis  activate new snow scheme

        -arch       name of the arch to use (default <$arch>)

        -arch_dir   where to find the arch files (default <$arch_dir>)

        -make_j     number of processes to parallelize installations (default <$make_j>)

        -jobcmd     command prepended to fcm compile jobs, e.g. "srun" (default <$jobcmd>)

        -noclean    will only download necessary files (but no thorough check is made on the integrity of existing files), and will recompile everything (very quick if it's already been compiled before)

........fin
                  exit 1;;
            "-v") version=$2; shift; shift;;
            "-r") svn_lmdz=$2; shift; shift;;
            "-d") grid_resolution=$2; shift; shift;;
            "-unstable") trusting="unstable"; shift;;
            "-cosp") cosp=$2
                     case $cosp in
                         "none"|"v1"|"v2") cosp=$2; shift; shift;;
                         *) echo "Only none v1 v2 for cosp option"; exit 1
                     esac;;
            "-nofcm") compile_with_fcm=0; echo "This option will be reactivated soon (promesse du 8dec2022)"; exit 1;  shift;;
            "-SCM") SCM=1; shift;;
            "-rad") rad=$2
                    case $rad in
                        "oldrad"|"rrtm"|"ecrad") rad=$2; shift; shift;;
                        *) echo "Only oldrad rrtm ecrad for rad option"; exit 1
                    esac;;
            "-parallel") parallel=$2
                         case $parallel in
                             "none"|"mpi"|"omp"|"mpi_omp") parallel=$2; shift; shift;;
                             *) echo "Only none mpi omp mpi_omp for the parallel option"; exit 1
                         esac;;
            "-bench") bench=$2; shift; shift;;
            "-debug") optim_debug=-debug; shift;;
            "-name") MODEL=$2; shift; shift;;
            "-netcdf") netcdf=$2; shift; shift;;
            "-benchphysiq") benchphysiq=$2; shift; shift;;
            "-compilephysiq") compphysiq=$2; shift; shift;;
            "-xios") with_xios=1; shift;;
            "-arch") arch=$2; shift; shift;;
            "-arch_dir") arch_dir=$2; shift; shift;;
            "-veget") veget=$2; shift; shift;;
            "-spla") aerosols=1; shift;;
            "-inlandsis") inlandsis=1; shift;;
            "-make_j") make_j=$2; shift; shift;;
            "-jobcmd") jobcmd=$2; shift; shift;;
            "-noclean") clean_install=0; shift;;
            *)  bash install_lmdz.sh -h; exit 1
        esac
    done

    # Isotopes : Compile and run with isotopes if lmdz_phys="lmdiso" in main.sh
    if [[ $compphysiq = "lmdiso" ]]; then isotopes=1; else isotopes=0; fi

    # Option de compilation pour Cosp
    case $cosp in
        v1) opt_cosp="-cosp true";;
        v2) opt_cosp="-cospv2 true";;
        *) opt_cosp=""
    esac

    #Define veget-related suffix for gcm name
    if [[ $veget = 'none' ]]; then
        suff_orc=''
    else
        suff_orc='_orch'
    fi


    if [[ $parallel = "none" ]]; then
        suff_para='_seq'
    else
        suff_para='_para_mem'
    fi

    if [[ $with_xios = 1 ]]; then opt_makelmdz_xios="-io xios"; fi

    if [[ $aerosols = 1 ]]; then
      opt_aer="-dust true"; suff_aer="_spla"
    else
      opt_aer=""; suff_aer=""
    fi

    if [[ $inlandsis = 1 ]]; then
       opt_inlandsis="-inlandsis true"
    else
       opt_inlandsis=""
    fi

    if [[ $isotopes = 1 ]]; then
      opt_isotopes="-isotopes true"; suff_iso="_iso"
    else
      opt_isotopes="" ; suff_iso=""
    fi

    # set default arch if parallel
    if [[ $arch = "local-gfortran" && $parallel != "none" ]]; then
      arch="local-gfortran-parallel"
      echo "Switching default arch to $arch"
    fi

    # Name of the model's folder. The convention taken here is that models that requires different compilation sources should have a different names.
    local xios_name=""
    if [[ $with_xios = 1 ]]; then xios_name="XIOS"; fi
    if [[ $MODEL = "" ]]; then MODEL="./LMDZ$version${svn_lmdz}OR$veget$xios_name"; fi

    if [[ $arch_dir = "" ]]; then
      arch_dir="$MODEL/modipsl/config/IPSLCM7/ARCH/";
    elif ! readlink -fe "$arch_dir"; then
      echo "STOP: no arch dir <$arch_dir>"; exit 1
    fi
}

function ensure_correct_option_combinations {
    # Check on veget version
    if [[ $veget != 'none' && $veget != "CMIP6" && $veget != "orch2.0" && $veget != "orch2.2" ]]; then
        re='^[0-9]+$'
        if ! [[ $veget =~ $re ]]; then
            echo 'Valeur de l option veget non valable'; exit 1
        fi
    fi

    ## if also compiling XIOS, parallel must be mpi_omp
    if [[ $with_xios = 1 && $parallel != "mpi_omp" ]]; then
        echo "Error, you must set -parallel mpi_omp if you want XIOS"; exit 1
    fi

    if [[ $cosp = "v2" && $with_xios = 0 ]]; then
        echo "Error, Cospv2 cannot run without Xios"; exit 1
    fi

    # STOP if trying to use both ORCHIDEE and Isotopes :
    if [[ $isotopes = 1 && $veget != "none" ]]; then
      echo "STOP: You cannot run LMDZ with ORCHIDEE and ISOtopes at the same time"; exit 1
    fi

    # STOP if trying to use both SPLA and Isotopes :
    if [[ $isotopes = 1 && $aerosols = 1 ]]; then
      echo "STOP: You cannot run LMDZ with Isotopes and aerosols=spla at the same time"; exit 1
    fi

    # (Temporary) STOP if trying to use Isotopes with XIOS :
    # TODO Amaury: check if still relevant
    if [[ $isotopes = 1 && $with_xios = 1 ]]; then
      echo "STOP: Isotopes cannont yet be run with XIOS"; exit 1
    fi

    if [[ $aerosols = 1 && $rad != "rrtm" ]]; then
      echo "STOP: For the time being, <aerosols=spla> requires <rad=rrtm>"; exit 1
    fi
    # TODO: vérifier quelles contraintes sont des contraintes lmdzsetup, et lesquelles sont des vraies contraintes
}

function check_available_software {
    echo "################################################################"
    echo "Check if required software is available"
    echo "################################################################"
    for logiciel in wget tar gzip make gcc cmake m4 c++; do
        if [[ $(which "$logiciel") = "" ]]; then
            echo "You must first install $logiciel on your system"; exit 1
        fi
    done

    cat <<eod > tt.f90
print*,'coucou'
end
eod
    $compiler tt.f90 || a.out
    ./a.out >| tt
    if [[ $(< tt sed -e 's/ //g' ) != "coucou" ]]; then
        echo "problem installing with compiler $compiler"; exit 1
    fi
    \rm tt a.out tt.f90
}

function download_model {
    if [[ $clean_install = 1 ]]; then rm -rf "$MODEL"; fi

    mkdir -p "$MODEL"
    MODEL=$(readlink -e -f "$MODEL"); echo "$MODEL"  # absolute path
    if [[ ! -d "$MODEL/modipsl" ]]; then
        echo "##########################################################"
        echo "Download a slightly modified version of LMDZ"
        echo "##########################################################"
        cd "$MODEL"
        getlog="$(pwd)/get.log"
        echo "logfile : $getlog"
        myget "src_archives/$trusting/modipsl.$version.tar.gz" &>> get.log
        echo "install_lmdz.sh wget_OK $(date)"
        gunzip "modipsl.$version.tar.gz" &>> get.log
        tar xf "modipsl.$version.tar" &>> get.log
        \rm "modipsl.$version.tar"
        cd - &> /dev/null
    fi
}

function init_arch {
    set +e; arch_dir=$(readlink -f "$arch_dir"); set -e  # full path. readlink must be called *after* the path is created

    # Check where default fcm, path, env are located - by default in $arch_path, instead in $MODEL/modipsl/modeles/LMDZ/arch/
    local i fcm_path path_path env_path
    for i in "path" "fcm" "env"; do
      local varname=${i}_path
      if [[ -f $arch_dir/arch-$arch.$i ]]; then
          declare $varname="$arch_dir/arch-$arch.$i"
      else
          declare $varname="$MODEL/modipsl/modeles/LMDZ/arch/arch-$arch.$i"
          if [[ ! -f ${!varname} ]]; then
              echo "STOP: no ${!varname}"; exit 1
          fi
      fi
    done
    default_fcm_path=$fcm_path
    default_path_path=$path_path
    default_env_path=$env_path

    # check compiler
    compiler=$(< "$default_fcm_path" grep "%COMPILER" | sed -e "s/%COMPILER\s*//")

    # load env
    # shellcheck disable=SC1090
    if [[ -f $default_env_path ]]; then source "$default_env_path"; fi

    local mpi_file  # can't be done before as it depends on sourcing the env
    mpi_file=$(readlink -e -f "$(which mpif90)")
    path_mpi=$(dirname "$mpi_file")
    root_mpi=$(dirname "$path_mpi")
}

function install_arch {
    local component=$1

    # Use same .env for all components (for module compatibility)
    cp -f "$default_env_path" "$MODEL/modipsl/modeles/$component/arch" &> /dev/null || true  # allow failure if we're copying the file to itself

    # Use local .path and .fcm is available, otherwise default
    if [[ ! -f "$MODEL/modipsl/modeles/$component/arch/arch-$arch.path" ]]; then
        cp -f "$default_path_path" "$MODEL/modipsl/modeles/$component/arch"

        if [[ $component = "ORCHIDEE" ]]; then
            if [[ $orcbranch = "/tags/ORCHIDEE_2_0/ORCHIDEE" ]]; then  # 2.0 and before have a different fcm convention
                sed -i'' -e "s/-I//" -e "s/-L//" "$MODEL/modipsl/modeles/ORCHIDEE/arch/arch-$arch.path"  # /!\ we only replace first occurence on purpose
            fi
        fi
    fi
    if [[ ! -f "$MODEL/modipsl/modeles/$component/arch/arch-$arch.fcm" ]]; then
        cp -f "$default_fcm_path"  "$MODEL/modipsl/modeles/$component/arch"

        if [[ $component = "XIOS" ]]; then
            # Adapt for XIOS, which uses different naming conventions
            sed -i'' -e "s/%COMPILER/%FCOMPILER/" -e "s/%LINK/%LINKER/" -e "s/-fdefault-real-8//" "$MODEL/modipsl/modeles/XIOS/arch/arch-$arch.fcm"
        fi
    fi
}

function install_netcdf {
    echo "Installing Netcdf"
    local ncdf_compiler="$compiler"

    if [[ $netcdf = 0 ]]; then
        ncdfdir=$(nf-config --prefix)
    else
        cd "$MODEL"

        # Convert non-basic compiler
        case $compiler in
            mpif90) ncdf_compiler=$($compiler --version | head -n 1 | cut -d " " -f -1)
        esac

        case $ncdf_compiler in
            gfortran | GNU) ncdf_compiler="gfortran"; opt1="-compiler gnu"; opt2="-CC gcc -FC gfortran -CXX g++";;
            *)      echo "unexpected compiler $ncdf_compiler for netcdf"; exit 1
        esac

        case $with_xios in
            0) script_install_netcdf="install_netcdf4_hdf5_seq.bash"
               ncdfdir="netcdf4_hdf5_seq"
               opt_="$opt1";;
            1) script_install_netcdf="install_netcdf4_hdf5.bash"
               ncdfdir="netcdf4_hdf5"
               opt_="$opt2 -MPI $root_mpi";;
            *) echo "with_xios=$with_xios, should be 0 or 1"; exit 1
        esac
        if [[ $netcdf = 1 ]]; then
           ncdfdir="$MODEL/$ncdfdir"
        else
           mkdir -p "$netcdf"; ncdfdir="$netcdf/$ncdfdir"
        fi

        echo "Repertoire netcdf $ncdfdir"
        if [[ ! -d $ncdfdir ]]; then
            netcdflog=$(pwd)/netcdf.log
            echo "----------------------------------------------------------"
            echo "Compiling the Netcdf library"
            echo "----------------------------------------------------------"
            echo "log file : $netcdflog"
            myget script_install/$script_install_netcdf &>> "$netcdflog"
            chmod u=rwx $script_install_netcdf
            # shellcheck disable=SC2086
            ./$script_install_netcdf -prefix "$ncdfdir" $opt_ &>> "$netcdflog"
        fi

        # Add to path
        export PATH="$ncdfdir/bin:$PATH"

        #----------------------------------------------------------------------------
        # LF rajout d'une verrue, pour une raison non encore expliquee,
        # la librairie est parfois rangée dans lib64 et non dans lib
        # par certains compilateurs
        if [[ ! -e lib && -d lib64 ]]; then ln -s lib64 lib; fi
        #----------------------------------------------------------------------------

        echo "install_lmdz.sh netcdf_OK $(date)"
    fi

    cat >test_netcdf90.f90 <<EOF
    use netcdf
    print *, "NetCDF library version: ", nf90_inq_libvers()
    end
EOF

    if $ncdf_compiler -I"$ncdfdir"/include test_netcdf90.f90 -L"$ncdfdir"/lib -lnetcdff -lnetcdf -Wl,-rpath="$ncdfdir"/lib && ./a.out; then
        \rm test_netcdf90.f90 a.out
    else
        cat <<EOF
Failed test program using NetCDF-Fortran. You can:
- check that you have NetCDF-Fortran installed in your system
- or specify an installation directory with option -netcdf of install_lmdz.sh
- or download and compile NetCDF-Fortran with option -netcdf 1 of install_lmdz.sh
EOF
        exit 1
    fi

    # Compile NetCDF95
    cd "$MODEL/modipsl/modeles/LMD"*
    echo "Installing NetCDF95"
    cd "$MODEL"
    if [[ ! -d "NetCDF95-0.3" ]]; then
        myget src_archives/netcdf/NetCDF95-0.3.tar.gz
        tar -xf NetCDF95-0.3.tar.gz
        rm NetCDF95-0.3.tar.gz
        cd NetCDF95-0.3
        mkdir -p build && cd build
        netCDF_INCLUDE_DIR=$(nc-config --includedir) netCDF_LIBRARY=$(nc-config --libdir) cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$ncdfdir" -DCMAKE_INSTALL_PREFIX="$MODEL/modipsl"
        make install
    fi
}

function install_IOIPSL {
    install_arch "IOIPSL"

    cd "$MODEL/modipsl/modeles/IOIPSL"
    ioipsllog="$(pwd)/ioipsl.log"
    echo "Compiling IOIPSL, the interface library with Netcdf $(date) (log: $ioipsllog)"

    echo "$jobcmd ./makeioipsl_fcm -j $make_j -arch $arch" > compile.sh
    chmod +x compile.sh
    echo "Compiling IOIPSL using $(\cat compile.sh)"
    if ! ./compile.sh &> "$ioipsllog"; then
        echo "STOP: IOIPSL compile failed, exiting"; exit 1
    fi

    # Link to modipsl/bin
    cp -f bin/* ../../bin

    echo "IOIPSL compiled $(date)"
}

function install_XIOS {
    if [[ $with_xios = 1 ]]; then
        cd "$MODEL/modipsl/modeles"
        xioslog="$(pwd)/XIOS/xios.log"
        echo "##########################################################"
        echo "Compiling XIOS (log $xioslog) $(date)"
        echo "##########################################################"

        # Download XIOS
        local xios_http="http://forge.ipsl.fr/ioserver/svn/XIOS2/branches/xios-2.6"
        local xios_rev="2568"
        
        cd "$MODEL/modipsl/modeles"
        set +e; svn co -r $xios_rev $xios_http XIOS; set -e

        cd XIOS

        install_arch "XIOS"

        echo "$jobcmd ./make_xios --job $make_j --arch $arch" > compile.sh
        chmod +x compile.sh
        echo "$(date) Compiling XIOS using $(\cat compile.sh) (log in $xioslog)"
        if ! ./compile.sh &> "$xioslog"; then
            echo "STOP: XIOS compilation failed, exiting"; exit 1
        fi

        echo "Compiled XIOS $(date)"
    fi
}

function get_orchidee_version {  # Set / Check ORCHIDEE version
    local fetch_rev=""
    orcbranch=""
    case $veget in
        "none") fcm_veget_version="false";;
        "orch2.0" | "CMIP6") fcm_veget_version=orchidee2.0; fetch_rev=7906;;  # in previous tar we used 6592 but with some modifications to xios_orchidee.f90, which got integrated in 7906
        "orch2.2") fcm_veget_version=orchidee2.1; orcbranch="/branches/ORCHIDEE_2_2/ORCHIDEE" ;; # the bundled version
        *) fetch_rev=$veget; fcm_veget_version=orchidee2.1;;  # /!\ arbitary rev only works for orch>=2.1
          # /!\ Note: for orch>=4, we should be using fcm_vegt_version="orchideetrunk". Below copied comment by Adriana in LMDZ_Setup docs:
#          Avec orchidee2.1, on va compiler LMDZ avec le cle cpp ORCHIDEE_NOLIC. On ne va donc pas prendre en compte les avancements fait dans le trunk qui permet que les fractions lic soitent traité par ORCHIDEE. Ca marche très bien sans cela puisque dans tout façon c'est en cours de développement et ce n'est pas activé par default. En fait on devrait compiler le trunk avec -v orchideetrunk mais avec landice_opt>2, ce qui ne change rien par rapport à orchidee2.1
#Si on voudrait activer landice_opt=2 , il faut compiler avec -v orchideetrunk.

    esac

    if [[ -n $fetch_rev ]]; then
        local curr_rev
        curr_rev=$(svn info "$MODEL/modipsl/modeles/ORCHIDEE" | grep Revision: | cut -d ":" -f 2 | cut -c 2-)
        orcbranch=$(svn log -v -q svn://forge.ipsl.fr/orchidee/ -r "$fetch_rev" | grep ORCHIDEE | head -1 | sed -e 's:ORCHIDEE/.*$:ORCHIDEE:' | awk '{print $2}')
        if [[ $fetch_rev != "$curr_rev" ]]; then
            echo "Fetching orch $fetch_rev from the repository (curr: $curr_rev)"
            echo "branch is $orcbranch"
            if [[ $fetch_rev -lt 4465 ]]; then echo 'ORCHIDEE version must be >=4465, exiting'; exit 1; fi
            echo "IF YOU INSTALL ORCHIDEE THE VERY FIRST TIME, ASK for PASSWORD at orchidee-help@listes.ipsl.fr"
            cd "$MODEL/modipsl/modeles"
            rm -rf ORCHIDEE
            svn co -r "$fetch_rev" "svn://forge.ipsl.fr/orchidee/$orcbranch"
            cd - > /dev/null
        fi
    fi

    # Check parallel LMDZ+ORCH
    if [[ (! $veget = "none") && $parallel = "none" && ($used_lmdz_rev -lt 4894) ]]; then
        echo "LMDZ revision must be >=4894 for orchidee without parallel support. Upgrade lmdz or use -parallel mpi_omp."; exit 1
    fi
}

function compile_orchidee {
    install_arch "ORCHIDEE"

    if [[ $veget != "none" ]]; then
        cd "$MODEL/modipsl/modeles/ORCHIDEE"

        orchideelog="$(pwd)/orchidee.log"
        echo "Compiling ORCHIDEE, the continental surface model (log $orchideelog) $(date)"

        local xios_orchid opt_orc
        if [[ $with_xios = 1 ]]; then
            xios_orchid="-xios";
        else
            xios_orchid="-noxios"
        fi
        if [[ $optim_debug = "-debug" ]]; then
            opt_orc="-debug";
        else
            opt_orc="-prod"
        fi

        if [[ $parallel != "none" && ! -d src_parallel ]]; then
           echo "STOP: Orchidee version too old for parallel support"; exit 1
        fi
        echo "$jobcmd ./makeorchidee_fcm -j $make_j $xios_orchid $opt_orc -parallel $parallel -arch $arch" > compile.sh
        chmod +x compile.sh
        echo "Compiling ORCHIDEE using $(\cat compile.sh)"
        if ! ./compile.sh &> "$orchideelog"; then
            echo "STOP: ORCHIDEE compilation failed, exiting"; exit 1
        fi
        echo "Compiled ORCHIDEE $(date)"
    fi
}

function get_lmdz_version {
    LMDZPATH=$(readlink -e -f "$MODEL/modipsl/modeles/LMD"*)
    cd "$LMDZPATH"
    lmdzlog="$(pwd)/lmdz.log"

    if [[ -n $svn_lmdz ]]; then
        local curr_rev
        curr_rev=$(svn info "$MODEL/modipsl/modeles/LMD"* | grep Revision: | cut -d ":" -f 2 | cut -c 2-)
        if [[ $svn_lmdz != "$curr_rev" ]]; then
            local lmdzbranch
            echo "Fetching LMDZ $svn_lmdz from the repository"
            lmdzbranch=$(svn log -v -q https://svn.lmd.jussieu.fr/LMDZ -r "$svn_lmdz" | grep LMDZ | head -1 | sed -e 's:trunk/.*$:trunk:' | awk '{print $2}')
            cd "$MODEL/modipsl/modeles"
            rm -rf LMD*
            svn co -r "$svn_lmdz" "https://svn.lmd.jussieu.fr/LMDZ$lmdzbranch" LMDZ
            cd - > /dev/null
        fi
        used_lmdz_rev=$svn_lmdz
    else  # get svn from info
        set +e; used_lmdz_rev=$(svn info | grep "Last Changed Rev" | cut -c 19-); set -e
        if [[ -z $used_lmdz_rev ]]; then  # svn info failed
            used_lmdz_rev=$(grep 'Revision: [0-9]' "$MODEL"/Read*.md | awk ' { print $2 } ' 2>/dev/null)
            if [[ -z $used_lmdz_rev ]]; then echo "Could not determine lmdz version. This is likely an issue with the .tar itself, please report to LMDZ team."; exit 1; fi
        fi
    fi
}

function compile_lmdz {
    install_arch "LMDZ"
    cd "$LMDZPATH"

    if [[ $used_lmdz_rev -le 4185 ]]; then
        exe_name="bin/gcm_${grid_resolution}_phy${compphysiq}_${suff_para}${suff_orc}${suff_aer}${suff_iso}.e"
    else
        exe_name="bin/gcm_${grid_resolution}_phy${compphysiq}_${rad}${suff_para}${suff_orc}${suff_aer}${suff_iso}.e"
    fi

    local opt_rad
    case $rad in
        oldrad) iflag_rrtm=0; NSW=2; opt_rad="";;
        rrtm)   iflag_rrtm=1; NSW=6
            if [[ $used_lmdz_rev -le 4185 ]]; then
                opt_rad="-rrtm true"
            else
                opt_rad="-rad rrtm"
            fi;;
        ecrad)  iflag_rrtm=2; NSW=6; opt_rad="-rad ecrad";;
        *) echo "Only oldrad rrtm ecrad for rad option"; exit 1
    esac
    if [[ $used_lmdz_rev -le 4185 && $rad = "ecrad" ]]; then
        echo "ecrad only available for LMDZ rev starting with 4186 "; exit 1
    fi

    # Compile
    makelmdz="makelmdz_fcm $optim_debug -arch $arch -j $make_j"
    local para_compile_opt="-mem -parallel $parallel"; if [[ $parallel = "none" ]]; then para_compile_opt=""; fi
    echo "$jobcmd ./$makelmdz $opt_rad $opt_cosp $opt_makelmdz_xios $opt_aer $opt_inlandsis $opt_isotopes -p $compphysiq -d ${grid_resolution} -v $fcm_veget_version $para_compile_opt gcm" > compile.sh
    echo "Compiling lmdz using $(\cat compile.sh) (log: $lmdzlog) $(date)"
    chmod +x ./compile.sh
    if ! ./compile.sh &> "$lmdzlog"; then
        echo "STOP: LMDZ compilation failed, exiting"; exit 1
    fi
    echo "Finished LMDZ compilation $(date)"

    # Check executable
    if [[ ! -f $exe_name ]]; then
        echo "STOP: Compilation failed, can't find the executable"; exit 1
    else
        echo "Compilation successfull, the executable is $exe_name $(date)"
    fi
}

function run_bench {
    cd "$MODEL/modipsl/modeles/LMDZ"*

    if [[ $bench = "tuto" ]]; then
        myget "Training/tutorial.tar"; tar xf tutorial.tar; cd TUTORIAL
        ./init.sh
    elif [[ $bench = 1 ]]; then
        \rm -rf "BENCH${grid_resolution}"
        local bench=bench_lmdz_${grid_resolution}
        myget "3DBenchs/$bench.tar.gz"
        tar xf "$bench.tar.gz"

        if [[ $cosp = "v1" || $cosp = "v2" ]]; then
            cd "BENCH${grid_resolution}"
            # copier les fichiers namelist input et output our COSP
            cp ../DefLists/cosp*_input_nl.txt .
            cp ../DefLists/cosp*_output_nl.txt .
            # Activer la cles ok_cosp pour tourner avec COSP
            sed -e 's@ok_cosp=n@ok_cosp=y@' config.def > tmp
            \mv -f tmp config.def
            cd ..
        fi

        if [[ -n "$benchphysiq" ]]; then
            cd "BENCH${grid_resolution}"
            if [[ -f "physiq.def_${benchphysiq}" ]]; then
                cp "physiq.def_${benchphysiq}" benchphysiq.def
                echo "using physiq.def_${benchphysiq}"
            else
                echo "using standard physiq.def"
            fi
            cd ..
        else
            echo "using standard physiq.def"
        fi

        if [[ $with_xios = 1 ]]; then
            cd "BENCH${grid_resolution}"
            cp ../DefLists/iodef.xml .
            cp ../DefLists/context_lmdz.xml .
            cp ../DefLists/field_def_lmdz.xml .
            # A raffiner par la suite
            echo "A FAIRE : Copier les *xml en fonction de l option cosp"
            cp ../DefLists/field_def_cosp*.xml .
            cp ../DefLists/file_def_hist*xml .
            # adapt iodef.xml to use attached mode
            sed -e 's@"using_server" type="bool">true@"using_server" type="bool">false@' \
                iodef.xml > tmp
            \mv -f tmp iodef.xml

            # and convert all the enabled="_AUTO_" (for libIGCM) to enabled=.FALSE.
            # except for histday
            for histfile in file_def_hist*xml; do
                if [[ "$histfile" = "file_def_histday_lmdz.xml" ]]; then
                    sed -e 's@enabled="_AUTO_"@type="one_file" enabled=".TRUE."@' \
                        "$histfile" > tmp
                    \mv -f tmp "$histfile"
                    sed -e 's@output_level="_AUTO_"@output_level="5"@' "$histfile" \
                        > tmp
                    \mv -f tmp "$histfile"
                    sed -e 's@compression_level="2"@compression_level="0"@' \
                        "$histfile" > tmp
                    \mv -f tmp "$histfile"
                else
                    sed -e 's@enabled="_AUTO_"@type="one_file" enabled=".FALSE."@' \
                        "$histfile" > tmp
                    \mv -f tmp "$histfile"
                fi
            done
            # and add option "ok_all_xml=y" in config.def
            echo "### XIOS outputs" >> config.def
            echo 'ok_all_xml=.true.' >> config.def

            #activer les sorties pour Cosp
            if [[ "$cosp" = "v1" ]]; then
                sed -i'' -e 's@enabled=".FALSE."@enabled=".TRUE."@' \
                         -e 's@output_level="_AUTO_"@output_level="5"@' \
                         -e 's@compression_level="2"@compression_level="0"@' \
                         file_def_histdayCOSP_lmdz.xml
            fi
            if [[ "$cosp" = "v2" ]]; then
                sed -i'' -e 's@compression_level="2"@compression_level="0"@' file_def_histdayCOSPv2_lmdz.xml
                for type_ in hf day mth; do
                    file=file_def_hist${type_}COSP
                    sed -i'' -e 's@src="./'${file}'_lmdz.xml"@src="./'${file}'v2_lmdz.xml"@' context_lmdz.xml
                done
                sed -i'' -e 's@field_def_cosp1.xml@field_def_cospv2.xml@' field_def_lmdz.xml
            fi

            cd ..
        fi

        # Cas Bench avec ecrad
        if [[ $rad = "ecrad" ]]; then
            cd "BENCH${grid_resolution}"
            cp  ../DefLists/namelist_ecrad .
            cp -r ../libf/phylmd/ecrad/data .
            cd ..
        fi

        # Adjusting bench physiq.def to radiative code chosen
        cd "BENCH${grid_resolution}"
        sed -e 's/iflag_rrtm=.*.$/iflag_rrtm='$iflag_rrtm'/' \
            -e 's/NSW=.*.$/NSW='$NSW'/' physiq.def > tmpdef
        \mv tmpdef physiq.def
        cd ..

        cp "$exe_name" "BENCH${grid_resolution}/gcm.e"
        cd "BENCH${grid_resolution}"

        local bench_cmd="./bench.sh"
        if [[ ${parallel:0:3} = "mpi" ]]; then
            # Lancement avec deux procs mpi et 2 openMP
            echo "export OMP_STACKSIZE=800M" > bench.sh
            if [[ "${parallel:4:3}" = "omp" ]]; then
                echo "export OMP_NUM_THREADS=2" >> bench.sh
            fi
            if [[ $cosp = "v1" || $cosp = "v2" ]]; then
                echo "ulimit -s 200000" >> bench.sh
            else
                echo "ulimit -s unlimited" >> bench.sh
            fi
            if which mpirun &> /dev/null; then
                echo "mpirun -np 2 gcm.e &> listing" >> bench.sh
            elif grep -q "Adastra" /etc/motd; then
                local account
                account=$(/usr/sbin/my_project.py -l 2>&1 | head -1 | cut -d " " -f 3- | cut -c 5-)
                bench_cmd="srun --nodes=1 --ntasks=1 --cpus-per-task=2 --threads-per-core=2 --time=0:10:00 --constraint=GENOA --account=$account bash bench.sh"
                echo "./gcm.e &> listing" >> bench.sh
            else
                echo "Error: No command found to run parallel bench"; exit 1
            fi
            if [[ $(hostname | cut -c -6) = "spirit" ]]; then  # ulimit unlimited segfaults on Spirit
                sed -i'' "s/ulimit -s unlimited/ulimit -Ss 8000/" bench.sh
            fi
            # Add rebuild, using reb.sh if it is there
            cat <<EOF >> bench.sh
if [[ -f reb.sh ]]; then
  ./reb.sh histday; ./reb.sh histmth; ./reb.sh histhf;
  ./reb.sh histins; ./reb.sh stomate_history;
  ./reb.sh sechiba_history; ./reb.sh sechiba_out_2
fi
EOF
        else
            echo "./gcm.e &> listing" > bench.sh
        fi
        # Getting orchidee stuff
        if [[ $veget = 'CMIP6' || $veget = "orch2.0" ]]; then  # TODO once we have a 2.2 bench, add it here (or in planned separate bench script)
            echo 'myget 3DBenchs/BENCHCMIP6.tar.gz'
            myget 3DBenchs/BENCHCMIP6.tar.gz
            tar xvzf BENCHCMIP6.tar.gz
            sed -e "s:VEGET=n:VEGET=y:" config.def > tmp
            mv -f tmp config.def
            if [[ $with_xios = 1 ]]; then
                cp ../../ORCHIDEE/src_xml/context_orchidee.xml .
                echo '<context id="orchidee" src="./context_orchidee.xml"/>' > add.tmp
                cp ../../ORCHIDEE/src_xml/field_def_orchidee.xml .
                cp ../../ORCHIDEE/src_xml/file_def_orchidee.xml .
                cp ../../ORCHIDEE/src_xml/file_def_input_orchidee.xml .
                if [[ -f ../../ORCHIDEE/src_xml/context_input_orchidee.xml ]]; then
                       cp ../../ORCHIDEE/src_xml/context_input_orchidee.xml .
                       echo '<context id="orchidee" src="./context_input_orchidee.xml"/>' >> add.tmp
                fi
                sed -e '/id="LMDZ"/r add.tmp' iodef.xml > tmp
                mv tmp iodef.xml
                sed -e'{/sechiba1/ s/enabled="_AUTO_"/type="one_file" enabled=".TRUE."/}' \
                    file_def_orchidee.xml > tmp
                \mv -f tmp file_def_orchidee.xml
                sed -e 's@enabled="_AUTO_"@type="one_file" enabled=".FALSE."@' \
                    file_def_orchidee.xml > tmp
                \mv -f tmp file_def_orchidee.xml
                sed -e 's@output_level="_AUTO_"@output_level="1"@' \
                    file_def_orchidee.xml > tmp
                \mv -f tmp file_def_orchidee.xml
                sed -e 's@output_freq="_AUTO_"@output_freq="1d"@' \
                    file_def_orchidee.xml > tmp
                \mv -f tmp file_def_orchidee.xml
                sed -e 's@compression_level="4"@compression_level="0"@' \
                    file_def_orchidee.xml > tmp
                \mv -f tmp file_def_orchidee.xml
                sed -e 's@XIOS_ORCHIDEE_OK = n@XIOS_ORCHIDEE_OK = y@' \
                    orchidee.def > tmp
                \mv -f tmp orchidee.def
            fi
        fi

        if [[ -f ../arch.env ]]; then source ../arch.env; fi

        echo "EXECUTION DU BENCH"
        date
        if (! $bench_cmd &> out.bench) || ! (tail -n 1 listing | grep "Everything is cool"); then
            tail listing
            echo "Bench FAILED, exiting"; exit 1
        fi
        date
        tail listing
    fi

    # 1D case
    if [[ $SCM = 1 ]]; then
        cd "$MODEL"
        myget 1D/1D.tar.gz
        tar xf 1D.tar.gz
        cd 1D
        for e in "fcm" "env" "path"; do
          cp "$MODEL/modipsl/modeles/LMDZ/arch/arch-$arch.$e" "$MODEL/modipsl/modeles/LMDZ/arch/arch-local.$e"
        done
        if [[ $rad = "oldrad" ]]; then
            sed -i'' -e 's/^rad=.*$/rad=oldrad/' run.sh
            sed -i'' -e 's/^rad=.*$/rad=oldrad/' bin/compile
        elif [[ $rad = ecrad ]] ; then
 		        sed -i'' -e 's/^rad=.*$/rad=ecrad/' run.sh
 		        sed -i'' -e 's/^rad=.*$/rad=ecrad/' bin/compile
 		    fi
        echo "Running 1D/run.sh, log in $(pwd)/run1d.log"
        ./run.sh &> "$(pwd)/run1d.log"
    fi
}

# If sourced: returns, else run setup
if [[ ! "${BASH_SOURCE[0]}" = "$0" ]]; then return 0; fi

echo "install_lmdz.sh DEBUT $(date)"

set_default_params
read_cmdline_args "$@"
ensure_correct_option_combinations
download_model
init_arch
check_available_software
get_lmdz_version
get_orchidee_version
install_netcdf
install_IOIPSL
install_XIOS
compile_orchidee
compile_lmdz
run_bench