dune-mmesh 1.4.1-git
Loading...
Searching...
No Matches
jacobian_iterative.hh
Go to the documentation of this file.
1// -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_PYTHON_MMESH_JACOBIAN_HH
4#define DUNE_PYTHON_MMESH_JACOBIAN_HH
5
6#include <dune/python/pybind11/functional.h>
7#include <dune/python/pybind11/numpy.h>
8#include <dune/python/pybind11/pybind11.h>
9#include <dune/python/pybind11/stl.h>
10
11#include <array>
13#include <functional>
14#include <list>
15#include <map>
16#include <memory>
17#include <sstream>
18#include <type_traits>
19
20namespace Dune {
21
22namespace Python {
23
24namespace MMesh {
27
29template <class GridPart, class Intersection, class Entity>
30const typename GridPart::IntersectionType convert(
31 const GridPart& gridPart, const Intersection& intersection,
32 const Entity& inside, Dune::PriorityTag<0>) {
33 const Entity outside = gridPart.convert(intersection.outside());
34
35 for (auto is : intersections(gridPart, inside))
36 if (is.outside() == outside) return is;
37 DUNE_THROW(InvalidStateException, "Intersection not found!");
38}
39
41template <class GridPart, class Intersection, class Entity>
43 std::is_convertible_v<Intersection, typename GridPart::IntersectionType>,
44 const typename GridPart::IntersectionType>
45convert(const GridPart& gridPart, const Intersection& intersection,
46 const Entity& inside, Dune::PriorityTag<1>) {
47 return intersection;
48}
49
51template <class GridPart, class Intersection, class Entity>
52const typename GridPart::IntersectionType convert(
53 const GridPart& gridPart, const Intersection& intersection,
54 const Entity& inside) {
55 return convert(gridPart, intersection, inside, Dune::PriorityTag<1>{});
56}
57
62template <class DomainSpace, class RangeSpace,
63 class Partition = Dune::Partitions::All>
64struct NeighborInterfaceStencil : public Fem::Stencil<DomainSpace, RangeSpace> {
66
67 typedef typename DomainSpace::GridPartType DomainGridPart;
68 typedef typename RangeSpace::GridPartType RangeGridPart;
69
70 public:
71 NeighborInterfaceStencil(const DomainSpace& dSpace, const RangeSpace& rSpace)
72 : BaseType(dSpace, rSpace),
73 domainGridPart_(dSpace.gridPart()),
74 rangeGridPart_(rSpace.gridPart()) {}
75
76 void setupStencil() const {
77 const auto& mmesh = domainGridPart_.grid().getMMesh();
78 for (const auto& entity : elements(domainGridPart_, Partition{})) {
79 const auto mmeshIntersection = mmesh.asIntersection(entity);
80 const auto inside = rangeGridPart_.convert(mmeshIntersection.inside());
81 const auto intersection =
82 convert(rangeGridPart_, mmeshIntersection, inside);
83
84 BaseType::fill(entity, intersection.inside());
85 BaseType::fill(entity, intersection.outside());
86 }
87 }
88
89 private:
90 const DomainGridPart& domainGridPart_;
91 const RangeGridPart& rangeGridPart_;
92};
93
98template <class DomainSpace, class RangeSpace,
99 class Partition = Dune::Partitions::All>
100struct InterfaceNeighborStencil : public Fem::Stencil<DomainSpace, RangeSpace> {
102
103 typedef typename DomainSpace::GridPartType DomainGridPart;
104 typedef typename RangeSpace::GridPartType RangeGridPart;
105
106 public:
107 InterfaceNeighborStencil(const DomainSpace& dSpace, const RangeSpace& rSpace)
108 : BaseType(dSpace, rSpace),
109 domainGridPart_(dSpace.gridPart()),
110 rangeGridPart_(rSpace.gridPart()) {}
111
112 void setupStencil() const {
113 for (const auto& entity : elements(domainGridPart_, Partition{})) {
114 for (const auto& intersection : intersections(domainGridPart_, entity)) {
115 if (intersection.neighbor() &&
116 domainGridPart_.grid().isInterface(intersection)) {
117 auto ientity = domainGridPart_.grid().asInterfaceEntity(intersection);
118 BaseType::fill(entity, ientity);
119 }
120 }
121 }
122 }
123
124 private:
125 const DomainGridPart& domainGridPart_;
126 const RangeGridPart& rangeGridPart_;
127};
128
129template <class X, class BulkDF, class InterfaceDF>
131 public:
132 typedef X domain_type;
133 typedef typename X::field_type field_type;
135
136 ParallelizedScalarProduct(const BulkDF& uh, const InterfaceDF& th)
137 : u(uh), v(uh), t(th), s(th) {}
138
139 virtual field_type dot(const X& x, const X& y) const {
140 u.blockVector() = x[_0];
141 t.blockVector() = x[_1];
142 v.blockVector() = y[_0];
143 s.blockVector() = y[_1];
144 return u.scalarProductDofs(v) + t.scalarProductDofs(s); // already parallel
145 }
146
147 virtual real_type norm(const X& x) const {
148 u.blockVector() = x[_0];
149 t.blockVector() = x[_1];
150 return std::sqrt(u.scalarProductDofs(u) +
151 t.scalarProductDofs(t)); // already parallel
152 }
153
154 private:
155 mutable BulkDF u, v;
156 mutable InterfaceDF t, s;
157};
158
159template <class M, class X, class Y, class BulkDF, class InterfaceDF>
161 public:
163 typedef M matrix_type;
164 typedef X domain_type;
165 typedef Y range_type;
166 typedef typename X::field_type field_type;
167
169 explicit ParallelizedMatrixAdapter(const M& A, const BulkDF& uh,
170 const InterfaceDF& th)
171 : _A_(stackobject_to_shared_ptr(A)), u(uh), t(th) {}
172
174 void apply(const X& x, Y& y) const override {
175 _A_->mv(x, y);
176 communicate(y);
177 }
178
180 void applyscaleadd(field_type alpha, const X& x, Y& y) const override {
181 _A_->usmv(alpha, x, y);
182 communicate(y);
183 }
184
186 const M& getmat() const override { return *_A_; }
187
192
193 private:
194 void communicate(Y& y) const {
195 u.blockVector() = y[_0];
196 t.blockVector() = y[_1];
197 u.communicate();
198 t.communicate();
199 y[_0] = u.blockVector();
200 y[_1] = t.blockVector();
201 }
202
203 const std::shared_ptr<const M> _A_;
204 mutable BulkDF u;
205 mutable InterfaceDF t;
206};
207
208template <class Sch, class ISch, class Sol, class ISol>
209class Jacobian {
210 using ThisType = Jacobian<Sch, ISch, Sol, ISol>;
211
212 public:
213 using Scheme = Sch;
214 using IScheme = ISch;
215 using Solution = Sol;
216 using ISolution = ISol;
217
218 using AType = typename Scheme::JacobianOperatorType;
219 using BType = Dune::Fem::ISTLLinearOperator<ISolution, Solution>;
220 using CType = Dune::Fem::ISTLLinearOperator<Solution, ISolution>;
221 using DType = typename IScheme::JacobianOperatorType;
222
223 // Block Matrix
228
232
233 // Block Vector
234 using AVectorBlock = typename AType::ColumnBlockVectorType;
235 using DVectorBlock = typename DType::ColumnBlockVectorType;
237
238 typedef typename AType::DomainSpaceType BulkSpaceType;
239 typedef typename DType::DomainSpaceType InterfaceSpaceType;
241 typename IScheme::LinearInverseOperatorType::SolverParameterType>;
242
243 Jacobian(const Scheme& scheme, const IScheme& ischeme, const Solution& uh,
244 const ISolution& th, const double eps,
245 const std::function<void()>& callback)
246 : scheme_(scheme),
247 ischeme_(ischeme),
248 A_("A", uh.space(), uh.space()),
249 B_("B", th.space(), uh.space()),
250 C_("C", uh.space(), th.space()),
251 D_("D", th.space(), th.space()),
252 eps_(eps),
253 callback_(callback),
254 n_(uh.size()),
255 m_(th.size()) {
256 x_[_0] = uh.blockVector();
257 x_[_1] = th.blockVector();
258 }
259
260 const Scheme& scheme() const { return scheme_; };
261 const BlockMatrix& M() const { return M_; };
262
263 void init() {
264 if (n_ == 0 || m_ == 0) return;
265
267 B_.domainSpace(), B_.rangeSpace());
268 stencilB.setupStencil();
269 B_.reserve(stencilB);
270
272 C_.domainSpace(), C_.rangeSpace());
273 stencilC.setupStencil();
274 C_.reserve(stencilC);
275 }
276
277 void update(const Solution& uh, const ISolution& th) {
278 scheme_.jacobian(uh, A_);
279 ischeme_.jacobian(th, D_);
280
281 if (n_ > 0 && m_ > 0) {
282 B_.clear();
283 C_.clear();
284 assembleB(scheme_, th, uh);
285 assembleC(ischeme_, uh, th);
286 }
287 }
288
289 void solve(const Solution& f, const ISolution& g, Solution& u, ISolution& t) {
290 auto setBlock = [this](const auto& block, const auto blockrow,
291 const auto blockcol) {
292 this->M_[blockrow][blockcol] = block.exportMatrix();
293 };
294
295 if (n_ > 0) setBlock(A_, _0, _0);
296 if (n_ > 0 && m_ > 0) {
297 setBlock(B_, _0, _1);
298 setBlock(C_, _1, _0);
299 }
300 if (m_ > 0) setBlock(D_, _1, _1);
301
302 b_[_0] = f.blockVector();
303 b_[_1] = g.blockVector();
304
305 auto params = std::make_shared<Fem::ISTLSolverParameter>(
306 ParameterType(scheme_.parameter()).linear());
307 const size_t numIterations = params->preconditionerIteration();
308 const double relaxFactor = params->relaxation();
309
310 using SolverAdapterType = Fem::ISTLSolverAdapter<-1, BlockVector>;
311 using ReductionType = typename SolverAdapterType::ReductionType;
312 SolverAdapterType solver(ReductionType(params), params);
313 solver.setMaxIterations(params->maxIterations());
314
316 ISolution>
317 linop(M_, u, t);
321
322 solver(linop, scp, prec, b_, x_, res);
323
324 u.blockVector() = x_[_0];
325 t.blockVector() = x_[_1];
326 u.communicate();
327 t.communicate();
328 }
329
330 private:
331 template <class Scheme, class DomainGridFunction, class RangeGridFunction>
332 void assembleB(const Scheme& scheme, const DomainGridFunction& t,
333 const RangeGridFunction& u) {
334 typedef InterfaceSpaceType DomainSpaceType;
335 typedef BulkSpaceType RangeSpaceType;
336
338 TemporaryLocalMatrixType;
339 typedef typename RangeGridFunction::DiscreteFunctionSpaceType
340 DiscreteFunctionSpaceType;
341
342 const auto& gridPart = t.gridPart();
343 const auto& grid = gridPart.grid();
344 const auto& mmesh = grid.getMMesh();
345
346 auto dFIn = u;
347 auto dFOut = u;
348
350 u.space());
352 u.space());
354 u.space());
356 u.space());
357
359
362
365
366 TemporaryLocalMatrixType localMatrixIn(B_.domainSpace(), B_.rangeSpace());
367 TemporaryLocalMatrixType localMatrixOut(B_.domainSpace(), B_.rangeSpace());
368
369 for (const auto& interface : elements(gridPart, Partitions::all)) {
370 tLocal.bind(interface);
371 auto& tDof = tLocal.localDofVector();
372
373 const auto mmeshIntersection = mmesh.asIntersection(interface);
374 const auto inside = u.gridPart().convert(mmeshIntersection.inside());
375 const auto intersection =
376 convert(u.gridPart(), mmeshIntersection, inside);
377
378 const auto& outside = intersection.outside();
379
380 FmTmpIn.bind(inside);
381 FmTmpOut.bind(outside);
382 FpTmpIn.bind(inside);
383 FpTmpOut.bind(outside);
384
385 uInside.bind(inside);
386 uOutside.bind(outside);
387
388 dFLocalIn.bind(inside);
389 dFLocalOut.bind(outside);
390
391 localMatrixIn.init(interface, inside);
392 localMatrixOut.init(interface, outside);
393
394 localMatrixIn.clear();
395 localMatrixOut.clear();
396
397 for (std::size_t i = 0; i < tDof.size(); ++i) {
398 dFIn.clear();
399 dFOut.clear();
400
401 FmTmpIn.clear();
402 FmTmpOut.clear();
403 FpTmpIn.clear();
404 FpTmpOut.clear();
405
406 double h = std::max(tDof[i] * eps_, eps_);
407 tDof[i] -= h;
408 callback_();
409 scheme.fullOperator().impl().addSkeletonIntegral(
410 intersection, uInside, uOutside, FmTmpIn, FmTmpOut);
411 tDof[i] += h;
412
413 dFIn.addLocalDofs(inside, FmTmpIn.localDofVector());
414 dFOut.addLocalDofs(outside, FmTmpOut.localDofVector());
415
416 dFIn *= -1.;
417 dFOut *= -1.;
418
419 tDof[i] += h;
420 callback_();
421 scheme.fullOperator().impl().addSkeletonIntegral(
422 intersection, uInside, uOutside, FpTmpIn, FpTmpOut);
423 tDof[i] -= h;
424
425 dFIn.addLocalDofs(inside, FpTmpIn.localDofVector());
426 dFOut.addLocalDofs(outside, FpTmpOut.localDofVector());
427
428 dFIn /= 2 * h;
429 dFOut /= 2 * h;
430
431 for (std::size_t j = 0; j < dFLocalIn.localDofVector().size(); ++j)
432 localMatrixIn.set(j, i, dFLocalIn[j]);
433
434 for (std::size_t j = 0; j < dFLocalOut.localDofVector().size(); ++j)
435 localMatrixOut.set(j, i, dFLocalOut[j]);
436 }
437
438 B_.addLocalMatrix(interface, inside, localMatrixIn);
439 B_.addLocalMatrix(interface, outside, localMatrixOut);
440 }
441 B_.compress();
442 }
443
444 template <class Scheme, class DomainGridFunction, class RangeGridFunction>
445 void assembleC(const Scheme& ischeme, const DomainGridFunction& u,
446 const RangeGridFunction& t) {
447 typedef BulkSpaceType DomainSpaceType;
448 typedef InterfaceSpaceType RangeSpaceType;
449
450 typedef Fem::TemporaryLocalMatrix<DomainSpaceType, RangeSpaceType>
451 TemporaryLocalMatrixType;
452 typedef typename RangeGridFunction::DiscreteFunctionSpaceType
453 DiscreteFunctionSpaceType;
454
455 const auto& gridPart = u.gridPart();
456 const auto& grid = gridPart.grid();
457
458 auto dG = t;
459
461 t.space());
463 t.space());
464
466
469
470 TemporaryLocalMatrixType localMatrix(C_.domainSpace(), C_.rangeSpace());
471
472 for (const auto& element : elements(gridPart, Partitions::all)) {
473 for (const auto& intersection : intersections(gridPart, element)) {
474 if (grid.isInterface(intersection)) {
475 const auto& interface = grid.asInterfaceEntity(intersection);
476
477 uLocal.bind(element);
478 auto& uDof = uLocal.localDofVector();
479
480 GmTmp.bind(interface);
481 GpTmp.bind(interface);
482 tInterface.bind(interface);
483
484 dGLocal.bind(interface);
485 localMatrix.init(element, interface);
486 localMatrix.clear();
487
488 for (std::size_t i = 0; i < uDof.size(); ++i) {
489 dG.clear();
490
491 GmTmp.clear();
492 GpTmp.clear();
493
494 double h = std::max(uDof[i] * eps_, eps_);
495 uDof[i] -= h;
496 callback_();
497 ischeme.fullOperator().impl().addInteriorIntegral(tInterface,
498 GmTmp);
499 uDof[i] += h;
500
501 dG.addLocalDofs(interface, GmTmp.localDofVector());
502 dG *= -1.;
503
504 uDof[i] += h;
505 callback_();
506 ischeme.fullOperator().impl().addInteriorIntegral(tInterface,
507 GpTmp);
508 uDof[i] -= h;
509
510 dG.addLocalDofs(interface, GpTmp.localDofVector());
511 dG /= 2 * h;
512
513 for (std::size_t j = 0; j < dGLocal.localDofVector().size(); ++j)
514 localMatrix.set(j, i, dGLocal[j]);
515 }
516
517 C_.addLocalMatrix(element, interface, localMatrix);
518 }
519 }
520 }
521 C_.compress();
522 }
523
524 const Scheme& scheme_;
525 const IScheme& ischeme_;
526 AType A_;
527 BType B_;
528 CType C_;
529 DType D_;
530 BlockMatrix M_;
531 BlockVector x_, b_;
532 std::size_t n_, m_;
533 const double eps_;
534 const std::function<void()> callback_;
535};
536
537template <class Jacobian, class... options>
538inline static auto registerJacobian(
539 pybind11::handle scope, pybind11::class_<Jacobian, options...> cls) {
540 using Solution = typename Jacobian::Solution;
541 using ISolution = typename Jacobian::ISolution;
542
543 cls.def(
544 "init", [](Jacobian& self) { self.init(); },
545 R"doc(
546 Initialize the mixed-dimensional jacobian.
547 )doc");
548
549 cls.def(
550 "update",
551 [](Jacobian& self, const Solution& uh, const ISolution& th) {
552 self.update(uh, th);
553 },
554 R"doc(
555 Update the mixed-dimensional jacobian.
556 )doc");
557
558 cls.def(
559 "solve",
560 [](Jacobian& self, const Solution& f, const ISolution& g, Solution& ux,
561 ISolution& tx) { self.solve(f, g, ux, tx); },
562 R"doc(
563 Solve the mixed-dimensional jacobian.
564 )doc");
565}
566
567} // namespace MMesh
568
569} // namespace Python
570
571} // namespace Dune
572
573#endif
Dune::ParameterTree options
static auto registerJacobian(pybind11::handle scope, pybind11::class_< Jacobian, options... > cls)
Definition jacobian.hh:464
const GridPart::IntersectionType convert(const GridPart &gridPart, const Intersection &intersection, const Entity &inside, Dune::PriorityTag< 0 >)
Convert intersection if gridPart is wrapped, e.g. geometryGridPart.
Definition jacobian.hh:29
double alpha() const
int size() const
static constexpr size_type M()
#define DUNE_THROW(E,...)
std::shared_ptr< T > stackobject_to_shared_ptr(T &t)
constexpr index_constant< 0 > _0
constexpr index_constant< 1 > _1
IteratorRange<... > intersections(const GV &gv, const Entity &e)
const GridPartType & gridPart() const
const DiscreteFunctionSpaceType & space() const
const EntityType & entity() const
typename Impl::ConstLocalFunction< GridFunction >::Type ConstLocalFunction
GridImp::template Codim< cd >::Entity Entity
void fill(const DomainEntityType &dEntity, const RangeEntityType &rEntity, bool fillGhost=true) const
const DomainSpaceType & domainSpace() const
void reserve(const std::vector< Set > &sparsityPattern)
void addLocalMatrix(const DomainEntityType &domainEntity, const RangeEntityType &rangeEntity, const LocalMatrix &localMat)
const RangeSpaceType & rangeSpace() const
Stencil contaning the entries (ien,en) for all interface entities ien and adjacent bulk entities en.
Definition jacobian.hh:64
NeighborInterfaceStencil(const DomainSpace &dSpace, const RangeSpace &rSpace)
Definition jacobian_iterative.hh:71
Fem::Stencil< DomainSpace, RangeSpace > BaseType
Definition jacobian_iterative.hh:65
DomainSpace::GridPartType DomainGridPart
Definition jacobian_iterative.hh:67
void setupStencil() const
Definition jacobian_iterative.hh:76
RangeSpace::GridPartType RangeGridPart
Definition jacobian_iterative.hh:68
Stencil contaning the entries (en,ien) for all entities en in the bulk and interface edges ien.
Definition jacobian.hh:100
RangeSpace::GridPartType RangeGridPart
Definition jacobian_iterative.hh:104
DomainSpace::GridPartType DomainGridPart
Definition jacobian_iterative.hh:103
Fem::Stencil< DomainSpace, RangeSpace > BaseType
Definition jacobian_iterative.hh:101
InterfaceNeighborStencil(const DomainSpace &dSpace, const RangeSpace &rSpace)
Definition jacobian_iterative.hh:107
void setupStencil() const
Definition jacobian_iterative.hh:112
Definition jacobian.hh:130
void solve(const Solution &f, const ISolution &g, Solution &u, ISolution &t)
Definition jacobian_iterative.hh:289
void update(const Solution &uh, const ISolution &th)
Definition jacobian_iterative.hh:277
typename AType::ColumnBlockVectorType AVectorBlock
Definition jacobian_iterative.hh:234
ISch IScheme
Definition jacobian.hh:133
DType::DomainSpaceType InterfaceSpaceType
Definition jacobian_iterative.hh:239
Dune::MultiTypeBlockMatrix< ABRowType, CDRowType > BlockMatrix
Definition jacobian_iterative.hh:231
typename Scheme::JacobianOperatorType AType
Definition jacobian.hh:139
typename DType::ColumnBlockVectorType DVectorBlock
Definition jacobian_iterative.hh:235
Sol Solution
Definition jacobian.hh:134
const BlockMatrix & M() const
Definition jacobian_iterative.hh:261
Dune::Fem::SparseRowLinearOperator< ISolution, Solution, SparseMatrix > BType
Definition jacobian.hh:141
Jacobian(const Scheme &scheme, const IScheme &ischeme, const Solution &uh, const ISolution &th, const double eps, const std::function< void()> &callback)
Definition jacobian_iterative.hh:243
typename IScheme::JacobianOperatorType DType
Definition jacobian.hh:144
ISol ISolution
Definition jacobian.hh:135
void init()
Definition jacobian_iterative.hh:263
const Scheme & scheme() const
Definition jacobian_iterative.hh:260
AType::DomainSpaceType BulkSpaceType
Definition jacobian_iterative.hh:238
Fem::NewtonParameter< typename IScheme::LinearInverseOperatorType::SolverParameterType > ParameterType
Definition jacobian_iterative.hh:241
Sch Scheme
Definition jacobian.hh:132
Dune::Fem::SparseRowLinearOperator< Solution, ISolution, SparseMatrix > CType
Definition jacobian.hh:143
Dune::MultiTypeBlockVector< AVectorBlock, DVectorBlock > BlockVector
Definition jacobian_iterative.hh:236
Definition jacobian_iterative.hh:130
X::field_type field_type
Definition jacobian_iterative.hh:133
virtual field_type dot(const X &x, const X &y) const
Definition jacobian_iterative.hh:139
ParallelizedScalarProduct(const BulkDF &uh, const InterfaceDF &th)
Definition jacobian_iterative.hh:136
X domain_type
Definition jacobian_iterative.hh:132
FieldTraits< field_type >::real_type real_type
Definition jacobian_iterative.hh:134
virtual real_type norm(const X &x) const
Definition jacobian_iterative.hh:147
Definition jacobian_iterative.hh:160
M matrix_type
export types
Definition jacobian_iterative.hh:163
void apply(const X &x, Y &y) const override
apply operator to x:
Definition jacobian_iterative.hh:174
Y range_type
Definition jacobian_iterative.hh:165
X::field_type field_type
Definition jacobian_iterative.hh:166
SolverCategory::Category category() const override
Category of the solver (see SolverCategory::Category)
Definition jacobian_iterative.hh:189
X domain_type
Definition jacobian_iterative.hh:164
const M & getmat() const override
get matrix via *
Definition jacobian_iterative.hh:186
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
apply operator to x, scale and add:
Definition jacobian_iterative.hh:180
ParallelizedMatrixAdapter(const M &A, const BulkDF &uh, const InterfaceDF &th)
constructor: just store a reference to a matrix
Definition jacobian_iterative.hh:169
T max(T... args)
T sqrt(T... args)