90 function load_o3prog(this, file, fileID)
result (err_message)
92 integer,
intent(in) :: fileid
93 character(len=*),
intent(in) :: file
94 character(len=128) :: err_message
95 integer :: i1, i2, i3, ierr
96 real(kind=4), dimension(:),
allocatable :: lat4, pres4, time4, tempin
97 real(kind=4) :: blatc4
103 open(unit=fileid,file=trim(file), form=
'unformatted', convert=
'big_endian', iostat=ierr, iomsg=err_message)
104 if (ierr /= 0 )
return
105 read (fileid, iostat=ierr, iomsg=err_message) this%ncf, this%nlat, this%nlev, this%ntime
106 if (ierr /= 0 )
return
109 allocate (this%lat(this%nlat))
110 allocate (this%pres(this%nlev))
111 allocate (this%po3(this%nlev))
112 allocate (this%time(this%ntime+1))
113 allocate (this%data(this%nlat,this%nlev,this%ncf,this%ntime))
115 allocate(lat4(this%nlat), pres4(this%nlev), time4(this%ntime+1))
116 read (fileid, iostat=ierr, iomsg=err_message) this%ncf, this%nlat, this%nlev, this%ntime, lat4, pres4, time4
117 if (ierr /= 0 )
return
120 this%pres(:) = pres4(:)
121 this%po3(:) = log(100.0*this%pres(:))
122 this%lat(:) = lat4(:)
123 this%time(:) = time4(:)
124 deallocate(lat4, pres4, time4)
126 allocate(tempin(this%nlat))
130 read(fileid, iostat=ierr, iomsg=err_message) tempin
131 if (ierr /= 0 )
return
132 this%data(:,i3,i2,i1) = tempin(:)
170 subroutine update_o3prog(this, idx1, idx2, idxh, rjday, idxt1, idxt2, ozpl)
172 integer,
intent(in) :: idx1(:), idx2(:)
173 real(kind_phys),
intent(in) :: idxh(:)
174 real(kind_phys),
intent(in) :: rjday
175 integer,
intent(in) :: idxt1, idxt2
176 real(kind_phys),
intent(out) :: ozpl(:,:,:)
177 integer :: nc, l, j, j1, j2
178 real(kind_phys) :: tem, tx1, tx2
180 tx1 = (this%time(idxt2) - rjday) / (this%time(idxt2) - this%time(idxt1))
185 do j=1,
size(ozpl(:,1,1))
189 ozpl(j,l,nc) = tx1*(tem*this%data(j1,l,nc,idxt1)+idxh(j)*this%data(j2,l,nc,idxt1)) &
190 + tx2*(tem*this%data(j1,l,nc,idxt2)+idxh(j)*this%data(j2,l,nc,idxt2))
200 subroutine run_o3prog_2015(this, con_1ovg, dt, p, t, dp, ozpl, oz, do3_dt_prd, &
201 do3_dt_ozmx, do3_dt_temp, do3_dt_ohoz)
204 real(kind_phys),
intent(in) :: &
206 real(kind_phys),
intent(in) :: &
208 real(kind_phys),
intent(in),
dimension(:,:) :: &
212 real(kind_phys),
intent(in),
dimension(:,:,:) :: &
214 real(kind_phys),
intent(inout),
dimension(:,:) :: &
216 real(kind_phys),
intent(inout),
dimension(:,:),
optional :: &
222 integer :: k, kmax, kmin, iLev, iCol, nCol, nLev, iCf
223 logical,
dimension(size(p,1)) :: flg
224 real(kind_phys) :: pmax, pmin, tem, temp
225 real(kind_phys),
dimension(size(p,1)) :: wk1, wk2, wk3, ozib
226 real(kind_phys),
dimension(size(p,1),this%ncf) :: prod
227 real(kind_phys),
dimension(size(p,1),size(p,2)) :: ozi
228 real(kind_phys),
dimension(size(p,1),size(p,2)+1) :: colo3, coloz
237 colo3(:,nlev+1) = 0.0
238 coloz(:,nlev+1) = 0.0
245 wk1(icol) = log(p(icol,ilev))
246 pmin = min(wk1(icol), pmin)
247 pmax = max(wk1(icol), pmax)
248 prod(icol,:) = 0._kind_phys
253 if (pmin < this%po3(k)) kmax = k
254 if (pmax < this%po3(k)) kmin = k
258 temp = 1.0 / (this%po3(k) - this%po3(k+1))
261 if (wk1(icol) < this%po3(k) .and. wk1(icol) >= this%po3(k+1))
then
263 wk2(icol) = (wk1(icol) - this%po3(k+1)) * temp
264 wk3(icol) = 1.0 - wk2(icol)
270 prod(icol,icf) = wk2(icol) * ozpl(icol,k,icf) + wk3(icol) * ozpl(icol,k+1,icf)
278 if (wk1(icol) < this%po3(this%nlev))
then
279 prod(icol,icf) = ozpl(icol,this%nlev,icf)
281 if (wk1(icol) >= this%po3(1))
then
282 prod(icol,icf) = ozpl(icol,1,icf)
287 colo3(icol,ilev) = colo3(icol,ilev+1) + ozi(icol,ilev) * dp(icol,ilev)*con_1ovg
288 coloz(icol,ilev) = coloz(icol,ilev+1) + prod(icol,6) * dp(icol,ilev)*con_1ovg
289 prod(icol,2) = min(prod(icol,2), 0.0)
292 ozib(icol) = ozi(icol,ilev)
293 tem = prod(icol,1) - prod(icol,2) * prod(icol,6) &
294 + prod(icol,3) * (t(icol,ilev) - prod(icol,5)) &
295 + prod(icol,4) * (colo3(icol,ilev)-coloz(icol,ilev))
296 oz(icol,ilev) = (ozib(icol) + tem*dt) / (1.0 - prod(icol,2)*dt)
300 if (
present(do3_dt_prd)) do3_dt_prd(:,ilev) = prod(:,1) * dt
301 if (
present(do3_dt_ozmx)) do3_dt_ozmx(:,ilev) = prod(:,2) * (oz(:,ilev) - prod(:,6)) * dt
302 if (
present(do3_dt_temp)) do3_dt_temp(:,ilev) = prod(:,3)*(t(:,ilev)-prod(:,5))*dt
303 if (
present(do3_dt_ohoz)) do3_dt_ohoz(:,ilev) = prod(:,4) * (colo3(:,ilev)-coloz(:,ilev))*dt
313 subroutine run_o3prog_2006(this, con_1ovg, dt, p, t, dp, ozpl, oz, do3_dt_prd, &
314 do3_dt_ozmx, do3_dt_temp, do3_dt_ohoz)
317 real(kind_phys),
intent(in) :: &
319 real(kind_phys),
intent(in) :: &
321 real(kind_phys),
intent(in),
dimension(:,:) :: &
325 real(kind_phys),
intent(in),
dimension(:,:,:) :: &
327 real(kind_phys),
intent(inout),
dimension(:,:) :: &
329 real(kind_phys),
intent(inout),
dimension(:,:),
optional :: &
336 integer :: k, kmax, kmin, iLev, iCol, nCol, nLev, iCf
337 logical,
dimension(size(p,1)) :: flg
338 real(kind_phys) :: pmax, pmin, tem, temp
339 real(kind_phys),
dimension(size(p,1)) :: wk1, wk2, wk3, ozib
340 real(kind_phys),
dimension(size(p,1),this%ncf) :: prod
341 real(kind_phys),
dimension(size(p,1),size(p,2)) :: ozi
342 real(kind_phys),
dimension(size(p,1),size(p,2)+1) :: colo3, coloz
352 if (this%ncf > 2)
then
353 colo3(:,nlev+1) = 0.0
356 colo3(icol,ilev) = colo3(icol,ilev+1) + ozi(icol,ilev) * dp(icol,ilev) * con_1ovg
367 wk1(icol) = log(p(icol,ilev))
368 pmin = min(wk1(icol), pmin)
369 pmax = max(wk1(icol), pmax)
370 prod(icol,:) = 0._kind_phys
375 if (pmin < this%po3(k)) kmax = k
376 if (pmax < this%po3(k)) kmin = k
380 temp = 1.0 / (this%po3(k) - this%po3(k+1))
383 if (wk1(icol) < this%po3(k) .and. wk1(icol) >= this%po3(k+1))
then
385 wk2(icol) = (wk1(icol) - this%po3(k+1)) * temp
386 wk3(icol) = 1.0 - wk2(icol)
392 prod(icol,icf) = wk2(icol) * ozpl(icol,k,icf) + wk3(icol) * ozpl(icol,k+1,icf)
400 if (wk1(icol) < this%po3(this%nlev))
then
401 prod(icol,icf) = ozpl(icol,this%nlev,icf)
403 if (wk1(icol) >= this%po3(1))
then
404 prod(icol,icf) = ozpl(icol,1,icf)
409 if (this%ncf == 2)
then
411 ozib(icol) = ozi(icol,ilev)
412 oz(icol,ilev) = (ozib(icol) + prod(icol,1)*dt) / (1.0 + prod(icol,2)*dt)
416 if (this%ncf == 4)
then
418 ozib(icol) = ozi(icol,ilev)
419 tem = prod(icol,1) + prod(icol,3)*t(icol,ilev) + prod(icol,4)*colo3(icol,ilev+1)
420 oz(icol,ilev) = (ozib(icol) + tem*dt) / (1.0 + prod(icol,2)*dt)
425 if (
present(do3_dt_prd)) do3_dt_prd(:,ilev) = prod(:,1)*dt
426 if (
present(do3_dt_ozmx)) do3_dt_ozmx(:,ilev) = (oz(:,ilev) - ozib(:))
427 if (
present(do3_dt_temp)) do3_dt_temp(:,ilev) = prod(:,3) * t(:,ilev) * dt
428 if (
present(do3_dt_ohoz)) do3_dt_ohoz(:,ilev) = prod(:,4) * colo3(:,ilev) * dt
436 subroutine run_o3clim(this, lat, prslk, con_pi, oz)
438 real(kind_phys),
intent(in) :: &
440 real(kind_phys),
intent(in),
dimension(:) :: &
442 real(kind_phys),
intent(in),
dimension(:,:) :: &
444 real(kind_phys),
intent(out),
dimension(:,:) :: &
447 integer :: nCol, iCol, nLev, iLev, j, j1, j2, l, ll
448 real(kind_phys) :: elte, deglat, tem, tem1, tem2, tem3, tem4, temp
449 real(kind_phys),
allocatable :: o3i(:,:),wk1(:)
452 ncol =
size(prslk(:,1))
453 nlev =
size(prslk(1,:))
454 allocate(o3i(ncol, this%nlevc),wk1(ncol))
457 top_at_1 = (prslk(1,1) .lt. prslk(1, nlev))
459 elte = this%blatc + (this%nlatc-1)*this%dphiozc
462 deglat = lat(icol) * 180.0 / con_pi
463 if (deglat > this%blatc .and. deglat < elte)
then
464 tem1 = (deglat - this%blatc) / this%dphiozc + 1
468 elseif (deglat <= this%blatc)
then
472 elseif (deglat >= elte)
then
480 tem3 = tem2*this%datac(j1,j,this%k1oz) + tem1*this%datac(j2,j,this%k1oz)
481 tem4 = tem2*this%datac(j1,j,this%k2oz) + tem1*this%datac(j2,j,this%k2oz)
482 o3i(icol,j) = tem4*this%facoz + tem3*(1.0 - this%facoz)
488 if (.not. top_at_1) ll = nlev - ilev + 1
491 wk1(icol) = prslk(icol,ll)
494 do j = 1, this%nlevc-1
495 temp = 1.0 / (this%pkstr(j+1) - this%pkstr(j))
497 if (wk1(icol) > this%pkstr(j) .and. wk1(icol) <= this%pkstr(j+1))
then
498 tem = (this%pkstr(j+1) - wk1(icol)) * temp
499 oz(icol,ll) = tem * o3i(icol,j) + (1.0 - tem) * o3i(icol,j+1)
505 if (wk1(icol) > this%pkstr(this%nlevc)) oz(icol,ll) = o3i(icol,this%nlevc)
506 if (wk1(icol) < this%pkstr(1)) oz(icol,ll) = o3i(icol,1)
514 function load_o3clim(this, file, fileID)
result (err_message)
516 integer,
intent(in) :: fileid
517 character(len=*),
intent(in) :: file
518 character(len=128) :: err_message
521 real(kind=4) :: blatc4
522 integer :: ilev, ilat, imo, ierr
523 real(kind=4), allocatable :: o3clim4(:,:,:), pstr4(:)
524 integer,
allocatable :: imond(:), ilatt(:,:)
529 open(unit=fileid,file=trim(file),form=
'unformatted',convert=
'big_endian', iostat=ierr, iomsg=err_message)
530 if (ierr /= 0 )
return
531 read (fileid,
end=101,iostat=ierr,iomsg=err_message) this%nlatc, this%nlevc, this%ntimec, blatc4
532 if (ierr /= 0 )
return
534101
if (this%nlevc < 10 .or. this%nlevc > 100)
then
546 this%dphiozc = -(this%blatc+this%blatc)/(this%nlatc-1)
548 allocate (o3clim4(this%nlatc,this%nlevc,12), pstr4(this%nlevc), imond(12), ilatt(this%nlatc,12) )
550 allocate (this%pkstr(this%nlevc), this%pstr(this%nlevc), this%datac(this%nlatc,this%nlevc,12))
551 if ( this%nlevc == 17 )
then
552 do ilev = 1, this%nlevc
553 read (fileid,15,iostat=ierr,iomsg=err_message) pstr4(ilev)
554 if (ierr /= 0 )
return
559 do ilat = 1, this%nlatc
560 read (fileid,16,iostat=ierr,iomsg=err_message) imond(imo), ilatt(ilat,imo), (o3clim4(ilat,ilev,imo),ilev=1,10)
561 if (ierr /= 0 )
return
56216
format(i2,i4,10f6.2)
563 read (fileid,20,iostat=ierr,iomsg=err_message) (o3clim4(ilat,ilev,imo),ilev=11,this%nlevc)
564 if (ierr /= 0 )
return
570 do ilev = 1, this%nlevc
571 read (fileid) pstr4(ilev)
575 do ilev = 1, this%nlevc
576 read (fileid,iostat=ierr,iomsg=err_message) (o3clim4(ilat,ilev,imo),ilat=1,this%nlatc)
577 if (ierr /= 0 )
return
583 do ilev = 1, this%nlevc
584 do ilat = 1, this%nlatc
585 this%datac(ilat,ilev,imo) = o3clim4(ilat,ilev,imo) * 1.655e-6
590 do ilev = 1, this%nlevc
591 this%pstr(ilev) = pstr4(ilev)
592 this%pkstr(ilev) = fpkapx(this%pstr(ilev)*100.0)
599 subroutine update_o3clim(this, imon, iday, ihour, loz1st)
601 integer,
intent(in) :: imon, iday, ihour
602 logical,
intent(in) :: loz1st
604 integer :: midmon=15, midm=15, midp=45, id
605 integer,
parameter,
dimension(13) :: mdays = (/31,28,31,30,31,30,31,31,30,31,30,31,30/)
608 midmon = mdays(imon)/2 + 1
609 change = loz1st .or. ( (iday==midmon) .and. (ihour==0) )
612 if ( iday < midmon )
then
613 this%k1oz = mod(imon+10, 12) + 1
614 midm = mdays(this%k1oz)/2 + 1
616 midp = mdays(this%k1oz) + midmon
620 this%k2oz = mod(imon, 12) + 1
621 midp = mdays(this%k2oz)/2 + 1 + mdays(this%k1oz)
625 if (iday < midmon)
then
626 id = iday + mdays(this%k1oz)
631 this%facoz = float(id - midm) / float(midp - midm)