#!/bin/bash
# $Id: makelmdz_fcm 5093 2024-07-21 11:07:18Z abarral $
# This is a script in Bash.

# FH : on ne crée plus le fichier arch.mk qui est supposé exister par
# FH : ailleurs.
# FH : ulterieurement, ce fichier sera pré-existant pour une série
# FH : de configurations en versions optimisées et debug qui seront
# FH : liés (ln -s) avec arch.mk en fonction de l'architecture.
# FH : Pour le moment, cette version est en test et on peut créer les
# FH : arch.mk en lançant une première fois makegcm.
#
set -eu

function init_vars() {
  ########################################################################
  # options par defaut pour la commande make
  ########################################################################

  dim="96x72x19"
  physique=lmd
  filtre=filtrez
  grille=reg
  couple=false
  veget=false
  inlandsis=false
  rad="oldrad"
  dust=false
  strataer=false
  chimie=false
  parallel=none
  paramem="mem"
  compil_mod=prod
  io=ioipsl
  cosp=false
  cosp2=false
  cospv2=false
  job=1
  full=''
  libphy=false
  isotopes=false
  isoverif=false
  diagiso=false
  isotrac=false
  force_compile=false
  cplocninca=false

  arch_defined="FALSE"
  arch_path="arch"
  arch_default_path="arch"

  LMDGCM=$(pwd)
  LIBOGCM=$LMDGCM/libo
  LIBFGCM=$LMDGCM/libf
  DYN_COMMON_PATH=$LIBFGCM/dyn3d_common
  # path for optional packages, but default set to ".void_dir"
  FILTRE_PATH=$LMDGCM/.void_dir
  DYN_PHYS_PATH=$LMDGCM/.void_dir
  DYN_PHYS_SUB_PATH=$LMDGCM/.void_dir
  PHY_COMMON_PATH=$LMDGCM/.void_dir
  RAD_PATH=$LMDGCM/.void_dir
  INLANDSIS_PATH=$LMDGCM/.void_dir
  DUST_PATH=$LMDGCM/.void_dir
  STRATAER_PATH=$LMDGCM/.void_dir
  COSP_PATH=$LMDGCM/.void_dir
  fcm_path=$LMDGCM/tools/fcm/bin

  ########################################################################
  #  Quelques initialisations de variables du shell.
  ########################################################################

  CPP_KEY="IN_LMDZ"
  INCLUDE=""
  LIB=""
  COMPIL_FFLAGS="%PROD_FFLAGS"
  PARA_FFLAGS=""
  PARA_LD=""
  EXT_SRC=""
}

