FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
test_matrix_factory.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include <iostream>
10#include <kernel/lafem/dense_matrix.hpp>
11#include <kernel/lafem/sparse_matrix_csr.hpp>
12#include <kernel/lafem/sparse_matrix_bcsr.hpp>
13#include <kernel/adjacency/dynamic_graph.hpp>
14#include <kernel/adjacency/graph.hpp>
15#include <kernel/util/random.hpp>
16
17namespace FEAT
18{
19 namespace LAFEM
20 {
24 enum class TestMatrixFlags : int
25 {
27 generic = 0x00,
29 symmetric_struct = 0x01,
31 symmetric = 0x02,
33 non_negative = 0x04,
35 non_empty_rows = 0x08,
37 non_empty_cols = 0x10,
39 non_empty_diag = 0x20,
41 non_zero_diag = 0x20,
44 };
45
48 {
49 return static_cast<TestMatrixFlags>(static_cast<int>(a) & static_cast<int>(b));
50 }
51
54 {
55 return static_cast<TestMatrixFlags>(static_cast<int>(a) | static_cast<int>(b));
56 }
57
60 {
61 return static_cast<int>(a & b) != 0;
62 }
63
65 {
66 public:
67 Random rng;
68
69 TestMatrixFactory() = default;
70
71 Random::SeedType get_rng_seed() const
72 {
73 return rng.get_seed();
74 }
75
94 template<typename DT_, typename IT_>
95 void create(SparseMatrixCSR<DT_, IT_>& matrix, Index nrows, Index ncols, Index nnze, TestMatrixFlags flags)
96 {
98 {
99 _create_non_empty_diag_struct(matrix, nrows, ncols, nnze);
102 }
103 else if(flags * (TestMatrixFlags::non_negative) && flags * (TestMatrixFlags::symmetric))
104 {
105 _create_symmetric_struct(matrix, nrows, ncols, nnze);
108 }
109 else if(flags * TestMatrixFlags::symmetric_struct)
110 {
111 _create_symmetric_struct(matrix, nrows, ncols, nnze);
112 _fill_generic_values(matrix);
113 }
114 else if(flags * TestMatrixFlags::symmetric)
115 {
116 _create_symmetric_struct(matrix, nrows, ncols, nnze);
117 _fill_generic_values(matrix);
119 }
120 else if(flags * TestMatrixFlags::non_negative)
121 {
122 _create_generic_struct(matrix, nrows, ncols, nnze);
124 }
125 else if(flags * TestMatrixFlags::non_empty_diag)
126 {
127 _create_non_empty_diag_struct(matrix, nrows, ncols, nnze);
128 _fill_generic_values(matrix);
129 }
130 else if(flags * TestMatrixFlags::non_zero_diag)
131 {
132 _create_non_empty_diag_struct(matrix, nrows, ncols, nnze);
133 _fill_generic_values(matrix);
134 _make_non_zero_diag(matrix);
135 }
137 {
138 _create_non_empty_diag_struct(matrix, nrows, ncols, nnze);
139 _fill_generic_values(matrix);
141 }
142 else
143 {
144 _create_generic_struct(matrix, nrows, ncols, nnze);
145 _fill_generic_values(matrix);
146 }
147 }
148
166 template<typename DT_, typename IT_, int BlockHeight_, int BlockWidth_>
168 {
170 {
171 _create_non_empty_diag_struct(matrix, nrows, ncols, nnze);
174 }
175 else if(flags * (TestMatrixFlags::non_negative) && flags * (TestMatrixFlags::symmetric))
176 {
177 _create_symmetric_struct(matrix, nrows, ncols, nnze);
180 }
181 else if(flags * TestMatrixFlags::symmetric_struct)
182 {
183 _create_symmetric_struct(matrix, nrows, ncols, nnze);
184 _fill_generic_values(matrix);
185 }
186 else if(flags * TestMatrixFlags::symmetric)
187 {
188 _create_symmetric_struct(matrix, nrows, ncols, nnze);
189 _fill_generic_values(matrix);
191 }
192 else if(flags * TestMatrixFlags::non_negative)
193 {
194 _create_generic_struct(matrix, nrows, ncols, nnze);
196 }
197 else if(flags * TestMatrixFlags::non_empty_diag)
198 {
199 _create_non_empty_diag_struct(matrix, nrows, ncols, nnze);
200 _fill_generic_values(matrix);
201 }
202 else if(flags * TestMatrixFlags::non_zero_diag)
203 {
204 _create_non_empty_diag_struct(matrix, nrows, ncols, nnze);
205 _fill_generic_values(matrix);
206 _make_non_zero_diag(matrix);
207 }
209 {
210 _create_non_empty_diag_struct(matrix, nrows, ncols, nnze);
211 _fill_generic_values(matrix);
213 }
214 else
215 {
216 _create_generic_struct(matrix, nrows, ncols, nnze);
217 _fill_generic_values(matrix);
218 }
219 }
220
221 protected:
238 {
239 XASSERT(nrows > 0u);
240 XASSERT(ncols > 0u);
241 XASSERT(nnze <= nrows * ncols);
242 Adjacency::DynamicGraph dygraph(nrows, ncols);
243 Index nm = nrows * ncols - Index(1);
244 while(dygraph.get_num_indices() < nnze)
245 {
246 Index k = rng(Index(0), nm);
247 dygraph.insert(k / ncols, k % ncols);
248 }
250 return graph;
251 }
252
253 template<typename DT_, typename IT_>
254 void _create_generic_struct(SparseMatrixCSR<DT_, IT_>& matrix, Index nrows, Index ncols, Index nnze)
255 {
256 matrix = SparseMatrixCSR<DT_, IT_>(_create_generic_struct(nrows, ncols, nnze));
257 }
258
274 template<typename DT_, typename IT_, int BlockHeight_, int BlockWidth_>
276 {
278 }
279
300 XASSERT(nrows > 0u);
301 XASSERT(ncols > 0u);
302 XASSERT(nrows == ncols);
303 XASSERT(nnze <= nrows * ncols);
304 Adjacency::DynamicGraph dygraph(nrows, ncols);
305 Index nm = nrows * ncols - Index(1);
306 while(dygraph.get_num_indices() < nnze)
307 {
308 Index k = rng(Index(0), nm);
309 dygraph.insert(k / ncols, k % ncols);
310 dygraph.insert(k % ncols, k / ncols);
311 }
313 return graph;
314 }
315
316 template<typename DT_, typename IT_>
317 void _create_symmetric_struct(SparseMatrixCSR<DT_, IT_>& matrix, Index nrows, Index ncols, Index nnze)
318 {
319 matrix = SparseMatrixCSR<DT_, IT_>(_create_symmetric_struct(nrows, ncols, nnze));
320 }
321
340 template<typename DT_, typename IT_, int BlockHeight_, int BlockWidth_>
342 {
343 XASSERT(BlockWidth_ == BlockHeight_);
345 }
346
365 XASSERT(nrows > 0u);
366 XASSERT(ncols > 0u);
367 XASSERT(nrows == ncols);
368 XASSERT(nnze <= nrows * ncols);
369 XASSERT(nnze >= ncols);
370 Adjacency::DynamicGraph dygraph(nrows, ncols);
371 Index nm = nrows * ncols - Index(1);
372 for(Index i(0); i < ncols; ++i)
373 {
374 dygraph.insert(i, i);
375 }
376
377 while(dygraph.get_num_indices() < nnze)
378 {
379 Index k = rng(Index(0), nm);
380 dygraph.insert(k / ncols, k % ncols);
381 }
383 return graph;
384 }
385
386 template<typename DT_, typename IT_>
388 {
389 matrix = SparseMatrixCSR<DT_, IT_>(_create_non_empty_diag_struct(nrows, ncols, nnze));
390 }
391
409 template<typename DT_, typename IT_, int BlockHeight_, int BlockWidth_>
411 {
412 XASSERT(BlockWidth_ == BlockHeight_);
414 }
415
423 template<typename DT_, typename IT_>
425 {
426 DT_* values = matrix.val();
427 const Index nnze = matrix.used_elements();
428 for(Index i(0); i < nnze; ++i)
429 values[i] = rng(-DT_(1), DT_(1));
430 }
431
439 template<typename DT_, typename IT_, int BlockHeight_, int BlockWidth_>
441 {
442 auto * values = matrix.val();
443 const Index nnze = matrix.used_elements();
444 for(Index i(0); i < nnze; ++i)
445 for(int j(0); j < BlockHeight_; ++j)
446 for(int k(0); k< BlockWidth_; ++k)
447 values[i][j][k] = rng(-DT_(1), DT_(1));
448 }
449
457 template<typename DT_, typename IT_>
459 {
460 DT_* values = matrix.val();
461 const Index nnze = matrix.used_elements();
462 for(Index i(0); i < nnze; ++i)
463 values[i] = rng(DT_(0), DT_(1));
464 }
465
473 template<typename DT_, typename IT_, int BlockHeight_, int BlockWidth_>
475 {
476 auto* values = matrix.val();
477 const Index nnze = matrix.used_elements();
478 for(Index i(0); i < nnze; ++i)
479 for(int j(0); j < BlockHeight_; ++j)
480 for(int k(0); k< BlockWidth_; ++k)
481 values[i][j][k] = rng(DT_(0), DT_(1));
482 }
483
494 template<typename DT_, typename IT_>
496 {
497 DT_* values = matrix.val();
498 const Index nrows = matrix.rows();
499 const IT_ * col_idx = matrix.col_ind();
500 const IT_ * row_ptr = matrix.row_ptr();
501
502 for (Index i = 0; i < nrows; ++i)
503 {
504 for (IT_ j = row_ptr[i]; j < row_ptr[i + 1]; ++j)
505 {
506 Index col_j = col_idx[j];
507 if(col_j > i)
508 break;
509 else
510 {
511 for (IT_ k = row_ptr[col_j]; k < row_ptr[col_j + 1]; ++k)
512 {
513 if (col_idx[k] == i)
514 {
515 values[k] = values[j];
516 break;
517 }
518 }
519 }
520 }
521 }
522 }
523
534 template<typename DT_, typename IT_, int BlockHeight_, int BlockWidth_>
536 {
537 auto* values = matrix.val();
538 const IT_* col_idx = matrix.col_ind();
539 const IT_* row_ptr = matrix.row_ptr();
540 const Index nrows = matrix.rows();
541
542 for (Index i = 0; i < nrows; ++i) {
543 for (IT_ j = row_ptr[i]; j < row_ptr[i + 1]; ++j) {
544 Index col_j = col_idx[j];
545 if(col_j > i)
546 break;
547 else
548 {
549 for (IT_ k = row_ptr[col_j]; k < row_ptr[col_j + 1]; ++k)
550 {
551 if (col_idx[k] == i)
552 {
553 for (int l = 0; l < BlockHeight_; ++l)
554 {
555 for (int m = 0; m < BlockWidth_; ++m)
556 {
557 values[k][m][l] = values[j][l][m];
558 }
559 }
560 break;
561 }
562 }
563 }
564 }
565 }
566 }
567
578 template<typename DT_, typename IT_>
580 {
581 DT_* values = matrix.val();
582 const IT_* col_idx = matrix.col_ind();
583 const IT_* row_ptr = matrix.row_ptr();
584 const Index nrows = matrix.rows();
585
586 for(Index i = 0; i < nrows; ++i)
587 {
588 for(IT_ j = row_ptr[i]; j < row_ptr[i+1]; ++j)
589 {
590 if(col_idx[j] == i) // Check if this is a diagonal element
591 {
592 values[j] = rng(DT_(0.1), DT_(1));
593 break;
594 }
595 }
596 }
597 }
598
609 template<typename DT_, typename IT_, int BlockHeight_, int BlockWidth_>
611 {
612 auto* values = matrix.val();
613 const IT_* col_idx = matrix.col_ind();
614 const IT_* row_ptr = matrix.row_ptr();
615 const Index nrows = matrix.rows();
616
617 for(Index i = 0; i < nrows; ++i)
618 {
619 for(IT_ j = row_ptr[i]; j < row_ptr[i+1]; ++j)
620 {
621 if(col_idx[j] == i) // Check if this is a diagonal element
622 {
623 for(int l(0); l < BlockHeight_; ++l)
624 values[j][l][l] = rng(DT_(0.1), DT_(1));
625 break;
626 }
627 }
628 }
629 }
630
641 template<typename DT_, typename IT_>
643 {
644 DT_* values = matrix.val();
645 const IT_* col_idx = matrix.col_ind();
646 const IT_* row_ptr = matrix.row_ptr();
647 const Index nrows = matrix.rows();
648
649 for(Index i = 0; i < nrows; ++i)
650 {
651 DT_ off_diagonal = 0;
652 for(IT_ j = row_ptr[i]; j < row_ptr[i + 1]; ++j)
653 {
654 if(col_idx[j] != i) // Skip the diagonal element
655 {
656 off_diagonal += std::abs(values[j]);
657 }
658 }
659
660 for(IT_ j = row_ptr[i]; j < row_ptr[i + 1]; ++j)
661 {
662 if(col_idx[j] == i) // Check if this is the diagonal element
663 {
664 values[j] = off_diagonal + rng(DT_(0.1), DT_(1)); // Set diagonal value and ensure it's greater than the sum of off-diagonal elements
665 break;
666 }
667 }
668 }
669 }
670
681 template<typename DT_, typename IT_, int BlockHeight_, int BlockWidth_>
683 {
684 auto* values = matrix.val();
685 const IT_* col_idx = matrix.col_ind();
686 const IT_* row_ptr = matrix.row_ptr();
687 const Index nrows = matrix.rows();
688
689 for(Index i = 0; i < nrows; ++i)
690 {
691 DT_ off_diagonal = 0;
692 for(IT_ j = row_ptr[i]; j < row_ptr[i + 1]; ++j)
693 {
694 if(col_idx[j] != i) // Skip the diagonal element
695 {
696 for(int k(0); k < BlockWidth_; ++k)
697 {
698 for(int l(0); l < BlockHeight_; ++l)
699 {
700 off_diagonal += std::abs(values[j][k][l]);
701 }
702 }
703 }
704 else
705 {
706 for(int k(0); k < BlockWidth_; ++k)
707 {
708 for(int l(0); l < BlockHeight_; ++l)
709 {
710 if(k != l)
711 off_diagonal += std::abs(values[j][k][l]);
712 }
713 }
714 }
715 }
716
717 for(IT_ j = row_ptr[i]; j < row_ptr[i + 1]; ++j)
718 {
719 if(col_idx[j] == i) // Check if this is the diagonal element
720 {
721 for(int k(0); k < BlockWidth_; ++k)
722 values[j][k][k] = off_diagonal + rng(DT_(0.1), DT_(1)); // Set diagonal value and ensure it's greater than the sum of off-diagonal elements
723 break;
724 }
725 }
726 }
727 }
728 }; // class TestMatrixFactory
729 } // namespace LAFEM
730} // namespace FEAT
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
Dynamic Adjacency Graph implementation.
bool insert(Index domain_node, Index image_node)
Inserts a new adjacency entry to the graph.
Index get_num_indices() const
Returns the total number of indices.
Adjacency Graph implementation.
Definition: graph.hpp:34
CSR based blocked sparse matrix.
Index rows() const
Retrieve matrix row count.
IT_ * col_ind()
Retrieve column indices array.
IT_ * row_ptr()
Retrieve row start index array.
Index used_elements() const
Retrieve non zero element count.
auto val() const -> const typename Intern::BCSRPerspectiveHelper< DT_, BlockHeight_, BlockWidth_, perspective_ >::Type *
Retrieve non zero element array.
CSR based sparse matrix.
IT_ * col_ind()
Retrieve column indices array.
DT_ * val()
Retrieve non zero element array.
Index rows() const
Retrieve matrix row count.
Index used_elements() const
Retrieve non zero element count.
IT_ * row_ptr()
Retrieve row start index array.
Adjacency::Graph _create_non_empty_diag_struct(Index nrows, Index ncols, Index nnze)
Creates a non empty diagonal sparse matrix structure in CSR format based on the specified dimensions ...
void _make_diagonal_dominant(SparseMatrixCSR< DT_, IT_ > &matrix)
Ensures that a sparse matrix in CSR format is diagonal dominant.
void create(SparseMatrixBCSR< DT_, IT_, BlockHeight_, BlockWidth_ > &matrix, Index nrows, Index ncols, Index nnze, TestMatrixFlags flags)
Creates a sparse matrix in BCSR format with various properties based on the specified flags.
void create(SparseMatrixCSR< DT_, IT_ > &matrix, Index nrows, Index ncols, Index nnze, TestMatrixFlags flags)
Creates a sparse matrix in CSR format with various properties based on the specified flags.
void _make_symmetric_values(SparseMatrixBCSR< DT_, IT_, BlockHeight_, BlockWidth_ > &matrix)
Ensures that the values of a sparse matrix in BCSR format are symmetric.
void _fill_generic_values(SparseMatrixCSR< DT_, IT_ > &matrix)
Fills the values of a sparse matrix in CSR format with random values between -1 and 1.
void _create_non_empty_diag_struct(SparseMatrixBCSR< DT_, IT_, BlockHeight_, BlockWidth_ > &matrix, Index nrows, Index ncols, Index nnze)
Creates a non empty diagonal sparse matrix structure in BCSR format based on the specified dimensions...
void _make_diagonal_dominant(SparseMatrixBCSR< DT_, IT_, BlockHeight_, BlockWidth_ > &matrix)
Ensures that a sparse matrix in BCSR format is diagonal dominant.
void _fill_non_negative_values(SparseMatrixCSR< DT_, IT_ > &matrix)
Fills the values of a sparse matrix in CSR format with random non negative values between 0 and 1.
void _fill_non_negative_values(SparseMatrixBCSR< DT_, IT_, BlockHeight_, BlockWidth_ > &matrix)
Fills the values of a sparse matrix in BCSR format with random non negative values between 0 and 1.
Adjacency::Graph _create_generic_struct(Index nrows, Index ncols, Index nnze)
Creates a generic sparse matrix structure in CSR format based on the specified dimensions and non-zer...
void _create_symmetric_struct(SparseMatrixBCSR< DT_, IT_, BlockHeight_, BlockWidth_ > &matrix, Index nrows, Index ncols, Index nnze)
Creates a symmetric sparse matrix structure in BCSR format based on the specified dimensions and non-...
void _make_symmetric_values(SparseMatrixCSR< DT_, IT_ > &matrix)
Ensures that the values of a sparse matrix in CSR format are symmetric.
void _make_non_zero_diag(SparseMatrixCSR< DT_, IT_ > &matrix)
Ensures that the diagonal entries of a sparse matrix in CSR format are non-zero.
void _make_non_zero_diag(SparseMatrixBCSR< DT_, IT_, BlockHeight_, BlockWidth_ > &matrix)
Ensures that the diagonal entries of a sparse matrix in BCSR format are non-zero.
Adjacency::Graph _create_symmetric_struct(Index nrows, Index ncols, Index nnze)
Creates a symmetric sparse matrix structure in CSR format based on the specified dimensions and non-z...
void _fill_generic_values(SparseMatrixBCSR< DT_, IT_, BlockHeight_, BlockWidth_ > &matrix)
Fills the values of a sparse matrix in BCSR format with random values between -1 and 1.
void _create_generic_struct(SparseMatrixBCSR< DT_, IT_, BlockHeight_, BlockWidth_ > &matrix, Index nrows, Index ncols, Index nnze)
Creates a generic sparse matrix structure in BCSR format based on the specified dimensions and non-ze...
Pseudo-Random Number Generator.
Definition: random.hpp:54
std::uint64_t SeedType
seed type
Definition: random.hpp:57
SeedType get_seed() const
Definition: random.hpp:95
@ as_is
Render-As-Is mode.
TestMatrixFlags
Flags for desired test matrix.
@ non_zero_diag
all main diagonal entries non-zero
@ non_empty_diag
all main diagonal entries non-empty
@ diagonal_dominant
diagonal dominant matrix
@ generic
generic matrix without special properties, values in range [-1,+1]
@ non_empty_cols
all columns non-empty
@ non_negative
all values non-negative, i.e. values in range [0,1]
@ symmetric_struct
matrix with symmetric structure
@ non_empty_rows
all rows non-empty
@ symmetric
matrix with symmetric structure and values
bool operator*(TestMatrixFlags a, TestMatrixFlags b)
checks whether a & b != 0
CompressionModes operator&(CompressionModes a, CompressionModes b)
bit-wise AND operator for CompressionModes
Definition: base.hpp:111
CompressionModes operator|(CompressionModes a, CompressionModes b)
bit-wise OR operator for Pack::Type
Definition: base.hpp:117
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.