11#ifndef LF_LOCCOMPELLBVP
12#define LF_LOCCOMPELLBVP
19#include <lf/mesh/utils/utils.h>
20#include <lf/quad/quad.h>
24#include "precomputed_scalar_reference_finite_element.h"
94 Eigen::Matrix<SCALAR, Eigen::Dynamic, 1>() +
96 Eigen::Matrix<SCALAR, Eigen::Dynamic, 1>())
::Scalar;
97 using ElemMat = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
127 DIFF_COEFF alpha, REACTION_COEFF gamma);
146 DIFF_COEFF alpha, REACTION_COEFF gamma,
155 virtual
bool isActive(const
lf::mesh::Entity & ) {
return true; }
188 std::array<PrecomputedScalarReferenceFiniteElement<SCALAR>, 5>
fe_precomp_;
196template <
class PTR,
class DIFF_COEFF,
class REACTION_COEFF>
198 REACTION_COEFF gamma)
200 typename PTR::element_type::Scalar, DIFF_COEFF, REACTION_COEFF>;
202template <
class PTR,
class DIFF_COEFF,
class REACTION_COEFF>
204 PTR fe_space, DIFF_COEFF alpha, REACTION_COEFF gamma,
205 std::map<lf::base::RefEl, lf::quad::QuadRule>)
207 typename PTR::element_type::Scalar, DIFF_COEFF, REACTION_COEFF>;
215 DIFF_COEFF alpha, REACTION_COEFF gamma)
216 : alpha_(std::move(alpha)), gamma_(std::move(gamma)), fe_precomp_() {
218 auto fe = fe_space->ShapeFunctionLayout(ref_el);
239 DIFF_COEFF alpha, REACTION_COEFF gamma,
241 : alpha_(std::move(alpha)), gamma_(std::move(gamma)), fe_precomp_() {
244 auto fe = fe_space->ShapeFunctionLayout(ref_el);
251 auto qr_coll_ptr = qr_collection.find(ref_el);
252 if (qr_coll_ptr != qr_collection.end()) {
255 LF_ASSERT_MSG(qr.
RefEl() == ref_el,
256 "qr.RefEl() = " << qr.
RefEl() <<
" <-> " << ref_el);
269 SCALAR, DIFF_COEFF, REACTION_COEFF>::ElemMat
277 fe_precomp_[ref_el.Id()];
282 std::stringstream temp;
283 temp <<
"No local shape function information or no quadrature rule for "
284 "reference element type "
291 LF_ASSERT_MSG(geo_ptr !=
nullptr,
"Invalid geometry!");
292 LF_ASSERT_MSG((geo_ptr->
DimLocal() == 2),
293 "Only 2D implementation available!");
295 "{}, shape = \n{}", ref_el,
296 geo_ptr->
Global(ref_el.NodeCoords()));
301 const Eigen::VectorXd determinants(
305 "Mismatch " << determinants.size() <<
" <-> " << pfe.
Qr().
NumPoints());
307 const Eigen::MatrixXd JinvT(
311 "Mismatch " << JinvT.cols() <<
" <-> " << 2 * pfe.
Qr().
NumPoints());
312 LF_ASSERT_MSG(JinvT.rows() == world_dim,
313 "Mismatch " << JinvT.rows() <<
" <-> " << world_dim);
316 auto alphaval = alpha_(cell, pfe.
Qr().
Points());
317 auto gammaval = gamma_(cell, pfe.
Qr().
Points());
325 const double w = pfe.
Qr().
Weights()[k] * determinants[k];
328 JinvT.block(0, 2 *
static_cast<Eigen::Index
>(k), world_dim, 2) *
330 .block(0, 2 * k, mat.rows(), 2)
333 const auto alpha_trf_grad(alphaval[k] * trf_grad);
334 mat += w * (trf_grad.adjoint() * alpha_trf_grad +
368 typename EDGESELECTOR>
373 decltype(
static_cast<SCALAR
>(0) *
375 using ElemMat = Eigen::Matrix<scalar_t, Eigen::Dynamic, Eigen::Dynamic>;
398 EDGESELECTOR edge_selector = base::PredicateTrue{})
399 :
gamma_(std::move(gamma)),
403 LF_ASSERT_MSG(fe !=
nullptr,
"No shape functions specified for edges");
424 :
gamma_(std::move(gamma)),
428 LF_ASSERT_MSG(fe !=
nullptr,
"No shape functions specified for edges");
430 "Quadrature rule not meant for EDGE entities!");
443 "Wrong type for an edge");
499 "Edge must be of segment type");
502 LF_ASSERT_MSG(geo_ptr !=
nullptr,
"Invalid geometry!");
505 const Eigen::VectorXd determinants(
507 LF_ASSERT_MSG(determinants.size() == fe_precomp_.Qr().NumPoints(),
508 "Mismatch " << determinants.size() <<
" <-> "
509 << fe_precomp_.Qr().NumPoints());
512 ElemMat mat(fe_precomp_.NumRefShapeFunctions(),
513 fe_precomp_.NumRefShapeFunctions());
516 auto gammaval = gamma_(edge, fe_precomp_.Qr().Points());
519 for (
long k = 0; k < determinants.size(); ++k) {
523 (fe_precomp_.Qr().Weights()[k] * determinants[k]) * gammaval[k];
524 mat += ((fe_precomp_.PrecompReferenceShapeFunctions().col(k)) *
525 (fe_precomp_.PrecompReferenceShapeFunctions().col(k).adjoint())) *
562template <base::Scalar SCALAR, mesh::utils::MeshFunction MESH_FUNCTION>
567 decltype(
static_cast<SCALAR
>(0) *
570 using ElemVec = Eigen::Matrix<scalar_t, Eigen::Dynamic, 1>;
607 virtual
bool isActive(const
lf::mesh::Entity & ) {
return true; }
623 std::array<PrecomputedScalarReferenceFiniteElement<SCALAR>, 5>
fe_precomp_;
632template <
class PTR,
class MESH_FUNCTION>
638template <base::Scalar SCALAR, mesh::utils::MeshFunction MESH_FUNCTION>
645 auto fe = fe_space->ShapeFunctionLayout(ref_el);
658template <base::Scalar SCALAR, mesh::utils::MeshFunction MESH_FUNCTION>
665 auto fe = fe_space->ShapeFunctionLayout(ref_el);
669 auto qr_coll_ptr = qr_collection.find(ref_el);
670 if (qr_coll_ptr != qr_collection.end()) {
673 LF_ASSERT_MSG(qr.
RefEl() == ref_el,
674 "qr.RefEl() = " << qr.
RefEl() <<
" <-> " << ref_el);
682 LF_ASSERT_MSG(
false,
"Quadrature rule missing for " << ref_el);
691template <base::Scalar SCALAR, mesh::utils::MeshFunction MESH_FUNCTION>
701 auto &pfe = fe_precomp_[ref_el.Id()];
705 "No local shape function information for entity type " << ref_el);
709 LF_ASSERT_MSG(geo_ptr !=
nullptr,
"Invalid geometry!");
710 LF_ASSERT_MSG((geo_ptr->
DimLocal() == 2),
711 "Only 2D implementation available!");
713 "{}, shape = \n{}", ref_el,
714 geo_ptr->
Global(ref_el.NodeCoords()));
717 const Eigen::VectorXd determinants(
720 determinants.size() == pfe.Qr().NumPoints(),
721 "Mismatch " << determinants.size() <<
" <-> " << pfe.Qr().NumPoints());
723 "LOCVEC({}): Metric factors :\n{}", ref_el,
724 determinants.transpose());
727 ElemVec vec(pfe.NumRefShapeFunctions());
730 auto fval = f_(cell, pfe.Qr().Points());
733 for (
long k = 0; k < determinants.size(); ++k) {
735 "LOCVEC: [{}] -> [weight = {}]",
736 pfe.Qr().Points().transpose(), pfe.Qr().Weights()[k]);
738 vec += (pfe.Qr().Weights()[k] * determinants[k] * fval[k]) *
739 pfe.PrecompReferenceShapeFunctions().col(k).conjugate();
789 decltype(
static_cast<SCALAR
>(0) *
791 using ElemVec = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;
816 EDGESELECTOR edge_sel = base::PredicateTrue{})
819 LF_ASSERT_MSG(fe !=
nullptr,
"No shape functions specified for edges");
839 LF_ASSERT_MSG(fe !=
nullptr,
"No shape functions specified for edges");
841 "Quadrature rule not meant for EDGE entities!");
873template <
class PTR,
class FUNCTOR,
class EDGE
SELECTOR = base::PredicateTrue>
890 "Edge must be of segment type");
893 LF_ASSERT_MSG(geo_ptr !=
nullptr,
"Invalid geometry!");
896 const Eigen::MatrixXd mapped_qpts(geo_ptr->
Global(pfe_.Qr().Points()));
898 mapped_qpts.cols() == pfe_.Qr().NumPoints(),
899 "Mismatch " << mapped_qpts.cols() <<
" <-> " << pfe_.Qr().NumPoints());
902 const Eigen::VectorXd determinants(
905 determinants.size() == pfe_.Qr().NumPoints(),
906 "Mismatch " << determinants.size() <<
" <-> " << pfe_.Qr().NumPoints());
909 ElemVec vec(pfe_.NumRefShapeFunctions());
912 auto g_vals = g_(edge, pfe_.Qr().Points());
917 const auto w = (pfe_.Qr().Weights()[k] * determinants[k]) * g_vals[k];
918 vec += pfe_.PrecompReferenceShapeFunctions().col(k).conjugate() * w;
A simple, general purpose exception class that is thrown by LehrFEM++ if something is wrong.
A Function Object that can be invoked with any arguments and that always returns the value true.
Represents a reference element with all its properties.
static constexpr RefEl kSegment()
Returns the (1-dimensional) reference segment.
static constexpr RefEl kTria()
Returns the reference triangle.
static constexpr RefEl kQuad()
Returns the reference quadrilateral.
Interface class for shape information on a mesh cell in the spirit of parametric finite element metho...
virtual Eigen::MatrixXd Global(const Eigen::MatrixXd &local) const =0
Map a number of points in local coordinates into the global coordinate system.
virtual dim_t DimLocal() const =0
Dimension of the domain of this mapping.
virtual dim_t DimGlobal() const =0
Dimension of the image of this mapping.
virtual Eigen::MatrixXd JacobianInverseGramian(const Eigen::MatrixXd &local) const =0
Evaluate the Jacobian * Inverse Gramian ( ) simultaneously at numPoints.
virtual Eigen::VectorXd IntegrationElement(const Eigen::MatrixXd &local) const =0
The integration element (factor appearing in integral transformation formula, see below) at number of...
Interface class representing a topological entity in a cellular complex
virtual const geometry::Geometry * Geometry() const =0
Describes the geometry of this entity.
virtual base::RefEl RefEl() const =0
Describes the reference element type of this entity.
Represents a Quadrature Rule over one of the Reference Elements.
const Eigen::VectorXd & Weights() const
All quadrature weights as a vector.
base::RefEl RefEl() const
The reference element over which this QuadRule integrates.
const Eigen::MatrixXd & Points() const
All quadrature points as column vectors.
base::size_type NumPoints() const
Return the total number of quadrature points (num of columns of points/weights)
Quadrature-based computation of local mass matrix for an edge.
MassEdgeMatrixProvider(std::shared_ptr< const UniformScalarFESpace< SCALAR > > fe_space, COEFF gamma, lf::quad::QuadRule quadrule, EDGESELECTOR edge_selector=base::PredicateTrue{})
Constructor performing cell-independent initializations.
bool isActive(const lf::mesh::Entity &edge)
If true, then an edge is taken into account during assembly.
MassEdgeMatrixProvider(MassEdgeMatrixProvider &&) noexcept=default
decltype(static_cast< SCALAR >(0) * static_cast< mesh::utils::MeshFunctionReturnType< COEFF > >(0)) scalar_t
Scalar type of the element matrix.
MassEdgeMatrixProvider(const MassEdgeMatrixProvider &)=delete
ElemMat Eval(const lf::mesh::Entity &edge)
actual computation of edge mass matrix
Eigen::Matrix< scalar_t, Eigen::Dynamic, Eigen::Dynamic > ElemMat
PrecomputedScalarReferenceFiniteElement< SCALAR > fe_precomp_
virtual ~MassEdgeMatrixProvider()=default
Helper class which stores a ScalarReferenceFiniteElement with precomputed values at the nodes of a qu...
bool isInitialized() const
Tells initialization status of object.
size_type NumRefShapeFunctions() const override
Total number of reference shape functions associated with the reference cell.
const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > & PrecompReferenceShapeFunctions() const
Value of EvalReferenceShapeFunctions(Qr().Points())
const quad::QuadRule & Qr() const
Return the Quadrature rule at which the shape functions (and their gradients) have been precomputed.
const Eigen::Matrix< SCALAR, Eigen::Dynamic, Eigen::Dynamic > & PrecompGradientsReferenceShapeFunctions() const
Value of EvalGradientsReferenceShapeFunctions(Qr().Points())
Class for local quadrature based computations for Lagrangian finite elements and second-order scalar ...
virtual ~ReactionDiffusionElementMatrixProvider()=default
virtual bool isActive(const lf::mesh::Entity &)
All cells are considered active in the default implementation.
std::array< PrecomputedScalarReferenceFiniteElement< SCALAR >, 5 > fe_precomp_
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > ElemMat
typename decltype(mesh::utils::MeshFunctionReturnType< DIFF_COEFF >() * Eigen::Matrix< SCALAR, Eigen::Dynamic, 1 >()+ mesh::utils::MeshFunctionReturnType< REACTION_COEFF >() * Eigen::Matrix< SCALAR, Eigen::Dynamic, 1 >())::Scalar Scalar
type of returned element matrix
ReactionDiffusionElementMatrixProvider(const ReactionDiffusionElementMatrixProvider &)=delete
standard constructors
ElemMat Eval(const lf::mesh::Entity &cell)
main routine for the computation of element matrices
ReactionDiffusionElementMatrixProvider(ReactionDiffusionElementMatrixProvider &&) noexcept=default
Local edge contributions to element vector.
ScalarLoadEdgeVectorProvider(const ScalarLoadEdgeVectorProvider &)=delete
virtual bool isActive(const lf::mesh::Entity &cell)
Default implement: all edges are active.
ScalarLoadEdgeVectorProvider(std::shared_ptr< const UniformScalarFESpace< SCALAR > > fe_space, FUNCTOR g, lf::quad::QuadRule quadrule, EDGESELECTOR edge_sel=base::PredicateTrue{})
Constructor, performs precomputations.
PrecomputedScalarReferenceFiniteElement< SCALAR > pfe_
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > ElemVec
virtual ~ScalarLoadEdgeVectorProvider()=default
ElemVec Eval(const lf::mesh::Entity &edge)
ScalarLoadEdgeVectorProvider(ScalarLoadEdgeVectorProvider &&) noexcept=default
decltype(static_cast< SCALAR >(0) * static_cast< mesh::utils::MeshFunctionReturnType< FUNCTOR > >(0)) Scalar
Local computation of general element (load) vector for scalar finite elements; volume contributions o...
Eigen::Matrix< scalar_t, Eigen::Dynamic, 1 > ElemVec
decltype(static_cast< SCALAR >(0) * static_cast< mesh::utils::MeshFunctionReturnType< MESH_FUNCTION > >( 0)) scalar_t
Scalar type of the element matrix.
ScalarLoadElementVectorProvider(const ScalarLoadElementVectorProvider &)=delete
ScalarLoadElementVectorProvider(ScalarLoadElementVectorProvider &&) noexcept=default
std::array< PrecomputedScalarReferenceFiniteElement< SCALAR >, 5 > fe_precomp_
ElemVec Eval(const lf::mesh::Entity &cell)
virtual ~ScalarLoadElementVectorProvider()=default
MESH_FUNCTION f_
An object providing the source function.
virtual bool isActive(const lf::mesh::Entity &)
Default implement: all cells are active.
Concept which is fulfilled if a type T is a scalar type, i.e. if it is a "field" in the mathematical ...
A MeshFunction is a function object that can be evaluated at any point on the mesh.
unsigned int size_type
general type for variables related to size of arrays
internal::VectorElement_t< internal::MeshFunctionReturnType_t< R > > MeshFunctionReturnType
Determine the type of objects returned by a MeshFunction.
QuadRule make_QuadRule(base::RefEl ref_el, unsigned degree)
Returns a QuadRule object for the given Reference Element and Degree.
Collects data structures and algorithms designed for scalar finite element methods primarily meant fo...
ScalarLoadElementVectorProvider(PTR fe_space, MESH_FUNCTION mf) -> ScalarLoadElementVectorProvider< typename PTR::element_type::Scalar, MESH_FUNCTION >
std::map< lf::base::RefEl, lf::quad::QuadRule > quad_rule_collection_t
Auxiliary data structure for passing collections of quadrature rules.
std::shared_ptr< spdlog::logger > & MassEdgeMatrixProviderLogger()
logger for MassEdgeMatrixProvider
std::shared_ptr< spdlog::logger > & ScalarLoadElementVectorProviderLogger()
logger used by ScalarLoadElementVectorProvider
lf::assemble::dim_t dim_t
std::shared_ptr< spdlog::logger > & ScalarLoadEdgeVectorProviderLogger()
logger for ScalarLoadEdgeVectorProvider class template.
ReactionDiffusionElementMatrixProvider(PTR fe_space, DIFF_COEFF alpha, REACTION_COEFF gamma) -> ReactionDiffusionElementMatrixProvider< typename PTR::element_type::Scalar, DIFF_COEFF, REACTION_COEFF >
ScalarLoadEdgeVectorProvider(PTR, FUNCTOR, EDGESELECTOR=base::PredicateTrue{}) -> ScalarLoadEdgeVectorProvider< typename PTR::element_type::Scalar, FUNCTOR, EDGESELECTOR >
MassEdgeMatrixProvider(PTR, COEFF coeff, EDGESELECTOR edge_predicate=base::PredicateTrue{}) -> MassEdgeMatrixProvider< typename PTR::element_type::Scalar, COEFF, EDGESELECTOR >
std::shared_ptr< spdlog::logger > & ReactionDiffusionElementMatrixProviderLogger()
logger for ReactionDiffusionElementMatrixProvider