source: trunk/LMDZ.COMMON/libf/evolution/deftank/lib_launchPEM.sh @ 3859

Last change on this file since 3859 was 3859, checked in by jbclement, 7 months ago

PEM:
Setting up an automatic selection of the XIOS output file for the PEM according to the number of slopes.
JBC

  • Property svn:executable set to *
File size: 17.0 KB
Line 
1#!/bin/bash
2########################################################################
3######## Library of bash functions for the PEM launching script ########
4########################################################################
5
6# To end the launching script
7endlaunch() {
8    # Restore the previous value of LC_NUMERIC
9    LC_NUMERIC=$OLD_LC_NUMERIC
10
11    date
12    echo "Success: the launching script for the PEM simulation completed normally!"
13    exit 0
14}
15
16# To end the launching script with error
17errlaunch() {
18    # Restore the previous value of LC_NUMERIC
19    LC_NUMERIC=$OLD_LC_NUMERIC
20
21    date
22    echo "Error: an issue occured in the launching script for the PEM simulation!"
23    exit 1
24}
25
26# To check what is the job scheduler
27function job_scheduler() {
28    if command -v squeue &> /dev/null; then
29        echo "SLURM is installed on $machine."
30        name_job="#SBATCH --job-name="
31        kill_job="scancel"
32        submit_job="sbatch --parsable"
33        submit_dependjob="sbatch --parsable --dependency"
34    elif command -v qstat &> /dev/null; then
35        echo "PBS/TORQUE is installed on $machine."
36        name_job="#PBS -N "
37        kill_job="qdel"
38        submit_job="qsub"
39        submit_dependjob="qsub -W depend"
40    else
41        echo "Error: neither SLURM nor TORQUE/PBS is installed on $machine!"
42        echo "You need to adapt the script to your job scheduler."
43        errlaunch
44    fi
45}
46
47# To get the number of slopes for the simulation
48get_nslope() {
49    ns=1
50    if [ -f "startfi.nc" ]; then
51        ns=$(ncdump -h startfi.nc | sed -n 's/.*nslope = \([0-9]*\) ;.*/\1/p')
52    else
53        for f in run_PCM.def callphys.def; do
54            if [[ -f "$f" ]]; then
55                while IFS= read -r line; do
56                    # Remove leading whitespace
57                    trimmed=$(echo "$line" | sed 's/^[[:space:]]*//')
58                    # Skip lines that are commented out
59                    if [[ "$trimmed" == \#* ]]; then
60                        continue
61                    fi
62                    # Check if line contains 'nslope = N'
63                    if [[ "$trimmed" =~ ^nslope[[:space:]]*=[[:space:]]*([0-9]+) ]]; then
64                        ns="${BASH_REMATCH[1]}"
65                        break
66                    fi
67                done < "$f"
68                [[ -n "$ns" ]] && break
69            fi
70        done
71    fi
72}
73
74# To modify the xml file according nslope
75modify_xml() {
76    tmp="tmp_file_def.xml"
77    in_diurnalave=false
78    in_diurnalave_s=false
79
80    sed -i 's/enabled="\.true\.\">/enabled=".false.">/g' file_def_physics_mars.xml
81    while IFS= read -r line; do
82        case "$line" in
83            *'<file id="diurnalave"'*)
84                in_diurnalave=true
85                ;;
86            *'<file id="diurnalave_s"'*)
87                in_diurnalave_s=true
88                ;;
89        esac
90
91        if [[ $line == *'enabled="'* ]]; then
92            if $in_diurnalave; then
93                if [[ $ns -eq 1 ]]; then
94                    line='              enabled=".true.">'
95                else
96                    line='              enabled=".false.">'
97                fi
98            elif $in_diurnalave_s; then
99                if [[ $ns -eq 1 ]]; then
100                    line='              enabled=".false.">'
101                else
102                    line='              enabled=".true.">'
103                fi
104            fi
105        fi
106
107        case "$line" in
108            *'</file>'*)
109                in_diurnalave=false
110                in_diurnalave_s=false
111                ;;
112        esac
113
114        echo "$line" >> "$tmp"
115    done < file_def_physics_mars.xml
116
117    mv "$tmp" file_def_physics_mars.xml
118}
119
120# To check if everything necessary for the launching script is ok
121checklaunch() {
122    # Save the current value of LC_NUMERIC and set it to a locale that uses a dot as the decimal separator
123    OLD_LC_NUMERIC=$LC_NUMERIC
124    LC_NUMERIC=en_US.UTF-8
125
126    if [ -v n_mars_years ] && [ ! -z "$n_mars_years" ]; then
127        if [ $(echo "$n_mars_years < 0." | bc -l) -eq 1 ]; then
128            echo "Error: the value of 'n_mars_years' must be >0!"
129            errlaunch
130        fi
131    elif [ -v n_earth_years ] && [ ! -z "$n_earth_years" ]; then
132        if [ $(echo "$n_earth_years < 0." | bc -l) -eq 1 ]; then
133            echo "Error: the value of 'n_earth_years' must be >0!"
134            errlaunch
135        fi
136    else
137        echo "Error: no number of years to be simulated has been set!"
138        errlaunch
139    fi
140    if [ $nPCM_ini -lt 2 ] || [ -z "$nPCM_ini" ]; then
141        echo "Error: the value of 'nPCM_ini' must be >1!"
142        errlaunch
143    fi
144    if [ $nPCM -lt 2 ] || [ -z "$nPCM" ]; then
145        echo "Error: the value of 'nPCM' must be >1!"
146        errlaunch
147    fi
148    if [ ! -f "PCMrun.job" ]; then
149        echo "Error: file \"PCMrun.job\" does not exist in $dir!"
150        errlaunch
151    fi
152    if [ ! -f "PEMrun.job" ]; then
153        echo "Error: file \"PEMrun.job\" does not exist in $dir!"
154        errlaunch
155    fi
156    if [ ! -f "run_PCM.def" ]; then
157        echo "Error: file \"run_PCM.def\" does not exist in $dir!"
158        errlaunch
159    fi
160    if [ ! -f "run_PEM.def" ]; then
161        echo "Error: file \"run_PEM.def\" does not exist in $dir!"
162        errlaunch
163    fi
164    if [ ! -f "context_lmdz_physics.xml" ]; then
165        echo "Error: file \"context_lmdz_physics.xml\" does not exist in $dir!"
166        errlaunch
167    fi
168    if [ ! -f "field_def_physics_mars.xml" ]; then
169        echo "Error: file \"field_def_physics_mars.xml\" does not exist in $dir!"
170        errlaunch
171    fi
172    if [ ! -f "file_def_physics_mars.xml" ]; then
173        echo "Error: file \"file_def_physics_mars.xml\" does not exist in $dir!"
174        errlaunch
175    fi
176    if [ ! -f "iodef.xml" ]; then
177        echo "Error: file \"iodef.xml\" does not exist in $dir!"
178        errlaunch
179    fi
180    if [ ! -d "out_PCM" ]; then
181        mkdir out_PCM
182    fi
183    if [ ! -d "out_PEM" ]; then
184        mkdir out_PEM
185    fi
186    if [ ! -d "starts" ]; then
187        mkdir starts
188    fi
189    if [ ! -d "diags" ]; then
190        mkdir diags
191    fi
192    if [ $mode -ne 0 ]; then
193        job_scheduler
194    fi
195    # Set automatically the XIOS output file for the PEM according to the number of slopes
196    get_nslope
197    modify_xml
198}
199
200# To convert Earth years into Mars years
201convertyears() {
202    myear=686.9725      # Number of Earth days in Martian year
203    eyear=365.256363004 # Number of days in Earth year
204    convert_years=$(echo "$myear/$eyear" | bc -l)
205    convert_years=$(printf "%.4f" $convert_years) # Rounding to the 4th decimal to respect the precision of Martian year
206    if [ -v n_mars_years ]; then
207        n_myear=$n_mars_years
208        echo "Number of years to be simulated: $n_myear Martian years."
209    elif [ -v n_earth_years ]; then
210        n_myear=$(echo "$n_earth_years/$convert_years" | bc -l)
211        echo "Number of years to be simulated: $n_earth_years Earth years = $n_myear Martian years."
212    fi
213}
214
215# To initialize the launching script
216initlaunch() {
217    echo "This is a chained simulation for PEM and PCM runs in $dir on $machine by $user."
218    convertyears
219    i_myear=0.
220    iPEM=1
221    iPCM=1
222    if [ -f "startfi.nc" ]; then
223        cp startfi.nc starts/
224    fi
225    if [ -f "start.nc" ]; then
226        cp start.nc starts/
227    elif [ -f "start1D.txt" ]; then
228        cp start1D.txt starts/
229    fi
230    if [ -f "startpem.nc" ]; then
231        cp startpem.nc starts/
232    fi
233
234    # Create a file to manage years of the chained simulation and store some info from the PEM runs
235    echo $i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini > info_PEM.txt
236}
237
238# To submit the PCM runs
239# arg1: launching mode
240# arg2: counting method
241# arg3: number of PCM runs to launch
242# arg4: local number of the PCM run from which to start (optional)
243submitPCM() {
244    find . -type f -name "PCMrun*.job" ! -name "PCMrun.job" -delete
245    ii=1
246    if [ ! -z $4 ]; then
247        ii=$4
248    fi
249    if [ $(echo "$i_myear < $n_myear" | bc -l) -eq 1 ]; then
250        echo "Run \"PCM $iPCM\" ($ii/$3)"
251        if [ $1 -eq 0 ]; then # Mode: processing scripts
252            sed -i "s/^k=-\?[0-9]\+$/k=$(echo "$ii - $3 + 2" | bc)/" PCMrun.job
253            ./PCMrun.job
254            if [ $? -ne 0 ]; then
255                errlaunch
256            fi
257        else # Mode: submitting jobs
258            cp PCMrun.job PCMrun${iPCM}.job
259            sed -i -E "/^$name_job/s/(.*[^0-9])([0-9]+)(_[^0-9]*)?$/\1${iPCM}\3/" PCMrun${iPCM}.job
260            sed -i "s/^k=-\?[0-9]\+$/k=$(echo "$ii - $3 + 2" | bc)/" PCMrun${iPCM}.job
261            jobID=$(eval "$submit_job PCMrun${iPCM}.job")
262            # Create a file to cancel the dependent jobs of the cycle
263            echo "#!/bin/bash" > kill_launchPEM.sh
264            chmod +x kill_launchPEM.sh
265            echo $kill_job $jobID >> kill_launchPEM.sh
266        fi
267        ((iPCM++))
268        if [ $2 -ne 0 ]; then # Counting: PCM runs taken into account
269            i_myear=$(echo "$i_myear + 1." | bc -l)
270        fi
271        ((ii++))
272    else
273        endlaunch
274    fi
275    for ((i = $ii; i <= $3; i++)); do
276        if [ $(echo "$i_myear < $n_myear" | bc -l) -eq 1 ]; then
277            echo "Run \"PCM $iPCM\" ($i/$3)"
278            if [ $1 -eq 0 ]; then # Mode: processing scripts
279                sed -i "s/^k=-\?[0-9]\+$/k=$(echo "$i - $3 + 2" | bc)/" PCMrun.job
280                ./PCMrun.job
281                if [ $? -ne 0 ]; then
282                    errlaunch
283                fi
284            else # Mode: submitting jobs
285                cp PCMrun.job PCMrun${iPCM}.job
286                sed -i -E "/^$name_job/s/(.*[^0-9])([0-9]+)(_[^0-9]*)?$/\1${iPCM}\3/" PCMrun${iPCM}.job
287                sed -i "s/^k=-\?[0-9]\+$/k=$(echo "$i - $3 + 2" | bc)/" PCMrun${iPCM}.job
288                jobID=$(eval "$submit_dependjob=afterok:${jobID} PCMrun${iPCM}.job")
289                echo $kill_job $jobID >> kill_launchPEM.sh
290            fi
291            ((iPCM++))
292            if [ $2 -ne 0 ]; then # Counting: PCM runs taken into account
293                i_myear=$(echo "$i_myear + 1." | bc -l)
294            fi
295        else
296            endlaunch
297        fi
298    done
299}
300
301# To submit the PEM run
302# arg1: launching mode
303submitPEM() {
304    if [ $(echo "$i_myear < $n_myear" | bc -l) -eq 1 ]; then
305        echo "Run \"PEM $iPEM\""
306        if [ $1 -eq 0 ]; then # Mode: processing scripts
307            ./PEMrun.job
308            if [ $? -ne 0 ]; then
309                errlaunch
310            fi
311        else # Mode: submitting jobs
312            sed -i -E "/^$name_job/s/(.*[^0-9])([0-9]+)(_[^0-9]*)?$/\1${iPEM}\3/" PEMrun.job
313            jobID=$(eval "$submit_job PEMrun.job")
314            # Create a file to cancel the dependent jobs of the cycle
315            echo "#!/bin/bash" > kill_launchPEM.sh
316            chmod +x kill_launchPEM.sh
317            echo $kill_job $jobID >> kill_launchPEM.sh
318        fi
319    else
320        endlaunch
321    fi
322}
323
324# To make one cycle of PCM and PEM runs
325# arg1: launching mode
326# arg2: counting method
327# arg3: number of PCM runs to launch
328# arg4: local number of the PCM run from which to start (optional)
329cyclelaunch() {
330    # PCM runs
331    submitPCM $1 $2 $3 $4
332
333    # PEM run
334    if [ $(echo "$i_myear < $n_myear" | bc -l) -eq 1 ]; then
335        echo "Run \"PEM $iPEM\""
336        if [ $1 -eq 0 ]; then # Mode: processing scripts
337            ./PEMrun.job
338            if [ $? -ne 0 ]; then
339                errlaunch
340            fi
341        else # Mode: submitting jobs
342            sed -i -E "/^$name_job/s/(.*[^0-9])([0-9]+)(_[^0-9]*)?$/\1${iPEM}\3/" PEMrun.job
343            jobID=$(eval "$submit_dependjob=afterok:${jobID} PEMrun.job")
344            echo $kill_job $jobID >> kill_launchPEM.sh
345        fi
346    else
347        endlaunch
348    fi
349}
350
351# To clean files after the starting run of the relaunch
352# arg1: file name prefix to clean
353# arg2: file name extension to clean
354# arg3: file number from which to clean
355cleanfiles() {
356    prefix=$1
357    extension=$2
358    if [ -z "$extension" ]; then
359        for file in ${prefix}*; do
360            num=${file#$prefix}
361            if [[ $num =~ ^[0-9]+$ ]] && [ $num -gt $3 ]; then
362                rm $file
363            fi
364        done
365    else
366        for file in ${prefix}*${extension}; do
367            num=${file#$prefix}
368            num=${num%$extension}
369            if [[ $num =~ ^[0-9]+$ ]] && [ $num -gt $3 ]; then
370                rm $file
371            fi
372        done
373    fi
374}
375
376# To relaunch from PCM run
377# arg1: launching mode
378# arg2: counting method
379relaunchPCM() {
380    iPCM=$(($irelaunch + 1))
381    cleanfiles diags/diagfi .nc $irelaunch
382    cleanfiles diags/diagsoil .nc $irelaunch
383    cleanfiles diags/data2reshape .nc $irelaunch
384    cleanfiles "out_PCM/run" "" $irelaunch
385    cleanfiles starts/restart1D .txt $irelaunch
386    cleanfiles starts/restart .nc $irelaunch
387    cleanfiles starts/restartfi .nc $irelaunch
388    cp starts/restartfi${irelaunch}.nc startfi.nc
389    if [ -f "starts/restart${irelaunch}.nc" ]; then
390        cp starts/restart${irelaunch}.nc start.nc
391    elif [ -f "starts/restart1D${irelaunch}.txt" ]; then
392        cp starts/restart1D${irelaunch}.txt start1D.txt
393    fi
394    if [ $irelaunch -le $nPCM_ini ]; then
395        # PCM relaunch during the initialization cycle
396        iPEM=1
397        if [ $2 -ne 0 ]; then # Counting: PCM runs taken into account
398            i_myear=$irelaunch
399        else # Counting: only PEM runs count
400            i_myear=0
401        fi
402        sed -i "1s/.*/$i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini/" info_PEM.txt
403        cleanfiles diags/diagpem .nc $(($iPEM - 1))
404        cleanfiles diags/diagsoilpem .nc $(($iPEM - 1))
405        cleanfiles "out_PEM/run" "" $(($iPEM - 1))
406        cleanfiles starts/restart1D_postPEM .txt $(($iPEM - 1))
407        cleanfiles starts/restart_postPEM .nc $(($iPEM - 1))
408        cleanfiles starts/restartfi_postPEM .nc $(($iPEM - 1))
409        cleanfiles starts/restartpem .nc $(($iPEM - 1))
410        rm -f startpem.nc
411        if [ -f "starts/startpem.nc" ]; then
412            cp starts/startpem.nc .
413        fi
414        if [ $irelaunch -eq $(($nPCM_ini - 1)) ]; then
415            cp diags/data2reshape${irelaunch}.nc data2reshape_Y1.nc
416            cyclelaunch $1 $2 $nPCM_ini $iPCM
417        elif [ $irelaunch -eq $nPCM_ini ]; then
418            cp diags/data2reshape$(($irelaunch - 1)).nc data2reshape_Y1.nc
419            cp diags/data2reshape${irelaunch}.nc data2reshape_Y2.nc
420            submitPEM $1 # The next job is a PEM run
421        else
422            cyclelaunch $1 $2 $nPCM_ini $iPCM
423        fi
424    else
425        # PCM relaunch during a cycle
426        iPEM=$(echo "($iPCM - $nPCM_ini)/$nPCM + 1" | bc)
427        il=$(echo "($irelaunch - $nPCM_ini + 1)%$nPCM + 1" | bc)
428        if [ $2 -ne 0 ]; then # Counting: PCM runs taken into account
429            i_myear=$(echo "$(awk "NR==$iPEM {printf \"%s\n\", \$3}" "info_PEM.txt") + $il" | bc -l)
430        else # Counting: only PEM runs count
431            i_myear=$(awk "NR==$iPEM {printf \"%s\n\", \$3}" "info_PEM.txt")
432        fi
433        sed -i "1s/.*/$i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini/" info_PEM.txt
434        cleanfiles diags/diagpem .nc $(($iPEM - 1))
435        cleanfiles diags/diagsoilpem .nc $(($iPEM - 1))
436        cleanfiles "out_PEM/run" "" $(($iPEM - 1))
437        cleanfiles starts/restart1D_postPEM .txt $(($iPEM - 1))
438        cleanfiles starts/restart_postPEM .nc $(($iPEM - 1))
439        cleanfiles starts/restartfi_postPEM .nc $(($iPEM - 1))
440        cleanfiles starts/restartpem .nc $(($iPEM - 1))
441        cp starts/restartpem$(($iPEM - 1)).nc startpem.nc
442        if [ $il -eq $(($nPCM - 1)) ]; then # Second to last PCM run
443            cp diags/data2reshape${irelaunch}.nc data2reshape_Y1.nc
444            cyclelaunch $1 $2 $nPCM $(($il + 1))
445        elif [ $il -eq $nPCM ]; then # Last PCM run so the next job is a PEM run
446            cp diags/data2reshape$(($irelaunch - 1)).nc data2reshape_Y1.nc
447            cp diags/data2reshape${irelaunch}.nc data2reshape_Y2.nc
448            submitPEM $1
449        else
450            cyclelaunch $1 $2 $nPCM $(($il + 1))
451        fi
452    fi
453}
454
455# To relaunch from PEM run
456# arg1: launching mode
457# arg2: counting method
458relaunchPEM() {
459    iPEM=$(echo "$irelaunch + 1" | bc)
460    iPCM=$(echo "$nPCM_ini + $nPCM*($irelaunch - 1) + 1" | bc)
461    i_myear=$(awk "NR==$iPEM {printf \"%s\n\", \$3}" "info_PEM.txt")
462    sed -i "1s/.*/$i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini/" info_PEM.txt
463    cleanfiles diags/diagfi .nc $(($iPCM - 1))
464    cleanfiles diags/diagsoil .nc $(($iPCM - 1))
465    cleanfiles "out_PCM/run" "" $(($iPCM - 1))
466    cleanfiles starts/restart1D .txt $(($iPCM - 1))
467    cleanfiles starts/restart .nc $(($iPCM - 1))
468    cleanfiles starts/restartfi .nc $(($iPCM - 1))
469    cleanfiles diags/data2reshape .nc $(($iPCM - 1))
470    cleanfiles diags/diagpem .nc $irelaunch
471    cleanfiles diags/diagsoilpem .nc $irelaunch
472    cleanfiles "out_PEM/run" "" $irelaunch
473    cleanfiles starts/restart1D_postPEM .txt $irelaunch
474    cleanfiles starts/restart_postPEM .nc $irelaunch
475    cleanfiles starts/restartfi_postPEM .nc $irelaunch
476    cleanfiles starts/restartpem .nc $irelaunch
477    cp starts/restartpem${irelaunch}.nc startpem.nc
478    cp starts/restartfi_postPEM${irelaunch}.nc startfi.nc
479    if [ -f "starts/restart_postPEM${irelaunch}.nc" ]; then
480        cp starts/restart_postPEM${irelaunch}.nc start.nc
481    elif [ -f "starts/restart1D_postPEM${irelaunch}.txt" ]; then
482        cp starts/restart1D_postPEM${irelaunch}.txt start1D.txt
483    fi
484    cyclelaunch $1 $2 $nPCM
485}
Note: See TracBrowser for help on using the repository browser.