FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
time_interp_external2.inc
1!***********************************************************************
2!* GNU Lesser General Public License
3!*
4!* This file is part of the GFDL Flexible Modeling System (FMS).
5!*
6!* FMS is free software: you can redistribute it and/or modify it under
7!* the terms of the GNU Lesser General Public License as published by
8!* the Free Software Foundation, either version 3 of the License, or (at
9!* your option) any later version.
10!*
11!* FMS is distributed in the hope that it will be useful, but WITHOUT
12!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14!* for more details.
15!*
16!* You should have received a copy of the GNU Lesser General Public
17!* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18!***********************************************************************
19!> @ingroup time_interp
20!> @addtogroup time_interp_external2_mod
21!> @{
22
23 !> @brief 2D interpolation for @ref time_interp_external
24 subroutine time_interp_external_2d_(index, time, data_in, interp, verbose,horz_interp, mask_out, &
25 is_in, ie_in, js_in, je_in, window_id)
26
27 integer, intent(in) :: index
28 type(time_type), intent(in) :: time
29 real(FMS_TI_KIND_), dimension(:,:), intent(inout) :: data_in
30 integer, intent(in), optional :: interp
31 logical, intent(in), optional :: verbose
32 type(horiz_interp_type),intent(in), optional :: horz_interp
33 logical, dimension(:,:), intent(out), optional :: mask_out !< set to true where output data is valid
34 integer, intent(in), optional :: is_in, ie_in, js_in, je_in
35 integer, intent(in), optional :: window_id
36
37 real(FMS_TI_KIND_), dimension(size(data_in,1), size(data_in,2), 1) :: data_out
38 logical, dimension(size(data_in,1), size(data_in,2), 1) :: mask3d
39
40 data_out(:,:,1) = data_in(:,:) ! fill initial values for the portions of array that are not touched by 3d routine
41 call time_interp_external(index, time, data_out, interp, verbose, horz_interp, mask3d, &
42 is_in=is_in,ie_in=ie_in,js_in=js_in,je_in=je_in,window_id=window_id)
43 data_in(:,:) = data_out(:,:,1)
44 if (PRESENT(mask_out)) mask_out(:,:) = mask3d(:,:,1)
45
46 return
47 end subroutine time_interp_external_2d_
48
49
50
51 !> 3D interpolation for @ref time_interp_external
52 !! Provide data from external file interpolated to current model time.
53 !! Data may be local to current processor or global, depending on
54 !! "init_external_field" flags.
55 subroutine time_interp_external_3d_(index, time, time_data, interp,verbose,horz_interp, mask_out, is_in, ie_in, &
56 & js_in, je_in, window_id)
57
58 integer, intent(in) :: index !< index of external field from previous call
59 !! to init_external_field
60 type(time_type), intent(in) :: time !< target time for data
61 real(FMS_TI_KIND_), dimension(:,:,:), intent(inout) :: time_data !< global or local data array
62 integer, intent(in), optional :: interp
63 logical, intent(in), optional :: verbose !< flag for debugging
64 type(horiz_interp_type), intent(in), optional :: horz_interp
65 logical, dimension(:,:,:), intent(out), optional :: mask_out !< set to true where output data is valid
66 integer, intent(in), optional :: is_in, ie_in, js_in, je_in
67 integer, intent(in), optional :: window_id
68
69 integer :: nx, ny, nz, interp_method, t1, t2
70 integer :: i1, i2, isc, iec, jsc, jec, mod_time
71 integer :: yy, mm, dd, hh, min, ss
72 character(len=256) :: err_msg
73 character(len=FMS_PATH_LEN) :: filename
74
75 integer :: isw, iew, jsw, jew, nxw, nyw
76 ! these are boundaries of the updated portion of the "data" argument
77 ! they are calculated using sizes of the "data" and isc,iec,jsc,jsc
78 ! fileds from respective input field, to center the updated portion
79 ! in the output array
80
81 real(FMS_TI_KIND_) :: w1,w2
82 logical :: verb
83 character(len=16) :: message1, message2
84 integer, parameter :: kindl = fms_ti_kind_
85
86 nx = size(time_data,1)
87 ny = size(time_data,2)
88 nz = size(time_data,3)
89
90 interp_method = linear_time_interp
91 if (PRESENT(interp)) interp_method = interp
92 verb=.false.
93 if (PRESENT(verbose)) verb=verbose
94 if (debug_this_module) verb = .true.
95
96 if (index < 1.or.index > num_fields) &
97 call mpp_error(fatal, &
98 & 'invalid index in call to time_interp_ext -- field was not initialized or failed to initialize')
99
100 isc=loaded_fields(index)%isc;iec=loaded_fields(index)%iec
101 jsc=loaded_fields(index)%jsc;jec=loaded_fields(index)%jec
102
103 if( loaded_fields(index)%numwindows == 1 ) then
104 nxw = iec-isc+1
105 nyw = jec-jsc+1
106 else
107 if(.not. present(is_in) .or. .not. present(ie_in) .or. .not. present(js_in) .or. .not. present(je_in))then
108 call mpp_error(fatal, 'time_interp_external: is_in, ie_in, js_in and je_in must be present ' // &
109 'when numwindows > 1, field='//trim(loaded_fields(index)%name))
110 endif
111 nxw = ie_in - is_in + 1
112 nyw = je_in - js_in + 1
113 isc = isc + is_in - 1
114 iec = isc + ie_in - is_in
115 jsc = jsc + js_in - 1
116 jec = jsc + je_in - js_in
117 endif
118
119 isw = (nx-nxw)/2+1; iew = isw+nxw-1
120 jsw = (ny-nyw)/2+1; jew = jsw+nyw-1
121
122 if (nx < nxw .or. ny < nyw .or. nz < loaded_fields(index)%siz(3)) then
123 write(message1,'(i6,2i5)') nx,ny,nz
124 call mpp_error(fatal,'field '//trim(loaded_fields(index)%name)// &
125 ' Array size mismatch in time_interp_external. Array "data" is too small. shape(data)=' &
126 //message1)
127 endif
128 if(PRESENT(mask_out)) then
129 if (size(mask_out,1) /= nx .or. size(mask_out,2) /= ny .or. size(mask_out,3) /= nz) then
130 write(message1,'(i6,2i5)') nx,ny,nz
131 write(message2,'(i6,2i5)') size(mask_out,1),size(mask_out,2),size(mask_out,3)
132 call mpp_error(fatal,'field '//trim(loaded_fields(index)%name)// &
133 ' array size mismatch in time_interp_external.'// &
134 ' Shape of array "mask_out" does not match that of array "data".'// &
135 ' shape(data)='//message1//' shape(mask_out)='//message2)
136 endif
137 endif
138
139 ! only one record in the file => time-independent field
140 if (loaded_fields(index)%siz(4) == 1) then
141 call load_record(loaded_fields(index),1,horz_interp, is_in, ie_in ,js_in, je_in,window_id)
142 i1 = find_buf_index(1,loaded_fields(index)%ibuf)
143 if( loaded_fields(index)%region_type == no_region ) then
144 where(loaded_fields(index)%mask(isc:iec,jsc:jec,:,i1))
145 time_data(isw:iew,jsw:jew,:) = real( loaded_fields(index)%domain_data(isc:iec,jsc:jec,:,i1),&
146 fms_ti_kind_)
147 elsewhere
148 ! time_data(isw:iew,jsw:jew,:) = time_interp_missing !field(index)%missing? Balaji
149 time_data(isw:iew,jsw:jew,:) = real(loaded_fields(index)%missing, fms_ti_kind_)
150 end where
151 else
152 where(loaded_fields(index)%mask(isc:iec,jsc:jec,:,i1))
153 time_data(isw:iew,jsw:jew,:) = real(loaded_fields(index)%domain_data(isc:iec,jsc:jec,:,i1),&
154 fms_ti_kind_)
155 end where
156 endif
157 if(PRESENT(mask_out)) mask_out(isw:iew,jsw:jew,:) = loaded_fields(index)%mask(isc:iec,jsc:jec,:,i1)
158 ! otherwise do interpolation
159 else
160 ! using time_interp_modulo
161 if(loaded_fields(index)%have_modulo_times) then
162 call time_interp(time,loaded_fields(index)%modulo_time_beg, loaded_fields(index)%modulo_time_end, &
163 loaded_fields(index)%time(:), w2, t1, t2, &
164 loaded_fields(index)%correct_leap_year_inconsistency, err_msg=err_msg)
165 if(err_msg .NE. '') then
166 filename = trim(loaded_fields(index)%fileobj%path)
167 call mpp_error(fatal,"time_interp_external 1: "//trim(err_msg)//&
168 ",file="//trim(filename)//",field="//trim(loaded_fields(index)%name) )
169 endif
170 ! using time_interp_list
171 else
172 if(loaded_fields(index)%modulo_time) then
173 mod_time=1
174 else
175 mod_time=0
176 endif
177 call time_interp(time,loaded_fields(index)%time(:),w2,t1,t2,modtime=mod_time, err_msg=err_msg)
178 if(err_msg .NE. '') then
179 filename = trim(loaded_fields(index)%fileobj%path)
180 call mpp_error(fatal,"time_interp_external 2: "//trim(err_msg)//&
181 ",file="//trim(filename)//",field="//trim(loaded_fields(index)%name) )
182 endif
183 endif
184 w1 = 1.0_kindl -w2
185 if (verb) then
186 call get_date(time,yy,mm,dd,hh,min,ss)
187 write(outunit,'(a,i4,a,i2,a,i2,1x,i2,a,i2,a,i2)') &
188 'target time yyyy/mm/dd hh:mm:ss= ',yy,'/',mm,'/',dd,hh,':',min,':',ss
189 write(outunit,*) 't1, t2, w1, w2= ', t1, t2, w1, w2
190 endif
191
192 call load_record(loaded_fields(index),t1,horz_interp, is_in, ie_in ,js_in, je_in, window_id)
193 call load_record(loaded_fields(index),t2,horz_interp, is_in, ie_in ,js_in, je_in, window_id)
194 i1 = find_buf_index(t1,loaded_fields(index)%ibuf)
195 i2 = find_buf_index(t2,loaded_fields(index)%ibuf)
196 if(i1<0.or.i2<0) &
197 call mpp_error(fatal,'time_interp_external : records were not loaded correctly in memory')
198
199 if (verb) then
200 write(outunit,*) 'ibuf= ',loaded_fields(index)%ibuf
201 write(outunit,*) 'i1,i2= ',i1, i2
202 endif
203
204 if( loaded_fields(index)%region_type == no_region ) then
205 where(loaded_fields(index)%mask(isc:iec,jsc:jec,:,i1) .and. &
206 loaded_fields(index)%mask(isc:iec,jsc:jec,:,i2))
207 time_data(isw:iew,jsw:jew,:) = real(loaded_fields(index)%domain_data(isc:iec,jsc:jec,:,i1), kindl)&
208 * w1 + real(loaded_fields(index)%domain_data(isc:iec,jsc:jec,:,i2), kindl) * w2
209 elsewhere
210 ! time_data(isw:iew,jsw:jew,:) = time_interp_missing !loaded_fields(index)%missing? Balaji
211 time_data(isw:iew,jsw:jew,:) = real(loaded_fields(index)%missing, kindl)
212 end where
213 else
214 where(loaded_fields(index)%mask(isc:iec,jsc:jec,:,i1) .and. &
215 loaded_fields(index)%mask(isc:iec,jsc:jec,:,i2))
216 time_data(isw:iew,jsw:jew,:) = real( loaded_fields(index)%domain_data(isc:iec,jsc:jec,:,i1), kindl)&
217 * w1 + real(loaded_fields(index)%domain_data(isc:iec,jsc:jec,:,i2), kindl) * w2
218 end where
219 endif
220 if(PRESENT(mask_out)) &
221 mask_out(isw:iew,jsw:jew,:) = &
222 loaded_fields(index)%mask(isc:iec,jsc:jec,:,i1).and.&
223 loaded_fields(index)%mask(isc:iec,jsc:jec,:,i2)
224 endif
225
226 end subroutine time_interp_external_3d_
227!</SUBROUTINE> NAME="time_interp_external"
228
229 !> @brief Scalar interpolation for @ref time_interp_external
230 subroutine time_interp_external_0d_(index, time, time_data, verbose)
231
232 integer, intent(in) :: index
233 type(time_type), intent(in) :: time
234 real(FMS_TI_KIND_), intent(inout) :: time_data
235 logical, intent(in), optional :: verbose
236
237 integer :: t1, t2
238 integer :: i1, i2, mod_time
239 integer :: yy, mm, dd, hh, min, ss
240 character(len=256) :: err_msg
241 character(len=FMS_PATH_LEN) :: filename
242
243 real(FMS_TI_KIND_) :: w1,w2
244 logical :: verb
245 integer, parameter :: kindl = fms_ti_kind_
246
247 verb=.false.
248 if (PRESENT(verbose)) verb=verbose
249 if (debug_this_module) verb = .true.
250
251 if (index < 1.or.index > num_fields) &
252 call mpp_error(fatal, &
253 & 'invalid index in call to time_interp_ext -- field was not initialized or failed to initialize')
254
255 if (loaded_fields(index)%siz(4) == 1) then
256 ! only one record in the file => time-independent loaded_fields
257 call load_record_0d(loaded_fields(index),1)
258 i1 = find_buf_index(1,loaded_fields(index)%ibuf)
259 time_data = real(loaded_fields(index)%domain_data(1,1,1,i1), fms_ti_kind_)
260 else
261 if(loaded_fields(index)%have_modulo_times) then
262 call time_interp(time,loaded_fields(index)%modulo_time_beg, loaded_fields(index)%modulo_time_end, &
263 loaded_fields(index)%time(:), w2, t1, t2, &
264 loaded_fields(index)%correct_leap_year_inconsistency, err_msg=err_msg)
265 if(err_msg .NE. '') then
266 filename = trim(loaded_fields(index)%fileobj%path)
267 call mpp_error(fatal,"time_interp_external 3:"//trim(err_msg)//&
268 ",file="//trim(filename)//",field="//trim(loaded_fields(index)%name) )
269 endif
270 else
271 if(loaded_fields(index)%modulo_time) then
272 mod_time=1
273 else
274 mod_time=0
275 endif
276 call time_interp(time,loaded_fields(index)%time(:),w2,t1,t2,modtime=mod_time, err_msg=err_msg)
277 if(err_msg .NE. '') then
278 filename = trim(loaded_fields(index)%fileobj%path)
279 call mpp_error(fatal,"time_interp_external 4:"//trim(err_msg)// &
280 ",file="//trim(filename)//",field="//trim(loaded_fields(index)%name) )
281 endif
282 endif
283 w1 = 1.0_kindl-w2
284 if (verb) then
285 call get_date(time,yy,mm,dd,hh,min,ss)
286 write(outunit,'(a,i4,a,i2,a,i2,1x,i2,a,i2,a,i2)') &
287 'target time yyyy/mm/dd hh:mm:ss= ',yy,'/',mm,'/',dd,hh,':',min,':',ss
288 write(outunit,*) 't1, t2, w1, w2= ', t1, t2, w1, w2
289 endif
290 call load_record_0d(loaded_fields(index),t1)
291 call load_record_0d(loaded_fields(index),t2)
292 i1 = find_buf_index(t1,loaded_fields(index)%ibuf)
293 i2 = find_buf_index(t2,loaded_fields(index)%ibuf)
294
295 if(i1<0.or.i2<0) &
296 call mpp_error(fatal,'time_interp_external : records were not loaded correctly in memory')
297 time_data = real(loaded_fields(index)%domain_data(1,1,1,i1), fms_ti_kind_)*w1 &
298 & + real(loaded_fields(index)%domain_data(1,1,1,i2), fms_ti_kind_)*w2
299 if (verb) then
300 write(outunit,*) 'ibuf= ',loaded_fields(index)%ibuf
301 write(outunit,*) 'i1,i2= ',i1, i2
302 endif
303 endif
304
305 end subroutine time_interp_external_0d_
306
307! ============================================================================