Changeset 4143 for LMDZ6/trunk/libf/dyn3d/check_isotopes.F90
- Timestamp:
- May 9, 2022, 12:35:40 PM (2 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
LMDZ6/trunk/libf/dyn3d/check_isotopes.F90
r4142 r4143 1 subroutine check_isotopes_seq(q,ip1jmp1,err_msg) 2 USE infotrac, ONLY: nqtot, nqo, niso, ntraciso, nzone, 3 & use_iso, 4 & iqiso, index_trac,indnum_fn_num, tnat 5 implicit none 1 SUBROUTINE check_isotopes_seq(q, ip1jmp1, err_msg) 2 USE strings_mod, ONLY: maxlen, msg, strIdx, strStack, int2str, real2str 3 USE infotrac, ONLY: nqtot, niso, nphas, isotope, isoCheck, iqIsoPha, isoSelect, & 4 ntiso, iH2O, nzone, tracers, isoName, itZonIso, tnat 5 IMPLICIT NONE 6 include "dimensions.h" 7 REAL, INTENT(INOUT) :: q(ip1jmp1,llm,nqtot) 8 INTEGER, INTENT(IN) :: ip1jmp1 9 CHARACTER(LEN=*), INTENT(IN) :: err_msg !--- Error message to display 10 CHARACTER(LEN=maxlen) :: modname, msg1, nm(2) 11 INTEGER :: ixt, ipha, k, i, iq, iiso, izon, ieau, iqeau, iqpar 12 INTEGER, ALLOCATABLE :: ix(:) 13 REAL :: xtractot, xiiso, deltaD, q1, q2 14 REAL, PARAMETER :: borne = 1e19, & 15 errmax = 1e-8, & !--- Max. absolute error 16 errmaxrel = 1e-3, & !--- Max. relative error 17 qmin = 1e-11, & 18 deltaDmax =1000.0, & 19 deltaDmin =-999.0, & 20 ridicule = 1e-12 21 INTEGER, SAVE :: iso_eau, iso_HDO, iso_O18, & 22 iso_O17, iso_HTO 23 LOGICAL, SAVE :: first=.TRUE. 6 24 7 #include "dimensions.h" 25 modname='check_isotopes' 26 IF(.NOT.isoCheck) RETURN !--- No need to check => finished 27 IF(isoSelect('H2O')) RETURN !--- No H2O isotopes group found 28 IF(niso == 0) RETURN !--- No isotopes => finished 29 IF(first) THEN 30 iso_eau = strIdx(isoName,'H2[16]O') 31 iso_HDO = strIdx(isoName,'H[2]HO') 32 iso_O18 = strIdx(isoName,'H2[18]O') 33 iso_O17 = strIdx(isoName,'H2[17]O') 34 iso_HTO = strIdx(isoName,'H[3]HO') 35 first = .FALSE. 36 END IF 37 CALL msg('31: err_msg='//TRIM(err_msg), modname) 8 38 9 ! inputs 10 integer ip1jmp1 11 real q(ip1jmp1,llm,nqtot) 12 character*(*) err_msg ! message d''erreur à afficher 39 !--- CHECK FOR NaNs (FOR ALL THE ISOTOPES, INCLUDING GEOGRAPHIC TAGGING TRACERS) 40 modname = 'check_isotopes:iso_verif_noNaN' 41 DO ixt = 1, ntiso 42 DO ipha = 1, nphas 43 iq = iqIsoPha(ixt,ipha) 44 DO k = 1, llm 45 DO i = 1, ip1jmp1 46 IF(ABS(q(i,k,iq)) < borne) CYCLE 47 WRITE(msg1,'(s,"(",i0,",",i0,",",i0,") = ",ES12.4)')TRIM(isoName(ixt)),i,k,iq,q(i,k,iq) 48 CALL msg(msg1, modname) 49 CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1) 50 END DO 51 END DO 52 END DO 53 END DO 13 54 14 ! locals 15 integer ixt,phase,k,i,iq,iiso,izone,ieau,iqeau 16 real xtractot,xiiso 17 real borne 18 real qmin 19 real errmax ! erreur maximale en absolu. 20 real errmaxrel ! erreur maximale en relatif autorisée 21 real deltaDmax,deltaDmin 22 real ridicule 23 parameter (borne=1e19) 24 parameter (errmax=1e-8) 25 parameter (errmaxrel=1e-3) 26 parameter (qmin=1e-11) 27 parameter (deltaDmax=1000.0,deltaDmin=-999.0) 28 parameter (ridicule=1e-12) 29 real deltaD 55 !--- CHECK CONSERVATION (MAIN ISOTOPE AND PARENT CONCENTRATIONS MUST BE EQUAL) 56 modname = 'check_isotopes:iso_verif_egalite' 57 ixt = iso_eau 58 IF(ixt /= 0) THEN 59 DO ipha = 1, nphas 60 iq = iqIsoPha(ixt,ipha) 61 iqpar = tracers(iq)%iqParent 62 DO k = 1, llm 63 DO i = 1, ip1jmp1 64 q1 = q(i,k,iqpar) 65 q2 = q(i,k,iq) 66 !--- IMPROVEMENT in case at least one isotope is not negligible compared to the main isotopic form. 67 ! This would be probably required to sum from smallest to highest concentrations ; the corresponding 68 ! indices vector can be computed once only (in the initializations stage), using mean concentrations. 69 ! q2 = SUM(q(i,k,tracers(iqPar)%iqDesc), DIM=3) 70 IF(ABS(q1-q2) <= errmax .OR. ABS(q1-q2)/MAX(MAX(ABS(q1),ABS(q2)),1e-18) <= errmaxrel) THEN 71 q(i,k,iq) = q1 !--- Bidouille pour convergence 72 ! q(i,k,tracers(iqPar)%iqDesc) = q(i,k,tracers(iqPar)%iqDesc) * q1 / q2 73 CYCLE 74 END IF 75 CALL msg('ixt, iq = '//TRIM(strStack(int2str([ixt,iq]))), modname) 76 msg1 = '('//TRIM(strStack(int2str([i,k])))//')' 77 CALL msg(TRIM(tracers(iqpar)%name)//TRIM(msg1)//' = '//TRIM(real2str(q1)), modname) 78 CALL msg(TRIM(tracers(iq )%name)//TRIM(msg1)//' = '//TRIM(real2str(q2)), modname) 79 CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1) 80 END DO 81 END DO 82 END DO 83 END IF 30 84 31 if (niso > 0) then 85 !--- CHECK DELTA ANOMALIES 86 modname = 'check_isotopes:iso_verif_aberrant' 87 ix = [ iso_HDO , iso_O18 ] 88 nm = ['deltaD ', 'deltaO18'] 89 DO iiso = 1, SIZE(ix) 90 ixt = ix(iiso) 91 IF(ixt == 0) CYCLE 92 DO ipha = 1, nphas 93 iq = iqIsoPha(ixt,ipha) 94 iqpar = tracers(iq)%iqParent 95 DO k = 1, llm 96 DO i = 1, ip1jmp1 97 q1 = q(i,k,iqpar) 98 q2 = q(i,k,iq) 99 !--- IMPROVEMENT in case at least one isotope is not negligible compared to the main isotopic form. 100 ! This would be probably required to sum from smallest to highest concentrations ; the corresponding 101 ! indices vector can be computed once only (in the initializations stage), using mean concentrations. 102 ! q2 = SUM(q(i,k,tracers(iqPar)%iqDesc), DIM=3) 103 IF(q2 <= qmin) CYCLE 104 deltaD = (q2/q1/tnat(ixt)-1.)*1000. 105 IF(deltaD <= deltaDmax .AND. deltaD >= deltaDmin) CYCLE 106 CALL msg('ixt, iq = '//TRIM(strStack(int2str([ixt,iq]))), modname) 107 msg1 = '('//TRIM(strStack(int2str([i,k])))//')' 108 CALL msg(TRIM(tracers(iqpar)%name)//TRIM(msg1)//' = '//TRIM(real2str(q1)), modname) 109 CALL msg(TRIM(tracers(iq )%name)//TRIM(msg1)//' = '//TRIM(real2str(q2)), modname) 110 CALL msg(TRIM(nm(iiso))//TRIM(real2str(deltaD)), modname) 111 CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1) 112 END DO 113 END DO 114 END DO 115 END DO 32 116 33 write(*,*) 'check_isotopes 31: err_msg=',err_msg 34 ! verifier que rien n'est NaN 35 do ixt=1,ntraciso 36 do phase=1,nqo 37 iq=iqiso(ixt,phase) 38 do k=1,llm 39 DO i = 1,ip1jmp1 40 if ((q(i,k,iq).gt.-borne).and. 41 : (q(i,k,iq).lt.borne)) then 42 else !if ((x(ixt,i,j).gt.-borne).and. 43 write(*,*) 'erreur detectee par iso_verif_noNaN:' 44 write(*,*) err_msg 45 write(*,*) 'q,i,k,iq=',q(i,k,iq),i,k,iq 46 write(*,*) 'borne=',borne 47 call abort_gcm('check_isotopes_loc','plantage iso',0) 48 endif !if ((x(ixt,i,j).gt.-borne).and. 49 enddo !DO i = 1,ip1jmp1 50 enddo !do k=1,llm 51 enddo !do phase=1,nqo 52 enddo !do ixt=1,ntraciso 117 IF(nzone == 0) RETURN 53 118 54 !write(*,*) 'check_isotopes 52' 55 ! verifier que l'eau normale est OK 56 if (use_iso(1)) then 57 ixt=indnum_fn_num(1) 58 do phase=1,nqo 59 iq=iqiso(ixt,phase) 60 do k=1,llm 61 DO i = 1,ip1jmp1 62 if ((abs(q(i,k,phase)-q(i,k,iq)).gt.errmax).and. 63 : (abs((q(i,k,phase)-q(i,k,iq))/ 64 : max(max(abs(q(i,k,phase)),abs(q(i,k,iq))),1e-18)) 65 : .gt.errmaxrel)) then 66 write(*,*) 'erreur detectee par iso_verif_egalite:' 67 write(*,*) err_msg 68 write(*,*) 'ixt,phase=',ixt,phase 69 write(*,*) 'q,iq,i,k=',q(i,k,iq),iq,i,k 70 write(*,*) 'q(i,k,phase)=',q(i,k,phase) 71 call abort_gcm('check_isotopes_loc','plantage iso',0) 72 endif !if ((abs(q(i,k,phase)-q(i,k,iq)).gt.errmax).and. 73 ! bidouille pour éviter divergence: 74 q(i,k,iq)= q(i,k,phase) 75 enddo ! DO i = 1,ip1jmp1 76 enddo !do k=1,llm 77 enddo ! do phase=1,nqo 78 endif !if (use_iso(1)) then 79 80 !write(*,*) 'check_isotopes 78' 81 ! verifier que HDO est raisonable 82 if (use_iso(2)) then 83 ixt=indnum_fn_num(2) 84 do phase=1,nqo 85 iq=iqiso(ixt,phase) 86 do k=1,llm 87 DO i = 1,ip1jmp1 88 if (q(i,k,iq).gt.qmin) then 89 deltaD=(q(i,k,iq)/q(i,k,phase)/tnat(2)-1)*1000 90 if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then 91 write(*,*) 'erreur detectee par iso_verif_aberrant:' 92 write(*,*) err_msg 93 write(*,*) 'ixt,phase=',ixt,phase 94 write(*,*) 'q,iq,i,k,=',q(i,k,iq),iq,i,k 95 write(*,*) 'q=',q(i,k,:) 96 write(*,*) 'deltaD=',deltaD 97 call abort_gcm('check_isotopes_loc','plantage iso',0) 98 endif !if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then 99 endif !if (q(i,k,iq).gt.qmin) then 100 enddo !DO i = 1,ip1jmp1 101 enddo !do k=1,llm 102 enddo ! do phase=1,nqo 103 endif !if (use_iso(2)) then 119 !--- CHECK FOR TAGGING TRACERS DELTAD ANOMALIES 120 modname = 'check_isotopes:iso_verif_aberrant' 121 IF(iso_eau /= 0 .AND. iso_HDO /= 0) THEN 122 DO izon = 1, nzone 123 ixt = itZonIso(izon, iso_HDO) 124 ieau = itZonIso(izon, iso_eau) 125 DO ipha = 1, nphas 126 iq = iqIsoPha(ixt, ipha) 127 iqeau = iqIsoPha(ieau, ipha) 128 DO k = 1, llm 129 DO i = 1, ip1jmp1 130 q1 = q(i,k,iqeau) 131 q2 = q(i,k,iq) 132 IF(q2<=qmin) CYCLE 133 deltaD = (q2/q1/tnat(iso_HDO)-1.)*1000. 134 IF(deltaD <= deltaDmax .AND. deltaD >= deltaDmin) CYCLE 135 CALL msg('izon, ipha = '//TRIM(strStack(int2str([izon, ipha]))), modname) 136 CALL msg( 'ixt, ieau = '//TRIM(strStack(int2str([ ixt, ieau]))), modname) 137 msg1 = '('//TRIM(strStack(int2str([i,k])))//')' 138 CALL msg(TRIM(tracers(iqeau)%name)//TRIM(msg1)//' = '//TRIM(real2str(q1)), modname) 139 CALL msg(TRIM(tracers(iq )%name)//TRIM(msg1)//' = '//TRIM(real2str(q2)), modname) 140 CALL msg('deltaD = '//TRIM(real2str(deltaD)), modname) 141 CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1) 142 END DO 143 END DO 144 END DO 145 END DO 146 END IF 104 147 105 !write(*,*) 'check_isotopes 103' 106 ! verifier que O18 est raisonable 107 if (use_iso(3)) then 108 ixt=indnum_fn_num(3) 109 do phase=1,nqo 110 iq=iqiso(ixt,phase) 111 do k=1,llm 112 DO i = 1,ip1jmp1 113 if (q(i,k,iq).gt.qmin) then 114 deltaD=(q(i,k,iq)/q(i,k,phase)/tnat(3)-1)*1000 115 if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then 116 write(*,*) 'erreur detectee iso_verif_aberrant O18:' 117 write(*,*) err_msg 118 write(*,*) 'ixt,phase=',ixt,phase 119 write(*,*) 'q,iq,i,k,=',q(i,k,phase),iq,i,k 120 write(*,*) 'xt=',q(i,k,:) 121 write(*,*) 'deltaO18=',deltaD 122 call abort_gcm('check_isotopes_loc','plantage iso',0) 123 endif !if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then 124 endif !if (q(i,k,iq).gt.qmin) then 125 enddo !DO i = 1,ip1jmp1 126 enddo !do k=1,llm 127 enddo ! do phase=1,nqo 128 endif !if (use_iso(2)) then 148 !--- CHECK FOR TAGGING TRACERS CONSERVATION (PARENT AND TAGGING TRACERS SUM OVER ALL REGIONS MUST BE EQUAL) 149 DO iiso = 1, niso 150 DO ipha = 1, nphas 151 iq = iqIsoPha(iiso, ipha) 152 DO k = 1, llm 153 DO i = 1, ip1jmp1 154 xiiso = q(i,k,iq) 155 xtractot = SUM(q(i, k, iqIsoPha(itZonIso(1:nzone,iiso), ipha))) 156 IF(ABS(xtractot-xiiso) > errmax .AND. ABS(xtractot-xiiso)/MAX(MAX(ABS(xtractot),ABS(xiiso)),1e-18) > errmaxrel) THEN 157 CALL msg('Error in iso_verif_aberrant trac: '//TRIM(err_msg)) 158 CALL msg('iiso, ipha = '//TRIM(strStack(int2str([iiso, ipha]))), modname) 159 CALL msg('q('//TRIM(strStack(int2str([i,k])))//',:) = '//TRIM(strStack(real2str(q(i,k,:)))), modname) 160 CALL abort_gcm(modname, 'Error with isotopes: '//TRIM(err_msg), 1) 161 END IF 162 IF(ABS(xtractot) <= ridicule) CYCLE 163 DO izon = 1, nzone 164 q(i,k,iq) = q(i,k,iq) / xtractot * xiiso !--- Bidouille pour convergence 165 END DO 166 END DO 167 END DO 168 END DO 169 END DO 129 170 171 END SUBROUTINE check_isotopes_seq 130 172 131 !write(*,*) 'check_isotopes 129'132 if (nzone > 0) then133 134 if (use_iso(2).and.use_iso(1)) then135 do izone=1,nzone136 ixt=index_trac(izone,indnum_fn_num(2))137 ieau=index_trac(izone,indnum_fn_num(1))138 do phase=1,nqo139 iq=iqiso(ixt,phase)140 iqeau=iqiso(ieau,phase)141 do k=1,llm142 DO i = 1,ip1jmp1143 if (q(i,k,iq).gt.qmin) then144 deltaD=(q(i,k,iq)/q(i,k,iqeau)/tnat(2)-1)*1000145 if ((deltaD.gt.deltaDmax).or.146 & (deltaD.lt.deltaDmin)) then147 write(*,*) 'erreur dans iso_verif_aberrant trac:'148 write(*,*) err_msg149 write(*,*) 'izone,phase=',izone,phase150 write(*,*) 'ixt,ieau=',ixt,ieau151 write(*,*) 'q,iq,i,k,=',q(i,k,iq),iq,i,k152 write(*,*) 'deltaD=',deltaD153 call abort_gcm('check_isotopes_loc','plantage iso',0)154 endif !if ((deltaD.gt.deltaDmax).or.155 endif !if (q(i,k,iq).gt.qmin) then156 enddo !DO i = 1,ip1jmp1157 enddo ! do k=1,llm158 enddo ! do phase=1,nqo159 enddo !do izone=1,nzone160 endif !if (use_iso(2).and.use_iso(1)) then161 162 do iiso=1,niso163 do phase=1,nqo164 iq=iqiso(iiso,phase)165 do k=1,llm166 DO i = 1,ip1jmp1167 xtractot=0.0168 xiiso=q(i,k,iq)169 do izone=1,nzone170 iq=iqiso(index_trac(izone,iiso),phase)171 xtractot=xtractot+ q(i,k,iq)172 enddo !do izone=1,ntraceurs_zone173 if ((abs(xtractot-xiiso).gt.errmax).and.174 : (abs(xtractot-xiiso)/175 : max(max(abs(xtractot),abs(xiiso)),1e-18)176 : .gt.errmaxrel)) then177 write(*,*) 'erreur detectee par iso_verif_traceurs:'178 write(*,*) err_msg179 write(*,*) 'iiso,phase=',iiso,phase180 write(*,*) 'i,k,=',i,k181 write(*,*) 'q(i,k,:)=',q(i,k,:)182 call abort_gcm('check_isotopes_loc','plantage iso',0)183 endif !if ((abs(q(i,k,phase)-q(i,k,iq)).gt.errmax).and.184 185 ! bidouille pour éviter divergence:186 if (abs(xtractot).gt.ridicule) then187 do izone=1,nzone188 ixt=index_trac(izone,iiso)189 q(i,k,iq)=q(i,k,iq)/xtractot*xiiso190 enddo !do izone=1,nzone191 endif !if ((abs(xtractot).gt.ridicule) then192 enddo !DO i = 1,ip1jmp1193 enddo !do k=1,llm194 enddo !do phase=1,nqo195 enddo !do iiso=1,niso196 197 endif !if (nzone > 0)198 199 endif ! if (niso > 0)200 !write(*,*) 'check_isotopes 198'201 202 end203
Note: See TracChangeset
for help on using the changeset viewer.