Added virtual method updateCoords for use in ALE-formulations of FSI-problems

git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@1264 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
kmo 2011-10-16 16:20:54 +00:00 committed by Knut Morten Okstad
parent cb8cb697c2
commit 781dc15126
16 changed files with 267 additions and 171 deletions

View File

@ -477,11 +477,10 @@ void ASMbase::extractElmRes (const Matrix& globRes, Matrix& elmRes) const
{
elmRes.resize(globRes.rows(),MLGE.size(),true);
size_t i, iel, ivel = 0;
size_t iel, ivel = 0;
for (iel = 0; iel < MLGE.size(); iel++)
if (MLGE[iel] > 0)
for (++ivel, i = 1; i <= globRes.rows(); i++)
elmRes(i,ivel) = globRes(i,MLGE[iel]);
elmRes.fillColumn(++ivel,globRes.getColumn(MLGE[iel]));
elmRes.resize(globRes.rows(),ivel);
}
@ -525,14 +524,6 @@ bool ASMbase::injectNodeVec (const Vector& nodeVec, Vector& globRes,
}
bool ASMbase::tesselate (ElementBlock&, const int*) const
{
std::cerr <<" *** ASMBase::tesselate: Must be implemented in sub-class."
<< std::endl;
return false;
}
bool ASMbase::getSolution (Matrix& sField, const Vector& locSol,
const IntVec& nodes) const
{
@ -545,10 +536,7 @@ bool ASMbase::getSolution (Matrix& sField, const Vector& locSol,
return false;
}
else
{
for (unsigned char j = 0; j < nf; j++)
sField(j+1,i+1) = locSol[nf*(nodes[i]-1)+j];
}
sField.fillColumn(i+1,locSol.ptr()+nf*nodes[i]-nf);
return true;
}

View File

@ -191,6 +191,10 @@ public:
bool updateDirichlet(const std::map<int,RealFunc*>& func,
const std::map<int,VecFunc*>& vfunc, double time = 0.0);
//! \brief Updates the nodal coordinates for this patch.
//! \param[in] displ Incremental displacements to update the coordinates with
virtual bool updateCoords(const Vector& displ) = 0;
//! \brief Initializes the patch level MADOF array for mixed problems.
virtual void initMADOF(const int*) {}
@ -242,7 +246,7 @@ public:
//! \param[out] grid The generated finite element grid
//! \param[in] npe Number of visualization nodes over each knot span
//! \note The number of element nodes must be set in \a grid on input.
virtual bool tesselate(ElementBlock& grid, const int* npe) const;
virtual bool tesselate(ElementBlock& grid, const int* npe) const = 0;
//! \brief Extract the primary solution field at the specified nodes.
//! \param[out] sField Solution field

View File