function read_cmdline_options() {

  ########################################################################
  # lecture des options de mymake
  ########################################################################

  while (($# > 0))
    do
    case $1 in
        "-h") cat <<fin
  Usage :
  makelmdz_fcm [options] -arch nom_arch exec
  [-h]                       : brief help
  [-d [[IMx]JMx]LM]          : IM, JM, LM are the dimensions in x, y, z (default: $dim)
  [-p PHYS]                  : set of physical parametrizations (in libf/phyPHYS), (default: lmd)
  [-prod / -dev / -debug]    : compilation mode production (default) / developement / debug
  [-c false/MPI1/OMCT]       : coupling with ocean model : MPI1/OMCT/false (default: false)
  [-v false/orchideetrunk/orchidee2.1/orchidee2.0/orchidee1.9] : version of the vegetation model to include (default: false)
            false       : no vegetation model
            orchideetrunk : compile using ORCHIDEE trunk from revision 7757 or higher
            orchidee2.1 : compile using ORCHIDEE 2.1 until 4.1 included or until revision 7757 on the trunk
            orchidee2.0 : compile using ORCHIDEE 2.0
            orchidee1.9 : compile using ORCHIDEE up to the version including OpenMP in ORCHIDEE : tag 1.9-1.9.5(version AR5)-1.9.6
            true        : (obsolete; for backward compatibility) use ORCHIDEE tag 1.9-1.9.6
  [-chimie INCA/false]       : with INCA chemistry model or without (default: false)
  [-cplocninca ]        : allow transfer of species from PISCES to INCA (default: false)
  [-cosp true/false]    : compile with/without cosp package (default: false)
  [-cosp2 true/false]    : compile with/without cosp2 package (default: false)
  [-cospv2 true/false]    : compile with/without cospv2 package (default: false)
  [-inlandsis true/false]  : compile with/without inlandsis package (default: false)
  [-rrtm true/false]    : compile with/without rrtm package (default: false)
  [-rad oldrad/rrtm/ecrad]    : compile with oldrad/rrtm/ecrad radiatif code (default: oldrad)
  [-dust true/false]    : compile with/without the dust package by Boucher and co (default: false)
  [-strataer true/false]    : compile with/without the strat aer package by Boucher and co (default: false)
  [-isotopes true/false]    : compile with/without water isotopes in the physics
  [-isoverif true/false]    : compile with/without verifications for water isotopes in the physics
  [-diagiso true/false]    : compile with/without special diagnostics for water isotopes in the physics
  [-isotrac true/false]    : compile with/without tracers of water isotopes in the physics
  [-parallel none/mpi/omp/mpi_omp] : parallelism (default: none) : mpi, openmp or mixted mpi_openmp
  [-g GRI]                   : grid configuration in dyn3d/GRI_xy.h  (default: reg, inclues a zoom)
  [-io ioipsl/mix/xios]                   : Input/Output library (default: ioipsl)
  [-include INCLUDES]        : extra include path to add
  [-cpp CPP_KEY]             : additional preprocessing definitions
  [-mem]                     : reduced memory dynamics (obsolete flag; always on in parallel mode)
  [-filtre NOMFILTRE]        : use filtre from libf/NOMFILTRE (default: filtrez)
  [-link LINKS]              : additional links with other libraries
  [-j n]                     : active parallel compiling on ntask
  [-full]                    : full recompiling
  [-libphy]                  : only compile physics package (no dynamics or main program)
  [-fcm_path path]           : path to the fcm tool (default: tools/fcm/bin)
  [-ext_src path]            : path to an additional set of routines to compile with the model
  [-arch_path path]          : path to architecture files (default: $arch_default_path)
  [-force_compile]           : recompile although there seems to be an on-going compilation
   -arch nom_arch            : target architecture
   exec                      : executable to build
fin
      exit 2;;

        "-d")
      dim=$2; shift; shift;;

        "-p")
      physique="$2";  shift; shift;;

        "-g")
      grille="$2"; shift; shift;;

        "-c")
      couple="$2"; shift; shift;;

        "-prod")
      compil_mod="prod"; shift;;

        "-dev")
      compil_mod="dev"; shift;;

        "-debug")
      compil_mod="debug"; shift;;

        "-io")
      io="$2"; shift; shift;;

        "-v")
      veget="$2"; shift; shift;;

        "-inlandsis")
            inlandsis="$2"; shift; shift;;

        "-rrtm")
            if [ "$2" = "false" ]; then rad="oldrad"; else rad="rrtm"; fi; shift; shift;;

        "-rad")
            rad="$2"; shift; shift;;

        "-dust")
      dust="$2"; shift; shift;;

        "-strataer")
      strataer="$2"; shift; shift;;

        "-chimie")
      chimie="$2"; shift; shift;;

       "-cplocninca")
            cplocninca=TRUE; shift;;

        "-isotopes")
      isotopes="$2"; shift; shift;;

        "-isoverif")
      isoverif="$2"; shift; shift;;

        "-diagiso")
      diagiso="$2"; shift; shift;;

        "-isotrac")
      isotrac="$2"; shift; shift;;

        "-parallel")
      parallel="$2"; shift; shift;;

        "-include")
      INCLUDE="$INCLUDE -I$2"; shift; shift;;

        "-cpp")
      CPP_KEY="$CPP_KEY $2"; shift; shift;;

        "-cosp")
            cosp="$2"; shift; shift;;

        "-cosp2")
            cosp2="$2"; shift; shift;;

        "-cospv2")
            cospv2="$2"; shift; shift;;

        "-mem")
            echo "option -mem is obsolete (now always on in parallel)"
            paramem="mem"; shift;;

        "-filtre")
      filtre=$2; shift; shift;;

        "-link")
      LIB="$LIB $2"; shift; shift;;

        "-fcm_path")
      fcm_path=$2; shift; shift;;

        "-ext_src")
      EXT_SRC=$2; shift; shift;;

        "-j")
      job=$2; shift; shift;;

        "-full")
      full="-full"; shift;;

        "-libphy")
      libphy="true"; shift;;

        "-arch")
      arch=$2; arch_defined="TRUE"; shift; shift;;

        "-arch_path")
      arch_path=$2; shift; shift;;

        "-force_compile")
      force_compile=true; shift;;

        *)
      code="$1"; shift;;
    esac
  done

  ###############################################################
  # path to fcm
  ###############################################################
  # handle case when provided path to fcm was given as a relative
  # path (from makelmdz_fcm script directory) and not an absolute path
  if [[ ${fcm_path:0:1} != "/" ]]; then
    # prepend with makelmdz_fcm location
    fcm_path="$(cd "$(dirname "$0")"; pwd)/$fcm_path"
  fi

  # add fcm_path to PATH
  export PATH=$fcm_path:$PATH
  echo "Path to fcm: $fcm_path"
}

