Commit 786ec0e9 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Gradient of the normal field

parent 8a9a9ab4
#include <vector>
#include <dune/common/fmatrix.hh>
namespace Dune {
template <class Geometry, class LFE>
class NormalGradient
/// type of the local coordinates in the geometry
using LocalCoordinate = typename Geometry::LocalCoordinates;
/// type of the global coordinates in the geometry
using GlobalCoordinate = typename Geometry::GlobalCoordinate;
/// type of the `J^{-T}` of the geometry
using JacobianInverseTransposed = typename Geometry::JacobianInverseTransposed;
/// type of the local finite-element
using FiniteElement = LFE;
/// traits types for the local basis
using BasisTraits = typename LFE::Traits::LocalBasisType::Traits;
/// type of the extended Weingarten map
using GlobalJacobian = FieldMatrix<typename Geometry::ctype, Geometry::coorddimension, Geometry::coorddimension>;
NormalGradient (const Geometry& geometry, const FiniteElement& localFE)
: geometry_(geometry)
, localFE_(localFE)
// create local discrete function of normal vectors by interpolation of the geometry normal
[&](const LocalCoordinate& local) { return geometry_.normalDirection(local); },
GlobalJacobian operator() (const LocalCoordinate& local,
const JacobianInverseTransposed& jiT) const
// Interpolated normal vector evaluated at local coordinate
localFE_.localBasis().evaluateFunction(local, nShapeValues_);
GlobalCoordinate nh(0);
for (std::size_t j = 0; j < nShapeValues_.size(); ++j)
nh.axpy(nShapeValues_[j], nCoefficients_[j]);
auto nh_nrm = nh.two_norm();
nh /= nh_nrm;
// P = I - n x n
GlobalJacobian Ph;
for (int r = 0; r < Geometry::coorddimension; ++r)
for (int s = 0; s < Geometry::coorddimension; ++s)
Ph[r][s] = (r == s ? 1 : 0) - nh[r]*nh[s];
// Compute the shape function gradients on the real element
localFE_.localBasis().evaluateJacobian(local, nShapeGradients_);
for (std::size_t j = 0; j < nGradients_.size(); ++j)[j][0], nGradients_[j]);
// Normal gradient evaluated at local coordinate
GlobalJacobian H(0);
for (std::size_t j = 0; j < nGradients_.size(); ++j)
for (int r = 0; r < Geometry::coorddimension; ++r)
for (int s = 0; s < Geometry::coorddimension; ++s)
H[r][s] += nGradients_[j][s] * nCoefficients_[j][r];
H /= nh_nrm;
return H;
GlobalJacobian operator() (const LocalCoordinate& local) const
return (*this)(local, geometry_.jacobianInverseTransposed(local));
const Geometry& geometry_;
FiniteElement localFE_;
std::vector<GlobalCoordinate> nCoefficients_;
mutable std::vector<GlobalCoordinate> nGradients_;
mutable std::vector<typename BasisTraits::RangeType> nShapeValues_;
mutable std::vector<typename BasisTraits::JacobianType> nShapeGradients_;
template <class Geometry, class LFE>
NormalGradient<Geometry,LFE> normalGradient (const Geometry& geometry, const LFE& localFE)
return NormalGradient<Geometry,LFE>{geometry,localFE};
} // end namespace Dune
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment