Am Montag, 13. Mai 2022, finden Wartungsarbeiten am Gitlab-Server (Update auf neue Version statt). Der Dienst wird daher am Montag für einige Zeit nicht verfügbar sein.
On Monday, May 13th 2022, the Gitlab server will be updated. The service will therefore not be accessible for some time on Monday.

Commit e653820b authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

partial derivative terms implemented

parent c64c2718
......@@ -3,6 +3,8 @@
#include <list>
#include <vector>
#include <dune/geometry/type.hh>
#include <dune/amdis/OperatorTermBase.hpp>
#include <dune/amdis/terms/TermGenerator.hpp>
......@@ -16,8 +18,8 @@ namespace AMDiS
GRD_PSI,
GRD_PHI
};
template <class MeshView>
class Operator
{
......@@ -26,10 +28,10 @@ namespace AMDiS
using ElementVector = Impl::ElementVector;
using ElementMatrix = Impl::ElementMatrix;
using IdType = typename MeshView::Grid::LocalIdSet::IdType;
public:
public:
/// Add coefficients for zero-order operator < c * u, v >.
/// The coefficient \p c must be a scalar expression.
template <class Term>
......@@ -37,7 +39,7 @@ namespace AMDiS
{
return addZOTImpl(toTerm(c));
}
template <class... Args>
static shared_ptr<Self> zot(Args&&... args)
{
......@@ -45,10 +47,10 @@ namespace AMDiS
op->addZOT(std::forward<Args>(args)...);
return op;
}
/// Add coefficients for first-order operator < psi, term * grad(phi) > or
/// < grad(psi), term * phi >, where the first corresponds to
/// Add coefficients for first-order operator < psi, term * grad(phi) > or
/// < grad(psi), term * phi >, where the first corresponds to
/// \p firstOrderType == GRD_PHI and the second one to \p firstOrderType == GRD_PSI.
/// The coefficient \p b must be a vector expression.
template <class Term>
......@@ -56,9 +58,9 @@ namespace AMDiS
{
return addFOTImpl(toTerm(b), firstOrderType);
}
/// Add coefficients for first-order operator < psi, b * d_i(phi) > or
/// < d_i(psi), b * phi >, where the first corresponds to
/// Add coefficients for first-order operator < psi, b * d_i(phi) > or
/// < d_i(psi), b * phi >, where the first corresponds to
/// \p firstOrderType == GRD_PHI and the second one to \p firstOrderType == GRD_PSI.
/// The coefficient \p b must be a scalar expression.
template <class Term, size_t I>
......@@ -66,7 +68,7 @@ namespace AMDiS
{
return addFOTImpl(toTerm(b), _i, firstOrderType);
}
template <class... Args>
static shared_ptr<Self> fot(Args&&... args)
{
......@@ -74,16 +76,16 @@ namespace AMDiS
op->addFOT(std::forward<Args>(args)...);
return op;
}
/// Add coefficients for second-order operator < grad(psi), A * grad(phi) >,
/// where \p A can be a matrix or a scalar expression.
/// where \p A can be a matrix or a scalar expression.
template <class Term>
Self& addSOT(Term const& A)
{
return addSOTImpl(toTerm(A));
}
/// Add coefficients for second-order operator < d_i(psi), A * d_j(phi) >,
/// where \p A can be a matrix or a scalar expression. The first index \p _i
/// corresponds to the derivative component of the test-function and the
......@@ -93,7 +95,7 @@ namespace AMDiS
{
return addSOTImpl(toTerm(A), _i, _j);
}
template <class... Args>
static shared_ptr<Self> sot(Args&&... args)
{
......@@ -101,110 +103,111 @@ namespace AMDiS
op->addSOT(std::forward<Args>(args)...);
return op;
}
/// Calls \ref zot(), \ref for() or \ref sot(), depending on template
/// Calls \ref zot(), \ref for() or \ref sot(), depending on template
/// parameter \p Order.
template <size_t Order, class... Args>
static shared_ptr<Self> create(Args&&... args)
{
return create(index_<Order>{}, std::forward<Args>(args)...);
}
/// Extract the polynomial degree from \p rowFeSpace and \p colFeSpace.
template <class RowFeSpace, class ColFeSpace>
void init(RowFeSpace const& rowFeSpace,
ColFeSpace const& colFeSpace);
/// Calculates the needed quadrature degree for the given term-order \p order.
/// This takes into account the polynomial degree of trial and test functions
/// and the polynomial degree of the coefficient functions
int getQuadratureDegree(int order, FirstOrderType firstOrderType = GRD_PHI);
template <class Element>
int getQuadratureDegree(Element const& element, int order, FirstOrderType firstOrderType = GRD_PHI);
template <class RowView, class ColView>
bool getElementMatrix(RowView const& rowView,
ColView const& colView,
ElementMatrix& elementMatrix,
double* factor = NULL);
template <class RowView>
bool getElementVector(RowView const& rowView,
ElementVector& elementVector,
double* factor = NULL);
protected:
template <class RowView, class ColView>
void assembleZeroOrderTerms(RowView const& rowView,
ColView const& colView,
ElementMatrix& elementMatrix);
template <class RowView>
void assembleZeroOrderTerms(RowView const& rowView,
ElementVector& elementVector);
template <class RowView, class ColView>
void assembleFirstOrderTermsGrdPhi(RowView const& rowView,
ColView const& colView,
ElementMatrix& elementMatrix);
template <class RowView, class ColView>
void assembleFirstOrderTermsGrdPsi(RowView const& rowView,
ColView const& colView,
ElementMatrix& elementMatrix);
template <class RowView>
void assembleFirstOrderTermsGrdPsi(RowView const& rowView,
ElementVector& elementVector);
template <class RowView, class ColView>
void assembleSecondOrderTerms(RowView const& rowView,
ColView const& colView,
ElementMatrix& elementMatrix);
private:
template <class Term>
Self& addZOTImpl(Term const& term);
template <class Term>
Self& addFOTImpl(Term const& term, FirstOrderType firstOrderType);
template <class Term, size_t I>
Self& addFOTImpl(Term const& term, const index_<I>,
Self& addFOTImpl(Term const& term, const index_<I>,
FirstOrderType firstOrderType);
template <class Term>
Self& addSOTImpl(Term const& term);
template <class Term, size_t I, size_t J>
Self& addSOTImpl(Term const& term, const index_<I>, const index_<J>);
template <class... Args>
static shared_ptr<Self> create(index_<0>, Args&&... args)
{
return zot(std::forward<Args>(args)...);
}
template <class... Args>
static shared_ptr<Self> create(index_<1>, Args&&... args)
{
return fot(std::forward<Args>(args)...);
}
template <class... Args>
static shared_ptr<Self> create(index_<2>, Args&&... args)
{
return sot(std::forward<Args>(args)...);
}
private:
template <class LocalView>
IdType getElementId(LocalView const& localView);
private:
/// List of all second order terms
std::list<OperatorTermType*> secondOrder;
......@@ -217,17 +220,17 @@ namespace AMDiS
/// List of all zero order terms
std::list<OperatorTermType*> zeroOrder;
int psiDegree = 1;
int phiDegree = 1;
IdType lastMatrixId = 0;
IdType lastVectorId = 0;
ElementMatrix cachedElementMatrix;
ElementVector cachedElementVector;
};
} // end namespace AMDiS
#include "Operator.inc.hpp"
......@@ -8,29 +8,33 @@ namespace AMDiS
ColFeSpace const& colFeSpace)
{
AMDIS_FUNCNAME("Operator::init()");
using IdType = typename Operator<MeshView>::IdType;
lastMatrixId = std::numeric_limits<IdType>::max();
lastVectorId = std::numeric_limits<IdType>::max();
// auto const& rowFE = rowView.tree().finiteElement();
// auto const& colFE = colView.tree().finiteElement();
// psiDegree = rowFE.localBasis().order();
// phiDegree = colFE.localBasis().order();
psiDegree = getPolynomialDegree<RowFeSpace>;
phiDegree = getPolynomialDegree<ColFeSpace>;
// TODO: calc quadrature degree here.
}
template <class MeshView>
int Operator<MeshView>::getQuadratureDegree(int order, FirstOrderType firstOrderType)
template <class Element>
int Operator<MeshView>::getQuadratureDegree(Element const& element, int order, FirstOrderType firstOrderType)
{
std::list<OperatorTermType*>* terms = NULL;
auto const& t = element.type();
auto geometry = element.geometry();
switch(order)
{
case 0:
......@@ -49,24 +53,31 @@ namespace AMDiS
int maxTermDegree = 0;
for (OperatorTermType* term : *terms)
maxTermDegree = std::max(maxTermDegree, term->getDegree());
maxTermDegree = std::max(maxTermDegree, term->getDegree(t));
int degree = psiDegree + phiDegree + maxTermDegree;
if (t.isSimplex())
degree -= order;
if (!geometry.affine())
degree += 1; // oder += (order+1)
return psiDegree + phiDegree - order + maxTermDegree;
return degree;
}
template <class MeshView>
template <class LocalView>
typename Operator<MeshView>::IdType
typename Operator<MeshView>::IdType
Operator<MeshView>::getElementId(LocalView const& localView)
{
auto const& element = localView.element();
auto const& grid = localView.globalBasis().gridView().grid();
auto const& idSet = grid.localIdSet();
return idSet.id(element);
}
template <class MeshView>
template <class RowView, class ColView>
......@@ -74,28 +85,28 @@ namespace AMDiS
ColView const& colView,
ElementMatrix& elementMatrix,
double* factor)
{
{
AMDIS_FUNCNAME("Operator::getElementMatrix()");
double fac = factor ? *factor : 1.0;
if (fac == 0.0)
return false;
const auto nRows = rowView.tree().finiteElement().size();
const auto nCols = colView.tree().finiteElement().size();
auto currentId = getElementId(rowView);
bool useCachedMatrix = (lastMatrixId == currentId
&& num_rows(cachedElementMatrix) == nRows
&& num_rows(cachedElementMatrix) == nRows
&& num_cols(cachedElementMatrix) == nCols);
bool assign = true;
if (!useCachedMatrix) {
cachedElementMatrix.change_dim(nRows, nCols);
set_to_zero(cachedElementMatrix);
if (!zeroOrder.empty())
assembleZeroOrderTerms(rowView, colView, cachedElementMatrix);
if (!firstOrderGrdPhi.empty())
......@@ -104,63 +115,63 @@ namespace AMDiS
assembleFirstOrderTermsGrdPsi(rowView, colView, cachedElementMatrix);
if (!secondOrder.empty())
assembleSecondOrderTerms(rowView, colView, cachedElementMatrix);
assign = !zeroOrder.empty() || !firstOrderGrdPhi.empty() ||
!firstOrderGrdPsi.empty() || !secondOrder.empty();
}
}degree
if (assign)
elementMatrix += fac * cachedElementMatrix;
lastMatrixId = currentId;
return true;
}
template <class MeshView>
template <class RowView>
bool Operator<MeshView>::getElementVector(RowView const& rowView,
ElementVector& elementVector,
double* factor)
{
{
AMDIS_FUNCNAME("Operator::getElementVector()");
double fac = factor ? *factor : 1.0;
if (fac == 0.0)
return false;
AMDIS_TEST_EXIT( firstOrderGrdPhi.empty() && secondOrder.empty(),
"Derivatives on ansatz-functions not allowed on the vector-side!");
const auto nRows = rowView.tree().finiteElement().size();
const auto nRows = rowView.tree().finiteElement().size();
auto currentId = getElementId(rowView);
bool useCachedVector = (lastVectorId == currentId && size(cachedElementVector) == nRows);
bool assign = true;
if (!useCachedVector) {
if (!useCachedVector) {
cachedElementVector.change_dim(nRows);
set_to_zero(cachedElementVector);
if (!zeroOrder.empty())
assembleZeroOrderTerms(rowView, cachedElementVector);
if (!firstOrderGrdPsi.empty())
assembleFirstOrderTermsGrdPsi(rowView, cachedElementVector);
assign = !zeroOrder.empty() || !firstOrderGrdPsi.empty();
}
if (assign)
elementVector += fac * cachedElementVector;
lastVectorId = currentId;
return true;
}
template <class MeshView>
template <class RowView, class ColView>
void Operator<MeshView>::assembleZeroOrderTerms(RowView const& rowView,
......@@ -168,31 +179,31 @@ namespace AMDiS
ElementMatrix& elementMatrix)
{
AMDIS_FUNCNAME("Operator::assembleZeroOrderTerms(elementMatrix)");
using Element = typename RowView::Element;
auto element = rowView.element();
const int dim = Element::dimension;
auto geometry = element.geometry();
auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis();
auto const& colLocalBasis = colView.tree().finiteElement().localBasis();
int order = getQuadratureDegree(0);
int order = getQuadratureDegree(element, 0);
auto const& quad = Dune::QuadratureRules<double, dim>::rule(element.type(), order);
for (auto* operatorTerm : zeroOrder)
operatorTerm->init(element, quad);
for (size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
const Dune::FieldVector<double,dim>& quadPos = quad[iq].position();
// The multiplicative factor in the integral transformation formula
const double factor = geometry.integrationElement(quadPos) * quad[iq].weight();
std::vector<Dune::FieldVector<double,1> > rowShapeValues, colShapeValues;
rowLocalBasis.evaluateFunction(quadPos, rowShapeValues);
if (psiDegree == phiDegree)
colShapeValues = rowShapeValues;
else
......@@ -203,44 +214,42 @@ namespace AMDiS
const int local_i = rowView.tree().localIndex(i);
const int local_j = colView.tree().localIndex(j);
for (auto* operatorTerm : zeroOrder)
elementMatrix[local_i][local_j]
elementMatrix[local_i][local_j]
+= operatorTerm->evalZot(iq, rowShapeValues[i], colShapeValues[j]) * factor;
}
}
}
}
template <class MeshView>
template <class RowView>
void Operator<MeshView>::assembleZeroOrderTerms(RowView const& rowView,
ElementVector& elementvector)
{
AMDIS_FUNCNAME("Operator::assembleZeroOrderTerms(elementvector)");
using Element = typename RowView::Element;
auto element = rowView.element();
const int dim = Element::dimension;
auto geometry = element.geometry();
auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis();
int order = getQuadratureDegree(0);
int order = getQuadratureDegree(element, 0);
auto const& quad = Dune::QuadratureRules<double, dim>::rule(element.type(), order);
for (auto* operatorTerm : zeroOrder)
operatorTerm->init(element, quad);
for (size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
const Dune::FieldVector<double,dim>& quadPos = quad[iq].position();
// The multiplicative factor in the integral transformation formula
const double factor = geometry.integrationElement(quadPos) * quad[iq].weight();
std::vector<Dune::FieldVector<double,1> > rowShapeValues;
rowLocalBasis.evaluateFunction(quadPos, rowShapeValues);
......@@ -251,7 +260,7 @@ namespace AMDiS
}
}
}
template <class MeshView>
template <class RowView, class ColView>
......@@ -260,23 +269,21 @@ namespace AMDiS
ElementMatrix& elementMatrix)
{
AMDIS_FUNCNAME("Operator::assembleFirstOrderTermsGrdPhi(elementMatrix)");
using Element = typename RowView::Element;
auto element = rowView.element();
auto geometry = element.geometry();
const int dim = Element::dimension;
auto const& rowLocalBasis = rowView.tree().finiteElement().localBasis();
auto const& colLocalBasis = colView.tree().finiteElement().localBasis();
int order = getQuadratureDegree(2);
int order = getQuadratureDegree(element, 1, GRD_PHI);
auto const& quad = Dune::QuadratureRules<double, dim>::rule(element.type(), order);
for (auto* operatorTerm : firstOrderGrdPhi)
operatorTerm->init(element, quad);
for (size_t iq = 0; iq < quad.size(); ++iq) {
// Position of the current quadrature point in the reference element
const Dune::FieldVector<double,dim>& quadPos = quad[iq].position();
......@@ -289,7 +296,7 @@ namespace AMDiS
std::vector<Dune::FieldVector<double,1> > rowShapeValues;
rowLocalBasis.evaluateFunction(quadPos, rowShapeValues);
// The gradients of the shape functions on the reference element
std::vector<Dune::FieldMatrix<double,1,dim> > colReferenceGradients;
colLocalBasis.evaluateJacobian(quadPos, colReferenceGradients);
......@@ -305,13 +312,13 @@ namespace AMDiS
const int local_i = rowView.tree().localIndex(i);
const int local_j = colView.tree().localIndex(j);
for (auto* operatorTerm : firstOrderGrdPhi)
elementMatrix[local_i][local_j]
elementMatrix[local_i][local_j]
+= operatorTerm->evalFot1(iq, rowShapeValues[i], colGradients[j]) * factor;
}
}
}
}
template <class MeshView>
template <class RowView, class ColView>
......@@ -320,21 +327,21 @@ namespace AMDiS