function init_arch() {
  ###############################################################
  # lecture des chemins propres à l'architecture de la machine #
  ###############################################################
  rm -f .void_file
  touch .void_file
  rm -rf .void_dir
  mkdir .void_dir

  if [[ "$arch_defined" = "TRUE" ]]; then
    local i
    for i in "path" "fcm" "env"; do
      rm -f "arch.$i"

      if [[ -f "$arch_path/arch-$arch.$i" ]]; then
        ln -s "$arch_path/arch-$arch.$i" "arch.$i"
      elif [[ -f "$arch_default_path/arch-$arch.$i" ]]; then
        ln -s "$arch_default_path/arch-$arch.$i" "arch.$i"
      elif [[ $i = "env" ]]; then
        ln -s .void_file arch.env
      fi
    done

    # source architecture PATH and ENV files
    source arch.env
    source arch.path
  else
    echo "STOP: You must define a target architecture"; exit 1
  fi
}

function cpp_keys_and_include_mod_path() {
  ########################################################################
  # Definition des clefs CPP, des chemins des includes et modules
  #  et des libraries
  ########################################################################

  if [[ $compil_mod = "prod" ]]; then
    COMPIL_FFLAGS="%PROD_FFLAGS"
  elif [[ $compil_mod = "dev" ]]; then
    COMPIL_FFLAGS="%DEV_FFLAGS"
  elif [[ $compil_mod = "debug" ]]; then
    COMPIL_FFLAGS="%DEBUG_FFLAGS"
  fi

  phys_root=$physique
  if [[ ${physique:0:3} = "lmd" ]]; then phys_root=lmd; fi
  if [[ ${physique:0:4} = "mars" ]]; then phys_root=mars; fi
  if [[ ${physique:0:3} = "std" ]]; then phys_root=std; fi
  if [[ ${physique:0:5} = "venus" ]]; then phys_root=venus; fi
  if [[ ${physique:0:5} = "titan" ]]; then phys_root=titan; fi
  if [[ ${physique:0:3} = "dev" ]]; then phys_root=dev; fi

  if [[ $physique != "nophys" ]]; then
     #We'll use some physics
     CPP_KEY="$CPP_KEY CPP_PHYS"
     # set physics common utilities path
     PHY_COMMON_PATH="${LIBFGCM}/phy_common"
     # set the dyn/phys interface path
     DYN_PHYS_PATH="${LIBFGCM}/dynphy_lonlat"
     DYN_PHYS_SUB_PATH="${LIBFGCM}/dynphy_lonlat/phy${phys_root}"
  fi

  if [[ $filtre = "filtrez" ]]; then
     FILTRE_PATH=${LIBFGCM}/$filtre
  fi

  if [[ $chimie = "INCA" ]]; then
     CPP_KEY="$CPP_KEY INCA"
     INCLUDE="$INCLUDE ${INCA_INCDIR}"
     LIB="$LIB ${INCA_LIBDIR} ${INCA_LIB}"
  fi

  if [[ $isotopes = "true" ]]; then
     CPP_KEY="$CPP_KEY ISO"
  fi

  if [[ $isoverif = "true" ]]; then
     CPP_KEY="$CPP_KEY ISOVERIF"
  fi

  if [[ $diagiso = "true" ]]; then
     CPP_KEY="$CPP_KEY DIAGISO"
  fi

  if [[ $isotrac = "true" ]]; then
     CPP_KEY="$CPP_KEY ISOTRAC"
  fi

  if [[ $couple != "false" ]]; then
      if [[ $couple = "MPI1" ]]; then
        CPP_KEY="$CPP_KEY CPP_COUPLE"
        export OASIS_INCDIR=$LMDGCM/../../prism/X64/build/lib/psmile.MPI1
        export OASIS_LIBDIR=$LMDGCM/../../prism/X64/lib
        INCLUDE="$INCLUDE -I${OASIS_INCDIR}"
        LIB="$LIB -L${OASIS_LIBDIR} -lpsmile.MPI1 -lmpp_io"
      else
        CPP_KEY="$CPP_KEY CPP_COUPLE CPP_OMCT"
        INCLUDE="$INCLUDE ${OASIS_INCDIR}"
        LIB="$LIB ${OASIS_LIBDIR} -lpsmile.MPI1 -lscrip -lmct -lmpeu"
      fi
  fi

  if [[ $parallel = "mpi" ]]; then
     CPP_KEY="$CPP_KEY CPP_PARA CPP_MPI"
     PARA_FFLAGS="%MPI_FFLAGS"
     PARA_LD="%MPI_LD"
  elif [[ $parallel = "omp" ]]; then
     CPP_KEY="$CPP_KEY CPP_PARA CPP_OMP"
     PARA_FFLAGS="%OMP_FFLAGS"
     PARA_LD="%OMP_LD"
  elif [[ $parallel = "mpi_omp" ]]; then
     CPP_KEY="$CPP_KEY CPP_PARA CPP_MPI CPP_OMP"
     PARA_FFLAGS="%MPI_FFLAGS %OMP_FFLAGS"
     PARA_LD="%MPI_LD %OMP_LD"
  fi

  if [[ ( $parallel = "omp" || $parallel = "mpi_omp" ) && $compil_mod = "debug" ]]; then
      echo "Usually, parallelization with OpenMP requires some optimization."
      echo "We suggest switching to \"-dev\"."
  fi

if [[ $veget = "true" || $veget = "orchidee1.9" || $veget = "orchidee2.0" \
   || $veget = "orchidee2.1" || $veget = "orchideetrunk" ]]; then
	echo "doing orchidee"
#NB: option 'true': for backward compatibility. To be used with ORCHIDEE tag 1.9-1.9.6
#    For this case, cpp flag ORCHIDEE_NOOPENMP must be added to the makelmdz_fcm arguments
#    option orchidee1.9 : Compile with ORCHIDEE version up to the inclusion of OpenMP in ORCHIDEE : tag 1.9-1.9.5(version AR5)-1.9.6
   INCLUDE="${INCLUDE} ${ORCH_INCDIR}"
   CPP_KEY="$CPP_KEY CPP_VEGET"
# temporary, for Orchidee versions 1.9.* (before openmp activation)
   if [[ "$veget" = "orchidee1.9" ]]; then
      CPP_KEY="$CPP_KEY ORCHIDEE_NOOPENMP"
    fi
    if [[ "$veget" = "orchidee2.0" ]]; then
      orch_libs="-lsechiba -lparameters -lstomate -lparallel -lorglob -lorchidee"
      CPP_KEY="$CPP_KEY ORCHIDEE_NOUNSTRUCT"
    elif [[ "$veget" = "orchidee2.1" ]]; then
      CPP_KEY="$CPP_KEY ORCHIDEE_NOLIC"
      orch_libs="-lsechiba -lparameters -lstomate -lparallel -lorglob -lorchidee"
    elif [[ "$veget" = "orchideetrunk" ]]; then
      orch_libs="-lorchidee"
    else
      orch_libs="-lsechiba -lparameters -lstomate -lparallel -lorglob"
    fi
    LIB="${LIB} ${ORCH_LIBDIR} ${orch_libs}"
    echo "orchidee lib"
    echo "${LIB}"
  elif [[ $veget != "false" ]]; then
    echo "Option -v $veget does not exist"
    echo "Use ./makelmdz_fcm -h for more information"
    exit  1
  fi

  if [[ $inlandsis = "true" ]]; then
     CPP_KEY="$CPP_KEY CPP_INLANDSIS"
     INLANDSIS_PATH="$LIBFGCM/phy${physique}/inlandsis"
  fi

  if [[ $rad = "rrtm" ]]; then
     CPP_KEY="$CPP_KEY CPP_RRTM"
     RAD_PATH="$LIBFGCM/phy${physique}/rrtm"
  elif [[ $rad = "ecrad" ]]; then
     CPP_KEY="$CPP_KEY CPP_ECRAD"
     RAD_PATH="$LIBFGCM/phy${physique}/ecrad"
  fi

  if [[ $dust = "true" ]]; then
     CPP_KEY="$CPP_KEY CPP_Dust"
     DUST_PATH="$LIBFGCM/phy${physique}/Dust"
  fi

  if [[ $strataer = "true" ]]; then
     CPP_KEY="$CPP_KEY CPP_StratAer"
     STRATAER_PATH="$LIBFGCM/phy${physique}/StratAer"
  fi

  INCLUDE="$INCLUDE ${NETCDF95_INCDIR}"
  LIB="$LIB ${NETCDF95_LIBDIR} ${NETCDF95_LIB}"

  if [[ $io = "ioipsl" ]]; then
     CPP_KEY="$CPP_KEY CPP_IOIPSL"
     INCLUDE="$INCLUDE ${IOIPSL_INCDIR}"
     LIB="$LIB ${IOIPSL_LIBDIR} ${IOIPSL_LIB}"
  elif [[ $io = "mix" ]]; then
     CPP_KEY="$CPP_KEY CPP_IOIPSL CPP_XIOS"
     INCLUDE="$INCLUDE ${IOIPSL_INCDIR} ${XIOS_INCDIR}"
     LIB="$LIB ${IOIPSL_LIBDIR} ${IOIPSL_LIB} ${XIOS_LIBDIR} ${XIOS_LIB}"
  elif [[ $io = "xios" ]]; then
     CPP_KEY="$CPP_KEY CPP_IOIPSL CPP_XIOS CPP_IOIPSL_NO_OUTPUT"
     INCLUDE="$INCLUDE ${IOIPSL_INCDIR} ${XIOS_INCDIR}"
     LIB="$LIB ${IOIPSL_LIBDIR} ${IOIPSL_LIB} ${XIOS_LIBDIR} ${XIOS_LIB}"
  fi

  if [[ $cosp = "true" ]]; then
     CPP_KEY="$CPP_KEY CPP_COSP"
     COSP_PATH="$LIBFGCM/phylmd/cosp"
  fi

  if [[ $cosp2 = "true" ]]; then
     CPP_KEY="$CPP_KEY CPP_COSP2"
     COSP_PATH="$LIBFGCM/phylmd/cosp2"
  fi

  if [[ $cospv2 = "true" ]]; then
     CPP_KEY="$CPP_KEY CPP_COSPV2"
     COSP_PATH="$LIBFGCM/phylmd/cospv2"
  fi

  if [[ $cplocninca = "TRUE" ]]; then
      CPP_KEY="${CPP_KEY} CPP_CPLOCNINCA"
  fi


  INCLUDE="$INCLUDE ${NETCDF_INCDIR}"
  LIB="$LIB ${NETCDF_LIBDIR} ${NETCDF_LIB}"
}

