1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4 ! This module provides routines for interpolation.
5 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
9 use misc_definitions_module
15 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
16 ! Name: interp_array_from_string
19 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20 function interp_array_from_string(interp_string)
25 character (len=*), intent(in) :: interp_string
28 integer :: j, p1, p2, iend, num_methods
31 integer, pointer, dimension(:) :: interp_array_from_string
33 ! Get an idea of how many interpolation methods are in the string
34 ! so we can allocate an appropriately sized array
36 do j=1,len_trim(interp_string)
37 if (interp_string(j:j) == '+') num_methods = num_methods + 1
40 allocate(interp_array_from_string(num_methods+1))
41 interp_array_from_string = 0
43 iend = len_trim(interp_string)
46 p2 = index(interp_string(1:iend),'+')
49 if (index(interp_string(p1:p2-1),'nearest_neighbor') /= 0 .and. &
50 len_trim(interp_string(p1:p2-1)) == len_trim('nearest_neighbor')) then
51 interp_array_from_string(j) = N_NEIGHBOR
53 else if (index(interp_string(p1:p2-1),'average_4pt') /= 0 .and. &
54 len_trim(interp_string(p1:p2-1)) == len_trim('average_4pt')) then
55 interp_array_from_string(j) = AVERAGE4
57 else if (index(interp_string(p1:p2-1),'average_16pt') /= 0 .and. &
58 len_trim(interp_string(p1:p2-1)) == len_trim('average_16pt')) then
59 interp_array_from_string(j) = AVERAGE16
61 else if (index(interp_string(p1:p2-1),'wt_average_4pt') /= 0 .and. &
62 len_trim(interp_string(p1:p2-1)) == len_trim('wt_average_4pt')) then
63 interp_array_from_string(j) = W_AVERAGE4
65 else if (index(interp_string(p1:p2-1),'wt_average_16pt') /= 0 .and. &
66 len_trim(interp_string(p1:p2-1)) == len_trim('wt_average_16pt')) then
67 interp_array_from_string(j) = W_AVERAGE16
69 else if (index(interp_string(p1:p2-1),'four_pt') /= 0 .and. &
70 len_trim(interp_string(p1:p2-1)) == len_trim('four_pt')) then
71 interp_array_from_string(j) = FOUR_POINT
73 else if (index(interp_string(p1:p2-1),'sixteen_pt') /= 0 .and. &
74 len_trim(interp_string(p1:p2-1)) == len_trim('sixteen_pt')) then
75 interp_array_from_string(j) = SIXTEEN_POINT
77 else if (index(interp_string(p1:p2-1),'search') /= 0) then
78 interp_array_from_string(j) = SEARCH
81 if (index(interp_string(p1:p2-1),'average_gcell') == 0) &
82 call mprintf(.true.,WARN,'Unrecognized interpolation method %s.',s1=interp_string(p1:p2-1))
85 p2 = index(interp_string(p1:iend),'+') + p1 - 1
90 if (index(interp_string(p1:p2-1),'nearest_neighbor') /= 0 .and. &
91 len_trim(interp_string(p1:p2-1)) == len_trim('nearest_neighbor')) then
92 interp_array_from_string(j) = N_NEIGHBOR
94 else if (index(interp_string(p1:p2-1),'average_4pt') /= 0 .and. &
95 len_trim(interp_string(p1:p2-1)) == len_trim('average_4pt')) then
96 interp_array_from_string(j) = AVERAGE4
98 else if (index(interp_string(p1:p2-1),'average_16pt') /= 0 .and. &
99 len_trim(interp_string(p1:p2-1)) == len_trim('average_16pt')) then
100 interp_array_from_string(j) = AVERAGE16
102 else if (index(interp_string(p1:p2-1),'wt_average_4pt') /= 0 .and. &
103 len_trim(interp_string(p1:p2-1)) == len_trim('wt_average_4pt')) then
104 interp_array_from_string(j) = W_AVERAGE4
106 else if (index(interp_string(p1:p2-1),'wt_average_16pt') /= 0 .and. &
107 len_trim(interp_string(p1:p2-1)) == len_trim('wt_average_16pt')) then
108 interp_array_from_string(j) = W_AVERAGE16
110 else if (index(interp_string(p1:p2-1),'four_pt') /= 0 .and. &
111 len_trim(interp_string(p1:p2-1)) == len_trim('four_pt')) then
112 interp_array_from_string(j) = FOUR_POINT
114 else if (index(interp_string(p1:p2-1),'sixteen_pt') /= 0 .and. &
115 len_trim(interp_string(p1:p2-1)) == len_trim('sixteen_pt')) then
116 interp_array_from_string(j) = SIXTEEN_POINT
118 else if (index(interp_string(p1:),'search') /= 0) then
119 interp_array_from_string(j) = SEARCH
122 if (index(interp_string(p1:p2-1),'average_gcell') == 0) &
123 call mprintf(.true.,WARN,'Unrecognized interpolation method %s.',s1=interp_string(p1:p2-1))
129 end function interp_array_from_string
132 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
133 ! Name: interp_options_from_string
136 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
137 function interp_options_from_string(interp_string)
142 character (len=*), intent(in) :: interp_string
145 integer :: j, p1, p2, iend, num_methods, istatus
148 integer, pointer, dimension(:) :: interp_options_from_string
150 ! Get an idea of how many interpolation methods are in the string
151 ! so we can allocate an appropriately sized array
153 do j=1,len_trim(interp_string)
154 if (interp_string(j:j) == '+') num_methods = num_methods + 1
157 allocate(interp_options_from_string(num_methods+1))
158 interp_options_from_string(:) = 0
160 iend = len_trim(interp_string)
163 p2 = index(interp_string(1:iend),'+')
166 if (index(interp_string(p1:p2-1),'nearest_neighbor') /= 0 .and. &
167 len_trim(interp_string(p1:p2-1)) == len_trim('nearest_neighbor')) then
168 interp_options_from_string(j) = 0
170 else if (index(interp_string(p1:p2-1),'average_4pt') /= 0 .and. &
171 len_trim(interp_string(p1:p2-1)) == len_trim('average_4pt')) then
172 interp_options_from_string(j) = 0
174 else if (index(interp_string(p1:p2-1),'average_16pt') /= 0 .and. &
175 len_trim(interp_string(p1:p2-1)) == len_trim('average_16pt')) then
176 interp_options_from_string(j) = 0
178 else if (index(interp_string(p1:p2-1),'wt_average_4pt') /= 0 .and. &
179 len_trim(interp_string(p1:p2-1)) == len_trim('wt_average_4pt')) then
180 interp_options_from_string(j) = 0
182 else if (index(interp_string(p1:p2-1),'wt_average_16pt') /= 0 .and. &
183 len_trim(interp_string(p1:p2-1)) == len_trim('wt_average_16pt')) then
184 interp_options_from_string(j) = 0
186 else if (index(interp_string(p1:p2-1),'four_pt') /= 0 .and. &
187 len_trim(interp_string(p1:p2-1)) == len_trim('four_pt')) then
188 interp_options_from_string(j) = 0
190 else if (index(interp_string(p1:p2-1),'sixteen_pt') /= 0 .and. &
191 len_trim(interp_string(p1:p2-1)) == len_trim('sixteen_pt')) then
192 interp_options_from_string(j) = 0
194 else if (index(interp_string(p1:p2-1),'search') /= 0) then
195 call get_search_depth(interp_string(p1:p2-1), interp_options_from_string(j), istatus)
198 if (index(interp_string(p1:p2-1),'average_gcell') == 0) &
199 call mprintf(.true.,WARN,'Unrecognized interpolation method %s.',s1=interp_string(p1:p2-1))
202 p2 = index(interp_string(p1:iend),'+') + p1 - 1
207 if (index(interp_string(p1:p2-1),'nearest_neighbor') /= 0 .and. &
208 len_trim(interp_string(p1:p2-1)) == len_trim('nearest_neighbor')) then
209 interp_options_from_string(j) = 0
211 else if (index(interp_string(p1:p2-1),'average_4pt') /= 0 .and. &
212 len_trim(interp_string(p1:p2-1)) == len_trim('average_4pt')) then
213 interp_options_from_string(j) = 0
215 else if (index(interp_string(p1:p2-1),'average_16pt') /= 0 .and. &
216 len_trim(interp_string(p1:p2-1)) == len_trim('average_16pt')) then
217 interp_options_from_string(j) = 0
219 else if (index(interp_string(p1:p2-1),'wt_average_4pt') /= 0 .and. &
220 len_trim(interp_string(p1:p2-1)) == len_trim('wt_average_4pt')) then
221 interp_options_from_string(j) = 0
223 else if (index(interp_string(p1:p2-1),'wt_average_16pt') /= 0 .and. &
224 len_trim(interp_string(p1:p2-1)) == len_trim('wt_average_16pt')) then
225 interp_options_from_string(j) = 0
227 else if (index(interp_string(p1:p2-1),'four_pt') /= 0 .and. &
228 len_trim(interp_string(p1:p2-1)) == len_trim('four_pt')) then
229 interp_options_from_string(j) = 0
231 else if (index(interp_string(p1:p2-1),'sixteen_pt') /= 0 .and. &
232 len_trim(interp_string(p1:p2-1)) == len_trim('sixteen_pt')) then
233 interp_options_from_string(j) = 0
235 else if (index(interp_string(p1:),'search') /= 0) then
236 call get_search_depth(interp_string(p1:), interp_options_from_string(j), istatus)
239 if (index(interp_string(p1:p2-1),'average_gcell') == 0) &
240 call mprintf(.true.,WARN,'Unrecognized interpolation method %s.',s1=interp_string(p1:p2-1))
246 end function interp_options_from_string
249 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
250 ! Name: get_search_depth
253 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
254 subroutine get_search_depth(interp_opt, depth, istatus)
259 integer, intent(out) :: istatus
260 integer, intent(out) :: depth
261 character (len=*), intent(in) :: interp_opt
264 integer :: i, p1, p2, p
269 i = index(interp_opt,'search')
272 ! Check for a max search depth
273 p = index(interp_opt(i:),'+')
274 if (p == 0) p = len_trim(interp_opt)
275 p1 = index(interp_opt(i:p),'(')
276 p2 = index(interp_opt(i:p),')')
277 if (p1 /= 0 .and. p2 /= 0) then
278 read(interp_opt(p1+1:p2-1),*,err=1000) depth
279 else if (p1 == 0 .and. p2 == 0) then
280 ! keep depth at 1200, no warning
282 call mprintf(.true., WARN, 'Problem with specified search depth '// &
283 'for search interp option. Setting max depth to 1200.')
291 1000 call mprintf(.true., ERROR, 'Search depth option to search interpolator '// &
292 'must be an integer value, enclosed in parentheses immediately '// &
293 'after keyword "search"')
295 end subroutine get_search_depth
298 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
299 ! Name: interp_sequence
301 ! Purpose: Delegates the actual task of interpolation to specific
302 ! interpolation routines defined in the module.
303 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
304 recursive function interp_sequence(xx, yy, izz, array, start_x, end_x, &
305 start_y, end_y, start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
310 integer, intent(in) :: start_x, start_y, start_z
311 integer, intent(in) :: end_x, end_y, end_z
312 integer, intent(in) :: izz ! The z-index of the 2d-array to
314 real, intent(in) :: xx , yy ! The location to interpolate to
315 real, intent(in) :: msgval
316 real, intent(in), optional :: maskval
317 real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), intent(in) :: array
318 integer, intent(in) :: idx
319 integer, dimension(:), intent(in) :: interp_list
320 integer, dimension(:), intent(in) :: interp_opts
321 real, dimension(start_x:end_x, start_y:end_y), intent(in), optional :: mask_array
322 character (len=1), intent(in), optional :: mask_relational
325 real :: interp_sequence
327 ! No more interpolation methods to try
328 if (interp_list(idx) == 0) then
329 interp_sequence = msgval
333 if (interp_list(idx) == FOUR_POINT) then
334 interp_sequence = four_pt(xx, yy, izz, array, start_x, end_x, &
335 start_y, end_y, start_z, end_z, &
336 msgval, interp_list, interp_opts, idx+1, mask_relational, maskval, mask_array)
337 else if (interp_list(idx) == AVERAGE4) then
338 interp_sequence = four_pt_average(xx, yy, izz, array, start_x, end_x, &
339 start_y, end_y, start_z, end_z, &
340 msgval, interp_list, interp_opts, idx+1, mask_relational, maskval, mask_array)
341 else if (interp_list(idx) == W_AVERAGE4) then
342 interp_sequence = wt_four_pt_average(xx, yy, izz, array, start_x, end_x, &
343 start_y, end_y, start_z, end_z, &
344 msgval, interp_list, interp_opts, idx+1, mask_relational, maskval, mask_array)
345 else if (interp_list(idx) == N_NEIGHBOR) then
346 interp_sequence = nearest_neighbor(xx, yy, izz, array, start_x, end_x, &
347 start_y, end_y, start_z, end_z, &
348 msgval, interp_list, interp_opts, idx+1, mask_relational, maskval, mask_array)
349 else if (interp_list(idx) == SIXTEEN_POINT) then
350 interp_sequence = sixteen_pt(xx, yy, izz, array, start_x, end_x, &
351 start_y, end_y, start_z, end_z, &
352 msgval, interp_list, interp_opts, idx+1, mask_relational, maskval, mask_array)
353 else if (interp_list(idx) == SEARCH) then
354 interp_sequence = search_extrap(xx, yy, izz, array, start_x, end_x, &
355 start_y, end_y, start_z, end_z, &
356 msgval, interp_list, interp_opts, idx+1, mask_relational, maskval, mask_array)
357 else if (interp_list(idx) == AVERAGE16) then
358 interp_sequence = sixteen_pt_average(xx, yy, izz, array, start_x, end_x, &
359 start_y, end_y, start_z, end_z, &
360 msgval, interp_list, interp_opts, idx+1, mask_relational, maskval, mask_array)
361 else if (interp_list(idx) == W_AVERAGE16) then
362 interp_sequence = wt_sixteen_pt_average(xx, yy, izz, array, start_x, end_x, &
363 start_y, end_y, start_z, end_z, &
364 msgval, interp_list, interp_opts, idx+1, mask_relational, maskval, mask_array)
367 end function interp_sequence
370 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
371 ! Name: nearest_neighbor
373 ! Purpose: Returns the point nearest to (xx,yy). If (xx,yy) is outside of the
374 ! array, the point on the edge of the array nearest to (xx,yy) is returned.
375 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
376 recursive function nearest_neighbor(xx, yy, izz, array, start_x, end_x, &
377 start_y, end_y, start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
382 integer, intent(in) :: start_x, start_y, start_z
383 integer, intent(in) :: end_x, end_y, end_z
384 integer, intent(in) :: izz ! The z-index of the 2d-array to
386 real, intent(in) :: xx , yy ! The location to interpolate to
387 real, intent(in) :: msgval
388 real, intent(in), optional :: maskval
389 real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), intent(in) :: array
390 integer, dimension(:), intent(in) :: interp_list
391 integer, dimension(:), intent(in) :: interp_opts
392 integer, intent(in) :: idx
393 real, dimension(start_x:end_x, start_y:end_y), intent(in), optional :: mask_array
394 character (len=1), intent(in), optional :: mask_relational
397 real :: nearest_neighbor
405 ! The first thing to do is to ensure that the point (xx,yy) is within the array
406 if (ix < start_x .or. ix > end_x) then
407 nearest_neighbor = msgval
411 if (iy < start_y .or. iy > end_y) then
412 nearest_neighbor = msgval
416 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
417 if (mask_relational == '<' .and. mask_array(ix,iy) < maskval) then
418 nearest_neighbor = msgval
419 else if (mask_relational == '>' .and. mask_array(ix,iy) > maskval) then
420 nearest_neighbor = msgval
421 else if (mask_relational == ' ' .and. mask_array(ix,iy) == maskval) then
422 nearest_neighbor = msgval
424 nearest_neighbor = array(ix,iy,izz)
426 else if (present(mask_array) .and. present(maskval)) then
427 if (maskval == mask_array(ix,iy)) then
428 nearest_neighbor = msgval
430 nearest_neighbor = array(ix,iy,izz)
433 nearest_neighbor = array(ix,iy,izz)
436 ! If we have a missing value, try the next interpolation method in the sequence
437 if (nearest_neighbor == msgval) then
438 nearest_neighbor = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
439 start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
442 end function nearest_neighbor
445 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
446 ! Name: search_extrap
448 ! Purpose: Returns the point nearest to (xx,yy) that has a non-missing value.
449 ! If no valid value can be found in the array, msgval is returned.
450 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
451 recursive function search_extrap(xx, yy, izz, array, start_x, end_x, &
452 start_y, end_y, start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
457 integer, intent(in) :: start_x, start_y, start_z
458 integer, intent(in) :: end_x, end_y, end_z
459 integer, intent(in) :: izz ! The z-index of the 2d-array to search
460 real, intent(in) :: xx , yy ! The location of the search origin
461 real, intent(in) :: msgval
462 real, intent(in), optional :: maskval
463 real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), &
465 integer, dimension(:), intent(in) :: interp_list
466 integer, dimension(:), intent(in) :: interp_opts
467 integer, intent(in) :: idx
468 real, dimension(start_x:end_x, start_y:end_y), &
469 intent(in), optional :: mask_array
470 character (len=1), intent(in), optional :: mask_relational
473 real :: search_extrap
478 logical :: found_valid
481 type (q_data) :: qdata
483 ! We only search if the starting point is within the array
484 if (nint(xx) < start_x .or. nint(xx) > end_x .or. &
485 nint(yy) < start_y .or. nint(yy) > end_y) then
486 search_extrap = msgval
490 call bitarray_create(b, (end_x-start_x+1), (end_y-start_y+1))
493 found_valid = .false.
497 call q_insert(q, qdata)
498 call bitarray_set(b, qdata%x-start_x+1, qdata%y-start_y+1)
500 do while (q_isdata(q) .and. (.not. found_valid))
505 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
506 if (mask_relational == '>' .and. mask_array(i,j) <= maskval .and. array(i,j,izz) /= msgval) then
508 else if (mask_relational == '<' .and. mask_array(i,j) >= maskval .and. array(i,j,izz) /= msgval) then
510 else if (mask_relational == ' ' .and. mask_array(i,j) /= maskval .and. array(i,j,izz) /= msgval) then
513 else if (present(mask_array) .and. present(maskval)) then
514 if (array(i,j,izz) /= msgval .and. mask_array(i,j) /= maskval) found_valid = .true.
516 if (array(i,j,izz) /= msgval) found_valid = .true.
519 if (i-1 >= start_x) then
520 if (.not. bitarray_test(b, (i-1)-start_x+1, j-start_y+1)) then
521 if (qdata%depth < interp_opts(idx-1)) then ! idx-1, since idx was incremented before call to this subroutine
524 qdata%depth = qdata%depth+1
525 call q_insert(q, qdata)
526 call bitarray_set(b, (i-1)-start_x+1, j-start_y+1)
530 if (i+1 <= end_x) then
531 if (.not. bitarray_test(b, (i+1)-start_x+1, j-start_y+1)) then
532 if (qdata%depth < interp_opts(idx-1)) then ! idx-1, since idx was incremented before call to this subroutine
535 qdata%depth = qdata%depth+1
536 call q_insert(q, qdata)
537 call bitarray_set(b, (i+1)-start_x+1, j-start_y+1)
541 if (j-1 >= start_y) then
542 if (.not. bitarray_test(b, i-start_x+1, (j-1)-start_y+1)) then
543 if (qdata%depth < interp_opts(idx-1)) then ! idx-1, since idx was incremented before call to this subroutine
546 qdata%depth = qdata%depth+1
547 call q_insert(q, qdata)
548 call bitarray_set(b, i-start_x+1, (j-1)-start_y+1)
552 if (j+1 <= end_y) then
553 if (.not. bitarray_test(b, i-start_x+1, (j+1)-start_y+1)) then
554 if (qdata%depth < interp_opts(idx-1)) then ! idx-1, since idx was incremented before call to this subroutine
557 qdata%depth = qdata%depth+1
558 call q_insert(q, qdata)
559 call bitarray_set(b, i-start_x+1, (j+1)-start_y+1)
565 if (found_valid) then
566 distance = (real(i)-xx)*(real(i)-xx)+(real(j)-yy)*(real(j)-yy)
567 search_extrap = array(i,j,izz)
568 do while (q_isdata(q))
570 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
571 if (mask_relational == '<' .and. mask_array(qdata%x,qdata%y) >= maskval &
572 .and. array(qdata%x,qdata%y,izz) /= msgval) then
573 if ((real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy) < distance) then
574 distance = (real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy)
575 search_extrap = array(qdata%x, qdata%y, izz)
577 else if (mask_relational == '>' .and. mask_array(qdata%x,qdata%y) <= maskval &
578 .and. array(qdata%x,qdata%y,izz) /= msgval) then
579 if ((real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy) < distance) then
580 distance = (real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy)
581 search_extrap = array(qdata%x, qdata%y, izz)
583 else if (mask_relational == ' ' .and. mask_array(qdata%x,qdata%y) /= maskval &
584 .and. array(qdata%x,qdata%y,izz) /= msgval) then
585 if ((real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy) < distance) then
586 distance = (real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy)
587 search_extrap = array(qdata%x, qdata%y, izz)
591 else if (present(mask_array) .and. present(maskval)) then
592 if (array(qdata%x,qdata%y,izz) /= msgval .and. mask_array(qdata%x,qdata%y) /= maskval) then
593 if ((real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy) < distance) then
594 distance = (real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy)
595 search_extrap = array(qdata%x, qdata%y, izz)
600 if (array(qdata%x,qdata%y,izz) /= msgval) then
601 if ((real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy) < distance) then
602 distance = (real(qdata%x)-xx)*(real(qdata%x)-xx)+(real(qdata%y)-yy)*(real(qdata%y)-yy)
603 search_extrap = array(qdata%x, qdata%y, izz)
609 search_extrap = msgval
613 call bitarray_destroy(b)
615 end function search_extrap
618 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
619 ! Name: four_pt_average
621 ! Purpose: Average of four surrounding grid point values
622 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
623 recursive function four_pt_average(xx, yy, izz, array, start_x, end_x, &
624 start_y, end_y, start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
629 integer, intent(in) :: start_x, start_y, start_z
630 integer, intent(in) :: end_x, end_y, end_z
631 integer, intent(in) :: izz ! The z-index of the 2d-array to
633 real, intent(in) :: xx, yy ! The location to interpolate to
634 real, intent(in) :: msgval
635 real, intent(in), optional :: maskval
636 real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), &
638 integer, dimension(:), intent(in) :: interp_list
639 integer, dimension(:), intent(in) :: interp_opts
640 integer, intent(in) :: idx
641 real, dimension(start_x:end_x, start_y:end_y), &
642 intent(in), optional :: mask_array
643 character (len=1), intent(in), optional :: mask_relational
646 real :: four_pt_average
649 integer :: ifx, ify, icx, icy
650 real :: fxfy, fxcy, cxfy, cxcy
662 ! First, make sure that the point is contained in the source array
663 if (ifx < start_x .or. icx > end_x .or. &
664 ify < start_y .or. icy > end_y) then
666 ! But if the point is at most half a grid point out, we can
667 ! still proceed with modified ifx, icx, ify, and icy.
668 if (xx > real(start_x)-0.5 .and. ifx < start_x) then
671 else if (xx < real(end_x)+0.5 .and. icx > end_x) then
676 if (yy > real(start_y)-0.5 .and. ify < start_y) then
679 else if (yy < real(end_y)+0.5 .and. icy > end_y) then
684 if (ifx < start_x .or. icx > end_x .or. &
685 ify < start_y .or. icy > end_y) then
686 four_pt_average = msgval
691 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
692 ! we determine which maskval is useable by... if the symbol > is found, then only
693 ! values less than 'maskval' can be used and if the symbol < is found,
694 ! then only the values greater than 'maskval' can be used.
695 if (mask_relational == '>') then
696 if (array(ifx, ify, izz) == msgval .or. mask_array(ifx,ify) > maskval) fxfy = 0.0
697 if (array(ifx, icy, izz) == msgval .or. mask_array(ifx,icy) > maskval) fxcy = 0.0
698 if (array(icx, ify, izz) == msgval .or. mask_array(icx,ify) > maskval) cxfy = 0.0
699 if (array(icx, icy, izz) == msgval .or. mask_array(icx,icy) > maskval) cxcy = 0.0
700 else if (mask_relational == '<') then
701 if (array(ifx, ify, izz) == msgval .or. mask_array(ifx,ify) < maskval) fxfy = 0.0
702 if (array(ifx, icy, izz) == msgval .or. mask_array(ifx,icy) < maskval) fxcy = 0.0
703 if (array(icx, ify, izz) == msgval .or. mask_array(icx,ify) < maskval) cxfy = 0.0
704 if (array(icx, icy, izz) == msgval .or. mask_array(icx,icy) < maskval) cxcy = 0.0
706 if (array(ifx, ify, izz) == msgval .or. mask_array(ifx,ify) == maskval) fxfy = 0.0
707 if (array(ifx, icy, izz) == msgval .or. mask_array(ifx,icy) == maskval) fxcy = 0.0
708 if (array(icx, ify, izz) == msgval .or. mask_array(icx,ify) == maskval) cxfy = 0.0
709 if (array(icx, icy, izz) == msgval .or. mask_array(icx,icy) == maskval) cxcy = 0.0
711 else if (present(mask_array) .and. present(maskval)) then
712 if (array(ifx, ify, izz) == msgval .or. mask_array(ifx,ify) == maskval) fxfy = 0.0
713 if (array(ifx, icy, izz) == msgval .or. mask_array(ifx,icy) == maskval) fxcy = 0.0
714 if (array(icx, ify, izz) == msgval .or. mask_array(icx,ify) == maskval) cxfy = 0.0
715 if (array(icx, icy, izz) == msgval .or. mask_array(icx,icy) == maskval) cxcy = 0.0
717 if (array(ifx, ify, izz) == msgval) fxfy = 0.0
718 if (array(ifx, icy, izz) == msgval) fxcy = 0.0
719 if (array(icx, ify, izz) == msgval) cxfy = 0.0
720 if (array(icx, icy, izz) == msgval) cxcy = 0.0
723 ! If all four points are missing, try the next interpolation method in the sequence
724 if (fxfy == 0.0 .and. fxcy == 0.0 .and. cxfy == 0.0 .and. cxcy == 0.0) then
725 four_pt_average = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
726 start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
728 four_pt_average = (fxfy * array(ifx, ify, izz) + &
729 fxcy * array(ifx, icy, izz) + &
730 cxfy * array(icx, ify, izz) + &
731 cxcy * array(icx, icy, izz) ) / (fxfy + fxcy + cxfy + cxcy)
734 end function four_pt_average
737 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
738 ! Name: wt_four_pt_average
740 ! Purpose: Weighted average of four surrounding grid point values
741 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
742 recursive function wt_four_pt_average(xx, yy, izz, array, start_x, end_x, &
743 start_y, end_y, start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
748 integer, intent(in) :: start_x, start_y, start_z
749 integer, intent(in) :: end_x, end_y, end_z
750 integer, intent(in) :: izz ! The z-index of the 2d-array to
752 real, intent(in) :: xx, yy ! The location to interpolate to
753 real, intent(in) :: msgval
754 real, intent(in), optional :: maskval
755 real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), &
757 integer, dimension(:), intent(in) :: interp_list
758 integer, dimension(:), intent(in) :: interp_opts
759 integer, intent(in) :: idx
760 real, dimension(start_x:end_x, start_y:end_y), &
761 intent(in), optional :: mask_array
762 character (len=1), intent(in), optional :: mask_relational
765 real :: wt_four_pt_average
768 integer :: ifx, ify, icx, icy
769 real :: fxfy, fxcy, cxfy, cxcy
776 fxfy = max(0., 1.0 - sqrt((xx-real(ifx))**2+(yy-real(ify))**2))
777 fxcy = max(0., 1.0 - sqrt((xx-real(ifx))**2+(yy-real(icy))**2))
778 cxfy = max(0., 1.0 - sqrt((xx-real(icx))**2+(yy-real(ify))**2))
779 cxcy = max(0., 1.0 - sqrt((xx-real(icx))**2+(yy-real(icy))**2))
781 ! First, make sure that the point is contained in the source array
782 if (ifx < start_x .or. icx > end_x .or. &
783 ify < start_y .or. icy > end_y) then
785 ! But if the point is at most half a grid point out, we can
786 ! still proceed with modified ifx, icx, ify, and icy.
787 if (xx > real(start_x)-0.5 .and. ifx < start_x) then
790 else if (xx < real(end_x)+0.5 .and. icx > end_x) then
795 if (yy > real(start_y)-0.5 .and. ifx < start_y) then
798 else if (yy < real(end_y)+0.5 .and. icy > end_y) then
803 if (ifx < start_x .or. icx > end_x .or. &
804 ify < start_y .or. icy > end_y) then
805 wt_four_pt_average = msgval
810 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
811 ! we determine which maskval is useable by... if the symbol > is found, then only
812 ! values less than 'maskval' can be used and if the symbol < is found,
813 ! then only the values greater than 'maskval' can be used.
814 if (mask_relational == '>') then
815 if (array(ifx, ify, izz) == msgval .or. mask_array(ifx,ify) > maskval) fxfy = 0.0
816 if (array(ifx, icy, izz) == msgval .or. mask_array(ifx,icy) > maskval) fxcy = 0.0
817 if (array(icx, ify, izz) == msgval .or. mask_array(icx,ify) > maskval) cxfy = 0.0
818 if (array(icx, icy, izz) == msgval .or. mask_array(icx,icy) > maskval) cxcy = 0.0
819 else if (mask_relational == '<') then
820 if (array(ifx, ify, izz) == msgval .or. mask_array(ifx,ify) < maskval) fxfy = 0.0
821 if (array(ifx, icy, izz) == msgval .or. mask_array(ifx,icy) < maskval) fxcy = 0.0
822 if (array(icx, ify, izz) == msgval .or. mask_array(icx,ify) < maskval) cxfy = 0.0
823 if (array(icx, icy, izz) == msgval .or. mask_array(icx,icy) < maskval) cxcy = 0.0
825 if (array(ifx, ify, izz) == msgval .or. mask_array(ifx,ify) == maskval) fxfy = 0.0
826 if (array(ifx, icy, izz) == msgval .or. mask_array(ifx,icy) == maskval) fxcy = 0.0
827 if (array(icx, ify, izz) == msgval .or. mask_array(icx,ify) == maskval) cxfy = 0.0
828 if (array(icx, icy, izz) == msgval .or. mask_array(icx,icy) == maskval) cxcy = 0.0
830 else if (present(mask_array) .and. present(maskval)) then
831 if (array(ifx, ify, izz) == msgval .or. mask_array(ifx,ify) == maskval) fxfy = 0.0
832 if (array(ifx, icy, izz) == msgval .or. mask_array(ifx,icy) == maskval) fxcy = 0.0
833 if (array(icx, ify, izz) == msgval .or. mask_array(icx,ify) == maskval) cxfy = 0.0
834 if (array(icx, icy, izz) == msgval .or. mask_array(icx,icy) == maskval) cxcy = 0.0
836 if (array(ifx, ify, izz) == msgval) fxfy = 0.0
837 if (array(ifx, icy, izz) == msgval) fxcy = 0.0
838 if (array(icx, ify, izz) == msgval) cxfy = 0.0
839 if (array(icx, icy, izz) == msgval) cxcy = 0.0
842 ! If all four points are missing, try the next interpolation method in the sequence
843 if (fxfy == 0.0 .and. fxcy == 0.0 .and. cxfy == 0.0 .and. cxcy == 0.0) then
844 wt_four_pt_average = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
845 start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
847 wt_four_pt_average = (fxfy * array(ifx, ify, izz) + &
848 fxcy * array(ifx, icy, izz) + &
849 cxfy * array(icx, ify, izz) + &
850 cxcy * array(icx, icy, izz) ) / (fxfy + fxcy + cxfy + cxcy)
853 end function wt_four_pt_average
856 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
857 ! Name: sixteen_pt_average
859 ! Purpose: Average of sixteen surrounding grid point values
860 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
861 recursive function sixteen_pt_average(xx, yy, izz, array, start_x, end_x, &
862 start_y, end_y, start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
867 integer, intent(in) :: start_x, start_y, start_z
868 integer, intent(in) :: end_x, end_y, end_z
869 integer, intent(in) :: izz ! The z-index of the 2d-array to
871 real, intent(in) :: xx , yy ! The location to interpolate to
872 real, intent(in) :: msgval
873 real, intent(in), optional :: maskval
874 real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), &
876 integer, dimension(:), intent(in) :: interp_list
877 integer, dimension(:), intent(in) :: interp_opts
878 integer, intent(in) :: idx
879 real, dimension(start_x:end_x, start_y:end_y), &
880 intent(in), optional :: mask_array
881 character (len=1), intent(in), optional :: mask_relational
884 real :: sixteen_pt_average
887 integer :: i, j, ifx, ify
888 real :: sum, sum_weight
889 real, dimension(4,4) :: weights
894 ! First see whether the point is far enough within the array to
895 ! allow for a sixteen point average.
896 if (ifx < start_x+1 .or. ifx > end_x-2 .or. &
897 ify < start_y+1 .or. ify > end_y-2) then
898 sixteen_pt_average = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
899 start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
906 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
907 if (mask_relational == '>' .and. mask_array(ifx+3-i, ify+3-j) > maskval) then
909 else if (mask_relational == '<' .and. mask_array(ifx+3-i, ify+3-j) < maskval) then
911 else if (mask_relational == ' ' .and. mask_array(ifx+3-i, ify+3-j) == maskval) then
916 if (array(ifx+3-i, ify+3-j, izz) == msgval) weights(i,j) = 0.0
917 else if (present(mask_array) .and. present(maskval)) then
918 if (array(ifx+3-i, ify+3-j, izz) == msgval .or. mask_array(ifx+3-i, ify+3-j) == maskval) then
924 if (array(ifx+3-i, ify+3-j, izz) == msgval) then
931 sum_weight = sum_weight + weights(i,j)
936 ! If all points are missing, try the next interpolation method in the sequence
937 if (sum_weight == 0.0) then
938 sixteen_pt_average = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
939 start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
944 sum = sum + weights(i,j) * array(ifx+3-i, ify+3-j, izz)
947 sixteen_pt_average = sum / sum_weight
950 end function sixteen_pt_average
953 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
954 ! Name: wt_sixteen_pt_average
956 ! Purpose: Weighted average of sixteen surrounding grid point values
957 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
958 recursive function wt_sixteen_pt_average(xx, yy, izz, array, start_x, end_x, &
959 start_y, end_y, start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
964 integer, intent(in) :: start_x, start_y, start_z
965 integer, intent(in) :: end_x, end_y, end_z
966 integer, intent(in) :: izz ! The z-index of the 2d-array to
968 real, intent(in) :: xx , yy ! The location to interpolate to
969 real, intent(in) :: msgval
970 real, intent(in), optional :: maskval
971 real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), &
973 integer, dimension(:), intent(in) :: interp_list
974 integer, dimension(:), intent(in) :: interp_opts
975 integer, intent(in) :: idx
976 real, dimension(start_x:end_x, start_y:end_y), &
977 intent(in), optional :: mask_array
978 character (len=1), intent(in), optional :: mask_relational
981 real :: wt_sixteen_pt_average
984 integer :: i, j, ifx, ify
985 real :: sum, sum_weight
986 real, dimension(4,4) :: weights
991 ! First see whether the point is far enough within the array to
992 ! allow for a sixteen point average.
993 if (ifx < start_x+1 .or. ifx > end_x-2 .or. &
994 ify < start_y+1 .or. ify > end_y-2) then
995 wt_sixteen_pt_average = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
996 start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1003 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
1004 if (mask_relational == '>' .and. mask_array(ifx+3-i, ify+3-j) > maskval) then
1006 else if (mask_relational == '<' .and. mask_array(ifx+3-i, ify+3-j) < maskval) then
1008 else if (mask_relational == ' ' .and. mask_array(ifx+3-i, ify+3-j) == maskval) then
1011 weights(i,j) = max(0., 2.0 - sqrt((xx-real(ifx+3-i))**2+(yy-real(ify+3-j))**2))
1013 if (array(ifx+3-i, ify+3-j, izz) == msgval) weights(i,j) = 0.0
1014 else if (present(mask_array) .and. present(maskval)) then
1015 if (array(ifx+3-i, ify+3-j, izz) == msgval .or. mask_array(ifx+3-i, ify+3-j) == maskval) then
1018 weights(i,j) = max(0., 2.0 - sqrt((xx-real(ifx+3-i))**2+(yy-real(ify+3-j))**2))
1021 if (array(ifx+3-i, ify+3-j, izz) == msgval) then
1024 weights(i,j) = max(0., 2.0 - sqrt((xx-real(ifx+3-i))**2+(yy-real(ify+3-j))**2))
1028 sum_weight = sum_weight + weights(i,j)
1033 ! If all points are missing, try the next interpolation method in the sequence
1034 if (sum_weight == 0.0) then
1035 wt_sixteen_pt_average = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
1036 start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1041 sum = sum + weights(i,j) * array(ifx+3-i, ify+3-j, izz)
1044 wt_sixteen_pt_average = sum / sum_weight
1047 end function wt_sixteen_pt_average
1050 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1053 ! Purpose: Bilinear interpolation among four grid values
1054 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1055 recursive function four_pt(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
1056 start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1061 integer, intent(in) :: start_x, start_y, start_z
1062 integer, intent(in) :: end_x, end_y, end_z
1063 integer, intent(in) :: izz ! The z-index of the 2d-array to
1064 ! interpolate within
1065 real, intent(in) :: xx , yy ! The location to interpolate to
1066 real, intent(in) :: msgval
1067 real, intent(in), optional :: maskval
1068 real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), intent(in) :: array
1069 integer, dimension(:), intent(in) :: interp_list
1070 integer, dimension(:), intent(in) :: interp_opts
1071 integer, intent(in) :: idx
1072 real, dimension(start_x:end_x, start_y:end_y), intent(in), optional :: mask_array
1073 character (len=1), intent(in), optional :: mask_relational
1079 integer :: min_x, min_y, max_x, max_y
1086 if (min_x < start_x .or. max_x > end_x) then
1087 four_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1088 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1092 if (min_y < start_y .or. max_y > end_y) then
1093 four_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1094 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1098 ! If we have a missing value, try the next interpolation method in the sequence
1099 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
1100 ! we determine which maskval is useable by... if the symbol > is found, then only
1101 ! values less than 'maskval' can be used and if the symbol < is found,
1102 ! then only the values greater than 'maskval' can be used.
1103 if (mask_relational == '>' ) then
1104 if (array(min_x,min_y,izz) == msgval .or. mask_array(min_x,min_y) > maskval .or. &
1105 array(max_x,min_y,izz) == msgval .or. mask_array(max_x,min_y) > maskval .or. &
1106 array(min_x,max_y,izz) == msgval .or. mask_array(min_x,max_y) > maskval .or. &
1107 array(max_x,max_y,izz) == msgval .or. mask_array(max_x,max_y) > maskval) then
1108 four_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1109 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1112 else if (mask_relational == '<' ) then
1113 if (array(min_x,min_y,izz) == msgval .or. mask_array(min_x,min_y) < maskval .or. &
1114 array(max_x,min_y,izz) == msgval .or. mask_array(max_x,min_y) < maskval .or. &
1115 array(min_x,max_y,izz) == msgval .or. mask_array(min_x,max_y) < maskval .or. &
1116 array(max_x,max_y,izz) == msgval .or. mask_array(max_x,max_y) < maskval) then
1117 four_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1118 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1121 else if (mask_relational == ' ' ) then
1122 if (array(min_x,min_y,izz) == msgval .or. mask_array(min_x,min_y) == maskval .or. &
1123 array(max_x,min_y,izz) == msgval .or. mask_array(max_x,min_y) == maskval .or. &
1124 array(min_x,max_y,izz) == msgval .or. mask_array(min_x,max_y) == maskval .or. &
1125 array(max_x,max_y,izz) == msgval .or. mask_array(max_x,max_y) == maskval) then
1126 four_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1127 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1131 else if (present(mask_array) .and. present(maskval)) then
1132 if (array(min_x,min_y,izz) == msgval .or. mask_array(min_x,min_y) == maskval .or. &
1133 array(max_x,min_y,izz) == msgval .or. mask_array(max_x,min_y) == maskval .or. &
1134 array(min_x,max_y,izz) == msgval .or. mask_array(min_x,max_y) == maskval .or. &
1135 array(max_x,max_y,izz) == msgval .or. mask_array(max_x,max_y) == maskval) then
1136 four_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1137 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1140 if (array(min_x,min_y,izz) == msgval .or. &
1141 array(max_x,min_y,izz) == msgval .or. &
1142 array(min_x,max_y,izz) == msgval .or. &
1143 array(max_x,max_y,izz) == msgval ) then
1144 four_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
1145 start_z, end_z, msgval, interp_list, interp_opts, idx)
1150 if (min_x == max_x) then
1151 if (min_y == max_y) then
1152 four_pt = array(min_x,min_y,izz)
1154 four_pt = array(min_x,min_y,izz)*(real(max_y)-yy) + &
1155 array(min_x,max_y,izz)*(yy-real(min_y))
1157 else if (min_y == max_y) then
1158 if (min_x == max_x) then
1159 four_pt = array(min_x,min_y,izz)
1161 four_pt = array(min_x,min_y,izz)*(real(max_x)-xx) + &
1162 array(max_x,min_y,izz)*(xx-real(min_x))
1165 four_pt = (yy - min_y) * (array(min_x,max_y,izz)*(real(max_x)-xx) + &
1166 array(max_x,max_y,izz)*(xx-real(min_x))) + &
1167 (max_y - yy) * (array(min_x,min_y,izz)*(real(max_x)-xx) + &
1168 array(max_x,min_y,izz)*(xx-real(min_x)));
1171 end function four_pt
1174 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1177 ! Purpose: Overlapping parabolic interpolation among sixteen grid values
1178 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1179 recursive function sixteen_pt(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1180 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1185 integer, intent(in) :: izz ! z-index of 2d-array to interpolate within
1186 integer, intent(in) :: start_x, start_y, start_z
1187 integer, intent(in) :: end_x, end_y, end_z
1188 real, intent(in) :: xx , yy ! The location to interpolate to
1189 real, intent(in) :: msgval
1190 real, intent(in), optional :: maskval
1191 real, dimension(start_x:end_x, start_y:end_y, start_z:end_z), &
1193 integer, dimension(:), intent(in) :: interp_list
1194 integer, dimension(:), intent(in) :: interp_opts
1195 integer, intent(in) :: idx
1196 real, dimension(start_x:end_x, start_y:end_y), &
1197 intent(in), optional :: mask_array
1198 character (len=1), intent(in), optional :: mask_relational
1204 integer :: n , i , j , k , kk , l , ll
1205 real :: x , y , a , b , c , d , e , f , g , h
1206 real, dimension(4,4) :: stl
1207 logical :: is_masked
1211 if (int(xx) < start_x .or. int(xx) > end_x .or. &
1212 int(yy) < start_y .or. int(yy) > end_y) then
1213 sixteen_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
1214 start_z, end_z, msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1220 i = int(xx + 0.00001)
1221 j = int(yy + 0.00001)
1225 if ( ( abs(x) > 0.0001 ) .or. ( abs(y) > 0.0001 ) ) then
1229 if ( kk < start_x) then
1231 else if ( kk > end_x) then
1237 if ( ll < start_y ) then
1239 else if ( ll > end_y) then
1242 stl(k,l) = array(kk,ll,izz)
1244 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
1245 if (mask_relational == '>' .and. mask_array(kk,ll) > maskval) then
1247 else if (mask_relational == '<' .and. mask_array(kk,ll) < maskval) then
1249 else if (mask_relational == ' ' .and. mask_array(kk,ll) == maskval) then
1252 else if (present(mask_array) .and. present(maskval)) then
1253 if (mask_array(kk,ll) == maskval) is_masked = .true.
1255 if ( stl(k,l) == 0. .and. msgval /= 0.) then
1261 ! If we have a missing value, try the next interpolation method in the sequence
1262 if (present(mask_array) .and. present(maskval)) then
1265 if (stl(k,l) == msgval .or. is_masked) then
1266 sixteen_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
1267 start_z, end_z, msgval, interp_list, interp_opts, idx, &
1268 mask_relational, maskval, mask_array)
1276 if (stl(k,l) == msgval) then
1277 sixteen_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, &
1278 start_z, end_z, msgval, interp_list, interp_opts, idx)
1285 a = oned(x,stl(1,1),stl(2,1),stl(3,1),stl(4,1))
1286 b = oned(x,stl(1,2),stl(2,2),stl(3,2),stl(4,2))
1287 c = oned(x,stl(1,3),stl(2,3),stl(3,3),stl(4,3))
1288 d = oned(x,stl(1,4),stl(2,4),stl(3,4),stl(4,4))
1289 sixteen_pt = oned(y,a,b,c,d)
1292 e = oned(y,stl(1,1),stl(1,2),stl(1,3),stl(1,4))
1293 f = oned(y,stl(2,1),stl(2,2),stl(2,3),stl(2,4))
1294 g = oned(y,stl(3,1),stl(3,2),stl(3,3),stl(3,4))
1295 h = oned(y,stl(4,1),stl(4,2),stl(4,3),stl(4,4))
1296 sixteen_pt = (sixteen_pt+oned(x,e,f,g,h)) * 0.5
1299 if (sixteen_pt == 1.E-20) sixteen_pt = 0.
1302 if (present(mask_array) .and. present(maskval) .and. present(mask_relational)) then
1303 if (i >= start_x .and. i <= end_x .and. j >= start_y .and. j <= end_y .and. &
1304 mask_relational == '<' .and. mask_array(i,j) >= maskval .and. array(i,j,izz) /= msgval) then
1305 sixteen_pt = array(i,j,izz)
1306 else if (i >= start_x .and. i <= end_x .and. j >= start_y .and. j <= end_y .and. &
1307 mask_relational == '>' .and. mask_array(i,j) <= maskval .and. array(i,j,izz) /= msgval) then
1308 sixteen_pt = array(i,j,izz)
1309 else if (i >= start_x .and. i <= end_x .and. j >= start_y .and. j <= end_y .and. &
1310 mask_relational == ' ' .and. mask_array(i,j) /= maskval .and. array(i,j,izz) /= msgval) then
1311 sixteen_pt = array(i,j,izz)
1313 sixteen_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1314 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1316 else if (present(mask_array) .and. present(maskval)) then
1317 if (i >= start_x .and. i <= end_x .and. j >= start_y .and. j <= end_y .and. &
1318 mask_array(i,j) /= maskval .and. array(i,j,izz) /= msgval) then
1319 sixteen_pt = array(i,j,izz)
1321 sixteen_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1322 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1325 if (i >= start_x .and. i <= end_x .and. j >= start_y .and. j <= end_y .and. array(i,j,izz) /= msgval) then
1326 sixteen_pt = array(i,j,izz)
1328 sixteen_pt = interp_sequence(xx, yy, izz, array, start_x, end_x, start_y, end_y, start_z, end_z, &
1329 msgval, interp_list, interp_opts, idx, mask_relational, maskval, mask_array)
1334 end function sixteen_pt
1337 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1340 ! Purpose: 1-dimensional overlapping parabolic interpolation
1341 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1342 function oned(x,a,b,c,d)
1347 real, intent(in) :: x,a,b,c,d
1356 else if ( x == 1. ) then
1361 if ( a*d == 0. ) then
1362 if ( ( a == 0 ) .and. ( d == 0 ) ) then
1363 oned = b*(1.0-x)+c*x
1364 else if ( a /= 0. ) then
1365 oned = b+x*(0.5*(c-a)+x*(0.5*(c+a)-b))
1366 else if ( d /= 0. ) then
1367 oned = c+(1.0-x)*(0.5*(b-d)+(1.0-x)*(0.5*(b+d)-c))
1370 oned = (1.0-x)*(b+x*(0.5*(c-a)+x*(0.5*(c+a)-b)))+x*(c+(1.0-x)*(0.5*(b-d)+(1.0-x)*(0.5*(b+d)-c)))
1376 end module interp_module