#! /bin/bash

# ICON
#
# ------------------------------------------
# Copyright (C) 2004-2026, DWD, MPI-M, DKRZ, KIT, ETH, MeteoSwiss
# Contact information: icon-model.org
# See AUTHORS.TXT for a list of authors
# See LICENSES/ for license information
# SPDX-License-Identifier: BSD-3-Clause
# ------------------------------------------

#______________________________________________________________________________
#
# This script makes finally the run scripts
#
# Original version by Leonidas Linardakis, MPI-M, 2010-11-22
#______________________________________________________________________________

set -eu

typeset -a free_variable
typeset -a free_variable_value
typeset -i no_of_free_variables
no_of_free_variables=0

use_mpi=""
use_openmp=""
use_cpu_time=""
use_mpi_procs_pernode=""
use_mpi_io_procs=""
use_nproma=""
use_nproma_sub=""
use_tasks=""
use_rrtmgp_columns_chunk=""
use_nblocks_c=""
use_openmp_threads=""
use_omp_stacksize=""
use_resources=""
use_memory_model=""
use_memory=""
use_node_usage=""
use_nodes=""
use_account_no=""
use_queue=""
output_name=""
input_name=""
job_name=""
input_folder=""
output_folder=""
use_shell=""
use_ulimit=""
use_BB_SLAVE=""
use_venum_lhost=""
use_cpunum_job=""
secondary_build_dir=""

###
# Data structure and nomenclature
#
# icon is built in what is specified by the configure script as $use_builddir
#   in run/set-up.info.
#
# A job or run script is a script that can be submitted by the HPC scheduler.
# An experiment script is the part of the job script that specifies the most
# settings of the experiment. It should not contain host specific settings.
#
# The experiment script is build from multiple files specified in $input_name,
# separated by space.
# All experiment scripts are located in (or can be reached via)
#   $base_folder/$input_folder
#   default: $input_folder="run"
#
# $base_folder is the parent directory of the directory of
# make_target_runscript, i.e. kind of run/.. .
#
# The job script will be named as $output_name
# The job script will be saved in $output_folder
# The job script will be saved as
#   $output_script="$output_folder/$output_name"
#
# The job name $job_name is used to check the final status of the job.
#   default: $job_name=$output_name
#
# The run/ directory which contains the add_run_routines is $run_folder
#
# The icon binary is
#   $use_builddir/bin/icon
#
# For usual in-source buildings, $base_folder and $use_builddir are the same.
# However in the way icon is build out-of-source by Buildbot, they are
# different. There, icon is build in $use_builddir while runscripts are
# generated and executed in $base_folder.
#
# Calling interface of make_target_runscript
# ==========================================
# Parameters (selection):
#   in_folder: relative path of the input folder (contains the experiments)
#   out_folder: relative path of the ouput folder (will contain the job scripts)
#
#   specific for host rcl:
#       memory: e.g. "24gb". Limit on maximum memory size that can be used
#           In case of SX-Aurora TSUBASA, it's the memory size used on VH.
#       BB_SLAVE: if "true" set the "BB_SLAVE" variable
#       venum_lhost: Number of VE per logical host.
#       cpunum_job: Limit on the number of CPUs that can be used
#           In case of SX-Aurora TSUBASA, it's the number of CPUs used on VH.
#       secondary_build_dir: Path to the additional build directory.
#          The secondary build dir is used for setups that require two ICON
#          binaries like a hybrid NEC host/vector system. If the present
#          build is for vector engine (VE), pass the path for the vector host
#          (VH) binary here or do it vice versa.

eval_argument ()
{
    case $1 in
        "with_mpi")          use_mpi=$2 ;;
        "with_openmp")       use_openmp=$2 ;;
        "cpu_time")          use_cpu_time=$2 ;;
        "mpi_procs_pernode") use_mpi_procs_pernode=$2 ;;
        "mpi_io_procs")      use_mpi_io_procs=$2 ;;
        "nblocks_c")         use_nblocks_c=$2 ;;
        "nproma")            use_nproma=$2 ;;
        "nproma_sub")        use_nproma_sub=$2 ;;
        "ntasks")            use_tasks=$2 ;;
        "openmp_threads")    use_openmp_threads=$2 ;;
        "omp_stacksize")     use_omp_stacksize=$2 ;;
        "resources")         use_resources=$2 ;;
        "memory_model")      use_memory_model=$2 ;;
        "memory")            use_memory=$2 ;;
        "node_usage")        use_node_usage=$2 ;;
        "no_of_nodes")       use_nodes=$2 ;;
        "account_no")        use_account_no=$2 ;;
        "queue")             use_queue=$2 ;;
        "out_script")        output_name=$2 ;;
        "in_script")         input_name="$input_name $2" ;;
        "job_name")          job_name="$2" ;;
        "in_folder")         input_folder=$2 ;;
        "out_folder")        output_folder=$2 ;;
        "with_shell")        use_shell=$2 ;;
        "BB_SLAVE")          use_BB_SLAVE=$2 ;;
        "venum_lhost")       use_venum_lhost=$2 ;;
        "cpunum_job")        use_cpunum_job=$2 ;;
        "secondary_build_dir") secondary_build_dir=$2 ;;
        *)
            ((no_of_free_variables+=1))
            free_variable[$no_of_free_variables]=$1
            free_variable_value[$no_of_free_variables]=$2
    esac
    input_name="${input_name#"${input_name%%[![:space:]]*}"}"
}

#______________________________________________________________________________
# main program

call_folder=$(pwd)
cd $(dirname $0)
this_folder=$(pwd)
base_folder=${this_folder%/*}

# initialize "use_..." variables, which characterize the target
# system, with values stored up by the "configure" script in
# set-up.info
if [[ ! -e "$this_folder/set-up.info" ]] ; then
  echo "[ERROR] 'set-up.info' does not exist."
  echo "Please call 'make_target_runscript' within the build directory."
  echo "(The build directory is the directory in which './configure' was called)."
  exit -1
fi
source $this_folder/set-up.info

# now use arguments passed to make_target_runscript to adjust
# "use_..." variables echo "Arguments for make_target_runscript:"

IFS=" ="
for arg
do
    eval_argument $arg
done

if [[ "x$input_name" == "x" ]] ; then
  echo "[ERROR] Specify in_script=<name>."
  exit -1
fi

first_name=${input_name%% *} # fist space separated entry of input_nanme
output_name=${output_name:="${first_name}.run"}
run_folder="$base_folder/${input_folder:=run}"
output_local_folder=${output_folder:=$input_folder}
output_folder="$base_folder/$output_local_folder"
output_script="$output_folder/$output_name"

if [[ ! -d $output_folder ]] ; then
  mkdir $output_folder
fi

# interpret secondary_build_dir relative to the call directory if it is not absolute
if [[ -n "${secondary_build_dir}" && "${secondary_build_dir:0:1}" != "/" ]]; then
    secondary_build_dir="${call_folder}/${secondary_build_dir}"
fi

job_name=${job_name:=$output_name}

echo -n "Creating the run script  $output_script ... "

# source the script create_target_header to define the shell function create_target_header
source $this_folder/create_target_header

# execute the shell function create_target_header to create the header
create_target_header

# add the script for the experiment and the execution:
input_script=$base_folder/$input_folder/$input_name
for in_name in $input_name
do
  cat_file=$base_folder/$input_folder/$in_name
  if [[ ! -f $cat_file ]] ; then
    echo "[ERROR] script $cat_file not found"
    exit 1
  fi
  cat $cat_file >> $output_script
done

chmod +x $output_script

echo "done."

cd $call_folder

exit 0
#______________________________________________________________________________
