source: BOL/replay_equip.sh @ 4392

Last change on this file since 4392 was 4336, checked in by fhourdin, 2 years ago

Import initial des outils Replay

File size: 13.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.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
76param=`basename $1 .F90`
77case $param in
78   thermcell_main|thermcell_plume_6A|thermcell_env|thermcell_height|thermcell_dry|\
79      thermcell_closure|thermcell_height|thermcell_dq|thermcell_flux2|thermcell_down) \
80      paramini=thermcell_ini ; inimod=thermcell_ini_mod ; klon=ngrid ; klev=nlay ;;
81   wake|wake_popdyn_2) paramini=wake_ini ; inimod=wake_ini_mod ; klon=klon ; klev=klev ;;
82   *) echo Cas non prevu ; exit
83esac
84
85replay_comment="replay automatic include"
86paraminc1=dump_param1.h
87paraminc2=dump_param2.h
88iniinc=dump_ini.h
89
90#-----------------------------------------------------------------------------
91# Transformer l'entete d'une subroutine en un call
92#-----------------------------------------------------------------------------
93
94function get_subroutine_arg(){
95   cat $2 | tr '[A-Z]' '[a-z]' > tmp
96   line1=`sed -n -e '/subrou.*'\`echo $1 | tr '[A-Z]' '[a-z]'\`'.*(/=' tmp | head -1 `
97   line2=`tail -n +$line1 tmp | sed -n -e '/)/=' | head -1`
98   tail -n +$line1 tmp | sed -n -e 1,${line2}p
99}
100
101#-----------------------------------------------------------------------------
102function dump_param_open(){
103#-----------------------------------------------------------------------------
104# Opening an direct access file with one record per time-step
105# Each record has the size and contains the arguments in and inout of the
106# routine
107#-----------------------------------------------------------------------------
108inout=$1 ; shift
109case $inout in
110   out) fort=81 ;;
111   in) fort=82
112esac
113echo '! <<< dump_param_open'
114for var in $* ; do echo 'rec_length=rec_length+kind('$var')*size(['$var'])' ; done
115cat <<eod
116open(${fort},file='dump_param_${inout}.bin',form='unformatted',access='direct',recl=rec_length)  ! $replay_comment
117eod
118echo '! dump_param_open >>> '
119}
120
121#-----------------------------------------------------------------------------
122function extract_subroutine(){
123#-----------------------------------------------------------------------------
124   # $1 nom de la subroutine
125   # $2 nom du fichier
126   # input <- routine under treatment with small caps only
127   cpp $2 | tr '[A-Z]' '[a-z]' > tmp
128   name_min=`echo $1 | tr '[A-Z]' '[a-z]'`
129   line1=`sed -n -e "/subrou.*${name_min}.*(/=" tmp | head -1 `
130   tail -n +$line1 tmp > tmp2
131   line2=`sed -n -e "/[Rr][Ee][Tt][Uu][Rr][Nn]/=" tmp2 | head -1`
132   head -$line2 tmp2  > input
133   \rm -f tmp tmp2
134}
135
136#-----------------------------------------------------------------------------
137function include_line(){
138#-----------------------------------------------------------------------------
139   # Including param_dump*.h in the parameterization
140   line_to_be_included=$1 
141   param_=$2
142   paramfile_=$3
143   where=$4
144   name_min=`echo $param_ | tr [A-Z] [a-z]`
145   echo $name_min ...
146   line_subroutine=`cat $paramfile_ | tr '[A-Z]' '[a-z]' | sed -n -e "/subrou.*${name_min}.*(/=" | head -1 `
147   echo LINE $line_subroutine
148   tail -n +$line_subroutine $paramfile_ > tmp
149   line_return=`sed -n -e "/[Rr][Ee][Tt][Uu][Rr][Nn]/=" tmp | head -1`
150   line_declarations=`head -$line_return tmp | tr '[A-Z]' '[a-z]' | sed -n -e 's/\!.*$//' -e "/[\ ,]real[\ ,]/=" -e "/[\ ,]integer[\ ,]/=" -e "/[\ ,]logical[\ ,]/=" -e "/[\ ,]character[\ ,]/=" | tail -1` 
151   echo lignes $line_subroutine $line_return $line_declarations
152   case $where in
153      after_declarations) linebefore_include=$(( $(( $line_subroutine + $line_declarations )) -1 )) ;;
154      before_return)      linebefore_include=$(( $(( $line_subroutine + $line_return )) -2 )) ;;
155      *)                  echo Cas non prevu where=$where in inclide_file
156   esac
157   # including lines in revers order
158   sed -i'' -e $linebefore_include"s/$/\n $line_to_be_included \!  $replay_comment/" $paramfile_ 
159}
160
161#-----------------------------------------------------------------------------
162function get_param_file(){
163#-----------------------------------------------------------------------------
164  p=$1
165  grep -i "subro.* $p[\ (]" *.F90 | sed -e 's/ //g' | grep "$p(" | cut -d: -f1
166}
167
168#-----------------------------------------------------------------------------
169function block_Replay0() {
170#-----------------------------------------------------------------------------
171condition=$1 ; shift
172suf1=$1 ; shift
173suf2=$1 ; shift
174if [ $# -gt 0 ] ; then
175   vars=$*
176   echo '   if ('$condition') then'
177   for var in $vars ; do echo '      '$var$suf1=$var$suf2 ; done
178   echo '   endif'
179fi
180}
181
182#-----------------------------------------------------------------------------
183# On nettoye les inclusions précédente dans les fichiers .F90
184#-----------------------------------------------------------------------------
185
186for file in `grep "$replay_comment" *.F90 2> /dev/null | cut -d: -f1` ; do
187   sed -i"" -e "/$replay_comment/d" $file
188done
189line=`sed -n -e "/CALL wake_ini/=" physiq_mod.F90 | head -1`
190sed -i"" -e "${line}s/$/\n   CALL iophys_ini(pdtphys) ! $replay_comment  ! $replay_comment/" physiq_mod.F90
191
192#-----------------------------------------------------------------------------
193# Modifying the parameterization routine
194#-----------------------------------------------------------------------------
195
196paramfile=`get_param_file $param`
197echo La parametrisation $param est contenue dans le fichier $paramfile
198if [ `echo ${paramfile} | wc -w` != 1 ] ; then echo file $paramfile multiple  exit ; fi
199extract_subroutine $param $paramfile
200
201#-----------------------------------------------------------------------------
202# Liste des variables d'intent in pour stokage
203#-----------------------------------------------------------------------------
204
205varin0=`grep inten.*.in input | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'`
206varinout0=`grep inten.*.inout input | sed -e '/\!.*$/d' | cut -d: -f3 | sed -e 's/,/ /g'`
207varin=`echo $varin0 | sed -e 's/ /,/g' -e "s/,,,/,/g" -e "s/,,/,/g"`
208echo varin $varin0 
209output=full # Attention, l'option full ne marche pas a cause de tableaux locaux undef
210nvar0D=0 ; nvar1D=0 ; nvar2D=0
211case $output in
212   light) search_str='real.*intent' ;;
213   full) search_str='real'
214esac
215var_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'`
216var_2D_noarg=`grep -i "$search_str" input | sed -e /intent/d | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'`
217var_1D=`grep -i "$search_str" input | grep $klon | sed -e 's/!.*$//' -e /$klev/d | cut -d: -f3 | sed -e 's/,/ /g'`
218var_2D=`grep -i "$search_str" input | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'`
219echo varin  : $varin
220echo var_1D_noarg : $var_1D_noarg
221echo var_2D_noarg : $var_2D_noarg
222echo var_1D : $var_1D
223echo var_2D : $var_2D
224
225#-----------------------------------------------------------------------------
226# Ecriture de la routine d'appel a la parametrisation en mode replay
227#-----------------------------------------------------------------------------
228
229cat > call_param_replay.F90 <<eod
230subroutine call_param_replay($klon,$klev)
231USE IOIPSL, ONLY : getin
232IMPLICIT NONE
233integer :: ifin,irec,it,rec_length=0,replay_irec0=1,replay_nt=1000
234eod
235grep 'intent.*::' input | sed -e 's/ //g' -e 's/,intent(.*[nt])//'>> call_param_replay.F90
236# duplicating declaration for inout variables
237for var in $varinout0 ; do
238    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
239done
240# Initalisation, shared with dump_param1.sh
241dump_param_open "in" $varin0 >> call_param_replay.F90
242for var in $varinout0 ; do
243    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
244done
245
246cat >> call_param_replay.F90 <<eod
247call getin('replay_nt',replay_nt)
248call getin('replay_irec0',replay_irec0)
249do it=1,replay_nt
250   if (replay_irec0>=0) then
251       irec=replay_irec0+it-1
252   else
253       irec=-replay_irec0
254   endif
255   print*,'Time step',it,', reading record',irec,'in dump_param.bin'
256   read(82,rec=irec,iostat=ifin) $varin
257   if (.NOT. ifin == 0 ) stop "Fin du fichier fort.82"
258eod
259
260block_Replay0 "it == 1"          _Replay0   ""       $varinout0 >> call_param_replay.F90
261block_Replay0 "replay_irec0 < 0" ""         _Replay0 $varinout0 >> call_param_replay.F90
262get_subroutine_arg $param $paramfile | sed -e 's/subroutine/   call/' >> call_param_replay.F90
263block_Replay0 "replay_irec0 < 0" _Replay0   ""       $varinout0 >> call_param_replay.F90
264cat >> call_param_replay.F90 <<eod
265enddo
266return
267end
268eod
269
270
271#-----------------------------------------------------------------------------
272# Creation d'un .h d'ecriture de toutes les variables intent in & out
273#-----------------------------------------------------------------------------
274
275\rm $paraminc1
276cat> $paraminc1 <<eod
277logical, save :: first=.true.
278integer, save :: rec_length=0,irec=0
279if (first) then
280eod
281dump_param_open out $varin0 >> $paraminc1
282cat>> $paraminc1 <<eod
283first=.false.
284endif
285irec=irec+1
286write(81,rec=irec) $varin
287eod
288for var in $var_1D_noarg $var_2D_noarg ; do echo $var=0. >> $paraminc1 ; done
289include_line "include \"$paraminc1\"" $param $paramfile after_declarations
290
291\rm $paraminc2
292for var in $var_1D ; do
293echo "call iotd_ecrit_seq('"$var"',1,'"$var"',' ',"$var")" >> $paraminc2
294done
295for var in $var_2D ; do
296echo "call iotd_ecrit_seq('"$var"',"$klev",'"$var"',' ',"$var")" >> $paraminc2
297done
298include_line "include \"$paraminc2\"" $param $paramfile before_return
299 
300#-----------------------------------------------------------------------------
301# dump_ini_module gere l'ecriture des variables d'interface de l'intialisation
302# du module en mode replay
303#-----------------------------------------------------------------------------
304
305varinmod=`grep -i 'intent.in' $inimod.F90 | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'`
306varinmodv=`echo $varinmod | sed -e 's/ /,/g'`
307cat > $iniinc <<eod
308open(90,file='$inimod.bin',form='unformatted')
309write(90) $varinmodv
310close(90)
311eod
312include_line "include \"$iniinc\"" $paramini $inimod.F90  before_return
313
314
315#-----------------------------------------------------------------------------
316# get_ini_module gere l'initialisation du module en mode replay
317#-----------------------------------------------------------------------------
318
319cat > get_ini_module.F90 <<eod
320subroutine get_ini_module
321use $inimod
322IMPLICIT NONE
323eod
324grep -i intent.in $inimod.F90  |  tr '[A-Z]' '[a-z]' | sed -e 's/,.*intent.i.*)//' >> get_ini_module.F90
325cat >> get_ini_module.F90 <<eod
326open(90,file='$inimod.bin',form='unformatted')
327read(90) $varinmodv
328close(90)
329eod
330#get_subroutine_arg $paramini $inimod.F90 ; exit
331get_subroutine_arg $paramini $inimod.F90 | sed -e 's/subroutine/call/' >> get_ini_module.F90
332cat >> get_ini_module.F90 <<eod
333return
334end
335eod
336
337#-----------------------------------------------------------------------------
338# Inclusion de l'ecriture de l'interface de l'initialisation
339#-----------------------------------------------------------------------------
340
341
342#\rm -f tmp input
Note: See TracBrowser for help on using the repository browser.