Ignore:
Timestamp:
May 9, 2022, 12:35:40 PM (2 years ago)
Author:
dcugnet
Message:
  • Some variables are renamed or replaced by direct equivalents:
    • iso_indnum -> tracers(:)%iso_iName
    • niso_possibles -> niso
    • iqiso -> iqIsoPha ; index_trac -> itZonIso
    • ok_iso_verif -> isoCheck
    • ntraceurs_zone -> nzone ; ntraciso -> ntiso
    • qperemin -> min_qparent ; masseqmin -> min_qmass ; ratiomin -> min_ratio
  • Some renamed variables are only aliased with the older name (using USE <module>, ONLY: <oldName> => <newName>) in routines where they are repeated many times.
  • Few hard-coded indexes are now computed (examples: ilic, iso, ivap, irneb, iq_vap, iq_liq, iso_H2O, iso_HDO, iso_HTO, iso_O17, iso_O18).
  • The IF(isoCheck) test is now embedded in the check_isotopes_seq and check_isotopes_loc routines (lighter calling).
File:
1 moved

Legend:

Unmodified
Added
Removed
  • LMDZ6/trunk/libf/dyn3dmem/check_isotopes_loc.F90

    r4142 r4143  
    1         subroutine check_isotopes(q,ijb,ije,err_msg)
    2         USE infotrac, ONLY: nqtot, nqo, niso, ntraciso, nzone,
    3      &                use_iso, ntraceurs_zone,
    4      &                iqiso, indnum_fn_num, index_trac, tnat
    5         USE parallel_lmdz
    6         implicit none
     1SUBROUTINE check_isotopes(q, ijb, ije, err_msg)
     2   USE parallel_lmdz
     3   USE strings_mod, ONLY: maxlen, msg, strIdx, strStack, int2str, real2str
     4   USE infotrac,    ONLY: nqtot, niso, nphas, isotope, isoCheck, iqIsoPha, isoSelect, &
     5                          ntiso, iH2O, nzone, tracers, isoName,  itZonIso, tnat
     6   IMPLICIT NONE
     7   include "dimensions.h"
     8   REAL,             INTENT(INOUT) :: q(ijb_u:ije_u,llm,nqtot)
     9   INTEGER,          INTENT(IN)    :: ijb, ije   !--- Can be local and different from ijb_u,ije_u, for example in qminimum
     10   CHARACTER(LEN=*), INTENT(IN)    :: err_msg    !--- Error message to display
     11   CHARACTER(LEN=maxlen) :: modname, msg1, nm(2)
     12   INTEGER :: ixt, ipha, k, i, iq, iiso, izon, ieau, iqeau, iqpar
     13   INTEGER, ALLOCATABLE :: ix(:)
     14   REAL    :: xtractot, xiiso, deltaD, q1, q2
     15   REAL, PARAMETER :: borne     = 1e19,  &
     16                      errmax    = 1e-8,  &       !--- Max. absolute error
     17                      errmaxrel = 1e-3,  &       !--- Max. relative error
     18                      qmin      = 1e-11, &
     19                      deltaDmax =1000.0, &
     20                      deltaDmin =-999.0, &
     21                      ridicule  = 1e-12
     22   INTEGER, SAVE :: iso_eau, iso_HDO, iso_O18, & !--- OpenMP shared variables
     23                             iso_O17, iso_HTO
     24   LOGICAL, SAVE :: first=.TRUE.
     25!$OMP THREADPRIVATE(first)
    726
    8 #include "dimensions.h"
     27   modname='check_isotopes'
     28   IF(.NOT.isoCheck)    RETURN                   !--- No need to check => finished
     29   IF(isoSelect('H2O')) RETURN                   !--- No H2O isotopes group found
     30   IF(niso == 0)        RETURN                   !--- No isotopes => finished
     31   IF(first) THEN
     32!$OMP MASTER
     33      iso_eau = strIdx(isoName,'H2[16]O')
     34      iso_HDO = strIdx(isoName,'H[2]HO')
     35      iso_O18 = strIdx(isoName,'H2[18]O')
     36      iso_O17 = strIdx(isoName,'H2[17]O')
     37      iso_HTO = strIdx(isoName,'H[3]HO')
     38!$OMP END MASTER
     39!$OMP BARRIER
     40      first = .FALSE.
     41   END IF
     42   CALL msg('31: err_msg='//TRIM(err_msg), modname)
    943
    10         ! inputs
    11         integer ijb,ije ! peut être local et différent de ijb_u,ije_u, ex: dans qminimum
    12         real q(ijb_u:ije_u,llm,nqtot)
    13         character*(*) err_msg ! message d''erreur à afficher
     44   !--- CHECK FOR NaNs (FOR ALL THE ISOTOPES, INCLUDING GEOGRAPHIC TAGGING TRACERS)
     45   modname = 'check_isotopes:iso_verif_noNaN'
     46   DO ixt = 1, ntiso
     47      DO ipha = 1, nphas
     48         iq = iqIsoPha(ixt,ipha)
     49!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
     50         DO k = 1, llm
     51            DO i = ijb, ije
     52               IF(ABS(q(i,k,iq))<=borne) CYCLE
     53               WRITE(msg1,'(s,"(",i0,",",i0,",",i0,") = ",ES12.4)')TRIM(isoName(ixt)),i,k,iq,q(i,k,iq)
     54               CALL msg(msg1, modname)
     55               CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
     56            END DO
     57         END DO
     58!$OMP END DO NOWAIT
     59      END DO
     60   END DO
    1461
    15         ! locals
    16         integer ixt,phase,k,i,iq,iiso,izone,ieau,iqeau
    17         real xtractot,xiiso
    18         real borne
    19         real qmin
    20         real errmax ! erreur maximale en absolu.
    21         real errmaxrel ! erreur maximale en relatif autorisée
    22         real deltaDmax,deltaDmin
    23         real ridicule
    24         parameter (borne=1e19)
    25         parameter (errmax=1e-8)
    26         parameter (errmaxrel=1e-3)
    27         parameter (qmin=1e-11)
    28         parameter (deltaDmax=1000.0,deltaDmin=-999.0)
    29         parameter (ridicule=1e-12)
    30         real deltaD
     62   !--- CHECK CONSERVATION (MAIN ISOTOPE AND PARENT CONCENTRATIONS MUST BE EQUAL)
     63   modname = 'check_isotopes:iso_verif_egalite'
     64   ixt = iso_eau
     65   IF(ixt /= 0) THEN
     66      DO ipha = 1, nphas
     67         iq = iqIsoPha(ixt,ipha)
     68         iqpar = tracers(iq)%iqParent
     69!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
     70         DO k = 1, llm
     71            DO i = ijb, ije
     72               q1 = q(i,k,iqpar)
     73               q2 = q(i,k,iq)
     74!--- IMPROVEMENT in case at least one isotope is not negligible compared to the main isotopic form.
     75!    This would be probably required to sum from smallest to highest concentrations ; the corresponding
     76!    indices vector can be computed once only (in the initializations stage), using mean concentrations.
     77!              q2 = SUM(q(i,k,tracers(iqPar)%iqDesc), DIM=3)
     78               IF(ABS(q1-q2) <= errmax .OR. ABS(q1-q2)/MAX(MAX(ABS(q1),ABS(q2)),1e-18) <= errmaxrel) THEN
     79                  q(i,k,iq) = q1                 !--- Bidouille pour convergence
     80!                 q(i,k,tracers(iqPar)%iqDesc) = q(i,k,tracers(iqPar)%iqDesc) * q1 / q2
     81                  CYCLE
     82               END IF
     83               CALL msg('ixt, iq = '//TRIM(strStack(int2str([ixt,iq]))), modname)
     84               msg1 = '('//TRIM(strStack(int2str([i,k])))//')'
     85               CALL msg(TRIM(tracers(iqpar)%name)//TRIM(msg1)//' = '//TRIM(real2str(q1)), modname)
     86               CALL msg(TRIM(tracers(iq   )%name)//TRIM(msg1)//' = '//TRIM(real2str(q2)), modname)
     87               CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
     88            END DO
     89         END DO
     90!$OMP END DO NOWAIT
     91      END DO
     92   END IF
    3193
    32         if (niso > 0) then
     94   !--- CHECK DELTA ANOMALIES
     95   modname = 'check_isotopes:iso_verif_aberrant'
     96   ix = [ iso_HDO  ,   iso_O18 ]
     97   nm = ['deltaD  ', 'deltaO18']
     98   DO iiso = 1, SIZE(ix)
     99      ixt = ix(iiso)
     100      IF(ixt  == 0) CYCLE
     101      DO ipha = 1, nphas
     102         iq = iqIsoPha(ixt,ipha)
     103         iqpar = tracers(iq)%iqParent
     104!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
     105         DO k = 1, llm
     106            DO i = ijb, ije
     107               q1 = q(i,k,iqpar)
     108               q2 = q(i,k,iq)
     109!--- IMPROVEMENT in case at least one isotope is not negligible compared to the main isotopic form.
     110!    This would be probably required to sum from smallest to highest concentrations ; the corresponding
     111!    indices vector can be computed once only (in the initializations stage), using mean concentrations.
     112!              q2 = SUM(q(i,k,tracers(iqPar)%iqDesc), DIM=3)
     113               IF(q2 <= qmin) CYCLE
     114               deltaD = (q2/q1/tnat(ixt)-1.)*1000.
     115               IF(deltaD <= deltaDmax .AND. deltaD >= deltaDmin) CYCLE
     116               CALL msg('ixt, iq = '//TRIM(strStack(int2str([ixt,iq]))), modname)
     117               msg1 = '('//TRIM(strStack(int2str([i,k])))//')'
     118               CALL msg(TRIM(tracers(iqpar)%name)//TRIM(msg1)//' = '//TRIM(real2str(q1)), modname)
     119               CALL msg(TRIM(tracers(iq   )%name)//TRIM(msg1)//' = '//TRIM(real2str(q2)), modname)
     120               CALL msg(TRIM(nm(iiso))//TRIM(real2str(deltaD)), modname)
     121               CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
     122            END DO
     123         END DO
     124!$OMP END DO NOWAIT
     125      END DO
     126   END DO
    33127
    34 !        write(*,*) 'check_isotopes 31: err_msg=',err_msg
    35         ! verifier que rien n'est NaN
    36         do ixt=1,ntraciso
    37           do phase=1,nqo
    38             iq=iqiso(ixt,phase)
    39 c$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
    40             do k=1,llm
    41               DO i = ijb,ije
    42                 if ((q(i,k,iq).gt.-borne).and.
    43      :            (q(i,k,iq).lt.borne)) then
    44                 else !if ((x(ixt,i,j).gt.-borne).and.
    45                   write(*,*) 'erreur detectee par iso_verif_noNaN:'
    46                   write(*,*) err_msg
    47                   write(*,*) 'q,i,k,iq=',q(i,k,iq),i,k,iq
    48                   write(*,*) 'borne=',borne
    49                   call abort_gcm('check_isotopes_loc','plantage iso',0)
    50                 endif  !if ((x(ixt,i,j).gt.-borne).and.
    51               enddo !DO i = ijb,ije
    52             enddo !do k=1,llm
    53 c$OMP END DO NOWAIT
    54           enddo !do phase=1,nqo
    55         enddo !do ixt=1,ntraciso
     128   IF(nzone == 0) RETURN
    56129
    57 !        write(*,*) 'check_isotopes 52'
    58         ! verifier que l'eau normale est OK
    59         if (use_iso(1)) then
    60           ixt=indnum_fn_num(1)
    61           do phase=1,nqo
    62             iq=iqiso(ixt,phase)
    63 c$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
    64             do k=1,llm
    65             DO i = ijb,ije 
    66               if ((abs(q(i,k,phase)-q(i,k,iq)).gt.errmax).and.
    67      :          (abs((q(i,k,phase)-q(i,k,iq))/
    68      :           max(max(abs(q(i,k,phase)),abs(q(i,k,iq))),1e-18))
    69      :           .gt.errmaxrel)) then
    70                   write(*,*) 'erreur detectee par iso_verif_egalite:'
    71                   write(*,*) err_msg
    72                   write(*,*) 'ixt,phase,ijb=',ixt,phase,ijb
    73                   write(*,*) 'q,iq,i,k=',q(i,k,iq),iq,i,k
    74                   write(*,*) 'q(i,k,phase)=',q(i,k,phase)
    75                   call abort_gcm('check_isotopes_loc','plantage iso',0)
    76               endif !if ((abs(q(i,k,phase)-q(i,k,iq)).gt.errmax).and.
    77               ! bidouille pour éviter divergence:
    78               q(i,k,iq)= q(i,k,phase)
    79             enddo ! DO i = ijb,ije
    80             enddo !do k=1,llm
    81 c$OMP END DO NOWAIT
    82           enddo ! do phase=1,nqo
    83         endif !if (use_iso(1)) then
    84        
    85 !        write(*,*) 'check_isotopes 78'
    86         ! verifier que HDO est raisonable
    87         if (use_iso(2)) then
    88           ixt=indnum_fn_num(2)
    89           do phase=1,nqo
    90             iq=iqiso(ixt,phase)
    91 c$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
    92             do k=1,llm
    93             DO i = ijb,ije
    94             if (q(i,k,iq).gt.qmin) then
    95              deltaD=(q(i,k,iq)/q(i,k,phase)/tnat(2)-1)*1000
    96              if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then
    97                   write(*,*) 'erreur detectee par iso_verif_aberrant:'
    98                   write(*,*) err_msg
    99                   write(*,*) 'ixt,phase=',ixt,phase
    100                   write(*,*) 'q,iq,i,k,=',q(i,k,iq),iq,i,k
    101                   write(*,*) 'q=',q(i,k,:)
    102                   write(*,*) 'deltaD=',deltaD
    103                   call abort_gcm('check_isotopes_loc','plantage iso',0)
    104              endif !if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then
    105             endif !if (q(i,k,iq).gt.qmin) then
    106             enddo !DO i = ijb,ije
    107             enddo !do k=1,llm
    108 c$OMP END DO NOWAIT
    109           enddo ! do phase=1,nqo
    110         endif !if (use_iso(2)) then
     130   !--- CHECK FOR TAGGING TRACERS DELTAD ANOMALIES
     131   modname = 'check_isotopes:iso_verif_aberrant'
     132   IF(iso_eau /= 0 .AND. iso_HDO /= 0) THEN
     133      DO izon = 1, nzone
     134         ixt  = itZonIso(izon, iso_HDO)
     135         ieau = itZonIso(izon, iso_eau)
     136         DO ipha = 1, nphas
     137            iq    = iqIsoPha(ixt,  ipha)
     138            iqeau = iqIsoPha(ieau, ipha)
     139!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
     140            DO k = 1, llm
     141               DO i = ijb, ije
     142                  q1 = q(i,k,iqeau)
     143                  q2 = q(i,k,iq)
     144                  IF(q2<=qmin) CYCLE
     145                  deltaD = (q2/q1/tnat(iso_HDO)-1.)*1000.
     146                  IF(deltaD <= deltaDmax .AND. deltaD >= deltaDmin) CYCLE
     147                  CALL msg('izon, ipha = '//TRIM(strStack(int2str([izon, ipha]))), modname)
     148                  CALL msg( 'ixt, ieau = '//TRIM(strStack(int2str([ ixt, ieau]))), modname)
     149                  msg1 = '('//TRIM(strStack(int2str([i,k])))//')'
     150                  CALL msg(TRIM(tracers(iqeau)%name)//TRIM(msg1)//' = '//TRIM(real2str(q1)), modname)
     151                  CALL msg(TRIM(tracers(iq   )%name)//TRIM(msg1)//' = '//TRIM(real2str(q2)), modname)
     152                  CALL msg('deltaD = '//TRIM(real2str(deltaD)), modname)
     153                  CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
     154               END DO
     155            END DO
     156!$OMP END DO NOWAIT
     157         END DO
     158      END DO
     159   END IF
    111160
    112 !        write(*,*) 'check_isotopes 103'
    113         ! verifier que O18 est raisonable
    114         if (use_iso(3)) then
    115           ixt=indnum_fn_num(3)
    116           do phase=1,nqo
    117             iq=iqiso(ixt,phase)
    118 c$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
    119             do k=1,llm
    120             DO i = ijb,ije
    121             if (q(i,k,iq).gt.qmin) then
    122              deltaD=(q(i,k,iq)/q(i,k,phase)/tnat(3)-1)*1000
    123              if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then
    124                   write(*,*) 'erreur detectee iso_verif_aberrant O18:'
    125                   write(*,*) err_msg
    126                   write(*,*) 'ixt,phase=',ixt,phase
    127                   write(*,*) 'q,iq,i,k,=',q(i,k,phase),iq,i,k
    128                   write(*,*) 'xt=',q(i,k,:)
    129                   write(*,*) 'deltaO18=',deltaD
    130                   call abort_gcm('check_isotopes_loc','plantage iso',0)
    131              endif !if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then
    132             endif !if (q(i,k,iq).gt.qmin) then
    133             enddo !DO i = ijb,ije
    134             enddo !do k=1,llm
    135 c$OMP END DO NOWAIT
    136           enddo ! do phase=1,nqo
    137         endif !if (use_iso(2)) then
     161   !--- CHECK FOR TAGGING TRACERS CONSERVATION (PARENT AND TAGGING TRACERS SUM OVER ALL REGIONS MUST BE EQUAL)
     162   DO iiso = 1, niso
     163      DO ipha = 1, nphas
     164         iq = iqIsoPha(iiso, ipha)
     165!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
     166         DO k = 1, llm
     167            DO i = ijb, ije
     168               xiiso = q(i,k,iq)
     169               xtractot = SUM(q(i, k, iqIsoPha(itZonIso(1:nzone,iiso), ipha)))
     170               IF(ABS(xtractot-xiiso) > errmax .AND. ABS(xtractot-xiiso)/MAX(MAX(ABS(xtractot),ABS(xiiso)),1e-18) > errmaxrel) THEN
     171                  CALL msg('Error in iso_verif_aberrant trac: '//TRIM(err_msg))
     172                  CALL msg('iiso, ipha = '//TRIM(strStack(int2str([iiso, ipha]))), modname)
     173                  CALL msg('q('//TRIM(strStack(int2str([i,k])))//',:) = '//TRIM(strStack(real2str(q(i,k,:)))), modname)
     174                  CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
     175               END IF
     176               IF(ABS(xtractot) <= ridicule) CYCLE
     177               DO izon = 1, nzone
     178                  q(i,k,iq) = q(i,k,iq) / xtractot * xiiso !--- Bidouille pour convergence
     179               END DO
     180            END DO
     181         END DO
     182!$OMP END DO NOWAIT
     183      END DO
     184   END DO
    138185
     186END SUBROUTINE check_isotopes
    139187
    140 !        write(*,*) 'check_isotopes 129'
    141         if (nzone > 0) then
    142 
    143           if (use_iso(2).and.use_iso(1)) then
    144             do izone=1,ntraceurs_zone
    145              ixt=index_trac(izone,indnum_fn_num(2))
    146              ieau=index_trac(izone,indnum_fn_num(1))
    147              do phase=1,nqo
    148                iq=iqiso(ixt,phase)
    149                iqeau=iqiso(ieau,phase)
    150 c$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
    151                do k=1,llm
    152                 DO i = ijb,ije
    153                 if (q(i,k,iq).gt.qmin) then
    154                  deltaD=(q(i,k,iq)/q(i,k,iqeau)/tnat(2)-1)*1000
    155                  if ((deltaD.gt.deltaDmax).or.
    156      &                   (deltaD.lt.deltaDmin)) then
    157                   write(*,*) 'erreur dans iso_verif_aberrant trac:'
    158                   write(*,*) err_msg
    159                   write(*,*) 'izone,phase=',izone,phase
    160                   write(*,*) 'ixt,ieau=',ixt,ieau
    161                   write(*,*) 'q,iq,i,k,=',q(i,k,iq),iq,i,k
    162                   write(*,*) 'deltaD=',deltaD                 
    163                   call abort_gcm('check_isotopes_loc','plantage iso',0)
    164                  endif !if ((deltaD.gt.deltaDmax).or.
    165                 endif !if (q(i,k,iq).gt.qmin) then
    166                 enddo !DO i = ijb,ije
    167                 enddo  ! do k=1,llm
    168 c$OMP END DO NOWAIT
    169               enddo ! do phase=1,nqo   
    170             enddo !do izone=1,ntraceurs_zone
    171           endif !if (use_iso(2).and.use_iso(1)) then
    172 
    173           do iiso=1,niso
    174            do phase=1,nqo
    175               iq=iqiso(iiso,phase)
    176 c$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
    177               do k=1,llm
    178                 DO i = ijb,ije
    179                    xtractot=0.0
    180                    xiiso=q(i,k,iq)
    181                    do izone=1,ntraceurs_zone
    182                       iq=iqiso(index_trac(izone,iiso),phase)
    183                       xtractot=xtractot+ q(i,k,iq)
    184                    enddo !do izone=1,ntraceurs_zone
    185                    if ((abs(xtractot-xiiso).gt.errmax).and.
    186      :                  (abs(xtractot-xiiso)/
    187      :                  max(max(abs(xtractot),abs(xiiso)),1e-18)
    188      :                  .gt.errmaxrel)) then
    189                   write(*,*) 'erreur detectee par iso_verif_traceurs:'
    190                   write(*,*) err_msg
    191                   write(*,*) 'iiso,phase=',iiso,phase
    192                   write(*,*) 'i,k,=',i,k
    193                   write(*,*) 'q(i,k,:)=',q(i,k,:)
    194                   call abort_gcm('check_isotopes_loc','plantage iso',0)
    195                  endif !if ((abs(q(i,k,phase)-q(i,k,iq)).gt.errmax).and.
    196                  
    197                  ! bidouille pour éviter divergence:
    198                  if (abs(xtractot).gt.ridicule) then
    199                    do izone=1,ntraceurs_zone
    200                      ixt=index_trac(izone,iiso)
    201                      q(i,k,iq)=q(i,k,iq)/xtractot*xiiso
    202                    enddo !do izone=1,ntraceurs_zone               
    203                   endif !if ((abs(xtractot).gt.ridicule) then
    204                 enddo !DO i = ijb,ije
    205               enddo !do k=1,llm
    206 c$OMP END DO NOWAIT
    207            enddo !do phase=1,nqo
    208           enddo !do iiso=1,niso
    209 
    210         endif !if (nzone > 0)
    211 
    212         endif ! if (niso > 0)
    213 !        write(*,*) 'check_isotopes 198'
    214        
    215         end
    216 
    217 
Note: See TracChangeset for help on using the changeset viewer.