function handle_dimension() {
  ########################################################################
  # calcul du nombre de dimensions
  ########################################################################

  dim_full=$dim
  dim=$(echo "$dim" | sed -e 's/[^0-9]/ /g')
  dimc=$(awk -F" " '{print NF}' <<< "$dim")
  echo "calcul de la dimension: dim=$dim, dimc=$dimc"
  
  ########################################################################
  # Gestion des dimensions du modele.
  # on cree ou remplace le fichier des dimensions
  ########################################################################
  
  cd "$LIBFGCM/grid"
  if [[ -f dimensions.h ]]; then
      if [[ $force_compile = "true" ]]; then
          rm -f "$LIBFGCM/grid/dimensions.h"
      else
          echo "WARNING: you are probably already compiling the model somewhere else."
          echo "Wait until the first compilation is finished before launching this one."
          echo "If you are sure that you are not compiling elsewhere, "
          echo "If you are sure that you are not compiling elsewhere, then"
          echo "rm -f \"$LIBFGCM/grid/dimensions.h\""
          echo "before reruning the compilation"
          echo "or run makelmdz_fcm with option -force_compile"
          exit 1
      fi
  fi
  
  cd "$LIBFGCM/grid/dimension"
  # shellcheck disable=SC2086
  ./makdim $dim
  cat "$LIBFGCM/grid/dimensions.h"
  cd "$LMDGCM"
}

