#!/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 do_compile_sh {
  local component=$1
  local command=$2
  local log

  log="$(pwd)/$component.log"
  echo "$command" > compile.sh
  echo "Compiling $component using $(\cat compile.sh) (log: $log) $(date)"
    chmod +x ./compile.sh
    if ! ./compile.sh &> "$log"; then
        echo "STOP: $component compilation failed, exiting"; exit 1
    fi
    echo "Finished $component compilation $(date)"
}

function get_svn_branch {
  local url=$1
  local rev=$2
  local res

  res=$(svn log -v -q "$url" -r "$rev" -l 1 | cut -d "/" -f -4)
  if echo "$res" | grep -q "/trunk/"; then
    res=$(echo "$res" | grep "/trunk/" | head -1 | cut -d "/" -f 2-3)
  elif echo "$res" | grep -q "/branches/"; then
    res=$(echo "$res" | grep "/branches/" | head -1 | cut -d "/" -f 2-4)
  else
    echo "Could not determine svn branch for $url, r=$rev"
  fi
  echo "$res"
}

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"
    is_1D="n"
    fortran_file="gcm"

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

    with_xios=0
    opt_makelmdz_xios=""

    icolmdz=0
    dynamico_commit="11001689"

    rad="rrtm"

    compile_with_fcm=1

    cosp="none"
    aerosols=0
    strataer=0
    inlandsis=0

    make_j=8
    clean_install=1
    local="$(pwd)"

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

    optim_flag="-prod"
    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)

        -icolmdz    to compile the icolmdz executable as well as the lonlat one

........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_flag="-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;;
            "-strataer") strataer=1; shift;;
            "-inlandsis") inlandsis=1; shift;;
            "-make_j") make_j=$2; shift; shift;;
            "-jobcmd") jobcmd=$2; shift; shift;;
            "-noclean") clean_install=0; shift;;
            "-icolmdz") icolmdz=1; 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 [[ $strataer = 1 ]]; then
      opt_strataer="-strataer true"
    else
      opt_strataer=""
    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" >/dev/null; then
      echo "STOP: no arch dir <$arch_dir>"; exit 1
    fi

    if ! (echo "$grid_resolution" | grep -q "x"); then
      is_1D="y"
      fortran_file="lmdz1d"
    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 compiling icolmdz, XIOS must be set
    if [[ $icolmdz = 1 && $with_xios = 0 ]]; then
      echo "Error, you must set -xios to compile the icolmdz executable"; exit 1
    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 :
    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
}

function check_available_software {
    local required_soft=("wget" "tar" "gzip" "make" "gcc" "cmake" "m4" "c++")
    echo "Checking if required software is available (${required_soft[*]})"
    for logiciel in "${required_soft[@]}"; 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_modipsl_tar {
    if [[ $clean_install = 1 ]]; then rm -rf "$MODEL"; fi

    mkdir -p "$MODEL"
    MODEL=$(readlink -e -f "$MODEL"); echo "MODEL: $MODEL"  # absolute path
    if [[ ! -d "$MODEL/modipsl" ]]; then
        echo "Downloading a slightly modified version of modipsl+LMDZ"
        cd "$MODEL"
        getlog="$(pwd)/get.log"
        echo "logfile : $getlog"
        set +e; myget "src_archives/$trusting/modipsl.$version.tar.gz" &>> "$getlog"; set -e
        if [[ ! -f "modipsl.$version.tar.gz" ]]; then
          echo "STOP: failed to download modipsl. $getlog: <$(tail "$getlog")>"; exit 1
        fi
        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"
    fi
}

function init_arch {
    cd "$local"
    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 if 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"
        echo "Bin PATH" $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)"
# in case ksh is not installed on the pc
    if [[ ! -x /bin/ksh ]]; then
      sed -i''  -e 's/ksh/bash/' ins_m_prec 
    fi
    echo "$jobcmd ./makeioipsl_fcm -j $make_j -arch $arch $optim_flag" > 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"
        do_compile_sh "XIOS" "$jobcmd ./make_xios --job $make_j --arch $arch"
    fi
}

