36 template <
class CG,
class RN,
class CN,
class Quad,
class LocalFctA,
class LocalFctB,
class LocalFctC,
class LocalFctF,
class Mat>
37 void assemble(CG
const& contextGeo, RN
const& rowNode, CN
const& colNode, Quad
const& quad,
38 LocalFctA
const& localFctA_, LocalFctB
const& localFctB_, LocalFctC
const& localFctC_, LocalFctF
const& localFctF_,
39 Mat& elementMatrix)
const
41 using A_range =
typename LocalFctA::Range;
42 static_assert(static_size_v<A_range> == 1 || (static_num_rows_v<A_range> == CG::dow && static_num_cols_v<A_range> == CG::dow),
43 "Expression A(x) must be of scalar or matrix type.");
44 using b_range =
typename LocalFctB::Range;
45 static_assert(static_size_v<b_range> == 1 || static_size_v<b_range> == CG::dow,
46 "Expression b(x) must be of scalar or vector type.");
47 using c_range =
typename LocalFctC::Range;
48 static_assert(static_size_v<c_range> == 1,
49 "Expression c(x) must be of scalar type.");
50 static_assert(Dune::TypeTree::Concept::LeafTreeNode<RN> && Dune::TypeTree::Concept::LeafTreeNode<CN>,
51 "Operator can be applied to Leaf-Nodes only." );
52 static_assert(std::is_same_v<FiniteElementType_t<RN>, FiniteElementType_t<CN>>,
53 "Galerkin operator requires equal finite elements for test and trial space." );
55 using RangeFieldType =
typename RN::LocalBasis::Traits::RangeFieldType;
56 using WorldVector = FieldVector<RangeFieldType,CG::dow>;
57 std::vector<WorldVector> gradients;
59 std::size_t numLocalFe = rowNode.size();
61 auto contextGeometry = contextGeo.geometry();
63 for (std::size_t iq = 0; iq < quad.size(); ++iq) {
65 auto&& local = contextGeo.coordinateInElement(quad[iq].position());
68 const auto jacobian = contextGeo.elementGeometry().jacobianInverseTransposed(local);
71 const auto factor = contextGeo.integrationElement(quad[iq].position()) * quad[iq].weight();
74 auto const& shapeValues = rowNode.localBasisValuesAt(local);
77 auto const& shapeGradients = rowNode.localBasisJacobiansAt(local);
80 gradients.resize(shapeGradients.size());
82 for (std::size_t i = 0; i < gradients.size(); ++i)
83 jacobian.mv(shapeGradients[i][0], gradients[i]);
85 const auto A = localFctA_(local);
86 WorldVector b = makeB<CG::dow>(localFctB_(local));
87 const auto c = localFctC_(local);
91 for (std::size_t i = 0; i < numLocalFe; ++i) {
92 const auto local_i = rowNode.localIndex(i);
93 multiply(Dune::MatVec::as_scalar(A), gradients[i], gradAi);
94 auto gradBi = b * gradients[i];
95 for (std::size_t j = 0; j < numLocalFe; ++j) {
96 const auto local_j = colNode.localIndex(j);
97 elementMatrix[local_i][local_j] += (dot(gradAi, gradients[j]) + (c * shapeValues[i] - gradBi) * shapeValues[j]) * factor;
102 for (std::size_t i = 0; i < numLocalFe; ++i) {
103 const auto local_i = rowNode.localIndex(i);
104 multiply(Dune::MatVec::as_scalar(A), gradients[i], grad_i);
105 grad_i.axpy(shapeValues[i], b);
106 for (std::size_t j = 0; j < numLocalFe; ++j) {
107 const auto local_j = colNode.localIndex(j);
108 elementMatrix[local_i][local_j] += (dot(grad_i, gradients[j]) + c * shapeValues[i] * shapeValues[j]) * factor;
116 template <
class CG,
class Node,
class Quad,
class LocalFctA,
class LocalFctB,
class LocalFctC,
class LocalFctF,
class Vec>
117 void assemble(CG
const& contextGeo, Node
const& node, Quad
const& quad, LocalFctA
const& localFctA_, LocalFctB
const& localFctB_, LocalFctC
const& localFctC_, LocalFctF
const& localFctF_, Vec& elementVector)
const
119 using f_range =
typename LocalFctF::Range;
120 static_assert( static_size_v<f_range> == 1,
121 "Expression f(x) must be of scalar type." );
122 static_assert(Dune::TypeTree::Concept::LeafTreeNode<Node>,
123 "Operator can be applied to Leaf-Nodes only." );
125 std::size_t numLocalFe = node.size();
127 for (std::size_t iq = 0; iq < quad.size(); ++iq) {
129 auto&& local = contextGeo.coordinateInElement(quad[iq].position());
132 auto const& shapeValues = node.localBasisValuesAt(local);
135 const auto factor = localFctF_(local) * contextGeo.integrationElement(quad[iq].position()) * quad[iq].weight();
137 for (std::size_t i = 0; i < numLocalFe; ++i) {
138 const auto local_i = node.localIndex(i);
139 elementVector[local_i] += shapeValues[i] * factor;
146 template <
class T1,
int M,
int N,
class T2,
class T3>
147 static void multiply(FieldMatrix<T1,M,N>
const& A, FieldVector<T2,N>
const& x, FieldVector<T3,M>& y)
152 template <
class T1,
int N,
class T2,
class T3,
153 std::enable_if_t<Dune::IsNumber<T1>::value,
int> = 0>
154 static void multiply(T1
const& alpha, FieldVector<T2,N>
const& x, FieldVector<T3,N>& y)
160 template <
int dow,
class T,
int N>
161 static FieldVector<T,dow> makeB(FieldVector<T,N>
const& b) {
return b; }
163 template <
int dow,
class T>
164 static FieldVector<T,dow> makeB(FieldVector<T,1>
const& b) {
return FieldVector<T,dow>(T(b)); }
166 template <
int dow,
class T,
167 std::enable_if_t<Dune::IsNumber<T>::value,
int> = 0>
168 static FieldVector<T,dow> makeB(T b) {
return FieldVector<T,dow>(b); }