MOM6
regrid_interp.F90
Go to the documentation of this file.
1 !> Vertical interpolation for regridding
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_error_handler, only : mom_error, fatal
8 
12 
16 
19 
20 implicit none ; private
21 
22 !> Control structure for regrid_interp module
23 type, public :: interp_cs_type ; private
24 
25  !> The following parameter is only relevant when used with the target
26  !! interface densities regridding scheme. It indicates which interpolation
27  !! to use to determine the grid.
28  integer :: interpolation_scheme = -1
29 
30  !> Indicate whether high-order boundary extrapolation should be used within
31  !! boundary cells
32  logical :: boundary_extrapolation
33 
34  !> If true use older, less acccurate expressions.
35  logical :: answers_2018 = .true.
36 end type interp_cs_type
37 
41 
42 ! List of interpolation schemes
43 integer, parameter :: interpolation_p1m_h2 = 0 !< O(h^2)
44 integer, parameter :: interpolation_p1m_h4 = 1 !< O(h^2)
45 integer, parameter :: interpolation_p1m_ih4 = 2 !< O(h^2)
46 integer, parameter :: interpolation_plm = 3 !< O(h^2)
47 integer, parameter :: interpolation_ppm_h4 = 4 !< O(h^3)
48 integer, parameter :: interpolation_ppm_ih4 = 5 !< O(h^3)
49 integer, parameter :: interpolation_p3m_ih4ih3 = 6 !< O(h^4)
50 integer, parameter :: interpolation_p3m_ih6ih5 = 7 !< O(h^4)
51 integer, parameter :: interpolation_pqm_ih4ih3 = 8 !< O(h^4)
52 integer, parameter :: interpolation_pqm_ih6ih5 = 9 !< O(h^5)
53 
54 !>@{ Interpolant degrees
55 integer, parameter :: degree_1 = 1, degree_2 = 2, degree_3 = 3, degree_4 = 4
56 integer, public, parameter :: degree_max = 5
57 !!@}
58 
59 !> When the N-R algorithm produces an estimate that lies outside [0,1], the
60 !! estimate is set to be equal to the boundary location, 0 or 1, plus or minus
61 !! an offset, respectively, when the derivative is zero at the boundary.
62 real, public, parameter :: nr_offset = 1e-6
63 !> Maximum number of Newton-Raphson iterations. Newton-Raphson iterations are
64 !! used to build the new grid by finding the coordinates associated with
65 !! target densities and interpolations of degree larger than 1.
66 integer, public, parameter :: nr_iterations = 8
67 !> Tolerance for Newton-Raphson iterations (stop when increment falls below this)
68 real, public, parameter :: nr_tolerance = 1e-12
69 
70 contains
71 
72 !> Builds an interpolated profile for the densities within each grid cell.
73 !!
74 !! It may happen that, given a high-order interpolator, the number of
75 !! available layers is insufficient (e.g., there are two available layers for
76 !! a third-order PPM ih4 scheme). In these cases, we resort to the simplest
77 !! continuous linear scheme (P1M h2).
78 subroutine regridding_set_ppolys(CS, densities, n0, h0, ppoly0_E, ppoly0_S, &
79  ppoly0_coefs, degree, h_neglect, h_neglect_edge)
80  type(interp_cs_type),intent(in) :: cs !< Interpolation control structure
81  real, dimension(:), intent(in) :: densities !< Actual cell densities
82  integer, intent(in) :: n0 !< Number of cells on source grid
83  real, dimension(:), intent(in) :: h0 !< cell widths on source grid
84  real, dimension(:,:),intent(inout) :: ppoly0_e !< Edge value of polynomial
85  real, dimension(:,:),intent(inout) :: ppoly0_s !< Edge slope of polynomial
86  real, dimension(:,:),intent(inout) :: ppoly0_coefs !< Coefficients of polynomial
87  integer, intent(inout) :: degree !< The degree of the polynomials
88  real, optional, intent(in) :: h_neglect !< A negligibly small width for the
89  !! purpose of cell reconstructions
90  !! in the same units as h0.
91  real, optional, intent(in) :: h_neglect_edge !< A negligibly small width
92  !! for the purpose of edge value calculations
93  !! in the same units as h0.
94  ! Local variables
95  logical :: extrapolate
96 
97  ! Reset piecewise polynomials
98  ppoly0_e(:,:) = 0.0
99  ppoly0_s(:,:) = 0.0
100  ppoly0_coefs(:,:) = 0.0
101 
102  extrapolate = cs%boundary_extrapolation
103 
104  ! Compute the interpolated profile of the density field and build grid
105  select case (cs%interpolation_scheme)
106 
107  case ( interpolation_p1m_h2 )
108  degree = degree_1
109  call edge_values_explicit_h2( n0, h0, densities, ppoly0_e, h_neglect_edge )
110  call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
111  if (extrapolate) then
112  call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
113  endif
114 
115  case ( interpolation_p1m_h4 )
116  degree = degree_1
117  if ( n0 >= 4 ) then
118  call edge_values_explicit_h4( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
119  else
120  call edge_values_explicit_h2( n0, h0, densities, ppoly0_e, h_neglect_edge )
121  endif
122  call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
123  if (extrapolate) then
124  call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
125  endif
126 
127  case ( interpolation_p1m_ih4 )
128  degree = degree_1
129  if ( n0 >= 4 ) then
130  call edge_values_implicit_h4( n0, h0, densities, ppoly0_e, h_neglect_edge, answers_2018=cs%answers_2018 )
131  else
132  call edge_values_explicit_h2( n0, h0, densities, ppoly0_e, h_neglect_edge )
133  endif
134  call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
135  if (extrapolate) then
136  call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
137  endif
138 
139  case ( interpolation_plm )
140  degree = degree_1
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 )
144  endif
145 
146  case ( interpolation_ppm_h4 )
147  if ( n0 >= 4 ) then
148  degree = degree_2
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 )
151  if (extrapolate) then
152  call ppm_boundary_extrapolation( n0, h0, densities, ppoly0_e, &
153  ppoly0_coefs, h_neglect )
154  endif
155  else
156  degree = degree_1
157  call edge_values_explicit_h2( n0, h0, densities, ppoly0_e, h_neglect_edge )
158  call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
159  if (extrapolate) then
160  call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
161  endif
162  endif
163 
164  case ( interpolation_ppm_ih4 )
165  if ( n0 >= 4 ) then
166  degree = degree_2
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 )
169  if (extrapolate) then
170  call ppm_boundary_extrapolation( n0, h0, densities, ppoly0_e, &
171  ppoly0_coefs, h_neglect )
172  endif
173  else
174  degree = degree_1
175  call edge_values_explicit_h2( n0, h0, densities, ppoly0_e, h_neglect_edge )
176  call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
177  if (extrapolate) then
178  call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
179  endif
180  endif
181 
182  case ( interpolation_p3m_ih4ih3 )
183  if ( n0 >= 4 ) then
184  degree = degree_3
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 )
189  if (extrapolate) then
190  call p3m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_s, &
191  ppoly0_coefs, h_neglect, h_neglect_edge )
192  endif
193  else
194  degree = degree_1
195  call edge_values_explicit_h2( n0, h0, densities, ppoly0_e, h_neglect_edge )
196  call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
197  if (extrapolate) then
198  call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
199  endif
200  endif
201 
202  case ( interpolation_p3m_ih6ih5 )
203  if ( n0 >= 6 ) then
204  degree = degree_3
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 )
209  if (extrapolate) then
210  call p3m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_s, &
211  ppoly0_coefs, h_neglect, h_neglect_edge )
212  endif
213  else
214  degree = degree_1
215  call edge_values_explicit_h2( n0, h0, densities, ppoly0_e, h_neglect_edge )
216  call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
217  if (extrapolate) then
218  call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
219  endif
220  endif
221 
222  case ( interpolation_pqm_ih4ih3 )
223  if ( n0 >= 4 ) then
224  degree = degree_4
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 )
229  if (extrapolate) then
230  call pqm_boundary_extrapolation_v1( n0, h0, densities, ppoly0_e, ppoly0_s, &
231  ppoly0_coefs, h_neglect )
232  endif
233  else
234  degree = degree_1
235  call edge_values_explicit_h2( n0, h0, densities, ppoly0_e, h_neglect_edge )
236  call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
237  if (extrapolate) then
238  call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
239  endif
240  endif
241 
242  case ( interpolation_pqm_ih6ih5 )
243  if ( n0 >= 6 ) then
244  degree = degree_4
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 )
249  if (extrapolate) then
250  call pqm_boundary_extrapolation_v1( n0, h0, densities, ppoly0_e, ppoly0_s, &
251  ppoly0_coefs, h_neglect )
252  endif
253  else
254  degree = degree_1
255  call edge_values_explicit_h2( n0, h0, densities, ppoly0_e, h_neglect_edge )
256  call p1m_interpolation( n0, h0, densities, ppoly0_e, ppoly0_coefs, h_neglect )
257  if (extrapolate) then
258  call p1m_boundary_extrapolation( n0, h0, densities, ppoly0_e, ppoly0_coefs )
259  endif
260  endif
261  end select
262 end subroutine regridding_set_ppolys
263 
264 !> Given target values (e.g., density), build new grid based on polynomial
265 !!
266 !! Given the grid 'grid0' and the piecewise polynomial interpolant
267 !! 'ppoly0' (possibly discontinuous), the coordinates of the new grid 'grid1'
268 !! are determined by finding the corresponding target interface densities.
269 subroutine interpolate_grid( n0, h0, x0, ppoly0_E, ppoly0_coefs, &
270  target_values, degree, n1, h1, x1, answers_2018 )
271  integer, intent(in) :: n0 !< Number of points on source grid
272  real, dimension(:), intent(in) :: h0 !< Thicknesses of source grid cells
273  real, dimension(:), intent(in) :: x0 !< Source interface positions
274  real, dimension(:,:), intent(in) :: ppoly0_e !< Edge values of interpolating polynomials
275  real, dimension(:,:), intent(in) :: ppoly0_coefs !< Coefficients of interpolating polynomials
276  real, dimension(:), intent(in) :: target_values !< Target values of interfaces
277  integer, intent(in) :: degree !< Degree of interpolating polynomials
278  integer, intent(in) :: n1 !< Number of points on target grid
279  real, dimension(:), intent(inout) :: h1 !< Thicknesses of target grid cells
280  real, dimension(:), intent(inout) :: x1 !< Target interface positions
281  logical, optional, intent(in) :: answers_2018 !< If true use older, less acccurate expressions.
282 
283  ! Local variables
284  logical :: use_2018_answers ! If true use older, less acccurate expressions.
285  integer :: k ! loop index
286  real :: t ! current interface target density
287 
288  ! Make sure boundary coordinates of new grid coincide with boundary
289  ! coordinates of previous grid
290  x1(1) = x0(1)
291  x1(n1+1) = x0(n0+1)
292 
293  ! Find coordinates for interior target values
294  do k = 2,n1
295  t = target_values(k)
296  x1(k) = get_polynomial_coordinate( n0, h0, x0, ppoly0_e, ppoly0_coefs, t, degree, &
297  answers_2018=answers_2018 )
298  h1(k-1) = x1(k) - x1(k-1)
299  enddo
300  h1(n1) = x1(n1+1) - x1(n1)
301 
302 end subroutine interpolate_grid
303 
304 !> Build a grid by interpolating for target values
305 subroutine build_and_interpolate_grid(CS, densities, n0, h0, x0, target_values, &
306  n1, h1, x1, h_neglect, h_neglect_edge)
307  type(interp_cs_type), intent(in) :: cs !< A control structure for regrid_interp
308  real, dimension(:), intent(in) :: densities !< Input cell densities [kg m-3]
309  real, dimension(:), intent(in) :: target_values !< Target values of interfaces
310  integer, intent(in) :: n0 !< The number of points on the input grid
311  real, dimension(:), intent(in) :: h0 !< Initial cell widths
312  real, dimension(:), intent(in) :: x0 !< Source interface positions
313  integer, intent(in) :: n1 !< The number of points on the output grid
314  real, dimension(:), intent(inout) :: h1 !< Output cell widths
315  real, dimension(:), intent(inout) :: x1 !< Target interface positions
316  real, optional, intent(in) :: h_neglect !< A negligibly small width for the
317  !! purpose of cell reconstructions
318  !! in the same units as h0.
319  real, optional, intent(in) :: h_neglect_edge !< A negligibly small width
320  !! for the purpose of edge value calculations
321  !! in the same units as h0.
322 
323  real, dimension(n0,2) :: ppoly0_e, ppoly0_s
324  real, dimension(n0,DEGREE_MAX+1) :: ppoly0_c
325  integer :: degree
326 
327  call regridding_set_ppolys(cs, densities, n0, h0, ppoly0_e, ppoly0_s, ppoly0_c, &
328  degree, h_neglect, h_neglect_edge)
329  call interpolate_grid(n0, h0, x0, ppoly0_e, ppoly0_c, target_values, degree, &
330  n1, h1, x1, answers_2018=cs%answers_2018)
331 end subroutine build_and_interpolate_grid
332 
333 !> Given a target value, find corresponding coordinate for given polynomial
334 !!
335 !! Here, 'ppoly' is assumed to be a piecewise discontinuous polynomial of degree
336 !! 'degree' throughout the domain defined by 'grid'. A target value is given
337 !! and we need to determine the corresponding grid coordinate to define the
338 !! new grid.
339 !!
340 !! If the target value is out of range, the grid coordinate is simply set to
341 !! be equal to one of the boundary coordinates, which results in vanished layers
342 !! near the boundaries.
343 !!
344 !! IT IS ASSUMED THAT THE PIECEWISE POLYNOMIAL IS MONOTONICALLY INCREASING.
345 !! IF THIS IS NOT THE CASE, THE NEW GRID MAY BE ILL-DEFINED.
346 !!
347 !! It is assumed that the number of cells defining 'grid' and 'ppoly' are the
348 !! same.
349 function get_polynomial_coordinate( N, h, x_g, ppoly_E, ppoly_coefs, &
350  target_value, degree, answers_2018 ) result ( x_tgt )
351  ! Arguments
352  integer, intent(in) :: n !< Number of grid cells
353  real, dimension(:), intent(in) :: h !< Grid cell thicknesses
354  real, dimension(:), intent(in) :: x_g !< Grid interface locations
355  real, dimension(:,:), intent(in) :: ppoly_e !< Edge values of interpolating polynomials
356  real, dimension(:,:), intent(in) :: ppoly_coefs !< Coefficients of interpolating polynomials
357  real, intent(in) :: target_value !< Target value to find position for
358  integer, intent(in) :: degree !< Degree of the interpolating polynomials
359  logical, optional, intent(in) :: answers_2018 !< If true use older, less acccurate expressions.
360  real :: x_tgt !< The position of x_g at which target_value is found.
361  ! Local variables
362  integer :: i, k ! loop indices
363  integer :: k_found ! index of target cell
364  integer :: iter
365  real :: xi0 ! normalized target coordinate
366  real, dimension(DEGREE_MAX) :: a ! polynomial coefficients
367  real :: numerator
368  real :: denominator
369  real :: delta ! Newton-Raphson increment
370  real :: x ! global target coordinate
371  real :: eps ! offset used to get away from
372  ! boundaries
373  real :: grad ! gradient during N-R iterations
374  logical :: use_2018_answers ! If true use older, less acccurate expressions.
375 
376  eps = nr_offset
377  k_found = -1
378  use_2018_answers = .true. ; if (present(answers_2018)) use_2018_answers = answers_2018
379 
380  ! If the target value is outside the range of all values, we
381  ! force the target coordinate to be equal to the lowest or
382  ! largest value, depending on which bound is overtaken
383  if ( target_value <= ppoly_e(1,1) ) then
384  x_tgt = x_g(1)
385  return ! return because there is no need to look further
386  endif
387 
388  ! Since discontinuous edge values are allowed, we check whether the target
389  ! value lies between two discontinuous edge values at interior interfaces
390  do k = 2,n
391  if ( ( target_value >= ppoly_e(k-1,2) ) .AND. &
392  ( target_value <= ppoly_e(k,1) ) ) then
393  x_tgt = x_g(k)
394  return ! return because there is no need to look further
395  exit
396  endif
397  enddo
398 
399  ! If the target value is outside the range of all values, we
400  ! force the target coordinate to be equal to the lowest or
401  ! largest value, depending on which bound is overtaken
402  if ( target_value >= ppoly_e(n,2) ) then
403  x_tgt = x_g(n+1)
404  return ! return because there is no need to look further
405  endif
406 
407  ! At this point, we know that the target value is bounded and does not
408  ! lie between discontinuous, monotonic edge values. Therefore,
409  ! there is a unique solution. We loop on all cells and find which one
410  ! contains the target value. The variable k_found holds the index value
411  ! of the cell where the taregt value lies.
412  do k = 1,n
413  if ( ( target_value > ppoly_e(k,1) ) .AND. &
414  ( target_value < ppoly_e(k,2) ) ) then
415  k_found = k
416  exit
417  endif
418  enddo
419 
420  ! At this point, 'k_found' should be strictly positive. If not, this is
421  ! a major failure because it means we could not find any target cell
422  ! despite the fact that the target value lies between the extremes. It
423  ! means there is a major problem with the interpolant. This needs to be
424  ! reported.
425  if ( k_found == -1 ) then
426  write(*,*) target_value, ppoly_e(1,1), ppoly_e(n,2)
427  write(*,*) 'Could not find target coordinate in ' //&
428  '"get_polynomial_coordinate". This is caused by an '//&
429  'inconsistent interpolant (perhaps not monotonically '//&
430  'increasing)'
431  call mom_error( fatal, 'Aborting execution' )
432  endif
433 
434  ! Reset all polynomial coefficients to 0 and copy those pertaining to
435  ! the found cell
436  a(:) = 0.0
437  do i = 1,degree+1
438  a(i) = ppoly_coefs(k_found,i)
439  enddo
440 
441  ! Guess value to start Newton-Raphson iterations (middle of cell)
442  xi0 = 0.5
443  iter = 1
444  delta = 1e10
445 
446  ! Newton-Raphson iterations
447  do
448  ! break if converged or too many iterations taken
449  if ( ( iter > nr_iterations ) .OR. &
450  ( abs(delta) < nr_tolerance ) ) then
451  exit
452  endif
453 
454  if (use_2018_answers) then
455  numerator = a(1) + a(2)*xi0 + a(3)*xi0*xi0 + a(4)*xi0*xi0*xi0 + &
456  a(5)*xi0*xi0*xi0*xi0 - target_value
457  denominator = a(2) + 2*a(3)*xi0 + 3*a(4)*xi0*xi0 + 4*a(5)*xi0*xi0*xi0
458  else ! These expressions are mathematicaly equivalent but more accurate.
459  numerator = (a(1) - target_value) + xi0*(a(2) + xi0*(a(3) + xi0*(a(4) + a(5)*xi0)))
460  denominator = a(2) + xi0*(2.*a(3) + xi0*(3.*a(4) + 4.*a(5)*xi0))
461  endif
462 
463  delta = -numerator / denominator
464 
465  xi0 = xi0 + delta
466 
467  ! Check whether new estimate is out of bounds. If the new estimate is
468  ! indeed out of bounds, we manually set it to be equal to the overtaken
469  ! bound with a small offset towards the interior when the gradient of
470  ! the function at the boundary is zero (in which case, the Newton-Raphson
471  ! algorithm does not converge).
472  if ( xi0 < 0.0 ) then
473  xi0 = 0.0
474  grad = a(2)
475  if ( grad == 0.0 ) xi0 = xi0 + eps
476  endif
477 
478  if ( xi0 > 1.0 ) then
479  xi0 = 1.0
480  if (use_2018_answers) then
481  grad = a(2) + 2*a(3) + 3*a(4) + 4*a(5)
482  else ! These expressions are mathematicaly equivalent but more accurate.
483  grad = a(2) + (2.*a(3) + (3.*a(4) + 4.*a(5)))
484  endif
485  if ( grad == 0.0 ) xi0 = xi0 - eps
486  endif
487 
488  iter = iter + 1
489  enddo ! end Newton-Raphson iterations
490 
491  x_tgt = x_g(k_found) + xi0 * h(k_found)
492 end function get_polynomial_coordinate
493 
494 !> Numeric value of interpolation_scheme corresponding to scheme name
495 integer function interpolation_scheme(interp_scheme)
496  character(len=*), intent(in) :: interp_scheme !< Name of the interpolation scheme
497  !! Valid values include "P1M_H2", "P1M_H4", "P1M_IH2", "PLM", "PPM_H4",
498  !! "PPM_IH4", "P3M_IH4IH3", "P3M_IH6IH5", "PQM_IH4IH3", and "PQM_IH6IH5"
499 
500  select case ( uppercase(trim(interp_scheme)) )
501  case ("P1M_H2"); interpolation_scheme = interpolation_p1m_h2
502  case ("P1M_H4"); interpolation_scheme = interpolation_p1m_h4
503  case ("P1M_IH2"); interpolation_scheme = interpolation_p1m_ih4
505  case ("PPM_H4"); interpolation_scheme = interpolation_ppm_h4
506  case ("PPM_IH4"); interpolation_scheme = interpolation_ppm_ih4
507  case ("P3M_IH4IH3"); interpolation_scheme = interpolation_p3m_ih4ih3
508  case ("P3M_IH6IH5"); interpolation_scheme = interpolation_p3m_ih6ih5
509  case ("PQM_IH4IH3"); interpolation_scheme = interpolation_pqm_ih4ih3
510  case ("PQM_IH6IH5"); interpolation_scheme = interpolation_pqm_ih6ih5
511  case default ; call mom_error(fatal, "regrid_interp: "//&
512  "Unrecognized choice for INTERPOLATION_SCHEME ("//trim(interp_scheme)//").")
513  end select
514 end function interpolation_scheme
515 
516 !> Store the interpolation_scheme value in the interp_CS based on the input string.
517 subroutine set_interp_scheme(CS, interp_scheme)
518  type(interp_cs_type), intent(inout) :: cs !< A control structure for regrid_interp
519  character(len=*), intent(in) :: interp_scheme !< Name of the interpolation scheme
520  !! Valid values include "P1M_H2", "P1M_H4", "P1M_IH2", "PLM", "PPM_H4",
521  !! "PPM_IH4", "P3M_IH4IH3", "P3M_IH6IH5", "PQM_IH4IH3", and "PQM_IH6IH5"
522 
523  cs%interpolation_scheme = interpolation_scheme(interp_scheme)
524 end subroutine set_interp_scheme
525 
526 !> Store the boundary_extrapolation value in the interp_CS
527 subroutine set_interp_extrap(CS, extrap)
528  type(interp_cs_type), intent(inout) :: cs !< A control structure for regrid_interp
529  logical, intent(in) :: extrap !< Indicate whether high-order boundary
530  !! extrapolation should be used in boundary cells
531 
532  cs%boundary_extrapolation = extrap
533 end subroutine set_interp_extrap
534 
535 end module regrid_interp
ppm_functions::ppm_boundary_extrapolation
subroutine, public ppm_boundary_extrapolation(N, h, u, ppoly_E, ppoly_coef, h_neglect)
Reconstruction by parabolas within boundary cells.
Definition: PPM_functions.F90:134
regrid_interp::interpolation_ppm_ih4
integer, parameter interpolation_ppm_ih4
O(h^3)
Definition: regrid_interp.F90:48
plm_functions::plm_boundary_extrapolation
subroutine, public plm_boundary_extrapolation(N, h, u, ppoly_E, ppoly_coef, h_neglect)
Reconstruction by linear polynomials within boundary cells.
Definition: PLM_functions.F90:206
regrid_edge_slopes::edge_slopes_implicit_h3
subroutine, public edge_slopes_implicit_h3(N, h, u, edge_slopes, h_neglect, answers_2018)
Compute ih4 edge slopes (implicit third order accurate) in the same units as h.
Definition: regrid_edge_slopes.F90:50
regrid_interp::interpolation_pqm_ih4ih3
integer, parameter interpolation_pqm_ih4ih3
O(h^4)
Definition: regrid_interp.F90:51
ppm_functions
Provides functions used with the Piecewise-Parabolic-Method in the vertical ALE algorithm.
Definition: PPM_functions.F90:2
regrid_interp::interpolation_ppm_h4
integer, parameter interpolation_ppm_h4
O(h^3)
Definition: regrid_interp.F90:47
regrid_interp::interpolation_p3m_ih4ih3
integer, parameter interpolation_p3m_ih4ih3
O(h^4)
Definition: regrid_interp.F90:49
regrid_interp::set_interp_scheme
subroutine, public set_interp_scheme(CS, interp_scheme)
Store the interpolation_scheme value in the interp_CS based on the input string.
Definition: regrid_interp.F90:518
regrid_edge_slopes::edge_slopes_implicit_h5
subroutine, public edge_slopes_implicit_h5(N, h, u, edge_slopes, h_neglect, answers_2018)
Compute ih5 edge values (implicit fifth order accurate)
Definition: regrid_edge_slopes.F90:192
regrid_interp::interpolation_plm
integer, parameter interpolation_plm
O(h^2)
Definition: regrid_interp.F90:46
p3m_functions::p3m_interpolation
subroutine, public p3m_interpolation(N, h, u, ppoly_E, ppoly_S, ppoly_coef, h_neglect)
Set up a piecewise cubic interpolation from cell averages and estimated edge slopes and values.
Definition: P3M_functions.F90:29
p3m_functions
Cubic interpolation functions.
Definition: P3M_functions.F90:2
mom_string_functions
Handy functions for manipulating strings.
Definition: MOM_string_functions.F90:2
regrid_interp::degree_1
integer, parameter degree_1
Interpolant degrees.
Definition: regrid_interp.F90:55
regrid_interp::interpolation_p3m_ih6ih5
integer, parameter interpolation_p3m_ih6ih5
O(h^4)
Definition: regrid_interp.F90:50
regrid_interp::interpolation_scheme
integer function interpolation_scheme(interp_scheme)
Numeric value of interpolation_scheme corresponding to scheme name.
Definition: regrid_interp.F90:496
regrid_edge_values
Edge value estimation for high-order resconstruction.
Definition: regrid_edge_values.F90:2
regrid_interp::degree_3
integer, parameter degree_3
Interpolant degrees.
Definition: regrid_interp.F90:55
regrid_interp::set_interp_extrap
subroutine, public set_interp_extrap(CS, extrap)
Store the boundary_extrapolation value in the interp_CS.
Definition: regrid_interp.F90:528
mom_string_functions::uppercase
character(len=len(input_string)) function, public uppercase(input_string)
Return a string in which all uppercase letters have been replaced by their lowercase counterparts.
Definition: MOM_string_functions.F90:42
regrid_interp::interpolation_p1m_h2
integer, parameter interpolation_p1m_h2
O(h^2)
Definition: regrid_interp.F90:43
p1m_functions
Linear interpolation functions.
Definition: P1M_functions.F90:2
regrid_edge_values::edge_values_explicit_h2
subroutine, public edge_values_explicit_h2(N, h, u, edge_val, h_neglect)
Compute h2 edge values (explicit second order accurate) in the same units as h.
Definition: regrid_edge_values.F90:226
regrid_interp
Vertical interpolation for regridding.
Definition: regrid_interp.F90:2
regrid_interp::degree_2
integer, parameter degree_2
Interpolant degrees.
Definition: regrid_interp.F90:55
regrid_interp::interpolation_p1m_h4
integer, parameter interpolation_p1m_h4
O(h^2)
Definition: regrid_interp.F90:44
regrid_interp::nr_iterations
integer, parameter, public nr_iterations
Maximum number of Newton-Raphson iterations. Newton-Raphson iterations are used to build the new grid...
Definition: regrid_interp.F90:66
p1m_functions::p1m_boundary_extrapolation
subroutine, public p1m_boundary_extrapolation(N, h, u, ppoly_E, ppoly_coef)
Interpolation by linear polynomials within boundary cells.
Definition: P1M_functions.F90:70
regrid_edge_values::edge_values_implicit_h4
subroutine, public edge_values_implicit_h4(N, h, u, edge_val, h_neglect, answers_2018)
Compute ih4 edge values (implicit fourth order accurate) in the same units as h.
Definition: regrid_edge_values.F90:492
regrid_interp::nr_tolerance
real, parameter, public nr_tolerance
Tolerance for Newton-Raphson iterations (stop when increment falls below this)
Definition: regrid_interp.F90:68
regrid_interp::degree_max
integer, parameter, public degree_max
Interpolant degrees.
Definition: regrid_interp.F90:56
regrid_interp::interpolation_pqm_ih6ih5
integer, parameter interpolation_pqm_ih6ih5
O(h^5)
Definition: regrid_interp.F90:52
pqm_functions
Piecewise quartic reconstruction functions.
Definition: PQM_functions.F90:2
regrid_interp::degree_4
integer, parameter degree_4
Interpolant degrees.
Definition: regrid_interp.F90:55
pqm_functions::pqm_boundary_extrapolation_v1
subroutine, public pqm_boundary_extrapolation_v1(N, h, u, ppoly_E, ppoly_S, ppoly_coef, h_neglect)
Reconstruction by parabolas within boundary cells.
Definition: PQM_functions.F90:508
plm_functions::plm_reconstruction
subroutine, public plm_reconstruction(N, h, u, ppoly_E, ppoly_coef, h_neglect)
Reconstruction by linear polynomials within each cell.
Definition: PLM_functions.F90:19
regrid_interp::interpolate_grid
subroutine, public interpolate_grid(n0, h0, x0, ppoly0_E, ppoly0_coefs, target_values, degree, n1, h1, x1, answers_2018)
Given target values (e.g., density), build new grid based on polynomial.
Definition: regrid_interp.F90:271
regrid_interp::interp_cs_type
Control structure for regrid_interp module.
Definition: regrid_interp.F90:23
mom_error_handler::mom_error
subroutine, public mom_error(level, message, all_print)
This provides a convenient interface for writing an mpp_error message with run-time filter based on a...
Definition: MOM_error_handler.F90:72
p1m_functions::p1m_interpolation
subroutine, public p1m_interpolation(N, h, u, ppoly_E, ppoly_coef, h_neglect)
Linearly interpolate between edge values.
Definition: P1M_functions.F90:28
regrid_edge_values::edge_values_implicit_h6
subroutine, public edge_values_implicit_h6(N, h, u, edge_val, h_neglect, answers_2018)
Compute ih6 edge values (implicit sixth order accurate) in the same units as h.
Definition: regrid_edge_values.F90:661
regrid_interp::build_and_interpolate_grid
subroutine, public build_and_interpolate_grid(CS, densities, n0, h0, x0, target_values, n1, h1, x1, h_neglect, h_neglect_edge)
Build a grid by interpolating for target values.
Definition: regrid_interp.F90:307
regrid_interp::regridding_set_ppolys
subroutine, public regridding_set_ppolys(CS, densities, n0, h0, ppoly0_E, ppoly0_S, ppoly0_coefs, degree, h_neglect, h_neglect_edge)
Builds an interpolated profile for the densities within each grid cell.
Definition: regrid_interp.F90:80
regrid_interp::get_polynomial_coordinate
real function get_polynomial_coordinate(N, h, x_g, ppoly_E, ppoly_coefs, target_value, degree, answers_2018)
Given a target value, find corresponding coordinate for given polynomial.
Definition: regrid_interp.F90:351
regrid_edge_slopes
Routines that estimate edge slopes to be used in high-order reconstruction schemes.
Definition: regrid_edge_slopes.F90:3
regrid_interp::nr_offset
real, parameter, public nr_offset
When the N-R algorithm produces an estimate that lies outside [0,1], the estimate is set to be equal ...
Definition: regrid_interp.F90:62
p3m_functions::p3m_boundary_extrapolation
subroutine, public p3m_boundary_extrapolation(N, h, u, ppoly_E, ppoly_S, ppoly_coef, h_neglect, h_neglect_edge)
Calculate the edge values and slopes at boundary cells as part of building a piecewise cubic sub-grid...
Definition: P3M_functions.F90:190
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
regrid_interp::interpolation_p1m_ih4
integer, parameter interpolation_p1m_ih4
O(h^2)
Definition: regrid_interp.F90:45
plm_functions
Piecewise linear reconstruction functions.
Definition: PLM_functions.F90:2
pqm_functions::pqm_reconstruction
subroutine, public pqm_reconstruction(N, h, u, ppoly_E, ppoly_S, ppoly_coef, h_neglect)
Reconstruction by quartic polynomials within each cell.
Definition: PQM_functions.F90:21
regrid_edge_values::edge_values_explicit_h4
subroutine, public edge_values_explicit_h4(N, h, u, edge_val, h_neglect, answers_2018)
Compute h4 edge values (explicit fourth order accurate) in the same units as h.
Definition: regrid_edge_values.F90:289
ppm_functions::ppm_reconstruction
subroutine, public ppm_reconstruction(N, h, u, ppoly_E, ppoly_coef, h_neglect)
Builds quadratic polynomials coefficients from cell mean and edge values.
Definition: PPM_functions.F90:29