32 template <
class CG,
class RN,
class CN,
class Quad,
class LocalFct,
class Mat>
33 void assemble(CG
const& contextGeo, RN
const& rowNode, CN
const& colNode,
34 Quad
const& quad, LocalFct
const& localFct, Mat& elementMatrix)
const
36 using expr_value_type =
typename LocalFct::Range;
37 static_assert(static_size_v<expr_value_type> == 1 ||
38 (static_num_rows_v<expr_value_type> == CG::dow &&
39 static_num_cols_v<expr_value_type> == CG::dow),
40 "Expression must be of scalar or matrix type.");
41 static_assert(Dune::TypeTree::Concept::LeafTreeNode<RN> && Dune::TypeTree::Concept::LeafTreeNode<CN>,
42 "Operator can be applied to Leaf-Nodes only.");
44 const bool sameFEType = std::is_same_v<FiniteElementType_t<RN>, FiniteElementType_t<CN>>;
45 using Category = ValueCategory_t<typename LocalFct::Range>;
47 if constexpr (sameFEType) {
48 const bool sameNode = rowNode.treeIndex() == colNode.treeIndex();
50 return getElementMatrixOptimized(contextGeo, quad, rowNode, colNode, localFct, elementMatrix, Category{});
52 const bool sameFEsize = rowNode.finiteElement().size() == colNode.finiteElement().size();
54 return getElementMatrixStandard(contextGeo, quad, rowNode, colNode, localFct, elementMatrix);
58 error_exit(
"Not implemented: currently only the implementation for equal fespaces available");
63 template <
class CG,
class QR,
class RN,
class CN,
class LocalFct,
class Mat>
64 void getElementMatrixStandard(CG
const& contextGeo, QR
const& quad,
65 RN
const& rowNode, CN
const& colNode,
66 LocalFct
const& localFct, Mat& elementMatrix)
const
68 std::size_t size = rowNode.size();
70 using RangeFieldType =
typename RN::LocalBasis::Traits::RangeFieldType;
71 using WorldVector = Dune::FieldVector<RangeFieldType,CG::dow>;
72 std::vector<WorldVector> gradients;
74 for (
auto const& qp : quad) {
76 auto&& local = contextGeo.coordinateInElement(qp.position());
79 const auto jacobian = contextGeo.elementGeometry().jacobianInverseTransposed(local);
82 const auto factor = contextGeo.integrationElement(qp.position()) * qp.weight();
83 const auto exprValue = localFct(local);
86 auto const& shapeGradients = rowNode.localBasisJacobiansAt(local);
89 gradients.resize(shapeGradients.size());
91 for (std::size_t i = 0; i < gradients.size(); ++i)
92 jacobian.mv(shapeGradients[i][0], gradients[i]);
94 for (std::size_t i = 0; i < size; ++i) {
95 const auto local_i = rowNode.localIndex(i);
96 for (std::size_t j = 0; j < size; ++j) {
97 const auto local_j = colNode.localIndex(j);
98 elementMatrix[local_i][local_j] += eval(exprValue, factor, gradients[i], gradients[j]);
104 template <
class CG,
class QR,
class RN,
class CN,
class LocalFct,
class Mat>
105 void getElementMatrixOptimized(CG
const& contextGeo, QR
const& quad,
106 RN
const& node, CN
const& ,
107 LocalFct
const& localFct, Mat& elementMatrix,
tag::scalar)
const
109 std::size_t size = node.size();
111 using RangeFieldType =
typename RN::LocalBasis::Traits::RangeFieldType;
112 using WorldVector = Dune::FieldVector<RangeFieldType,CG::dow>;
113 std::vector<WorldVector> gradients;
115 for (
auto const& qp : quad) {
117 auto&& local = contextGeo.coordinateInElement(qp.position());
120 const auto jacobian = contextGeo.elementGeometry().jacobianInverseTransposed(local);
123 const auto factor = localFct(local) * contextGeo.integrationElement(qp.position()) * qp.weight();
126 auto const& shapeGradients = node.localBasisJacobiansAt(local);
129 gradients.resize(shapeGradients.size());
130 for (std::size_t i = 0; i < gradients.size(); ++i)
131 jacobian.mv(shapeGradients[i][0], gradients[i]);
133 for (std::size_t i = 0; i < size; ++i) {
134 const auto local_i = node.localIndex(i);
136 elementMatrix[local_i][local_i] += factor * (gradients[i] * gradients[i]);
138 for (std::size_t j = i+1; j < size; ++j) {
139 const auto local_j = node.localIndex(j);
140 const auto value = factor * (gradients[i] * gradients[j]);
142 elementMatrix[local_i][local_j] += value;
143 elementMatrix[local_j][local_i] += value;
149 template <
class CG,
class QR,
class RN,
class CN,
class LocalFct,
class Mat>
150 void getElementMatrixOptimized(CG
const& contextGeo, QR
const& quad,
151 RN
const& node, CN
const& ,
152 LocalFct
const& localFct, Mat& elementMatrix,
tag::matrix)
const
154 std::size_t size = node.size();
156 using RangeFieldType =
typename RN::LocalBasis::Traits::RangeFieldType;
157 using WorldVector = Dune::FieldVector<RangeFieldType,CG::dow>;
158 std::vector<WorldVector> gradients;
160 for (
auto const& qp : quad) {
162 auto&& local = contextGeo.coordinateInElement(qp.position());
165 const auto jacobian = contextGeo.elementGeometry().jacobianInverseTransposed(local);
168 const auto factor = contextGeo.integrationElement(qp.position()) * qp.weight();
169 const auto exprValue = localFct(local);
172 auto const& shapeGradients = node.localBasisJacobiansAt(local);
175 gradients.resize(shapeGradients.size());
176 for (std::size_t i = 0; i < gradients.size(); ++i)
177 jacobian.mv(shapeGradients[i][0], gradients[i]);
179 for (std::size_t i = 0; i < size; ++i) {
180 const auto local_i = node.localIndex(i);
181 for (std::size_t j = 0; j < size; ++j) {
182 const auto local_j = node.localIndex(j);
183 elementMatrix[local_i][local_j] += eval(exprValue, factor, gradients[i], gradients[j]);
191 template <
class S,
class F,
class T,
int dow,
192 std::enable_if_t<Category::Scalar<S>,
int> = 0>
193 T eval(S
const& scalar, F factor,
194 Dune::FieldVector<T,dow>
const& grad_test,
195 Dune::FieldVector<T,dow>
const& grad_trial)
const
197 return (scalar * factor) * (grad_test * grad_trial);
200 template <
class M,
class F,
class T,
int dow,
201 std::enable_if_t<Category::Matrix<M>,
int> = 0>
202 T eval(M
const& mat, F factor,
203 Dune::FieldVector<T,dow>
const& grad_test,
204 Dune::FieldVector<T,dow>
const& grad_trial)
const
206 return factor * (grad_test * (mat * grad_trial));