source: BOL/Replay/replay_equip.sh @ 4373

Last change on this file since 4373 was 4373, checked in by fhourdin, 22 months ago

Adding thermcell_updown_dq

File size: 18.1 KB
Line 
1#!/bin/bash
2
3#set -vx
4
5#=============================================================================
6#  F. Hourdin : 2022/05/03
7#
8#  Objet :
9#  -----
10#  Script préparant les programes pour rejouer (replay) une paramétrisation
11#  ou un morceau de paramétriation.
12#
13#
14#  Applicabilité :
15#  ---------------
16#  Est fait pour rejouer des paramétisation de LMDZ organisées comme
17#    des calcul sur des successions de colonnes indépendantes (boucle
18#    interne en $klon) de $klev niveaux verticaux.
19#  Demande que la paramétrisation répondent aux règles de codage suivantes :
20#  1) Les routines de calcul et les routines ou fonctions qu'elles appellent
21#     n'ont que deux interfaces : A) les arguments d'entrée
22#                                 B) le use d'un unique module
23#     Entre autre, les dimensions de la paramétrisation sont passés
24#     en argument, ce qui permet une allocation dynamique implicite
25#     de toutes les variables.
26#  2) le module d'initialisation doit lui même être initialisé par
27#     une unique routine pilotée entièrement par ses arguments.
28#  3) Toutes les variables d'interface doivent être déclarées intent in
29#     out, ou inout
30#  On appelera la paramétriation "param" et l'intialisation "param_ini"
31#     mais les noms de fichiers sont en argument dans le script.
32#
33#
34#  Principe :
35#  ----------
36#  Dans une première simulation, on écrit dans un fichier binaire toutes
37#  les variables "intent in/inout" de la routine d'initialisation et de la routine
38#  de calcul.
39#
40#
41#  En pratique :
42#  -------------
43#
44#  Le script a comme argument le nom de la routine à traiter, nommée $param
45#   Des correpspondances en déduisent :
46#   paramini=wake_ini  # nom de la subroutine d'intialisation
47#   inimod= # nom du module contenant $param_ini
48#   klon=klon ; klev=klev  # nom des dimensions horiz; vert utilisée
49#
50#  Le fichier ${paramfile} contenant $param est detecté automatiquement
51#  Le script crée 5 fichiers
52#  * dump_param1.h          : écriture de l'interface "in" de param (dump_param.bin fort.82)
53#  * dump_param2.h          : écriture des sorties de la routines dans phys.nc
54#  * call_param_replay.F90 : sous programme d'appelle en boucle à la param
55#  * dump_ini_module.F90   : écriture de l'interface "in" de param_ini
56#  * get_ini_module.F90    : lecture de l'interface "in" de param_ini
57#                dans ${param_ini}_mod.bin.
58#  Par ailleurs, un programme replay1d a été ajouté dans phylmd/dyn1d
59#        qui appelle call_param_replay
60#  Le script ajoute par ailleurs quelques lignes dans ${paramfile} et
61#        ${param_ini}.F90
62#  replay_clean.sh élimine toutes les lignes ajoutées
63#
64#
65#  A travailler :
66#  --------------
67#  * détecter automatiquement le fichier contenant l'intialisation
68#  * détecter automatiquement les dimensions
69#  * avoir un moyen de vérifier si les variables intent in et out sont
70#    bien les bonnes.
71#  * Initialisation plus simple de la routine getin_p
72#  * Des choix sur la facon de controler l'initialisation et le pb des getin
73#
74#=============================================================================
75
76#-----------------------------------------------------------------------------
77# Reading rguments
78#-----------------------------------------------------------------------------
79nconly=false
80where=-before_return
81
82if [ $# = 0 ] ; then $0 -h ; exit ; fi
83while (($# > 0))
84   do
85   case $1 in
86     -h|--help) cat <<........fin
87           $0 [-nconly] [-ncvars var1,var2,...] [-pre prefix] [location_in_the_code] routine_name
88           The prefix will be put on each variable stored in the nc file to avoid duplicate
89                variables names
90           If -ncvars is not specified, all the variables are output
91           The prefix is used to prevent having twice the same name if the same variable is
92              output at two locations in the code.
93           location_in_the_code can be : -before_return               (the default valuer)
94                                         -after_declarations
95                                         -before_line  "line in code"
96                                         -after_line   "line in code"
97                                         -before_call  "param_name"   (TO BE DONE)
98                                         -after_call   "param_name"   (TO BE DONE)
99........fin
100        exit ;;
101     -nconly) nconly=true ; shift ;;
102     -before_line|-after_line|-before_call|-after_call) where="$1 $2" ; shift ; shift ;;
103     -before_return|-after_declarations) where=$1 ; shift ;;
104     -pre) prefix=$2 ; shift ; shift ;;
105     -ncvars) ncvars="`echo $2 | sed -e 's/,/ /g'`" ; shift ; shift ;;
106     *) if (( $# > 1 )) ; then $0 -h ; exit ; fi ; param=`basename $1 .F90` ; shift
107    esac
108done
109if [ "$param" = "" ] ; then $0 -h ; exit ; fi
110
111case $param in
112   thermcell_main|thermcell_plume_6A|thermcell_env|thermcell_height|thermcell_dry|\
113      thermcell_closure|thermcell_height|thermcell_dq|thermcell_flux2|thermcell_down| \
114      thermcell_updown_dq) \
115      paramini=thermcell_ini ; inimod=thermcell_ini_mod ; klon=ngrid ; klev=nlay ;;
116   wake|wake_popdyn_2) paramini=wake_ini ; inimod=wake_ini_mod ; klon=klon ; klev=klev ;;
117   *) echo Cas non prevu ; exit
118esac
119
120replay_comment="replay automatic include"
121paraminc1=dump_replay_${param}_head.h
122paraminc2=dump_replay_${param}_nc_${prefix}.h
123iniinc=dump_replay_ini.h
124paramfile=`grep -i "subro.* ${param}[\ (]" *.F90 | sed -e 's/ //g' | grep "${param}(" | cut -d: -f1`
125echo ===================================================================================
126echo Equiping $param contained in file $paramfile
127if [ `echo ${paramfile} | wc -w` != 1 ] ; then echo file $paramfile multiple  ; $0 -h ; exit ; fi
128
129
130#-----------------------------------------------------------------------------
131# Transformer l'entete d'une subroutine en un call
132#-----------------------------------------------------------------------------
133
134function get_subroutine_arg(){
135   cat $2 | tr '[A-Z]' '[a-z]' > tmp
136   line1=`sed -n -e '/subrou.*'\`echo $1 | tr '[A-Z]' '[a-z]'\`'.*(/=' tmp | head -1 `
137   line2=`tail -n +$line1 tmp | sed -n -e '/)/=' | head -1`
138   tail -n +$line1 tmp | sed -n -e 1,${line2}p
139}
140
141#-----------------------------------------------------------------------------
142function dump_param_open(){
143#-----------------------------------------------------------------------------
144# Opening an direct access file with one record per time-step
145# Each record has the size and contains the arguments in and inout of the
146# routine
147#-----------------------------------------------------------------------------
148inout=$1 ; shift
149case $inout in
150   out) fort=81 ;;
151   in) fort=82
152esac
153echo '! <<< dump_param_open'
154for var in $* ; do echo 'rec_length_replay=rec_length_replay+kind('$var')*size(['$var'])' ; done
155cat <<eod
156open(${fort},file='dump_param_${inout}.bin',form='unformatted',access='direct',recl=rec_length_replay)  ! $replay_comment
157eod
158echo '! dump_param_open >>> '
159}
160
161
162#-----------------------------------------------------------------------------
163function extract_subroutine(){
164#-----------------------------------------------------------------------------
165   # $1 nom de la subroutine
166   # $2 nom du fichier
167   # input <- routine under treatment with small caps only
168   ( cpp $2 2>/dev/null ) | tr '[A-Z]' '[a-z]' > tmp
169   name_min=`echo $1 | tr '[A-Z]' '[a-z]'`
170   line1=`sed -n -e "/subrou.*${name_min}.*(/=" tmp | head -1 `
171   tail -n +$line1 tmp > tmp2
172   line2=`sed -n -e "/[Rr][Ee][Tt][Uu][Rr][Nn]/=" tmp2 | head -1`
173   head -$line2 tmp2  > input
174   \rm -f tmp tmp2
175}
176
177
178#-----------------------------------------------------------------------------
179function include_line(){
180#-----------------------------------------------------------------------------
181   # Including param_dump*.h in the parameterization
182   #set -vx
183   line_to_be_included=$1  ; shift
184   param_=$1 ; shift
185   paramfile_=$1 ; shift
186   name_min=`echo $param_ | tr [A-Z] [a-z]`
187   line_subroutine=`cat $paramfile_ | tr '[A-Z]' '[a-z]' | sed -n -e "/subrou.*${name_min}.*(/=" | head -1 `
188   tail -n +$line_subroutine $paramfile_ > tmp # file starting at the subroutine instruction
189   line_return=`sed -n -e "/[Rr][Ee][Tt][Uu][Rr][Nn]/=" tmp | head -1`
190   head -$line_return tmp > tmp2               # file containing the routine
191   sed -e 's/\!.*$//' tmp2 > tmp3
192   cpp tmp2 > tmp3 2>/dev/null
193   cat tmp3 | tr '[A-Z]' '[a-z]' > tmp2_cpp   # same after cpp filtering
194   last_line_declaration2="`sed -n -e 's/\!.*$//' -e 's/^/ /' -e '/[\ ,]real[\ ,]/p' -e '/[\ ,]integer[\ ,]/p' -e '/[\ ,]logical[\ ,]/p' -e '/[\ ,]character[\ ,]/p' tmp2_cpp | tail -1 | sed -e 's/  / /g' -e 's/ /.*/g'`"
195   line_last_declaration=`cat tmp2 | tr '[A-Z]' '[a-z]' | sed -n -e "/$last_line_declaration2/="`
196   if [ "$line_last_declaration" = "" ] ; then echo line_last_declaration $line_last_declaration line $last_line_declaration2  ; exit ; fi
197   if (( $# > 0 )) ; then
198      wtype=`echo $1 | awk ' { print $1 } '`
199      case $wtype in
200         -after_declarations)      targeted_line=$line_last_declaration ;;
201         -before_return)           targeted_line=$line_return ;;
202         -before_line|-after_line) linestr=`echo $1 | sed -e "s/$wtype //"` ; targeted_line=`sed -n -e "/$linestr/=" tmp2` ;;
203         *)                  echo Cas non prevu 0 where=$where in inclide_file
204      esac
205      case $wtype in
206         -after_declarations|-after_line)  line0=$(( $line_subroutine - 1 )) ;;
207         -before_return|-before_line)      line0=$(( $line_subroutine - 2 )) ;;
208         *)                  echo Cas non prevu 1 where=$where in inclide_file
209      esac
210      echo Including line $line0 in $paramfile_ the line : $line_to_be_included
211      linebefore_include=$(( $line0 + $targeted_line ))
212     sed -i'' -e $linebefore_include"s/$/\n $line_to_be_included \!  $replay_comment/" $paramfile_ 
213   fi
214}
215
216
217
218
219#-----------------------------------------------------------------------------
220function block_Replay0() {
221#-----------------------------------------------------------------------------
222condition=$1 ; shift
223suf1=$1 ; shift
224suf2=$1 ; shift
225if [ $# -gt 0 ] ; then
226   vars=$*
227   echo '   if ('$condition') then'
228   for var in $vars ; do echo '      '$var$suf1=$var$suf2 ; done
229   echo '   endif'
230fi
231}
232
233#-----------------------------------------------------------------------------
234function iotd_calls(){
235#-----------------------------------------------------------------------------
236    klev_=$1 ; shift
237    pre=$1 ; shift
238    if (( $# >> 0 )) ; then
239       vars=$*
240       for var in $vars ; do
241          echo "call iotd_ecrit_seq('"$pre$var"',$klev_,'"$pre$var in $param"',' ',"$var")"
242       done
243    fi
244}
245         
246#-----------------------------------------------------------------------------
247function b_among_a() {
248#-----------------------------------------------------------------------------
249   a="$1"
250   b="$2"
251   o=""
252   for v in $a ; do
253       for vv in $b ; do
254           if [ "$v" = "$vv" ] ; then o="$o $v" ;  fi
255       done
256   done
257   echo $o
258}
259
260
261#-----------------------------------------------------------------------------
262# On nettoye les inclusions précédente dans les fichiers .F90
263#-----------------------------------------------------------------------------
264
265if [ $nconly = false ] ; then
266   for file in `grep "$replay_comment" *.F90 2> /dev/null | cut -d: -f1` ; do
267      sed -i"" -e "/$replay_comment/d" $file
268   done
269   line=`sed -n -e "/CALL wake_ini/=" physiq_mod.F90 | head -1`
270   sed -i"" -e "${line}s/$/\n   CALL iophys_ini(pdtphys) ! $replay_comment  ! $replay_comment/" physiq_mod.F90
271fi
272
273#-----------------------------------------------------------------------------
274# Analysis of the variables to be stored and there nature
275#-----------------------------------------------------------------------------
276
277extract_subroutine $param $paramfile # -> input file
278varin0=`grep inten.*.in input | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'`
279varinout0=`grep inten.*.inout input | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'`
280varin=`echo $varin0 | sed -e 's/ /,/g' -e "s/,,,/,/g" -e "s/,,/,/g"`
281output=full # Attention, l'option full ne marche pas a cause de tableaux locaux undef
282nvar0D=0 ; nvar1D=0 ; nvar2D=0
283case $output in
284   light) search_str='real.*intent' ;;
285   full) search_str='real'
286esac
287var_1D_inout=`grep -i "$search_str" input | grep intent.*inout | grep $klon | sed -e 's/!.*$//' -e /$klev/d | cut -d: -f3 | sed -e 's/,/ /g'`
288var_2D_inout=`grep -i "$search_str" input | grep intent.*inout | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'`
289var_1D_noarg=`grep -i "$search_str" input | sed -e /intent/d | grep $klon | sed -e 's/!.*$//' -e /$klev/d | cut -d: -f3 | sed -e 's/,/ /g'`
290var_2D_noarg=`grep -i "$search_str" input | sed -e /intent/d | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'`
291var_1D=`grep -i "$search_str" input | grep $klon | sed -e 's/!.*$//' -e /$klev/d | cut -d: -f3 | sed -e 's/,/ /g'`
292var_2D=`grep -i "$search_str" input | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'`
293if [ "$ncvars" != "" ] ; then
294   var_1D=`b_among_a "$var_1D" "$ncvars"`
295   var_2D=`b_among_a "$var_2D" "$ncvars"`
296fi
297echo Variables in and inout : $varin0
298echo 1D variables "(all)" : $var_1D
299echo 2D variables "(all)" : $var_2D
300echo 1D variables "intent(inout)" : $var_1D_inout
301echo 2D variables "intent(inout)" : $var_2D_inout
302echo local 1D variables : $var_1D_noarg
303echo local 2D variables : $var_2D_noarg
304
305#-----------------------------------------------------------------------------
306# Ecriture de la routine d'appel a la parametrisation en mode replay
307#-----------------------------------------------------------------------------
308
309if [ $nconly = false ] ; then
310
311cat > call_param_replay.F90 <<eod
312subroutine call_param_replay($klon,$klev)
313USE IOIPSL, ONLY : getin
314IMPLICIT NONE
315integer :: ifin,irec,it,rec_length_replay=0,replay_irec0=1,replay_nt=1000
316eod
317grep 'intent.*::' input | sed -e 's/ //g' -e 's/,intent(.*[nt])//'>> call_param_replay.F90
318# duplicating declaration for inout variables
319
320for var in $varinout0 ; do
321    sed -e 's/::/ :: /' -e 's/,/ , /g' -e 's/$/ /' input | grep 'intent.*inout.*::.* '$var' ' | sed -e 's/ //g' -e 's/,intent(.*[nt])//' | sed -e 's/::.*$/, allocatable, save :: '$var'_Replay0/' | sed -e 's/'$klon'/:/' -e 's/'$klev'/:/' >> call_param_replay.F90
322done
323# Initalisation, shared with dump_param1.sh
324dump_param_open "in" $varin0 >> call_param_replay.F90
325for var in $varinout0 ; do
326    sed -e 's/::/ :: /' -e 's/,/ , /g' -e 's/$/ /' input | grep 'intent.*inout.*::.* '$var' ' | sed -e 's/intent(.*t)//' -e 's/^.*(/allocate('$var'_Replay0(/' -e 's/).*$/))/' >> call_param_replay.F90
327done
328
329cat >> call_param_replay.F90 <<eod
330call getin('replay_nt',replay_nt)
331call getin('replay_irec0',replay_irec0)
332do it=1,replay_nt
333   if (replay_irec0>=0) then
334       irec=replay_irec0+it-1
335   else
336       irec=-replay_irec0
337   endif
338   print*,'Time step',it,', reading record',irec,'in dump_param.bin'
339   read(82,rec=irec,iostat=ifin) $varin
340   if (.NOT. ifin == 0 ) stop "Fin du fichier fort.82"
341eod
342
343block_Replay0 "it == 1"          _Replay0   ""       $varinout0 >> call_param_replay.F90
344block_Replay0 "replay_irec0 < 0" ""         _Replay0 $varinout0 >> call_param_replay.F90
345get_subroutine_arg $param $paramfile | sed -e 's/subroutine/   call/' >> call_param_replay.F90
346block_Replay0 "replay_irec0 < 0" _Replay0   ""       $varinout0 >> call_param_replay.F90
347cat >> call_param_replay.F90 <<eod
348enddo
349return
350end
351eod
352
353fi # nconly = false
354
355#-----------------------------------------------------------------------------
356# Creating file dump_${param}_head.h
357#-----------------------------------------------------------------------------
358
359if [ $nconly = false ] ; then
360\rm $paraminc1
361cat> $paraminc1 <<eod
362logical, save :: first_replay=.true.
363integer, save :: rec_length_replay=0,irec=0
364if (first_replay) then
365eod
366dump_param_open out $varin0 >> $paraminc1
367cat>> $paraminc1 <<eod
368first_replay=.false.
369endif
370irec=irec+1
371write(81,rec=irec) $varin
372eod
373iotd_calls 1     in_${prefix} $var_1D_inout >> $paraminc1
374iotd_calls $klev in_${prefix} $var_2D_inout >> $paraminc1
375fi # nconly = false
376
377if [ "`grep $paraminc1 $paramfile`" = "" ] ; then
378   # Not changing $paraminc1 if it is already included in the file
379   # To allow adding new nc outputs in a routine equiped for replay
380   for var in $var_1D_noarg $var_2D_noarg ; do echo $var=0. >> $paraminc1 ; done
381   include_line "include \"$paraminc1\"" $param $paramfile -after_declarations
382fi
383
384#-----------------------------------------------------------------------------
385# Creating file dump_${param}_nc_${prefix}.h
386#-----------------------------------------------------------------------------
387
388\rm $paraminc2
389iotd_calls 1     "${prefix}" $var_1D >> $paraminc2
390iotd_calls $klev "${prefix}" $var_2D >> $paraminc2
391include_line "include \"$paraminc2\"" $param $paramfile "$where"
392 
393#-----------------------------------------------------------------------------
394# dump_ini_module gere l'ecriture des variables d'interface de l'intialisation
395# du module en mode replay
396#-----------------------------------------------------------------------------
397
398if [ $nconly = false ] ; then
399varinmod=`grep -i 'intent.in' $inimod.F90 | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'`
400varinmodv=`echo $varinmod | sed -e 's/ /,/g'`
401cat > $iniinc <<eod
402open(90,file='$inimod.bin',form='unformatted')
403write(90) $varinmodv
404close(90)
405eod
406include_line "include \"$iniinc\"" $paramini $inimod.F90  -before_return
407fi # nconly = false
408
409
410#-----------------------------------------------------------------------------
411# get_ini_module gere l'initialisation du module en mode replay
412#-----------------------------------------------------------------------------
413if [ $nconly = false ] ; then
414cat > get_ini_module.F90 <<eod
415subroutine get_ini_module
416use $inimod
417IMPLICIT NONE
418eod
419grep -i intent.in $inimod.F90  |  tr '[A-Z]' '[a-z]' | sed -e 's/,.*intent.i.*)//' >> get_ini_module.F90
420cat >> get_ini_module.F90 <<eod
421open(90,file='$inimod.bin',form='unformatted')
422read(90) $varinmodv
423close(90)
424eod
425#get_subroutine_arg $paramini $inimod.F90 ; exit
426get_subroutine_arg $paramini $inimod.F90 | sed -e 's/subroutine/call/' >> get_ini_module.F90
427cat >> get_ini_module.F90 <<eod
428return
429end
430eod
431fi # nconly = false
432
433#-----------------------------------------------------------------------------
434# Inclusion de l'ecriture de l'interface de l'initialisation
435#-----------------------------------------------------------------------------
436
437
438#\rm -f tmp input
Note: See TracBrowser for help on using the repository browser.