function different_dynamics() {
  ########################################################################
  # Differentes dynamiques (3d, 2d, 1d)
  ########################################################################

  if [[ $dimc = 3 ]]; then
    cd "$LIBFGCM/grid"
    rm fxyprim.h
    cp -p "fxy_${grille}.h" fxyprim.h
  fi

  if [[ $dimc = 1 ]]; then
    CPP_KEY="$CPP_KEY CPP_1D"
    ## no filtre in 1d:
    FILTRE_PATH="$LMDGCM/.void_dir"
    ## no need to compile all routines in dyn3d_common either:
    DYN_COMMON_PATH="$LMDGCM/.void_dir"
    ## no need to compile all routines in dynlmdz_phy...;
    ## (because key ones are included in 1D main program)
    DYN_PHYS_PATH="$LMDGCM/.void_dir"
    DYN_PHYS_SUB_PATH="$LMDGCM/.void_dir"
  fi

  ######################################################################
  # Gestion du filtre qui n'existe qu'en 3d.
  ######################################################################
  if [[ $dimc -gt 2 ]]; then
     filtre="FILTRE=$filtre"
  else
     filtre="FILTRE= L_FILTRE= "
  fi
  echo "MACRO FILTRE $filtre (dimc=$dimc)"
}

function create_config_suffix() {
  ######################################################################
  # Creation du suffixe de la configuration
  ######################################################################

  SUFF_NAME=_${dim_full}
  SUFF_NAME=${SUFF_NAME}_phy${physique}_${rad}

  if [[ $parallel != "none" ]]; then
    SUFF_NAME=${SUFF_NAME}_para
    DYN=dyn${dimc}d${paramem}
    if [[ $paramem = "mem" ]]; then
        SUFF_NAME=${SUFF_NAME}_${paramem}
    else
        echo "The version of the dynamics in dyn3dpar is no longer updated."
        echo "You should use option \"-mem\"."
        exit 1
    fi
  else
    SUFF_NAME=${SUFF_NAME}_seq
    if [[ $dimc = 1 ]]; then
      # dynamics-related routines in"dyn1d" subdirectory of phy${physique}
      DYN=phy${physique}/dyn1d
    else
      DYN=dyn${dimc}d
    fi
  fi

  if [[ $veget != "false" ]]; then
    SUFF_NAME=${SUFF_NAME}_orch
  fi

  if [[ $dust = "true" ]]; then
    SUFF_NAME=${SUFF_NAME}_spla
  fi

  if [[ $couple != "false" ]]; then
    SUFF_NAME=${SUFF_NAME}_couple
  fi

  if [[ $chimie = "INCA" ]]; then
    SUFF_NAME=${SUFF_NAME}_inca
  fi

  if [[ "$isotopes" = "true" ]]; then
    SUFF_NAME=${SUFF_NAME}_iso
  fi
  if [[ "$isoverif" = "true" ]]; then
    SUFF_NAME=${SUFF_NAME}_isoverif
  fi
  if [[ "$isotrac" = "true" ]]; then
    SUFF_NAME=${SUFF_NAME}_isotrac
  fi
  if [[ "$diagiso" = "true" ]]; then
    SUFF_NAME=${SUFF_NAME}_diagiso
  fi

  if [[ $libphy = "true" ]]; then
    # special case where we compile only the physics
    DYN=$LMDGCM/.void_dir
    DYN_COMMON_PATH=$LMDGCM/.void_dir
    FILTRE_PATH=$LMDGCM/.void_dir
    DYN_PHYS_PATH=$LMDGCM/.void_dir
    DYN_PHYS_SUB_PATH=$LMDGCM/.void_dir
    #and there is no main program to generate
    code=""
    SUFF_NAME=""
  else
    SUFF_NAME=${SUFF_NAME}.e
  fi
}

