Liebe Gitlab-Nutzer, lieber Gitlab-Nutzer, es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Ein Anmelden über dieses erzeugt ein neues Konto. Das alte Konto ist über den Reiter "Standard" erreichbar. Die Administratoren

Dear Gitlab user, it is now possible to log in to our service using the ZIH login/LDAP. Logging in via this will create a new account. The old account can be accessed via the "Standard" tab. The administrators

Commit 7e44b707 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

new operator style implemented, using tags

parent 0057b587
......@@ -14,9 +14,6 @@
namespace AMDiS
{
const Flag EQUAL_BASES = 0x01L;
const Flag EQUAL_LOCALBASES = 0x02L;
template <class Traits>
class Assembler
{
......
......@@ -110,7 +110,7 @@ void Assembler<Traits>::assembleElementOperators(
auto assemble_operators = [&](auto const& context, auto& operator_list) {
for (auto scaled : operator_list) {
scaled.op->bind(element, geometry);
bool add_op = scaled.op->assemble(context, elementContainer, localViews.tree()..., scaled.factor);
bool add_op = scaled.op->assemble(context, elementContainer, localViews.tree()...);
scaled.op->unbind();
add = add || add_op;
}
......@@ -148,18 +148,16 @@ void Assembler<Traits>::initMatrixVector(
auto localView = globalBasis_.localView();
forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
{
#ifdef HAVE_EXTENDED_DUNE_FUNCTIONS
if (rowNode.isLeaf)
msg(globalBasis_.dimension(rowTreePath), " DOFs for Basis[", to_string(rowTreePath), "]");
#endif
auto rowBasis = Dune::Functions::subspaceBasis(globalBasis_, rowTreePath);
//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);
for (auto bc : constraints_[rowNode][colNode].scalar)
bc->init(matrix, solution, rhs, rowBasis, colBasis);
......
#pragma once
namespace AMDiS
{
template <class LocalContext, class Geometry, class LocalGeometry>
struct ContextGeometry
{
enum {
dim = Geometry::mydimension, //< the dimension of the grid element
dow = Geometry::coorddimension //< the dimension of the world
};
LocalContext const& localContext;
Geometry const& geometry;
LocalGeometry const& localGeometry;
/// Coordinate `p` given in `localGeometry`, transformed to coordinate in `geometry`.
template <class Coordinate>
decltype(auto) position(Coordinate const& p) const
{
return position(p, std::is_same<Geometry, LocalGeometry>{});
}
/// The integration element from the `localGeometry`, the quadrature points are
/// defined in.
template <class Coordinate>
auto integrationElement(Coordinate const& p) const
{
return localGeometry.integrationElement(p);
}
/// Transformation of coordinate `p` given in `localGeometry` to world space coordinates.
template <class Coordinate>
decltype(auto) global(Coordinate const& p) const
{
return geometry.global(p);
}
private: // implementation detail
// position for elements
template <class Coordinate>
Coordinate const& position(Coordinate const& p, std::true_type) const
{
return p;
}
// position for intersection
template <class Coordinate>
auto position(Coordinate const& p, std::false_type) const
{
return localGeometry.global(p);
}
};
} // end namespace AMDiS
......@@ -91,7 +91,7 @@ namespace AMDiS
{
using WorldVector = typename GlobalBasis::GridView::template Codim<0>::Geometry::GlobalCoordinate;
template <class Node>
template <class RowNode, class ColNode>
struct type
{
std::list<std::shared_ptr<DirichletBC<WorldVector, double>>> scalar;
......
#pragma once
#include <vector>
#include <dune/typetree/nodetags.hh>
#include <dune/amdis/LocalAssembler.hpp>
#include <dune/amdis/common/Mpl.hpp>
#include <dune/amdis/common/TypeDefs.hpp>
#include <dune/amdis/utility/GetEntity.hpp>
namespace AMDiS
{
template <class GridView, class LocalContext, FirstOrderType type>
class FirstOrderAssembler
: public LocalAssembler<GridView, LocalContext>
{
using Super = LocalAssembler<GridView, LocalContext>;
static constexpr int dim = GridView::dimension;
static constexpr int dow = GridView::dimensionworld;
using ElementMatrix = Impl::ElementMatrix;
using ElementVector = Impl::ElementVector;
using OrderTag = std::conditional_t<(type==GRD_PHI), tag::fot_grd_phi, tag::fot_grd_psi>;
public:
FirstOrderAssembler()
: Super(1, type)
{}
template <class Operator, class... Args>
void bind(double factor, Operator& op, LocalContext const& localContext, Args&&... args)
{
Super::bind(op, localContext, std::forward<Args>(args)...);
factor_ = factor;
op.init(OrderTag{}, localContext, Super::getQuadrature());
}
// tag dispatching for FirstOrderType...
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
ElementMatrix& elementMatrix,
RowNode const& rowNode, ColNode const& colNode)
{
calculateElementMatrix(op, elementMatrix, rowNode, colNode,
typename RowNode::NodeTag{}, typename ColNode::NodeTag{}, FirstOrderType_<type>);
}
template <class Operator, class Node>
void calculateElementVector(Operator& op,
ElementVector& elementVector,
Node const& node)
{
calculateElementVector(op, elementVector, node,
typename Node::NodeTag{}, FirstOrderType_<type>);
}
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
ElementMatrix& elementMatrix,
RowNode const& rowNode, ColNode const& colNode,
Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PHI>)
{
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) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const double factor = Super::getLocalGeometry().integrationElement(quad[iq].position()) * quad[iq].weight() * factor_;
std::vector<Dune::FieldVector<double,1> > 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(local, colReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > colGradients(colReferenceGradients.size());
for (std::size_t i = 0; i < colGradients.size(); ++i)
jacobian.mv(colReferenceGradients[i][0], colGradients[i]);
for (std::size_t i = 0; i < rowLocalFE.size(); ++i) {
for (std::size_t j = 0; j < colLocalFE.size(); ++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]);
}
}
}
}
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
ElementMatrix& elementMatrix,
RowNode const& rowNode, ColNode const& colNode,
Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PSI>)
{
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) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
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(local, rowReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > rowGradients(rowReferenceGradients.size());
for (std::size_t i = 0; i < rowGradients.size(); ++i)
jacobian.mv(rowReferenceGradients[i][0], rowGradients[i]);
std::vector<Dune::FieldVector<double,1> > 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 = 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]);
}
}
}
}
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
ElementMatrix& elementMatrix,
RowNode const& rowNode, ColNode const& colNode,
Dune::TypeTree::LeafNodeTag, Dune::TypeTree::PowerNodeTag,
FirstOrderType_t<GRD_PHI>)
{
auto const& rowLocalFE = rowNode.finiteElement();
auto const& colLocalFE = colNode.child(0).finiteElement();
auto const& quad = Super::getQuadrature().getRule();
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) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
const double factor = Super::getLocalGeometry().integrationElement(quad[iq].position()) * quad[iq].weight() * factor_;
std::vector<Dune::FieldVector<double,1> > 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(local, colReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > colGradients(colReferenceGradients.size());
for (std::size_t i = 0; i < colGradients.size(); ++i)
jacobian.mv(colReferenceGradients[i][0], colGradients[i]);
// <div(u), q>
for (std::size_t i = 0; i < rowLocalFE.size(); ++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(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]);
}
}
}
}
}
template <class Operator, class RowNode, class ColNode>
void calculateElementMatrix(Operator& op,
ElementMatrix& elementMatrix,
RowNode const& rowNode, ColNode const& colNode,
Dune::TypeTree::PowerNodeTag, Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PSI>)
{
auto const& rowLocalFE = rowNode.child(0).finiteElement();
auto const& colLocalFE = colNode.finiteElement();
auto const& quad = Super::getQuadrature().getRule();
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) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
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(local, rowReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > rowGradients(rowReferenceGradients.size());
for (std::size_t i = 0; i < rowGradients.size(); ++i)
jacobian.mv(rowReferenceGradients[i][0], rowGradients[i]);
std::vector<Dune::FieldVector<double,1> > colShapeValues;
colLocalFE.localBasis().evaluateFunction(local, colShapeValues);
// <p, div(v)>
for (std::size_t j = 0; j < colLocalFE.size(); ++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(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]);
}
}
}
}
}
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 Node>
void calculateElementVector(Operator& op,
ElementVector& elementVector,
Node const& node,
Dune::TypeTree::LeafNodeTag,
FirstOrderType_t<GRD_PSI>)
{
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) local = Super::getLocal(quad[iq].position());
// The transposed inverse Jacobian of the map from the reference element to the element
const auto jacobian = Super::getGeometry().jacobianInverseTransposed(local);
// The multiplicative factor in the integral transformation formula
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(local, rowReferenceGradients);
// Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,dow> > rowGradients(rowReferenceGradients.size());
for (std::size_t i = 0; i < rowGradients.size(); ++i)
jacobian.mv(rowReferenceGradients[i][0], rowGradients[i]);
for (std::size_t i = 0; i < localFE.size(); ++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 Node, class NodeTag, class FOT>
void calculateElementVector(Operator&, ElementVector&,
Node const&, NodeTag, FOT)
{
warning("FirstOrderAssembler::calculateElementVector not implemented for Node");
}
private:
double factor_;
};
} // end namespace AMDiS
#pragma once
// std c++ headers
#include <functional>
#include <memory>
#include <type_traits>
// AMDiS includes
#include <dune/amdis/QuadratureRules.hpp>
#include <dune/amdis/common/TypeDefs.hpp>
#include <dune/geometry/quadraturerules.hh>
#include <dune/amdis/ContextGeometry.hpp>
#include <dune/amdis/LocalAssemblerBase.hpp>
#include <dune/amdis/common/Concepts.hpp>
#include <dune/amdis/utility/FiniteElementType.hpp>
namespace AMDiS
{
// the LocalContext is either an Codim=0-EntityType or an IntersectionType
template <class GridView, class LocalContext>
/// Implementation of interface \ref LocalAssemblerBase
template <class LocalContext, class Operator, class... Nodes>
class LocalAssembler
: public LocalAssemblerBase<LocalContext, Nodes...>
{
static constexpr int dim = GridView::dimension;
using ctype = typename GridView::ctype;
using Super = LocalAssemblerBase<LocalContext, Nodes...>;
private:
using Element = typename Super::Element;
using ElementMatrixVector = typename Super::ElementMatrixVector;
using LocalQuadratureRules = Dune::QuadratureRules<ctype, LocalContext::mydimension>;
using QuadratureRule = QuadratureRuleFactory_t<LocalContext, ctype, dim>;
using Geometry = typename Super::Geometry;
using LocalGeometry = typename Super::LocalGeometry;
using Geometry = typename GridView::template Codim<0>::Entity::Geometry;
using LocalGeometry = typename Impl::Get<LocalContext>::Geometry;
using Context = ContextGeometry<LocalContext, Geometry, LocalGeometry>;
public:
explicit LocalAssembler(int degree, FirstOrderType type = GRD_PHI)
: degree_(degree)
, type_(type)
/// Constructor. Stores a copy of operator `op`.
explicit LocalAssembler(Operator const& op)
: opStorage_(std::make_unique<Operator>(op))
, op_(*opStorage_)
{}
/// Constructor. Stores the reference to the operator.
explicit LocalAssembler(std::reference_wrapper<Operator> const& op)
: op_(op)
{}
/// Constructor, initializes the geometry of the element and a
/// quadrature-rule wrapper
template <class Operator>
void bind(Operator& op, LocalContext const& localContext, Geometry const& geometry, LocalGeometry const& localGeometry)
/// \brief Implementation of \ref LocalAssemblerBase::bind.
/**
* Binds the operator `op_` to the `element` and `geometry` and
* stores point to the `element` and `geometry`.
**/
virtual void bind(Element const& element, Geometry const& geometry) final
{
localContext_ = &localContext;
element_ = &element;
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));
op_.bind(element, geometry);
}
void unbind()
/// \brief Implementation of \ref LocalAssemblerBase::unbind
/**
* Unbinds the operator `op_` and sets \ref element_ and \ref geometry_
* to nullptr.
**/
virtual void unbind() final
{
localContext_ = nullptr;
op_.unbind();
geometry_ = nullptr;
localGeometry_ = nullptr;
element_ = nullptr;
}
/// \brief Returns reference to the transformed quadrature rule
/// Implementation of \ref LocalAssemblerBase::assemble
/**
* For intersections this corresponds to the points in the intersection
* geometry, but coordinates extended to the whole inside-entity. For
* elements this is a wrapper around the classical element quadrature rule.
* Access the underlying dune-quadrature rule, with `quadrature->getRule()`.
* Provides a quadrature formula with necessary degree to integrate the operator,
* stores geometry and localGeometry and a \ref ContextGeometry and calls
* \ref calculateElementVector or \ref calculateElementMatrix on the
* vector or matrix operator, respectively.
*
* The call to operator passes two optimization flags:
* 1. RowNode and ColNode implement the same local finiteelement
* 2. RowNode and ColNode are the same node in the globalBasis tree.
**/
QuadratureRule const& getQuadrature() const
virtual bool assemble(
LocalContext const& localContext,
ElementMatrixVector& elementMatrixVector,
Nodes const&... nodes) final
{
assert( quadrature_ );
return *quadrature_;
decltype(auto) localGeometry = getLocalGeometry(localContext);
using QuadratureRules = Dune::QuadratureRules<typename Geometry::ctype, LocalContext::mydimension>;
int degree = op_.getDegree(nodes...);
auto const& quad = QuadratureRules::rule(localGeometry.type(), degree);
Context data{localContext, getGeometry(), localGeometry};
assembleImpl(data, quad, elementMatrixVector, nodes...);
return true;
}
#ifndef DOXYGEN
protected: // implementation detail
// matrix assembling
template <class QuadratureRule, class ElementMatrix, class RowNode, class ColNode>
void assembleImpl(Context const& context,
QuadratureRule const& quad,
ElementMatrix& elementMatrix,
RowNode const& rowNode, ColNode const& colNode)
{
assembleImpl(context, quad, elementMatrix, rowNode, colNode,
std::is_same<FiniteElementType_t<RowNode>, FiniteElementType_t<ColNode>>{});
}
LocalContext const& getLocalContext() const
// local finite elements are the same for rowNode and colNode
template <class QuadratureRule, class ElementMatrix, class RowNode, class ColNode>
void assembleImpl(Context const& context,