BELFEM 0.9.0
Berkeley Lab Finite Element Framework
Loading...
Searching...
No Matches
belfem::solver::Wrapper Class Reference

parent class for solver specific data More...

#include <cl_SolverWrapper.hpp>

Inheritance diagram for belfem::solver::Wrapper:
[legend]
Collaboration diagram for belfem::solver::Wrapper:
[legend]

Public Member Functions

 Wrapper (const string &aLabel, const bool aUsesMPI)
virtual ~Wrapper ()
const stringlabel () const
 returns the name of the solver as string
void set_soft_fail (const bool aFlag)
 arm/disarm the soft-fail contract ( see the member note )
bool failed () const
 true if the last factorization/solve failed softly
void clear_failure ()
 clear a recorded soft failure before the next solve
virtual void solve (SpMatrix &aMatrix, Vector< real > &aLHS, Vector< real > &aRHS)
virtual void solve (SpMatrix &aMatrix, Matrix< real > &aLHS, Matrix< real > &aRHS)
bool is_initialized () const
 tells if the initialitzation routine has already been called
proc_t rank () const
 returns the communication rank of this proc
proc_t comm_size () const
 returns the communication size of this proc
bool uses_mpi () const
virtual void initialize (SpMatrix &aMatrix, const SymmetryMode aSymmetryMode=SymmetryMode::Unsymmetric, const int_t aNumRhsColumns=1)
void free () override
virtual real get_determinant () const
 returns the determinant, if supported by the solver and computation was requested
virtual real get_cond1 () const
 returns the conditioning numbner, if supported by the solver and computation was requested
virtual real get_cond2 () const
 returns the conditioning numbner, if supported by the solver and computation was requested
virtual real get_forward_error () const
 estimated FORWARD error of the last solve, || dx || / || x ||, if supported by the solver and computation was requested.
virtual real get_backward_error () const
 componentwise BACKWARD error of the last solve, if supported by the solver and computation was requested: the smallest relative perturbation of A and b for which the computed x is exact.
virtual real get_omega2 () const
 the SECOND half of that backward error on its own, if supported.
virtual bool supports_factorization_reuse () const
 true if this wrapper can solve against an EXISTING factorization rather than rebuilding it.
virtual void freeze_factorization (const SpMatrix &aMatrix)
 arm the frozen state: subsequent solves reuse the factorization that the LAST SUCCESSFUL solve built, instead of rebuilding it.
virtual void unfreeze_factorization ()
 drop the frozen state and return to ordinary re-factorizing solves.
virtual bool factorization_is_frozen () const
 true while the frozen scope is armed
Public Member Functions inherited from belfem::CommunicationObject
 CommunicationObject ()
 ~CommunicationObject ()
index_t index () const

Protected Member Functions

bool soft_fail () const
 subclass hooks for the soft-fail contract
void flag_failure ()
virtual void initialize ()
void hatch_turtle ()
 print a warning ( the turtle ) when the MPI ranks sharing a node ask for more OpenMP threads than the node has PHYSICAL cores.
void mat2vec (const Matrix< real > &aM, Vector< real > &aV)
void vec2mat (const Vector< real > &aV, Matrix< real > &aM)
SpMatrixmatrix ()
Vector< real > & x ()
Vector< real > & y ()

Protected Attributes

SpMatrixmMatrix = nullptr
Vector< real > * mX = nullptr
Vector< real > * mY = nullptr

Detailed Description

parent class for solver specific data

Constructor & Destructor Documentation

◆ Wrapper()

belfem::solver::Wrapper::Wrapper ( const string & aLabel,
const bool aUsesMPI )

◆ ~Wrapper()

belfem::solver::Wrapper::~Wrapper ( )
virtual

Member Function Documentation

◆ clear_failure()

void belfem::solver::Wrapper::clear_failure ( )
inline

clear a recorded soft failure before the next solve

◆ comm_size()

proc_t belfem::solver::Wrapper::comm_size ( ) const
inline

returns the communication size of this proc

◆ factorization_is_frozen()

bool belfem::solver::Wrapper::factorization_is_frozen ( ) const
virtual

true while the frozen scope is armed

Reimplemented in belfem::solver::MUMPS.

◆ failed()

bool belfem::solver::Wrapper::failed ( ) const
inline

true if the last factorization/solve failed softly