function get_orchidee_version {  # Set / Check ORCHIDEE version
    echo "Checking Orchidee source 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
        echo "IF YOU INSTALL ORCHIDEE THE VERY FIRST TIME, ASK for PASSWORD at orchidee-help@listes.ipsl.fr"
        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
            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"

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

        if [[ $parallel != "none" && ! -d src_parallel ]]; then
           echo "STOP: Orchidee version too old for parallel support"; exit 1
        fi
        do_compile_sh "ORCHIDEE" "$jobcmd ./makeorchidee_fcm -j $make_j $xios_orchid $optim_flag -parallel $parallel -arch $arch"
    fi
}

function get_lmdz_version {
    echo "Checking LMDZ source version"
    LMDZPATH=$(readlink -e -f "$MODEL/modipsl/modeles/LMD"*)
    cd "$LMDZPATH"

    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=$(get_svn_branch "https://svn.lmd.jussieu.fr/LMDZ" "$svn_lmdz")
            echo "branch is $lmdzbranch"
            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/${fortran_file}_${grid_resolution}_phy${compphysiq}_${suff_para}${suff_orc}${suff_aer}${suff_iso}.e"
    else
        exe_name="bin/${fortran_file}_${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
    local makelmdz="makelmdz_fcm $optim_flag -arch $arch -j $make_j"
    local para_compile_opt="-mem -parallel $parallel"; if [[ $parallel = "none" ]]; then para_compile_opt=""; fi
    do_compile_sh "LMDZ" "$jobcmd ./$makelmdz $opt_rad $opt_cosp $opt_makelmdz_xios $opt_aer $opt_inlandsis $opt_strataer $opt_isotopes -p $compphysiq -d ${grid_resolution} -v $fcm_veget_version $para_compile_opt $fortran_file"

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

function get_dynamico_icosa_version {
  if [[ $icolmdz = 1 ]]; then
    echo "Checking DYNAMICO source version"
    cd "$MODEL/modipsl/modeles"
    if [[ ! -d DYNAMICO ]]; then
      git clone https://gitlab.in2p3.fr/ipsl/projets/dynamico/dynamico.git DYNAMICO
    fi
    cd DYNAMICO
    git checkout master && git checkout $dynamico_commit
    cd - > /dev/null

    echo "Checking ICOSA_LMDZ source version"
    if [[ ! -d ICOSA_LMDZ ]]; then
      svn checkout http://svn.lmd.jussieu.fr/LMDZ/ICOSA_LMDZ
    fi
    cd ICOSA_LMDZ
    svn up -r 5320
  fi
}

function compile_icolmdzor {
    if [[ $icolmdz = 1 ]]; then
      install_arch "ICOSA_LMDZ"
      local para_compile_opt="-parallel $parallel"; if [[ $parallel = "none" ]]; then para_compile_opt=""; fi

      # LMDZ physics package library already available in LMDZ/config/lib directory

      # Compile DYNAMICO
      cd "$MODEL/modipsl/modeles/DYNAMICO"

      # Need to get rather than install the archs as DYNAMICO uses FCMv2 that does not understand the makefile syntax ($shell)
      cd arch
      wget "http://lmdz.lmd.jussieu.fr/pub/src_archives/misc/arch/DYNAMICO/arch-$arch.env"
      wget "http://lmdz.lmd.jussieu.fr/pub/src_archives/misc/arch/DYNAMICO/arch-$arch.fcm"
      wget "http://lmdz.lmd.jussieu.fr/pub/src_archives/misc/arch/DYNAMICO/arch-$arch.path"
      cd ..

      do_compile_sh "DYNAMICO" "$jobcmd ./make_icosa $optim_flag -arch $arch -job $make_j $para_compile_opt -external_ioipsl -with_xios"

      # Compile icosa_lmdz
      echo "Bin PATH before icosalmdz" "$PATH"
      cd "$MODEL/modipsl/modeles/ICOSA_LMDZ"
      do_compile_sh "ICOSA_LMDZ" "$jobcmd ./make_icosa_lmdz -arch $arch -j $make_j -nodeps -p lmd $optim_flag $para_compile_opt -with_orchidee"
      echo "# Running environment for icosa_lmdz" > icosalmdz.env
      echo "# "                                   >> icosalmdz.env
      if [[ -v LD_LIBRARY_PATH ]]; then  
        echo "export LD_LIBRARY_PATH=$ncdfdir/lib:$LD_LIBRARY_PATH" >> icosalmdz.env 
      else 
        echo "export LD_LIBRARY_PATH=$ncdfdir/lib" >> icosalmdz.env
      fi
    fi
}

function run_bench {
    local bench_cmd="./bench.sh"

    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}
      if [[ $compphysiq = "lmdiso" ]]; then bench=bench_lmdz_iso_${grid_resolution}; fi

      if [[ $is_1D = "y" ]] ; then  # 1D
        myget "1D/1D.tar.gz"
        mkdir -p "BENCH${grid_resolution}"
        tar xf "1D.tar.gz" -C "BENCH${grid_resolution}" --strip-components=1
        cd "BENCH${grid_resolution}"
        # Below: ugly, but until we rewrite the 1D case...
        sed -i'' -e "s:^listecas=.*$:listecas=ARMCU/REF:" -e "s:cd \$local/bin ; ./compile -L \$L:#cd \$local/bin ; ./compile -L \$L:" \
            -e "s:./compile -L \$llm:#./compile -L \$llm:" -e "s:ln -sf \$bin/\\\\\${main}\${suffixe}.e .:ln -sf ../../../../../$exe_name \\\\\${main}\${suffixe}.e:" -e "s:gzip listing:cp listing restartphy.nc ../../../../; exit 0:" \
            run.sh
        cp "../$exe_name" bin/
        bench_cmd="./run.sh -rad $rad"  # suppress ferret commands that launch after bench is "over"
      else
        myget "3DBenchs/$bench.tar.gz"
        mkdir "BENCH${grid_resolution}"
        tar xf "$bench.tar.gz" -C "BENCH${grid_resolution}" --strip-components=1

        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}"

        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
        chmod +x bench.sh
        # 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

        fi

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

        echo "STARTING 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
}

