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

Last change on this file since 3725 was 3725, checked in by emillour, 8 weeks ago

Generic PCM:
Change the way the rate of outputs for diagfi.nc files is specified:
IMPORTANT: Specifying "ecritphy" no longer possible and will trigger an error.
Use "diagfi_output_rate" to specify output rate (in physics steps) instead.
This should makes things (hopefully) clearer for users and also better
enforces a cleaner and clearer separation between dynamics and physics.
EM

  • Property svn:executable set to *
File size: 20.8 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: diagfi_output_rate ! output rate
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,intent(in) :: icount ! physics iteration number
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            call photochemistry_asis(nlayer,ngrid,                         &
259                                ig,lswitch,zycol,szacol,fractcol,ptimestep,&
260                                zpress,zlocal,ztemp,zdens,zmmean,dist_sol, &
261                                surfdust1d,surfice1d,taucol,iter,zdtchim(ig,:))
262
263            ! diagnostic photochemical heating
264            zdtchim_output(ig) = 0.
265            do l = 1,nlayer
266              dEzchim(ig,l) = zdtchim(ig,l)*cpp*(pplev(ig,l) - pplev(ig,l+1))/glat(ig)
267              zdtchim_output(ig) = zdtchim_output(ig) + zdtchim(ig,l)*cpp*(pplev(ig,l) - pplev(ig,l+1))/glat(ig)
268            end do
269
270            do l = 1,nlayer
271               iter_3d(ig,l) = iter(l)
272            end do
273
274!        chemistry in upper atmosphere
275       
276!         if (thermochem) then
277!            call chemthermos(ig,nlayer,lswitch,chemthermod,zycol,ztemp,&
278!                             zdens,zpress,zlocal,szacol,ptimestep,zday)
279!         end if
280
281!        dry deposition
282
283         if (depos) then
284            call deposition_source(ngrid, nlayer, nq,   &
285                        ig, zzlay, zzlev, zdens, zycol, ptimestep)
286            surface_flux2(ig,:) = surface_flux2(ig,:) + surface_flux(ig,:)
287            if(mod(icount,diagfi_output_rate).eq.0) then
288              !note that surface_flux2(:,:) is reset every diagfi_output_rate
289              surface_flux2(ig,:) = surface_flux2(ig,:)/float(diagfi_output_rate)
290            endif
291         end if ! of if (depos)
292
293!=======================================================================
294!     tendencies
295!=======================================================================
296
297!     index of the most abundant species at each level
298
299!         major(:) = maxloc(zycol, dim = 2)
300
301!     tendency for the most abundant species = - sum of others
302
303         do l = 1,nlayer
304            iloc=maxloc(zycol(l,:))
305            iqmax=iloc(1)
306            do iq = 1,nesp
307               if (iq /= iqmax) then
308                  dqchim(ig,l,iq) = (zycol(l,iq)*xmmol(l,iq) - zq(ig,l,iq))/ptimestep
309                  dqchim(ig,l,iq) = max(dqchim(ig,l,iq),-zq(ig,l,iq)/ptimestep)
310                  dqchim(ig,l,iqmax) = dqchim(ig,l,iqmax) - dqchim(ig,l,iq)
311               end if
312            end do
313
314         end do ! of do l = 1,nlayer
315
316
317
318
319
320
321!=======================================================================
322!     end of loop over grid
323!=======================================================================
324
325      end do ! of do ig=1,ngridbidon(ig,:) = 1
326
327!=======================================================================
328!     write outputs
329!=======================================================================
330
331! value of parameter 'output' to trigger writting of outputs
332! is set above at the declaration of the variable.
333      if (output) then
334
335            ! photoloysis
336            do i=1,nb_phot_hv_max
337               call wstats(ngrid,trim(jlabel(i,1)),jlabel(i,1),    &
338                                's-1',3,v_phot_3d(1,1,i))
339            end do
340            ! iter
341            call wstats(ngrid,'iter','iterations',  &
342                             ' ',3,iter_3d(1,1))
343            ! phothcemical heating
344            call wstats(ngrid,'zdtchim','dT chim',    &
345                             'K.s-1',3,zdtchim)
346            call wstats(ngrid,'dEzchim','dE chim',    &
347                             'W m-2',3,dEzchim)
348            call wstats(ngrid,"Ezchim","integrated dT chim","W m-2",2,zdtchim_output)
349            ! Mean molecular mass
350            call wstats(ngrid,'mmean','mean molecular mass',       &
351                           'g.mole-1',3,mmean(1,1))
352            ! Chemical tendencies
353            do iesp=1,nesp
354               call wstats(ngrid,trim(chemnoms(iesp))//'_dq',trim(chemnoms(iesp))//'_dq',    &
355                               'kg/kg s^-1',3,dqchim(1,1,iesp) )
356            end do
357            if (depos) then
358               ! Surface fluxes and escape
359               do iesp=1,nesp
360                  call wstats(ngrid,trim(chemnoms(iesp))//'_flux_mean',trim(chemnoms(iesp))//' mean flux',    &
361                               'molecule.m-2.s-1',2,surface_flux2(1,indexchim(trim(chemnoms(iesp)))))
362                  call wstats(ngrid,trim(chemnoms(iesp))//'_flux',trim(chemnoms(iesp))//' flux',    &
363                               'molecule.m-2.s-1',2,surface_flux(1,indexchim(trim(chemnoms(iesp)))))
364                  call wstats(ngrid,trim(chemnoms(iesp))//'_escape',trim(chemnoms(iesp))//' escape',    &
365                               'molecule.m-2.s-1',2,escape(1,indexchim(trim(chemnoms(iesp)))))
366               end do
367            endif ! end depos
368
369         ! photoloysis
370         do i=1,nb_phot_hv_max
371            call writediagfi(ngrid,trim(jlabel(i,1)),jlabel(i,1),    &
372                             's-1',3,v_phot_3d(1,1,i))
373         end do
374         ! iter
375         call writediagfi(ngrid,'iter','iterations',  &
376                          ' ',3,iter_3d(1,1))
377         ! phothcemical heating
378         call writediagfi(ngrid,'zdtchim','dT chim',    &
379                          'K.s-1',3,zdtchim)
380         call writediagfi(ngrid,'dEzchim','dE chim',    &
381                          'W m-2',3,dEzchim)
382         call writediagfi(ngrid,"Ezchim","integrated dT chim","W m-2",2,zdtchim_output)
383         ! Mean molecular mass
384         call writediagfi(ngrid,'mmean','mean molecular mass',       &
385                        'g.mole-1',3,mmean(1,1))
386         ! Chemical tendencies
387         do iesp=1,nesp
388            call writediagfi(ngrid,trim(chemnoms(iesp))//'_dq',trim(chemnoms(iesp))//'_dq',    &
389                            'kg/kg s^-1',3,dqchim(1,1,iesp) )
390         end do
391         if (depos) then
392            ! Surface fluxes and escape
393            do iesp=1,nesp
394               call writediagfi(ngrid,trim(chemnoms(iesp))//'_flux_mean',trim(chemnoms(iesp))//' mean flux',    &
395                            'molecule.m-2.s-1',2,surface_flux2(1,indexchim(trim(chemnoms(iesp)))))
396               call writediagfi(ngrid,trim(chemnoms(iesp))//'_flux',trim(chemnoms(iesp))//' flux',    &
397                            'molecule.m-2.s-1',2,surface_flux(1,indexchim(trim(chemnoms(iesp)))))
398               call writediagfi(ngrid,trim(chemnoms(iesp))//'_escape',trim(chemnoms(iesp))//' escape',    &
399                            'molecule.m-2.s-1',2,escape(1,indexchim(trim(chemnoms(iesp)))))
400            end do
401            ! Restart flux average
402            if(mod(icount,diagfi_output_rate).eq.0) then
403              surface_flux2(:,:) = 0.0
404            endif
405         endif ! end depos
406
407         if (jonline .and. output_writediagspecUV) then
408
409            !flux at the surface
410            call writediagspecUV(ngrid,"flux_surf","Surface flux(lon,lat,band)","photon.s-1.nm-1.cm-2",3,fluxUV(:,:,1))
411
412         endif ! end jonline
413
414      end if ! of if (output)
415
416
417      contains
418
419
420!======================================================================
421
422      subroutine ini_tracchim
423
424!======================================================================
425! YJ Modern tracer.def
426! Get in tracer.def chemical parameters
427!======================================================================
428
429         use chimiedata_h
430         use tracer_h, only:   is_chim
431         implicit none
432
433         ! local
434         character(len=500) :: tracline ! to store a line of text
435         integer            :: nq       ! number of tracers
436         integer            :: iesp, iq
437
438         ! Get nq
439         open(90,file='traceur.def',status='old',form='formatted',iostat=ierr)
440         if (ierr.eq.0) then
441           READ(90,'(A)') tracline
442           IF (trim(tracline).ne.'#ModernTrac-v1') THEN ! Test modern traceur.def
443            READ(tracline,*,iostat=ierr) nq ! Try standard traceur.def
444           ELSE
445              DO
446                READ(90,'(A)',iostat=ierr) tracline
447                IF (ierr.eq.0) THEN
448                  IF (index(tracline,'#').ne.1) THEN ! Allows arbitary number of comments lines in the header
449                    READ(tracline,*,iostat=ierr) nq
450                    EXIT
451                  ENDIF
452                ELSE ! If pb, or if reached EOF without having found number of tracer
453                   write(*,*) "calchim: error reading line of tracers"
454                   write(*,*) "   (first lines of traceur.def) "
455                   stop
456                ENDIF
457              ENDDO
458           ENDIF ! if modern or standard traceur.def
459         else
460            write(*,*) "calchim: error opening traceur.def"
461            stop
462         endif
463
464         ! Get data of tracers
465         iesp = 0
466         do iq=1,nq
467            read(90,'(A)') tracline
468            if (is_chim(iq).eq.1) then
469               iesp = iesp + 1
470               read(tracline,*) chemnoms(iesp)
471               write(*,*)"ini_tracchim: iq=",iq,"noms(iq)=",trim(chemnoms(iesp))
472               if (index(tracline,'SF_mode='    ) /= 0) then
473                  read(tracline(index(tracline,'SF_mode=')+len('SF_mode='):),*) SF_mode(iesp)
474                  write(*,*) ' Parameter value (traceur.def) : SF_mode=', SF_mode(iesp)
475               else
476                  write(*,*) ' Parameter value (default)     : SF_mode=', SF_mode(iesp)
477               end if
478               if (index(tracline,'SF_value='   ) /= 0) then
479                  read(tracline(index(tracline,'SF_value=')+len('SF_value='):),*) SF_value(iesp)
480                  write(*,*) ' Parameter value (traceur.def) : SF_value=', SF_value(iesp)
481               else
482                  write(*,*) ' Parameter value (default)     : SF_value=', SF_value(iesp)
483               end if
484               if (index(tracline,'prod_rate='  ) /= 0) then
485                  read(tracline(index(tracline,'prod_rate=')+len('prod_rate='):),*) prod_rate(iesp)
486                  write(*,*) ' Parameter value (traceur.def) : prod_rate=', prod_rate(iesp)
487               else
488                  write(*,*) ' Parameter value (default)     : prod_rate=', prod_rate(iesp)
489               end if
490               if (index(tracline,'escape='     ) /= 0) then
491                  read(tracline(index(tracline,'escape=')+len('escape='):),*) escape(:,iesp)
492                  write(*,*) ' Parameter value (traceur.def) : escape=', escape(:,iesp)
493               else
494                  write(*,*) ' Parameter value (default)     : escape=', escape(:,iesp)
495               end if
496            end if
497         end do
498
499         close(90)
500
501      end subroutine ini_tracchim
502
503      end subroutine calchim_asis
504
Note: See TracBrowser for help on using the repository browser.