| 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 |
|---|