#!/bin/bash #============================================================================= # 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 fonction 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 # ou intent out. # 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" de la routine d'initialisation et de la routine # de calcul. # # # En pratique : # ------------- # # Le script est commandé par les variables suivantes # param=wake # nom de la subroutine (à l'interireur du fichier) # 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 4 fichiers # * dump_param.h : écriture de l'interface "in" de param (dump_param.bin fort.82) # * 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. # * test en 3D. # * Initialisation plus simple de la routine getin_p # * Des choix sur la facon de controler l'initialisation et le pb des getin # * Modifier la compilation du 1D pour pouvoir compiler lmdz1d et replay1d # * Comprendre pourquoi le replay de wake ne semble pas donner une convegence # numerique avec la version initiale # * L'identification des variables intent in & out pour l'ecriture dans .h # va sans doute foirer si plusieurs routines dans le même fichier. # On pourrait d'ailleurs sortir toutes les variables locales également. # En option par exemple # * Corriger create_make_gcm (pour le main) et makelmdz (pour les checks # sur la necessitee d'appeler create_make_gcm) # * Mettre en option le fait de pouvoir sortir non seulement toutes # les variables d'interface mais même toutes les variables internes. # #============================================================================= param=$1 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) paramini=wake_ini ; inimod=wake_ini_mod ; klon=klon ; klev=klev ;; *) echo Cas non prevu ; exit esac replay_comment="replay automatic include" #----------------------------------------------------------------------------- # Transformer l'entete d'une subroutine en un call #----------------------------------------------------------------------------- function get_subroutine_arg(){ cat $1 | tr '[A-Z]' '[a-z]' > tmp line1=`sed -n -e '/subrou.*(/=' tmp | head -1 ` line2=`tail -n +$line1 tmp | sed -n -e '/)/=' | head -1` tail -n +$line1 tmp | sed -n -e 1,${line2}p } #----------------------------------------------------------------------------- function extract_subroutine(){ #----------------------------------------------------------------------------- # $1 nom de la subroutine # $2 nom du fichier # cat $2 | tr '[A-Z]' '[a-z]' > tmp 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 \rm -f tmp tmp2 } #----------------------------------------------------------------------------- function get_param_file(){ #----------------------------------------------------------------------------- grep -i "subro.* $1[\ (]" *.F90 | sed -e 's/ //g' | grep "$1(" | cut -d: -f1 } #----------------------------------------------------------------------------- # Identification et passage à la casse du bas pour du fichier contenant la param #----------------------------------------------------------------------------- paramfile=`get_param_file $param` echo La parametrisation $param est contenue dans le fichier $paramfile if [ `echo ${paramfile} | wc -w` != 1 ] ; then exit ; fi extract_subroutine $param $paramfile > input #----------------------------------------------------------------------------- # Liste des variables d'intent in pour stokage #----------------------------------------------------------------------------- varin0=`grep inten.*.in input | sed -e '/\!.*$/d' | cut -d: -f3 | sed -e 's/,/ /g'` echo varin0 $varin0 varin=`echo $varin0 | sed -e 's/ /,/g' -e "s/,,,/,/g" -e "s/,,/,/g"` echo varin $varin 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=`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 : $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 cat >> call_param_replay.F90 <> call_param_replay.F90 echo return >> call_param_replay.F90 echo end >> call_param_replay.F90 #----------------------------------------------------------------------------- # Creation d'un .h d'ecriture de toutes les variables intent in & out #----------------------------------------------------------------------------- paraminc=dump_param.h cat > $paraminc <> $paraminc done for var in $var_2D ; do echo "call iotd_ecrit_seq('"$var"',"$klev",'"$var"',' ',"$var")" >> $paraminc done #----------------------------------------------------------------------------- # 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 > dump_ini.h < get_ini_module.F90 <> get_ini_module.F90 cat >> get_ini_module.F90 <> get_ini_module.F90 cat >> get_ini_module.F90 < /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` cp physiq_mod.F90 physiq_mod.$$ sed -i"" -e "${line}s/$/\n CALL iophys_ini(pdtphys) ! $replay_comment\n open(81,file='dump_param.bin',form='unformatted') ! $replay_comment/" physiq_mod.F90 #----------------------------------------------------------------------------- # Inclusion d'un include dans la parametrisation #----------------------------------------------------------------------------- line=`sed -n -e "/^.*[Rr][Ee][Tt][Uu][Rr][Nn].*$/=" $paramfile | head -1` sed -i"" -e "${line}s/^.*$/ include \"$paraminc\" ! $replay_comment \n RETURN/" $paramfile #----------------------------------------------------------------------------- # Inclusion de l'ecriture de l'interface de l'initialisation #----------------------------------------------------------------------------- sed -i'' -e "s/^.*[Rr][Ee][Tt][Uu][Rr][Nn].*$/include \"dump_ini.h\" ! $replay_comment \n RETURN/" $inimod.F90 #\rm -f tmp input