#include <NodeQuadCFInterp2.H>
Public Methods | |
NodeQuadCFInterp2 () | |
{\bf constructors, destructor and defines} | |
NodeQuadCFInterp2 (const DisjointBoxLayout &a_grids, Real a_dx, const ProblemDomain &a_domain, const LayoutData< NodeCFIVS > *const a_loCFIVS, const LayoutData< NodeCFIVS > *const a_hiCFIVS, bool a_interfaceOnly, int a_interpolationDegree, int a_ncomp=1) | |
~NodeQuadCFInterp2 () | |
void | define (const DisjointBoxLayout &a_grids, Real a_dx, const ProblemDomain &a_domain, const LayoutData< NodeCFIVS > *const a_loCFIVS, const LayoutData< NodeCFIVS > *const a_hiCFIVS, bool a_interfaceOnly, int a_interpolationDegree, int a_ncomp=1) |
bool | isDefined () const |
void | coarseFineInterp (LevelData< NodeFArrayBox > &a_phiFine, const LevelData< NodeFArrayBox > &a_phiCoarse) |
{\bf data modification functions} | |
Protected Attributes | |
DisjointBoxLayout | m_grids |
ProblemDomain | m_domain |
BoxLayout | m_gridsNodes |
BoxLayout | m_coarsenedGridsNodes |
Box | m_domainCoarseNodes |
LevelData< NodeFArrayBox > | m_coarseCopy |
bool | m_interfaceOnly |
int | m_interpolationDegree |
int | m_ncomp |
Real | m_dx |
bool | m_isDefined |
const LayoutData< NodeCFIVS > * | m_loCFIVS |
const LayoutData< NodeCFIVS > * | m_hiCFIVS |
BoxLayoutData< BaseFab< int > > | m_mask |
BoxLayoutData< BaseFab< int > > | m_maskCoarse |
Class to interpolate quadratically at interface between this level and next coarser level, when the refinement ratio is 2. This class should be considered internal to NodeQuadCFInterp.
{\bf Long Description:} \
The interface has codimension one. If a fine node coincides with a coarse node, then we merely project from the coarse node to the fine node. Otherwise, we take the mean of the neighboring coarse nodes and subtract 1/8 * dx^2 times the sum of the second derivatives in the appropriate directions, provided there are enough uncovered coarse points to estimate the second derivatives. If there are not enough points to estimate a second derivative and some of the neighboring coarse nodes are covered, then we may instead subtract 1/2 * dx times a first derivative.
The interpolation is performed in function coarseFineInterp().\ The constructor computes m_loCFIVS and m_hiCFIVS to determine the fine nodes at the interface with the coarse level.\
The constructor also takes m_loCFIVS and m_hiCFIVS to determine the fine nodes at the interface with the coarse level. Calling getFineIVS() on m_loCFIVS[idir][dit()] gives us the IntVectSet of nodes of m_grids[dit()] on the face in the low direction in dimension idir, that lie on the interface with the coarser level. Similarly with m_hiCFIVS[idir][dit()] for the opposite face, in the high direction in dimension idir.\
{\bf 2-D Description:} \
In the 2-D problem, the interface is 1-D. Between coarse nodes at 0 and 1, we need to interpolate to find f(1/2).\
The first approximation to f(1/2) is the mean of f(0) and f(1), taking the values at the uncovered nodes only. If both 0 and 1 are covered, then there is an error.\
We attempt to approximate the value at the fine node by \ f(1/2) ~ mean(f(0), f(1)) - 1/8 * f''(1/2) \ where we estimate the second derivative f''(1/2) from values of f at coarse points. A second-derivative estimate requires that there be three consecutive uncovered coarse points.
If -1, 0, 1, 2 are all uncovered: \begin{verbatim} o---o-x-o---o -1 0 1 2 \end{verbatim} then we use f''(1/2) ~ (f(-1) - f(0) - f(1) + f(2))/2. \
If -1, 0, 1 are uncovered but 2 is covered: \begin{verbatim} o---o-x-o o -1 0 1 2 \end{verbatim} then we approximate f''(1/2) by f''(0) and use f''(0) ~ (f(-1) - 2 * f(0) + f(1)). \
If 0, 1, 2 are uncovered bt -1 is covered: \begin{verbatim} o o-x-o---o -1 0 1 2 \end{verbatim} then we approximate f''(1/2) by f''(1) and use f''(1) ~ (f(0) - 2 * f(1) + f(2)). \
Now if either 0 or 1 is covered but an estimate of the second derivative is not obtainable, then we attempt to use a first-derivative estimate to obtain f(1/2). \
So if 1 and -2 are covered, but -1 is not: \begin{verbatim} o o---o-x o -2 -1 0 1 \end{verbatim} then we use the linear approximation \ f(1/2) ~ f(0) + 1/2 * (f(0) - f(-1)) . \
If -1 and 3 are covered, but 2 is not: \begin{verbatim} o o x-o---o o -1 0 1 2 3 \end{verbatim} then we use the linear approximation \ f(1/2) ~ f(1) - 1/2 * (f(2) - f(1)) . \
In the 2-D problem, the interface is 1-D. We approximate with Lagrange interpolating polynomials. Between coarse nodes at 0 and 1, the fine node is located at point 1/2.\
We use m_wtLo if the next coarse node in the low direction is on the grid, but the next coarse node in the high direction is not: \begin{verbatim} vvv o---o---o -1 0 +1 \end{verbatim} In this case, we interpolate at the fine nodes between 0 and +1 from values at the coarse nodes -1, 0, +1. The weights come from the quadratic Lagrange interpolating polynomial:\ f(x) ~ x*(-1+x)/2 * f(-1) + (1-x*x) * f(0) + x*(1+x)/2 * f(1) \
We use m_wtHi if the next coarse node in the high direction is on the grid, but the next coarse node in the low direction is not: \begin{verbatim} vvv o---o---o 0 +1 +2 \end{verbatim} In this case, we interpolate at the fine nodes between 0 and +1 from values at the coarse nodes 0, +1, +2. The weights come from the quadratic Lagrange interpolating polynomial:\ f(x) ~ (x-1)*(-1+x-1)/2 * f(0) + (1-(x-1)*(x-1)) * f(1) + (x-1)*(1+x-1)/2 * f(2) \
We use m_wtC if the next coarse nodes in both low and high directions are on the grid: \ \begin{verbatim} vvv o---o---o---o -1 0 +1 +2 \end{verbatim} In this case, we interpolate at the fine nodes between 0 and +1 from values at the coarse nodes -1, 0, +1, +2. The weights come from the cubic Lagrange interpolating polynomial through these four points:\ f(x) ~ x*(x-1)*(x-2)/(-6) * f(-1) + (x+1)*(x-1)*(x-2)/2 * f(0) + (x+1)*x*(x-2)/(-2) * f(1) + (x+1)*x*(x-1)/6 * f(2) \
{\bf 3-D Description:} \
In the 3-D problem, the interface is 2-D. We approximate with 2-D Taylor polynomials (writing "d" for partial derivative):\ f(x,y) ~ f(a,b) + df/dx (a,b) * (x-a) + df/dy (a,b) * (y-b) + d^2 f/dx^2 (a,b) * (x-a)^2/2 + d^2 f/dy^2 (a,b) * (y-b)^2/2 + d^2 f/dxdy (a,b) * (x-a)*(y-b) \
\begin{verbatim} (0,1) (1,1) o-*-*-*-o * * * * * * * * * * * * o-*-*-*-o (0,0) (1,0) \end{verbatim}
For fine nodes in the unit square bounded by the coarse points (0,0), (0,1), (1,0) and (1,1), we use the mean of the above Taylor approximations at the four coarse points. \
The partial derivatives are approximated from values at the coarse nodes. \
First and second partials with respect to one variable are approximated by the derivatives of a one-dimensional Lagrange interpolating polynomial through collinear coarse points. As in the 2-D case, we define m_wtLo, m_wtHi, and m_wtC in the constructor. \
We use m_wtLo if the next coarse node in the low direction is on the grid, but the next coarse node in the high direction is not: \begin{verbatim} vvv o---o---o -1 0 +1 \end{verbatim} In this case, we interpolate at the fine nodes between 0 and +1 from values at the coarse nodes -1, 0, +1. The quadratic L.I.P. and its derivatives are: \ L(x) = (-x/2+x*x/2) * f(-1) + (1-x*x) * f(0) + (x/2+x*x/2) * f(1) \ L'(x) = (-1/2+x) * f(-1) + (-2*x) * f(0) + (1/2+x) * f(1) \ L''(x) = f(-1) - 2 * f(0) + f(1) \ And hence we use the approximations:\ df/dx(0) = -1/2*f(-1) + 1/2*f(+1) \ df/dx(1) = 1/2*f(-1) - 2*f(0) + 3/2*f(+1) \ For a = 0 or 1, we take d^2 f/dx^2(a) = f(-1) - 2*f(0) + f(+1) . \
We use m_wtHi if the next coarse node in the high direction is on the grid, but the next coarse node in the low direction is not: \begin{verbatim} vvv o---o---o 0 +1 +2 \end{verbatim} In this case, we interpolate at the fine nodes between 0 and +1 from values at the coarse nodes 0, +1, +2. The quadratic L.I.P. and its derivatives are: \ L(x) = (1-3/2*x+x*x/2) * f(0) + (2*x-x*x) * f(1) + (-x/2+x*x/2) * f(2) \ L'(x) = (-3/2+x) * f(0) + (2-2*x) * f(1) + (-1/2+x) * f(2) \ L''(x) = f(0) - 2 * f(1) + f(2) \ And hence we use the approximations:\ df/dx(0) = -3/2*f(0) + 2*f(1) - 1/2*f(2) \ df/dx(1) = -1/2*f(0) + 1/2*f(2) \ For a = 0 or 1, we take d^2 f/dx^2(a) = f(0) - 2*f(1) + f(2) . \
We use m_wtC if the next coarse nodes in both low and high directions are on the grid: \ \begin{verbatim} vvv o---o---o---o -1 0 +1 +2 \end{verbatim} In this case, we interpolate at the fine nodes between 0 and +1 from values at the coarse nodes -1, 0, +1, +2. The cubic L.I.P. and its derivatives are: \ L(x) = (-x/3+x*x/2-x*x*x/6) * f(-1) + (1-x/2-x*x+x*x*x/2) * f(0) + (x+x*x/2-x*x*x/2) * f(1) + (-x/6+x*x*x/6) * f(2) \ L'(x) = (-1/3+x-x*x/2) * f(-1) + (-1/2-2*x+3/2*x*x) * f(0) + (1+x-3/2*x*x) * f(1) + (-1/6+x*x/2) * f(2) \ L''(x) = (1-x) * f(-1) + (-2+3*x) * f(0) + (1-3*x) * f(1) + x * f(2) \ And hence we use the approximations:\ df/dx(0) = -1/3*f(-1) - 1/2*f(0) + 1*f(1) - 1/6*f(2) \ df/dx(1) = 1/6*f(-1) - 1*f(0) + 1/2*f(1) + 1/3*f(2) \ d^2 f/dx^2(0) = 1*f(-1) - 2*f(0) + 1*f(1) \ d^2 f/dx^2(1) = 1*f(0) - 2*f(1) + 1*f(2) .\
After the first and second partials with respect to x and y are accounted for with one of the weight arrays in each dimension, we still have the constant and mixed partial terms. These are simple. For any (a,b) in the unit square, we approximate \ d^2 f/dxdy (a,b) ~ (f(0,0) + f(1,1) - f(1,0) - f(0,1)). \
Taking the mean of the mixed and constant terms in the four expansions at the four coarse nodes, evaluated at (x,y), the result is: \ (1/4 + (x-1/2)*(y-1/2)) * (f(0,0) + f(1,1)) + (1/4 - (x-1/2)*(y-1/2)) * (f(0,1) + f(1,0)) .
|
{\bf constructors, destructor and defines} Default constructor. User must subsequently call define(). |
|
|
|
Destructor. |
|
{\bf data modification functions} Coarse / Fine (inhomogeneous) interpolation operator. Fill the nodes of a_phi on the coarse/fine interface with interpolated data from a_phiCoarse. {\bf Arguments:}\ a_phiFine (modified): the data at this level.\ a_phiCoarse (not modified): the data at the next coarser level.\ |
|
Full define function. Makes all coarse-fine information and sets internal variables. The current level is taken to be the fine level. {\bf Arguments:}\ a_grids: domain of this level.\ a_dx: mesh spacing at this level.\ a_domain: physical domain at this level.\ a_loCFIVS, a_hiCFIVS: pointers to objects used for figuring out which nodes lie on interface with the next coarser level. \ a_interfaceOnly: interpolating from interface only?\ a_interpolationDegree: 1 for (bi)linear, 2 for (bi)quadratic\ a_ncomp: number of components.\ |
|
Returns true if this object was created with the defining constructor or if define() has been called. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|