source: trunk/LMDZ.GENERIC/libf/aeronostd/calchim_asis.F90 @ 3233

Last change on this file since 3233 was 3155, checked in by yjaziri, 19 months ago

PCM Generic:

correction error commit 3131 in writting output escape

YJ

  • Property svn:executable set to *
File size: 20.9 KB
Line 
1      subroutine calchim_asis(ngrid,nlayer,nq,                              &
2                         ptimestep,pplay,pplev,pt,pdt,dist_sol,mu0,fract,   &
3                         zzlev,zzlay,zday,pq,pdq,dqchim,dqschim,            &
4                         tauref,co2ice,                                     &
5                         pu,pdu,pv,pdv,surfdust,surfice,icount,zdtchim)
6
7      use tracer_h, only: mmol, noms, nesp, is_chim
8
9      use conc_mod, only: mmean ! mean molecular mass of the atmosphere
10      USE comcstfi_mod
11      use callkeys_mod
12      use time_phylmdz_mod, only: ecritphy, iphysiq ! output rate set by ecritphy
13      use types_asis,       only: v_phot_3d, jlabel, nb_phot_hv_max
14      use chimiedata_h
15      use radcommon_h,      only: glat
16      use wstats_mod, only: wstats
17
18      implicit none
19
20!=======================================================================
21!
22!   subject:
23!   --------
24!
25!  Prepare the call for the photochemical module, and send back the
26!  tendencies from photochemistry in the chemical species mass mixing ratios
27!
28!   Author:   Sebastien Lebonnois (08/11/2002)
29!   -------
30!    update 12/06/2003 for water ice clouds and compatibility with dust
31!    update 07/2003 for coupling with thermosphere (Monica Angelats-i-Coll)
32!    update 03/05/2005 cosmetic changes (Franck Lefevre)
33!    update sept. 2008 identify tracers by their names (Ehouarn Millour)
34!    update 05/12/2011 synchronize with latest version of chemistry (Franck Lefevre)
35!    update 16/03/2012 optimization (Franck Lefevre)
36!    update 11/12/2013 optimization (Franck Lefevre)
37!    update 20/10/2017 adapted to LMDZ GENERIC+cosmetic changes (Benjamin Charnay)
38!    update 06/03/2021 generic tracer/network + photolysis online (Yassin Jaziri)
39!
40!   Arguments:
41!   ----------
42!
43!  Input:
44!
45!    ptimestep                  timestep (s)
46!    pplay(ngrid,nlayer)    Pressure at the middle of the layers (Pa)
47!    pplev(ngrid,nlayer+1)  Intermediate pressure levels (Pa)
48!    pt(ngrid,nlayer)       Temperature (K)
49!    pdt(ngrid,nlayer)      Temperature tendency (K)
50!    pu(ngrid,nlayer)       u component of the wind (ms-1)
51!    pdu(ngrid,nlayer)      u component tendency (K)
52!    pv(ngrid,nlayer)       v component of the wind (ms-1)
53!    pdv(ngrid,nlayer)      v component tendency (K)
54!    dist_sol                   distance of the sun (AU)
55!    mu0(ngrid)               cos of solar zenith angle (=1 when sun at zenith)
56!    fract(ngrid)           day fraction (for diurnal=false)
57!    pq(ngrid,nlayer,nq)  Advected fields, ie chemical species here
58!    pdq(ngrid,nlayer,nq) Previous tendencies on pq
59!    tauref(ngrid)            Optical depth at 7 hPa
60!    co2ice(ngrid)            co2 ice surface layer (kg.m-2)
61!    surfdust(ngrid,nlayer) dust surface area (m2/m3)
62!    surfice(ngrid,nlayer)  ice surface area (m2/m3)
63!
64!  Output:
65!
66!    dqchim(ngrid,nlayer,nesp)   ! tendencies on pq due to chemistry
67!    dqschim(ngrid,nesp)         ! tendencies on qsurf
68!
69!=======================================================================
70
71!     input:
72
73      integer,intent(in) :: ngrid    ! number of atmospheric columns
74      integer,intent(in) :: nlayer   ! number of atmospheric layers
75      integer,intent(in) :: nq       ! number of tracers
76      real :: ptimestep
77      real :: pplay(ngrid,nlayer)    ! pressure at the middle of the layers
78      real :: zzlay(ngrid,nlayer)    ! altitude at the middle of the layers
79      real :: pplev(ngrid,nlayer+1)  ! intermediate pressure levels
80      real :: zzlev(ngrid,nlayer+1)  ! altitude at layer boundaries
81      real :: pt(ngrid,nlayer)       ! temperature
82      real :: pdt(ngrid,nlayer)      ! temperature tendency
83      real :: pu(ngrid,nlayer)       ! u component of the wind (m.s-1)
84      real :: pdu(ngrid,nlayer)      ! u component tendency
85      real :: pv(ngrid,nlayer)       ! v component of the wind (m.s-1)
86      real :: pdv(ngrid,nlayer)      ! v component tendency
87      real :: dist_sol               ! distance of the sun (AU)
88      real :: mu0(ngrid)             ! cos of solar zenith angle (=1 when sun at zenith)
89      real :: pq(ngrid,nlayer,nq)    ! tracers mass mixing ratio
90      real :: pdq(ngrid,nlayer,nq)   ! previous tendencies
91      real :: zday                   ! date (time since Ls=0, in martian days)
92      real :: tauref(ngrid)          ! optical depth at 7 hPa
93      real :: co2ice(ngrid)          ! co2 ice surface layer (kg.m-2)
94      real :: surfdust(ngrid,nlayer) ! dust surface area (m2/m3)
95      real :: surfice(ngrid,nlayer)  !  ice surface area (m2/m3)
96
97!     output:
98
99      real :: dqchim(ngrid,nlayer,nesp)   ! tendencies on pq due to chemistry
100      real :: dqschim(ngrid,nesp)         ! tendencies on qsurf
101
102!     local variables:
103
104      integer :: iloc(1)                  ! index of major species
105      integer :: ig,l,i,iq,iqmax,iesp
106      integer :: foundswitch, lswitch     ! to switch between photochem and thermochem ? (YJ)
107      integer,save :: chemthermod
108
109      real    :: zq(ngrid,nlayer,nesp) ! pq+pdq*ptimestep before chemistry
110                                       ! new mole fraction after
111      real    :: zt(ngrid,nlayer)      ! temperature
112      real    :: zu(ngrid,nlayer)      ! u component of the wind
113      real    :: zv(ngrid,nlayer)      ! v component of the wind
114      real    :: taucol                ! optical depth at 7 hPa
115      real    :: xmmol(nlayer,nesp)    ! mmol/mmean but only for chemical species
116 
117      logical,save :: firstcall = .true.
118
119!     for each column of atmosphere:
120
121      real :: zpress(nlayer)       ! Pressure (mbar)
122      real :: zdens(nlayer)        ! Density  (cm-3)
123      real :: ztemp(nlayer)        ! Temperature (K)
124      real :: zlocal(nlayer)       ! Altitude (km)
125      real :: zycol(nlayer,nesp)   ! Composition (mole fractions)
126      real :: zmmean(nlayer)       ! Mean molecular mass (g.mole-1)
127      real :: szacol               ! Solar zenith angle
128      real :: fract(ngrid)         ! day fraction
129      real :: fractcol             ! day fraction
130      real :: surfice1d(nlayer)    ! Ice surface area (cm2/cm3)
131      real :: surfdust1d(nlayer)   ! Dust surface area (cm2/cm3)
132
133      integer :: iter(nlayer)      !  Number of chemical iterations
134                                   !  within one physical timestep
135      integer :: icount
136!     for output:
137
138      logical :: output              ! to issue calls to writediagfi and stats
139      parameter (output = .true.)
140      real :: iter_3d(ngrid,nlayer)  ! Number of chemical iterations
141                                     !  within one physical timestep
142      integer           ::  ierr
143      real              ::  zdtchim(ngrid,nlayer)    ! temperature modification by chemistry
144      real              ::  dEzchim(ngrid,nlayer)    ! energy modification by chemistry
145      real              ::  zdtchim_output(ngrid)    ! flux modification by chemistry in W.m-2
146
147!=======================================================================
148!     initialization of the chemistry (first call only)
149!=======================================================================
150
151      if (firstcall) then
152
153!! Moved to routine indice in photochemistry_asis
154!! because nb_phot_hv_max value needed in order
155!! to choose if we call read_phototable or not.
156!! A cleaner solution need to be find.
157!         if (photochem .and. .not. jonline) then
158!           print*,'calchim: Read photolysis lookup table'
159!           call read_phototable
160!         end if
161
162         if (.not.allocated(SF_mode))       allocate(SF_mode(nesp))
163         if (.not.allocated(SF_value))      allocate(SF_value(nesp))
164         if (.not.allocated(prod_rate))     allocate(prod_rate(nesp))
165         if (.not.allocated(surface_flux))  allocate(surface_flux(ngrid,nesp))
166         if (.not.allocated(surface_flux2)) allocate(surface_flux2(ngrid,nesp))
167         if (.not.allocated(escape))        allocate(escape(ngrid,nesp))
168         if (.not.allocated(chemnoms))      allocate(chemnoms(nesp))
169
170         surface_flux(:,:)  = 0.
171         surface_flux2(:,:) = 0.
172         escape(:,:)        = 0.
173         SF_mode(:)         = 2
174         SF_value(:)        = 0.
175         prod_rate(:)       = 0.
176         iter_3d(:,:)       = 0.
177         iter(:)            = 0.
178
179         call ini_tracchim
180
181         ! Sanity check mmol /= 0. in chemistry
182         do iq = 1,nq
183            if (is_chim(iq).eq.1 .and. mmol(iq).eq.0.) then
184               write(*,*) 'Error in calchim:'
185               write(*,*) 'Mmol cannot be equal to 0 for chemical species'
186               stop
187            end if
188         end do
189
190         firstcall = .false.
191      end if ! if (firstcall)
192
193! Initializations
194
195      zycol(:,:)    = 0.
196      dqchim(:,:,:) = 0.
197      dqschim(:,:)  = 0.
198
199!=======================================================================
200!     loop over grid
201!=======================================================================
202
203      do ig = 1,ngrid
204         
205         foundswitch = 0
206         do l = 1,nlayer
207            iesp = 0
208            do iq = 1,nq
209               if (is_chim(iq).eq.1) then
210                  iesp = iesp + 1
211                  zq(ig,l,iesp) = pq(ig,l,iq) + pdq(ig,l,iq)*ptimestep
212                  xmmol(l,iesp) = mmol(iq)/mmean(ig,l)
213                  zycol(l,iesp) = zq(ig,l,iesp)/xmmol(l,iesp)
214               end if
215            end do
216
217            zt(ig,l)  = pt(ig,l) + pdt(ig,l)*ptimestep
218            zu(ig,l)  = pu(ig,l) + pdu(ig,l)*ptimestep
219            zv(ig,l)  = pv(ig,l) + pdv(ig,l)*ptimestep
220            zpress(l) = pplay(ig,l)/100.
221            ztemp(l)  = zt(ig,l)
222            zdens(l)  = zpress(l)/(kb*1.e4*ztemp(l))
223            zlocal(l) = zzlay(ig,l)/1000.
224            zmmean(l) = mmean(ig,l)
225
226!           surfdust1d and surfice1d: conversion from m2/m3 to cm2/cm3
227
228            surfdust1d(l) = surfdust(ig,l)*1.e-2
229            surfice1d(l)  = surfice(ig,l)*1.e-2
230
231!           search for switch index between regions
232
233!            if (photochem .and. thermochem) then
234!               if (foundswitch == 0 .and. pplay(ig,l) < 1.e-1) then
235!                  lswitch = l
236!                  foundswitch = 1
237!               end if
238!            end if
239            if (.not. photochem) then
240               lswitch = 22
241            end if
242!            if (.not. thermochem) then
243               lswitch = min(50,nlayer+1)
244!            end if
245
246         end do ! of do l=1,nlayer
247
248         szacol   = acos(mu0(ig))*180./pi
249         taucol   = tauref(ig)*(700./610.)  ! provisoire en attente de nouveau jmars
250         fractcol = fract(ig)
251
252!=======================================================================
253!     call chemical subroutines
254!=======================================================================
255
256!        chemistry in lower atmosphere
257
258!         if (photochem) then
259
260            call photochemistry_asis(nlayer,ngrid,                         &
261                                ig,lswitch,zycol,szacol,fractcol,ptimestep,&
262                                zpress,zlocal,ztemp,zdens,zmmean,dist_sol, &
263                                surfdust1d,surfice1d,taucol,iter,zdtchim(ig,:))
264
265            ! diagnostic photochemical heating
266            zdtchim_output(ig) = 0.
267            do l = 1,nlayer
268              dEzchim(ig,l) = zdtchim(ig,l)*cpp*(pplev(ig,l) - pplev(ig,l+1))/glat(ig)
269              zdtchim_output(ig) = zdtchim_output(ig) + zdtchim(ig,l)*cpp*(pplev(ig,l) - pplev(ig,l+1))/glat(ig)
270            end do
271
272            do l = 1,nlayer
273               iter_3d(ig,l) = iter(l)
274            end do
275
276!        chemistry in upper atmosphere
277       
278!         if (thermochem) then
279!            call chemthermos(ig,nlayer,lswitch,chemthermod,zycol,ztemp,&
280!                             zdens,zpress,zlocal,szacol,ptimestep,zday)
281!         end if
282
283!        dry deposition
284
285         if (depos) then
286            call deposition_source(ngrid, nlayer, nq,   &
287                        ig, zzlay, zzlev, zdens, zycol, ptimestep)
288            surface_flux2(ig,:) = surface_flux2(ig,:) + surface_flux(ig,:)
289            if (ngrid==1) then
290              if(mod(icount,ecritphy).eq.0) then
291                surface_flux2(ig,:) = surface_flux2(ig,:)/float(ecritphy)
292              endif
293            else
294              if(mod(icount*iphysiq,ecritphy).eq.0) then
295                surface_flux2(ig,:) = surface_flux2(ig,:)*iphysiq/float(ecritphy)
296              endif
297            endif
298         end if
299
300!=======================================================================
301!     tendencies
302!=======================================================================
303
304!     index of the most abundant species at each level
305
306!         major(:) = maxloc(zycol, dim = 2)
307
308!     tendency for the most abundant species = - sum of others
309
310         do l = 1,nlayer
311            iloc=maxloc(zycol(l,:))
312            iqmax=iloc(1)
313            do iq = 1,nesp
314               if (iq /= iqmax) then
315                  dqchim(ig,l,iq) = (zycol(l,iq)*xmmol(l,iq) - zq(ig,l,iq))/ptimestep
316                  dqchim(ig,l,iq) = max(dqchim(ig,l,iq),-zq(ig,l,iq)/ptimestep)
317                  dqchim(ig,l,iqmax) = dqchim(ig,l,iqmax) - dqchim(ig,l,iq)
318               end if
319            end do
320
321         end do ! of do l = 1,nlayer
322
323
324
325
326
327
328!=======================================================================
329!     end of loop over grid
330!=======================================================================
331
332      end do ! of do ig=1,ngridbidon(ig,:) = 1
333
334!=======================================================================
335!     write outputs
336!=======================================================================
337
338! value of parameter 'output' to trigger writting of outputs
339! is set above at the declaration of the variable.
340      if (photochem .and. output) then
341
342            ! photoloysis
343            do i=1,nb_phot_hv_max
344               call wstats(ngrid,trim(jlabel(i,1)),jlabel(i,1),    &
345                                's-1',3,v_phot_3d(1,1,i))
346            end do
347            ! iter
348            call wstats(ngrid,'iter','iterations',  &
349                             ' ',3,iter_3d(1,1))
350            ! phothcemical heating
351            call wstats(ngrid,'zdtchim','dT chim',    &
352                             'K.s-1',3,zdtchim)
353            call wstats(ngrid,'dEzchim','dE chim',    &
354                             'W m-2',3,dEzchim)
355            call wstats(ngrid,"Ezchim","integrated dT chim","W m-2",2,zdtchim_output)
356            ! Mean molecular mass
357            call wstats(ngrid,'mmean','mean molecular mass',       &
358                           'g.mole-1',3,mmean(1,1))
359            ! Chemical tendencies
360            do iesp=1,nesp
361               call wstats(ngrid,trim(chemnoms(iesp))//'_dq',trim(chemnoms(iesp))//'_dq',    &
362                               'kg/kg s^-1',3,dqchim(1,1,iesp) )
363            end do
364            if (depos) then
365               ! Surface fluxes and escape
366               do iesp=1,nesp
367                  call wstats(ngrid,trim(chemnoms(iesp))//'_flux_mean',trim(chemnoms(iesp))//' mean flux',    &
368                               'molecule.m-2.s-1',2,surface_flux2(1,indexchim(trim(chemnoms(iesp)))))
369                  call wstats(ngrid,trim(chemnoms(iesp))//'_flux',trim(chemnoms(iesp))//' flux',    &
370                               'molecule.m-2.s-1',2,surface_flux(1,indexchim(trim(chemnoms(iesp)))))
371                  call wstats(ngrid,trim(chemnoms(iesp))//'_escape',trim(chemnoms(iesp))//' escape',    &
372                               'molecule.m-2.s-1',2,escape(1,indexchim(trim(chemnoms(iesp)))))
373               end do
374            endif ! end depos
375
376         ! photoloysis
377         do i=1,nb_phot_hv_max
378            call writediagfi(ngrid,trim(jlabel(i,1)),jlabel(i,1),    &
379                             's-1',3,v_phot_3d(1,1,i))
380         end do
381         ! iter
382         call writediagfi(ngrid,'iter','iterations',  &
383                          ' ',3,iter_3d(1,1))
384         ! phothcemical heating
385         call writediagfi(ngrid,'zdtchim','dT chim',    &
386                          'K.s-1',3,zdtchim)
387         call writediagfi(ngrid,'dEzchim','dE chim',    &
388                          'W m-2',3,dEzchim)
389         call writediagfi(ngrid,"Ezchim","integrated dT chim","W m-2",2,zdtchim_output)
390         ! Mean molecular mass
391         call writediagfi(ngrid,'mmean','mean molecular mass',       &
392                        'g.mole-1',3,mmean(1,1))
393         ! Chemical tendencies
394         do iesp=1,nesp
395            call writediagfi(ngrid,trim(chemnoms(iesp))//'_dq',trim(chemnoms(iesp))//'_dq',    &
396                            'kg/kg s^-1',3,dqchim(1,1,iesp) )
397         end do
398         if (depos) then
399            ! Surface fluxes and escape
400            do iesp=1,nesp
401               call writediagfi(ngrid,trim(chemnoms(iesp))//'_flux_mean',trim(chemnoms(iesp))//' mean flux',    &
402                            'molecule.m-2.s-1',2,surface_flux2(1,indexchim(trim(chemnoms(iesp)))))
403               call writediagfi(ngrid,trim(chemnoms(iesp))//'_flux',trim(chemnoms(iesp))//' flux',    &
404                            'molecule.m-2.s-1',2,surface_flux(1,indexchim(trim(chemnoms(iesp)))))
405               call writediagfi(ngrid,trim(chemnoms(iesp))//'_escape',trim(chemnoms(iesp))//' escape',    &
406                            'molecule.m-2.s-1',2,escape(1,indexchim(trim(chemnoms(iesp)))))
407            end do
408            ! Restart flux average
409            if (ngrid == 1) then
410               if(mod(icount,ecritphy).eq.0) then
411                  surface_flux2(:,:) = 0.0
412               endif
413            else
414               if(mod(icount*iphysiq,ecritphy).eq.0) then
415                  surface_flux2(:,:) = 0.0
416               endif
417            endif
418         endif ! end depos
419
420      end if ! of if (output)
421
422      return
423
424
425      contains
426
427
428!======================================================================
429
430      subroutine ini_tracchim
431
432!======================================================================
433! YJ Modern tracer.def
434! Get in tracer.def chemical parameters
435!======================================================================
436
437         use chimiedata_h
438         use tracer_h, only:   is_chim
439         implicit none
440
441         ! local
442         character(len=500) :: tracline ! to store a line of text
443         integer            :: nq       ! number of tracers
444         integer            :: iesp, iq
445
446         ! Get nq
447         open(90,file='traceur.def',status='old',form='formatted',iostat=ierr)
448         if (ierr.eq.0) then
449           READ(90,'(A)') tracline
450           IF (trim(tracline).ne.'#ModernTrac-v1') THEN ! Test modern traceur.def
451            READ(tracline,*,iostat=ierr) nq ! Try standard traceur.def
452           ELSE
453              DO
454                READ(90,'(A)',iostat=ierr) tracline
455                IF (ierr.eq.0) THEN
456                  IF (index(tracline,'#').ne.1) THEN ! Allows arbitary number of comments lines in the header
457                    READ(tracline,*,iostat=ierr) nq
458                    EXIT
459                  ENDIF
460                ELSE ! If pb, or if reached EOF without having found number of tracer
461                   write(*,*) "calchim: error reading line of tracers"
462                   write(*,*) "   (first lines of traceur.def) "
463                   stop
464                ENDIF
465              ENDDO
466           ENDIF ! if modern or standard traceur.def
467         else
468            write(*,*) "calchim: error opening traceur.def"
469            stop
470         endif
471
472         ! Get data of tracers
473         iesp = 0
474         do iq=1,nq
475            read(90,'(A)') tracline
476            if (is_chim(iq).eq.1) then
477               iesp = iesp + 1
478               read(tracline,*) chemnoms(iesp)
479               write(*,*)"ini_tracchim: iq=",iq,"noms(iq)=",trim(chemnoms(iesp))
480               if (index(tracline,'SF_mode='    ) /= 0) then
481                  read(tracline(index(tracline,'SF_mode=')+len('SF_mode='):),*) SF_mode(iesp)
482                  write(*,*) ' Parameter value (traceur.def) : SF_mode=', SF_mode(iesp)
483               else
484                  write(*,*) ' Parameter value (default)     : SF_mode=', SF_mode(iesp)
485               end if
486               if (index(tracline,'SF_value='   ) /= 0) then
487                  read(tracline(index(tracline,'SF_value=')+len('SF_value='):),*) SF_value(iesp)
488                  write(*,*) ' Parameter value (traceur.def) : SF_value=', SF_value(iesp)
489               else
490                  write(*,*) ' Parameter value (default)     : SF_value=', SF_value(iesp)
491               end if
492               if (index(tracline,'prod_rate='  ) /= 0) then
493                  read(tracline(index(tracline,'prod_rate=')+len('prod_rate='):),*) prod_rate(iesp)
494                  write(*,*) ' Parameter value (traceur.def) : prod_rate=', prod_rate(iesp)
495               else
496                  write(*,*) ' Parameter value (default)     : prod_rate=', prod_rate(iesp)
497               end if
498               if (index(tracline,'escape='     ) /= 0) then
499                  read(tracline(index(tracline,'escape=')+len('escape='):),*) escape(:,iesp)
500                  write(*,*) ' Parameter value (traceur.def) : escape=', escape(:,iesp)
501               else
502                  write(*,*) ' Parameter value (default)     : escape=', escape(:,iesp)
503               end if
504            end if
505         end do
506
507         close(90)
508
509      end subroutine ini_tracchim
510
511      end subroutine calchim_asis
512
Note: See TracBrowser for help on using the repository browser.