svMultiPhysics
Loading...
Searching...
No Matches
DenseLinearAlgebra.h
1// SPDX-FileCopyrightText: Copyright (c) Stanford University, The Regents of the University of California, and others.
2// SPDX-License-Identifier: BSD-3-Clause
3
4#ifndef SVMP_FE_MATH_DENSELINEARALGEBRA_H
5#define SVMP_FE_MATH_DENSELINEARALGEBRA_H
6
7#include "Types.h"
8
9#include <cstddef>
10#include <limits>
11#include <memory>
12#include <span>
13#include <string>
14#include <string_view>
15#include <vector>
16
17namespace svmp::FE::math {
18
19// Dense solve, inverse, rank, and pseudo-inverse support for FE construction
20// utilities. Matrices are row-major: matrix[row * cols + col]. The
21// error_message_label argument on the routines below is used only to prefix the
22// diagnostic message of any exception they throw.
23
24/**
25 * @brief Largest absolute entry of a dense matrix.
26 * @ingroup FE_Math
27 * @param matrix Row-major matrix entries.
28 * @return Maximum of |entry| over all entries, or 0 for an empty matrix.
29 */
30[[nodiscard]] double dense_matrix_max_abs(std::span<const double> matrix) noexcept;
31
32/**
33 * @brief Scale-aware pivot tolerance for dense factorization.
34 * @ingroup FE_Math
35 *
36 * @details Proportional to machine epsilon scaled by the matrix size and
37 * magnitude; pivots below it are treated as rank-deficient.
38 *
39 * @param rows Row count.
40 * @param cols Column count.
41 * @param max_abs Largest absolute matrix entry (see dense_matrix_max_abs()).
42 * @param multiplier Safety factor applied to the epsilon-scaled tolerance.
43 * @return Pivot magnitude threshold.
44 */
45[[nodiscard]] double dense_matrix_pivot_tolerance(std::size_t rows,
46 std::size_t cols,
47 double max_abs,
48 double multiplier = double(64)) noexcept;
49
50/**
51 * @brief Scale-aware singular-value tolerance for rank decisions.
52 * @ingroup FE_Math
53 *
54 * @details Singular values at or below the returned tolerance are treated as
55 * zero when computing rank or a pseudo-inverse.
56 *
57 * @param rows Row count.
58 * @param cols Column count.
59 * @param largest_singular_value Largest singular value of the matrix.
60 * @param multiplier Safety factor applied to the epsilon-scaled tolerance.
61 * @return Singular-value threshold.
62 */
63[[nodiscard]] double dense_matrix_singular_value_tolerance(std::size_t rows,
64 std::size_t cols,
65 double largest_singular_value,
66 double multiplier = double(64)) noexcept;
67
68/** @brief Result of a rank-revealing pseudo-inverse. @ingroup FE_Math */
70 std::vector<double> inverse; ///< Row-major pseudo-inverse.
71 std::size_t rank{0}; ///< Numerical rank at the chosen tolerance.
72 double tolerance{0}; ///< Singular-value tolerance used.
73 double largest_singular_value{0}; ///< Largest singular value.
74 double smallest_retained_singular_value{0}; ///< Smallest singular value kept.
75};
76
77/** @brief SVD-based conditioning and rank diagnostics for a dense matrix. @ingroup FE_Math */
79 std::size_t rank{0}; ///< Numerical rank at @ref tolerance.
80 double tolerance{0}; ///< Singular-value tolerance used.
81 double largest_singular_value{0}; ///< Largest singular value.
82 double smallest_retained_singular_value{0}; ///< Smallest singular value kept.
83 double condition_estimate{std::numeric_limits<double>::infinity()}; ///< Condition estimate; infinite when rank-deficient.
84};
85
86/** @brief A dense inverse together with its diagnostics. @ingroup FE_Math */
88 std::vector<double> inverse; ///< Row-major inverse.
89 DenseMatrixDiagnostics diagnostics; ///< Conditioning/rank diagnostics of the input.
90 bool used_svd_fallback{false}; ///< True when an SVD fallback was used for a high-condition matrix.
91};
92
93/**
94 * @brief Condition estimate above which the inverse switches to an SVD fallback.
95 * @ingroup FE_Math
96 * @return The fallback condition-number threshold.
97 */
98[[nodiscard]] double dense_matrix_condition_fallback_threshold() noexcept;
99/**
100 * @brief Condition estimate above which validation rejects a dense inverse.
101 * @ingroup FE_Math
102 * @return The error condition-number threshold.
103 */
104[[nodiscard]] double dense_matrix_condition_error_threshold() noexcept;
105
106/**
107 * @brief LU factorization of a dense square matrix with a cached pivot summary.
108 * @ingroup FE_Math
109 *
110 * @details Produced by factor_dense_matrix(); move-only because it owns the Eigen
111 * factorization. @ref error_message_label prefixes the messages of exceptions
112 * thrown by the solve methods.
113 */
115 struct Impl;
116
119 DenseLUSolver(DenseLUSolver&&) noexcept;
120 DenseLUSolver& operator=(DenseLUSolver&&) noexcept;
121 DenseLUSolver(const DenseLUSolver&) = delete;
122 DenseLUSolver& operator=(const DenseLUSolver&) = delete;
123
124 std::size_t n{0}; ///< Matrix dimension.
125 DenseMatrixDiagnostics diagnostics; ///< Pivot-derived diagnostics (rank, tolerance).
126 double pivot_tolerance{0}; ///< Scale-aware pivot tolerance used.
127 double min_pivot{0}; ///< Smallest pivot magnitude.
128 double max_pivot{0}; ///< Largest pivot magnitude.
129 std::string error_message_label; ///< Prefix for solve-time exception messages.
130 std::unique_ptr<Impl> impl; ///< Eigen factorization (pimpl).
131
132 /**
133 * @brief Whether the factorization is empty (n == 0).
134 * @return True when no matrix has been factored.
135 */
136 [[nodiscard]] bool empty() const noexcept { return n == 0; }
137
138 /**
139 * @brief Solve A x = rhs in place for a single right-hand side.
140 * @param rhs On entry the right-hand side; on return the solution (size n).
141 */
142 void solve_in_place(std::span<double> rhs) const;
143 /**
144 * @brief Solve A X = RHS in place for several right-hand sides.
145 * @param rhs Row-major block of size n * rhs_count (solutions on return).
146 * @param rhs_count Number of right-hand sides.
147 */
148 void solve_in_place(std::span<double> rhs, std::size_t rhs_count) const;
149 /**
150 * @brief Solve A x = rhs and return the solution.
151 * @param rhs Right-hand side of size n.
152 * @return Solution vector of size n.
153 */
154 [[nodiscard]] std::vector<double> solve(std::span<const double> rhs) const;
155};
156
157// Inverses and pseudo-inverses keep the same row-major convention for their
158// returned dimensions.
159
160/**
161 * @brief SVD-based rank and conditioning diagnostics for a dense matrix.
162 * @ingroup FE_Math
163 * @param matrix Row-major matrix of size rows * cols.
164 * @param rows Row count.
165 * @param cols Column count.
166 * @param error_message_label Prefix for the message of any exception thrown.
167 * @return Rank, tolerance, singular-value, and condition diagnostics.
168 * @throws FEException If the matrix size is inconsistent or the matrix is empty.
169 */
170[[nodiscard]] DenseMatrixDiagnostics dense_matrix_diagnostics(
171 std::span<const double> matrix,
172 std::size_t rows,
173 std::size_t cols,
174 std::string_view error_message_label = "dense matrix");
175
176/**
177 * @brief LU-factor a dense square matrix.
178 * @ingroup FE_Math
179 * @param matrix Row-major n * n matrix (consumed).
180 * @param n Matrix dimension.
181 * @param error_message_label Prefix for the message of any exception thrown.
182 * @return The factorization.
183 * @throws FEException If the size is inconsistent or the matrix is rank-deficient.
184 */
185[[nodiscard]] DenseLUSolver factor_dense_matrix(std::vector<double> matrix,
186 std::size_t n,
187 std::string_view error_message_label = "dense matrix");
188
189/**
190 * @brief Invert a dense square matrix.
191 * @ingroup FE_Math
192 * @param matrix Row-major n * n matrix (consumed).
193 * @param n Matrix dimension.
194 * @param error_message_label Prefix for the message of any exception thrown.
195 * @return Row-major inverse of size n * n.
196 * @throws FEException If the size is inconsistent or the matrix is singular.
197 */
198[[nodiscard]] std::vector<double> invert_dense_matrix(std::vector<double> matrix,
199 std::size_t n,
200 std::string_view error_message_label = "dense matrix");
201
202/**
203 * @brief Invert a dense square matrix with diagnostics, using an SVD fallback for
204 * high-condition matrices.
205 * @ingroup FE_Math
206 * @param matrix Row-major n * n matrix (consumed).
207 * @param n Matrix dimension.
208 * @param error_message_label Prefix for the message of any exception thrown.
209 * @return Inverse plus diagnostics and whether the SVD fallback was used.
210 * @throws FEException If the size is inconsistent or the matrix is rank-deficient.
211 */
212[[nodiscard]] DenseInverseResult invert_dense_matrix_with_diagnostics(
213 std::vector<double> matrix,
214 std::size_t n,
215 std::string_view error_message_label = "dense matrix");
216
217/**
218 * @brief Validate that a dense inverse has full rank and acceptable conditioning.
219 * @ingroup FE_Math
220 * @param result Result from invert_dense_matrix_with_diagnostics().
221 * @param expected_rank Required (full) rank.
222 * @param error_message_label Prefix for the message of any exception thrown.
223 * @param max_condition Largest acceptable condition estimate.
224 * @throws FEException If the rank is below expected_rank or the condition exceeds max_condition.
225 */
227 const DenseInverseResult& result,
228 std::size_t expected_rank,
229 std::string_view error_message_label = "dense matrix",
230 double max_condition = dense_matrix_condition_error_threshold());
231
232/**
233 * @brief Numerical rank of a dense matrix from its singular values.
234 * @ingroup FE_Math
235 * @param matrix Row-major matrix of size rows * cols (consumed).
236 * @param rows Row count.
237 * @param cols Column count.
238 * @return Number of singular values above the scale-aware tolerance.
239 * @throws FEException If the matrix size is inconsistent.
240 */
241[[nodiscard]] std::size_t dense_matrix_rank(std::vector<double> matrix,
242 std::size_t rows,
243 std::size_t cols);
244
245/**
246 * @brief Moore-Penrose pseudo-inverse via a rank-revealing SVD.
247 * @ingroup FE_Math
248 * @param matrix Row-major matrix of size rows * cols.
249 * @param rows Row count.
250 * @param cols Column count.
251 * @param error_message_label Prefix for the message of any exception thrown.
252 * @return Row-major pseudo-inverse (cols * rows) plus rank/tolerance diagnostics.
253 * @throws FEException If the matrix size is inconsistent or the matrix is empty.
254 */
255[[nodiscard]] DensePseudoInverseResult rank_revealing_pseudo_inverse(
256 std::span<const double> matrix,
257 std::size_t rows,
258 std::size_t cols,
259 std::string_view error_message_label = "dense matrix");
260
261} // namespace svmp::FE::math
262
263#endif // SVMP_FE_MATH_DENSELINEARALGEBRA_H
Fundamental type definitions for the finite element library.
DenseInverseResult invert_dense_matrix_with_diagnostics(std::vector< double > matrix, std::size_t n, std::string_view error_message_label)
Invert a dense square matrix with diagnostics, using an SVD fallback for high-condition matrices.
Definition DenseLinearAlgebra.cpp:199
double dense_matrix_pivot_tolerance(std::size_t rows, std::size_t cols, double max_abs, double multiplier) noexcept
Scale-aware pivot tolerance for dense factorization.
Definition DenseLinearAlgebra.cpp:59
std::vector< double > invert_dense_matrix(std::vector< double > matrix, std::size_t n, std::string_view error_message_label)
Invert a dense square matrix.
Definition DenseLinearAlgebra.cpp:263
double dense_matrix_singular_value_tolerance(std::size_t rows, std::size_t cols, double largest_singular_value, double multiplier) noexcept
Scale-aware singular-value tolerance for rank decisions.
Definition DenseLinearAlgebra.cpp:69
std::size_t dense_matrix_rank(std::vector< double > matrix, std::size_t rows, std::size_t cols)
Numerical rank of a dense matrix from its singular values.
Definition DenseLinearAlgebra.cpp:273
void validate_dense_inverse_diagnostics(const DenseInverseResult &result, std::size_t expected_rank, std::string_view error_message_label, double max_condition)
Validate that a dense inverse has full rank and acceptable conditioning.
Definition DenseLinearAlgebra.cpp:243
double dense_matrix_condition_error_threshold() noexcept
Condition estimate above which validation rejects a dense inverse.
Definition DenseLinearAlgebra.cpp:83
double dense_matrix_max_abs(std::span< const double > matrix) noexcept
Largest absolute entry of a dense matrix.
Definition DenseLinearAlgebra.cpp:51
DensePseudoInverseResult rank_revealing_pseudo_inverse(std::span< const double > matrix, std::size_t rows, std::size_t cols, std::string_view error_message_label)
Moore-Penrose pseudo-inverse via a rank-revealing SVD.
Definition DenseLinearAlgebra.cpp:298
double dense_matrix_condition_fallback_threshold() noexcept
Condition estimate above which the inverse switches to an SVD fallback.
Definition DenseLinearAlgebra.cpp:79
DenseMatrixDiagnostics dense_matrix_diagnostics(std::span< const double > matrix, std::size_t rows, std::size_t cols, std::string_view error_message_label)
SVD-based rank and conditioning diagnostics for a dense matrix.
Definition DenseLinearAlgebra.cpp:117
DenseLUSolver factor_dense_matrix(std::vector< double > matrix, std::size_t n, std::string_view error_message_label)
LU-factor a dense square matrix.
Definition DenseLinearAlgebra.cpp:157
A dense inverse together with its diagnostics.
Definition DenseLinearAlgebra.h:87
std::vector< double > inverse
Row-major inverse.
Definition DenseLinearAlgebra.h:88
bool used_svd_fallback
True when an SVD fallback was used for a high-condition matrix.
Definition DenseLinearAlgebra.h:90
DenseMatrixDiagnostics diagnostics
Conditioning/rank diagnostics of the input.
Definition DenseLinearAlgebra.h:89
Definition DenseLinearAlgebra.cpp:42
LU factorization of a dense square matrix with a cached pivot summary.
Definition DenseLinearAlgebra.h:114
bool empty() const noexcept
Whether the factorization is empty (n == 0).
Definition DenseLinearAlgebra.h:136
std::unique_ptr< Impl > impl
Eigen factorization (pimpl).
Definition DenseLinearAlgebra.h:130
std::string error_message_label
Prefix for solve-time exception messages.
Definition DenseLinearAlgebra.h:129
DenseMatrixDiagnostics diagnostics
Pivot-derived diagnostics (rank, tolerance).
Definition DenseLinearAlgebra.h:125
SVD-based conditioning and rank diagnostics for a dense matrix.
Definition DenseLinearAlgebra.h:78
std::size_t rank
Numerical rank at tolerance.
Definition DenseLinearAlgebra.h:79
double condition_estimate
Condition estimate; infinite when rank-deficient.
Definition DenseLinearAlgebra.h:83
double tolerance
Singular-value tolerance used.
Definition DenseLinearAlgebra.h:80
double smallest_retained_singular_value
Smallest singular value kept.
Definition DenseLinearAlgebra.h:82
double largest_singular_value
Largest singular value.
Definition DenseLinearAlgebra.h:81
Result of a rank-revealing pseudo-inverse.
Definition DenseLinearAlgebra.h:69
std::vector< double > inverse
Row-major pseudo-inverse.
Definition DenseLinearAlgebra.h:70