FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
time_interp_external2_bridge.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_bridge
24 subroutine time_interp_external_bridge_2d_(index1, index2, 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) :: index1 !< index of first external field
28 integer, intent(in) :: index2 !< index of second external field
29 type(time_type), intent(in) :: time !< target time for data
30 real(FMS_TI_KIND_), dimension(:,:), intent(inout) :: data_in !< global or local data array
31 integer, intent(in), optional :: interp !< hardcoded to linear
32 logical, intent(in), optional :: verbose !< flag for debugging
33 type(horiz_interp_type),intent(in), optional :: horz_interp !< horizontal interpolation type
34 logical, dimension(:,:), intent(out), optional :: mask_out !< set to true where output data is valid
35 integer, intent(in), optional :: is_in, ie_in, js_in, je_in !< horizontal indices for load_record
36 integer, intent(in), optional :: window_id !< harcoded to 1 in load_record
37
38 real(FMS_TI_KIND_), dimension(size(data_in,1), size(data_in,2), 1) :: data_out !< 3d version of data_in
39 logical, dimension(size(data_in,1), size(data_in,2), 1) :: mask3d !< 3d version of mask_out
40
41 data_out(:,:,1) = data_in(:,:) ! fill initial values for the portions of array that are not touched by 3d routine
42 call time_interp_external_bridge(index1, index2, time, data_out, interp, verbose, horz_interp, mask3d, &
43 is_in=is_in,ie_in=ie_in,js_in=js_in,je_in=je_in,window_id=window_id)
44 data_in(:,:) = data_out(:,:,1)
45 if (PRESENT(mask_out)) mask_out(:,:) = mask3d(:,:,1)
46
47 return
49
50 !> 3D interpolation for @ref time_interp_external
51 !! Provide data from external file interpolated to current model time.
52 !! Data may be local to current processor or global, depending on
53 !! "init_external_field" flags.
54 subroutine time_interp_external_bridge_3d_(index1, index2, time, time_data, interp,verbose,horz_interp, mask_out, &
55 & is_in, ie_in, js_in, je_in, window_id)
56
57 integer, intent(in) :: index1 !< index of first external field
58 integer, intent(in) :: index2 !< index of second external field
59 type(time_type), intent(in) :: time !< target time for data
60 real(FMS_TI_KIND_), dimension(:,:,:), intent(inout) :: time_data !< global or local data array
61 integer, intent(in), optional :: interp !< hardcoded to linear
62 logical, intent(in), optional :: verbose !< flag for debugging
63 type(horiz_interp_type), intent(in), optional :: horz_interp !< horizontal interpolation type
64 logical, dimension(:,:,:), intent(out), optional :: mask_out !< set to true where output data is valid
65 integer, intent(in), optional :: is_in, ie_in !< x horizontal indices for load_record
66 integer, intent(in), optional :: js_in, je_in !< y horizontal indices for load_record
67 integer, intent(in), optional :: window_id !< harcoded to 1 in load_record
68
69 type(time_type) :: time1 !< time type associated with index1 of external field
70 type(time_type) :: time2 !< time type associated with index2 of external field
71 integer :: dims1(4) !< dimensions XYZT of index1
72 integer :: dims2(4) !< dimensions XYZT of index2
73 integer :: nx, ny, nz !< size in X,Y,Z of array
74 integer :: interp_method !< hardcoded to linear in time
75 integer :: t1, t2 !< temporary to store time index
76 integer :: i1, i2 !< temporary to store time index
77 integer :: isc, iec, jsc, jec !< start/end arrays in X,Y
78 integer :: isc1, iec1, jsc1, jec1 !< start/end arrays in X,Y for field1
79 integer :: isc2, iec2, jsc2, jec2 !< start/end arrays in X,Y for field2
80 integer :: yy, mm, dd, hh, minu, ss !< year, month, day, hour, minute, second for date
81
82 integer :: isw, iew, jsw, jew, nxw, nyw !< these are boundaries of the updated portion of the "data" argument
83 !! they are calculated using sizes of the "data" and isc,iec,jsc,jsc
84 !! fileds from respective input field, to center the updated portion
85 !! in the output array
86
87 real(FMS_TI_KIND_) :: w1 !< interp weight for index1
88 real(FMS_TI_KIND_) :: w2 !< interp weight for index2
89 logical :: verb !< verbose
90 character(len=16) :: message1 !< temp string
91 character(len=16) :: message2 !< temp string
92 integer, parameter :: kindl = fms_ti_kind_
93
94 nx = size(time_data,1)
95 ny = size(time_data,2)
96 nz = size(time_data,3)
97
98 interp_method = linear_time_interp
99 if (PRESENT(interp)) interp_method = interp
100 verb=.false.
101 if (PRESENT(verbose)) verb=verbose
102 if (debug_this_module) verb = .true.
103
104 if (index1 < 1 .or. index1 > num_fields) &
105 call mpp_error(fatal,'invalid index1 in call to time_interp_external_bridge:' // &
106 '-- field was not initialized or failed to initialize')
107 if (index2 < 1 .or. index2 > num_fields) &
108 call mpp_error(fatal,'invalid index2 in call to time_interp_external_bridge:' // &
109 ' -- field was not initialized or failed to initialize')
110
111 isc1=loaded_fields(index1)%isc;iec1=loaded_fields(index1)%iec
112 jsc1=loaded_fields(index1)%jsc;jec1=loaded_fields(index1)%jec
113 isc2=loaded_fields(index2)%isc;iec2=loaded_fields(index2)%iec
114 jsc2=loaded_fields(index2)%jsc;jec2=loaded_fields(index2)%jec
115
116 if ((isc1 /= isc2) .or. (iec1 /= iec2) .or. (jsc1 /= jsc2) .or. (jec1 /= jec2)) then
117 call mpp_error(fatal, 'time_interp_external_bridge: dimensions must be the same in both index1 and index2 ')
118 endif
119
120 isc=isc1 ; iec=iec1 ; jsc=jsc1 ; jec=jec1
121
122 if (trim(loaded_fields(index2)%name) /= trim(loaded_fields(index1)%name)) then
123 call mpp_error(fatal, 'time_interp_external_bridge: cannot bridge between different fields.' // &
124 'field1='//trim(loaded_fields(index1)%name)//' field2='//trim(loaded_fields(index2)%name))
125 endif
126
127 if ((loaded_fields(index1)%numwindows == 1) .and. (loaded_fields(index2)%numwindows == 1)) then
128 nxw = iec-isc+1
129 nyw = jec-jsc+1
130 else
131 if(.not. present(is_in) .or. .not. present(ie_in) .or. .not. present(js_in) .or. .not. present(je_in))then
132 call mpp_error(fatal, 'time_interp_external: is_in, ie_in, js_in and je_in must be present ' // &
133 'when numwindows > 1, field='//trim(loaded_fields(index1)%name))
134 endif
135 nxw = ie_in - is_in + 1
136 nyw = je_in - js_in + 1
137 isc = isc + is_in - 1
138 iec = isc + ie_in - is_in
139 jsc = jsc + js_in - 1
140 jec = jsc + je_in - js_in
141 endif
142
143 isw = (nx-nxw)/2+1; iew = isw+nxw-1
144 jsw = (ny-nyw)/2+1; jew = jsw+nyw-1
145
146 if (nx < nxw .or. ny < nyw .or. nz < loaded_fields(index1)%siz(3)) then
147 write(message1,'(i6,2i5)') nx,ny,nz
148 call mpp_error(fatal,'field '//trim(loaded_fields(index1)%name)// &
149 ' Array size mismatch in time_interp_external_bridge.'// &
150 ' Array "data" is too small. shape(time_data)='//message1)
151 endif
152 if (nx < nxw .or. ny < nyw .or. nz < loaded_fields(index2)%siz(3)) then
153 write(message1,'(i6,2i5)') nx,ny,nz
154 call mpp_error(fatal,'field '//trim(loaded_fields(index2)%name)// &
155 ' Array size mismatch in time_interp_external_bridge.'// &
156 ' Array "data" is too small. shape(time_data)='//message1)
157 endif
158
159 if(PRESENT(mask_out)) then
160 if (size(mask_out,1) /= nx .or. size(mask_out,2) /= ny .or. size(mask_out,3) /= nz) then
161 write(message1,'(i6,2i5)') nx,ny,nz
162 write(message2,'(i6,2i5)') size(mask_out,1),size(mask_out,2),size(mask_out,3)
163 call mpp_error(fatal,'field '//trim(loaded_fields(index1)%name)// &
164 ' array size mismatch in time_interp_external_bridge.'// &
165 ' Shape of array "mask_out" does not match that of array "data".'// &
166 ' shape(time_data)='//message1//' shape(mask_out)='//message2)
167 endif
168 endif
169
170 if ((loaded_fields(index1)%have_modulo_times) .or. (loaded_fields(index2)%have_modulo_times)) then
171 call mpp_error(fatal, 'time_interp_external_bridge: field '//trim(loaded_fields(index1)%name)// &
172 ' array cannot have modulo time')
173 endif
174 if ((loaded_fields(index1)%modulo_time) .or. (loaded_fields(index2)%modulo_time)) then
175 call mpp_error(fatal, 'time_interp_external_bridge: field '//trim(loaded_fields(index1)%name)// &
176 ' array cannot have modulo time')
177 endif
178
179 dims1 = get_external_field_size(index1)
180 dims2 = get_external_field_size(index2)
181
182 t1 = dims1(4)
183 t2 = 1
184
185 time1 = loaded_fields(index1)%time(t1)
186 time2 = loaded_fields(index2)%time(t2)
187 w2= (time - time1) // (time2 - time1)
188 w1 = 1.0_kindl-w2
189
190 if (verb) then
191 call get_date(time,yy,mm,dd,hh,minu,ss)
192 write(outunit,'(a,i4,a,i2,a,i2,1x,i2,a,i2,a,i2)') &
193 'target time yyyy/mm/dd hh:mm:ss= ',yy,'/',mm,'/',dd,hh,':',minu,':',ss
194 write(outunit,*) 't1, t2, w1, w2= ', t1, t2, w1, w2
195 endif
196
197 call load_record(loaded_fields(index1),t1,horz_interp, is_in, ie_in ,js_in, je_in, window_id)
198 call load_record(loaded_fields(index2),t2,horz_interp, is_in, ie_in ,js_in, je_in, window_id)
199 i1 = find_buf_index(t1,loaded_fields(index1)%ibuf)
200 i2 = find_buf_index(t2,loaded_fields(index2)%ibuf)
201 if(i1<0.or.i2<0) &
202 call mpp_error(fatal,'time_interp_external_bridge : records were not loaded correctly in memory')
203
204 if (verb) then
205 write(outunit,*) 'ibuf= ',loaded_fields(index2)%ibuf
206 write(outunit,*) 'i1,i2= ',i1, i2
207 endif
208
209 if((loaded_fields(index1)%region_type == no_region) .and. (loaded_fields(index2)%region_type == no_region) ) then
210 where(loaded_fields(index1)%mask(isc:iec,jsc:jec,:,i1).and.loaded_fields(index2)%mask(isc:iec,jsc:jec,:,i2))
211 time_data(isw:iew,jsw:jew,:) = real(loaded_fields(index1)%domain_data(isc:iec,jsc:jec,:,i1), kindl)*w1 + &
212 real(loaded_fields(index2)%domain_data(isc:iec,jsc:jec,:,i2), kindl)*w2
213 elsewhere
214 time_data(isw:iew,jsw:jew,:) = real(loaded_fields(index1)%missing, kindl)
215 end where
216 else
217 where(loaded_fields(index1)%mask(isc:iec,jsc:jec,:,i1).and.loaded_fields(index2)%mask(isc:iec,jsc:jec,:,i2))
218 time_data(isw:iew,jsw:jew,:) = real(loaded_fields(index1)%domain_data(isc:iec,jsc:jec,:,i1), kindl)*w1 + &
219 real(loaded_fields(index2)%domain_data(isc:iec,jsc:jec,:,i2), kindl)*w2
220 end where
221 endif
222
223 if(PRESENT(mask_out)) &
224 mask_out(isw:iew,jsw:jew,:) = &
225 loaded_fields(index1)%mask(isc:iec,jsc:jec,:,i1).and.&
226 loaded_fields(index2)%mask(isc:iec,jsc:jec,:,i2)
227
229
230 subroutine time_interp_external_bridge_0d_(index1, index2, time, time_data, verbose)
231
232 integer, intent(in) :: index1 !< index of first external field
233 integer, intent(in) :: index2 !< index of second external field
234 type(time_type), intent(in) :: time !< target time for data
235 real(FMS_TI_KIND_), intent(inout) :: time_data !< global or local data array
236 logical, intent(in), optional :: verbose !< flag for debugging
237
238 integer :: t1, t2 !< temporary to store time index
239 integer :: i1, i2 !< temporary to store time index
240 integer :: yy, mm, dd, hh, minu, ss !< year, month, day, hour, minute, second for date
241 type(time_type) :: time1 !< time type associated with index1 of external field
242 type(time_type) :: time2 !< time type associated with index2 of external field
243 integer :: dims1(4) !< dimensions XYZT of index1
244 integer :: dims2(4) !< dimensions XYZT of index2
245
246 real(FMS_TI_KIND_) :: w1 !< interp weight for index1
247 real(FMS_TI_KIND_) :: w2 !< interp weight for index2
248 logical :: verb !< verbose
249 integer, parameter :: kindl = fms_ti_kind_
250
251 verb=.false.
252 if (PRESENT(verbose)) verb=verbose
253 if (debug_this_module) verb = .true.
254
255 if (index1 < 0 .or. index1 > num_fields) &
256 call mpp_error(fatal,'invalid index1 in call to time_interp_ext' // &
257 ' -- field was not initialized or failed to initialize')
258 if (index2 < 0 .or. index2 > num_fields) &
259 call mpp_error(fatal,'invalid index2 in call to time_interp_ext' // &
260 ' -- field was not initialized or failed to initialize')
261
262 if ((loaded_fields(index1)%have_modulo_times) .or. (loaded_fields(index2)%have_modulo_times)) then
263 call mpp_error(fatal, 'time_interp_external_bridge: field '//trim(loaded_fields(index1)%name)// &
264 ' array cannot have modulo time')
265 endif
266 if ((loaded_fields(index1)%modulo_time) .or. (loaded_fields(index2)%modulo_time)) then
267 call mpp_error(fatal, 'time_interp_external_bridge: field '//trim(loaded_fields(index1)%name)// &
268 ' array cannot have modulo time')
269 endif
270
271 dims1 = get_external_field_size(index1)
272 dims2 = get_external_field_size(index2)
273
274 t1 = dims1(4)
275 t2 = 1
276
277 time1 = loaded_fields(index1)%time(t1)
278 time2 = loaded_fields(index2)%time(t2)
279 w2= (time - time1) // (time2 - time1)
280 w1 = 1.0_kindl-w2
281
282 if (verb) then
283 call get_date(time,yy,mm,dd,hh,minu,ss)
284 write(outunit,'(a,i4,a,i2,a,i2,1x,i2,a,i2,a,i2)') &
285 'target time yyyy/mm/dd hh:mm:ss= ',yy,'/',mm,'/',dd,hh,':',minu,':',ss
286 write(outunit,*) 't1, t2, w1, w2= ', t1, t2, w1, w2
287 endif
288 call load_record_0d(loaded_fields(index2),t1)
289 call load_record_0d(loaded_fields(index2),t2)
290 i1 = find_buf_index(t1,loaded_fields(index2)%ibuf)
291 i2 = find_buf_index(t2,loaded_fields(index2)%ibuf)
292
293 if(i1<0.or.i2<0) &
294 call mpp_error(fatal,'time_interp_external : records were not loaded correctly in memory')
295 time_data = real(loaded_fields(index2)%domain_data(1,1,1,i1), fms_ti_kind_)*w1 &
296 + real(loaded_fields(index2)%domain_data(1,1,1,i2), fms_ti_kind_)*w2
297 if (verb) then
298 write(outunit,*) 'ibuf= ',loaded_fields(index2)%ibuf
299 write(outunit,*) 'i1,i2= ',i1, i2
300 endif
301
303
304
305! ============================================================================
subroutine time_interp_external_bridge_3d_(index1, index2, time, time_data, interp, verbose, horz_interp, mask_out, is_in, ie_in, js_in, je_in, window_id)
3D interpolation for time_interp_external Provide data from external file interpolated to current mod...
subroutine time_interp_external_bridge_0d_(index1, index2, time, time_data, verbose)
subroutine time_interp_external_bridge_2d_(index1, index2, time, data_in, interp, verbose, horz_interp, mask_out, is_in, ie_in, js_in, je_in, window_id)
2D interpolation for time_interp_external_bridge