#!/bin/bash #set -vx #============================================================================= # F. Hourdin : 2022/05/03 # # Objet : # ----- # Script préparant les programes pour rejouer (replay) une paramétrisation # ou un morceau de paramétriation. # # # Applicabilité : # --------------- # Est fait pour rejouer des paramétisation de LMDZ organisées comme # des calcul sur des successions de colonnes indépendantes (boucle # interne en $klon) de $klev niveaux verticaux. # Demande que la paramétrisation répondent aux règles de codage suivantes : # 1) Les routines de calcul et les routines ou fonctions qu'elles appellent # n'ont que deux interfaces : A) les arguments d'entrée # B) le use d'un unique module # Entre autre, les dimensions de la paramétrisation sont passés # en argument, ce qui permet une allocation dynamique implicite # de toutes les variables. # 2) le module d'initialisation doit lui même être initialisé par # une unique routine pilotée entièrement par ses arguments. # 3) Toutes les variables d'interface doivent être déclarées intent in # out, ou inout # On appelera la paramétriation "param" et l'intialisation "param_ini" # mais les noms de fichiers sont en argument dans le script. # # # Principe : # ---------- # Dans une première simulation, on écrit dans un fichier binaire toutes # les variables "intent in/inout" de la routine d'initialisation et de la routine # de calcul. # # # En pratique : # ------------- # # Le script a comme argument le nom de la routine à traiter, nommée $param # Des correpspondances en déduisent : # paramini=wake_ini # nom de la subroutine d'intialisation # inimod= # nom du module contenant $param_ini # klon=klon ; klev=klev # nom des dimensions horiz; vert utilisée # # Le fichier ${paramfile} contenant $param est detecté automatiquement # Le script crée 5 fichiers # * dump_param1.h : écriture de l'interface "in" de param (dump_param.bin fort.82) # * dump_param2.h : écriture des sorties de la routines dans phys.nc # * call_param_replay.F90 : sous programme d'appelle en boucle à la param # * dump_ini_module.F90 : écriture de l'interface "in" de param_ini # * get_ini_module.F90 : lecture de l'interface "in" de param_ini # dans ${param_ini}_mod.bin. # Par ailleurs, un programme replay1d a été ajouté dans phylmd/dyn1d # qui appelle call_param_replay # Le script ajoute par ailleurs quelques lignes dans ${paramfile} et # ${param_ini}.F90 # replay_clean.sh élimine toutes les lignes ajoutées # # # A travailler : # -------------- # * détecter automatiquement le fichier contenant l'intialisation # * détecter automatiquement les dimensions # * avoir un moyen de vérifier si les variables intent in et out sont # bien les bonnes. # * Initialisation plus simple de la routine getin_p # * Des choix sur la facon de controler l'initialisation et le pb des getin # #============================================================================= param=`basename $1 .F90` case $param in thermcell_main|thermcell_plume_6A|thermcell_env|thermcell_height|thermcell_dry|\ thermcell_closure|thermcell_height|thermcell_dq|thermcell_flux2|thermcell_down) \ paramini=thermcell_ini ; inimod=thermcell_ini_mod ; klon=ngrid ; klev=nlay ;; wake|wake_popdyn_2) paramini=wake_ini ; inimod=wake_ini_mod ; klon=klon ; klev=klev ;; *) echo Cas non prevu ; exit esac replay_comment="replay automatic include" paraminc1=dump_param1.h paraminc2=dump_param2.h iniinc=dump_ini.h #----------------------------------------------------------------------------- # Transformer l'entete d'une subroutine en un call #----------------------------------------------------------------------------- function get_subroutine_arg(){ cat $2 | tr '[A-Z]' '[a-z]' > tmp line1=`sed -n -e '/subrou.*'\`echo $1 | tr '[A-Z]' '[a-z]'\`'.*(/=' tmp | head -1 ` line2=`tail -n +$line1 tmp | sed -n -e '/)/=' | head -1` tail -n +$line1 tmp | sed -n -e 1,${line2}p } #----------------------------------------------------------------------------- function dump_param_open(){ #----------------------------------------------------------------------------- # Opening an direct access file with one record per time-step # Each record has the size and contains the arguments in and inout of the # routine #----------------------------------------------------------------------------- inout=$1 ; shift case $inout in out) fort=81 ;; in) fort=82 esac echo '! <<< dump_param_open' for var in $* ; do echo 'rec_length=rec_length+kind('$var')*size(['$var'])' ; done cat <>> ' } #----------------------------------------------------------------------------- function extract_subroutine(){ #----------------------------------------------------------------------------- # $1 nom de la subroutine # $2 nom du fichier # input <- routine under treatment with small caps only cpp $2 | tr '[A-Z]' '[a-z]' > tmp name_min=`echo $1 | tr '[A-Z]' '[a-z]'` line1=`sed -n -e "/subrou.*${name_min}.*(/=" tmp | head -1 ` tail -n +$line1 tmp > tmp2 line2=`sed -n -e "/[Rr][Ee][Tt][Uu][Rr][Nn]/=" tmp2 | head -1` head -$line2 tmp2 > input \rm -f tmp tmp2 } #----------------------------------------------------------------------------- function include_line(){ #----------------------------------------------------------------------------- # Including param_dump*.h in the parameterization line_to_be_included=$1 param_=$2 paramfile_=$3 where=$4 name_min=`echo $param_ | tr [A-Z] [a-z]` echo $name_min ... line_subroutine=`cat $paramfile_ | tr '[A-Z]' '[a-z]' | sed -n -e "/subrou.*${name_min}.*(/=" | head -1 ` echo LINE $line_subroutine tail -n +$line_subroutine $paramfile_ > tmp line_return=`sed -n -e "/[Rr][Ee][Tt][Uu][Rr][Nn]/=" tmp | head -1` 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` echo lignes $line_subroutine $line_return $line_declarations case $where in after_declarations) linebefore_include=$(( $(( $line_subroutine + $line_declarations )) -1 )) ;; before_return) linebefore_include=$(( $(( $line_subroutine + $line_return )) -2 )) ;; *) echo Cas non prevu where=$where in inclide_file esac # including lines in revers order sed -i'' -e $linebefore_include"s/$/\n $line_to_be_included \! $replay_comment/" $paramfile_ } #----------------------------------------------------------------------------- function get_param_file(){ #----------------------------------------------------------------------------- p=$1 grep -i "subro.* $p[\ (]" *.F90 | sed -e 's/ //g' | grep "$p(" | cut -d: -f1 } #----------------------------------------------------------------------------- function block_Replay0() { #----------------------------------------------------------------------------- condition=$1 ; shift suf1=$1 ; shift suf2=$1 ; shift if [ $# -gt 0 ] ; then vars=$* echo ' if ('$condition') then' for var in $vars ; do echo ' '$var$suf1=$var$suf2 ; done echo ' endif' fi } #----------------------------------------------------------------------------- # On nettoye les inclusions précédente dans les fichiers .F90 #----------------------------------------------------------------------------- for file in `grep "$replay_comment" *.F90 2> /dev/null | cut -d: -f1` ; do sed -i"" -e "/$replay_comment/d" $file done line=`sed -n -e "/CALL wake_ini/=" physiq_mod.F90 | head -1` sed -i"" -e "${line}s/$/\n CALL iophys_ini(pdtphys) ! $replay_comment ! $replay_comment/" physiq_mod.F90 #----------------------------------------------------------------------------- # Modifying the parameterization routine #----------------------------------------------------------------------------- paramfile=`get_param_file $param` echo La parametrisation $param est contenue dans le fichier $paramfile if [ `echo ${paramfile} | wc -w` != 1 ] ; then echo file $paramfile multiple exit ; fi extract_subroutine $param $paramfile #----------------------------------------------------------------------------- # Liste des variables d'intent in pour stokage #----------------------------------------------------------------------------- varin0=`grep inten.*.in input | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'` varinout0=`grep inten.*.inout input | sed -e '/\!.*$/d' | cut -d: -f3 | sed -e 's/,/ /g'` varin=`echo $varin0 | sed -e 's/ /,/g' -e "s/,,,/,/g" -e "s/,,/,/g"` echo varin $varin0 output=full # Attention, l'option full ne marche pas a cause de tableaux locaux undef nvar0D=0 ; nvar1D=0 ; nvar2D=0 case $output in light) search_str='real.*intent' ;; full) search_str='real' esac var_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'` var_2D_noarg=`grep -i "$search_str" input | sed -e /intent/d | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'` var_1D=`grep -i "$search_str" input | grep $klon | sed -e 's/!.*$//' -e /$klev/d | cut -d: -f3 | sed -e 's/,/ /g'` var_2D=`grep -i "$search_str" input | grep $klon | grep $klev | cut -d: -f3 | sed -e 's/!.*$//' -e 's/,/ /g'` echo varin : $varin echo var_1D_noarg : $var_1D_noarg echo var_2D_noarg : $var_2D_noarg echo var_1D : $var_1D echo var_2D : $var_2D #----------------------------------------------------------------------------- # Ecriture de la routine d'appel a la parametrisation en mode replay #----------------------------------------------------------------------------- cat > call_param_replay.F90 <> call_param_replay.F90 # duplicating declaration for inout variables for var in $varinout0 ; do 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 done # Initalisation, shared with dump_param1.sh dump_param_open "in" $varin0 >> call_param_replay.F90 for var in $varinout0 ; do 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 done cat >> call_param_replay.F90 <=0) then irec=replay_irec0+it-1 else irec=-replay_irec0 endif print*,'Time step',it,', reading record',irec,'in dump_param.bin' read(82,rec=irec,iostat=ifin) $varin if (.NOT. ifin == 0 ) stop "Fin du fichier fort.82" eod block_Replay0 "it == 1" _Replay0 "" $varinout0 >> call_param_replay.F90 block_Replay0 "replay_irec0 < 0" "" _Replay0 $varinout0 >> call_param_replay.F90 get_subroutine_arg $param $paramfile | sed -e 's/subroutine/ call/' >> call_param_replay.F90 block_Replay0 "replay_irec0 < 0" _Replay0 "" $varinout0 >> call_param_replay.F90 cat >> call_param_replay.F90 < $paraminc1 <> $paraminc1 cat>> $paraminc1 <> $paraminc1 ; done include_line "include \"$paraminc1\"" $param $paramfile after_declarations \rm $paraminc2 for var in $var_1D ; do echo "call iotd_ecrit_seq('"$var"',1,'"$var"',' ',"$var")" >> $paraminc2 done for var in $var_2D ; do echo "call iotd_ecrit_seq('"$var"',"$klev",'"$var"',' ',"$var")" >> $paraminc2 done include_line "include \"$paraminc2\"" $param $paramfile before_return #----------------------------------------------------------------------------- # dump_ini_module gere l'ecriture des variables d'interface de l'intialisation # du module en mode replay #----------------------------------------------------------------------------- varinmod=`grep -i 'intent.in' $inimod.F90 | sed -e 's/\!.*$//' | cut -d: -f3 | sed -e 's/,/ /g'` varinmodv=`echo $varinmod | sed -e 's/ /,/g'` cat > $iniinc < get_ini_module.F90 <> get_ini_module.F90 cat >> get_ini_module.F90 <> get_ini_module.F90 cat >> get_ini_module.F90 <