Skip to main content

FvMatrix

Struct FvMatrix 

Source
pub struct FvMatrix {
    pub mesh: Arc<FvMesh>,
    pub ldu: LduMatrix,
    pub source: Field<f64>,
}
Expand description

Sparse implicit matrix equation A·φ = b for a scalar field φ.

Mirrors Foam::fvMatrix<scalar> from src/finiteVolume/fvMatrices/fvMatrix/fvMatrix.H.

Assembled incrementally by fvm:: operators in Layer 3; solved via self.solve().

Fields§

§mesh: Arc<FvMesh>

Mesh the equation is defined on (shares the face addressing).

§ldu: LduMatrix

Sparse LDU coefficients of the operator A.

§source: Field<f64>

Right-hand-side source term, length n_cells.

Implementations§

Source§

impl FvMatrix

Source

pub fn new(mesh: Arc<FvMesh>) -> Self

Create a new zero-initialised FvMatrix for the given mesh.

The LDU face addressing holds the mesh’s internal faces, then one slot per CyclicCoupling (conformal periodic seam), then one slot per AmiWeight of each AmiCoupling (non-conformal periodic / AMI seam, in ami_couplings order — see FvMesh::ami_ldu_start). Every matrix built on a given mesh therefore shares one structure — a prerequisite for the coefficient-wise matrix arithmetic (+/−). Operators that ignore seams (e.g. fvm::ddt) simply leave those slots zero; fvm::laplacian/fvm::div fill them via the paired-cell coupling.

Source

