Loading...
Searching...
No Matches
debug_sparse_assembly.hpp
Go to the documentation of this file.
1
2#pragma once
3
7
9
10/// @brief Assembles a VectorQ1Scalar into a Eigen::SparseVector. Likely not efficient - only use for debugging.
11/// @note Only works in the serial case and on host space (only for debugging!).
12template < typename ScalarType >
13Eigen::SparseVector< ScalarType > debug_sparse_assembly_vector_vec_q1_scalar( const VectorQ1Scalar< double >& vec )
14{
15 if ( mpi::num_processes() != 1 )
16 {
17 throw std::runtime_error( "debug_sparse_assembly_vector_vec_q1_scalar: only works in serial case" );
18 }
19
20 if ( !vec.grid_data().is_hostspace )
21 {
22 throw std::runtime_error( "debug_sparse_assembly_vector_vec_q1_scalar: vec must be on host space" );
23 }
24
25 const auto rows = kernels::common::count_masked< long >( vec.mask_data(), grid::NodeOwnershipFlag::OWNED );
26
27 Eigen::SparseVector< ScalarType > result( rows );
28
29 int row = 0;
30
31 for ( int idx_0 = 0; idx_0 < vec.grid_data().extent( 0 ); ++idx_0 )
32 {
33 for ( int idx_1 = 0; idx_1 < vec.grid_data().extent( 1 ); ++idx_1 )
34 {
35 for ( int idx_2 = 0; idx_2 < vec.grid_data().extent( 2 ); ++idx_2 )
36 {
37 for ( int idx_3 = 0; idx_3 < vec.grid_data().extent( 3 ); ++idx_3 )
38 {
40 vec.mask_data()( idx_0, idx_1, idx_2, idx_3 ), grid::NodeOwnershipFlag::OWNED ) )
41 {
42 continue;
43 }
44
45 const auto value = vec.grid_data()( idx_0, idx_1, idx_2, idx_3 );
46 if ( value != 0.0 )
47 {
48 result.insert( row ) = value;
49 }
50
51 row++;
52 }
53 }
54 }
55 }
56
57 return result;
58}
59
60/// @brief Brute force sparse matrix assembly for debugging purposes.
61///
62/// Let the operator be representable by a nxm matrix. The assembly involves m matrix-vector multiplications, one with
63/// each of the standard basis vectors {e^1, ..., e^m} of R^m (per matrix-vector multiplication one column of the
64/// operator is 'assembled').
65///
66/// Needless to say, this is a very inefficient but flexible approach as any kind of operator can be assembled easily,
67/// but it involves many (n) matrix-vector multiplications.
68///
69/// @note ONLY FOR TESTING/DEBUGGING PURPOSES - EXPECTED TO BE EXTREMELY SLOW
70/// @note Only works when running in host space, in serial.
71template < OperatorLike Operator >
73 const grid::shell::DistributedDomain& domain_src,
74 Operator& A,
77{
78 static_assert( std::is_same_v< SrcOf< Operator >, VectorQ1Scalar< double > > );
79 static_assert( std::is_same_v< DstOf< Operator >, VectorQ1Scalar< double > > );
80
81 if ( mpi::num_processes() != 1 )
82 {
83 throw std::runtime_error( "debug_sparse_assembly_operator_vec_q1_scalar: only works in serial case" );
84 }
85
86 if ( !tmp_src.grid_data().is_hostspace )
87 {
88 throw std::runtime_error( "debug_sparse_assembly_vec_q1_scalar: tmp_src must be on host space" );
89 }
90
91 const auto rows = kernels::common::count_masked< long >( tmp_dst.mask_data(), grid::NodeOwnershipFlag::OWNED );
92 const auto cols = kernels::common::count_masked< long >( tmp_src.mask_data(), grid::NodeOwnershipFlag::OWNED );
93
94 Eigen::SparseMatrix< double > mat( rows, cols );
95
96 assign( tmp_src, 0.0 );
97
98 int A_col = 0;
99
100 for ( int idx_0 = 0; idx_0 < tmp_src.grid_data().extent( 0 ); ++idx_0 )
101 {
102 for ( int idx_1 = 0; idx_1 < tmp_src.grid_data().extent( 1 ); ++idx_1 )
103 {
104 for ( int idx_2 = 0; idx_2 < tmp_src.grid_data().extent( 2 ); ++idx_2 )
105 {
106 for ( int idx_3 = 0; idx_3 < tmp_src.grid_data().extent( 3 ); ++idx_3 )
107 {
109 tmp_src.mask_data()( idx_0, idx_1, idx_2, idx_3 ), grid::NodeOwnershipFlag::OWNED ) )
110 {
111 continue;
112 }
113
114 assign( tmp_src, 0.0 );
115 tmp_src.grid_data()( idx_0, idx_1, idx_2, idx_3 ) = 1.0;
116
119
120 linalg::apply( A, tmp_src, tmp_dst );
121
122 int A_row = 0;
123
124 for ( int iidx_0 = 0; iidx_0 < tmp_dst.grid_data().extent( 0 ); ++iidx_0 )
125 {
126 for ( int iidx_1 = 0; iidx_1 < tmp_dst.grid_data().extent( 1 ); ++iidx_1 )
127 {
128 for ( int iidx_2 = 0; iidx_2 < tmp_dst.grid_data().extent( 2 ); ++iidx_2 )
129 {
130 for ( int iidx_3 = 0; iidx_3 < tmp_dst.grid_data().extent( 3 ); ++iidx_3 )
131 {
133 tmp_dst.mask_data()( iidx_0, iidx_1, iidx_2, iidx_3 ),
135 {
136 continue;
137 }
138
139 const auto value = tmp_dst.grid_data()( iidx_0, iidx_1, iidx_2, iidx_3 );
140 if ( value != 0.0 )
141 {
142 mat.insert( A_row, A_col ) =
143 tmp_dst.grid_data()( iidx_0, iidx_1, iidx_2, iidx_3 );
144 }
145
146 A_row++;
147 }
148 }
149 }
150 }
151
152 A_col++;
153 }
154 }
155 }
156 }
157
158 mat.makeCompressed();
159 return mat;
160}
161
162} // namespace terra::linalg::util
Parallel data structure organizing the thick spherical shell metadata for distributed (MPI parallel) ...
Definition spherical_shell.hpp:2498
Q1 scalar finite element vector on a distributed shell grid.
Definition vector_q1.hpp:21
const grid::Grid4DDataScalar< ScalarType > & grid_data() const
Get const reference to grid data.
Definition vector_q1.hpp:137
const grid::Grid4DDataScalar< grid::NodeOwnershipFlag > & mask_data() const
Get const reference to mask data.
Definition vector_q1.hpp:142
void send_recv(const grid::shell::DistributedDomain &domain, grid::Grid4DDataScalar< ScalarType > &grid, const CommunicationReduction reduction=CommunicationReduction::SUM)
Executes packing, sending, receiving, and unpacking operations for the shell.
Definition communication.hpp:750
@ MAX
Stores the max of all received values during receive.
Definition debug_sparse_assembly.hpp:8
Eigen::SparseMatrix< double > debug_sparse_assembly_operator_vec_q1_scalar(const grid::shell::DistributedDomain &domain_src, Operator &A, VectorQ1Scalar< double > &tmp_src, VectorQ1Scalar< double > &tmp_dst)
Brute force sparse matrix assembly for debugging purposes.
Definition debug_sparse_assembly.hpp:72
Eigen::SparseVector< ScalarType > debug_sparse_assembly_vector_vec_q1_scalar(const VectorQ1Scalar< double > &vec)
Assembles a VectorQ1Scalar into a Eigen::SparseVector. Likely not efficient - only use for debugging.
Definition debug_sparse_assembly.hpp:13
void apply(LinearForm &L, typename LinearForm::DstVectorType &dst)
Apply a linear form and write to a destination vector.
Definition linear_form.hpp:37
void assign(Vector &y, const ScalarOf< Vector > &c0)
Assign a scalar value to a vector. Implements: .
Definition vector.hpp:97
int num_processes()
Definition mpi.hpp:17
constexpr bool has_flag(E mask_value, E flag) noexcept
Checks if a bitmask value contains a specific flag.
Definition bit_masking.hpp:43