Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
dunefunctionsoperatorassembler.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4// SPDX-FileCopyrightText: Copyright © DUNE-FUFEM Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#ifndef DUNE_FUFEM_ASSEMBLERS_DUNEFUNCTIONSOPERATORASSEMBLER_HH
8#define DUNE_FUFEM_ASSEMBLERS_DUNEFUNCTIONSOPERATORASSEMBLER_HH
9
10#ifndef DUNE_FUFEM_DISABLE_HEADER_DEPRECATION
11#warning This header is deprecated and will be removed after 2.11. Use the global assemblers from dune/assembler/defaultglobalassembler.hh instead.
12#endif
13
21#include <cstddef>
22#include <type_traits>
23
26
27#include <dune/istl/matrix.hh>
28
29#include <dune/grid/common/capabilities.hh>
31
34
35
36namespace Dune {
37namespace Fufem {
38
39
40
47template <class TestBasis, class AnsatzBasis>
48class
49[[deprecated("This class will be removed after 2.11. Use Dune::Assembler::Assembler together with Dune::Fufem::Forms based local assemblers instead.")]]
51{
52 using GridView = typename TestBasis::GridView;
53
54 // Zero-initialize local entries contained in the tree.
55 // In case of a subspace basis, this does not touch
56 // entries not contained in the subspace.
57 template<class TestLocalView, class AnsatzLocalView, class LocalMatrix>
58 static void zeroInitializeLocal(const TestLocalView& testLocalView, const AnsatzLocalView& ansatzLocalView, LocalMatrix& localMatrix)
59 {
60 for (size_t i=0; i<testLocalView.tree().size(); ++i)
61 {
62 auto localRow = testLocalView.tree().localIndex(i);
63 for (size_t j=0; j<ansatzLocalView.tree().size(); ++j)
64 {
65 auto localCol = ansatzLocalView.tree().localIndex(j);
66 localMatrix[localRow][localCol] = 0;
67 }
68 }
69 }
70
71 // Distribute local matrix pattern to global pattern builder
72 // In case of a subspace basis, this does not touch
73 // entries not contained in the subspace.
74 template<class TestLocalView, class AnsatzLocalView, class PatternBuilder>
75 static void distributeLocalPattern(const TestLocalView& testLocalView, const AnsatzLocalView& ansatzLocalView, PatternBuilder& patternBuilder)
76 {
77 for (size_t i=0; i<testLocalView.tree().size(); ++i)
78 {
79 auto localRow = testLocalView.tree().localIndex(i);
80 auto row = testLocalView.index(localRow);
81 for (size_t j=0; j<ansatzLocalView.tree().size(); ++j)
82 {
83 auto localCol = ansatzLocalView.tree().localIndex(j);
84 auto col = ansatzLocalView.index(localCol);
85 patternBuilder.insertEntry(row,col);
86 }
87 }
88 }
89
90 // Distribute local matrix entries to global matrix
91 // In case of a subspace basis, this does not touch
92 // entries not contained in the subspace.
93 template<class TestLocalView, class AnsatzLocalView, class LocalMatrix, class MatrixBackend>
94 static void distributeLocalEntries(const TestLocalView& testLocalView, const AnsatzLocalView& ansatzLocalView, const LocalMatrix& localMatrix, MatrixBackend& matrixBackend)
95 {
96 for (size_t i=0; i<testLocalView.tree().size(); ++i)
97 {
98 auto localRow = testLocalView.tree().localIndex(i);
99 auto row = testLocalView.index(localRow);
100 for (size_t j=0; j<ansatzLocalView.tree().size(); ++j)
101 {
102 auto localCol = ansatzLocalView.tree().localIndex(j);
103 auto col = ansatzLocalView.index(localCol);
104 matrixBackend(row,col) += localMatrix[localRow][localCol];
105 }
106 }
107 }
108
109 // SFINAE expression check for preprocess() method of local assembler
110 template <class LocalAssembler>
112
113public:
115 [[deprecated("This class will be removed after 2.11. Use Dune::Assembler::Assembler together with Dune::Fufem::Forms based local assemblers instead.")]]
116 DuneFunctionsOperatorAssembler(const TestBasis& tBasis, const AnsatzBasis& aBasis) :
117 testBasis_(tBasis),
118 ansatzBasis_(aBasis)
119 {}
120
121
122
123 template <class PatternBuilder>
124 void assembleBulkPattern(PatternBuilder& patternBuilder) const
125 {
126 patternBuilder.resize(testBasis_, ansatzBasis_);
127
128 // create two localViews but use only one if bases are the same
129 auto ansatzLocalView = ansatzBasis_.localView();
130 auto separateTestLocalView = testBasis_.localView();
131 auto& testLocalView = selectTestLocalView(ansatzLocalView, separateTestLocalView);
132
133 for (const auto& element : elements(testBasis_.gridView()))
134 {
135 // bind the localViews to the element
136 bind(ansatzLocalView, testLocalView, element);
137
138 distributeLocalPattern(testLocalView, ansatzLocalView, patternBuilder);
139 }
140 }
141
152 template <class PatternBuilder, class ElementPartition>
153 void assembleBulkPattern(PatternBuilder& patternBuilder, const ElementPartition& elementPartition, std::size_t threadCount) const
154 {
155 static_assert(Dune::Capabilities::viewThreadSafe<typename GridView::Grid>::v, "Trying to use thread parallel assembler but grid is not viewThreadSafe.");
156
157 patternBuilder.resize(testBasis_, ansatzBasis_);
158
159 parallelAlgorithm(threadCount, [&](auto parallel) mutable {
160 // create two localViews but use only one if bases are the same
161 auto ansatzLocalView = ansatzBasis_.localView();
162 auto separateTestLocalView = testBasis_.localView();
163 auto& testLocalView = selectTestLocalView(ansatzLocalView, separateTestLocalView);
164
165 parallel.coloredForEach(elementPartition, [&](const auto& element) {
166 bind(ansatzLocalView, testLocalView, element);
167 distributeLocalPattern(testLocalView, ansatzLocalView, patternBuilder);
168 });
169 });
170 }
171
172
173 template <class PatternBuilder>
174 void assembleSkeletonPattern(PatternBuilder& patternBuilder) const
175 {
176 patternBuilder.resize(testBasis_, ansatzBasis_);
177
178 auto insideTestLocalView = testBasis_.localView();
179
180 auto insideAnsatzLocalView = ansatzBasis_.localView();
181
182 auto outsideAnsatzLocalView = ansatzBasis_.localView();
183
184 for (const auto& element : elements(testBasis_.gridView()))
185 {
186 insideTestLocalView.bind(element);
187
188 insideAnsatzLocalView.bind(element);
189
190 /* Coupling on the same element */
191 distributeLocalPattern(insideTestLocalView, insideAnsatzLocalView, patternBuilder);
192
193 for (const auto& is : intersections(testBasis_.gridView(), element))
194 {
195 /* Elements on the boundary have been treated above, iterate along the inner edges */
196 if (is.neighbor())
197 {
198 // Current outside element
199 const auto& outsideElement = is.outside();
200
201 // Bind the outer parts to the outer element
202 outsideAnsatzLocalView.bind(outsideElement);
203
204 // We assume that all basis functions of the inner element couple with all basis functions from the outer one
205 distributeLocalPattern(insideTestLocalView, outsideAnsatzLocalView, patternBuilder);
206 }
207 }
208 }
209 }
210
211
212
222 template <class Matrix, class LocalAssembler>
223 void assembleBulkEntries(Matrix&& matrix, LocalAssembler&& localAssembler) const
224 {
226 auto&& matrixBackend = toMatrixBackend<TestBasis, AnsatzBasis>(matrix);
228
229 // create two localViews but use only one if bases are the same
230 auto ansatzLocalView = ansatzBasis_.localView();
231 auto separateTestLocalView = testBasis_.localView();
232 auto& testLocalView = selectTestLocalView(ansatzLocalView, separateTestLocalView);
233
234 if constexpr(Dune::Std::is_detected_v<LocalAssemblerPreprocess, LocalAssembler>)
235 localAssembler.preprocess(testLocalView, ansatzLocalView);
236
237 using Field = std::decay_t<decltype(matrixBackend(testLocalView.index(0), ansatzLocalView.index(0)))>;
238 using LocalMatrix = Dune::Matrix<Field>;
239
240 auto localMatrix = LocalMatrix();
241
242 localMatrix.setSize(testLocalView.maxSize(), ansatzLocalView.maxSize());
243
244 for (const auto& element : elements(testBasis_.gridView()))
245 {
246 // bind the localViews to the element
247 bind(ansatzLocalView, testLocalView, element);
248
249 zeroInitializeLocal(testLocalView, ansatzLocalView, localMatrix);
250
251 localAssembler(element, localMatrix, testLocalView, ansatzLocalView);
252
253 // Add element stiffness matrix onto the global stiffness matrix
254 distributeLocalEntries(testLocalView, ansatzLocalView, localMatrix, matrixBackend);
255 }
256 }
257
258
273 template <class Matrix, class LocalAssembler, class ElementPartition>
274 void assembleBulkEntries(Matrix&& matrix, LocalAssembler&& localAssembler, const ElementPartition& elementPartition, std::size_t threadCount) const
275 {
276 static_assert(Dune::Capabilities::viewThreadSafe<typename GridView::Grid>::v, "Trying to use thread parallel assembler but grid is not viewThreadSafe.");
277
279 auto&& matrixBackend = toMatrixBackend<TestBasis, AnsatzBasis>(matrix);
281
282 parallelAlgorithm(threadCount, [&, localAssembler](auto parallel) mutable {
283 // create two localViews but use only one if bases are the same
284 auto ansatzLocalView = ansatzBasis_.localView();
285 auto separateTestLocalView = testBasis_.localView();
286 auto& testLocalView = selectTestLocalView(ansatzLocalView, separateTestLocalView);
287
288 if constexpr(Dune::Std::is_detected_v<LocalAssemblerPreprocess, std::decay_t<LocalAssembler>>)
289 localAssembler.preprocess(testLocalView, ansatzLocalView);
290
291 using Field = std::decay_t<decltype(matrixBackend(testLocalView.index(0), ansatzLocalView.index(0)))>;
292 using LocalMatrix = Dune::Matrix<Field>;
293
294 auto localMatrix = LocalMatrix();
295
296 localMatrix.setSize(testLocalView.maxSize(), ansatzLocalView.maxSize());
297
298 parallel.coloredForEach(elementPartition, [&](const auto& element) {
299 // bind the localViews to the element
300 bind(ansatzLocalView, testLocalView, element);
301
302 zeroInitializeLocal(testLocalView, ansatzLocalView, localMatrix);
303
304 localAssembler(element, localMatrix, testLocalView, ansatzLocalView);
305
306 // Add element stiffness matrix onto the global stiffness matrix
307 distributeLocalEntries(testLocalView, ansatzLocalView, localMatrix, matrixBackend);
308 });
309 });
310 }
311
312
313
314
315 /* This variant of the IntersectionOperatorAssembler that works
316 * with dune-functions bases.
317 *
318 * Currently not supported are constrained bases and lumping.
319 *
320 * Note that this was written (and tested) having discontinuous Galerkin bases in mind.
321 * There may be cases where things do not work as expected for standard (continuous) Galerkin spaces.
322 *
323 * If passed matrix does not satisfy the MatrixBackend concept,
324 * it is wrapped using `istlMatrixBackend()`.
325 */
326 template <class Matrix, class LocalAssembler, class LocalBoundaryAssembler>
327 void assembleSkeletonEntries(Matrix&& matrix, LocalAssembler&& localAssembler, LocalBoundaryAssembler&& localBoundaryAssembler) const
328 {
330 auto&& matrixBackend = toMatrixBackend<TestBasis, AnsatzBasis>(matrix);
332
334
335 auto insideTestLocalView = testBasis_.localView();
336
337 auto insideAnsatzLocalView = ansatzBasis_.localView();
338
339 auto outsideTestLocalView = testBasis_.localView();
340
341 auto outsideAnsatzLocalView = ansatzBasis_.localView();
342
343 using Field = std::decay_t<decltype(matrixBackend(insideTestLocalView.index(0), insideAnsatzLocalView.index(0)))>;
344 using LocalMatrix = Dune::Matrix<Field>;
345 using MatrixContainer = Dune::Matrix<LocalMatrix>;
346 auto matrixContrainer = MatrixContainer(2,2);
347
348 matrixContrainer[0][0].setSize(insideTestLocalView.maxSize(), insideAnsatzLocalView.maxSize());
349 matrixContrainer[0][1].setSize(insideTestLocalView.maxSize(), outsideAnsatzLocalView.maxSize());
350 matrixContrainer[1][0].setSize(outsideTestLocalView.maxSize(), insideAnsatzLocalView.maxSize());
351 matrixContrainer[1][1].setSize(outsideTestLocalView.maxSize(), outsideAnsatzLocalView.maxSize());
352
353 for (const auto& element : elements(testBasis_.gridView()))
354 {
355 insideTestLocalView.bind(element);
356
357 insideAnsatzLocalView.bind(element);
358
359 for (const auto& is : intersections(testBasis_.gridView(), element))
360 {
361
362 /* Assemble (depending on whether we have a boundary edge or not) */
363 if (is.boundary())
364 {
365 auto& localMatrix = matrixContrainer[0][0];
366
367 zeroInitializeLocal(insideTestLocalView, insideAnsatzLocalView, localMatrix);
368
369 localBoundaryAssembler(is, localMatrix, insideTestLocalView, insideAnsatzLocalView);
370
371 distributeLocalEntries(insideTestLocalView, insideAnsatzLocalView, localMatrix, matrixBackend);
372
373 }
374 else if (is.neighbor())
375 {
376 /* Only handle every intersection once; we choose the case where the inner element has the lower index
377 *
378 * This should also work with grids where elements can have different geometries. TODO: Actually test this somewhere!*/
379 const auto& outsideElement = is.outside();
380 if (faceMapper.index(element) > faceMapper.index(outsideElement))
381 continue;
382
383
384 // Bind the outer parts to the outer element
385 outsideTestLocalView.bind(outsideElement);
386
387 outsideAnsatzLocalView.bind(outsideElement);
388
389 zeroInitializeLocal(insideTestLocalView, insideAnsatzLocalView, matrixContrainer[0][0]);
390 zeroInitializeLocal(insideTestLocalView, outsideAnsatzLocalView, matrixContrainer[0][1]);
391 zeroInitializeLocal(outsideTestLocalView, insideAnsatzLocalView, matrixContrainer[1][0]);
392 zeroInitializeLocal(outsideTestLocalView, outsideAnsatzLocalView, matrixContrainer[1][1]);
393
394 localAssembler(is, matrixContrainer, insideTestLocalView, insideAnsatzLocalView, outsideTestLocalView, outsideAnsatzLocalView);
395
396 distributeLocalEntries(insideTestLocalView, insideAnsatzLocalView, matrixContrainer[0][0], matrixBackend);
397 distributeLocalEntries(insideTestLocalView, outsideAnsatzLocalView, matrixContrainer[0][1], matrixBackend);
398 distributeLocalEntries(outsideTestLocalView, insideAnsatzLocalView, matrixContrainer[1][0], matrixBackend);
399 distributeLocalEntries(outsideTestLocalView, outsideAnsatzLocalView, matrixContrainer[1][1], matrixBackend);
400 }
401 }
402 }
403 }
404
405
417 template <class Matrix, class LocalAssembler>
418 void assembleBulk(Matrix&& matrix, LocalAssembler&& localAssembler) const
419 {
421 auto&& matrixBackend = toMatrixBackend<TestBasis, AnsatzBasis>(matrix);
423
424 auto patternBuilder = matrixBackend.patternBuilder();
425 assembleBulkPattern(patternBuilder);
426 patternBuilder.setupMatrix();
427 matrixBackend.assign(0);
428 assembleBulkEntries(matrixBackend, std::forward<LocalAssembler>(localAssembler));
429 }
430
462 template <class Matrix, class LocalAssembler, class ElementPartition>
463 void assembleBulk(Matrix&& matrix, LocalAssembler&& localAssembler, const ElementPartition& elementPartition, std::size_t threadCount) const
464 {
465 static_assert(Dune::Capabilities::viewThreadSafe<typename GridView::Grid>::v, "Trying to use thread parallel assembler but grid is not viewThreadSafe.");
466
468 auto&& matrixBackend = toMatrixBackend<TestBasis, AnsatzBasis>(matrix);
470
471 auto patternBuilder = matrixBackend.patternBuilder();
472 assembleBulkPattern(patternBuilder, elementPartition, threadCount);
473 patternBuilder.setupMatrix();
474 matrixBackend.assign(0);
475 assembleBulkEntries(matrixBackend, std::forward<LocalAssembler>(localAssembler), elementPartition, threadCount);
476 }
477
478private:
479
481template<class AnsatzLocalView, class TestLocalView>
482TestLocalView& selectTestLocalView(AnsatzLocalView& ansatzLocalView, TestLocalView& testLocalView) const
483{
485 {
486 if (&testBasis_ == &ansatzBasis_)
487 return ansatzLocalView;
488 else
489 return testLocalView;
490 }
491 else
492 return testLocalView;
493}
494
496template<class AnsatzLocalView, class TestLocalView, class E>
497void bind(AnsatzLocalView& ansatzLocalView, TestLocalView& testLocalView, const E& e) const
498{
499 ansatzLocalView.bind(e);
501 if (&testLocalView == &ansatzLocalView)
502 return;
503 // localViews differ: bind testLocalView too
504 testLocalView.bind(e);
505}
506
507protected:
508 const TestBasis& testBasis_;
509 const AnsatzBasis& ansatzBasis_;
510};
511
512
520template <class TestBasis, class AnsatzBasis>
521// [[deprecated("This function will be removed after 2.11. Use Dune::Assembler::Assembler together with Dune::Fufem::Forms based local assemblers instead.")]]
522auto duneFunctionsOperatorAssembler(const TestBasis& testBasis, const AnsatzBasis& ansatzBasis)
523{
525 return DuneFunctionsOperatorAssembler<TestBasis, AnsatzBasis>(testBasis, ansatzBasis);
527}
528
529
530
531} // namespace Fufem
532} // namespace Dune
533
534
535#endif // DUNE_FUFEM_ASSEMBLERS_DUNEFUNCTIONSOPERATORASSEMBLER_HH
536
Col col
int size() const
#define DUNE_NO_DEPRECATED_END
#define DUNE_NO_DEPRECATED_BEGIN
void parallelAlgorithm(std::size_t threadCount, F &&threadImp)
Utility for implementing parallel algorithms based on colored entity partitions.
Definition parallelalgorithm.hh:147
auto duneFunctionsOperatorAssembler(const TestBasis &testBasis, const AnsatzBasis &ansatzBasis)
Create DuneFunctionsOperatorAssembler.
Definition dunefunctionsoperatorassembler.hh:522
MCMGLayout mcmgElementLayout()
Generic global assembler for operators on a gridview.
Definition dunefunctionsoperatorassembler.hh:51
void assembleBulkEntries(Matrix &&matrix, LocalAssembler &&localAssembler) const
Assemble bulk integrals.
Definition dunefunctionsoperatorassembler.hh:223
const TestBasis & testBasis_
Definition dunefunctionsoperatorassembler.hh:508
void assembleBulkEntries(Matrix &&matrix, LocalAssembler &&localAssembler, const ElementPartition &elementPartition, std::size_t threadCount) const
Thread parallel version of assembleBulkEntries.
Definition dunefunctionsoperatorassembler.hh:274
void assembleSkeletonPattern(PatternBuilder &patternBuilder) const
Definition dunefunctionsoperatorassembler.hh:174
DuneFunctionsOperatorAssembler(const TestBasis &tBasis, const AnsatzBasis &aBasis)
create assembler for grid
Definition dunefunctionsoperatorassembler.hh:116
void assembleBulkPattern(PatternBuilder &patternBuilder) const
Definition dunefunctionsoperatorassembler.hh:124
void assembleBulk(Matrix &&matrix, LocalAssembler &&localAssembler) const
Create matrix pattern and assemble bulk integrals.
Definition dunefunctionsoperatorassembler.hh:418
const AnsatzBasis & ansatzBasis_
Definition dunefunctionsoperatorassembler.hh:509
void assembleSkeletonEntries(Matrix &&matrix, LocalAssembler &&localAssembler, LocalBoundaryAssembler &&localBoundaryAssembler) const
Definition dunefunctionsoperatorassembler.hh:327
void assembleBulkPattern(PatternBuilder &patternBuilder, const ElementPartition &elementPartition, std::size_t threadCount) const
Thread parallel version of assembleBulkPattern.
Definition dunefunctionsoperatorassembler.hh:153
void assembleBulk(Matrix &&matrix, LocalAssembler &&localAssembler, const ElementPartition &elementPartition, std::size_t threadCount) const
Thread parallel version of assembleBulk.
Definition dunefunctionsoperatorassembler.hh:463
T forward(T... args)