@ -426,6 +426,45 @@ Vec3 ASMs1D::getCoord (size_t inod) const
}
bool ASMs1D::updateCoords (const Vector& displ)
{
if (!curv) return true; // silently ignore empty patches
if (displ.size() != nsd*MLGN.size())
{
std::cerr <<" *** ASMs1D::updateCoords: Invalid dimension "
<< displ.size() <<" on displ, should be "
<< nsd*MLGN.size() << std::endl;
return false;
}
//TODO: This should be placed in GoTools (SplineCurve::deform)
//curv->deform(displ,nsd);
RealArray::iterator cit;
int i, j, cdim = curv->dimension();
if (curv->rational())
for (cit = curv->rcoefs_begin(), j = 0; cit != curv->rcoefs_end(); cit++)
{
double weight = cit[cdim];
for (i = 0; i < cdim && i < nsd; i++)
cit[i] += displ[j+i] * weight;
cit += cdim;
j += nsd;
}
for (cit = curv->coefs_begin(), j = 0; cit != curv->coefs_end();)
{
for (i = 0; i < cdim && i < nsd; i++)
cit[i] += displ[j+i];
cit += cdim;
j += nsd;
}
return true;
}
int ASMs1D::getSize (int) const
{
if (!curv) return 0;

View File

@ -54,6 +54,10 @@ public:
//! \param[in] inod 1-based node index local to current patch
virtual Vec3 getCoord(size_t inod) const;
//! \brief Updates the nodal coordinates for this patch.
//! \param[in] displ Incremental displacements to update the coordinates with
virtual bool updateCoords(const Vector& displ);
//! \brief Creates an instance by reading the given input stream.
bool read(std::istream&);
//! \brief Writes the geometry of the SplineCurve object to given stream.

View File

@ -7,7 +7,7 @@
//!
//! \author Einar Christensen / SINTEF
//!
//! \brief Driver for assembly of structured 1D Lagrange FE models.
//! \brief Driver for assembly of 1D Lagrange FE models.
//!
//==============================================================================
@ -104,6 +104,14 @@ bool ASMs1DLag::generateFEMTopology ()
}
Vec3 ASMs1DLag::getCoord (size_t inod) const
{
if (inod < 1 || inod > coord.size()) return Vec3();
return coord[inod-1];
}
bool ASMs1DLag::getElementCoordinates (Matrix& X, int iel) const
{
if (iel < 1 || (size_t)iel > MNPC.size())
@ -132,11 +140,21 @@ void ASMs1DLag::getNodalCoordinates (Matrix& X) const
}
Vec3 ASMs1DLag::getCoord (size_t inod) const
bool ASMs1DLag::updateCoords (const Vector& displ)
{
if (inod < 1 || inod > coord.size()) return Vec3();
if (displ.size() != nsd*coord.size())
{
std::cerr <<" *** ASMs1DLag::updateCoords: Invalid dimension "
<< displ.size() <<" on displ, should be "
<< nsd*coord.size() << std::endl;
return false;
}
return coord[inod-1];
const double* u = displ.ptr();
for (size_t inod = 0; inod < coord.size(); inod++, u += nsd)
coord[inod] += RealArray(u,u+nsd);
return true;
}
@ -380,11 +398,10 @@ bool ASMs1DLag::evalSolution (Matrix& sField, const Vector& locSol,
if (nComp*nPoints != locSol.size())
return false;
size_t i, n, ip = 0;
sField.resize(nComp,nPoints);
for (n = 1; n <= nPoints; n++)
for (i = 1; i <= nComp; i++)
sField(i,n) = locSol(++ip);
const double* u = locSol.ptr();
for (size_t n = 1; n <= nPoints; n++, u += nComp)
sField.fillColumn(n,u);
return true;
}

View File

@ -7,7 +7,7 @@
//!
//! \author Einar Christensen / SINTEF
//!
//! \brief Driver for assembly of structured 1D Lagrange FE models.
//! \brief Driver for assembly of 1D Lagrange FE models.
//!
//==============================================================================
@ -19,8 +19,8 @@
/*!
\brief Driver for assembly of structured 2D Lagrange FE models.
\details This class contains methods for structured 2D Lagrange patches.
\brief Driver for assembly of 1D Lagrange FE models.
\details This class contains methods for 1D Lagrange patches.
*/
class ASMs1DLag : public ASMs1D
@ -51,6 +51,10 @@ public:
//! \param[in] inod 1-based node index local to current patch
virtual Vec3 getCoord(size_t inod) const;
//! \brief Updates the nodal coordinates for this patch.
//! \param[in] displ Incremental displacements to update the coordinates with
virtual bool updateCoords(const Vector& displ);
// Methods for integration of finite element quantities.
// These are the main computational methods of the ASM class hierarchy.

View File

