1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2007 - 2020 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15
16 #ifndef dealii_matrix_block_h
17 #define dealii_matrix_block_h
18
19 #include <deal.II/base/config.h>
20
21 #include <deal.II/algorithms/any_data.h>
22
23 #include <deal.II/base/memory_consumption.h>
24 #include <deal.II/base/mg_level_object.h>
25 #include <deal.II/base/smartpointer.h>
26
27 #include <deal.II/lac/block_indices.h>
28 #include <deal.II/lac/block_sparsity_pattern.h>
29 #include <deal.II/lac/full_matrix.h>
30 #include <deal.II/lac/sparse_matrix.h>
31
32 #include <memory>
33
34
35 DEAL_II_NAMESPACE_OPEN
36
37 // Forward declarations
38 #ifndef DOXYGEN
39 template <typename MatrixType>
40 class MatrixBlock;
41 #endif
42
43 namespace internal
44 {
45 template <typename MatrixType>
46 void
47 reinit(MatrixBlock<MatrixType> &v, const BlockSparsityPattern &p);
48
49 template <typename number>
50 void
51 reinit(MatrixBlock<dealii::SparseMatrix<number>> &v,
52 const BlockSparsityPattern & p);
53 } // namespace internal
54
55 /**
56 * A wrapper around a matrix object, storing the coordinates in a block matrix
57 * as well.
58 *
59 * This class is an alternative to BlockMatrixBase, if you only want to
60 * generate a single block of the system, not the whole system. Using the
61 * add() functions of this class, it is possible to use the standard
62 * assembling functions used for block matrices, but only enter in one of the
63 * blocks and still avoiding the index computations involved. The reason for
64 * this class is, that we may need a different number of matrices for
65 * different blocks in a block system. For example, a preconditioner for the
66 * Oseen system can be built as a block system, where the pressure block is of
67 * the form <b>M</b><sup>-1</sup><b>FA</b><sup>-1</sup> with <b>M</b> the
68 * pressure mass matrix, <b>A</b> the pressure Laplacian and <b>F</b> the
69 * advection diffusion operator applied to the pressure space. Since only a
70 * single matrix is needed for the other blocks, using BlockSparseMatrix or
71 * similar would be a waste of memory.
72 *
73 * While the add() functions make a MatrixBlock appear like a block matrix for
74 * assembling, the functions vmult(), Tvmult(), vmult_add(), and Tvmult_add()
75 * make it behave like a MatrixType, when it comes to applying it to a vector.
76 * This behavior allows us to store MatrixBlock objects in vectors, for
77 * instance in MGLevelObject without extracting the #matrix first.
78 *
79 * MatrixBlock comes handy when using BlockMatrixArray. Once the MatrixBlock
80 * has been properly initialized and filled, it can be used in the simplest
81 * case as:
82 * @code
83 * MatrixBlockVector<SparseMatrix<double> > > blocks;
84 *
85 * ...
86 *
87 * BlockMatrixArray matrix (n_blocks, n_blocks);
88 *
89 * for (size_type i=0;i<blocks.size;++i)
90 * matrix.enter(blocks.block(i).row, blocks.block(i).column,
91 * blocks.matrix(i));
92 * @endcode
93 *
94 * Here, we have not gained very much, except that we do not need to set up
95 * empty blocks in the block system.
96 *
97 * @note This class expects, that the row and column BlockIndices objects for
98 * the system are equal. If they are not, some functions will throw
99 * ExcNotImplemented.
100 *
101 * @todo Example for the product preconditioner of the pressure Schur
102 * complement.
103 *
104 * @ingroup Matrix2
105 * @ingroup vector_valued
106 *
107 * @see
108 * @ref GlossBlockLA "Block (linear algebra)"
109 */
110 template <typename MatrixType>
111 class MatrixBlock : public Subscriptor
112 {
113 public:
114 /**
115 * Declare type for container size.
116 */
117 using size_type = types::global_dof_index;
118
119 /**
120 * Declare a type for matrix entries.
121 */
122 using value_type = typename MatrixType::value_type;
123
124 /**
125 * Constructor rendering an uninitialized object.
126 */
127 MatrixBlock();
128
129 /**
130 * Copy constructor.
131 */
132 MatrixBlock(const MatrixBlock<MatrixType> &M) = default;
133
134 /**
135 * Assignment operator.
136 */
137 MatrixBlock<MatrixType> &
138 operator=(const MatrixBlock<MatrixType> &) = default;
139
140 /**
141 * Constructor setting block coordinates, but not initializing the matrix.
142 */
143
144 MatrixBlock(size_type i, size_type j);
145
146 /**
147 * Reinitialize the matrix for a new BlockSparsityPattern. This adjusts the
148 * #matrix as well as the #row_indices and #column_indices.
149 *
150 * @note The row and column block structure of the sparsity pattern must be
151 * equal.
152 */
153 void
154 reinit(const BlockSparsityPattern &sparsity);
155
156 operator MatrixType &();
157 operator const MatrixType &() const;
158
159 /**
160 * Add <tt>value</tt> to the element (<i>i,j</i>). Throws an error if the
161 * entry does not exist or if it is in a different block.
162 */
163 void
164 add(const size_type i,
165 const size_type j,
166 const typename MatrixType::value_type value);
167
168 /**
169 * Add all elements in a FullMatrix into sparse matrix locations given by
170 * <tt>indices</tt>. This function assumes a quadratic sparse matrix and a
171 * quadratic full_matrix. The global locations are translated into
172 * locations in this block and ExcBlockIndexMismatch is thrown, if the
173 * global index does not point into the block referred to by #row and
174 * #column.
175 *
176 * @todo <tt>elide_zero_values</tt> is currently ignored.
177 *
178 * The optional parameter <tt>elide_zero_values</tt> can be used to specify
179 * whether zero values should be added anyway or these should be filtered
180 * away and only non-zero data is added. The default value is <tt>true</tt>,
181 * i.e., zero values won't be added into the matrix.
182 */
183 template <typename number>
184 void
185 add(const std::vector<size_type> &indices,
186 const FullMatrix<number> & full_matrix,
187 const bool elide_zero_values = true);
188
189 /**
190 * Add all elements in a FullMatrix into global locations given by
191 * <tt>row_indices</tt> and <tt>col_indices</tt>, respectively. The global
192 * locations are translated into locations in this block and
193 * ExcBlockIndexMismatch is thrown, if the global index does not point into
194 * the block referred to by #row and #column.
195 *
196 * @todo <tt>elide_zero_values</tt> is currently ignored.
197 *
198 * The optional parameter <tt>elide_zero_values</tt> can be used to specify
199 * whether zero values should be added anyway or these should be filtered
200 * away and only non-zero data is added. The default value is <tt>true</tt>,
201 * i.e., zero values won't be added into the matrix.
202 */
203 template <typename number>
204 void
205 add(const std::vector<size_type> &row_indices,
206 const std::vector<size_type> &col_indices,
207 const FullMatrix<number> & full_matrix,
208 const bool elide_zero_values = true);
209
210 /**
211 * Set several elements in the specified row of the matrix with column
212 * indices as given by <tt>col_indices</tt> to the respective value. This is
213 * the function doing the actual work for the ones adding full matrices. The
214 * global locations <tt>row_index</tt> and <tt>col_indices</tt> are
215 * translated into locations in this block and ExcBlockIndexMismatch is
216 * thrown, if the global index does not point into the block referred to by
217 * #row and #column.
218 *
219 * @todo <tt>elide_zero_values</tt> is currently ignored.
220 *
221 * The optional parameter <tt>elide_zero_values</tt> can be used to specify
222 * whether zero values should be added anyway or these should be filtered
223 * away and only non-zero data is added. The default value is <tt>true</tt>,
224 * i.e., zero values won't be added into the matrix.
225 */
226 template <typename number>
227 void
228 add(const size_type row_index,
229 const std::vector<size_type> &col_indices,
230 const std::vector<number> & values,
231 const bool elide_zero_values = true);
232
233 /**
234 * Add an array of values given by <tt>values</tt> in the given global
235 * matrix row at columns specified by col_indices in the sparse matrix.
236 *
237 * The optional parameter <tt>elide_zero_values</tt> can be used to specify
238 * whether zero values should be added anyway or these should be filtered
239 * away and only non-zero data is added. The default value is <tt>true</tt>,
240 * i.e., zero values won't be added into the matrix.
241 */
242 template <typename number>
243 void
244 add(const size_type row,
245 const size_type n_cols,
246 const size_type *col_indices,
247 const number * values,
248 const bool elide_zero_values = true,
249 const bool col_indices_are_sorted = false);
250
251 /**
252 * Matrix-vector-multiplication, forwarding to the same function in
253 * MatrixType. No index computations are done, thus, the vectors need to
254 * have sizes matching #matrix.
255 */
256 template <class VectorType>
257 void
258 vmult(VectorType &w, const VectorType &v) const;
259
260 /**
261 * Matrix-vector-multiplication, forwarding to the same function in
262 * MatrixType. No index computations are done, thus, the vectors need to
263 * have sizes matching #matrix.
264 */
265 template <class VectorType>
266 void
267 vmult_add(VectorType &w, const VectorType &v) const;
268
269 /**
270 * Matrix-vector-multiplication, forwarding to the same function in
271 * MatrixType. No index computations are done, thus, the vectors need to
272 * have sizes matching #matrix.
273 */
274 template <class VectorType>
275 void
276 Tvmult(VectorType &w, const VectorType &v) const;
277
278 /**
279 * Matrix-vector-multiplication, forwarding to the same function in
280 * MatrixType. No index computations are done, thus, the vectors need to
281 * have sizes matching #matrix.
282 */
283 template <class VectorType>
284 void
285 Tvmult_add(VectorType &w, const VectorType &v) const;
286
287 /**
288 * The memory used by this object.
289 */
290 std::size_t
291 memory_consumption() const;
292
293 /**
294 * The block number computed from an index by using BlockIndices does not
295 * match the block coordinates stored in this object.
296 */
297 DeclException2(ExcBlockIndexMismatch,
298 size_type,
299 size_type,
300 << "Block index " << arg1 << " does not match " << arg2);
301
302 /**
303 * Row coordinate. This is the position of the data member matrix on the
304 * global matrix.
305 */
306 size_type row;
307 /**
308 * Column coordinate. This is the position of the data member matrix on the
309 * global matrix.
310 */
311 size_type column;
312
313 /**
314 * The matrix itself
315 */
316 MatrixType matrix;
317
318 private:
319 /**
320 * The row BlockIndices of the whole system. Using row(), this allows us to
321 * find the index of the first row degree of freedom for this block.
322 */
323 BlockIndices row_indices;
324 /**
325 * The column BlockIndices of the whole system. Using column(), this allows
326 * us to find the index of the first column degree of freedom for this
327 * block.
328 */
329 BlockIndices column_indices;
330
331 template <class OTHER_MatrixType>
332 friend void
333 dealii::internal::reinit(MatrixBlock<OTHER_MatrixType> &,
334 const BlockSparsityPattern &);
335
336 template <typename number>
337 friend void
338 internal::reinit(MatrixBlock<dealii::SparseMatrix<number>> &v,
339 const BlockSparsityPattern & p);
340 };
341
342
343 /**
344 * A vector of MatrixBlock, which is implemented using shared pointers, in
345 * order to allow for copying and rearranging. Each matrix block can be
346 * identified by name.
347 *
348 * @relatesalso MatrixBlock
349 * @ingroup vector_valued
350 */
351 template <typename MatrixType>
352 class MatrixBlockVector : private AnyData
353 {
354 public:
355 /**
356 * Declare type for container size.
357 */
358 using size_type = types::global_dof_index;
359
360 /**
361 * The type of object stored.
362 */
363 using value_type = MatrixBlock<MatrixType>;
364
365 /**
366 * The pointer type used for storing the objects. We use a shard pointer,
367 * such that they get deleted automatically when not used anymore.
368 */
369 using ptr_type = std::shared_ptr<value_type>;
370
371 /**
372 * Add a new matrix block at the position <tt>(row,column)</tt> in the block
373 * system.
374 */
375 void
376 add(size_type row, size_type column, const std::string &name);
377
378 /**
379 * For matrices using a SparsityPattern, this function reinitializes each
380 * matrix in the vector with the correct pattern from the block system.
381 */
382 void
383 reinit(const BlockSparsityPattern &sparsity);
384
385 /**
386 * Clear the object.
387 *
388 * Since often only clearing of the individual matrices is desired, but not
389 * removing the blocks themselves, there is an optional argument. If the
390 * argument is missing or @p false, all matrices will be empty, but the size
391 * of this object and the block positions will not change. If @p
392 * really_clean is @p true, then the object will contain no blocks at the
393 * end.
394 */
395 void
396 clear(bool really_clean = false);
397
398 /**
399 * The memory used by this object.
400 */
401 std::size_t
402 memory_consumption() const;
403
404 /**
405 * Access a constant reference to the block at position <i>i</i>.
406 */
407 const value_type &
408 block(size_type i) const;
409
410 /**
411 * Access a reference to the block at position <i>i</i>.
412 */
413 value_type &
414 block(size_type i);
415
416 /**
417 * Access the matrix at position <i>i</i> for read and write access.
418 */
419 MatrixType &
420 matrix(size_type i);
421
422 /**
423 * import functions from private base class
424 */
425 using AnyData::name;
426 using AnyData::size;
427 using AnyData::subscribe;
428 using AnyData::unsubscribe;
429 };
430
431
432 /**
433 * A vector of MGLevelObject<MatrixBlock>, which is implemented using shared
434 * pointers, in order to allow for copying and rearranging. Each matrix block
435 * can be identified by name.
436 *
437 * @relatesalso MatrixBlock
438 * @ingroup vector_valued
439 */
440 template <typename MatrixType>
441 class MGMatrixBlockVector : public Subscriptor
442 {
443 public:
444 /**
445 * Declare type for container size.
446 */
447 using size_type = types::global_dof_index;
448
449 /**
450 * The type of object stored.
451 */
452 using value_type = MGLevelObject<MatrixBlock<MatrixType>>;
453 /**
454 * Constructor, determining which matrices should be stored.
455 *
456 * If <tt>edge_matrices</tt> is true, then objects for edge matrices for
457 * discretizations with degrees of freedom on faces are allocated.
458 *
459 * If <tt>edge_flux_matrices</tt> is true, then objects for DG fluxes on the
460 * refinement edge are allocated.
461 */
462 MGMatrixBlockVector(const bool edge_matrices = false,
463 const bool edge_flux_matrices = false);
464
465 /**
466 * The number of blocks.
467 */
468 unsigned int
469 size() const;
470
471 /**
472 * Add a new matrix block at the position <tt>(row,column)</tt> in the block
473 * system. The third argument allows to give the matrix a name for later
474 * identification.
475 */
476 void
477 add(size_type row, size_type column, const std::string &name);
478
479 /**
480 * For matrices using a SparsityPattern, this function reinitializes each
481 * matrix in the vector with the correct pattern from the block system.
482 *
483 * This function reinitializes the level matrices.
484 */
485 void
486 reinit_matrix(const MGLevelObject<BlockSparsityPattern> &sparsity);
487 /**
488 * For matrices using a SparsityPattern, this function reinitializes each
489 * matrix in the vector with the correct pattern from the block system.
490 *
491 * This function reinitializes the matrices for degrees of freedom on the
492 * refinement edge.
493 */
494 void
495 reinit_edge(const MGLevelObject<BlockSparsityPattern> &sparsity);
496 /**
497 * For matrices using a SparsityPattern, this function reinitializes each
498 * matrix in the vector with the correct pattern from the block system.
499 *
500 * This function reinitializes the flux matrices over the refinement edge.
501 */
502 void
503 reinit_edge_flux(const MGLevelObject<BlockSparsityPattern> &sparsity);
504
505 /**
506 * Clear the object.
507 *
508 * Since often only clearing of the individual matrices is desired, but not
509 * removing the blocks themselves, there is an optional argument. If the
510 * argument is missing or @p false, all matrices will be empty, but the size
511 * of this object and the block positions will not change. If @p
512 * really_clean is @p true, then the object will contain no blocks at the
513 * end.
514 */
515 void
516 clear(bool really_clean = false);
517
518 /**
519 * Access a constant reference to the matrix block at position <i>i</i>.
520 */
521 const value_type &
522 block(size_type i) const;
523
524 /**
525 * Access a reference to the matrix block at position <i>i</i>.
526 */
527 value_type &
528 block(size_type i);
529
530 /**
531 * Access a constant reference to the edge matrix block at position
532 * <i>i</i>.
533 */
534 const value_type &
535 block_in(size_type i) const;
536
537 /**
538 * Access a reference to the edge matrix block at position <i>i</i>.
539 */
540 value_type &
541 block_in(size_type i);
542
543 /**
544 * Access a constant reference to the edge matrix block at position
545 * <i>i</i>.
546 */
547 const value_type &
548 block_out(size_type i) const;
549
550 /**
551 * Access a reference to the edge matrix block at position <i>i</i>.
552 */
553 value_type &
554 block_out(size_type i);
555
556 /**
557 * Access a constant reference to the edge flux matrix block at position
558 * <i>i</i>.
559 */
560 const value_type &
561 block_up(size_type i) const;
562
563 /**
564 * Access a reference to the edge flux matrix block at position <i>i</i>.
565 */
566 value_type &
567 block_up(size_type i);
568
569 /**
570 * Access a constant reference to the edge flux matrix block at position
571 * <i>i</i>.
572 */
573 const value_type &
574 block_down(size_type i) const;
575
576 /**
577 * Access a reference to the edge flux matrix block at position <i>i</i>.
578 */
579 value_type &
580 block_down(size_type i);
581
582 /**
583 * The memory used by this object.
584 */
585 std::size_t
586 memory_consumption() const;
587
588 private:
589 /// Clear one of the matrix objects
590 void
591 clear_object(AnyData &);
592
593 /// Flag for storing matrices_in and matrices_out
594 const bool edge_matrices;
595
596 /// Flag for storing flux_matrices_up and flux_matrices_down
597 const bool edge_flux_matrices;
598
599 /// The level matrices
600 AnyData matrices;
601 /// The matrix from the interior of a level to the refinement edge
602 AnyData matrices_in;
603 /// The matrix from the refinement edge to the interior of a level
604 AnyData matrices_out;
605 /// The DG flux from a level to the lower level
606 AnyData flux_matrices_down;
607 /// The DG flux from the lower level to a level
608 AnyData flux_matrices_up;
609 };
610
611
612 //----------------------------------------------------------------------//
613
614 namespace internal
615 {
616 template <typename MatrixType>
617 void
reinit(MatrixBlock<MatrixType> & v,const BlockSparsityPattern & p)618 reinit(MatrixBlock<MatrixType> &v, const BlockSparsityPattern &p)
619 {
620 v.row_indices = p.get_row_indices();
621 v.column_indices = p.get_column_indices();
622 }
623
624
625 template <typename number>
626 void
reinit(MatrixBlock<dealii::SparseMatrix<number>> & v,const BlockSparsityPattern & p)627 reinit(MatrixBlock<dealii::SparseMatrix<number>> &v,
628 const BlockSparsityPattern & p)
629 {
630 v.row_indices = p.get_row_indices();
631 v.column_indices = p.get_column_indices();
632 v.matrix.reinit(p.block(v.row, v.column));
633 }
634 } // namespace internal
635
636
637 template <typename MatrixType>
MatrixBlock()638 inline MatrixBlock<MatrixType>::MatrixBlock()
639 : row(numbers::invalid_size_type)
640 , column(numbers::invalid_size_type)
641 {}
642
643
644 template <typename MatrixType>
MatrixBlock(size_type i,size_type j)645 inline MatrixBlock<MatrixType>::MatrixBlock(size_type i, size_type j)
646 : row(i)
647 , column(j)
648 {}
649
650
651 template <typename MatrixType>
652 inline void
reinit(const BlockSparsityPattern & sparsity)653 MatrixBlock<MatrixType>::reinit(const BlockSparsityPattern &sparsity)
654 {
655 internal::reinit(*this, sparsity);
656 }
657
658
659 template <typename MatrixType>
660 inline MatrixBlock<MatrixType>::operator MatrixType &()
661 {
662 return matrix;
663 }
664
665
666 template <typename MatrixType>
667 inline MatrixBlock<MatrixType>::operator const MatrixType &() const
668 {
669 return matrix;
670 }
671
672
673 template <typename MatrixType>
674 inline void
add(const size_type gi,const size_type gj,const typename MatrixType::value_type value)675 MatrixBlock<MatrixType>::add(const size_type gi,
676 const size_type gj,
677 const typename MatrixType::value_type value)
678 {
679 Assert(row_indices.size() != 0, ExcNotInitialized());
680 Assert(column_indices.size() != 0, ExcNotInitialized());
681
682 const std::pair<unsigned int, size_type> bi = row_indices.global_to_local(gi);
683 const std::pair<unsigned int, size_type> bj =
684 column_indices.global_to_local(gj);
685
686 Assert(bi.first == row, ExcBlockIndexMismatch(bi.first, row));
687 Assert(bj.first == column, ExcBlockIndexMismatch(bj.first, column));
688
689 matrix.add(bi.second, bj.second, value);
690 }
691
692
693 template <typename MatrixType>
694 template <typename number>
695 inline void
add(const std::vector<size_type> & r_indices,const std::vector<size_type> & c_indices,const FullMatrix<number> & values,const bool elide_zero_values)696 MatrixBlock<MatrixType>::add(const std::vector<size_type> &r_indices,
697 const std::vector<size_type> &c_indices,
698 const FullMatrix<number> & values,
699 const bool elide_zero_values)
700 {
701 Assert(row_indices.size() != 0, ExcNotInitialized());
702 Assert(column_indices.size() != 0, ExcNotInitialized());
703
704 AssertDimension(r_indices.size(), values.m());
705 AssertDimension(c_indices.size(), values.n());
706
707 for (size_type i = 0; i < row_indices.size(); ++i)
708 add(r_indices[i],
709 c_indices.size(),
710 c_indices.data(),
711 &values(i, 0),
712 elide_zero_values);
713 }
714
715
716 template <typename MatrixType>
717 template <typename number>
718 inline void
add(const size_type b_row,const size_type n_cols,const size_type * col_indices,const number * values,const bool,const bool)719 MatrixBlock<MatrixType>::add(const size_type b_row,
720 const size_type n_cols,
721 const size_type *col_indices,
722 const number * values,
723 const bool,
724 const bool)
725 {
726 Assert(row_indices.size() != 0, ExcNotInitialized());
727 Assert(column_indices.size() != 0, ExcNotInitialized());
728
729 const std::pair<unsigned int, size_type> bi =
730 row_indices.global_to_local(b_row);
731
732 // In debug mode, we check whether
733 // all indices are in the correct
734 // block.
735
736 // Actually, for the time being, we
737 // leave it at this. While it may
738 // not be the most efficient way,
739 // it is at least thread safe.
740 //#ifdef DEBUG
741 Assert(bi.first == row, ExcBlockIndexMismatch(bi.first, row));
742
743 for (size_type j = 0; j < n_cols; ++j)
744 {
745 const std::pair<unsigned int, size_type> bj =
746 column_indices.global_to_local(col_indices[j]);
747 Assert(bj.first == column, ExcBlockIndexMismatch(bj.first, column));
748
749 matrix.add(bi.second, bj.second, values[j]);
750 }
751 //#endif
752 }
753
754
755 template <typename MatrixType>
756 template <typename number>
757 inline void
add(const std::vector<size_type> & indices,const FullMatrix<number> & values,const bool elide_zero_values)758 MatrixBlock<MatrixType>::add(const std::vector<size_type> &indices,
759 const FullMatrix<number> & values,
760 const bool elide_zero_values)
761 {
762 Assert(row_indices.size() != 0, ExcNotInitialized());
763 Assert(column_indices.size() != 0, ExcNotInitialized());
764
765 AssertDimension(indices.size(), values.m());
766 Assert(values.n() == values.m(), ExcNotQuadratic());
767
768 for (size_type i = 0; i < indices.size(); ++i)
769 add(indices[i],
770 indices.size(),
771 indices.data(),
772 &values(i, 0),
773 elide_zero_values);
774 }
775
776
777
778 template <typename MatrixType>
779 template <typename number>
780 inline void
add(const size_type row,const std::vector<size_type> & col_indices,const std::vector<number> & values,const bool elide_zero_values)781 MatrixBlock<MatrixType>::add(const size_type row,
782 const std::vector<size_type> &col_indices,
783 const std::vector<number> & values,
784 const bool elide_zero_values)
785 {
786 Assert(row_indices.size() != 0, ExcNotInitialized());
787 Assert(column_indices.size() != 0, ExcNotInitialized());
788
789 AssertDimension(col_indices.size(), values.size());
790 add(row,
791 col_indices.size(),
792 col_indices.data(),
793 values.data(),
794 elide_zero_values);
795 }
796
797
798 template <typename MatrixType>
799 template <class VectorType>
800 inline void
vmult(VectorType & w,const VectorType & v)801 MatrixBlock<MatrixType>::vmult(VectorType &w, const VectorType &v) const
802 {
803 matrix.vmult(w, v);
804 }
805
806
807 template <typename MatrixType>
808 template <class VectorType>
809 inline void
vmult_add(VectorType & w,const VectorType & v)810 MatrixBlock<MatrixType>::vmult_add(VectorType &w, const VectorType &v) const
811 {
812 matrix.vmult_add(w, v);
813 }
814
815
816 template <typename MatrixType>
817 template <class VectorType>
818 inline void
Tvmult(VectorType & w,const VectorType & v)819 MatrixBlock<MatrixType>::Tvmult(VectorType &w, const VectorType &v) const
820 {
821 matrix.Tvmult(w, v);
822 }
823
824
825 template <typename MatrixType>
826 template <class VectorType>
827 inline void
Tvmult_add(VectorType & w,const VectorType & v)828 MatrixBlock<MatrixType>::Tvmult_add(VectorType &w, const VectorType &v) const
829 {
830 matrix.Tvmult_add(w, v);
831 }
832
833
834 template <typename MatrixType>
835 inline std::size_t
memory_consumption()836 MatrixBlock<MatrixType>::memory_consumption() const
837 {
838 return (sizeof(*this) + MemoryConsumption::memory_consumption(matrix) -
839 sizeof(matrix));
840 }
841
842 //----------------------------------------------------------------------//
843
844 template <typename MatrixType>
845 inline void
add(size_type row,size_type column,const std::string & name)846 MatrixBlockVector<MatrixType>::add(size_type row,
847 size_type column,
848 const std::string &name)
849 {
850 ptr_type p(new value_type(row, column));
851 AnyData::add(p, name);
852 }
853
854
855 template <typename MatrixType>
856 inline void
reinit(const BlockSparsityPattern & sparsity)857 MatrixBlockVector<MatrixType>::reinit(const BlockSparsityPattern &sparsity)
858 {
859 for (size_type i = 0; i < this->size(); ++i)
860 {
861 block(i).reinit(sparsity);
862 }
863 }
864
865
866 template <typename MatrixType>
867 inline void
clear(bool really_clean)868 MatrixBlockVector<MatrixType>::clear(bool really_clean)
869 {
870 if (really_clean)
871 {
872 Assert(false, ExcNotImplemented());
873 }
874 else
875 {
876 for (size_type i = 0; i < this->size(); ++i)
877 matrix(i).clear();
878 }
879 }
880
881
882
883 template <typename MatrixType>
884 inline const MatrixBlock<MatrixType> &
block(size_type i)885 MatrixBlockVector<MatrixType>::block(size_type i) const
886 {
887 return *this->read<ptr_type>(i);
888 }
889
890
891 template <typename MatrixType>
892 inline MatrixBlock<MatrixType> &
block(size_type i)893 MatrixBlockVector<MatrixType>::block(size_type i)
894 {
895 return *this->entry<ptr_type>(i);
896 }
897
898
899 template <typename MatrixType>
900 inline MatrixType &
matrix(size_type i)901 MatrixBlockVector<MatrixType>::matrix(size_type i)
902 {
903 return this->entry<ptr_type>(i)->matrix;
904 }
905
906
907
908 //----------------------------------------------------------------------//
909
910 template <typename MatrixType>
MGMatrixBlockVector(const bool e,const bool f)911 inline MGMatrixBlockVector<MatrixType>::MGMatrixBlockVector(const bool e,
912 const bool f)
913 : edge_matrices(e)
914 , edge_flux_matrices(f)
915 {}
916
917
918 template <typename MatrixType>
919 inline unsigned int
size()920 MGMatrixBlockVector<MatrixType>::size() const
921 {
922 return matrices.size();
923 }
924
925
926 template <typename MatrixType>
927 inline void
add(size_type row,size_type column,const std::string & name)928 MGMatrixBlockVector<MatrixType>::add(size_type row,
929 size_type column,
930 const std::string &name)
931 {
932 MGLevelObject<MatrixBlock<MatrixType>> p(0, 1);
933 p[0].row = row;
934 p[0].column = column;
935
936 matrices.add(p, name);
937 if (edge_matrices)
938 {
939 matrices_in.add(p, name);
940 matrices_out.add(p, name);
941 }
942 if (edge_flux_matrices)
943 {
944 flux_matrices_up.add(p, name);
945 flux_matrices_down.add(p, name);
946 }
947 }
948
949
950 template <typename MatrixType>
951 inline const MGLevelObject<MatrixBlock<MatrixType>> &
block(size_type i)952 MGMatrixBlockVector<MatrixType>::block(size_type i) const
953 {
954 return *matrices.read<const MGLevelObject<MatrixType> *>(i);
955 }
956
957
958 template <typename MatrixType>
959 inline MGLevelObject<MatrixBlock<MatrixType>> &
block(size_type i)960 MGMatrixBlockVector<MatrixType>::block(size_type i)
961 {
962 return *matrices.entry<MGLevelObject<MatrixType> *>(i);
963 }
964
965
966 template <typename MatrixType>
967 inline const MGLevelObject<MatrixBlock<MatrixType>> &
block_in(size_type i)968 MGMatrixBlockVector<MatrixType>::block_in(size_type i) const
969 {
970 return *matrices_in.read<const MGLevelObject<MatrixType> *>(i);
971 }
972
973
974 template <typename MatrixType>
975 inline MGLevelObject<MatrixBlock<MatrixType>> &
block_in(size_type i)976 MGMatrixBlockVector<MatrixType>::block_in(size_type i)
977 {
978 return *matrices_in.entry<MGLevelObject<MatrixType> *>(i);
979 }
980
981
982 template <typename MatrixType>
983 inline const MGLevelObject<MatrixBlock<MatrixType>> &
block_out(size_type i)984 MGMatrixBlockVector<MatrixType>::block_out(size_type i) const
985 {
986 return *matrices_out.read<const MGLevelObject<MatrixType> *>(i);
987 }
988
989
990 template <typename MatrixType>
991 inline MGLevelObject<MatrixBlock<MatrixType>> &
block_out(size_type i)992 MGMatrixBlockVector<MatrixType>::block_out(size_type i)
993 {
994 return *matrices_out.entry<MGLevelObject<MatrixType> *>(i);
995 }
996
997
998 template <typename MatrixType>
999 inline const MGLevelObject<MatrixBlock<MatrixType>> &
block_up(size_type i)1000 MGMatrixBlockVector<MatrixType>::block_up(size_type i) const
1001 {
1002 return *flux_matrices_up.read<const MGLevelObject<MatrixType> *>(i);
1003 }
1004
1005
1006 template <typename MatrixType>
1007 inline MGLevelObject<MatrixBlock<MatrixType>> &
block_up(size_type i)1008 MGMatrixBlockVector<MatrixType>::block_up(size_type i)
1009 {
1010 return *flux_matrices_up.entry<MGLevelObject<MatrixType> *>(i);
1011 }
1012
1013
1014 template <typename MatrixType>
1015 inline const MGLevelObject<MatrixBlock<MatrixType>> &
block_down(size_type i)1016 MGMatrixBlockVector<MatrixType>::block_down(size_type i) const
1017 {
1018 return *flux_matrices_down.read<const MGLevelObject<MatrixType> *>(i);
1019 }
1020
1021
1022 template <typename MatrixType>
1023 inline MGLevelObject<MatrixBlock<MatrixType>> &
block_down(size_type i)1024 MGMatrixBlockVector<MatrixType>::block_down(size_type i)
1025 {
1026 return *flux_matrices_down.entry<MGLevelObject<MatrixType> *>(i);
1027 }
1028
1029
1030 template <typename MatrixType>
1031 inline void
reinit_matrix(const MGLevelObject<BlockSparsityPattern> & sparsity)1032 MGMatrixBlockVector<MatrixType>::reinit_matrix(
1033 const MGLevelObject<BlockSparsityPattern> &sparsity)
1034 {
1035 for (size_type i = 0; i < this->size(); ++i)
1036 {
1037 MGLevelObject<MatrixBlock<MatrixType>> &o = block(i);
1038 const size_type row = o[o.min_level()].row;
1039 const size_type col = o[o.min_level()].column;
1040
1041 o.resize(sparsity.min_level(), sparsity.max_level());
1042 for (size_type level = o.min_level(); level <= o.max_level(); ++level)
1043 {
1044 o[level].row = row;
1045 o[level].column = col;
1046 internal::reinit(o[level], sparsity[level]);
1047 }
1048 }
1049 }
1050
1051
1052 template <typename MatrixType>
1053 inline void
reinit_edge(const MGLevelObject<BlockSparsityPattern> & sparsity)1054 MGMatrixBlockVector<MatrixType>::reinit_edge(
1055 const MGLevelObject<BlockSparsityPattern> &sparsity)
1056 {
1057 for (size_type i = 0; i < this->size(); ++i)
1058 {
1059 MGLevelObject<MatrixBlock<MatrixType>> &o = block(i);
1060 const size_type row = o[o.min_level()].row;
1061 const size_type col = o[o.min_level()].column;
1062
1063 block_in(i).resize(sparsity.min_level(), sparsity.max_level());
1064 block_out(i).resize(sparsity.min_level(), sparsity.max_level());
1065 for (size_type level = o.min_level(); level <= o.max_level(); ++level)
1066 {
1067 block_in(i)[level].row = row;
1068 block_in(i)[level].column = col;
1069 internal::reinit(block_in(i)[level], sparsity[level]);
1070 block_out(i)[level].row = row;
1071 block_out(i)[level].column = col;
1072 internal::reinit(block_out(i)[level], sparsity[level]);
1073 }
1074 }
1075 }
1076
1077
1078 template <typename MatrixType>
1079 inline void
reinit_edge_flux(const MGLevelObject<BlockSparsityPattern> & sparsity)1080 MGMatrixBlockVector<MatrixType>::reinit_edge_flux(
1081 const MGLevelObject<BlockSparsityPattern> &sparsity)
1082 {
1083 for (size_type i = 0; i < this->size(); ++i)
1084 {
1085 MGLevelObject<MatrixBlock<MatrixType>> &o = block(i);
1086 const size_type row = o[o.min_level()].row;
1087 const size_type col = o[o.min_level()].column;
1088
1089 block_up(i).resize(sparsity.min_level(), sparsity.max_level());
1090 block_down(i).resize(sparsity.min_level(), sparsity.max_level());
1091 for (size_type level = o.min_level(); level <= o.max_level(); ++level)
1092 {
1093 block_up(i)[level].row = row;
1094 block_up(i)[level].column = col;
1095 internal::reinit(block_up(i)[level], sparsity[level]);
1096 block_down(i)[level].row = row;
1097 block_down(i)[level].column = col;
1098 internal::reinit(block_down(i)[level], sparsity[level]);
1099 }
1100 }
1101 }
1102
1103
1104 template <typename MatrixType>
1105 inline void
clear_object(AnyData & mo)1106 MGMatrixBlockVector<MatrixType>::clear_object(AnyData &mo)
1107 {
1108 for (size_type i = 0; i < mo.size(); ++i)
1109 {
1110 MGLevelObject<MatrixBlock<MatrixType>> &o =
1111 mo.entry<MGLevelObject<MatrixType> *>(i);
1112 for (size_type level = o.min_level(); level <= o.max_level(); ++level)
1113 o[level].matrix.clear();
1114 }
1115 }
1116
1117
1118 template <typename MatrixType>
1119 inline void
clear(bool really_clean)1120 MGMatrixBlockVector<MatrixType>::clear(bool really_clean)
1121 {
1122 if (really_clean)
1123 {
1124 Assert(false, ExcNotImplemented());
1125 }
1126 else
1127 {
1128 clear_object(matrices);
1129 clear_object(matrices_in);
1130 clear_object(matrices_out);
1131 clear_object(flux_matrices_up);
1132 clear_object(flux_matrices_down);
1133 }
1134 }
1135
1136
1137
1138 DEAL_II_NAMESPACE_CLOSE
1139
1140 #endif
1141