forked from ESCOMP/CTSM
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDiurnalOzoneType.F90
159 lines (129 loc) · 5.16 KB
/
DiurnalOzoneType.F90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
module DiurnalOzoneType
!-----------------------------------------------------------------------
! !DESCRIPTION:
! Sets up type for converting multi-day ozone input to sub-daily values using an input
! ozone anomaly file
!
! !USES:
#include "shr_assert.h"
use shr_kind_mod , only : r8 => shr_kind_r8
use decompMod , only : bounds_type
use clm_varcon , only : spval
use clm_varctl , only : iulog
use abortutils , only : endrun
implicit none
save
private
! !PUBLIC TYPES:
type, public :: diurnal_ozone_anom_type
private
! Private data members
integer :: ntimes ! size of time dimension
real(r8), public, allocatable :: o3_anomaly_grc(:,:) ! o3 anomaly data [grc, ntimes]
real(r8), public, allocatable :: time_arr(:) ! time dimension (units = seconds of day)
contains
! Public routines
procedure, public :: Init
procedure, private :: InitAllocate
procedure, public :: Interp
end type diurnal_ozone_anom_type
character(len=*), parameter, private :: sourcefile = &
__FILE__
contains
! ========================================================================
! Infrastructure routines (initialization, etc.)
! ========================================================================
!-----------------------------------------------------------------------
subroutine Init(this, bounds, n)
!
! DESCRIPTION:
! Initialize ozone anomaly data structures
!
!
! ARGUMENTS:
class(diurnal_ozone_anom_type), intent(inout) :: this
type(bounds_type), intent(in) :: bounds
integer, intent(in) :: n
!-----------------------------------------------------------------------
! set ntimes from input
this%ntimes = n
! allocate arrays
call this%InitAllocate(bounds)
end subroutine Init
!-----------------------------------------------------------------------
subroutine InitAllocate(this, bounds)
!
! !DESCRIPTION:
! Allocate module variables and data structures
!
! !USES:
use shr_infnan_mod, only: nan => shr_infnan_nan, assignment(=)
!
! !ARGUMENTS:
class(diurnal_ozone_anom_type), intent(inout) :: this
type(bounds_type), intent(in) :: bounds
!
! LOCAL VARIABLES:
integer :: begg, endg
!---------------------------------------------------------------------
begg = bounds%begg; endg = bounds%endg
allocate(this%o3_anomaly_grc(begg:endg,1:this%ntimes)); this%o3_anomaly_grc(:,:) = nan
allocate(this%time_arr(1:this%ntimes)); this%time_arr(:) = nan
end subroutine InitAllocate
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------
subroutine Interp(this, bounds, forc_o3, forc_o3_down)
!
! !DESCRIPTION:
! Downscale/interpolate multi-day ozone data to subdaily
!
! !USES:
use clm_time_manager , only : get_curr_date
use clm_varcon , only : secspday
!
! !ARGUMENTS:
class(diurnal_ozone_anom_type), intent(in) :: this
type(bounds_type), intent(in) :: bounds ! bounds type
real(r8), intent(in) :: forc_o3(:) ! ozone partial pressure (mol/mol)
real(r8), intent(out) :: forc_o3_down(:) ! ozone partial pressure, downscaled (mol/mol)
!
! LOCAL VARIABLES:
integer :: t ! looping index
integer :: yr ! year
integer :: mon ! month
integer :: day ! day of month
integer :: tod ! time of day (seconds past 0Z)
integer :: begg, endg ! bounds
integer :: t_prev ! previous time index
real(r8) :: tdiff_end
real(r8) :: tdiff_start
real(r8) :: tdiff
!-----------------------------------------------------------------------
begg = bounds%begg; endg = bounds%endg
! Get current date/time - we really only need seconds
call get_curr_date(yr, mon, day, tod)
! find the time interval we are in
do t = 1, this%ntimes
if (real(tod) <= this%time_arr(t)) then
exit
end if
end do
! interpolate, checking for edge cases
if (t == 1) then
! wrap around back
t_prev = this%ntimes
tdiff_end = secspday - this%time_arr(t_prev) + real(tod)
tdiff = this%time_arr(t) + secspday - this%time_arr(t_prev)
else
t_prev = t - 1
tdiff_end = real(tod) - this%time_arr(t_prev)
tdiff = this%time_arr(t) - this%time_arr(t_prev)
end if
tdiff_start = this%time_arr(t) - real(tod)
! interpolate
forc_o3_down(begg:endg) = forc_o3(begg:endg)* &
((this%o3_anomaly_grc(begg:endg, t_prev)*tdiff_start + &
this%o3_anomaly_grc(begg:endg, t_prev)*tdiff_end)/tdiff)
end subroutine Interp
!-----------------------------------------------------------------------
end module DiurnalOzoneType