Commit e18609d3 authored by Praetorius, Simon's avatar Praetorius, Simon

corrected error in quadrature degree, restructuring of zero/first/secondOrderAssembler

parent 781a6094
......@@ -24,6 +24,7 @@ namespace AMDiS
using GridView = typename GlobalBasis::GridView;
public:
/// Constructor, stores a shared-pointer to the feSpaces
Assembler(GlobalBasis& globalBasis,
MatrixOperators<GlobalBasis>& matrixOperators,
......@@ -48,7 +49,9 @@ namespace AMDiS
SystemVectorType& rhs,
bool asmMatrix, bool asmVector);
private:
/// Sets the system to zero and initializes all operators and boundary conditions
template <class SystemMatrixType, class SystemVectorType>
void initMatrixVector(
......@@ -58,11 +61,12 @@ namespace AMDiS
bool asmMatrix, bool asmVector) const;
template <class ElementContainer, class Container, class Operators, class... Bases>
template <class ElementContainer, class Container, class Operators, class Geometry, class... Bases>
void assembleElementOperators(
ElementContainer& elementContainer,
Container& container,
Operators& operators,
Geometry const& geometry,
Bases const&... subBases) const;
......@@ -90,22 +94,9 @@ namespace AMDiS
return globalBasis_.gridView();
}
public:
template <class RowNode, class ColNode>
Flag optimizationFlags(RowNode const& rowNode, ColNode const& colNode) const
{
Flag flag;
if (rowNode.treeIndex() == colNode.treeIndex())
flag |= EQUAL_BASES;
// NOTE: find a way to compare localBases directly
// if (rowNode.finiteElement().localBasis().order() == colNode.finiteElement().localBasis().order())
// flag |= EQUAL_LOCALBASES;
return flag;
}
private:
GlobalBasis& globalBasis_;
MatrixOperators<GlobalBasis>& matrixOperators_;
VectorOperators<GlobalBasis>& rhsOperators_;
......
......@@ -23,8 +23,8 @@ void Assembler<GlobalBasis>::assemble(
// 2. create a local matrix and vector
std::size_t localSize = localView.maxSize();
mtl::dense2D<double> elementMatrix(localSize, localSize);
mtl::dense_vector<double> elementVector(localSize);
Impl::ElementMatrix elementMatrix(localSize, localSize);
Impl::ElementVector elementVector(localSize);
// 3. traverse grid and assemble operators on the elements
for (auto const& element : elements(globalBasis_.gridView()))
......@@ -33,6 +33,7 @@ void Assembler<GlobalBasis>::assemble(
set_to_zero(elementVector);
localView.bind(element);
auto geometry = element.geometry();
// traverse type-tree of global-basis
forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
......@@ -43,7 +44,7 @@ void Assembler<GlobalBasis>::assemble(
auto& rhsOp = rhsOperators_[rowNode];
if (rhsOp.assemble(asmVector) && !rhsOp.empty())
assembleElementOperators(elementVector, rhs, rhsOp, rowLocalView);
assembleElementOperators(elementVector, rhs, rhsOp, geometry, rowLocalView);
forEachNode(localView.tree(), [&,this](auto const& colNode, auto colTreePath)
{
......@@ -53,8 +54,7 @@ void Assembler<GlobalBasis>::assemble(
auto colLocalView = colBasis.localView();
colLocalView.bind(element); // NOTE: Is this necessary
assembleElementOperators(elementMatrix, matrix, matOp, rowLocalView, colLocalView,
optimizationFlags(rowNode, colNode));
assembleElementOperators(elementMatrix, matrix, matOp, geometry, rowLocalView, colLocalView);
}
});
});
......@@ -92,11 +92,12 @@ void Assembler<GlobalBasis>::assemble(
template <class GlobalBasis>
template <class ElementContainer, class Container, class Operators, class... LocalViews>
template <class ElementContainer, class Container, class Operators, class Geometry, class... LocalViews>
void Assembler<GlobalBasis>::assembleElementOperators(
ElementContainer& elementContainer,
Container& container,
Operators& operators,
Geometry const& geometry,
LocalViews const&... localViews) const
{
auto const& element = getElement(localViews...);
......@@ -106,7 +107,9 @@ void Assembler<GlobalBasis>::assembleElementOperators(
auto assemble_operators = [&](auto const& context, auto& operator_list) {
for (auto scaled : operator_list) {
bool add_op = scaled.op->assemble(context, elementContainer, localViews..., scaled.factor);
scaled.op->bind(element, geometry);
bool add_op = scaled.op->assemble(context, elementContainer, localViews.tree()..., scaled.factor);
scaled.op->unbind();
add = add || add_op;
}
};
......@@ -147,14 +150,14 @@ void Assembler<GlobalBasis>::initMatrixVector(
msg(0, " DOFs for Basis[", to_string(rowTreePath), "]"); // TODO: add right values
auto rowBasis = Dune::Functions::subspaceBasis(globalBasis_, rowTreePath);
if (rhsOperators_[rowNode].assemble(asmVector))
rhsOperators_[rowNode].init(rowBasis);
//if (rhsOperators_[rowNode].assemble(asmVector))
// rhsOperators_[rowNode].init(rowBasis);
forEachNode(localView.tree(), [&,this](auto const& colNode, auto colTreePath)
{
auto colBasis = Dune::Functions::subspaceBasis(globalBasis_, colTreePath);
if (matrixOperators_[rowNode][colNode].assemble(asmMatrix))
matrixOperators_[rowNode][colNode].init(rowBasis, colBasis);
//if (matrixOperators_[rowNode][colNode].assemble(asmMatrix))
// matrixOperators_[rowNode][colNode].init(rowBasis, colBasis);
for (auto bc : constraints_[rowNode][colNode].scalar)
bc->init(matrix, solution, rhs, rowBasis, colBasis);
......
......@@ -26,68 +26,67 @@ namespace AMDiS
using OrderTag = std::conditional_t<(type==GRD_PHI), tag::fot_grd_phi, tag::fot_grd_psi>;
public:
template <class Operator>
FirstOrderAssembler(Operator& op, LocalContext const& element)
: Super(op, element, 1, type)
FirstOrderAssembler()
: Super(1, type)
{}
template <class Operator, class... Args>
void bind(double factor, Operator& op, LocalContext const& localContext, Args&&... args)
{
op.init(OrderTag{}, element, Super::getQuadrature());
Super::bind(op, localContext, std::forward<Args>(args)...);
factor_ = factor;
op.init(OrderTag{}, localContext, Super::getQuadrature());
}
// tag dispatching for FirstOrderType...
template <class Operator, class RowView, class ColView>
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
RowView const& rowView, ColView const& colView,
ElementMatrix& elementMatrix, double fac)
ElementMatrix& elementMatrix,
RowNode const& rowNode, ColNode const& colNode)
{
using RowNode = typename RowView::Tree;
using ColNode = typename ColView::Tree;
calculateElementMatrix(op, rowView, colView, elementMatrix, fac,
calculateElementMatrix(op, elementMatrix, rowNode, colNode,
typename RowNode::NodeTag{}, typename ColNode::NodeTag{}, FirstOrderType_<type>);
}
template <class Operator, class RowView>
template <class Operator, class Node>
void calculateElementVector(Operator& op,
RowView const& rowView,
ElementVector& elementVector, double fac)
ElementVector& elementVector,
Node const& node)
{
using RowNode = typename RowView::Tree;
calculateElementVector(op, rowView, elementVector, fac,
typename RowNode::NodeTag{}, FirstOrderType_<type>);
calculateElementVector(op, elementVector, node,
typename Node::NodeTag{}, FirstOrderType_<type>);
}
template <class Operator, class RowView, class ColView>
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
RowView const& rowView, ColView const& colView,
ElementMatrix& elementMatrix,
double fac,
RowNode const& rowNode, ColNode const& colNode,
Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PHI>)
{
auto geometry = rowView.element().geometry();
auto const& quad_geometry = Super::getGeometry();
auto const& rowLocalFE = rowView.tree().finiteElement();
auto const& colLocalFE = colView.tree().finiteElement();
auto const& rowLocalFE = rowNode.finiteElement();
auto const& colLocalFE = colNode.finiteElement();
auto const& quad = Super::getQuadrature().getRule();
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) quadPos = Super::map(quad[iq].position());
decltype(auto) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = geometry.jacobianInverseTransposed(quadPos);
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const double factor = quad_geometry.integrationElement(quad[iq].position()) * quad[iq].weight() * fac;
const double factor = Super::getLocalGeometry().integrationElement(quad[iq].position()) * quad[iq].weight() * factor_;
std::vector<Dune::FieldVector<double,1> > rowShapeValues;
rowLocalFE.localBasis().evaluateFunction(quadPos, rowShapeValues);
rowLocalFE.localBasis().evaluateFunction(local, rowShapeValues);
// The gradients of the shape functions on the reference element
std::vector<Dune::FieldMatrix<double,1,dim> > colReferenceGradients;
colLocalFE.localBasis().evaluateJacobian(quadPos, colReferenceGradients);
colLocalFE.localBasis().evaluateJacobian(local, colReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > colGradients(colReferenceGradients.size());
......@@ -97,8 +96,8 @@ namespace AMDiS
for (std::size_t i = 0; i < rowLocalFE.size(); ++i) {
for (std::size_t j = 0; j < colLocalFE.size(); ++j) {
const int local_i = rowView.tree().localIndex(i);
const int local_j = colView.tree().localIndex(j);
const int local_i = rowNode.localIndex(i);
const int local_j = colNode.localIndex(j);
op.eval(tag::fot_grd_phi{}, elementMatrix[local_i][local_j], iq, factor, rowShapeValues[i], colGradients[j]);
}
}
......@@ -106,34 +105,30 @@ namespace AMDiS
}
template <class Operator, class RowView, class ColView>
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
RowView const& rowView, ColView const& colView,
ElementMatrix& elementMatrix,
double fac,
RowNode const& rowNode, ColNode const& colNode,
Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PSI>)
{
auto geometry = rowView.element().geometry();
auto const& quad_geometry = Super::getGeometry();
auto const& rowLocalFE = rowView.tree().finiteElement();
auto const& colLocalFE = colView.tree().finiteElement();
auto const& rowLocalFE = rowNode.finiteElement();
auto const& colLocalFE = colNode.finiteElement();
auto const& quad = Super::getQuadrature().getRule();
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) quadPos = Super::map(quad[iq].position());
decltype(auto) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = geometry.jacobianInverseTransposed(quadPos);
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const double factor = quad_geometry.integrationElement(quad[iq].position()) * quad[iq].weight() * fac;
const double factor = Super::getLocalGeometry().integrationElement(quad[iq].position()) * quad[iq].weight() * factor_;
// The gradients of the shape functions on the reference element
std::vector<Dune::FieldMatrix<double,1,dim> > rowReferenceGradients;
rowLocalFE.localBasis().evaluateJacobian(quadPos, rowReferenceGradients);
rowLocalFE.localBasis().evaluateJacobian(local, rowReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > rowGradients(rowReferenceGradients.size());
......@@ -142,12 +137,12 @@ namespace AMDiS
jacobian.mv(rowReferenceGradients[i][0], rowGradients[i]);
std::vector<Dune::FieldVector<double,1> > colShapeValues;
colLocalFE.localBasis().evaluateFunction(quadPos, colShapeValues);
colLocalFE.localBasis().evaluateFunction(local, colShapeValues);
for (std::size_t i = 0; i < rowLocalFE.size(); ++i) {
for (std::size_t j = 0; j < colLocalFE.size(); ++j) {
const int local_i = rowView.tree().localIndex(i);
const int local_j = colView.tree().localIndex(j);
const int local_i = rowNode.localIndex(i);
const int local_j = colNode.localIndex(j);
op.eval(tag::fot_grd_psi{}, elementMatrix[local_i][local_j], iq, factor, rowGradients[i], colShapeValues[j]);
}
}
......@@ -155,39 +150,35 @@ namespace AMDiS
}
template <class Operator, class RowView, class ColView>
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
RowView const& rowView, ColView const& colView,
ElementMatrix& elementMatrix,
double fac,
RowNode const& rowNode, ColNode const& colNode,
Dune::TypeTree::LeafNodeTag, Dune::TypeTree::PowerNodeTag,
FirstOrderType_t<GRD_PHI>)
{
auto geometry = rowView.element().geometry();
auto const& quad_geometry = Super::getGeometry();
auto const& rowLocalFE = rowView.tree().finiteElement();
auto const& colLocalFE = colView.tree().child(0).finiteElement();
auto const& rowLocalFE = rowNode.finiteElement();
auto const& colLocalFE = colNode.child(0).finiteElement();
auto const& quad = Super::getQuadrature().getRule();
test_exit( dow == degree(colView.tree()), "Number of childs of Power-Node must be DOW");
test_exit( dow == degree(colNode), "Number of childs of Power-Node must be DOW");
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) quadPos = Super::map(quad[iq].position());
decltype(auto) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = geometry.jacobianInverseTransposed(quadPos);
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const double factor = quad_geometry.integrationElement(quad[iq].position()) * quad[iq].weight() * fac;
const double factor = Super::getLocalGeometry().integrationElement(quad[iq].position()) * quad[iq].weight() * factor_;
std::vector<Dune::FieldVector<double,1> > rowShapeValues;
rowLocalFE.localBasis().evaluateFunction(quadPos, rowShapeValues);
rowLocalFE.localBasis().evaluateFunction(local, rowShapeValues);
// The gradients of the shape functions on the reference element
std::vector<Dune::FieldMatrix<double,1,dim> > colReferenceGradients;
colLocalFE.localBasis().evaluateJacobian(quadPos, colReferenceGradients);
colLocalFE.localBasis().evaluateJacobian(local, colReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > colGradients(colReferenceGradients.size());
......@@ -197,10 +188,10 @@ namespace AMDiS
// <div(u), q>
for (std::size_t i = 0; i < rowLocalFE.size(); ++i) {
const int local_i = rowView.tree().localIndex(i);
const int local_i = rowNode.localIndex(i);
for (std::size_t j = 0; j < colLocalFE.size(); ++j) {
for (std::size_t k = 0; k < degree(colView.tree()); ++k) {
const int local_j = colView.tree().child(k).localIndex(j);
for (std::size_t k = 0; k < degree(colNode); ++k) {
const int local_j = colNode.child(k).localIndex(j);
op.eval(tag::fot_grd_phi{}, elementMatrix[local_i][local_j], iq, factor, rowShapeValues[i], colGradients[j][k]);
}
}
......@@ -209,36 +200,32 @@ namespace AMDiS
}
template <class Operator, class RowView, class ColView>
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
RowView const& rowView, ColView const& colView,
ElementMatrix& elementMatrix,
double fac,
RowNode const& rowNode, ColNode const& colNode,
Dune::TypeTree::PowerNodeTag, Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PSI>)
{
auto geometry = rowView.element().geometry();
auto const& quad_geometry = Super::getGeometry();
auto const& rowLocalFE = rowView.tree().child(0).finiteElement();
auto const& colLocalFE = colView.tree().finiteElement();
auto const& rowLocalFE = rowNode.child(0).finiteElement();
auto const& colLocalFE = colNode.finiteElement();
auto const& quad = Super::getQuadrature().getRule();
test_exit( dow == degree(rowView.tree()), "Number of childs of Power-Node must be DOW");
test_exit( dow == degree(rowNode), "Number of childs of Power-Node must be DOW");
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) quadPos = Super::map(quad[iq].position());
decltype(auto) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = geometry.jacobianInverseTransposed(quadPos);
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const double factor = quad_geometry.integrationElement(quad[iq].position()) * quad[iq].weight() * fac;
const double factor = Super::getLocalGeometry().integrationElement(quad[iq].position()) * quad[iq].weight() * factor_;
// The gradients of the shape functions on the reference element
std::vector<Dune::FieldMatrix<double,1,dim> > rowReferenceGradients;
rowLocalFE.localBasis().evaluateJacobian(quadPos, rowReferenceGradients);
rowLocalFE.localBasis().evaluateJacobian(local, rowReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > rowGradients(rowReferenceGradients.size());
......@@ -247,14 +234,14 @@ namespace AMDiS
jacobian.mv(rowReferenceGradients[i][0], rowGradients[i]);
std::vector<Dune::FieldVector<double,1> > colShapeValues;
colLocalFE.localBasis().evaluateFunction(quadPos, colShapeValues);
colLocalFE.localBasis().evaluateFunction(local, colShapeValues);
// <p, div(v)>
for (std::size_t j = 0; j < colLocalFE.size(); ++j) {
const int local_j = colView.tree().localIndex(j);
const int local_j = colNode.localIndex(j);
for (std::size_t i = 0; i < rowLocalFE.size(); ++i) {
for (std::size_t k = 0; k < degree(rowView.tree()); ++k) {
const int local_i = rowView.tree().child(k).localIndex(i);
for (std::size_t k = 0; k < degree(rowNode); ++k) {
const int local_i = rowNode.child(k).localIndex(i);
op.eval(tag::fot_grd_psi{}, elementMatrix[local_i][local_j], iq, factor, rowGradients[i][k], colShapeValues[j]);
}
}
......@@ -263,45 +250,38 @@ namespace AMDiS
}
template <class Operator, class RowView, class ColView, class RowNodeTag, class ColNodeTag, class FOT>
void calculateElementMatrix(Operator& op,
RowView const& rowView,
ColView const& colView,
ElementMatrix& elementMatrix,
double fac,
template <class Operator, class RowNode, class ColNode, class RowNodeTag, class ColNodeTag, class FOT>
void calculateElementMatrix(Operator&, ElementMatrix&,
RowNode const&, ColNode const&,
RowNodeTag, ColNodeTag, FOT)
{
warning("FirstOrderAssembler::calculateElementMatrix not implemented for RowNode x ColNode");
}
template <class Operator, class RowView>
template <class Operator, class Node>
void calculateElementVector(Operator& op,
RowView const& rowView,
ElementVector& elementVector,
double fac,
Node const& node,
Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PSI>)
{
auto geometry = rowView.element().geometry();
auto const& quad_geometry = Super::getGeometry();
auto const& localFE = rowView.tree().finiteElement();
auto const& localFE = node.finiteElement();
auto const& quad = Super::getQuadrature().getRule();
for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
decltype(auto) quadPos = Super::map(quad[iq].position());
decltype(auto) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = geometry.jacobianInverseTransposed(quadPos);
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const double factor = quad_geometry.integrationElement(quad[iq].position()) * quad[iq].weight() * fac;
const double factor = Super::getLocalGeometry().integrationElement(quad[iq].position()) * quad[iq].weight() * factor_;
// The gradients of the shape functions on the reference element
std::vector<Dune::FieldMatrix<double,1,dim> > rowReferenceGradients;
localFE.localBasis().evaluateJacobian(quadPos, rowReferenceGradients);
localFE.localBasis().evaluateJacobian(local, rowReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > rowGradients(rowReferenceGradients.size());
......@@ -310,22 +290,22 @@ namespace AMDiS
jacobian.mv(rowReferenceGradients[i][0], rowGradients[i]);
for (std::size_t i = 0; i < localFE.size(); ++i) {
const int local_i = rowView.tree().localIndex(i);
const int local_i = node.localIndex(i);
op.eval(tag::fot_grd_psi{}, elementVector[local_i], iq, factor, rowGradients[i]);
}
}
}
template <class Operator, class RowView, class NodeTag, class FOT>
void calculateElementVector(Operator& op,
RowView const& rowView,
ElementVector& elementVector,
double fac,
NodeTag, FOT)
template <class Operator, class Node, class NodeTag, class FOT>
void calculateElementVector(Operator&, ElementVector&,
Node const&, NodeTag, FOT)
{
warning("FirstOrderAssembler::calculateElementVector not implemented for RowNode");
warning("FirstOrderAssembler::calculateElementVector not implemented for Node");
}
private:
double factor_;
};
} // end namespace AMDiS
......@@ -18,19 +18,36 @@ namespace AMDiS
using LocalQuadratureRules = Dune::QuadratureRules<ctype, LocalContext::mydimension>;
using QuadratureRule = QuadratureRuleFactory_t<LocalContext, ctype, dim>;
using Geometry = typename Impl::Get<LocalContext>::Geometry;
using Geometry = typename GridView::template Codim<0>::Entity::Geometry;
using LocalGeometry = typename Impl::Get<LocalContext>::Geometry;
public:
LocalAssembler(int degree, FirstOrderType type = GRD_PHI)
: degree_(degree)
, type_(type)
{}
/// Constructor, initializes the geometry of the element and a
/// quadrature-rule wrapper
template <class Operator>
LocalAssembler(Operator& op, LocalContext const& element, int degree, FirstOrderType type = GRD_PHI)
: geometry(get_geometry(element))
void bind(Operator& op, LocalContext const& localContext, Geometry const& geometry, LocalGeometry const& localGeometry)
{
int order = op.getQuadratureDegree(geometry.type(), geometry, degree, type);
auto const& quad = LocalQuadratureRules::rule(geometry.type(), order);
localContext_ = &localContext;
geometry_ = &geometry;
localGeometry_ = &localGeometry;
int order = op.getQuadratureDegree(localGeometry.type(), localGeometry, degree_, type_);
auto const& quad = LocalQuadratureRules::rule(localGeometry.type(), order);
quadrature_.reset(new QuadratureRule(localContext, quad));
}
quadrature.reset(new QuadratureRule(element, quad));
void unbind()
{
localContext_ = nullptr;
geometry_ = nullptr;
localGeometry_ = nullptr;
}
/// \brief Returns reference to the transformed quadrature rule
......@@ -42,34 +59,44 @@ namespace AMDiS
**/
QuadratureRule const& getQuadrature() const
{
return *quadrature;
assert( quadrature_ );
return *quadrature_;
}
LocalContext const& getLocalContext() const
{
assert( localContext_ );
return *localContext_;
}
/// Return the geometry of the Object
/**
* The geometry is either the element geometry, or the geometry of the
* inside-element for intersections.
**/
Geometry const& getGeometry() const
{
return geometry;
assert( geometry_ );
return *geometry_;
}
protected:
LocalGeometry const& getLocalGeometry() const
{
assert( localGeometry_ );
return *localGeometry_;
}
// transform coords from intersection coords to element coords
template <class Coordinate>
decltype(auto) map(Coordinate const& p) const
decltype(auto) getLocal(Coordinate const& p) const
{
return get_position<LocalContext>(geometry, p);
return get_position<LocalContext>(getLocalGeometry(), p);
}
private:
/// transformed quadrature rule