#!/bin/bash

function create_exp() { # executable expname output_grid output_freq  - $* passed to rundef_$expname 
    EXEC=$1 ; shift
    EXP=$1 ; shift
    OUTPUT_GRID=$1 ; shift
    OUTPUT_FREQ=$1 ; shift
    EXPDIR=${EXP}_${EXEC}_$1
    echo "Creating $EXPDIR"
    rm -rf $EXPDIR
    mkdir $EXPDIR
    cd $EXPDIR
    ln -sf $ROOT/build_${EXEC} build
    ln -sf build/bin/icosa_gcm.exe gcm.exe
    cp $ROOT/python/common.py post.py
    echo "post_${EXP}()" >> post.py
#    ln -sf $ROOT/python/post_${EXP}.py post.py
    rundef_$EXP $* > tmp.def
    sort tmp.def | cut -c 7- > run.def
    rm -f tmp.def
    xml_iodef > iodef.xml
    xml_icosa > icosa.xml
    xml_field_def > field_def.xml
    xml_dcmip $EXP $OUTPUT_GRID $OUTPUT_FREQ > filedef_dcmip2016.xml
    job_${EXP} ${EXEC} $* > job.sh
    cd ..
}

function rundef_all() {
    cat <<EOF
100   #------------- Planet ---------------
200   #------------- Dynamics  ------------
300   #-------------- Mesh ----------------
400   #------------ Numerics --------------
500   #----------- Dissipation ------------
600   #-------------- Physics -------------
700   #---------------- Run ---------------
EOF
}

function setvar()
{
    while (($# > 1)) ; do
	ii=${idx[$1]}
	echo "$ii   $1=$2"
	shift ; shift
    done
}
function order()
{
    ii=$1 ; shift
    for name in $* ; do
	((ii+=1))
       idx[${name}]=$ii
#       echo $name ${idx[${name}]}
    done
}

#----------------------------- pre-defined resolutions ---------------------------

function set_nbp_40() {
    setvar dt 480 optim_it 500
    split_${EXEC}_40
}

function set_nbp_80() {
    setvar dt 240 optim_it 1000
    split_${EXEC}_80
}

#-------------------------------- Williamson (1991) ------------------------------

function rundef_W91() {
    NBP=$1 ; TAU=$2
    rundef_all
    set_nbp_$NBP
    setvar caldyn_conserv enstrophy caldyn_eta eta_lag boussinesq .TRUE. llm 1 radius 6.37122e6 g 9.80616
    setvar nitergdiv 2 nitergrot 2 niterdivgrad 2 tau_graddiv $TAU tau_gradrot $TAU tau_divgrad $TAU
    setvar write_period 86400 run_length 2592000 etat0 williamson91.6
}

function job_W91() {
    job_$1_$2 W91_$1
}

#-------------------------------- Jablonowsky & Williamson (2006) ------------------------------

function rundef_DCMIP(){
    rundef_all
    set_nbp_$1
    setvar radius 6.37122e6 g 9.80616 kappa 0.2857143 cpp 1004.5 preff 1e5
    setvar nitergdiv 2 nitergrot 2 niterdivgrad 2 tau_graddiv
}

function rundef_JW06() { # NBP TAU
    NBP=$1 ; TAU=$2
    rundef_DCMIP $NBP
    setvar hydrostatic .FALSE.
    setvar omega 7.292e-5 llm 60 disvert ncar ncar_dz 500 nqtot 2 itau_adv 3
    setvar tau_graddiv $TAU tau_gradrot $TAU tau_divgrad $TAU
    setvar write_period 21600 run_length 864000 etat0 jablonowsky06
}

function job_JW06() { # EXEC NBP
    job_$1_$2 JW06_$1 # e.g. job_mpi_80 JW06_mpi
}

#------------------------------------- DCMIP 2012 ---------------------------------

function rundef_DCMIP21() { # NBP TAU
    NBP=$1 ; TAU=$2
    rundef_DCMIP $NBP
    setvar omega 0. llm 60 disvert ncar ncar_T0 300 ncar_p0 1e5 ncar_disvert_c 1 ncar_dz 500 
    setvar tau_graddiv $TAU tau_gradrot $TAU tau_divgrad $TAU 
    setvar scale_factor 500 write_period 50000 run_length 1.8e6 etat0 dcmip2_schaer_noshear
    setvar rayleigh_friction_type dcmip2_schaer_noshear rayleigh_friction_tau 12500
}

function rundef_DCMIP31() { # NBP TAU HYDRO
    NBP=$1 ; TAU=$2 ; HYDRO=$3
    rundef_DCMIP $NBP
    setvar dysl .TRUE. hydrostatic $3
    setvar omega 0. llm 10 disvert ncar ncar_T0 300 ncar_p0 1e5 ncar_disvert_c 1 ncar_dz 1118
    setvar tau_graddiv $TAU tau_gradrot $TAU tau_divgrad $TAU 
    setvar scale_factor 125 write_period 7500 run_length 4.5e5 etat0 dcmip3
}

function rundef_DCMIP41() { # NBP TAU
    NBP=$1 ; TAU=$2
    rundef_DCMIP $NBP
#    setvar dysl .TRUE.
#    setvar hydrostatic .FALSE.
    setvar diagflux .TRUE.
    setvar omega 7.292e-5 llm 30 disvert ncarl30 nqtot 2 itau_adv 3
    setvar tau_graddiv $TAU tau_gradrot $TAU tau_divgrad $TAU
    setvar write_period 21600 run_length 2592000 etat0 dcmip4 dcmip4_testcase 1
}

function rundef_DCMIP51() { # NBP TAU
    NBP=$1 ; TAU=$2
    rundef_DCMIP $NBP
    setvar omega 7.292e-5 llm 30 disvert ncarl30 nqtot 1 itau_adv 3
    setvar tau_graddiv $TAU tau_gradrot $TAU tau_divgrad $TAU
    setvar write_period 7200 run_length 864000 etat0 dcmip5
    setvar physics dcmip dcmip_physics 0 itau_physics 6
}

function job_DCMIP21() { # EXEC NBP
    job_$1_$2 DCMIP21_$1 # e.g. job_mpi_80 DCMIP31_mpi
}
function job_DCMIP31() { # EXEC NBP
    job_$1_$2 DCMIP31_$1 # e.g. job_mpi_80 DCMIP31_mpi
}
function job_DCMIP41() { # EXEC NBP
    job_$1_$2 DCMIP41_$1
}
function job_DCMIP51() { # EXEC NBP
    job_$1_$2 DCMIP51_$1
}

#------------------------------------- OTHER ---------------------------------

function rundef_bubble() { # NBP TAU
    NBP=$1 ; TAU=$2
    rundef_all
    set_nbp_$NBP
    setvar llm 50 disvert ncar ncar_dz 20 ncar_T0 300 ncar_p0 1e5
#    setvar time_scheme ARK2.3
    setvar nitergdiv 2 nitergrot 2 niterdivgrad 2 tau_graddiv $TAU tau_gradrot $TAU tau_divgrad $TAU
    setvar radius 5e6 scale_factor 10000  g 9.80616 kappa 0.2857143 cpp 1004.5 preff 1e5 omega 0.
}
function job_bubble() { # EXEC NBP
    job_$1_$2 Bubble_$1
}

function rundef_held_suarez() { # NBP TAU
    NBP=$1 ; TAU=$2
    rundef_DCMIP $NBP
    setvar llm 19 disvert std write_period 86400 run_length 2592000 etat0 held_suarez # physics held_suarez
    setvar time_scheme RK2.5
    setvar nitergdiv 2 nitergrot 2 niterdivgrad 2 tau_graddiv $TAU tau_gradrot $TAU tau_divgrad $TAU
}
function job_held_suarez() { # EXEC NBP
    job_$1_$2 HS94_$1
}

#-------------------------------- END TEST CASES -----------------------------

function basic()
{
    rm -rf RUNS
    mkdir RUNS
    cd RUNS
# Williamson 1991
#    create_exp serial W91 two_degree 24h 40 5000 # nbp tau
#    create_exp mpi W91 two_degree 24h 40 5000 # nbp tau
    create_exp mpi JW06 two_degree 24h 40 10000 # nbp tau 
# DCMIP 2012
    create_exp mpi DCMIP21 two_degree 100s 40 90000 # nbp tau 
    create_exp mpi DCMIP31 two_degree 60s 40 90000 .FALSE. # nbp tau hydro
    create_exp mpi_omp DCMIP31 two_degree 60s 40 90000 .TRUE. # nbp tau hydro 
    create_exp mpi_omp DCMIP41 two_degree 24h 40 10000 # nbp tau 
#    create_exp mpi DCMIP51 one_degree 2h  80 10000 # nbp tau 
# Other
    create_exp mpi_omp held_suarez two_degree 24h 40 10000 # nbp tau 
}

function main()
{
# the number associated to each run.def parameter is used to sort the lines and order them in a logical way
    declare -A idx
    order 100 radius omega g cpp kappa preff scale_factor
    order 200 boussinesq hydrostatic dysl
    order 300 nbp optim_it nsplit_i nsplit_j llm omp_level_size disvert ncar_disvert_c ncar_dz ncar_T0 ncar_p0
    order 400 caldyn_eta time_scheme caldyn_conserv dt nqtot itau_adv
    order 500 nitergdiv tau_graddiv nitergrot tau_gradrot niterdivgrad tau_divgrad rayleigh_friction_type rayleigh_friction_tau
    order 600 physics dcmip_physics itau_physics 
    order 700 run_length write_period etat0 dcmip4_testcase diagflux

    basic
}

source current_args
source bash/${arch}.sh
source bash/xml.sh
ROOT=$PWD
main
