Commit 301640ea authored by Praetorius, Simon's avatar Praetorius, Simon

some examples modified to make it running

parent 5c70d545
......@@ -6,6 +6,7 @@
#include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh>
#include <dune/amdis/DirichletBC.hpp>
#include <dune/amdis/LinearAlgebra.hpp>
#include <dune/amdis/Operator.hpp>
#include <dune/amdis/common/Mpl.hpp>
......@@ -23,10 +24,12 @@ namespace AMDiS
/// Constructor, stores a shared-pointer to the feSpaces
Assembler(GlobalBasis& globalBasis,
MatrixOperators<GlobalBasis>& matrixOperators,
VectorOperators<GlobalBasis>& rhsOperators)
VectorOperators<GlobalBasis>& rhsOperators,
Constraints<GlobalBasis>& constraints)
: globalBasis_(globalBasis)
, matrixOperators_(matrixOperators)
, rhsOperators_(rhsOperators)
, constraints_(constraints)
{}
void update(GridView const& gv)
......@@ -88,6 +91,7 @@ namespace AMDiS
GlobalBasis& globalBasis_;
MatrixOperators<GlobalBasis>& matrixOperators_;
VectorOperators<GlobalBasis>& rhsOperators_;
Constraints<GlobalBasis>& constraints_;
};
} // end namespace AMDiS
......
#pragma once
#include <dune/functions/functionspacebases/subspacebasis.hh>
#include <dune/typetree/treepath.hh>
#include <dune/amdis/utility/TreePath.hpp>
#include <dune/amdis/utility/Visitor.hpp>
namespace AMDiS {
......@@ -64,16 +64,20 @@ void Assembler<GlobalBasis>::assemble(
for (std::size_t i = 0; i < localView.size(); ++i) {
auto const row = localIndexSet.index(i);
for (std::size_t j = 0; j < localView.size(); ++j) {
if (elementMatrix(i,j) != 0.0) {
auto const col = localIndexSet.index(j);
matrix(row,col) += elementMatrix(i,j);
}
}
}
// add element-vector to system-vector
for (std::size_t i = 0; i < localView.size(); ++i) {
if (elementVector[i] != 0.0) {
auto const idx = localIndexSet.index(i);
rhs[idx] += elementVector[i];
}
}
localIndexSet.unbind();
localView.unbind();
......@@ -86,43 +90,6 @@ void Assembler<GlobalBasis>::assemble(
}
template <class GlobalBasis>
template <class SystemMatrixType, class SystemVectorType>
void Assembler<GlobalBasis>::initMatrixVector(
SystemMatrixType& matrix,
SystemVectorType& solution,
SystemVectorType& rhs,
bool asmMatrix, bool asmVector) const
{
matrix.init(asmMatrix);
solution.compress();
rhs.compress();
auto localView = globalBasis_.localView();
forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
{
if (rowNode.isLeaf)
msg(0, " DOFs for Basis[", 1, "]"); // TODO: add right values
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);
// init boundary condition
// for (int c = 0; c < nComponents; ++c)
// for (auto bc : matrixOperators[R][c].dirichlet)
// bc->init(c == C, matrix(_r, _c), solution[_c], rhs[_r]);
});
});
}
template <class GlobalBasis>
template <class ElementContainer, class Container, class Operators, class... LocalViews>
void Assembler<GlobalBasis>::assembleElementOperators(
......@@ -160,6 +127,44 @@ void Assembler<GlobalBasis>::assembleElementOperators(
}
template <class GlobalBasis>
template <class SystemMatrixType, class SystemVectorType>
void Assembler<GlobalBasis>::initMatrixVector(
SystemMatrixType& matrix,
SystemVectorType& solution,
SystemVectorType& rhs,
bool asmMatrix, bool asmVector) const
{
matrix.init(asmMatrix);
solution.compress();
rhs.compress();
auto localView = globalBasis_.localView();
forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
{
if (rowNode.isLeaf)
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);
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);
for (auto bc : constraints_[rowNode][colNode].vector)
bc->init(matrix, solution, rhs, rowBasis, colBasis);
});
});
msg(globalBasis_.dimension(), " total DOFs");
}
template <class GlobalBasis>
template <class SystemMatrixType, class SystemVectorType>
std::size_t Assembler<GlobalBasis>::finishMatrixVector(
......@@ -171,27 +176,25 @@ std::size_t Assembler<GlobalBasis>::finishMatrixVector(
matrix.finish();
auto localView = globalBasis_.localView();
forEachNode(localView.tree(), [&,this](auto const& rowNode, auto /*rowTreePath*/)
forEachNode(localView.tree(), [&,this](auto const& rowNode, auto rowTreePath)
{
auto rowBasis = Dune::Functions::subspaceBasis(globalBasis_, rowTreePath);
auto& rhsOp = rhsOperators_[rowNode];
if (rhsOp.assemble(asmVector))
rhsOp.assembled = true;
forEachNode(localView.tree(), [&,this](auto const& colNode, auto /*colTreePath*/)
forEachNode(localView.tree(), [&,this](auto const& colNode, auto colTreePath)
{
auto colBasis = Dune::Functions::subspaceBasis(globalBasis_, colTreePath);
auto& matOp = matrixOperators_[rowNode][colNode];
if (matOp.assemble(asmMatrix))
matOp.assembled = true;
// finish boundary condition
// for (int c = 0; c < nComponents; ++c) {
// for (int r = 0; r < nComponents; ++r) {
// if (r != R && c != C)
// continue;
// for (auto bc : matrixOperators[r][c].dirichlet)
// bc->finish(r == R, c == C, matrix(_r, _c), solution[_c], rhs[_r]);
// }
// }
for (auto bc : constraints_[rowNode][colNode].scalar)
bc->finish(matrix, solution, rhs, rowBasis, colBasis);
for (auto bc : constraints_[rowNode][colNode].vector)
bc->finish(matrix, solution, rhs, rowBasis, colBasis);
});
});
......
......@@ -4,9 +4,9 @@
#include <type_traits>
#include <vector>
#include <dune/amdis/common/Concepts.hpp>
#include <dune/amdis/Output.hpp>
#include <dune/amdis/common/Concepts.hpp>
#include <dune/amdis/utility/TreeData.hpp>
namespace AMDiS
{
......@@ -25,13 +25,13 @@ namespace AMDiS
* support this symmetric modification. As a result, this method returns a list
* of columns values, that should be subtracted from the rhs.
**/
template <class WorldVector>
template <class Domain, class Range = double>
class DirichletBC
{
public:
template <class Predicate, class Values,
REQUIRES(Concepts::Functor<Predicate, bool(WorldVector)> &&
Concepts::Functor<Values, double(WorldVector)>) >
REQUIRES(Concepts::Functor<Predicate, bool(Domain)> &&
Concepts::Functor<Values, Range(Domain)>) >
DirichletBC(Predicate&& predicate, Values&& values)
: predicate(std::forward<Predicate>(predicate))
, values(std::forward<Values>(values))
......@@ -41,11 +41,15 @@ namespace AMDiS
/// Prepare the matrix, rhs and solution block for assembling dirichlet
/// boundary conditions, e.g. collect the corresponding indices of boundary
/// DOFS for later elimination in \ref finish.
template <class Matrix, class VectorX, class VectorB>
void init(bool apply,
Matrix& matrix,
VectorX& rhs,
VectorB& solution);
template <class Matrix, class VectorX, class VectorB, class RowBasis, class ColBasis>
void init(Matrix& /*matrix*/, VectorX& /*rhs*/, VectorB& /*solution*/,
RowBasis const& rowBasis,
ColBasis const& /*colBasis*/)
{
using RowNode = typename RowBasis::LocalView::Tree;
initImpl(rowBasis, typename RowNode::NodeTag{});
}
/// \brief Apply dirichlet BC to matrix and vector, i.e., add a unit-row
......@@ -55,21 +59,51 @@ namespace AMDiS
* is assembled. The \p matrix, \p rhs, and \p solution correspond to the
* currently visited blocks of system-matrix and system-vector.
**/
template <class Matrix, class VectorX, class VectorB>
void finish(bool apply_row,
bool apply_col,
Matrix& matrix,
template <class Matrix, class VectorX, class VectorB, class RowBasis, class ColBasis>
void finish(Matrix& matrix,
VectorX& rhs,
VectorB& solution);
VectorB& solution,
RowBasis const& rowBasis,
ColBasis const& colBasis);
protected:
template <class RowBasis>
void initImpl(RowBasis const& rowBasis, Dune::TypeTree::LeafNodeTag);
template <class RowBasis>
void initImpl(RowBasis const& rowBasis, Dune::TypeTree::PowerNodeTag);
template <class RB, class RowNodeTag>
void initImpl(RB const&, RowNodeTag) {}
private:
std::function<bool(WorldVector)> predicate;
std::function<double(WorldVector)> values;
std::function<bool(Domain)> predicate;
std::function<Range(Domain)> values;
bool initialized = false;
std::vector<char> dirichletNodes;
};
template <class GlobalBasis>
struct DirichletData
{
using WorldVector = typename GlobalBasis::GridView::template Codim<0>::Geometry::GlobalCoordinate;
template <class Node>
struct type
{
std::list<std::shared_ptr<DirichletBC<WorldVector, double>>> scalar;
std::list<std::shared_ptr<DirichletBC<WorldVector, WorldVector>>> vector;
void push_back(std::shared_ptr<DirichletBC<WorldVector, double>> const& bc) { scalar.push_back(bc); }
void push_back(std::shared_ptr<DirichletBC<WorldVector, WorldVector>> const& bc) { vector.push_back(bc); }
};
};
template <class GlobalBasis>
using Constraints = MatrixData<GlobalBasis, DirichletData<GlobalBasis>::template type>;
} // end namespace AMDiS
#include "DirichletBC.inc.hpp"
#pragma once
#include <dune/functions/functionspacebases/interpolate.hh>
#include <dune/functions/functionspacebases/subspacebasis.hh>
#include <dune/amdis/LinearAlgebra.hpp>
#include <dune/amdis/linear_algebra/HierarchicWrapper.hpp>
namespace AMDiS
{
template <class WorldVector>
template <class Matrix, class VectorX, class VectorB>
void DirichletBC<WorldVector>::init(bool /*apply*/,
Matrix& matrix,
VectorX& /*solution*/,
VectorB& /*rhs*/)
template <class WorldVector, class Range>
template <class RowBasis>
void DirichletBC<WorldVector, Range>::initImpl(
RowBasis const& rowBasis, Dune::TypeTree::LeafNodeTag)
{
using Dune::Functions::interpolate;
if (!initialized) {
interpolate(matrix.getRowFeSpace(), dirichletNodes, predicate);
interpolate(rowBasis, hierarchicVectorWrapper(dirichletNodes), predicate);
initialized = true;
}
}
template <class WorldVector, class Range>
template <class RowBasis>
void DirichletBC<WorldVector, Range>::initImpl(
RowBasis const& rowBasis, Dune::TypeTree::PowerNodeTag)
{
using Dune::Functions::interpolate;
template <class WorldVector>
template <class Matrix, class VectorX, class VectorB>
void DirichletBC<WorldVector>::finish(bool apply_row,
bool apply_col,
Matrix& matrix,
VectorX& solution,
VectorB& rhs)
if (!initialized) {
auto tp = rowBasis.prefixPath();
auto const& basis = rowBasis.rootBasis();
for (std::size_t i = 0; i < degree(rowBasis.localView().tree()); ++i)
interpolate(Dune::Functions::subspaceBasis(basis, push_back(tp,i)),
hierarchicVectorWrapper(dirichletNodes), predicate);
initialized = true;
}
}
template <class WorldVector, class Range>
template <class Matrix, class VectorX, class VectorB, class RowBasis, class ColBasis>
void DirichletBC<WorldVector, Range>::finish(
Matrix& matrix, VectorX& solution, VectorB& rhs,
RowBasis const& rowBasis, ColBasis const& colBasis)
// Dune::TypeTree::LeafNodeTag, Dune::TypeTree::LeafNodeTag)
{
using Dune::Functions::interpolate;
test_exit_dbg(initialized, "Boundary condition not initialized!");
auto columns = matrix.applyDirichletBC(dirichletNodes, apply_row, apply_col);
auto columns = matrix.applyDirichletBC(dirichletNodes);
if (apply_col) {
interpolate(matrix.getRowFeSpace(), wrapper(rhs.getVector()), values, dirichletNodes);
if (apply_row)
interpolate(matrix.getColFeSpace(), wrapper(solution.getVector()), values, dirichletNodes);
interpolate(rowBasis, hierarchicVectorWrapper(rhs.getVector()), values, hierarchicVectorWrapper(dirichletNodes));
interpolate(colBasis, hierarchicVectorWrapper(solution.getVector()), values, hierarchicVectorWrapper(dirichletNodes));
// subtract columns of dirichlet nodes from rhs
for (auto const& triplet : columns)
rhs[triplet.row] -= triplet.value * solution[triplet.col];
}
}
} // end namespace AMDiS
This diff is collapsed.
......@@ -37,6 +37,7 @@
#include <dune/amdis/common/Utility.hpp>
#include <dune/amdis/utility/RangeType.hpp>
#include <dune/amdis/utility/TreePath.hpp>
namespace AMDiS
{
......@@ -164,11 +165,19 @@ namespace AMDiS
/// Adds a Dirichlet boundary condition
template <class Predicate, class Values>
template <class Predicate, class RowTreePath, class ColTreePath, class Values>
void addDirichletBC(Predicate const& predicate,
int row, int col,
RowTreePath row, ColTreePath col,
Values const& values);
template <class Predicate, class RowTreePath, class ColTreePath>
void addDirichletBC(Predicate const& predicate,
RowTreePath row, ColTreePath col,
double constant)
{
addDirichletBC(predicate, row, col, [constant](auto const&) { return constant; });
}
/// Implementation of \ref ProblemStatBase::solve
virtual void solve(AdaptInfo& adaptInfo,
......@@ -236,23 +245,27 @@ namespace AMDiS
/// Return a pointer to the solution, \ref solution
auto getSolution() { return solution; }
auto getSolution() const { return solution; }
std::shared_ptr<SystemVector> getSolution() { return solution; }
std::shared_ptr<SystemVector const> getSolution() const { return solution; }
/// Return the i'th \ref solution component
/// Return a view to a solution component
template <class TreePath>
auto getSolution(TreePath path)
{
using namespace Dune::Functions;
auto tp = makeTreePath(path);
using TP = decltype(tp);
using Node = typename GlobalBasis::NodeFactory::template Node<decltype(tp)>;
using Range = RangeType<Node, double>;
using Tree = typename GlobalBasis::LocalView::Tree;
using Node = typename Dune::TypeTree::ChildForTreePath<Tree, TP>;
using Range = RangeType<Node>;
using NTRM = Dune::Functions::DefaultNodeToRangeMap<Node>;
return makeDiscreteGlobalBasisFunction<Range>(
subspaceBasis(*globalBasis, tp),
*solution);
using DiscreteFunction = Dune::Functions::DiscreteGlobalBasisFunction<GlobalBasis,TP,SystemVector,NTRM,Range>;
auto nodeToRange = std::make_shared<NTRM>(makeDefaultNodeToRangeMap(*globalBasis, tp));
return std::make_shared<DiscreteFunction>(globalBasis, tp, solution, nodeToRange);
}
......@@ -332,8 +345,10 @@ namespace AMDiS
void createGlobalBasis()
{
globalBasis = std::make_shared<GlobalBasis>(makeGlobalBasis<GlobalBasis>(leafGridView()));
matrixOperators.init(*globalBasis);
rhsOperators.init(*globalBasis);
globalTree = std::make_shared<typename GlobalBasis::LocalView::Tree>(globalBasis->localView().tree());
matrixOperators.init(*globalTree);
rhsOperators.init(*globalTree);
constraints.init(*globalTree);
}
void createMatricesAndVectors()
......@@ -381,6 +396,7 @@ namespace AMDiS
/// FE spaces of this problem.
std::shared_ptr<GlobalBasis> globalBasis; // eventuell const
std::shared_ptr<typename GlobalBasis::LocalView::Tree> globalTree;
/// A FileWriter object
std::shared_ptr<FileWriter<GlobalBasis>> filewriter;
......@@ -404,13 +420,7 @@ namespace AMDiS
MatrixOperators<GlobalBasis> matrixOperators;
VectorOperators<GlobalBasis> rhsOperators;
template <class Node>
struct DirichletData
{
std::list<std::shared_ptr<DirichletBC<WorldVector>>> bc;
};
MatrixData<GlobalBasis, DirichletData> matrixConstraints;
Constraints<GlobalBasis> constraints;
};
......
......@@ -7,7 +7,6 @@
#include <dune/amdis/common/Loops.hpp>
#include <dune/amdis/common/Timer.hpp>
#include <dune/amdis/linear_algebra/HierarchicWrapper.hpp>
#include <dune/amdis/utility/TreePath.hpp>
namespace AMDiS {
......@@ -241,9 +240,9 @@ addVectorOperator(std::map< int, std::pair<ElementOperator, bool> > ops)
// Adds a Dirichlet boundary condition
template <class GlobalBasis>
template <class Predicate, class Values>
template <class Predicate, class RowTreePath, class ColTreePath, class Values>
void ProblemStat<GlobalBasis>::
addDirichletBC(Predicate const& predicate, int row, int col, Values const& values)
addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Values const& values)
{
static_assert( Concepts::Functor<Predicate, bool(WorldVector)>,
"Function passed to addDirichletBC for predicate does not model the Functor<bool(WorldVector)> concept");
......@@ -251,15 +250,14 @@ addDirichletBC(Predicate const& predicate, int row, int col, Values const& value
static_assert( Concepts::Callable<Values, WorldVector>,
"Function passed to addDirichletBC for values does not model the Callable<WorldVector> concept");
#if 0
test_exit(row >= 0 && row < nComponents, "row number out of range: ", row);
test_exit(col >= 0 && col < nComponents, "col number out of range: ", col);
auto i = child(globalBasis->localView().tree(), makeTreePath(row));
auto j = child(globalBasis->localView().tree(), makeTreePath(col));
// boundaryConditionSet = true;
using Range = decltype(values(std::declval<WorldVector>()));
using BcType = DirichletBC<WorldVector,Range>;
using BcType = DirichletBC<WorldVector>;
matrixOperators[row][col].dirichlet.emplace_back( new BcType{predicate, values} );
#endif
auto bc = std::make_shared<BcType>(predicate, values);
constraints[i][i].push_back(bc);
}
......@@ -309,7 +307,7 @@ buildAfterCoarsen(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool
{
Timer t;
Assembler<GlobalBasis> assembler(*globalBasis, matrixOperators, rhsOperators);
Assembler<GlobalBasis> assembler(*globalBasis, matrixOperators, rhsOperators, constraints);
auto gv = leafGridView();
assembler.update(gv);
......@@ -324,7 +322,7 @@ void ProblemStat<GlobalBasis>::
writeFiles(AdaptInfo& adaptInfo, bool /*force*/)
{
Timer t;
filewriter->write(adaptInfo.getTime(), *solution);
// filewriter->write(adaptInfo.getTime(), *solution);
msg("writeFiles needed ", t.elapsed(), " seconds");
}
......
......@@ -14,7 +14,6 @@ namespace AMDiS
{
namespace Impl
{
template <class GridView, int k, class MultiIndex>
struct LagrangeBasisSubFactory
{
......@@ -27,31 +26,73 @@ namespace AMDiS
using type = Dune::Functions::PQ1NodeFactory<GridView, MultiIndex>;
};
// factory to construct a global basis of several lagrange bases, with flat indexing.
template <class GridView, bool same, int... deg>
struct LagrangeBasisBuilderImpl;
// specialization for composite basis
template <class GridView, int... deg>
struct LagrangeBasisBuilder
struct LagrangeBasisBuilderImpl<GridView, false, deg...>
{
using MultiIndex = Dune::ReservedVector<std::size_t,1>;
using IndexTag = Dune::Functions::BasisBuilder::FlatLexicographic;
using NodeFactory = Dune::Functions::CompositeNodeFactory<MultiIndex, IndexTag,
using type = Dune::Functions::CompositeNodeFactory<MultiIndex, IndexTag,
typename LagrangeBasisSubFactory<GridView,deg,MultiIndex>::type...>;
};
// specialization for power basis
template <class GridView, int deg, int... degs>
struct LagrangeBasisBuilderImpl<GridView, true, deg, degs...>
{
using MultiIndex = Dune::ReservedVector<std::size_t,1>;
using IndexTag = Dune::Functions::BasisBuilder::FlatLexicographic;
using type = Dune::Functions::PowerNodeFactory<MultiIndex, IndexTag,
typename LagrangeBasisSubFactory<GridView,deg,MultiIndex>::type, 1 + sizeof...(degs)>;
};
// factory to construct a global basis of several lagrange bases, with flat indexing.
template <class GridView, int deg, int... degs>
struct LagrangeBasisBuilder
{
using type = typename LagrangeBasisBuilderImpl<GridView, and_t<(deg == degs)...>::value, deg, degs...>::type;
};
template <class GridView>
struct TaylorHoodBasisBuilder
{
using MultiIndex = Dune::ReservedVector<std::size_t,1>;
using IndexTagV = Dune::Functions::BasisBuilder::FlatInterleaved;
using type = Dune::Functions::DefaultGlobalBasis<NodeFactory>;
using VelocityNodeFactory = Dune::Functions::PowerNodeFactory<MultiIndex, IndexTagV,
typename LagrangeBasisSubFactory<GridView,2,MultiIndex>::type, 2>;
using PressureNodeFactory = typename LagrangeBasisSubFactory<GridView,1,MultiIndex>::type;
using IndexTag = Dune::Functions::BasisBuilder::FlatLexicographic;
using type = Dune::Functions::CompositeNodeFactory<MultiIndex, IndexTag,
VelocityNodeFactory, PressureNodeFactory>;
};
} // end namespace Impl
/// \brief A factory for a composite basis composed of lagrange bases of different degree.
template <class GridView, int... degrees>
using LagrangeBasis
= typename Impl::LagrangeBasisBuilder<GridView, degrees...>::type;
= Dune::Functions::DefaultGlobalBasis<typename Impl::LagrangeBasisBuilder<GridView, degrees...>::type>;
/// Specialization of \ref LagrangeBasis for Grid type \ref Dune::YaspGrid for a given dimension.
template <int dim, int... degrees>
using YaspGridBasis = LagrangeBasis<typename Dune::YaspGrid<dim>::LeafGridView, degrees...>;
template <class GridView>
using TaylorHoodBasis
= Dune::Functions::DefaultGlobalBasis<typename Impl::TaylorHoodBasisBuilder<GridView>::type>;
} // end namespace AMDiS
......
......@@ -56,11 +56,11 @@ namespace AMDiS
auto geometry = rowView.element().geometry();
auto const& quad_geometry = Super::getGeometry();
auto const& rowLocalBasis = rowView