BELFEM 0.9.0
Berkeley Lab Finite Element Framework
Loading...
Searching...
No Matches
cl_FEM_Controller.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,
4 * through 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#ifndef CL_FEM_CONTROLLER_HPP
12#define CL_FEM_CONTROLLER_HPP
14#include "typedefs.hpp"
15#include "cl_Timer.hpp"
16#include "cl_Input_Section.hpp"
17#include "cl_Circuit.hpp"
19#include "cl_FEM_Kernel.hpp"
20#include "cl_ShiftRegister.hpp"
21
22namespace belfem
23{
24 class Mesh ;
25
26 namespace fem
27 {
28 class Kernel ;
29 class IWG_Timestep ;
30
38 {
39 const proc_t mCommRank ;
40 const proc_t mCommSize ;
41 Kernel * mKernel = nullptr ;
42 IWG_Timestep * mEquation = nullptr ;
43 Mesh * mMesh = nullptr ;
44 Kernel * mKernel2 = nullptr ;
45 IWG_Timestep * mEquation2 = nullptr ;
46 Mesh * mMesh2 = nullptr ;
47 Circuit * mCircuit = nullptr ;
48
49 real mTime = 0.0 ;
50 real mDeltaTime = BELFEM_QUIET_NAN ;
51 real mDeltaTimeTemporary = BELFEM_QUIET_NAN ; //Temporary time step to reach the time steps to be saved
52 real mDeltaTime0 = BELFEM_QUIET_NAN ;
53
64 real mDeltaTimeInitial = BELFEM_QUIET_NAN ;
65 uint mRunningTimeStep = 0 ;
66 uint mMeshTimeStep = 1 ;
67
68 real mTime2 = 0.0 ;
69 real mDeltaTime2 = BELFEM_QUIET_NAN ;
70 real mDeltaTimeTemporary2 = BELFEM_QUIET_NAN ; //Temporary time step to reach the time steps to be saved
71
72 // - - - - - - begin user settings - - - - - -
73
74 real mAlpha = 0.5 ;
75 real mBeta = 1.1 ;
76 real mGamma = 0.4 ;
77
78 uint mMinNumIterations = 2 ;
79 uint mMaxNumIterations = 100 ;
80 uint mIterationTarget = 20 ;
81
89 uint mDivergenceStrikes = 0 ;
90
91 // stagnation guard: if the mean absolute deviation of the last
92 // mStallWindow residuals (in dB) stays below mStallBand while the
93 // residual is still above tolerance, the timestep is cut instead of
94 // grinding on to mMaxNumIterations (see iterate_coupled).
95 // The band must sit ABOVE the noise of a floored residual, or the
96 // Newton->Picard demotion this guard exists for never fires: the
97 // sidecoatings floor wandered +-0.05..0.2 dB against the old
98 // 0.001 dB band and burned the full watchdog window instead.
99 // Genuine convergence moves >= O(1) dB per iterate, so 0.2 dB
100 // separates the two regimes. Deck override: "stall tolerance"
101 uint mStallWindow = 5 ;
102 real mStallBand = 0.2 ; // dB
103
104 // progress watchdog: cut the timestep when the residual has not
105 // reached a NEW MINIMUM for this many iterations while still above
106 // 10x tolerance. Catches what the flat-band guard cannot see:
107 // omega-sawtooth limit cycles ( locally "converging" on any short
108 // window ) and slow monotone creep of the thermal residual at the
109 // relaxation floor. 0 disables. Input key: "watchdog window".
110 uint mWatchdogWindow = 30 ;
111 uint mWatchdogWindow2 = 30 ;
112
119 real mWatchdogOmegaPrev = BELFEM_QUIET_NAN ;
120 real mWatchdogOmegaPrev2 = BELFEM_QUIET_NAN ;
121
122 uint mMinNumIterations2 = 2 ;
123 uint mMaxNumIterations2 = 100 ;
124 uint mIterationTarget2 = 20 ;
125
126 uint mMaxNumIterationsDiv = 10 ; //Number of diverging iterations before resetting the relaxation
127 uint mNumIterationsDiv = 0; //Number of diverging iterations
128 // conditioning diagnostic, per field. It describes a property of
129 // ONE solve, and the two fields configure their solvers
130 // separately ( "linear magnetic" / "linear thermal", falling back
131 // to "linear" ), so the flag lives with them.
132 // "compute conditioning" in the solver section still sets both.
133 //
134 // These gate the EIGENVALUE estimate and nothing else. The MUMPS
135 // Arioli/Demmel/Duff numbers have their own flag below -- the two
136 // diagnostics are independent, and either may be asked for alone
137 bool mComputeConditioning = false ; // magnetic; always costs ARPACK
138 bool mComputeConditioning2 = false ; // thermal
139
140 // "mumps error analysis", per field, read from the same three
141 // places as the flag above. Gates MUMPS ICNTL(11) ONLY -- the
142 // COND1 / COND2 / omega2 triple that feeds the "MUMPS ADD" footer
143 // rows. A no-op on any other library, which is why the key names
144 // MUMPS: see the warnings raised for a field that asks for it
145 // without one
146 bool mMumpsErrorAnalysis = false ; // magnetic
147 bool mMumpsErrorAnalysis2 = false ; // thermal
148
149 // guards check_thermal_diagnostics() against warning twice: both
150 // attach paths call it, and a caller can use both
151 bool mThermalDiagnosticsChecked = false ;
152
153 // whether set_params has run. The thermal diagnostics must not be
154 // judged against the DEFAULT flags, so their check requires both
155 // prerequisites -- parsed params AND an attached kernel -- and
156 // runs from whichever call arrives second, in any order
157 bool mParamsSet = false ;
158
167 real mOmegaNoiseBand = 0.05 ;
168
169 // MIT-3a: consecutive first-trial Newton steps that at least
170 // halved the residual. The geometric omega recovery
171 // ( tGrowth = 2.0 ) requires TWO of them, because a single
172 // qualifying step is not evidence of contraction near a noise
173 // floor -- on tapestack3d the doubling fired once ( omega
174 // 0.483 -> 0.966 ) and regressed on the very next iterate.
175 // SCOPE: this addresses the x2 rule ONLY; a later loss in the
176 // same trace came from ordinary arctan growth and is NOT fixed
177 // here. A healthily
178 // contracting Newton earns the streak on its second step and
179 // keeps the acceleration; a lucky step never does.
180 //
181 // Reset on: timestep start ( both drivers ), reject,
182 // promotion, escalation, and every demotion ON THE COUPLED
183 // PATH -- the evidence belongs to one uninterrupted Newton
184 // run, not to the timestep. NOTE this is NOT simply
185 // "wherever mFirstFlip is reset": iterate_magnetic's
186 // promotion clears mFirstFlip without touching the streak.
187 // That twin never increments and never consumes the streak
188 // ( it has no x2 rule ), and initialize_magnetic zeroes at
189 // every step start, so the omission is inert -- but do not
190 // rely on the mFirstFlip locator when adding a path
191 uint mNewtonTrustStreak = 0 ;
192
193 real mEpsilonSwitch = 1e-4 ; // residual at which Picard hands off to Newton (Messe et al. 2023, Eq. 13)
194 real mRelativeEpsilonTarget = 1e-6 ; // relative error criterion
199 real mAbsoluteEpsilonTarget = 0.0 ;
200
201 real mEpsilonSwitch2 = 1e-3 ; // thermal residual at which Picard hands off to Newton
202 real mRelativeEpsilonTarget2 = 1e-6 ; // relative thermal error criterion
203 real mAbsoluteEpsilonTarget2 = 0.0 ; // absolute thermal error criterion ( see above: opt-in )
204
212 real mThermalUpdateGate = BELFEM_REAL_MAX ;
213
218 bool mThermalFrozen = false ;
219
220 real mSimulationTime = BELFEM_REAL_MAX ;
221 bool mAdaptTimestep = true ;
222 real mSaveEvery = 0.0 ;
223 bool mLastSave = false ;
224 bool mSave = true ;
225
226 // - - - - - - end user settings - - - - - -
227
228 // todo: add flag if we want to reset omega at each timestep
229
230 // end user settings
231 real mOmegaNewton = 1.0 ;
232 real mOmegaPicard = 1.0 ;
233 real mOmegaNewton2 = 1.0 ;
234 real mOmegaPicard2 = 1.0 ;
235 bool mJustPicard = false ;
236 bool mJustPicard2 = false ;
237
240 uint mThermalFlipCount = 0 ;
241
246 uint mAndersonDepth = 0 ;
247 uint mAndersonDepth2 = 0 ;
248
254 uint mAndersonCommits = 0 ;
255 uint mAndersonCommits2 = 0 ;
256
257 // Picard-breakdown rescue ( see try_escalate_to_newton ). When the magnetic
258 // Picard iteration diverges at a residual far above mEpsilonSwitch -- so the
259 // normal Picard->Newton promotion never fires -- the controller escalates to
260 // the configured Newton tangent once before cutting the timestep. mForceNewton
261 // pins the solver to Newton for the rest of the attempt; mNewtonEscalated caps
262 // the escalation at one per timestep attempt so it cannot ping-pong.
263 bool mForceNewton = false ;
264 bool mNewtonEscalated = false ;
265
266 // Thermal twin of the pair above ( see try_escalate_thermal_to_newton,
267 // ). The thermal Picard residual can floor bit-flat ABOVE
268 // mEpsilonSwitch2, and since the coupled Picard->Newton promotion fires
269 // only below the switch, Newton is gated behind progress that only
270 // Newton can make. Same lifecycle as the magnetic pair: cleared in
271 // initialize_timestep / initialize_thermal, at most one escalation
272 // per timestep attempt.
273 bool mForceNewton2 = false ;
274 bool mNewtonEscalated2 = false ;
275
277 SolverAlgorithm mAlgorithmThermal = SolverAlgorithm::Picard ;
281
282 real mOmega0 = BELFEM_QUIET_NAN ;
283
284 real mOmegaMin = 0.001 ;
285 real mOmegaMax = 1.0 ;
286 real mOmegaMin2 = 0.1 ;
287 real mOmegaMax2 = 1.0 ;
288
289 real mTime0 = 0.0 ;
290 real mTime02 = 0.0 ;
291 Timer * mTimer = nullptr ;
292
293 real mEpsilon = BELFEM_REAL_MAX ;
294 real mEpsilon0 = BELFEM_REAL_MAX ;
295
296 real mEpsilon2 = BELFEM_REAL_MAX ;
297 real mEpsilon20 = BELFEM_REAL_MAX ;
298
302 real mEpsilonAbs2 = BELFEM_REAL_MAX ;
303
310 real mEpsilonAbs = BELFEM_REAL_MAX ;
311
318 uint mThermalFlatCount = 0 ;
319 bool mThermalStalled = false ;
320
327 bool mMagneticHitTarget = false ;
328
334 bool mMagBodyRanLastTrip = true ;
335
336 bool mTripExit = false ;
337
340 real mBestEpsilon = BELFEM_REAL_MAX ;
341 real mBestEpsilon2 = BELFEM_REAL_MAX ;
342 uint mBestEpsilonIteration = 0 ;
343 uint mBestEpsilonIteration2 = 0 ;
344
349 uint mSolverFailCount = 0 ;
350
355 bool mUseLegacyTimestepControl = false ;
356
363 real mCtrlKp = 0.15 ;
364 real mCtrlKi = 0.30 ;
365 real mCtrlKd = 0.0 ;
366
371 real mCtrlErr0 = 1.0 ;
372 real mCtrlErr1 = 1.0 ;
373 real mCtrlErr2 = 1.0 ;
374
381 uint mPostFailureHold = 0 ;
382 uint mPostFailureHoldSteps = 2 ;
383
390 uint mFloorRetries = 0 ;
391 uint mFloorEscalationCap = 4 ;
392
400 uint mMaxFloorRetries = 20 ;
401
404 uint mMaxNumIterationsDeck = 100 ;
405 uint mMaxNumIterations2Deck = 100 ;
406 uint mWatchdogWindowDeck = 30 ;
407 uint mWatchdogWindow2Deck = 30 ;
408
414 bool mAllowRestart = true ;
415
417 uint mIteration = 0 ;
418 uint mIteration2 = 0 ;
419 uint mIterationTime = 0 ;
420 uint mIteration0 = 0 ;
421 uint mIteration02 = 0 ;
422 uint mEigenAnalysisTime = 0 ;
423 uint mPostprocesingTime = 0 ;
424
436
440 // slot 0 : the eigen estimate ( spectral ratio, or kappa_2 when
441 // the symmetric driver earned the name )
442 // slot 1 : MUMPS ADD COND1
443 // slot 2 : MUMPS ADD COND2
444 // slot 3 : MUMPS omega2 -- NOT reported, it is the discriminator
445 // that says whether slot 2 is a measurement at all
448
449 real mDeltaTimeMax = BELFEM_REAL_MAX ;
450 real mDeltaTimeMin = 1e-10 ;
451 bool mReset = false ;
452 bool mResetThermal = false ;
453 bool mFirstFlip = false ;
454 bool mFirstFlip2 = false ;
455
456 bool mIsFullyCoupled = true ;
457 real mCouplingFactor = 1 ; //Number of thermal time steps within each magnetic time steps
458
459
460 Cell < PhysicalBoundaryCondition * > mCircuitCurrentBCs ;
461 Cell < PhysicalBoundaryCondition * > mCircuitVoltageBCs ;
462
463 Vector< real > mLHS ;
464 Vector< real > mLHS0 ;
465 bool mFirstIVSave = true ;
466
469 Cell< string > mIVNamesI ;
470 Cell< string > mIVNamesU ;
471
472 // ring buffer of the last mStallWindow residuals (in dB)
473 ShiftRegister< real > mResidualHistory ;
474
475 Cell< Vector< real > > mBackupFields ;
476 Vector< real > mBackupDofValues ;
477
479 real mLastJJcMax = 0. ;
480
485 bool mBoxSectionOpen = false ;
486
491 bool mPostProcessed = false ;
492
493 public:
494
495 Controller( Kernel * aKernel, Kernel * aKernel2 = nullptr ) ;
496
497 ~Controller();
498
499 void
501
502 void
504
505 void
507
508//------------------------------------------------------------------------------
509
513 void
515
516 void
518
519 void
521
522 bool
524
525 void
526 finalize( const bool aPostProcess = true );
527
528 const real &
529 time() const;
530
531 const real &
532 time_thermal() const;
533
534 real
535 epsilon() const ;
536
537 uint
538 iteration() const ;
539
540
541 bool
542 is_fullycoupled() const ;
543
544 bool
545 reset() const ;
546
547 void
548 save( const std::string & aFilename );
549
550 void
551 save_IV( const std::string & aFilename );
552
558 void
560
561 void
562 set_params( const input::Section * aSection );
563
564 void
565 set_thermal_kernel( Kernel * aKernel );
566
567 real
568 simulation_time() const ;
569
570 bool
571 save() const ;
572
573 void
574 set_circuit( Circuit * aCircuit );
575
576 Circuit *
577 circuit() ;
578
579 Kernel *
580 kernel() ;
581
582 Kernel *
584
585 void
586 save_memdump( const string & aPath );
587
588 void
589 load_memdump( const string & aPath );
590
592 euler_method() const ;
593
594
595 private:
596
597 // imposes the voltage/current boundary conditions on the RHS ( rank 0 only,
598 // after assembly and before the solve ); shared by the magnetic iterate paths
602
603 void
604 iterate_coupled();
605
606 void
607 iterate_magnetic();
608
609 void
610 iterate_thermal();
611
612 void
613 impose_voltage_bcs();
614
615 // env-gated diagnostic dump of the assembled system, shared by both
616 // iterate paths; off unless BELFEM_DUMP_SYSTEM is set.
617 // aTag names the field in the file name, and aCount is that field's
618 // OWN budget -- one shared counter let whichever field assembled
619 // first spend all four dumps and starve the other
620 void
621 dump_system_if_requested( DofManager * aDofMgr,
622 const char * aTag,
623 int & aCount );
624
628 int mDumpCountMagnetic = 0 ;
629 int mDumpCountThermal = 0 ;
630
631
632 // magnetic stagnation guard: if the residual window is flat ( deviation below
633 // mStallBand ), Newton falls back to Picard internally; returns true only when
634 // Picard itself has stalled, signalling the caller to reset_timestep()
635 bool
636 magnetic_stagnation_forces_reset();
637
638 // progress watchdogs ( see mWatchdogWindow ): update the best-residual
639 // tracker and return true when the attempt has made no new minimum for
640 // the configured window while still far from tolerance -- UNLESS the
641 // field's relaxation grew since the previous call, which marks a line
642 // search recovering from an overshoot rather than a stall ( replayed
643 // 2026-08-21: fires on the omega-pinned grinds, spares the AIMD
644 // recovery whose cut used to cascade the timestep down ).
645 //
646 // aOmega must be the relaxation that PRODUCED the current residual --
647 // the caller's post-line-search tOmega / tOmega2 -- never re-derived
648 // from the live algorithm, which a same-call escalation or a
649 // stagnation demotion may already have flipped or mutated.
650 bool
651 watchdog_magnetic( const real aOmega );
652
653 bool
654 watchdog_thermal( const real aOmega );
655
656 // Anderson bookkeeping ( plan §3.2 ): SolverData stages the pair,
657 // the controller decides its fate. Helpers keep the commit
658 // counters and the per-kernel SolverData in sync; all are cheap
659 // no-ops while the respective depth is 0.
660 void anderson_commit_magnetic();
661 void anderson_discard_magnetic();
662 void anderson_clear_magnetic();
663 void anderson_commit_thermal();
664 void anderson_clear_thermal();
665
666 // Picard-breakdown rescue: if the configured terminal algorithm is Newton and
667 // the magnetic Picard iteration has broken down ( residual stuck far above
668 // mEpsilonSwitch, so the normal promotion never fires ), switch to the Newton
669 // tangent for the rest of this timestep attempt instead of cutting Δt. Returns
670 // true if it escalated ( caller keeps iterating ), false otherwise ( caller
671 // resets ). Escalates at most once per attempt, guarded by mNewtonEscalated.
672 bool
673 try_escalate_to_newton();
674
675 // Thermal twin: called from the coupled stagnation
676 // detector when the thermal Picard residual sits bit-flat above
677 // mEpsilonSwitch2 with Newton configured but not running. Returns
678 // true if it escalated. At most once per attempt ( mNewtonEscalated2 ).
679 bool
680 try_escalate_thermal_to_newton();
681
682 void
683 reset_timestep();
684
685 void
686 reset_thermal();
687
688 void
689 adjust_timestep();
690
691 void
692 compute_circuit_current() ;
693
694 void
695 compute_conditioning();
696
697 // MUMPS computes its condition estimate during the SOLVE, so the
698 // error analysis is armed for exactly ONE solve per timestep --
699 // the first iterate -- and disarmed as soon as the value is read.
700 // Leaving it armed ( the pre-2026-08-10 behaviour ) paid for the
701 // analysis on every solve of every iteration and read one value.
702 // The first iterate is also the better sample: it is assembled at
703 // the converged previous step, so kappa is measured at a
704 // comparable state in every timestep and the series is a trend.
705 // All four are no-ops unless that FIELD's error-analysis flag is
706 // set ( mMumpsErrorAnalysis / mMumpsErrorAnalysis2 -- NOT the
707 // eigen flags, which gate a different diagnostic ) and its own
708 // solver is MUMPS. They run on EVERY rank, unguarded:
709 // the ICNTL setting must match across the communicator, and the
710 // branch is taken identically everywhere
711 void
712 arm_conditioning_magnetic();
713
714 void
715 arm_conditioning_thermal();
716
717 void
718 capture_conditioning_magnetic();
719
720 void
721 capture_conditioning_thermal();
722
727 void
728 setup_thermal_eigen();
729
735 void
736 check_magnetic_diagnostics();
737
739 void
740 check_thermal_diagnostics();
741
742//-----------------------------------------------------------------------------
743
760 void
761 check_iterative_solver_headroom(
762 DofManager * aDofMgr,
763 const real aNonlinTol,
764 const char * aFieldName ) const ;
765
766//-----------------------------------------------------------------------------
767
778 void
779 check_compression_headroom(
780 DofManager * aDofMgr,
781 const real aNonlinTol,
782 const char * aFieldName ) const ;
783
784//-----------------------------------------------------------------------------
785
793 void
794 synchronize_history_fields(
795 IWG_Timestep * aEquation,
796 DofManager * aDofMgr,
797 const uint aStepCount,
798 const string & aPath,
799 const char * aEquationName );
800
801 void
802 print_header();
803
804 void
805 print_line( const real aOmega, const real aOmega2 );
806
807 void
808 print_line_magnetic( const real aOmega );
809
810 void
811 print_line_thermal( const real aOmega );
812
813 void
814 print_footer();
815
819 void
820 print_thermal_stall_warning();
821
822 real
823 get_Tmax();
824
825 real
826 get_Imax();
827
835 string
836 excitation_cell();
837
838 real
839 get_JJCmax();
840
841 void
842 print_physics_stats();
843
844 void
845 reset_dotQ();
846
847 void
848 collect_dotQ();
849
850 };
851
852 inline
853 Circuit *
855 {
856 return mCircuit;
857 }
858
859 inline
860 Kernel *
862 {
863 return mKernel;
864 }
865
866 inline
867 Kernel *
869 {
870 return mKernel2;
871 }
872
873 inline
876 {
877 return mTimeStepping;
878 }
879
880 }
881}
882
883#endif //CL_FEM_CONTROLLER_HPP
Definition cl_Circuit.hpp:20
Top-level container for all mesh entities.
Definition cl_Mesh.hpp:60
High-resolution wall-clock timing.
Definition cl_Timer.hpp:28
void create_iv_names()
names the I/U pair of every abstract dof: after the deck label of the terminal condition that drives ...
Definition cl_FEM_Controller.cpp:4118
void solve_thermal()
Definition cl_FEM_Controller.cpp:2068
EulerMethod euler_method() const
Definition cl_FEM_Controller.hpp:875
void set_circuit(Circuit *aCircuit)
Definition cl_FEM_Controller.cpp:5161
Kernel * thermal_kernel()
Definition cl_FEM_Controller.hpp:868
const real & time() const
Definition cl_FEM_Controller.cpp:143
bool is_fullycoupled() const
Definition cl_FEM_Controller.cpp:4076
void save_IV(const std::string &aFilename)
Definition cl_FEM_Controller.cpp:4209
void save(const std::string &aFilename)
Definition cl_FEM_Controller.cpp:4088
void solve_magnetic()
Definition cl_FEM_Controller.cpp:2047
bool reset() const
Definition cl_FEM_Controller.cpp:4082
Controller(Kernel *aKernel, Kernel *aKernel2=nullptr)
Definition cl_FEM_Controller.cpp:76
const real & time_thermal() const
Definition cl_FEM_Controller.cpp:149
real simulation_time() const
Definition cl_FEM_Controller.cpp:5131
void initialize_magnetic()
Definition cl_FEM_Controller.cpp:329
void set_params(const input::Section *aSection)
Definition cl_FEM_Controller.cpp:4319
void save_memdump(const string &aPath)
Definition cl_FEM_Controller.cpp:5259
void set_thermal_kernel(Kernel *aKernel)
Definition cl_FEM_Controller.cpp:5068
void initialize_thermal()
Definition cl_FEM_Controller.cpp:440
bool solve_circuit()
Definition cl_FEM_Controller.cpp:2565
Kernel * kernel()
Definition cl_FEM_Controller.hpp:861
real epsilon() const
Definition cl_FEM_Controller.cpp:155
uint iteration() const
Definition cl_FEM_Controller.cpp:161
void initialize_timestep()
Definition cl_FEM_Controller.cpp:167
Circuit * circuit()
Definition cl_FEM_Controller.hpp:854
void load_memdump(const string &aPath)
Definition cl_FEM_Controller.cpp:5349
void finalize(const bool aPostProcess=true)
Definition cl_FEM_Controller.cpp:3059
void solve_coupled()
Definition cl_FEM_Controller.cpp:973
this class creates the DOFs based on the passed equation object.
Definition cl_FEM_DofManager.hpp:55
Base class for transient problems.
Definition cl_IWG_Timestep.hpp:33
Top-level orchestrator; owns the mesh, materials, boundary conditions and DOF managers.
Definition cl_FEM_Kernel.hpp:50
One hierarchical section of a configuration file.
Definition cl_Input_Section.hpp:34
Definition cl_IFB_LINE3.hpp:21
SolverAlgorithm
Definition en_FEM_SolverAlgorithm.hpp:20
@ Picard
Definition en_FEM_SolverAlgorithm.hpp:23
USER GUIDES:
Definition cl_Capacitor.cpp:16
EulerMethod
Definition en_SolverEnums.hpp:47
@ BackwardDifference1
Definition en_SolverEnums.hpp:52
unsigned int uint
Definition typedefs.hpp:30
int proc_t
Definition commtypes.hpp:29
double real
Definition typedefs.hpp:36
#define BELFEM_REAL_MAX
Definition typedefs.hpp:81
#define BELFEM_QUIET_NAN
Definition typedefs.hpp:87