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

Last change on this file since 4031 was 3740, checked in by emillour, 9 months ago

Mars PCM:
Code tidying; removed unused mufract.F (mucorr.F does the job); turned
ambiguously named sig.F to sig_h2o.F90 and make it a module.
EM

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