DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
EulerJacobian.hpp
Go to the documentation of this file.
1/** @file EulerJacobian.hpp
2 * @brief Jacobian storage and factorization structures for implicit time stepping.
3 *
4 * Provides block-diagonal and sparse-local Jacobian data structures used in
5 * the implicit solver (e.g. backward-Euler, LUSGS, GMRES with ILU/LDLT
6 * preconditioning):
7 *
8 * - JacobianDiagBlock: per-cell diagonal or block-diagonal Jacobian with
9 * forward multiply and inverse operations.
10 * - JacobianLocalLU: full LU factorization of the cell-local Jacobian
11 * using the mesh adjacency structure (SerialSymLUStructure).
12 * - JacobianLocalLDLT: symmetric LDLT factorization variant (lower + diagonal only).
13 *
14 * All classes are templated on nVarsFixed for compile-time Eigen sizing.
15 */
16#pragma once
17
18#include "DNDS/Defines.hpp" // for correct DNDS_SWITCH_INTELLISENSE
19#include "Euler.hpp"
21#include "Solver/Direct.hpp"
22
23namespace DNDS::Euler
24{
25 /**
26 * @brief Per-cell diagonal or block-diagonal Jacobian storage for implicit time stepping.
27 *
28 * Operates in one of two modes selected by SetModeAndInit():
29 * - **Scalar-diagonal** (mode 0): stores an nVars-length diagonal vector per cell.
30 * Matrix-vector products are element-wise multiplications.
31 * - **Matrix-block** (mode 1): stores a full nVars×nVars matrix per cell.
32 * Matrix-vector products are dense matrix multiplies.
33 *
34 * Both modes support lazy inversion via GetInvert(). The scalar mode inverts
35 * element-wise; the matrix mode uses diagonal-preconditioned full-pivot LU
36 * (InvertDiag pattern) for robustness on ill-conditioned blocks.
37 *
38 * @tparam nVarsFixed Compile-time number of conservative variables
39 * (or Eigen::Dynamic).
40 */
41 template <int nVarsFixed>
43 {
44 public:
45 using TU = Eigen::Vector<real, nVarsFixed>; ///< State vector type.
46 using tComponent = Eigen::Matrix<real, nVarsFixed, nVarsFixed>; ///< Full block matrix type.
47 using tComponentDiag = Eigen::Vector<real, nVarsFixed>; ///< Diagonal vector type.
48
49 private:
50 ArrayDOFV<nVarsFixed> _dataDiag, _dataDiagInvert; ///< Diagonal data and its inverse (scalar mode).
51 DNDS::ArrayPair<DNDS::ArrayEigenMatrix<nVarsFixed, nVarsFixed>> _data, _dataInvert; ///< Block data and its inverse (matrix mode).
52 bool hasInvert{false}; ///< True after GetInvert() has computed the inverse.
53 int _mode{0}; ///< Storage mode: 0 = scalar-diagonal, nonzero = matrix-block.
54
55 public:
56 /// @brief Default constructor; mode and storage are uninitialized until SetModeAndInit().
58
59 /**
60 * @brief Select the storage mode and allocate arrays matching @p mock's layout.
61 *
62 * In block mode (mode != 0), allocates nVarsC×nVarsC matrices per cell.
63 * In scalar-diagonal mode (mode == 0), allocates nVarsC-length vectors.
64 * Ghost (son) arrays are allocated with zero size.
65 *
66 * @param mode Storage mode: 0 = scalar-diagonal, nonzero = matrix-block.
67 * @param nVarsC Runtime number of variables (must equal nVarsFixed when fixed).
68 * @param mock A reference ArrayDOFV whose MPI layout and sizes are mimicked.
69 */
70 void SetModeAndInit(int mode, int nVarsC, ArrayDOFV<nVarsFixed> &mock)
71 {
72 _mode = mode;
73 if (isBlock())
74 {
75 _data.InitPair("JacobianLocalLU::SetModeAndInit::_data", mock.father->getMPI());
76 _data.father->Resize(mock.father->Size(), nVarsC, nVarsC);
77 _data.son->Resize(mock.son->Size() * 0, nVarsC, nVarsC);
78 _dataInvert.InitPair("JacobianLocalLU::SetModeAndInit::_dataInvert", mock.father->getMPI());
79 _dataInvert.father->Resize(mock.father->Size(), nVarsC, nVarsC);
80 _dataInvert.son->Resize(mock.son->Size() * 0, nVarsC, nVarsC); // ! warning, sons are set to zero sizes
81 }
82 else
83 {
84 _dataDiag.InitPair("JacobianLocalLU::SetModeAndInit::_dataDiag", mock.father->getMPI());
85 _dataDiag.father->Resize(mock.father->Size(), nVarsC, 1);
86 _dataDiag.son->Resize(mock.son->Size() * 0, nVarsC, 1);
87 _dataDiagInvert.InitPair("JacobianLocalLU::SetModeAndInit::_dataDiagInvert", mock.father->getMPI());
88 _dataDiagInvert.father->Resize(mock.father->Size(), nVarsC, 1);
89 _dataDiagInvert.son->Resize(mock.son->Size() * 0, nVarsC, 1);
90 }
91 }
92
93 /// @brief Return true if using matrix-block mode, false for scalar-diagonal.
94 bool isBlock() const { return _mode; }
95
96 /**
97 * @brief Access the full nVars×nVars block matrix for cell @p iCell (block mode only).
98 * @param iCell Local cell index.
99 * @return Eigen map/ref to the stored block matrix.
100 */
101 auto getBlock(index iCell)
102 {
104 return _data[iCell];
105 }
106
107 /**
108 * @brief Access the diagonal vector for cell @p iCell (scalar-diagonal mode only).
109 * @param iCell Local cell index.
110 * @return Eigen map/ref to the stored diagonal vector.
111 */
112 auto getDiag(index iCell)
113 {
115 return _dataDiag[iCell];
116 }
117
118 /**
119 * @brief Return the Jacobian as a full matrix for cell @p iCell (either mode).
120 *
121 * In scalar-diagonal mode the returned matrix is constructed as asDiagonal().
122 *
123 * @param iCell Local cell index.
124 * @return nVars×nVars matrix (by value).
125 */
127 {
128 if (isBlock())
129 return _data[iCell];
130 else
131 return _dataDiag[iCell].asDiagonal();
132 }
133
134 /// @brief Return the number of cells in the local partition.
136 {
137 if (isBlock())
138 return _data.Size();
139 else
140 return _dataDiag.Size();
141 }
142
143 /**
144 * @brief Compute and cache the inverse of every cell's Jacobian block.
145 *
146 * In matrix-block mode, uses diagonal-preconditioned full-pivot LU
147 * (the InvertDiag pattern) for robustness on ill-conditioned blocks.
148 * In scalar-diagonal mode, inverts element-wise.
149 *
150 * This is a lazy operation: subsequent calls are no-ops until clearValues()
151 * invalidates the cache.
152 */
154 {
155 if (!hasInvert)
156 {
157#if defined(DNDS_DIST_MT_USE_OMP)
158#pragma omp parallel for schedule(runtime)
159#endif
160 for (index iCell = 0; iCell < Size(); iCell++)
161 if (isBlock())
162 {
163 DNDS_assert(_data[iCell].diagonal().array().abs().minCoeff() != 0);
164 tComponent preCon = _data[iCell].diagonal().array().inverse().matrix().asDiagonal() * _data[iCell];
165 auto luDiag = preCon.fullPivLu();
166 DNDS_assert(luDiag.isInvertible());
167 _dataInvert[iCell] = luDiag.inverse() * _data[iCell].diagonal().array().inverse().matrix().asDiagonal();
168 if (!_dataInvert[iCell].allFinite() || _dataInvert[iCell].hasNaN())
169 {
170 std::cout << "xxxx"
171 << "\n";
172 std::cout << _data[iCell] << "\n";
173 std::cout << preCon << "\n";
174 std::cout << luDiag.inverse() << "\n";
175 std::cout << std::endl;
176 DNDS_assert(false);
177 }
178 }
179 else
180 {
181 DNDS_assert(_dataDiag[iCell].array().abs().minCoeff() != 0);
182 _dataDiagInvert[iCell] = _dataDiag[iCell].array().inverse();
183 }
184 hasInvert = true;
185 }
186 }
187
188 /**
189 * @brief Left-multiply a vector by the Jacobian block for cell @p iCell.
190 * @tparam TV Vector type compatible with Eigen matrix-vector product.
191 * @param iCell Local cell index.
192 * @param v Input vector of length nVars.
193 * @return Result of J * v.
194 */
195 template <class TV>
196 TU MatVecLeft(index iCell, TV v)
197 {
198 if (isBlock())
199 return _data[iCell] * v;
200 else
201 return _dataDiag[iCell].asDiagonal() * v;
202 }
203
204 /**
205 * @brief Left-multiply a vector by the *inverse* Jacobian block for cell @p iCell.
206 *
207 * GetInvert() must have been called first; otherwise behavior is undefined.
208 *
209 * @tparam TV Vector type compatible with Eigen matrix-vector product.
210 * @param iCell Local cell index.
211 * @param v Input vector of length nVars.
212 * @return Result of J^{-1} * v.
213 */
214 template <class TV>
216 {
217 if (isBlock())
218 return _dataInvert[iCell] * v;
219 else
220 return _dataDiagInvert[iCell].asDiagonal() * v;
221 }
222
223 /// @brief Zero all stored values and invalidate the cached inverse.
225 {
226 if (isBlock())
227 {
228#if defined(DNDS_DIST_MT_USE_OMP)
229#pragma omp parallel for schedule(static)
230#endif
231 for (index i = 0; i < _data.Size(); i++)
232 _data[i].setZero();
233 }
234 else
235 {
236#if defined(DNDS_DIST_MT_USE_OMP)
237#pragma omp parallel for schedule(static)
238#endif
239 for (index i = 0; i < _dataDiag.Size(); i++)
240 _dataDiag[i].setZero();
241 }
242 hasInvert = false;
243 }
244 };
245
246 // DNDS_SWITCH_INTELLISENSE(
247 // template <int nVarsFixed = 5>,
248 // template <int nVarsFixed_masked>
249 // )
250 /**
251 * @brief Complete LU factorization of the cell-local Jacobian for GMRES preconditioning.
252 *
253 * Stores diagonal (D), lower-triangular (L), and upper-triangular (U) blocks
254 * indexed by the mesh adjacency graph (SerialSymLUStructure). Inherits the
255 * decompose/solve interface from Direct::LocalLUBase via CRTP.
256 *
257 * **Row layout in LDU for each cell iCell:**
258 * - Index 0: diagonal block D.
259 * - Indices [1, 1 + nLower): lower-triangular off-diagonal blocks L.
260 * - Indices [1 + nLower, end): upper-triangular off-diagonal blocks U.
261 *
262 * where nLower = symLU->lowerTriStructure[iCell].size().
263 *
264 * @tparam nVarsFixed Compile-time number of conservative variables
265 * (or Eigen::Dynamic).
266 */
267 template <int nVarsFixed>
269 : public Direct::LocalLUBase<
270 JacobianLocalLU<nVarsFixed>,
271 Eigen::Matrix<real, nVarsFixed, nVarsFixed>,
272 ArrayDOFV<nVarsFixed>>
273 {
274 using tLocalMat = ArrayEigenUniMatrixBatch<nVarsFixed, nVarsFixed>; ///< Batch storage for nVars×nVars blocks.
275 using tComponent = Eigen::Matrix<real, nVarsFixed, nVarsFixed>; ///< Single block matrix type.
276 using tVec = ArrayDOFV<nVarsFixed>; ///< Distributed vector type.
279 Eigen::Matrix<real, nVarsFixed, nVarsFixed>,
280 ArrayDOFV<nVarsFixed>>; ///< CRTP base providing decompose/solve.
281 // using tIndices = Geom::UnstructuredMesh::tLocalMatStruct;
282 /**
283 * @brief Sparse row storage for D, L, U blocks.
284 *
285 * Each row i stores blocks in the order:
286 * [0] = diag,
287 * [1, 1 + symLU->lowerTriStructure[i].size()) = lower-triangular,
288 * [1 + symLU->lowerTriStructure[i].size(), end) = upper-triangular.
289 */
291
292 /**
293 * @brief Construct and allocate the LU storage for the given adjacency structure.
294 * @param nMesh Shared pointer to the symmetric LU sparsity structure.
295 * @param nVarsC Runtime number of conservative variables.
296 */
297 JacobianLocalLU(const ssp<Direct::SerialSymLUStructure> &nMesh, int nVarsC) : tBase{nMesh}
298 {
299 DNDS_assert(tBase::symLU->lowerTriStructure.size() == tBase::symLU->Num());
300 LDU.Resize(tBase::symLU->Num(), nVarsC, nVarsC);
301 for (index iCell = 0; iCell < tBase::symLU->Num(); iCell++)
302 {
303 LDU.ResizeRow(iCell,
304 1 + tBase::symLU->lowerTriStructure[iCell].size() +
305 tBase::symLU->upperTriStructure[iCell].size());
306 for (auto &v : LDU[iCell])
307 v.setZero();
308 }
309 LDU.Compress();
310 }
311
312 /// @brief Zero all D, L, U blocks and mark the factorization as not yet decomposed.
313 void setZero()
314 {
315 tBase::isDecomposed = false;
316#if defined(DNDS_DIST_MT_USE_OMP)
317#pragma omp parallel for schedule(runtime)
318#endif
319 for (index iCell = 0; iCell < tBase::symLU->Num(); iCell++)
320 for (auto &v : LDU[iCell])
321 v.setZero();
322 }
323
324 /// @brief Return the diagonal block for row @p i (compliant with LocalLUBase CRTP).
325 /// @param i Cell (row) index.
326 auto GetDiag(index i) // compliant to LocalLUBase
327 {
328 return LDU(i, 0);
329 }
330 /// @brief Return lower-triangular block @p iInLow for row @p i (compliant with LocalLUBase CRTP).
331 /// @param i Cell (row) index.
332 /// @param iInLow Index within the lower-triangular neighbor list.
333 auto GetLower(index i, int iInLow) // compliant to LocalLUBase
334 {
335 return LDU(i, 1 + iInLow);
336 }
337 /// @brief Return upper-triangular block @p iInUpp for row @p i (compliant with LocalLUBase CRTP).
338 /// @param i Cell (row) index.
339 /// @param iInUpp Index within the upper-triangular neighbor list.
340 auto GetUpper(index i, int iInUpp) // compliant to LocalLUBase
341 {
342 return LDU(i, 1 + tBase::symLU->lowerTriStructure[i].size() + iInUpp);
343 }
344
345 /// @brief Print all non-zero entries (with diagonal inverted) to the log stream.
346 void PrintLog()
347 {
348 log() << "nz Entries with Diag part inverse-ed" << std::endl;
349 for (index iCell = 0; iCell < tBase::symLU->Num(); iCell++)
350 {
351 log() << "=== Row " << iCell << std::endl
352 << std::setprecision(10);
353 for (auto &v : LDU[iCell])
354 log() << v << std::endl
355 << std::endl;
356 }
357 }
358
359 /**
360 * @brief Invert a diagonal block using diagonal-preconditioned full-pivot LU.
361 *
362 * Preconditions the matrix by scaling rows with the inverse of the diagonal,
363 * then applies Eigen's fullPivLu(). This two-step approach improves numerical
364 * stability for ill-conditioned Jacobian blocks.
365 *
366 * @param v The nVars×nVars block matrix to invert.
367 * @return The inverse matrix v^{-1}.
368 */
370 {
371 tComponent AI;
372 {
373 DNDS_assert(v.diagonal().array().abs().minCoeff() != 0);
374 tComponent preCon = v.diagonal().array().inverse().matrix().asDiagonal() * v;
375 auto luDiag = preCon.fullPivLu();
376 DNDS_assert_info(luDiag.isInvertible(), [&]()
377 {
378 std::cerr << v << "\n\n" << preCon << "\n\n";
379 return "=== error info ==="; }());
380 AI = luDiag.inverse() * v.diagonal().array().inverse().matrix().asDiagonal();
381 }
382 {
383 // Eigen::MatrixXd A = v;
384 // Eigen::MatrixXd AII;
385 // HardEigen::EigenLeastSquareInverse(A, AII, 0.0);
386 // AI = AII;
387 }
388 return AI;
389 }
390 };
391
392 /**
393 * @brief Symmetric LDLT factorization of the cell-local Jacobian.
394 *
395 * Similar to JacobianLocalLU but exploits symmetry: only the diagonal and
396 * lower-triangular blocks are stored (no separate upper-triangular storage).
397 * Inherits the decompose/solve interface from Direct::LocalLDLTBase via CRTP.
398 *
399 * **Row layout in LDU for each cell iCell:**
400 * - Index 0: diagonal block D.
401 * - Indices [1, 1 + nLower): lower-triangular off-diagonal blocks L.
402 *
403 * The upper triangle is implicitly L^T.
404 *
405 * @tparam nVarsFixed Compile-time number of conservative variables
406 * (or Eigen::Dynamic).
407 */
408 template <int nVarsFixed>
410 : public Direct::LocalLDLTBase<
411 JacobianLocalLDLT<nVarsFixed>,
412 Eigen::Matrix<real, nVarsFixed, nVarsFixed>,
413 ArrayDOFV<nVarsFixed>>
414 {
415 using tLocalMat = ArrayEigenUniMatrixBatch<nVarsFixed, nVarsFixed>; ///< Batch storage for nVars×nVars blocks.
416 using tComponent = Eigen::Matrix<real, nVarsFixed, nVarsFixed>; ///< Single block matrix type.
417 using tVec = ArrayDOFV<nVarsFixed>; ///< Distributed vector type.
420 Eigen::Matrix<real, nVarsFixed, nVarsFixed>,
421 ArrayDOFV<nVarsFixed>>; ///< CRTP base providing decompose/solve.
422 // using tIndices = Geom::UnstructuredMesh::tLocalMatStruct;
423 /**
424 * @brief Sparse row storage for D and L blocks.
425 *
426 * Each row i stores blocks in the order:
427 * [0] = diag,
428 * [1, 1 + symLU->lowerTriStructure[i].size()) = lower-triangular.
429 */
431
432 /**
433 * @brief Construct and allocate the LDLT storage for the given adjacency structure.
434 *
435 * Unlike JacobianLocalLU, only diagonal + lower blocks are allocated
436 * (no upper-triangular storage).
437 *
438 * @param nMesh Shared pointer to the symmetric LU sparsity structure.
439 * @param nVarsC Runtime number of conservative variables.
440 */
442 {
443 DNDS_assert(tBase::symLU->lowerTriStructure.size() == tBase::symLU->Num());
444 LDU.Resize(tBase::symLU->Num(), nVarsC, nVarsC);
445 for (index iCell = 0; iCell < tBase::symLU->Num(); iCell++)
446 {
447 LDU.ResizeRow(iCell,
448 1 + tBase::symLU->lowerTriStructure[iCell].size());
449 for (auto &v : LDU[iCell])
450 v.setZero();
451 }
452 LDU.Compress();
453 }
454
455 /// @brief Zero all D and L blocks and mark the factorization as not yet decomposed.
456 void setZero()
457 {
458 tBase::isDecomposed = false;
459#if defined(DNDS_DIST_MT_USE_OMP)
460#pragma omp parallel for schedule(static)
461#endif
462 for (index iCell = 0; iCell < tBase::symLU->Num(); iCell++)
463 for (auto &v : LDU[iCell])
464 v.setZero();
465 }
466
467 /// @brief Return the diagonal block for row @p i (compliant with LocalLDLTBase CRTP).
468 /// @param i Cell (row) index.
469 auto GetDiag(index i) // compliant to LocalLDLTBase
470 {
471 return LDU(i, 0);
472 }
473 /// @brief Return lower-triangular block @p iInLow for row @p i (compliant with LocalLDLTBase CRTP).
474 /// @param i Cell (row) index.
475 /// @param iInLow Index within the lower-triangular neighbor list.
476 auto GetLower(index i, int iInLow) // compliant to LocalLDLTBase
477 {
478 return LDU(i, 1 + iInLow);
479 }
480
481 /// @brief Print all non-zero entries (with diagonal inverted) to the log stream.
482 void PrintLog()
483 {
484 log() << "nz Entries with Diag part inverse-ed" << std::endl;
485 for (index iCell = 0; iCell < tBase::symLU->Num(); iCell++)
486 {
487 log() << "=== Row " << iCell << std::endl
488 << std::setprecision(10);
489 for (auto &v : LDU[iCell])
490 log() << v << std::endl
491 << std::endl;
492 }
493 }
494
495 /**
496 * @brief Invert a diagonal block using diagonal-preconditioned full-pivot LU.
497 *
498 * Same algorithm as JacobianLocalLU::InvertDiag: preconditions with the
499 * diagonal inverse, then applies Eigen's fullPivLu().
500 *
501 * @param v The nVars×nVars block matrix to invert.
502 * @return The inverse matrix v^{-1}.
503 */
505 {
506 tComponent AI;
507 {
508 DNDS_assert(v.diagonal().array().abs().minCoeff() != 0);
509 tComponent preCon = v.diagonal().array().inverse().matrix().asDiagonal() * v;
510 auto luDiag = preCon.fullPivLu();
511 DNDS_assert(luDiag.isInvertible());
512 AI = luDiag.inverse() * v.diagonal().array().inverse().matrix().asDiagonal();
513 }
514 {
515 // Eigen::MatrixXd A = v;
516 // Eigen::MatrixXd AII;
517 // HardEigen::EigenLeastSquareInverse(A, AII, 0.0);
518 // AI = AII;
519 }
520 return AI;
521 }
522 };
523}
Batch of uniform-sized Eigen matrices per row, with variable batch count.
Core type aliases, constants, and metaprogramming utilities for the DNDS framework.
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
Definition Errors.hpp:113
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Definition Errors.hpp:108
Core type definitions, enumerations, and distributed array wrappers for compressible Navier-Stokes / ...
void Resize(index n_size, int r, int c)
void ResizeRow(index i, rowsize b_size)
void Compress()
Layout-polymorphic compress: no-op for non-CSR, calls CSRCompress for CSR.
Definition Array.hpp:355
MPI-parallel distributed array of per-cell Degrees-of-Freedom (conservative variable vectors).
Definition Euler.hpp:93
Per-cell diagonal or block-diagonal Jacobian storage for implicit time stepping.
Eigen::Vector< real, nVarsFixed > tComponentDiag
Diagonal vector type.
auto getBlock(index iCell)
Access the full nVars×nVars block matrix for cell iCell (block mode only).
TU MatVecLeftInvert(index iCell, TV v)
Left-multiply a vector by the inverse Jacobian block for cell iCell.
void clearValues()
Zero all stored values and invalidate the cached inverse.
Eigen::Vector< real, nVarsFixed > TU
State vector type.
TU MatVecLeft(index iCell, TV v)
Left-multiply a vector by the Jacobian block for cell iCell.
Eigen::Matrix< real, nVarsFixed, nVarsFixed > tComponent
Full block matrix type.
auto getDiag(index iCell)
Access the diagonal vector for cell iCell (scalar-diagonal mode only).
bool isBlock() const
Return true if using matrix-block mode, false for scalar-diagonal.
tComponent getValue(index iCell) const
Return the Jacobian as a full matrix for cell iCell (either mode).
index Size()
Return the number of cells in the local partition.
JacobianDiagBlock()
Default constructor; mode and storage are uninitialized until SetModeAndInit().
void GetInvert()
Compute and cache the inverse of every cell's Jacobian block.
void SetModeAndInit(int mode, int nVarsC, ArrayDOFV< nVarsFixed > &mock)
Select the storage mode and allocate arrays matching mock's layout.
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:107
std::shared_ptr< T > ssp
Shortened alias for std::shared_ptr used pervasively in DNDSR.
Definition Defines.hpp:138
std::ostream & log()
Return the current DNDSR log stream (either std::cout or the installed file).
Definition Defines.cpp:49
Convenience bundle of a father, son, and attached ArrayTransformer.
ssp< TArray > father
Owned-side array (must be resized before ghost setup).
index Size() const
Combined row count (father->Size() + son->Size()).
void InitPair(const std::string &name, Args &&...args)
Allocate both father and son arrays, forwarding all args to TArray constructor.
ssp< TArray > son
Ghost-side array (sized automatically by createMPITypes / BorrowAndPull).
Symmetric LDLT factorization of the cell-local Jacobian.
auto GetLower(index i, int iInLow)
Return lower-triangular block iInLow for row i (compliant with LocalLDLTBase CRTP).
void setZero()
Zero all D and L blocks and mark the factorization as not yet decomposed.
auto GetDiag(index i)
Return the diagonal block for row i (compliant with LocalLDLTBase CRTP).
tLocalMat LDU
Sparse row storage for D and L blocks.
JacobianLocalLDLT(const ssp< Direct::SerialSymLUStructure > &nMesh, int nVarsC)
Construct and allocate the LDLT storage for the given adjacency structure.
Eigen::Matrix< real, nVarsFixed, nVarsFixed > tComponent
Single block matrix type.
void PrintLog()
Print all non-zero entries (with diagonal inverted) to the log stream.
tComponent InvertDiag(const tComponent &v)
Invert a diagonal block using diagonal-preconditioned full-pivot LU.
Complete LU factorization of the cell-local Jacobian for GMRES preconditioning.
tLocalMat LDU
Sparse row storage for D, L, U blocks.
auto GetLower(index i, int iInLow)
Return lower-triangular block iInLow for row i (compliant with LocalLUBase CRTP).
tComponent InvertDiag(const tComponent &v)
Invert a diagonal block using diagonal-preconditioned full-pivot LU.
JacobianLocalLU(const ssp< Direct::SerialSymLUStructure > &nMesh, int nVarsC)
Construct and allocate the LU storage for the given adjacency structure.
auto GetDiag(index i)
Return the diagonal block for row i (compliant with LocalLUBase CRTP).
Eigen::Matrix< real, nVarsFixed, nVarsFixed > tComponent
Single block matrix type.
auto GetUpper(index i, int iInUpp)
Return upper-triangular block iInUpp for row i (compliant with LocalLUBase CRTP).
void PrintLog()
Print all non-zero entries (with diagonal inverted) to the log stream.
void setZero()
Zero all D, L, U blocks and mark the factorization as not yet decomposed.
Eigen::Matrix< real, 5, 1 > v