1#ifndef __ELLIPTIC_OPERATOR_HH__
2#define __ELLIPTIC_OPERATOR_HH__
4#include <dune/common/fmatrix.hh>
6#include <dune/fem/operator/common/differentiableoperator.hh>
7#include <dune/fem/operator/common/temporarylocalmatrix.hh>
8#include <dune/fem/operator/common/stencil.hh>
11#include "../models/operatorparts/operatorparts.hh"
12#include "../common/quadrature.hh"
13#include "../functions/constantfunction.hh"
77 template<
class OperatorParts,
79 class RangeFunction = DomainFunction,
80 class Constraints = EmptyBlockConstraints<RangeFunction>,
81 template<
class>
class QuadratureTraits = DefaultQuadratureTraits>
83 :
public virtual std::conditional<OperatorParts::isLinear,
84 Fem::LinearOperator<DomainFunction, RangeFunction>,
85 Fem::Operator<DomainFunction, RangeFunction> >::type
88 typedef DomainFunction DomainFunctionType;
89 typedef RangeFunction RangeFunctionType;
90 typedef RangeFunctionType DiscreteFunctionType;
91 static_assert(std::is_base_of<Fem::IsDiscreteFunction, DiscreteFunctionType>::value,
92 "The RangeFunctionType has to be a discrete function");
93 static_assert(std::is_base_of<Fem::HasLocalFunction, DiscreteFunctionType>::value,
94 "The DomainFunctionType has to be provide a local function");
95 typedef OperatorParts OperatorPartsType;
96 typedef Constraints ConstraintsOperatorType;
98 typedef typename std::conditional<
99 std::is_same<ConstraintsOperatorType, EmptyBlockConstraints<RangeFunction> >::value,
101 const ConstraintsOperatorType&>::type
102 ConstraintsOperatorStorageType;
104 typedef typename ConstraintsOperatorType::LocalOperatorType LocalConstraintsOperatorType;
106 typedef typename DomainFunctionType::FunctionSpaceType DomainFunctionSpaceType;
107 typedef typename RangeFunctionType::FunctionSpaceType RangeFunctionSpaceType;
109 static_assert(std::is_same<DomainFunctionSpaceType, RangeFunctionSpaceType>::value,
110 "Domain and range function spaces have to be the same");
112 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
113 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
114 typedef typename LocalFunctionType::RangeType RangeType;
115 typedef typename LocalFunctionType::JacobianRangeType JacobianRangeType;
117 typedef typename DomainFunctionType::LocalFunctionType LocalDomainFunctionType;
119 typedef typename DiscreteFunctionSpaceType::IteratorType IteratorType;
120 typedef typename IteratorType::Entity EntityType;
121 typedef typename EntityType::Geometry ElementGeometryType;
123 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
125 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
126 typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
127 typedef typename IntersectionIteratorType::Intersection IntersectionType;
128 typedef typename IntersectionType::Geometry IntersectionGeometryType;
131 typedef QuadratureTraits<GridPartType> QuadratureTraitsType;
132 typedef typename QuadratureTraitsType::BulkQuadratureType QuadratureType;
133 typedef typename QuadratureTraitsType::BulkMassQuadratureType MassQuadratureType;
134 typedef typename QuadratureTraitsType::FaceQuadratureType FaceQuadratureType;
135 typedef typename QuadratureTraitsType::FaceMassQuadratureType FaceMassQuadratureType;
138 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, true> IntersectionQuadratureType;
140 typedef typename IntersectionQuadratureType::FaceQuadratureType BndryQuadratureType;
142 typedef Dune::Fem::IntersectionQuadrature<FaceMassQuadratureType, true> IntersectionMassQuadratureType;
144 typedef typename IntersectionMassQuadratureType::FaceQuadratureType BndryMassQuadratureType;
149 const ConstraintsOperatorType& constraints = ConstraintsOperatorType())
150 : operatorParts_(parts), constraintsOperator_(constraints)
154 virtual void operator()(
const DomainFunctionType &u, RangeFunctionType &w)
const;
159 return OperatorPartsType::isSymmetric;
162 virtual bool positiveDefinite()
const
164 return OperatorPartsType::isSemiDefinite;
168 const ConstraintsOperatorType& constraints()
const {
return constraintsOperator_; }
169 const OperatorPartsType& operatorParts()
const {
return operatorParts_; }
170 OperatorPartsType& operatorParts() {
return operatorParts_; }
172 OperatorPartsType operatorParts_;
173 ConstraintsOperatorStorageType constraintsOperator_;
176 template<
class JacobianOperator,
178 class Constraints = DifferentiableEmptyBlockConstraints<JacobianOperator>,
179 template<
class>
class QuadratureTraits = DefaultQuadratureTraits>
180 class DifferentiableEllipticOperator
181 :
public EllipticOperator<OperatorParts,
182 typename JacobianOperator::DomainFunctionType,
183 typename JacobianOperator::RangeFunctionType,
184 Constraints, QuadratureTraits>,
185 public Fem::DifferentiableOperator<JacobianOperator>,
186 public virtual std::conditional<OperatorParts::isLinear,
187 Fem::AssembledOperator<typename JacobianOperator::DomainFunctionType,
188 typename JacobianOperator::RangeFunctionType>,
189 Fem::Operator<typename JacobianOperator::DomainFunctionType,
190 typename JacobianOperator::RangeFunctionType> >::type
194 typename JacobianOperator::DomainFunctionType,
195 typename JacobianOperator::RangeFunctionType,
196 Constraints, QuadratureTraits>
199 typedef JacobianOperator JacobianOperatorType;
200 typedef typename JacobianOperatorType::DomainFunctionType DomainFunctionType;
201 typedef typename JacobianOperatorType::RangeFunctionType RangeFunctionType;
202 typedef DomainFunctionType DiscreteFunctionType;
203 typedef typename DomainFunctionType::LocalFunctionType LocalDomainFunctionType;
204 typedef OperatorParts OperatorPartsType;
205 typedef Constraints ConstraintsOperatorType;
207 typedef typename ConstraintsOperatorType::LocalOperatorType LocalConstraintsOperatorType;
209 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
210 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
211 typedef typename LocalFunctionType::RangeType RangeType;
212 typedef typename LocalFunctionType::JacobianRangeType JacobianRangeType;
214 typedef typename DiscreteFunctionSpaceType::IteratorType IteratorType;
215 typedef typename IteratorType::Entity EntityType;
216 typedef typename EntityType::Geometry ElementGeometryType;
218 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
220 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
221 typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
222 typedef typename IntersectionIteratorType::Intersection IntersectionType;
223 typedef typename IntersectionType::Geometry IntersectionGeometryType;
226 typedef QuadratureTraits<GridPartType> QuadratureTraitsType;
227 typedef typename QuadratureTraitsType::BulkQuadratureType QuadratureType;
228 typedef typename QuadratureTraitsType::BulkMassQuadratureType MassQuadratureType;
229 typedef typename QuadratureTraitsType::FaceQuadratureType FaceQuadratureType;
230 typedef typename QuadratureTraitsType::FaceMassQuadratureType FaceMassQuadratureType;
233 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, true> IntersectionQuadratureType;
235 typedef typename IntersectionQuadratureType::FaceQuadratureType BndryQuadratureType;
237 typedef Dune::Fem::IntersectionQuadrature<FaceMassQuadratureType, true> IntersectionMassQuadratureType;
239 typedef typename IntersectionMassQuadratureType::FaceQuadratureType BndryMassQuadratureType;
243 DifferentiableEllipticOperator(
const OperatorPartsType &parts,
244 const ConstraintsOperatorType& constraints = ConstraintsOperatorType())
245 : BaseType(parts, constraints)
249 using BaseType::operator();
251 using BaseType::positiveDefinite;
254 void jacobian(
const DiscreteFunctionType &u, JacobianOperatorType &jOp)
const;
257 using BaseType::operatorParts;
258 using BaseType::constraints;
262 template<
class OperatorParts,
263 class DomainFunction,
class RangeFunction,
265 template<
class>
class QuadratureTraits>
273 const DiscreteFunctionSpaceType &dfSpace = w.space();
274 const GridPartType& gridPart = dfSpace.gridPart();
276 const bool hasFlux = OperatorPartsType::hasFlux;
277 const bool hasSources = OperatorPartsType::hasSources;
278 const bool hasRobin = OperatorPartsType::hasRobinFlux;
279 const bool hasMassQuadrature = !std::is_same<QuadratureType, MassQuadratureType>::value;
282 constraints().rebuild();
283 const bool doConstraints = constraints().size() > 0;
286 const IteratorType end = dfSpace.end();
287 for (IteratorType it = dfSpace.begin(); it != end; ++it) {
290 const EntityType &entity = *it;
292 const ElementGeometryType &geometry = entity.geometry();
295 const LocalDomainFunctionType uLocal = u.localFunction(entity);
297 LocalFunctionType wLocal = w.localFunction(entity);
300 operatorParts().setEntity(entity);
303 const int quadOrder = uLocal.order() + wLocal.order();
305 if (hasSources || hasFlux) {
306 QuadratureType quadrature(entity, quadOrder);
307 const size_t numQuadraturePoints = quadrature.nop();
308 for (
size_t pt = 0; pt < numQuadraturePoints; ++pt) {
310 const typename QuadratureType::CoordinateType &x = quadrature.point(pt);
311 const double weight = quadrature.weight(pt) * geometry.integrationElement(x);
313 RangeType phiKern(0);
314 JacobianRangeType dPhiKern(0);
317 JacobianRangeType du;
318 uLocal.jacobian(quadrature[pt], du);
322 uLocal.evaluate(quadrature[pt], vu);
324 if (hasSources && !hasMassQuadrature) {
326 operatorParts().source(entity, quadrature[pt], vu, du, avu);
331 JacobianRangeType adu(0);
333 operatorParts().flux(entity, quadrature[pt], vu, du, adu);
339 wLocal.axpy(quadrature[pt], phiKern);
343 wLocal.axpy(quadrature[pt], dPhiKern);
348 if (hasSources && hasMassQuadrature) {
349 MassQuadratureType quadrature(entity, quadOrder);
351 const size_t numQuadraturePoints = quadrature.nop();
352 for (
size_t pt = 0; pt < numQuadraturePoints; ++pt) {
354 const typename MassQuadratureType::CoordinateType &x = quadrature.point(pt);
355 const double weight = quadrature.weight(pt) * geometry.integrationElement(x);
358 JacobianRangeType du;
359 uLocal.jacobian(quadrature[pt], du);
363 uLocal.evaluate(quadrature[pt], vu);
366 operatorParts().source(entity, quadrature[pt], vu, du, phiKern);
370 wLocal.axpy(quadrature[pt], phiKern);
378 IntersectionIteratorType iend = gridPart.iend(entity);
379 for (IntersectionIteratorType it = gridPart.ibegin(entity); it != iend; ++it) {
381 const IntersectionType &intersection = *it;
383 assert(intersection.conforming() ==
true);
385 if (intersection.neighbor() || !intersection.boundary()) {
391 if (!operatorParts().setIntersection(intersection)) {
395 if (std::is_same<FaceQuadratureType, FaceMassQuadratureType>::value) {
396 int quadOrder = 3*dfSpace.order();
398 IntersectionQuadratureType intersectionQuad(gridPart, intersection, quadOrder);
399 const BndryQuadratureType &bndryQuad = intersectionQuad.inside();
400 const int numQuadraturePoints = bndryQuad.nop();
402 for (
int pt = 0; pt < numQuadraturePoints; ++pt) {
408 const double weight = bndryQuad.weight(pt);
411 DomainType integrationNormal
412 = intersection.integrationOuterNormal(bndryQuad.localPoint(pt));
414 const double integrationElement = integrationNormal.two_norm();
416 integrationNormal /= integrationElement;
419 uLocal.evaluate(bndryQuad[pt], vu);
422 operatorParts().robinFlux(intersection, bndryQuad[pt], integrationNormal, vu, phiKern);
423 phiKern *= weight * integrationElement;
424 wLocal.axpy(bndryQuad[pt], phiKern);
429 IntersectionMassQuadratureType intersectionQuad(gridPart, intersection, quadOrder);
430 const BndryMassQuadratureType &bndryQuad = intersectionQuad.inside();
431 const int numQuadraturePoints = bndryQuad.nop();
433 for (
int pt = 0; pt < numQuadraturePoints; ++pt) {
437 const double weight = bndryQuad.weight(pt);
440 DomainType integrationNormal
441 = intersection.integrationOuterNormal(bndryQuad.localPoint(pt));
443 const double integrationElement = integrationNormal.two_norm();
445 integrationNormal /= integrationElement;
448 uLocal.evaluate(bndryQuad[pt], vu);
451 operatorParts().robinFlux(intersection, bndryQuad[pt], integrationNormal, vu, phiKern);
452 phiKern *= weight *integrationElement;
453 wLocal.axpy(bndryQuad[pt], phiKern);
463 if (
false && doConstraints) {
465 LocalConstraintsOperatorType localConstraints(constraints().localOperator(entity));
467 localConstraints(uLocal, wLocal);
482 template<
class JacobianOperator,
class OperatorParts,
class Constra
ints,
template<
class>
class QuadratureTraits>
483 void DifferentiableEllipticOperator<JacobianOperator, OperatorParts, Constraints, QuadratureTraits>
484 ::jacobian (
const DiscreteFunctionType &u, JacobianOperator &jOp)
const
486 typedef typename JacobianOperator::LocalMatrixType LocalMatrixType;
487 typedef typename DiscreteFunctionSpaceType::BasisFunctionSetType BasisFunctionSetType;
489 typedef Dune::Fem::DiagonalStencil<DiscreteFunctionSpaceType, DiscreteFunctionSpaceType> StencilType;
490 typedef Dune::Fem::TemporaryLocalMatrix<DiscreteFunctionSpaceType, DiscreteFunctionSpaceType> ElementMatrixType;
492 const DiscreteFunctionSpaceType &dfSpace = u.space();
493 const GridPartType& gridPart = dfSpace.gridPart();
497 jOp.reserve(StencilType(dfSpace, dfSpace));
501 const unsigned maxNumBasisFunctions =
502 DiscreteFunctionSpaceType::localBlockSize * dfSpace.blockMapper().maxNumDofs();
503 std::vector<typename LocalFunctionType::RangeType> phi(maxNumBasisFunctions);
504 std::vector<typename LocalFunctionType::JacobianRangeType> dphi(maxNumBasisFunctions);
506 const bool hasFlux = OperatorPartsType::hasFlux;
507 const bool hasSources = OperatorPartsType::hasSources;
508 const bool hasRobin = OperatorPartsType::hasRobinFlux;
509 const bool isAffineLinear = OperatorPartsType::isLinear;
510 const bool hasMassQuadrature = !std::is_same<QuadratureType, MassQuadratureType>::value;
513 constraints().rebuild();
514 const bool doConstraints = constraints().size() > 0;
517 JacobianRangeType Du0(0);
519 LocalConstraintsOperatorType localConstraints(constraints().localOperator());
520 bool totallyConstrained =
false;
522 ElementMatrixType elementMatrix(dfSpace, dfSpace);
524 const IteratorType end = dfSpace.end();
525 for (IteratorType it = dfSpace.begin(); it != end; ++it) {
526 const EntityType &entity = *it;
527 const ElementGeometryType &geometry = entity.geometry();
530 operatorParts().setEntity(entity);
532 const LocalDomainFunctionType uLocal = u.localFunction(entity);
534 elementMatrix.init(entity, entity);
535 elementMatrix.clear();
537 const BasisFunctionSetType &baseSet = elementMatrix.domainBasisFunctionSet();
538 const unsigned int numBaseFunctions = baseSet.size();
541 localConstraints.init(entity);
542 totallyConstrained = localConstraints.totallyConstrained();
545 if (!totallyConstrained && (hasFlux || hasSources)) {
547 QuadratureType quadrature(entity, 2*dfSpace.order());
548 const size_t numQuadraturePoints = quadrature.nop();
550 for (
size_t pt = 0; pt < numQuadraturePoints; ++pt) {
552 const typename QuadratureType::CoordinateType &x = quadrature.point(pt);
553 const double weight = quadrature.weight(pt) * geometry.integrationElement(x);
558 baseSet.evaluateAll(quadrature[pt], phi);
561 baseSet.jacobianAll(quadrature[pt], dphi);
563 if (!isAffineLinear) {
564 uLocal.evaluate(quadrature[pt], u0);
565 uLocal.jacobian(quadrature[pt], Du0);
569 JacobianRangeType adphi(0);
571 for (
unsigned int localCol = 0; localCol < numBaseFunctions; ++localCol) {
573 if (hasSources && !hasMassQuadrature) {
574 operatorParts().linearizedSource(u0, Du0, entity, quadrature[pt], phi[localCol], dphi[localCol], aphi);
580 operatorParts().linearizedFlux(u0, Du0, entity, quadrature[pt], phi[localCol], dphi[localCol], adphi);
586 elementMatrix.column(localCol).axpy(phi, dphi, aphi, adphi, weight);
592 if (hasSources && hasMassQuadrature) {
594 MassQuadratureType quadrature(entity, 2*dfSpace.order());
595 const size_t numQuadraturePoints = quadrature.nop();
597 for (
size_t pt = 0; pt < numQuadraturePoints; ++pt) {
599 const typename MassQuadratureType::CoordinateType &x = quadrature.point(pt);
600 const double weight = quadrature.weight(pt) * geometry.integrationElement(x);
605 baseSet.evaluateAll(quadrature[pt], phi);
607 if (!isAffineLinear) {
608 uLocal.evaluate(quadrature[pt], u0);
609 uLocal.jacobian(quadrature[pt], Du0);
613 JacobianRangeType adphi(0);
615 for (
unsigned int localCol = 0; localCol < numBaseFunctions; ++localCol) {
617 operatorParts().linearizedSource(u0, Du0, entity, quadrature[pt], phi[localCol], dphi[localCol], aphi);
622 elementMatrix.column(localCol).axpy(phi, dphi, aphi, adphi, weight);
629 if (!totallyConstrained && hasRobin) {
631 IntersectionIteratorType iend = dfSpace.gridPart().iend(entity);
632 for (IntersectionIteratorType it = dfSpace.gridPart().ibegin(entity); it != iend; ++it) {
634 const IntersectionType &intersection = *it;
636 assert(intersection.conforming() ==
true);
638 if (intersection.neighbor() || !intersection.boundary()) {
644 if (!operatorParts().setIntersection(intersection)) {
651 int quadOrder = 3*dfSpace.order();
653 IntersectionMassQuadratureType intersectionQuad(gridPart, intersection, quadOrder);
654 const BndryMassQuadratureType &bndryQuad = intersectionQuad.inside();
655 const int numQuadraturePoints = bndryQuad.nop();
657 for (
int pt = 0; pt < numQuadraturePoints; ++pt) {
661 const double weight = bndryQuad.weight(pt);
664 DomainType integrationNormal
665 = intersection.integrationOuterNormal(bndryQuad.localPoint(pt));
668 double integrationElement = integrationNormal.two_norm();
670 integrationNormal /= integrationElement;
674 baseSet.evaluateAll(bndryQuad[pt], phi);
676 if (!isAffineLinear) {
678 uLocal.evaluate(bndryQuad[pt], u0);
681 for (
unsigned int localCol = 0; localCol < numBaseFunctions; ++localCol) {
684 operatorParts().linearizedRobinFlux(u0, intersection, bndryQuad[pt], integrationNormal, phi[localCol], alphaphi);
685 alphaphi *= integrationElement;
688 elementMatrix.column(localCol).axpy(phi, alphaphi, weight);
700 localConstraints.jacobian(uLocal , elementMatrix);
703 jOp.addLocalMatrix(entity, entity, elementMatrix);
A class defining an elliptic operator.
Definition: ellipticoperator.hh:86
EllipticOperator(const OperatorPartsType &parts, const ConstraintsOperatorType &constraints=ConstraintsOperatorType())
contructor
Definition: ellipticoperator.hh:148
virtual bool symmetric() const
linear operator interface
Definition: ellipticoperator.hh:157
A class modelling do-nothing constraints.
Definition: emptyblockconstraints.hh:40
Empty do-nothing constraints.
virtual void operator()(const DomainFunctionType &u, RangeFunctionType &w) const
application operator, works "on the fly"
Definition: ellipticoperator.hh:267