pub fn solve( &self, name: impl Into<String>, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve A·φ = source and return the solution as a VolScalarField.

Uses Gauss-Seidel as the default solver. Layer 3 will add conjugate gradient / GAMG when those are ported.

Source

pub fn solve_cg( &self, name: impl Into<String>, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve the system with preconditioned conjugate gradient (cold start).

PCG requires a symmetric SPD matrix (upper == lower), which holds for the pressure Poisson equation assembled by fvm::laplacian. It converges in O(√κ) iterations versus O(κ) for Gauss-Seidel — dramatically faster for the elliptic pressure solve. Do not use it for the asymmetric convection-bearing momentum matrix.

This starts the iteration from x = 0. In a transient solver, prefer solve_cg_with_guess to warm-start from the previous time step’s field — near steady state that converges in a handful of iterations instead of from scratch every step.

Source

pub fn solve_cg_with_guess( &self, name: impl Into<String>, initial: &VolScalarField, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve with PCG, warm-started from initial (typically the previous time step’s field).

The DIC-preconditioned CG begins from initial.internal instead of zero. For a transient run approaching steady state the solution barely changes between steps, so the starting residual is tiny and the solve completes in very few iterations — often zero. See conjugate_gradient for the preconditioner and warm-start details.

Source

pub fn solve_gamg( &self, name: impl Into<String>, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve the system with GAMG (algebraic multigrid), cold-started from x = 0.

GAMG requires a symmetric SPD matrix (upper == lower) — the pressure Poisson case. It is near mesh-independent (a handful of V-cycles), unlike PCG whose iteration count grows with the mesh, so it is the better choice for the pressure solve on fine grids. As with PCG, prefer solve_gamg_with_guess in a transient loop to warm-start from the previous time step’s field.

Source

pub fn solve_gamg_with_guess( &self, name: impl Into<String>, initial: &VolScalarField, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve with GAMG, warm-started from initial (typically the previous time step’s field). See gamg for the multigrid algorithm and solve_gamg for the cold variant.

Source

pub fn solve_bicgstab( &self, name: impl Into<String>, options: KrylovOptions, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve the system with preconditioned BiCGStab, cold-started from x = 0.

This is the solver to use for any equation carrying a convection term — scalar transport, energy, species — where the matrix is asymmetric (lower[f] != upper[f]) because upwinding puts the flux on the donor side only. PCG (solve_cg) and GAMG (solve_gamg) require symmetry and must not be used on those matrices; the only prior alternative was solve’s Gauss-Seidel, whose iteration count grows like the condition number.

With the default KrylovOptions this is ILU(0)-preconditioned BiCGStab — the direct analogue of OpenFOAM’s PBiCGStab with DILU.

settings.tolerance is tested against the relative 2-norm residual ||b − A·phi||₂ / ||b||₂ (the same measure solve_cg uses), not the L1-scaled measure solve reports.

In a transient loop prefer solve_bicgstab_with_guess to warm-start from the previous time step.

Source

pub fn solve_bicgstab_with_guess( &self, name: impl Into<String>, initial: &VolScalarField, options: KrylovOptions, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve with preconditioned BiCGStab, warm-started from initial (typically the previous time step’s field).

See solve_bicgstab for when to use BiCGStab at all. Near steady state the starting residual is already tiny, so the solve completes in a handful of iterations — often zero.

Source

pub fn solve_gmres( &self, name: impl Into<String>, options: KrylovOptions, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve the system with restarted, right-preconditioned GMRES(m), cold-started from x = 0.

GMRES minimises the residual over the Krylov subspace, so its residual history is monotone and it cannot break down the way BiCGStab can — at the cost of storing options.restart basis vectors (O(restart · n_cells) memory). Reach for it when solve_bicgstab reports converged = false on a strongly nonnormal (high-Peclet, highly non-orthogonal) matrix.

Like solve_bicgstab, settings.tolerance is tested against ||b − A·phi||₂ / ||b||₂.

Source

pub fn solve_gmres_with_guess( &self, name: impl Into<String>, initial: &VolScalarField, options: KrylovOptions, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve with restarted GMRES(m), warm-started from initial.

See solve_gmres.

Source

pub fn solve_krylov( &self, name: impl Into<String>, initial: Option<&VolScalarField>, method: KrylovMethod, options: KrylovOptions, settings: SolverSettings, ) -> (VolScalarField, SolverPerformance)

Solve with the Krylov method named by method, optionally warm-started.

The general form behind solve_bicgstab and solve_gmres; use it when the method is chosen at run time (e.g. fall back from BiCGStab to GMRES after a breakdown) instead of being fixed at the call site.

initial is the starting iterate; None starts from zero.

Source

pub fn add_to_diag(&mut self, coeff: &Field<f64>)

Add coeff * I to the diagonal (e.g. from a time derivative term).

Source

pub fn add_to_source(&mut self, term: &Field<f64>)

Add coeff[c] to the source at cell c.

Source

pub fn add_face_coeff(&mut self, face: usize, coeff: f64)

Add upper/lower contributions from a face (used by fvm::laplacian etc.).

Source

pub fn set_reference(&mut self, cell: usize, value: f64)

Pin one cell to a reference value — fixes the singular pressure matrix in a closed domain (no fixed-pressure BCs).

Adds a large coefficient to diag[cell] and a matching term to source[cell] so that the solution is forced toward value.

Source

pub fn a_field(&self) -> VolScalarField

Diagonal coefficient per cell: A[c] = diag[c].

Used in PISO: rAU = 1 / pEqn.a_field().

Source

pub fn h_field(&self, x: &VolScalarField) -> VolScalarField

Off-diagonal residual: H[c] = source[c] − Σ off-diag · x.

For a zero initial guess x = 0 this is just source. Used in pressure correction: H = pEqn.h_field(p).

Trait Implementations§

Source§

impl Add for FvMatrix

Source§

type Output = FvMatrix

The resulting type after applying the + operator.
Source§

fn add(self, rhs: Self) -> Self

Performs the + operation. Read more
Source§

impl AddAssign for FvMatrix

Source§

fn add_assign(&mut self, rhs: Self)

Performs the += operation. Read more
Source§

impl Neg for FvMatrix

Source§

type Output = FvMatrix

The resulting type after applying the - operator.
Source§

fn neg(self) -> Self

Performs the unary - operation. Read more
Source§

impl Sub for FvMatrix

Source§

type Output = FvMatrix

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: Self) -> Self

Performs the - operation. Read more
Source§

impl SubAssign for FvMatrix

Source§

fn sub_assign(&mut self, rhs: Self)

Performs the -= operation. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.