@ -668,6 +668,45 @@ Vec3 ASMs2D::getCoord (size_t inod) const
}
bool ASMs2D::updateCoords (const Vector& displ)
{
if (!surf) return true; // silently ignore empty patches
if (displ.size() != nsd*MLGN.size())
{
std::cerr <<" *** ASMs2D::updateCoords: Invalid dimension "
<< displ.size() <<" on displ, should be "
<< nsd*MLGN.size() << std::endl;
return false;
}
//TODO: This should be placed in GoTools (SplineSurface::deform)
//surf->deform(displ,nsd);
RealArray::iterator cit;
int i, j, cdim = surf->dimension();
if (surf->rational())
for (cit = surf->rcoefs_begin(), j = 0; cit != surf->rcoefs_end(); cit++)
{
double weight = cit[cdim];
for (i = 0; i < cdim && i < nsd; i++)
cit[i] += displ[j+i] * weight;
cit += cdim;
j += nsd;
}
for (cit = surf->coefs_begin(), j = 0; cit != surf->coefs_end();)
{
for (i = 0; i < cdim && i < nsd; i++)
cit[i] += displ[j+i];
cit += cdim;
j += nsd;
}
return true;
}
bool ASMs2D::getSize (int& n1, int& n2, int) const
{
if (!surf) return false;

View File

@ -95,6 +95,10 @@ public:
//! \param[in] inod 1-based node index local to current patch
virtual Vec3 getCoord(size_t inod) const;
//! \brief Updates the nodal coordinates for this patch.
//! \param[in] displ Incremental displacements to update the coordinates with
virtual bool updateCoords(const Vector& displ);
//! \brief Creates an instance by reading the given input stream.
bool read(std::istream&);
//! \brief Writes the geometry of the SplineSurface object to given stream.

View File

@ -120,6 +120,14 @@ bool ASMs2DLag::generateFEMTopology ()
}
Vec3 ASMs2DLag::getCoord (size_t inod) const
{
if (inod < 1 || inod > coord.size()) return Vec3();
return coord[inod-1];
}
bool ASMs2DLag::getElementCoordinates (Matrix& X, int iel) const
{
if (iel < 1 || (size_t)iel > MNPC.size())
@ -149,11 +157,21 @@ void ASMs2DLag::getNodalCoordinates (Matrix& X) const
}
Vec3 ASMs2DLag::getCoord (size_t inod) const
bool ASMs2DLag::updateCoords (const Vector& displ)
{
if (inod < 1 || inod > coord.size()) return Vec3();
if (displ.size() != nsd*coord.size())
{
std::cerr <<" *** ASMs2DLag::updateCoords: Invalid dimension "
<< displ.size() <<" on displ, should be "
<< nsd*coord.size() << std::endl;
return false;
}
return coord[inod-1];
const double* u = displ.ptr();
for (size_t inod = 0; inod < coord.size(); inod++, u += nsd)
coord[inod] += RealArray(u,u+nsd);
return true;
}
@ -497,11 +515,10 @@ bool ASMs2DLag::evalSolution (Matrix& sField, const Vector& locSol,
if (nComp*nPoints != locSol.size())
return false;
size_t i, n, ip = 0;
sField.resize(nComp,nPoints);
for (n = 1; n <= nPoints; n++)
for (i = 1; i <= nComp; i++)
sField(i,n) = locSol(++ip);
const double* u = locSol.ptr();
for (size_t n = 1; n <= nPoints; n++, u += nComp)
sField.fillColumn(n,u);
return true;
}

View File

@ -51,6 +51,10 @@ public:
//! \param[in] inod 1-based node index local to current patch
virtual Vec3 getCoord(size_t inod) const;
//! \brief Updates the nodal coordinates for this patch.
//! \param[in] displ Incremental displacements to update the coordinates with
virtual bool updateCoords(const Vector& displ);
// Methods for integration of finite element quantities.
// These are the main computational methods of the ASM class hierarchy.

View File

