13 use plm_functions,
only : plm_reconstruction, plm_boundary_extrapolation
14 use ppm_functions,
only : ppm_reconstruction, ppm_boundary_extrapolation
15 use pqm_functions,
only : pqm_reconstruction, pqm_boundary_extrapolation_v1
17 use p1m_functions,
only : p1m_interpolation, p1m_boundary_extrapolation
18 use p3m_functions,
only : p3m_interpolation, p3m_boundary_extrapolation
20 implicit none ;
private
28 integer :: interpolation_scheme = -1
32 logical :: boundary_extrapolation
35 logical :: answers_2018 = .true.
38 public regridding_set_ppolys, interpolate_grid
39 public build_and_interpolate_grid
40 public set_interp_scheme, set_interp_extrap
43 integer,
parameter :: interpolation_p1m_h2 = 0
44 integer,
parameter :: interpolation_p1m_h4 = 1
45 integer,
parameter :: interpolation_p1m_ih4 = 2
46 integer,
parameter :: interpolation_plm = 3
47 integer,
parameter :: interpolation_ppm_h4 = 4
48 integer,
parameter :: interpolation_ppm_ih4 = 5
49 integer,
parameter :: interpolation_p3m_ih4ih3 = 6
50 integer,
parameter :: interpolation_p3m_ih6ih5 = 7
51 integer,
parameter :: interpolation_pqm_ih4ih3 = 8
52 integer,
parameter :: interpolation_pqm_ih6ih5 = 9
55 integer,
parameter :: degree_1 = 1, degree_2 = 2, degree_3 = 3, degree_4 = 4
56 integer,
public,
parameter :: degree_max = 5
62 real,
public,
parameter :: nr_offset = 1e-6
66 integer,
public,
parameter :: nr_iterations = 8
68 real,
public,
parameter :: nr_tolerance = 1e-12
78 subroutine regridding_set_ppolys(CS, densities, n0, h0, ppoly0_E, ppoly0_S, &
79 ppoly0_coefs, degree, h_neglect, h_neglect_edge)
81 integer,
intent(in) :: n0
82 real,
dimension(n0),
intent(in) :: densities
83 real,
dimension(n0),
intent(in) :: h0
84 real,
dimension(n0,2),
intent(inout) :: ppoly0_e
85 real,
dimension(n0,2),
intent(inout) :: ppoly0_s
86 real,
dimension(n0,DEGREE_MAX+1),
intent(inout) :: ppoly0_coefs
87 integer,
intent(inout) :: degree
88 real,
optional,
intent(in) :: h_neglect
91 real,
optional,
intent(in) :: h_neglect_edge
95 logical :: extrapolate
100 ppoly0_coefs(:,:) = 0.0
102 extrapolate = cs%boundary_extrapolation
105 select case (cs%interpolation_scheme)
107 case ( interpolation_p1m_h2 )
109 call edge_values_explicit_h2( n0, h0, densities, ppoly0_e )
110 call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
111 if (extrapolate)
then
112 call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
115 case ( interpolation_p1m_h4 )
118 call edge_values_explicit_h4( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
120 call edge_values_explicit_h2( n0, h0, densities, ppoly0_e )
122 call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
123 if (extrapolate)
then
124 call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
127 case ( interpolation_p1m_ih4 )
130 call edge_values_implicit_h4( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
132 call edge_values_explicit_h2( n0, h0, densities, ppoly0_e )
134 call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
135 if (extrapolate)
then
136 call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
139 case ( interpolation_plm )
141 call plm_reconstruction( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
142 if (extrapolate)
then
143 call plm_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
146 case ( interpolation_ppm_h4 )
149 call edge_values_explicit_h4( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
150 call ppm_reconstruction( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
151 if (extrapolate)
then
152 call ppm_boundary_extrapolation( n0, h0, densities, ppoly0_e, &
153 ppoly0_coefs, h_neglect )
157 call edge_values_explicit_h2( n0, h0, densities, ppoly0_e )
158 call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
159 if (extrapolate)
then
160 call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
164 case ( interpolation_ppm_ih4 )
167 call edge_values_implicit_h4( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
168 call ppm_reconstruction( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
169 if (extrapolate)
then
170 call ppm_boundary_extrapolation( n0, h0, densities, ppoly0_e, &
171 ppoly0_coefs, h_neglect )
175 call edge_values_explicit_h2( n0, h0, densities, ppoly0_e )
176 call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
177 if (extrapolate)
then
178 call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
182 case ( interpolation_p3m_ih4ih3 )
185 call edge_values_implicit_h4( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
186 call edge_slopes_implicit_h3( n0, h0, densities, ppoly0_s, h_neglect, answers_2018=cs%answers_2018 )
187 call p3m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_s, &
188 ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
189 if (extrapolate)
then
190 call p3m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_s, &
191 ppoly0_coefs, h_neglect, h_neglect_edge )
195 call edge_values_explicit_h2( n0, h0, densities, ppoly0_e )
196 call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
197 if (extrapolate)
then
198 call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
202 case ( interpolation_p3m_ih6ih5 )
205 call edge_values_implicit_h6( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
206 call edge_slopes_implicit_h5( n0, h0, densities, ppoly0_s, h_neglect, answers_2018=cs%answers_2018 )
207 call p3m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_s, &
208 ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
209 if (extrapolate)
then
210 call p3m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_s, &
211 ppoly0_coefs, h_neglect, h_neglect_edge )
215 call edge_values_explicit_h2( n0, h0, densities, ppoly0_e )
216 call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
217 if (extrapolate)
then
218 call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
222 case ( interpolation_pqm_ih4ih3 )
225 call edge_values_implicit_h4( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
226 call edge_slopes_implicit_h3( n0, h0, densities, ppoly0_s, h_neglect, answers_2018=cs%answers_2018 )
227 call pqm_reconstruction( n0, h0, densities, ppoly0_e, ppoly0_s, &
228 ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
229 if (extrapolate)
then
230 call pqm_boundary_extrapolation_v1( n0, h0, densities, ppoly0_e, ppoly0_s, &
231 ppoly0_coefs, h_neglect )
235 call edge_values_explicit_h2( n0, h0, densities, ppoly0_e )
236 call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
237 if (extrapolate)
then
238 call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
242 case ( interpolation_pqm_ih6ih5 )
245 call edge_values_implicit_h6( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
246 call edge_slopes_implicit_h5( n0, h0, densities, ppoly0_s, h_neglect, answers_2018=cs%answers_2018 )
247 call pqm_reconstruction( n0, h0, densities, ppoly0_e, ppoly0_s, &
248 ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
249 if (extrapolate)
then
250 call pqm_boundary_extrapolation_v1( n0, h0, densities, ppoly0_e, ppoly0_s, &
251 ppoly0_coefs, h_neglect )
255 call edge_values_explicit_h2( n0, h0, densities, ppoly0_e )
256 call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect, answers_2018=cs%answers_2018 )
257 if (extrapolate)
then
258 call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
263 end subroutine regridding_set_ppolys
270 subroutine interpolate_grid( n0, h0, x0, ppoly0_E, ppoly0_coefs, &
271 target_values, degree, n1, h1, x1, answers_2018 )
272 integer,
intent(in) :: n0
273 integer,
intent(in) :: n1
274 real,
dimension(n0),
intent(in) :: h0
275 real,
dimension(n0+1),
intent(in) :: x0
276 real,
dimension(n0,2),
intent(in) :: ppoly0_e
277 real,
dimension(n0,DEGREE_MAX+1), &
278 intent(in) :: ppoly0_coefs
279 real,
dimension(n1+1),
intent(in) :: target_values
280 integer,
intent(in) :: degree
281 real,
dimension(n1),
intent(inout) :: h1
282 real,
dimension(n1+1),
intent(inout) :: x1
283 logical,
optional,
intent(in) :: answers_2018
286 logical :: use_2018_answers
298 x1(k) = get_polynomial_coordinate( n0, h0, x0, ppoly0_e, ppoly0_coefs, t, degree, &
299 answers_2018=answers_2018 )
300 h1(k-1) = x1(k) - x1(k-1)
302 h1(n1) = x1(n1+1) - x1(n1)
304 end subroutine interpolate_grid
307 subroutine build_and_interpolate_grid(CS, densities, n0, h0, x0, target_values, &
308 n1, h1, x1, h_neglect, h_neglect_edge)
310 integer,
intent(in) :: n0
311 integer,
intent(in) :: n1
312 real,
dimension(n0),
intent(in) :: densities
313 real,
dimension(n1+1),
intent(in) :: target_values
314 real,
dimension(n0),
intent(in) :: h0
315 real,
dimension(n0+1),
intent(in) :: x0
316 real,
dimension(n1),
intent(inout) :: h1
317 real,
dimension(n1+1),
intent(inout) :: x1
318 real,
optional,
intent(in) :: h_neglect
321 real,
optional,
intent(in) :: h_neglect_edge
325 real,
dimension(n0,2) :: ppoly0_e
326 real,
dimension(n0,2) :: ppoly0_s
327 real,
dimension(n0,DEGREE_MAX+1) :: ppoly0_c
330 call regridding_set_ppolys(cs, densities, n0, h0, ppoly0_e, ppoly0_s, ppoly0_c, &
331 degree, h_neglect, h_neglect_edge)
332 call interpolate_grid(n0, h0, x0, ppoly0_e, ppoly0_c, target_values, degree, &
333 n1, h1, x1, answers_2018=cs%answers_2018)
334 end subroutine build_and_interpolate_grid
352 function get_polynomial_coordinate( N, h, x_g, edge_values, ppoly_coefs, &
353 target_value, degree, answers_2018 )
result ( x_tgt )
355 integer,
intent(in) :: n
356 real,
dimension(N),
intent(in) :: h
357 real,
dimension(N+1),
intent(in) :: x_g
358 real,
dimension(N,2),
intent(in) :: edge_values
359 real,
dimension(N,DEGREE_MAX+1),
intent(in) :: ppoly_coefs
360 real,
intent(in) :: target_value
361 integer,
intent(in) :: degree
362 logical,
optional,
intent(in) :: answers_2018
367 real,
dimension(DEGREE_MAX) :: a
374 integer :: i, k, iter
376 character(len=200) :: mesg
377 logical :: use_2018_answers
381 use_2018_answers = .true. ;
if (
present(answers_2018)) use_2018_answers = answers_2018
386 if ( target_value <= edge_values(1,1) )
then
394 if ( ( target_value >= edge_values(k-1,2) ) .AND. ( target_value <= edge_values(k,1) ) )
then
403 if ( target_value >= edge_values(n,2) )
then
414 if ( ( target_value > edge_values(k,1) ) .AND. ( target_value < edge_values(k,2) ) )
then
425 if ( k_found == -1 )
then
426 write(mesg,*)
'Could not find target coordinate', target_value,
'in get_polynomial_coordinate. This is '//&
427 'caused by an inconsistent interpolant (perhaps not monotonically increasing):', &
428 target_value, edge_values(1,1), edge_values(n,2)
429 call mom_error( fatal, mesg )
436 a(i) = ppoly_coefs(k_found,i)
443 do iter = 1,nr_iterations
445 if (use_2018_answers)
then
446 numerator = a(1) + a(2)*xi0 + a(3)*xi0*xi0 + a(4)*xi0*xi0*xi0 + &
447 a(5)*xi0*xi0*xi0*xi0 - target_value
448 denominator = a(2) + 2*a(3)*xi0 + 3*a(4)*xi0*xi0 + 4*a(5)*xi0*xi0*xi0
450 numerator = (a(1) - target_value) + xi0*(a(2) + xi0*(a(3) + xi0*(a(4) + a(5)*xi0)))
451 denominator = a(2) + xi0*(2.*a(3) + xi0*(3.*a(4) + 4.*a(5)*xi0))
454 delta = -numerator / denominator
463 if ( xi0 < 0.0 )
then
466 if ( grad == 0.0 ) xi0 = xi0 + eps
469 if ( xi0 > 1.0 )
then
471 if (use_2018_answers)
then
472 grad = a(2) + 2*a(3) + 3*a(4) + 4*a(5)
474 grad = a(2) + (2.*a(3) + (3.*a(4) + 4.*a(5)))
476 if ( grad == 0.0 ) xi0 = xi0 - eps
480 if ( abs(delta) < nr_tolerance )
exit
483 x_tgt = x_g(k_found) + xi0 * h(k_found)
484 end function get_polynomial_coordinate
487 integer function interpolation_scheme(interp_scheme)
488 character(len=*),
intent(in) :: interp_scheme
492 select case ( uppercase(trim(interp_scheme)) )
493 case (
"P1M_H2"); interpolation_scheme = interpolation_p1m_h2
494 case (
"P1M_H4"); interpolation_scheme = interpolation_p1m_h4
495 case (
"P1M_IH2"); interpolation_scheme = interpolation_p1m_ih4
496 case (
"PLM"); interpolation_scheme = interpolation_plm
497 case (
"PPM_H4"); interpolation_scheme = interpolation_ppm_h4
498 case (
"PPM_IH4"); interpolation_scheme = interpolation_ppm_ih4
499 case (
"P3M_IH4IH3"); interpolation_scheme = interpolation_p3m_ih4ih3
500 case (
"P3M_IH6IH5"); interpolation_scheme = interpolation_p3m_ih6ih5
501 case (
"PQM_IH4IH3"); interpolation_scheme = interpolation_pqm_ih4ih3
502 case (
"PQM_IH6IH5"); interpolation_scheme = interpolation_pqm_ih6ih5
503 case default ;
call mom_error(fatal,
"regrid_interp: "//&
504 "Unrecognized choice for INTERPOLATION_SCHEME ("//trim(interp_scheme)//
").")
506 end function interpolation_scheme
509 subroutine set_interp_scheme(CS, interp_scheme)
511 character(len=*),
intent(in) :: interp_scheme
515 cs%interpolation_scheme = interpolation_scheme(interp_scheme)
516 end subroutine set_interp_scheme
519 subroutine set_interp_extrap(CS, extrap)
521 logical,
intent(in) :: extrap
524 cs%boundary_extrapolation = extrap
525 end subroutine set_interp_extrap