source: BOL/Replay/replay_equip.sh @ 4432

Last change on this file since 4432 was 4378, checked in by fhourdin, 18 months ago

Modification pour eviter la recompilation

File size: 18.9 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 : 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    : 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   vdif_k) paramini=None ; inimod=None ; klon=ngrid ; klev=nlay ;;
113   thermcell_main|thermcell_plume_6A|thermcell_env|thermcell_height|thermcell_dry|\
114      thermcell_closure|thermcell_height|thermcell_dq|thermcell_flux2|thermcell_down| \
115      thermcell_updown_dq) \
116      paramini=thermcell_ini ; inimod=thermcell_ini_mod ; klon=ngrid ; klev=nlay ;;
117   wake|wake_popdyn_2) paramini=wake_ini ; inimod=wake_ini_mod ; klon=klon ; klev=klev ;;
118   *) echo Cas non prevu ; exit
119esac
120
121replay_comment="replay automatic include"
122paraminc1=dump_replay_${param}_head.h
123paraminc2=dump_replay_${param}_nc_${prefix}.h
124iniinc=dump_replay_ini.h
125paramfile=`grep -i "subro.* ${param}[\ (]" *.F90 | sed -e 's/ //g' | grep "${param}(" | cut -d: -f1`
126echo ===================================================================================
127echo Equiping $param contained in file $paramfile
128if [ `echo ${paramfile} | wc -w` != 1 ] ; then echo file $paramfile multiple  ; $0 -h ; exit ; fi
129
130
131#-----------------------------------------------------------------------------
132# Transformer l'entete d'une subroutine en un call
133#-----------------------------------------------------------------------------
134
135function get_subroutine_arg(){
136   cat $2 | tr '[A-Z]' '[a-z]' > tmp
137   line1=`sed -n -e '/subrou.*'\`echo $1 | tr '[A-Z]' '[a-z]'\`'.*(/=' tmp | head -1 `
138   line2=`tail -n +$line1 tmp | sed -n -e '/)/=' | head -1`
139   tail -n +$line1 tmp | sed -n -e 1,${line2}p
140}
141
142#-----------------------------------------------------------------------------
143function dump_param_open(){
144#-----------------------------------------------------------------------------
145# Opening an direct access file with one record per time-step
146# Each record has the size and contains the arguments in and inout of the
147# routine
148#-----------------------------------------------------------------------------
149inout=$1 ; shift
150case $inout in
151   out) fort=81 ;;
152   in) fort=82
153esac
154echo '! <<< dump_param_open'
155for var in $* ; do echo 'rec_length_replay=rec_length_replay+kind('$var')*size(['$var'])' ; done
156cat <<eod
157open(${fort},file='dump_param_${inout}.bin',form='unformatted',access='direct',recl=rec_length_replay)  ! $replay_comment
158eod
159echo '! dump_param_open >>> '
160}
161
162
163#-----------------------------------------------------------------------------
164function extract_subroutine(){
165#-----------------------------------------------------------------------------
166   # $1 nom de la subroutine
167   # $2 nom du fichier
168   # input <- routine under treatment with small caps only
169   ( cpp $2 2>/dev/null ) | tr '[A-Z]' '[a-z]' > tmp
170   name_min=`echo $1 | tr '[A-Z]' '[a-z]'`
171   line1=`sed -n -e "/subrou.*${name_min}.*(/=" tmp | head -1 `
172   tail -n +$line1 tmp > tmp2
173   line2=`sed -n -e "/[Rr][Ee][Tt][Uu][Rr][Nn]/=" tmp2 | head -1`
174   head -$line2 tmp2  > input
175   \rm -f tmp tmp2
176}
177
178
179#-----------------------------------------------------------------------------
180function include_line(){
181#-----------------------------------------------------------------------------
182   # Including param_dump*.h in the parameterization
183   #set -vx
184   line_to_be_included=$1  ; shift
185   param_=$1 ; shift
186   paramfile_=$1 ; shift
187   name_min=`echo $param_ | tr [A-Z] [a-z]`
188   line_subroutine=`cat $paramfile_ | tr '[A-Z]' '[a-z]' | sed -n -e "/subrou.*${name_min}.*(/=" | head -1 `
189   tail -n +$line_subroutine $paramfile_ > tmp # file starting at the subroutine instruction
190   line_return=`sed -n -e "/[Rr][Ee][Tt][Uu][Rr][Nn]/=" tmp | head -1`
191   head -$line_return tmp > tmp2               # file containing the routine
192   sed -e 's/\!.*$//' tmp2 > tmp3
193   cpp tmp2 > tmp3 2>/dev/null
194   cat tmp3 | tr '[A-Z]' '[a-z]' > tmp2_cpp   # same after cpp filtering
195   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'`"
196   line_last_declaration=`cat tmp2 | tr '[A-Z]' '[a-z]' | sed -n -e "/$last_line_declaration2/="`
197   if [ "$line_last_declaration" = "" ] ; then echo line_last_declaration $line_last_declaration line $last_line_declaration2  ; exit ; fi
198   if (( $# > 0 )) ; then
199      wtype=`echo $1 | awk ' { print $1 } '`
200      case $wtype in
201         -after_declarations)      targeted_line=$line_last_declaration ;;
202         -before_return)           targeted_line=$line_return ;;
203         -before_line|-after_line) linestr=`echo $1 | sed -e "s/$wtype //"` ; targeted_line=`sed -n -e "/$linestr/=" tmp2` ;;
204         *)                  echo Cas non prevu 0 where=$where in inclide_file
205      esac
206      case $wtype in
207         -after_declarations|-after_line)  line0=$(( $line_subroutine - 1 )) ;;
208         -before_return|-before_line)      line0=$(( $line_subroutine - 2 )) ;;
209         *)                  echo Cas non prevu 1 where=$where in inclide_file
210      esac
211      echo Including line $line0 in $paramfile_ the line : $line_to_be_included
212      linebefore_include=$(( $line0 + $targeted_line ))
213     sed -i'' -e $linebefore_include"s/$/\n $line_to_be_included \!  $replay_comment/" $paramfile_ 
214   fi
215}
216
217
218
219
220#-----------------------------------------------------------------------------
221function block_Replay0() {
222#-----------------------------------------------------------------------------
223condition=$1 ; shift
224suf1=$1 ; shift
225suf2=$1 ; shift
226if [ $# -gt 0 ] ; then
227   vars=$*
228   echo '   if ('$condition') then'
229   for var in $vars ; do echo '      '$var$suf1=$var$suf2 ; done
230   echo '   endif'
231fi
232}
233
234#-----------------------------------------------------------------------------
235function iotd_calls(){
236#-----------------------------------------------------------------------------
237    klev_=$1 ; shift
238    pre=$1 ; shift
239    if (( $# >> 0 )) ; then
240       vars=$*
241       for var in $vars ; do
242          echo "call iotd_ecrit_seq('"$pre$var"',$klev_,'"$pre$var in $param"',' ',"$var")"
243       done
244    fi
245}
246         
247#-----------------------------------------------------------------------------
248function b_among_a() {
249#-----------------------------------------------------------------------------
250   a="$1"
251   b="$2"
252   o=""
253   for v in $a ; do
254       for vv in $b ; do
255           if [ "$v" = "$vv" ] ; then o="$o $v" ;  fi
256       done
257   done
258   echo $o
259}
260
261
262#-----------------------------------------------------------------------------
263# On nettoye les inclusions précédente dans les fichiers .F90
264#-----------------------------------------------------------------------------
265
266if [ $nconly = false ] ; then
267   for file in `grep "$replay_comment" *.F90 2> /dev/null | cut -d: -f1` ; do
268      sed -i"" -e "/$replay_comment/d" $file
269   done
270   line=`sed -n -e "/CALL wake_ini/=" physiq_mod.F90 | head -1`
271   sed -i"" -e "${line}s/$/\n   CALL iophys_ini(pdtphys) ! $replay_comment  ! $replay_comment/" physiq_mod.F90
272fi
273
274#-----------------------------------------------------------------------------
275# Analysis of the variables to be stored and there nature
276#-----------------------------------------------------------------------------
277
278extract_subroutine $param $paramfile # -> input file
279varin0=`grep inten.*.in input | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'`
280varinout0=`grep inten.*.inout input | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'`
281varin=`echo $varin0 | sed -e 's/ /,/g' -e "s/,,,/,/g" -e "s/,,/,/g"`
282output=full # Attention, l'option full ne marche pas a cause de tableaux locaux undef
283nvar0D=0 ; nvar1D=0 ; nvar2D=0
284case $output in
285   light) search_str='real.*intent' ;;
286   full) search_str='real'
287esac
288var_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'`
289var_2D_inout=`grep -i "$search_str" input | grep intent.*inout | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'`
290var_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'`
291var_2D_noarg=`grep -i "$search_str" input | sed -e /intent/d | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'`
292var_1D=`grep -i "$search_str" input | grep $klon | sed -e 's/!.*$//' -e /$klev/d | cut -d: -f3 | sed -e 's/,/ /g'`
293var_2D=`grep -i "$search_str" input | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'`
294if [ "$ncvars" != "" ] ; then
295   var_1D=`b_among_a "$var_1D" "$ncvars"`
296   var_2D=`b_among_a "$var_2D" "$ncvars"`
297fi
298echo Variables in and inout : $varin0
299echo 1D variables "(all)" : $var_1D
300echo 2D variables "(all)" : $var_2D
301echo 1D variables "intent(inout)" : $var_1D_inout
302echo 2D variables "intent(inout)" : $var_2D_inout
303echo local 1D variables : $var_1D_noarg
304echo local 2D variables : $var_2D_noarg
305
306#-----------------------------------------------------------------------------
307# Ecriture de la routine d'appel a la parametrisation en mode replay
308#-----------------------------------------------------------------------------
309
310if [ $nconly = false ] ; then
311
312cat > call_param_replay <<eod
313subroutine call_param_replay($klon,$klev)
314USE IOIPSL, ONLY : getin
315IMPLICIT NONE
316integer :: ifin,irec,it,rec_length_replay=0,replay_irec0=1,replay_nt=1000
317eod
318grep 'intent.*::' input | sed -e 's/ //g' -e 's/,intent(.*[nt])//'>> call_param_replay
319# duplicating declaration for inout variables
320
321for var in $varinout0 ; do
322    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
323done
324# Initalisation, shared with dump_param1.sh
325dump_param_open "in" $varin0 >> call_param_replay
326for var in $varinout0 ; do
327    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
328done
329
330cat >> call_param_replay <<eod
331call getin('replay_nt',replay_nt)
332call getin('replay_irec0',replay_irec0)
333do it=1,replay_nt
334   if (replay_irec0>=0) then
335       irec=replay_irec0+it-1
336   else
337       irec=-replay_irec0
338   endif
339   print*,'Time step',it,', reading record',irec,'in dump_param.bin'
340   read(82,rec=irec,iostat=ifin) $varin
341   if (.NOT. ifin == 0 ) stop "Fin du fichier fort.82"
342eod
343
344block_Replay0 "it == 1"          _Replay0   ""       $varinout0 >> call_param_replay
345block_Replay0 "replay_irec0 < 0" ""         _Replay0 $varinout0 >> call_param_replay
346get_subroutine_arg $param $paramfile | sed -e 's/subroutine/   call/' >> call_param_replay
347block_Replay0 "replay_irec0 < 0" _Replay0   ""       $varinout0 >> call_param_replay
348cat >> call_param_replay <<eod
349enddo
350return
351end
352eod
353
354fi # nconly = false
355
356#-----------------------------------------------------------------------------
357# Creating file dump_${param}_head.h
358#-----------------------------------------------------------------------------
359
360if [ $nconly = false ] ; then
361\rm $paraminc1
362cat> $paraminc1 <<eod
363logical, save :: first_replay=.true.
364integer, save :: rec_length_replay=0,irec=0
365if (first_replay) then
366eod
367dump_param_open out $varin0 >> $paraminc1
368cat>> $paraminc1 <<eod
369first_replay=.false.
370endif
371irec=irec+1
372write(81,rec=irec) $varin
373eod
374iotd_calls 1     in_${prefix} $var_1D_inout >> $paraminc1
375iotd_calls $klev in_${prefix} $var_2D_inout >> $paraminc1
376fi # nconly = false
377
378if [ "`grep $paraminc1 $paramfile`" = "" ] ; then
379   # Not changing $paraminc1 if it is already included in the file
380   # To allow adding new nc outputs in a routine equiped for replay
381   for var in $var_1D_noarg $var_2D_noarg ; do echo $var=0. >> $paraminc1 ; done
382   include_line "include \"$paraminc1\"" $param $paramfile -after_declarations
383fi
384
385#-----------------------------------------------------------------------------
386# Creating file dump_${param}_nc_${prefix}.h
387#-----------------------------------------------------------------------------
388
389\rm $paraminc2
390iotd_calls 1     "${prefix}" $var_1D >> $paraminc2
391iotd_calls $klev "${prefix}" $var_2D >> $paraminc2
392include_line "include \"$paraminc2\"" $param $paramfile "$where"
393 
394#-----------------------------------------------------------------------------
395# dump_ini_module gere l'ecriture des variables d'interface de l'intialisation
396# du module en mode replay
397#-----------------------------------------------------------------------------
398
399if [ $nconly = false -a $paramini != None ] ; then
400   varinmod=`grep -i 'intent.in' $inimod.F90 | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'`
401   varinmodv=`echo $varinmod | sed -e 's/ /,/g'`
402   cat > $iniinc <<...eod...............................................
403   open(90,file='$inimod.bin',form='unformatted')
404   write(90) $varinmodv
405   close(90)
406...eod...............................................
407   include_line "include \"$iniinc\"" $paramini $inimod.F90  -before_return
408fi # nconly = false
409
410
411#-----------------------------------------------------------------------------
412# get_ini_module gere l'initialisation du module en mode replay
413#-----------------------------------------------------------------------------
414if [ $nconly = false -a $paramini != None ] ; then
415    cat > get_ini_module <<....eod............................................
416    subroutine get_ini_module
417    use $inimod
418    IMPLICIT NONE
419....eod............................................
420    grep -i intent.in $inimod.F90  |  tr '[A-Z]' '[a-z]' | sed -e 's/,.*intent.i.*)//' >> get_ini_module
421    cat >> get_ini_module <<....eod...........................................
422    open(90,file='$inimod.bin',form='unformatted')
423    read(90) $varinmodv
424    close(90)
425....eod...........................................
426    #get_subroutine_arg $paramini $inimod.F90 ; exit
427    get_subroutine_arg $paramini $inimod.F90 | sed -e 's/subroutine/call/' >> get_ini_module
428    cat >> get_ini_module <<....eod...........................................
429    return
430    end
431....eod...........................................
432fi # nconly = false
433
434#-----------------------------------------------------------------------------
435# Inclusion de l'ecriture de l'interface de l'initialisation
436#-----------------------------------------------------------------------------
437
438if [ $nconly = false ] ; then
439     for file in get_ini_module call_param_replay ; do sed -i'' -e "s/$/                                        \!$replay_comment/"  $file ; done
440     cat get_ini_module >> $inimod.F90
441     cat call_param_replay >> $paramfile
442fi
443
444#\rm -f tmp input
Note: See TracBrowser for help on using the repository browser.