source: trunk/LMDZ.MARS/libf/phymars/aeropacity.F @ 1242

Last change on this file since 1242 was 1226, checked in by aslmd, 11 years ago

LMDZ.MARS : Replaced comcstfi and planete includes by modules.

File size: 19.4 KB
Line 
1      SUBROUTINE aeropacity(ngrid,nlayer,nq,zday,pplay,pplev,ls,
2     &    pq,tauscaling,tauref,tau,taucloudtes,aerosol,reffrad,nueffrad,
3     &    QREFvis3d,QREFir3d,omegaREFvis3d,omegaREFir3d)
4                                                   
5! to use  'getin'
6      USE ioipsl_getincom, only: getin
7      use tracer_mod, only: noms, igcm_h2o_ice, igcm_dust_mass,
8     &                      igcm_dust_submicron, rho_dust, rho_ice,
9     &                      nqdust
10      use comgeomfi_h, only: lati, sinlat ! grid point latitudes (rad)
11      use yomaer_h, only: tauvis
12      use planete_h
13      USE comcstfi_h
14       IMPLICIT NONE
15c=======================================================================
16c   subject:
17c   --------
18c   Computing aerosol optical depth in each gridbox.
19c
20c   author: F.Forget
21c   ------
22c   update F. Montmessin (water ice scheme)
23c      and S. Lebonnois (12/06/2003) compatibility dust/ice/chemistry
24c   update J.-B. Madeleine 2008-2009:
25c       - added 3D scattering by aerosols;
26c       - dustopacity transferred from physiq.F to callradite.F,
27c           and renamed into aeropacity.F;
28c   update E. Millour, march 2012:
29c         - reference pressure is now set to 610Pa (not 700Pa)
30c   
31c   input:
32c   -----
33c   ngrid             Number of gridpoint of horizontal grid
34c   nlayer            Number of layer
35c   nq                Number of tracer
36c   zday                  Date (time since Ls=0, in martian days)
37c   ls                Solar longitude (Ls) , radian
38c   pplay,pplev       pressure (Pa) in the middle and boundary of each layer
39c   pq                Dust mixing ratio (used if tracer =T and active=T).
40c   reffrad(ngrid,nlayer,naerkind)  Aerosol effective radius
41c   QREFvis3d(ngrid,nlayer,naerkind) \ 3d extinction coefficients
42c   QREFir3d(ngrid,nlayer,naerkind)  / at reference wavelengths;
43c   omegaREFvis3d(ngrid,nlayer,naerkind) \ 3d single scat. albedo
44c   omegaREFir3d(ngrid,nlayer,naerkind)  / at reference wavelengths;
45c
46c   output:
47c   -------
48c   tauref       Prescribed mean column optical depth at 610 Pa
49c   tau          Column total visible dust optical depth at each point
50c   aerosol      aerosol(ig,l,1) is the dust optical
51c                depth in layer l, grid point ig
52
53c
54c=======================================================================
55!#include "dimensions.h"
56!#include "dimphys.h"
57#include "callkeys.h"
58!#include "comgeomfi.h"
59!#include "dimradmars.h"
60!#include "yomaer.h"
61!#include "tracer.h"
62! naerkind is set in scatterers.h (built when compiling with makegcm -s #)
63#include"scatterers.h"
64#include "aerkind.h"
65
66c-----------------------------------------------------------------------
67c
68c    Declarations :
69c    --------------
70c
71c    Input/Output
72c    ------------
73      INTEGER ngrid,nlayer,nq
74
75      REAL ls,zday,expfactor   
76      REAL pplev(ngrid,nlayer+1),pplay(ngrid,nlayer)
77      REAL pq(ngrid,nlayer,nq)
78      REAL tauref(ngrid), tau(ngrid,naerkind)
79      REAL aerosol(ngrid,nlayer,naerkind)
80      REAL dsodust(ngrid,nlayer)
81      REAL reffrad(ngrid,nlayer,naerkind)
82      REAL nueffrad(ngrid,nlayer,naerkind)
83      REAL QREFvis3d(ngrid,nlayer,naerkind)
84      REAL QREFir3d(ngrid,nlayer,naerkind)
85      REAL omegaREFvis3d(ngrid,nlayer,naerkind)
86      REAL omegaREFir3d(ngrid,nlayer,naerkind)
87c
88c    Local variables :
89c    -----------------
90      INTEGER l,ig,iq,i,j
91      INTEGER iaer           ! Aerosol index
92      real topdust(ngrid)
93      real zlsconst, zp
94      real taueq,tauS,tauN
95c     Mean Qext(vis)/Qext(ir) profile
96      real msolsir(nlayer,naerkind)
97c     Mean Qext(ir)/Qabs(ir) profile
98      real mqextsqabs(nlayer,naerkind)
99c     Variables used when multiple particle sizes are used
100c       for dust or water ice particles in the radiative transfer
101c       (see callradite.F for more information).
102      REAL taudusttmp(ngrid)! Temporary dust opacity
103                               !   used before scaling
104      REAL tauscaling(ngrid) ! Scaling factor for qdust and Ndust
105      REAL taudustvis(ngrid) ! Dust opacity after scaling
106      REAL taudusttes(ngrid) ! Dust opacity at IR ref. wav. as
107                               !   "seen" by the GCM.
108      REAL taucloudvis(ngrid)! Cloud opacity at visible
109                               !   reference wavelength
110      REAL taucloudtes(ngrid)! Cloud opacity at infrared
111                               !   reference wavelength using
112                               !   Qabs instead of Qext
113                               !   (direct comparison with TES)
114      REAL topdust0(ngrid)
115
116c   local saved variables
117c   ---------------------
118
119c     Level under which the dust mixing ratio is held constant
120c       when computing the dust opacity in each layer
121c       (this applies when doubleq and active are true)
122      INTEGER, PARAMETER :: cstdustlevel0 = 7
123      INTEGER, SAVE      :: cstdustlevel
124
125      LOGICAL,SAVE :: firstcall=.true.
126
127! indexes of water ice and dust tracers:
128      INTEGER,SAVE :: i_ice=0  ! water ice
129      real,parameter :: odpref=610. ! DOD reference pressure (Pa)
130      CHARACTER(LEN=20) :: txt ! to temporarly store text
131      CHARACTER(LEN=1) :: txt2 ! to temporarly store text
132! indexes of dust scatterers:
133      INTEGER,SAVE :: iaerdust(naerkind)
134      INTEGER,SAVE :: naerdust ! number of dust scatterers
135
136      tau(1:ngrid,1:naerkind)=0
137
138! identify tracers
139
140      IF (firstcall) THEN
141        ! identify scatterers that are dust
142        naerdust=0
143        DO iaer=1,naerkind
144          txt=name_iaer(iaer)
145          IF (txt(1:4).eq."dust") THEN
146            naerdust=naerdust+1
147            iaerdust(naerdust)=iaer
148          ENDIF
149        ENDDO
150        ! identify tracers which are dust
151        i=0
152        DO iq=1,nq
153          txt=noms(iq)
154          IF (txt(1:4).eq."dust") THEN
155          i=i+1
156          nqdust(i)=iq
157          ENDIF
158        ENDDO
159
160        IF (water.AND.activice) THEN
161          i_ice=igcm_h2o_ice
162          write(*,*) "aeropacity: i_ice=",i_ice
163        ENDIF
164
165c       typical profile of solsir and (1-w)^(-1):
166        msolsir(1:nlayer,1:naerkind)=0
167        mqextsqabs(1:nlayer,1:naerkind)=0
168        WRITE(*,*) "Typical profiles of Qext(vis)/Qext(IR)"
169        WRITE(*,*) "  and Qext(IR)/Qabs(IR):"
170        DO iaer = 1, naerkind ! Loop on aerosol kind
171          WRITE(*,*) "Aerosol # ",iaer
172          DO l=1,nlayer
173            DO ig=1,ngrid
174              msolsir(l,iaer)=msolsir(l,iaer)+
175     &              QREFvis3d(ig,l,iaer)/
176     &              QREFir3d(ig,l,iaer)
177              mqextsqabs(l,iaer)=mqextsqabs(l,iaer)+
178     &              (1.E0-omegaREFir3d(ig,l,iaer))**(-1)
179            ENDDO
180            msolsir(l,iaer)=msolsir(l,iaer)/REAL(ngrid)
181            mqextsqabs(l,iaer)=mqextsqabs(l,iaer)/REAL(ngrid)
182          ENDDO
183          WRITE(*,*) "solsir: ",msolsir(:,iaer)
184          WRITE(*,*) "Qext/Qabs(IR): ",mqextsqabs(:,iaer)
185        ENDDO
186
187!       load value of tauvis from callphys.def (if given there,
188!       otherwise default value read from starfi.nc file will be used)
189        call getin("tauvis",tauvis)
190
191        IF (freedust) THEN
192          cstdustlevel = 1
193        ELSE
194          cstdustlevel = cstdustlevel0
195        ENDIF
196
197
198        firstcall=.false.
199
200      END IF
201
202c     Vertical column optical depth at "odpref" Pa
203c     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
204      IF(freedust) THEN
205         tauref(:) = 0. ! tauref is computed after, instead of being forced
206
207      ELSE IF(iaervar.eq.1) THEN
208         do ig=1, ngrid
209          tauref(ig)=max(tauvis,1.e-9) ! tauvis=cste (set in callphys.def
210                                       ! or read in starfi
211        end do
212      ELSE IF (iaervar.eq.2) THEN   ! << "Viking" Scenario>>
213
214        tauref(1) = 0.7+.3*cos(ls+80.*pi/180.) ! like seen by VL1
215        do ig=2,ngrid
216          tauref(ig) = tauref(1)
217        end do
218
219      ELSE IF (iaervar.eq.3) THEN  ! << "MGS" scenario >>
220
221        taueq= 0.2 +(0.5-0.2) *(cos(0.5*(ls-4.363)))**14
222        tauS= 0.1 +(0.5-0.1)  *(cos(0.5*(ls-4.363)))**14
223        tauN = 0.1
224c          if (peri_day.eq.150) then
225c            tauS=0.1
226c            tauN=0.1 +(0.5-0.1)  *(cos(0.5*(ls+pi-4.363)))**14
227c            taueq= 0.2 +(0.5-0.2) *(cos(0.5*(ls+pi-4.363)))**14
228c           endif
229        do ig=1,ngrid
230          if (lati(ig).ge.0) then
231          ! Northern hemisphere
232            tauref(ig)= tauN +
233     &      (taueq-tauN)*0.5*(1+tanh((45-lati(ig)*180./pi)*6/60))
234          else
235          ! Southern hemisphere
236            tauref(ig)= tauS +
237     &      (taueq-tauS)*0.5*(1+tanh((45+lati(ig)*180./pi)*6/60))
238          endif
239        enddo ! of do ig=1,ngrid
240      ELSE IF (iaervar.eq.5) THEN   ! << Escalier Scenario>>
241c         tauref(1) = 0.2
242c         if ((ls.ge.210.*pi/180.).and.(ls.le.330.*pi/180.))
243c    &                              tauref(1) = 2.5
244        tauref(1) = 2.5
245        if ((ls.ge.30.*pi/180.).and.(ls.le.150.*pi/180.))
246     &                              tauref(1) = .2
247
248        do ig=2,ngrid
249          tauref(ig) = tauref(1)
250        end do
251      ELSE IF ((iaervar.ge.6).and.(iaervar.le.7)) THEN
252      ! cold or warm synthetic scenarios
253        call read_dust_scenario(ngrid,nlayer,zday,pplev,tauref)
254      ELSE IF ((iaervar.ge.24).and.(iaervar.le.30))
255     &     THEN  ! << MY... dust scenarios >>
256        call read_dust_scenario(ngrid,nlayer,zday,pplev,tauref)
257      ELSE IF ((iaervar.eq.4).or.
258     &         ((iaervar.ge.124).and.(iaervar.le.126))) THEN
259       ! "old" TES assimation dust scenario (values at 700Pa in files!)
260        call read_dust_scenario(ngrid,nlayer,zday,pplev,tauref)
261      ELSE
262        stop 'problem with iaervar in aeropacity.F'
263      ENDIF
264
265c -----------------------------------------------------------------
266c Computing the opacity in each layer
267c -----------------------------------------------------------------
268
269      DO iaer = 1, naerkind ! Loop on aerosol kind
270c     --------------------------------------------
271        aerkind: SELECT CASE (name_iaer(iaer))
272c==================================================================
273        CASE("dust_conrath") aerkind      ! Typical dust profile
274c==================================================================
275
276c       Altitude of the top of the dust layer
277c       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
278        zlsconst=SIN(ls-2.76)
279        if (iddist.eq.1) then
280          do ig=1,ngrid
281             topdust(ig)=topdustref         ! constant dust layer top
282          end do
283
284        else if (iddist.eq.2) then          ! "Viking" scenario
285          do ig=1,ngrid
286            ! altitude of the top of the aerosol layer (km) at Ls=2.76rad:
287            ! in the Viking year scenario
288            topdust0(ig)=60. -22.*sinlat(ig)**2
289            topdust(ig)=topdust0(ig)+18.*zlsconst
290          end do
291
292        else if(iddist.eq.3) then         !"MGS" scenario
293          do ig=1,ngrid
294            topdust(ig)=60.+18.*zlsconst
295     &                -(32+18*zlsconst)*sin(lati(ig))**4
296     &                 - 8*zlsconst*(sin(lati(ig)))**5
297          end do
298        endif
299
300c       Optical depth in each layer :
301c       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
302        if(iddist.ge.1) then
303
304          expfactor=0.
305          DO l=1,nlayer
306            DO ig=1,ngrid
307c             Typical mixing ratio profile
308              if(pplay(ig,l).gt.odpref
309     $                        /(988.**(topdust(ig)/70.))) then
310                zp=(odpref/pplay(ig,l))**(70./topdust(ig))
311                 expfactor=max(exp(0.007*(1.-max(zp,1.))),1.e-3)
312              else   
313                expfactor=1.e-3
314              endif
315c             Vertical scaling function
316              aerosol(ig,l,iaer)= (pplev(ig,l)-pplev(ig,l+1)) *
317     &          expfactor *
318     &          QREFvis3d(ig,l,iaer) / QREFvis3d(ig,1,iaer)
319            ENDDO
320          ENDDO
321
322        else if(iddist.eq.0) then   
323c         old dust vertical distribution function (pollack90)
324          DO l=1,nlayer
325             DO ig=1,ngrid
326                zp=odpref/pplay(ig,l)
327                aerosol(ig,l,1)= tauref(ig)/odpref *
328     s           (pplev(ig,l)-pplev(ig,l+1))
329     s           *max( exp(.03*(1.-max(zp,1.))) , 1.E-3 )
330             ENDDO
331          ENDDO
332        end if
333
334c==================================================================
335        CASE("dust_doubleq") aerkind! Two-moment scheme for dust
336c        (transport of mass and number mixing ratio)
337c==================================================================
338
339          DO l=1,nlayer
340            IF (l.LE.cstdustlevel) THEN
341c           Opacity in the first levels is held constant to
342c             avoid unrealistic values due to constant lifting:
343              DO ig=1,ngrid
344                aerosol(ig,l,iaer) =
345     &          (  0.75 * QREFvis3d(ig,cstdustlevel,iaer) /
346     &          ( rho_dust * reffrad(ig,cstdustlevel,iaer) )  ) *
347     &          pq(ig,cstdustlevel,igcm_dust_mass) *
348     &          ( pplev(ig,l) - pplev(ig,l+1) ) / g
349              ENDDO
350            ELSE
351              DO ig=1,ngrid
352                aerosol(ig,l,iaer) =
353     &          (  0.75 * QREFvis3d(ig,l,iaer) /
354     &          ( rho_dust * reffrad(ig,l,iaer) )  ) *
355     &          pq(ig,l,igcm_dust_mass) *
356     &          ( pplev(ig,l) - pplev(ig,l+1) ) / g
357              ENDDO
358            ENDIF
359          ENDDO
360
361c==================================================================
362        CASE("dust_submicron") aerkind   ! Small dust population
363c==================================================================
364
365          DO l=1,nlayer
366            IF (l.LE.cstdustlevel) THEN
367c           Opacity in the first levels is held constant to
368c             avoid unrealistic values due to constant lifting:
369              DO ig=1,ngrid
370                aerosol(ig,l,iaer) =
371     &          (  0.75 * QREFvis3d(ig,cstdustlevel,iaer) /
372     &          ( rho_dust * reffrad(ig,cstdustlevel,iaer) )  ) *
373     &          pq(ig,cstdustlevel,igcm_dust_submicron) *
374     &          ( pplev(ig,l) - pplev(ig,l+1) ) / g
375              ENDDO
376            ELSE
377              DO ig=1,ngrid
378                aerosol(ig,l,iaer) =
379     &          (  0.75 * QREFvis3d(ig,l,iaer) /
380     &          ( rho_dust * reffrad(ig,l,iaer) )  ) *
381     &          pq(ig,l,igcm_dust_submicron) *
382     &          ( pplev(ig,l) - pplev(ig,l+1) ) / g
383              ENDDO
384            ENDIF
385          ENDDO
386
387c==================================================================
388        CASE("h2o_ice") aerkind             ! Water ice crystals
389c==================================================================
390
391c       1. Initialization
392        aerosol(1:ngrid,1:nlayer,iaer) = 0.
393        taucloudvis(1:ngrid) = 0.
394        taucloudtes(1:ngrid) = 0.
395c       2. Opacity calculation
396        DO ig=1, ngrid
397          DO l=1,nlayer
398            aerosol(ig,l,iaer) = max(1E-20,
399     &        (  0.75 * QREFvis3d(ig,l,iaer) /
400     &        ( rho_ice * reffrad(ig,l,iaer) )  ) *
401     &        pq(ig,l,i_ice) *
402     &        ( pplev(ig,l) - pplev(ig,l+1) ) / g
403     &                              )
404            taucloudvis(ig) = taucloudvis(ig) + aerosol(ig,l,iaer)
405            taucloudtes(ig) = taucloudtes(ig) + aerosol(ig,l,iaer)*
406     &        QREFir3d(ig,l,iaer) / QREFvis3d(ig,l,iaer) *
407     &        ( 1.E0 - omegaREFir3d(ig,l,iaer) )
408          ENDDO
409        ENDDO
410c       3. Outputs -- Now done in physiq.F
411!        IF (ngrid.NE.1) THEN
412!          CALL WRITEDIAGFI(ngrid,'tauVIS','tauext VIS refwvl',
413!     &      ' ',2,taucloudvis)
414!          CALL WRITEDIAGFI(ngrid,'tauTES','tauabs IR refwvl',
415!     &      ' ',2,taucloudtes)
416!          IF (callstats) THEN
417!            CALL wstats(ngrid,'tauVIS','tauext VIS refwvl',
418!     &        ' ',2,taucloudvis)
419!            CALL wstats(ngrid,'tauTES','tauabs IR refwvl',
420!     &        ' ',2,taucloudtes)
421!          ENDIF
422!        ELSE
423!         CALL writeg1d(ngrid,1,taucloudtes,'tautes','NU')
424!        ENDIF
425c==================================================================
426        END SELECT aerkind
427c     -----------------------------------
428      ENDDO ! iaer (loop on aerosol kind)
429
430c -----------------------------------------------------------------
431c Rescaling each layer to reproduce the choosen (or assimilated)
432c   dust extinction opacity at visible reference wavelength, which
433c   is originally scaled to an equivalent odpref Pa pressure surface.
434c -----------------------------------------------------------------
435
436      IF (freedust) THEN
437          tauscaling(:) = 1.
438
439      ELSE
440c       Temporary scaling factor
441        taudusttmp(1:ngrid)=0.
442        DO iaer=1,naerdust
443          DO l=1,nlayer
444            DO ig=1,ngrid
445c             Scaling factor
446              taudusttmp(ig) = taudusttmp(ig) +
447     &                         aerosol(ig,l,iaerdust(iaer))
448            ENDDO
449          ENDDO
450        ENDDO
451
452c       Saved scaling factor
453        DO ig=1,ngrid
454            tauscaling(ig) = tauref(ig) *
455     &                       pplev(ig,1) / odpref / taudusttmp(ig)
456        ENDDO
457
458      ENDIF
459
460c     Opacity computation
461      DO iaer=1,naerdust
462        DO l=1,nlayer
463          DO ig=1,ngrid
464            aerosol(ig,l,iaerdust(iaer)) = max(1E-20,
465     &                aerosol(ig,l,iaerdust(iaer))* tauscaling(ig))
466          ENDDO
467        ENDDO
468      ENDDO
469
470      IF (freedust) THEN
471        ! tauref has been initialized to 0 before.
472        DO iaer=1,naerdust
473          DO l=1,nlayer
474            DO ig=1,ngrid
475              tauref(ig) = tauref(ig) +
476     &                    aerosol(ig,l,iaerdust(iaer))
477            ENDDO
478          ENDDO
479        ENDDO
480        tauref(:) = tauref(:) * odpref / pplev(:,1)
481      ENDIF
482     
483c output for debug
484c        IF (ngrid.NE.1) THEN
485c             CALL WRITEDIAGFI(ngrid,'taudusttmp','virtual tau dust',
486c     &      '#',2,taudusttmp)
487c             CALL WRITEDIAGFI(ngrid,'tausca','tauscaling',
488c     &      '#',2,tauscaling)
489c        ELSE
490c             CALL WRITEDIAGFI(ngrid,'taudusttmp','virtual tau dust',
491c     &      '#',0,taudusttmp)
492c             CALL WRITEDIAGFI(ngrid,'tausca','tauscaling',
493c     &      '#',0,tauscaling)
494c        ENDIF
495c -----------------------------------------------------------------
496c Column integrated visible optical depth in each point
497c -----------------------------------------------------------------
498      DO iaer=1,naerkind
499        do l=1,nlayer
500           do ig=1,ngrid
501             tau(ig,iaer) = tau(ig,iaer) + aerosol(ig,l,iaer)
502           end do
503        end do
504      ENDDO
505c -----------------------------------------------------------------
506c Density scaled opacity and column opacity output
507c -----------------------------------------------------------------
508c      dsodust(1:ngrid,1:nlayer) = 0.
509c      DO iaer=1,naerdust
510c        DO l=1,nlayer
511c          DO ig=1,ngrid
512c            dsodust(ig,l) = dsodust(ig,l) +
513c     &                      aerosol(ig,l,iaerdust(iaer)) * g /
514c     &                      (pplev(ig,l) - pplev(ig,l+1))
515c          ENDDO
516c        ENDDO
517c        IF (ngrid.NE.1) THEN
518c          write(txt2,'(i1.1)') iaer
519c          call WRITEDIAGFI(ngrid,'taudust'//txt2,
520c     &                    'Dust col opacity',
521c     &                    ' ',2,tau(1,iaerdust(iaer)))
522c          IF (callstats) THEN
523c            CALL wstats(ngrid,'taudust'//txt2,
524c     &                 'Dust col opacity',
525c     &                 ' ',2,tau(1,iaerdust(iaer)))
526c          ENDIF
527c        ENDIF
528c      ENDDO
529
530c      IF (ngrid.NE.1) THEN
531c       CALL WRITEDIAGFI(ngrid,'dsodust','tau*g/dp',
532c    &                    'm2.kg-1',3,dsodust)
533c        IF (callstats) THEN
534c          CALL wstats(ngrid,'dsodust',
535c     &               'tau*g/dp',
536c     &               'm2.kg-1',3,dsodust)
537c        ENDIF
538c      ELSE
539c        CALL WRITEDIAGFI(ngrid,"dsodust","dsodust","m2.kg-1",1,
540c     &                   dsodust)
541c      ENDIF ! of IF (ngrid.NE.1)
542c -----------------------------------------------------------------
543      return
544      end
Note: See TracBrowser for help on using the repository browser.