deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
block_sparsity_pattern.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2000 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
14#include <deal.II/base/config.h>
15
21#include <deal.II/base/table.h>
22
28
29#include <Kokkos_Macros.hpp>
30
31#include <cstddef>
32#include <memory>
33#include <ostream>
34#include <string>
35#include <vector>
36
38
39
40template <typename SparsityPatternType>
45
46
47
48template <typename SparsityPatternType>
56
57
58
59template <typename SparsityPatternType>
63{
64 Assert(s.n_block_rows() == 0 && s.n_block_cols() == 0,
66 "This constructor can only be called if the provided argument "
67 "is the sparsity pattern for an empty matrix. This constructor can "
68 "not be used to copy-construct a non-empty sparsity pattern."));
69}
70
71
72
73template <typename SparsityPatternType>
74void
76 const size_type new_block_rows,
77 const size_type new_block_columns)
78{
79 sub_objects.reinit(0, 0);
80
81 block_rows = new_block_rows;
82 block_columns = new_block_columns;
83
84 sub_objects.reinit(block_rows, block_columns);
85 for (size_type i = 0; i < n_block_rows(); ++i)
86 for (size_type j = 0; j < n_block_cols(); ++j)
87 sub_objects[i][j] = std::make_unique<SparsityPatternType>();
88}
89
90
91template <typename SparsityPatternType>
95{
96 AssertDimension(n_block_rows(), bsp.n_block_rows());
97 AssertDimension(n_block_cols(), bsp.n_block_cols());
98 // copy objects
99 for (size_type i = 0; i < n_block_rows(); ++i)
100 for (size_type j = 0; j < n_block_cols(); ++j)
101 *sub_objects[i][j] = *bsp.sub_objects[i][j];
102 // update index objects
103 collect_sizes();
104
105 return *this;
106}
108
109
110template <typename SparsityPatternType>
113{
114 // only count in first column, since
115 // all rows should be equivalent
116 size_type count = 0;
117 for (size_type r = 0; r < n_block_rows(); ++r)
118 count += sub_objects[r][0]->n_rows();
119 return count;
120}
121
122
123
124template <typename SparsityPatternType>
127{
128 // only count in first row, since
129 // all rows should be equivalent
130 size_type count = 0;
131 for (size_type c = 0; c < n_block_cols(); ++c)
132 count += sub_objects[0][c]->n_cols();
133 return count;
134}
135
136
137
138template <typename SparsityPatternType>
139void
141{
142 SparsityPatternBase::resize(compute_n_rows(), compute_n_cols());
143
144 std::vector<size_type> row_sizes(n_block_rows());
145 std::vector<size_type> col_sizes(n_block_cols());
146
147 // first find out the row sizes
148 // from the first block column
149 for (size_type r = 0; r < n_block_rows(); ++r)
150 row_sizes[r] = sub_objects[r][0]->n_rows();
151 // then check that the following
152 // block columns have the same
153 // sizes
154 for (size_type c = 1; c < n_block_cols(); ++c)
155 for (size_type r = 0; r < n_block_rows(); ++r)
156 Assert(row_sizes[r] == sub_objects[r][c]->n_rows(),
157 ExcIncompatibleRowNumbers(r, 0, r, c));
158
159 // finally initialize the row
160 // indices with this array
161 row_indices.reinit(row_sizes);
162
163
164 // then do the same with the columns
165 for (size_type c = 0; c < n_block_cols(); ++c)
166 col_sizes[c] = sub_objects[0][c]->n_cols();
167 for (size_type r = 1; r < n_block_rows(); ++r)
168 for (size_type c = 0; c < n_block_cols(); ++c)
169 Assert(col_sizes[c] == sub_objects[r][c]->n_cols(),
170 ExcIncompatibleRowNumbers(0, c, r, c));
171
172 // finally initialize the row
173 // indices with this array
174 column_indices.reinit(col_sizes);
175
176 // Resize scratch arrays
177 block_column_indices.resize(n_block_cols());
178 counter_within_block.resize(n_block_cols());
179}
180
181
182
183template <typename SparsityPatternType>
184void
186{
187 for (size_type i = 0; i < n_block_rows(); ++i)
188 for (size_type j = 0; j < n_block_cols(); ++j)
189 sub_objects[i][j]->compress();
190}
191
192
193
194template <typename SparsityPatternType>
195bool
197{
198 for (size_type i = 0; i < n_block_rows(); ++i)
199 for (size_type j = 0; j < n_block_cols(); ++j)
200 if (sub_objects[i][j]->empty() == false)
201 return false;
202 return true;
203}
205
206
207template <typename SparsityPatternType>
210{
211 size_type max_entries = 0;
212 for (size_type block_row = 0; block_row < n_block_rows(); ++block_row)
213 {
214 size_type this_row = 0;
215 for (size_type c = 0; c < n_block_cols(); ++c)
216 this_row += sub_objects[block_row][c]->max_entries_per_row();
217
218 if (this_row > max_entries)
219 max_entries = this_row;
220 }
221 return max_entries;
222}
223
224
225
226template <typename SparsityPatternType>
229{
230 size_type count = 0;
231 for (size_type i = 0; i < n_block_rows(); ++i)
232 for (size_type j = 0; j < n_block_cols(); ++j)
233 count += sub_objects[i][j]->n_nonzero_elements();
234 return count;
235}
236
237
238
239template <typename SparsityPatternType>
240void
242{
243 size_type k = 0;
244 for (size_type ib = 0; ib < n_block_rows(); ++ib)
245 {
246 for (size_type i = 0; i < block(ib, 0).n_rows(); ++i)
247 {
248 out << '[' << i + k;
249 size_type l = 0;
250 for (size_type jb = 0; jb < n_block_cols(); ++jb)
251 {
252 const SparsityPatternType &b = block(ib, jb);
253 for (size_type j = 0; j < b.n_cols(); ++j)
254 if (b.exists(i, j))
255 out << ',' << l + j;
256 l += b.n_cols();
257 }
258 out << ']' << std::endl;
259 }
260 k += block(ib, 0).n_rows();
261 }
262}
263
264
265#ifndef DOXYGEN
266template <>
267void
269{
270 size_type k = 0;
271 for (size_type ib = 0; ib < n_block_rows(); ++ib)
272 {
273 for (size_type i = 0; i < block(ib, 0).n_rows(); ++i)
274 {
275 out << '[' << i + k;
276 size_type l = 0;
277 for (size_type jb = 0; jb < n_block_cols(); ++jb)
278 {
279 const DynamicSparsityPattern &b = block(ib, jb);
280 if (b.row_index_set().size() == 0 ||
281 b.row_index_set().is_element(i))
282 for (size_type j = 0; j < b.n_cols(); ++j)
283 if (b.exists(i, j))
284 out << ',' << l + j;
285 l += b.n_cols();
286 }
287 out << ']' << std::endl;
288 }
289 k += block(ib, 0).n_rows();
290 }
291}
292#endif
293
294
295
296template <typename SparsityPatternType>
297void
299 std::ostream &out) const
300{
301 size_type k = 0;
302 for (size_type ib = 0; ib < n_block_rows(); ++ib)
303 {
304 for (size_type i = 0; i < block(ib, 0).n_rows(); ++i)
305 {
306 size_type l = 0;
307 for (size_type jb = 0; jb < n_block_cols(); ++jb)
308 {
309 const SparsityPatternType &b = block(ib, jb);
310 for (size_type j = 0; j < b.n_cols(); ++j)
311 if (b.exists(i, j))
312 out << l + j << " " << -static_cast<signed int>(i + k)
313 << std::endl;
314 l += b.n_cols();
315 }
316 }
317 k += block(ib, 0).n_rows();
318 }
319}
320
321
322
323template <typename SparsityPatternType>
324void
326 std::ostream &out) const
327{
328 const unsigned int m = this->n_rows();
329 const unsigned int n = this->n_cols();
330 out
331 << "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 "
332 << n + 2 << " " << m + 2
333 << " \">\n"
334 "<style type=\"text/css\" >\n"
335 " <![CDATA[\n"
336 " rect.pixel {\n"
337 " fill: #ff0000;\n"
338 " }\n"
339 " ]]>\n"
340 " </style>\n\n"
341 " <rect width=\""
342 << n + 2 << "\" height=\"" << m + 2
343 << "\" fill=\"rgb(128, 128, 128)\"/>\n"
344 " <rect x=\"1\" y=\"1\" width=\""
345 << n + 0.1 << "\" height=\"" << m + 0.1
346 << "\" fill=\"rgb(255, 255, 255)\"/>\n\n";
347
348 for (unsigned int block_i = 0; block_i < n_block_rows(); ++block_i)
349 for (unsigned int block_j = 0; block_j < n_block_cols(); ++block_j)
350 for (const auto &entry : block(block_i, block_j))
351 {
352 out << " <rect class=\"pixel\" x=\""
353 << column_indices.local_to_global(block_j, entry.column()) + 1
354 << "\" y=\""
355 << row_indices.local_to_global(block_i, entry.row()) + 1
356 << "\" width=\".9\" height=\".9\"/>\n";
357 }
358
359 out << "</svg>" << std::endl;
360}
361
362
363
364template <typename SparsityPatternType>
365std::size_t
367{
368 std::size_t mem = 0;
369 mem += (MemoryConsumption::memory_consumption(n_block_rows()) +
374 for (size_type r = 0; r < n_block_rows(); ++r)
375 for (size_type c = 0; c < n_block_cols(); ++c)
376 mem += MemoryConsumption::memory_consumption(*sub_objects[r][c]);
377
378 return mem;
379}
380
381
382
384 const size_type n_columns)
385 : BlockSparsityPatternBase<SparsityPattern>(n_rows, n_columns)
386{}
387
388
389void
391 const BlockIndices &rows,
392 const BlockIndices &cols,
393 const std::vector<std::vector<unsigned int>> &row_lengths)
394{
395 AssertDimension(row_lengths.size(), cols.size());
396
397 this->reinit(rows.size(), cols.size());
398 for (size_type j = 0; j < cols.size(); ++j)
399 for (size_type i = 0; i < rows.size(); ++i)
400 {
401 const size_type start = rows.local_to_global(i, 0);
402 const size_type length = rows.block_size(i);
404 if (row_lengths[j].size() == 1)
405 block(i, j).reinit(rows.block_size(i),
406 cols.block_size(j),
407 row_lengths[j][0]);
408 else
410 Assert(row_lengths[j].begin() + start + length <=
411 row_lengths[j].end(),
414 start,
415 length);
416 block(i, j).reinit(rows.block_size(i),
417 cols.block_size(j),
418 block_rows);
419 }
420 }
421 this->collect_sizes();
422 Assert(this->row_indices == rows, ExcInternalError());
423 Assert(this->column_indices == cols, ExcInternalError());
424}
425
426
427bool
429{
430 for (size_type i = 0; i < n_block_rows(); ++i)
431 for (size_type j = 0; j < n_block_cols(); ++j)
432 if (sub_objects[i][j]->is_compressed() == false)
433 return false;
434 return true;
435}
436
437
438
439void
441{
442 // delete old content, set block
443 // sizes anew
444 reinit(dsp.n_block_rows(), dsp.n_block_cols());
445
446 // copy over blocks
447 for (size_type i = 0; i < n_block_rows(); ++i)
448 for (size_type j = 0; j < n_block_cols(); ++j)
449 block(i, j).copy_from(dsp.block(i, j));
450
451 // and finally enquire their new
452 // sizes
454}
455
456
457
463
464
465
467 const std::vector<size_type> &row_indices,
468 const std::vector<size_type> &col_indices)
470 col_indices.size())
471{
472 for (size_type i = 0; i < row_indices.size(); ++i)
473 for (size_type j = 0; j < col_indices.size(); ++j)
474 this->block(i, j).reinit(row_indices[i], col_indices[j]);
475 this->collect_sizes();
476}
477
478
479
481 const std::vector<IndexSet> &partitioning)
483 partitioning.size())
484{
485 for (size_type i = 0; i < partitioning.size(); ++i)
486 for (size_type j = 0; j < partitioning.size(); ++j)
487 this->block(i, j).reinit(partitioning[i].size(),
488 partitioning[j].size(),
489 partitioning[i]);
490 this->collect_sizes();
491}
492
493
494
496 const BlockIndices &row_indices,
497 const BlockIndices &col_indices)
498{
499 reinit(row_indices, col_indices);
500}
501
502
503
504void
506 const std::vector<size_type> &row_block_sizes,
507 const std::vector<size_type> &col_block_sizes)
508{
510 row_block_sizes.size(), col_block_sizes.size());
511 for (size_type i = 0; i < row_block_sizes.size(); ++i)
512 for (size_type j = 0; j < col_block_sizes.size(); ++j)
513 this->block(i, j).reinit(row_block_sizes[i], col_block_sizes[j]);
514 this->collect_sizes();
515}
516
517
518
519void
520BlockDynamicSparsityPattern::reinit(const std::vector<IndexSet> &partitioning)
521{
523 partitioning.size());
524 for (size_type i = 0; i < partitioning.size(); ++i)
525 for (size_type j = 0; j < partitioning.size(); ++j)
526 this->block(i, j).reinit(partitioning[i].size(),
527 partitioning[j].size(),
528 partitioning[i]);
529 this->collect_sizes();
530}
531
532
533
534void
536 const BlockIndices &col_indices)
537{
539 col_indices.size());
540 for (size_type i = 0; i < row_indices.size(); ++i)
541 for (size_type j = 0; j < col_indices.size(); ++j)
542 this->block(i, j).reinit(row_indices.block_size(i),
543 col_indices.block_size(j));
544 this->collect_sizes();
545}
546
547
548#ifdef DEAL_II_TRILINOS_WITH_EPETRA
549namespace TrilinosWrappers
550{
552 const size_type n_columns)
553 : ::BlockSparsityPatternBase<SparsityPattern>(n_rows, n_columns)
554 {}
555
556
557
559 const std::vector<size_type> &row_indices,
560 const std::vector<size_type> &col_indices)
562 col_indices.size())
563 {
564 for (size_type i = 0; i < row_indices.size(); ++i)
565 for (size_type j = 0; j < col_indices.size(); ++j)
566 this->block(i, j).reinit(row_indices[i], col_indices[j], 0);
567 this->collect_sizes();
568 }
569
570
571
573 const std::vector<IndexSet> &parallel_partitioning,
574 const MPI_Comm communicator)
575 : BlockSparsityPatternBase<SparsityPattern>(parallel_partitioning.size(),
576 parallel_partitioning.size())
577 {
578 for (size_type i = 0; i < parallel_partitioning.size(); ++i)
579 for (size_type j = 0; j < parallel_partitioning.size(); ++j)
580 this->block(i, j).reinit(parallel_partitioning[i],
581 parallel_partitioning[j],
582 communicator,
583 0);
584 this->collect_sizes();
585 }
586
587
588
590 const std::vector<IndexSet> &row_parallel_partitioning,
591 const std::vector<IndexSet> &col_parallel_partitioning,
592 const std::vector<IndexSet> &writable_rows,
593 const MPI_Comm communicator)
595 row_parallel_partitioning.size(),
596 col_parallel_partitioning.size())
597 {
598 for (size_type i = 0; i < row_parallel_partitioning.size(); ++i)
599 for (size_type j = 0; j < col_parallel_partitioning.size(); ++j)
600 this->block(i, j).reinit(row_parallel_partitioning[i],
601 col_parallel_partitioning[j],
602 writable_rows[i],
603 communicator,
604 0);
605 this->collect_sizes();
606 }
607
608
609
610 void
611 BlockSparsityPattern::reinit(const std::vector<size_type> &row_block_sizes,
612 const std::vector<size_type> &col_block_sizes)
613 {
615 row_block_sizes.size(), col_block_sizes.size());
616 for (size_type i = 0; i < row_block_sizes.size(); ++i)
617 for (size_type j = 0; j < col_block_sizes.size(); ++j)
618 this->block(i, j).reinit(row_block_sizes[i], col_block_sizes[j], 0);
619 this->collect_sizes();
620 }
621
622
623
624 void
626 const std::vector<IndexSet> &parallel_partitioning,
627 const MPI_Comm communicator)
628 {
630 parallel_partitioning.size(), parallel_partitioning.size());
631 for (size_type i = 0; i < parallel_partitioning.size(); ++i)
632 for (size_type j = 0; j < parallel_partitioning.size(); ++j)
633 this->block(i, j).reinit(parallel_partitioning[i],
634 parallel_partitioning[j],
635 communicator,
636 0);
637 this->collect_sizes();
638 }
639
640
641
642 void
644 const std::vector<IndexSet> &row_parallel_partitioning,
645 const std::vector<IndexSet> &col_parallel_partitioning,
646 const MPI_Comm communicator)
647 {
649 row_parallel_partitioning.size(), col_parallel_partitioning.size());
650 for (size_type i = 0; i < row_parallel_partitioning.size(); ++i)
651 for (size_type j = 0; j < col_parallel_partitioning.size(); ++j)
652 this->block(i, j).reinit(row_parallel_partitioning[i],
653 col_parallel_partitioning[j],
654 communicator,
655 0);
656 this->collect_sizes();
657 }
658
659
660
661 void
663 const std::vector<IndexSet> &row_parallel_partitioning,
664 const std::vector<IndexSet> &col_parallel_partitioning,
665 const std::vector<IndexSet> &writable_rows,
666 const MPI_Comm communicator)
667 {
668 AssertDimension(writable_rows.size(), row_parallel_partitioning.size());
670 row_parallel_partitioning.size(), col_parallel_partitioning.size());
671 for (size_type i = 0; i < row_parallel_partitioning.size(); ++i)
672 for (size_type j = 0; j < col_parallel_partitioning.size(); ++j)
673 this->block(i, j).reinit(row_parallel_partitioning[i],
674 col_parallel_partitioning[j],
675 writable_rows[i],
676 communicator,
677 0);
678 this->collect_sizes();
679 }
680
681} // namespace TrilinosWrappers
682
683#endif
684
687#ifdef DEAL_II_TRILINOS_WITH_EPETRA
689#endif
690
*  iterator end()
*  *  iterator begin()
void reinit(const std::vector< size_type > &row_block_sizes, const std::vector< size_type > &col_block_sizes)
size_type block_size(const unsigned int i) const
unsigned int size() const
void print_gnuplot(std::ostream &out) const
Table< 2, std::unique_ptr< SparsityPatternType > > sub_objects
SparsityPattern & block(const size_type row, const size_type column)
void print(std::ostream &out) const
std::size_t memory_consumption() const
void print_svg(std::ostream &out) const
void reinit(const size_type n_block_rows, const size_type n_block_columns)
BlockSparsityPatternBase & operator=(const BlockSparsityPatternBase &)
void copy_from(const BlockDynamicSparsityPattern &dsp)
void reinit(const size_type n_block_rows, const size_type n_block_columns)
BlockSparsityPattern()=default
void reinit(const size_type m, const size_type n, const IndexSet &rowset=IndexSet())
virtual void resize(const size_type rows, const size_type cols)
void reinit(const size_type m, const size_type n, const ArrayView< const unsigned int > &row_lengths)
void copy_from(const size_type n_rows, const size_type n_cols, const ForwardIterator begin, const ForwardIterator end)
void reinit(const std::vector< size_type > &row_block_sizes, const std::vector< size_type > &col_block_sizes)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< index_type > data
Definition mpi.cc:734
std::size_t size
Definition mpi.cc:733
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)