@ -974,6 +974,45 @@ Vec3 ASMs3D::getCoord (size_t inod) const
}
bool ASMs3D::updateCoords (const Vector& displ)
{
if (!svol) return true; // silently ignore empty patches
if (displ.size() != 3*MLGN.size())
{
std::cerr <<" *** ASMs3D::updateCoords: Invalid dimension "
<< displ.size() <<" on displ, should be "
<< 3*MLGN.size() << std::endl;
return false;
}
//TODO: This should be placed in GoTools (SplineVolume::deform)
//svol->deform(displ);
RealArray::iterator cit;
int i, j, cdim = svol->dimension();
if (svol->rational())
for (cit = svol->rcoefs_begin(), j = 0; cit != svol->rcoefs_end(); cit++)
{
double weight = cit[cdim];
for (i = 0; i < cdim && i < 3; i++)
cit[i] += displ[j+i] * weight;
cit += cdim;
j += 3;
}
for (cit = svol->coefs_begin(), j = 0; cit != svol->coefs_end();)
{
for (i = 0; i < cdim && i < 3; i++)
cit[i] += displ[j+i];
cit += cdim;
j += 3;
}
return true;
}
bool ASMs3D::getSize (int& n1, int& n2, int& n3, int) const
{
if (!svol) return false;

View File

@ -113,6 +113,10 @@ public:
//! \param[in] inod 1-based node index local to current patch
virtual Vec3 getCoord(size_t inod) const;
//! \brief Updates the nodal coordinates for this patch.
//! \param[in] displ Incremental displacements to update the coordinates with
virtual bool updateCoords(const Vector& displ);
//! \brief Creates an instance by reading the given input stream.
bool read(std::istream&);
//! \brief Writes the geometry of the SplineVolume object to given stream.

View File

@ -134,6 +134,14 @@ bool ASMs3DLag::generateFEMTopology ()
}
Vec3 ASMs3DLag::getCoord (size_t inod) const
{
if (inod < 1 || inod > coord.size()) return Vec3();
return coord[inod-1];
}
bool ASMs3DLag::getElementCoordinates (Matrix& X, int iel) const
{
if (iel < 1 || (size_t)iel > MNPC.size())
@ -163,11 +171,21 @@ void ASMs3DLag::getNodalCoordinates (Matrix& X) const
}
Vec3 ASMs3DLag::getCoord (size_t inod) const
bool ASMs3DLag::updateCoords (const Vector& displ)
{
if (inod < 1 || inod > coord.size()) return Vec3();
if (displ.size() != nsd*coord.size())
{
std::cerr <<" *** ASMs3DLag::updateCoords: Invalid dimension "
<< displ.size() <<" on displ, should be "
<< nsd*coord.size() << std::endl;
return false;
}
return coord[inod-1];
const double* u = displ.ptr();
for (size_t inod = 0; inod < coord.size(); inod++, u += nsd)
coord[inod] += RealArray(u,u+nsd);
return true;
}
@ -673,11 +691,10 @@ bool ASMs3DLag::evalSolution (Matrix& sField, const Vector& locSol,
if (nComp*nPoints != locSol.size())
return false;
size_t i, n, ip = 0;
sField.resize(nComp,nPoints);
for (n = 1; n <= nPoints; n++)
for (i = 1; i <= nComp; i++)
sField(i,n) = locSol(++ip);
const double* u = locSol.ptr();
for (size_t n = 1; n <= nPoints; n++, u += nsd)
sField.fillColumn(n,u);
return true;
}

View File

@ -51,6 +51,10 @@ public:
//! \param[in] inod 1-based node index local to current patch
virtual Vec3 getCoord(size_t inod) const;
//! \brief Updates the nodal coordinates for this patch.
//! \param[in] displ Incremental displacements to update the coordinates with
virtual bool updateCoords(const Vector& displ);
// Methods for integration of finite element quantities.
// These are the main computational methods of the ASM class hierarchy.

View File