function run_bench_icosa {
    local bench_cmd="./bench.sh"

    if [[ $icolmdz = 1 ]]; then
      cd "$MODEL/modipsl/modeles/ICOSA_LMDZ"
      if [[ $bench = 1 ]]; then
        namebench="bench_icolmdz_nbp10_79"
        rm -rf $namebench
        myget "3DBenchs/$namebench.tar.gz"
        mkdir -p $namebench
        tar xf "$namebench.tar.gz" -C "$namebench" --strip-components=1
        cd $namebench
        # copy executables
        if [[ ! -x ../bin/icosa_lmdz.exe ]]; then
          echo "STOP in icosa_lmdz bench, icosa_lmdz.exe executable not present"; exit 1
        fi
        cp ../bin/icosa_lmdz.exe .
         if [[ ! -x ../../XIOS/bin/xios_server.exe ]]; then
          echo "STOP in icosa_lmdz bench, XIOS executable not present"; exit 1
        fi
        cp ../../XIOS/bin/xios_server.exe .
        echo "STARTING ICOSA_LMDZ BENCH"
        date
        if (! $bench_cmd &> out.bench) || ! ( grep "Time elapsed" listing); then
            tail listing
            echo "ICOSA_LMDZ bench FAILED, exiting"; exit 1
        fi
        date
        echo "ICOSA_LMDZ bench finished"
      fi
    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_modipsl_tar
init_arch
check_available_software
get_lmdz_version
get_dynamico_icosa_version
get_orchidee_version
install_netcdf
install_IOIPSL
install_XIOS
compile_orchidee
compile_lmdz
compile_icolmdzor
run_bench
run_bench_icosa
