Commit 98c0ebbe authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

added virtual destructors, wrong extension string in mesh reader, forward...

added virtual destructors, wrong extension string in mesh reader, forward declaration in operation::composer
parent d355c059
...@@ -51,6 +51,8 @@ namespace AMDiS ...@@ -51,6 +51,8 @@ namespace AMDiS
public: public:
virtual ~LocalAssemblerBase() {}
virtual void bind(Element const& element, Geometry const& geometry) = 0; virtual void bind(Element const& element, Geometry const& geometry) = 0;
virtual void unbind() = 0; virtual void unbind() = 0;
...@@ -97,6 +99,21 @@ namespace AMDiS ...@@ -97,6 +99,21 @@ namespace AMDiS
{ {
return flag && (!assembled || changing); return flag && (!assembled || changing);
} }
template <class Geo>
void bind(Element const& elem, Geo const& geo)
{
for (auto& scaled : element) scaled.op->bind(elem,geo);
for (auto& scaled : boundary) scaled.op->bind(elem,geo);
for (auto& scaled : intersection) scaled.op->bind(elem,geo);
}
void unbind()
{
for (auto& scaled : element) scaled.op->unbind();
for (auto& scaled : boundary) scaled.op->unbind();
for (auto& scaled : intersection) scaled.op->unbind();
}
}; };
public: public:
......
...@@ -113,14 +113,14 @@ namespace AMDiS ...@@ -113,14 +113,14 @@ namespace AMDiS
auto ext = fn.extension(); auto ext = fn.extension();
#if HAVE_ALBERTA #if HAVE_ALBERTA
if (ext == "1d" || ext == "2d" || ext == "3d") { if (ext == ".1d" || ext == ".2d" || ext == ".3d") {
Dune::GridFactory<Grid> factory; Dune::GridFactory<Grid> factory;
Dune::AlbertaReader<Grid> reader; Dune::AlbertaReader<Grid> reader;
reader.readGrid(filename, factory); reader.readGrid(filename, factory);
return std::unique_ptr<Grid>{factory.createGrid()}; return std::unique_ptr<Grid>{factory.createGrid()};
} }
#endif #endif
if (ext == "msh") { if (ext == ".msh") {
Dune::GmshReader<Grid> reader; Dune::GmshReader<Grid> reader;
return std::unique_ptr<Grid>{reader.read(filename)}; return std::unique_ptr<Grid>{reader.read(filename)};
} }
......
...@@ -14,5 +14,6 @@ ...@@ -14,5 +14,6 @@
#include <amdis/operations/Basic.hpp> #include <amdis/operations/Basic.hpp>
#include <amdis/operations/CMath.hpp> #include <amdis/operations/CMath.hpp>
#include <amdis/operations/Composer.hpp> #include <amdis/operations/Composer.hpp>
#include <amdis/operations/Composer.impl.hpp>
#include <amdis/operations/FieldMatVec.hpp> #include <amdis/operations/FieldMatVec.hpp>
#include <amdis/operations/MaxMin.hpp> #include <amdis/operations/MaxMin.hpp>
...@@ -79,6 +79,23 @@ namespace AMDiS ...@@ -79,6 +79,23 @@ namespace AMDiS
std::unique_ptr<SystemVector> oldSolution; std::unique_ptr<SystemVector> oldSolution;
}; };
#if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
// Deduction rule
template <class Traits>
ProblemInstat(std::string name, ProblemStat<Traits>& prob)
-> ProblemInstat<Traits>;
#endif
// Generator for ProblemInstat with given ProblemStat
template <class Traits>
ProblemInstat<Traits>
makeProblemInstat(std::string name, ProblemStat<Traits>& prob)
{
return {std::move(name), prob};
}
} // end namespace AMDiS } // end namespace AMDiS
#include "ProblemInstat.inc.hpp" #include "ProblemInstat.inc.hpp"
...@@ -65,11 +65,11 @@ namespace AMDiS ...@@ -65,11 +65,11 @@ namespace AMDiS
const auto exprValue = Super::coefficient(local); const auto exprValue = Super::coefficient(local);
// The gradients of the shape functions on the reference element // The gradients of the shape functions on the reference element
std::vector<Dune::FieldMatrix<double,1,Context::dim> > referenceGradients; thread_local std::vector<Dune::FieldMatrix<double,1,Context::dim> > referenceGradients;
rowLocalFE.localBasis().evaluateJacobian(local, referenceGradients); rowLocalFE.localBasis().evaluateJacobian(local, referenceGradients);
// Compute the shape function gradients on the real element // Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,Context::dow> > gradients(referenceGradients.size()); thread_local std::vector<Dune::FieldVector<double,Context::dow> > gradients(referenceGradients.size());
for (std::size_t i = 0; i < gradients.size(); ++i) for (std::size_t i = 0; i < gradients.size(); ++i)
jacobian.mv(referenceGradients[i][0], gradients[i]); jacobian.mv(referenceGradients[i][0], gradients[i]);
...@@ -113,7 +113,7 @@ namespace AMDiS ...@@ -113,7 +113,7 @@ namespace AMDiS
tag::scalar) tag::scalar)
{ {
auto const& localFE = node.finiteElement(); auto const& localFE = node.finiteElement();
std::vector<Dune::FieldMatrix<double,1,Context::dim> > referenceGradients; thread_local std::vector<Dune::FieldMatrix<double,1,Context::dim> > referenceGradients;
for (std::size_t iq = 0; iq < quad.size(); ++iq) { for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element // Position of the current quadrature point in the reference element
...@@ -129,7 +129,7 @@ namespace AMDiS ...@@ -129,7 +129,7 @@ namespace AMDiS
localFE.localBasis().evaluateJacobian(local, referenceGradients); localFE.localBasis().evaluateJacobian(local, referenceGradients);
// Compute the shape function gradients on the real element // Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,Context::dow> > gradients(referenceGradients.size()); thread_local std::vector<Dune::FieldVector<double,Context::dow> > gradients(referenceGradients.size());
for (std::size_t i = 0; i < gradients.size(); ++i) for (std::size_t i = 0; i < gradients.size(); ++i)
jacobian.mv(referenceGradients[i][0], gradients[i]); jacobian.mv(referenceGradients[i][0], gradients[i]);
...@@ -160,7 +160,7 @@ namespace AMDiS ...@@ -160,7 +160,7 @@ namespace AMDiS
tag::matrix) tag::matrix)
{ {
auto const& localFE = node.finiteElement(); auto const& localFE = node.finiteElement();
std::vector<Dune::FieldMatrix<double,1,Context::dim> > referenceGradients; thread_local std::vector<Dune::FieldMatrix<double,1,Context::dim> > referenceGradients;
for (std::size_t iq = 0; iq < quad.size(); ++iq) { for (std::size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element // Position of the current quadrature point in the reference element
...@@ -177,7 +177,7 @@ namespace AMDiS ...@@ -177,7 +177,7 @@ namespace AMDiS
localFE.localBasis().evaluateJacobian(local, referenceGradients); localFE.localBasis().evaluateJacobian(local, referenceGradients);
// Compute the shape function gradients on the real element // Compute the shape function gradients on the real element
std::vector<Dune::FieldVector<double,Context::dow> > gradients(referenceGradients.size()); thread_local std::vector<Dune::FieldVector<double,Context::dow> > gradients(referenceGradients.size());
for (std::size_t i = 0; i < gradients.size(); ++i) for (std::size_t i = 0; i < gradients.size(); ++i)
jacobian.mv(referenceGradients[i][0], gradients[i]); jacobian.mv(referenceGradients[i][0], gradients[i]);
......
...@@ -139,7 +139,7 @@ namespace AMDiS ...@@ -139,7 +139,7 @@ namespace AMDiS
&& all_of_v<Concepts::HasOrder<LFs>...>)> && all_of_v<Concepts::HasOrder<LFs>...>)>
int order(FunctorLocalFunction<Sig,F,LFs...> const& lf) int order(FunctorLocalFunction<Sig,F,LFs...> const& lf)
{ {
return Dune::Std::apply([&lf](auto const&... gfs) { return order(lf.fct(), order(gfs)...); }, return Dune::Std::apply([&lf](auto const&... lgfs) { return order(lf.fct(), order(lgfs)...); },
lf.localFcts()); lf.localFcts());
} }
......
...@@ -24,6 +24,8 @@ namespace AMDiS ...@@ -24,6 +24,8 @@ namespace AMDiS
Parameters::get(base + "->name", name_); Parameters::get(base + "->name", name_);
} }
virtual ~FileWriterInterface() {}
// pure virtual method to be implemented by derived classes // pure virtual method to be implemented by derived classes
virtual void writeFiles(AdaptInfo& adaptInfo, bool force) = 0; virtual void writeFiles(AdaptInfo& adaptInfo, bool force) = 0;
......
...@@ -67,34 +67,10 @@ namespace AMDiS ...@@ -67,34 +67,10 @@ namespace AMDiS
return Dune::Std::apply([&](auto const&... gs) { return order(c.f_, deg(gs)...); }, c.gs_); return Dune::Std::apply([&](auto const&... gs) { return order(c.f_, deg(gs)...); }, c.gs_);
} }
// forward declaration
struct Multiplies;
struct Plus;
/// Partial derivative of composed function: /// Partial derivative of composed function:
/// Implements: // sum_i [ d_i(f)[g...] * d_j(g_i) ] /// Implements: // sum_i [ d_i(f)[g...] * d_j(g_i) ]
template <int J, class F, class... Gs> template <int J, class F, class... Gs>
auto partial(Composer<F,Gs...> const& c, index_t<J> _j) auto partial(Composer<F,Gs...> const& c, index_t<J> _j);
{
auto index_seq = MakeSeq_t<sizeof...(Gs)>{};
// d_i(f)[g...] * d_j(g_i)
auto term_i = [&](auto const _i)
{
auto di_f = Dune::Std::apply([&](auto const&... gs) {
return compose(partial(c.f_, _i), gs...);
}, c.gs_);
auto const& g_i = std::get<_i>(c.gs_);
return compose(Multiplies{}, di_f, partial(g_i, _j));
};
// sum_i [ d_i(f)[g...] * d_j(g_i) ]
return Dune::Std::apply([&](auto const... _i)
{
return compose(Plus{}, term_i(_i)...);
}, index_seq);
}
#ifndef DOXYGEN #ifndef DOXYGEN
......
...@@ -4,219 +4,114 @@ ...@@ -4,219 +4,114 @@
#include <dune/typetree/treepath.hh> #include <dune/typetree/treepath.hh>
#include <dune/typetree/visitor.hh> #include <dune/typetree/visitor.hh>
namespace AMDiS { namespace AMDiS
{
#ifndef DOXYGEN // these are all internals and not public API. Only access is using applyToTree().
// forward declaration of main engine struct // forward declaration of main engine struct
template <typename tag = Dune::TypeTree::StartTag, bool doApply = true> template <typename NodeTag, bool visit = true>
struct TraverseTree; struct TraverseTree;
// This struct is the core of the algorithm. While this specialization simply serves as the starting point
// of the traversal and takes care of some setup work, the struct has to be specialized for each TreeType node type it
// should support.
// The first parameter is the tag of the node type
// and the second one must always be specialized as true, as a value of false means the node should in fact not be visited.
// That case is already handled by a specialization of the struct.
template <bool doApply>
struct TraverseTree<Dune::TypeTree::StartTag, doApply>
{
template <typename Node, typename Visitor>
static void apply(Node&& node, Visitor&& visitor)
{
TraverseTree<Dune::TypeTree::NodeTag<Node>>::apply(std::forward<Node>(node),
std::forward<Visitor>(visitor),
Dune::TypeTree::hybridTreePath());
}
};
// Do not visit nodes the visitor is not interested in // Do not visit nodes the visitor is not interested in
template <typename NodeTag> template <typename NodeTag>
struct TraverseTree<NodeTag, false> struct TraverseTree<NodeTag, false>
{ {
// we won't do anything with the objects, so having them all const
// works fine.
template <typename Node, typename Visitor, typename TreePath> template <typename Node, typename Visitor, typename TreePath>
static void apply(const Node& node, const Visitor& visitor, TreePath treePath) static void apply(const Node& node, const Visitor& visitor, TreePath const& tp)
{} {}
}; };
#ifndef DOXYGEN
// some implementation details
// ******************************************************************************** template <class Node, class Index>
// LeafNode struct HybridChildType
// ******************************************************************************** : HybridChildType<std::remove_const_t<Node>, std::remove_const_t<Index>> {};
// LeafNode - just call the leaf() callback template <class Node>
template <> struct HybridChildType<Node, std::size_t>
struct TraverseTree<Dune::TypeTree::LeafNodeTag, true>
{ {
template <typename N, typename V, typename TreePath> using type = typename Node::template Child<0>::Type;
static void apply(N&& n, V&& v, TreePath tp)
{
v.leaf(std::forward<N>(n),tp);
}
}; };
template <class Node, std::size_t K>
struct HybridChildType<Node, Dune::index_constant<K>>
{
using type = typename Node::template Child<K>::Type;
};
// ******************************************************************************** template <class NodeTag, class Node>
// PwerNode constexpr std::size_t hybridDegree(NodeTag, Node const& node)
// ******************************************************************************** {
return Dune::TypeTree::degree(node);
}
template <> template <class Node>
struct TraverseTree<Dune::TypeTree::PowerNodeTag, true> constexpr auto hybridDegree(Dune::TypeTree::CompositeNodeTag, Node const& node)
{ {
template <typename N, typename V, typename TreePath> return Dune::index_constant<Node::CHILDREN>{};
static void apply(N&& n, V&& v, TreePath tp) }
{
v.pre(std::forward<N>(n),tp);
typedef typename std::remove_reference<N>::type Node;
typedef typename std::remove_reference<V>::type Visitor;
// get child type template <std::size_t k, std::size_t n>
typedef typename Node::template Child<0>::Type C; constexpr bool notLastChild(Dune::index_constant<k> const&, Dune::index_constant<n> const&)
{
return k < n-1;
}
constexpr bool notLastChild(std::size_t k, std::size_t n)
{
return k < n-1;
}
// Do we have to visit the children? As the TreePath is dynamic, it does not #endif
// contain any information that could be evaluated at compile time, so we only
// have to query the visitor once.
const bool visit = Visitor::template VisitChild<Node,C,TreePath>::value;
auto child_tp = push_back(tp, std::size_t(0));
static const std::size_t last = treePathSize(tp);
// iterate over children template <class NodeTag>
for (std::size_t k = 0; k < degree(n); ++k) struct TraverseTree<NodeTag, true>
{
template <typename N, typename V, typename TreePath>
static void apply(N&& n, V&& v, TreePath const& tp)
{
using Node = std::remove_reference_t<N>;
using Visitor = std::remove_reference_t<V>;
v.pre(std::forward<N>(n),tp);
auto const deg = hybridDegree(NodeTag{}, n);
forEach(Dune::range(deg), [&](auto const _k)
{ {
// always call beforeChild(), regardless of the value of visit // always call beforeChild(), regardless of the value of visit
v.beforeChild(std::forward<N>(n),n.child(k),tp,k); v.beforeChild(std::forward<N>(n),n.child(_k),tp,_k);
// update TreePath
std::get<last>(child_tp._data) = k;
// descend to child // descend to child
TraverseTree<Dune::TypeTree::NodeTag<C>,visit>::apply(n.child(k),std::forward<V>(v),child_tp); using C = typename HybridChildType<Node, decltype(_k)>::type;
const bool visit = Visitor::template VisitChild<Node,C,TreePath>::value;
TraverseTree<Dune::TypeTree::NodeTag<C>,visit>::apply(n.child(_k),std::forward<V>(v),push_back(tp, _k));
// always call afterChild(), regardless of the value of visit // always call afterChild(), regardless of the value of visit
v.afterChild(std::forward<N>(n),n.child(k),tp,k); v.afterChild(std::forward<N>(n),n.child(_k),tp,_k);
// if this is not the last child, call infix callback // if this is not the last child, call infix callback
if (k < degree(n) - 1) if (notLastChild(_k, deg))
v.in(std::forward<N>(n),tp); v.in(std::forward<N>(n),tp);
} });
v.post(std::forward<N>(n),tp); v.post(std::forward<N>(n),tp);
} }
}; };
// LeafNode - just call the leaf() callback
namespace Impl
{
// ********************************************************************************
// Static Version
// ********************************************************************************
template <std::size_t inverse_k, std::size_t count>
struct TraverseTreeStatic
{
template <typename N, typename V, typename TreePath>
static void apply(N&& n, V&& v, TreePath tp)
{
// make sure we do not try to work with references to the actual types
typedef typename std::remove_reference<N>::type Node;
typedef typename std::remove_reference<V>::type Visitor;
// get child type
typedef typename Node::template Child<count-inverse_k>::Type C;
// extend TreePath by child index
auto k = std::integral_constant<std::size_t, count-inverse_k>{};
auto child_tp = push_back(tp, k);
// is the visitor interested in this child?
const bool visit = Visitor::template VisitChild<Node,C,decltype(child_tp)>::value;
// beforeChild() gets called regardless of the value of visit
v.beforeChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp,k);
// traverse to child
TraverseTree<Dune::TypeTree::NodeTag<C>,visit>::apply(n.template child<count-inverse_k>(),
std::forward<V>(v),
child_tp);
// afterChild() gets called regardless of the value of visit
v.afterChild(std::forward<N>(n),n.template child<count-inverse_k>(),tp,k);
// we are not at the last child (that is specialized), so call infix visitor callback
v.in(std::forward<N>(n),tp);
// continue with next child
TraverseTreeStatic<inverse_k-1,count>::apply(std::forward<N>(n), std::forward<V>(v), tp);
}
};
// Specialization for last child. This specialization stops the recursion and
// does not call the infix visitor on the CompositeNode.
template <std::size_t count>
struct TraverseTreeStatic<1,count>
{
template<typename N, typename V, typename TreePath>
static void apply(N&& n, V&& v, TreePath tp)
{
typedef typename std::remove_reference<N>::type Node;
typedef typename std::remove_reference<V>::type Visitor;
typedef typename Node::template Child<count-1>::Type C;
auto k = std::integral_constant<std::size_t, count-1>{};
auto child_tp = push_back(tp, k);
const bool visit = Visitor::template VisitChild<Node,C,decltype(child_tp)>::value;
v.beforeChild(std::forward<N>(n),n.template child<count-1>(),tp,k);
TraverseTree<Dune::TypeTree::NodeTag<C>,visit>::apply(n.template child<count-1>(),
std::forward<V>(v),
child_tp);
v.afterChild(std::forward<N>(n),n.template child<count-1>(),tp,k);
}
};
// Specialization for CompositeNode without any children.
template <>
struct TraverseTreeStatic<0,0>
{
template <typename N, typename V, typename TreePath>
static void apply(N&& n, V&& v, TreePath tp) {}
};
} // end namespace Impl
// ********************************************************************************
// CompositeNode
// ********************************************************************************
// Traverse CompositeNode - just forward to the generic algorithm
template <> template <>
struct TraverseTree<Dune::TypeTree::CompositeNodeTag,true> struct TraverseTree<Dune::TypeTree::LeafNodeTag, true>
{ {
template <typename N, typename V, typename TreePath> template <typename N, typename V, typename TreePath>
static void apply(N&& n, V&& v, TreePath tp) static void apply(N&& n, V&& v, TreePath const& tp)
{ {
v.pre(std::forward<N>(n),tp); v.leaf(std::forward<N>(n),tp);
typedef typename std::remove_reference<N>::type Node;
static const std::size_t C = Dune::TypeTree::StaticDegree<Node>::value;
Impl::TraverseTreeStatic<C,C>::apply(std::forward<N>(n), std::forward<V>(v), tp);
v.post(std::forward<N>(n),tp);
} }
}; };
#endif // DOXYGEN
// ********************************************************************************
// Public Interface
// ********************************************************************************
//! Apply visitor to TypeTree. //! Apply visitor to TypeTree.
/** /**
* This function applies the given visitor to the given tree. Both visitor and tree may be const * This function applies the given visitor to the given tree. Both visitor and tree may be const
...@@ -231,7 +126,10 @@ namespace AMDiS { ...@@ -231,7 +126,10 @@ namespace AMDiS {
template <typename Tree, typename Visitor> template <typename Tree, typename Visitor>
void traverseTree(Tree&& tree, Visitor&& visitor) void traverseTree(Tree&& tree, Visitor&& visitor)
{ {
TraverseTree<>::apply(std::forward<Tree>(tree), std::forward<Visitor>(visitor)); using Node = std::remove_reference_t<Tree>;
using NodeTag = Dune::TypeTree::NodeTag<Node>;
using TreePath = Dune::TypeTree::HybridTreePath<>;
TraverseTree<NodeTag>::apply(std::forward<Tree>(tree), std::forward<Visitor>(visitor), TreePath{});
} }
} // end namespace AMDiS } // end namespace AMDiS
...@@ -145,6 +145,26 @@ namespace AMDiS ...@@ -145,6 +145,26 @@ namespace AMDiS
return ""; return "";
}