function create_fcm_conf() {
  cd "$LMDGCM"
  config_fcm="config.fcm"
  rm -f "bin/${code}${SUFF_NAME}.e"
  rm -f arch.fcm
  rm -f arch.opt

  {
    echo "%ARCH          $arch"
    echo "%INCDIR        $INCLUDE"
    echo "%LIB           $LIB"
    echo "%ROOT_PATH     $PWD"
    echo "%LIBF          $LIBFGCM"
    echo "%LIBO          $LIBOGCM"
    echo "%DYN           $DYN"
    echo "%DYN_COMMON    $DYN_COMMON_PATH"
    echo "%PHY_COMMON    $PHY_COMMON_PATH"
    echo "%FILTRE        $FILTRE_PATH"
    echo "%PHYS          phy${physique}"
    echo "%DYN_PHYS      $DYN_PHYS_PATH"
    echo "%DYN_PHYS_SUB  $DYN_PHYS_SUB_PATH"
    echo "%RAD           $RAD_PATH"
    echo "%DUST          $DUST_PATH"
    echo "%STRATAER      $STRATAER_PATH"
    echo "%INLANDSIS     $INLANDSIS_PATH"
    echo "%COSP          $COSP_PATH"
    echo "%CPP_KEY       $CPP_KEY"
    echo "%EXEC          $code"
    echo "%SUFF_NAME     $SUFF_NAME"
    echo "%COMPIL_FFLAGS $COMPIL_FFLAGS"
    echo "%PARA_FFLAGS   $PARA_FFLAGS"
    echo "%PARA_LD       $PARA_LD"
    echo "%EXT_SRC       $EXT_SRC"
  } > $config_fcm

  # ecrad conf
  if [[ $rad = "ecrad" ]]; then
    cp bld.cfg.ecrad bld.cfg
  else
    cp bld.cfg.rrtm bld.cfg
  fi

  # arch.fcm and arch.opt
  ln -s "arch/arch-$arch.fcm" arch.fcm
  if [[ -f arch/arch-$arch.opt && $compil_mod = "prod" ]]; then
    ln -s "arch/arch-$arch.opt" arch.opt
  else
    ln -s .void_file arch.opt
  fi
}

