source: LMDZ6/branches/cirrus/libf/dyn3dmem/check_isotopes_loc.F90

Last change on this file was 5203, checked in by Laurent Fairhead, 8 hours ago

Merge with trunk revision 5202 before reintegration to trunk

File size: 8.7 KB
Line 
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, getKey
6#ifdef CPP_IOIPSL
7   USE ioipsl,          ONLY: getin
8#else
9   USE ioipsl_getincom, ONLY: getin
10#endif
11   IMPLICIT NONE
12   include "dimensions.h"
13   REAL,             INTENT(INOUT) :: q(ijb_u:ije_u,llm,nqtot)
14   INTEGER,          INTENT(IN)    :: ijb, ije   !--- Can be local and different from ijb_u,ije_u, for example in qminimum
15   CHARACTER(LEN=*), INTENT(IN)    :: err_msg    !--- Error message to display
16   CHARACTER(LEN=maxlen) :: modname, msg1, nm(2)
17   INTEGER :: ixt, ipha, k, i, iq, iiso, izon, ieau, iqeau, iqpar
18   INTEGER, ALLOCATABLE ::   ix(:)
19   REAL,    ALLOCATABLE, SAVE :: tnat(:)         !--- OpenMP shared variable
20   REAL    :: xtractot, xiiso, deltaD, q1, q2
21   REAL, PARAMETER :: borne     = 1e19,  &
22                      errmax    = 1e-8,  &       !--- Max. absolute error
23                      errmaxrel = 1e-3,  &       !--- Max. relative error
24                      qmin      = 1e-11, &
25                      deltaDmax =1000.0, &
26                      deltaDmin =-999.0, &
27                      ridicule  = 1e-12
28   INTEGER, SAVE :: iso_eau, iso_HDO, iso_O18, iso_O17, iso_HTO
29!$OMP THREADPRIVATE(iso_eau, iso_HDO, iso_O18, iso_O17, iso_HTO)
30   LOGICAL       :: ltnat1
31   LOGICAL, SAVE :: first=.TRUE.
32!$OMP THREADPRIVATE(first)
33
34   modname='check_isotopes'
35   IF(.NOT.isoCheck)    RETURN                   !--- No need to check => finished
36   IF(isoSelect('H2O')) RETURN                   !--- No H2O isotopes group found
37   IF(niso == 0)        RETURN                   !--- No isotopes => finished
38   IF(first) THEN
39!$OMP MASTER
40      ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1)
41      ALLOCATE(tnat(niso))
42      iso_eau = strIdx(isoName,'H216O')
43      iso_O17 = strIdx(isoName,'H217O')
44      iso_O18 = strIdx(isoName,'H218O')
45      iso_HDO = strIdx(isoName,'HDO')
46      iso_HTO = strIdx(isoName,'HTO')
47      IF(ltnat1) THEN
48         tnat(:)=1.0
49      ELSE
50         IF(getKey('tnat', tnat)) CALL abort_gcm(modname, 'missing isotopic parameter', 1)
51      END IF
52!$OMP END MASTER
53!$OMP BARRIER
54      first = .FALSE.
55   END IF
56   CALL msg('31: err_msg='//TRIM(err_msg), modname)
57
58   !--- CHECK FOR NaNs (FOR ALL THE ISOTOPES, INCLUDING GEOGRAPHIC TAGGING TRACERS)
59   modname = 'check_isotopes:iso_verif_noNaN'
60   DO ixt = 1, ntiso
61      DO ipha = 1, nphas
62         iq = iqIsoPha(ixt,ipha)
63!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
64         DO k = 1, llm
65            DO i = ijb, ije
66               IF(ABS(q(i,k,iq)) <= borne) CYCLE
67               WRITE(msg1,'(s,"(",i0,",",i0,",",i0,") = ",ES12.4)')TRIM(isoName(ixt)),i,k,iq,q(i,k,iq)
68               CALL msg(msg1, modname)
69               CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
70            END DO
71         END DO
72!$OMP END DO NOWAIT
73      END DO
74   END DO
75
76   !--- CHECK CONSERVATION (MAIN ISOTOPE AND PARENT CONCENTRATIONS MUST BE EQUAL)
77   modname = 'check_isotopes:iso_verif_egalite'
78   ixt = iso_eau
79   IF(ixt /= 0) THEN
80      DO ipha = 1, nphas
81         iq = iqIsoPha(ixt,ipha)
82         iqpar = tracers(iq)%iqParent
83!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
84         DO k = 1, llm
85            DO i = ijb, ije
86               q1 = q(i,k,iqpar)
87               q2 = q(i,k,iq)
88!--- IMPROVEMENT in case at least one isotope is not negligible compared to the main isotopic form.
89!    This would be probably required to sum from smallest to highest concentrations ; the corresponding
90!    indices vector can be computed once only (in the initializations stage), using mean concentrations.
91!              q2 = SUM(q(i,k,tracers(iqPar)%iqDesc), DIM=3)
92               IF(ABS(q1-q2) <= errmax .OR. ABS(q1-q2)/MAX(MAX(ABS(q1),ABS(q2)),1e-18) <= errmaxrel) THEN
93                  q(i,k,iq) = q1                 !--- Bidouille pour convergence
94!                 q(i,k,tracers(iqPar)%iqDesc) = q(i,k,tracers(iqPar)%iqDesc) * q1 / q2
95                  CYCLE
96               END IF
97               CALL msg('ixt, iq = '//TRIM(strStack(int2str([ixt,iq]))), modname)
98               msg1 = '('//TRIM(strStack(int2str([i,k])))//')'
99               CALL msg(TRIM(tracers(iqpar)%name)//TRIM(msg1)//' = '//TRIM(real2str(q1)), modname)
100               CALL msg(TRIM(tracers(iq   )%name)//TRIM(msg1)//' = '//TRIM(real2str(q2)), modname)
101               CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
102            END DO
103         END DO
104!$OMP END DO NOWAIT
105      END DO
106   END IF
107
108   !--- CHECK DELTA ANOMALIES
109   modname = 'check_isotopes:iso_verif_aberrant'
110   ix = [ iso_HDO  ,   iso_O18 ]
111   nm = ['deltaD  ', 'deltaO18']
112   DO iiso = 1, SIZE(ix)
113      ixt = ix(iiso)
114      IF(ixt  == 0) CYCLE
115      DO ipha = 1, nphas
116         iq = iqIsoPha(ixt,ipha)
117         iqpar = tracers(iq)%iqParent
118!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
119         DO k = 1, llm
120            DO i = ijb, ije
121               q1 = q(i,k,iqpar)
122               q2 = q(i,k,iq)
123!--- IMPROVEMENT in case at least one isotope is not negligible compared to the main isotopic form.
124!    This would be probably required to sum from smallest to highest concentrations ; the corresponding
125!    indices vector can be computed once only (in the initializations stage), using mean concentrations.
126!              q2 = SUM(q(i,k,tracers(iqPar)%iqDesc), DIM=3)
127               IF(q2 <= qmin) CYCLE
128               deltaD = (q2/q1/tnat(ixt)-1.)*1000.
129               IF(deltaD <= deltaDmax .AND. deltaD >= deltaDmin) CYCLE
130               CALL msg('ixt, iq = '//TRIM(strStack(int2str([ixt,iq]))), modname)
131               msg1 = '('//TRIM(strStack(int2str([i,k])))//')'
132               CALL msg(TRIM(tracers(iqpar)%name)//TRIM(msg1)//' = '//TRIM(real2str(q1)), modname)
133               CALL msg(TRIM(tracers(iq   )%name)//TRIM(msg1)//' = '//TRIM(real2str(q2)), modname)
134               CALL msg(TRIM(nm(iiso))//TRIM(real2str(deltaD)), modname)
135               CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
136            END DO
137         END DO
138!$OMP END DO NOWAIT
139      END DO
140   END DO
141
142   IF(nzone == 0) RETURN
143
144   !--- CHECK FOR TAGGING TRACERS DELTAD ANOMALIES
145   modname = 'check_isotopes:iso_verif_aberrant'
146   IF(iso_eau /= 0 .AND. iso_HDO /= 0) THEN
147      DO izon = 1, nzone
148         ixt  = itZonIso(izon, iso_HDO)
149         ieau = itZonIso(izon, iso_eau)
150         DO ipha = 1, nphas
151            iq    = iqIsoPha(ixt,  ipha)
152            iqeau = iqIsoPha(ieau, ipha)
153!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
154            DO k = 1, llm
155               DO i = ijb, ije
156                  q1 = q(i,k,iqeau)
157                  q2 = q(i,k,iq)
158                  IF(q2<=qmin) CYCLE
159                  deltaD = (q2/q1/tnat(iso_HDO)-1.)*1000.
160                  IF(deltaD <= deltaDmax .AND. deltaD >= deltaDmin) CYCLE
161                  CALL msg('izon, ipha = '//TRIM(strStack(int2str([izon, ipha]))), modname)
162                  CALL msg( 'ixt, ieau = '//TRIM(strStack(int2str([ ixt, ieau]))), modname)
163                  msg1 = '('//TRIM(strStack(int2str([i,k])))//')'
164                  CALL msg(TRIM(tracers(iqeau)%name)//TRIM(msg1)//' = '//TRIM(real2str(q1)), modname)
165                  CALL msg(TRIM(tracers(iq   )%name)//TRIM(msg1)//' = '//TRIM(real2str(q2)), modname)
166                  CALL msg('deltaD = '//TRIM(real2str(deltaD)), modname)
167                  CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
168               END DO
169            END DO
170!$OMP END DO NOWAIT
171         END DO
172      END DO
173   END IF
174
175   !--- CHECK FOR TAGGING TRACERS CONSERVATION (PARENT AND TAGGING TRACERS SUM OVER ALL REGIONS MUST BE EQUAL)
176   DO iiso = 1, niso
177      DO ipha = 1, nphas
178         iq = iqIsoPha(iiso, ipha)
179!$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
180         DO k = 1, llm
181            DO i = ijb, ije
182               xiiso = q(i,k,iq)
183               xtractot = SUM(q(i, k, iqIsoPha(itZonIso(1:nzone,iiso), ipha)))
184               IF(ABS(xtractot-xiiso) > errmax .AND. ABS(xtractot-xiiso)/MAX(MAX(ABS(xtractot),ABS(xiiso)),1e-18) > errmaxrel) THEN
185                  CALL msg('Error in iso_verif_aberrant trac: '//TRIM(err_msg))
186                  CALL msg('iiso, ipha = '//TRIM(strStack(int2str([iiso, ipha]))), modname)
187                  CALL msg('q('//TRIM(strStack(int2str([i,k])))//',:) = '//TRIM(strStack(real2str(q(i,k,:)))), modname)
188                  CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1)
189               END IF
190               IF(ABS(xtractot) <= ridicule) CYCLE
191               DO izon = 1, nzone
192                  q(i,k,iq) = q(i,k,iq) / xtractot * xiiso !--- Bidouille pour convergence
193               END DO
194            END DO
195         END DO
196!$OMP END DO NOWAIT
197      END DO
198   END DO
199
200END SUBROUTINE check_isotopes
201
Note: See TracBrowser for help on using the repository browser.