MOM6
P1M_functions.F90
Go to the documentation of this file.
2 !==============================================================================
3 !
4 ! This file is part of MOM.
5 !
6 ! Date of creation: 2008.06.09
7 ! L. White
8 !
9 ! This module contains p1m (linear) interpolation routines.
10 !
11 ! p1m interpolation is performed by estimating the edge values and
12 ! linearly interpolating between them.
13 
14 ! Once the edge values are estimated, the limiting process takes care of
15 ! ensuring that (1) edge values are bounded by neighoring cell averages
16 ! and (2) discontinuous edge values are averaged in order to provide a
17 ! fully continuous interpolant throughout the domain. This last step is
18 ! essential for the regridding problem to yield a unique solution.
19 ! Also, a routine is provided that takes care of linear extrapolation
20 ! within the boundary cells.
21 !
22 ! The module contains the following routines:
23 !
24 ! P1M_interpolation (public)
25 ! P1M_boundary_extrapolation (public)
26 !
27 !==============================================================================
29 
30 implicit none ; private
31 
32 ! -----------------------------------------------------------------------------
33 ! The following routines are visible to the outside world
34 ! -----------------------------------------------------------------------------
36 
37 contains
38 
39 
40 !------------------------------------------------------------------------------
41 ! p1m interpolation
42 !------------------------------------------------------------------------------
43 subroutine p1m_interpolation( N, h, u, ppoly_E, ppoly_coefficients )
44 ! ------------------------------------------------------------------------------
45 ! Linearly interpolate between edge values.
46 ! The resulting piecewise interpolant is stored in 'ppoly'.
47 ! See 'ppoly.F90' for a definition of this structure.
48 !
49 ! The edge values MUST have been estimated prior to calling this routine.
50 !
51 ! The estimated edge values must be limited to ensure monotonicity of the
52 ! interpolant. We also make sure that edge values are NOT discontinuous.
53 !
54 ! It is assumed that the size of the array 'u' is equal to the number of cells
55 ! defining 'grid' and 'ppoly'. No consistency check is performed here.
56 ! ------------------------------------------------------------------------------
57 
58  ! Arguments
59  integer, intent(in) :: N ! Number of cells
60  real, dimension(:), intent(in) :: h ! cell widths (size N)
61  real, dimension(:), intent(in) :: u ! cell averages (size N)
62  real, dimension(:,:), intent(inout) :: ppoly_E
63  real, dimension(:,:), intent(inout) :: ppoly_coefficients
64 
65  ! Local variables
66  integer :: k ! loop index
67  real :: u0_l, u0_r ! edge values (left and right)
68 
69  ! Bound edge values (routine found in 'edge_values.F90')
70  call bound_edge_values( n, h, u, ppoly_e )
71 
72  ! Systematically average discontinuous edge values (routine found in
73  ! 'edge_values.F90')
74  call average_discontinuous_edge_values( n, ppoly_e )
75 
76  ! Loop on interior cells to build interpolants
77  do k = 1,n
78 
79  u0_l = ppoly_e(k,1)
80  u0_r = ppoly_e(k,2)
81 
82  ppoly_coefficients(k,1) = u0_l
83  ppoly_coefficients(k,2) = u0_r - u0_l
84 
85  end do ! end loop on interior cells
86 
87 end subroutine p1m_interpolation
88 
89 
90 !------------------------------------------------------------------------------
91 ! p1m boundary extrapolation
92 ! -----------------------------------------------------------------------------
93 subroutine p1m_boundary_extrapolation( N, h, u, ppoly_E, ppoly_coefficients )
94 !------------------------------------------------------------------------------
95 ! Interpolation by linear polynomials within boundary cells.
96 ! The left and right edge values in the left and right boundary cells,
97 ! respectively, are estimated using a linear extrapolation within the cells.
98 !
99 ! N: number of cells in grid
100 ! h: thicknesses of grid cells
101 ! u: cell averages to use in constructing piecewise polynomials
102 ! ppoly_E : edge values of piecewise polynomials
103 ! ppoly_coefficients : coefficients of piecewise polynomials
104 !
105 ! It is assumed that the size of the array 'u' is equal to the number of cells
106 ! defining 'grid' and 'ppoly'. No consistency check is performed here.
107 !------------------------------------------------------------------------------
108 
109  ! Arguments
110  integer, intent(in) :: N ! Number of cells
111  real, dimension(:), intent(in) :: h ! cell widths (size N)
112  real, dimension(:), intent(in) :: u ! cell averages (size N)
113  real, dimension(:,:), intent(inout) :: ppoly_E
114  real, dimension(:,:), intent(inout) :: ppoly_coefficients
115 
116  ! Local variables
117  real :: u0, u1 ! cell averages
118  real :: h0, h1 ! corresponding cell widths
119  real :: slope ! retained PLM slope
120  real :: u0_l, u0_r ! edge values
121 
122  ! -----------------------------------------
123  ! Left edge value in the left boundary cell
124  ! -----------------------------------------
125  h0 = h(1)
126  h1 = h(2)
127 
128  u0 = u(1)
129  u1 = u(2)
130 
131  ! The standard PLM slope is computed as a first estimate for the
132  ! interpolation within the cell
133  slope = 2.0 * ( u1 - u0 )
134 
135  ! The right edge value is then computed and we check whether this
136  ! right edge value is consistent: it cannot be larger than the edge
137  ! value in the neighboring cell if the data set is increasing.
138  ! If the right value is found to too large, the slope is further limited
139  ! by using the edge value in the neighboring cell.
140  u0_r = u0 + 0.5 * slope
141 
142  if ( (u1 - u0) * (ppoly_e(2,1) - u0_r) .LT. 0.0 ) then
143  slope = 2.0 * ( ppoly_e(2,1) - u0 )
144  end if
145 
146  ! Using the limited slope, the left edge value is reevaluated and
147  ! the interpolant coefficients recomputed
148  if ( h0 .NE. 0.0 ) then
149  ppoly_e(1,1) = u0 - 0.5 * slope
150  else
151  ppoly_e(1,1) = u0
152  end if
153 
154  ppoly_coefficients(1,1) = ppoly_e(1,1)
155  ppoly_coefficients(1,2) = ppoly_e(1,2) - ppoly_e(1,1)
156 
157  ! ------------------------------------------
158  ! Right edge value in the left boundary cell
159  ! ------------------------------------------
160  h0 = h(n-1)
161  h1 = h(n)
162 
163  u0 = u(n-1)
164  u1 = u(n)
165 
166  slope = 2.0 * ( u1 - u0 )
167 
168  u0_l = u1 - 0.5 * slope
169 
170  if ( (u1 - u0) * (u0_l - ppoly_e(n-1,2)) .LT. 0.0 ) then
171  slope = 2.0 * ( u1 - ppoly_e(n-1,2) )
172  end if
173 
174  if ( h1 .NE. 0.0 ) then
175  ppoly_e(n,2) = u1 + 0.5 * slope
176  else
177  ppoly_e(n,2) = u1
178  end if
179 
180  ppoly_coefficients(n,1) = ppoly_e(n,1)
181  ppoly_coefficients(n,2) = ppoly_e(n,2) - ppoly_e(n,1)
182 
183 end subroutine p1m_boundary_extrapolation
184 
185 end module p1m_functions
subroutine, public p1m_boundary_extrapolation(N, h, u, ppoly_E, ppoly_coefficients)
subroutine, public p1m_interpolation(N, h, u, ppoly_E, ppoly_coefficients)
subroutine, public average_discontinuous_edge_values(N, edge_values)
subroutine, public bound_edge_values(N, h, u, edge_values)