◆ flag_failure()

void belfem::solver::Wrapper::flag_failure ( )
inlineprotected

◆ free()

void belfem::solver::Wrapper::free ( )
overridevirtual

Reimplemented from belfem::CommunicationObject.

◆ freeze_factorization()

void belfem::solver::Wrapper::freeze_factorization ( const SpMatrix & aMatrix)
virtual

arm the frozen state: subsequent solves reuse the factorization that the LAST SUCCESSFUL solve built, instead of rebuilding it.

This is a scope, not a hint, and the caller owns the whole of it:

solve( A, x, b ) <- builds the factorization freeze_factorization( A ) <- arm, only after that succeeded solve( A, y, c ) ... <- reuse, values of A must NOT change unfreeze_factorization() <- always, including on every failure

Why a scope rather than a flag: if the values of A change while frozen, the solver returns a valid-LOOKING solution of the wrong matrix, with no error anywhere. Pointer identity cannot detect that – the wrapper already treats the same pointer as "same structure, different values" and deliberately re-factorizes for exactly this reason. So the contract is that NO assembly may happen inside the scope, the caller guarantees it, and the wrapper checks everything about the matrix it cheaply can ( structure and identity, not an O( nnz ) values scan on every solve ).

Checks are ALWAYS-ACTIVE errors rather than assertions: a silent stale-factor solve is precisely the failure that must not survive into a release build.

Rank behaviour: only the rank that owns the matrix can record its identity – on every other rank the matrix argument is a local submatrix or empty, and the distributed solvers never read it. So a worker records only that it is frozen. Uniformity comes from the caller arming and dropping the scope at the same point of the same code path on every rank, never from a rank-local decision.

The default implementation throws: a wrapper that does not support reuse must be asked via supports_factorization_reuse() first

Reimplemented in belfem::solver::MUMPS.

◆ get_backward_error()

real belfem::solver::Wrapper::get_backward_error ( ) const
virtual

componentwise BACKWARD error of the last solve, if supported by the solver and computation was requested: the smallest relative perturbation of A and b for which the computed x is exact.

Near machine precision means the solver did its job and any lost accuracy is the matrix's doing, not the factorization's

Reimplemented in belfem::solver::MUMPS.

◆ get_cond1()

real belfem::solver::Wrapper::get_cond1 ( ) const
virtual

returns the conditioning numbner, if supported by the solver and computation was requested

Reimplemented in belfem::solver::MUMPS.

◆ get_cond2()

real belfem::solver::Wrapper::get_cond2 ( ) const
virtual

returns the conditioning numbner, if supported by the solver and computation was requested

Reimplemented in belfem::solver::MUMPS.

◆ get_determinant()

real belfem::solver::Wrapper::get_determinant ( ) const
virtual

returns the determinant, if supported by the solver and computation was requested

Reimplemented in belfem::solver::MUMPS, and belfem::solver::PARDISO.

◆ get_forward_error()

real belfem::solver::Wrapper::get_forward_error ( ) const
virtual

estimated FORWARD error of the last solve, || dx || / || x ||, if supported by the solver and computation was requested.

Distinct from the condition numbers above: those bound the worst case the matrix admits, this reports how many digits the solve actually lost. That makes it the cheaper thing to steer on – a timestepper can read it directly – while the condition number is the more descriptive figure to show a user

Reimplemented in belfem::solver::MUMPS.

◆ get_omega2()

real belfem::solver::Wrapper::get_omega2 ( ) const
virtual

the SECOND half of that backward error on its own, if supported.

Zero means the term it weights contributes nothing to the forward error, so the matching second condition number is inert for this solve. Deliberately stated in terms of the ERROR BOUND and not of any one solver's internals – what makes a row of the split empty is the implementation's business, and MUMPS documents its own rule on the override

Reimplemented in belfem::solver::MUMPS.

◆ hatch_turtle()

void belfem::solver::Wrapper::hatch_turtle ( )
protected

print a warning ( the turtle ) when the MPI ranks sharing a node ask for more OpenMP threads than the node has PHYSICAL cores.

Each rank spawns omp_get_max_threads() BLAS/solver threads, and the runtimes cannot see each other: with OMP_NUM_THREADS unset each one defaults to its affinity mask, which counts every hyperthread.

