source: trunk/LMDZ.MARS/libf/aeronomars/jthermcalc_util.F @ 3726

Last change on this file since 3726 was 3726, checked in by emillour, 2 months ago

Mars PCM:
Turn "callkeys.h" into module "callkeys_mod.F90"
EM

File size: 28.8 KB
Line 
1      module jthermcalc_util
2     
3      implicit none
4     
5      contains
6
7c**********************************************************************
8c**********************************************************************
9
10      subroutine column(ig,nlayer,chemthermod,rm,nesptherm,tx,iz,zenit,
11     $     co2colx,o2colx,o3pcolx,h2colx,h2ocolx,h2o2colx,o3colx,
12     $     n2colx,ncolx,nocolx,cocolx,hcolx,no2colx)
13
14c     nov 2002        fgg           first version
15
16c**********************************************************************
17
18      use tracer_mod, only: igcm_o, igcm_co2, igcm_o2, igcm_h2,
19     &                      igcm_h2o_vap, igcm_h2o2, igcm_co, igcm_h,
20     &                      igcm_o3, igcm_n2, igcm_n, igcm_no, igcm_no2,
21     &                      mmol
22      use param_v4_h, only: radio,gg,masa,kboltzman,n_avog
23
24      implicit none
25
26
27c    local parameters and variables
28
29
30
31c     input and output variables
32
33      integer    ig,nlayer
34      integer    chemthermod
35      integer    nesptherm                      !# of species undergoing chemistry, input
36      real       rm(nlayer,nesptherm)         !densities (cm-3), input
37      real       tx(nlayer)                   !temperature profile, input
38      real       iz(nlayer+1)                 !height profile, input
39      real       zenit                          !SZA, input
40      real       co2colx(nlayer)              !column density of CO2 (cm^-2), output
41      real       o2colx(nlayer)               !column density of O2(cm^-2), output
42      real       o3pcolx(nlayer)              !column density of O(3P)(cm^-2), output
43      real       h2colx(nlayer)               !H2 column density (cm-2), output
44      real       h2ocolx(nlayer)              !H2O column density (cm-2), output
45      real       h2o2colx(nlayer)             !column density of H2O2(cm^-2), output
46      real       o3colx(nlayer)               !O3 column density (cm-2), output
47      real       n2colx(nlayer)               !N2 column density (cm-2), output
48      real       ncolx(nlayer)                !N column density (cm-2), output
49      real       nocolx(nlayer)               !NO column density (cm-2), output
50      real       cocolx(nlayer)               !CO column density (cm-2), output
51      real       hcolx(nlayer)                !H column density (cm-2), output
52      real       no2colx(nlayer)              !NO2 column density (cm-2), output
53
54
55c     local variables
56
57      real       xx
58      real       grav(nlayer)
59      real       Hco2,Ho3p,Ho2,Hh2,Hh2o,Hh2o2
60      real       Ho3,Hn2,Hn,Hno,Hco,Hh,Hno2
61
62      real       co2x(nlayer)
63      real       o2x(nlayer)
64      real       o3px(nlayer)
65      real       cox(nlayer)
66      real       hx(nlayer)
67      real       h2x(nlayer)
68      real       h2ox(nlayer)
69      real       h2o2x(nlayer)
70      real       o3x(nlayer)
71      real       n2x(nlayer)
72      real       nx(nlayer)
73      real       nox(nlayer)
74      real       no2x(nlayer)
75
76      integer    i,j,k,icol,indexint          !indexes
77
78c     variables for optical path calculation
79
80      integer    nz3
81!      parameter  (nz3=nz*2)
82
83      integer    jj
84      real*8      esp(nlayer*2)
85      real*8      ilayesp(nlayer*2)
86      real*8      szalayesp(nlayer*2)
87      integer     nlayesp
88      real*8      zmini
89      real*8      depth
90      real*8      espco2, espo2, espo3p, esph2, esph2o, esph2o2,espo3
91      real*8      espn2,espn,espno,espco,esph,espno2
92      real*8      rcmnz, rcmmini
93      real*8      szadeg
94
95
96      ! Tracer indexes in the thermospheric chemistry:
97      !!! ATTENTION. These values have to be identical to those in chemthermos.F90
98      !!! If the values are changed there, the same has to be done here  !!!
99      integer,parameter :: i_co2  =  1
100      integer,parameter :: i_co   =  2
101      integer,parameter :: i_o    =  3
102      integer,parameter :: i_o1d  =  4
103      integer,parameter :: i_o2   =  5
104      integer,parameter :: i_o3   =  6
105      integer,parameter :: i_h    =  7
106      integer,parameter :: i_h2   =  8
107      integer,parameter :: i_oh   =  9
108      integer,parameter :: i_ho2  = 10
109      integer,parameter :: i_h2o2 = 11
110      integer,parameter :: i_h2o  = 12
111      integer,parameter :: i_n    = 13
112      integer,parameter :: i_n2d  = 14
113      integer,parameter :: i_no   = 15
114      integer,parameter :: i_no2  = 16
115      integer,parameter :: i_n2   = 17
116!      integer,parameter :: i_co2=1
117!      integer,parameter :: i_o2=2
118!      integer,parameter :: i_o=3
119!      integer,parameter :: i_co=4
120!      integer,parameter :: i_h=5
121!      integer,parameter :: i_h2=8
122!      integer,parameter :: i_h2o=9
123!      integer,parameter :: i_h2o2=10
124!      integer,parameter :: i_o3=12
125!      integer,parameter :: i_n2=13
126!      integer,parameter :: i_n=14
127!      integer,parameter :: i_no=15
128!      integer,parameter :: i_no2=17
129
130
131c*************************PROGRAM STARTS*******************************
132
133      nz3 = nlayer*2
134      do i=1,nlayer
135         xx = ( radio + iz(i) ) * 1.e5
136         grav(i) = gg * masa /(xx**2)
137      end do
138
139      !Scale heights
140      xx = kboltzman * tx(nlayer) * n_avog / grav(nlayer)
141      Ho3p  = xx / mmol(igcm_o)
142      Hco2  = xx / mmol(igcm_co2)
143      Ho2   = xx / mmol(igcm_o2)
144      Hh2   = xx / mmol(igcm_h2)
145      Hh2o  = xx / mmol(igcm_h2o_vap)
146      Hh2o2 = xx / mmol(igcm_h2o2)
147      Hco   = xx / mmol(igcm_co)
148      Hh    = xx / mmol(igcm_h)
149      !Only if O3 chem. required
150      if(chemthermod.ge.1)
151     $     Ho3   = xx / mmol(igcm_o3)
152      !Only if N or ion chem.
153      if(chemthermod.ge.2) then
154         Hn2   = xx / mmol(igcm_n2)
155         Hn    = xx / mmol(igcm_n)
156         Hno   = xx / mmol(igcm_no)
157         Hno2  = xx / mmol(igcm_no2)
158      endif
159      ! first loop in altitude : initialisation
160      do i=nlayer,1,-1
161         !Column initialisation
162         co2colx(i)  = 0.
163         o2colx(i)   = 0.
164         o3pcolx(i)  = 0.
165         h2colx(i)   = 0.
166         h2ocolx(i)  = 0.
167         h2o2colx(i) = 0.
168         o3colx(i)   = 0.
169         n2colx(i)   = 0.
170         ncolx(i)    = 0.
171         nocolx(i)   = 0.
172         cocolx(i)   = 0.
173         hcolx(i)    = 0.
174         no2colx(i)  = 0.
175         !Densities
176         co2x(i)  = rm(i,i_co2)
177         o2x(i)   = rm(i,i_o2)
178         o3px(i)  = rm(i,i_o)
179         h2x(i)   = rm(i,i_h2)
180         h2ox(i)  = rm(i,i_h2o)
181         h2o2x(i) = rm(i,i_h2o2)
182         cox(i)   = rm(i,i_co)
183         hx(i)    = rm(i,i_h)
184         !Only if O3 chem. required
185         if(chemthermod.ge.1)
186     $        o3x(i)   = rm(i,i_o3)
187         !Only if Nitrogen of ion chemistry requested
188         if(chemthermod.ge.2) then
189            n2x(i)   = rm(i,i_n2)
190            nx(i)    = rm(i,i_n)
191            nox(i)   = rm(i,i_no)
192            no2x(i)  = rm(i,i_no2)
193         endif
194      enddo
195      ! second loop in altitude : column calculations
196      do i=nlayer,1,-1
197         !Routine to calculate the geometrical length of each layer
198         call espesor_optico_A(ig,i,nlayer,zenit,iz(i),nz3,iz,esp,
199     $         ilayesp,szalayesp,nlayesp, zmini)
200         if(ilayesp(nlayesp).eq.-1) then
201            co2colx(i)=1.e25
202            o2colx(i)=1.e25
203            o3pcolx(i)=1.e25
204            h2colx(i)=1.e25
205            h2ocolx(i)=1.e25
206            h2o2colx(i)=1.e25
207            o3colx(i)=1.e25
208            n2colx(i)=1.e25
209            ncolx(i)=1.e25
210            nocolx(i)=1.e25
211            cocolx(i)=1.e25
212            hcolx(i)=1.e25
213            no2colx(i)=1.e25
214         else
215            rcmnz = ( radio + iz(nlayer) ) * 1.e5
216            rcmmini = ( radio + zmini ) * 1.e5
217            !Column calculation taking into account the geometrical depth
218            !calculated before
219            do j=1,nlayesp
220               jj=ilayesp(j)
221               !Top layer
222               if(jj.eq.nlayer) then
223                  if(zenit.le.60.) then
224                     o3pcolx(i)=o3pcolx(i)+o3px(nlayer)*Ho3p*esp(j)
225     $                    *1.e-5
226                     co2colx(i)=co2colx(i)+co2x(nlayer)*Hco2*esp(j)
227     $                    *1.e-5
228                     h2o2colx(i)=h2o2colx(i)+
229     $                    h2o2x(nlayer)*Hh2o2*esp(j)*1.e-5
230                     o2colx(i)=o2colx(i)+o2x(nlayer)*Ho2*esp(j)
231     $                    *1.e-5
232                     h2colx(i)=h2colx(i)+h2x(nlayer)*Hh2*esp(j)
233     $                    *1.e-5
234                     h2ocolx(i)=h2ocolx(i)+h2ox(nlayer)*Hh2o*esp(j)
235     $                    *1.e-5                     
236                     cocolx(i)=cocolx(i)+cox(nlayer)*Hco*esp(j)
237     $                    *1.e-5
238                     hcolx(i)=hcolx(i)+hx(nlayer)*Hh*esp(j)
239     $                    *1.e-5
240                     !Only if O3 chemistry required
241                     if(chemthermod.ge.1) o3colx(i)=
242     $                    o3colx(i)+o3x(nlayer)*Ho3*esp(j)
243     $                    *1.e-5
244                     !Only if N or ion chemistry requested
245                     if(chemthermod.ge.2) then
246                        n2colx(i)=n2colx(i)+n2x(nlayer)*Hn2*esp(j)
247     $                    *1.e-5
248                        ncolx(i)=ncolx(i)+nx(nlayer)*Hn*esp(j)
249     $                       *1.e-5
250                        nocolx(i)=nocolx(i)+nox(nlayer)*Hno*esp(j)
251     $                       *1.e-5
252                        no2colx(i)=no2colx(i)+no2x(nlayer)*Hno2*esp(j)
253     $                       *1.e-5
254                     endif
255                  else if(zenit.gt.60.) then
256                     espco2 =sqrt((rcmnz+Hco2)**2 -rcmmini**2) - esp(j)
257                     espo2  = sqrt((rcmnz+Ho2)**2 -rcmmini**2) - esp(j)
258                     espo3p = sqrt((rcmnz+Ho3p)**2 -rcmmini**2)- esp(j)
259                     esph2  = sqrt((rcmnz+Hh2)**2 -rcmmini**2) - esp(j)
260                     esph2o = sqrt((rcmnz+Hh2o)**2 -rcmmini**2)- esp(j)
261                     esph2o2= sqrt((rcmnz+Hh2o2)**2-rcmmini**2)- esp(j)
262                     espco  = sqrt((rcmnz+Hco)**2 -rcmmini**2) - esp(j)
263                     esph   = sqrt((rcmnz+Hh)**2 -rcmmini**2)  - esp(j)
264                     !Only if O3 chemistry required
265                     if(chemthermod.ge.1)                     
266     $                   espo3=sqrt((rcmnz+Ho3)**2-rcmmini**2)-esp(j)
267                     !Only if N or ion chemistry requested
268                     if(chemthermod.ge.2) then
269                        espn2 =sqrt((rcmnz+Hn2)**2-rcmmini**2)-esp(j)
270                        espn  =sqrt((rcmnz+Hn)**2-rcmmini**2)  - esp(j)
271                        espno =sqrt((rcmnz+Hno)**2-rcmmini**2) - esp(j)
272                        espno2=sqrt((rcmnz+Hno2)**2-rcmmini**2)- esp(j)
273                     endif
274                     co2colx(i) = co2colx(i) + espco2*co2x(nlayer)
275                     o2colx(i)  = o2colx(i)  + espo2*o2x(nlayer)
276                     o3pcolx(i) = o3pcolx(i) + espo3p*o3px(nlayer)
277                     h2colx(i)  = h2colx(i)  + esph2*h2x(nlayer)
278                     h2ocolx(i) = h2ocolx(i) + esph2o*h2ox(nlayer)
279                     h2o2colx(i)= h2o2colx(i)+ esph2o2*h2o2x(nlayer)
280                     cocolx(i)  = cocolx(i)  + espco*cox(nlayer)
281                     hcolx(i)   = hcolx(i)   + esph*hx(nlayer)
282                     !Only if O3 chemistry required
283                     if(chemthermod.ge.1)                     
284     $                  o3colx(i) = o3colx(i)  + espo3*o3x(nlayer)
285                     !Only if N or ion chemistry requested
286                     if(chemthermod.ge.2) then
287                        n2colx(i)  = n2colx(i)  + espn2*n2x(nlayer)
288                        ncolx(i)   = ncolx(i)   + espn*nx(nlayer)
289                        nocolx(i)  = nocolx(i)  + espno*nox(nlayer)
290                        no2colx(i) = no2colx(i) + espno2*no2x(nlayer)
291                     endif
292                  endif !Of if zenit.lt.60
293               !Other layers
294               else
295                  co2colx(i)  = co2colx(i) +
296     $                 esp(j) * (co2x(jj)+co2x(jj+1)) / 2.
297                  o2colx(i)   = o2colx(i) +
298     $                 esp(j) * (o2x(jj)+o2x(jj+1)) / 2.
299                  o3pcolx(i)  = o3pcolx(i) +
300     $                 esp(j) * (o3px(jj)+o3px(jj+1)) / 2.
301                  h2colx(i)   = h2colx(i) +
302     $                 esp(j) * (h2x(jj)+h2x(jj+1)) / 2.
303                  h2ocolx(i)  = h2ocolx(i) +
304     $                 esp(j) * (h2ox(jj)+h2ox(jj+1)) / 2.
305                  h2o2colx(i) = h2o2colx(i) +
306     $                 esp(j) * (h2o2x(jj)+h2o2x(jj+1)) / 2.
307                  cocolx(i)   = cocolx(i) +
308     $                 esp(j) * (cox(jj)+cox(jj+1)) / 2.
309                  hcolx(i)    = hcolx(i) +
310     $                 esp(j) * (hx(jj)+hx(jj+1)) / 2.
311                  !Only if O3 chemistry required
312                  if(chemthermod.ge.1)
313     $                 o3colx(i) = o3colx(i) +
314     $                 esp(j) * (o3x(jj)+o3x(jj+1)) / 2.
315                  !Only if N or ion chemistry requested
316                  if(chemthermod.ge.2) then
317                     n2colx(i)   = n2colx(i) +
318     $                 esp(j) * (n2x(jj)+n2x(jj+1)) / 2.
319                     ncolx(i)    = ncolx(i) +
320     $                    esp(j) * (nx(jj)+nx(jj+1)) / 2.
321                     nocolx(i)   = nocolx(i) +
322     $                    esp(j) * (nox(jj)+nox(jj+1)) / 2.
323                     no2colx(i)  = no2colx(i) +
324     $                    esp(j) * (no2x(jj)+no2x(jj+1)) / 2.
325                  endif
326               endif  !Of if jj.eq.nlayer
327            end do    !Of do j=1,nlayesp
328         endif        !Of ilayesp(nlayesp).eq.-1
329      enddo           !Of do i=nlayer,1,-1
330
331
332      end subroutine column
333
334
335c**********************************************************************
336c**********************************************************************
337
338      subroutine interfast(wm,wp,nm,p,nlayer,pin,nl,limdown,limup)
339C
340C subroutine to perform linear interpolation in pressure from 1D profile
341C escin(nl) sampled on pressure grid pin(nl) to profile
342C escout(nlayer) on pressure grid p(nlayer).
343C
344      real*8,intent(out) :: wm(nlayer),wp(nlayer) ! interpolation weights
345      integer,intent(out) :: nm(nlayer) ! index of nearest point
346      real*8,intent(in) :: pin(nl),p(nlayer)
347      real*8,intent(in) :: limup,limdown
348      integer,intent(in) :: nl,nlayer
349      integer :: n1,n,np,nini
350      logical,parameter :: extra_sanity_checks=.false.
351
352! Added sanity check: is input p(:) indeed monotonically increasing?
353      if (extra_sanity_checks) then
354       do nini=1,nlayer-1
355        if (p(nini).gt.p(nini+1)) then
356          write(*,*) "possible interfast issue, nini=",nini
357          write(*,*) "p(nini)=",p(nini),"> p(nini+1)=",p(nini+1)
358        endif
359       enddo
360      endif ! of if (extra_sanity_checks)
361
362      nini=1
363      do n1=1,nlayer
364         if(p(n1) .gt. limup .or. p(n1) .lt. limdown) then
365            wm(n1) = 0.d0
366            wp(n1) = 0.d0
367         else
368            do n = nini,nl-1
369               if (p(n1).ge.pin(n).and.p(n1).le.pin(n+1)) then
370                  nm(n1)=n
371                  np=n+1
372                  wm(n1)=abs(pin(n)-p(n1))/(pin(np)-pin(n))
373                  wp(n1)=1.d0 - wm(n1)
374                  nini = n
375                  exit
376               endif
377            enddo
378         endif
379      enddo
380
381! Added sanity check: does nm(:) indeed contain values
382! between 1 and nl-1 ?
383      if (extra_sanity_checks) then
384       if ((minval(nm)<1).or.(maxval(nm)>nl-1)) then
385        write(*,*) "interfast issue nm(:) contains incoherent values"
386        write(*,*) "  nm(:) values should be between 1 and ",nl-1
387        write(*,*) " but nm(:)=",nm(:)
388       endif
389      endif ! of if (extra_sanity_checks)
390
391      end subroutine interfast
392
393
394c**********************************************************************
395c**********************************************************************
396
397      subroutine espesor_optico_A (ig,capa,nlayer, szadeg,z,
398     @                   nz3,iz,esp,ilayesp,szalayesp,nlayesp, zmini)
399
400c     fgg              nov 03      Adaptation to Martian model
401c     malv             jul 03      Corrected z grid. Split in alt & frec codes
402c     fgg              feb 03      first version
403*************************************************************************
404
405      use param_v4_h, only: radio
406      implicit none
407
408c     arguments
409
410      real        szadeg                ! I. SZA [rad]
411      real        z                     ! I. altitude of interest [km]
412      integer     nz3,ig,nlayer         ! I. dimension of esp, ylayesp, etc...
413                                        !  (=2*nlayer= max# of layers in ray path)
414      real     iz(nlayer+1)              ! I. Altitude of each layer
415      real*8        esp(nz3)            ! O. layer widths after geometrically
416                                        !    amplified; in [cm] except at TOA
417                                        !    where an auxiliary value is used
418      real*8        ilayesp(nz3)        ! O. Indexes of layers along ray path
419      real*8        szalayesp(nz3)      ! O. SZA [deg]    "     "       "
420      integer       nlayesp
421!      real*8        nlayesp             ! O. # layers along ray path at this z
422      real*8        zmini               ! O. Minimum altitud of ray path [km]
423
424
425c     local variables and constants
426
427        integer     j,i,capa
428        integer     jmin                  ! index of min.altitude along ray path
429        real*8      szarad                ! SZA [deg]
430        real*8      zz
431        real*8      diz(nlayer+1)
432        real*8      rkmnz                 ! distance TOA to center of Planet [km]
433        real*8      rkmmini               ! distance zmini to center of P [km]
434        real*8      rkmj                  ! intermediate distance to C of P [km]
435c external function
436c        external  grid_R8          ! Returns index of layer containing the altitude
437c                                ! of interest, z; for example, if
438c                                ! zkm(i)=z or zkm(i)<z<zkm(i+1) => grid(z)=i
439c        integer   grid_R8
440
441*************************************************************************     
442        szarad = dble(szadeg)*3.141592d0/180.d0
443        zz=dble(z)
444        do i=1,nlayer
445           diz(i)=dble(iz(i))
446        enddo
447        do j=1,nz3
448          esp(j) = 0.d0
449          szalayesp(j) = 777.d0
450          ilayesp(j) = 0
451        enddo
452        nlayesp = 0
453
454        ! First case: szadeg<60
455        ! The optical thickness will be given by  1/cos(sza)
456        ! We deal with 2 different regions:
457        !   1: First, all layers between z and ztop ("upper part of ray")
458        !   2: Second, the layer at ztop
459        if(szadeg.lt.60.d0) then
460
461           zmini = zz
462           if(abs(zz-diz(nlayer)).lt.1.d-3) goto 1357
463           ! 1st Zone: Upper part of ray
464           !
465           do j=grid_R8(zz,diz,nlayer),nlayer-1
466             nlayesp = nlayesp + 1
467             ilayesp(nlayesp) = j
468             esp(nlayesp) = (diz(j+1)-diz(j)) / cos(szarad)        ! [km]
469             esp(nlayesp) = esp(nlayesp) * 1.d5                    ! [cm]
470             szalayesp(nlayesp) = szadeg
471           end do
472
473           !
474           ! 2nd Zone: Top layer
475 1357      continue
476           nlayesp = nlayesp + 1
477           ilayesp(nlayesp) = nlayer
478           esp(nlayesp) = 1.d0 / cos(szarad)         ! aux. non-dimens. factor
479           szalayesp(nlayesp) = szadeg
480
481
482        ! Second case:  60 < szadeg < 90
483        ! The optical thickness is evaluated.
484        !    (the magnitude of the effect of not using cos(sza) is 3.e-5
485        !     for z=60km & sza=30, and 5e-4 for z=60km & sza=60, approximately)
486        ! We deal with 2 different regions:
487        !   1: First, all layers between z and ztop ("upper part of ray")
488        !   2: Second, the layer at ztop ("uppermost layer")
489        else if(szadeg.le.90.d0.and.szadeg.ge.60.d0) then
490
491           zmini=(radio+zz)*sin(szarad)-radio
492           rkmmini = radio + zmini
493
494           if(abs(zz-diz(nlayer)).lt.1.d-4) goto 1470
495
496           ! 1st Zone: Upper part of ray
497           !
498           do j=grid_R8(zz,diz,nlayer),nlayer-1
499              nlayesp = nlayesp + 1
500              ilayesp(nlayesp) = j
501              esp(nlayesp) =
502     &             sqrt( (radio+diz(j+1))**2 - rkmmini**2 ) -
503     &             sqrt( (radio+diz(j))**2 - rkmmini**2 )           ! [km]
504              esp(nlayesp) = esp(nlayesp) * 1.d5                    ! [cm]
505              rkmj = radio+diz(j)
506              szalayesp(nlayesp) = asin( rkmmini/rkmj )             ! [rad]
507              szalayesp(nlayesp) = szalayesp(nlayesp) * 180.d0/3.141592 ! [deg]
508           end do
509 1470      continue
510           ! 2nd Zone:  Uppermost layer of ray.
511           !
512           nlayesp = nlayesp + 1
513           ilayesp(nlayesp) = nlayer
514           rkmnz = radio+diz(nlayer)
515           esp(nlayesp)  =  sqrt( rkmnz**2 - rkmmini**2 )       ! aux.factor[km]
516           esp(nlayesp)  =  esp(nlayesp) * 1.d5                 ! aux.f. [cm]
517           szalayesp(nlayesp) = asin( rkmmini/rkmnz )           ! [rad]
518           szalayesp(nlayesp) = szalayesp(nlayesp) * 180.d0/3.141592! [deg]
519
520
521        ! Third case:  szadeg > 90
522        ! The optical thickness is evaluated.
523        ! We deal with 5 different regions:
524        !   1: all layers between z and ztop ("upper part of ray")
525        !   2: the layer at ztop ("uppermost layer")
526        !   3: the lowest layer, at zmini
527        !   4: the layers increasing from zmini to z (here SZA<90)
528        !   5: the layers decreasing from z to zmini (here SZA>90)
529        else if(szadeg.gt.90.d0) then
530
531           zmini=(radio+zz)*sin(szarad)-radio
532           !zmini should be lower than zz, as SZA<90. However, in situations
533           !where SZA is very close to 90, rounding errors can make zmini
534           !slightly higher than zz, causing problems in the determination
535           !of the jmin index. A correction is implemented in the determination
536           !of jmin, some lines below
537           rkmmini = radio + zmini
538
539           if(zmini.lt.diz(1)) then         ! Can see the sun?  No => esp(j)=inft
540             nlayesp = nlayesp + 1
541             ilayesp(nlayesp) = - 1     ! Value to mark "no sun on view"
542!             esp(nlayesp) = 1.e30
543
544           else
545              jmin=grid_R8(zmini,diz,nlayer)+1
546              !Correction for possible rounding errors when SZA very close
547              !to 90 degrees
548              if(jmin.gt.grid_R8(zz,diz,nlayer)) then
549                 write(*,*)'jthermcalc warning: possible rounding error'
550                 write(*,*)'point,sza,layer:',ig,szadeg,capa
551                 jmin=grid_R8(zz,diz,nlayer)
552              endif
553
554              if(abs(zz-diz(nlayer)).lt.1.d-4) goto 9876
555
556              ! 1st Zone: Upper part of ray
557              !
558              do j=grid_R8(zz,diz,nlayer),nlayer-1
559                nlayesp = nlayesp + 1
560                ilayesp(nlayesp) = j
561                esp(nlayesp) =
562     $                sqrt( (radio+diz(j+1))**2 - rkmmini**2 ) -
563     $                sqrt( (radio+diz(j))**2 - rkmmini**2 )          ! [km]
564                esp(nlayesp) = esp(nlayesp) * 1.d5                    ! [cm]
565                rkmj = radio+diz(j)
566                szalayesp(nlayesp) = asin( rkmmini/rkmj )              ! [rad]
567                szalayesp(nlayesp) = szalayesp(nlayesp) *180.d0/3.141592      ! [deg]
568              end do
569
570 9876         continue
571              ! 2nd Zone:  Uppermost layer of ray.
572              !
573              nlayesp = nlayesp + 1
574              ilayesp(nlayesp) = nlayer
575              rkmnz = radio+diz(nlayer)
576              esp(nlayesp) =  sqrt( rkmnz**2 - rkmmini**2 )      !aux.factor[km]
577              esp(nlayesp) = esp(nlayesp) * 1.d5                 !aux.f.[cm]
578              szalayesp(nlayesp) = asin( rkmmini/rkmnz )           ! [rad]
579              szalayesp(nlayesp) = szalayesp(nlayesp) *180.d0/3.141592 ! [deg]
580
581              ! 3er Zone: Lowestmost layer of ray
582              !
583              if ( jmin .ge. 2 ) then      ! If above the planet's surface
584                j=jmin-1
585                nlayesp = nlayesp + 1
586                ilayesp(nlayesp) = j
587                esp(nlayesp) = 2. *
588     $                 sqrt( (radio+diz(j+1))**2 -rkmmini**2 )       ! [km]
589                esp(nlayesp) = esp(nlayesp) * 1.d5                   ! [cm]
590                rkmj = radio+diz(j+1)
591                szalayesp(nlayesp) = asin( rkmmini/rkmj ) ! [rad]
592                szalayesp(nlayesp) = szalayesp(nlayesp) *180.d0/3.141592 ! [deg]
593              endif
594
595              ! 4th zone: Lower part of ray, increasing from zmin to z
596              !    ( layers with SZA < 90 deg )
597              do j=jmin,grid_R8(zz,diz,nlayer)-1
598                nlayesp = nlayesp + 1
599                ilayesp(nlayesp) = j
600                esp(nlayesp) =
601     $                    sqrt( (radio+diz(j+1))**2 - rkmmini**2 )
602     $                  - sqrt( (radio+diz(j))**2 - rkmmini**2 )       ! [km]
603                esp(nlayesp) = esp(nlayesp) * 1.d5                     ! [cm]
604                rkmj = radio+diz(j)
605                szalayesp(nlayesp) = asin( rkmmini/rkmj )              ! [rad]
606                szalayesp(nlayesp) = szalayesp(nlayesp) *180.d0/3.141592 ! [deg]
607              end do
608
609              ! 5th zone: Lower part of ray, decreasing from z to zmin
610              !    ( layers with SZA > 90 deg )
611              do j=grid_R8(zz,diz,nlayer)-1, jmin, -1
612                nlayesp = nlayesp + 1
613                ilayesp(nlayesp) = j
614                esp(nlayesp) =
615     $                    sqrt( (radio+diz(j+1))**2 - rkmmini**2 )
616     $                  - sqrt( (radio+diz(j))**2 - rkmmini**2 )        ! [km]
617                esp(nlayesp) = esp(nlayesp) * 1.d5                      ! [cm]
618                rkmj = radio+diz(j)
619                szalayesp(nlayesp) = 3.141592 - asin( rkmmini/rkmj )          ! [rad]
620                szalayesp(nlayesp) = szalayesp(nlayesp)*180.d0/3.141592 ! [deg]
621              end do
622
623           end if
624
625        end if
626
627
628        end subroutine espesor_optico_A
629
630
631
632c**********************************************************************
633c***********************************************************************
634
635        function grid_R8 (z, zgrid, nz)
636
637c Returns the index where z is located within vector zgrid
638c The vector zgrid must be monotonously increasing, otherwise program stops.
639c If z is outside zgrid limits, or zgrid dimension is nz<2, the program stops.
640c
641c FGG     Aug-2004     Correct z.lt.zgrid(i) to .le.
642c MALV    Jul-2003
643c***********************************************************************
644
645        implicit none
646
647c Arguments
648        integer   nz
649        real*8      z
650        real*8      zgrid(nz)
651        integer   grid_R8
652
653c Local 
654        integer   i, nz1, nznew
655
656c*** CODE START
657
658        if ( z .lt. zgrid(1)  ) then
659           write (*,*) ' GRID/ z outside bounds of zgrid '
660           write (*,*) ' z,zgrid(1),zgrid(nz) =', z,zgrid(1),zgrid(nz)
661           z = zgrid(1)
662           write(*,*) 'WARNING: error in grid_r8 (jthermcalc.F)'
663           write(*,*) 'Please check values of z and zgrid above'
664        endif
665        if (z .gt. zgrid(nz) ) then
666           write (*,*) ' GRID/ z outside bounds of zgrid '
667           write (*,*) ' z,zgrid(1),zgrid(nz) =', z,zgrid(1),zgrid(nz)
668           z = zgrid(nz)
669           write(*,*) 'WARNING: error in grid_r8 (jthermcalc.F)'
670           write(*,*) 'Please check values of z and zgrid above'
671        endif
672        if ( nz .lt. 2 ) then
673           write (*,*) ' GRID/ zgrid needs 2 points at least ! '
674           stop ' Serious error in GRID.F '
675        endif
676        if ( zgrid(1) .ge. zgrid(nz) ) then
677           write (*,*) ' GRID/ zgrid must increase with index'
678           stop ' Serious error in GRID.F '
679        endif
680
681        nz1 = 1
682        nznew = nz/2
683        if ( z .gt. zgrid(nznew) ) then
684           nz1 = nznew
685           nznew = nz
686        endif
687        do i=nz1+1,nznew
688           if ( z. eq. zgrid(i) ) then
689              grid_R8=i
690              return
691              elseif ( z .le. zgrid(i) ) then
692              grid_R8 = i-1
693              return
694           endif
695        enddo
696        grid_R8 = nz
697
698
699
700        end function grid_R8
701
702
703
704!c***************************************************
705!c***************************************************
706
707      subroutine flujo(date)
708
709
710!c     fgg           nov 2002     first version
711!c***************************************************
712
713      use comsaison_h, only: dist_sol
714      use param_v4_h, only: ninter,
715     .                      fluxtop, ct1, ct2, p1, p2
716      use callkeys_mod, only: solvarmod
717      implicit none
718
719
720!     Arguments
721
722      real,intent(inout) :: date
723
724
725!     Local variable and constants
726
727      integer i
728      integer inter
729      real    nada
730
731!c*************************************************
732
733      if(date.lt.1985.) date=1985.
734      if(date.gt.2001.) date=2001.
735     
736      do i=1,ninter
737         fluxtop(i)=1.
738         !Variation of solar flux with 11 years solar cycle
739         !For more details, see Gonzalez-Galindo et al. 2005
740         !To be improved in next versions
741        if(i.le.24.and.solvarmod.eq.0) then
742            fluxtop(i)=(((ct1(i)+p1(i)*date)/2.)                 
743     $           *sin(2.*3.1416/11.*(date-1985.-3.1416))         
744     $           +(ct2(i)+p2(i)*date)+1.)*fluxtop(i)
745         end if
746         fluxtop(i)=fluxtop(i)*(1.52/dist_sol)**2
747      end do
748     
749      end subroutine flujo
750
751      end module jthermcalc_util
Note: See TracBrowser for help on using the repository browser.