@ -58,7 +58,7 @@ ASMu2D::ASMu2D (std::istream& is, unsigned char n_s, unsigned char n_f)
bool ASMu2D::read (std::istream& is)
{
if (lrspline) delete lrspline;
delete lrspline;
// read inputfile as either an LRSpline file directly or a tensor product B-spline and convert
char firstline[256];
@ -126,8 +126,8 @@ void ASMu2D::clear (bool retainGeometry)
if (!retainGeometry) {
// Erase spline data
if (lrspline) delete lrspline;
if (tensorspline) delete tensorspline;
delete lrspline;
delete tensorspline;
lrspline = 0;
tensorspline = 0;
geo = 0;
@ -150,10 +150,9 @@ bool ASMu2D::cornerRefine (int minBasisfunctions)
lrspline->insert_const_v_edge(h-unif_step_h, 0, h);
h -= unif_step_h;
}
std::ofstream meshFile;
meshFile.open("mesh.eps");
std::ofstream meshFile("mesh.eps");
lrspline->writePostscriptMesh(meshFile);
meshFile.close();
return true;
}
@ -180,11 +179,9 @@ bool ASMu2D::diagonalRefine (int minBasisfunctions)
v = h/2.0;
}
}
std::ofstream meshFile;
meshFile.open("mesh.eps");
lrspline->writePostscriptMesh(meshFile);
meshFile.close();
std::ofstream meshFile("mesh.eps");
lrspline->writePostscriptMesh(meshFile);
return true;
}
@ -216,10 +213,9 @@ bool ASMu2D::uniformRefine (int minBasisfunctions)
}
}
}
std::ofstream meshFile;
meshFile.open("mesh.eps");
std::ofstream meshFile("mesh.eps");
lrspline->writePostscriptMesh(meshFile);
meshFile.close();
return true;
}
@ -247,7 +243,7 @@ bool ASMu2D::uniformRefine (int dir, int nInsert)
else
tensorspline->insertKnot_v(extraKnots);
if(lrspline) delete lrspline;
delete lrspline;
geo = lrspline = new LR::LRSplineSurface(tensorspline);
return true;
}
@ -278,7 +274,7 @@ bool ASMu2D::refine (int dir, const RealArray& xi)
else
tensorspline->insertKnot_v(extraKnots);
if(lrspline) delete lrspline;
delete lrspline;
geo = lrspline = new LR::LRSplineSurface(tensorspline);
return true;
}
@ -288,7 +284,7 @@ bool ASMu2D::raiseOrder (int ru, int rv)
if (!tensorspline) return false;
tensorspline->raiseOrder(ru,rv);
if(lrspline) delete lrspline;
delete lrspline;
geo = lrspline = new LR::LRSplineSurface(tensorspline);
return true;
}
@ -385,37 +381,6 @@ bool ASMu2D::generateFEMTopology ()
#if 0
int ASMu2D::Edge::next ()
{
int ret = icnod;
icnod += incr;
return ret;
}
int ASMu2D::BlockNodes::next ()
{
int ret = iinod;
iinod += inc[0];
if (++indxI >= nnodI-1)
{
indxI = 1;
iinod += inc[1] - inc[0]*(nnodI-2);
}
return ret;
}
bool ASMu2D::assignNodeNumbers ()
{
for(size_t i=0; i<MLGN.size(); i++)
MLGN[i] = i+1;
return true;
}
bool ASMu2D::connectPatch (int edge, ASMu2D& neighbor, int nedge, bool revers)
{
return this->connectBasis(edge,neighbor,nedge,revers);
@ -660,9 +625,8 @@ bool ASMu2D::getElementCoordinates (Matrix& X, int iel) const
X.resize(nsd,mnpc.size());
std::vector<LR::Basisfunction*>::iterator bit = lrspline->getElement(iel-1)->supportBegin();
for (size_t n = 0; n < mnpc.size(); n++, bit++)
for (size_t i = 0; i < nsd; i++)
X(i+1,n+1) = (*bit)->controlpoint_[i];
for (size_t n = 1; n <= mnpc.size(); n++, bit++)
X.fillColumn(n,(*bit)->controlpoint_);
#if SP_DEBUG > 2
std::cout <<"\nCoordinates for element "<< iel << X << std::endl;
@ -677,10 +641,8 @@ void ASMu2D::getNodalCoordinates (Matrix& X) const
X.resize(nsd,nBasis);
std::vector<LR::Basisfunction*>::iterator bit = lrspline->basisBegin();
for(int inod=0; inod<nBasis; inod++, bit++)
for(size_t i=0; i<nsd; i++)
X(i+1,inod+1) = (*bit)->controlpoint_[i];
for (int inod = 1; inod <= nBasis; inod++, bit++)
X.fillColumn(inod,(*bit)->controlpoint_);
}
@ -695,6 +657,13 @@ Vec3 ASMu2D::getCoord (size_t inod) const
}
bool ASMu2D::updateCoords (const Vector& displ)
{
std::cerr <<" *** ASMu2D::updateCoords: Not implemented!"<< std::endl;
return false;
}
void ASMu2D::getGaussPointParameters (RealArray& uGP, int dir, int nGauss,
int iel, const double* xi) const
{

View File

@ -34,50 +34,7 @@ namespace LR {
class ASMu2D : public ASMunstruct, public ASM2D
{
//! \brief Struct for nodal point data.
struct IJ
{
int I; //!< Index in first parameter direction
int J; //!< Index in second parameter direction
};
// topology-stuff like connecting multiple patches. Will be introduced later
#if 0
//! \brief Struct for edge node definitions.
struct Edge
{
int icnod; //!< Global node number of first interior point along the edge
int incr; //!< Increment in the global numbering along the edge
//! \brief Default constructor.
Edge() { icnod = incr = 0; }
//! \brief Returns \a icnod which then is incremented.
int next();
};
public:
//! \brief Struct with data for definition of global node numbers of a patch.
struct BlockNodes
{
int ibnod[4]; //!< Vertex nodes
Edge edges[4]; //!< Edge nodes
int iinod; //!< Global node number of the first interior node
int inc[2]; //!< Increment in global node numbering in each direction
int nnodI; //!< Number of nodes in parameter direction I
int indxI; //!< Running node index in the local I-direction
//! \brief Default constructor.
BlockNodes() { iinod = inc[0] = inc[1] = 0; indxI = 1; }
//! \brief Returns \a iinod which then is incremented.
int next();
};
#endif
public:
//! \brief Constructor creating an instance by reading the given file.
ASMu2D(const char* fName = 0, unsigned char n_s = 2, unsigned char n_f = 2);
//! \brief Constructor creating an instance by reading the given input stream.
@ -85,13 +42,12 @@ public:
//! \brief Empty destructor.
virtual ~ASMu2D() {}
// Methods to access data
// ============================
//! \brief Returns the spline surface representing this patch.
LR::LRSplineSurface* getSurface() { return lrspline; }
// Methods for model generation
// ============================
// Methods for model generation and refinement
// ===========================================
//! \brief Generates the finite element topology data for the patch.
//! \details The data generated are the element-to-node connectivity array,
@ -107,27 +63,15 @@ public:
//! \param[in] inod 1-based node index local to current patch
virtual Vec3 getCoord(size_t inod) const;
//! \brief Updates the nodal coordinates for this patch.
//! \param[in] displ Incremental displacements to update the coordinates with
virtual bool updateCoords(const Vector& displ);
//! \brief Creates an instance by reading the given input stream.
bool read(std::istream&);
//! \brief Writes the geometry of the SplineSurface object to given stream.
virtual bool write(std::ostream&, int = 0) const;
#if 0
//! \brief Assigns new global node numbers for all nodes of the patch.
//! \param nodes Object with global nodes numbers to assign to this patch
//! \param[in] basis Which basis to assign node numbers for in mixed methods
//!
//! \details The global node numbers generated by \a generateFEMTopology are
//! non-unique in the sense that a node that is shared by two (or more)
//! patches along a common interface has a different number in each patch.
//! This method therefore assigns a new global number to each node in the
//! patch. The data provided through the \a nodes argument is sufficient
//! to determine the unique global number under the assumption that they
//! are ordered in the sequence determined by the local orientation of the
//! patch and its edges.
bool assignNodeNumbers();
#endif
//! \brief Refines along the diagonal of the LR-spline patch.
//! \details Progressively refine until the LR-spline object contains at least
//! \a minBasisfunctions basis functions.
@ -203,7 +147,6 @@ public:
// More multipatch stuff
#if 0
//! \brief Connects all matching nodes on two adjacent boundary edges.
//! \param[in] edge Local edge index of this patch, in range [1,4]
//! \param neighbor The neighbor patch
@ -217,9 +160,9 @@ public:
//! \param[in] basis Which basis to connect (mixed methods), 0 means both
//! \param[in] master 1-based index of the first master node in this basis
virtual void closeEdges(int dir, int basis = 0, int master = 1);
#endif
// Methods for integration of finite element quantities.
// These are the main computational methods of the ASM class hierarchy.
// ====================================================================
@ -261,7 +204,6 @@ public:
//! \note The number of element nodes must be set in \a grid on input.
virtual bool tesselate(ElementBlock& grid, const int* npe) const;
//! \brief Evaluates the primary solution field at all visualization points.
//! \param[out] sField Solution field
//! \param[in] locSol Solution vector in DOF-order
@ -385,12 +327,13 @@ protected:
Vector& N, Matrix& dNdu, Matrix3D& d2Ndu2);
protected:
LR::LRSplineSurface* lrspline; //!< Pointer to the actual spline surface object
LR::LRSplineSurface* lrspline; //!< Pointer to the LR-spline surface object
private:
Go::SplineSurface* tensorspline; //!< Pointer to the original tensor spline object
// the tensor spline object is kept for backwards compatability with the REFINE and RAISEORDER
// key-words, although we take note that there is a possibility of optimization since all mapping
// values and jacobians may be performed on this object for increased efficiency
Go::SplineSurface* tensorspline; //!< Pointer to original tensor spline object
// The tensor spline object is kept for backward compatability with the REFINE
// and RAISEORDER key-words, although we take note that there is a possibility
// of optimization since all mapping values and Jacobians may be performed on
// this object for increased efficiency.
};
#endif