ecconf.cfg 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #!/bin/bash
  2. # Platform dependent configuration functions for the 'zenobe' machine
  3. #(zenobe.hpc.cenaero.be)
  4. function configure()
  5. {
  6. # This function should configure all settings/modules needed to
  7. # later prepare the EC-Earth run directory and set variables used
  8. # in the run script
  9. # SCRATCH is not defined in MN3, define it here
  10. # and also make sure it is defined when compiling
  11. export SCRATCH=/gpfs/scratch/acad/ecearth/${USER}
  12. # Configure paths for building/running EC-Earth
  13. ecearth_src_dir=${HOME}/models/ecearth_3.3.3.2/sources
  14. run_dir=/gpfs/scratch/acad/ecearth/${USER}/ecearth/run/${exp_name}
  15. ini_data_dir=/gpfs/scratch/acad/ecearth/data/bsc32/v3.3.3.2/inidata
  16. archive_dir=/gpfs/scratch/acad/ecearth/${USER}/ecearth/archive/${exp_name}
  17. # File for standard output.
  18. # NOTE: This will be modified for restart jobs!
  19. stdout_file=${SLURM_SUBMIT_DIR-$PWD}/${SLURM_JOB_NAME-"local"}_${SLURM_JOB_ID-"id"}.log
  20. # Resubmit this job for automatic restarts? [true/false]
  21. # Also, add options for the resubmit command here.
  22. resubmit_job=true
  23. resubmit_opt=""
  24. module load craype-x86-milan
  25. module load PrgEnv-intel/8.3.3
  26. MODULEPATH=$MODULEPATH:/gpfs/projects/acad/ecearth/softs/easybuild/modules/all
  27. module load netCDF-Fortran/4.6.0-iompi-2022.05
  28. module load imkl/2022.1.0 OpenJPEG/2.5.0-GCCcore-11.3.0 grib_api/1.24.0-iompi-2022.05
  29. # Configure grib api paths
  30. export GRIB_DEFINITION_PATH=${HOME}/models/ecearth_3.3.3.2/sources/util/grib_table_126:${EBROOTGRIB_API}/share/grib_api/definitions
  31. export GRIB_SAMPLES_PATH=${EBROOTGRIB_API}/share/grib_api/ifs_samples/grib1
  32. export GRIB_BIN_PATH=${EBROOTGRIB_API}/bin
  33. # Configure number of processors per node
  34. proc_per_node=128
  35. # Use machinefiles or not
  36. [[ `echo "$use_machinefile" | tr '[:upper:]' '[:lower:]'` == true ]] && use_machinefile=true || use_machinefile=false
  37. ulimit -s unlimited
  38. # Load specific MPI environment configuration
  39. configure_mpi
  40. }
  41. function configure_python()
  42. {
  43. # specific for python+eccodes setup - used for OSM pre/post-processing
  44. # it would be simple to do the following in configure
  45. # module load eccodes/2.8.0 python/2.7.13
  46. module load eccodes/2.8.0 python/2.7.13
  47. unset GRIB_DEFINITION_PATH
  48. unset GRIB_SAMPLES_PATH
  49. unset GRIB_BIN_PATH
  50. export GRIB_BIN_PATH=/apps/ECCODES/2.8.0/INTEL/bin
  51. }
  52. function configure_mpi()
  53. {
  54. [ -z "${OMP_NUM_THREADS-}" ] && export OMP_NUM_THREADS=1
  55. #export I_MPI_DEBUG=5
  56. #export I_MPI_ADJUST_BCAST=3
  57. #export PSM2_MTU=8196
  58. #export PSM2_MEMORY=large
  59. #export PSM2_MQ_RNDV_HFI_THRESH=1
  60. #export I_MPI_FABRIC=ofi
  61. #unset I_MPI_PMI_LIBRARY
  62. #export I_MPI_JOB_RESPECT_PROCESS_PLACEMENT=0
  63. #export I_MPI_FABRICS=shm:ofi
  64. }
  65. function get_hosts()
  66. {
  67. # This function uses a scheduler command to get the hosts allocated for the current job
  68. hosts=(`scontrol show hostname | paste -s`)
  69. }
  70. function machinefile_config()
  71. {
  72. # User configuration starts here
  73. # hard-coded c4mip configurations, must use the proper _numproc settings
  74. if has_config ifs nemo pisces rnfmapper xios lpjg ; then
  75. if ! has_config tm5 ; then
  76. ifs_ppn=48 ; [[ ${ifs_numproc} != 336 ]] && info "wrong numproc setting for ifs in machinefile_config" || true
  77. nem_ppn=43 ; [[ ${nem_numproc} != 380 ]] && info "wrong numproc setting for nemo in machinefile_config" || true
  78. xio_ppn=5 ; [[ ${xio_numproc} != 5 ]] && info "wrong numproc setting for xios in machinefile_config" || true
  79. lpjg_ppn=5 ; [[ ${lpjg_numproc} != 40 ]] && info "wrong numproc setting for lpjg in machinefile_config" || true
  80. else
  81. ifs_ppn=48 ; [[ ${ifs_numproc} != 256 ]] && info "wrong numproc setting for ifs in machinefile_config" || true
  82. nem_ppn=46 ; [[ ${nem_numproc} != 192 ]] && info "wrong numproc setting for nemo in machinefile_config" || true
  83. xio_ppn=2 ; [[ ${xio_numproc} != 2 ]] && info "wrong numproc setting for xios in machinefile_config" || true
  84. lpjg_ppn=2 ; [[ ${lpjg_numproc} != 8 ]] && info "wrong numproc setting for lpjg in machinefile_config" || true
  85. tm5_ppn=4 ; [[ ${tm5_numproc} != 4 ]] && info "wrong numproc setting for tm5 in machinefile_config" || true
  86. fi
  87. else
  88. # Add any new exclusive binary here
  89. ifs_exc=TRUE
  90. nem_exc=TRUE
  91. xio_exc=TRUE
  92. lpjg_exc=TRUE
  93. tm5_exc=TRUE
  94. # Modify the allocation to each binary using more than one process here
  95. ifs_ppn=48
  96. nem_ppn=48
  97. xio_ppn=48
  98. lpjg_ppn=48
  99. tm5_ppn=45
  100. fi
  101. }
  102. function machinefile_init()
  103. {
  104. # Get max processes per node from the platform variable
  105. max_ppn=$proc_per_node
  106. components=( ifs nem xio rnf amip lpjg )
  107. if $(has_config tm5)
  108. then
  109. components=( "${components[@]}" "tm5" )
  110. fi
  111. for component in ${components[@]}
  112. do
  113. eval ${component}_exc=FALSE
  114. eval ${component}_ppn=1
  115. done
  116. # Call user configuration and get_host functions
  117. machinefile_config
  118. get_hosts
  119. # Declare array to store the processes as they are assigned
  120. declare -a -g processes_hosts
  121. for n in `seq 0 ${#hosts[@]}`
  122. do
  123. processes_hosts[$n]=0
  124. done
  125. > machinefile
  126. current_hostid=0
  127. }
  128. machinefile_find_available_node()
  129. {
  130. while [ $((${processes_hosts[$current_hostid]} + ${!ppn})) -gt $max_ppn ]
  131. do
  132. let "current_hostid += 1"
  133. done
  134. }
  135. machinefile_add()
  136. {
  137. total_proc=$2
  138. # Iterate through all the possible binaries
  139. for component in ${components[@]}
  140. do
  141. binary="${component}_exe_file"
  142. exclusive="${component}_exc"
  143. # Check if the current binary matches the input executable
  144. if [ ./$(basename ${!binary}) = "$1" ]
  145. then
  146. ppn="${component}_ppn"
  147. # Exclusive mode: start allocation at the first empty node
  148. if [[ ${!exclusive} == "TRUE" ]]
  149. then
  150. while [ ${processes_hosts[$current_hostid]} -gt 0 ]
  151. do
  152. let "current_hostid += 1"
  153. done
  154. # Shared mode: start allocation in the first node with enough free cores
  155. # Notice that only the first node is checked
  156. # Then, if a previous binary had "exc=TRUE", allocation space is not ensure in subsequent nodes
  157. else
  158. current_hostid=0
  159. machinefile_find_available_node
  160. fi
  161. # Allocate ppn cores in each of the subsequent nodes till there are no more processes to assign
  162. count=0
  163. while [ ${total_proc} -gt 0 ]
  164. do
  165. if [ ${current_hostid} -ge ${#hosts[@]} ]
  166. then
  167. echo "Not enough computing nodes"
  168. exit 1
  169. fi
  170. current_hostname=${hosts[$current_hostid]}
  171. while [[ ${total_proc} -gt 0 && ${count} -lt ${!ppn} ]]
  172. do
  173. echo ${hosts[$current_hostid]} >> machinefile
  174. let "count += 1"
  175. let "processes_hosts[$current_hostid] += 1"
  176. let "total_proc -= 1" || true
  177. done
  178. if [ ${count} -eq ${!ppn} ]
  179. then
  180. let "current_hostid += 1"
  181. machinefile_find_available_node
  182. count=0
  183. fi
  184. done
  185. fi
  186. done
  187. }
  188. function launch()
  189. {
  190. # Compute and check the node distribution
  191. info "======================="
  192. info "Node/proc distribution:"
  193. info "-----------------------"
  194. info "IFS: ${ifs_numproc}"
  195. info "NEMO: ${nem_numproc}"
  196. info "XIOS: ${xio_numproc}"
  197. info "RUNOFF: ${rnf_numproc}"
  198. info "======================="
  199. cmd="mpirun"
  200. cat /dev/null > prog.conf
  201. proc_id=0
  202. if [ "$use_machinefile" = "true" ]
  203. then
  204. cmd="mpirun -machinefile machinefile"
  205. machinefile_init
  206. fi
  207. while (( "$#" ))
  208. do
  209. # Get number of MPI ranks and executable name
  210. nranks=$1
  211. executable=./$(basename $2)
  212. if [ "$use_machinefile" = "true" ]
  213. then
  214. machinefile_add $executable $nranks
  215. fi
  216. shift
  217. shift
  218. cmd+=" -n $nranks $executable"
  219. # Add any arguments to executable
  220. while (( "$#" )) && [ "$1" != "--" ]
  221. do
  222. cmd+=" $1"
  223. shift
  224. done
  225. shift || true
  226. for i in $(eval echo "{1..${nranks}}")
  227. do
  228. echo "$proc_id ${executable}" >> prog.conf
  229. proc_id=$(($proc_id+1))
  230. done
  231. # Add colon of more executables follow
  232. (( "$#" )) && cmd+=" :"
  233. done
  234. #cmd="srun --kill-on-bad-exit=1 --multi-prog prog.conf"
  235. pwd
  236. echo $cmd
  237. #exit
  238. $cmd
  239. }
  240. function finalise()
  241. {
  242. # This function should execute of any post run functionality, e.g.
  243. # platform dependent cleaning or a resubmit
  244. if ${resubmit_job} && [ $(date -d "${leg_end_date}" +%s) -lt $(date -d "${run_end_date}" +%s) ]
  245. then
  246. info "Resubmitting job for leg $((leg_number+1))"
  247. # Need to go to start_dir to find the run script
  248. cd ${start_dir}
  249. # Submit command
  250. # Note: This does not work if you specify a job name with sbatch -J jobname!
  251. sbatch -N ${SLURM_JOB_NUM_NODES} \
  252. -o ${run_dir}/$(basename ${stdout_file}).$(printf %03d $((leg_number+1))) \
  253. -e ${run_dir}/$(basename ${stdout_file}).$(printf %03d $((leg_number+1))) \
  254. -d ${SLURM_JOB_ID} \
  255. ${resubmit_opt} \
  256. ./${SLURM_JOB_NAME}.sh
  257. fi
  258. }