Commit 781a6094 authored by Praetorius, Simon's avatar Praetorius, Simon

some optimizations in dune-functions discretization

parent 301640ea
......@@ -14,6 +14,9 @@
namespace AMDiS
{
const Flag EQUAL_BASES = 0x01L;
const Flag EQUAL_LOCALBASES = 0x02L;
template <class GlobalBasis>
class Assembler
{
......@@ -87,11 +90,28 @@ 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_;
Constraints<GlobalBasis>& constraints_;
//TODO: add caching of localBases
};
} // end namespace AMDiS
......
......@@ -24,14 +24,14 @@ void Assembler<GlobalBasis>::assemble(
std::size_t localSize = localView.maxSize();
mtl::dense2D<double> elementMatrix(localSize, localSize);
set_to_zero(elementMatrix);
mtl::dense_vector<double> elementVector(localSize);
set_to_zero(elementVector);
// 3. traverse grid and assemble operators on the elements
for (auto const& element : elements(globalBasis_.gridView()))
{
set_to_zero(elementMatrix);
set_to_zero(elementVector);
localView.bind(element);
// traverse type-tree of global-basis
......@@ -53,7 +53,8 @@ void Assembler<GlobalBasis>::assemble(
auto colLocalView = colBasis.localView();
colLocalView.bind(element); // NOTE: Is this necessary
assembleElementOperators(elementMatrix, matrix, matOp, rowLocalView, colLocalView);
assembleElementOperators(elementMatrix, matrix, matOp, rowLocalView, colLocalView,
optimizationFlags(rowNode, colNode));
}
});
});
......@@ -105,7 +106,7 @@ 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, localViews..., elementContainer, scaled.factor);
bool add_op = scaled.op->assemble(context, elementContainer, localViews..., scaled.factor);
add = add || add_op;
}
};
......
#pragma once
#include <string>
#include <vector>
#include <array>
//#include <vector>
//#include <array>
#include <memory>
#include <dune/functions/functionspacebases/lagrangebasis.hh>
#include <dune/grid/io/file/vtk/vtkwriter.hh>
#include <dune/grid/io/file/vtk/vtksequencewriter.hh>
#include <dune/geometry/referenceelements.hh>
//#include <dune/geometry/referenceelements.hh>
#include <dune/typetree/childextraction.hh>
#include <dune/amdis/Initfile.hpp>
#include <dune/amdis/common/Loops.hpp>
#include <dune/amdis/io/FileWriterInterface.hpp>
#include <dune/amdis/utility/Filesystem.hpp>
namespace AMDiS
{
template <class Traits>
template <class GlobalBasis, class TreePath>
class FileWriter
: public FileWriterInterface
{
private: // typedefs and static constants
using MeshView = typename Traits::GridView;
using GridView = typename GlobalBasis::GridView;
/// Dimension of the mesh
static constexpr int dim = MeshView::dimension;
static constexpr int dim = GridView::dimension;
/// Dimension of the world
static constexpr int dow = MeshView::dimensionworld;
static constexpr int dow = GridView::dimensionworld;
/// Number of problem components
static constexpr int nComponents = 1;
using Vector = DOFVector<GlobalBasis>;
public:
public:
/// Constructor.
FileWriter(std::string base, MeshView const& meshView, std::vector<std::string> const& names)
: meshView(meshView)
, names(names)
FileWriter(std::string baseName,
std::shared_ptr<GlobalBasis> const& basis,
TreePath const& tp,
std::shared_ptr<Vector> const& vector)
: FileWriterInterface(baseName)
, basis_(basis)
, treePath_(tp)
, vector_(vector)
{
filename = "solution";
Parameters::get(base + "->filename", filename);
dir = "output";
Parameters::get(base + "->output directory", dir);
//int subSampling = Parameters::get<int>(baseName + "->subsampling").value_or(0);
if (!filesystem::exists(dir))
error_exit("Output directory '",dir,"' does not exist!");
//if (subSampling > 0)
// vtkWriter_ = std::make_shared<Dune::SubsamplingVTKWriter<GridView>>(basis_->gridView(), subSampling);
//else
vtkWriter_ = std::make_shared<Dune::VTKWriter<GridView>>(basis_->gridView());
vtkWriter = std::make_shared<Dune::VTKWriter<MeshView>>(meshView);
vtkSeqWriter = std::make_shared<Dune::VTKSequenceWriter<MeshView>>(vtkWriter, filename, dir, "");
vtkSeqWriter_ = std::make_shared<Dune::VTKSequenceWriter<GridView>>(vtkWriter_, filename_, dir_, "");
mode_ = Parameters::get<int>(baseName + "->ParaView mode").value_or(0);
}
/// Implements \ref FileWriterInterface::writeFiles
virtual void writeFiles(AdaptInfo& adaptInfo, bool force) override
{
using Tree = typename GlobalBasis::LocalView::Tree;
using Node = typename Dune::TypeTree::ChildForTreePath<Tree, TreePath>;
writeVertexData(typename Node::NodeTag{}, index_<Node::CHILDREN>, [&,this]()
{
if (mode_ == 0)
vtkSeqWriter_->write(adaptInfo.getTime(), Dune::VTK::ascii);
else if (mode_ == 1)
vtkSeqWriter_->write(adaptInfo.getTime(), Dune::VTK::appendedraw);
});
}
protected:
template <class W>
void writeVertexData(Dune::TypeTree::LeafNodeTag, index_t<0>, W write)
{
using namespace Dune::Functions::BasisBuilder;
auto fct = makeDiscreteFunction(basis_,treePath_,vector_);
auto p1basis = makeBasis(basis_->gridView(), lagrange<1>());
auto data = makeDOFVector(p1basis, name_);
interpolate(p1basis, data, *fct);
auto dataFct = Dune::Functions::makeDiscreteGlobalBasisFunction<double>(p1basis,data);
vtkWriter_->addVertexData(dataFct, Dune::VTK::FieldInfo(name_, Dune::VTK::FieldInfo::Type::scalar, 1));
write();
vtkWriter_->clear();
}
template <std::size_t C, class W>
void writeVertexData(Dune::TypeTree::PowerNodeTag, index_t<C>, W write)
{
using namespace Dune::Functions::BasisBuilder;
assert( C == dow );
auto fct = makeDiscreteFunction(basis_,treePath_,vector_);
auto p1basis = makeBasis(basis_->gridView(), power<C>(lagrange<1>(), flatLexicographic()));
auto data = makeDOFVector(p1basis, name_);
interpolate(p1basis, data, *fct);
using Range = Dune::FieldVector<double,C>;
auto dataFct = Dune::Functions::makeDiscreteGlobalBasisFunction<Range>(p1basis,data);
vtkWriter_->addVertexData(dataFct, Dune::VTK::FieldInfo(name_, Dune::VTK::FieldInfo::Type::vector, C));
write();
vtkWriter_->clear();
}
template <class NodeTag, std::size_t C, class W>
void writeVertexData(NodeTag, index_t<C>, W) {}
#if 0
/// default write method for time-depended data
template <class SystemVectorType>
void write(double time, SystemVectorType const& solutions)
......@@ -82,9 +144,6 @@ namespace AMDiS
vtkWriter->pwrite(filename, dir, "" /*, Dune::VTK::appendedraw*/);
}
protected:
template <class DOFVector, class Vector>
void dofVector2vertexVector(DOFVector const& dofvector, Vector& data)
{
......@@ -98,7 +157,7 @@ namespace AMDiS
auto localView = feSpace.localView();
auto localIndexSet = feSpace.localIndexSet();
#if 0
// copy data to P1-vector
for (auto const& element : elements(meshView)) {
localView.bind(element);
......@@ -124,19 +183,21 @@ namespace AMDiS
}
}
}
#endif
}
#endif
private:
MeshView meshView;
shared_ptr<Dune::VTKWriter<MeshView>> vtkWriter;
shared_ptr<Dune::VTKSequenceWriter<MeshView>> vtkSeqWriter;
std::shared_ptr<GlobalBasis> basis_;
TreePath treePath_;
std::shared_ptr<Vector> vector_;
std::shared_ptr<Dune::VTKWriter<GridView>> vtkWriter_;
std::shared_ptr<Dune::VTKSequenceWriter<GridView>> vtkSeqWriter_;
std::vector<std::string> names;
std::array<std::vector<double>, nComponents> data_vectors;
// std::vector<double> data_vector;
std::string filename;
std::string dir;
// represents VTK::OutputType: 0...ascii, 1...appendedraw
int mode_;
};
} // end namespace AMDiS
......@@ -23,15 +23,14 @@ namespace AMDiS
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:
template <class Operator>
FirstOrderAssembler(Operator& op, LocalContext const& element)
: Super(op, element, 1, type)
{
if (type == GRD_PHI)
op.initFot1(element, Super::getQuadrature());
else
op.initFot2(element, Super::getQuadrature());
op.init(OrderTag{}, element, Super::getQuadrature());
}
......@@ -100,12 +99,13 @@ namespace AMDiS
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);
op.evalFot1(elementMatrix[local_i][local_j], iq, factor, rowShapeValues[i], colGradients[j]);
op.eval(tag::fot_grd_phi{}, elementMatrix[local_i][local_j], iq, factor, rowShapeValues[i], colGradients[j]);
}
}
}
}
template <class Operator, class RowView, class ColView>
void calculateElementMatrix(Operator& op,
RowView const& rowView, ColView const& colView,
......@@ -148,7 +148,7 @@ namespace AMDiS
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);
op.evalFot2(elementMatrix[local_i][local_j], iq, factor, rowGradients[i], colShapeValues[j]);
op.eval(tag::fot_grd_psi{}, elementMatrix[local_i][local_j], iq, factor, rowGradients[i], colShapeValues[j]);
}
}
}
......@@ -201,13 +201,14 @@ namespace AMDiS
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);
op.evalZot(elementMatrix[local_i][local_j], iq, factor, rowShapeValues[i], colGradients[j][k]);
op.eval(tag::fot_grd_phi{}, elementMatrix[local_i][local_j], iq, factor, rowShapeValues[i], colGradients[j][k]);
}
}
}
}
}
template <class Operator, class RowView, class ColView>
void calculateElementMatrix(Operator& op,
RowView const& rowView, ColView const& colView,
......@@ -254,7 +255,7 @@ namespace AMDiS
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);
op.evalZot(elementMatrix[local_i][local_j], iq, factor, rowGradients[i][k], colShapeValues[j]);
op.eval(tag::fot_grd_psi{}, elementMatrix[local_i][local_j], iq, factor, rowGradients[i][k], colShapeValues[j]);
}
}
}
......@@ -269,7 +270,10 @@ namespace AMDiS
ElementMatrix& elementMatrix,
double fac,
RowNodeTag, ColNodeTag, FOT)
{}
{
warning("FirstOrderAssembler::calculateElementMatrix not implemented for RowNode x ColNode");
}
template <class Operator, class RowView>
void calculateElementVector(Operator& op,
......@@ -307,18 +311,21 @@ namespace AMDiS
for (std::size_t i = 0; i < localFE.size(); ++i) {
const int local_i = rowView.tree().localIndex(i);
op.evalFot2(elementVector[local_i], iq, factor, rowGradients[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)
{}
{
warning("FirstOrderAssembler::calculateElementVector not implemented for RowNode");
}
};
} // end namespace AMDiS
......@@ -65,15 +65,15 @@ namespace AMDiS
void Initfile::getInternalParameters()
{
int val = 0;
get("level of information", val, 0);
get("level of information", val);
msgInfo = val;
val = 1;
get("parameter information", val, 0);
get("parameter information", val);
paramInfo = val;
val = 0;
get("break on missing tag", val, 0);
get("break on missing tag", val);
breakOnMissingTag = val;
if (msgInfo == 0)
......@@ -88,9 +88,9 @@ namespace AMDiS
}
// explicit template instatiation
template void Initfile::get(std::string, int&, int);
template void Initfile::get(std::string, double&, int);
template void Initfile::get(std::string, std::string&, int);
template void Initfile::get(std::string, int&);
template void Initfile::get(std::string, double&);
template void Initfile::get(std::string, std::string&);
} // end namespace AMDiS
......@@ -190,62 +190,30 @@ namespace AMDiS
static void init(std::string in);
/** Static get routine for getting parameter-values from init-file
* initialized in init()-method.
* Cast the value to the desired type using std::stringstream.
* @param tag: The tag to look for
* @param value: The result.
* @param debugInfo: msgInfo for current parameter. (0..no printing,
* 1..print missing parameter info, 2..print parameter value) [optional]
*/
template <class T>
static void get(std::string tag, T& value, int debugInfo = -1)
static boost::optional<T> get(std::string tag)
{
if (debugInfo == -1)
debugInfo = singlett().getMsgInfo();
else
{
int swap(debugInfo);
debugInfo = singlett().getMsgInfo();
singlett().msgInfo=swap;
}
using path = boost::property_tree::ptree::path_type;
replaceAll(tag, "->", ">");
auto tagPath = path(tag, '>');
// TODO: use boost::optional instead
// TODO: use convert method from above
std::string valueStr = "-";
valueStr = singlett().pt.get(tagPath, valueStr);
if (valueStr != "-")
detail::Convert<T>::eval(valueStr, value);
// if (debugInfo == 2)
// {
// std::cout << "Parameter '" << tag << "'"
// << " initialized with: " << value << std::endl;
// }
singlett().msgInfo = debugInfo;
}
template <class T, class S>
static T get(std::string tag, S const& default_value)
{
T value = default_value;
Self::get(tag, value);
return value;
return singlett().pt.get_optional<T>(tagPath);
}
/** \brief Static get routine for getting parameter-values from init-file
* initialized in init()-method.
* Cast the value to the desired type.
*
* \param tag: The tag to look for
* \param value: The result.
*/
template <class T>
static T get(std::string tag)
static void get(std::string tag, T& value)
{
T value; nullify(value);
Self::get(tag, value);
return value;
auto v = get<std::string>(tag);
if (v)
detail::Convert<T>::eval(v.value(), value);
}
......@@ -336,9 +304,9 @@ namespace AMDiS
using Parameters = Initfile;
#ifndef AMDIS_NO_EXTERN_INITFILE
extern template void Initfile::get(std::string, int&, int);
extern template void Initfile::get(std::string, double&, int);
extern template void Initfile::get(std::string, std::string&, int);
extern template void Initfile::get(std::string, int&);
extern template void Initfile::get(std::string, double&);
extern template void Initfile::get(std::string, std::string&);
#endif
} // end namespace AMDiS
......@@ -7,6 +7,7 @@
#include <dune/typetree/typetree.hh>
#include <dune/functions/common/treedata.hh>
#include <dune/amdis/Flag.hpp>
#include <dune/amdis/OperatorTermBase.hpp>
#include <dune/amdis/ZeroOrderAssembler.hpp>
#include <dune/amdis/FirstOrderAssembler.hpp>
......@@ -19,7 +20,6 @@
namespace AMDiS
{
// the LocalContext is either an Codim=0-EntityType or an IntersectionType
template <class GridView, class LocalContext>
class Operator
......@@ -133,17 +133,18 @@ namespace AMDiS
template <class RowView, class ColView, class ElementMatrix>
bool assemble(
LocalContext const& element,
ElementMatrix& elementMatrix,
RowView const& rowView,
ColView const& colView,
ElementMatrix& elementMatrix,
Flag const& optimizationFlag,
double* factor = NULL);
// assemble vector operator
template <class LocalView, class ElementVector>
bool assemble(
LocalContext const& element,
LocalView const& localView,
ElementVector& elementVector,
LocalView const& localView,
double* factor = NULL);
......@@ -167,68 +168,27 @@ namespace AMDiS
protected: // sum up constribution from all operator-terms
template <class... Args>
void evalZot(double& result, int iq, double factor, Args const&... args)
{
for (auto* operatorTerm : zeroOrder)
result += operatorTerm->evalZot(iq, args...) * factor;
}
template <class... Args>
void evalFot1(double& result, int iq, double factor, Args const&... args)
{
for (auto* operatorTerm : firstOrderGrdPhi)
result += operatorTerm->evalFot1(iq, args...) * factor;
}
template <class... Args>
void evalFot2(double& result, int iq, double factor, Args const&... args)
{
for (auto* operatorTerm : firstOrderGrdPsi)
result += operatorTerm->evalFot2(iq, args...) * factor;
}
template <class... Args>
void evalSot(double& result, int iq, double factor, Args const&... args)
template <class OrderTag, class E, class Quadrature>
void init(OrderTag, E const& element, Quadrature const& quad)
{
for (auto* operatorTerm : secondOrder)
result += operatorTerm->evalSot(iq, args...) * factor;
}
protected: // initialize opoerator-terms
template <class E, class Quadrature>
void initZot(E const& element, Quadrature const& quad)
{
for (auto* operatorTerm : zeroOrder)
for (auto* operatorTerm : getOperatorTerms(OrderTag{}))
operatorTerm->init(element, quad);
}
template <class E, class Quadrature>
void initFot1(E const& element, Quadrature const& quad)
template <class OrderTag, class... Args>
void eval(OrderTag, double& result, int iq, double factor, Args const&... args)
{
for (auto* operatorTerm : firstOrderGrdPhi)
operatorTerm->init(element, quad);
for (auto* operatorTerm : getOperatorTerms(OrderTag{}))
result += operatorTerm->eval(iq, args...) * factor;
}
template <class E, class Quadrature>
void initFot2(E const& element, Quadrature const& quad)
{
for (auto* operatorTerm : firstOrderGrdPsi)
operatorTerm->init(element, quad);
}
template <class E, class Quadrature>
void initSot(E const& element, Quadrature const& quad)
{
for (auto* operatorTerm : secondOrder)
operatorTerm->init(element, quad);
}
private:
std::list<OperatorTermType*>& getOperatorTerms(tag::zot) { return zeroOrder; }
std::list<OperatorTermType*>& getOperatorTerms(tag::fot_grd_phi) { return firstOrderGrdPhi; }
std::list<OperatorTermType*>& getOperatorTerms(tag::fot_grd_psi) { return firstOrderGrdPsi; }
std::list<OperatorTermType*>& getOperatorTerms(tag::sot) { return secondOrder; }
template <class LocalView>
std::size_t getElementIndex(GridView const& gridView, LocalView const& localView) const
{
......
......@@ -75,9 +75,10 @@ template <class GridView, class Element>
template <class RowView, class ColView, class ElementMatrix>
bool Operator<GridView, Element>::assemble(
Element const& element,
ElementMatrix& elementMatrix,
RowView const& rowView,
ColView const& colView,
ElementMatrix& elementMatrix,
Flag const& /*optimizationFlag*/,
double* factor)
{
double fac = factor ? *factor : 1.0;
......@@ -110,8 +111,8 @@ template <class GridView, class Element>
template <class LocalView, class ElementVector>
bool Operator<GridView, Element>::assemble(
Element const& element,
LocalView const& localView,
ElementVector& elementVector,
LocalView const& localView,
double* factor)
{
double fac = factor ? *factor : 1.0;
......
......@@ -21,6 +21,13 @@ struct Evaluate
return v * test * trial;
}
template <class ValueType>
static auto zot(tag::scalar, tag::none, ValueType const& v,
Scalar const& test)
{
return v * test;
}
template <class... Args>
static auto fot(Args...) { assert( false ); return 0; }
......@@ -46,6 +53,30 @@ struct Evaluate
}
template <class ValueType, class Gradient>
static auto fot(tag::scalar, VectorComponent comp, ValueType const& v,
Gradient const& grad_test)
{
return v * grad_test[comp.index] ;
}
template <class ValueType, class Gradient>
static auto fot(tag::vector, tag::none, ValueType const& v,
Gradient const& grad_test)
{
return (v * grad_test);
}
template <class ValueType, class Gradient>
static auto fot(tag::scalar, tag::none, ValueType const& v,
Gradient const& grad_test)
{
return v * sum(grad_test);
}
template <class... Args>
static auto sot(Args...) { assert( false ); return 0; }
......
......@@ -29,27 +29,34 @@ namespace AMDiS
// initialize operator-term on the current element
virtual void init(LocalContext const& element, QuadratureRule const& points) = 0;
virtual double eval(std::size_t iq,
Dune::FieldVector<double,1> const& test) const = 0;
virtual double eval(std::size_t iq,
Dune::FieldVector<double,dow> const& grad_test) const = 0;
// evaluate operator-term at quadrature point as zero-order term,
// with no gradients involved
virtual double evalZot(std::size_t iq,
virtual double eval(std::size_t iq,
Dune::FieldVector<double,1> const& test,
Dune::FieldVector<double,1> const trial = 1.0) const = 0;
Dune::FieldVector<double,1> const trial) const = 0;
// evaluate operator-term at quadrature point as first-order term,
// with gradients on the trial-function
virtual double evalFot1(std::size_t iq,
virtual double eval(std::size_t iq,
Dune::FieldVector<double,1> const& test,
Dune::FieldVector<double,dow> const& grad_trial) const = 0;
// evaluate operator-term at quadrature point as first-order term,
// with gradients on the test-function
virtual double evalFot2(std::size_t iq,
virtual double eval(std::size_t iq,
Dune::FieldVector<double,dow> const& grad_test,
Dune::FieldVector<double,1> const trial = 1.0) const = 0;
Dune::FieldVector<double,1> const trial) const = 0;
// evaluate operator-term at quadrature point as second-order term,
// with gradients on the trial and test-function
virtual double evalSot(std::size_t iq,