BELFEM 0.9.0
Berkeley Lab Finite Element Framework
Loading...
Searching...
No Matches
cl_SolverParameters.hpp
Go to the documentation of this file.
1/*
2 * BELFEM -- The Berkeley Lab Finite Element Framework
3 * Copyright (c) 2026, The Regents of the University of California, through
4 * Lawrence Berkeley National Laboratory (subject to receipt of any required
5 * approvals from the U.S. Dept. of Energy). All rights reserved.
6 *
7 * Developers: Christian Messe, Gregory Giard
8 *
9 * See the top-level LICENSE file for the complete license and disclaimer.
10 */
11
12#ifndef BELFEM_CL_SOLVERPARAMETERS_HPP
13#define BELFEM_CL_SOLVERPARAMETERS_HPP
14#include "en_SolverEnums.hpp"
15#include "cl_Input_Section.hpp"
16#include "commtools.hpp"
17
18namespace belfem
19{
27 {
28 const proc_t mCommRank ;
29 const SolverType mSolverType = gDefaultSolver ;
30
31 // CSR is recommended: STRUMPACK's set_distributed_csr_matrix() is
32 // its primary and most-tested MPI interface. The MPIAIJ path
33 // (set_MPIAIJ_matrix) causes hangs during distributed multifrontal
34 // factorization and lacks upstream C++ test coverage.
35 DistributedMatrixType mDistributedMatrixType = DistributedMatrixType::CSR ;
36
38
40
41 // BLR compression tolerance, consumed ONLY when the deck says
42 // compression scheme : blr. One number, two strictnesses:
43 // STRUMPACK applies it as a RELATIVE rel_tol, MUMPS as the
44 // ABSOLUTE CNTL(7) dropping parameter ( MUMPS 5.7.3 §5.19 ).
45 // See src/sparse/doc/solver_memory_and_compression.md §4
46 real mCompressionCutoff = 1e-8 ;
47
48 // true once the deck ( or a programmatic caller ) stated a
49 // cutoff — distinguishes a chosen trade from the inherited
50 // default in the headroom check
51 bool mHaveCompressionCutoff = false ;
52
53 // MUMPS only: per-process working-memory cap in MB, handed to
54 // ICNTL(23) before the first factorization. 0 = not stated; the
55 // wrapper then measures the machine itself in initialize() ( see
56 // MUMPS::memory_budget_mb ) and applies that number as ICNTL(23)
57 // on the first out-of-workspace failure. An explicit value wins
58 // over that measurement
59 uint mMemoryBudget = 0 ;
60 bool mHaveMemoryBudget = false ;
61
62 // MC64 matrix matching, only used by STRUMPACK. Its permutation is
63 // load-bearing for the coupled h-phi Jacobian: without it the Newton
64 // stage hits exact zero pivots that replace_tiny_pivots cannot absorb
65 // (observed 2026-07-05, serial hphirun, ZERO_PIVOT at Newton 17).
66 // Expensive in MPI mode ( STRUMPACK gathers the full matrix on rank 0,
67 // once per initialize ) -- ( matching : off ) is an opt-out for cases
68 // verified to tolerate it.
69 bool mUseMatrixMatching = true ;
70
71 // STRUMPACK / serial-METIS only. METIS_NodeNDP returns the separator
72 // tree; METIS_NodeND does not, so STRUMPACK has to rebuild a supernodal
73 // tree from the elimination tree instead, and that reconstruction is
74 // what produces very deep trees. Observed on tapestack3d 2026-08-12,
75 // 832k magnetic dofs: "used METIS_NodeND (iso METIS_NodeNDP)",
76 // "supernodal tree was built from etree", 56 levels — and STRUMPACK's
77 // own diagnostic then warned that it "does not handle this safely,
78 // which could lead to segmentation faults due to stack overflows",
79 // recommending precisely this flag. The same deep tree is the likely
80 // cause of the factorisation memory landing overwhelmingly on one rank
81 // ( 23 GiB against 2.8 GiB on its siblings ).
82 //
83 // METIS_NodeNDP is UNDOCUMENTED in METIS and declared by STRUMPACK
84 // itself, so it is kept switchable: ( metis nodendp : false ) restores
85 // METIS_NodeND if a METIS build does not provide it. Irrelevant to
86 // PARMETIS and SCOTCH, which ignore the flag.
87 bool mUseMetisNodeNDP = true ;
88
89 // Only used for PETSc, ignored otherwise.
90 //
91 // ASM ( additive Schwarz, PETSc default sub-solver ILU(0) ) rather than
92 // the former GAMG-in-parallel / JACOBI-in-serial pair, for two reasons.
93 //
94 // 1. The consumer is not the operator GAMG is built for. Smoothed
95 // aggregation assumes a symmetric elliptic system; that describes
96 // the PICARD thermal operator ( M/dt + K, SPD ) but not the NEWTON
97 // tangent, which carries the non-symmetric mixed-operator term
98 // ( B'*grad T ) (x) ( dlambda/dT * N ) from mt_thermal_h. Measured
99 // on tapestack3d 2026-08-12, 337k thermal dofs, rtol 1e-8:
100 // GAMG needed ~74 Krylov iterations on the two Picard iterates and
101 // ~700 on every Newton iterate of the same step -- a 9x penalty
102 // that appears exactly when the algorithm flips. ASM is slightly
103 // worse on the Picard operator ( ~107 ) and does not degrade on the
104 // Newton one, which is the trade this default takes.
105 //
106 // 2. The old pair changed the preconditioner WITH THE RANK COUNT, so a
107 // serial and a parallel run of the same deck solved with different
108 // numerics. Same defect class as the thermal Picard freeze, where
109 // partition-order roundoff selected the nonlinear algorithm. ASM with one block
110 // degenerates to ILU, so the family is now continuous in comm_size.
111 //
112 // A deck that knows its operator is symmetric can still ask for GAMG
113 // through ( preconditioner : gamg ) -- and should, since GAMG wins on
114 // the Picard operator.
115 Preconditioner mPreconditioner = Preconditioner::ASM ;
116
117 // only used for PETSc and STRUMPACK. AUTO resolves to PREONLY behind a
118 // direct LU preconditioner and GMRES otherwise ( cl_SolverPETSC.cpp ),
119 // which is the correct choice for the non-symmetric Newton tangent
120 // above -- a symmetric-only method such as CG must not become the
121 // default while that term is in the operator.
122 KrylovMethod mKrylovMethod = KrylovMethod::AUTO ;
123
124 // Relative tolerance: PETSc KSP rtol AND STRUMPACK outer-GMRES
125 // rel_tol, always applied ( STRUMPACK since 2026-08-18; before
126 // that only when stated, and an unstated deck inherited the
127 // library's 1e-6 — the tapestack3d A/B showed that loose exit
128 // test WAS the printed nonlinear residual, see strumpacktools ).
129 //
130 // 1e-10 rather than 1e-8 because a transient solved for an ABSOLUTE
131 // field accepts an absolute error of ~rtol * |field| per step. A
132 // thermal run in kelvin therefore drifts by ~rtol * T every step, and
133 // in an adiabatic or weakly forced problem nothing pulls it back:
134 // measured on tapestack3d 2026-08-13, 337k thermal dofs, a uniform
135 // 77 K start drifted 8.6e-5 K in 23 steps at rtol 1e-8, and 2.6e-7 K
136 // at rtol 1e-10. The failure is silent -- no residual, no message --
137 // so the default carries the safety margin rather than the deck.
138 // ( The old reassurance "STRUMPACK pays nothing, the factorization
139 // already delivers ~2e-16" was refuted by the A/B: on an
140 // ill-conditioned matrix the raw factor gives ~4 digits and the
141 // OUTER GMRES is what reaches deep residuals. )
142 //
143 // This is a mitigation, not the cure. The cure is to solve in
144 // increment form, where the criterion becomes scale-free.
145 real mRelativeTolerance = 1e-10;
146
147 // Set when the deck or set_relative_tolerance() stated a value.
148 // NOT a consumer gate: since 2026-08-18 STRUMPACK always applies
149 // mRelativeTolerance ( same as PETSc ). Do not re-introduce the
150 // have_relative_tolerance() guard in strumpacktools — that was
151 // the REFINE-era split, retired after the tapestack3d
152 // 1e-8 vs 1e-10 A/B; stall protection is now PREC_GMRES +
153 // maxit 50 + always-set abs_tol. The flag still rides
154 // synchronize() so the positional payload keeps its slot ( current
155 // width 13, see the history note in synchronize() ).
156 bool mHaveRelativeTolerance = false ;
157
158 // Absolute tolerance of the ITERATIVE part of a linear solve.
159 //
160 // STRUMPACK: exit test of the outer GMRES next to rel_tol. The
161 // library default is 1e-10 ( StrumpackOptions.hpp ), and BELFEM
162 // shipped with it unset for years — on a SMALL right-hand side
163 // ( transient startup, ||b|| ~ 1e-2 ) that floor sits exactly at
164 // a 1e-11 RELATIVE nonlinear target and Newton converges only by
165 // GMRES overshoot lottery ( three-voice jury 2026-08-17 ).
166 // 1e-14 restores >= 3 decades of headroom while keeping GMRES:
167 // the factorization-preconditioned iteration reaches it in a few
168 // extra Arnoldi steps, and the maxit cap bounds the cost.
169 //
170 // PETSc: passed as KSP atol when stated in the deck; PETSC_DEFAULT
171 // otherwise ( the historical behavior ).
172 real mAbsoluteTolerance = 1e-14 ;
173
174 // true once the deck ( or a programmatic caller ) stated an
175 // absolute tolerance. PETSc applies the value only then;
176 // STRUMPACK always applies mAbsoluteTolerance, because its
177 // library default is the overshoot-lottery defect above.
178 bool mHaveAbsoluteTolerance = false ;
179
180 bool mUseInitialGuess = false ;
181
182 // deck-stated Krylov iteration budget for ITERATIVE solvers
183 // ( "max iterations" in a linear section — distinct from the
184 // nonlinear key of the same name, which the controller parses ).
185 // 0 = not stated, keep the library default ( PETSc: 10000 ).
186 // Consumed by PETSc only; STRUMPACK's refinement cap is a fixed
187 // safety net against the refinement stall, deliberately not deck-tunable
188 uint mMaxNumIterations = 0 ;
189
190 public:
191
192 SolverParameters( const SolverType aType ) ;
193
194 SolverParameters( const input::Section * aInput );
195
196 SolverParameters( const SolverParameters & aOther );
197
200
201 ~SolverParameters() = default ;
202
203 void
205
206 void
207 set_preconditioner( const Preconditioner aPreconditioner );
208
209 void
210 set_krylov_method( const KrylovMethod aKrylovMethod );
211
212 void
213 set_reordering_method( const ReorderingMethod aReorderingMethod );
214
215 void
216 set_compression_method( const CompressionMethod aCompressionMethod );
217
218 void
219 set_relative_tolerance( const real aEpsilon );
220
221 void
222 set_absolute_tolerance( const real aEpsilon );
223
224 void
225 set_use_initial_guess( const bool aUse );
226
227 void
228 set_matrix_matching( const bool aUse );
229
231 type() const ;
232
235
237 preconditioner() const;
238
240 krylov_method() const;
241
243 reordering_method() const;
244
246 compression_method() const;
247
248 real
249 relative_tolerance() const ;
250
251 real
252 absolute_tolerance() const ;
253
256 bool
258
259 bool
261
263 uint
264 max_iterations() const ;
265
268 void
269 set_compression_cutoff( const real aCutoff );
270
272 bool
274
275 real
276 compression_cutoff() const ;
277
280 void
281 set_memory_budget( const uint aMegaBytes );
282
284 bool
285 have_memory_budget() const ;
286
288 uint
289 memory_budget() const ;
290
291
292 bool
293 use_initial_guess() const ;
294
295 bool
296 use_matrix_matching() const ;
297
298 bool
299 use_metis_nodendp() const ;
300
301 void
302 synchronize();
303
304 private:
305
307 get_solver_type_from_input( const input::Section * aInput ) const ;
308
309 };
310}
311#endif //BELFEM_CL_SOLVERPARAMETERS_HPP
bool use_matrix_matching() const
Definition cl_SolverParameters.cpp:354
void set_preconditioner(const Preconditioner aPreconditioner)
Definition cl_SolverParameters.cpp:169
real compression_cutoff() const
Definition cl_SolverParameters.cpp:289
void set_memory_budget(const uint aMegaBytes)
Definition cl_SolverParameters.cpp:314
SolverParameters(SolverParameters &&aOther)=delete
uint max_iterations() const
deck-stated Krylov iteration budget; 0 = library default
Definition cl_SolverParameters.cpp:283
void set_reordering_method(const ReorderingMethod aReorderingMethod)
Definition cl_SolverParameters.cpp:181
real relative_tolerance() const
Definition cl_SolverParameters.cpp:259
void set_matrix_matching(const bool aUse)
Definition cl_SolverParameters.cpp:216
void set_compression_method(const CompressionMethod aCompressionMethod)
Definition cl_SolverParameters.cpp:187
bool have_compression_cutoff() const
true if the cutoff was stated rather than inherited
Definition cl_SolverParameters.cpp:308
CompressionMethod compression_method() const
Definition cl_SolverParameters.cpp:253
DistributedMatrixType distributed_matrix_type() const
Definition cl_SolverParameters.cpp:229
void set_use_initial_guess(const bool aUse)
Definition cl_SolverParameters.cpp:210
real absolute_tolerance() const
Definition cl_SolverParameters.cpp:271
bool use_initial_guess() const
Definition cl_SolverParameters.cpp:348
SolverType type() const
Definition cl_SolverParameters.cpp:222
void set_compression_cutoff(const real aCutoff)
Definition cl_SolverParameters.cpp:295
void set_krylov_method(const KrylovMethod aKrylovMethod)
Definition cl_SolverParameters.cpp:175
KrylovMethod krylov_method() const
Definition cl_SolverParameters.cpp:241
void set_distributed_matrix_type(const DistributedMatrixType aType)
Definition cl_SolverParameters.cpp:163
bool have_absolute_tolerance() const
Definition cl_SolverParameters.cpp:277
bool have_memory_budget() const
true if the deck ( or a caller ) stated a budget
Definition cl_SolverParameters.cpp:336
Preconditioner preconditioner() const
Definition cl_SolverParameters.cpp:235
uint memory_budget() const
MB per process; 0 when not stated.
Definition cl_SolverParameters.cpp:342
SolverParameters(const SolverType aType)
Definition cl_SolverParameters.cpp:21
SolverParameters & operator=(SolverParameters &&aOther)=delete
void set_relative_tolerance(const real aEpsilon)
Definition cl_SolverParameters.cpp:193
bool use_metis_nodendp() const
Definition cl_SolverParameters.cpp:360
void synchronize()
Definition cl_SolverParameters.cpp:366
ReorderingMethod reordering_method() const
Definition cl_SolverParameters.cpp:247
bool have_relative_tolerance() const
Definition cl_SolverParameters.cpp:265
void set_absolute_tolerance(const real aEpsilon)
Definition cl_SolverParameters.cpp:200
One hierarchical section of a configuration file.
Definition cl_Input_Section.hpp:34
USER GUIDES:
Definition cl_Capacitor.cpp:16
DistributedMatrixType
Definition en_SolverEnums.hpp:66
@ CSR
Definition en_SolverEnums.hpp:68
unsigned int uint
Definition typedefs.hpp:30
int proc_t
Definition commtypes.hpp:29
const SolverType gDefaultSolver
Definition en_SolverEnums.hpp:209
SolverType
Definition en_SolverEnums.hpp:23
ReorderingMethod
Definition en_SolverEnums.hpp:116
@ AUTOMATIC
Definition en_SolverEnums.hpp:120
KrylovMethod
PETSC only.
Definition en_SolverEnums.hpp:101
@ AUTO
Definition en_SolverEnums.hpp:109
Preconditioner
PETSC only.
Definition en_SolverEnums.hpp:79
@ ASM
Definition en_SolverEnums.hpp:81
double real
Definition typedefs.hpp:36
CompressionMethod
Definition en_SolverEnums.hpp:129
@ AUTOMATIC
Definition en_SolverEnums.hpp:132