function build_gcm() {
  set +e

  rm -f "$LIBOGCM/$arch$SUFF_NAME/.config/fcm.bld.lock"
  ./build_gcm "$fcm_path" -j "$job" $full
  build_status=$?

  rm -rf tmp_src config
  ln -s "$LIBOGCM/$arch$SUFF_NAME/.config" config
  ln -s "$LIBOGCM/$arch$SUFF_NAME/.config/ppsrc" tmp_src
  cp -r "$LIBOGCM/$arch$SUFF_NAME/.config/bin" .

  if [[ -r $LIBFGCM/grid/dimensions.h ]]; then
    # Cleanup: remove dimension.h file
    rm -f "$LIBFGCM/grid/dimensions.h"
  fi

  # build netcdf95 library necessary for the makelmdz script
  if [[ $build_status = 0 ]]; then
    if [[ ! -d tools/netcdf95/include ]]; then
        mkdir tools/netcdf95/include tools/netcdf95/lib
        cp config/inc/netcdf95.mod config/inc/nf95_*mod tools/netcdf95/include
        cp config/obj/netcdf95.o config/obj/nf95_*o config/obj/check_start_count_m.o tools/netcdf95/lib
        cd tools/netcdf95/lib; ar rv libnetcdf95.a -- *.o; ranlib libnetcdf95.a
        cd -
      fi
  fi

  exit $build_status
}

init_vars
read_cmdline_options "$@"
init_arch
cpp_keys_and_include_mod_path
handle_dimension
different_dynamics
create_config_suffix
create_fcm_conf
build_gcm
