Current State
The solver has some exception usage, but it lacks a solver-wide infrastructure that would be useful for a modular FE plan.
- Most production code throws generic standard exceptions, predominantly
std::runtime_error, spread across many modules. Examples include Code/Source/solver/Parameters.h:166, Code/Source/solver/Vector.h
- There is one localized custom exception family for boundary-condition handling in
Code/Source/solver/BoundaryCondition.h, but it is subsystem-specific. It stores only a message string and is not tied to shared status codes, source locations, MPI context, or common solver macros.
- Some failure paths bypass exceptions entirely and terminate the process directly, for example
Code/Source/solver/trilinos_impl.cpp.
- The solver execution path also does not currently have a consistent top-level exception boundary. The
read_files() catch is commented out in Code/Source/solver/main.cpp, while the simulation loop proceeds without a surrounding catch in Code/Source/solver/main.cpp.
Solution
We want to implement a core exception system that can define failure handling into a set of shared contracts instead of a pile of unrelated strings and exits. This system will need to be able to accommodate the following:
- A types list that provides a common vocabulary: semantic index types like
LocalIndex, GlobalIndex, an DofIndex etc,, plus a status taxonomy. The current solver mixes raw int/double, backend-native codes like PetscErrorCode, and subsystem-local conventions, so there is no single way to say “this is invalid input” versus “this is a backend failure” versus “this is a convergence failure.”
FEException class to add a base exception carrying structured context: message, status, file/line/function, MPI rank, and optional debug stack trace. It also will define typed subclasses like InvalidArgumentException in and standardized throw/check macros.
- Against the current code, that would give three immediate benefits: failures become classifiable instead of string-only, tests can assert on error categories instead of exact text, and MPI/backend failures can be surfaced consistently instead of sometimes throwing, sometimes aborting, and sometimes just printing. This will be crucial for testing modular subsystems in the future.
Current State
The solver has some exception usage, but it lacks a solver-wide infrastructure that would be useful for a modular FE plan.
std::runtime_error, spread across many modules. Examples includeCode/Source/solver/Parameters.h:166, Code/Source/solver/Vector.hCode/Source/solver/BoundaryCondition.h, but it is subsystem-specific. It stores only a message string and is not tied to shared status codes, source locations, MPI context, or common solver macros.Code/Source/solver/trilinos_impl.cpp.read_files()catch is commented out inCode/Source/solver/main.cpp, while the simulation loop proceeds without a surrounding catch inCode/Source/solver/main.cpp.Solution
We want to implement a core exception system that can define failure handling into a set of shared contracts instead of a pile of unrelated strings and exits. This system will need to be able to accommodate the following:
LocalIndex,GlobalIndex, anDofIndexetc,, plus a status taxonomy. The current solver mixes raw int/double, backend-native codes likePetscErrorCode, and subsystem-local conventions, so there is no single way to say “this is invalid input” versus “this is a backend failure” versus “this is a convergence failure.”FEExceptionclass to add a base exception carrying structured context: message, status, file/line/function, MPI rank, and optional debug stack trace. It also will define typed subclasses likeInvalidArgumentExceptionin and standardized throw/check macros.