source: trunk/LMDZ.MARS/libf/phymars/nirco2abs.F @ 1036

Last change on this file since 1036 was 1036, checked in by emillour, 11 years ago

Mars GCM: (a first step towards using parallel dynamics)

  • IMPORTANT CHANGE: Implemented dynamic tracers. It is no longer necessary to compile the model with the '-t #' option, number of tracers is simply read from tracer.def file (as before). Adapted makegcm_* scripts (and co.) accordingly. Technical aspects of the switch to dynamic tracers are:
    • advtrac.h (in dyn3d) removed and replaced by module infotrac.F
    • tracer.h (in phymars) removed and replaced by module tracer_mod.F90 (which contains nqmx, the number of tracers, etc. and can be used anywhere in the physics).
  • Included some side cleanups: removed unused files (in dyn3d) anldoppler2.F, anl_mcdstats.F and anl_stats-diag.F, and all the unecessary dimensions.* files in grid/dimension.
  • Checked that changes are clean and that GCM yields identical results (in debug mode) to previous svn version.

EM

File size: 8.5 KB
Line 
1      SUBROUTINE nirco2abs(ngrid,nlayer,pplay,dist_sol,nq,pq,
2     $     mu0,fract,declin,pdtnirco2)
3                                                   
4       use tracer_mod, only: igcm_co2, igcm_o
5       IMPLICIT NONE
6c=======================================================================
7c   subject:
8c   --------
9c   Computing heating rate due to
10c   absorption by CO2 in the near-infrared
11c   This version includes NLTE effects
12c
13c   (Scheme to be described in Forget et al., JGR, 2003)
14c   (old Scheme described in Forget et al., JGR, 1999)
15c
16c   This version updated with a new functional fit,
17c   see NLTE correction-factor of Lopez-Valverde et al (1998)
18c   Stephen Lewis 2000
19c
20c   jul 2011 malv+fgg    New corrections for NLTE implemented
21c   08/2002 : correction for bug when running with diurnal=F
22c
23c   author:  Frederic Hourdin 1996
24c   ------
25c            Francois Forget 1999
26c
27c   input:
28c   -----
29c   ngrid                 number of gridpoint of horizontal grid
30c   nlayer                Number of layer
31c   dist_sol              sun-Mars distance (AU)
32c   mu0(ngridmx)         
33c   fract(ngridmx)        day fraction of the time interval
34c   declin                latitude of subslar point
35c
36c   output:
37c   -------
38c
39c   pdtnirco2(ngrid,nlayer)      Heating rate (K/s)
40c
41c
42c=======================================================================
43c
44c    0.  Declarations :
45c    ------------------
46c
47#include "dimensions.h"
48#include "dimphys.h"
49#include "comcstfi.h"
50#include "callkeys.h"
51#include "comdiurn.h"
52#include "nirdata.h"
53!#include "tracer.h"
54
55c-----------------------------------------------------------------------
56c    Input/Output
57c    ------------
58      integer,intent(in) :: ngrid ! number of (horizontal) grid points
59      integer,intent(in) :: nlayer ! number of atmospheric layers
60      real,intent(in) :: pplay(ngrid,nlayer) ! Pressure
61      real,intent(in) :: dist_sol ! Sun-Mars distance (in AU)
62      integer,intent(in) :: nq ! number of tracers
63      real,intent(in) :: pq(ngrid,nlayer,nq) ! tracers
64      real,intent(in) :: mu0(ngridmx) ! solar angle
65      real,intent(in) :: fract(ngridmx) ! day fraction of the time interval
66      real,intent(in) :: declin ! latitude of sub-solar point
67     
68      real,intent(out) :: pdtnirco2(ngrid,nlayer) ! heating rate (K/s)
69c
70c    Local variables :
71c    -----------------
72      INTEGER l,ig, n, nstep,i
73      REAL co2heat0, zmu(ngridmx)
74
75c     special diurnal=F
76      real mu0_int(ngridmx),fract_int(ngridmx),zday_int
77      real ztim1,ztim2,ztim3,step
78
79c
80c   local saved variables
81c   ---------------------
82      logical,save :: firstcall=.true.
83      integer,save :: ico2=0 ! index of "co2" tracer
84      integer,save :: io=0 ! index of "o" tracer
85c     p0noonlte is a pressure below which non LTE effects are significant.
86c     REAL p0nonlte
87c     DATA p0nonlte/7.5e-3/
88c     SAVE p0nonlte
89
90c     parameters for CO2 heating fit
91      real n_a, n_p0, n_b
92      parameter (n_a=1.1956475)
93      parameter (n_b=1.9628251)
94      parameter (n_p0=0.0015888279)
95
96c     Variables added to implement NLTE correction factor (feb 2011)
97      real    pyy(nlayer)
98      real    cor1(nlayer),oldoco2(nlayer),alfa2(nlayer)
99      real    p2011,cociente1,merge
100      real    cor0,oco2gcm
101
102c----------------------------------------------------------------------
103
104c     Initialisation
105c     --------------
106      if (firstcall) then
107        if (nircorr.eq.1) then
108          ! we will need co2 and o tracers
109          ico2=igcm_co2
110          if (ico2==0) then
111            write(*,*) "nirco2abs error: I need a CO2 tracer"
112            write(*,*) "     when running with nircorr==1"
113            stop
114          endif
115          io=igcm_o
116          if (io==0) then
117            write(*,*) "nirco2abs error: I need an O tracer"
118            write(*,*) "     when running with nircorr==1"
119            stop
120          endif
121        endif
122        firstcall=.false.
123      endif
124
125
126c     co2heat is the heating by CO2 at 700Pa for a zero zenithal angle.
127      co2heat0=n_a*(1.52/dist_sol)**2/daysec
128
129c     Simple calcul for a given sun incident angle (if diurnal=T)
130c     --------------------------------------------
131
132      IF (diurnal) THEN 
133         do ig=1,ngrid
134            zmu(ig)=sqrt(1224.*mu0(ig)*mu0(ig)+1.)/35.
135
136            if(nircorr.eq.1) then
137               do l=1,nlayer
138                  pyy(l)=pplay(ig,l)
139               enddo
140
141               call interpnir(cor1,pyy,nlayer,corgcm,pres1d,npres)
142               call interpnir(oldoco2,pyy,nlayer,oco21d,pres1d,npres)
143               call interpnir(alfa2,pyy,nlayer,alfa,pres1d,npres)
144            endif
145
146            do l=1,nlayer
147!           Calculations for the O/CO2 correction
148               if(nircorr.eq.1) then
149                  cor0=1./(1.+n_p0/pplay(ig,l))**n_b
150                  if(pq(ig,l,ico2).gt.1.e-6) then
151                     oco2gcm=pq(ig,l,io)/pq(ig,l,ico2)
152                  else
153                     oco2gcm=1.e6
154                  endif
155                  cociente1=oco2gcm/oldoco2(l)
156                  merge=alog10(cociente1)*alfa2(l)+alog10(cor0)*
157     $                 (1.-alfa2(l))
158                  merge=10**merge
159                  p2011=sqrt(merge)*cor0
160               else if (nircorr.eq.0) then
161                  p2011=1.
162                  cor1(l)=1.
163               endif
164
165               if(fract(ig).gt.0.) pdtnirco2(ig,l)=
166     &             co2heat0*sqrt((700.*zmu(ig))/pplay(ig,l))
167     &             /(1.+n_p0/pplay(ig,l))**n_b
168!           Corrections from tabulation
169     $              * cor1(l) * p2011
170c           OLD SCHEME (forget et al. 1999)
171c    s           co2heat0*sqrt((700.*zmu(ig))/pplay(ig,l))
172c    s          / (1+p0nonlte/pplay(ig,l))
173           enddo
174         enddo
175         
176
177c     Averaging over diurnal cycle (if diurnal=F)
178c     -------------------------------------------
179c     NIR CO2 abs is slightly non linear. To remove the diurnal
180c     cycle, it is better to average the heating rate over 1 day rather
181c     than using the mean mu0 computed by mucorr in physiq.F (FF, 1998)
182
183      ELSE      ! if (.not.diurnal) then
184
185         nstep = 20   ! number of integration step /sol
186         do n=1,nstep
187            zday_int = (n-1)/float(nstep)
188            ztim2=COS(declin)*COS(2.*pi*(zday_int-.5))
189            ztim3=-COS(declin)*SIN(2.*pi*(zday_int-.5))
190            CALL solang(ngrid,sinlon,coslon,sinlat,coslat,
191     s             ztim1,ztim2,ztim3,
192     s             mu0_int,fract_int)
193            do ig=1,ngrid
194               zmu(ig)=sqrt(1224.*mu0_int(ig)*mu0_int(ig)+1.)/35.
195
196               if(nircorr.eq.1) then
197                  do l=1,nlayer
198                     pyy(l)=pplay(ig,l)
199                  enddo
200               call interpnir(cor1,pyy,nlayer,corgcm,pres1d,npres)
201               call interpnir(oldoco2,pyy,nlayer,oco21d,pres1d,npres)
202               call interpnir(alfa2,pyy,nlayer,alfa,pres1d,npres)
203               endif
204
205               do l=1,nlayer
206                  if(nircorr.eq.1) then
207                     cor0=1./(1.+n_p0/pplay(ig,l))**n_b
208                     oco2gcm=pq(ig,l,io)/pq(ig,l,ico2)
209                     cociente1=oco2gcm/oldoco2(l)
210                     merge=alog10(cociente1)*alfa2(l)+alog10(cor0)*
211     $                    (1.-alfa2(l))
212                     merge=10**merge
213                     p2011=sqrt(merge)*cor0
214                  else if (nircorr.eq.0) then
215                     p2011=1.
216                     cor1(l)=1.
217                  endif
218
219                  if(fract_int(ig).gt.0.) pdtnirco2(ig,l)=
220     &                 pdtnirco2(ig,l) + (1/float(nstep))*
221     &                 co2heat0*sqrt((700.*zmu(ig))/pplay(ig,l))
222     &                 /(1.+n_p0/pplay(ig,l))**n_b
223!                      Corrections from tabulation
224     $                 * cor1(l) * p2011
225               enddo
226            enddo
227         end do
228      END IF
229
230      return
231      end
232
233
234     
235      subroutine interpnir(escout,p,nlayer,escin,pin,nl)
236C
237C subroutine to perform linear interpolation in pressure from 1D profile
238C escin(nl) sampled on pressure grid pin(nl) to profile
239C escout(nlayer) on pressure grid p(nlayer).
240C
241      real escout(nlayer),p(nlayer)
242      real escin(nl),pin(nl),wm,wp
243      integer nl,nlayer,n1,n,nm,np
244      do n1=1,nlayer
245         if(p(n1) .gt. 1500. .or. p(n1) .lt. 1.0e-13) then
246            escout(n1) = 0.0
247         else
248            do n = 1,nl-1
249               if (p(n1).le.pin(n).and.p(n1).ge.pin(n+1)) then
250                  nm=n
251                  np=n+1
252                  wm=abs(pin(np)-p(n1))/(pin(nm)-pin(np))
253                  wp=1.0 - wm
254               endif
255            enddo
256            escout(n1) = escin(nm)*wm + escin(np)*wp
257         endif
258      enddo
259      return
260      end
Note: See TracBrowser for help on using the repository browser.