source: trunk/LMDZ.GENERIC/utilities/generate_kmatrix.F90 @ 1217

Last change on this file since 1217 was 253, checked in by emillour, 13 years ago

Generic GCM

  • Massive update to version 0.7

EM+RW

File size: 13.6 KB
Line 
1      program generate_kmatrix
2      implicit none
3
4!     -------------------------------------------------------------
5!     Purpose: to read hires spectra and produce kdistribution data
6!     Authour: Robin Wordsworth (2010)
7!     -------------------------------------------------------------
8
9      integer nmolec,mol
10      integer i,j,k,im
11      integer Nb
12
13      character*4 fname
14      character*32 fnum
15
16      integer iT, iP, iQ, Nlevs
17
18      double precision nuT, sigT, kT
19
20      integer Nq
21      parameter (Nq=16) ! we choose this here
22
23      integer Nmax
24      parameter (Nmax=1000) ! maximum number of levels
25
26      integer Nmol_max
27      parameter (Nmol_max=10) ! maximum number of radiatively active species
28
29      integer Nkmax
30      ! large array = slow calculation... this makes a huge difference
31      !parameter (Nkmax=50000) ! works for IR, 27 bands
32      !parameter (Nkmax=100000) ! works for IR, 27 bands
33      !parameter (Nkmax=140000) ! works for IR, 32 bands
34      !parameter (Nkmax=250000) ! works for VI, 36 bands
35      parameter (Nkmax=400000) ! works for IR, 8 bands
36      !parameter (Nkmax=400000) ! works for VI, 12 bands
37      !parameter (Nkmax=200000) ! works for IR, 30 bands
38
39      integer NbMAX
40      parameter (NbMAX=100)
41
42      integer Ngres
43      parameter (Ngres=200)
44
45      character*10 molec_names(1:Nmol_max)
46      double precision T(1:Nmax), P(1:Nmax), Q(1:Nmax)
47
48
49      double precision pi
50      parameter (pi=3.14159265)
51      double precision x
52      double precision y(1:Nq+2)
53
54      double precision nu_min(1:NbMAX) ! make allocatable?
55      double precision nu_max(1:NbMAX)
56
57      integer quad, band
58
59      double precision ktemp(1:Nq)
60      double precision w(1:Nq), gw(1:Nq)
61
62      double precision, allocatable :: kdist_temp(:)
63      double precision, allocatable :: kdist(:,:,:,:,:)
64
65      double precision nuband(1:Nkmax), kband(1:Nkmax), nuwband(1:Nkmax) ! better static I think
66      double precision nuwbtot
67
68      double precision gfine(1:Ngres)     
69      double precision klevs(1:Ngres)
70      double precision addline(1:Nkmax)
71
72      double precision kmax, kmin, lkmax, lkmin, dlogK, klev
73      integer ic, ib, ig, ik1, ik2
74
75      integer filerr
76      logical filexi
77
78      logical addCIA
79      integer iCO2
80      double precision k1,k2,kCIA,amg,Pp
81
82      real truemean, distmean, etot
83     
84
85      addCIA=.false.
86
87      print*,'Creating the GCM correlated-k data...'
88      print*,' '
89
90      !--------------------------------------------------------
91      ! load temperature, pressure, mixing ratio data
92      open(9,file='T.dat')
93      read(9,*) iT
94      do i=1,iT
95         read(9,*) T(i)
96      enddo
97      close(9)
98
99      open(10,file='p.dat')
100      read(10,*) iP
101      do i=1,iP
102         read(10,*) P(i)
103         P(i)=10.**P(i)  ! note we keep P in millibars for the conversion later
104      enddo
105      close(10)
106
107      open(11,file='Q.dat')
108      read(11,*) nmolec
109      do mol=1,nmolec
110         read(11,*) molec_names(mol)
111      enddo
112      read(11,*) iQ
113      do i=1,iQ
114         read(11,*) Q(i)
115      enddo
116      close(11)
117
118      Nlevs=iT*iP*iQ ! total number of layers
119
120      print*,'Temperature layers:  ',iT
121      print*,'Pressure layers:     ',iP
122      print*,'Mixing ratio layers: ',iQ
123      print*,'Total:               ',Nlevs
124
125
126      if(addCIA)then
127
128         if(nmolec.gt.2)then
129            print*,'I cant deal with this situation yet'
130            call abort
131         endif
132
133         iCO2=0
134         do mol=1,nmolec
135            if(molec_names(mol).eq.'CO2')then
136               iCO2=mol
137            endif
138         enddo
139
140         !if(iCO2.eq.1)then
141         print*,' '
142         print*,'--- Adding CO2 CIA ---'
143         !else
144         !   print*,'Warning, not CO2+H2O mixture, need CO2 mixing ratio'
145         !   call abort
146         !endif
147      endif
148
149      !--------------------------------------------------------
150      ! load spectral data
151      open(12,file='narrowbands.in')
152      read(12,*) Nb
153
154      do band=1,Nb
155         read(12,*) nu_min(band),nu_max(band)
156      enddo
157      close(12)
158
159      print*,' '
160      print*,'Number of spectral bands: ',Nb
161
162      print*,'Band limits:'
163      do band=1,Nb
164         print*,band,'-->',nu_min(band),nu_max(band),' cm^-1'
165      end do
166
167      !--------------------------------------------------------
168      ! create g-space data
169      do quad=0,Nq+1
170         x=dble(quad)/dble(Nq+2)
171         !y(quad+1)=sin(pi*x)*exp(-5*x)
172         !y(quad+1)=sin(pi*x)*exp(-9*x)  ! CO2_H2Ovar 38x36
173         y(quad+1)=sin(pi*x)*exp(-12*x)
174         !y(quad+1)=sin(pi*x)*exp(-15*x) ! CO2_CH4
175      enddo
176
177      do quad=1,Nq
178         w(quad)=y(quad+1)
179      enddo
180      w=w/sum(w)
181
182      print*,' '
183      print*,'Number of g-space intervals: ',Nq
184
185      print*,'g-space weighting:'
186      do quad=1,Nq
187         print*,quad,'-->',w(quad)
188      end do
189
190      ! write g-space data
191      open(14,file='g.dat')
192      write(14,*) Nq+1
193
194      do quad=1,Nq
195         write(14,*) w(quad)
196      enddo
197      write(14,*) 0.0
198      close(14)
199
200      ! cumulative sum for g-vector
201      gw(1)=w(1)
202      do quad=2,Nq
203         gw(quad)=gw(quad-1)+w(quad)
204      enddo
205
206      ! allocate 5D matrices
207      allocate(kdist_temp(Nq))
208      allocate(kdist(iT,iP,iQ,Nb,Nq+1))
209
210
211      nuT=0.0
212      do i=1,iQ
213         do j=1,iP
214
215
216            if(addCIA.and.(iCO2.eq.1))then
217               Pp=P(j)*(1.0-Q(i))
218            else
219               Pp=P(j)*Q(i)
220            endif
221            !if(addCIA) Pp=P(j)*(1.0-Q(i))
222
223
224            do k=1,iT             
225               im = (i-1)*iP*iT + (j-1)*iT + k
226
227               !-----------------------------------------------
228               ! open kspectrum file
229               write(fnum,*) im
230               if(im<10)then
231                   fname='k00'//trim(adjustl(fnum))
232               elseif(im<100)then
233                   fname='k0'//trim(adjustl(fnum))
234               else
235                   fname='k'//trim(adjustl(fnum))
236               endif
237
238               ! check that the file exists
239               inquire(FILE='hires_spectrum/'//fname,EXIST=filexi)
240               if(.not.filexi) then
241                  write(*,*)'The file ',fname(1:LEN_TRIM(fname))
242                  write(*,*)'was not found in the folder hires_spectrum, exiting.'
243                  call abort
244               endif
245
246               print*,'Opening file ',fname(1:LEN_TRIM(fname))
247               open(17,file='hires_spectrum/'//fname)
248
249               nuT=0.0
250               do band=1,Nb
251               print*,'Band ---> ',band
252
253                  !--------------------------------------------
254                  ! write kdata to temporary band arrays
255                  ! and find max / min k-values in band
256                  do while (nuT.lt.nu_min(band))
257                      read(17,*,IOSTAT=filerr) nuT, sigT, kT
258                   ! ideally need to catch all errors here (ask Ehouarn)
259                      if(filerr.lt.0)then
260                         print*,    &
261                             'nu_min greater than highest value in file'
262                         print*,'IOSTAT=',filerr
263                         print*,'nu_min=',nu_min(band)
264                         print*,'nu_endoffile=',nuT
265                         call abort
266                      endif
267                  enddo
268
269                  ic=1
270                  kmin=kT
271                  kmax=kT
272                  nuband(:)=0
273                  kband(:)=0
274
275                  do while (nuT.lt.nu_max(band))
276
277                      nuband(ic)=nuT
278                      kband(ic)=kT
279
280                      ! insert CIA option here
281                      if(addCIA)then
282
283                         k1=0.0
284                         k2=0.0
285                         if(nuT.lt.500.0) call getspc(T(k),nuT,k1)
286                         if((nuT.gt.1000.0).and.(nuT.lt.1800.0)) call baranov(T(k),nuT,k2)
287                         ! cm^-1.amagat^2
288
289                         amg=273.15D+0/T(k)*(Pp/1013.25) ! amagats of CO2
290
291                         kCIA=(k1+k2)*1.0D+2*amg**2.0D+0 ! m^-1
292                         kband(ic)=kband(ic)+kCIA
293                         kT=kband(ic)
294
295                         !kband(ic)=kCIA
296                         !kT=kCIA
297                         !if(nuband(ic).gt.1250.0)then
298                         !      print*,'P=',P(i)
299                         !      print*,'T=',T(k)
300                         !      print*,'amg=',amg
301                         !      print*,'nu=',nuband(ic)
302                         !       print*,'k1=',k1
303                         !       print*,'k2=',k2
304                         !       print*,'kCIA=',kCIA
305                         !      call abort
306                         !endif
307
308                      endif
309
310                      if(kT.lt.kmin)then
311                        kmin=kT
312                      endif
313                      if(kT.gt.kmax)then ! bug corrected!
314                        kmax=kT
315                      endif
316
317                      read(17,*,IOSTAT=filerr) nuT, sigT, kT
318                      if(filerr.lt.0)then
319                         print*,    &
320                             'nu_max greater than highest value in file'
321                         print*,'IOSTAT=',filerr
322                         print*,'nu_max=',nu_max(band)
323                         print*,'nu_endoffile=',nuT
324                         call abort
325                      endif
326
327
328                      ic=ic+1
329                     
330                      if(ic.gt.Nkmax)then
331                         print*,'Spectral resolution too low for these bands, exiting!'
332                         print*,'Increase Nkmax in generate_kmatrix.F90.'
333                         call abort
334                      endif
335
336                  enddo
337                  nuband(ic)=nuT
338                  kband(ic)=kT
339
340                  if(kmax.le.0.0)then
341                  !if(kmax.le.1.0e-15)then
342                     print*,'kmax=',kmax
343                     print*,'Setting values to zero in this band.'
344                     kdist(k,j,i,band,1:(Nq+1))=0.0
345                  else
346
347                  if(kmin.lt.1e-30)then
348                     kmin=1.0e-30
349                  endif
350
351                  !--------------------------------------------
352                  ! calculate delta nu values
353                  nuwband(:)=0.0
354                  do ib=2,(ic-1)
355                      nuwband(ib)=(nuband(ib+1)-nuband(ib-1))/2
356                  enddo
357                  nuwband(1)=nuwband(2)
358                  nuwband(ic)=nuwband(ic-1) ! causes tiny boundary error; whatever
359                  nuwbtot=sum(nuwband)
360
361                  lkmax=log10(kmax)
362                  lkmin=log10(kmin)
363                 
364                  dlogK=(lkmax-lkmin)/(Ngres-1)                 
365
366                  !--------------------------------------------
367                  ! calculate the g function
368                  gfine(:)=0.0
369                  do ig=1,Ngres
370                    klev=lkmin + dble(ig)*dlogK
371                    klev=10**klev
372                    klevs(ig)=klev
373
374                    addline(:)=0
375                    do ib=1,ic
376                        if(kband(ib).lt.klev)then
377                           addline(ib)=1.0
378                        endif
379                    enddo
380                    gfine(ig)=sum(addline(:)*nuwband(:))/nuwbtot
381
382                  enddo
383                  print*,'gnorm    = ',gfine(Ngres)
384
385                  !--------------------------------------------
386                  ! invert the g function
387                  ik1=1
388                  ik2=1
389                  kdist_temp(:)=0.0
390                  do quad=1,Nq
391                   
392                    ik2=ik1
393
394                    gfind: do while (gfine(ik2).lt.gw(quad))
395                       ik2=ik2+1
396                       if(ik2.gt.Ngres)then
397                          print*,'g-inversion overflow...'
398                          ik2=Ngres
399                          exit gfind
400                       endif
401                    enddo gfind
402
403                    !if(ik2.gt.Ngres)then ! avoid out-of-bounds on final step
404                    !   ik2=Ngres
405                    !endif
406
407
408                     if(.not.(ik1.ge.ik2))then ! this could probably be improved
409                        !kdist_temp(quad)=sum(klevs(ik1:ik2))/(ik2-ik1) ! a bug was here!
410                        kdist_temp(quad)=sum(klevs(ik1:ik2))/(ik2+1-ik1)
411
412
413                     elseif(quad.ne.1)then
414                        kdist_temp(quad)=kdist_temp(quad-1)
415                     else
416                        kdist_temp(quad)=kmin
417                     endif
418
419                     !-----------------------------------------
420                     ! assign to 5D matrix and convert to cm^2 / molecule
421                     kdist(k,j,i,band,quad)=1.3807e-21 *               &
422                                kdist_temp(quad) * T(k)/P(j)
423
424                     ik1=ik2
425                  enddo ! g-space
426                  kdist(k,j,i,band,Nq+1)=0.0
427
428                  truemean = sum(kband(1:ic)*nuwband(1:ic))/sum(nuwband(1:ic))
429                  distmean = sum(kdist_temp(:)*w(:))/sum(w)
430                  etot     = 100*abs(truemean-distmean)/(distmean+truemean)
431                  print*,'truemean = ',truemean
432                  print*,'distmean = ',distmean
433                  !print*,'kdisttemp = ',kdist_temp(Nq)
434                  !print*,'kdistmax  = ',kmax
435                  print*,'etot (%) = ',etot
436                  !print*,'w  = ',w
437
438                  endif ! if kmax .le. 0.0
439
440               enddo ! bands
441
442            enddo
443         enddo
444      enddo
445
446      !--------------------------------------------------------
447      ! save data and clean up
448      close(17)
449      open(14,file='corrk_gcm.dat',form='formatted')
450      write(14,*) kdist
451      close(14)
452      print*,' '
453      print*,'Correlated-k data saved in corrk_gcm.dat'
454      print*,' '
455      print*,'Now you must change the values of L_NTREF etc. in radinc_h.F90 (if necessary)'
456      print*,'and the variable "corrkdata" in callphys.def'
457
458      deallocate(kdist_temp)
459      deallocate(kdist)
460
461    end program generate_kmatrix
Note: See TracBrowser for help on using the repository browser.