[253] | 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 |
---|