Changes between Version 8 and Version 9 of TravailTraceur


Ignore:
Timestamp:
Jan 13, 2020, 6:04:54 PM (4 years ago)
Author:
dcugnet
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • TravailTraceur

    v8 v9  
    166166Ces descripteurs présentent l'avantage de regrouper en une seule variable vectorielle les informations utiles pour tous les traceurs.
    167167
    168  * De nombreuses variables possèdent un pendant isotopique (souvent repéré par un **x** additionnel dans le préfixe) ; les opérations s'appliquant à ces variables comme à leurs descendantes forçent pour l'instant la création explicite de ces descendantes ainsi que la duplication des lignes de code correspondant aux opérations en question.
    169 L'utilisation d'un pointeur semble toute indiquée. Par exemple, pour **q_seri** étendue à ses isotopes, pour l'exemple donné plus haut, il faudrait pouvoir écrire:
     168 * De nombreuses variables possèdent un pendant isotopique (souvent repéré par un **x** additionnel dans le préfixe) ; les opérations s'appliquant à ces variables comme à leurs descendantes forcent pour l'instant la création explicite de ces descendantes ainsi que la duplication des lignes de code correspondant aux opérations en question.
     169L'utilisation d'un pointeur semble toute indiquée. Par exemple, pour **q_seri** (exemple purement illustratif: qx doit être mis à jour en fin de pas de temps, non pas à chaque ajout de tendance comme q_seri: q_seri ne peut donc être un alias de qx, mais doit être sa copie partielle en début de pas de temps !) étendue à ses isotopes, pour l'exemple donné plus haut, il faudrait pouvoir écrire:
    170170{{{
    171171q_seri => qx(:,:,[1,(k,k=10:21)])
    172172}}}
    173 Cette extension de la fonction **aliasTracer()** est hélas illicite en fortran: un pointeur ne peut être associé à des sections non contigües d'un tableau.
    174 Abandonner le classement des traceurs dans **qx** par génération croissante pourrait résoudre le problème, mais rendrait l'organisation bien moins claire (resterait aussi à savoir comment ranger les traceurs de tagging).
     173Cette extension de la fonction **aliasTracer()** est hélas illicite en fortran: un pointeur ne peut être associé à des sections non contigües d'un tableau.\\
     174Abandonner le classement des traceurs dans **qx** par génération croissante pourrait résoudre le problème, mais rendrait l'organisation bien moins claire (resterait aussi à savoir comment ranger les traceurs de tagging).\\
    175175Il semble préférable de se contenter de définir **q_seri** (et les autres variables analogues) sous la forme d'un objet de type dérivé muni d'une composante contenant le vecteur d'indices des traceurs de **qx** requis. Les opérations répétées sur la variable principale et ses variables isotopiques le sont par simple bouclage sur ce vecteur d'indices.
     176
    176177On définit donc le type dérivé suivant:
    177178{{{
    178179TYPE tr2
    179   REAL,   ALLOCATABLE :: v(:,:,:)
     180  CHARACTER(LEN=1)    :: typ
     181  REAL,   POINTER     :: v(:,:)
     182  REAL,   ALLOCATABLE :: f(:,:)
    180183  INTEGER ALLOCATABLE :: iq(:)
    181184END TYPE tr2
    182185}}}
    183 Dans le cas de **q_seri**:
     186Lorsque typ=='a', on se contente d'un alias (POINTER), alors que pour typ=='c', on copie la variable concernée (ALLOCATABLE).\\
     187Dans les deux cas, le contenu est accessible via les composantes out(:)%v.
     188
     189La fonction **defVar** encapsule les opérations nécessaires à la création de l'objet voulu:
     190{{{
     191FUNCTION defVar(name,typ,nGen) RESULT(out)
     192  TYPE(tr2),                 ALLOCATABLE :: out(:)     !--- Output object
     193  CHARACTER(LEN=*),           INTENT(IN) :: name       !--- Tracer name
     194  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: typ        !--- 'a'lias or 'c'opy
     195  INTEGER,          OPTIONAL, INTENT(IN) :: nGen       !--- Number of generations kept
     196  INTEGER              :: iq, ng, k
     197  CHARACTER(LEN=1)     :: tp
     198  LOGICAL, ALLOCATABLE ::  ll(:)
     199  tp = 'c'; IF(PRESENT(typ))  tp = typ
     200  ng =  2 ; IF(PRESENT(nGen)) ng = nGen
     201  ALLOCATE(ll(nqtrue)); ll(idxTracer(name)) = .TRUE.   !--- Main tracer index
     202  DO iq=1,nqtrue                                       !--- Identify the kept tracers
     203    IF(tracers(iq)%igen>ng) EXIT
     204    IF(ll(idxTracer(tracers(iq)%prnt))) ll(iq)=.TRUE.  !--- Tracer "name" is an ancestor
     205  END DO
     206  ALLOCATE(out(COUNT(ll))); out(:)%typ = typ; k = 0
     207  DO iq=1,nqtrue; IF(.NOT.ll(iq)) CYCLE
     208    k = k + 1; out(k)%iq = iq
     209    IF(tp=='p') THEN; out(k)%v => qx(:,:,iq)
     210    ELSE;             out(k)%f =  qx(:,:,iq); out(k)%v => out(k)%f; END IF
     211    k = k+1
     212  END DO
     213END FUNCTION defVar
     214}}}
     215
     216Et pour **q_seri**, la syntaxe se réduit à (par défaut: copie de variables, 2 générations utilisées):
    184217{{{
    185218TYPE(tr2) :: q_seri
    186219q_seri = defVar('H2O-g')
    187220}}}
    188 La fonction **defVar** encapsule les opérations nécessaires:
    189 {{{
    190 TYPE(tr2) FUNCTION defVar(name) RESULT(out)
    191   CHARACTER(LEN=*), INTENT(IN) :: name
    192   INTEGER :: ix, n
    193   ix = idxTracer(name)
    194   out%iq = [ix, tracers(ix)%ichild(:)]
    195   out%v  = [ ( qx(:,:,out%iq(k)), k=1, SIZE(out(:), DIM=1) ) ]
    196 END FUNCTION defVar
    197 }}}
    198 On peut envisager d'ajouter un second argument à defVar: la génération maximale (2 dans l'exemple ci-dessus).
    199 La boucle typique pour une opération agissant sur une grandeur de génération 1 et ses dérivés isotopiques prend alors la forme (exemple pour **q_seri**):
    200 {{{
    201   DO k=1,SIZE(t_seri%iq, DIM=1)
    202     Opérations sur  t_seri%v(:,:,t_seri%iq(k))
     221Si les opérations à pratiquer sur la vapeur et ses descendants sont identiques, la boucle suivante suffit:
     222{{{
     223  DO k=1,SIZE(t_seri, DIM=1)
     224    Opérations sur t_seri(k)%v(:,:)
    203225  END DO
    204226}}}
    205 Si l'objectif est d'agir directement sur des composantes de **qx**, sans création d'une variable spécifique **t_seri%v(:,:,:)**, il suffit de remplacer **t_seri%v(:,:,t_seri%iq(k))** par **qx(:,:,iq(k))**, où **iq(:)** est le vecteur d'undices non encapsulé dans un type dérivé.
     227Les informations des traceurs constituant cet objet sont accessibles via l'indice iq et le descripteur de traceurs tracers(:).\\
     228Par exemple, le nom de la kième composante de **t_seri** est: {{{tracers(t_seri(k)%iq)%name}}}.
    206229
    207230 * Ajout de caractéristiques des isotopes dans le fichier **tracer_*.def** directement, en tant que clefs supplémentaires, accessibles grâce à la routine **getKey()**.
     
    258281}}}
    259282Ça me semble un peu lourd, et on ne sait pas au premier coup d'œil ce qui est vraiment utilisé dans le modèle.
    260 La solution initiale (pas de base de données complète dans tout fichier **tracer_*.def** concernant des paramètres supplémentaires du type **tnat** ou **alpha_ideal**) semble donc préférable.
     283La solution initiale (pas de base de données complète dans tout fichier **tracer_*.def** concernant des paramètres supplémentaires du type **tnat** ou **alpha_ideal**) semble donc préférable.\\
     284=> Avis de Camille: les **tnat** sont des constantes immuables, et les **alpha** ne servent que pour l'initialisation: autant les garder en dur dans le code.\\
     285=> Idée: garder séparément d'infotrac, assez générique, toutes les grandeurs spécifiques. On pourrait donc imaginer un fichier **isotopes_params_mod.F90** où regrouper ces informations (tnat et alpha notamment), ou encore un fichier de paramètres (à lire comme tracers_*.def) qui ne serait pas susceptible d'être modifié.
    261286À discuter.