The cost is time and memory, not a hang: measured on this code, 4 ranks x 4 threads on 10 physical cores ran the factorization ~15 % slower than 4 x 2 and used ~13 GiB more ( doc/parallel_execution.md ). BELFEM's element loop carries no omp pragmas, so the extra threads cannot help the assembly at all – only STRUMPACK and MKL consume them.

Self-checking: a no-op unless oversubscribed, a no-op when the physical core count cannot be established ( an unknown budget must never become a recommendation ), and a no-op entirely when built without OpenMP.

The budget comes from THIS rank's affinity mask, which no rank can compare against its siblings' without a node-local communicator. The two configurations separate arithmetically instead: disjoint per-rank slices must fit inside the machine, a shared mask cannot, so cores_in_my_mask * ranks_on_node <= cores_on_machine classifies them. Ambiguity is resolved toward NOT warning – a false alarm on a correctly bound run teaches the reader to ignore the box.

LIMITATIONS: a shared cgroup smaller than the machine can look like a set of slices and be under-warned; cpu_set_t is fixed at CPU_SETSIZE, so a mask wider than that yields no budget at all. In that last case the warning still fires when OMP_NUM_THREADS was never set and several ranks share the node – it just names no number, because a budget it could not measure must never become a recommendation.

◆ initialize() [1/2]

void belfem::solver::Wrapper::initialize ( )
protectedvirtual

◆ initialize() [2/2]

void belfem::solver::Wrapper::initialize ( SpMatrix & aMatrix,
const SymmetryMode aSymmetryMode = SymmetryMode::Unsymmetric,
const int_t aNumRhsColumns = 1 )
virtual

◆ is_initialized()

bool belfem::solver::Wrapper::is_initialized ( ) const
inline

tells if the initialitzation routine has already been called

◆ label()

const string & belfem::solver::Wrapper::label ( ) const

returns the name of the solver as string

Returns

◆ mat2vec()

void belfem::solver::Wrapper::mat2vec ( const Matrix< real > & aM,
Vector< real > & aV )
protected

◆ matrix()

SpMatrix * belfem::solver::Wrapper::matrix ( )
inlineprotected

◆ rank()

proc_t belfem::solver::Wrapper::rank ( ) const
inline

returns the communication rank of this proc

◆ set_soft_fail()

void belfem::solver::Wrapper::set_soft_fail ( const bool aFlag)
inline

arm/disarm the soft-fail contract ( see the member note )

◆ soft_fail()

bool belfem::solver::Wrapper::soft_fail ( ) const
inlineprotected

subclass hooks for the soft-fail contract

◆ solve() [1/2]

void belfem::solver::Wrapper::solve ( SpMatrix & aMatrix,
Matrix< real > & aLHS,
Matrix< real > & aRHS )
virtual

◆ solve() [2/2]

void belfem::solver::Wrapper::solve ( SpMatrix & aMatrix,
Vector< real > & aLHS,
Vector< real > & aRHS )
virtual

◆ supports_factorization_reuse()

bool belfem::solver::Wrapper::supports_factorization_reuse ( ) const
virtual

true if this wrapper can solve against an EXISTING factorization rather than rebuilding it.

Default false: a wrapper that has not implemented the frozen path must never be asked to take it

Reimplemented in belfem::solver::MUMPS.

◆ unfreeze_factorization()

void belfem::solver::Wrapper::unfreeze_factorization ( )
virtual

drop the frozen state and return to ordinary re-factorizing solves.

Safe to call when not frozen, so a scope guard can call it unconditionally on the way out

Reimplemented in belfem::solver::MUMPS.

◆ uses_mpi()

bool belfem::solver::Wrapper::uses_mpi ( ) const
inline

◆ vec2mat()

void belfem::solver::Wrapper::vec2mat ( const Vector< real > & aV,
Matrix< real > & aM )
protected

◆ x()

Vector< real > & belfem::solver::Wrapper::x ( )
inlineprotected

◆ y()

Vector< real > & belfem::solver::Wrapper::y ( )
inlineprotected

Member Data Documentation

◆ mMatrix

SpMatrix* belfem::solver::Wrapper::mMatrix = nullptr
protected

◆ mX

Vector< real >* belfem::solver::Wrapper::mX = nullptr
protected

◆ mY

Vector< real >* belfem::solver::Wrapper::mY = nullptr
protected

The documentation for this class was generated from the following files: