Pierre-Yves Barriat 1 рік тому
батько
коміт
5307324563
32 змінених файлів з 7992 додано та 1 видалено
  1. 42 1
      eORCA025/eORCA025.L121-LUCIA00/README.md
  2. 0 0
      eORCA025/eORCA025.L121-LUCIA00/cfgs/ORCA025_ICE/cpp_ORCA025_ICE.fcm
  3. 76 0
      eORCA025/eORCA025.L121-LUCIA01/README.md
  4. 475 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/NE4_00.sh
  5. 1 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/axis_def_nemo.xml
  6. 567 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/build_namelist_cfg.sh
  7. 40 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/context_nemo.xml
  8. 1 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/domain_def_nemo.xml
  9. 1 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/field_def_nemo-ice.xml
  10. 1 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/field_def_nemo-oce.xml
  11. 130 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/file_def_nemo-ice.xml
  12. 151 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/file_def_nemo-oce.xml
  13. 431 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/grid_def_nemo.xml
  14. 28 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/iodef.xml
  15. 105 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/namelist_ice_cfg
  16. 1 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/namelist_ice_ref
  17. 1 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/namelist_ref
  18. 1 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/nemo
  19. 280 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/dommsk.F90
  20. 220 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icb_oce.F90
  21. 617 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbdia.F90
  22. 450 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbdyn.F90
  23. 534 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbini.F90
  24. 436 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbrst.F90
  25. 182 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbstp.F90
  26. 312 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbthm.F90
  27. 1525 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/sbcblk.F90
  28. 259 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/sbcfwb.F90
  29. 590 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/sbcrnf.F90
  30. 421 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/sbcssr.F90
  31. 113 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/shapiro.F90
  32. 1 0
      eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/cpp_ORCA025_ICE.fcm

+ 42 - 1
eORCA025/eORCA025.L121-LUCIA00/README.md

@@ -81,11 +81,52 @@ eORCA025_sss_WOA2018_c3.0_v19812010.5.1_nohls.nc
 eORCA025_seaice_c3.0_v19802004.0_nohls.nc
 ```
 
+**NE4_01** ran 12 legs (JRA limited to one year: needs others years if you want to continue)
+
 ## Change the forcing
 
 |  CC   | Release | RES |  XIOS  | NEMO | #NODES | Optimization|  WTIME per MONTH        |
 | ----- | --- | ---- | ------ | -------------- | ------ | ------- | -------------------- |
 | `NE4_02.sh` | foss 2022a | e025 |   8  |   592  |   6    |  -O3         | **45min**       |
 | `NE4_03.sh` | foss 2022a | e025 |  10  |  2390  |  24    |  -O3         | **13min**       |
+| `NE4_04.sh` | foss 2022a | e025 |   9  |  1191  |  12    |  -O3         | **21min**       |
+
+- starting from year 1960, restart every month
+- forcing ERA5 leap 3h
+- `nem_time_step_sec=1350` and `lim_time_step_sec=1350`
+
+**NE4_03** runs 15 legs then:
+
+```bash
+[cns182:1940326:0:1940326] Caught signal 11 (Segmentation fault: Sent by the kernel at address (nil))
+==== backtrace (tid:1940326) ====
+ 0 0x000000000004eb20 killpg()  ???:0
+ 1 0x0000000000b0c32f __icblbc_MOD_icb_lbc_mpp()  ???:0
+ 2 0x000000000081127c __icbstp_MOD_icb_stp()  ???:0
+ 3 0x0000000000475e86 __sbcmod_MOD_sbc()  ???:0
+ 4 0x00000000004a60c0 __step_MOD_stp()  ???:0
+ 5 0x000000000046401f __nemogcm_MOD_nemo_gcm()  ???:0
+ 6 0x00000000004594ed main()  ???:0
+ 7 0x000000000003acf3 __libc_start_main()  ???:0
+ 8 0x000000000046123e _start()  ???:0
+=================================
+
+Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
+
+Backtrace for this error:
+#0  0x1489006d0b1f in ???
+#1  0xb0c32f in ???
+#2  0x81127b in ???
+#3  0x475e85 in ???
+#4  0x4a60bf in ???
+#5  0x46401e in ???
+#6  0x4594ec in ???
+#7  0x1489006bccf2 in ???
+#8  0x46123d in ???
+#9  0xffffffffffffffff in ???
+srun: error: cns182: task 2382: Segmentation fault (core dumped)
+srun: launch/slurm: _step_signal: Terminating StepId=458518.0
+slurmstepd: error: *** STEP 458518.0 ON cns159 CANCELLED AT 2023-04-24T11:38:53 ***
+```
 
-- forcing ERA5 leap 3h
+> re-launch 3 times with differents nodes: same issue

+ 0 - 0
eORCA025/eORCA025.L121-LUCIA00/cfgs/ORCA025_ICE/cpp_MY_ORCA025_ICE.fcm → eORCA025/eORCA025.L121-LUCIA00/cfgs/ORCA025_ICE/cpp_ORCA025_ICE.fcm


+ 76 - 0
eORCA025/eORCA025.L121-LUCIA01/README.md

@@ -0,0 +1,76 @@
+Running eORCA025.L121-LUCIA01
+=============================
+
+Same as [eORCA025.L121-LUCIA00](../eORCA025.L121-LUCIA00) but with older XIOS.
+
+**`2482` --> `2326`**
+
+## Source code
+
+Download NEMO code 4.2.0
+
+```bash
+git clone --branch 4.2.0 https://forge.nemo-ocean.eu/nemo/nemo.git nemo_4.2.0
+```
+
+Extract and install XIOS (trunk)
+
+```bash
+svn co http://forge.ipsl.jussieu.fr/ioserver/svn/XIOS/trunk xios_trunk
+```
+
+> revision 2326
+
+## Setup
+
+Same as [eORCA025.L121-LUCIA00](../eORCA025.L121-LUCIA00)
+
+### Compile NEMO 
+
+- with this [**arch file**](../eORCA025.L121-LUCIA00/arch_nemo)
+  > check the path to your XIOS
+- with this [**cfg folder**](./cfgs/ORCA025_ICE)
+  > open and add a line to `nemo_4.2.0/cfgs/ref_cfgs.txt` :
+
+  > ORCA025_ICE OCE ICE
+
+```bash
+./makenemo -m 'lucia_gnu' -r ORCA025_ICE -n 'MY_ORCA025_ICE' -j '4'
+```
+
+### Data
+
+Same as [eORCA025.L121-LUCIA00](../eORCA025.L121-LUCIA00)
+
+## Change XIOS
+
+|  CC   | Release | RES |  XIOS  | NEMO | #NODES | Optimization|  WTIME per MONTH        |
+| ----- | --- | ---- | ------ | -------------- | ------ | ------- | -------------------- |
+| `NE4_22.sh` | foss 2022a | e025 | 100  |   600  |   7    |  -O3         | **40min**       |
+
+- starting from year 1960, restart every month
+- forcing ERA5 leap 3h
+- `nem_time_step_sec=1350` and `lim_time_step_sec=1350`
+
+Initial data:
+
+```bash
+Goutorbe_ghflux.nc
+eORCA025_ghflux_v2.0_c3.0_weights_bilin_nohls.nc
+eORCA025_iwm_b0.2_v1.0_nohls.nc
+eORCA025.L121_domain_cfg_b0.5_c3.0_d1.0_nohls_clean.nc
+eORCA025_runoff_b0.2_v0.0_nohls.nc
+eORCA025_calving_b0.2_v2.3_nohls.nc
+eORCA025_ttv_b0.2_v0.0_nohls.nc
+eORCA025_bfr2d_v0.2_nohls.nc
+eORCA025_shlat2d_v0.2_nohls.nc
+eORCA025_distcoast_b0.2_v0.0_nohls.nc
+eORCA025.L121-empc_nohls.nc
+eORCA025.L121_WOA2018_c3.0_d1.0_v19812010.5.2_nohls.nc
+chlorophyl_v0.0.nc
+eORCA025_chlorophyl_v0.0_c3.0_weights_bilin_nohls.nc
+eORCA025_sss_WOA2018_c3.0_v19812010.5.1_nohls.nc
+eORCA025_seaice_c3.0_v19802004.0_nohls.nc
+```
+
+**NE4_22** is runnning... (10 legs now)

+ 475 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/NE4_00.sh

@@ -0,0 +1,475 @@
+#!/bin/bash
+
+#
+# Job options 
+#
+#SBATCH --job-name=NE4_00
+#SBATCH --time=12:00:00
+#SBATCH --account=ecearth
+#
+#SBATCH --nodes=7
+#SBATCH --exclusive
+##SBATCH --ntasks=1320
+#SBATCH --ntasks-per-node=100
+#SBATCH --partition=batch
+#
+set -ueo pipefail
+#
+LOCAL_NODES=7
+LOCAL_TASKS=700
+#
+stdout_file=${SLURM_SUBMIT_DIR-$PWD}/${SLURM_JOB_NAME-"local"}_${SLURM_JOB_ID-"id"}.log
+exec > ${stdout_file}
+echo "------------------ Job Info --------------------"
+echo "jobid : ${SLURM_JOB_ID-"id"}"
+echo "jobname : ${SLURM_JOB_NAME-"local"}"
+echo "nodename : ${SLURMD_NODENAME-"nlocal"}"
+echo "# nodes : ${SLURM_JOB_NUM_NODES-$LOCAL_NODES}"
+echo "# tasks : ${SLURM_NTASKS-$LOCAL_TASKS}"
+echo "submit dir : ${SLURM_SUBMIT_DIR-$PWD}"
+
+set -ue 
+#
+# Cluster variables
+#
+NB_CORES_PER_NODES=128
+MAX_CORES_PER_NODES=100
+LIST_CORES_SOCKET=`seq -s',' 0 $((NB_CORES_PER_NODES-1))`
+#
+# Experiment options
+#
+exp_name=NE4_00
+run_start_date="1960-01-01"
+run_duration="1 year"
+rst_freq="1 month"
+run_num_legs=12
+special_restart=false
+special_restart_from=EXP0
+special_restart_date="1959-01-01"
+# ORCA025=1350 - ORCA1=2700 - ORCA2=5400
+#    1-23360      1-11680       1-5840
+nem_time_step_sec=1350
+lim_time_step_sec=1350
+nem_restart_offset=0
+nem_config_name=ORCA025_ICE
+info_file="nemo.info"
+start_dir=${SLURM_SUBMIT_DIR-$PWD}
+run_dir="/gpfs/scratch/acad/ecearth/$USER/nemo/run/${exp_name}"
+archive_dir="/gpfs/scratch/acad/ecearth/$USER/nemo/archive/${exp_name}"
+
+#
+# Program configuration
+#
+#192 - 230 - 460 - 1150
+#debug nem_numproc=360
+nem_numproc=600
+xio_numproc=100
+#debug xio_numproc=24
+#4 - 4 - 6 - 14 (max 26)
+
+nemo_src_dir=${HOME}/modeles/nemo_4.2.0
+shared_dir=${nemo_src_dir}/cfgs/SHARED
+nem_exe=nemo.exe
+nem_exe_file=${start_dir}/../BLD/bin/nemo.exe
+xio_exe=xios_server.exe
+xio_exe_file=${nemo_src_dir}/ext/xios-trunk-2326_gnu/bin/xios_server.exe
+
+all_proc=$(($nem_numproc+$xio_numproc))
+if [[ "${SLURM_JOB_NAME-"local"}" != "local" ]] ; then
+  if (( $all_proc != ${SLURM_NTASKS-$LOCAL_TASKS} ))
+  then
+    echo "XIOS procs + NEMOC procs do not fit with SLURM requirements."
+    #exit 0
+  fi
+fi
+
+#
+# Data configuration
+#
+nem_grid=ORCA025L121
+#
+ini_data_dir=/gpfs/scratch/acad/ecearth/pbarriat/data/nemo
+#
+ic_subdir=initial
+ic_files=(
+"Goutorbe_ghflux.nc"
+"eORCA025_ghflux_v2.0_c3.0_weights_bilin_nohls.nc => weights_ghflux_bilinear.nc"
+"eORCA025_iwm_b0.2_v1.0_nohls.nc => zdfiwm_forcing.nc"
+"eORCA025.L121_domain_cfg_b0.5_c3.0_d1.0_nohls_clean.nc => domain_cfg.nc"
+"eORCA025_runoff_b0.2_v0.0_nohls.nc => runoff.nc"
+"eORCA025_calving_b0.2_v2.3_nohls.nc => calving.nc"
+"eORCA025_ttv_b0.2_v0.0_nohls.nc => boost_tidal_velocity.nc"
+"eORCA025_bfr2d_v0.2_nohls.nc => bfr_coef.nc"
+"eORCA025_shlat2d_v0.2_nohls.nc => shlat2d.nc"
+"eORCA025_distcoast_b0.2_v0.0_nohls.nc => distcoast.nc"
+"eORCA025.L121-empc_nohls.nc => empc.nc"
+)
+#
+nem_res_hor=$(echo ${nem_grid} | sed 's:ORCA\([0-9]\+\)L[0-9]\+:\1:')
+#
+clim_subdir=climatology
+clim_files=(
+"eORCA025.L121_WOA2018_c3.0_d1.0_v19812010.5.2_nohls.nc => woce_monthly_init.nc"
+"chlorophyl_v0.0.nc => chlorophyl.nc"
+"eORCA025_chlorophyl_v0.0_c3.0_weights_bilin_nohls.nc => chlorophyl_weights_bilin.nc"
+"eORCA025_sss_WOA2018_c3.0_v19812010.5.1_nohls.nc => sss_absolute_salinity.nc"
+"eORCA025_seaice_c3.0_v19802004.0_nohls.nc => seaice.nc"
+)
+#
+forcing_subdir=forcing
+nem_forcing_set=ERA5
+#nem_forcing_set=JRA55
+forcing_files=(
+"* => ."
+)
+#
+shared_files=(
+"namelist_ice_ref"
+"namelist_ref"
+"domain_def_nemo.xml"
+"axis_def_nemo.xml"
+"field_def_nemo-ice.xml"
+"field_def_nemo-oce.xml"
+"grid_def_nemo.xml"
+)
+
+#
+# Script logic
+#
+function leap_days()
+{
+  local ld=0
+  local frstYYYY=$(date -ud "$1" +%Y)
+  local lastYYYY=$(date -ud "$2" +%Y)
+
+  set +e
+
+  $(date -ud "${frstYYYY}-02-29" > /dev/null 2>&1) \
+    && (( $(date -ud "$1" +%s) < $(date -ud "${frstYYYY}-03-01" +%s) )) \
+    && (( $(date -ud "$2" +%s) > $(date -ud "${lastYYYY}-02-28" +%s) )) \
+    && (( ld++ ))
+
+  for (( y=(( ${frstYYYY}+1 )); y<=(( ${lastYYYY}-1 )); y++ ))
+  do
+    $(date -ud "$y-02-29" > /dev/null 2>&1) && (( ld++ ))
+  done
+
+  (( $lastYYYY > $frstYYYY )) \
+    && $(date -ud "${lastYYYY}-02-29" > /dev/null 2>&1) \
+    && (( $(date -ud "$1" +%s) < $(date -ud "${frstYYYY}-03-01" +%s) )) \
+    && (( $(date -ud "$2" +%s) > $(date -ud "${lastYYYY}-02-28" +%s) )) \
+    && (( ld++ ))
+
+  set -e
+
+  echo "$ld"
+}
+
+
+[[ $@ == *verbose* ]] && set -x
+
+#module purge
+module load craype-x86-milan
+module load PrgEnv-gnu/8.3.3
+module load netCDF-Fortran/4.6.0-gompi-2022a
+module load Perl/.5.34.1-GCCcore-11.3.0
+
+if [ ! -d ${run_dir:?} ]
+then
+  mkdir -p ${run_dir}
+  #
+  if $special_restart
+  then
+    rsync -av --delete ${run_dir}/../${special_restart_from}/ --exclude log --exclude output --exclude restart --exclude="${special_restart_from}_*" --exclude="ocean*" --exclude="restart_*" --exclude="debug.*" --exclude="output.*" ${run_dir}
+    cp -f ${nem_exe_file} ${run_dir}
+    cp -f ${xio_exe_file} ${run_dir}
+    special_year=${special_restart_date:0:4}
+    sed -i "/$special_year/q" ${run_dir}/${info_file}
+    . ${run_dir}/${info_file}
+    special_restart_leg=$(printf %03d $((leg_number+1)))
+    cd ${run_dir}/../../archive/${special_restart_from}/restart/${special_restart_leg}
+    for f in *.nc; do
+      nf=${exp_name}${f:4}
+      cp $f ${run_dir}/$nf
+    done
+    cd -
+    cd ${run_dir}
+    for f in ${exp_name}_????????_restart_???_????.nc; do
+      nf=${f:14}
+      ln -s $f $nf
+    done
+    cd -
+  fi
+
+  cd ${start_dir}
+  cp context_nemo.xml file_def_nemo-ice.xml file_def_nemo-oce.xml iodef.xml namelist_ice_cfg* build_namelist_cfg* ${run_dir}
+  cd ${run_dir}
+  cp ${xio_exe_file} ${xio_exe}
+  cp ${nem_exe_file} ${nem_exe}
+  
+  [[ ! -f EMPave_old.dat ]] && echo "                               0  0.0000000000000000E+00  0.0000000000000000E+00" > EMPave_old.dat
+  for file in "${ic_files[@]}"; do 
+      [[ ! -e ${file#*> } ]] && ln -sf $(sed 's/ *=> */ /' <<< "${ini_data_dir}/${ic_subdir}/${nem_grid}/$file") 
+  done
+  for file in "${ic_files[@]}"; do
+      [[ ! -e ${file#*> } ]] && ln -sf $(sed 's/ *=> */ /' <<< "${ini_data_dir}/${ic_subdir}/$file")
+  done
+  for file in "${clim_files[@]}"; do
+      [[ ! -e ${file#*> } ]] && ln -sf $(sed 's/ *=> */ /' <<< "${ini_data_dir}/${clim_subdir}/${nem_grid}/$file")
+  done
+  for file in "${clim_files[@]}"; do
+      [[ ! -e ${file#*> } ]] && ln -sf $(sed 's/ *=> */ /' <<< "${ini_data_dir}/${clim_subdir}/$file")
+  done
+  for file in "${forcing_files[@]}"; do
+      [[ ! -e ${file#*> } ||  "$file" == \** ]] && ln -sf $(sed 's/ *=> */ /' <<< "${ini_data_dir}/${forcing_subdir}/${nem_forcing_set}/$file")
+  done
+  for file in "${shared_files[@]}"; do
+      [[ ! -e ${file#*> } ]] && ln -sf $(sed 's/ *=> */ /' <<< "${shared_dir}/$file")
+  done
+
+else
+  cd ${run_dir}
+  shopt -s nullglob
+  for v in grid_U grid_V grid_W grid_T icemod SBC SBC_scalar diaptr2D diaptr3D
+  do
+    for f in ${exp_name}_??_????????_????????_${v}_????.nc
+    do
+      rm -f "$f"
+    done
+    for f in ${exp_name}_??_????????_????????_${v}.nc
+    do
+      rm -f "$f"
+    done
+    for f in ${exp_name}_??_${v}.nc
+    do
+      rm -f "$f"
+    done
+  done
+  for f in ocean.output time.step ; do rm -f "${f}"; done
+  shopt -u nullglob
+
+fi
+
+run_start_date=$(date -uR -d "${run_start_date}")
+run_end_date="${run_start_date} + ${run_duration:?}"
+run_end_date=$(date -uR -d "${run_end_date}")
+
+run_start_epoch=$(date -u -d"${run_start_date}" +%s)
+run_end_epoch=$(date -u -d"${run_end_date}" +%s)
+
+for (( ; run_num_legs>0 ; run_num_legs-- ))
+do
+
+  [[ -r "${info_file:?}" ]] && source "${info_file:?}"
+  leg_start_date=${leg_end_date:-$run_start_date}
+  leg_number=$((${leg_number:=0}+1))
+  leg_start_epoch=$(date -u -d "${leg_start_date}" +%s)
+  leg_end_epoch=$(date -u -d "${leg_start_date:?} + ${rst_freq:=$run_duration}" +%s)
+  leg_end_date=$(date -uR -d@"${leg_end_epoch}")
+  leg_length_sec=$(( leg_end_epoch - leg_start_epoch ))
+  leg_start_sec=$(( leg_start_epoch - run_start_epoch ))
+  leg_end_sec=$(( leg_end_epoch - run_start_epoch ))
+  leg_start_date_yyyymmdd=$(date -u -d "${leg_start_date}" +%Y%m%d) 
+  leg_length_sec=$(( leg_length_sec - $(leap_days "${leg_start_date}" "${leg_end_date}")*24*3600 ))
+  leg_start_sec=$(( leg_start_sec - $(leap_days "${run_start_date}" "${leg_start_date}")*24*3600 ))
+  leg_end_sec=$(( leg_end_sec - $(leap_days "${run_start_date}" "${leg_end_date}")*24*3600 ))
+  (( leg_number > 1 )) && leg_is_restart=true || leg_is_restart=false
+
+  (( leg_end_epoch > run_end_epoch )) && leg_end_date=${run_end_epoch}
+
+  if (( leg_start_epoch >= run_end_epoch ))
+  then
+    echo "Leg start date equal to or after end of simulation."
+    echo "Nothing left to do. Cleaning and exiting."
+    for (( n=0 ; n<nem_numproc ; n++ ))
+    do
+      np=$(printf %04d ${n})
+      rm -f "restart_oce_${np}.nc"
+      rm -f "restart_ice_${np}.nc"
+      rm -f "restart_icb_${np}.nc"
+    done
+    exit 0
+  fi
+
+  source build_namelist_cfg.sh > namelist_cfg
+
+  ns=$(printf %08d $(( leg_start_sec / nem_time_step_sec - nem_restart_offset )))
+  echo "ns=$ns"
+  if ((leg_start_sec > 0 )); then
+    for (( n=0 ; n<nem_numproc ; n++ ))
+    do
+      np=$(printf %04d ${n})
+      formatted_leg_number=$(printf %03d $((leg_number)))
+      [[ -f "${exp_name:?}_${ns}_restart_oce_${np}.nc" ]] || { cp $archive_dir/restart/${formatted_leg_number}/*oce* . ; } 
+      [[ -f "${exp_name:?}_${ns}_restart_oce_${np}.nc" ]] || { echo "Error: restart file not found." ; exit 2 ; }
+      ln -fs "${exp_name:?}_${ns}_restart_oce_${np}.nc" "restart_oce_${np}.nc"
+      [[ -f "${exp_name:?}_${ns}_restart_ice_${np}.nc" ]] || { cp $archive_dir/restart/${formatted_leg_number}/*ice* . ; }
+      [[ -f "${exp_name:?}_${ns}_restart_ice_${np}.nc" ]] || { echo "Error: restart file not found." ; exit 2 ; }
+      ln -fs "${exp_name:?}_${ns}_restart_ice_${np}.nc" "restart_ice_${np}.nc"
+      [[ -f "${exp_name:?}_${ns}_restart_icb_${np}.nc" ]] || { cp $archive_dir/restart/${formatted_leg_number}/*icb* . ; }
+      [[ -f "${exp_name:?}_${ns}_restart_icb_${np}.nc" ]] || { echo "Error: restart file not found." ; exit 2 ; }
+      ln -fs "${exp_name:?}_${ns}_restart_icb_${np}.nc" "restart_icb_${np}.nc"
+    done
+  fi
+
+  [[ $@ == *preponly* ]] && exit 0
+
+  time_begin=$(date +%s)
+  ulimit -s unlimited
+  if [[ "${SLURM_JOB_NAME-"local"}" == "local" ]] ; then
+    echo "!!! Local RUN !!!"
+    #xio_numproc=2
+    #nem_numproc=24
+  fi
+  #
+  echo "run dir : $run_dir"
+  echo "leg_number : $leg_number"
+  #echo "ulimit -s unlimited"
+  #echo "Lemaitre3-2018: I_MPI_FABRICS=tcp mpirun -np ${xio_numproc} ./${xio_exe} : -np ${nem_numproc} ./${nem_exe}"
+  #echo "Lemaitre3>2019: I_MPI_FABRICS=ofi FI_PROVIDER=tcp mpirun -np ${xio_numproc} ./${xio_exe} : -np ${nem_numproc} ./${nem_exe}"
+  #echo "Nic5: I_MPI_HYDRA_TOPOLIB=ipl I_MPI_FABRICS=ofi mpirun -np ${xio_numproc} ./${xio_exe} : -np ${nem_numproc} ./${nem_exe}"
+  #echo "Zenobe: mpirun -np ${xio_numproc} ./${xio_exe} : -np ${nem_numproc} ./${nem_exe}"
+  #echo "Cyclone: I_MPI_FABRICS=tcp mpirun -np "${xio_numproc:?}" "./${xio_exe:?}" : -np "${nem_numproc:?}" "./${nem_exe:?}"
+  #echo "LUMI: srun --multi-prog prog.conf (SLURM_JOB_NUM_NODES:${SLURM_JOB_NUM_NODES-$LOCAL_NODES} SLURM_CPUS_ON_NODE:${SLURM_CPUS_ON_NODE-$NB_CORES_PER_NODES})"
+  echo "LUCIA: srun srun_wrapper.sh (SLURM_JOB_NUM_NODES:${SLURM_JOB_NUM_NODES-$LOCAL_NODES} SLURM_CPUS_ON_NODE:${SLURM_CPUS_ON_NODE-$NB_CORES_PER_NODES})"
+
+  export OMP_NUM_THREADS=1
+  #export MKL_NUM_THREADS=1
+  #export PMI_NO_PREINITIALIZE=y
+  export TIME="launch timing : %e elapsed %U user %S system"
+
+  # Split XIOS nodes
+  #cat /dev/null > prog.conf
+  #nem_numproc_slice=$(($nem_numproc/${SLURM_JOB_NUM_NODES-$LOCAL_NODES}))
+  #nem_numproc_slice_0=$(($nem_numproc_slice-1))
+  #xio_numproc_slice_0=$(($xio_numproc/${SLURM_JOB_NUM_NODES-$LOCAL_NODES}-1))
+  #xio_numproc_slice=$(($nem_numproc_slice+$xio_numproc_slice_0))
+  #proc_id=0
+  #for i in $(eval echo "{1..${SLURM_JOB_NUM_NODES-$LOCAL_NODES}}")
+  #do
+  #  for j in $(eval echo "{0..$nem_numproc_slice_0}")
+  #  do
+  #    echo "$proc_id ./${nem_exe}" >> prog.conf
+  #    proc_id=$(($proc_id+1))
+  #  done
+  #  for j in $(eval echo "{$nem_numproc_slice..$xio_numproc_slice}")
+  #  do
+  #    echo "$proc_id ./${xio_exe}" >> prog.conf
+  #    proc_id=$(($proc_id+1))
+  #  done
+  #done
+  # Group XIOS nodes
+  cat /dev/null > prog.conf
+  proc_id=0
+  for i in $(eval echo "{1..${nem_numproc}}")
+  do
+    echo "$proc_id ./${nem_exe}" >> prog.conf
+    proc_id=$(($proc_id+1))
+  done
+  for i in $(eval echo "{1..${xio_numproc}}")
+  do
+    echo "$proc_id ./${xio_exe}" >> prog.conf
+    proc_id=$(($proc_id+1))
+  done
+  #echo "LUMI: srun --kill-on-bad-exit=1 --multi-prog prog.conf"
+
+  #cat /dev/null > ./ztask_file.conf
+  #echo "0-$(($xio_numproc-1)) ./${xio_exe}" >> ./ztask_file.conf
+  #echo "$xio_numproc-$(($xio_numproc+$nem_numproc-1)) ./${nem_exe}" >> ./ztask_file.conf
+  #BINDING=map_cpu:$LIST_CORES_SOCKET
+  #echo "LUMI: srun --kill-on-bad-exit=1 --mpi=pmi2 -m cyclic --cpu_bind=$BINDING --multi-prog ./ztask_file.conf"
+
+  #exit
+  echo $time_begin
+  #mpirun -np ${xio_numproc} ./${xio_exe} : -np ${nem_numproc} ./${nem_exe}
+  srun --kill-on-bad-exit=1 --multi-prog prog.conf
+  #srun --kill-on-bad-exit=1 --mpi=pmi2 -m cyclic --cpu_bind=$BINDING --multi-prog ./ztask_file.conf
+  #srun --kill-on-bad-exit=1 ./${xio_exe} : ./${nem_exe}
+  time_end=$(date +%s)
+  echo $time_end
+
+  formatted_leg_number=$(printf %03d $((leg_number)))
+  outdir="${archive_dir:?}/output/${formatted_leg_number}"
+  mkdir -p "${outdir}"
+
+  shopt -s nullglob
+  for v in grid_U grid_V grid_W grid_T icemod SBC SBC_scalar diaptr2D diaptr3D
+  do
+    for f in ${exp_name}_??_????????_????????_${v}_????.nc
+    do
+      mv "$f" "$outdir/"
+    done
+    for f in ${exp_name}_??_????????_????????_${v}.nc
+    do
+      mv "$f" "$outdir/"
+    done
+    for f in ${exp_name}_??_${v}.nc
+    do
+      mv "$f" "$outdir/"
+    done
+  done
+
+  outdir="$archive_dir/restart/${formatted_leg_number}"
+  mkdir -p "${outdir}"
+
+  for f in ${exp_name}_${ns}_restart_???_????.nc
+  do
+    [ -f "$f" ] && mv "$f" "${outdir}"
+  done
+
+  outdir="$archive_dir/log/${formatted_leg_number}"
+  mkdir -p "${outdir}"
+  for f in ocean.output time.step ; do mv "${f}" "${outdir}"; done
+  cp -f namelist_ice_ref namelist_ice_cfg namelist_ref namelist_cfg ${archive_dir}
+  [[ -f ${start_dir}/${SLURM_JOB_NAME-"run"}.sh ]] && cp -f ${start_dir}/${SLURM_JOB_NAME-"run"}.sh ${archive_dir}
+
+  shopt -u nullglob
+
+  tr=$(date -d "0 -$time_begin sec + $time_end sec" +%T) 
+  current_date=$(date +'%F %T')
+  {
+    echo "#"
+    echo "# Finished leg at ${current_date} after ${tr} (hh:mm:ss)" 
+    echo "leg_number=${leg_number}"
+    echo "leg_start_date=\"${leg_start_date}\""
+    echo "leg_end_date=\"${leg_end_date}\""
+  } | tee -a "${info_file}"
+
+  special_restart=false
+done
+cd - >/dev/null
+[[ $@ == *noresubmit* ]] && exit 0
+if (( leg_end_epoch < run_end_epoch )) ; then
+  echo "Leg end earlier than end of simulation."
+  echo "Submitting another job."
+  if [[ "$@" == *"run"* ]] ; then
+    exec "$0" "$@"
+  elif hash sbatch 2>/dev/null; then
+    # Need to go to start_dir to find the run script
+    cd ${start_dir}
+    echo "sbatch -N ${SLURM_JOB_NUM_NODES-"1"} -o ${run_dir}/$(basename ${stdout_file}).$(printf %03d $((leg_number+1))) -e ${run_dir}/$(basename ${stdout_file}).$(printf %03d $((leg_number+1))) -d ${SLURM_JOB_ID-"id"} ./${SLURM_JOB_NAME-"run"}.sh"
+    # Submit command
+    # Note: This does not work if you specify a job name with sbatch -J jobname!
+    sbatch -N ${SLURM_JOB_NUM_NODES-"1"}                                             \
+      -o ${run_dir}/$(basename ${stdout_file}).$(printf %03d $((leg_number+1))) \
+      -e ${run_dir}/$(basename ${stdout_file}).$(printf %03d $((leg_number+1))) \
+      -d ${SLURM_JOB_ID-"id"}                                                   \
+      ./${SLURM_JOB_NAME-"run"}.sh
+    #
+  else
+    cd ${start_dir}
+    echo "qsub ${PBS_JOBNAME}.sh" 
+    qsub ./${PBS_JOBNAME}.sh
+  fi
+else
+  echo "Nothing left to do. Cleaning and exiting." # FIXME Factorize this (we have two exit points)
+  for (( n=0 ; n<nem_numproc ; n++ ))
+  do
+    np=$(printf %04d ${n})
+    rm -f "restart_oce_${np}.nc"
+    rm -f "restart_ice_${np}.nc"
+    rm -f "restart_icb_${np}.nc"
+  done
+fi
+
+exit 0

+ 1 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/axis_def_nemo.xml

@@ -0,0 +1 @@
+../../SHARED/axis_def_nemo.xml

+ 567 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/build_namelist_cfg.sh

@@ -0,0 +1,567 @@
+# This configuration namelist will overwrite SHARED/namelist_ref
+#
+if $leg_is_restart
+then
+    nemo_restart=".TRUE."
+else
+    nemo_restart=".FALSE."
+fi
+
+cat << EOF
+!!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+!! NEMO/OCE  Configuration namelist : overwrite default values defined in SHARED/namelist_ref
+!!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+!!             ORCA025 - ICE configuration                            !!
+!!======================================================================
+!!              ***  Domain & Run management namelists  ***           !!
+!!                                                                    !!
+!!   namrun       parameters of the run
+!!   namdom       space and time domain
+!!   namcfg       parameters of the configuration                       (default: user defined GYRE)
+!!   namwad       Wetting and drying                                    (default: OFF)
+!!   namtsd       data: temperature & salinity                          (default: OFF)
+!!   namcrs       coarsened grid (for outputs and/or TOP)               (ln_crs =T)
+!!   namc1d       1D configuration options                              (ln_c1d =T)
+!!   namc1d_dyndmp 1D newtonian damping applied on currents             (ln_c1d =T)
+!!   namc1d_uvd   1D data (currents)                                    (ln_c1d =T)
+!!======================================================================
+!
+!-----------------------------------------------------------------------
+&namrun        !   parameters of the run
+!-----------------------------------------------------------------------
+   cn_exp        =  "${exp_name}" !  experience name
+   nn_it000      =  $(( leg_start_sec / nem_time_step_sec + 1 )) !  first time step
+   nn_itend      =  $(( leg_end_sec / nem_time_step_sec ))       !  last  time step (std 5475)
+   nn_date0      =  ${leg_start_date_yyyymmdd} !  date at nit_0000 (format yyyymmdd)
+   ln_rstart     = ${nemo_restart} !  start from rest (F) or from a restart file (T)
+   nn_leapy      =  1             !  Leap year calendar (1) or not (0)
+   nn_rstctl     =  1             !  restart control ==> activated only if ln_rstart=T
+                                  !  = 0 nn_date0 read in namelist ; nn_it000 : read in namelist
+                                  !  = 1 nn_date0 read in namelist ; nn_it000 : check consistancy between namelist and restart
+                                  !  = 2 nn_date0 read in restart  ; nn_it000 : check consistancy between namelist and restart
+   cn_ocerst_in  = "restart_oce"  !  suffix of ocean restart name (input)
+   cn_ocerst_indir = "."          !  directory from which to read input ocean restarts
+   cn_ocerst_out = "restart_oce"  !  suffix of ocean restart name (output)
+   ln_cfmeta   = .true.   !  output additional data to netCDF files required for compliance with the CF metadata standard
+/
+!-----------------------------------------------------------------------
+&namdom        !   time and space domain
+!-----------------------------------------------------------------------
+   rn_Dt       = ${nem_time_step_sec} !  time step for the dynamics and tracer
+   ln_meshmask = .false.   !  =T create a mesh file
+/
+!-----------------------------------------------------------------------
+&namcfg        !   parameters of the configuration                      (default: use namusr_def in namelist_cfg)
+!-----------------------------------------------------------------------
+   ln_read_cfg = .true.    !  (=T) read the domain configuration file
+/
+!-----------------------------------------------------------------------
+&namtsd        !    Temperature & Salinity Data  (init/dmp)             (default: OFF)
+!-----------------------------------------------------------------------
+   !                       ! =T  read T-S fields for:
+   ln_tsd_init = .true.          !  ocean initialisation
+   ln_tsd_dmp  = .false.         !  T-S restoring   (see namtra_dmp)
+
+   cn_dir = './'     !  root directory for the T-S data location
+   !___________!_________________________!___________________!___________!_____________!________!___________!__________________!__________!_______________!
+   !           !  file name              ! frequency (hours) ! variable  ! time interp.!  clim  ! 'yearly'/ ! weights filename ! rotation ! land/sea mask !
+   !           !                         !  (if <0  months)  !   name    !   (logical) !  (T/F) ! 'monthly' !                  ! pairing  !    filename   !
+   sn_tem  = 'woce_monthly_init.nc', -1 ,'t_an' , .true. , .true. , 'yearly' , ''  ,   ''    ,    ''
+   sn_sal  = 'woce_monthly_init.nc', -1 ,'s_an' , .true. , .true. , 'yearly' , ''  ,   ''    ,    ''
+/
+!!======================================================================
+!!            ***  Surface Boundary Condition namelists  ***          !!
+!!                                                                    !!
+!!   namsbc          surface boundary condition manager                 (default: NO selection)
+!!   namsbc_flx      flux               formulation                     (ln_flx     =T)
+!!   namsbc_blk      Bulk formulae formulation                          (ln_blk     =T)
+!!   namsbc_cpl      CouPLed            formulation                     ("key_oasis3" )
+!!   namsbc_sas      Stand-Alone Surface module                         (SAS_SRC  only)
+!!   namsbc_iif      Ice-IF: use observed ice cover                     (nn_ice = 1   )
+!!   namtra_qsr      penetrative solar radiation                        (ln_traqsr  =T)
+!!   namsbc_ssr      sea surface restoring term (for T and/or S)        (ln_ssr     =T)
+!!   namsbc_rnf      river runoffs                                      (ln_rnf     =T)
+!!   namsbc_apr      Atmospheric Pressure                               (ln_apr_dyn =T)
+!!   namsbc_isf      ice shelf melting/freezing                         (ln_isfcav  =T : read (ln_read_cfg=T) or set or usr_def_zgr )
+!!   namsbc_iscpl    coupling option between land ice model and ocean   (ln_isfcav  =T)
+!!   namsbc_wave     external fields from wave model                    (ln_wave    =T)
+!!   namberg         iceberg floats                                     (ln_icebergs=T)
+!!======================================================================
+!
+!-----------------------------------------------------------------------
+&namsbc        !   Surface Boundary Condition manager                   (default: NO selection)
+!-----------------------------------------------------------------------
+   nn_fsbc     = $(( lim_time_step_sec / nem_time_step_sec )) !  frequency of SBC module call
+                           !     (also = the frequency of sea-ice & iceberg model call)
+                     ! Type of air-sea fluxes
+   ln_blk      = .true.    !  Bulk formulation                          (T => fill namsbc_blk )
+                     ! Sea-ice :
+   nn_ice      = 2         !  =2 or 3 automatically for SI3 or CICE    ("key_si3" or "key_cice")
+                     ! Misc. options of sbc : 
+   ln_traqsr   = .true.   !  Light penetration in the ocean            (T => fill namtra_qsr)
+   ln_ssr      = .true.   !  Sea Surface Restoring on T and/or S       (T => fill namsbc_ssr)
+   ln_rnf      = .true.   !  runoffs                                   (T => fill namsbc_rnf)
+/
+!-----------------------------------------------------------------------
+&namsbc_blk    !   namsbc_blk  generic Bulk formula                     (ln_blk =T)
+!-----------------------------------------------------------------------
+   !                    !  bulk algorithm :
+   ln_NCAR      = .true.     ! "NCAR"      algorithm   (Large and Yeager 2008)
+      rn_zqt       =  2.     !  Air temperature & humidity reference height (m)
+   !
+   cn_dir      = './'      !  root directory for the bulk data location
+   !_______!__________________!___________________!___________!_____________!_________!___________!_____________________________________________!__________!_______________!
+   !       !  file name       ! frequency (hours) ! variable  ! time interp.!  clim   ! 'yearly'/ !       weights filename                      ! rotation !  lsm          !
+   !       !                  !  (if <0  months)  !   name    !   (logical) !  (T/F)  ! 'monthly' !                                             !  paring  !               !
+   sn_wndi = 'ERA5_3h_uas'    ,  3.               ,  'uas'    ,    .true.   , .false. , 'yearly'  , 'weights_bicub_ERA5_eORCA025.L121_nohls.nc' , 'U1'     ,   ''
+   sn_wndj = 'ERA5_3h_vas'    ,  3.               ,  'vas'    ,    .true.   , .false. , 'yearly'  , 'weights_bicub_ERA5_eORCA025.L121_nohls.nc' , 'V1'     ,   ''
+   sn_qsr  = 'ERA5_3h_rsds'   ,  3.               ,  'rsds'   ,    .true.   , .false. , 'yearly'  , 'weights_bilin_ERA5_eORCA025.L121_nohls.nc' , ''       ,   ''
+   sn_qlw  = 'ERA5_3h_rlds'   ,  3.               ,  'rlds'   ,    .true.   , .false. , 'yearly'  , 'weights_bilin_ERA5_eORCA025.L121_nohls.nc' , ''       ,   ''
+   sn_tair = 'ERA5_3h_tas'    ,  3.               ,  'tas'    ,    .true.   , .false. , 'yearly'  , 'weights_bilin_ERA5_eORCA025.L121_nohls.nc' , ''       ,   ''
+   sn_humi = 'ERA5_3h_huss'   ,  3.               ,  'huss'   ,    .true.   , .false. , 'yearly'  , 'weights_bilin_ERA5_eORCA025.L121_nohls.nc' , ''       ,   ''
+   sn_prec = 'ERA5_3h_pr'     ,  3.               ,  'pr'     ,    .true.   , .false. , 'yearly'  , 'weights_bilin_ERA5_eORCA025.L121_nohls.nc' , ''       ,   ''
+   sn_snow = 'ERA5_3h_prsn '  ,  3.               ,  'prsn'   ,    .true.   , .false. , 'yearly'  , 'weights_bilin_ERA5_eORCA025.L121_nohls.nc' , ''       ,   ''
+   sn_slp  = 'ERA5_3h_psl'    ,  3.               ,  'psl'    ,    .true.   , .false. , 'yearly'  , 'weights_bilin_ERA5_eORCA025.L121_nohls.nc' , ''       ,   ''
+/
+!-----------------------------------------------------------------------
+&namsbc_sas    !   Stand-Alone Surface module: ocean data               (SAS_SRC  only)
+!-----------------------------------------------------------------------
+   l_sasread   = .false.    !  =T Read in file ;  =F set all to 0. (see sbcssm)
+/
+!-----------------------------------------------------------------------
+&namtra_qsr    !   penetrative solar radiation                          (ln_traqsr =T)
+!-----------------------------------------------------------------------
+   !                       ! type of penetration                        (default: NO selection)
+   ln_qsr_rgb  = .true.       !  RGB light penetration (Red-Green-Blue)
+   rn_abs      =   0.53       !  RGB & 2BD: fraction absorbed in the very near surface  ! std value 0.58. RBB -> 0.53
+   nn_chldta   =      1       !  RGB : Chl data (=1) or cst value (=0)
+
+   cn_dir = './'  !  root directory for the chlorophyl data location
+   !___________!_________________________!___________________!___________!_____________!________!___________!__________________!__________!_______________!
+   !           !  file name              ! frequency (hours) ! variable  ! time interp.!  clim  ! 'yearly'/ ! weights filename ! rotation ! land/sea mask !
+   !           !                         !  (if <0  months)  !   name    !   (logical) !  (T/F) ! 'monthly' !                  ! pairing  !    filename   !
+   sn_chl      = 'chlorophyl'       , -1.               , 'CHLA'    ,   .true.    , .true. , 'yearly'  , 'chlorophyl_weights_bilin.nc'       , ''       , ''
+/
+!-----------------------------------------------------------------------
+&namsbc_ssr    !   surface boundary condition : sea surface restoring   (ln_ssr =T)
+!-----------------------------------------------------------------------
+   nn_sssr     =     3     !  add a damping term to the surface freshwater flux
+      !                    !  or to SSS only (=1) or no damping term (=0) or read from a file (=3)
+
+   cn_dir      = './'      !  root directory for the SST/SSS data location
+   !___________!_________________________!___________________!___________!_____________!________!___________!__________________!__________!_______________!
+   !           !  file name              ! frequency (hours) ! variable  ! time interp.!  clim  ! 'yearly'/ ! weights filename ! rotation ! land/sea mask !
+   !           !                         !  (if <0  months)  !   name    !   (logical) !  (T/F) ! 'monthly' !                  ! pairing  !    filename   !
+   sn_sst      = 'NOT USED'              ,       120         , 'votemper',    .true.   , .false., 'yearly'  , ''               , ''       , ''
+   sn_sss      = 'NOT USED'              ,       120         , 'vosaline',    .true.   , .false., 'yearly'  , ''               , ''       , ''
+/
+!-----------------------------------------------------------------------
+&namsbc_ssr_drk !   surface boundary condition : sea surface restoring   (ln_ssr =T)
+!-----------------------------------------------------------------------
+   ln_sssr_flt  = .false.  ! use filtering of SSS model for sss restoring
+   nn_shap_iter =  300     ! number of iteration of the shapiro filter
+   ln_sssr_msk  = .true.   ! use a mask near the coast
+   !___________!____________________!___________________!__________!_____________!________!___________!__________!__________!_______________!
+   !           !  file name         ! frequency (hours) ! variable ! time interp.!  clim  ! 'yearly'/ ! weights  ! rotation ! land/sea mask !
+   !           !                    !  (if <0  months)  !   name   !   (logical) !  (T/F) ! 'monthly' ! filename ! pairing  !    filename   !
+   sn_coast    = 'distcoast'         ,  0.              , 'Tcoast' , .false.     , .true. , 'yearly'  ,  ''      , ''       , ''
+   sn_empc     = 'empc'              , -1.              , 'sowafld', .true.      , .true.,  'yearly'  ,  ''      ,    ''    ,     ''
+
+   rn_dist    =  150.      ! distance to the coast
+/
+!-----------------------------------------------------------------------
+&namsbc_rnf    !   runoffs                                              (ln_rnf =T)
+!-----------------------------------------------------------------------
+   ln_rnf_mouth = .false.     !  specific treatment at rivers mouths
+      rn_hrnf    =  10.e0     !  depth over which enhanced vertical mixing is used    (ln_rnf_mouth=T)
+      rn_avt_rnf =   2.e-3    !  value of the additional vertical mixing coef. [m2/s] (ln_rnf_mouth=T)
+   ln_rnf_icb   = .false.     !  read in iceberg flux from a file (fill sn_i_rnf if .true.)
+
+   cn_dir      = './'      !  root directory for the runoff data location
+   !___________!_________________________!___________________!___________!_____________!________!___________!__________________!__________!_______________!
+   !           !  file name              ! frequency (hours) ! variable  ! time interp.!  clim  ! 'yearly'/ ! weights filename ! rotation ! land/sea mask !
+   !           !                         !  (if <0  months)  !   name    !   (logical) !  (T/F) ! 'monthly' !                  ! pairing  !    filename   !
+   sn_rnf      = 'runoff'                ,        -1.        , 'sorunoff',   .true.    , .true. , 'yearly'  , ''               , ''       , ''
+   sn_cnf      = 'runoff'                ,         0.        , 'socoefr' ,   .false.   , .true. , 'yearly'  , ''               , ''       , ''
+   sn_s_rnf    = 'NOT_USED'              ,        24.        , 'rosaline',   .true.    , .true. , 'yearly'  , ''               , ''       , ''
+   sn_t_rnf    = 'NOT_USED'              ,        24.        , 'rotemper',   .true.    , .true. , 'yearly'  , ''               , ''       , ''
+   sn_dep_rnf  = 'NOT_USED'              ,         0.        , 'rodepth' ,   .false.   , .true. , 'yearly'  , ''               , ''       , ''
+   sn_i_rnf    = 'bergmelt'              ,       120.        ,'berg_melt',   .true.    , .false., 'yearly'  , ''               , ''       , ''
+/
+!-----------------------------------------------------------------------
+&namisf       !  Top boundary layer (ISF)                               (default: OFF)
+!-----------------------------------------------------------------------
+   !
+   ! ---------------- ice shelf melt formulation -------------------------------
+   !
+   ln_isf = .true.            ! activate ice shelf module
+      !
+      ! ---------------- cavities opened -------------------------------
+      !
+      ln_isfcav_mlt = .true.      ! ice shelf melting into the cavity (need ln_isfcav = .true. in domain_cfg.nc)
+         !
+         rn_htbl     =  20.      ! thickness of the top boundary layer    (Losh et al. 2008)
+         !                       ! 0 => thickness of the tbl = thickness of the first wet cell
+         !
+         !* 'spe' and 'oasis' case
+         !___________!_____________!___________________!___________!_____________!_________!___________!__________!__________!_______________!
+         !           !  file name  ! frequency (hours) ! variable  ! time interp.!  clim   ! 'yearly'/ ! weights  ! rotation ! land/sea mask !
+         !           !             !  (if <0  months)  !   name    !  (logical)  !  (T/F)  ! 'monthly' ! filename ! pairing  ! filename      !
+         sn_isfcav_fwf = 'NOT_USED',      -12.      , 'fwflisf'  ,  .false.    , .true.  , 'yearly'  ,    ''    ,   ''     ,    ''
+      !
+      ! ---------------- cavities parametrised -------------------------------
+      !
+      ln_isfpar_mlt = .false.   ! ice shelf melting parametrised
+         cn_isfpar_mlt = 'spe'  ! ice shelf melting parametrisation (spe/bg03/oasis)
+         !                      ! spe   = fwfisf is read from a forcing field
+         !                      ! bg03  = melt computed using Beckmann and Goosse parametrisation
+         !                      ! oasis = fwfisf is given by oasis and pattern by file sn_isfpar_fwf
+         !
+         !* all cases
+         !___________!_____________!___________________!___________!_____________!_________!___________!__________!__________!_______________!
+         !           !  file name  ! frequency (hours) ! variable  ! time interp.!  clim   ! 'yearly'/ ! weights  ! rotation ! land/sea mask !
+         !           !             !  (if <0  months)  !   name    !  (logical)  !  (T/F)  ! 'monthly' ! filename ! pairing  ! filename      !
+         sn_isfpar_zmax = 'NOT_USED'  ,       0        ,'sozisfmax',  .false.    , .true.  , 'yearly'  ,    ''    ,   ''     ,    ''
+         sn_isfpar_zmin = 'NOT_USED'  ,       0        ,'sozisfmin',  .false.    , .true.  , 'yearly'  ,    ''    ,   ''     ,    ''
+         !* 'spe' and 'oasis' case
+         sn_isfpar_fwf = 'NOT_USED'   ,      -12.      ,'sofwfisf' ,  .false.    , .true.  , 'yearly'   ,    ''    ,   ''     ,    ''
+         !* 'bg03' case
+         sn_isfpar_Leff = 'NOT_USED'  ,       0.       ,'Leff'     ,  .false.    , .true.  , 'yearly'   ,    ''    ,   ''     ,    ''
+/
+!-----------------------------------------------------------------------
+&namberg       !   iceberg parameters                                   (default: OFF)
+!-----------------------------------------------------------------------
+   ln_icebergs = .true.       ! activate iceberg floats (force =F with "key_agrif")
+   !
+   !                          ! diagnostics:
+   nn_verbose_write  = 64            ! Timesteps between verbose messages
+   nn_sample_rate    = 64            ! Timesteps between sampling for trajectory storage
+   !
+   !                          ! iceberg setting:
+   rn_distribution   = 0.0003, 0.018, 0.047, 0.097, 0.041, 0.093, 0.085, 0.145, 0.185, 0.276
+   nn_test_icebergs        =  -1     ! Create test icebergs of this class (-1 = no)
+   rn_speed_limit          = 0.4      ! CFL speed limit for a berg
+   !
+   ln_M2016                = .true.  ! use Merino et al. (2016) modification (use of 3d ocean data instead of only sea surface data)
+   ln_icb_area_mask        = .true. !Avoid the overfilling of a grid cell by too many icebergs
+   !
+   cn_dir      = './'      !  root directory for the calving data location
+   !___________!_________________________!___________________!___________!_____________!________!___________!__________________!__________!_______________!
+   !           !  file name              ! frequency (hours) ! variable  ! time interp.!  clim  ! 'yearly'/ ! weights filename ! rotation ! land/sea mask !
+   !           !                         !  (if <0  months)  !   name    !   (logical) !  (T/F) ! 'monthly' !                  ! pairing  !    filename   !
+   sn_icb     =  'calving'               ,      -12.         ,'soicbclv' ,    .true.   , .true. , 'yearly'  , ''               , ''       , ''
+/
+!!======================================================================
+!!               ***  Lateral boundary condition  ***                 !!
+!!                                                                    !!
+!!   namlbc        lateral momentum boundary condition                  (default: NO selection)
+!!   namagrif      agrif nested grid   (read by child model only)       ("key_agrif")
+!!   nam_tide      Tidal forcing                                        (default: OFF)
+!!   nambdy        Unstructured open boundaries                         (default: OFF)
+!!   nambdy_dta    Unstructured open boundaries - external data         (see  nambdy)
+!!   nambdy_tide   tidal forcing at open boundaries                     (default: OFF)
+!!======================================================================
+!
+!-----------------------------------------------------------------------
+&namlbc        !   lateral momentum boundary condition                  (default: NO selection)
+!-----------------------------------------------------------------------
+   rn_shlat    =    0.     !  no slip
+/
+!-----------------------------------------------------------------------
+&namlbc_drk    !   lateral momentum boundary condition                  (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_shlat2d  = .true.   !  use 2D file for shlat
+   cn_dir      = './'
+   !___________!____________________!___________________!___________!_____________!________!___________!__________________!__________!_______________!
+   !           !  file name         ! frequency (hours) ! variable  ! time interp.!  clim  ! 'yearly'/ ! weights filename ! rotation ! land/sea mask !
+   !           !                    !  (if <0  months)  !   name    !   (logical) !  (T/F) ! 'monthly' !                  ! pairing  !    filename   !
+   sn_shlat2d = 'shlat2d' , -12.          , 'shlat2d' , .false.     , .true. ,  'yearly' , ''               , ''       , ''
+/
+!-----------------------------------------------------------------------
+&namagrif      !  AGRIF zoom                                            ("key_agrif")
+!-----------------------------------------------------------------------
+/
+!!======================================================================
+!!                ***  Top/Bottom boundary condition  ***             !!
+!!                                                                    !!
+!!   namdrg        top/bottom drag coefficient                          (default: NO selection)
+!!   namdrg_top    top    friction                                      (ln_OFF=F & ln_isfcav=T)
+!!   namdrg_bot    bottom friction                                      (ln_OFF=F)
+!!   nambbc        bottom temperature boundary condition                (default: OFF)
+!!   nambbl        bottom boundary layer scheme                         (default: OFF)
+!!======================================================================
+!
+!-----------------------------------------------------------------------
+&namdrg        !   top/bottom drag coefficient                          (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_non_lin  = .true.   !  non-linear  drag: Cd = Cd0 |U|
+/
+!-----------------------------------------------------------------------
+&namdrg_top    !   TOP friction                                         (ln_drg_OFF =F & ln_isfcav=T)
+!-----------------------------------------------------------------------
+   rn_Cd0      =  2.5e-3    !  drag coefficient [-]
+   rn_ke0      =  0.0      !  background kinetic energy  [m2/s2] (non-linear cases)
+/
+!-----------------------------------------------------------------------
+&namdrg_bot    !   BOTTOM friction                                      (ln_OFF =F)
+!-----------------------------------------------------------------------
+   rn_Cd0      =  1.e-3   !  drag coefficient [-]
+   ln_boost    = .true.    !  =T regional boost of Cd0 ; =F constant
+/
+!-----------------------------------------------------------------------
+&nambbc        !   bottom temperature boundary condition                (default: OFF)
+!-----------------------------------------------------------------------
+   ln_trabbc   = .true.    !  Apply a geothermal heating at the ocean bottom
+
+   cn_dir = './'  !  root directory for the geothermal data location
+   !___________!____________________!___________________!___________!_____________!________!___________!__________________!__________!_______________!
+   !           !  file name         ! frequency (hours) ! variable  ! time interp.!  clim  ! 'yearly'/ ! weights filename ! rotation ! land/sea mask !
+   !           !                    !  (if <0  months)  !   name    !   (logical) !  (T/F) ! 'monthly' !                  ! pairing  !    filename   !
+   sn_qgh      = 'Goutorbe_ghflux.nc'      ,       -12.        , 'gh_flux' ,   .false.   , .true. , 'yearly'  , 'weights_ghflux_bilinear.nc' ,   ''     ,   ''
+/
+!-----------------------------------------------------------------------
+&nambbl        !   bottom boundary layer scheme                         (default: OFF)
+!-----------------------------------------------------------------------
+   ln_trabbl   = .true.    !  Bottom Boundary Layer parameterisation flag
+      nn_bbl_adv  =  1        !  advective bbl (=1/2) or not (=0)
+/
+!!======================================================================
+!!                        Tracer (T-S) namelists                      !!
+!!                                                                    !!
+!!   nameos        equation of state                                    (default: NO selection)
+!!   namtra_adv    advection scheme                                     (default: NO selection)
+!!   namtra_ldf    lateral diffusion scheme                             (default: NO selection)
+!!   namtra_mle    mixed layer eddy param. (Fox-Kemper param.)          (default: OFF)
+!!   namtra_eiv    eddy induced velocity param.                         (default: OFF)
+!!   namtra_dmp    T & S newtonian damping                              (default: OFF)
+!!======================================================================
+!
+!-----------------------------------------------------------------------
+&nameos        !   ocean Equation Of Seawater                           (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_teos10   = .true.         !  = Use TEOS-10
+/
+!-----------------------------------------------------------------------
+&namtra_adv    !   advection scheme for tracer                          (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_traadv_fct = .true.     !  FCT scheme
+      nn_fct_h   =  4               !  =2/4, horizontal 2nd / 4th order 
+/
+!-----------------------------------------------------------------------
+&namtra_ldf    !   lateral diffusion scheme for tracers                 (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_traldf_lap   = .true.    !    laplacian operator
+   ln_traldf_iso   = .true.    !  iso-neutral (Standard operator)
+   !                       !  Coefficients:
+   nn_aht_ijk_t    = 20        !  space/time variation of eddy coef
+      !                             !   = 20     aht = 1/2  Ud. max(e1,e2)
+      rn_Ud        = 0.011          !  lateral diffusive velocity [m/s] (nn_aht_ijk_t= 0, 10, 20, 30)
+/
+!-----------------------------------------------------------------------
+&namtra_mle    !   mixed layer eddy parametrisation (Fox-Kemper)        (default: OFF)
+!-----------------------------------------------------------------------
+/
+!-----------------------------------------------------------------------
+&namtra_eiv    !   eddy induced velocity param.                         (default: OFF)
+!-----------------------------------------------------------------------
+   ln_ldfeiv   = .true.    ! use eddy induced velocity parameterization
+      !                        !  Coefficients:
+      nn_aei_ijk_t  = 21          ! space/time variation of the eiv coeficient
+      !                                !   = 21 F(i,j,t)  =Treguier et al. JPO 1997 formulation
+      !                           !  time invariant coefficients:  aei0 = 1/2  Ue*Le 
+      rn_Ue        = 0.03             !  lateral diffusive velocity [m/s] (nn_aht_ijk_t= 0, 10, 20, 30)
+      rn_Le        = 10.e+3           !  lateral diffusive length   [m]   (nn_aht_ijk_t= 0, 10)
+/
+!-----------------------------------------------------------------------
+&namtra_dmp    !   tracer: T & S newtonian damping                      (default: OFF)
+!-----------------------------------------------------------------------
+      cn_resto = 'NOT_USED'   !  Name of file containing restoration coeff. field (use dmp_tools to create this)
+/
+!!======================================================================
+!!                      ***  Dynamics namelists  ***                  !!
+!!                                                                    !!
+!!   nam_vvl       vertical coordinate options                          (default: z-star)
+!!   namdyn_adv    formulation of the momentum advection                (default: NO selection)
+!!   namdyn_vor    advection scheme                                     (default: NO selection)
+!!   namdyn_hpg    hydrostatic pressure gradient                        (default: NO selection)
+!!   namdyn_spg    surface pressure gradient                            (default: NO selection)
+!!   namdyn_ldf    lateral diffusion scheme                             (default: NO selection)
+!!   namdta_dyn    offline TOP: dynamics read in files                  (OFF_SRC only)
+!!======================================================================
+!
+!-----------------------------------------------------------------------
+&nam_vvl       !   vertical coordinate options                          (default: z-star)
+!-----------------------------------------------------------------------
+   nn_vvl_interp =  0               !  interpolation method of scale factor anomalies at U/V/F points
+                                    !  =0 linear even at the bottom (old)
+                                    !  =1 linear with bottom correction
+                                    !  =2 proportionnal to scale factors at rest ("qco" like)
+/
+!-----------------------------------------------------------------------
+&namdyn_adv    !   formulation of the momentum advection                (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_dynadv_vec = .true.  !  vector form - 2nd centered scheme
+     nn_dynkeg     = 1        ! grad(KE) scheme: =0   C2  ;  =1   Hollingsworth correction
+/
+!-----------------------------------------------------------------------
+&namdyn_vor    !   Vorticity / Coriolis scheme                          (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_dynvor_een = .true.  !  energy & enstrophy scheme
+/
+!-----------------------------------------------------------------------
+&namdyn_hpg    !   Hydrostatic pressure gradient option                 (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_hpg_isf  = .true.    !  s-coordinate (sco ) adapted to isf
+/
+!-----------------------------------------------------------------------
+&namdyn_spg    !   surface pressure gradient                            (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_dynspg_ts  = .true.  !  split-explicit free surface
+/
+!-----------------------------------------------------------------------
+&namdyn_ldf    !   lateral diffusion on momentum                        (default: NO selection)
+!-----------------------------------------------------------------------
+   ln_dynldf_blp = .true.      !  bilaplacian operator
+   ln_dynldf_hor = .true.      !  horizontal  (geopotential)
+   nn_ahm_ijk_t  = 20          !  space/time variation of eddy coefficient :
+      !                             !  =-30  read in eddy_viscosity_3D.nc file
+      !                             !  =-20  read in eddy_viscosity_2D.nc file
+      !                             !  =  0  constant
+      !                             !  = 10  F(k)=c1d
+      !                             !  = 20  F(i,j)=F(grid spacing)=c2d
+      !                             !  = 30  F(i,j,k)=c2d*c1d
+      !                             !  = 31  F(i,j,k)=F(grid spacing and local velocity)
+      !                             !  = 32  F(i,j,k)=F(local gridscale and deformation rate)
+      !                        !  time invariant coefficients :  ahm = 1/2  Uv*Lv   (lap case)
+      !                             !                            or  = 1/12 Uv*Lv^3 (blp case)
+      rn_Uv      = 0.0838           !  lateral viscous velocity [m/s] (nn_ahm_ijk_t= 0, 10, 20, 30)
+/
+!!======================================================================
+!!                     vertical physics namelists                     !!
+!!                                                                    !!
+!!    namzdf        vertical physics manager                            (default: NO selection)
+!!    namzdf_ric    richardson number vertical mixing                   (ln_zdfric=T)
+!!    namzdf_tke    TKE vertical mixing                                 (ln_zdftke=T)
+!!    namzdf_gls    GLS vertical mixing                                 (ln_zdfgls=T)
+!!    namzdf_osm    OSM vertical diffusion                              (ln_zdfosm=T)
+!!    namzdf_iwm    tidal mixing parameterization                       (ln_zdfiwm=T)
+!!======================================================================
+!
+!-----------------------------------------------------------------------
+&namzdf        !   vertical physics manager                             (default: NO selection)
+!-----------------------------------------------------------------------
+   !                       ! adaptive-implicit vertical advection
+   ln_zad_Aimp = .true.      !  Courant number dependent scheme (Shchepetkin 2015)
+   !
+   !                       ! type of vertical closure (required)
+   ln_zdftke   = .true.       !  Turbulent Kinetic Energy closure       (T =>   fill namzdf_tke)
+   !
+   !                       ! convection
+   ln_zdfevd   = .true.       !  Enhanced Vertical Diffusion scheme
+      nn_evdm  =    1            !  evd apply on tracer (=0) or on tracer and momentum (=1)
+      rn_evd   =   10.           !  evd mixing coefficient [m2/s]
+   !
+   ln_zdfddm   = .true.    ! double diffusive mixing
+   !
+   !                       ! gravity wave-driven vertical mixing
+   ln_zdfiwm   = .true.      ! internal wave-induced mixing            (T =>   fill namzdf_iwm)
+   !
+   !                       !  Coefficients
+   rn_avm0     =   1.4e-6     !  vertical eddy viscosity   [m2/s]       (background Kz if ln_zdfcst=F)
+   rn_avt0     =   1.4e-7     !  vertical eddy diffusivity [m2/s]       (background Kz if ln_zdfcst=F)
+   nn_havtb    =    1         !  horizontal shape for avtb (=1) or not (=0)
+/
+!-----------------------------------------------------------------------
+&namzdf_tke    !   turbulent eddy kinetic dependent vertical diffusion  (ln_zdftke =T)
+!-----------------------------------------------------------------------
+   rn_emin     =   1.e-10  !  minimum value of tke [m2/s2] (1.e-10 is because of iwm)
+      nn_eice     =   3       !  below sea ice: =0 ON ; =4 OFF when ice fraction > 1/4   
+/
+!-----------------------------------------------------------------------
+&namzdf_iwm    !    internal wave-driven mixing parameterization        (ln_zdfiwm =T)
+!-----------------------------------------------------------------------
+   ln_mevar    = .true.    !  variable (T) or constant (F) mixing efficiency
+   ln_tsdiff   = .true.    !  account for differential T/S mixing (T) or not (F)
+
+   cn_dir      = './'      !  root directory for the iwm data location
+   !___________!_________________________!___________________!___________!_____________!________!___________!__________________!__________!_______________!
+   !           !  file name              ! frequency (hours) ! variable  ! time interp.!  clim  ! 'yearly'/ ! weights filename ! rotation ! land/sea mask !
+   !           !                         !  (if <0  months)  !   name    !   (logical) !  (T/F) ! 'monthly' !                  ! pairing  !    filename   !
+   sn_mpb      = 'zdfiwm_forcing.nc'      , -12      , 'power_bot'   , .false.  , .true. , 'yearly' , '' , ''  , ''
+   sn_mpc      = 'zdfiwm_forcing.nc'      , -12      , 'power_cri'   , .false.  , .true. , 'yearly' , '' , ''  , ''
+   sn_mpn      = 'zdfiwm_forcing.nc'      , -12      , 'power_nsq'   , .false.  , .true. , 'yearly' , '' , ''  , ''
+   sn_mps      = 'zdfiwm_forcing.nc'      , -12      , 'power_sho'   , .false.  , .true. , 'yearly' , '' , ''  , ''
+   sn_dsb      = 'zdfiwm_forcing.nc'      , -12      , 'scale_bot'   , .false.  , .true. , 'yearly' , '' , ''  , ''
+   sn_dsc      = 'zdfiwm_forcing.nc'      , -12      , 'scale_cri'   , .false.  , .true. , 'yearly' , '' , ''  , ''
+/
+!!======================================================================
+!!                  ***  Diagnostics namelists  ***                   !!
+!!                                                                    !!
+!!   namtrd       dynamics and/or tracer trends                         (default: OFF)
+!!   namptr       Poleward Transport Diagnostics                        (default: OFF)
+!!   namhsb       Heat and salt budgets                                 (default: OFF)
+!!   namdiu       Cool skin and warm layer models                       (default: OFF)
+!!   namdiu       Cool skin and warm layer models                       (default: OFF)
+!!   namflo       float parameters                                      (default: OFF)
+!!   nam_diaharm  Harmonic analysis of tidal constituents               (default: OFF)
+!!   nam_diadct   transports through some sections                      (default: OFF)
+!!   nam_diatmb   Top Middle Bottom Output                              (default: OFF)
+!!   nam_dia25h   25h Mean Output                                       (default: OFF)
+!!   namnc4       netcdf4 chunking and compression settings             ("key_netcdf4")
+!!======================================================================
+!-----------------------------------------------------------------------
+&namtrd        !   trend diagnostics                                    (default: OFF)
+!-----------------------------------------------------------------------
+/
+!-----------------------------------------------------------------------
+&namptr        !   Poleward Transport Diagnostic                        (default: OFF)
+!-----------------------------------------------------------------------
+/
+!-----------------------------------------------------------------------
+&nam_diaharm   !   Harmonic analysis of tidal constituents              (default: OFF)
+!-----------------------------------------------------------------------
+/
+!-----------------------------------------------------------------------
+&namnc4        !   netcdf4 chunking and compression settings            ("key_netcdf4")
+!-----------------------------------------------------------------------
+/
+!!======================================================================
+!!               ***  Observation & Assimilation  ***                 !!
+!!                                                                    !!
+!!   namobs       observation and model comparison                      (default: OFF)
+!!   nam_asminc   assimilation increments                               ('key_asminc')
+!!======================================================================
+!
+!!======================================================================
+!!                  ***  Miscellaneous namelists  ***                 !!
+!!                                                                    !!
+!!   nammpp            Massively Parallel Processing                    ("key_mpp_mpi")
+!!   namctl            Control prints                                   (default: OFF)
+!!   namsto            Stochastic parametrization of EOS                (default: OFF)
+!!======================================================================
+!
+!-----------------------------------------------------------------------
+&nammpp        !   Massively Parallel Processing                        ("key_mpp_mpi")
+!-----------------------------------------------------------------------
+/
+!-----------------------------------------------------------------------
+&namctl        !   Control prints                                       (default: OFF)
+!-----------------------------------------------------------------------
+   ln_timing   = .true.           !  timing by routine write out in timing.output file
+/
+!-----------------------------------------------------------------------
+&namhsb        !  Heat and salt budgets                                 (default: OFF)
+!-----------------------------------------------------------------------
+/
+!-----------------------------------------------------------------------
+&namnc4        !   netcdf4 chunking and compression settings            ("key_netcdf4")
+!-----------------------------------------------------------------------
+   nn_nchunks_i =   4       !  number of chunks in i-dimension
+   nn_nchunks_j =   4       !  number of chunks in j-dimension
+   nn_nchunks_k =   121     !  number of chunks in k-dimension
+   !                       !  setting nn_nchunks_k = jpk will give a chunk size of 1 in the vertical which
+   !                       !  is optimal for postprocessing which works exclusively with horizontal slabs
+   ln_nc4zip   = .true.    !  (T) use netcdf4 chunking and compression
+   !                       !  (F) ignore chunking information and produce netcdf3-compatible files
+/
+EOF

+ 40 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/context_nemo.xml

@@ -0,0 +1,40 @@
+<!--
+ ============================================================================================== 
+    NEMO context
+============================================================================================== 
+-->
+<context id="nemo">
+    <!-- $id$ -->
+    <variable_definition>
+       <!-- Year/Month/Day of time origin for NetCDF files; defaults to 1800-01-01 -->
+       <variable id="ref_year"  type="int"> 1900 </variable>
+       <variable id="ref_month" type="int"> 01 </variable>
+       <variable id="ref_day"   type="int"> 01 </variable>
+       <variable id="rho0"      type="float" > 1026.0 </variable>
+       <variable id="cpocean"   type="float" > 3991.86795711963 </variable>
+       <variable id="convSpsu"  type="float" > 0.99530670233846  </variable>
+       <variable id="rhoic"     type="float" > 917.0 </variable>
+       <variable id="rhosn"     type="float" > 330.0 </variable>
+       <variable id="missval"   type="float" > 1.e20 </variable>
+    </variable_definition>
+
+<!-- Fields definition -->
+    <field_definition src="./field_def_nemo-oce.xml"/>    <!--  NEMO ocean dynamics     -->
+    <field_definition src="./field_def_nemo-ice.xml"/>    <!--  NEMO sea-ice model      -->
+
+<!-- Files definition -->
+    <file_definition src="./file_def_nemo-oce.xml"/>     <!--  NEMO ocean dynamics      -->
+    <file_definition src="./file_def_nemo-ice.xml"/>     <!--  NEMO sea-ice model       -->
+
+
+<!-- Axis definition -->
+    <axis_definition src="./axis_def_nemo.xml"/>
+ 
+<!-- Domain definition -->
+    <domain_definition src="./domain_def_nemo.xml"/>
+
+<!-- Grids definition -->
+    <grid_definition   src="./grid_def_nemo.xml"/>
+  
+
+</context>

+ 1 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/domain_def_nemo.xml

@@ -0,0 +1 @@
+../../SHARED/domain_def_nemo.xml

+ 1 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/field_def_nemo-ice.xml

@@ -0,0 +1 @@
+../../SHARED/field_def_nemo-ice.xml

+ 1 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/field_def_nemo-oce.xml

@@ -0,0 +1 @@
+../../SHARED/field_def_nemo-oce.xml

+ 130 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/file_def_nemo-ice.xml

@@ -0,0 +1,130 @@
+<?xml version="1.0"?>
+
+<!--
+===================================================================================================
+=                                  output files definition                                        =
+=                             Define your own files for sea ice                                   =
+=                                put the variables you want...                                    =
+===================================================================================================
+-->
+
+<file_definition type="multiple_file" name="@expname@_@freq@_@startdate@_@enddate@" sync_freq="1mo" min_digits="4">
+
+  <file_group id="1ts" output_freq="1ts" output_level="10" enabled=".TRUE."/> <!-- 1 time step files -->
+
+  <file_group id="1h" output_freq="1h" output_level="10" enabled=".TRUE."/> <!-- 1h files -->
+  <file_group id="2h" output_freq="2h" output_level="10" enabled=".TRUE."/> <!-- 2h files -->
+  <file_group id="3h" output_freq="3h" output_level="10" enabled=".TRUE."/> <!-- 3h files -->
+  <file_group id="4h" output_freq="4h" output_level="10" enabled=".TRUE."/> <!-- 4h files -->
+  <file_group id="6h" output_freq="6h" output_level="10" enabled=".TRUE."/> <!-- 6h files -->
+
+  <file_group id="1d" output_freq="1d"  output_level="10" enabled=".TRUE.">  <!-- 1d files -->
+
+    <file id="file21" name_suffix="_icemod" description="ice variables" enabled=".true." >
+
+      <!-- general -->
+      <field field_ref="iceconc" name="siconc" />
+      <field field_ref="icethic" name="sithic" />
+      <field field_ref="snwthic" name="snthic" />
+
+      <!-- momentum -->
+      <field field_ref="uice"   name="sivelu" />
+      <field field_ref="vice"   name="sivelv" />
+      <field field_ref="icevel" name="sivelo" />
+
+    </file>
+
+  </file_group>
+
+  <file_group id="5d" output_freq="5d" output_level="10" enabled=".TRUE."/> <!-- 5d files -->
+
+  <file_group id="1m" output_freq="1mo" output_level="10" enabled=".TRUE."> <!-- real monthly files -->
+
+    <file id="file22" name_suffix="_icemod" description="ice variables" enabled=".true." >
+
+      <!-- general -->
+      <field field_ref="iceconc"    name="siconc" />
+      <field field_ref="icethic"    name="sithic" />
+      <field field_ref="icevolu"    name="sivolu" />
+      <field field_ref="snwthic"    name="snthic" />
+      <field field_ref="snwvolu"    name="snvolu" />
+      <field field_ref="icesalt"    name="sisali" />
+      <field field_ref="iceapnd"    name="siapnd" />
+      <field field_ref="icevpnd"    name="sivpnd" />
+
+      <!-- heat -->
+      <field field_ref="icetemp"    name="sitemp" />
+      <field field_ref="snwtemp"    name="sntemp" />
+      <field field_ref="icettop"    name="sittop" />
+      <field field_ref="icetbot"    name="sitbot" />
+
+      <!-- momentum -->
+      <field field_ref="uice"       name="sivelu" />
+      <field field_ref="vice"       name="sivelv" />
+      <field field_ref="icevel"     name="sivelo" />
+      <field field_ref="utau_ai"    name="utau_ai" />
+      <field field_ref="vtau_ai"    name="vtau_ai" />
+      <field field_ref="utau_oi"    name="utau_oi" />
+      <field field_ref="vtau_oi"    name="vtau_oi" />
+
+      <!-- rheology -->
+      <field field_ref="icediv"     name="sidive" />
+      <field field_ref="iceshe"     name="sishea" />
+      <field field_ref="icestr"     name="sistre" />
+      <field field_ref="normstr"    name="normstr" />
+      <field field_ref="sheastr"    name="sheastr" />
+      <field field_ref="sig1_pnorm" name="sig1_pnorm" />
+      <field field_ref="sig2_pnorm" name="sig2_pnorm" />
+
+      <!-- trends -->
+      <field field_ref="afxthd"     name="afxthd" />
+      <field field_ref="afxdyn"     name="afxdyn" />
+      <field field_ref="afxtot"     name="afxtot" />
+
+    </file>
+
+    <file id="file23" name_suffix="_icemod_flx" description="ice variables (fluxes)" enabled=".true." >
+
+      <!-- surface heat fluxes -->
+      <field field_ref="qt_oce_ai"   name="qt_oce_ai" />
+      <field field_ref="qt_atm_oi"   name="qt_atm_oi" />
+      <field field_ref="qtr_ice_top" name="qtr_ice_top" />
+      <field field_ref="qtr_ice_bot" name="qtr_ice_bot" />
+      <field field_ref="qt_ice"      name="qt_ice" />
+      <field field_ref="qsr_ice"     name="qsr_ice" />
+      <field field_ref="qns_ice"     name="qns_ice" />
+      <field field_ref="qemp_ice"    name="qemp_ice" />
+      <field field_ref="albedo"      name="albedo" />
+
+      <!-- salt fluxes -->
+      <field field_ref="sfxice"      name="sfxice" />
+
+      <!-- mass fluxes -->
+      <field field_ref="vfxice"      name="vfxice" />
+      <field field_ref="vfxsnw"      name="vfxsnw" />
+
+    </file>
+
+    <file id="file24" name_suffix="_icemod_cat" description="ice variables (categories)" enabled=".true." >
+
+      <!-- categories -->
+      <field field_ref="iceconc_cat" name="siconcat" />
+      <field field_ref="icethic_cat" name="sithicat" />
+      <field field_ref="snwthic_cat" name="snthicat" />
+      <field field_ref="iceage_cat"  name="siagecat" />
+
+    </file>
+
+  </file_group>
+
+  <file_group id="2m" output_freq="2mo" output_level="10" enabled=".TRUE."/> <!-- real 2m files -->
+  <file_group id="3m" output_freq="3mo" output_level="10" enabled=".TRUE."/> <!-- real 3m files -->
+  <file_group id="4m" output_freq="4mo" output_level="10" enabled=".TRUE."/> <!-- real 4m files -->
+  <file_group id="6m" output_freq="6mo" output_level="10" enabled=".TRUE."/> <!-- real 6m files -->
+
+  <file_group id="1y"  output_freq="1y"  output_level="10" enabled=".TRUE."/> <!-- real yearly files -->
+  <file_group id="2y"  output_freq="2y"  output_level="10" enabled=".TRUE."/> <!-- real 2y files -->
+  <file_group id="5y"  output_freq="5y"  output_level="10" enabled=".TRUE."/> <!-- real 5y files -->
+  <file_group id="10y" output_freq="10y" output_level="10" enabled=".TRUE."/> <!-- real 10y files -->
+
+</file_definition>

+ 151 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/file_def_nemo-oce.xml

@@ -0,0 +1,151 @@
+<?xml version="1.0"?>
+
+<!--
+===================================================================================================
+=                                  output files definition                                        =
+=                             Define your own files for ocean dynamics                            =
+=                                put the variables you want...                                    =
+===================================================================================================
+-->
+
+<file_definition type="multiple_file" name="@expname@_@freq@_@startdate@_@enddate@" sync_freq="1mo" min_digits="4">
+
+  <file_group id="1ts" output_freq="1ts" output_level="10" enabled=".TRUE."/> <!-- 1 time step files -->
+
+  <file_group id="1h" output_freq="1h" output_level="10" enabled=".TRUE."/> <!-- 1h files -->
+  <file_group id="2h" output_freq="2h" output_level="10" enabled=".TRUE."/> <!-- 2h files -->
+  <file_group id="3h" output_freq="3h" output_level="10" enabled=".TRUE."/> <!-- 3h files -->
+  <file_group id="4h" output_freq="4h" output_level="10" enabled=".TRUE."/> <!-- 4h files -->
+  <file_group id="6h" output_freq="6h" output_level="10" enabled=".TRUE."/> <!-- 6h files -->
+
+  <file_group id="1d" output_freq="1d"  output_level="10" enabled=".TRUE."> <!-- 1d files -->
+
+    <file id="file11" name_suffix="_grid_T" description="ocean T grid variables" >
+
+      <field field_ref="sst" name="tos" />
+      <field field_ref="sss" name="sos" />
+      <field field_ref="ssh" name="zos" />
+      <field field_ref="mldkz5" />
+      <field field_ref="mldr10_1" />
+
+    </file>
+
+    <file id="file12" name_suffix="_grid_U" description="ocean U grid variables" >
+
+      <field field_ref="ssu"  name="uos" />
+      <field field_ref="utau" name="tauuo" />
+
+    </file>
+
+    <file id="file13" name_suffix="_grid_V" description="ocean V grid variables" >
+
+      <field field_ref="ssv"  name="vos" />
+      <field field_ref="vtau" name="tauvo" />
+
+    </file>
+
+  </file_group>
+
+  <file_group id="5d" output_freq="5d" output_level="10" enabled=".TRUE."/> <!-- 5d files -->
+
+  <file_group id="1m" output_freq="1mo" output_level="10" enabled=".TRUE."> <!-- real monthly files -->
+
+    <file id="file31" name_suffix="_grid_T" description="ocean T grid variables" >
+
+      <field field_ref="e3t" />
+      <field field_ref="toce" name="thetao" operation="instant" freq_op="1mo" > @toce_e3t / @e3t </field>
+      <field field_ref="soce" name="so"     operation="instant" freq_op="1mo" > @soce_e3t / @e3t </field>
+      <field field_ref="sst"  name="tos" />
+      <field field_ref="sss"  name="sos" />
+      <field field_ref="ssh"  name="zos" />
+      <field field_ref="mldkz5" />
+      <field field_ref="mldr10_1" />
+      <field field_ref="sbt" />
+      <field field_ref="heatc" name="heatc" />
+      <field field_ref="saltc" name="saltc" />
+
+    </file>
+
+    <file id="file32" name_suffix="_SBC" description="SBC fields" >
+
+      <field field_ref="empmr"   name="wfo" />
+      <field field_ref="precip"  name="precip" />
+      <field field_ref="snowpre" name="snowpre" />
+      <field field_ref="saltflx" name="sfx" />
+  	  <field field_ref="qsr_oce" name="qsr_oce" />
+      <field field_ref="qns_oce" name="qns_oce" />
+      <field field_ref="qt_oce"  name="qt_oce" />
+      <field field_ref="taum"    name="taum" />
+      <field field_ref="wspd"    name="windsp" />
+
+      <field field_ref="runoffs" />
+      <field field_ref="fwfisf_cav" />
+      <field field_ref="fwfisf_par" />
+      <field field_ref="calving_cea" />
+
+    </file>
+
+    <file id="file33" name_suffix="_grid_U" description="ocean U grid variables" >
+
+      <field field_ref="e3u" />
+      <field field_ref="uoce"     name="uo" operation="instant" freq_op="1mo" > @uoce_e3u / @e3u </field>
+      <field field_ref="ssu"      name="uos" />
+      <field field_ref="utau"     name="tauuo" />
+
+    </file>
+
+    <file id="file34" name_suffix="_grid_V" description="ocean V grid variables" >
+
+      <field field_ref="e3v" />
+      <field field_ref="voce"     name="vo" operation="instant" freq_op="1mo" > @voce_e3v / @e3v </field>
+      <field field_ref="ssv"      name="vos" />
+      <field field_ref="vtau"     name="tauvo" />
+
+    </file>
+
+    <file id="file35" name_suffix="_grid_W" description="ocean W grid variables" >
+      <field field_ref="e3w" />
+      <field field_ref="woce" name="wo" />
+    </file>
+
+    <file id="file36" name_suffix="_diaptr2D" description="zonal mean variables" >
+
+      <field field_ref="sophtove"    name="htovovrt"      grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sopstove"    name="sltovovrt"     grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sophtgyre"   name="htovgyre"      grid_ref="grid_znl_T_2D"  > sophtvtr - sophtove  </field>
+      <field field_ref="sopstgyre"   name="sltogyre"      grid_ref="grid_znl_T_2D"  > sophtvtr - sopstove  </field>
+      <field field_ref="sophtbtr"    name="htbtr"         grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sopstbtr"    name="sltbtr"        grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sophtadv"    name="htadv"         grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sopstadv"    name="sltadv"        grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sophtldf"    name="htldf"         grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sopstldf"    name="sltldf"        grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sophtvtr"    name="hfbasin"       grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sopstvtr"    name="sltbasin"      grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sophteiv"    name="hfbasinpmadv"  grid_ref="grid_znl_T_2D"  />
+      <field field_ref="sopsteiv"    name="sltbasinpmadv" grid_ref="grid_znl_T_2D"  />
+
+    </file>
+
+    <file id="file37" name_suffix="_diaptr3D" description="zonal mean variables" >
+
+      <field field_ref="zomsf"       name="msftyz"        grid_ref="grid_znl_W_3D"  />
+      <field field_ref="zotem"       name="znltem"        grid_ref="grid_znl_T_3D"  />
+      <field field_ref="zosal"       name="znlsal"        grid_ref="grid_znl_T_3D"  />
+      <field field_ref="zosrf"       name="znlsrf"        grid_ref="grid_znl_T_3D"  />
+
+    </file>
+
+  </file_group>
+
+  <file_group id="2m" output_freq="2mo" output_level="10" enabled=".TRUE."/> <!-- real 2m files -->
+  <file_group id="3m" output_freq="3mo" output_level="10" enabled=".TRUE."/> <!-- real 3m files -->
+  <file_group id="4m" output_freq="4mo" output_level="10" enabled=".TRUE."/> <!-- real 4m files -->
+  <file_group id="6m" output_freq="6mo" output_level="10" enabled=".TRUE."/> <!-- real 6m files -->
+
+  <file_group id="1y"  output_freq="1y"  output_level="10" enabled=".TRUE."/> <!-- real yearly files -->
+  <file_group id="2y"  output_freq="2y"  output_level="10" enabled=".TRUE."/> <!-- real 2y files -->
+  <file_group id="5y"  output_freq="5y"  output_level="10" enabled=".TRUE."/> <!-- real 5y files -->
+  <file_group id="10y" output_freq="10y" output_level="10" enabled=".TRUE."/> <!-- real 10y files -->
+
+</file_definition>

+ 431 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/grid_def_nemo.xml

@@ -0,0 +1,431 @@
+<?xml version="1.0"?>
+<!--
+============================================================================================================
+= grid definition = = DO NOT CHANGE =
+============================================================================================================
+-->
+
+<grid_definition>
+
+  <!--  -->
+  <grid id="grid_T_2D" >
+    <domain domain_ref="grid_T" />
+  </grid>
+  <grid id="grid_T_2D_inner" >
+    <domain domain_ref="grid_T_inner" name="grid_T" />
+  </grid>
+  <!--  -->
+  <grid id="grid_T_ncatice" >
+    <domain domain_ref="grid_T" />
+    <axis axis_ref="ncatice" />
+  </grid>
+  <grid id="grid_T_ncatice_inner" >
+    <domain domain_ref="grid_T_inner" name="grid_T" />
+    <axis axis_ref="ncatice" />
+  </grid>
+  <!--  -->
+  <grid id="grid_T_3D" >
+    <domain domain_ref="grid_T" />
+    <axis axis_ref="deptht" />
+  </grid>
+  <grid id="grid_T_3D_inner" >
+    <domain domain_ref="grid_T_inner" name="grid_T" />
+    <axis axis_ref="deptht" />
+  </grid>
+  <!--  -->
+  <grid id="grid_T_3DS" >
+    <domain domain_ref="grid_T" />
+    <axis axis_ref="profsed" />
+  </grid>
+  <grid id="grid_T_3DS_inner" >
+    <domain domain_ref="grid_T_inner" name="grid_T" />
+    <axis axis_ref="profsed" />
+  </grid>
+  <!--  -->
+  <grid id="grid_U_2D" >
+    <domain domain_ref="grid_U" />
+  </grid>
+  <grid id="grid_U_2D_inner" >
+    <domain domain_ref="grid_U_inner" name="grid_U" />
+  </grid>
+  <!--  -->
+  <grid id="grid_U_3D" >
+    <domain domain_ref="grid_U" />
+    <axis axis_ref="depthu" />
+  </grid>
+  <grid id="grid_U_3D_inner" >
+    <domain domain_ref="grid_U_inner" name="grid_U" />
+    <axis axis_ref="depthu" />
+  </grid>
+  <!--  -->
+  <grid id="grid_V_2D" >
+    <domain domain_ref="grid_V" />
+  </grid>
+  <grid id="grid_V_2D_inner" >
+    <domain domain_ref="grid_V_inner" name="grid_V" />
+  </grid>
+  <!--  -->
+  <grid id="grid_V_3D" >
+    <domain domain_ref="grid_V" />
+    <axis axis_ref="depthv" />
+  </grid>
+  <grid id="grid_V_3D_inner" >
+    <domain domain_ref="grid_V_inner" name="grid_V" />
+    <axis axis_ref="depthv" />
+  </grid>
+  <!--  -->
+  <grid id="grid_W_2D" >
+    <domain domain_ref="grid_W" />
+  </grid>
+  <grid id="grid_W_2D_inner" >
+    <domain domain_ref="grid_W_inner" name="grid_W" />
+  </grid>
+  <!--  -->
+  <grid id="grid_W_3D" >
+    <domain domain_ref="grid_W" />
+    <axis axis_ref="depthw" />
+  </grid>
+  <grid id="grid_W_3D_inner" >
+    <domain domain_ref="grid_W_inner" name="grid_W" />
+    <axis axis_ref="depthw" />
+  </grid>
+  <!--  -->
+  <grid id="grid_F_2D" >
+    <domain domain_ref="grid_F" />
+  </grid>
+  <grid id="grid_F_2D_inner" >
+    <domain domain_ref="grid_F_inner" name="grid_F" />
+  </grid>
+  <!--  -->
+  <grid id="grid_F_3D" >
+    <domain domain_ref="grid_F" />
+    <axis axis_ref="depthf" />
+  </grid>
+  <grid id="grid_F_3D_inner" >
+    <domain domain_ref="grid_F_inner" name="grid_F" />
+    <axis axis_ref="depthf" />
+  </grid>
+  <!--  -->
+  <grid id="grid_1point" >
+    <domain domain_ref="1point"/>
+  </grid>
+  <!--  -->
+  <grid id="grid_T_nfloat" >
+    <domain domain_ref="grid_T" />
+    <axis axis_ref="nfloat" />
+  </grid>
+  <!--  -->
+  <grid id="grid_EqT" >
+    <domain domain_ref="EqT" />
+  </grid>
+  <!--  -->
+
+  <grid id="grid_znl_T_2D">
+    <domain domain_ref="gznl" />
+    <axis axis_ref="basin" />
+  </grid>
+
+  <grid id="grid_znl_T_3D">
+    <domain domain_ref="gznl" />
+    <axis axis_ref="deptht"  />
+    <axis axis_ref="basin" />
+  </grid>
+
+  <grid id="grid_znl_W_3D">
+    <domain domain_ref="gznl" />
+    <axis axis_ref="depthw"  />
+    <axis axis_ref="basin" />
+  </grid>
+
+  <grid id="grid_ptr_T_2D">
+    <domain domain_ref="ptr" />
+    <axis axis_ref="basin" />
+  </grid>
+
+  <grid id="grid_ptr_T_3D">
+    <domain  domain_ref="ptr" />
+    <axis axis_ref="deptht"  />
+    <axis axis_ref="basin" />
+  </grid>
+
+  <grid id="grid_ptr_W_3D">
+    <domain  domain_ref="ptr" />
+    <axis axis_ref="depthw"  />
+    <axis axis_ref="basin" />
+  </grid>
+
+  <grid id="grid_ptr_W_GLO">
+    <domain  domain_ref="ptr" />
+    <axis axis_ref="depthw"  />
+    <scalar>
+      <extract_axis position="0" />
+    </scalar>
+  </grid>
+
+  <grid id="grid_ptr_W_ATL">
+    <domain  domain_ref="ptr" />
+    <axis axis_ref="depthw"  />
+    <scalar>
+      <extract_axis position="1" />
+    </scalar>
+  </grid>
+
+  <grid id="grid_ptr_W_IND">
+    <domain  domain_ref="ptr" />
+    <axis axis_ref="depthw"  />
+    <scalar>
+      <extract_axis position="2" />
+    </scalar>
+  </grid>
+
+  <grid id="grid_T_SFC">
+    <domain domain_ref="grid_T" />
+    <scalar>
+      <extract_axis position="0" />
+    </scalar>
+  </grid>
+
+  <grid id="grid_T_vsum">
+    <domain domain_ref="grid_T"/>
+    <scalar>
+      <reduce_axis operation="sum" />
+    </scalar>
+  </grid>
+
+  <grid id="grid_U_vsum">
+    <domain domain_ref="grid_U"/>
+    <scalar>
+      <reduce_axis operation="sum" />
+    </scalar>
+  </grid>
+
+  <grid id="grid_V_vsum">
+    <domain domain_ref="grid_V"/>
+    <scalar>
+      <reduce_axis operation="sum" />
+    </scalar>
+  </grid>
+
+  <!-- for ORCA2 grid  
+  <grid id="cumul_U">
+    <axis axis_ref="cumul_U" n_glo="180" >
+      <reduce_domain local="true" operation="sum" direction="jDir" />
+      <reduce_axis operation="sum" />
+    </axis>
+    <axis axis_ref="depthu" />
+  </grid>
+  -->
+
+  <!-- for eORCA1 grid
+
+  <grid id="cumul_U">
+    <axis axis_ref="cumul_U" n_glo="360" >
+      <reduce_domain local="true" operation="sum" direction="jDir" />
+      <reduce_axis operation="sum" />
+    </axis>
+    <axis axis_ref="depthu" />
+  </grid-->
+
+  <!-- for eORCA025 grid -->
+
+  <grid id="cumul_U">
+    <axis axis_ref="cumul_U" n_glo="1440" >
+      <reduce_domain local="true" operation="sum" direction="jDir" />
+      <reduce_axis operation="sum" />
+    </axis>
+    <axis axis_ref="depthu" />
+  </grid>
+
+
+  <grid id="grid_T_zoom_300">
+    <domain domain_ref="grid_T" />
+    <axis axis_ref="deptht300" />
+  </grid>
+
+  <grid id="grid_U_scalar" >
+    <domain domain_ref="grid_U" />
+    <scalar/>
+  </grid>
+
+  <grid id="grid_V_scalar" >
+    <domain domain_ref="grid_V" />
+    <scalar/>
+  </grid>
+
+  <grid id="grid_U_4strait">
+    <domain domain_ref="grid_U" />
+    <axis axis_ref="section">
+      <duplicate_scalar/>
+    </axis>
+  </grid>
+
+  <grid id="grid_V_4strait">
+    <domain domain_ref="grid_V" />
+    <axis axis_ref="section">
+      <duplicate_scalar/>
+    </axis>
+  </grid>
+
+  <grid id="grid_U_4strait_hsum">
+    <scalar >
+      <reduce_domain operation="sum" local="true"/>
+      <reduce_scalar operation="sum" />
+    </scalar>
+    <axis axis_ref="section"/>
+  </grid>
+
+  <grid id="grid_V_4strait_hsum">
+    <scalar >
+      <reduce_domain operation="sum" local="true"/>
+      <reduce_scalar operation="sum" />
+    </scalar>
+    <axis axis_ref="section"/>
+  </grid>
+
+  <grid id="grid_4strait">
+    <axis axis_ref="section"/>
+  </grid>
+
+  <grid id="grid_U_4strait_ice">
+    <domain domain_ref="grid_U" />
+    <axis axis_ref="section_ice">
+      <duplicate_scalar/>
+    </axis>
+  </grid>
+
+  <grid id="grid_V_4strait_ice">
+    <domain domain_ref="grid_V" />
+    <axis axis_ref="section_ice">
+      <duplicate_scalar/>
+    </axis>
+  </grid>
+
+  <grid id="grid_U_4strait_ice_hsum">
+    <scalar >
+      <reduce_domain operation="sum" local="true"/>
+      <reduce_scalar operation="sum" />
+    </scalar>
+    <axis axis_ref="section_ice"/>
+  </grid>
+
+  <grid id="grid_V_4strait_ice_hsum">
+    <scalar >
+      <reduce_domain operation="sum" local="true"/>
+      <reduce_scalar operation="sum" />
+    </scalar>
+    <axis axis_ref="section_ice"/>
+  </grid>
+
+  <grid id="grid_4strait_ice">
+    <axis axis_ref="section_ice"/>
+  </grid>
+
+  <!-- scalars -->
+  <grid id="grid_scalar" >
+    <scalar/>
+  </grid>
+
+  <!-- ABL grid definition -->
+  <grid id="grid_TA_2D">
+    <domain domain_ref="grid_T" />
+  </grid>
+  <grid id="grid_TA_3D">
+    <domain domain_ref="grid_T" />
+    <axis  id="ght_abl" />
+  </grid>
+  <grid id="grid_WA_3D">
+    <domain domain_ref="grid_T" />
+    <axis  id="ghw_abl" />
+  </grid>
+  <!--  -->
+
+  <!-- grid definitions for multiple-linear-regression analysis (diamlr) -->
+  <grid id="diamlr_grid_scalar" >
+    <scalar />
+    <scalar />
+  </grid>
+  <grid id="diamlr_grid_T_2D" >
+    <domain domain_ref="grid_T" />
+    <scalar />
+  </grid>
+  <grid id="diamlr_grid_U_2D" >
+    <domain domain_ref="grid_U" />
+    <scalar />
+  </grid>
+  <grid id="diamlr_grid_V_2D" >
+    <domain domain_ref="grid_V" />
+    <scalar />
+  </grid>
+  <grid id="diamlr_grid_W_2D" >
+    <domain domain_ref="grid_W" />
+    <scalar />
+  </grid>
+  <grid id="diamlr_grid_2D_to_grid_T_3D" >
+    <domain domain_ref="grid_T" />
+    <axis axis_ref="deptht">
+      <duplicate_scalar />
+    </axis>
+  </grid>
+  <grid id="diamlr_grid_2D_to_grid_U_3D" >
+    <domain domain_ref="grid_U" />
+    <axis axis_ref="depthu">
+      <duplicate_scalar />
+    </axis>
+  </grid>
+  <grid id="diamlr_grid_2D_to_grid_V_3D" >
+    <domain domain_ref="grid_V" />
+    <axis axis_ref="depthv">
+      <duplicate_scalar />
+    </axis>
+  </grid>
+  <grid id="diamlr_grid_2D_to_grid_W_3D" >
+    <domain domain_ref="grid_W" />
+    <axis axis_ref="depthw">
+      <duplicate_scalar />
+    </axis>
+  </grid>
+  <grid id="diamlr_grid_2D_to_scalar" >
+    <scalar>
+      <reduce_domain operation="average" />
+    </scalar>
+    <scalar />
+  </grid>
+  <!-- grid definitions for the computation of daily detided model diagnostics (diadetide) -->
+  <grid id="diadetide_grid_T_2D" >
+    <domain domain_ref="grid_T" />
+    <scalar />
+  </grid>
+  <grid id="diadetide_grid_U_2D" >
+    <domain domain_ref="grid_U" />
+    <scalar />
+  </grid>
+  <grid id="diadetide_grid_V_2D" >
+    <domain domain_ref="grid_V" />
+    <scalar />
+  </grid>
+  <grid id="diadetide_grid_2D_to_grid_T_3D" >
+    <domain domain_ref="grid_T" />
+    <axis axis_ref="deptht">
+      <duplicate_scalar />
+    </axis>
+  </grid>
+  <grid id="diadetide_grid_2D_to_grid_U_3D" >
+    <domain domain_ref="grid_U" />
+    <axis axis_ref="depthu">
+      <duplicate_scalar />
+    </axis>
+  </grid>
+  <grid id="diadetide_grid_2D_to_grid_V_3D" >
+    <domain domain_ref="grid_V" />
+    <axis axis_ref="depthv">
+      <duplicate_scalar />
+    </axis>
+  </grid>
+  <grid id="diadetide_grid_2D_to_grid_W_3D" >
+    <domain domain_ref="grid_W" />
+    <axis axis_ref="depthw">
+      <duplicate_scalar />
+    </axis>
+  </grid>
+
+</grid_definition>

+ 28 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/iodef.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<simulation>
+
+<!-- ============================================================================================ -->
+<!-- XIOS context                                                                                 -->
+<!-- ============================================================================================ -->
+
+  <context id="xios" >
+
+      <variable_definition>
+
+          <variable id="info_level"                type="int">10</variable>
+          <variable id="using_server"              type="bool">true</variable>
+          <variable id="using_oasis"               type="bool">false</variable>
+	  <variable id="oasis_codes_id"            type="string" >oceanx</variable>
+	  <variable id="optimal_buffer_size"       type="string" >memory</variable>
+	  <variable id="buffer_size_factor"        type="double" >2.0</variable>
+
+      </variable_definition>
+  </context>
+
+<!-- ============================================================================================ -->
+<!-- NEMO  CONTEXT add and suppress the components you need                                       -->
+<!-- ============================================================================================ -->
+
+  <context id="nemo" src="./context_nemo.xml"/>       <!--  NEMO       -->
+
+</simulation>

+ 105 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/namelist_ice_cfg

@@ -0,0 +1,105 @@
+!!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+!! SI3 configuration namelist: Overwrites SHARED/namelist_ice_ref
+!!              1 - Generic parameters                 (nampar)
+!!              2 - Ice thickness discretization       (namitd)
+!!              3 - Ice dynamics                       (namdyn)
+!!              4 - Ice ridging/rafting                (namdyn_rdgrft)
+!!              5 - Ice rheology                       (namdyn_rhg)
+!!              6 - Ice advection                      (namdyn_adv)
+!!              7 - Ice surface boundary conditions    (namsbc)
+!!              8 - Ice thermodynamics                 (namthd)
+!!              9 - Ice heat diffusion                 (namthd_zdf)
+!!             10 - Ice lateral melting                (namthd_da)
+!!             11 - Ice growth in open water           (namthd_do)
+!!             12 - Ice salinity                       (namthd_sal)
+!!             13 - Ice melt ponds                     (namthd_pnd)
+!!             14 - Ice initialization                 (namini)
+!!             15 - Ice/snow albedos                   (namalb)
+!!             16 - Ice diagnostics                    (namdia)
+!!>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+!
+!------------------------------------------------------------------------------
+&nampar         !   Generic parameters
+!------------------------------------------------------------------------------
+   nlay_s           =   1             !  number of snow layers (only 1 is working)
+   rn_amax_s        =   0.95          !  maximum tolerated ice concentration SH
+/
+!------------------------------------------------------------------------------
+&namitd         !   Ice discretization
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namdyn         !   Ice dynamics
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namdyn_rdgrft  !   Ice ridging/rafting
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namdyn_rhg     !   Ice rheology
+!------------------------------------------------------------------------------
+      ln_aEVP       = .false.          !     adaptive rheology (Kimmritz et al. 2016 & 2017)
+      nn_nevp       = 120             !     number of EVP subcycles                             
+/
+!------------------------------------------------------------------------------
+&namdyn_adv     !   Ice advection
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namsbc         !   Ice surface boundary conditions
+!------------------------------------------------------------------------------
+   nn_qtrice        =   1             !  Solar flux transmitted thru the surface scattering layer:
+                                      !     = 0  Grenfell and Maykut 1977 (depends on cloudiness and is 0 when there is snow) 
+                                      !     = 1  Lebrun 2019 (equals 0.3 anytime with different melting/dry snw conductivities)
+/
+!------------------------------------------------------------------------------
+&namthd         !   Ice thermodynamics
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namthd_zdf     !   Ice heat diffusion
+!------------------------------------------------------------------------------
+   rn_cnd_s         =   0.35          !  thermal conductivity of the snow (0.31 W/m/K, Maykut and Untersteiner, 1971)
+                                      !     Obs: 0.1-0.5 (Lecomte et al, JAMES 2013)
+/
+!------------------------------------------------------------------------------
+&namthd_da      !   Ice lateral melting
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namthd_do      !   Ice growth in open water
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namthd_sal     !   Ice salinity
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namthd_pnd     !   Melt ponds
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namini         !   Ice initialization
+!------------------------------------------------------------------------------
+   nn_iceini_file   =   1             !     0 = Initialise sea ice based on SSTs
+                                      !     1 = Initialise sea ice from single category netcdf file
+                                      !     2 = Initialise sea ice from multi category restart file
+   ! -- for nn_iceini_file = 1
+   sn_hti = 'seaice'                , -1 ,'sithic' ,  .true.   , .true., 'yearly'  , '' , '', ''
+   sn_hts = 'seaice'                , -1 ,'snthic' ,  .true.   , .true., 'yearly'  , '' , '', ''
+   sn_ati = 'seaice'                , -1 ,'siconc' ,  .true.   , .true., 'yearly'  , '' , '', ''
+   sn_smi = 'NOT USED'              , -12. ,'smi'   ,  .false.  , .true., 'yearly'  , '' , '', ''
+   sn_tmi = 'NOT USED'              , -12. ,'tmi'   ,  .false.  , .true., 'yearly'  , '' , '', ''
+   sn_tsu = 'NOT USED'              , -12. ,'tsu'   ,  .false.  , .true., 'yearly'  , '' , '', ''
+/
+!------------------------------------------------------------------------------
+&namalb         !   albedo parameters
+!------------------------------------------------------------------------------
+/
+!------------------------------------------------------------------------------
+&namdia         !   Diagnostics
+!------------------------------------------------------------------------------
+      rn_icechk_cel =  100.           !     check at each gridcell          (1.e-4m/h)=> stops the code if violated (and writes a file)
+      rn_icechk_glo =  1.             !     check over the entire ice cover (1.e-6m/h)=> only prints warnings
+/

+ 1 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/namelist_ice_ref

@@ -0,0 +1 @@
+../../SHARED/namelist_ice_ref

+ 1 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/namelist_ref

@@ -0,0 +1 @@
+../../SHARED/namelist_ref

+ 1 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/EXPREF/nemo

@@ -0,0 +1 @@
+/gpfs/home/acad/ucl-elic/pbarriat/modeles/nemo_4.2.0/cfgs/MY_ORCA025_ICE_ELIC/BLD/bin/nemo.exe

+ 280 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/dommsk.F90

@@ -0,0 +1,280 @@
+MODULE dommsk
+   !!======================================================================
+   !!                       ***  MODULE dommsk   ***
+   !! Ocean initialization : domain land/sea mask 
+   !!======================================================================
+   !! History :  OPA  ! 1987-07  (G. Madec)  Original code
+   !!            6.0  ! 1993-03  (M. Guyon)  symetrical conditions (M. Guyon)
+   !!            7.0  ! 1996-01  (G. Madec)  suppression of common work arrays
+   !!             -   ! 1996-05  (G. Madec)  mask computed from tmask
+   !!            8.0  ! 1997-02  (G. Madec)  mesh information put in domhgr.F
+   !!            8.1  ! 1997-07  (G. Madec)  modification of kbat and fmask
+   !!             -   ! 1998-05  (G. Roullet)  free surface
+   !!            8.2  ! 2000-03  (G. Madec)  no slip accurate
+   !!             -   ! 2001-09  (J.-M. Molines)  Open boundaries
+   !!   NEMO     1.0  ! 2002-08  (G. Madec)  F90: Free form and module
+   !!             -   ! 2005-11  (V. Garnier) Surface pressure gradient organization
+   !!            3.2  ! 2009-07  (R. Benshila) Suppression of rigid-lid option
+   !!            3.6  ! 2015-05  (P. Mathiot) ISF: add wmask,wumask and wvmask
+   !!            4.0  ! 2016-06  (G. Madec, S. Flavoni)  domain configuration / user defined interface
+   !!            4.x  ! 2020-02  (G. Madec, S. Techene) introduce ssh to h0 ratio
+   !!----------------------------------------------------------------------
+
+   !!----------------------------------------------------------------------
+   !!   dom_msk       : compute land/ocean mask
+   !!----------------------------------------------------------------------
+   USE oce            ! ocean dynamics and tracers
+   USE dom_oce        ! ocean space and time domain
+   USE domutl         ! 
+   USE usrdef_fmask   ! user defined fmask
+   USE bdy_oce        ! open boundary
+   !
+   USE in_out_manager ! I/O manager
+   USE iom            ! IOM library
+   USE lbclnk         ! ocean lateral boundary conditions (or mpp link)
+   USE lib_mpp        ! Massively Parallel Processing library
+#if defined key_drakkar
+   USE fldread , ONLY : FLD_N    ! for the case shlat2d
+#endif
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   dom_msk    ! routine called by inidom.F90
+
+   !                            !!* Namelist namlbc : lateral boundary condition *
+   REAL(wp)        :: rn_shlat   ! type of lateral boundary condition on velocity
+   LOGICAL, PUBLIC :: ln_vorlat  !  consistency of vorticity boundary condition 
+   !                                            with analytical eqs.
+
+   !! * Substitutions
+#  include "do_loop_substitute.h90"
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: dommsk.F90 15556 2021-11-29 15:23:06Z jchanut $ 
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   SUBROUTINE dom_msk( k_top, k_bot )
+      !!---------------------------------------------------------------------
+      !!                 ***  ROUTINE dom_msk  ***
+      !!
+      !! ** Purpose :   Compute land/ocean mask arrays at tracer points, hori-
+      !!      zontal velocity points (u & v), vorticity points (f) points.
+      !!
+      !! ** Method  :   The ocean/land mask  at t-point is deduced from ko_top 
+      !!      and ko_bot, the indices of the fist and last ocean t-levels which 
+      !!      are either defined in usrdef_zgr or read in zgr_read.
+      !!                The velocity masks (umask, vmask, wmask, wumask, wvmask) 
+      !!      are deduced from a product of the two neighboring tmask.
+      !!                The vorticity mask (fmask) is deduced from tmask taking
+      !!      into account the choice of lateral boundary condition (rn_shlat) :
+      !!         rn_shlat = 0, free slip  (no shear along the coast)
+      !!         rn_shlat = 2, no slip  (specified zero velocity at the coast)
+      !!         0 < rn_shlat < 2, partial slip   | non-linear velocity profile
+      !!         2 < rn_shlat, strong slip        | in the lateral boundary layer
+      !!
+      !! ** Action :   tmask, umask, vmask, wmask, wumask, wvmask : land/ocean mask 
+      !!                         at t-, u-, v- w, wu-, and wv-points (=0. or 1.)
+      !!               fmask   : land/ocean mask at f-point (=0., or =1., or 
+      !!                         =rn_shlat along lateral boundaries)
+      !!               ssmask , ssumask, ssvmask, ssfmask : 2D ocean mask, i.e. at least 1 wet cell in the vertical
+      !!               tmask_i : ssmask * ( excludes halo+duplicated points (NP folding) )
+      !!----------------------------------------------------------------------
+      INTEGER, DIMENSION(:,:), INTENT(in) ::   k_top, k_bot   ! first and last ocean level
+      !
+      INTEGER  ::   ji, jj, jk     ! dummy loop indices
+      INTEGER  ::   iktop, ikbot   !   -       -
+      INTEGER  ::   ios, inum
+      !!
+      NAMELIST/namlbc/ rn_shlat, ln_vorlat
+      NAMELIST/nambdy/ ln_bdy ,nb_bdy, ln_coords_file, cn_coords_file,         &
+         &             ln_mask_file, cn_mask_file, cn_dyn2d, nn_dyn2d_dta,     &
+         &             cn_dyn3d, nn_dyn3d_dta, cn_tra, nn_tra_dta,             &
+         &             ln_tra_dmp, ln_dyn3d_dmp, rn_time_dmp, rn_time_dmp_out, &
+         &             cn_ice, nn_ice_dta,                                     &
+         &             ln_vol, nn_volctl, nn_rimwidth
+#if defined key_drakkar
+      REAL(wp) :: zshlat           !: working variable
+      REAL(wp), DIMENSION(:,:) , ALLOCATABLE :: zshlat2d
+      CHARACTER(lc)  :: cn_dir
+      LOGICAL        :: ln_shlat2d
+      TYPE(FLD_N)    :: sn_shlat2d
+      !!
+      NAMELIST/namlbc_drk/ ln_shlat2d, cn_dir, sn_shlat2d
+#endif
+      !!---------------------------------------------------------------------
+      !
+      READ  ( numnam_ref, namlbc, IOSTAT = ios, ERR = 901 )
+901   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namlbc in reference namelist' )
+      READ  ( numnam_cfg, namlbc, IOSTAT = ios, ERR = 902 )
+902   IF( ios >  0 )   CALL ctl_nam ( ios , 'namlbc in configuration namelist' )
+      IF(lwm) WRITE ( numond, namlbc )
+#if defined key_drakkar
+      READ  ( numnam_ref, namlbc_drk, IOSTAT = ios, ERR = 905 )
+905   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namlbc_drk in reference namelist' )
+      READ  ( numnam_cfg, namlbc_drk, IOSTAT = ios, ERR = 906 )
+906   IF( ios >  0 )   CALL ctl_nam ( ios , 'namlbc_drk in configuration namelist' )
+      IF(lwm) WRITE ( numond, namlbc_drk )
+#endif
+      
+      IF(lwp) THEN                  ! control print
+         WRITE(numout,*)
+         WRITE(numout,*) 'dommsk : ocean mask '
+         WRITE(numout,*) '~~~~~~'
+         WRITE(numout,*) '   Namelist namlbc'
+         WRITE(numout,*) '      lateral momentum boundary cond.    rn_shlat  = ',rn_shlat
+         WRITE(numout,*) '      consistency with analytical form   ln_vorlat = ',ln_vorlat 
+      ENDIF
+      !
+      IF(lwp) WRITE(numout,*)
+      IF     (      rn_shlat == 0.               ) THEN   ;   IF(lwp) WRITE(numout,*) '   ==>>>   ocean lateral  free-slip'
+      ELSEIF (      rn_shlat == 2.               ) THEN   ;   IF(lwp) WRITE(numout,*) '   ==>>>   ocean lateral  no-slip'
+      ELSEIF ( 0. < rn_shlat .AND. rn_shlat < 2. ) THEN   ;   IF(lwp) WRITE(numout,*) '   ==>>>   ocean lateral  partial-slip'
+      ELSEIF ( 2. < rn_shlat                     ) THEN   ;   IF(lwp) WRITE(numout,*) '   ==>>>   ocean lateral  strong-slip'
+      ELSE
+         CALL ctl_stop( 'dom_msk: wrong value for rn_shlat (i.e. a negalive value). We stop.' )
+      ENDIF
+#if defined key_drakkar
+      IF ( ln_shlat2d ) THEN
+         IF(lwp) WRITE(numout,*) '         READ shlat as a 2D coefficient in a file '
+         ALLOCATE (zshlat2d(jpi,jpj) )
+         rn_shlat = 9999.  ! set rn_shlat to a dummy value to force fmask modif
+         CALL iom_open(TRIM(cn_dir)//'/'//TRIM(sn_shlat2d%clname), inum)
+!JMMM check iom_get 4.2 ...
+         CALL iom_get (inum, jpdom_global,       sn_shlat2d%clvar, zshlat2d, 1) !
+         CALL iom_close(inum)
+      ENDIF
+#endif
+
+      !  Ocean/land mask at t-point  (computed from ko_top and ko_bot)
+      ! ----------------------------
+      !
+      tmask(:,:,:) = 0._wp
+      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+         iktop = k_top(ji,jj)
+         ikbot = k_bot(ji,jj)
+         IF( iktop /= 0 ) THEN       ! water in the column
+            tmask(ji,jj,iktop:ikbot) = 1._wp
+         ENDIF
+      END_2D
+      !
+      ! Mask corrections for bdy (read in mppini2)
+      READ  ( numnam_ref, nambdy, IOSTAT = ios, ERR = 903)
+903   IF( ios /= 0 )   CALL ctl_nam ( ios , 'nambdy in reference namelist' )
+      READ  ( numnam_cfg, nambdy, IOSTAT = ios, ERR = 904 )
+904   IF( ios >  0 )   CALL ctl_nam ( ios , 'nambdy in configuration namelist' )
+      ! ------------------------
+      IF ( ln_bdy .AND. ln_mask_file ) THEN
+         CALL iom_open( cn_mask_file, inum )
+         CALL iom_get ( inum, jpdom_global, 'bdy_msk', bdytmask(:,:) )
+         CALL iom_close( inum )
+         DO_3D( 1, 1, 1, 1, 1, jpkm1 )
+            tmask(ji,jj,jk) = tmask(ji,jj,jk) * bdytmask(ji,jj)
+         END_3D
+      ENDIF
+         
+      !  Ocean/land mask at u-, v-, and f-points   (computed from tmask)
+      ! ----------------------------------------
+      ! NB: at this point, fmask is designed for free slip lateral boundary condition
+      DO_3D( 0, 0, 0, 0, 1, jpk )
+         umask(ji,jj,jk) = tmask(ji,jj  ,jk) * tmask(ji+1,jj  ,jk)
+         vmask(ji,jj,jk) = tmask(ji,jj  ,jk) * tmask(ji  ,jj+1,jk)
+         fmask(ji,jj,jk) = tmask(ji,jj  ,jk) * tmask(ji+1,jj  ,jk)   &
+            &            * tmask(ji,jj+1,jk) * tmask(ji+1,jj+1,jk)
+      END_3D
+      !
+      ! In case of a coarsened grid, account her for possibly aditionnal  
+      ! masked points; these have been read in the mesh file and stored in mbku, mbkv, mbkf
+      DO_2D( 0, 0, 0, 0 )
+         IF ( MAXVAL(umask(ji,jj,:))/=0._wp )  umask(ji,jj,mbku(ji,jj)+1:jpk) = 0._wp
+         IF ( MAXVAL(vmask(ji,jj,:))/=0._wp )  vmask(ji,jj,mbkv(ji,jj)+1:jpk) = 0._wp
+         IF ( MAXVAL(fmask(ji,jj,:))/=0._wp )  fmask(ji,jj,mbkf(ji,jj)+1:jpk) = 0._wp
+      END_2D
+      CALL lbc_lnk( 'dommsk', umask, 'U', 1.0_wp, vmask, 'V', 1.0_wp, fmask, 'F', 1.0_wp )      ! Lateral boundary conditions
+ 
+      ! Ocean/land mask at wu-, wv- and w points    (computed from tmask)
+      !-----------------------------------------
+      wmask (:,:,1) = tmask(:,:,1)     ! surface
+      wumask(:,:,1) = umask(:,:,1)
+      wvmask(:,:,1) = vmask(:,:,1)
+      DO jk = 2, jpk                   ! interior values
+         wmask (:,:,jk) = tmask(:,:,jk) * tmask(:,:,jk-1)
+         wumask(:,:,jk) = umask(:,:,jk) * umask(:,:,jk-1)   
+         wvmask(:,:,jk) = vmask(:,:,jk) * vmask(:,:,jk-1)
+      END DO
+
+      ! Ocean/land column mask at t-, u-, and v-points   (i.e. at least 1 wet cell in the vertical)
+      ! ----------------------------------------------
+      ssmask (:,:) = MAXVAL( tmask(:,:,:), DIM=3 )
+      ssumask(:,:) = MAXVAL( umask(:,:,:), DIM=3 )
+      ssvmask(:,:) = MAXVAL( vmask(:,:,:), DIM=3 )
+      ssfmask(:,:) = MAXVAL( fmask(:,:,:), DIM=3 )
+      IF( lk_SWE ) THEN      ! Shallow Water Eq. case : redefine ssfmask
+         DO_2D( 0, 0, 0, 0 )
+            ssfmask(ji,jj) = MAX(  ssmask(ji,jj+1), ssmask(ji+1,jj+1),  & 
+               &                   ssmask(ji,jj  ), ssmask(ji+1,jj  )   )
+         END_2D
+         CALL lbc_lnk( 'dommsk', ssfmask, 'F', 1.0_wp )
+      ENDIF
+      fe3mask(:,:,:) = fmask(:,:,:)
+
+      ! Interior domain mask  (used for global sum) : 2D ocean mask x (halo+duplicated points) mask 
+      ! --------------------
+      !
+      CALL dom_uniq( tmask_i, 'T' )
+      tmask_i(:,:) = ssmask(:,:) * tmask_i(:,:)
+
+      ! Lateral boundary conditions on velocity (modify fmask)
+      ! ---------------------------------------  
+      IF( rn_shlat /= 0._wp ) THEN      ! Not free-slip lateral boundary condition
+         !
+#if defined key_drakkar
+      IF ( ln_shlat2d ) THEN  !  use 2D shlat
+         DO_3D( 0, 0, 0, 0, 1, jpk )
+            IF( fmask(ji,jj,jk) == 0._wp ) THEN
+               zshlat = zshlat2d(ji,jj)
+               fmask(ji,jj,jk) = zshlat * MIN( 1._wp , MAX( umask(ji,jj,jk), umask(ji,jj+1,jk), &
+                  &                                           vmask(ji,jj,jk), vmask(ji+1,jj,jk) ) )
+            ENDIF
+         END_3D
+      ELSE
+#endif
+         DO_3D( 0, 0, 0, 0, 1, jpk )
+            IF( fmask(ji,jj,jk) == 0._wp ) THEN
+               fmask(ji,jj,jk) = rn_shlat * MIN( 1._wp , MAX( umask(ji,jj,jk), umask(ji,jj+1,jk), &
+                  &                                           vmask(ji,jj,jk), vmask(ji+1,jj,jk) ) )
+            ENDIF
+         END_3D
+#if defined key_drakkar
+     ENDIF
+         IF ( ln_shlat2d ) THEN
+           DEALLOCATE (zshlat2d)
+         ENDIF
+#endif
+         CALL lbc_lnk( 'dommsk', fmask, 'F', 1._wp )      ! Lateral boundary conditions on fmask
+         !
+         ! CAUTION : The fmask may be further modified in dyn_vor_init ( dynvor.F90 ) depending on ln_vorlat
+         !
+      ENDIF
+      
+      ! User defined alteration of fmask (use to reduce ocean transport in specified straits)
+      ! -------------------------------- 
+      !
+      CALL usr_def_fmask( cn_cfg, nn_cfg, fmask )
+      !
+#if defined key_agrif
+      ! Reset masks defining updated points over parent grids
+      !  = 1 : updated point from child(s)
+      !  = 0 : point not updated
+      ! 
+      tmask_upd(:,:) = 0._wp
+      umask_upd(:,:) = 0._wp
+      vmask_upd(:,:) = 0._wp
+#endif     
+      !
+   END SUBROUTINE dom_msk
+   
+   !!======================================================================
+END MODULE dommsk

+ 220 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icb_oce.F90

@@ -0,0 +1,220 @@
+MODULE icb_oce
+   !!======================================================================
+   !!                       ***  MODULE  icb_oce  ***
+   !! Icebergs:  declare variables for iceberg tracking
+   !!======================================================================
+   !! History :  3.3  !  2010-01  (T. Martin & A. Adcroft)  Original code
+   !!             -   !  2011-03  (G. Madec)  Part conversion to NEMO form
+   !!             -   !                       Removal of mapping from another grid
+   !!             -   !  2011-04  (S. Alderson) Extensive rewrite ; Split into separate modules
+   !!----------------------------------------------------------------------
+   !!
+   !! Track Icebergs as Lagrangian objects within the model domain
+   !! Interaction with the other model variables through 'icebergs_gridded'
+   !!
+   !! A single iceberg is held as an instance of type 'iceberg'
+   !! This type defines a linked list, so each instance contains a pointer 
+   !! to the previous and next icebergs in the list
+   !!
+   !! Type 'icebergs' is a convenience container for all relevant arrays
+   !! It contains one pointer to an 'iceberg' instance representing all icebergs in the processor
+   !!
+   !! Each iceberg has a position represented as a real cartesian coordinate which is 
+   !! fractional grid cell, centred on T-points; so an iceberg position of (1.0,1.0) lies 
+   !! exactly on the first T-point and the T-cell spans 0.5 to 1.5 in each direction
+   !!
+   !! Each iceberg is assigned a unique id even in MPI
+   !! This consists of an array of integers: the first element is used to label, the second
+   !! and subsequent elements are used to count the number of times the first element wraps
+   !! around all possible values within the valid size for this datatype.
+   !! Labelling is done by starting the first label in each processor (even when only one)
+   !! as narea, and then incrementing by jpnij (i.e. the total number of processors.
+   !! This means that the source processor for each iceberg can be identified by arithmetic
+   !! modulo jpnij.
+   !! 
+   !!----------------------------------------------------------------------
+   USE par_oce   ! ocean parameters
+   USE lib_mpp   ! MPP library
+
+   IMPLICIT NONE
+   PUBLIC
+
+   PUBLIC   icb_alloc   ! routine called by icb_init in icbini.F90 module
+
+   INTEGER, PUBLIC, PARAMETER ::   nclasses = 10   !: Number of icebergs classes   
+   INTEGER, PUBLIC, PARAMETER ::   nkounts  =  3   !: Number of integers combined for unique naming
+
+   TYPE, PUBLIC ::   icebergs_gridded   !: various icebergs properties on model grid
+      REAL(wp), DIMENSION(:,:)  , ALLOCATABLE ::   calving         ! Calving mass rate  (into stored ice)         [kg/s]
+      REAL(wp), DIMENSION(:,:)  , ALLOCATABLE ::   calving_hflx    ! Calving heat flux [heat content of calving]  [W/m2]
+      REAL(wp), DIMENSION(:,:)  , ALLOCATABLE ::   floating_melt   ! Net melting rate to icebergs + bits      [kg/s/m^2]
+      INTEGER , DIMENSION(:,:)  , ALLOCATABLE ::   maxclass        ! maximum class number at calving source point
+      REAL(wp), DIMENSION(:,:)  , ALLOCATABLE ::   tmp             ! Temporary work space
+      REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::   stored_ice      ! Accumulated ice mass flux at calving locations [kg]
+      REAL(wp), DIMENSION(:,:)  , ALLOCATABLE ::   stored_heat     ! Heat content of stored ice                      [J]
+   END TYPE icebergs_gridded
+
+   TYPE, PUBLIC ::   point              !: properties of an individual iceberg (position, mass, size, etc...)
+      INTEGER  ::   year
+      REAL(wp) ::   xi , yj , zk                                              ! iceberg coordinates in the (i,j) referential (global) and deepest level affected
+      REAL(wp) ::   e1 , e2                                                   ! horizontal scale factors at the iceberg position
+      REAL(wp) ::   lon, lat, day                                             ! geographic position
+      REAL(wp) ::   mass, thickness, width, length, uvel, vvel                ! iceberg physical properties
+      REAL(wp) ::   ssu, ssv, ui, vi, ua, va, ssh_x, ssh_y, sst, sss, cn, hi  ! properties of iceberg environment 
+      REAL(wp) ::   mass_of_bits, heat_density
+      INTEGER  ::   kb                                                   ! icb bottom level
+   END TYPE point
+
+   TYPE, PUBLIC ::   iceberg            !: linked list defining all the icebergs present in the model domain
+      TYPE(iceberg), POINTER      ::   prev=>NULL(), next=>NULL()   ! pointers to previous and next unique icebergs in linked list
+      INTEGER, DIMENSION(nkounts) ::   number                       ! variables which do not change for this iceberg
+      REAL(wp)                    ::   mass_scaling                 !    -        -            -                -  
+      TYPE(point), POINTER        ::   current_point => NULL()      ! variables which change with time are held in a separate type
+   END TYPE iceberg
+
+
+   TYPE(icebergs_gridded), POINTER ::   berg_grid                 !: master instance of gridded iceberg type
+   TYPE(iceberg)         , POINTER ::   first_berg => NULL()      !: master instance of linked list iceberg type
+
+   !                                                             !!! parameters controlling iceberg characteristics and modelling
+   REAL(wp)                            ::   berg_dt                   !: Time-step between iceberg CALLs (should make adaptive?)
+   REAL(wp), DIMENSION(:), ALLOCATABLE ::   first_width, first_length !: 
+   LOGICAL                             ::   l_restarted_bergs=.FALSE.  ! Indicate whether we read state from a restart or not
+   !                                                               ! arbitrary numbers for diawri entry
+   REAL(wp), DIMENSION(nclasses), PUBLIC ::   class_num=(/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /)
+
+   ! Extra arrays with bigger halo, needed when interpolating forcing onto iceberg position
+   ! particularly for MPP when iceberg can lie inside T grid but outside U, V, or f grid
+   REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE ::   ssu_e, ssv_e
+   REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE ::   sst_e, sss_e, fr_e
+   REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE ::   ua_e, va_e
+   REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE ::   ssh_e
+   REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE ::   tmask_e, umask_e, vmask_e
+   REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE ::   virtual_area, virtual_area_e
+   REAl(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE ::   rlon_e, rlat_e, ff_e
+   REAl(wp), PUBLIC, DIMENSION(:,:,:), ALLOCATABLE ::   uoce_e, voce_e, toce_e, e3t_e
+   !
+#if defined key_si3 || defined key_cice
+   REAL(wp), PUBLIC, DIMENSION(:,:), ALLOCATABLE ::   hi_e, ui_e, vi_e
+#endif
+
+   !!gm almost all those PARAM ARE defined in NEMO
+   REAL(wp), PUBLIC, PARAMETER :: pp_rho_ice      = 916.7_wp   !: Density of fresh ice   @ 0oC [kg/m^3]
+   REAL(wp), PUBLIC, PARAMETER :: pp_rho_water    = 999.8_wp   !: Density of fresh water @ 0oC [kg/m^3]
+   REAL(wp), PUBLIC, PARAMETER :: pp_rho_air      = 1.1_wp     !: Density of air         @ 0oC [kg/m^3]
+   REAL(wp), PUBLIC, PARAMETER :: pp_rho_seawater = 1025._wp   !: Approx. density of surface sea water @ 0oC [kg/m^3]
+   !!gm end
+   REAL(wp), PUBLIC, PARAMETER :: pp_Cd_av = 1.3_wp      !: (Vertical) Drag coefficient between bergs and atmos 
+   REAL(wp), PUBLIC, PARAMETER :: pp_Cd_ah = 0.0055_wp   !: (lateral ) Drag coefficient between bergs and atmos 
+   REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wv = 0.9_wp      !: (Vertical) Drag coefficient between bergs and ocean
+   REAL(wp), PUBLIC, PARAMETER :: pp_Cd_wh = 0.0012_wp   !: (lateral ) Drag coefficient between bergs and ocean 
+   REAL(wp), PUBLIC, PARAMETER :: pp_Cd_iv = 0.9_wp      !: (Vertical) Drag coefficient between bergs and sea-ice
+!TOM> no horizontal drag for sea ice! real, PARAMETER :: pp_Cd_ih=0.0012 ! (lateral) Drag coeff. between bergs and sea-ice
+
+   !                                                         !!* namberg namelist parameters (and defaults) **
+   LOGICAL , PUBLIC ::   ln_bergdia                      !: Calculate budgets
+   INTEGER , PUBLIC ::   nn_verbose_level                !: Turn on debugging when level > 0
+   INTEGER , PUBLIC ::   nn_test_icebergs                !: Create icebergs in absence of a restart file from the supplied class nb
+   REAL(wp), PUBLIC, DIMENSION(4) ::   rn_test_box       !: lon1,lon2,lat1,lat2 box to create them in
+   LOGICAL , PUBLIC ::   ln_use_calving                  !: Force use of calving data even with nn_test_icebergs > 0 
+                                                         !  (default is not to use calving data with test bergs)
+   INTEGER , PUBLIC ::   nn_sample_rate                  !: Timesteps between sampling of position for trajectory storage
+   INTEGER , PUBLIC ::   nn_verbose_write                !: timesteps between verbose messages
+   REAL(wp), PUBLIC ::   rn_rho_bergs                    !: Density of icebergs
+   REAL(wp), PUBLIC ::   rho_berg_1_oce                  !: convertion factor (thickness to draft) (rn_rho_bergs/pp_rho_seawater)
+   REAL(wp), PUBLIC ::   rn_LoW_ratio                    !: Initial ratio L/W for newly calved icebergs
+   REAL(wp), PUBLIC ::   rn_bits_erosion_fraction        !: Fraction of erosion melt flux to divert to bergy bits
+   REAL(wp), PUBLIC ::   rn_sicn_shift                   !: Shift of sea-ice concentration in erosion flux modulation (0<sicn_shift<1)
+   LOGICAL , PUBLIC ::   ln_operator_splitting           !: Use first order operator splitting for thermodynamics
+   LOGICAL , PUBLIC ::   ln_passive_mode                 !: iceberg - ocean decoupling
+   LOGICAL , PUBLIC ::   ln_time_average_weight          !: Time average the weight on the ocean    !!gm I don't understand that !
+   REAL(wp), PUBLIC ::   rn_speed_limit                  !: CFL speed limit for a berg
+   LOGICAL , PUBLIC ::   ln_M2016, ln_icb_grd            !: use Nacho's Merino 2016 work
+   LOGICAL , PUBLIC ::   ln_icb_area_mask                !: check icb total area in a cell in grounding scheme
+   !
+   ! restart
+   CHARACTER(len=256), PUBLIC :: cn_icbrst_indir , cn_icbrst_in  !:  in: restart directory, restart name
+   CHARACTER(len=256), PUBLIC :: cn_icbrst_outdir, cn_icbrst_out !: out: restart directory, restart name
+   !
+   !                                     ! Mass thresholds between iceberg classes [kg]
+   REAL(wp), DIMENSION(nclasses), PUBLIC ::   rn_initial_mass      ! Fraction of calving to apply to this class [non-dim]
+   REAL(wp), DIMENSION(nclasses), PUBLIC ::   rn_distribution      ! Ratio between effective and real iceberg mass (non-dim)
+   REAL(wp), DIMENSION(nclasses), PUBLIC ::   rn_mass_scaling      ! Total thickness of newly calved bergs [m]
+   REAL(wp), DIMENSION(nclasses), PUBLIC ::   rn_initial_thickness !  Single instance of an icebergs type initialised in icebergs_init and updated in icebergs_run
+   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)     ::   src_calving, src_calving_hflx    !: accumulate input ice
+   INTEGER , PUBLIC             , SAVE                     ::   micbkb                           !: deepest level affected by icebergs
+   INTEGER , PUBLIC             , SAVE                     ::   numicb                           !: iceberg IO
+   INTEGER , PUBLIC             , SAVE, DIMENSION(nkounts) ::   num_bergs                        !: iceberg counter
+   INTEGER , PUBLIC             , SAVE                     ::   nicbdi, nicbei, nicbdj, nicbej   !: processor bounds
+   REAL(wp), PUBLIC             , SAVE                     ::   ricb_left, ricb_right            !: cyclical bounds
+   INTEGER , PUBLIC             , SAVE                     ::   nicbpack                         !: packing integer
+   INTEGER , PUBLIC             , SAVE                     ::   nktberg, nknberg                 !: helpers
+   INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:)       ::   nicbfldpts                       !: nfold packed points
+   INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:)       ::   nicbflddest                      !: nfold destination proc
+   INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:)       ::   nicbfldproc                      !: nfold destination proc
+   INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:)       ::   nicbfldnsend                     !: nfold number of bergs to send to nfold neighbour
+   INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:)       ::   nicbfldexpect                    !: nfold expected number of bergs
+   INTEGER , PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:)       ::   nicbfldreq                       !: nfold message handle (immediate send)
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: icb_oce.F90 14030 2020-12-03 09:26:33Z mathiot $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+   
+   INTEGER FUNCTION icb_alloc()
+      !!----------------------------------------------------------------------
+      !!                ***  ROUTINE icb_alloc  ***
+      !!----------------------------------------------------------------------
+      INTEGER ::   ill
+      !!----------------------------------------------------------------------
+      !
+      icb_alloc = 0
+      ALLOCATE( berg_grid, STAT=ill )
+      icb_alloc = icb_alloc + ill
+      ALLOCATE( berg_grid%calving    (jpi,jpj) , berg_grid%calving_hflx (jpi,jpj)          ,   &
+         &      berg_grid%stored_heat(jpi,jpj) , berg_grid%floating_melt(jpi,jpj)          ,   &
+         &      berg_grid%maxclass   (jpi,jpj) , berg_grid%stored_ice   (jpi,jpj,nclasses) ,   &
+         &      berg_grid%tmp        (jpi,jpj) , STAT=ill)
+      icb_alloc = icb_alloc + ill
+      !
+      ! expanded arrays for bilinear interpolation
+      ALLOCATE( ssu_e(0:jpi+1,0:jpj+1) , ua_e(0:jpi+1,0:jpj+1) ,   &
+         &      ssv_e(0:jpi+1,0:jpj+1) , va_e(0:jpi+1,0:jpj+1) ,   &
+#if defined key_si3 || defined key_cice
+         &      ui_e(0:jpi+1,0:jpj+1) ,                            &
+         &      vi_e(0:jpi+1,0:jpj+1) ,                            &
+         &      hi_e(0:jpi+1,0:jpj+1) ,                            &
+#endif
+         &      fr_e(0:jpi+1,0:jpj+1) ,                            &
+         &      sst_e(0:jpi+1,0:jpj+1) , ssh_e(0:jpi+1,0:jpj+1) ,  &
+         &      sss_e(0:jpi+1,0:jpj+1) ,                           & 
+         &      first_width(nclasses) , first_length(nclasses) ,   &
+         &      src_calving (jpi,jpj) ,                            &
+         &      src_calving_hflx(jpi,jpj) , STAT=ill)
+      icb_alloc = icb_alloc + ill
+
+      IF ( ln_M2016 ) THEN
+         ALLOCATE( uoce_e(0:jpi+1,0:jpj+1,jpk), voce_e(0:jpi+1,0:jpj+1,jpk), &
+            &      toce_e(0:jpi+1,0:jpj+1,jpk), e3t_e(0:jpi+1,0:jpj+1,jpk) , STAT=ill )
+         icb_alloc = icb_alloc + ill
+      END IF
+      !
+      ALLOCATE( tmask_e(0:jpi+1,0:jpj+1), umask_e(0:jpi+1,0:jpj+1), vmask_e(0:jpi+1,0:jpj+1), &
+         &      rlon_e(0:jpi+1,0:jpj+1) , rlat_e(0:jpi+1,0:jpj+1) , ff_e(0:jpi+1,0:jpj+1)   , STAT=ill)
+      icb_alloc = icb_alloc + ill
+
+      ALLOCATE( nicbfldpts(jpi) , nicbflddest(jpi) , nicbfldproc(jpni) , &
+         &      nicbfldnsend(jpni), nicbfldexpect(jpni) , nicbfldreq(jpni), STAT=ill)
+      icb_alloc = icb_alloc + ill
+
+      ALLOCATE( virtual_area (jpi,jpj), virtual_area_e(0:jpi+1,0:jpj+1), STAT=ill   )
+      icb_alloc = icb_alloc + ill
+
+      CALL mpp_sum ( 'icb_oce', icb_alloc )
+      IF( icb_alloc > 0 )   CALL ctl_warn('icb_alloc: allocation of arrays failed')
+      !
+   END FUNCTION icb_alloc
+
+   !!======================================================================
+END MODULE icb_oce

+ 617 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbdia.F90

@@ -0,0 +1,617 @@
+MODULE icbdia
+   !!======================================================================
+   !!                       ***  MODULE  icbdia  ***
+   !! Icebergs:  initialise variables for iceberg budgets and diagnostics
+   !!======================================================================
+   !! History : 3.3 !  2010-01  (Martin, Adcroft) Original code
+   !!            -  !  2011-03  (Madec)          Part conversion to NEMO form
+   !!            -  !                            Removal of mapping from another grid
+   !!            -  !  2011-04  (Alderson)       Split into separate modules
+   !!            -  !  2011-05  (Alderson)       Budgets are now all here with lots
+   !!            -  !                            of silly routines to call to get values in
+   !!            -  !                            from the right points in the code
+   !!----------------------------------------------------------------------
+ 
+   !!----------------------------------------------------------------------
+   !!   icb_dia_init  : initialise iceberg budgeting
+   !!   icb_dia       : global iceberg diagnostics
+   !!   icb_dia_step  : reset at the beginning of each timestep
+   !!   icb_dia_put   : output (via iom_put) iceberg fields
+   !!   icb_dia_calve : 
+   !!   icb_dia_income: 
+   !!   icb_dia_size  : 
+   !!   icb_dia_speed : 
+   !!   icb_dia_melt  : 
+   !!   report_state  : 
+   !!   report_consistant : 
+   !!   report_budget : 
+   !!   report_istate : 
+   !!   report_ibudget: 
+   !!----------------------------------------------------------------------
+   USE par_oce        ! ocean parameters
+   USE dom_oce        ! ocean domain
+   USE in_out_manager ! nemo IO
+   USE lib_mpp        ! MPP library
+   USE iom            ! I/O library
+   USE icb_oce        ! iceberg variables
+   USE icbutl         ! iceberg utility routines
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   icb_dia_init      ! routine called in icbini.F90 module
+   PUBLIC   icb_dia           ! routine called in icbstp.F90 module
+   PUBLIC   icb_dia_step      ! routine called in icbstp.F90 module
+   PUBLIC   icb_dia_put       ! routine called in icbstp.F90 module
+   PUBLIC   icb_dia_melt      ! routine called in icbthm.F90 module
+   PUBLIC   icb_dia_size      ! routine called in icbthm.F90 module
+   PUBLIC   icb_dia_speed     ! routine called in icbdyn.F90 module
+   PUBLIC   icb_dia_calve     ! routine called in icbclv.F90 module
+   PUBLIC   icb_dia_income    ! routine called in icbclv.F90 module
+
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   berg_melt       ! Melting+erosion rate of icebergs     [kg/s/m2]
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   berg_melt_hcflx ! Heat flux to ocean due to heat content of melting icebergs [J/s/m2]
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   berg_melt_qlat  ! Heat flux to ocean due to latent heat of melting icebergs [J/s/m2]
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   buoy_melt       ! Buoyancy component of melting rate   [kg/s/m2]
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   eros_melt       ! Erosion component of melting rate    [kg/s/m2]
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   conv_melt       ! Convective component of melting rate [kg/s/m2]
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   bits_src        ! Mass flux from berg erosion into bergy bits [kg/s/m2]
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   bits_melt       ! Melting rate of bergy bits           [kg/s/m2]
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   bits_mass       ! Mass distribution of bergy bits      [kg/s/m2]
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, PUBLIC  ::   berg_mass       ! Mass distribution                    [kg/m2]
+   REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, PUBLIC  ::   real_calving    ! Calving rate into iceberg class at
+   !                                                                          ! calving locations                    [kg/s]
+   
+   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE ::   tmpc                     ! Temporary work space
+   REAL(wp), DIMENSION(:)    , ALLOCATABLE ::   rsumbuf                  ! Temporary work space to reduce mpp exchanges
+   INTEGER , DIMENSION(:)    , ALLOCATABLE ::   nsumbuf                  ! Temporary work space to reduce mpp exchanges
+
+   REAL(wp)                      ::  berg_melt_net
+   REAL(wp)                      ::  bits_src_net
+   REAL(wp)                      ::  bits_melt_net
+   REAL(wp)                      ::  bits_mass_start     , bits_mass_end
+   REAL(wp)                      ::  floating_heat_start , floating_heat_end
+   REAL(wp)                      ::  floating_mass_start , floating_mass_end
+   REAL(wp)                      ::  bergs_mass_start    , bergs_mass_end
+   REAL(wp)                      ::  stored_start        , stored_heat_start
+   REAL(wp)                      ::  stored_end          , stored_heat_end
+   REAL(wp)                      ::  calving_src_net     , calving_out_net
+   REAL(wp)                      ::  calving_src_heat_net, calving_out_heat_net
+   REAL(wp)                      ::  calving_src_heat_used_net
+   REAL(wp)                      ::  calving_rcv_net  , calving_ret_net  , calving_used_net
+   REAL(wp)                      ::  heat_to_bergs_net, heat_to_ocean_net, melt_net
+   REAL(wp)                      ::  calving_to_bergs_net
+
+   INTEGER                       ::  nbergs_start, nbergs_end, nbergs_calved
+   INTEGER                       ::  nbergs_melted
+   INTEGER                       ::  nspeeding_tickets, nspeeding_tickets_all
+   INTEGER , DIMENSION(nclasses) ::  nbergs_calved_by_class
+
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: icbdia.F90 14773 2021-04-30 10:23:51Z clem $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   SUBROUTINE icb_dia_init( )
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      !
+      IF( .NOT.ln_bergdia )   RETURN
+
+      ALLOCATE( berg_melt    (jpi,jpj)   )           ;   berg_melt   (:,:)   = 0._wp
+      ALLOCATE( berg_melt_hcflx(jpi,jpj) )           ;   berg_melt_hcflx(:,:)   = 0._wp
+      ALLOCATE( berg_melt_qlat(jpi,jpj)  )           ;   berg_melt_qlat(:,:)   = 0._wp
+      ALLOCATE( buoy_melt    (jpi,jpj)   )           ;   buoy_melt   (:,:)   = 0._wp
+      ALLOCATE( eros_melt    (jpi,jpj)   )           ;   eros_melt   (:,:)   = 0._wp
+      ALLOCATE( conv_melt    (jpi,jpj)   )           ;   conv_melt   (:,:)   = 0._wp
+      ALLOCATE( bits_src     (jpi,jpj)   )           ;   bits_src    (:,:)   = 0._wp
+      ALLOCATE( bits_melt    (jpi,jpj)   )           ;   bits_melt   (:,:)   = 0._wp
+      ALLOCATE( bits_mass    (jpi,jpj)   )           ;   bits_mass   (:,:)   = 0._wp
+      ALLOCATE( berg_mass    (jpi,jpj)   )           ;   berg_mass   (:,:)   = 0._wp
+      ALLOCATE( real_calving (jpi,jpj,nclasses) )    ;   real_calving(:,:,:) = 0._wp
+      ALLOCATE( tmpc(jpi,jpj) )                      ;   tmpc        (:,:)   = 0._wp
+
+      nbergs_start              = 0
+      nbergs_end                = 0
+      stored_end                = 0._wp
+      nbergs_start              = 0._wp
+      stored_start              = 0._wp
+      nbergs_melted             = 0
+      nbergs_calved             = 0
+      nbergs_calved_by_class(:) = 0
+      nspeeding_tickets         = 0
+      nspeeding_tickets_all     = 0
+      stored_heat_end           = 0._wp
+      floating_heat_end         = 0._wp
+      floating_mass_end         = 0._wp
+      bergs_mass_end            = 0._wp
+      bits_mass_end             = 0._wp
+      stored_heat_start         = 0._wp
+      floating_heat_start       = 0._wp
+      floating_mass_start       = 0._wp
+      bergs_mass_start          = 0._wp
+      bits_mass_start           = 0._wp
+      bits_mass_end             = 0._wp
+      calving_used_net          = 0._wp
+      calving_to_bergs_net      = 0._wp
+      heat_to_bergs_net         = 0._wp
+      heat_to_ocean_net         = 0._wp
+      calving_rcv_net           = 0._wp
+      calving_ret_net           = 0._wp
+      calving_src_net           = 0._wp
+      calving_out_net           = 0._wp
+      calving_src_heat_net      = 0._wp
+      calving_src_heat_used_net = 0._wp
+      calving_out_heat_net      = 0._wp
+      melt_net                  = 0._wp
+      berg_melt_net             = 0._wp
+      bits_melt_net             = 0._wp
+      bits_src_net              = 0._wp
+
+      floating_mass_start       = icb_utl_mass( first_berg )
+      bergs_mass_start          = icb_utl_mass( first_berg, justbergs=.TRUE. )
+      bits_mass_start           = icb_utl_mass( first_berg, justbits =.TRUE. )
+      IF( lk_mpp ) THEN
+         ALLOCATE( rsumbuf(23) )          ; rsumbuf(:) = 0._wp
+         ALLOCATE( nsumbuf(4+nclasses) )  ; nsumbuf(:) = 0
+         rsumbuf(1) = floating_mass_start
+         rsumbuf(2) = bergs_mass_start
+         rsumbuf(3) = bits_mass_start
+         CALL mpp_sum( 'icbdia', rsumbuf(1:3), 3 )
+         floating_mass_start = rsumbuf(1)
+         bergs_mass_start = rsumbuf(2)
+         bits_mass_start = rsumbuf(3)
+      ENDIF
+      !
+   END SUBROUTINE icb_dia_init
+
+
+   SUBROUTINE icb_dia( ld_budge )
+      !!----------------------------------------------------------------------
+      !! sum all the things we've accumulated so far in the current processor
+      !! in MPP case then add these sums across all processors
+      !! for this we pack variables into buffer so we only need one mpp_sum
+      !!----------------------------------------------------------------------
+      LOGICAL, INTENT(in) ::   ld_budge   !
+      !
+      INTEGER ::   ik
+      REAL(wp)::   zunused_calving, ztmpsum, zgrdd_berg_mass, zgrdd_bits_mass
+      !!----------------------------------------------------------------------
+      !
+      IF( .NOT.ln_bergdia )   RETURN
+
+      zunused_calving      = SUM( berg_grid%calving(:,:) )
+      ztmpsum              = SUM( berg_grid%floating_melt(:,:) * e1e2t(:,:) * tmask_i(:,:) )
+      melt_net             = melt_net + ztmpsum * berg_dt
+      calving_out_net      = calving_out_net + ( zunused_calving + ztmpsum ) * berg_dt
+      ztmpsum              = SUM( berg_melt(:,:) * e1e2t(:,:) * tmask_i(:,:) )
+      berg_melt_net        = berg_melt_net + ztmpsum * berg_dt
+      ztmpsum              = SUM( bits_src(:,:) * e1e2t(:,:) * tmask_i(:,:) )
+      bits_src_net         = bits_src_net + ztmpsum * berg_dt
+      ztmpsum              = SUM( bits_melt(:,:) * e1e2t(:,:) * tmask_i(:,:) )
+      bits_melt_net        = bits_melt_net + ztmpsum * berg_dt
+      ztmpsum              = SUM( src_calving(:,:) * tmask_i(:,:) )
+      calving_ret_net      = calving_ret_net + ztmpsum * berg_dt
+      ztmpsum              = SUM( berg_grid%calving_hflx(:,:) * e1e2t(:,:) * tmask_i(:,:) )
+      calving_out_heat_net = calving_out_heat_net + ztmpsum * berg_dt   ! Units of J
+      !
+      IF( ld_budge ) THEN
+         stored_end        = SUM( berg_grid%stored_ice(:,:,:) )
+         stored_heat_end   = SUM( berg_grid%stored_heat(:,:) )
+         floating_mass_end = icb_utl_mass( first_berg )
+         bergs_mass_end    = icb_utl_mass( first_berg,justbergs=.TRUE. )
+         bits_mass_end     = icb_utl_mass( first_berg,justbits =.TRUE. )
+         floating_heat_end = icb_utl_heat( first_berg )
+         !
+         nbergs_end        = icb_utl_count()
+         zgrdd_berg_mass   = SUM( berg_mass(:,:)*e1e2t(:,:)*tmask_i(:,:) )
+         zgrdd_bits_mass   = SUM( bits_mass(:,:)*e1e2t(:,:)*tmask_i(:,:) )
+         !
+         IF( lk_mpp ) THEN
+            rsumbuf( 1) = stored_end
+            rsumbuf( 2) = stored_heat_end
+            rsumbuf( 3) = floating_mass_end
+            rsumbuf( 4) = bergs_mass_end
+            rsumbuf( 5) = bits_mass_end
+            rsumbuf( 6) = floating_heat_end
+            rsumbuf( 7) = calving_ret_net
+            rsumbuf( 8) = calving_out_net
+            rsumbuf( 9) = calving_rcv_net
+            rsumbuf(10) = calving_src_net
+            rsumbuf(11) = calving_src_heat_net
+            rsumbuf(12) = calving_src_heat_used_net
+            rsumbuf(13) = calving_out_heat_net
+            rsumbuf(14) = calving_used_net
+            rsumbuf(15) = calving_to_bergs_net
+            rsumbuf(16) = heat_to_bergs_net
+            rsumbuf(17) = heat_to_ocean_net
+            rsumbuf(18) = melt_net
+            rsumbuf(19) = berg_melt_net
+            rsumbuf(20) = bits_src_net
+            rsumbuf(21) = bits_melt_net
+            rsumbuf(22) = zgrdd_berg_mass
+            rsumbuf(23) = zgrdd_bits_mass
+            !
+            CALL mpp_sum( 'icbdia', rsumbuf(1:23), 23)
+            !
+            stored_end                = rsumbuf( 1)
+            stored_heat_end           = rsumbuf( 2)
+            floating_mass_end         = rsumbuf( 3)
+            bergs_mass_end            = rsumbuf( 4)
+            bits_mass_end             = rsumbuf( 5)
+            floating_heat_end         = rsumbuf( 6)
+            calving_ret_net           = rsumbuf( 7)
+            calving_out_net           = rsumbuf( 8)
+            calving_rcv_net           = rsumbuf( 9)
+            calving_src_net           = rsumbuf(10)
+            calving_src_heat_net      = rsumbuf(11)
+            calving_src_heat_used_net = rsumbuf(12)
+            calving_out_heat_net      = rsumbuf(13)
+            calving_used_net          = rsumbuf(14)
+            calving_to_bergs_net      = rsumbuf(15)
+            heat_to_bergs_net         = rsumbuf(16)
+            heat_to_ocean_net         = rsumbuf(17)
+            melt_net                  = rsumbuf(18)
+            berg_melt_net             = rsumbuf(19)
+            bits_src_net              = rsumbuf(20)
+            bits_melt_net             = rsumbuf(21)
+            zgrdd_berg_mass           = rsumbuf(22)
+            zgrdd_bits_mass           = rsumbuf(23)
+            !
+            nsumbuf(1) = nbergs_end
+            nsumbuf(2) = nbergs_calved
+            nsumbuf(3) = nbergs_melted
+            nsumbuf(4) = nspeeding_tickets
+            DO ik = 1, nclasses
+               nsumbuf(4+ik) = nbergs_calved_by_class(ik)
+            END DO
+            CALL mpp_sum( 'icbdia', nsumbuf(1:nclasses+4), nclasses+4 )
+            !
+            nbergs_end            = nsumbuf(1)
+            nbergs_calved         = nsumbuf(2)
+            nbergs_melted         = nsumbuf(3)
+            nspeeding_tickets_all = nsumbuf(4)
+            DO ik = 1,nclasses
+               nbergs_calved_by_class(ik)= nsumbuf(4+ik)
+            END DO
+            !
+         ENDIF
+         !
+         CALL report_state  ( 'stored ice','kg','',stored_start,'',stored_end,'')
+         CALL report_state  ( 'floating','kg','',floating_mass_start,'',floating_mass_end,'',nbergs_end )
+         CALL report_state  ( 'icebergs','kg','',bergs_mass_start,'',bergs_mass_end,'')
+         CALL report_state  ( 'bits','kg','',bits_mass_start,'',bits_mass_end,'')
+         CALL report_istate ( 'berg #','',nbergs_start,'',nbergs_end,'')
+         CALL report_ibudget( 'berg #','calved',nbergs_calved, &
+            &                          'melted',nbergs_melted, &
+            &                          '#',nbergs_start,nbergs_end)
+         CALL report_budget( 'stored mass','kg','calving used',calving_used_net, &
+            &                              'bergs',calving_to_bergs_net, &
+            &                              'stored mass',stored_start,stored_end)
+         CALL report_budget( 'floating mass','kg','calving used',calving_to_bergs_net, &
+            &                                'bergs',melt_net, &
+            &                                'stored mass',floating_mass_start,floating_mass_end)
+         CALL report_budget( 'berg mass','kg','calving',calving_to_bergs_net, &
+            &                                 'melt+eros',berg_melt_net, &
+            &                                 'berg mass',bergs_mass_start,bergs_mass_end)
+         CALL report_budget( 'bits mass','kg','eros used',bits_src_net, &
+            &                                 'bergs',bits_melt_net, &
+            &                                 'stored mass',bits_mass_start,bits_mass_end)
+         CALL report_budget( 'net mass','kg','recvd',calving_rcv_net, &
+            &                                'rtrnd',calving_ret_net, &
+            &                                'net mass',stored_start+floating_mass_start, &
+            &                                           stored_end+floating_mass_end)
+         CALL report_consistant( 'iceberg mass','kg','gridded',zgrdd_berg_mass,'bergs',bergs_mass_end)
+         CALL report_consistant( 'bits mass','kg','gridded',zgrdd_bits_mass,'bits',bits_mass_end)
+         CALL report_state( 'net heat','J','',stored_heat_start+floating_heat_start,'', &
+            &                                 stored_heat_end+floating_heat_end,'')
+         CALL report_state( 'stored heat','J','',stored_heat_start,'',stored_heat_end,'')
+         CALL report_state( 'floating heat','J','',floating_heat_start,'',floating_heat_end,'')
+         CALL report_budget( 'net heat','J','net heat',calving_src_heat_net, &
+            &                               'net heat',calving_out_heat_net, &
+            &                               'net heat',stored_heat_start+floating_heat_start, &
+            &                                          stored_heat_end+floating_heat_end)
+         CALL report_budget( 'stored heat','J','calving used',calving_src_heat_used_net, &
+            &                                  'bergs',heat_to_bergs_net, &
+            &                                  'net heat',stored_heat_start,stored_heat_end)
+         CALL report_budget( 'flting heat','J','calved',heat_to_bergs_net, &
+            &                                  'melt',heat_to_ocean_net, &
+            &                                  'net heat',floating_heat_start,floating_heat_end)
+         IF (nn_verbose_level >= 1) THEN
+            CALL report_consistant( 'top interface','kg','from SIS',calving_src_net, &
+               &                    'received',calving_rcv_net)
+            CALL report_consistant( 'bot interface','kg','sent',calving_out_net, &
+               &                    'returned',calving_ret_net)
+         ENDIF
+         IF (nn_verbose_level > 0) THEN
+            WRITE( numicb, '("calved by class = ",i6,20(",",i6))') (nbergs_calved_by_class(ik),ik=1,nclasses)
+            IF( nspeeding_tickets_all > 0 ) THEN
+                WRITE( numicb, '("speeding tickets issued (this domain)  = ",i6)') nspeeding_tickets
+                WRITE( numicb, '("speeding tickets issued (all domains)  = ",i6)') nspeeding_tickets_all
+            END IF
+         ENDIF
+         !
+         nbergs_start              = nbergs_end
+         stored_start              = stored_end
+         nbergs_melted             = 0
+         nbergs_calved             = 0
+         nbergs_calved_by_class(:) = 0
+         nspeeding_tickets         = 0
+         nspeeding_tickets_all     = 0
+         stored_heat_start         = stored_heat_end
+         floating_heat_start       = floating_heat_end
+         floating_mass_start       = floating_mass_end
+         bergs_mass_start          = bergs_mass_end
+         bits_mass_start           = bits_mass_end
+         calving_used_net          = 0._wp
+         calving_to_bergs_net      = 0._wp
+         heat_to_bergs_net         = 0._wp
+         heat_to_ocean_net         = 0._wp
+         calving_rcv_net           = 0._wp
+         calving_ret_net           = 0._wp
+         calving_src_net           = 0._wp
+         calving_out_net           = 0._wp
+         calving_src_heat_net      = 0._wp
+         calving_src_heat_used_net = 0._wp
+         calving_out_heat_net      = 0._wp
+         melt_net                  = 0._wp
+         berg_melt_net             = 0._wp
+         bits_melt_net             = 0._wp
+         bits_src_net              = 0._wp
+      ENDIF
+      !
+   END SUBROUTINE icb_dia
+
+
+   SUBROUTINE icb_dia_step
+      !!----------------------------------------------------------------------
+      !! things to reset at the beginning of each timestep
+      !!----------------------------------------------------------------------
+      !
+      IF( .NOT.ln_bergdia )   RETURN
+      berg_melt   (:,:)   = 0._wp
+      berg_melt_hcflx(:,:)   = 0._wp
+      berg_melt_qlat(:,:)   = 0._wp
+      buoy_melt   (:,:)   = 0._wp
+      eros_melt   (:,:)   = 0._wp
+      conv_melt   (:,:)   = 0._wp
+      bits_src    (:,:)   = 0._wp
+      bits_melt   (:,:)   = 0._wp
+      bits_mass   (:,:)   = 0._wp
+      berg_mass   (:,:)   = 0._wp
+      real_calving(:,:,:) = 0._wp
+      !
+   END SUBROUTINE icb_dia_step
+
+
+   SUBROUTINE icb_dia_put
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      !
+      IF( .NOT.ln_bergdia )   RETURN            !!gm useless iom will control whether it is output or not
+      !
+      CALL iom_put( "berg_melt"        , berg_melt   (:,:)   )   ! Melt rate of icebergs                     [kg/m2/s]
+      !! NB. The berg_melt_hcflx field is currently always zero - see comment in icbthm.F90
+      CALL iom_put( "berg_melt_hcflx"  , berg_melt_hcflx(:,:))   ! Heat flux to ocean due to heat content of melting icebergs [J/m2/s]
+      CALL iom_put( "berg_melt_qlat"   , berg_melt_qlat(:,:) )   ! Heat flux to ocean due to latent heat of melting icebergs [J/m2/s]
+      CALL iom_put( "berg_buoy_melt"   , buoy_melt   (:,:)   )   ! Buoyancy component of iceberg melt rate   [kg/m2/s]
+      CALL iom_put( "berg_eros_melt"   , eros_melt   (:,:)   )   ! Erosion component of iceberg melt rate    [kg/m2/s]
+      CALL iom_put( "berg_conv_melt"   , conv_melt   (:,:)   )   ! Convective component of iceberg melt rate [kg/m2/s]
+      CALL iom_put( "berg_virtual_area", virtual_area(:,:)   )   ! Virtual coverage by icebergs              [m2]
+      CALL iom_put( "bits_src"         , bits_src    (:,:)   )   ! Mass source of bergy bits                 [kg/m2/s]
+      CALL iom_put( "bits_melt"        , bits_melt   (:,:)   )   ! Melt rate of bergy bits                   [kg/m2/s]
+      CALL iom_put( "bits_mass"        , bits_mass   (:,:)   )   ! Bergy bit density field                   [kg/m2]
+      CALL iom_put( "berg_mass"        , berg_mass   (:,:)   )   ! Iceberg density field                     [kg/m2]
+      CALL iom_put( "berg_real_calving", real_calving(:,:,:) )   ! Calving into iceberg class                [kg/s]
+      !
+   END SUBROUTINE icb_dia_put
+
+
+   SUBROUTINE icb_dia_calve( ki, kj, kn, pcalved, pheated )
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      INTEGER , INTENT(in)  ::   ki, kj, kn
+      REAL(wp), INTENT(in)  ::   pcalved
+      REAL(wp), INTENT(in)  ::   pheated
+      !!----------------------------------------------------------------------
+      !
+      IF( .NOT. ln_bergdia ) RETURN
+      real_calving(ki,kj,kn)     = real_calving(ki,kj,kn) + pcalved / berg_dt
+      nbergs_calved              = nbergs_calved              + 1
+      nbergs_calved_by_class(kn) = nbergs_calved_by_class(kn) + 1
+      calving_to_bergs_net       = calving_to_bergs_net + pcalved
+      heat_to_bergs_net          = heat_to_bergs_net    + pheated
+      !
+   END SUBROUTINE icb_dia_calve
+
+
+   SUBROUTINE icb_dia_income( kt,  pcalving_used, pheat_used )
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      INTEGER ,                 INTENT(in)  :: kt
+      REAL(wp),                 INTENT(in)  :: pcalving_used
+      REAL(wp), DIMENSION(:,:), INTENT(in)  :: pheat_used
+      !!----------------------------------------------------------------------
+      !
+      IF( .NOT.ln_bergdia )   RETURN
+      !
+      IF( kt == nit000 ) THEN
+         stored_start = SUM( berg_grid%stored_ice(:,:,:) )
+         CALL mpp_sum( 'icbdia', stored_start )
+         !
+         stored_heat_start = SUM( berg_grid%stored_heat(:,:) )
+         CALL mpp_sum( 'icbdia', stored_heat_start )
+         IF (nn_verbose_level > 0) THEN
+            WRITE(numicb,'(a,es13.6,a)')   'icb_dia_income: initial stored mass=',stored_start,' kg'
+            WRITE(numicb,'(a,es13.6,a)')   'icb_dia_income: initial stored heat=',stored_heat_start,' J'
+         ENDIF
+      ENDIF
+      !
+      calving_rcv_net = calving_rcv_net + SUM( berg_grid%calving(:,:) ) * berg_dt
+      calving_src_net = calving_rcv_net
+      calving_src_heat_net = calving_src_heat_net +  &
+         &                      SUM( berg_grid%calving_hflx(:,:) * e1e2t(:,:) ) * berg_dt   ! Units of J
+      calving_used_net = calving_used_net + pcalving_used * berg_dt
+      calving_src_heat_used_net = calving_src_heat_used_net + SUM( pheat_used(:,:) )
+      !
+   END SUBROUTINE icb_dia_income
+
+
+   SUBROUTINE icb_dia_size(ki, kj, pWn, pLn, pAbits,   &
+      &                    pmass_scale, pMnew, pnMbits, pz1_e1e2)
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      INTEGER , INTENT(in) ::   ki, kj
+      REAL(wp), INTENT(in) ::   pWn, pLn, pAbits, pmass_scale, pMnew, pnMbits, pz1_e1e2
+      !!----------------------------------------------------------------------
+      !
+      IF( .NOT.ln_bergdia )   RETURN
+      berg_mass(ki,kj)    = berg_mass(ki,kj) + pMnew * pz1_e1e2                             ! kg/m2
+      bits_mass(ki,kj)    = bits_mass(ki,kj) + pnMbits * pz1_e1e2                           ! kg/m2
+      !
+   END SUBROUTINE icb_dia_size
+
+
+   SUBROUTINE icb_dia_speed()
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      !
+      IF( .NOT.ln_bergdia )   RETURN
+      nspeeding_tickets = nspeeding_tickets + 1
+      !
+   END SUBROUTINE icb_dia_speed
+
+
+   SUBROUTINE icb_dia_melt(ki, kj, pmnew, pheat_hcflux, pheat_latent, pmass_scale,     &
+      &                    pdM, pdMbitsE, pdMbitsM, pdMb, pdMe,   &
+      &                    pdMv, pz1_dt_e1e2, pz1_e1e2 )
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      INTEGER , INTENT(in) ::   ki, kj
+      REAL(wp), INTENT(in) ::   pmnew, pheat_hcflux, pheat_latent, pmass_scale
+      REAL(wp), INTENT(in) ::   pdM, pdMbitsE, pdMbitsM, pdMb, pdMe, pdMv, pz1_dt_e1e2, pz1_e1e2
+      !!----------------------------------------------------------------------
+      !
+      IF( .NOT.ln_bergdia )   RETURN
+      !
+      berg_melt (ki,kj) = berg_melt (ki,kj) + pdM      * pz1_dt_e1e2   ! kg/m2/s
+      berg_melt_hcflx (ki,kj) = berg_melt_hcflx (ki,kj) + pheat_hcflux * pz1_e1e2   ! W/m2
+      berg_melt_qlat (ki,kj) = berg_melt_qlat (ki,kj) + pheat_latent * pz1_e1e2   ! W/m2
+      bits_src  (ki,kj) = bits_src  (ki,kj) + pdMbitsE * pz1_dt_e1e2   ! mass flux into bergy bitskg/m2/s
+      bits_melt (ki,kj) = bits_melt (ki,kj) + pdMbitsM * pz1_dt_e1e2   ! melt rate of bergy bits kg/m2/s
+      buoy_melt (ki,kj) = buoy_melt (ki,kj) + pdMb     * pz1_dt_e1e2   ! kg/m2/s
+      eros_melt (ki,kj) = eros_melt (ki,kj) + pdMe     * pz1_dt_e1e2   ! erosion rate kg/m2/s
+      conv_melt (ki,kj) = conv_melt (ki,kj) + pdMv     * pz1_dt_e1e2   ! kg/m2/s
+      heat_to_ocean_net = heat_to_ocean_net + (pheat_hcflux + pheat_latent) * pmass_scale * berg_dt         ! J
+      IF( pmnew <= 0._wp ) nbergs_melted = nbergs_melted + 1                        ! Delete the berg if completely melted
+      !
+   END SUBROUTINE icb_dia_melt
+
+
+   SUBROUTINE report_state( cd_budgetstr, cd_budgetunits, cd_startstr, pstartval, cd_endstr,   &
+      &                     pendval, cd_delstr, kbergs )
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      CHARACTER*(*), INTENT(in)           :: cd_budgetstr, cd_budgetunits, cd_startstr, cd_endstr, cd_delstr
+      REAL(wp),      INTENT(in)           :: pstartval, pendval
+      INTEGER,       INTENT(in), OPTIONAL :: kbergs
+      !!----------------------------------------------------------------------
+      !
+      IF (nn_verbose_level == 0) RETURN
+      IF( PRESENT(kbergs) ) THEN
+         WRITE(numicb,100) cd_budgetstr // ' state:',                                    &
+            &              cd_startstr  // ' start',  pstartval,         cd_budgetunits, &
+            &              cd_endstr    // ' end',    pendval,           cd_budgetunits, &
+            &              'Delta '     // cd_delstr, pendval-pstartval, cd_budgetunits, &
+            &              '# of bergs', kbergs
+      ELSE
+         WRITE(numicb,100) cd_budgetstr // ' state:',                                   &
+            &              cd_startstr  // ' start', pstartval,         cd_budgetunits, &
+            &              cd_endstr    // ' end',   pendval,           cd_budgetunits, &
+            &              cd_delstr    // 'Delta',  pendval-pstartval, cd_budgetunits
+      ENDIF
+100   FORMAT(a19,3(a18,"=",es14.7,x,a2,:,","),a12,i8)
+      !
+   END SUBROUTINE report_state
+
+
+   SUBROUTINE report_consistant( cd_budgetstr, cd_budgetunits, cd_startstr, pstartval, cd_endstr, pendval)
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      CHARACTER*(*), INTENT(in) :: cd_budgetstr, cd_budgetunits, cd_startstr, cd_endstr
+      REAL(wp),      INTENT(in) :: pstartval, pendval
+      !!----------------------------------------------------------------------
+      !
+      IF (nn_verbose_level == 0) RETURN
+      WRITE(numicb,200) cd_budgetstr // ' check:',                 &
+         &              cd_startstr,    pstartval, cd_budgetunits, &
+         &              cd_endstr,      pendval,   cd_budgetunits, &
+         &              'error',        (pendval-pstartval)/((pendval+pstartval)+1e-30), 'nd'
+200   FORMAT(a19,10(a18,"=",es14.7,x,a2,:,","))
+      !
+   END SUBROUTINE report_consistant
+
+
+   SUBROUTINE report_budget( cd_budgetstr, cd_budgetunits, cd_instr, pinval, cd_outstr,   &
+      &                      poutval, cd_delstr, pstartval, pendval)
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      CHARACTER*(*), INTENT(in) :: cd_budgetstr, cd_budgetunits, cd_instr, cd_outstr, cd_delstr
+      REAL(wp),      INTENT(in) :: pinval, poutval, pstartval, pendval
+      !
+      REAL(wp) ::   zval
+      !!----------------------------------------------------------------------
+      !
+      IF (nn_verbose_level == 0) RETURN
+      zval = ( ( pendval - pstartval ) - ( pinval - poutval ) ) /   &
+         &   MAX( 1.e-30, MAX( ABS( pendval - pstartval ) , ABS( pinval - poutval ) ) )
+         !
+      WRITE(numicb,200) cd_budgetstr // ' budget:', &
+         &              cd_instr     // ' in',      pinval,         cd_budgetunits, &
+         &              cd_outstr    // ' out',     poutval,        cd_budgetunits, &
+         &              'Delta '     // cd_delstr,  pinval-poutval, cd_budgetunits, &
+         &              'error',        zval,                       'nd'
+  200 FORMAT(a19,3(a18,"=",es14.7,x,a2,:,","),a8,"=",es10.3,x,a2)
+      !
+   END SUBROUTINE report_budget
+
+
+   SUBROUTINE report_istate( cd_budgetstr, cd_startstr, pstartval, cd_endstr, pendval, cd_delstr)
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      CHARACTER*(*), INTENT(in) ::   cd_budgetstr, cd_startstr, cd_endstr, cd_delstr
+      INTEGER      , INTENT(in) ::   pstartval, pendval
+      !!----------------------------------------------------------------------
+      !
+      IF (nn_verbose_level == 0) RETURN
+      WRITE(numicb,100) cd_budgetstr // ' state:',           &
+         &              cd_startstr  // ' start', pstartval, &
+         &              cd_endstr    // ' end',   pendval,   &
+         &              cd_delstr    // 'Delta',  pendval-pstartval
+  100 FORMAT(a19,3(a18,"=",i14,x,:,","))
+      !
+   END SUBROUTINE report_istate
+
+
+   SUBROUTINE report_ibudget( cd_budgetstr, cd_instr, pinval, cd_outstr, poutval,   &
+      &                       cd_delstr, pstartval, pendval)
+      !!----------------------------------------------------------------------
+      !!----------------------------------------------------------------------
+      CHARACTER*(*), INTENT(in) :: cd_budgetstr, cd_instr, cd_outstr, cd_delstr
+      INTEGER,       INTENT(in) :: pinval, poutval, pstartval, pendval
+      !!----------------------------------------------------------------------
+      !
+      IF (nn_verbose_level == 0) RETURN
+      WRITE(numicb,200) cd_budgetstr // ' budget:', &
+         &              cd_instr     // ' in',      pinval, &
+         &              cd_outstr    // ' out',     poutval, &
+         &              'Delta '     // cd_delstr,  pinval-poutval, &
+         &              'error',                    ( ( pendval - pstartval ) - ( pinval - poutval ) )
+200   FORMAT(a19,10(a18,"=",i14,x,:,","))
+      !
+   END SUBROUTINE report_ibudget
+
+   !!======================================================================
+END MODULE icbdia

+ 450 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbdyn.F90

@@ -0,0 +1,450 @@
+MODULE icbdyn
+   !!======================================================================
+   !!                       ***  MODULE  icbdyn  ***
+   !! Iceberg:  time stepping routine for iceberg tracking
+   !!======================================================================
+   !! History :  3.3  !  2010-01  (Martin&Adcroft)  Original code
+   !!             -   !  2011-03  (Madec)  Part conversion to NEMO form
+   !!             -   !                    Removal of mapping from another grid
+   !!             -   !  2011-04  (Alderson)  Split into separate modules
+   !!             -   !  2011-05  (Alderson)  Replace broken grounding routine with one of
+   !!             -   !                       Gurvan's suggestions (just like the broken one)
+   !!----------------------------------------------------------------------
+   USE par_oce        ! NEMO parameters
+   USE dom_oce        ! NEMO ocean domain
+   USE phycst         ! NEMO physical constants
+   USE in_out_manager                      ! IO parameters
+   !
+   USE icb_oce        ! define iceberg arrays
+   USE icbutl         ! iceberg utility routines
+   USE icbdia         ! iceberg budget routines
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   icb_dyn  ! routine called in icbstp.F90 module
+
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: icbdyn.F90 15088 2021-07-06 13:03:34Z acc $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   SUBROUTINE icb_dyn( kt )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE icb_dyn  ***
+      !!
+      !! ** Purpose :   iceberg evolution.
+      !!
+      !! ** Method  : - See Martin & Adcroft, Ocean Modelling 34, 2010
+      !!----------------------------------------------------------------------
+      INTEGER, INTENT(in) ::   kt   !
+      !
+      LOGICAL  ::   ll_bounced
+      REAL(wp) ::   zuvel1 , zvvel1 , zu1, zv1, zax1, zay1, zxi1 , zyj1
+      REAL(wp) ::   zuvel2 , zvvel2 , zu2, zv2, zax2, zay2, zxi2 , zyj2
+      REAL(wp) ::   zuvel3 , zvvel3 , zu3, zv3, zax3, zay3, zxi3 , zyj3
+      REAL(wp) ::   zuvel4 , zvvel4 , zu4, zv4, zax4, zay4, zxi4 , zyj4
+      REAL(wp) ::   zuvel_n, zvvel_n, zxi_n   , zyj_n
+      REAL(wp) ::   zdt, zdt_2, zdt_6, ze1, ze2
+      TYPE(iceberg), POINTER ::   berg
+      TYPE(point)  , POINTER ::   pt
+      !!----------------------------------------------------------------------
+      !
+      ! 4th order Runge-Kutta to solve:   d/dt X = V,  d/dt V = A
+      !                    with I.C.'s:   X=X1 and V=V1
+      !
+      !                                    ; A1=A(X1,V1)
+      !  X2 = X1+dt/2*V1 ; V2 = V1+dt/2*A1 ; A2=A(X2,V2)
+      !  X3 = X1+dt/2*V2 ; V3 = V1+dt/2*A2 ; A3=A(X3,V3)
+      !  X4 = X1+  dt*V3 ; V4 = V1+  dt*A3 ; A4=A(X4,V4)
+      !
+      !  Xn = X1+dt*(V1+2*V2+2*V3+V4)/6
+      !  Vn = V1+dt*(A1+2*A2+2*A3+A4)/6
+
+      ! time steps
+      zdt   = berg_dt
+      zdt_2 = zdt * 0.5_wp
+      zdt_6 = zdt / 6._wp
+
+      berg => first_berg                    ! start from the first berg
+      !
+      DO WHILE ( ASSOCIATED(berg) )          !==  loop over all bergs  ==!
+         !
+         pt => berg%current_point
+
+         ll_bounced = .FALSE.
+
+
+         ! STEP 1 !
+         ! ====== !
+         zxi1 = pt%xi   ;   zuvel1 = pt%uvel     !**   X1 in (i,j)  ;  V1 in m/s
+         zyj1 = pt%yj   ;   zvvel1 = pt%vvel
+
+
+         !                                         !**   A1 = A(X1,V1)
+         CALL icb_accel( kt, berg , zxi1, ze1, zuvel1, zuvel1, zax1,     &
+            &                   zyj1, ze2, zvvel1, zvvel1, zay1, zdt_2, 0.5_wp )
+         !
+         zu1 = zuvel1 / ze1                           !**   V1 in d(i,j)/dt
+         zv1 = zvvel1 / ze2
+
+         ! STEP 2 !
+         ! ====== !
+         !                                         !**   X2 = X1+dt/2*V1   ;   V2 = V1+dt/2*A1
+         ! position using di/dt & djdt   !   V2  in m/s
+         zxi2 = zxi1 + zdt_2 * zu1          ;   zuvel2 = zuvel1 + zdt_2 * zax1
+         zyj2 = zyj1 + zdt_2 * zv1          ;   zvvel2 = zvvel1 + zdt_2 * zay1
+         !
+         CALL icb_ground( berg, zxi2, zxi1, zu1,   &
+            &                   zyj2, zyj1, zv1, ll_bounced )
+
+         !                                         !**   A2 = A(X2,V2)
+         CALL icb_accel( kt, berg , zxi2, ze1, zuvel2, zuvel1, zax2,    &
+            &                   zyj2, ze2, zvvel2, zvvel1, zay2, zdt_2, 0.5_wp )
+         !
+         zu2 = zuvel2 / ze1                           !**   V2 in d(i,j)/dt
+         zv2 = zvvel2 / ze2
+         !
+         ! STEP 3 !
+         ! ====== !
+         !                                         !**  X3 = X1+dt/2*V2  ;   V3 = V1+dt/2*A2; A3=A(X3)
+         zxi3  = zxi1  + zdt_2 * zu2   ;   zuvel3 = zuvel1 + zdt_2 * zax2
+         zyj3  = zyj1  + zdt_2 * zv2   ;   zvvel3 = zvvel1 + zdt_2 * zay2
+         !
+         CALL icb_ground( berg, zxi3, zxi1, zu2,   &
+            &                   zyj3, zyj1, zv2, ll_bounced )
+
+         !                                         !**   A3 = A(X3,V3)
+         CALL icb_accel( kt, berg , zxi3, ze1, zuvel3, zuvel1, zax3,    &
+            &                   zyj3, ze2, zvvel3, zvvel1, zay3, zdt, 1._wp )
+         !
+         zu3 = zuvel3 / ze1                           !**   V3 in d(i,j)/dt
+         zv3 = zvvel3 / ze2
+
+         ! STEP 4 !
+         ! ====== !
+         !                                         !**   X4 = X1+dt*V3   ;   V4 = V1+dt*A3
+         zxi4 = zxi1 + zdt * zu3   ;   zuvel4 = zuvel1 + zdt * zax3
+         zyj4 = zyj1 + zdt * zv3   ;   zvvel4 = zvvel1 + zdt * zay3
+
+         CALL icb_ground( berg, zxi4, zxi1, zu3,   &
+            &                   zyj4, zyj1, zv3, ll_bounced )
+
+         !                                         !**   A4 = A(X4,V4)
+         CALL icb_accel( kt, berg , zxi4, ze1, zuvel4, zuvel1, zax4,    &
+            &                   zyj4, ze2, zvvel4, zvvel1, zay4, zdt, 1._wp )
+
+         zu4 = zuvel4 / ze1                           !**   V4 in d(i,j)/dt
+         zv4 = zvvel4 / ze2
+
+         ! FINAL STEP !
+         ! ========== !
+         !                                         !**   Xn = X1+dt*(V1+2*V2+2*V3+V4)/6
+         !                                         !**   Vn = V1+dt*(A1+2*A2+2*A3+A4)/6
+         zxi_n   = pt%xi   + zdt_6 * (  zu1  + 2.*(zu2  + zu3 ) + zu4  )
+         zyj_n   = pt%yj   + zdt_6 * (  zv1  + 2.*(zv2  + zv3 ) + zv4  )
+         zuvel_n = pt%uvel + zdt_6 * (  zax1 + 2.*(zax2 + zax3) + zax4 )
+         zvvel_n = pt%vvel + zdt_6 * (  zay1 + 2.*(zay2 + zay3) + zay4 )
+
+         CALL icb_ground( berg, zxi_n, zxi1, zuvel_n,   &
+            &                   zyj_n, zyj1, zvvel_n, ll_bounced )
+
+         pt%uvel = zuvel_n                        !** save in berg structure
+         pt%vvel = zvvel_n
+         pt%xi   = zxi_n
+         pt%yj   = zyj_n
+
+         berg => berg%next                         ! switch to the next berg
+         !
+      END DO                                  !==  end loop over all bergs  ==!
+      !
+   END SUBROUTINE icb_dyn
+
+
+   SUBROUTINE icb_ground( berg, pi, pi0, pu,   &
+      &                         pj, pj0, pv, ld_bounced )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE icb_ground  ***
+      !!
+      !! ** Purpose :   iceberg grounding.
+      !!
+      !! ** Method  : - adjust velocity and then put iceberg back to start position
+      !!                NB two possibilities available one of which is hard-coded here
+      !!----------------------------------------------------------------------
+      TYPE(iceberg ), POINTER, INTENT(in   ) ::   berg             ! berg
+      !
+      REAL(wp), INTENT(inout) ::   pi , pj      ! current iceberg position
+      REAL(wp), INTENT(in   ) ::   pi0, pj0     ! previous iceberg position
+      REAL(wp), INTENT(inout) ::   pu  , pv     ! current iceberg velocities
+      LOGICAL , INTENT(  out) ::   ld_bounced   ! bounced indicator
+      !
+      INTEGER  ::   ii, ii0
+      INTEGER  ::   ij, ij0
+      INTEGER  ::   ikb
+      INTEGER  ::   ibounce_method
+      !
+      REAL(wp) :: zD 
+      REAL(wp), DIMENSION(jpk) :: ze3t
+      !
+      LOGICAL  :: licb_free
+      !!----------------------------------------------------------------------
+      !
+      ld_bounced = .FALSE.
+      !
+      ii0 = INT( pi0+0.5 ) + (nn_hls-1)   ;   ij0 = INT( pj0+0.5 ) + (nn_hls-1)      ! initial gridpoint position (T-cell)
+      ii  = INT( pi +0.5 ) + (nn_hls-1)   ;   ij  = INT( pj +0.5 ) + (nn_hls-1)      ! current     -         -
+      !
+      IF( ii == ii0  .AND.  ij == ij0  )   RETURN           ! berg remains in the same cell
+      !
+      ! map into current processor
+      ii0 = mi1( ii0 )
+      ij0 = mj1( ij0 )
+      ii  = mi1( ii  )
+      ij  = mj1( ij  )
+      !
+      ! first check if enough room to go in the new cell (use before virtual area to avoid reproducibility issue)
+      ! case icb stay in the same cell => icb free to move (prevent issue with icb with icb area > cell area).
+      licb_free=.TRUE.
+      IF ( ln_icb_area_mask ) THEN                                   ! 
+         IF ( ii0 /= ii .OR. ij0 /= ij ) THEN                           ! icb enter in a new cell
+            IF ( virtual_area_e(ii,ij) > e1e2t(ii,ij) ) licb_free=.FALSE. ! the new cell is full, icb cannot go in
+         END IF
+      END IF
+         
+      ! assume icb is grounded if tmask(ii,ij,1) or tmask(ii,ij,ikb), depending of the option is not 0
+      IF ( ln_M2016 .AND. ln_icb_grd ) THEN
+         !
+         ! draught (keel depth)
+         zD = rho_berg_1_oce * berg%current_point%thickness
+         !
+         ! interpol needed data
+         CALL icb_utl_interp( pi, pj, pe3t=ze3t )
+         ! 
+         !compute bottom level
+         CALL icb_utl_getkb( ikb, ze3t, zD )
+         !
+         ! berg reach a new t-cell, but an ocean one
+         ! .AND. needed in case berg hit an isf (tmask(ii,ij,1) == 0 and tmask(ii,ij,ikb) /= 0)
+         IF(  tmask(ii,ij,ikb) /= 0._wp .AND. tmask(ii,ij,1) /= 0._wp .AND. licb_free ) RETURN
+         !
+      ELSE
+         IF(  tmask(ii,ij,1)  /=   0._wp .AND. licb_free )   RETURN           ! berg reach a new t-cell, but an ocean one
+      END IF
+      !
+      ! From here, berg have reach land: treat grounding/bouncing
+      ! -------------------------------
+      ld_bounced = .TRUE.
+
+      !! not obvious what should happen now
+      !! if berg tries to enter a land box, the only location we can return it to is the start 
+      !! position (pi0,pj0), since it has to be in a wet box to do any melting;
+      !! first option is simply to set whole velocity to zero and move back to start point
+      !! second option (suggested by gm) is only to set the velocity component in the (i,j) direction
+      !! of travel to zero; at a coastal boundary this has the effect of sliding the berg along the coast
+
+      ibounce_method = 2
+      SELECT CASE ( ibounce_method )
+      CASE ( 1 )
+         pi = pi0
+         pj = pj0
+         pu = 0._wp
+         pv = 0._wp
+      CASE ( 2 )
+         IF( ii0 /= ii ) THEN
+            pi = pi0                   ! return back to the initial position
+            pu = 0._wp                 ! zeroing of velocity in the direction of the grounding
+         ENDIF
+         IF( ij0 /= ij ) THEN
+            pj = pj0                   ! return back to the initial position
+            pv = 0._wp                 ! zeroing of velocity in the direction of the grounding
+         ENDIF
+      END SELECT
+      !
+   END SUBROUTINE icb_ground
+
+
+   SUBROUTINE icb_accel( kt, berg , pxi, pe1, puvel, puvel0, pax,                 &
+      &                             pyj, pe2, pvvel, pvvel0, pay, pdt, pcfl_scale )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE icb_accel  ***
+      !!
+      !! ** Purpose :   compute the iceberg acceleration.
+      !!
+      !! ** Method  : - sum the terms in the momentum budget
+      !!----------------------------------------------------------------------
+      TYPE(iceberg ), POINTER, INTENT(in   ) ::   berg             ! berg
+      INTEGER                , INTENT(in   ) ::   kt               ! time step
+      REAL(wp)               , INTENT(in   ) ::   pcfl_scale
+      REAL(wp)               , INTENT(in   ) ::   pxi   , pyj      ! berg position in (i,j) referential
+      REAL(wp)               , INTENT(in   ) ::   puvel , pvvel    ! berg velocity [m/s]
+      REAL(wp)               , INTENT(in   ) ::   puvel0, pvvel0   ! initial berg velocity [m/s]
+      REAL(wp)               , INTENT(  out) ::   pe1, pe2         ! horizontal scale factor at (xi,yj)
+      REAL(wp)               , INTENT(inout) ::   pax, pay         ! berg acceleration
+      REAL(wp)               , INTENT(in   ) ::   pdt              ! berg time step
+      !
+      REAL(wp), PARAMETER ::   pp_alpha     = 0._wp      !
+      REAL(wp), PARAMETER ::   pp_beta      = 1._wp      !
+      REAL(wp), PARAMETER ::   pp_vel_lim   =15._wp      ! max allowed berg speed
+      REAL(wp), PARAMETER ::   pp_accel_lim = 1.e-2_wp   ! max allowed berg acceleration
+      REAL(wp), PARAMETER ::   pp_Cr0       = 0.06_wp    !
+      !
+      INTEGER  ::   itloop, ikb, jk
+      REAL(wp) ::   zuo, zssu, zui, zua, zuwave, zssh_x, zcn, zhi
+      REAL(wp) ::   zvo, zssv, zvi, zva, zvwave, zssh_y
+      REAL(wp) ::   zff, zT, zD, zW, zL, zM, zF
+      REAL(wp) ::   zdrag_ocn, zdrag_atm, zdrag_ice, zwave_rad
+      REAL(wp) ::   z_ocn, z_atm, z_ice, zdep
+      REAL(wp) ::   zampl, zwmod, zCr, zLwavelength, zLcutoff, zLtop
+      REAL(wp) ::   zlambda, zdetA, zA11, zA12, zaxe, zaye, zD_hi
+      REAL(wp) ::   zuveln, zvveln, zus, zvs, zspeed, zloc_dx, zspeed_new
+      REAL(wp), DIMENSION(jpk) :: zuoce, zvoce, ze3t, zdepw
+      !!----------------------------------------------------------------------
+
+      ! Interpolate gridded fields to berg
+      nknberg = berg%number(1)
+      CALL icb_utl_interp( pxi, pyj, pe1=pe1, pe2=pe2,     &   ! scale factor
+         &                 pssu=zssu, pui=zui, pua=zua,    &   ! oce/ice/atm velocities
+         &                 pssv=zssv, pvi=zvi, pva=zva,    &   ! oce/ice/atm velocities
+         &                 pssh_i=zssh_x, pssh_j=zssh_y,   &   ! ssh gradient
+         &                 phi=zhi, pff=zff)                   ! ice thickness and coriolis
+
+      zM = berg%current_point%mass
+      zT = berg%current_point%thickness               ! total thickness
+      zD = rho_berg_1_oce * zT                        ! draught (keel depth)
+      zF = zT - zD                                    ! freeboard
+      zW = berg%current_point%width
+      zL = berg%current_point%length
+
+      zhi   = MIN( zhi   , zD    )
+      zD_hi = MAX( 0._wp, zD-zhi )
+ 
+     ! Wave radiation
+      zuwave = zua - zssu   ;   zvwave = zva - zssv   ! Use wind speed rel. to ocean for wave model
+      zwmod  = zuwave*zuwave + zvwave*zvwave          ! The wave amplitude and length depend on the  current;
+      !                                               ! wind speed relative to the ocean. Actually wmod is wmod**2 here.
+      zampl        = 0.5_wp * 0.02025_wp * zwmod      ! This is "a", the wave amplitude
+      zLwavelength =       0.32_wp    * zwmod         ! Surface wave length fitted to data in table at
+      !                                               ! http://www4.ncsu.edu/eos/users/c/ceknowle/public/chapter10/part2.html
+      zLcutoff     = 0.125_wp * zLwavelength
+      zLtop        = 0.25_wp  * zLwavelength
+      zCr          = pp_Cr0 * MIN(  MAX( 0._wp, (zL-zLcutoff) / ((zLtop-zLcutoff)+1.e-30)) , 1._wp)  ! Wave radiation coefficient
+      !                                               ! fitted to graph from Carrieres et al.,  POAC Drift Model.
+      zwave_rad    = 0.5_wp * pp_rho_seawater / zM * zCr * grav * zampl * MIN( zampl,zF ) * (2._wp*zW*zL) / (zW+zL)
+      zwmod        = SQRT( zua*zua + zva*zva )        ! Wind speed
+      IF( zwmod /= 0._wp ) THEN
+         zuwave = zua/zwmod   ! Wave radiation force acts in wind direction ...       !!gm  this should be the wind rel. to ocean ?
+         zvwave = zva/zwmod
+      ELSE
+         zuwave = 0._wp   ;    zvwave=0._wp   ;    zwave_rad=0._wp ! ... and only when wind is present.     !!gm  wave_rad=0. is useless
+      ENDIF
+
+      ! Weighted drag coefficients
+      z_ocn = pp_rho_seawater / zM * (0.5_wp*pp_Cd_wv*zW*(zD_hi)+pp_Cd_wh*zW*zL)
+      z_atm = pp_rho_air      / zM * (0.5_wp*pp_Cd_av*zW*zF     +pp_Cd_ah*zW*zL)
+      z_ice = pp_rho_ice      / zM * (0.5_wp*pp_Cd_iv*zW*zhi              )
+      IF( abs(zui) + abs(zvi) == 0._wp )   z_ice = 0._wp
+
+      ! lateral velocities
+      ! default ssu and ssv
+      ! ln_M2016: mean velocity along the profile
+      IF ( ln_M2016 ) THEN
+         ! interpol needed data
+         CALL icb_utl_interp( pxi, pyj, puoce=zuoce, pvoce=zvoce, pe3t=ze3t )   ! 3d velocities
+        
+         !compute bottom level
+         CALL icb_utl_getkb( ikb, ze3t, zD )
+         
+         ! compute mean velocity 
+         CALL icb_utl_zavg(zuo, zuoce, ze3t, zD, ikb)
+         CALL icb_utl_zavg(zvo, zvoce, ze3t, zD, ikb)
+      ELSE
+         zuo = zssu
+         zvo = zssv
+      END IF
+
+      zuveln = puvel   ;   zvveln = pvvel ! Copy starting uvel, vvel
+      !
+      DO itloop = 1, 2  ! Iterate on drag coefficients
+         !
+         zus = 0.5_wp * ( zuveln + puvel )
+         zvs = 0.5_wp * ( zvveln + pvvel )
+         zdrag_ocn = z_ocn * SQRT( (zus-zuo)*(zus-zuo) + (zvs-zvo)*(zvs-zvo) )
+         zdrag_atm = z_atm * SQRT( (zus-zua)*(zus-zua) + (zvs-zva)*(zvs-zva) )
+         zdrag_ice = z_ice * SQRT( (zus-zui)*(zus-zui) + (zvs-zvi)*(zvs-zvi) )
+         !
+         ! Explicit accelerations
+         !zaxe= zff*pvvel -grav*zssh_x +zwave_rad*zuwave &
+         !    -zdrag_ocn*(puvel-zssu) -zdrag_atm*(puvel-zua) -zdrag_ice*(puvel-zui)
+         !zaye=-zff*puvel -grav*zssh_y +zwave_rad*zvwave &
+         !    -zdrag_ocn*(pvvel-zssv) -zdrag_atm*(pvvel-zva) -zdrag_ice*(pvvel-zvi)
+         zaxe = -grav * zssh_x + zwave_rad * zuwave
+         zaye = -grav * zssh_y + zwave_rad * zvwave
+         IF( pp_alpha > 0._wp ) THEN   ! If implicit, use time-level (n) rather than RK4 latest
+            zaxe = zaxe + zff*pvvel0
+            zaye = zaye - zff*puvel0
+         ELSE
+            zaxe = zaxe + zff*pvvel
+            zaye = zaye - zff*puvel
+         ENDIF
+         IF( pp_beta > 0._wp ) THEN    ! If implicit, use time-level (n) rather than RK4 latest
+            zaxe = zaxe - zdrag_ocn*(puvel0-zuo) - zdrag_atm*(puvel0-zua) -zdrag_ice*(puvel0-zui)
+            zaye = zaye - zdrag_ocn*(pvvel0-zvo) - zdrag_atm*(pvvel0-zva) -zdrag_ice*(pvvel0-zvi)
+         ELSE
+            zaxe = zaxe - zdrag_ocn*(puvel -zuo) - zdrag_atm*(puvel -zua) -zdrag_ice*(puvel -zui)
+            zaye = zaye - zdrag_ocn*(pvvel -zvo) - zdrag_atm*(pvvel -zva) -zdrag_ice*(pvvel -zvi)
+         ENDIF
+
+         ! Solve for implicit accelerations
+         IF( pp_alpha + pp_beta > 0._wp ) THEN
+            zlambda = zdrag_ocn + zdrag_atm + zdrag_ice
+            zA11    = 1._wp + pp_beta *pdt*zlambda
+            zA12    =         pp_alpha*pdt*zff
+            zdetA   = 1._wp / ( zA11*zA11 + zA12*zA12 )
+            pax     = zdetA * ( zA11*zaxe + zA12*zaye )
+            pay     = zdetA * ( zA11*zaye - zA12*zaxe )
+         ELSE
+            pax = zaxe   ;   pay = zaye
+         ENDIF
+
+         zuveln = puvel0 + pdt*pax
+         zvveln = pvvel0 + pdt*pay
+         !
+      END DO      ! itloop
+
+      IF( rn_speed_limit > 0._wp ) THEN       ! Limit speed of bergs based on a CFL criteria (if asked)
+         zspeed = SQRT( zuveln*zuveln + zvveln*zvveln )    ! Speed of berg
+         IF( zspeed > 0._wp ) THEN
+            zloc_dx = MIN( pe1, pe2 )                                ! minimum grid spacing
+            ! cfl scale is function of the RK4 step
+            zspeed_new = zloc_dx / pdt * rn_speed_limit * pcfl_scale ! Speed limit as a factor of dx / dt
+            IF( zspeed_new < zspeed ) THEN
+               zuveln = zuveln * ( zspeed_new / zspeed )             ! Scale velocity to reduce speed
+               zvveln = zvveln * ( zspeed_new / zspeed )             ! without changing the direction
+               pax = (zuveln - puvel0)/pdt
+               pay = (zvveln - pvvel0)/pdt
+               !
+               ! print speeding ticket
+               IF (nn_verbose_level > 0) THEN
+                  WRITE(numicb, 9200) 'icb speeding : ',kt, nknberg, zspeed, &
+                       &                pxi, pyj, zuo, zvo, zua, zva, zui, zvi
+                  9200 FORMAT(a,i9,i6,f9.2,1x,4(1x,2f9.2))
+               END IF
+               !
+               CALL icb_dia_speed()
+            ENDIF
+         ENDIF
+      ENDIF
+      !                                      ! check the speed and acceleration limits
+      IF (nn_verbose_level > 0) THEN
+         IF( ABS( zuveln ) > pp_vel_lim   .OR. ABS( zvveln ) > pp_vel_lim   )   &
+            WRITE(numicb,'("pe=",i3,x,a)') narea,'Dump triggered by excessive velocity'
+         IF( ABS( pax    ) > pp_accel_lim .OR. ABS( pay    ) > pp_accel_lim )   &
+            WRITE(numicb,'("pe=",i3,x,a)') narea,'Dump triggered by excessive acceleration'
+      ENDIF
+      !
+   END SUBROUTINE icb_accel
+
+   !!======================================================================
+END MODULE icbdyn

+ 534 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbini.F90

@@ -0,0 +1,534 @@
+MODULE icbini
+   !!======================================================================
+   !!                       ***  MODULE  icbini  ***
+   !! Icebergs:  initialise variables for iceberg tracking
+   !!======================================================================
+   !! History :   -   !  2010-01  (T. Martin & A. Adcroft)  Original code
+   !!            3.3  !  2011-03  (G. Madec)  Part conversion to NEMO form ; Removal of mapping from another grid
+   !!             -   !  2011-04  (S. Alderson)  Split into separate modules ; Restore restart routines
+   !!             -   !  2011-05  (S. Alderson)  generate_test_icebergs restored ; new forcing arrays with extra halo ;
+   !!             -   !                          north fold exchange arrays added
+   !!----------------------------------------------------------------------
+   !!----------------------------------------------------------------------
+   !!   icb_init     : initialise icebergs
+   !!   icb_ini_gen  : generate test icebergs
+   !!   icb_nam      : read iceberg namelist
+   !!----------------------------------------------------------------------
+   USE dom_oce        ! ocean domain
+   USE in_out_manager ! IO routines and numout in particular
+   USE lib_mpp        ! mpi library and lk_mpp in particular
+   USE sbc_oce        ! ocean  : surface boundary condition
+   USE sbc_ice        ! sea-ice: surface boundary condition
+   USE iom            ! IOM library
+   USE fldread        ! field read
+   USE lbclnk         ! lateral boundary condition - MPP link
+   !
+   USE icb_oce        ! define iceberg arrays
+   USE icbutl         ! iceberg utility routines
+   USE icbrst         ! iceberg restart routines
+   USE icbtrj         ! iceberg trajectory I/O routines
+   USE icbdia         ! iceberg budget routines
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   icb_init  ! routine called in nemogcm.F90 module
+
+   CHARACTER(len=100)                                 ::   cn_dir = './'   !: Root directory for location of icb files
+   TYPE(FLD_N)                                        ::   sn_icb          !: information about the calving file to be read
+   TYPE(FLD), PUBLIC, ALLOCATABLE     , DIMENSION(:)  ::   sf_icb          !: structure: file information, fields read
+                                                                           !: used in icbini and icbstp
+   !! * Substitutions
+#  include "do_loop_substitute.h90"
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: icbini.F90 15372 2021-10-14 15:47:24Z davestorkey $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   SUBROUTINE icb_init( pdt, kt )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE dom_init  ***
+      !!
+      !! ** Purpose :   iceberg initialization.
+      !!
+      !! ** Method  : - read the iceberg namelist
+      !!              - find non-overlapping processor interior since we can only
+      !!                have one instance of a particular iceberg
+      !!              - calculate the destinations for north fold exchanges
+      !!              - setup either test icebergs or calving file
+      !!----------------------------------------------------------------------
+      REAL(wp), INTENT(in) ::   pdt   ! iceberg time-step (rn_Dt*nn_fsbc)
+      INTEGER , INTENT(in) ::   kt    ! time step number
+      !
+      INTEGER ::   ji, jj, jn               ! dummy loop indices
+      INTEGER ::   i1, i2, i3               ! local integers
+      INTEGER ::   ii, inum, ivar           !   -       -
+      INTEGER ::   istat1, istat2, istat3   !   -       -
+      CHARACTER(len=300) ::   cl_sdist      ! local character
+      !!----------------------------------------------------------------------
+      !
+      CALL icb_nam               ! Read and print namelist parameters
+      !
+      IF( .NOT. ln_icebergs )   RETURN
+      !
+      ALLOCATE( utau_icb(jpi,jpj), vtau_icb(jpi,jpj) )
+      !
+      !                          ! allocate gridded fields
+      IF( icb_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'icb_alloc : unable to allocate arrays' )
+      !
+      !                          ! initialised variable with extra haloes to zero
+      ssu_e(:,:) = 0._wp   ;   ssv_e(:,:) = 0._wp   ;
+      ua_e(:,:)  = 0._wp   ;   va_e(:,:)  = 0._wp   ;
+      ff_e(:,:)  = 0._wp   ;   sst_e(:,:) = 0._wp   ;
+      fr_e(:,:)  = 0._wp   ;   sss_e(:,:) = 0._wp   ;
+      !
+      IF ( ln_M2016 ) THEN
+         toce_e(:,:,:) = 0._wp
+         uoce_e(:,:,:) = 0._wp
+         voce_e(:,:,:) = 0._wp
+         e3t_e(:,:,:)  = 0._wp
+      END IF
+      !
+#if defined key_si3
+      hi_e(:,:) = 0._wp   ;
+      ui_e(:,:) = 0._wp   ;   vi_e(:,:) = 0._wp   ;
+#endif
+      ssh_e(:,:) = 0._wp  ; 
+      !
+      !                          ! open ascii output file or files for iceberg status information
+      !                          ! note that we choose to do this on all processors since we cannot
+      !                          ! predict where icebergs will be ahead of time
+      IF( nn_verbose_level > 0) THEN
+         CALL ctl_opn( numicb, 'icebergs.stat', 'REPLACE', 'FORMATTED', 'SEQUENTIAL', -1, numout, lwp, narea )
+      ENDIF
+
+      ! set parameters (mostly from namelist)
+      !
+      berg_dt         = pdt
+      first_width (:) = SQRT(  rn_initial_mass(:) / ( rn_LoW_ratio * rn_rho_bergs * rn_initial_thickness(:) )  )
+      first_length(:) = rn_LoW_ratio * first_width(:)
+      rho_berg_1_oce  = rn_rho_bergs / pp_rho_seawater  ! scale factor used for convertion thickness to draft
+      !
+      ! deepest level affected by icebergs
+      ! can be tuned but the safest is this 
+      ! (with z* and z~ the depth of each level change overtime, so the more robust micbkb is jpk)
+      micbkb = jpk
+
+      berg_grid%calving      (:,:)   = 0._wp
+      berg_grid%calving_hflx (:,:)   = 0._wp
+      berg_grid%stored_heat  (:,:)   = 0._wp
+      berg_grid%floating_melt(:,:)   = 0._wp
+      berg_grid%maxclass     (:,:)   = nclasses
+      berg_grid%stored_ice   (:,:,:) = 0._wp
+      berg_grid%tmp          (:,:)   = 0._wp
+      src_calving            (:,:)   = 0._wp
+      src_calving_hflx       (:,:)   = 0._wp
+
+      !                          ! domain for icebergs
+      IF( lk_mpp .AND. jpni == 1 )   CALL ctl_stop( 'icbinit: having ONE processor in x currently does not work' )
+      ! NB: the issue here is simply that cyclic east-west boundary condition have not been coded in mpp case
+      ! for the north fold we work out which points communicate by asking
+      ! lbc_lnk to pass processor number (valid even in single processor case)
+      ! borrow src_calving arrays for this
+      !
+      ! pack i and j together using a scaling of a power of 10
+      nicbpack = 10000
+      IF( jpiglo >= nicbpack )   CALL ctl_stop( 'icbini: processor index packing failure' )
+      nicbfldproc(:) = -1
+
+      DO_2D( 1, 1, 1, 1 )
+         src_calving_hflx(ji,jj) = narea
+         src_calving     (ji,jj) = nicbpack * mjg(jj) + mig(ji)
+      END_2D
+      CALL lbc_lnk( 'icbini', src_calving_hflx, 'T', 1._wp )
+      CALL lbc_lnk( 'icbini', src_calving     , 'T', 1._wp )
+
+      ! work out interior of processor from exchange array
+      ! first entry with narea for this processor is left hand interior index
+      ! last  entry                               is right hand interior index
+      jj = jpj/2
+      nicbdi = -1
+      nicbei = -1
+      DO ji = 1, jpi
+         i3 = INT( src_calving(ji,jj) )
+         i2 = INT( i3/nicbpack )
+         i1 = i3 - i2*nicbpack
+         i3 = INT( src_calving_hflx(ji,jj) )
+         IF( i1 == mig(ji) .AND. i3 == narea ) THEN
+            IF( nicbdi < 0 ) THEN   ;   nicbdi = ji
+            ELSE                    ;   nicbei = ji
+            ENDIF
+         ENDIF
+      END DO
+      !
+      ! repeat for j direction
+      ji = jpi/2
+      nicbdj = -1
+      nicbej = -1
+      DO jj = 1, jpj
+         i3 = INT( src_calving(ji,jj) )
+         i2 = INT( i3/nicbpack )
+         i1 = i3 - i2*nicbpack
+         i3 = INT( src_calving_hflx(ji,jj) )
+         IF( i2 == mjg(jj) .AND. i3 == narea ) THEN
+            IF( nicbdj < 0 ) THEN   ;   nicbdj = jj
+            ELSE                    ;   nicbej = jj
+            ENDIF
+         ENDIF
+      END DO
+      !   
+      ! special for east-west boundary exchange we save the destination index
+      i1 = MAX( nicbdi-1, 1)
+      i3 = INT( src_calving(i1,jpj/2) )
+      jj = INT( i3/nicbpack )
+      ricb_left = REAL( i3 - nicbpack*jj, wp ) - (nn_hls-1)
+      i1 = MIN( nicbei+1, jpi )
+      i3 = INT( src_calving(i1,jpj/2) )
+      jj = INT( i3/nicbpack )
+      ricb_right = REAL( i3 - nicbpack*jj, wp ) - (nn_hls-1)
+      
+      ! north fold
+      IF( l_IdoNFold ) THEN
+         !
+         ! icebergs in row nicbej+1 get passed across fold
+         nicbfldpts(:)  = INT( src_calving(:,nicbej+1) )
+         nicbflddest(:) = INT( src_calving_hflx(:,nicbej+1) )
+         !
+         ! work out list of unique processors to talk to
+         ! pack them into a fixed size array where empty slots are marked by a -1
+         DO ji = nicbdi, nicbei
+            ii = nicbflddest(ji)
+            IF( ii .GT. 0 ) THEN     ! Needed because land suppression can mean
+                                     ! that unused points are not set in edge haloes
+               DO jn = 1, jpni
+                  ! work along array until we find an empty slot
+                  IF( nicbfldproc(jn) == -1 ) THEN
+                     nicbfldproc(jn) = ii
+                     EXIT                             !!gm EXIT should be avoided: use DO WHILE expression instead
+                  ENDIF
+                  ! before we find an empty slot, we may find processor number is already here so we exit
+                  IF( nicbfldproc(jn) == ii ) EXIT
+               END DO
+            ENDIF
+         END DO
+      ENDIF
+      !
+      IF( nn_verbose_level > 0) THEN
+         WRITE(numicb,*) 'processor ', narea
+         WRITE(numicb,*) 'jpi, jpj   ', jpi, jpj
+         WRITE(numicb,*) 'Nis0, Nie0 ', Nis0, Nie0
+         WRITE(numicb,*) 'Njs0, Nje0 ', Njs0, Nje0
+         WRITE(numicb,*) 'berg i interior ', nicbdi, nicbei
+         WRITE(numicb,*) 'berg j interior ', nicbdj, nicbej
+         WRITE(numicb,*) 'berg left       ', ricb_left
+         WRITE(numicb,*) 'berg right      ', ricb_right
+         jj = jpj/2
+         WRITE(numicb,*) "central j line:"
+         WRITE(numicb,*) "i processor"
+         WRITE(numicb,*) (INT(src_calving_hflx(ji,jj)), ji=1,jpi)
+         WRITE(numicb,*) "i point"
+         WRITE(numicb,*) (INT(src_calving(ji,jj)), ji=1,jpi)
+         ji = jpi/2
+         WRITE(numicb,*) "central i line:"
+         WRITE(numicb,*) "j processor"
+         WRITE(numicb,*) (INT(src_calving_hflx(ji,jj)), jj=1,jpj)
+         WRITE(numicb,*) "j point"
+         WRITE(numicb,*) (INT(src_calving(ji,jj)), jj=1,jpj)
+         IF( l_IdoNFold ) THEN
+            WRITE(numicb,*) 'north fold destination points '
+            WRITE(numicb,*) nicbfldpts
+            WRITE(numicb,*) 'north fold destination procs  '
+            WRITE(numicb,*) nicbflddest
+            WRITE(numicb,*) 'north fold destination proclist  '
+            WRITE(numicb,*) nicbfldproc
+         ENDIF
+         CALL flush(numicb)
+      ENDIF
+      
+      src_calving     (:,:) = 0._wp
+      src_calving_hflx(:,:) = 0._wp
+
+      ! definition of extended surface masked needed by icb_bilin_h
+      tmask_e(:,:) = 0._wp   ;   tmask_e(1:jpi,1:jpj) = tmask(:,:,1)
+      umask_e(:,:) = 0._wp   ;   umask_e(1:jpi,1:jpj) = umask(:,:,1)
+      vmask_e(:,:) = 0._wp   ;   vmask_e(1:jpi,1:jpj) = vmask(:,:,1)
+      CALL lbc_lnk_icb( 'icbini', tmask_e, 'T', +1._wp, 1, 1 )
+      CALL lbc_lnk_icb( 'icbini', umask_e, 'U', +1._wp, 1, 1 )
+      CALL lbc_lnk_icb( 'icbini', vmask_e, 'V', +1._wp, 1, 1 )
+
+      ! definition of extended lat/lon array needed by icb_bilin_h
+      rlon_e(:,:) = 0._wp     ;  rlon_e(1:jpi,1:jpj) = glamt(:,:) 
+      rlat_e(:,:) = 0._wp     ;  rlat_e(1:jpi,1:jpj) = gphit(:,:)
+      CALL lbc_lnk_icb( 'icbini', rlon_e, 'T', +1._wp, 1, 1 )
+      CALL lbc_lnk_icb( 'icbini', rlat_e, 'T', +1._wp, 1, 1 )
+      !
+      ! definnitionn of extennded ff_f array needed by icb_utl_interp
+      ff_e(:,:) = 0._wp       ;  ff_e(1:jpi,1:jpj) = ff_f(:,:)
+      CALL lbc_lnk_icb( 'icbini', ff_e, 'F', +1._wp, 1, 1 )
+
+      ! definition of the virtual area array
+      virtual_area(:,:) = 0._wp
+      virtual_area_e(:,:) = 0._wp
+
+      ! assign each new iceberg with a unique number constructed from the processor number
+      ! and incremented by the total number of processors
+      num_bergs(:) = 0
+      num_bergs(1) = narea - jpnij
+
+      ! when not generating test icebergs we need to setup calving file
+      IF( nn_test_icebergs < 0 .OR. ln_use_calving ) THEN
+         !
+         ! maximum distribution class array does not change in time so read it once
+         cl_sdist = TRIM( cn_dir )//TRIM( sn_icb%clname )
+         CALL iom_open ( cl_sdist, inum )                              ! open file
+         ivar = iom_varid( inum, 'maxclass', ldstop=.FALSE. )
+         IF( ivar > 0 ) THEN
+            CALL iom_get  ( inum, jpdom_global, 'maxclass', src_calving )   ! read the max distribution array
+            berg_grid%maxclass(:,:) = INT( src_calving )
+            src_calving(:,:) = 0._wp
+         ENDIF
+         CALL iom_close( inum )                                     ! close file
+         !
+         IF( nn_verbose_level > 0) THEN
+            WRITE(numicb,*)
+            WRITE(numicb,*) '          calving read in a file'
+         ENDIF
+         ALLOCATE( sf_icb(1), STAT=istat1 )         ! Create sf_icb structure (calving)
+         ALLOCATE( sf_icb(1)%fnow(jpi,jpj,1), STAT=istat2 )
+         ALLOCATE( sf_icb(1)%fdta(jpi,jpj,1,2), STAT=istat3 )
+         IF( istat1+istat2+istat3 > 0 ) THEN
+            CALL ctl_stop( 'sbc_icb: unable to allocate sf_icb structure' )   ;   RETURN
+         ENDIF
+         !                                          ! fill sf_icb with the namelist (sn_icb) and control print
+         CALL fld_fill( sf_icb, (/ sn_icb /), cn_dir, 'icb_init', 'read calving data', 'namicb' )
+         !
+      ENDIF
+
+      IF( .NOT.ln_rstart ) THEN
+         IF( nn_test_icebergs > 0 )   CALL icb_ini_gen()
+      ELSE
+         IF( nn_test_icebergs > 0 ) THEN
+            CALL icb_ini_gen()
+         ELSE
+            CALL icb_rst_read()
+            l_restarted_bergs = .TRUE.
+         ENDIF
+      ENDIF
+      !
+      IF( nn_sample_rate .GT. 0 ) CALL icb_trj_init( nitend )
+      !
+      CALL icb_dia_init()
+      !
+      IF( nn_verbose_level >= 2 )   CALL icb_utl_print('icb_init, initial status', nit000-1)
+      !
+   END SUBROUTINE icb_init
+
+
+   SUBROUTINE icb_ini_gen()
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE icb_ini_gen  ***
+      !!
+      !! ** Purpose :   iceberg generation
+      !!
+      !! ** Method  : - at each grid point of the test box supplied in the namelist
+      !!                generate an iceberg in one class determined by the value of
+      !!                parameter nn_test_icebergs
+      !!----------------------------------------------------------------------
+      INTEGER                         ::   ji, jj, ibergs
+      TYPE(iceberg)                   ::   localberg ! NOT a pointer but an actual local variable
+      TYPE(point)                     ::   localpt
+      INTEGER                         ::   iyr, imon, iday, ihr, imin, isec
+      INTEGER                         ::   iberg
+      !!----------------------------------------------------------------------
+
+      ! For convenience
+      iberg = nn_test_icebergs
+
+      ! call get_date(Time, iyr, imon, iday, ihr, imin, isec)
+      ! Convert nemo time variables from dom_oce into local versions
+      iyr  = nyear
+      imon = nmonth
+      iday = nday
+      ihr = INT(nsec_day/3600)
+      imin = INT((nsec_day-ihr*3600)/60)
+      isec = nsec_day - ihr*3600 - imin*60
+
+      ! no overlap for icebergs since we want only one instance of each across the whole domain
+      ! so restrict area of interest
+      ! use tmask here because tmask_i has been doctored on one side of the north fold line
+
+      DO jj = nicbdj, nicbej
+         DO ji = nicbdi, nicbei
+            IF( tmask(ji,jj,1) > 0._wp        .AND.                                       &
+                rn_test_box(1) < glamt(ji,jj) .AND. glamt(ji,jj) < rn_test_box(2) .AND.   &
+                rn_test_box(3) < gphit(ji,jj) .AND. gphit(ji,jj) < rn_test_box(4) ) THEN
+               localberg%mass_scaling = rn_mass_scaling(iberg)
+               localpt%xi = REAL( mig(ji) - (nn_hls-1), wp )
+               localpt%yj = REAL( mjg(jj) - (nn_hls-1), wp )
+               CALL icb_utl_interp( localpt%xi, localpt%yj, plat=localpt%lat, plon=localpt%lon )   
+               localpt%mass      = rn_initial_mass     (iberg)
+               localpt%thickness = rn_initial_thickness(iberg)
+               localpt%width  = first_width (iberg)
+               localpt%length = first_length(iberg)
+               localpt%year = iyr
+               localpt%day = REAL(iday,wp)+(REAL(ihr,wp)+REAL(imin,wp)/60._wp)/24._wp
+               localpt%mass_of_bits = 0._wp
+               localpt%heat_density = 0._wp
+               localpt%uvel = 0._wp
+               localpt%vvel = 0._wp
+               localpt%kb   = 1
+               CALL icb_utl_incr()
+               localberg%number(:) = num_bergs(:)
+               call icb_utl_add(localberg, localpt)
+            ENDIF
+         END DO
+      END DO
+      !
+      ibergs = icb_utl_count()
+      CALL mpp_sum('icbini', ibergs)
+      IF( nn_verbose_level > 0) THEN
+         WRITE(numicb,'(a,i6,a)') 'diamonds, icb_ini_gen: ',ibergs,' were generated'
+      ENDIF
+      !
+   END SUBROUTINE icb_ini_gen
+
+
+   SUBROUTINE icb_nam
+      !!----------------------------------------------------------------------
+      !!                     ***  ROUTINE icb_nam  ***
+      !!
+      !! ** Purpose :   read iceberg namelist and print the variables.
+      !!
+      !! ** input   : - namberg namelist
+      !!----------------------------------------------------------------------
+      INTEGER  ::   jn      ! dummy loop indices
+      INTEGER  ::   ios     ! Local integer output status for namelist read
+      REAL(wp) ::   zfact   ! local scalar
+      !
+      NAMELIST/namberg/ ln_icebergs    , ln_bergdia     , nn_sample_rate      , rn_initial_mass      ,   &
+         &              rn_distribution, rn_mass_scaling, rn_initial_thickness, nn_verbose_write     ,   &
+         &              rn_rho_bergs   , rn_LoW_ratio   , nn_verbose_level    , ln_operator_splitting,   &
+         &              rn_bits_erosion_fraction        , rn_sicn_shift       , ln_passive_mode      ,   &
+         &              ln_time_average_weight          , nn_test_icebergs    , rn_test_box          ,   &
+         &              ln_use_calving , rn_speed_limit , cn_dir, sn_icb      , ln_M2016             ,   &
+         &              cn_icbrst_indir, cn_icbrst_in   , cn_icbrst_outdir    , cn_icbrst_out        ,   &
+         &              ln_icb_grd, ln_icb_area_mask
+      !!----------------------------------------------------------------------
+
+#if defined key_agrif
+      IF(lwp) THEN
+         WRITE(numout,*)
+         WRITE(numout,*) 'icb_nam : AGRIF is not compatible with namelist namberg :  '
+         WRITE(numout,*) '~~~~~~~   definition of rn_initial_mass(nclasses) with nclasses as PARAMETER '
+         WRITE(numout,*)
+         WRITE(numout,*) '   ==>>>   force  NO icebergs used. The namelist namberg is not read'
+      ENDIF
+      ln_icebergs = .false.      
+      RETURN
+#else
+      IF(lwp) THEN
+         WRITE(numout,*)
+         WRITE(numout,*) 'icb_nam : iceberg initialization through namberg namelist read'
+         WRITE(numout,*) '~~~~~~~~ '
+      ENDIF
+#endif   
+      !                             !==  read namelist  ==!
+      READ  ( numnam_ref, namberg, IOSTAT = ios, ERR = 901)
+901   IF( ios /= 0 ) CALL ctl_nam ( ios , 'namberg in reference namelist' )
+      READ  ( numnam_cfg, namberg, IOSTAT = ios, ERR = 902 )
+902   IF( ios >  0 ) CALL ctl_nam ( ios , 'namberg in configuration namelist' )
+      IF(lwm) WRITE ( numond, namberg )
+      !
+      IF(lwp) WRITE(numout,*)
+      IF( ln_icebergs ) THEN
+         IF(lwp) WRITE(numout,*) '   ==>>>   icebergs are used'
+      ELSE
+         IF(lwp) WRITE(numout,*) '   ==>>>   No icebergs used'
+         RETURN
+      ENDIF
+      !
+      IF( nn_test_icebergs > nclasses ) THEN
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   Resetting of nn_test_icebergs to ', nclasses
+         nn_test_icebergs = nclasses
+      ENDIF
+      !
+      IF( nn_test_icebergs < 0 .AND. .NOT. ln_use_calving ) THEN
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   Resetting ln_use_calving to .true. since we are not using test icebergs'
+         ln_use_calving = .true.
+      ENDIF
+      !
+      IF(lwp) THEN                  ! control print
+         WRITE(numout,*)
+         WRITE(numout,*) 'icb_nam : iceberg initialization through namberg namelist read'
+         WRITE(numout,*) '~~~~~~~~ '
+         WRITE(numout,*) '   Calculate budgets                                            ln_bergdia       = ', ln_bergdia
+         WRITE(numout,*) '   Period between sampling of position for trajectory storage   nn_sample_rate = ', nn_sample_rate
+         WRITE(numout,*) '   Mass thresholds between iceberg classes (kg)                 rn_initial_mass     ='
+         DO jn = 1, nclasses
+            WRITE(numout,'(a,f15.2)') '                                                                ', rn_initial_mass(jn)
+         ENDDO
+         WRITE(numout,*) '   Fraction of calving to apply to this class (non-dim)         rn_distribution     ='
+         DO jn = 1, nclasses
+            WRITE(numout,'(a,f10.4)') '                                                                ', rn_distribution(jn)
+         END DO
+         WRITE(numout,*) '   Ratio between effective and real iceberg mass (non-dim)      rn_mass_scaling     = '
+         DO jn = 1, nclasses
+            WRITE(numout,'(a,f10.2)') '                                                                ', rn_mass_scaling(jn)
+         END DO
+         WRITE(numout,*) '   Total thickness of newly calved bergs (m)                    rn_initial_thickness = '
+         DO jn = 1, nclasses
+            WRITE(numout,'(a,f10.2)') '                                                                ', rn_initial_thickness(jn)
+         END DO
+         WRITE(numout,*) '   Timesteps between verbose messages                           nn_verbose_write    = ', nn_verbose_write
+
+         WRITE(numout,*) '   Density of icebergs                           rn_rho_bergs  = ', rn_rho_bergs
+         WRITE(numout,*) '   Initial ratio L/W for newly calved icebergs   rn_LoW_ratio  = ', rn_LoW_ratio
+         WRITE(numout,*) '   Turn on more verbose output                          level  = ', nn_verbose_level
+         WRITE(numout,*) '   Use first order operator splitting for thermodynamics    ',   &
+            &                    'use_operator_splitting = ', ln_operator_splitting
+         WRITE(numout,*) '   Fraction of erosion melt flux to divert to bergy bits    ',   &
+            &                    'bits_erosion_fraction = ', rn_bits_erosion_fraction
+
+         WRITE(numout,*) '   Use icb module modification from Merino et al. (2016) : ln_M2016 = ', ln_M2016
+         WRITE(numout,*) '       ground icebergs if icb bottom lvl hit the oce bottom level : ln_icb_grd = ', ln_icb_grd
+
+         WRITE(numout,*) '   Check total icb area in a cell in grounding scheme : ln_icb_area_mask = ', ln_icb_area_mask
+
+         WRITE(numout,*) '   Shift of sea-ice concentration in erosion flux modulation ',   &
+            &                    '(0<sicn_shift<1)    rn_sicn_shift  = ', rn_sicn_shift
+         WRITE(numout,*) '   Do not add freshwater flux from icebergs to ocean                ',   &
+            &                    '                  passive_mode            = ', ln_passive_mode
+         WRITE(numout,*) '   Time average the weight on the ocean   time_average_weight       = ', ln_time_average_weight
+         WRITE(numout,*) '   Create icebergs in absence of a restart file   nn_test_icebergs  = ', nn_test_icebergs
+         WRITE(numout,*) '                   in lon/lat box                                   = ', rn_test_box
+         WRITE(numout,*) '   Use calving data even if nn_test_icebergs > 0    ln_use_calving  = ', ln_use_calving
+         WRITE(numout,*) '   CFL speed limit for a berg            speed_limit                = ', rn_speed_limit
+         WRITE(numout,*) '   Writing Iceberg status information to icebergs.stat file        '
+      ENDIF
+      !
+      ! ensure that the sum of berg input distribution is equal to one
+      zfact = SUM( rn_distribution )
+      IF( zfact /= 1._wp .AND. 0_wp /= zfact ) THEN
+         rn_distribution(:) = rn_distribution(:) / zfact
+         IF(lwp) THEN
+            WRITE(numout,*)
+            WRITE(numout,*) '      ==>>> CAUTION:    sum of berg input distribution = ', zfact
+            WRITE(numout,*) '            *******     redistribution has been rescaled'
+            WRITE(numout,*) '                        updated berg distribution is :'
+            DO jn = 1, nclasses
+               WRITE(numout,'(a,f10.4)') '                                   ',rn_distribution(jn)
+            END DO
+         ENDIF
+      ENDIF
+      IF( MINVAL( rn_distribution(:) ) < 0._wp ) THEN
+         CALL ctl_stop( 'icb_nam: a negative rn_distribution value encountered ==>> change your namelist namberg' )
+      ENDIF
+      !
+   END SUBROUTINE icb_nam
+
+   !!======================================================================
+END MODULE icbini

+ 436 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbrst.F90

@@ -0,0 +1,436 @@
+MODULE icbrst
+   !!======================================================================
+   !!                       ***  MODULE  icbrst  ***
+   !! Ocean physics:  read and write iceberg restart files
+   !!======================================================================
+   !! History : 3.3.1 !  2010-01  (Martin&Adcroft) Original code
+   !!            -    !  2011-03  (Madec)          Part conversion to NEMO form
+   !!            -    !                            Removal of mapping from another grid
+   !!            -    !  2011-04  (Alderson)       Split into separate modules
+   !!            -    !  2011-04  (Alderson)       Restore restart routine
+   !!            -    !                            Currently needs a fixed processor
+   !!            -    !                            layout between restarts
+   !!            -    !  2015-11  Dave Storkey     Convert icb_rst_read to use IOM so can
+   !!                                              read single restart files
+   !!----------------------------------------------------------------------
+
+   !!----------------------------------------------------------------------
+   !!   icb_rst_read    : read restart file
+   !!   icb_rst_write   : write restart file
+   !!----------------------------------------------------------------------
+   USE par_oce        ! NEMO parameters
+   USE dom_oce        ! NEMO domain
+   USE in_out_manager ! NEMO IO routines
+   USE lib_mpp        ! NEMO MPI library, lk_mpp in particular
+   USE netcdf         ! netcdf routines for IO
+   USE iom
+   USE icb_oce        ! define iceberg arrays
+   USE icbutl         ! iceberg utility routines
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   icb_rst_read    ! routine called in icbini.F90 module
+   PUBLIC   icb_rst_write   ! routine called in icbstp.F90 module
+   
+   INTEGER ::   nlonid, nlatid, nxid, nyid, nuvelid, nvvelid
+   INTEGER ::   nmassid, nthicknessid, nwidthid, nlengthid
+   INTEGER ::   nyearid, ndayid
+   INTEGER ::   nscaling_id, nmass_of_bits_id, nheat_density_id, numberid
+   INTEGER ::   nsiceid, nsheatid, ncalvid, ncalvhid, nkountid, nvirtid
+   INTEGER ::   nret, ncid, nc_dim
+   
+   INTEGER,  DIMENSION(3)                  :: nstrt3, nlngth3
+
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: icbrst.F90 15088 2021-07-06 13:03:34Z acc $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   SUBROUTINE icb_rst_read()
+      !!----------------------------------------------------------------------
+      !!                 ***  SUBROUTINE icb_rst_read  ***
+      !!
+      !! ** Purpose :   read a iceberg restart file
+      !!      NB: for this version, we just read back in the restart for this processor
+      !!      so we cannot change the processor layout currently with iceberg code
+      !!----------------------------------------------------------------------
+      INTEGER                      ::   idim, ivar, iatt
+      INTEGER                      ::   jn, iunlim_dim, ibergs_in_file
+      INTEGER                      ::   ii, ij, iclass, ibase_err, imax_icb
+      REAL(wp), DIMENSION(nkounts) ::   zdata      
+      LOGICAL                      ::   ll_found_restart
+      CHARACTER(len=256)           ::   cl_path
+      CHARACTER(len=256)           ::   cl_filename
+      CHARACTER(len=NF90_MAX_NAME) ::   cl_dname
+      TYPE(iceberg)                ::   localberg ! NOT a pointer but an actual local variable
+      TYPE(point)                  ::   localpt   ! NOT a pointer but an actual local variable
+      !!----------------------------------------------------------------------
+      ! Find a restart file. Assume iceberg restarts in same directory as ocean restarts
+      ! and are called TRIM(cn_ocerst)//'_icebergs'
+      cl_path = TRIM(cn_icbrst_indir)
+      IF( cl_path(LEN_TRIM(cl_path):) /= '/' ) cl_path = TRIM(cl_path) // '/'
+      cl_filename = TRIM(cn_icbrst_in)
+      CALL iom_open( TRIM(cl_path)//cl_filename, ncid )
+
+      imax_icb = 0
+      IF( iom_file(ncid)%iduld .GE. 0) THEN
+
+         ibergs_in_file = iom_file(ncid)%lenuld
+         DO jn = 1,ibergs_in_file
+
+            ! iom_get treats the unlimited dimension as time. Here the unlimited dimension 
+            ! is the iceberg index, but we can still use the ktime keyword to get the iceberg we want. 
+
+            CALL iom_get( ncid, 'xi'     ,localpt%xi  , ktime=jn )
+            CALL iom_get( ncid, 'yj'     ,localpt%yj  , ktime=jn )
+
+            ii = INT( localpt%xi + 0.5 ) + ( nn_hls-1 )
+            ij = INT( localpt%yj + 0.5 ) + ( nn_hls-1 )
+            ! Only proceed if this iceberg is on the local processor (excluding halos).
+            IF ( ii >= mig(Nis0) .AND. ii <= mig(Nie0) .AND.   &
+           &     ij >= mjg(Njs0) .AND. ij <= mjg(Nje0) ) THEN           
+
+               CALL iom_get( ncid, jpdom_unknown, 'number', zdata(:) , ktime=jn, kstart=(/1/), kcount=(/nkounts/) )
+               localberg%number(:) = INT(zdata(:))
+               imax_icb = MAX( imax_icb, INT(zdata(1)) )
+               CALL iom_get( ncid, 'mass_scaling' , localberg%mass_scaling, ktime=jn )
+               CALL iom_get( ncid, 'lon'          , localpt%lon           , ktime=jn )
+               CALL iom_get( ncid, 'lat'          , localpt%lat           , ktime=jn )
+               CALL iom_get( ncid, 'uvel'         , localpt%uvel          , ktime=jn )
+               CALL iom_get( ncid, 'vvel'         , localpt%vvel          , ktime=jn )
+               CALL iom_get( ncid, 'mass'         , localpt%mass          , ktime=jn )
+               CALL iom_get( ncid, 'thickness'    , localpt%thickness     , ktime=jn )
+               CALL iom_get( ncid, 'width'        , localpt%width         , ktime=jn )
+               CALL iom_get( ncid, 'length'       , localpt%length        , ktime=jn )
+               CALL iom_get( ncid, 'year'         , zdata(1)              , ktime=jn )
+               localpt%year = INT(zdata(1))
+               CALL iom_get( ncid, 'day'          , localpt%day           , ktime=jn )
+               CALL iom_get( ncid, 'mass_of_bits' , localpt%mass_of_bits  , ktime=jn )
+               CALL iom_get( ncid, 'heat_density' , localpt%heat_density  , ktime=jn )
+               !
+               CALL icb_utl_add( localberg, localpt )
+               !
+            ENDIF
+            !
+         END DO
+         !
+      ELSE
+         ibergs_in_file = 0
+      ENDIF 
+
+      ! Gridded variables
+      CALL iom_get( ncid, jpdom_auto,    'calving'     , src_calving  )
+      CALL iom_get( ncid, jpdom_auto,    'calving_hflx', src_calving_hflx  )
+      CALL iom_get( ncid, jpdom_auto,    'stored_heat' , berg_grid%stored_heat  )
+      ! with jpdom_auto_xy, ue use only the third element of kstart and kcount.
+      CALL iom_get( ncid, jpdom_auto_xy, 'stored_ice'  , berg_grid%stored_ice, kstart=(/-99,-99,1/), kcount=(/-99,-99,nclasses/) )
+      
+      CALL iom_get( ncid, jpdom_unknown, 'kount' , zdata(:) )
+      num_bergs(:) = INT(zdata(:))
+      CALL iom_get( ncid, jpdom_auto,    'virtual_area'     , virtual_area  )
+      !
+
+      ! Sanity checks
+      jn = icb_utl_count()
+      IF ( lwp .AND. nn_verbose_level >= 0 )   &
+         WRITE(numout,'(2(a,i5))') 'icebergs, read_restart_bergs: # bergs =',jn,' on PE',narea-1
+      IF( lk_mpp ) THEN
+         ! Only mpp_sum ibergs_in_file if we are reading from multiple restart files. 
+         IF( INDEX(iom_file(ncid)%name,'icebergs.nc' ) .EQ. 0 ) CALL mpp_sum('icbrst', ibergs_in_file)
+         CALL mpp_sum('icbrst', jn)
+      ENDIF
+      IF( lwp )   WRITE(numout,'(a,i5,a,i5,a)') 'icebergs, icb_rst_read: there were',ibergs_in_file,   &
+         &                                    ' bergs in the restart file and', jn,' bergs have been read'
+      ! Close file
+      CALL iom_close( ncid )
+      !
+      ! Confirm that all areas have a suitable base for assigning new iceberg
+      ! numbers. This will not be the case if restarting from a collated dataset
+      ! (even if using the same processor decomposition)
+      !
+      ibase_err = 0
+      IF( num_bergs(1) < 0 .AND. num_bergs(1) /= narea - jpnij ) THEN
+         ! If this area has never calved a new berg then the base should be
+         ! set to narea - jpnij. If it is negative but something else then
+         ! a new base will be needed to guarantee unique, future iceberg numbers
+         ibase_err = 1
+      ELSEIF( MOD( num_bergs(1) - narea , jpnij ) /= 0 ) THEN
+         ! If this area has a base which is not in the set {narea + N*jpnij}
+         ! for positive integers N then a new base will be needed to guarantee 
+         ! unique, future iceberg numbers
+         ibase_err = 1
+      ENDIF
+      IF( lk_mpp ) THEN
+         CALL mpp_sum('icbrst', ibase_err)
+      ENDIF
+      IF( ibase_err > 0 ) THEN
+         ! 
+         ! A new base is needed. The only secure solution is to set bases such that
+         ! all future icebergs numbers will be greater than the current global maximum
+         IF( lk_mpp ) THEN
+            CALL mpp_max('icbrst', imax_icb)
+         ENDIF
+         num_bergs(1) = imax_icb - jpnij + narea
+      ENDIF
+      !
+      IF( lwp .AND. nn_verbose_level >= 0 )  WRITE(numout,'(a)') 'icebergs, icb_rst_read: completed'
+      !
+   END SUBROUTINE icb_rst_read
+
+
+   SUBROUTINE icb_rst_write( kt )
+      !!----------------------------------------------------------------------
+      !!                 ***  SUBROUTINE icb_rst_write  ***
+      !!
+      !!----------------------------------------------------------------------
+      INTEGER, INTENT( in ) :: kt
+      !
+      INTEGER ::   jn   ! dummy loop index
+      INTEGER ::   idg  ! number of digits
+      INTEGER ::   ix_dim, iy_dim, ik_dim, in_dim
+      CHARACTER(len=256)     :: cl_path
+      CHARACTER(len=256)     :: cl_filename
+      CHARACTER(len=8  )     :: cl_kt
+      CHARACTER(LEN=12 )     :: clfmt            ! writing format
+      TYPE(iceberg), POINTER :: this
+      TYPE(point)  , POINTER :: pt
+      !!----------------------------------------------------------------------
+
+      ! Following the normal restart procedure, this routine will be called
+      ! the timestep before a restart stage as well as the restart timestep.
+      ! This is a performance step enabling the file to be opened and contents
+      ! defined in advance of the write. This is not possible with icebergs
+      ! since the number of bergs to be written could change between timesteps
+      IF( kt == nitrst ) THEN
+         ! Only operate on the restart timestep itself.
+         ! Assume we write iceberg restarts to same directory as ocean restarts.
+         !
+         ! directory name
+         cl_path = TRIM(cn_icbrst_outdir)
+         IF( cl_path(LEN_TRIM(cl_path):) /= '/' ) cl_path = TRIM(cl_path) // '/'
+         !
+         ! file name
+         WRITE(cl_kt, '(i8.8)') kt
+         cl_filename = TRIM(cexper)//"_"//cl_kt//"_"//TRIM(cn_icbrst_out)
+         IF( lk_mpp ) THEN
+            idg = MAX( INT(LOG10(REAL(MAX(1,jpnij-1),wp))) + 1, 4 )          ! how many digits to we need to write? min=4, max=9
+            WRITE(clfmt, "('(a,a,i', i1, '.', i1, ',a)')") idg, idg          ! '(a,a,ix.x,a)'
+            WRITE(cl_filename,  clfmt) TRIM(cl_filename), '_', narea-1, '.nc'
+         ELSE
+            WRITE(cl_filename,'(a,a)') TRIM(cl_filename),               '.nc'
+         ENDIF
+
+         IF ( lwp .AND. nn_verbose_level >= 0) WRITE(numout,'(2a)') 'icebergs, write_restart: creating ',  &
+           &                                                         TRIM(cl_path)//TRIM(cl_filename)
+   
+         nret = NF90_CREATE(TRIM(cl_path)//TRIM(cl_filename), NF90_CLOBBER, ncid)
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_create failed')
+   
+         ! Dimensions
+         nret = NF90_DEF_DIM(ncid, 'x', Ni_0, ix_dim)
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_def_dim x failed')
+   
+         nret = NF90_DEF_DIM(ncid, 'y', Nj_0, iy_dim)
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_def_dim y failed')
+   
+         nret = NF90_DEF_DIM(ncid, 'c', nclasses, nc_dim)
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_def_dim c failed')
+   
+         nret = NF90_DEF_DIM(ncid, 'k', nkounts, ik_dim)
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_def_dim k failed')
+   
+         ! global attributes
+         IF( lk_mpp ) THEN
+            ! Set domain parameters (assume jpdom_local_full)
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_number_total'   , jpnij                        )
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_number'         , narea-1                      )
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_dimensions_ids' , (/ 1         , 2          /) )
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_size_global'    , (/ Ni0glo    , Nj0glo     /) )
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_size_local'     , (/ Ni_0      , Nj_0       /) )
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_position_first' , (/ mig0(Nis0), mjg0(Njs0) /) )
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_position_last'  , (/ mig0(Nie0), mjg0(Nje0) /) )
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_halo_size_start', (/ 0         , 0          /) )
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_halo_size_end'  , (/ 0         , 0          /) )
+            nret = NF90_PUT_ATT( ncid, NF90_GLOBAL, 'DOMAIN_type'           , 'BOX'                        )
+         ENDIF
+         
+         IF (associated(first_berg)) then
+            nret = NF90_DEF_DIM(ncid, 'n', NF90_UNLIMITED, in_dim)
+            IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_def_dim n failed')
+         ENDIF
+   
+         ! Variables
+         nret = NF90_DEF_VAR(ncid, 'kount'       , NF90_INT   , (/ ik_dim /), nkountid)
+         nret = NF90_DEF_VAR(ncid, 'calving'     , NF90_DOUBLE, (/ ix_dim, iy_dim /), ncalvid)
+         nret = NF90_DEF_VAR(ncid, 'calving_hflx', NF90_DOUBLE, (/ ix_dim, iy_dim /), ncalvhid)
+         nret = NF90_DEF_VAR(ncid, 'stored_ice'  , NF90_DOUBLE, (/ ix_dim, iy_dim, nc_dim /), nsiceid)
+         nret = NF90_DEF_VAR(ncid, 'stored_heat' , NF90_DOUBLE, (/ ix_dim, iy_dim /), nsheatid)
+	 nret = NF90_DEF_VAR(ncid, 'virtual_area', NF90_DOUBLE, (/ ix_dim, iy_dim /), nvirtid)
+   
+         ! Attributes
+         nret = NF90_PUT_ATT(ncid, ncalvid , 'long_name', 'iceberg calving')
+         nret = NF90_PUT_ATT(ncid, ncalvid , 'units', 'some')
+         nret = NF90_PUT_ATT(ncid, ncalvhid, 'long_name', 'heat flux associated with iceberg calving')
+         nret = NF90_PUT_ATT(ncid, ncalvhid, 'units', 'some')
+         nret = NF90_PUT_ATT(ncid, nsiceid , 'long_name', 'stored ice used to calve icebergs')
+         nret = NF90_PUT_ATT(ncid, nsiceid , 'units', 'kg/s')
+         nret = NF90_PUT_ATT(ncid, nsheatid, 'long_name', 'heat in stored ice used to calve icebergs')
+         nret = NF90_PUT_ATT(ncid, nsheatid, 'units', 'J/kg/s')
+	 nret = NF90_PUT_ATT(ncid, nvirtid, 'units', 'm2')
+	 nret = NF90_PUT_ATT(ncid, nvirtid, 'long_name', 'icebergs virtual area')
+   
+         IF ( ASSOCIATED(first_berg) ) THEN
+   
+            ! Only add berg variables for this PE if we have anything to say
+   
+            ! Variables
+            nret = NF90_DEF_VAR(ncid, 'lon', NF90_DOUBLE, in_dim, nlonid)
+            nret = NF90_DEF_VAR(ncid, 'lat', NF90_DOUBLE, in_dim, nlatid)
+            nret = NF90_DEF_VAR(ncid, 'xi', NF90_DOUBLE, in_dim, nxid)
+            nret = NF90_DEF_VAR(ncid, 'yj', NF90_DOUBLE, in_dim, nyid)
+            nret = NF90_DEF_VAR(ncid, 'uvel', NF90_DOUBLE, in_dim, nuvelid)
+            nret = NF90_DEF_VAR(ncid, 'vvel', NF90_DOUBLE, in_dim, nvvelid)
+            nret = NF90_DEF_VAR(ncid, 'mass', NF90_DOUBLE, in_dim, nmassid)
+            nret = NF90_DEF_VAR(ncid, 'thickness', NF90_DOUBLE, in_dim, nthicknessid)
+            nret = NF90_DEF_VAR(ncid, 'width', NF90_DOUBLE, in_dim, nwidthid)
+            nret = NF90_DEF_VAR(ncid, 'length', NF90_DOUBLE, in_dim, nlengthid)
+            nret = NF90_DEF_VAR(ncid, 'number', NF90_INT, (/ik_dim,in_dim/), numberid)
+            nret = NF90_DEF_VAR(ncid, 'year', NF90_INT, in_dim, nyearid)
+            nret = NF90_DEF_VAR(ncid, 'day', NF90_DOUBLE, in_dim, ndayid)
+            nret = NF90_DEF_VAR(ncid, 'mass_scaling', NF90_DOUBLE, in_dim, nscaling_id)
+            nret = NF90_DEF_VAR(ncid, 'mass_of_bits', NF90_DOUBLE, in_dim, nmass_of_bits_id)
+            nret = NF90_DEF_VAR(ncid, 'heat_density', NF90_DOUBLE, in_dim, nheat_density_id)
+   
+            ! Attributes
+            nret = NF90_PUT_ATT(ncid, nlonid, 'long_name', 'longitude')
+            nret = NF90_PUT_ATT(ncid, nlonid, 'units', 'degrees_E')
+            nret = NF90_PUT_ATT(ncid, nlatid, 'long_name', 'latitude')
+            nret = NF90_PUT_ATT(ncid, nlatid, 'units', 'degrees_N')
+            nret = NF90_PUT_ATT(ncid, nxid, 'long_name', 'x grid box position')
+            nret = NF90_PUT_ATT(ncid, nxid, 'units', 'fractional')
+            nret = NF90_PUT_ATT(ncid, nyid, 'long_name', 'y grid box position')
+            nret = NF90_PUT_ATT(ncid, nyid, 'units', 'fractional')
+            nret = NF90_PUT_ATT(ncid, nuvelid, 'long_name', 'zonal velocity')
+            nret = NF90_PUT_ATT(ncid, nuvelid, 'units', 'm/s')
+            nret = NF90_PUT_ATT(ncid, nvvelid, 'long_name', 'meridional velocity')
+            nret = NF90_PUT_ATT(ncid, nvvelid, 'units', 'm/s')
+            nret = NF90_PUT_ATT(ncid, nmassid, 'long_name', 'mass')
+            nret = NF90_PUT_ATT(ncid, nmassid, 'units', 'kg')
+            nret = NF90_PUT_ATT(ncid, nthicknessid, 'long_name', 'thickness')
+            nret = NF90_PUT_ATT(ncid, nthicknessid, 'units', 'm')
+            nret = NF90_PUT_ATT(ncid, nwidthid, 'long_name', 'width')
+            nret = NF90_PUT_ATT(ncid, nwidthid, 'units', 'm')
+            nret = NF90_PUT_ATT(ncid, nlengthid, 'long_name', 'length')
+            nret = NF90_PUT_ATT(ncid, nlengthid, 'units', 'm')
+            nret = NF90_PUT_ATT(ncid, numberid, 'long_name', 'iceberg number on this processor')
+            nret = NF90_PUT_ATT(ncid, numberid, 'units', 'count')
+            nret = NF90_PUT_ATT(ncid, nyearid, 'long_name', 'calendar year of calving event')
+            nret = NF90_PUT_ATT(ncid, nyearid, 'units', 'years')
+            nret = NF90_PUT_ATT(ncid, ndayid, 'long_name', 'year day of calving event')
+            nret = NF90_PUT_ATT(ncid, ndayid, 'units', 'days')
+            nret = NF90_PUT_ATT(ncid, nscaling_id, 'long_name', 'scaling factor for mass of calving berg')
+            nret = NF90_PUT_ATT(ncid, nscaling_id, 'units', 'none')
+            nret = NF90_PUT_ATT(ncid, nmass_of_bits_id, 'long_name', 'mass of bergy bits')
+            nret = NF90_PUT_ATT(ncid, nmass_of_bits_id, 'units', 'kg')
+            nret = NF90_PUT_ATT(ncid, nheat_density_id, 'long_name', 'heat density')
+            nret = NF90_PUT_ATT(ncid, nheat_density_id, 'units', 'J/kg')
+   
+         ENDIF ! associated(first_berg)
+   
+         ! End define mode
+         nret = NF90_ENDDEF(ncid)
+   
+         ! --------------------------------
+         ! now write some data
+   
+         nstrt3(1) = 1
+         nstrt3(2) = 1
+         nlngth3(1) = Ni_0
+         nlngth3(2) = Nj_0
+         nlngth3(3) = 1
+   
+         DO jn=1,nclasses
+            nstrt3(3) = jn
+            nret = NF90_PUT_VAR( ncid, nsiceid, berg_grid%stored_ice(Nis0:Nie0,Njs0:Nje0,jn), nstrt3, nlngth3 )
+            IF (nret .ne. NF90_NOERR) THEN
+               IF( lwp ) WRITE(numout,*) TRIM(NF90_STRERROR( nret ))
+               CALL ctl_stop('icebergs, write_restart: nf_put_var stored_ice failed')
+            ENDIF
+         ENDDO
+         IF( lwp ) WRITE(numout,*) 'file: ',TRIM(cl_path)//TRIM(cl_filename),' var: stored_ice  written'
+   
+         nret = NF90_PUT_VAR( ncid, nkountid, num_bergs(:) )
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_put_var kount failed')
+   
+         nret = NF90_PUT_VAR( ncid, nsheatid, berg_grid%stored_heat(Nis0:Nie0,Njs0:Nje0) )
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_put_var stored_heat failed')
+         IF( lwp ) WRITE(numout,*) 'file: ',TRIM(cl_path)//TRIM(cl_filename),' var: stored_heat written'
+   
+         nret = NF90_PUT_VAR( ncid, ncalvid , src_calving(Nis0:Nie0,Njs0:Nje0) )
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_put_var calving failed')
+         nret = NF90_PUT_VAR( ncid, ncalvhid, src_calving_hflx(Nis0:Nie0,Njs0:Nje0) )
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_put_var calving_hflx failed')
+         IF( lwp ) WRITE(numout,*) 'file: ',TRIM(cl_path)//TRIM(cl_filename),' var: calving written'
+	 
+	 nret = NF90_PUT_VAR( ncid, nvirtid, virtual_area(Nis0:Nie0,Njs0:Nje0) )
+         IF (nret .ne. NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_put_var virtual_area failed')
+         IF( lwp ) WRITE(numout,*) 'file: ',TRIM(cl_path)//TRIM(cl_filename),' var: virtual_area written'
+   
+         IF ( ASSOCIATED(first_berg) ) THEN
+   
+            ! Write variables
+            ! just write out the current point of the trajectory
+   
+            this => first_berg
+            jn = 0
+            DO WHILE (ASSOCIATED(this))
+               pt => this%current_point
+               jn=jn+1
+   
+               nret = NF90_PUT_VAR(ncid, numberid, this%number, (/1,jn/), (/nkounts,1/) )
+               nret = NF90_PUT_VAR(ncid, nscaling_id, this%mass_scaling, (/ jn /) )
+   
+               nret = NF90_PUT_VAR(ncid, nlonid, pt%lon, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nlatid, pt%lat, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nxid, pt%xi, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nyid, pt%yj, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nuvelid, pt%uvel, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nvvelid, pt%vvel, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nmassid, pt%mass, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nthicknessid, pt%thickness, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nwidthid, pt%width, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nlengthid, pt%length, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nyearid, pt%year, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, ndayid, pt%day, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nmass_of_bits_id, pt%mass_of_bits, (/ jn /) )
+               nret = NF90_PUT_VAR(ncid, nheat_density_id, pt%heat_density, (/ jn /) )
+   
+               this=>this%next
+            END DO
+            !
+         ENDIF ! associated(first_berg)
+   
+         ! Finish up
+         nret = NF90_CLOSE(ncid)
+         IF (nret /= NF90_NOERR) CALL ctl_stop('icebergs, write_restart: nf_close failed')
+   
+         ! Sanity check
+         jn = icb_utl_count()
+         IF ( lwp .AND. nn_verbose_level >= 0)   &
+            WRITE(numout,'(2(a,i5))') 'icebergs, icb_rst_write: # bergs =',jn,' on PE',narea-1
+         IF( lk_mpp ) THEN
+            CALL mpp_sum('icbrst', jn)
+         ENDIF
+         IF(lwp)   WRITE(numout,'(a,i5,a,i5,a)') 'icebergs, icb_rst_write: ', jn,   &
+            &                                    ' bergs in total have been written at timestep ', kt
+         !
+         ! Finish up
+         !
+      ENDIF
+   END SUBROUTINE icb_rst_write
+   !
+   !!======================================================================
+END MODULE icbrst

+ 182 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbstp.F90

@@ -0,0 +1,182 @@
+MODULE icbstp
+   !!======================================================================
+   !!                       ***  MODULE  icbstp  ***
+   !! Icebergs:  initialise variables for iceberg tracking
+   !!======================================================================
+   !! History : 3.3.1 !  2010-01  (Martin&Adcroft) Original code
+   !!            -    !  2011-03  (Madec)          Part conversion to NEMO form
+   !!            -    !                            Removal of mapping from another grid
+   !!            -    !  2011-04  (Alderson)       Split into separate modules
+   !!            -    !                            Move budgets to icbdia routine
+   !!            -    !  2011-05  (Alderson)       Add call to copy forcing arrays
+   !!            -    !                            into icb copies with haloes
+   !!----------------------------------------------------------------------
+
+   !!----------------------------------------------------------------------
+   !!   icb_stp       : start iceberg tracking
+   !!   icb_end       : end   iceberg tracking
+   !!----------------------------------------------------------------------
+   USE par_oce        ! nemo parameters
+   USE dom_oce        ! ocean domain
+   USE sbc_oce        ! ocean surface forcing
+   USE phycst         ! physical constants
+   !
+   USE icb_oce        ! iceberg: define arrays
+   USE icbini         ! iceberg: initialisation routines
+   USE icbutl         ! iceberg: utility routines
+   USE icbrst         ! iceberg: restart routines
+   USE icbdyn         ! iceberg: dynamics (ie advection) routines
+   USE icbclv         ! iceberg: calving routines
+   USE icbthm         ! iceberg: thermodynamics routines
+   USE icblbc         ! iceberg: lateral boundary routines (including mpp)
+   USE icbtrj         ! iceberg: trajectory I/O routines
+   USE icbdia         ! iceberg: budget
+   !
+   USE in_out_manager ! nemo IO
+   USE lib_mpp        ! massively parallel library 
+   USE iom            ! I/O manager
+   USE fldread        ! field read
+   USE timing         ! timing
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   icb_stp        ! routine called in sbcmod.F90 module
+   PUBLIC   icb_end        ! routine called in nemogcm.F90 module
+
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: icbstp.F90 14239 2020-12-23 08:57:16Z smasson $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   SUBROUTINE icb_stp( kt, Kmm )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE icb_stp  ***
+      !!
+      !! ** Purpose :   iceberg time stepping.
+      !!
+      !! ** Method  : - top level routine to do things in the correct order
+      !!----------------------------------------------------------------------
+      INTEGER, INTENT(in) ::   kt   ! time step index
+      INTEGER, INTENT(in) ::   Kmm  ! ocean time level index
+      !
+      LOGICAL ::   ll_sample_traj, ll_budget, ll_verbose   ! local logical
+      !!----------------------------------------------------------------------
+      !
+      IF( ln_timing )   CALL timing_start('icb_stp')
+
+      !                       !==  start of timestep housekeeping  ==!
+      !
+      nktberg = kt
+      !
+      !CALL test_icb_utl_getkb
+      !CALL ctl_stop('end test icb')
+      !
+      IF( nn_test_icebergs < 0 .OR. ln_use_calving ) THEN !* read calving data
+         !
+         CALL fld_read ( kt, 1, sf_icb )
+         src_calving     (:,:) = sf_icb(1)%fnow(:,:,1)    ! calving in km^3/year (water equivalent)
+         src_calving_hflx(:,:) = 0._wp                    ! NO heat flux for now
+         !
+      ENDIF
+      !
+      berg_grid%floating_melt(:,:) = 0._wp
+      !
+      !                                   !* anything that needs to be reset to zero each timestep 
+      CALL icb_dia_step()                 !  for budgets is dealt with here
+      !
+      !                                   !* write out time
+      ll_verbose = .FALSE.
+      IF( nn_verbose_write > 0 .AND. MOD( kt-1 , nn_verbose_write ) == 0 )   ll_verbose = ( nn_verbose_level > 0 )
+      !
+      IF( ll_verbose )   WRITE(numicb,9100) nktberg, ndastp, nsec_day
+ 9100 FORMAT('kt= ',i8, ' day= ',i8,' secs=',i8)
+      !
+      !                                   !* copy nemo forcing arrays into iceberg versions with extra halo
+      CALL icb_utl_copy( Kmm )                 ! only necessary for variables not on T points
+      !
+      !
+      !                       !==  process icebergs  ==!
+      !                              !
+                                     CALL icb_clv_flx( kt )   ! Accumulate ice from calving
+      !                              !
+                                     CALL icb_clv( kt )       ! Calve excess stored ice into icebergs
+      !                              !
+      !
+      !                       !==  For each berg, evolve  ==!
+      !
+      IF( ASSOCIATED(first_berg) )   CALL icb_dyn( kt )       ! ice berg dynamics
+
+      IF( lk_mpp ) THEN   ;          CALL icb_lbc_mpp()       ! Send bergs to other PEs
+      ELSE                ;          CALL icb_lbc()           ! Deal with any cyclic boundaries in non-mpp case
+      ENDIF
+      !
+      ! reset virtual area to 0 here
+      virtual_area = 0._wp
+      IF( ASSOCIATED(first_berg) )   CALL icb_thm( kt )       ! Ice berg thermodynamics (melting) + rolling
+      virtual_area_e(1:jpi,1:jpj)=virtual_area(:,:)
+      CALL lbc_lnk_icb( 'icbthm', virtual_area_e, 'T', +1._wp, 1, 1 )
+      !
+      !
+      !
+      !                       !==  diagnostics and output  ==!
+      !
+      !                                   !* For each berg, record trajectory (when needed)
+      ll_sample_traj = .FALSE.
+      IF( nn_sample_rate > 0 .AND. MOD(kt-1,nn_sample_rate) == 0 )   ll_sample_traj = .TRUE.
+      IF( ll_sample_traj .AND. ASSOCIATED(first_berg) )   CALL icb_trj_write( kt )
+
+      !                                   !* Gridded diagnostics
+      !                                   !  To get these iom_put's and those preceding to actually do something
+      !                                   !  use key_xios in cpp file and create content for XML file
+      !
+      CALL iom_put( "calving"           , berg_grid%calving      (:,:)   )  ! 'calving mass input'
+      CALL iom_put( "berg_floating_melt", berg_grid%floating_melt(:,:)   )  ! 'Melt rate of icebergs + bits' , 'kg/m2/s'
+      CALL iom_put( "berg_stored_ice"   , berg_grid%stored_ice   (:,:,:) )  ! 'Accumulated ice mass by class', 'kg'
+      !
+      CALL icb_dia_put()                  !* store mean budgets
+      !
+      !                                   !*  Dump icebergs to screen
+      IF( nn_verbose_level >= 2 )   CALL icb_utl_print( 'icb_stp, status', kt )
+      !
+      !                                   !* Diagnose budgets
+      ll_budget = .FALSE.
+      IF( nn_verbose_write > 0 .AND. MOD(kt-1,nn_verbose_write) == 0 )   ll_budget = ln_bergdia
+      CALL icb_dia( ll_budget )
+      !
+      IF( lrst_oce ) THEN    !* restart
+         CALL icb_rst_write( kt )
+         IF( nn_sample_rate > 0 )   CALL icb_trj_sync()
+      ENDIF
+      !
+      IF( ln_timing )   CALL timing_stop('icb_stp')
+      !
+   END SUBROUTINE icb_stp
+
+
+   SUBROUTINE icb_end( kt )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE icb_end  ***
+      !!
+      !! ** Purpose :   close iceberg files
+      !!
+      !!----------------------------------------------------------------------
+      INTEGER, INTENT( in )  ::   kt   ! model time-step index
+      !!----------------------------------------------------------------------
+      !
+      ! finish with trajectories if they were written
+      IF( nn_sample_rate > 0 )   CALL icb_trj_end()
+
+      IF(lwp) WRITE(numout,'(a,i6)') 'icebergs: icb_end complete', narea
+      !
+      IF( nn_verbose_level > 0 ) THEN
+         CALL flush( numicb )
+         CLOSE( numicb )
+      ENDIF
+      !
+   END SUBROUTINE icb_end
+
+   !!======================================================================
+END MODULE icbstp

+ 312 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/icbthm.F90

@@ -0,0 +1,312 @@
+MODULE icbthm
+   !!======================================================================
+   !!                       ***  MODULE  icbthm  ***
+   !! Icebergs:  thermodynamics routines for icebergs
+   !!======================================================================
+   !! History : 3.3.1 !  2010-01  (Martin&Adcroft) Original code
+   !!            -    !  2011-03  (Madec)          Part conversion to NEMO form
+   !!            -    !                            Removal of mapping from another grid
+   !!            -    !  2011-04  (Alderson)       Split into separate modules
+   !!            -    !  2011-05  (Alderson)       Use tmask instead of tmask_i
+   !!----------------------------------------------------------------------
+   !!----------------------------------------------------------------------
+   !!   icb_thm : initialise
+   !!             reference for equations - M = Martin + Adcroft, OM 34, 2010
+   !!----------------------------------------------------------------------
+   USE par_oce        ! NEMO parameters
+   USE dom_oce        ! NEMO domain
+   USE in_out_manager ! NEMO IO routines, numout in particular
+   USE lib_mpp        ! NEMO MPI routines, ctl_stop in particular
+   USE phycst         ! NEMO physical constants
+   USE sbc_oce
+   USE eosbn2         ! equation of state
+   USE lib_fortran, ONLY : DDPDD
+   USE bdy_oce, ONLY : bdytmask,ln_bdy
+
+   USE icb_oce        ! define iceberg arrays
+   USE icbutl         ! iceberg utility routines
+   USE icbdia         ! iceberg budget routines
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   icb_thm ! routine called in icbstp.F90 module
+
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: icbthm.F90 15088 2021-07-06 13:03:34Z acc $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   SUBROUTINE icb_thm( kt )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE icb_thm  ***
+      !!
+      !! ** Purpose :   compute the iceberg thermodynamics.
+      !!
+      !! ** Method  : - See Martin & Adcroft, Ocean Modelling 34, 2010
+      !!----------------------------------------------------------------------
+      INTEGER, INTENT(in) ::   kt   ! timestep number, just passed to icb_utl_print_berg
+      !
+      INTEGER  ::   ii, ij, jk, ikb
+      REAL(wp) ::   zM, zT, zW, zL, zSST, zVol, zLn, zWn, zTn, znVol, zIC, zDn, zD, zvb, zub, ztb
+      REAL(wp) ::   zMv, zMe, zMb, zmelt, zdvo, zdvob, zdva, zdM, zSs, zdMe, zdMb, zdMv
+      REAL(wp) ::   zSSS, zfzpt
+      REAL(wp) ::   zMnew, zMnew1, zMnew2, zheat_hcflux, zheat_latent, z1_12
+      REAL(wp) ::   zMbits, znMbits, zdMbitsE, zdMbitsM, zLbits, zAbits, zMbb
+      REAL(wp) ::   zxi, zyj, zff, z1_rday, z1_e1e2, zdt, z1_dt, z1_dt_e1e2, zdepw
+      REAL(wp), DIMENSION(jpk) :: ztoce, zuoce, zvoce, ze3t, zzMv
+      TYPE(iceberg), POINTER ::   this, next
+      TYPE(point)  , POINTER ::   pt
+      !
+      COMPLEX(dp), DIMENSION(jpi,jpj) :: cicb_melt, cicb_hflx
+      !!----------------------------------------------------------------------
+      !
+      !! initialiaze cicb_melt and cicb_heat
+      cicb_melt = CMPLX( 0.e0, 0.e0, dp ) 
+      cicb_hflx = CMPLX( 0.e0, 0.e0, dp ) 
+      !
+      z1_rday = 1._wp / rday
+      z1_12   = 1._wp / 12._wp
+      zdt     = berg_dt
+      z1_dt   = 1._wp / zdt
+      !
+      ! we're either going to ignore berg fresh water melt flux and associated heat
+      ! or we pass it into the ocean, so at this point we set them both to zero,
+      ! accumulate the contributions to them from each iceberg in the while loop following
+      ! and then pass them (or not) to the ocean
+      !
+      berg_grid%floating_melt(:,:) = 0._wp
+      ! calving_hflx re-used here as temporary workspace for the heat flux associated with melting
+      berg_grid%calving_hflx(:,:)  = 0._wp
+      !
+      ! virtual area set to 0
+      virtual_area(:,:)= 0._wp
+      virtual_area_e(:,:)= 0._wp
+      !
+      this => first_berg
+      DO WHILE( ASSOCIATED(this) )
+         !
+         pt => this%current_point
+         nknberg = this%number(1)
+
+         CALL icb_utl_interp( pt%xi, pt%yj,            &   ! position
+             &                 pssu=pt%ssu, pua=pt%ua, &   ! oce/atm velocities
+             &                 pssv=pt%ssv, pva=pt%va, &   ! oce/atm velocities
+             &                 psst=pt%sst, pcn=pt%cn, &
+             &                 psss=pt%sss             )
+
+         IF ( nn_sample_rate > 0 .AND. MOD(kt-1,nn_sample_rate) == 0 ) THEN
+            CALL icb_utl_interp( pt%xi, pt%yj, pe1=pt%e1, pe2=pt%e2,                 &
+               &                 pui=pt%ui, pssh_i=pt%ssh_x, &
+               &                 pvi=pt%vi, pssh_j=pt%ssh_y, &
+               &                 phi=pt%hi,                  &
+               &                 plat=pt%lat, plon=pt%lon )
+         END IF
+         !
+         zSST = pt%sst
+         zSSS = pt%sss
+         CALL eos_fzp(zSSS,zfzpt)                       ! freezing point
+         zIC  = MIN( 1._wp, pt%cn + rn_sicn_shift )     ! Shift sea-ice concentration       !!gm ???
+         zM   = pt%mass
+         zT   = pt%thickness                               ! total thickness
+         zD   = rho_berg_1_oce * zT                        ! draught (keel depth)
+         zW   = pt%width
+         zL   = pt%length
+         zxi  = pt%xi                                      ! position in (i,j) referential
+         zyj  = pt%yj
+         ii  = INT( zxi + 0.5 )                            ! T-cell of the berg
+         ii  = mi1( ii + (nn_hls-1) )
+         ij  = INT( zyj + 0.5 )              
+         ij  = mj1( ij + (nn_hls-1) )
+         zVol = zT * zW * zL
+
+         ! Environment
+         ! default sst, ssu and ssv
+         ! ln_M2016: use temp, u and v profile
+         IF ( ln_M2016 ) THEN
+
+            ! load t, u, v and e3 profile at icb position
+            CALL icb_utl_interp( pt%xi, pt%yj, ptoce=ztoce, puoce=zuoce, pvoce=zvoce, pe3t=ze3t )
+            
+            !compute bottom level
+            CALL icb_utl_getkb( pt%kb, ze3t, zD )
+
+            ikb = MIN(pt%kb,mbkt(ii,ij))                             ! limit pt%kb by mbkt 
+                                                                     ! => bottom temperature used to fill ztoce(mbkt:jpk)
+            ztb = ztoce(ikb)                                         ! basal temperature
+            zub = zuoce(ikb)
+            zvb = zvoce(ikb)
+         ELSE
+            ztb = pt%sst
+            zub = pt%ssu
+            zvb = pt%ssv
+         END IF
+
+         zdvob = SQRT( (pt%uvel-zub)**2 + (pt%vvel-zvb)**2 )        ! relative basal velocity
+         zdva  = SQRT( (pt%ua  -pt%ssu)**2 + (pt%va  -pt%ssv)**2 )  ! relative wind
+         zSs   = 1.5_wp * SQRT( zdva ) + 0.1_wp * zdva              ! Sea state      (eqn M.A9)
+         !
+         ! Melt rates in m/s (i.e. division by rday)
+         ! Buoyant convection at sides (eqn M.A10)
+         IF ( ln_M2016 ) THEN
+            ! averaging along all the iceberg draft
+            zzMv(:) = MAX( 7.62d-3*ztoce(:)+1.29d-3*(ztoce(:)**2), 0._wp ) * z1_rday
+            CALL icb_utl_zavg(zMv, zzMv, ze3t, zD, ikb )
+         ELSE
+            zMv = MAX( 7.62d-3*zSST+1.29d-3*(zSST**2), 0._wp ) * z1_rday
+         END IF
+         !
+         ! Basal turbulent melting     (eqn M.A7 )
+         IF ( zSST > zfzpt ) THEN                                                              ! Calculate basal melting only if SST above freezing point  
+            zMb = MAX( 0.58_wp*(zdvob**0.8_wp)*(ztb+4.0_wp)/(zL**0.2_wp) , 0._wp ) * z1_rday
+         ELSE
+            zMb = 0._wp                                                                        ! No basal melting if SST below freezing point     
+         ENDIF
+         !
+         ! Wave erosion                (eqn M.A8 )
+         zMe = MAX( z1_12*(zSST+2.)*zSs*(1._wp+COS(rpi*(zIC**3)))     , 0._wp ) * z1_rday
+
+         IF( ln_operator_splitting ) THEN      ! Operator split update of volume/mass
+            zTn    = MAX( zT - zMb*zdt , 0._wp )         ! new total thickness (m)
+            znVol  = zTn * zW * zL                       ! new volume (m^3)
+            zMnew1 = ( znVol / zVol ) * zM               ! new mass (kg)
+            zdMb   = zM - zMnew1                         ! mass lost to basal melting (>0) (kg)
+            !
+            zLn    = MAX( zL - zMv*zdt , 0._wp )         ! new length (m)
+            zWn    = MAX( zW - zMv*zdt , 0._wp )         ! new width (m)
+            znVol  = zTn * zWn * zLn                     ! new volume (m^3)
+            zMnew2 = ( znVol / zVol ) * zM               ! new mass (kg)
+            zdMv   = zMnew1 - zMnew2                     ! mass lost to buoyant convection (>0) (kg)
+            !
+            zLn    = MAX( zLn - zMe*zdt , 0._wp )        ! new length (m)
+            zWn    = MAX( zWn - zMe*zdt , 0._wp )        ! new width (m)
+            znVol  = zTn * zWn * zLn                     ! new volume (m^3)
+            zMnew  = ( znVol / zVol ) * zM               ! new mass (kg)
+            zdMe   = zMnew2 - zMnew                      ! mass lost to erosion (>0) (kg)
+            zdM    = zM - zMnew                          ! mass lost to all erosion and melting (>0) (kg)
+            !
+         ELSE                                         ! Update dimensions of berg
+            zLn = MAX( zL -(zMv+zMe)*zdt ,0._wp )        ! (m)
+            zWn = MAX( zW -(zMv+zMe)*zdt ,0._wp )        ! (m)
+            zTn = MAX( zT - zMb    *zdt ,0._wp )         ! (m)
+            ! Update volume and mass of berg
+            znVol = zTn*zWn*zLn                          ! (m^3)
+            zMnew = (znVol/zVol)*zM                      ! (kg)
+            zdM   = zM - zMnew                           ! (kg)
+            zdMb = (zM/zVol) * (zW*   zL ) *zMb*zdt      ! approx. mass loss to basal melting (kg)
+            zdMe = (zM/zVol) * (zT*(zW+zL)) *zMe*zdt     ! approx. mass lost to erosion (kg)
+            zdMv = (zM/zVol) * (zT*(zW+zL)) *zMv*zdt     ! approx. mass loss to buoyant convection (kg)
+         ENDIF
+
+         IF( rn_bits_erosion_fraction > 0._wp ) THEN     ! Bergy bits
+            !
+            zMbits   = pt%mass_of_bits                                               ! mass of bergy bits (kg)
+            zdMbitsE = rn_bits_erosion_fraction * zdMe                               ! change in mass of bits (kg)
+            znMbits  = zMbits + zdMbitsE                                             ! add new bergy bits to mass (kg)
+            zLbits   = MIN( zL, zW, zT, 40._wp )                                     ! assume bergy bits are smallest dimension or 40 meters
+            zAbits   = ( zMbits / rn_rho_bergs ) / zLbits                            ! Effective bottom area (assuming T=Lbits)
+            zMbb     = MAX( 0.58_wp*(zdvob**0.8_wp)*(zSST+2._wp) /   &
+               &                              ( zLbits**0.2_wp ) , 0._wp ) * z1_rday ! Basal turbulent melting (for bits)
+            zMbb     = rn_rho_bergs * zAbits * zMbb                                  ! in kg/s
+            zdMbitsM = MIN( zMbb*zdt , znMbits )                                     ! bergy bits mass lost to melting (kg)
+            znMbits  = znMbits-zdMbitsM                                              ! remove mass lost to bergy bits melt
+            IF( zMnew == 0._wp ) THEN                                                ! if parent berg has completely melted then
+               zdMbitsM = zdMbitsM + znMbits                                         ! instantly melt all the bergy bits
+               znMbits  = 0._wp
+            ENDIF
+         ELSE                                                     ! No bergy bits
+            zAbits   = 0._wp
+            zdMbitsE = 0._wp
+            zdMbitsM = 0._wp
+            znMbits  = pt%mass_of_bits                             ! retain previous value incase non-zero
+         ENDIF
+
+         ! use tmask rather than tmask_i when dealing with icebergs
+         IF( tmask(ii,ij,1) /= 0._wp ) THEN    ! Add melting to the grid and field diagnostics
+            z1_e1e2    = r1_e1e2t(ii,ij) * this%mass_scaling
+            z1_dt_e1e2 = z1_dt * z1_e1e2
+            !
+            ! iceberg melt
+            !! the use of DDPDD function for the cumulative sum is needed for reproducibility
+            zmelt    = ( zdM - ( zdMbitsE - zdMbitsM ) ) * z1_dt   ! kg/s
+            CALL DDPDD( CMPLX( zmelt * z1_e1e2, 0.e0, dp ), cicb_melt(ii,ij) )
+            !
+            ! iceberg heat flux
+            !! the use of DDPDD function for the cumulative sum is needed for reproducibility
+            !! NB. The src_calving_hflx field is currently hardwired to zero in icb_stp, which means that the
+            !!     heat density of the icebergs is zero and the heat content flux to the ocean from iceberg
+            !!     melting is always zero. Leaving the term in the code until such a time as this is fixed. DS.
+            zheat_hcflux = zmelt * pt%heat_density       ! heat content flux : kg/s x J/kg = J/s
+            zheat_latent = - zmelt * rLfus               ! latent heat flux:  kg/s x J/kg = J/s
+            CALL DDPDD( CMPLX( ( zheat_hcflux + zheat_latent ) * z1_e1e2, 0.e0, dp ), cicb_hflx(ii,ij) )
+            !
+            ! diagnostics
+            CALL icb_dia_melt( ii, ij, zMnew, zheat_hcflux, zheat_latent, this%mass_scaling,       &
+               &                       zdM, zdMbitsE, zdMbitsM, zdMb, zdMe,   &
+               &                       zdMv, z1_dt_e1e2, z1_e1e2 )
+         ELSE
+            WRITE(numout,*) 'icb_thm: berg ',this%number(:),' appears to have grounded  at ',narea,ii,ij
+            CALL icb_utl_print_berg( this, kt )
+            WRITE(numout,*) 'msk=',tmask(ii,ij,1), e1e2t(ii,ij)
+            CALL ctl_stop('icb_thm', 'berg appears to have grounded!')
+         ENDIF
+
+         ! Rolling
+         zDn = rho_berg_1_oce * zTn       ! draught (keel depth)
+         IF( zDn > 0._wp .AND. MAX(zWn,zLn) < SQRT( 0.92*(zDn**2) + 58.32*zDn ) ) THEN
+            zT  = zTn
+            zTn = zWn
+            zWn = zT
+         ENDIF
+
+         ! Store the new state of iceberg (with L>W)
+         pt%mass         = zMnew
+         pt%mass_of_bits = znMbits
+         pt%thickness    = zTn
+         pt%width        = MIN( zWn , zLn )
+         pt%length       = MAX( zWn , zLn )
+
+         next=>this%next
+
+!!gm  add a test to avoid over melting ?
+!!pm  I agree, over melting could break conservation (more melt than calving)
+
+         IF( zMnew <= 0._wp ) THEN       ! Delete the berg if completely melted
+            CALL icb_utl_delete( first_berg, this )
+            !
+         ELSE IF (ln_bdy .AND. bdytmask(ii,ij)==0.) THEN !!pm + CK remove icb if at bdy
+	 
+	     CALL icb_utl_delete( first_berg, this )
+	 
+	 ELSE                             ! Diagnose mass distribution on grid
+            z1_e1e2 = r1_e1e2t(ii,ij) * this%mass_scaling
+            CALL icb_dia_size( ii, ij, zWn, zLn, zAbits,   &
+               &               this%mass_scaling, zMnew, znMbits, z1_e1e2 )
+            ! 
+            !                            ! diagnose virtual area on grid (ln_icb_area_mask or ln_icb_diag)
+            virtual_area(ii,ij) = virtual_area(ii,ij) + ( zWn * zLn + zAbits ) * this%mass_scaling      ! m^2
+            !	       
+         ENDIF
+         !
+	 
+	 
+         this=>next
+         !
+      END DO
+      !
+      berg_grid%floating_melt = REAL(cicb_melt,dp)    ! kg/m2/s
+      berg_grid%calving_hflx  = REAL(cicb_hflx,dp)
+      !
+      ! now use melt and associated heat flux in ocean (or not)
+      !
+      IF(.NOT. ln_passive_mode ) THEN
+         emp (:,:) = emp (:,:) - berg_grid%floating_melt(:,:)
+         qns (:,:) = qns (:,:) + berg_grid%calving_hflx (:,:)  
+      ENDIF
+      !
+   END SUBROUTINE icb_thm
+
+   !!======================================================================
+END MODULE icbthm

+ 1525 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/sbcblk.F90

@@ -0,0 +1,1525 @@
+MODULE sbcblk
+   !!======================================================================
+   !!                       ***  MODULE  sbcblk  ***
+   !! Ocean forcing:  momentum, heat and freshwater flux formulation
+   !!                         Aerodynamic Bulk Formulas
+   !!                        SUCCESSOR OF "sbcblk_core"
+   !!=====================================================================
+   !! History :  1.0  !  2004-08  (U. Schweckendiek)  Original CORE code
+   !!            2.0  !  2005-04  (L. Brodeau, A.M. Treguier)  improved CORE bulk and its user interface
+   !!            3.0  !  2006-06  (G. Madec)  sbc rewritting
+   !!             -   !  2006-12  (L. Brodeau)  Original code for turb_core
+   !!            3.2  !  2009-04  (B. Lemaire)  Introduce iom_put
+   !!            3.3  !  2010-10  (S. Masson)  add diurnal cycle
+   !!            3.4  !  2011-11  (C. Harris)  Fill arrays required by CICE
+   !!            3.7  !  2014-06  (L. Brodeau)  simplification and optimization of CORE bulk
+   !!            4.0  !  2016-06  (L. Brodeau)  sbcblk_core becomes sbcblk and is not restricted to the CORE algorithm anymore
+   !!                 !                        ==> based on AeroBulk (https://github.com/brodeau/aerobulk/)
+   !!            4.0  !  2016-10  (G. Madec)  introduce a sbc_blk_init routine
+   !!            4.0  !  2016-10  (M. Vancoppenolle)  Introduce conduction flux emulator (M. Vancoppenolle)
+   !!            4.0  !  2019-03  (F. Lemarié & G. Samson)  add ABL compatibility (ln_abl=TRUE)
+   !!            4.2  !  2020-12  (L. Brodeau) Introduction of various air-ice bulk parameterizations + improvements
+   !!----------------------------------------------------------------------
+
+   !!----------------------------------------------------------------------
+   !!   sbc_blk_init  : initialisation of the chosen bulk formulation as ocean surface boundary condition
+   !!   sbc_blk       : bulk formulation as ocean surface boundary condition
+   !!   blk_oce_1     : computes pieces of momentum, heat and freshwater fluxes over ocean for ABL model  (ln_abl=TRUE)
+   !!   blk_oce_2     : finalizes momentum, heat and freshwater fluxes computation over ocean after the ABL step  (ln_abl=TRUE)
+   !!             sea-ice case only :
+   !!   blk_ice_1   : provide the air-ice stress
+   !!   blk_ice_2   : provide the heat and mass fluxes at air-ice interface
+   !!   blk_ice_qcn   : provide ice surface temperature and snow/ice conduction flux (emulating conduction flux)
+   !!----------------------------------------------------------------------
+   USE oce            ! ocean dynamics and tracers
+   USE dom_oce        ! ocean space and time domain
+   USE phycst         ! physical constants
+   USE fldread        ! read input fields
+   USE sbc_oce        ! Surface boundary condition: ocean fields
+   USE trc_oce         ! share SMS/Ocean variables
+   USE cyclone        ! Cyclone 10m wind form trac of cyclone centres
+   USE sbcdcy         ! surface boundary condition: diurnal cycle
+   USE sbcwave , ONLY :   cdn_wave ! wave module
+   USE lib_fortran    ! to use key_nosignedzero and glob_sum
+   !
+#if defined key_si3
+   USE sbc_ice        ! Surface boundary condition: ice fields #LB? ok to be in 'key_si3' ???
+   USE ice     , ONLY :   u_ice, v_ice, jpl, a_i_b, at_i_b, t_su, rn_cnd_s, hfx_err_dif, nn_qtrice
+   USE icevar         ! for CALL ice_var_snwblow
+   USE sbcblk_algo_ice_an05
+   USE sbcblk_algo_ice_lu12
+   USE sbcblk_algo_ice_lg15
+#endif
+   USE sbcblk_algo_ncar     ! => turb_ncar     : NCAR - (formerly known as CORE, Large & Yeager, 2009)
+   USE sbcblk_algo_coare3p0 ! => turb_coare3p0 : COAREv3.0 (Fairall et al. 2003)
+   USE sbcblk_algo_coare3p6 ! => turb_coare3p6 : COAREv3.6 (Fairall et al. 2018 + Edson et al. 2013)
+   USE sbcblk_algo_ecmwf    ! => turb_ecmwf    : ECMWF (IFS cycle 45r1)
+   USE sbcblk_algo_andreas  ! => turb_andreas  : Andreas et al. 2015
+   !
+   USE iom            ! I/O manager library
+   USE in_out_manager ! I/O manager
+   USE lib_mpp        ! distribued memory computing library
+   USE lbclnk         ! ocean lateral boundary conditions (or mpp link)
+   USE prtctl         ! Print control
+
+   USE sbc_phy        ! Catalog of functions for physical/meteorological parameters in the marine boundary layer
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   sbc_blk_init  ! called in sbcmod
+   PUBLIC   sbc_blk       ! called in sbcmod
+   PUBLIC   blk_oce_1     ! called in sbcabl
+   PUBLIC   blk_oce_2     ! called in sbcabl
+#if defined key_si3
+   PUBLIC   blk_ice_1     ! routine called in icesbc
+   PUBLIC   blk_ice_2     ! routine called in icesbc
+   PUBLIC   blk_ice_qcn   ! routine called in icesbc
+#endif
+
+   INTEGER , PUBLIC, PARAMETER ::   jp_wndi  =  1   ! index of 10m wind velocity (i-component) (m/s)    at T-point
+   INTEGER , PUBLIC, PARAMETER ::   jp_wndj  =  2   ! index of 10m wind velocity (j-component) (m/s)    at T-point
+   INTEGER , PUBLIC, PARAMETER ::   jp_tair  =  3   ! index of 10m air temperature             (Kelvin)
+   INTEGER , PUBLIC, PARAMETER ::   jp_humi  =  4   ! index of specific humidity               (kg/kg)
+   INTEGER , PUBLIC, PARAMETER ::   jp_qsr   =  5   ! index of solar heat                      (W/m2)
+   INTEGER , PUBLIC, PARAMETER ::   jp_qlw   =  6   ! index of Long wave                       (W/m2)
+   INTEGER , PUBLIC, PARAMETER ::   jp_prec  =  7   ! index of total precipitation (rain+snow) (Kg/m2/s)
+   INTEGER , PUBLIC, PARAMETER ::   jp_snow  =  8   ! index of snow (solid prcipitation)       (kg/m2/s)
+   INTEGER , PUBLIC, PARAMETER ::   jp_slp   =  9   ! index of sea level pressure              (Pa)
+   INTEGER , PUBLIC, PARAMETER ::   jp_uoatm = 10   ! index of surface current (i-component)
+   !                                                !          seen by the atmospheric forcing (m/s) at T-point
+   INTEGER , PUBLIC, PARAMETER ::   jp_voatm = 11   ! index of surface current (j-component)
+   !                                                !          seen by the atmospheric forcing (m/s) at T-point
+   INTEGER , PUBLIC, PARAMETER ::   jp_cc    = 12   ! index of cloud cover                     (-)      range:0-1
+   INTEGER , PUBLIC, PARAMETER ::   jp_hpgi  = 13   ! index of ABL geostrophic wind or hpg (i-component) (m/s) at T-point
+   INTEGER , PUBLIC, PARAMETER ::   jp_hpgj  = 14   ! index of ABL geostrophic wind or hpg (j-component) (m/s) at T-point
+#if defined key_drakkar
+   LOGICAL                     ::   ln_clim_forcing = .false.   ! Logical flag for use of climatological forcing 
+                                                  !     ( T= climatological, F=interannual)
+   INTEGER , PUBLIC, PARAMETER ::   jp_wmod =15     ! index of wind module                     (m/s)
+   INTEGER , PUBLIC, PARAMETER ::   jp_uw   =16     ! index of zonal pseudo stress             (m2/s2)
+   INTEGER , PUBLIC, PARAMETER ::   jp_vw   =17     ! index of meridional pseudo stress        (m2/s2)
+   INTEGER , PUBLIC, PARAMETER ::   jpfld    = 17   ! maximum number of files to read
+#else
+   INTEGER , PUBLIC, PARAMETER ::   jpfld    = 14   ! maximum number of files to read
+#endif
+
+   ! Warning: keep this structure allocatable for Agrif...
+   TYPE(FLD), PUBLIC, ALLOCATABLE, DIMENSION(:) ::   sf   ! structure of input atmospheric fields (file informations, fields read)
+
+   !                           !!* Namelist namsbc_blk : bulk parameters
+   LOGICAL  ::   ln_NCAR        ! "NCAR"      algorithm   (Large and Yeager 2008)
+   LOGICAL  ::   ln_COARE_3p0   ! "COARE 3.0" algorithm   (Fairall et al. 2003)
+   LOGICAL  ::   ln_COARE_3p6   ! "COARE 3.6" algorithm   (Edson et al. 2013)
+   LOGICAL  ::   ln_ECMWF       ! "ECMWF"     algorithm   (IFS cycle 45r1)
+   LOGICAL  ::   ln_ANDREAS     ! "ANDREAS"   algorithm   (Andreas et al. 2015)
+   !
+   !#LB:
+   LOGICAL  ::   ln_Cx_ice_cst             ! use constant air-ice bulk transfer coefficients (value given in namelist's rn_Cd_i, rn_Ce_i & rn_Ch_i)
+   REAL(wp) ::   rn_Cd_i, rn_Ce_i, rn_Ch_i ! values for  "    "
+   LOGICAL  ::   ln_Cx_ice_AN05            ! air-ice bulk transfer coefficients based on Andreas et al., 2005
+   LOGICAL  ::   ln_Cx_ice_LU12            ! air-ice bulk transfer coefficients based on Lupkes et al., 2012
+   LOGICAL  ::   ln_Cx_ice_LG15            ! air-ice bulk transfer coefficients based on Lupkes & Gryanik, 2015
+   !#LB.
+   !
+   LOGICAL  ::   ln_crt_fbk     ! Add surface current feedback to the wind stress computation  (Renault et al. 2020)
+   REAL(wp) ::   rn_stau_a      ! Alpha and Beta coefficients of Renault et al. 2020, eq. 10: Stau = Alpha * Wnd + Beta
+   REAL(wp) ::   rn_stau_b      !
+   !
+   REAL(wp)         ::   rn_pfac   ! multiplication factor for precipitation
+   REAL(wp), PUBLIC ::   rn_efac   ! multiplication factor for evaporation
+   REAL(wp)         ::   rn_zqt    ! z(q,t) : height of humidity and temperature measurements
+   REAL(wp)         ::   rn_zu     ! z(u)   : height of wind measurements
+   !
+   INTEGER          :: nn_iter_algo   !  Number of iterations in bulk param. algo ("stable ABL + weak wind" requires more)
+
+   REAL(wp),         ALLOCATABLE, DIMENSION(:,:) ::   theta_zu, q_zu                 ! air temp. and spec. hum. at wind speed height (L15 bulk scheme)
+
+#if defined key_si3
+   REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: Cd_ice , Ch_ice , Ce_ice   !#LB transfert coefficients over ice
+   REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: theta_zu_i, q_zu_i         !#LB fixme ! air temp. and spec. hum. over ice at wind speed height (L15 bulk scheme)
+#endif
+
+
+   LOGICAL  ::   ln_skin_cs     ! use the cool-skin (only available in ECMWF and COARE algorithms) !LB
+   LOGICAL  ::   ln_skin_wl     ! use the warm-layer parameterization (only available in ECMWF and COARE algorithms) !LB
+   LOGICAL  ::   ln_humi_sph    ! humidity read in files ("sn_humi") is specific humidity [kg/kg] if .true. !LB
+   LOGICAL  ::   ln_humi_dpt    ! humidity read in files ("sn_humi") is dew-point temperature [K] if .true. !LB
+   LOGICAL  ::   ln_humi_rlh    ! humidity read in files ("sn_humi") is relative humidity     [%] if .true. !LB
+   LOGICAL  ::   ln_tair_pot    ! temperature read in files ("sn_tair") is already potential temperature (not absolute)
+   !
+   INTEGER  ::   nhumi          ! choice of the bulk algorithm
+   !                            ! associated indices:
+   INTEGER, PARAMETER :: np_humi_sph = 1
+   INTEGER, PARAMETER :: np_humi_dpt = 2
+   INTEGER, PARAMETER :: np_humi_rlh = 3
+
+   INTEGER  ::   nblk           ! choice of the bulk algorithm
+   !                            ! associated indices:
+   INTEGER, PARAMETER ::   np_NCAR      = 1   ! "NCAR" algorithm        (Large and Yeager 2008)
+   INTEGER, PARAMETER ::   np_COARE_3p0 = 2   ! "COARE 3.0" algorithm   (Fairall et al. 2003)
+   INTEGER, PARAMETER ::   np_COARE_3p6 = 3   ! "COARE 3.6" algorithm   (Edson et al. 2013)
+   INTEGER, PARAMETER ::   np_ECMWF     = 4   ! "ECMWF" algorithm       (IFS cycle 45r1)
+   INTEGER, PARAMETER ::   np_ANDREAS   = 5   ! "ANDREAS" algorithm       (Andreas et al. 2015)
+
+   !#LB:
+#if defined key_si3
+   ! Same, over sea-ice:
+   INTEGER  ::   nblk_ice           ! choice of the bulk algorithm
+   !                            ! associated indices:
+   INTEGER, PARAMETER ::   np_ice_cst  = 1   ! constant transfer coefficients
+   INTEGER, PARAMETER ::   np_ice_an05 = 2   ! Andreas et al., 2005
+   INTEGER, PARAMETER ::   np_ice_lu12 = 3   ! Lupkes el al., 2012
+   INTEGER, PARAMETER ::   np_ice_lg15 = 4   ! Lupkes & Gryanik, 2015
+#endif
+   !LB.
+
+
+
+   !! * Substitutions
+#  include "do_loop_substitute.h90"
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: sbcblk.F90 15551 2021-11-28 20:19:36Z gsamson $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   INTEGER FUNCTION sbc_blk_alloc()
+      !!-------------------------------------------------------------------
+      !!             ***  ROUTINE sbc_blk_alloc ***
+      !!-------------------------------------------------------------------
+      ALLOCATE( theta_zu(jpi,jpj), q_zu(jpi,jpj),  STAT=sbc_blk_alloc )
+      CALL mpp_sum ( 'sbcblk', sbc_blk_alloc )
+      IF( sbc_blk_alloc /= 0 )   CALL ctl_stop( 'STOP', 'sbc_blk_alloc: failed to allocate arrays' )
+   END FUNCTION sbc_blk_alloc
+
+#if defined key_si3
+   INTEGER FUNCTION sbc_blk_ice_alloc()
+      !!-------------------------------------------------------------------
+      !!             ***  ROUTINE sbc_blk_ice_alloc ***
+      !!-------------------------------------------------------------------
+      ALLOCATE( Cd_ice (jpi,jpj), Ch_ice (jpi,jpj), Ce_ice (jpi,jpj),         &
+         &      theta_zu_i(jpi,jpj), q_zu_i(jpi,jpj),  STAT=sbc_blk_ice_alloc )
+      CALL mpp_sum ( 'sbcblk', sbc_blk_ice_alloc )
+      IF( sbc_blk_ice_alloc /= 0 )   CALL ctl_stop( 'STOP', 'sbc_blk_ice_alloc: failed to allocate arrays' )
+   END FUNCTION sbc_blk_ice_alloc
+#endif
+
+
+   SUBROUTINE sbc_blk_init
+      !!---------------------------------------------------------------------
+      !!                    ***  ROUTINE sbc_blk_init  ***
+      !!
+      !! ** Purpose :   choose and initialize a bulk formulae formulation
+      !!
+      !! ** Method  :
+      !!
+      !!----------------------------------------------------------------------
+      INTEGER  ::   jfpr                  ! dummy loop indice and argument
+      INTEGER  ::   ios, ierror, ioptio   ! Local integer
+      !!
+      CHARACTER(len=100)            ::   cn_dir                ! Root directory for location of atmospheric forcing files
+      TYPE(FLD_N), DIMENSION(jpfld) ::   slf_i                 ! array of namelist informations on the fields to read
+      TYPE(FLD_N) ::   sn_wndi, sn_wndj , sn_humi, sn_qsr      ! informations about the fields to be read
+      TYPE(FLD_N) ::   sn_qlw , sn_tair , sn_prec, sn_snow     !       "                        "
+      TYPE(FLD_N) ::   sn_slp , sn_uoatm, sn_voatm             !       "                        "
+      TYPE(FLD_N) ::   sn_cc, sn_hpgi, sn_hpgj                 !       "                        "
+      INTEGER     ::   ipka                                    ! number of levels in the atmospheric variable
+      NAMELIST/namsbc_blk/ ln_NCAR, ln_COARE_3p0, ln_COARE_3p6, ln_ECMWF, ln_ANDREAS, &   ! bulk algorithm
+         &                 rn_zqt, rn_zu, nn_iter_algo, ln_skin_cs, ln_skin_wl,       &
+         &                 rn_pfac, rn_efac,                                          &
+         &                 ln_crt_fbk, rn_stau_a, rn_stau_b,                          &   ! current feedback
+         &                 ln_humi_sph, ln_humi_dpt, ln_humi_rlh, ln_tair_pot,        &
+         &                 ln_Cx_ice_cst, rn_Cd_i, rn_Ce_i, rn_Ch_i,                  &
+         &                 ln_Cx_ice_AN05, ln_Cx_ice_LU12, ln_Cx_ice_LG15,            &
+         &                 cn_dir,                                                    &
+         &                 sn_wndi, sn_wndj, sn_qsr, sn_qlw ,                         &   ! input fields
+         &                 sn_tair, sn_humi, sn_prec, sn_snow, sn_slp,                &
+         &                 sn_uoatm, sn_voatm, sn_cc, sn_hpgi, sn_hpgj
+#if defined key_drakkar
+      TYPE(FLD_N) :: sn_wmod, sn_uw, sn_vw
+      NAMELIST/namsbc_blk_drk/ ln_clim_forcing,sn_wmod, sn_uw, sn_vw
+#endif
+
+      ! cool-skin / warm-layer !LB
+      !!---------------------------------------------------------------------
+      !
+      !                                      ! allocate sbc_blk_core array
+      IF( sbc_blk_alloc()     /= 0 )   CALL ctl_stop( 'STOP', 'sbc_blk : unable to allocate standard arrays' )
+      !
+#if defined key_si3
+      IF( sbc_blk_ice_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'sbc_blk : unable to allocate standard ice arrays' )
+#endif
+      !
+      !                             !** read bulk namelist
+      READ  ( numnam_ref, namsbc_blk, IOSTAT = ios, ERR = 901)
+901   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namsbc_blk in reference namelist' )
+      !
+      READ  ( numnam_cfg, namsbc_blk, IOSTAT = ios, ERR = 902 )
+902   IF( ios >  0 )   CALL ctl_nam ( ios , 'namsbc_blk in configuration namelist' )
+      !
+      IF(lwm) WRITE( numond, namsbc_blk )
+#if defined key_drakkar
+      !                             !** read bulk  drakkar namelist  
+      READ  ( numnam_ref, namsbc_blk_drk, IOSTAT = ios, ERR = 903)
+903   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namsbc_blk_drk in reference namelist' )
+      !
+      READ  ( numnam_cfg, namsbc_blk_drk, IOSTAT = ios, ERR = 904 )
+904   IF( ios >  0 )   CALL ctl_nam ( ios , 'namsbc_blk_drk in configuration namelist' )
+      !
+      IF(lwm) WRITE( numond, namsbc_blk_drk )
+#endif
+      !
+      !                             !** initialization of the chosen bulk formulae (+ check)
+      !                                   !* select the bulk chosen in the namelist and check the choice
+      ioptio = 0
+      IF( ln_NCAR      ) THEN
+         nblk =  np_NCAR        ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ln_COARE_3p0 ) THEN
+         nblk =  np_COARE_3p0   ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ln_COARE_3p6 ) THEN
+         nblk =  np_COARE_3p6   ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ln_ECMWF     ) THEN
+         nblk =  np_ECMWF       ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ln_ANDREAS     ) THEN
+         nblk =  np_ANDREAS       ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ioptio /= 1 )   CALL ctl_stop( 'sbc_blk_init: Choose one and only one bulk algorithm' )
+
+      !                             !** initialization of the cool-skin / warm-layer parametrization
+      IF( ln_skin_cs .OR. ln_skin_wl ) THEN
+         !! Some namelist sanity tests:
+         IF( ln_NCAR )      &
+            & CALL ctl_stop( 'sbc_blk_init: Cool-skin/warm-layer param. not compatible with NCAR algorithm' )
+         IF( ln_ANDREAS )      &
+            & CALL ctl_stop( 'sbc_blk_init: Cool-skin/warm-layer param. not compatible with ANDREAS algorithm' )
+         !IF( nn_fsbc /= 1 ) &
+         !   & CALL ctl_stop( 'sbc_blk_init: Please set "nn_fsbc" to 1 when using cool-skin/warm-layer param.')
+      END IF
+
+      IF( ln_skin_wl ) THEN
+         !! Check if the frequency of downwelling solar flux input makes sense and if ln_dm2dc=T if it is daily!
+         IF( (sn_qsr%freqh  < 0.).OR.(sn_qsr%freqh  > 24.) ) &
+            & CALL ctl_stop( 'sbc_blk_init: Warm-layer param. (ln_skin_wl) not compatible with freq. of solar flux > daily' )
+         IF( (sn_qsr%freqh == 24.).AND.(.NOT. ln_dm2dc) ) &
+            & CALL ctl_stop( 'sbc_blk_init: Please set ln_dm2dc=T for warm-layer param. (ln_skin_wl) to work properly' )
+      END IF
+
+      ioptio = 0
+      IF( ln_humi_sph ) THEN
+         nhumi =  np_humi_sph    ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ln_humi_dpt ) THEN
+         nhumi =  np_humi_dpt    ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ln_humi_rlh ) THEN
+         nhumi =  np_humi_rlh    ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ioptio /= 1 )   CALL ctl_stop( 'sbc_blk_init: Choose one and only one type of air humidity' )
+      !
+      IF( ln_dm2dc ) THEN                 !* check: diurnal cycle on Qsr
+         IF( sn_qsr%freqh /= 24. )   CALL ctl_stop( 'sbc_blk_init: ln_dm2dc=T only with daily short-wave input' )
+         IF( sn_qsr%ln_tint ) THEN
+            CALL ctl_warn( 'sbc_blk_init: ln_dm2dc=T daily qsr time interpolation done by sbcdcy module',   &
+               &           '              ==> We force time interpolation = .false. for qsr' )
+            sn_qsr%ln_tint = .false.
+         ENDIF
+      ENDIF
+
+#if defined key_si3
+      ioptio = 0
+      IF( ln_Cx_ice_cst ) THEN
+         nblk_ice =  np_ice_cst     ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ln_Cx_ice_AN05 ) THEN
+         nblk_ice =  np_ice_an05   ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ln_Cx_ice_LU12 ) THEN
+         nblk_ice =  np_ice_lu12    ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ln_Cx_ice_LG15 ) THEN
+         nblk_ice =  np_ice_lg15   ;   ioptio = ioptio + 1
+      ENDIF
+      IF( ioptio /= 1 )   CALL ctl_stop( 'sbc_blk_init: Choose one and only one ice-atm bulk algorithm' )
+#endif
+
+
+      !                                   !* set the bulk structure
+      !                                      !- store namelist information in an array
+      !
+      slf_i(jp_wndi ) = sn_wndi    ;   slf_i(jp_wndj ) = sn_wndj
+      slf_i(jp_qsr  ) = sn_qsr     ;   slf_i(jp_qlw  ) = sn_qlw
+      slf_i(jp_tair ) = sn_tair    ;   slf_i(jp_humi ) = sn_humi
+      slf_i(jp_prec ) = sn_prec    ;   slf_i(jp_snow ) = sn_snow
+      slf_i(jp_slp  ) = sn_slp     ;   slf_i(jp_cc   ) = sn_cc
+      slf_i(jp_uoatm) = sn_uoatm   ;   slf_i(jp_voatm) = sn_voatm
+      slf_i(jp_hpgi ) = sn_hpgi    ;   slf_i(jp_hpgj ) = sn_hpgj
+      !
+      IF( .NOT. ln_abl ) THEN   ! force to not use jp_hpgi and jp_hpgj, should already be done in namelist_* but we never know...
+         slf_i(jp_hpgi)%clname = 'NOT USED'
+         slf_i(jp_hpgj)%clname = 'NOT USED'
+      ENDIF
+#if defined key_drakkar
+      slf_i(jp_wmod ) = sn_wmod    ;   slf_i(jp_uw ) = sn_uw  ; slf_i(jp_vw ) = sn_vw
+      IF( .NOT. ln_clim_forcing) THEN 
+         slf_i(jp_wmod)%clname = 'NOT USED'
+         slf_i(jp_uw  )%clname = 'NOT USED'
+         slf_i(jp_vw  )%clname = 'NOT USED'
+      ELSE
+         slf_i(jp_wndi)%clname = 'NOT USED'
+         slf_i(jp_wndj)%clname = 'NOT USED'
+      ENDIF
+#endif
+      !
+      !                                      !- allocate the bulk structure
+      ALLOCATE( sf(jpfld), STAT=ierror )
+      IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_blk_init: unable to allocate sf structure' )
+      !
+      !                                      !- fill the bulk structure with namelist informations
+      CALL fld_fill( sf, slf_i, cn_dir, 'sbc_blk_init', 'surface boundary condition -- bulk formulae', 'namsbc_blk' )
+      sf(jp_wndi )%zsgn = -1._wp   ;   sf(jp_wndj )%zsgn = -1._wp   ! vector field at T point: overwrite default definition of zsgn
+      sf(jp_uoatm)%zsgn = -1._wp   ;   sf(jp_voatm)%zsgn = -1._wp   ! vector field at T point: overwrite default definition of zsgn
+      sf(jp_hpgi )%zsgn = -1._wp   ;   sf(jp_hpgj )%zsgn = -1._wp   ! vector field at T point: overwrite default definition of zsgn
+      !
+      DO jfpr= 1, jpfld
+         !
+         IF(   ln_abl    .AND.                                                      &
+            &    ( jfpr == jp_wndi .OR. jfpr == jp_wndj .OR. jfpr == jp_humi .OR.   &
+            &      jfpr == jp_hpgi .OR. jfpr == jp_hpgj .OR. jfpr == jp_tair     )  ) THEN
+            ipka = jpka   ! ABL: some fields are 3D input
+         ELSE
+            ipka = 1
+         ENDIF
+         !
+         ALLOCATE( sf(jfpr)%fnow(jpi,jpj,ipka) )
+         !
+         IF( TRIM(sf(jfpr)%clrootname) == 'NOT USED' ) THEN    !--  not used field  --!   (only now allocated and set to default)
+            IF(     jfpr == jp_slp ) THEN
+               sf(jfpr)%fnow(:,:,1:ipka) = 101325._wp   ! use standard pressure in Pa
+            ELSEIF( jfpr == jp_prec .OR. jfpr == jp_snow .OR. jfpr == jp_uoatm .OR. jfpr == jp_voatm ) THEN
+               sf(jfpr)%fnow(:,:,1:ipka) = 0._wp        ! no precip or no snow or no surface currents
+            ELSEIF( jfpr == jp_hpgi .OR. jfpr == jp_hpgj ) THEN
+               IF( .NOT. ln_abl ) THEN
+                  DEALLOCATE( sf(jfpr)%fnow )   ! deallocate as not used in this case
+               ELSE
+                  sf(jfpr)%fnow(:,:,1:ipka) = 0._wp
+               ENDIF
+            ELSEIF( jfpr == jp_cc  ) THEN
+               sf(jp_cc)%fnow(:,:,1:ipka) = pp_cldf
+#if defined key_drakkar
+            ELSEIF( jfpr == jp_wmod .OR. jfpr == jp_uw .OR. jfpr == jp_vw ) THEN
+               sf(jfpr)%fnow(:,:,1:ipka) = 0._wp
+#endif
+            ELSE
+               WRITE(ctmp1,*) 'sbc_blk_init: no default value defined for field number', jfpr
+               CALL ctl_stop( ctmp1 )
+            ENDIF
+         ELSE                                                  !-- used field  --!
+            IF( sf(jfpr)%ln_tint )   ALLOCATE( sf(jfpr)%fdta(jpi,jpj,ipka,2) )   ! allocate array for temporal interpolation
+            !
+            IF( sf(jfpr)%freqh > 0. .AND. MOD( NINT(3600. * sf(jfpr)%freqh), nn_fsbc * NINT(rn_Dt) ) /= 0 )   &
+         &  CALL ctl_warn( 'sbc_blk_init: sbcmod timestep rn_Dt*nn_fsbc is NOT a submultiple of atmospheric forcing frequency.',   &
+         &                 '               This is not ideal. You should consider changing either rn_Dt or nn_fsbc value...' )
+         ENDIF
+      END DO
+      !
+      IF( ln_abl ) THEN       ! ABL: read 3D fields for wind, temperature, humidity and pressure gradient
+         rn_zqt = ght_abl(2)          ! set the bulk altitude to ABL first level
+         rn_zu  = ght_abl(2)
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ABL formulation: overwrite rn_zqt & rn_zu with ABL first level altitude'
+      ENDIF
+      !
+      !
+      IF(lwp) THEN                     !** Control print
+         !
+         WRITE(numout,*)                  !* namelist
+         WRITE(numout,*) '   Namelist namsbc_blk (other than data information):'
+         WRITE(numout,*) '      "NCAR"      algorithm   (Large and Yeager 2008)      ln_NCAR      = ', ln_NCAR
+         WRITE(numout,*) '      "COARE 3.0" algorithm   (Fairall et al. 2003)       ln_COARE_3p0 = ', ln_COARE_3p0
+         WRITE(numout,*) '      "COARE 3.6" algorithm (Fairall 2018 + Edson al 2013) ln_COARE_3p6 = ', ln_COARE_3p6
+         WRITE(numout,*) '      "ECMWF"     algorithm   (IFS cycle 45r1)             ln_ECMWF     = ', ln_ECMWF
+         WRITE(numout,*) '      "ANDREAS"   algorithm   (Andreas et al. 2015)       ln_ANDREAS   = ', ln_ANDREAS
+#if defined key_drakkar
+         WRITE(numout,*) '      Use climatolofical forcing formulation           ln_clim_forcing = ', ln_clim_forcing
+#endif
+         WRITE(numout,*) '      Air temperature and humidity reference height (m)   rn_zqt       = ', rn_zqt
+         WRITE(numout,*) '      Wind vector reference height (m)                    rn_zu        = ', rn_zu
+         WRITE(numout,*) '      factor applied on precipitation (total & snow)      rn_pfac      = ', rn_pfac
+         WRITE(numout,*) '      factor applied on evaporation                       rn_efac      = ', rn_efac
+         WRITE(numout,*) '         (form absolute (=0) to relative winds(=1))'
+         WRITE(numout,*) '      use surface current feedback on wind stress         ln_crt_fbk   = ', ln_crt_fbk
+         IF(ln_crt_fbk) THEN
+         WRITE(numout,*) '         Renault et al. 2020, eq. 10: Stau = Alpha * Wnd + Beta'
+         WRITE(numout,*) '            Alpha                                         rn_stau_a    = ', rn_stau_a
+         WRITE(numout,*) '            Beta                                          rn_stau_b    = ', rn_stau_b
+         ENDIF
+         !
+         WRITE(numout,*)
+         SELECT CASE( nblk )              !* Print the choice of bulk algorithm
+         CASE( np_NCAR      )   ;   WRITE(numout,*) '   ==>>>   "NCAR" algorithm        (Large and Yeager 2008)'
+         CASE( np_COARE_3p0 )   ;   WRITE(numout,*) '   ==>>>   "COARE 3.0" algorithm   (Fairall et al. 2003)'
+         CASE( np_COARE_3p6 )   ;   WRITE(numout,*) '   ==>>>   "COARE 3.6" algorithm (Fairall 2018+Edson et al. 2013)'
+         CASE( np_ECMWF     )   ;   WRITE(numout,*) '   ==>>>   "ECMWF" algorithm       (IFS cycle 45r1)'
+         CASE( np_ANDREAS   )   ;   WRITE(numout,*) '   ==>>>   "ANDREAS" algorithm (Andreas et al. 2015)'
+         END SELECT
+         !
+         WRITE(numout,*)
+         WRITE(numout,*) '      use cool-skin  parameterization (SSST)  ln_skin_cs  = ', ln_skin_cs
+         WRITE(numout,*) '      use warm-layer parameterization (SSST)  ln_skin_wl  = ', ln_skin_wl
+         !
+         WRITE(numout,*)
+         SELECT CASE( nhumi )              !* Print the choice of air humidity
+         CASE( np_humi_sph )   ;   WRITE(numout,*) '   ==>>>   air humidity is SPECIFIC HUMIDITY     [kg/kg]'
+         CASE( np_humi_dpt )   ;   WRITE(numout,*) '   ==>>>   air humidity is DEW-POINT TEMPERATURE [K]'
+         CASE( np_humi_rlh )   ;   WRITE(numout,*) '   ==>>>   air humidity is RELATIVE HUMIDITY     [%]'
+         END SELECT
+         !
+         !#LB:
+#if defined key_si3
+         IF( nn_ice > 0 ) THEN
+            WRITE(numout,*)
+            WRITE(numout,*) '      use constant ice-atm bulk transfer coeff.           ln_Cx_ice_cst  = ', ln_Cx_ice_cst
+            WRITE(numout,*) '      use ice-atm bulk coeff. from Andreas et al., 2005   ln_Cx_ice_AN05 = ', ln_Cx_ice_AN05
+            WRITE(numout,*) '      use ice-atm bulk coeff. from Lupkes et al., 2012    ln_Cx_ice_LU12 = ', ln_Cx_ice_LU12
+            WRITE(numout,*) '      use ice-atm bulk coeff. from Lupkes & Gryanik, 2015 ln_Cx_ice_LG15 = ', ln_Cx_ice_LG15
+         ENDIF
+         WRITE(numout,*)
+         SELECT CASE( nblk_ice )              !* Print the choice of bulk algorithm
+         CASE( np_ice_cst  )
+            WRITE(numout,*) '   ==>>>   Constant bulk transfer coefficients over sea-ice:'
+            WRITE(numout,*) '      => Cd_ice, Ce_ice, Ch_ice =', REAL(rn_Cd_i,4), REAL(rn_Ce_i,4), REAL(rn_Ch_i,4)
+            IF( (rn_Cd_i<0._wp).OR.(rn_Cd_i>1.E-2_wp).OR.(rn_Ce_i<0._wp).OR.(rn_Ce_i>1.E-2_wp).OR.(rn_Ch_i<0._wp).OR.(rn_Ch_i>1.E-2_wp) ) &
+               & CALL ctl_stop( 'Be realistic in your pick of Cd_ice, Ce_ice & Ch_ice ! (0 < Cx < 1.E-2)')
+         CASE( np_ice_an05 )   ;   WRITE(numout,*) '   ==>>> bulk algo over ice: Andreas et al, 2005'
+         CASE( np_ice_lu12 )   ;   WRITE(numout,*) '   ==>>> bulk algo over ice: Lupkes et al, 2012'
+         CASE( np_ice_lg15 )   ;   WRITE(numout,*) '   ==>>> bulk algo over ice: Lupkes & Gryanik, 2015'
+         END SELECT
+#endif
+         !#LB.
+         !
+      ENDIF
+      !
+   END SUBROUTINE sbc_blk_init
+
+
+   SUBROUTINE sbc_blk( kt )
+      !!---------------------------------------------------------------------
+      !!                    ***  ROUTINE sbc_blk  ***
+      !!
+      !! ** Purpose :   provide at each time step the surface ocean fluxes
+      !!              (momentum, heat, freshwater and runoff)
+      !!
+      !! ** Method  :
+      !!              (1) READ each fluxes in NetCDF files:
+      !!      the wind velocity (i-component) at z=rn_zu  (m/s) at T-point
+      !!      the wind velocity (j-component) at z=rn_zu  (m/s) at T-point
+      !!      the specific humidity           at z=rn_zqt (kg/kg)
+      !!      the air temperature             at z=rn_zqt (Kelvin)
+      !!      the solar heat                              (W/m2)
+      !!      the Long wave                               (W/m2)
+      !!      the total precipitation (rain+snow)         (Kg/m2/s)
+      !!      the snow (solid precipitation)              (kg/m2/s)
+      !!      ABL dynamical forcing (i/j-components of either hpg or geostrophic winds)
+      !!              (2) CALL blk_oce_1 and blk_oce_2
+      !!
+      !!      C A U T I O N : never mask the surface stress fields
+      !!                      the stress is assumed to be in the (i,j) mesh referential
+      !!
+      !! ** Action  :   defined at each time-step at the air-sea interface
+      !!              - utau, vtau  i- and j-component of the wind stress
+      !!              - taum        wind stress module at T-point
+      !!              - wndm        wind speed  module at T-point over free ocean or leads in presence of sea-ice
+      !!              - qns, qsr    non-solar and solar heat fluxes
+      !!              - emp         upward mass flux (evapo. - precip.)
+      !!              - sfx         salt flux due to freezing/melting (non-zero only if ice is present)
+      !!
+      !! ** References :   Large & Yeager, 2004 / Large & Yeager, 2008
+      !!                   Brodeau et al. Ocean Modelling 2010
+      !!----------------------------------------------------------------------
+      INTEGER, INTENT(in) ::   kt   ! ocean time step
+      !!----------------------------------------------------------------------
+      REAL(wp), DIMENSION(jpi,jpj) ::   zssq, zcd_du, zsen, zlat, zevp, zpre, ztheta
+      REAL(wp) :: ztst
+      LOGICAL  :: llerr
+      !!----------------------------------------------------------------------
+      !
+      CALL fld_read( kt, nn_fsbc, sf )             ! input fields provided at the current time-step
+
+      ! Sanity/consistence test on humidity at first time step to detect potential screw-up:
+      IF( kt == nit000 ) THEN
+         ! mean humidity over ocean on proc
+         ztst = glob_sum( 'sbcblk', sf(jp_humi)%fnow(:,:,1) * e1e2t(:,:) * tmask(:,:,1) ) / glob_sum( 'sbcblk', e1e2t(:,:) * tmask(:,:,1) )
+         llerr = .FALSE.
+         SELECT CASE( nhumi )
+         CASE( np_humi_sph ) ! specific humidity => expect: 0. <= something < 0.065 [kg/kg] (0.061 is saturation at 45degC !!!)
+            IF( (ztst <   0._wp) .OR. (ztst > 0.065_wp) )   llerr = .TRUE.
+         CASE( np_humi_dpt ) ! dew-point temperature => expect: 110. <= something < 320. [K]
+            IF( (ztst < 110._wp) .OR. (ztst >  320._wp) )   llerr = .TRUE.
+         CASE( np_humi_rlh ) ! relative humidity => expect: 0. <= something < 100. [%]
+            IF( (ztst <   0._wp) .OR. (ztst >  100._wp) )   llerr = .TRUE.
+         END SELECT
+         IF(llerr) THEN
+            WRITE(ctmp1,'("   Error on mean humidity value: ",f10.5)') ztst
+            CALL ctl_stop( 'STOP', ctmp1, 'Something is wrong with air humidity!!!', &
+               &   ' ==> check the unit in your input files'       , &
+               &   ' ==> check consistence of namelist choice: specific? relative? dew-point?', &
+               &   ' ==> ln_humi_sph -> [kg/kg] | ln_humi_rlh -> [%] | ln_humi_dpt -> [K] !!!' )
+         ENDIF
+         IF(lwp) THEN
+            WRITE(numout,*) ''
+            WRITE(numout,*) ' Global mean humidity at kt = nit000: ', ztst
+            WRITE(numout,*) ' === Sanity/consistence test on air humidity sucessfuly passed! ==='
+            WRITE(numout,*) ''
+         ENDIF
+      ENDIF   !IF( kt == nit000 )
+      !                                            ! compute the surface ocean fluxes using bulk formulea
+      IF( MOD( kt - 1, nn_fsbc ) == 0 ) THEN
+
+         ! Specific humidity of air at z=rn_zqt
+         SELECT CASE( nhumi )
+         CASE( np_humi_sph )
+            q_air_zt(:,:) = sf(jp_humi )%fnow(:,:,1)      ! what we read in file is already a spec. humidity!
+         CASE( np_humi_dpt )
+            IF((kt==nit000).AND.lwp) WRITE(numout,*) ' *** sbc_blk() => computing q_air out of dew-point and P !'
+            q_air_zt(:,:) = q_sat( sf(jp_humi )%fnow(:,:,1), sf(jp_slp  )%fnow(:,:,1) )
+         CASE( np_humi_rlh )
+            IF((kt==nit000).AND.lwp) WRITE(numout,*) ' *** sbc_blk() => computing q_air out of RH, t_air and slp !' !LBrm
+            q_air_zt(:,:) = q_air_rh( 0.01_wp*sf(jp_humi )%fnow(:,:,1), &
+               &                      sf(jp_tair )%fnow(:,:,1), sf(jp_slp  )%fnow(:,:,1) ) !#LB: 0.01 => RH is % percent in file
+         END SELECT
+
+         ! Potential temperature of air at z=rn_zqt (most reanalysis products provide absolute temp., not potential temp.)
+         IF( ln_tair_pot ) THEN
+            ! temperature read into file is already potential temperature, do nothing...
+            theta_air_zt(:,:) = sf(jp_tair )%fnow(:,:,1)
+         ELSE
+            ! temperature read into file is ABSOLUTE temperature (that's the case for ECMWF products for example...)
+            IF((kt==nit000).AND.lwp) WRITE(numout,*) ' *** sbc_blk() => air temperature converted from ABSOLUTE to POTENTIAL!'
+            zpre(:,:)         = pres_temp( q_air_zt(:,:), sf(jp_slp)%fnow(:,:,1), rn_zu, pta=sf(jp_tair)%fnow(:,:,1) )
+            theta_air_zt(:,:) = theta_exner( sf(jp_tair)%fnow(:,:,1), zpre(:,:) )
+         ENDIF
+         !
+         CALL blk_oce_1( kt, sf(jp_wndi )%fnow(:,:,1), sf(jp_wndj )%fnow(:,:,1),   &   !   <<= in
+            &                theta_air_zt(:,:), q_air_zt(:,:),                     &   !   <<= in
+            &                sf(jp_slp  )%fnow(:,:,1), sst_m, ssu_m, ssv_m,        &   !   <<= in
+            &                sf(jp_uoatm)%fnow(:,:,1), sf(jp_voatm)%fnow(:,:,1),   &   !   <<= in
+            &                sf(jp_qsr  )%fnow(:,:,1), sf(jp_qlw  )%fnow(:,:,1),   &   !   <<= in (wl/cs)
+            &                tsk_m, zssq, zcd_du, zsen, zlat, zevp )                   !   =>> out
+
+         CALL blk_oce_2(     theta_air_zt(:,:),                                    &   !   <<= in
+            &                sf(jp_qlw  )%fnow(:,:,1), sf(jp_prec )%fnow(:,:,1),   &   !   <<= in
+            &                sf(jp_snow )%fnow(:,:,1), tsk_m,                      &   !   <<= in
+            &                zsen, zlat, zevp )                                        !   <=> in out
+      ENDIF
+      !
+#if defined key_cice
+      IF( MOD( kt - 1, nn_fsbc ) == 0 )   THEN
+         qlw_ice(:,:,1)   = sf(jp_qlw )%fnow(:,:,1)
+         IF( ln_dm2dc ) THEN
+            qsr_ice(:,:,1) = sbc_dcy( sf(jp_qsr)%fnow(:,:,1) )
+         ELSE
+            qsr_ice(:,:,1) =          sf(jp_qsr)%fnow(:,:,1)
+         ENDIF
+         tatm_ice(:,:) = sf(jp_tair)%fnow(:,:,1)    !#LB: should it be POTENTIAL temperature (theta_air_zt) instead ????
+         qatm_ice(:,:) = q_air_zt(:,:)
+         tprecip(:,:)  = sf(jp_prec)%fnow(:,:,1) * rn_pfac
+         sprecip(:,:)  = sf(jp_snow)%fnow(:,:,1) * rn_pfac
+         wndi_ice(:,:) = sf(jp_wndi)%fnow(:,:,1)
+         wndj_ice(:,:) = sf(jp_wndj)%fnow(:,:,1)
+      ENDIF
+#endif
+
+#if defined key_top
+      IF( ln_trcdc2dm )  THEN      !  diurnal cycle in TOP
+         IF( MOD( kt - 1, nn_fsbc ) == 0 ) THEN
+            IF( ln_dm2dc )  THEN
+                qsr_mean(:,:) = ( 1. - albo )  * sf(jp_qsr)%fnow(:,:,1)  * tmask(:,:,1)
+            ELSE
+                ncpl_qsr_freq = sf(jp_qsr)%freqh * 3600 !   qsr_mean will be computed in TOP
+            ENDIF
+         ENDIF
+      ENDIF
+#endif
+      !
+   END SUBROUTINE sbc_blk
+
+
+   SUBROUTINE blk_oce_1( kt, pwndi, pwndj, ptair, pqair,         &  ! inp
+      &                      pslp , pst  , pu   , pv,            &  ! inp
+      &                      puatm, pvatm, pdqsr , pdqlw ,       &  ! inp
+      &                      ptsk , pssq , pcd_du, psen, plat, pevp ) ! out
+      !!---------------------------------------------------------------------
+      !!                     ***  ROUTINE blk_oce_1  ***
+      !!
+      !! ** Purpose :   if ln_blk=T, computes surface momentum, heat and freshwater fluxes
+      !!                if ln_abl=T, computes Cd x |U|, Ch x |U|, Ce x |U| for ABL integration
+      !!
+      !! ** Method  :   bulk formulae using atmospheric fields from :
+      !!                if ln_blk=T, atmospheric fields read in sbc_read
+      !!                if ln_abl=T, the ABL model at previous time-step
+      !!
+      !! ** Outputs : - pssq    : surface humidity used to compute latent heat flux (kg/kg)
+      !!              - pcd_du  : Cd x |dU| at T-points  (m/s)
+      !!              - psen    : sensible heat flux (W/m^2)
+      !!              - plat    : latent heat flux   (W/m^2)
+      !!              - pevp    : evaporation        (mm/s) #lolo
+      !!---------------------------------------------------------------------
+      INTEGER , INTENT(in   )                 ::   kt     ! time step index
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pwndi  ! atmospheric wind at T-point              [m/s]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pwndj  ! atmospheric wind at T-point              [m/s]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pqair  ! specific humidity at T-points            [kg/kg]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   ptair  ! potential temperature at T-points        [Kelvin]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pslp   ! sea-level pressure                       [Pa]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pst    ! surface temperature                      [Celsius]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pu     ! surface current at U-point (i-component) [m/s]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pv     ! surface current at V-point (j-component) [m/s]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   puatm  ! surface current seen by the atm at T-point (i-component) [m/s]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pvatm  ! surface current seen by the atm at T-point (j-component) [m/s]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pdqsr  ! downwelling solar (shortwave) radiation at surface [W/m^2]
+      REAL(wp), INTENT(in   ), DIMENSION(:,:) ::   pdqlw  ! downwelling longwave radiation at surface [W/m^2]
+      REAL(wp), INTENT(  out), DIMENSION(:,:) ::   ptsk   ! skin temp. (or SST if CS & WL not used)  [Celsius]
+      REAL(wp), INTENT(  out), DIMENSION(:,:) ::   pssq   ! specific humidity at pst                 [kg/kg]
+      REAL(wp), INTENT(  out), DIMENSION(:,:) ::   pcd_du
+      REAL(wp), INTENT(  out), DIMENSION(:,:) ::   psen
+      REAL(wp), INTENT(  out), DIMENSION(:,:) ::   plat
+      REAL(wp), INTENT(  out), DIMENSION(:,:) ::   pevp
+      !
+      INTEGER  ::   ji, jj               ! dummy loop indices
+      REAL(wp) ::   zztmp                ! local variable
+      REAL(wp) ::   zstmax, zstau
+#if defined key_cyclone
+      REAL(wp), DIMENSION(jpi,jpj) ::   zwnd_i, zwnd_j    ! wind speed components at T-point
+#endif
+      REAL(wp), DIMENSION(jpi,jpj) ::   ztau_i, ztau_j    ! wind stress components at T-point
+      REAL(wp), DIMENSION(jpi,jpj) ::   zU_zu             ! bulk wind speed at height zu  [m/s]
+      REAL(wp), DIMENSION(jpi,jpj) ::   zcd_oce           ! momentum transfert coefficient over ocean
+      REAL(wp), DIMENSION(jpi,jpj) ::   zch_oce           ! sensible heat transfert coefficient over ocean
+      REAL(wp), DIMENSION(jpi,jpj) ::   zce_oce           ! latent   heat transfert coefficient over ocean
+      REAL(wp), DIMENSION(jpi,jpj) ::   zsspt             ! potential sea-surface temperature [K]
+      REAL(wp), DIMENSION(jpi,jpj) ::   zpre, ztabs       ! air pressure [Pa] & absolute temperature [K]
+      REAL(wp), DIMENSION(jpi,jpj) ::   zztmp1, zztmp2
+#if defined key_drakkar
+      REAL(wp), DIMENSION(jpi,jpj) ::   zwu, zwv
+#endif
+      !!---------------------------------------------------------------------
+      !
+      ! local scalars ( place there for vector optimisation purposes)
+      !                           ! Temporary conversion from Celcius to Kelvin (and set minimum value far above 0 K)
+      ptsk(:,:) = pst(:,:) + rt0  ! by default: skin temperature = "bulk SST" (will remain this way if NCAR algorithm used!)
+
+      ! sea surface potential temperature [K]
+      zsspt(:,:) = theta_exner( ptsk(:,:), pslp(:,:) )
+
+      ! --- cloud cover --- !
+      cloud_fra(:,:) = sf(jp_cc)%fnow(:,:,1)
+
+      ! ----------------------------------------------------------------------------- !
+      !      0   Wind components and module at T-point relative to the moving ocean   !
+      ! ----------------------------------------------------------------------------- !
+
+      ! ... components ( U10m - U_oce ) at T-point (unmasked)
+#if defined key_cyclone
+      zwnd_i(:,:) = 0._wp
+      zwnd_j(:,:) = 0._wp
+      CALL wnd_cyc( kt, zwnd_i, zwnd_j )    ! add analytical tropical cyclone (Vincent et al. JGR 2012)
+      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+         zwnd_i(ji,jj) = pwndi(ji,jj) + zwnd_i(ji,jj)
+         zwnd_j(ji,jj) = pwndj(ji,jj) + zwnd_j(ji,jj)
+         ! ... scalar wind at T-point (not masked)
+         wndm(ji,jj) = SQRT( zwnd_i(ji,jj) * zwnd_i(ji,jj) + zwnd_j(ji,jj) * zwnd_j(ji,jj) )
+      END_2D
+#else
+#if defined key_drakkar
+    IF (ln_clim_forcing) THEN
+       wndm(:,:) = sf(jp_wmod)%fnow(:,:,1)
+    ELSE
+#endif
+      ! ... scalar wind module at T-point (not masked)
+      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+         wndm(ji,jj) = SQRT(  pwndi(ji,jj) * pwndi(ji,jj) + pwndj(ji,jj) * pwndj(ji,jj)  )
+      END_2D
+#if defined key_drakkar
+    ENDIF
+#endif
+#endif
+      ! ----------------------------------------------------------------------------- !
+      !      I   Solar FLUX                                                           !
+      ! ----------------------------------------------------------------------------- !
+
+      ! ocean albedo assumed to be constant + modify now Qsr to include the diurnal cycle                    ! Short Wave
+      zztmp = 1. - albo
+      IF( ln_dm2dc ) THEN
+         qsr(:,:) = zztmp * sbc_dcy( pdqsr(:,:) ) * tmask(:,:,1)
+      ELSE
+         qsr(:,:) = zztmp *          pdqsr(:,:)   * tmask(:,:,1)
+      ENDIF
+
+
+      ! ----------------------------------------------------------------------------- !
+      !     II   Turbulent FLUXES                                                     !
+      ! ----------------------------------------------------------------------------- !
+
+      ! specific humidity at SST
+      pssq(:,:) = rdct_qsat_salt * q_sat( ptsk(:,:), pslp(:,:) )
+
+      IF( ln_skin_cs .OR. ln_skin_wl ) THEN
+         !! Backup "bulk SST" and associated spec. hum.
+         zztmp1(:,:) = zsspt(:,:)
+         zztmp2(:,:) = pssq(:,:)
+      ENDIF
+
+      !! Time to call the user-selected bulk parameterization for
+      !!  ==  transfer coefficients  ==!   Cd, Ch, Ce at T-point, and more...
+      SELECT CASE( nblk )
+
+      CASE( np_NCAR      )
+         CALL turb_ncar    (     rn_zqt, rn_zu, zsspt, ptair, pssq, pqair, wndm, &
+            &                zcd_oce, zch_oce, zce_oce, theta_zu, q_zu, zU_zu , &
+            &                nb_iter=nn_iter_algo )
+         !
+      CASE( np_COARE_3p0 )
+         CALL turb_coare3p0( kt, rn_zqt, rn_zu, zsspt, ptair, pssq, pqair, wndm, &
+            &                ln_skin_cs, ln_skin_wl,                            &
+            &                zcd_oce, zch_oce, zce_oce, theta_zu, q_zu, zU_zu,  &
+            &                nb_iter=nn_iter_algo,                              &
+            &                Qsw=qsr(:,:), rad_lw=pdqlw(:,:), slp=pslp(:,:) )
+         !
+      CASE( np_COARE_3p6 )
+         CALL turb_coare3p6( kt, rn_zqt, rn_zu, zsspt, ptair, pssq, pqair, wndm, &
+            &                ln_skin_cs, ln_skin_wl,                            &
+            &                zcd_oce, zch_oce, zce_oce, theta_zu, q_zu, zU_zu,  &
+            &                nb_iter=nn_iter_algo,                              &
+            &                Qsw=qsr(:,:), rad_lw=pdqlw(:,:), slp=pslp(:,:) )
+         !
+      CASE( np_ECMWF     )
+         CALL turb_ecmwf   ( kt, rn_zqt, rn_zu, zsspt, ptair, pssq, pqair, wndm, &
+            &                ln_skin_cs, ln_skin_wl,                            &
+            &                zcd_oce, zch_oce, zce_oce, theta_zu, q_zu, zU_zu,  &
+            &                nb_iter=nn_iter_algo,                              &
+            &                Qsw=qsr(:,:), rad_lw=pdqlw(:,:), slp=pslp(:,:) )
+         !
+      CASE( np_ANDREAS   )
+         CALL turb_andreas (     rn_zqt, rn_zu, zsspt, ptair, pssq, pqair, wndm, &
+            &                zcd_oce, zch_oce, zce_oce, theta_zu, q_zu, zU_zu , &
+            &                nb_iter=nn_iter_algo   )
+         !
+      CASE DEFAULT
+         CALL ctl_stop( 'STOP', 'sbc_oce: non-existing bulk parameterizaton selected' )
+         !
+      END SELECT
+
+      IF( iom_use('Cd_oce') )   CALL iom_put("Cd_oce",   zcd_oce * tmask(:,:,1))
+      IF( iom_use('Ce_oce') )   CALL iom_put("Ce_oce",   zce_oce * tmask(:,:,1))
+      IF( iom_use('Ch_oce') )   CALL iom_put("Ch_oce",   zch_oce * tmask(:,:,1))
+      !! LB: mainly here for debugging purpose:
+      IF( iom_use('theta_zt') ) CALL iom_put("theta_zt", (ptair-rt0) * tmask(:,:,1)) ! potential temperature at z=zt
+      IF( iom_use('q_zt') )     CALL iom_put("q_zt",     pqair       * tmask(:,:,1)) ! specific humidity       "
+      IF( iom_use('theta_zu') ) CALL iom_put("theta_zu", (theta_zu -rt0) * tmask(:,:,1)) ! potential temperature at z=zu
+      IF( iom_use('q_zu') )     CALL iom_put("q_zu",     q_zu        * tmask(:,:,1)) ! specific humidity       "
+      IF( iom_use('ssq') )      CALL iom_put("ssq",      pssq        * tmask(:,:,1)) ! saturation specific humidity at z=0
+      IF( iom_use('wspd_blk') ) CALL iom_put("wspd_blk", zU_zu       * tmask(:,:,1)) ! bulk wind speed at z=zu
+
+      IF( ln_skin_cs .OR. ln_skin_wl ) THEN
+         !! In the presence of sea-ice we forget about the cool-skin/warm-layer update of zsspt, pssq & ptsk:
+         WHERE ( fr_i(:,:) > 0.001_wp )
+            ! sea-ice present, we forget about the update, using what we backed up before call to turb_*()
+            zsspt(:,:) = zztmp1(:,:)
+            pssq(:,:)  = zztmp2(:,:)
+         END WHERE
+         ! apply potential temperature increment to abolute SST
+         ptsk(:,:) = ptsk(:,:) + ( zsspt(:,:) - zztmp1(:,:) )
+      END IF
+
+      !  Turbulent fluxes over ocean  => BULK_FORMULA @ sbc_phy.F90
+      ! -------------------------------------------------------------
+
+      IF( ln_abl ) THEN         !==  ABL formulation  ==!   multiplication by rho_air and turbulent fluxes computation done in ablstp
+
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+            zztmp = zU_zu(ji,jj)
+            wndm(ji,jj)   = zztmp                   ! Store zU_zu in wndm to compute ustar2 in ablmod
+            pcd_du(ji,jj) = zztmp * zcd_oce(ji,jj)
+            psen(ji,jj)   = zztmp * zch_oce(ji,jj)
+            pevp(ji,jj)   = zztmp * zce_oce(ji,jj)
+            zpre(ji,jj)   = pres_temp( pqair(ji,jj), pslp(ji,jj), rn_zu, ptpot=ptair(ji,jj), pta=ztabs(ji,jj) )
+            rhoa(ji,jj)   = rho_air( ztabs(ji,jj), pqair(ji,jj), zpre(ji,jj) )
+         END_2D
+
+      ELSE                      !==  BLK formulation  ==!   turbulent fluxes computation
+
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+            zpre(ji,jj) = pres_temp( q_zu(ji,jj), pslp(ji,jj), rn_zu, ptpot=theta_zu(ji,jj), pta=ztabs(ji,jj) )
+            rhoa(ji,jj) = rho_air( ztabs(ji,jj), q_zu(ji,jj), zpre(ji,jj) )
+         END_2D
+
+         CALL BULK_FORMULA( rn_zu, zsspt(:,:), pssq(:,:), theta_zu(:,:), q_zu(:,:), &
+            &               zcd_oce(:,:), zch_oce(:,:), zce_oce(:,:),          &
+            &               wndm(:,:), zU_zu(:,:), pslp(:,:), rhoa(:,:),       &
+            &               taum(:,:), psen(:,:), plat(:,:),                   &
+            &               pEvap=pevp(:,:), pfact_evap=rn_efac )
+
+         psen(:,:) = psen(:,:) * tmask(:,:,1)
+         plat(:,:) = plat(:,:) * tmask(:,:,1)
+         taum(:,:) = taum(:,:) * tmask(:,:,1)
+         pevp(:,:) = pevp(:,:) * tmask(:,:,1)
+
+#if defined key_drakkar
+        IF ( ln_clim_forcing ) THEN
+            zwu(:,:) =  sf(jp_uw)%fnow(:,:,1)
+            zwv(:,:) =  sf(jp_vw)%fnow(:,:,1)
+
+            DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+               IF( wndm(ji,jj) > 0._wp ) THEN
+                  zztmp = taum(ji,jj) / wndm(ji,jj) / wndm(ji,jj)
+            ! note that key_cyclone is not supported with climatological forcing
+                  ztau_i(ji,jj) = zztmp * zwu(ji,jj)
+                  ztau_j(ji,jj) = zztmp * zwv(ji,jj)
+               ELSE
+                 ztau_i(ji,jj) = 0._wp
+                 ztau_j(ji,jj) = 0._wp
+               ENDIF
+            END_2D
+        ELSE
+#endif
+
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+            IF( wndm(ji,jj) > 0._wp ) THEN
+              zztmp = taum(ji,jj) / wndm(ji,jj)
+#if defined key_cyclone
+               ztau_i(ji,jj) = zztmp * zwnd_i(ji,jj)
+               ztau_j(ji,jj) = zztmp * zwnd_j(ji,jj)
+#else
+               ztau_i(ji,jj) = zztmp * pwndi(ji,jj)
+               ztau_j(ji,jj) = zztmp * pwndj(ji,jj)
+#endif
+            ELSE
+               ztau_i(ji,jj) = 0._wp
+               ztau_j(ji,jj) = 0._wp
+            ENDIF
+         END_2D
+#if defined key_drakkar
+        ENDIF
+#endif
+
+         IF( ln_crt_fbk ) THEN   ! aply eq. 10 and 11 of Renault et al. 2020 (doi: 10.1029/2019MS001715)
+            zstmax = MIN( rn_stau_a * 3._wp + rn_stau_b, 0._wp )   ! set the max value of Stau corresponding to a wind of 3 m/s (<0)
+            DO_2D( 0, 1, 0, 1 )   ! end at jpj and jpi, as ztau_j(ji,jj+1) ztau_i(ji+1,jj) used in the next loop
+               zstau = MIN( rn_stau_a * wndm(ji,jj) + rn_stau_b, zstmax )   ! stau (<0) must be smaller than zstmax
+               ztau_i(ji,jj) = ztau_i(ji,jj) + zstau * ( 0.5_wp * ( pu(ji-1,jj  ) + pu(ji,jj) ) - puatm(ji,jj) )
+               ztau_j(ji,jj) = ztau_j(ji,jj) + zstau * ( 0.5_wp * ( pv(ji  ,jj-1) + pv(ji,jj) ) - pvatm(ji,jj) )
+               taum(ji,jj) = SQRT( ztau_i(ji,jj) * ztau_i(ji,jj) + ztau_j(ji,jj) * ztau_j(ji,jj) )
+            END_2D
+         ENDIF
+
+         ! ... utau, vtau at U- and V_points, resp.
+         !     Note the use of 0.5*(2-umask) in order to unmask the stress along coastlines
+         !     Note that coastal wind stress is not used in the code... so this extra care has no effect
+         DO_2D( 0, 0, 0, 0 )              ! start loop at 2, in case ln_crt_fbk = T
+            utau(ji,jj) = 0.5 * ( 2. - umask(ji,jj,1) ) * ( ztau_i(ji,jj) + ztau_i(ji+1,jj  ) ) &
+               &              * MAX(tmask(ji,jj,1),tmask(ji+1,jj,1))
+            vtau(ji,jj) = 0.5 * ( 2. - vmask(ji,jj,1) ) * ( ztau_j(ji,jj) + ztau_j(ji  ,jj+1) ) &
+               &              * MAX(tmask(ji,jj,1),tmask(ji,jj+1,1))
+         END_2D
+
+         IF( ln_crt_fbk ) THEN
+            CALL lbc_lnk( 'sbcblk', utau, 'U', -1._wp, vtau, 'V', -1._wp, taum, 'T', 1._wp )
+         ELSE
+            CALL lbc_lnk( 'sbcblk', utau, 'U', -1._wp, vtau, 'V', -1._wp )
+         ENDIF
+
+         ! Saving open-ocean wind-stress (module and components) on T-points:
+         CALL iom_put( "taum_oce",   taum(:,:)*tmask(:,:,1) )   ! output wind stress module
+         !#LB: These 2 lines below mostly here for 'STATION_ASF' test-case, otherwize "utau" (U-grid) and vtau" (V-grid) does the job in: [DYN/dynatf.F90])
+         CALL iom_put( "utau_oce", ztau_i(:,:)*tmask(:,:,1) )  ! utau at T-points!
+         CALL iom_put( "vtau_oce", ztau_j(:,:)*tmask(:,:,1) )  ! vtau at T-points!
+
+         IF(sn_cfctl%l_prtctl) THEN
+            CALL prt_ctl( tab2d_1=pssq   , clinfo1=' blk_oce_1: pssq   : ')
+            CALL prt_ctl( tab2d_1=wndm   , clinfo1=' blk_oce_1: wndm   : ')
+            CALL prt_ctl( tab2d_1=utau   , clinfo1=' blk_oce_1: utau   : ', mask1=umask,   &
+               &          tab2d_2=vtau   , clinfo2='            vtau   : ', mask2=vmask )
+            CALL prt_ctl( tab2d_1=zcd_oce, clinfo1=' blk_oce_1: Cd     : ')
+         ENDIF
+         !
+      ENDIF ! ln_blk / ln_abl
+
+      ptsk(:,:) = ( ptsk(:,:) - rt0 ) * tmask(:,:,1)  ! Back to Celsius
+
+      IF( ln_skin_cs .OR. ln_skin_wl ) THEN
+         CALL iom_put( "t_skin" ,  ptsk        )  ! T_skin in Celsius
+         CALL iom_put( "dt_skin" , ptsk - pst  )  ! T_skin - SST temperature difference
+      ENDIF
+      !
+   END SUBROUTINE blk_oce_1
+
+
+   SUBROUTINE blk_oce_2( ptair, pdqlw, pprec, psnow, &   ! <<= in
+      &                   ptsk, psen, plat, pevp     )   ! <<= in
+      !!---------------------------------------------------------------------
+      !!                     ***  ROUTINE blk_oce_2  ***
+      !!
+      !! ** Purpose :   finalize the momentum, heat and freshwater fluxes computation
+      !!                at the ocean surface at each time step knowing Cd, Ch, Ce and
+      !!                atmospheric variables (from ABL or external data)
+      !!
+#if defined key_drakkar
+      !! ** Outputs : - emp     :  evaporation minus precipitation       (kg/m2/s)
+      !!              - qns     : Non Solar heat flux over the ocean    (W/m2)
+      !!                          (include heat content of the precip, evap
+      !!                           latent heat flux from melting snow )
+      !!              - qns_oce : Just the sensible, latent and LW (to be used in SI3)
+      !!              - qsr_oce : = qsr   (to be used in SI3)
+#else
+      !! ** Outputs : - utau    : i-component of the stress at U-point  (N/m2)
+      !!              - vtau    : j-component of the stress at V-point  (N/m2)
+      !!              - taum    : Wind stress module at T-point         (N/m2)
+      !!              - wndm    : Wind speed module at T-point          (m/s)
+      !!              - qsr     : Solar heat flux over the ocean        (W/m2)
+      !!              - qns     : Non Solar heat flux over the ocean    (W/m2)
+      !!              - emp     : evaporation minus precipitation       (kg/m2/s)
+      !!---------------------------------------------------------------------
+#endif
+      REAL(wp), INTENT(in), DIMENSION(:,:) ::   ptair   ! potential temperature of air #LB: confirm!
+      REAL(wp), INTENT(in), DIMENSION(:,:) ::   pdqlw   ! downwelling longwave radiation at surface [W/m^2]
+      REAL(wp), INTENT(in), DIMENSION(:,:) ::   pprec
+      REAL(wp), INTENT(in), DIMENSION(:,:) ::   psnow
+      REAL(wp), INTENT(in), DIMENSION(:,:) ::   ptsk   ! SKIN surface temperature   [Celsius]
+      REAL(wp), INTENT(in), DIMENSION(:,:) ::   psen
+      REAL(wp), INTENT(in), DIMENSION(:,:) ::   plat
+      REAL(wp), INTENT(in), DIMENSION(:,:) ::   pevp
+      !
+      INTEGER  ::   ji, jj               ! dummy loop indices
+      REAL(wp) ::   zztmp,zz1,zz2,zz3    ! local variable
+      REAL(wp), DIMENSION(jpi,jpj) ::   zqlw              ! net long wave radiative heat flux
+      REAL(wp), DIMENSION(jpi,jpj) ::   zcptrain, zcptsnw, zcptn ! Heat content per unit mass (J/kg)
+      !!---------------------------------------------------------------------
+      !
+      ! Heat content per unit mass (J/kg)
+      zcptrain(:,:) = (      ptair        - rt0 ) * rcp  * tmask(:,:,1)
+      zcptsnw (:,:) = ( MIN( ptair, rt0 ) - rt0 ) * rcpi * tmask(:,:,1)
+      zcptn   (:,:) =        ptsk                 * rcp  * tmask(:,:,1)
+      !
+      ! ----------------------------------------------------------------------------- !
+      !     III    Net longwave radiative FLUX                                        !
+      ! ----------------------------------------------------------------------------- !
+      !! #LB: now moved after Turbulent fluxes because must use the skin temperature rather than bulk SST
+      !! (ptsk is skin temperature if ln_skin_cs==.TRUE. .OR. ln_skin_wl==.TRUE.)
+      zqlw(:,:) = qlw_net( pdqlw(:,:), ptsk(:,:)+rt0 )
+
+      ! ----------------------------------------------------------------------------- !
+      !     IV    Total FLUXES                                                       !
+      ! ----------------------------------------------------------------------------- !
+      !
+      emp (:,:) = ( pevp(:,:) - pprec(:,:) * rn_pfac ) * tmask(:,:,1)      ! mass flux (evap. - precip.)
+      !
+      qns(:,:) = zqlw(:,:) + psen(:,:) + plat(:,:)                     &   ! Downward Non Solar
+         &     - psnow(:,:) * rn_pfac * rLfus                          &   ! remove latent melting heat for solid precip
+         &     - pevp(:,:) * zcptn(:,:)                                &   ! remove evap heat content at SST
+         &     + ( pprec(:,:) - psnow(:,:) ) * rn_pfac * zcptrain(:,:) &   ! add liquid precip heat content at Tair
+         &     + psnow(:,:) * rn_pfac * zcptsnw(:,:)                       ! add solid  precip heat content at min(Tair,Tsnow)
+      qns(:,:) = qns(:,:) * tmask(:,:,1)
+      !
+#if defined key_si3
+      qns_oce(:,:) = zqlw(:,:) + psen(:,:) + plat(:,:)                             ! non solar without emp (only needed by SI3)
+      qsr_oce(:,:) = qsr(:,:)
+#endif
+      !
+      CALL iom_put( "rho_air"  , rhoa*tmask(:,:,1) )       ! output air density [kg/m^3]
+      CALL iom_put( "evap_oce" , pevp )                    ! evaporation
+      CALL iom_put( "qlw_oce"  , zqlw )                    ! output downward longwave heat over the ocean
+      CALL iom_put( "qsb_oce"  , psen )                    ! output downward sensible heat over the ocean
+      CALL iom_put( "qla_oce"  , plat )                    ! output downward latent   heat over the ocean
+      tprecip(:,:) = pprec(:,:) * rn_pfac * tmask(:,:,1)   ! output total precipitation [kg/m2/s]
+      sprecip(:,:) = psnow(:,:) * rn_pfac * tmask(:,:,1)   ! output solid precipitation [kg/m2/s]
+      CALL iom_put( 'snowpre', sprecip )                   ! Snow
+      CALL iom_put( 'precip' , tprecip )                   ! Total precipitation
+      !
+      IF ( nn_ice == 0 ) THEN
+         CALL iom_put( "qemp_oce" , qns-zqlw-psen-plat )   ! output downward heat content of E-P over the ocean
+         CALL iom_put( "qns_oce"  ,   qns  )               ! output downward non solar heat over the ocean
+         CALL iom_put( "qsr_oce"  ,   qsr  )               ! output downward solar heat over the ocean
+         CALL iom_put( "qt_oce"   ,   qns+qsr )            ! output total downward heat over the ocean
+      ENDIF
+      !
+      IF(sn_cfctl%l_prtctl) THEN
+         CALL prt_ctl(tab2d_1=zqlw , clinfo1=' blk_oce_2: zqlw  : ')
+         CALL prt_ctl(tab2d_1=psen , clinfo1=' blk_oce_2: psen  : ' )
+         CALL prt_ctl(tab2d_1=plat , clinfo1=' blk_oce_2: plat  : ' )
+         CALL prt_ctl(tab2d_1=qns  , clinfo1=' blk_oce_2: qns   : ' )
+         CALL prt_ctl(tab2d_1=emp  , clinfo1=' blk_oce_2: emp   : ')
+      ENDIF
+      !
+   END SUBROUTINE blk_oce_2
+
+
+#if defined key_si3
+   !!----------------------------------------------------------------------
+   !!   'key_si3'                                       SI3 sea-ice model
+   !!----------------------------------------------------------------------
+   !!   blk_ice_1   : provide the air-ice stress
+   !!   blk_ice_2   : provide the heat and mass fluxes at air-ice interface
+   !!   blk_ice_qcn : provide ice surface temperature and snow/ice conduction flux (emulating conduction flux)
+   !!----------------------------------------------------------------------
+
+   SUBROUTINE blk_ice_1( pwndi, pwndj, ptair, pqair, pslp , puice, pvice, ptsui,  &   ! inputs
+      &                  putaui, pvtaui, pseni, pevpi, pssqi, pcd_dui             )   ! optional outputs
+      !!---------------------------------------------------------------------
+      !!                     ***  ROUTINE blk_ice_1  ***
+      !!
+      !! ** Purpose :   provide the surface boundary condition over sea-ice
+      !!
+      !! ** Method  :   compute momentum using bulk formulation
+      !!                formulea, ice variables and read atmospheric fields.
+      !!                NB: ice drag coefficient is assumed to be a constant
+      !!---------------------------------------------------------------------
+      REAL(wp) , INTENT(in   ), DIMENSION(:,:  ) ::   pslp    ! sea-level pressure [Pa]
+      REAL(wp) , INTENT(in   ), DIMENSION(:,:  ) ::   pwndi   ! atmospheric wind at T-point [m/s]
+      REAL(wp) , INTENT(in   ), DIMENSION(:,:  ) ::   pwndj   ! atmospheric wind at T-point [m/s]
+      REAL(wp) , INTENT(in   ), DIMENSION(:,:  ) ::   ptair   ! atmospheric potential temperature at T-point [K]
+      REAL(wp) , INTENT(in   ), DIMENSION(:,:  ) ::   pqair   ! atmospheric specific humidity at T-point [kg/kg]
+      REAL(wp) , INTENT(in   ), DIMENSION(:,:  ) ::   puice   ! sea-ice velocity on I or C grid [m/s]
+      REAL(wp) , INTENT(in   ), DIMENSION(:,:  ) ::   pvice   ! "
+      REAL(wp) , INTENT(in   ), DIMENSION(:,:  ) ::   ptsui   ! sea-ice surface temperature [K]
+      REAL(wp) , INTENT(  out), DIMENSION(:,:  ), OPTIONAL ::   putaui  ! if ln_blk
+      REAL(wp) , INTENT(  out), DIMENSION(:,:  ), OPTIONAL ::   pvtaui  ! if ln_blk
+      REAL(wp) , INTENT(  out), DIMENSION(:,:  ), OPTIONAL ::   pseni   ! if ln_abl
+      REAL(wp) , INTENT(  out), DIMENSION(:,:  ), OPTIONAL ::   pevpi   ! if ln_abl
+      REAL(wp) , INTENT(  out), DIMENSION(:,:  ), OPTIONAL ::   pssqi   ! if ln_abl
+      REAL(wp) , INTENT(  out), DIMENSION(:,:  ), OPTIONAL ::   pcd_dui ! if ln_abl
+      !
+      INTEGER  ::   ji, jj    ! dummy loop indices
+      REAL(wp) ::   zootm_su                      ! sea-ice surface mean temperature
+      REAL(wp) ::   zztmp1, zztmp2                ! temporary scalars
+      REAL(wp), DIMENSION(jpi,jpj) :: ztmp, zsipt ! temporary array
+#if defined key_drakkar
+      REAL(wp), DIMENSION(jpi,jpj) :: zwu, zwv    ! temporary array
+#endif
+      !!---------------------------------------------------------------------
+      !
+      ! ------------------------------------------------------------ !
+      !    Wind module relative to the moving ice ( U10m - U_ice )   !
+      ! ------------------------------------------------------------ !
+      ! C-grid ice dynamics :   U & V-points (same as ocean)
+#if defined key_drakkar
+      IF ( ln_clim_forcing) THEN
+        wndm_ice(:,:) = sf(jp_wmod)%fnow(:,:,1)
+      ELSE
+#endif
+      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+         wndm_ice(ji,jj) = SQRT( pwndi(ji,jj) * pwndi(ji,jj) + pwndj(ji,jj) * pwndj(ji,jj) )
+      END_2D
+#if defined key_drakkar
+      ENDIF
+#endif
+      !
+      ! potential sea-ice surface temperature [K]
+      zsipt(:,:) = theta_exner( ptsui(:,:), pslp(:,:) )
+
+      ! sea-ice <-> atmosphere bulk transfer coefficients
+      SELECT CASE( nblk_ice )
+
+      CASE( np_ice_cst      )
+         ! Constant bulk transfer coefficients over sea-ice:
+         Cd_ice(:,:) = rn_Cd_i
+         Ch_ice(:,:) = rn_Ch_i
+         Ce_ice(:,:) = rn_Ce_i
+         ! no height adjustment, keeping zt values:
+         theta_zu_i(:,:) = ptair(:,:)
+         q_zu_i(:,:)     = pqair(:,:)
+
+      CASE( np_ice_an05 )  ! calculate new drag from Lupkes(2015) equations
+         ztmp(:,:) = q_sat( ptsui(:,:), pslp(:,:), l_ice=.TRUE. ) ! temporary array for SSQ
+         CALL turb_ice_an05( rn_zqt, rn_zu, zsipt, ptair, ztmp, pqair, wndm_ice,       &
+            &                      Cd_ice, Ch_ice, Ce_ice, theta_zu_i, q_zu_i )
+         !!
+      CASE( np_ice_lu12 )
+         ztmp(:,:) = q_sat( ptsui(:,:), pslp(:,:), l_ice=.TRUE. ) ! temporary array for SSQ
+         CALL turb_ice_lu12( rn_zqt, rn_zu, zsipt, ptair, ztmp, pqair, wndm_ice, fr_i, &
+            &                      Cd_ice, Ch_ice, Ce_ice, theta_zu_i, q_zu_i )
+         !!
+      CASE( np_ice_lg15 )  ! calculate new drag from Lupkes(2015) equations
+         ztmp(:,:) = q_sat( ptsui(:,:), pslp(:,:), l_ice=.TRUE. ) ! temporary array for SSQ
+         CALL turb_ice_lg15( rn_zqt, rn_zu, zsipt, ptair, ztmp, pqair, wndm_ice, fr_i, &
+            &                      Cd_ice, Ch_ice, Ce_ice, theta_zu_i, q_zu_i )
+         !!
+      END SELECT
+
+      IF( iom_use('Cd_ice').OR.iom_use('Ce_ice').OR.iom_use('Ch_ice').OR.iom_use('taum_ice').OR.iom_use('utau_ice').OR.iom_use('vtau_ice') ) &
+         & ztmp(:,:) = ( 1._wp - MAX(0._wp, SIGN( 1._wp, 1.E-6_wp - fr_i )) )*tmask(:,:,1) ! mask for presence of ice !
+
+      IF( iom_use('Cd_ice') ) CALL iom_put("Cd_ice", Cd_ice*ztmp)
+      IF( iom_use('Ce_ice') ) CALL iom_put("Ce_ice", Ce_ice*ztmp)
+      IF( iom_use('Ch_ice') ) CALL iom_put("Ch_ice", Ch_ice*ztmp)
+
+
+      IF( ln_blk ) THEN
+         ! ---------------------------------------------------- !
+         !    Wind stress relative to nonmoving ice ( U10m )    !
+         ! ---------------------------------------------------- !
+         ! supress moving ice in wind stress computation as we don't know how to do it properly...
+#if defined key_drakkar
+      IF ( ln_clim_forcing ) THEN
+         zwu(:,:) = sf(jp_uw)%fnow(:,:,1)
+         zwv(:,:) = sf(jp_vw)%fnow(:,:,1)
+         DO_2D( 0, 1, 0, 1 )    ! at T point
+            zztmp1        = rhoa(ji,jj) * Cd_ice(ji,jj) 
+            putaui(ji,jj) = zztmp1 * zwu (ji,jj)
+            pvtaui(ji,jj) = zztmp1 * zwv (ji,jj)
+         END_2D
+      ELSE
+#endif
+         DO_2D( 0, 1, 0, 1 )    ! at T point
+            zztmp1        = rhoa(ji,jj) * Cd_ice(ji,jj) * wndm_ice(ji,jj)
+            putaui(ji,jj) = zztmp1 * pwndi(ji,jj)
+            pvtaui(ji,jj) = zztmp1 * pwndj(ji,jj)
+         END_2D
+#if defined key_drakkar
+      ENDIF
+#endif
+
+         !#LB: saving the module, and x-y components, of the ai wind-stress at T-points: NOT weighted by the ice concentration !!!
+         IF(iom_use('taum_ice')) CALL iom_put('taum_ice', SQRT( putaui*putaui + pvtaui*pvtaui )*ztmp )
+         !#LB: These 2 lines below mostly here for 'STATION_ASF' test-case, otherwize "utau_oi" (U-grid) and vtau_oi" (V-grid) does the job in: [ICE/icedyn_rhg_evp.F90])
+         IF(iom_use('utau_ice')) CALL iom_put("utau_ice", putaui*ztmp)  ! utau at T-points!
+         IF(iom_use('vtau_ice')) CALL iom_put("vtau_ice", pvtaui*ztmp)  ! vtau at T-points!
+
+         !
+         DO_2D( 0, 0, 0, 0 )    ! U & V-points (same as ocean).
+            !#LB: QUESTION?? so SI3 expects wind stress vector to be provided at U & V points? Not at T-points ?
+            ! take care of the land-sea mask to avoid "pollution" of coastal stress. p[uv]taui used in frazil and  rheology
+            zztmp1 = 0.5_wp * ( 2. - umask(ji,jj,1) ) * MAX( tmask(ji,jj,1),tmask(ji+1,jj  ,1) )
+            zztmp2 = 0.5_wp * ( 2. - vmask(ji,jj,1) ) * MAX( tmask(ji,jj,1),tmask(ji  ,jj+1,1) )
+            putaui(ji,jj) = zztmp1 * ( putaui(ji,jj) + putaui(ji+1,jj  ) )
+            pvtaui(ji,jj) = zztmp2 * ( pvtaui(ji,jj) + pvtaui(ji  ,jj+1) )
+         END_2D
+         CALL lbc_lnk( 'sbcblk', putaui, 'U', -1._wp, pvtaui, 'V', -1._wp )
+         !
+         IF(sn_cfctl%l_prtctl)  CALL prt_ctl( tab2d_1=putaui  , clinfo1=' blk_ice: putaui : '   &
+            &                               , tab2d_2=pvtaui  , clinfo2='          pvtaui : ' )
+      ELSE ! ln_abl
+
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+            pcd_dui(ji,jj) = wndm_ice(ji,jj) * Cd_ice(ji,jj)
+            pseni  (ji,jj) = wndm_ice(ji,jj) * Ch_ice(ji,jj)
+            pevpi  (ji,jj) = wndm_ice(ji,jj) * Ce_ice(ji,jj)
+         END_2D
+         pssqi(:,:) = q_sat( ptsui(:,:), pslp(:,:), l_ice=.TRUE. ) ; ! more accurate way to obtain ssq !
+
+      ENDIF ! ln_blk  / ln_abl
+      !
+      IF(sn_cfctl%l_prtctl)  CALL prt_ctl(tab2d_1=wndm_ice  , clinfo1=' blk_ice: wndm_ice : ')
+      !
+   END SUBROUTINE blk_ice_1
+
+
+   SUBROUTINE blk_ice_2( ptsu, phs, phi, palb, ptair, pqair, pslp, pdqlw, pprec, psnow  )
+      !!---------------------------------------------------------------------
+      !!                     ***  ROUTINE blk_ice_2  ***
+      !!
+      !! ** Purpose :   provide the heat and mass fluxes at air-ice interface
+      !!
+      !! ** Method  :   compute heat and freshwater exchanged
+      !!                between atmosphere and sea-ice using bulk formulation
+      !!                formulea, ice variables and read atmmospheric fields.
+      !!
+      !! caution : the net upward water flux has with mm/day unit
+      !!---------------------------------------------------------------------
+      REAL(wp), DIMENSION(:,:,:), INTENT(in)  ::   ptsu   ! sea ice surface temperature [K]
+      REAL(wp), DIMENSION(:,:,:), INTENT(in)  ::   phs    ! snow thickness
+      REAL(wp), DIMENSION(:,:,:), INTENT(in)  ::   phi    ! ice thickness
+      REAL(wp), DIMENSION(:,:,:), INTENT(in)  ::   palb   ! ice albedo (all skies)
+      REAL(wp), DIMENSION(:,:  ), INTENT(in)  ::   ptair  ! potential temperature of air #LB: okay ???
+      REAL(wp), DIMENSION(:,:  ), INTENT(in)  ::   pqair  ! specific humidity of air
+      REAL(wp), DIMENSION(:,:  ), INTENT(in)  ::   pslp
+      REAL(wp), DIMENSION(:,:  ), INTENT(in)  ::   pdqlw
+      REAL(wp), DIMENSION(:,:  ), INTENT(in)  ::   pprec
+      REAL(wp), DIMENSION(:,:  ), INTENT(in)  ::   psnow
+      !!
+      INTEGER  ::   ji, jj, jl               ! dummy loop indices
+      REAL(wp) ::   zst, zst3, zsq, zsipt    ! local variable
+      REAL(wp) ::   zcoef_dqlw, zcoef_dqla   !   -      -
+      REAL(wp) ::   zztmp, zzblk, zztmp1, z1_rLsub   !   -      -
+      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z_qlw         ! long wave heat flux over ice
+      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z_qsb         ! sensible  heat flux over ice
+      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z_dqlw        ! long wave heat sensitivity over ice
+      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   z_dqsb        ! sensible  heat sensitivity over ice
+      REAL(wp), DIMENSION(jpi,jpj)     ::   zevap, zsnw   ! evaporation and snw distribution after wind blowing (SI3)
+      REAL(wp), DIMENSION(jpi,jpj)     ::   ztmp, ztmp2
+      REAL(wp), DIMENSION(jpi,jpj)     ::   ztri
+      REAL(wp), DIMENSION(jpi,jpj)     ::   zcptrain, zcptsnw, zcptn ! Heat content per unit mass (J/kg)
+      !!---------------------------------------------------------------------
+      !
+      zcoef_dqlw = 4._wp * emiss_i * stefan             ! local scalars
+      zztmp = 1. / ( 1. - albo )
+      dqla_ice(:,:,:) = 0._wp
+
+      ! Heat content per unit mass (J/kg)
+      zcptrain(:,:) = (      ptair        - rt0 ) * rcp  * tmask(:,:,1)
+      zcptsnw (:,:) = ( MIN( ptair, rt0 ) - rt0 ) * rcpi * tmask(:,:,1)
+      zcptn   (:,:) =        sst_m                * rcp  * tmask(:,:,1)
+      !
+      !                                     ! ========================== !
+      DO jl = 1, jpl                        !  Loop over ice categories  !
+         !                                  ! ========================== !
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+
+            zst   = ptsu(ji,jj,jl)                                ! surface temperature of sea-ice [K]
+            zsq   = q_sat( zst, pslp(ji,jj), l_ice=.TRUE. )       ! surface saturation specific humidity when ice present
+            zsipt = theta_exner( zst, pslp(ji,jj) )               ! potential sea-ice surface temperature [K]  
+
+            ! ----------------------------!
+            !      I   Radiative FLUXES   !
+            ! ----------------------------!
+            ! Short Wave (sw)
+            qsr_ice(ji,jj,jl) = zztmp * ( 1. - palb(ji,jj,jl) ) * qsr(ji,jj)
+
+            ! Long  Wave (lw)
+            zst3 = zst * zst * zst
+            z_qlw(ji,jj,jl)   = emiss_i * ( pdqlw(ji,jj) - stefan * zst * zst3 ) * tmask(ji,jj,1)
+            ! lw sensitivity
+            z_dqlw(ji,jj,jl)  = zcoef_dqlw * zst3
+
+            ! ----------------------------!
+            !     II    Turbulent FLUXES  !
+            ! ----------------------------!
+
+            ! ... turbulent heat fluxes with Ch_ice recalculated in blk_ice_1
+
+            ! Common term in bulk F. equations...
+            zzblk = rhoa(ji,jj) * wndm_ice(ji,jj)
+
+            ! Sensible Heat
+            zztmp1 = zzblk * rCp_air * Ch_ice(ji,jj)
+            z_qsb (ji,jj,jl) = zztmp1 * (zsipt - theta_zu_i(ji,jj))
+            z_dqsb(ji,jj,jl) = zztmp1                        ! ==> Qsens sensitivity (Dqsb_ice/Dtn_ice)
+
+            ! Latent Heat
+            zztmp1 = zzblk * rLsub * Ce_ice(ji,jj)
+            qla_ice(ji,jj,jl) = MAX( zztmp1 * (zsq - q_zu_i(ji,jj)) , 0._wp )   ! #LB: only sublimation (and not condensation) ???
+            IF(qla_ice(ji,jj,jl)>0._wp) dqla_ice(ji,jj,jl) = zztmp1*dq_sat_dt_ice(zst, pslp(ji,jj)) ! ==> Qlat sensitivity  (dQlat/dT)
+            !                                                                                       !#LB: dq_sat_dt_ice() in "sbc_phy.F90"
+            !#LB: without this unjustified "condensation sensure":
+            !qla_ice( ji,jj,jl) = zztmp1 * (zsq - q_zu_i(ji,jj))
+            !dqla_ice(ji,jj,jl) = zztmp1 * dq_sat_dt_ice(zst, pslp(ji,jj)) ! ==> Qlat sensitivity  (dQlat/dT)
+
+
+            ! ----------------------------!
+            !     III    Total FLUXES     !
+            ! ----------------------------!
+            ! Downward Non Solar flux
+            qns_ice (ji,jj,jl) =     z_qlw (ji,jj,jl) - z_qsb (ji,jj,jl) - qla_ice (ji,jj,jl)
+            ! Total non solar heat flux sensitivity for ice
+            dqns_ice(ji,jj,jl) = - ( z_dqlw(ji,jj,jl) + z_dqsb(ji,jj,jl) + dqla_ice(ji,jj,jl) ) !#LB: correct signs ????
+
+         END_2D
+         !
+      END DO
+      !
+      tprecip(:,:) = pprec(:,:) * rn_pfac * tmask(:,:,1)  ! total precipitation [kg/m2/s]
+      sprecip(:,:) = psnow(:,:) * rn_pfac * tmask(:,:,1)  ! solid precipitation [kg/m2/s]
+      CALL iom_put( 'snowpre', sprecip )                  ! Snow precipitation
+      CALL iom_put( 'precip' , tprecip )                  ! Total precipitation
+
+      ! --- evaporation --- !
+      z1_rLsub = 1._wp / rLsub
+      evap_ice (:,:,:) = rn_efac * qla_ice (:,:,:) * z1_rLsub    ! sublimation
+      devap_ice(:,:,:) = rn_efac * dqla_ice(:,:,:) * z1_rLsub    ! d(sublimation)/dT
+      zevap    (:,:)   = emp(:,:) + tprecip(:,:)   ! evaporation over ocean  !LB: removed rn_efac here, correct???
+
+      ! --- evaporation minus precipitation --- !
+      zsnw(:,:) = 0._wp
+      CALL ice_var_snwblow( (1.-at_i_b(:,:)), zsnw )  ! snow distribution over ice after wind blowing
+      emp_oce(:,:) = ( 1._wp - at_i_b(:,:) ) * zevap(:,:) - ( tprecip(:,:) - sprecip(:,:) ) - sprecip(:,:) * (1._wp - zsnw )
+      emp_ice(:,:) = SUM( a_i_b(:,:,:) * evap_ice(:,:,:), dim=3 ) - sprecip(:,:) * zsnw
+      emp_tot(:,:) = emp_oce(:,:) + emp_ice(:,:)
+
+      ! --- heat flux associated with emp --- !
+      qemp_oce(:,:) = - ( 1._wp - at_i_b(:,:) ) * zevap(:,:) * zcptn(:,:)         & ! evap at sst
+         &          + ( tprecip(:,:) - sprecip(:,:) )   *   zcptrain(:,:)         & ! liquid precip at Tair
+         &          +   sprecip(:,:) * ( 1._wp - zsnw ) * ( zcptsnw (:,:) - rLfus ) ! solid precip at min(Tair,Tsnow)
+      qemp_ice(:,:) =   sprecip(:,:) *           zsnw   * ( zcptsnw (:,:) - rLfus ) ! solid precip (only)
+
+      ! --- total solar and non solar fluxes --- !
+      qns_tot(:,:) = ( 1._wp - at_i_b(:,:) ) * qns_oce(:,:) + SUM( a_i_b(:,:,:) * qns_ice(:,:,:), dim=3 )  &
+         &           + qemp_ice(:,:) + qemp_oce(:,:)
+      qsr_tot(:,:) = ( 1._wp - at_i_b(:,:) ) * qsr_oce(:,:) + SUM( a_i_b(:,:,:) * qsr_ice(:,:,:), dim=3 )
+
+      ! --- heat content of precip over ice in J/m3 (to be used in 1D-thermo) --- !
+      qprec_ice(:,:) = rhos * ( zcptsnw(:,:) - rLfus )
+
+      ! --- heat content of evap over ice in W/m2 (to be used in 1D-thermo) ---
+      DO jl = 1, jpl
+         qevap_ice(:,:,jl) = 0._wp ! should be -evap_ice(:,:,jl)*( ( Tice - rt0 ) * rcpi * tmask(:,:,1) )
+         !                         ! But we do not have Tice => consider it at 0degC => evap=0
+      END DO
+
+      ! --- shortwave radiation transmitted thru the surface scattering layer (W/m2) --- !
+      IF( nn_qtrice == 0 ) THEN
+         ! formulation derived from Grenfell and Maykut (1977), where transmission rate
+         !    1) depends on cloudiness
+         !    2) is 0 when there is any snow
+         !    3) tends to 1 for thin ice
+         ztri(:,:) = 0.18 * ( 1.0 - cloud_fra(:,:) ) + 0.35 * cloud_fra(:,:)  ! surface transmission when hi>10cm
+         DO jl = 1, jpl
+            WHERE    ( phs(:,:,jl) <= 0._wp .AND. phi(:,:,jl) <  0.1_wp )     ! linear decrease from hi=0 to 10cm
+               qtr_ice_top(:,:,jl) = qsr_ice(:,:,jl) * ( ztri(:,:) + ( 1._wp - ztri(:,:) ) * ( 1._wp - phi(:,:,jl) * 10._wp ) )
+            ELSEWHERE( phs(:,:,jl) <= 0._wp .AND. phi(:,:,jl) >= 0.1_wp )     ! constant (ztri) when hi>10cm
+               qtr_ice_top(:,:,jl) = qsr_ice(:,:,jl) * ztri(:,:)
+            ELSEWHERE                                                         ! zero when hs>0
+               qtr_ice_top(:,:,jl) = 0._wp
+            END WHERE
+         ENDDO
+      ELSEIF( nn_qtrice == 1 ) THEN
+         ! formulation is derived from the thesis of M. Lebrun (2019).
+         !    It represents the best fit using several sets of observations
+         !    It comes with snow conductivities adapted to freezing/melting conditions (see icethd_zdf_bl99.F90)
+         qtr_ice_top(:,:,:) = 0.3_wp * qsr_ice(:,:,:)
+      ENDIF
+      !
+      IF( iom_use('evap_ao_cea') .OR. iom_use('hflx_evap_cea') ) THEN
+         CALL iom_put( 'evap_ao_cea'  , zevap(:,:) * ( 1._wp - at_i_b(:,:) ) * tmask(:,:,1)              )   ! ice-free oce evap (cell average)
+         CALL iom_put( 'hflx_evap_cea', zevap(:,:) * ( 1._wp - at_i_b(:,:) ) * tmask(:,:,1) * zcptn(:,:) )   ! heat flux from evap (cell average)
+      ENDIF
+      IF( iom_use('rain') .OR. iom_use('rain_ao_cea') .OR. iom_use('hflx_rain_cea') ) THEN
+         CALL iom_put( 'rain'         ,   tprecip(:,:) - sprecip(:,:)                             )          ! liquid precipitation 
+         CALL iom_put( 'rain_ao_cea'  , ( tprecip(:,:) - sprecip(:,:) ) * ( 1._wp - at_i_b(:,:) ) )          ! liquid precipitation over ocean (cell average)
+         CALL iom_put( 'hflx_rain_cea', ( tprecip(:,:) - sprecip(:,:) ) * zcptrain(:,:) )                    ! heat flux from rain (cell average)
+      ENDIF
+      IF(  iom_use('snow_ao_cea')   .OR. iom_use('snow_ai_cea')      .OR. &
+         & iom_use('hflx_snow_cea') .OR. iom_use('hflx_snow_ao_cea') .OR. iom_use('hflx_snow_ai_cea')  )  THEN
+         CALL iom_put( 'snow_ao_cea'     , sprecip(:,:)                            * ( 1._wp - zsnw(:,:) ) ) ! Snow over ice-free ocean  (cell average)
+         CALL iom_put( 'snow_ai_cea'     , sprecip(:,:)                            *           zsnw(:,:)   ) ! Snow over sea-ice         (cell average)
+         CALL iom_put( 'hflx_snow_cea'   , sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) )                         ! heat flux from snow (cell average)
+         CALL iom_put( 'hflx_snow_ao_cea', sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) * ( 1._wp - zsnw(:,:) ) ) ! heat flux from snow (over ocean)
+         CALL iom_put( 'hflx_snow_ai_cea', sprecip(:,:) * ( zcptsnw(:,:) - rLfus ) *           zsnw(:,:)   ) ! heat flux from snow (over ice)
+      ENDIF
+      IF( iom_use('hflx_prec_cea') ) THEN                                                                    ! heat flux from precip (cell average)
+         CALL iom_put('hflx_prec_cea' ,    sprecip(:,:)                  * ( zcptsnw (:,:) - rLfus )  &
+            &                          + ( tprecip(:,:) - sprecip(:,:) ) *   zcptrain(:,:) )
+      ENDIF
+      IF( iom_use('subl_ai_cea') .OR. iom_use('hflx_subl_cea') ) THEN
+         CALL iom_put( 'subl_ai_cea'  , SUM( a_i_b(:,:,:) *  evap_ice(:,:,:), dim=3 ) * tmask(:,:,1) ) ! Sublimation over sea-ice (cell average)
+         CALL iom_put( 'hflx_subl_cea', SUM( a_i_b(:,:,:) * qevap_ice(:,:,:), dim=3 ) * tmask(:,:,1) ) ! Heat flux from sublimation (cell average)
+      ENDIF
+      !
+      IF(sn_cfctl%l_prtctl) THEN
+         CALL prt_ctl(tab3d_1=qla_ice , clinfo1=' blk_ice: qla_ice  : ', tab3d_2=z_qsb   , clinfo2=' z_qsb    : ', kdim=jpl)
+         CALL prt_ctl(tab3d_1=z_qlw   , clinfo1=' blk_ice: z_qlw    : ', tab3d_2=dqla_ice, clinfo2=' dqla_ice : ', kdim=jpl)
+         CALL prt_ctl(tab3d_1=z_dqsb  , clinfo1=' blk_ice: z_dqsb   : ', tab3d_2=z_dqlw  , clinfo2=' z_dqlw   : ', kdim=jpl)
+         CALL prt_ctl(tab3d_1=dqns_ice, clinfo1=' blk_ice: dqns_ice : ', tab3d_2=qsr_ice , clinfo2=' qsr_ice  : ', kdim=jpl)
+         CALL prt_ctl(tab3d_1=ptsu    , clinfo1=' blk_ice: ptsu     : ', tab3d_2=qns_ice , clinfo2=' qns_ice  : ', kdim=jpl)
+         CALL prt_ctl(tab2d_1=tprecip , clinfo1=' blk_ice: tprecip  : ', tab2d_2=sprecip , clinfo2=' sprecip  : ')
+      ENDIF
+
+      !#LB:
+      ! air-ice heat flux components that are not written from ice_stp()@icestp.F90:
+      IF( iom_use('qla_ice') )  CALL iom_put( 'qla_ice', SUM( - qla_ice * a_i_b, dim=3 ) ) !#LB: sign consistent with what's done for ocean
+      IF( iom_use('qsb_ice') )  CALL iom_put( 'qsb_ice', SUM( -   z_qsb * a_i_b, dim=3 ) ) !#LB:     ==> negative => loss of heat for sea-ice
+      IF( iom_use('qlw_ice') )  CALL iom_put( 'qlw_ice', SUM(     z_qlw * a_i_b, dim=3 ) )
+      !#LB.
+
+   END SUBROUTINE blk_ice_2
+
+
+   SUBROUTINE blk_ice_qcn( ld_virtual_itd, ptsu, ptb, phs, phi )
+      !!---------------------------------------------------------------------
+      !!                     ***  ROUTINE blk_ice_qcn  ***
+      !!
+      !! ** Purpose :   Compute surface temperature and snow/ice conduction flux
+      !!                to force sea ice / snow thermodynamics
+      !!                in the case conduction flux is emulated
+      !!
+      !! ** Method  :   compute surface energy balance assuming neglecting heat storage
+      !!                following the 0-layer Semtner (1976) approach
+      !!
+      !! ** Outputs : - ptsu    : sea-ice / snow surface temperature (K)
+      !!              - qcn_ice : surface inner conduction flux (W/m2)
+      !!
+      !!---------------------------------------------------------------------
+      LOGICAL                   , INTENT(in   ) ::   ld_virtual_itd  ! single-category option
+      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   ptsu            ! sea ice / snow surface temperature
+      REAL(wp), DIMENSION(:,:)  , INTENT(in   ) ::   ptb             ! sea ice base temperature
+      REAL(wp), DIMENSION(:,:,:), INTENT(in   ) ::   phs             ! snow thickness
+      REAL(wp), DIMENSION(:,:,:), INTENT(in   ) ::   phi             ! sea ice thickness
+      !
+      INTEGER , PARAMETER ::   nit = 10                  ! number of iterations
+      REAL(wp), PARAMETER ::   zepsilon = 0.1_wp         ! characteristic thickness for enhanced conduction
+      !
+      INTEGER  ::   ji, jj, jl           ! dummy loop indices
+      INTEGER  ::   iter                 ! local integer
+      REAL(wp) ::   zfac, zfac2, zfac3   ! local scalars
+      REAL(wp) ::   zkeff_h, ztsu, ztsu0 !
+      REAL(wp) ::   zqc, zqnet           !
+      REAL(wp) ::   zhe, zqa0            !
+      REAL(wp), DIMENSION(jpi,jpj,jpl) ::   zgfac   ! enhanced conduction factor
+      !!---------------------------------------------------------------------
+
+      ! -------------------------------------!
+      !      I   Enhanced conduction factor  !
+      ! -------------------------------------!
+      ! Emulates the enhancement of conduction by unresolved thin ice (ld_virtual_itd = T)
+      ! Fichefet and Morales Maqueda, JGR 1997
+      !
+      zgfac(:,:,:) = 1._wp
+
+      IF( ld_virtual_itd ) THEN
+         !
+         zfac  = 1._wp /  ( rn_cnd_s + rcnd_i )
+         zfac2 = EXP(1._wp) * 0.5_wp * zepsilon
+         zfac3 = 2._wp / zepsilon
+         !
+         DO jl = 1, jpl
+            DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+               zhe = ( rn_cnd_s * phi(ji,jj,jl) + rcnd_i * phs(ji,jj,jl) ) * zfac                            ! Effective thickness
+               IF( zhe >=  zfac2 )   zgfac(ji,jj,jl) = MIN( 2._wp, 0.5_wp * ( 1._wp + LOG( zhe * zfac3 ) ) ) ! Enhanced conduction factor
+            END_2D
+         END DO
+         !
+      ENDIF
+
+      ! -------------------------------------------------------------!
+      !      II   Surface temperature and conduction flux            !
+      ! -------------------------------------------------------------!
+      !
+      zfac = rcnd_i * rn_cnd_s
+      !
+      DO jl = 1, jpl
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+            !
+            zkeff_h = zfac * zgfac(ji,jj,jl) / &                                    ! Effective conductivity of the snow-ice system divided by thickness
+               &      ( rcnd_i * phs(ji,jj,jl) + rn_cnd_s * MAX( 0.01, phi(ji,jj,jl) ) )
+            ztsu    = ptsu(ji,jj,jl)                                                ! Store current iteration temperature
+            ztsu0   = ptsu(ji,jj,jl)                                                ! Store initial surface temperature
+            zqa0    = qsr_ice(ji,jj,jl) - qtr_ice_top(ji,jj,jl) + qns_ice(ji,jj,jl) ! Net initial atmospheric heat flux
+            !
+            DO iter = 1, nit     ! --- Iterative loop
+               zqc   = zkeff_h * ( ztsu - ptb(ji,jj) )                              ! Conduction heat flux through snow-ice system (>0 downwards)
+               zqnet = zqa0 + dqns_ice(ji,jj,jl) * ( ztsu - ptsu(ji,jj,jl) ) - zqc  ! Surface energy budget
+               ztsu  = ztsu - zqnet / ( dqns_ice(ji,jj,jl) - zkeff_h )              ! Temperature update
+            END DO
+            !
+            ptsu   (ji,jj,jl) = MIN( rt0, ztsu )
+            qcn_ice(ji,jj,jl) = zkeff_h * ( ptsu(ji,jj,jl) - ptb(ji,jj) )
+            qns_ice(ji,jj,jl) = qns_ice(ji,jj,jl) + dqns_ice(ji,jj,jl) * ( ptsu(ji,jj,jl) - ztsu0 )
+            qml_ice(ji,jj,jl) = ( qsr_ice(ji,jj,jl) - qtr_ice_top(ji,jj,jl) + qns_ice(ji,jj,jl) - qcn_ice(ji,jj,jl) )  &
+               &   * MAX( 0._wp , SIGN( 1._wp, ptsu(ji,jj,jl) - rt0 ) )
+
+            ! --- Diagnose the heat loss due to changing non-solar flux (as in icethd_zdf_bl99) --- !
+            hfx_err_dif(ji,jj) = hfx_err_dif(ji,jj) - ( dqns_ice(ji,jj,jl) * ( ptsu(ji,jj,jl) - ztsu0 ) ) * a_i_b(ji,jj,jl)
+
+         END_2D
+         !
+      END DO
+      !
+   END SUBROUTINE blk_ice_qcn
+
+#endif
+
+   !!======================================================================
+END MODULE sbcblk

+ 259 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/sbcfwb.F90

@@ -0,0 +1,259 @@
+MODULE sbcfwb
+   !!======================================================================
+   !!                       ***  MODULE  sbcfwb  ***
+   !! Ocean fluxes   : domain averaged freshwater budget
+   !!======================================================================
+   !! History :  OPA  ! 2001-02  (E. Durand)  Original code
+   !!   NEMO     1.0  ! 2002-06  (G. Madec)  F90: Free form and module
+   !!            3.0  ! 2006-08  (G. Madec)  Surface module
+   !!            3.2  ! 2009-07  (C. Talandier) emp mean s spread over erp area 
+   !!            3.6  ! 2014-11  (P. Mathiot  ) add ice shelf melting
+   !!----------------------------------------------------------------------
+
+   !!----------------------------------------------------------------------
+   !!   sbc_fwb       : freshwater budget for global ocean configurations (free surface & forced mode)
+   !!----------------------------------------------------------------------
+   USE oce            ! ocean dynamics and tracers
+   USE dom_oce        ! ocean space and time domain
+   USE sbc_oce        ! surface ocean boundary condition
+   USE isf_oce , ONLY : fwfisf_cav, fwfisf_par                    ! ice shelf melting contribution
+   USE sbc_ice , ONLY : snwice_mass, snwice_mass_b, snwice_fmass
+   USE phycst         ! physical constants
+   USE sbcrnf         ! ocean runoffs
+   USE sbcssr         ! Sea-Surface damping terms
+   !
+   USE in_out_manager ! I/O manager
+   USE iom            ! IOM
+   USE lib_mpp        ! distribued memory computing library
+   USE timing         ! Timing
+   USE lbclnk         ! ocean lateral boundary conditions
+   USE lib_fortran    ! 
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   sbc_fwb    ! routine called by step
+
+   REAL(wp) ::   rn_fwb0   ! initial freshwater adjustment flux [kg/m2/s] (nn_fwb = 2 only)
+   REAL(wp) ::   a_fwb     ! annual domain averaged freshwater budget from the previous year
+   REAL(wp) ::   a_fwb_b   ! annual domain averaged freshwater budget from the year before or at initial state
+   REAL(wp) ::   a_fwb_ini ! initial domain averaged freshwater budget
+   REAL(wp) ::   area      ! global mean ocean surface (interior domain)
+
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: sbcfwb.F90 15439 2021-10-22 17:53:09Z clem $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   SUBROUTINE sbc_fwb( kt, kn_fwb, kn_fsbc, Kmm )
+      !!---------------------------------------------------------------------
+      !!                  ***  ROUTINE sbc_fwb  ***
+      !!
+      !! ** Purpose :   Control the mean sea surface drift
+      !!
+      !! ** Method  :   several ways  depending on kn_fwb
+      !!                =0 no control 
+      !!                =1 global mean of emp set to zero at each nn_fsbc time step
+      !!                =2 annual global mean corrected from previous year
+      !!                =3 global mean of emp set to zero at each nn_fsbc time step
+      !!                   & spread out over erp area depending its sign
+      !! Note: if sea ice is embedded it is taken into account when computing the budget 
+      !!----------------------------------------------------------------------
+      INTEGER, INTENT( in ) ::   kt       ! ocean time-step index
+      INTEGER, INTENT( in ) ::   kn_fsbc  ! 
+      INTEGER, INTENT( in ) ::   kn_fwb   ! ocean time-step index
+      INTEGER, INTENT( in ) ::   Kmm      ! ocean time level index
+      !
+      INTEGER  ::   ios, inum, ikty       ! local integers
+      REAL(wp) ::   z_fwf, z_fwf_nsrf, zsum_fwf, zsum_erp                ! local scalars
+      REAL(wp) ::   zsurf_neg, zsurf_pos, zsurf_tospread, zcoef          !   -      -
+      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   ztmsk_neg, ztmsk_pos, z_wgt ! 2D workspaces
+      REAL(wp), ALLOCATABLE, DIMENSION(:,:) ::   ztmsk_tospread, zerp_cor    !   -      -
+      REAL(wp)   ,DIMENSION(1) ::   z_fwfprv  
+      COMPLEX(dp),DIMENSION(1) ::   y_fwfnow  
+      !
+      NAMELIST/namsbc_fwb/rn_fwb0
+      !!----------------------------------------------------------------------
+      !
+      IF( kt == nit000 ) THEN
+         READ( numnam_ref, namsbc_fwb, IOSTAT = ios, ERR = 901 )
+901      IF( ios /= 0 ) CALL ctl_nam( ios, 'namsbc_fwb in reference namelist'     )
+         READ( numnam_cfg, namsbc_fwb, IOSTAT = ios, ERR = 902 )
+902      IF( ios >  0 ) CALL ctl_nam( ios, 'namsbc_fwb in configuration namelist' )
+         IF(lwm) WRITE( numond, namsbc_fwb )
+         IF(lwp) THEN
+            WRITE(numout,*)
+            WRITE(numout,*) 'sbc_fwb : FreshWater Budget correction'
+            WRITE(numout,*) '~~~~~~~'
+            IF( kn_fwb == 1 )   WRITE(numout,*) '          instantaneously set to zero'
+            IF( kn_fwb == 3 )   WRITE(numout,*) '          fwf set to zero and spread out over erp area'
+            IF( kn_fwb == 2 ) THEN
+               WRITE(numout,*) '          adjusted from previous year budget'
+               WRITE(numout,*)
+               WRITE(numout,*) '   Namelist namsbc_fwb'
+               WRITE(numout,*) '      Initial freshwater adjustment flux [kg/m2/s] = ', rn_fwb0
+            END IF
+         ENDIF
+         !
+         IF( kn_fwb == 3 .AND. nn_sssr /= 2 )   CALL ctl_stop( 'sbc_fwb: nn_fwb = 3 requires nn_sssr = 2, we stop ' )
+         IF( kn_fwb == 3 .AND. ln_isfcav    )   CALL ctl_stop( 'sbc_fwb: nn_fwb = 3 with ln_isfcav = .TRUE. not working, we stop ' )
+         !
+         area = glob_sum( 'sbcfwb', e1e2t(:,:) * tmask(:,:,1))           ! interior global domain surface
+         ! isf cavities are excluded because it can feedback to the melting with generation of inhibition of plumes
+         ! and in case of no melt, it can generate HSSW.
+         !
+#if ! defined key_si3 && ! defined key_cice
+         snwice_mass_b(:,:) = 0.e0               ! no sea-ice model is being used : no snow+ice mass
+         snwice_mass  (:,:) = 0.e0
+         snwice_fmass (:,:) = 0.e0
+#endif
+         !
+      ENDIF
+
+      SELECT CASE ( kn_fwb )
+      !
+      CASE ( 1 )                             !==  global mean fwf set to zero  ==!
+         !
+         IF( MOD( kt-1, kn_fsbc ) == 0 ) THEN
+            y_fwfnow(1) = local_sum( e1e2t(:,:) * ( emp(:,:) - rnf(:,:) - fwfisf_cav(:,:) - fwfisf_par(:,:) - snwice_fmass(:,:) ) )
+            CALL mpp_delay_sum( 'sbcfwb', 'fwb', y_fwfnow(:), z_fwfprv(:), kt == nitend - nn_fsbc + 1 )
+            z_fwfprv(1) = z_fwfprv(1) / area
+            zcoef = z_fwfprv(1) * rcp
+            emp(:,:) = emp(:,:) - z_fwfprv(1)        * tmask(:,:,1)
+            qns(:,:) = qns(:,:) + zcoef * sst_m(:,:) * tmask(:,:,1) ! account for change to the heat budget due to fw correction
+            ! outputs
+            IF( iom_use('hflx_fwb_cea') )  CALL iom_put( 'hflx_fwb_cea', zcoef * sst_m(:,:) * tmask(:,:,1) )
+            IF( iom_use('vflx_fwb_cea') )  CALL iom_put( 'vflx_fwb_cea', z_fwfprv(1)        * tmask(:,:,1) )
+         ENDIF
+#if defined key_drakkar
+          CALL iom_put( "fwprv", z_fwfprv(1))
+#endif
+         !
+      CASE ( 2 )                             !==  fw adjustment based on fw budget at the end of the previous year  ==!
+         !                                                simulation is supposed to start 1st of January
+         IF( kt == nit000 ) THEN                                                                 ! initialisation
+            !                                                                                    ! set the fw adjustment (a_fwb)
+            IF ( ln_rstart .AND. iom_varid( numror, 'a_fwb_b', ldstop = .FALSE. ) > 0     &      !    as read from restart file
+               &           .AND. iom_varid( numror, 'a_fwb',   ldstop = .FALSE. ) > 0 ) THEN
+               IF(lwp)   WRITE(numout,*) 'sbc_fwb : reading freshwater-budget from restart file'
+               CALL iom_get( numror, 'a_fwb_b', a_fwb_b )
+               CALL iom_get( numror, 'a_fwb'  , a_fwb )
+               !
+               a_fwb_ini = a_fwb_b
+            ELSE                                                                                 !    as specified in namelist
+               IF(lwp)   WRITE(numout,*) 'sbc_fwb : setting freshwater-budget from namelist rn_fwb0'
+               a_fwb   = rn_fwb0
+               a_fwb_b = 0._wp   ! used only the first year then it is replaced by a_fwb_ini
+               !
+               a_fwb_ini = glob_sum( 'sbcfwb', e1e2t(:,:) * ( ssh(:,:,Kmm) + snwice_mass(:,:) * r1_rho0 ) ) &
+                  &      * rho0 / ( area * rday * REAL(nyear_len(1), wp) )
+            END IF
+            !
+            IF(lwp)   WRITE(numout,*)
+            IF(lwp)   WRITE(numout,*)'sbc_fwb : freshwater-budget at the end of previous year = ', a_fwb    , 'kg/m2/s'
+            IF(lwp)   WRITE(numout,*)'          freshwater-budget at initial state            = ', a_fwb_ini, 'kg/m2/s'
+            !
+         ELSE
+            ! at the end of year n:
+            ikty = nyear_len(1) * 86400 / NINT(rn_Dt)
+            IF( MOD( kt, ikty ) == 0 ) THEN   ! Update a_fwb at the last time step of a year
+               !                                It should be the first time step of a year MOD(kt-1,ikty) but then the restart would be wrong
+               !                                Hence, we make a small error here but the code is restartable
+               a_fwb_b = a_fwb_ini
+               ! mean sea level taking into account ice+snow
+               a_fwb   = glob_sum( 'sbcfwb', e1e2t(:,:) * ( ssh(:,:,Kmm) + snwice_mass(:,:) * r1_rho0 ) )
+               a_fwb   = a_fwb * rho0 / ( area * rday * REAL(nyear_len(1), wp) )   ! convert in kg/m2/s
+            ENDIF
+            !
+         ENDIF
+         !
+         IF( MOD( kt-1, kn_fsbc ) == 0 ) THEN         ! correct the freshwater fluxes using previous year budget minus initial state
+            zcoef = ( a_fwb - a_fwb_b )
+            emp(:,:) = emp(:,:) + zcoef * tmask(:,:,1)
+            qns(:,:) = qns(:,:) - zcoef * rcp * sst_m(:,:) * tmask(:,:,1) ! account for change to the heat budget due to fw correction
+            ! outputs
+            IF( iom_use('hflx_fwb_cea') )  CALL iom_put( 'hflx_fwb_cea', -zcoef * rcp * sst_m(:,:) * tmask(:,:,1) )
+            IF( iom_use('vflx_fwb_cea') )  CALL iom_put( 'vflx_fwb_cea', -zcoef * tmask(:,:,1) )
+         ENDIF
+         ! Output restart information
+         IF( lrst_oce ) THEN
+            IF(lwp) WRITE(numout,*)
+            IF(lwp) WRITE(numout,*) 'sbc_fwb : writing FW-budget adjustment to ocean restart file at it = ', kt
+            IF(lwp) WRITE(numout,*) '~~~~'
+            CALL iom_rstput( kt, nitrst, numrow, 'a_fwb_b', a_fwb_b )
+            CALL iom_rstput( kt, nitrst, numrow, 'a_fwb',   a_fwb   )
+         END IF
+         !
+         IF( kt == nitend .AND. lwp ) THEN
+            WRITE(numout,*) 'sbc_fwb : freshwater-budget at the end of simulation (year now) = ', a_fwb  , 'kg/m2/s'
+            WRITE(numout,*) '          freshwater-budget at initial state                    = ', a_fwb_b, 'kg/m2/s'
+         ENDIF
+         !
+      CASE ( 3 )                             !==  global fwf set to zero and spread out over erp area  ==!
+         !
+         ALLOCATE( ztmsk_neg(jpi,jpj) , ztmsk_pos(jpi,jpj) , ztmsk_tospread(jpi,jpj) , z_wgt(jpi,jpj) , zerp_cor(jpi,jpj) )
+         !
+         IF( MOD( kt-1, kn_fsbc ) == 0 ) THEN
+            ztmsk_pos(:,:) = tmask_i(:,:)                      ! Select <0 and >0 area of erp
+            WHERE( erp < 0._wp )   ztmsk_pos = 0._wp
+            ztmsk_neg(:,:) = tmask_i(:,:) - ztmsk_pos(:,:)
+            !                                                  ! fwf global mean (excluding ocean to ice/snow exchanges) 
+            z_fwf     = glob_sum( 'sbcfwb', e1e2t(:,:) * ( emp(:,:) - rnf(:,:) - fwfisf_cav(:,:) - fwfisf_par(:,:) - snwice_fmass(:,:) ) ) / area
+            !            
+            IF( z_fwf < 0._wp ) THEN         ! spread out over >0 erp area to increase evaporation
+               zsurf_pos = glob_sum( 'sbcfwb', e1e2t(:,:)*ztmsk_pos(:,:) )
+               zsurf_tospread      = zsurf_pos
+               ztmsk_tospread(:,:) = ztmsk_pos(:,:)
+            ELSE                             ! spread out over <0 erp area to increase precipitation
+               zsurf_neg = glob_sum( 'sbcfwb', e1e2t(:,:)*ztmsk_neg(:,:) )  ! Area filled by <0 and >0 erp 
+               zsurf_tospread      = zsurf_neg
+               ztmsk_tospread(:,:) = ztmsk_neg(:,:)
+            ENDIF
+            !
+            zsum_fwf   = glob_sum( 'sbcfwb', e1e2t(:,:) * z_fwf )         ! fwf global mean over <0 or >0 erp area
+!!gm :  zsum_fwf   = z_fwf * area   ???  it is right?  I think so....
+            z_fwf_nsrf =  zsum_fwf / ( zsurf_tospread + rsmall )
+            !                                                  ! weight to respect erp field 2D structure 
+            zsum_erp   = glob_sum( 'sbcfwb', ztmsk_tospread(:,:) * erp(:,:) * e1e2t(:,:) )
+            z_wgt(:,:) = ztmsk_tospread(:,:) * erp(:,:) / ( zsum_erp + rsmall )
+            !                                                  ! final correction term to apply
+            zerp_cor(:,:) = -1. * z_fwf_nsrf * zsurf_tospread * z_wgt(:,:)
+            !
+!!gm   ===>>>>  lbc_lnk should be useless as all the computation is done over the whole domain !
+            CALL lbc_lnk( 'sbcfwb', zerp_cor, 'T', 1.0_wp )
+            !
+            emp(:,:) = emp(:,:) + zerp_cor(:,:)
+            qns(:,:) = qns(:,:) - zerp_cor(:,:) * rcp * sst_m(:,:)  ! account for change to the heat budget due to fw correction
+            erp(:,:) = erp(:,:) + zerp_cor(:,:)
+            ! outputs
+            IF( iom_use('hflx_fwb_cea') )  CALL iom_put( 'hflx_fwb_cea', -zerp_cor(:,:) * rcp * sst_m(:,:) )
+            IF( iom_use('vflx_fwb_cea') )  CALL iom_put( 'vflx_fwb_cea', -zerp_cor(:,:) )
+            !
+            IF( lwp ) THEN                   ! control print
+               IF( z_fwf < 0._wp ) THEN
+                  WRITE(numout,*)'   z_fwf < 0'
+                  WRITE(numout,*)'   SUM(erp+)     = ', SUM( ztmsk_tospread(:,:)*erp(:,:)*e1e2t(:,:) )*1.e-9,' Sv'
+               ELSE
+                  WRITE(numout,*)'   z_fwf >= 0'
+                  WRITE(numout,*)'   SUM(erp-)     = ', SUM( ztmsk_tospread(:,:)*erp(:,:)*e1e2t(:,:) )*1.e-9,' Sv'
+               ENDIF
+               WRITE(numout,*)'   SUM(empG)     = ', SUM( z_fwf*e1e2t(:,:) )*1.e-9,' Sv'
+               WRITE(numout,*)'   z_fwf         = ', z_fwf      ,' Kg/m2/s'
+               WRITE(numout,*)'   z_fwf_nsrf    = ', z_fwf_nsrf ,' Kg/m2/s'
+               WRITE(numout,*)'   MIN(zerp_cor) = ', MINVAL(zerp_cor) 
+               WRITE(numout,*)'   MAX(zerp_cor) = ', MAXVAL(zerp_cor) 
+            ENDIF
+         ENDIF
+         DEALLOCATE( ztmsk_neg , ztmsk_pos , ztmsk_tospread , z_wgt , zerp_cor )
+         !
+      CASE DEFAULT                           !==  you should never be there  ==!
+         CALL ctl_stop( 'sbc_fwb : wrong nn_fwb value for the FreshWater Budget correction, choose either 1, 2 or 3' )
+         !
+      END SELECT
+      !
+   END SUBROUTINE sbc_fwb
+
+   !!======================================================================
+END MODULE sbcfwb

+ 590 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/sbcrnf.F90

@@ -0,0 +1,590 @@
+MODULE sbcrnf
+   !!======================================================================
+   !!                       ***  MODULE  sbcrnf  ***
+   !! Ocean forcing:  river runoff
+   !!=====================================================================
+   !! History :  OPA  ! 2000-11  (R. Hordoir, E. Durand)  NetCDF FORMAT
+   !!   NEMO     1.0  ! 2002-09  (G. Madec)  F90: Free form and module
+   !!            3.0  ! 2006-07  (G. Madec)  Surface module
+   !!            3.2  ! 2009-04  (B. Lemaire)  Introduce iom_put
+   !!            3.3  ! 2010-10  (R. Furner, G. Madec) runoff distributed over ocean levels
+   !!----------------------------------------------------------------------
+
+   !!----------------------------------------------------------------------
+   !!   sbc_rnf       : monthly runoffs read in a NetCDF file
+   !!   sbc_rnf_init  : runoffs initialisation
+   !!   rnf_mouth     : set river mouth mask
+   !!----------------------------------------------------------------------
+   USE dom_oce        ! ocean space and time domain
+   USE phycst         ! physical constants
+   USE sbc_oce        ! surface boundary condition variables
+   USE eosbn2         ! Equation Of State
+   USE closea, ONLY: l_clo_rnf, clo_rnf ! closed seas
+   !
+   USE in_out_manager ! I/O manager
+   USE fldread        ! read input field at current time step
+   USE iom            ! I/O module
+   USE lib_mpp        ! MPP library
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   sbc_rnf       ! called in sbcmod module
+   PUBLIC   sbc_rnf_div   ! called in divhor module
+   PUBLIC   sbc_rnf_alloc ! called in sbcmod module
+   PUBLIC   sbc_rnf_init  ! called in sbcmod module
+
+   !                                                !!* namsbc_rnf namelist *
+   CHARACTER(len=100)         ::   cn_dir            !: Root directory for location of rnf files
+   LOGICAL           , PUBLIC ::   ln_rnf_depth      !: depth       river runoffs attribute specified in a file
+   LOGICAL                    ::      ln_rnf_depth_ini  !: depth       river runoffs  computed at the initialisation
+   REAL(wp)                   ::      rn_rnf_max        !: maximum value of the runoff climatologie (ln_rnf_depth_ini =T)
+   REAL(wp)                   ::      rn_dep_max        !: depth over which runoffs is spread       (ln_rnf_depth_ini =T)
+   INTEGER                    ::      nn_rnf_depth_file !: create (=1) a runoff depth file or not (=0)
+   LOGICAL           , PUBLIC ::   ln_rnf_icb        !: iceberg flux is specified in a file
+   LOGICAL                    ::   ln_rnf_tem        !: temperature river runoffs attribute specified in a file
+   LOGICAL           , PUBLIC ::   ln_rnf_sal        !: salinity    river runoffs attribute specified in a file
+   TYPE(FLD_N)       , PUBLIC ::   sn_rnf            !: information about the runoff file to be read
+   TYPE(FLD_N)                ::   sn_cnf            !: information about the runoff mouth file to be read
+   TYPE(FLD_N)                ::   sn_i_rnf        !: information about the iceberg flux file to be read
+   TYPE(FLD_N)                ::   sn_s_rnf          !: information about the salinities of runoff file to be read
+   TYPE(FLD_N)                ::   sn_t_rnf          !: information about the temperatures of runoff file to be read
+   TYPE(FLD_N)                ::   sn_dep_rnf        !: information about the depth which river inflow affects
+   LOGICAL           , PUBLIC ::   ln_rnf_mouth      !: specific treatment in mouths vicinity
+   REAL(wp)                   ::   rn_hrnf           !: runoffs, depth over which enhanced vertical mixing is used
+   REAL(wp)          , PUBLIC ::   rn_avt_rnf        !: runoffs, value of the additional vertical mixing coef. [m2/s]
+   REAL(wp)          , PUBLIC ::   rn_rfact          !: multiplicative factor for runoff
+
+   LOGICAL , PUBLIC ::   l_rnfcpl = .false.   !: runoffs recieved from oasis
+   INTEGER , PUBLIC ::   nkrnf = 0            !: nb of levels over which Kz is increased at river mouths
+
+   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   rnfmsk              !: river mouth mask (hori.)
+   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:)     ::   rnfmsk_z            !: river mouth mask (vert.)
+   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   h_rnf               !: depth of runoff in m
+   INTEGER,  PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:)   ::   nk_rnf              !: depth of runoff in model levels
+   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) ::   rnf_tsc_b, rnf_tsc  !: before and now T & S runoff contents   [K.m/s & PSU.m/s]
+
+   TYPE(FLD),        ALLOCATABLE, DIMENSION(:) ::   sf_rnf       ! structure: river runoff (file information, fields read)
+   TYPE(FLD),        ALLOCATABLE, DIMENSION(:) ::   sf_i_rnf     ! structure: iceberg flux (file information, fields read)
+   TYPE(FLD),        ALLOCATABLE, DIMENSION(:) ::   sf_s_rnf     ! structure: river runoff salinity (file information, fields read)
+   TYPE(FLD),        ALLOCATABLE, DIMENSION(:) ::   sf_t_rnf     ! structure: river runoff temperature (file information, fields read)
+#if defined key_drakkar
+   INTEGER                    :: nn_rnf_freq     !: number of runoff data set
+   TYPE(FLD_N), DIMENSION(5)  :: sn_rnf2         !: information about the extra runoff file to be read
+   TYPE(FLD_N), DIMENSION(6)  :: slf_rnf         !: information about all the runoff in namelist
+#endif
+
+   !! * Substitutions
+#  include "do_loop_substitute.h90"
+#  include "domzgr_substitute.h90"
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: sbcrnf.F90 15190 2021-08-13 12:52:50Z gsamson $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   INTEGER FUNCTION sbc_rnf_alloc()
+      !!----------------------------------------------------------------------
+      !!                ***  ROUTINE sbc_rnf_alloc  ***
+      !!----------------------------------------------------------------------
+      ALLOCATE( rnfmsk(jpi,jpj)         , rnfmsk_z(jpk)          ,     &
+         &      h_rnf (jpi,jpj)         , nk_rnf  (jpi,jpj)      ,     &
+         &      rnf_tsc_b(jpi,jpj,jpts) , rnf_tsc (jpi,jpj,jpts) , STAT=sbc_rnf_alloc )
+         !
+      CALL mpp_sum ( 'sbcrnf', sbc_rnf_alloc )
+      IF( sbc_rnf_alloc > 0 )   CALL ctl_warn('sbc_rnf_alloc: allocation of arrays failed')
+   END FUNCTION sbc_rnf_alloc
+
+
+   SUBROUTINE sbc_rnf( kt )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE sbc_rnf  ***
+      !!
+      !! ** Purpose :   Introduce a climatological run off forcing
+      !!
+      !! ** Method  :   Set each river mouth with a monthly climatology
+      !!                provided from different data.
+      !!                CAUTION : upward water flux, runoff forced to be < 0
+      !!
+      !! ** Action  :   runoff updated runoff field at time-step kt
+      !!----------------------------------------------------------------------
+      INTEGER, INTENT(in) ::   kt          ! ocean time step
+      !
+      INTEGER  ::   ji, jj    ! dummy loop indices
+      INTEGER  ::   z_err = 0 ! dummy integer for error handling
+      !!----------------------------------------------------------------------
+      REAL(wp), DIMENSION(jpi,jpj) ::   ztfrz   ! freezing point used for temperature correction
+      !
+      !
+      !                                            !-------------------!
+      !                                            !   Update runoff   !
+      !                                            !-------------------!
+      !
+      !
+      IF( .NOT. l_rnfcpl )  THEN
+                            CALL fld_read ( kt, nn_fsbc, sf_rnf   )    ! Read Runoffs data and provide it at kt ( runoffs + iceberg )
+         IF( ln_rnf_icb )   CALL fld_read ( kt, nn_fsbc, sf_i_rnf )    ! idem for iceberg flux if required
+      ENDIF
+      IF(   ln_rnf_tem   )   CALL fld_read ( kt, nn_fsbc, sf_t_rnf )    ! idem for runoffs temperature if required
+      IF(   ln_rnf_sal   )   CALL fld_read ( kt, nn_fsbc, sf_s_rnf )    ! idem for runoffs salinity    if required
+      !
+      IF( MOD( kt - 1, nn_fsbc ) == 0 ) THEN
+         !
+         IF( .NOT. l_rnfcpl ) THEN
+#if defined key_drakkar
+             rnf(:,:) = 0._wp
+             DO ji = 1, nn_rnf_freq
+               rnf(:,:) = rnf(:,:) + sf_rnf(ji)%fnow(:,:,1)    !
+             ENDDO
+             rnf(:,:) = rn_rfact * rnf(:,:) * tmask(:,:,1)  ! updated runoff value at time step kt
+#else
+             rnf(:,:) = rn_rfact * ( sf_rnf(1)%fnow(:,:,1) ) * tmask(:,:,1)  ! updated runoff value at time step kt
+#endif
+             IF( ln_rnf_icb ) THEN
+                fwficb(:,:) = rn_rfact * ( sf_i_rnf(1)%fnow(:,:,1) ) * tmask(:,:,1)  ! updated runoff value at time step kt
+                rnf(:,:) = rnf(:,:) + fwficb(:,:)
+                qns(:,:) = qns(:,:) - fwficb(:,:) * rLfus
+                !!qns_tot(:,:) = qns_tot(:,:) - fwficb(:,:) * rLfus                
+                !!qns_oce(:,:) = qns_oce(:,:) - fwficb(:,:) * rLfus                
+                CALL iom_put( 'iceberg_cea'  ,  fwficb(:,:)  )          ! output iceberg flux
+                CALL iom_put( 'hflx_icb_cea' , -fwficb(:,:) * rLfus )   ! output Heat Flux into Sea Water due to Iceberg Thermodynamics -->
+             ENDIF
+         ENDIF
+         !
+         !                                                           ! set temperature & salinity content of runoffs
+         IF( ln_rnf_tem ) THEN                                       ! use runoffs temperature data
+            rnf_tsc(:,:,jp_tem) = ( sf_t_rnf(1)%fnow(:,:,1) ) * rnf(:,:) * r1_rho0
+            CALL eos_fzp( sss_m(:,:), ztfrz(:,:) )
+            WHERE( sf_t_rnf(1)%fnow(:,:,1) == -999._wp )             ! if missing data value use SST as runoffs temperature
+               rnf_tsc(:,:,jp_tem) = sst_m(:,:) * rnf(:,:) * r1_rho0
+            END WHERE
+         ELSE                                                        ! use SST as runoffs temperature
+            !CEOD River is fresh water so must at least be 0 unless we consider ice
+            rnf_tsc(:,:,jp_tem) = MAX( sst_m(:,:), 0.0_wp ) * rnf(:,:) * r1_rho0
+         ENDIF
+         !                                                           ! use runoffs salinity data
+         IF( ln_rnf_sal )   rnf_tsc(:,:,jp_sal) = ( sf_s_rnf(1)%fnow(:,:,1) ) * rnf(:,:) * r1_rho0
+         !                                                           ! else use S=0 for runoffs (done one for all in the init)
+                                         CALL iom_put( 'runoffs'     , rnf(:,:)                         )   ! output runoff mass flux
+         IF( iom_use('hflx_rnf_cea') )   CALL iom_put( 'hflx_rnf_cea', rnf_tsc(:,:,jp_tem) * rho0 * rcp )   ! output runoff sensible heat (W/m2)
+         IF( iom_use('sflx_rnf_cea') )   CALL iom_put( 'sflx_rnf_cea', rnf_tsc(:,:,jp_sal) * rho0       )   ! output runoff salt flux (g/m2/s)
+      ENDIF
+      !
+      !                                                ! ---------------------------------------- !
+      IF( kt == nit000 ) THEN                          !   set the forcing field at nit000 - 1    !
+         !                                             ! ---------------------------------------- !
+         IF( ln_rstart .AND. .NOT.l_1st_euler ) THEN         !* Restart: read in restart file
+            IF(lwp) WRITE(numout,*) '          nit000-1 runoff forcing fields red in the restart file', lrxios
+            CALL iom_get( numror, jpdom_auto, 'rnf_b'   , rnf_b                 )   ! before runoff
+            CALL iom_get( numror, jpdom_auto, 'rnf_hc_b', rnf_tsc_b(:,:,jp_tem) )   ! before heat content of runoff
+            CALL iom_get( numror, jpdom_auto, 'rnf_sc_b', rnf_tsc_b(:,:,jp_sal) )   ! before salinity content of runoff
+         ELSE                                                !* no restart: set from nit000 values
+            IF(lwp) WRITE(numout,*) '          nit000-1 runoff forcing fields set to nit000'
+            rnf_b    (:,:  ) = rnf    (:,:  )
+            rnf_tsc_b(:,:,:) = rnf_tsc(:,:,:)
+         ENDIF
+      ENDIF
+      !                                                ! ---------------------------------------- !
+      IF( lrst_oce ) THEN                              !      Write in the ocean restart file     !
+         !                                             ! ---------------------------------------- !
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) 'sbcrnf : runoff forcing fields written in ocean restart file ',   &
+            &                    'at it= ', kt,' date= ', ndastp
+         IF(lwp) WRITE(numout,*) '~~~~'
+         CALL iom_rstput( kt, nitrst, numrow, 'rnf_b'   , rnf                 )
+         CALL iom_rstput( kt, nitrst, numrow, 'rnf_hc_b', rnf_tsc(:,:,jp_tem) )
+         CALL iom_rstput( kt, nitrst, numrow, 'rnf_sc_b', rnf_tsc(:,:,jp_sal) )
+      ENDIF
+      !
+   END SUBROUTINE sbc_rnf
+
+
+   SUBROUTINE sbc_rnf_div( phdivn, Kmm )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE sbc_rnf  ***
+      !!
+      !! ** Purpose :   update the horizontal divergence with the runoff inflow
+      !!
+      !! ** Method  :
+      !!                CAUTION : rnf is positive (inflow) decreasing the
+      !!                          divergence and expressed in m/s
+      !!
+      !! ** Action  :   phdivn   decreased by the runoff inflow
+      !!----------------------------------------------------------------------
+      INTEGER                   , INTENT(in   ) ::   Kmm      ! ocean time level index
+      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   phdivn   ! horizontal divergence
+      !!
+      INTEGER  ::   ji, jj, jk   ! dummy loop indices
+      REAL(wp) ::   zfact     ! local scalar
+      !!----------------------------------------------------------------------
+      !
+      zfact = 0.5_wp
+      !
+      IF( ln_rnf_depth .OR. ln_rnf_depth_ini ) THEN      !==   runoff distributed over several levels   ==!
+         IF( ln_linssh ) THEN    !* constant volume case : just apply the runoff input flow
+            DO_2D_OVR( nn_hls-1, nn_hls, nn_hls-1, nn_hls )
+               DO jk = 1, nk_rnf(ji,jj)
+                  phdivn(ji,jj,jk) = phdivn(ji,jj,jk) - ( rnf(ji,jj) + rnf_b(ji,jj) ) * zfact * r1_rho0 / h_rnf(ji,jj)
+               END DO
+            END_2D
+         ELSE                    !* variable volume case
+            DO_2D_OVR( nn_hls, nn_hls, nn_hls, nn_hls )         ! update the depth over which runoffs are distributed
+               h_rnf(ji,jj) = 0._wp
+               DO jk = 1, nk_rnf(ji,jj)                             ! recalculates h_rnf to be the depth in metres
+                  h_rnf(ji,jj) = h_rnf(ji,jj) + e3t(ji,jj,jk,Kmm)   ! to the bottom of the relevant grid box
+               END DO
+            END_2D
+            DO_2D_OVR( nn_hls-1, nn_hls, nn_hls-1, nn_hls )         ! apply the runoff input flow
+               DO jk = 1, nk_rnf(ji,jj)
+                  phdivn(ji,jj,jk) = phdivn(ji,jj,jk) - ( rnf(ji,jj) + rnf_b(ji,jj) ) * zfact * r1_rho0 / h_rnf(ji,jj)
+               END DO
+            END_2D
+         ENDIF
+      ELSE                       !==   runoff put only at the surface   ==!
+         DO_2D_OVR( nn_hls, nn_hls, nn_hls, nn_hls )
+            h_rnf (ji,jj)   = e3t(ji,jj,1,Kmm)        ! update h_rnf to be depth of top box
+         END_2D
+         DO_2D_OVR( nn_hls-1, nn_hls, nn_hls-1, nn_hls )
+            phdivn(ji,jj,1) = phdivn(ji,jj,1) - ( rnf(ji,jj) + rnf_b(ji,jj) ) * zfact * r1_rho0 / e3t(ji,jj,1,Kmm)
+         END_2D
+      ENDIF
+      !
+   END SUBROUTINE sbc_rnf_div
+
+
+   SUBROUTINE sbc_rnf_init( Kmm )
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE sbc_rnf_init  ***
+      !!
+      !! ** Purpose :   Initialisation of the runoffs if (ln_rnf=T)
+      !!
+      !! ** Method  : - read the runoff namsbc_rnf namelist
+      !!
+      !! ** Action  : - read parameters
+      !!----------------------------------------------------------------------
+      INTEGER, INTENT(in) :: Kmm           ! ocean time level index
+      CHARACTER(len=32) ::   rn_dep_file   ! runoff file name
+      INTEGER           ::   ji, jj, jk, jm    ! dummy loop indices
+      INTEGER           ::   ierror, inum  ! temporary integer
+      INTEGER           ::   ios           ! Local integer output status for namelist read
+      INTEGER           ::   nbrec         ! temporary integer
+      REAL(wp)          ::   zacoef
+      REAL(wp), DIMENSION(jpi,jpj,2) :: zrnfcl
+      !!
+      NAMELIST/namsbc_rnf/ cn_dir            , ln_rnf_depth, ln_rnf_tem, ln_rnf_sal, ln_rnf_icb,   &
+         &                 sn_rnf, sn_cnf    , sn_i_rnf, sn_s_rnf    , sn_t_rnf  , sn_dep_rnf,   &
+         &                 ln_rnf_mouth      , rn_hrnf     , rn_avt_rnf, rn_rfact,     &
+         &                 ln_rnf_depth_ini  , rn_dep_max  , rn_rnf_max, nn_rnf_depth_file
+#if defined key_drakkar
+      INTEGER           :: ierror2
+      NAMELIST/namsbc_rnf_drk/ nn_rnf_freq, sn_rnf2
+#endif
+      !!----------------------------------------------------------------------
+      !
+      !                                         !==  allocate runoff arrays
+      IF( sbc_rnf_alloc() /= 0 )   CALL ctl_stop( 'STOP', 'sbc_rnf_alloc : unable to allocate arrays' )
+      !
+      IF( .NOT. ln_rnf ) THEN                      ! no specific treatment in vicinity of river mouths
+         ln_rnf_mouth  = .FALSE.                   ! default definition needed for example by sbc_ssr or by tra_adv_muscl
+         nkrnf         = 0
+         rnf     (:,:) = 0.0_wp
+         rnf_b   (:,:) = 0.0_wp
+         rnfmsk  (:,:) = 0.0_wp
+         rnfmsk_z(:)   = 0.0_wp
+         RETURN
+      ENDIF
+      !
+      !                                   ! ============
+      !                                   !   Namelist
+      !                                   ! ============
+      !
+      READ  ( numnam_ref, namsbc_rnf, IOSTAT = ios, ERR = 901)
+901   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namsbc_rnf in reference namelist' )
+
+      READ  ( numnam_cfg, namsbc_rnf, IOSTAT = ios, ERR = 902 )
+902   IF( ios >  0 )   CALL ctl_nam ( ios , 'namsbc_rnf in configuration namelist' )
+      IF(lwm) WRITE ( numond, namsbc_rnf )
+#if defined key_drakkar
+      READ  ( numnam_ref, namsbc_rnf_drk, IOSTAT = ios, ERR = 903)
+903   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namsbc_rnf_drk in reference namelist' )
+
+      READ  ( numnam_cfg, namsbc_rnf_drk, IOSTAT = ios, ERR = 904 )
+904   IF( ios >  0 )   CALL ctl_nam ( ios , 'namsbc_rnf_drk in configuration namelist' )
+      IF(lwm) WRITE ( numond, namsbc_rnf_drk )
+#endif
+      !
+      !                                         ! Control print
+      IF(lwp) THEN
+         WRITE(numout,*)
+         WRITE(numout,*) 'sbc_rnf_init : runoff '
+         WRITE(numout,*) '~~~~~~~~~~~~ '
+         WRITE(numout,*) '   Namelist namsbc_rnf'
+         WRITE(numout,*) '      specific river mouths treatment            ln_rnf_mouth = ', ln_rnf_mouth
+         WRITE(numout,*) '      river mouth additional Kz                  rn_avt_rnf   = ', rn_avt_rnf
+         WRITE(numout,*) '      depth of river mouth additional mixing     rn_hrnf      = ', rn_hrnf
+         WRITE(numout,*) '      multiplicative factor for runoff           rn_rfact     = ', rn_rfact
+      ENDIF
+      !                                   ! ==================
+      !                                   !   Type of runoff
+      !                                   ! ==================
+      !
+      IF( .NOT. l_rnfcpl ) THEN
+#if defined key_drakkar
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   runoffs inflow read in ',nn_rnf_freq,' file(s)'
+         ALLOCATE( sf_rnf(nn_rnf_freq), STAT=ierror )         ! Create sf_rnf structure (runoff inflow)
+         DO ji = 1, nn_rnf_freq
+            ALLOCATE ( sf_rnf(ji)%fnow(jpi,jpj,1)  , STAT=ierror2) ; ierror = ierror + ierror2
+            ALLOCATE ( sf_rnf(ji)%fdta(jpi,jpj,1,2), STAT=ierror2) ; ierror = ierror + ierror2
+         ENDDO
+         IF( ierror > 0 ) THEN
+            CALL ctl_stop( 'sbc_rnf_init: unable to allocate sf_rnf structure' )   ;   RETURN
+         ENDIF
+         slf_rnf(1)  = sn_rnf
+         DO ji = 2, nn_rnf_freq 
+            slf_rnf(ji) = sn_rnf2(ji-1)
+         ENDDO
+         CALL fld_fill( sf_rnf, slf_rnf(1:nn_rnf_freq), cn_dir, 'sbc_rnf_init', 'read runoffs data', 'namsbc_rnf', no_print )
+#else
+         ALLOCATE( sf_rnf(1), STAT=ierror )         ! Create sf_rnf structure (runoff inflow)
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   runoffs inflow read in a file'
+         IF( ierror > 0 ) THEN
+            CALL ctl_stop( 'sbc_rnf_init: unable to allocate sf_rnf structure' )   ;   RETURN
+         ENDIF
+         ALLOCATE( sf_rnf(1)%fnow(jpi,jpj,1)   )
+         IF( sn_rnf%ln_tint ) ALLOCATE( sf_rnf(1)%fdta(jpi,jpj,1,2) )
+         CALL fld_fill( sf_rnf, (/ sn_rnf /), cn_dir, 'sbc_rnf_init', 'read runoffs data', 'namsbc_rnf', no_print )
+#endif
+         !
+         IF( ln_rnf_icb ) THEN                      ! Create (if required) sf_i_rnf structure
+            IF(lwp) WRITE(numout,*)
+            IF(lwp) WRITE(numout,*) '          iceberg flux read in a file'
+            ALLOCATE( sf_i_rnf(1), STAT=ierror  )
+            IF( ierror > 0 ) THEN
+               CALL ctl_stop( 'sbc_rnf_init: unable to allocate sf_i_rnf structure' )   ;   RETURN
+            ENDIF
+            ALLOCATE( sf_i_rnf(1)%fnow(jpi,jpj,1)   )
+            IF( sn_i_rnf%ln_tint ) ALLOCATE( sf_i_rnf(1)%fdta(jpi,jpj,1,2) )
+            CALL fld_fill (sf_i_rnf, (/ sn_i_rnf /), cn_dir, 'sbc_rnf_init', 'read iceberg flux data', 'namsbc_rnf' )
+         ELSE
+            fwficb(:,:) = 0._wp
+         ENDIF
+
+      ENDIF
+      !
+      IF( ln_rnf_tem ) THEN                      ! Create (if required) sf_t_rnf structure
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   runoffs temperatures read in a file'
+         ALLOCATE( sf_t_rnf(1), STAT=ierror  )
+         IF( ierror > 0 ) THEN
+            CALL ctl_stop( 'sbc_rnf_init: unable to allocate sf_t_rnf structure' )   ;   RETURN
+         ENDIF
+         ALLOCATE( sf_t_rnf(1)%fnow(jpi,jpj,1)   )
+         IF( sn_t_rnf%ln_tint ) ALLOCATE( sf_t_rnf(1)%fdta(jpi,jpj,1,2) )
+         CALL fld_fill (sf_t_rnf, (/ sn_t_rnf /), cn_dir, 'sbc_rnf_init', 'read runoff temperature data', 'namsbc_rnf', no_print )
+      ENDIF
+      !
+      IF( ln_rnf_sal  ) THEN                     ! Create (if required) sf_s_rnf and sf_t_rnf structures
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   runoffs salinities read in a file'
+         ALLOCATE( sf_s_rnf(1), STAT=ierror  )
+         IF( ierror > 0 ) THEN
+            CALL ctl_stop( 'sbc_rnf_init: unable to allocate sf_s_rnf structure' )   ;   RETURN
+         ENDIF
+         ALLOCATE( sf_s_rnf(1)%fnow(jpi,jpj,1)   )
+         IF( sn_s_rnf%ln_tint ) ALLOCATE( sf_s_rnf(1)%fdta(jpi,jpj,1,2) )
+         CALL fld_fill (sf_s_rnf, (/ sn_s_rnf /), cn_dir, 'sbc_rnf_init', 'read runoff salinity data', 'namsbc_rnf', no_print )
+      ENDIF
+      !
+      IF( ln_rnf_depth ) THEN                    ! depth of runoffs set from a file
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   runoffs depth read in a file'
+         rn_dep_file = TRIM( cn_dir )//TRIM( sn_dep_rnf%clname )
+         IF( .NOT. sn_dep_rnf%ln_clim ) THEN   ;   WRITE(rn_dep_file, '(a,"_y",i4)' ) TRIM( rn_dep_file ), nyear    ! add year
+            IF( sn_dep_rnf%clftyp == 'monthly' )   WRITE(rn_dep_file, '(a,"m",i2)'  ) TRIM( rn_dep_file ), nmonth   ! add month
+         ENDIF
+         CALL iom_open ( rn_dep_file, inum )                                                 ! open file
+         CALL iom_get  ( inum, jpdom_global, sn_dep_rnf%clvar, h_rnf, kfill = jpfillcopy )   ! read the river mouth. no 0 on halos!
+         CALL iom_close( inum )                                                              ! close file
+         !
+         nk_rnf(:,:) = 0                               ! set the number of level over which river runoffs are applied
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+            IF( h_rnf(ji,jj) > 0._wp ) THEN
+               jk = 2
+               DO WHILE ( jk < mbkt(ji,jj) .AND. gdept_0(ji,jj,jk) < h_rnf(ji,jj) ) ;  jk = jk + 1
+               END DO
+               nk_rnf(ji,jj) = jk
+            ELSEIF( h_rnf(ji,jj) == -1._wp   ) THEN   ;  nk_rnf(ji,jj) = 1
+            ELSEIF( h_rnf(ji,jj) == -999._wp ) THEN   ;  nk_rnf(ji,jj) = mbkt(ji,jj)
+            ELSE
+               CALL ctl_stop( 'sbc_rnf_init: runoff depth not positive, and not -999 or -1, rnf value in file fort.999'  )
+               WRITE(999,*) 'ji, jj, h_rnf(ji,jj) :', ji, jj, h_rnf(ji,jj)
+            ENDIF
+         END_2D
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )                           ! set the associated depth
+            h_rnf(ji,jj) = 0._wp
+            DO jk = 1, nk_rnf(ji,jj)
+               h_rnf(ji,jj) = h_rnf(ji,jj) + e3t(ji,jj,jk,Kmm)
+            END DO
+         END_2D
+         !
+      ELSE IF( ln_rnf_depth_ini ) THEN           ! runoffs applied at the surface
+         !
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   depth of runoff computed once from max value of runoff'
+         IF(lwp) WRITE(numout,*) '        max value of the runoff climatologie (over global domain) rn_rnf_max = ', rn_rnf_max
+         IF(lwp) WRITE(numout,*) '        depth over which runoffs is spread                        rn_dep_max = ', rn_dep_max
+         IF(lwp) WRITE(numout,*) '        create (=1) a runoff depth file or not (=0)      nn_rnf_depth_file  = ', nn_rnf_depth_file
+
+         CALL iom_open( TRIM( sn_rnf%clname ), inum )    !  open runoff file
+         nbrec = iom_getszuld( inum )
+         zrnfcl(:,:,1) = 0._wp                                                            ! init the max to 0. in 1
+         DO jm = 1, nbrec
+            CALL iom_get( inum, jpdom_global, TRIM( sn_rnf%clvar ), zrnfcl(:,:,2), jm )   ! read the value in 2
+            zrnfcl(:,:,1) = MAXVAL( zrnfcl(:,:,:), DIM=3 )                                ! store the maximum value in time in 1
+         END DO
+         CALL iom_close( inum )
+         !
+         h_rnf(:,:) = 1.
+         !
+         zacoef = rn_dep_max / rn_rnf_max            ! coef of linear relation between runoff and its depth (150m for max of runoff)
+         !
+         WHERE( zrnfcl(:,:,1) > 0._wp )  h_rnf(:,:) = zacoef * zrnfcl(:,:,1)   ! compute depth for all runoffs
+         !
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )                ! take in account min depth of ocean rn_hmin
+            IF( zrnfcl(ji,jj,1) > 0._wp ) THEN
+               jk = mbkt(ji,jj)
+               h_rnf(ji,jj) = MIN( h_rnf(ji,jj), gdept_0(ji,jj,jk ) )
+            ENDIF
+         END_2D
+         !
+         nk_rnf(:,:) = 0                       ! number of levels on which runoffs are distributed
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+            IF( zrnfcl(ji,jj,1) > 0._wp ) THEN
+               jk = 2
+               DO WHILE ( jk < mbkt(ji,jj) .AND. gdept_0(ji,jj,jk) < h_rnf(ji,jj) ) ;  jk = jk + 1
+               END DO
+               nk_rnf(ji,jj) = jk
+            ELSE
+               nk_rnf(ji,jj) = 1
+            ENDIF
+         END_2D
+         !
+         DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )                          ! set the associated depth
+            h_rnf(ji,jj) = 0._wp
+            DO jk = 1, nk_rnf(ji,jj)
+               h_rnf(ji,jj) = h_rnf(ji,jj) + e3t(ji,jj,jk,Kmm)
+            END DO
+         END_2D
+         !
+         IF( nn_rnf_depth_file == 1 ) THEN      !  save  output nb levels for runoff
+            IF(lwp) WRITE(numout,*) '   ==>>>   create runoff depht file'
+            CALL iom_open  ( TRIM( sn_dep_rnf%clname ), inum, ldwrt = .TRUE. )
+            CALL iom_rstput( 0, 0, inum, 'rodepth', h_rnf )
+            CALL iom_close ( inum )
+         ENDIF
+      ELSE                                       ! runoffs applied at the surface
+         nk_rnf(:,:) = 1
+         h_rnf (:,:) = e3t(:,:,1,Kmm)
+      ENDIF
+      !
+      rnf(:,:) =  0._wp                         ! runoff initialisation
+      rnf_tsc(:,:,:) = 0._wp                    ! runoffs temperature & salinty contents initilisation
+      !
+      !                                   ! ========================
+      !                                   !   River mouth vicinity
+      !                                   ! ========================
+      !
+      IF( ln_rnf_mouth ) THEN                   ! Specific treatment in vicinity of river mouths :
+         !                                      !    - Increase Kz in surface layers ( rn_hrnf > 0 )
+         !                                      !    - set to zero SSS damping (ln_ssr=T)
+         !                                      !    - mixed upstream-centered (ln_traadv_cen2=T)
+         !
+         IF( ln_rnf_depth )   CALL ctl_warn( 'sbc_rnf_init: increased mixing turned on but effects may already',   &
+            &                                              'be spread through depth by ln_rnf_depth'               )
+         !
+         nkrnf = 0                                  ! Number of level over which Kz increase
+         IF( rn_hrnf > 0._wp ) THEN
+            nkrnf = 2
+            DO WHILE( nkrnf /= jpkm1 .AND. gdepw_1d(nkrnf+1) < rn_hrnf )   ;   nkrnf = nkrnf + 1
+            END DO
+            IF( ln_sco )   CALL ctl_warn( 'sbc_rnf_init: number of levels over which Kz is increased is computed for zco...' )
+         ENDIF
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   Specific treatment used in vicinity of river mouths :'
+         IF(lwp) WRITE(numout,*) '             - Increase Kz in surface layers (if rn_hrnf > 0 )'
+         IF(lwp) WRITE(numout,*) '               by ', rn_avt_rnf,' m2/s  over ', nkrnf, ' w-levels'
+         IF(lwp) WRITE(numout,*) '             - set to zero SSS damping       (if ln_ssr=T)'
+         IF(lwp) WRITE(numout,*) '             - mixed upstream-centered       (if ln_traadv_cen2=T)'
+         !
+         CALL rnf_mouth                             ! set river mouth mask
+         !
+      ELSE                                      ! No treatment at river mouths
+         IF(lwp) WRITE(numout,*)
+         IF(lwp) WRITE(numout,*) '   ==>>>   No specific treatment at river mouths'
+         rnfmsk  (:,:) = 0._wp
+#if defined key_drakkar
+         ! rnf_msk is read from socoefr even if ln_rnf_mouth = F 
+         !   because it is used in SSS restoring
+         CALL rnf_mouth                             ! set river mouth mask
+#endif
+         rnfmsk_z(:)   = 0._wp
+         nkrnf = 0
+      ENDIF
+      !
+   END SUBROUTINE sbc_rnf_init
+
+
+   SUBROUTINE rnf_mouth
+      !!----------------------------------------------------------------------
+      !!                  ***  ROUTINE rnf_mouth  ***
+      !!
+      !! ** Purpose :   define the river mouths mask
+      !!
+      !! ** Method  :   read the river mouth mask (=0/1) in the river runoff
+      !!                climatological file. Defined a given vertical structure.
+      !!                CAUTION, the vertical structure is hard coded on the
+      !!                first 5 levels.
+      !!                This fields can be used to:
+      !!                 - set an upstream advection scheme
+      !!                   (ln_rnf_mouth=T and ln_traadv_cen2=T)
+      !!                 - increase vertical on the top nn_krnf vertical levels
+      !!                   at river runoff input grid point (nn_krnf>=2, see step.F90)
+      !!                 - set to zero SSS restoring flux at river mouth grid points
+      !!
+      !! ** Action  :   rnfmsk   set to 1 at river runoff input, 0 elsewhere
+      !!                rnfmsk_z vertical structure
+      !!----------------------------------------------------------------------
+      INTEGER            ::   inum        ! temporary integers
+      CHARACTER(len=140) ::   cl_rnfile   ! runoff file name
+      !!----------------------------------------------------------------------
+      !
+      IF(lwp) WRITE(numout,*)
+      IF(lwp) WRITE(numout,*) '   rnf_mouth : river mouth mask'
+      IF(lwp) WRITE(numout,*) '   ~~~~~~~~~ '
+      !
+      cl_rnfile = TRIM( cn_dir )//TRIM( sn_cnf%clname )
+      IF( .NOT. sn_cnf%ln_clim ) THEN   ;   WRITE(cl_rnfile, '(a,"_y",i4.4)' ) TRIM( cl_rnfile ), nyear    ! add year
+         IF( sn_cnf%clftyp == 'monthly' )   WRITE(cl_rnfile, '(a,"m" ,i2.2)' ) TRIM( cl_rnfile ), nmonth   ! add month
+      ENDIF
+      !
+      ! horizontal mask (read in NetCDF file)
+      CALL iom_open ( cl_rnfile, inum )                             ! open file
+      CALL iom_get  ( inum, jpdom_global, sn_cnf%clvar, rnfmsk )    ! read the river mouth array
+      CALL iom_close( inum )                                        ! close file
+      !
+      IF( l_clo_rnf )   CALL clo_rnf( rnfmsk )   ! closed sea inflow set as river mouth
+      !
+      rnfmsk_z(:)   = 0._wp                                       ! vertical structure
+      rnfmsk_z(1)   = 1.0
+      rnfmsk_z(2)   = 1.0                                         ! **********
+      rnfmsk_z(3)   = 0.5                                         ! HARD CODED on the 5 first levels
+      rnfmsk_z(4)   = 0.25                                        ! **********
+      rnfmsk_z(5)   = 0.125
+      !
+   END SUBROUTINE rnf_mouth
+
+   !!======================================================================
+END MODULE sbcrnf

+ 421 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/sbcssr.F90

@@ -0,0 +1,421 @@
+MODULE sbcssr
+   !!======================================================================
+   !!                       ***  MODULE  sbcssr  ***
+   !! Surface module :  heat and fresh water fluxes a restoring term toward observed SST/SSS
+   !!======================================================================
+   !! History :  3.0  !  2006-06  (G. Madec)  Original code
+   !!            3.2  !  2009-04  (B. Lemaire)  Introduce iom_put
+   !!----------------------------------------------------------------------
+
+   !!----------------------------------------------------------------------
+   !!   sbc_ssr       : add to sbc a restoring term toward SST/SSS climatology
+   !!   sbc_ssr_init  : initialisation of surface restoring
+   !!----------------------------------------------------------------------
+   USE oce            ! ocean dynamics and tracers
+   USE dom_oce        ! ocean space and time domain
+   USE sbc_oce        ! surface boundary condition
+   USE phycst         ! physical constants
+   USE sbcrnf         ! surface boundary condition : runoffs
+   !
+   USE fldread        ! read input fields
+   USE in_out_manager ! I/O manager
+   USE iom            ! I/O manager
+   USE lib_mpp        ! distribued memory computing library
+   USE lbclnk         ! ocean lateral boundary conditions (or mpp link)
+   USE lib_fortran    ! Fortran utilities (allows no signed zero when 'key_nosignedzero' defined)  
+#if defined key_drakkar
+   USE shapiro
+#endif
+
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC   sbc_ssr        ! routine called in sbcmod
+   PUBLIC   sbc_ssr_init   ! routine called in sbcmod
+   PUBLIC   sbc_ssr_alloc  ! routine called in sbcmod
+
+   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) ::   erp   !: evaporation damping   [kg/m2/s]
+   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) ::   qrp   !: heat flux damping        [w/m2]
+   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) ::   coefice   !: under ice relaxation coefficient
+
+   !                                   !!* Namelist namsbc_ssr *
+   INTEGER, PUBLIC ::   nn_sstr         ! SST/SSS restoring indicator
+   INTEGER, PUBLIC ::   nn_sssr         ! SST/SSS restoring indicator
+   REAL(wp)        ::   rn_dqdt         ! restoring factor on SST and SSS
+   REAL(wp)        ::   rn_deds         ! restoring factor on SST and SSS
+   LOGICAL         ::   ln_sssr_bnd     ! flag to bound erp term 
+   REAL(wp)        ::   rn_sssr_bnd     ! ABS(Max./Min.) value of erp term [mm/day]
+   INTEGER         ::   nn_sssr_ice     ! Control of restoring under ice
+#if defined key_drakkar
+   ! local modification of ssr
+   REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) ::   erpcoef !:  multiplicating coef for local change to erp
+   ! filtering of model fields
+   LOGICAL, PUBLIC ::   ln_sssr_flt     ! flag to filter sss for restoring
+   INTEGER, PUBLIC ::   nn_shap_iter    ! number of iteration for shapiro
+   ! Limit SSS restoring in coastal areas
+   LOGICAL         :: ln_sssr_msk
+   TYPE(FLD_N)     :: sn_coast
+   REAL(wp), PUBLIC, ALLOCATABLE, DIMENSION(:,:) :: distcoast   ! use to read the distance and then for weight purpose
+   REAL(wp)        :: rn_dist      ! (km) decaying lenght scale for SSS restoring near the coast
+   TYPE(FLD), ALLOCATABLE, DIMENSION(:) ::   sf_empc  ! structure of input SSS (file informations, fields read)
+#endif
+
+   REAL(wp) , ALLOCATABLE, DIMENSION(:) ::   buffer   ! Temporary buffer for exchange
+   TYPE(FLD), ALLOCATABLE, DIMENSION(:) ::   sf_sst   ! structure of input SST (file informations, fields read)
+   TYPE(FLD), ALLOCATABLE, DIMENSION(:) ::   sf_sss   ! structure of input SSS (file informations, fields read)
+
+   !! * Substitutions
+#  include "do_loop_substitute.h90"
+   !!----------------------------------------------------------------------
+   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
+   !! $Id: sbcssr.F90 14834 2021-05-11 09:24:44Z hadcv $
+   !! Software governed by the CeCILL license (see ./LICENSE)
+   !!----------------------------------------------------------------------
+CONTAINS
+
+   SUBROUTINE sbc_ssr( kt )
+      !!---------------------------------------------------------------------
+      !!                     ***  ROUTINE sbc_ssr  ***
+      !!
+      !! ** Purpose :   Add to heat and/or freshwater fluxes a damping term
+      !!                toward observed SST and/or SSS.
+      !!
+      !! ** Method  : - Read namelist namsbc_ssr
+      !!              - Read observed SST and/or SSS
+      !!              - at each nscb time step
+      !!                   add a retroaction term on qns    (nn_sstr = 1)
+      !!                   add a damping term on sfx        (nn_sssr = 1)
+      !!                   add a damping term on emp        (nn_sssr = 2)
+      !!---------------------------------------------------------------------
+      INTEGER, INTENT(in   ) ::   kt   ! ocean time step
+      !!
+      INTEGER  ::   ji, jj   ! dummy loop indices
+      REAL(wp) ::   zerp     ! local scalar for evaporation damping
+      REAL(wp) ::   zqrp     ! local scalar for heat flux damping
+      REAL(wp) ::   zsrp     ! local scalar for unit conversion of rn_deds factor
+      REAL(wp) ::   zerp_bnd ! local scalar for unit conversion of rn_epr_max factor
+      INTEGER  ::   ierror   ! return error code
+#if defined key_drakkar
+      REAL(wp) , DIMENSION (jpi,jpj) :: zsss_m ! temporary array
+      REAL(wp) , DIMENSION (jpi,jpj) :: zsst_m ! temporary array
+      TYPE(FLD_N) ::   sn_empc                 ! informations about the fields to be read
+#endif
+      !!
+      CHARACTER(len=100) ::  cn_dir          ! Root directory for location of ssr files
+      TYPE(FLD_N) ::   sn_sst, sn_sss        ! informations about the fields to be read
+      !!----------------------------------------------------------------------
+      !
+      IF( nn_sstr + nn_sssr /= 0 ) THEN
+         !
+         IF( nn_sstr == 1)   CALL fld_read( kt, nn_fsbc, sf_sst )   ! Read SST data and provides it at kt
+#if defined key_drakkar
+         IF( nn_sssr <= 2)   CALL fld_read( kt, nn_fsbc, sf_sss )   ! Read SSS data and provides it at kt
+#else
+         IF( nn_sssr >= 1)   CALL fld_read( kt, nn_fsbc, sf_sss )   ! Read SSS data and provides it at kt
+#endif
+         !
+         !                                         ! ========================= !
+         IF( MOD( kt-1, nn_fsbc ) == 0 ) THEN      !    Add restoring term     !
+            !                                      ! ========================= !
+            !
+            qrp(:,:) = 0._wp ! necessary init
+            erp(:,:) = 0._wp
+            !
+            IF( nn_sstr == 1 ) THEN                                   !* Temperature restoring term
+               DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+                  zqrp = rn_dqdt * ( sst_m(ji,jj) - sf_sst(1)%fnow(ji,jj,1) ) * tmask(ji,jj,1)
+                  qns(ji,jj) = qns(ji,jj) + zqrp
+                  qrp(ji,jj) = zqrp
+               END_2D
+            ENDIF
+            !
+#if defined key_drakkar
+            IF( nn_sssr /= 0 .AND. nn_sssr /= 3 .AND. nn_sssr_ice /= 1 ) THEN
+#else
+            IF( nn_sssr /= 0 .AND. nn_sssr_ice /= 1 ) THEN
+#endif
+              ! use fraction of ice ( fr_i ) to adjust relaxation under ice if nn_sssr_ice .ne. 1
+              ! n.b. coefice is initialised and fixed to 1._wp if nn_sssr_ice = 1
+               DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+                  SELECT CASE ( nn_sssr_ice )
+                    CASE ( 0 )    ;  coefice(ji,jj) = 1._wp - fr_i(ji,jj)              ! no/reduced damping under ice
+                    CASE  DEFAULT ;  coefice(ji,jj) = 1._wp + ( nn_sssr_ice - 1 ) * fr_i(ji,jj) ! reinforced damping (x nn_sssr_ice) under ice )
+                  END SELECT
+               END_2D
+            ENDIF
+            !
+            IF( nn_sssr == 1 ) THEN                                   !* Salinity damping term (salt flux only (sfx))
+               zsrp = rn_deds / rday                                  ! from [mm/day] to [kg/m2/s]
+               DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+                  zerp = zsrp * ( 1. - 2.*rnfmsk(ji,jj) )   &      ! No damping in vicinity of river mouths
+                     &        *   coefice(ji,jj)            &      ! Optional control of damping under sea-ice
+#if defined key_drakkar
+                     &        * ( sss_m(ji,jj) - sf_sss(1)%fnow(ji,jj,1) ) * tmask(ji,jj,1) * erpcoef(ji,jj)
+#else
+                     &        * ( sss_m(ji,jj) - sf_sss(1)%fnow(ji,jj,1) ) * tmask(ji,jj,1)
+#endif
+                  sfx(ji,jj) = sfx(ji,jj) + zerp                 ! salt flux
+                  erp(ji,jj) = zerp / MAX( sss_m(ji,jj), 1.e-20 ) ! converted into an equivalent volume flux (diagnostic only)
+               END_2D
+               !
+            ELSEIF( nn_sssr == 2 ) THEN                               !* Salinity damping term (volume flux (emp) and associated heat flux (qns)
+               zsrp = rn_deds / rday                                  ! from [mm/day] to [kg/m2/s]
+               zerp_bnd = rn_sssr_bnd / rday                          !       -              -    
+#if defined key_drakkar
+               !  fliter model field 
+               IF (ln_sssr_flt ) THEN
+                  CALL Shapiro_1D ( sss_m(:,:), nn_shap_iter, 'ORCA_GLOB', zsss_m )
+                  CALL Shapiro_1D ( sst_m(:,:), nn_shap_iter, 'ORCA_GLOB', zsst_m )
+                  zsss_m = zsss_m * tmask(:,:,1)
+                  zsst_m = zsst_m * tmask(:,:,1)
+               ELSE
+                  zsss_m = sss_m * tmask(:,:,1)
+                  zsst_m = sst_m * tmask(:,:,1)
+               ENDIF
+
+               DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+                   ! use filters model fields and multiply zerp by erpcoef
+                     zerp = zsrp * ( 1. - 2.*rnfmsk(ji,jj) )   &      ! No damping in vicinity of river mouths
+                        &        *   coefice(ji,jj)            &      ! Optional control of damping under sea-ice
+                        &        * ( zsss_m(ji,jj) - sf_sss(1)%fnow(ji,jj,1) )   &
+                        &        / MAX(  zsss_m(ji,jj), 1.e-20   ) * tmask(ji,jj,1)              &
+                        &        * erpcoef(ji,jj)
+                     IF( ln_sssr_bnd )   zerp = SIGN( 1., zerp ) * MIN( zerp_bnd, ABS(zerp) )
+                   ! use distance to the coast
+                     IF( ln_sssr_msk )   zerp = zerp * distcoast(ji,jj) ! multiply by weigh to fade zerp out near the coast
+                  qns(ji,jj) = qns(ji,jj) - zerp * rcp * sst_m(ji,jj)
+                  erp(ji,jj) = zerp
+                  qrp(ji,jj) = qrp(ji,jj) - zerp * rcp * sst_m(ji,jj)
+               END_2D
+#else
+               DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+                  zerp = zsrp * ( 1. - 2.*rnfmsk(ji,jj) )   &      ! No damping in vicinity of river mouths
+                     &        *   coefice(ji,jj)            &      ! Optional control of damping under sea-ice
+                     &        * ( sss_m(ji,jj) - sf_sss(1)%fnow(ji,jj,1) )   &
+                     &        / MAX(  sss_m(ji,jj), 1.e-20   ) * tmask(ji,jj,1)
+                  IF( ln_sssr_bnd )   zerp = SIGN( 1.0_wp, zerp ) * MIN( zerp_bnd, ABS(zerp) )
+                  emp(ji,jj) = emp (ji,jj) + zerp
+                  qns(ji,jj) = qns(ji,jj) - zerp * rcp * sst_m(ji,jj)
+                  erp(ji,jj) = zerp
+                  qrp(ji,jj) = qrp(ji,jj) - zerp * rcp * sst_m(ji,jj)
+               END_2D
+#endif
+#if defined key_drakkar
+            ELSEIF ( nn_sssr == 3) THEN
+            CALL fld_read( kt, nn_fsbc, sf_empc )   ! Read SST data and provides it at kt
+            DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
+               erp(ji,jj) = sf_empc(1)%fnow(ji,jj,1)
+               emp(ji,jj) = emp(ji,jj) + erp(ji,jj)
+               qns(ji,jj) = qns(ji,jj) - erp(ji,jj) * rcp * sst_m(ji,jj)
+               qrp(ji,jj) = qrp(ji,jj) - erp(ji,jj) * rcp * sst_m(ji,jj)
+            END_2D
+#endif
+            ENDIF
+            ! outputs
+            CALL iom_put( 'hflx_ssr_cea', qrp(:,:) )
+            IF( nn_sssr == 1 )   CALL iom_put( 'sflx_ssr_cea',  erp(:,:) * sss_m(:,:) )
+            IF( nn_sssr == 2 )   CALL iom_put( 'vflx_ssr_cea', -erp(:,:) )
+            !
+         ENDIF
+         !
+      ENDIF
+      !
+   END SUBROUTINE sbc_ssr
+
+ 
+   SUBROUTINE sbc_ssr_init
+      !!---------------------------------------------------------------------
+      !!                  ***  ROUTINE sbc_ssr_init  ***
+      !!
+      !! ** Purpose :   initialisation of surface damping term
+      !!
+      !! ** Method  : - Read namelist namsbc_ssr
+      !!              - Read observed SST and/or SSS if required
+      !!---------------------------------------------------------------------
+      INTEGER  ::   ji, jj   ! dummy loop indices
+      REAL(wp) ::   zerp     ! local scalar for evaporation damping
+      REAL(wp) ::   zqrp     ! local scalar for heat flux damping
+      REAL(wp) ::   zsrp     ! local scalar for unit conversion of rn_deds factor
+      REAL(wp) ::   zerp_bnd ! local scalar for unit conversion of rn_epr_max factor
+      INTEGER  ::   ierror   ! return error code
+#if defined key_drakkar
+      INTEGER  ::   ii0, ii1, ii2, ij0, ij1, ij2, inum
+      REAL(wp) :: zalph
+      CHARACTER(LEN=100) ::  cl_coastfile
+      TYPE(FLD_N) ::   sn_empc
+      NAMELIST/namsbc_ssr_drk/ ln_sssr_flt, ln_sssr_msk, sn_coast, rn_dist, nn_shap_iter, sn_empc
+#endif
+      !!
+      CHARACTER(len=100) ::  cn_dir          ! Root directory for location of ssr files
+      TYPE(FLD_N) ::   sn_sst, sn_sss        ! informations about the fields to be read
+      NAMELIST/namsbc_ssr/ cn_dir, nn_sstr, nn_sssr, rn_dqdt, rn_deds, sn_sst, &
+              & sn_sss, ln_sssr_bnd, rn_sssr_bnd, nn_sssr_ice
+      INTEGER     ::  ios
+      !!----------------------------------------------------------------------
+      !
+      IF(lwp) THEN
+         WRITE(numout,*)
+         WRITE(numout,*) 'sbc_ssr : SST and/or SSS damping term '
+         WRITE(numout,*) '~~~~~~~ '
+      ENDIF
+      ! 
+      READ  ( numnam_ref, namsbc_ssr, IOSTAT = ios, ERR = 901)
+901   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namsbc_ssr in reference namelist' )
+
+      READ  ( numnam_cfg, namsbc_ssr, IOSTAT = ios, ERR = 902 )
+902   IF( ios >  0 )   CALL ctl_nam ( ios , 'namsbc_ssr in configuration namelist' )
+      IF(lwm) WRITE ( numond, namsbc_ssr )
+
+#if defined key_drakkar
+      READ  ( numnam_ref, namsbc_ssr_drk, IOSTAT = ios, ERR = 903)
+903   IF( ios /= 0 )   CALL ctl_nam ( ios , 'namsbc_ssr_drk in reference namelist' )
+
+      READ  ( numnam_cfg, namsbc_ssr_drk, IOSTAT = ios, ERR = 904 )
+904   IF( ios >  0 )   CALL ctl_nam ( ios , 'namsbc_ssr_drk in configuration namelist' )
+      IF(lwm) WRITE ( numond, namsbc_ssr )
+#endif
+
+      IF(lwp) THEN                 !* control print
+         WRITE(numout,*) '   Namelist namsbc_ssr :'
+         WRITE(numout,*) '      SST restoring term (Yes=1)             nn_sstr        = ', nn_sstr
+         WRITE(numout,*) '         dQ/dT (restoring magnitude on SST)     rn_dqdt     = ', rn_dqdt, ' W/m2/K'
+         WRITE(numout,*) '      SSS damping term (Yes=1, salt   flux)  nn_sssr        = ', nn_sssr
+         WRITE(numout,*) '                       (Yes=2, volume flux) '
+#if defined key_drakkar
+         WRITE(numout,*) '                       (Yes=3, from input file and as volume flux) '
+#endif
+         WRITE(numout,*) '         dE/dS (restoring magnitude on SST)     rn_deds     = ', rn_deds, ' mm/day'
+         WRITE(numout,*) '         flag to bound erp term                 ln_sssr_bnd = ', ln_sssr_bnd
+         WRITE(numout,*) '         ABS(Max./Min.) erp threshold           rn_sssr_bnd = ', rn_sssr_bnd, ' mm/day'
+         WRITE(numout,*) '      Cntrl of surface restoration under ice nn_sssr_ice    = ', nn_sssr_ice
+         WRITE(numout,*) '          ( 0 = no restoration under ice)'
+         WRITE(numout,*) '          ( 1 = restoration everywhere  )'
+         WRITE(numout,*) '          (>1 = enhanced restoration under ice  )'
+#if defined key_drakkar
+         IF ( nn_sssr == 3 ) THEN
+            WRITE(numout,*)
+            WRITE(numout,*) '      Read sssr term from a forcing (prescribed emp correction).'
+            WRITE(numout,*)
+         ELSE
+            WRITE(numout,*) '      Filtering of sss for restoring         ln_sssr_flt = ', ln_sssr_flt 
+            IF ( ln_sssr_flt ) THEN
+               WRITE(numout,*) '      Number of used Shapiro filter           nn_shap_iter = ', nn_shap_iter
+            ENDIF
+            WRITE(numout,*) '      Limit sss restoring near the coast     ln_sssr_msk = ', ln_sssr_msk
+            IF ( ln_sssr_msk ) WRITE(numout,*) '      Decaying lenght scale from the coast   rn_dist     = ', rn_dist, ' km'
+         END IF
+#endif
+      ENDIF
+      !
+      IF( nn_sstr == 1 ) THEN      !* set sf_sst structure & allocate arrays
+         !
+         ALLOCATE( sf_sst(1), STAT=ierror )
+         IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate sf_sst structure' )
+         ALLOCATE( sf_sst(1)%fnow(jpi,jpj,1), STAT=ierror )
+         IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate sf_sst now array' )
+         !
+         ! fill sf_sst with sn_sst and control print
+         CALL fld_fill( sf_sst, (/ sn_sst /), cn_dir, 'sbc_ssr', 'SST restoring term toward SST data', 'namsbc_ssr', no_print )
+         IF( sf_sst(1)%ln_tint )   ALLOCATE( sf_sst(1)%fdta(jpi,jpj,1,2), STAT=ierror )
+         IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate sf_sst data array' )
+         !
+      ENDIF
+      !
+#if defined key_drakkar
+      IF( nn_sssr >= 1 .AND. nn_sssr < 3) THEN
+#else
+      IF( nn_sssr >= 1 ) THEN      !* set sf_sss structure & allocate arrays
+#endif
+         !
+         ALLOCATE( sf_sss(1), STAT=ierror )
+         IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate sf_sss structure' )
+         ALLOCATE( sf_sss(1)%fnow(jpi,jpj,1), STAT=ierror )
+         IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate sf_sss now array' )
+         !
+         ! fill sf_sss with sn_sss and control print
+         CALL fld_fill( sf_sss, (/ sn_sss /), cn_dir, 'sbc_ssr', 'SSS restoring term toward SSS data', 'namsbc_ssr', no_print )
+         IF( sf_sss(1)%ln_tint )   ALLOCATE( sf_sss(1)%fdta(jpi,jpj,1,2), STAT=ierror )
+         IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate sf_sss data array' )
+         !
+#if defined key_drakkar
+         ! if masking of coastal area is used
+         IF ( ln_sssr_msk ) THEN
+            ALLOCATE( distcoast(jpi,jpj),STAT=ierror )  
+            IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate erp and qrp array' )
+            WRITE(cl_coastfile,'(a,a)' ) TRIM( cn_dir ), TRIM( sn_coast%clname )
+            CALL iom_open ( cl_coastfile, inum )                          ! open file
+            CALL iom_get  ( inum, jpdom_global, sn_coast%clvar, distcoast,  kfill=jpfillcopy ) ! read tcoast  in m
+            CALL iom_close( inum )
+            ! transform distcoast to weight 
+            rn_dist=rn_dist*1000.  ! tranform rn_dist to m
+            distcoast(:,:)=0.5*(tanh(3.*(distcoast(:,:)*distcoast(:,:)/rn_dist/rn_dist - 1 )) + 1 )
+         ENDIF
+      ALLOCATE( erpcoef(jpi,jpj),STAT=ierror )
+      IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate erpcoef' )
+      ! DRAKKAR { initialize erpcoef to increase erp in the med sea
+      erpcoef(:,:) = 1._wp
+!!! JMM : see how do to it nicely either in a an external file of is a usr_ routine
+! to keep the spirit of NEMO 4 
+!     IF( cp_cfg == "orca" .AND. jp_cfg == 25 ) THEN  ! ORCA R025 configuration
+!        !! add extra SSS restoring in the Red Sea
+!        ii0= 1280       ;  ii1 = 1325
+!        ij0= 560        ;  ij1 = 625
+!        erpcoef( mi0(ii0):mi1(ii1) , mj0(ij0):mj1(ij1)) =  5.0
+
+         !! add extra SSS restoring in the Med sea (x3) decreasing to 1 into the alboran sea
+!        ii1 = 1145  ; ii2 =  1330
+!        ij1 = 626   ; ij2 =  726
+!        erpcoef( mi0(ii1):mi1(ii2) , mj0(ij1):mj1(ij2)) = 3.0
+
+         !! decrease in alboran sea (along i )
+!        ii0= 1128       ;  ii1 = 1144
+!        ij0= 645        ;  ij1 = 670
+!        DO jj=mj0(ij0), mj1(ij1)
+!           DO ji= mi0(ii0), mi1(ii1)
+!              !zalph=( alph1 -alph0 )* (I - ii0 )/(ii1-ii0) + alph0
+               !zalph=( 3.    - 1.   )* (I - ii0 )/(ii1-ii0) + 1.
+!              zalph=     2.   *    (mig(ji)-ii0)/(ii1-ii0) + 1.
+!              erpcoef(ji,jj) = zalph 
+!           ENDDO
+!        ENDDO
+!     ENDIF
+      ELSEIF ( nn_sssr == 3 ) THEN
+         ALLOCATE( sf_empc(1), STAT=ierror )
+         IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate sf_empc structure' )
+         ALLOCATE( sf_empc(1)%fnow(jpi,jpj,1), STAT=ierror )
+         IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate sf_empc now array' )
+         !
+         ! fill sf_empc with sn_empc and control print
+         CALL fld_fill( sf_empc, (/ sn_empc /), cn_dir, 'sbc_ssr', 'SSS restoring term toward SSS data', 'namsbc_ssr', no_print )
+         IF( sf_empc(1)%ln_tint )   ALLOCATE( sf_empc(1)%fdta(jpi,jpj,1,2), STAT=ierror )
+         IF( ierror > 0 )   CALL ctl_stop( 'STOP', 'sbc_ssr: unable to allocate sf_empc data array' )
+#endif
+      ENDIF
+      !
+      coefice(:,:) = 1._wp         !  Initialise coefice to 1._wp ; will not need to be changed if nn_sssr_ice=1
+      !                            !* Initialize qrp and erp if no restoring 
+      IF( nn_sstr /= 1                   )   qrp(:,:) = 0._wp
+#if defined key_drakkar
+      IF( nn_sssr > 0 ) erp(:,:) = 0._wp
+#else
+      IF( nn_sssr /= 1 .OR. nn_sssr /= 2 )   erp(:,:) = 0._wp
+#endif
+      !
+   END SUBROUTINE sbc_ssr_init
+         
+   INTEGER FUNCTION sbc_ssr_alloc()
+      !!----------------------------------------------------------------------
+      !!               ***  FUNCTION sbc_ssr_alloc  ***
+      !!----------------------------------------------------------------------
+      sbc_ssr_alloc = 0       ! set to zero if no array to be allocated
+      IF( .NOT. ALLOCATED( erp ) ) THEN
+         ALLOCATE( qrp(jpi,jpj), erp(jpi,jpj), coefice(jpi,jpj), STAT= sbc_ssr_alloc )
+         !
+         IF( lk_mpp                  )   CALL mpp_sum ( 'sbcssr', sbc_ssr_alloc )
+         IF( sbc_ssr_alloc /= 0 )   CALL ctl_warn('sbc_ssr_alloc: failed to allocate arrays.')
+         !
+      ENDIF
+   END FUNCTION
+      
+   !!======================================================================
+END MODULE sbcssr

+ 113 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/MY_SRC/shapiro.F90

@@ -0,0 +1,113 @@
+MODULE shapiro 
+   !!==============================================================================
+   !!                       ***  MODULE shapiro   ***
+   !! spatial filtering of input field
+   !!==============================================================================
+   !! History :       !  09-08  (S. Cailleau ) from N. Ferry
+                      !  09-09  (C. Regnier  ) corrections
+                      !  04-10  (J.M. Molines) module and nemo standard
+   !!----------------------------------------------------------------------
+   !! * Modules used
+   USE in_out_manager
+   USE dom_oce         ! ocean space and time domain
+   USE timing          ! Timing
+   USE lbclnk
+
+   
+   IMPLICIT NONE
+   PRIVATE
+
+   PUBLIC Shapiro_1D  ! use by sbcblk_core  and sbcssr
+
+  CONTAINS
+
+  SUBROUTINE Shapiro_1D(ptabin, kiter, cd_overlap, ptabout) !GIG
+      !!----------------------------------------------------------------------
+      !!                  ***  routine Shapiro_1D  ***
+      !!
+      !! ** Purpose :  Multiple application (kiter) of a shapiro filter
+      !!               on ptabin to produce ptabout.
+      !!
+      !! ** Method  :   
+      !!
+      !! ** Action  :   ptabout filtered output from ptabin
+      !!
+      !!----------------------------------------------------------------------
+      INTEGER,                  INTENT(IN)  :: kiter      ! number of iterations to perform
+      REAL(wp), DIMENSION(:,:), INTENT(IN)  :: ptabin     ! input array
+      CHARACTER(len=*),         INTENT(IN)  :: cd_overlap ! = one of MERCA_GLOB, REGULAR_GLOB, ORCA_GLOB (??)
+      REAL(wp), DIMENSION(:,:), INTENT(OUT) :: ptabout    ! output array
+
+      ! * Local variable
+      INTEGER                               :: ji, jj, jn ! dummy loop index
+      INTEGER                               :: jpim1, jpjm1  ! for compatibility ...
+      REAL(wp), DIMENSION(:,:), ALLOCATABLE :: zvarout    ! working array
+      REAL(wp), PARAMETER                   :: rp_aniso_diff_XY=2.25 !  anisotrope case (???)
+                                                          ! Empirical value for 140 iterations
+                                                          ! for an anisotropic ratio of 1.5.
+                                                          ! (re ???)
+      REAL(wp)                              :: zalphax    ! weight coeficient (x direction)
+      REAL(wp)                              :: zalphay    ! weight coeficient (y direction)
+      REAL(wp)                              :: znum       ! numerator
+      REAL(wp)                              :: zden       ! denominator
+!
+!------------------------------------------------------------------------------
+!
+      IF( ln_timing )  CALL timing_start('Shapiro')
+      ! 
+      ALLOCATE(zvarout(jpi,jpj) )
+
+!     Global ocean case
+      IF (( cd_overlap == 'MERCA_GLOB' )   .OR.   &
+          ( cd_overlap == 'REGULAR_GLOB' ) .OR.   &
+          ( cd_overlap == 'ORCA_GLOB' )) THEN
+       ptabout(:,:) = ptabin(:,:)
+       zvarout(:,:) = ptabout(:,:)  ! ptabout intent out ???
+
+       zalphax=1./2.
+       zalphay=1./2.
+
+!  Dx/Dy=rp_aniso_diff_XY  , D_ = vitesse de diffusion
+!  140 passes du fitre, Lx/Ly=1.5, le rp_aniso_diff_XY correspondant est:
+
+       IF ( rp_aniso_diff_XY >=  1. ) zalphay=zalphay/rp_aniso_diff_XY
+       IF ( rp_aniso_diff_XY <   1. ) zalphax=zalphax*rp_aniso_diff_XY
+
+       jpim1=jpi - 1
+       jpjm1=jpj - 1
+
+        DO jn = 1,kiter
+            DO jj = 2,jpjm1
+               DO ji = 2,jpim1
+                  ! We crop on the coast
+                   znum = zvarout(ji,jj)   &
+                          + 0.25*zalphax*(zvarout(ji-1,jj  )-zvarout(ji,jj))*tmask(ji-1,jj  ,1)  &
+                          + 0.25*zalphax*(zvarout(ji+1,jj  )-zvarout(ji,jj))*tmask(ji+1,jj  ,1)  &
+                          + 0.25*zalphay*(zvarout(ji  ,jj-1)-zvarout(ji,jj))*tmask(ji  ,jj-1,1)  &
+                          + 0.25*zalphay*(zvarout(ji  ,jj+1)-zvarout(ji,jj))*tmask(ji  ,jj+1,1)
+                   ptabout(ji,jj)=znum*tmask(ji,jj,1)+ptabin(ji,jj)*(1.-tmask(ji,jj,1))
+                ENDDO  ! end loop jj
+            ENDDO  ! end loop ji
+!
+!
+!           Periodical condition in case of cd_overlap (global ocean)
+!           - on a mercator projection grid we consider that singular point at poles
+!             are a mean of the values at points of the previous latitude
+!           - on ORCA and regular grid we copy the values at points of the previous latitude
+            IF ( cd_overlap == 'MERCAT_GLOB' ) THEN
+!GIG case unchecked  ! JMM for sure not valid in MPP (BUG)
+               ptabout(1,1) = SUM(ptabout(:,2)) / jpi
+               ptabout(jpi,jpj) = SUM(ptabout(:,jpj-1)) / jpi
+            ELSE
+               CALL lbc_lnk('shapiro',ptabout, 'T', 1.) ! Boundary condition
+            ENDIF
+            zvarout(:,:) = ptabout(:,:)
+         ENDDO  ! end loop jn
+      ENDIF
+
+      DEALLOCATE(zvarout)
+      IF( ln_timing )  CALL timing_stop('Shapiro')
+!
+END SUBROUTINE Shapiro_1D     
+
+END MODULE shapiro

+ 1 - 0
eORCA025/eORCA025.L121-LUCIA01/cfgs/ORCA025_ICE/cpp_ORCA025_ICE.fcm

@@ -0,0 +1 @@
+bld::tool::fppkeys key_si3 key_xios key_netcdf4 key_isf key_drakkar key_nosignedzero