Skip to main content

outram_foam_basic_lib/mesh/
error.rs

1// SPDX-License-Identifier: GPL-3.0-only
2// Copyright (C) 2026 OUTRAM PARK contributors
3
4/// Errors produced by the mesh layer (mesh construction and validation).
5#[derive(Debug, Clone, PartialEq)]
6pub enum MeshError {
7    /// An array field in the mesh has the wrong length.
8    ///
9    /// For example, `owner` must have length `n_faces`; `neighbour` must have
10    /// length `n_internal_faces`; `cell_volumes` must have length `n_cells`.
11    ArrayLengthMismatch {
12        /// Name of the offending array (e.g. `"owner"`, `"cell_volumes"`).
13        array: &'static str,
14        expected: usize,
15        got: usize,
16    },
17
18    /// A boundary patch does not start immediately after the previous one,
19    /// leaving a gap or overlap in face coverage.
20    PatchStartMismatch {
21        /// Name of the offending patch.
22        name: String,
23        expected: usize,
24        got: usize,
25    },
26
27    /// The sum of all patch sizes does not equal the number of boundary faces.
28    PatchCoverageMismatch {
29        /// Total face count covered by all patches.
30        covered: usize,
31        /// Total face count in the mesh.
32        n_faces: usize,
33    },
34
35    /// `number_of_cells` was zero or negative when building a 1-D mesh.
36    NonPositiveCellCount { got: i64 },
37
38    /// A [`PatchKind::Cyclic`](crate::mesh::PatchKind::Cyclic) patch pair is
39    /// inconsistent — e.g. the partner index is out of range, the partner does
40    /// not name this patch back, or the two halves have different face counts.
41    CyclicPairMismatch {
42        /// Name of the offending cyclic patch.
43        name: String,
44        /// Why the pair is invalid.
45        reason: &'static str,
46    },
47
48    /// A [`PatchKind::CyclicAmi`](crate::mesh::PatchKind::CyclicAmi)
49    /// (non-conformal periodic) coupling is inconsistent — e.g. a target/source
50    /// cell or face index is out of range, or a target face has no overlapping
51    /// source faces.
52    AmiCouplingInvalid {
53        /// Global face index of the offending AMI target face.
54        target_face: usize,
55        /// Why the coupling is invalid.
56        reason: &'static str,
57    },
58}
59
60impl std::fmt::Display for MeshError {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        match self {
63            MeshError::ArrayLengthMismatch {
64                array,
65                expected,
66                got,
67            } => write!(
68                f,
69                "mesh array '{array}': expected length {expected}, got {got}"
70            ),
71            MeshError::PatchStartMismatch {
72                name,
73                expected,
74                got,
75            } => write!(
76                f,
77                "patch '{name}': expected to start at face {expected}, starts at {got}"
78            ),
79            MeshError::PatchCoverageMismatch { covered, n_faces } => write!(
80                f,
81                "boundary patches cover {covered} faces but n_faces = {n_faces}"
82            ),
83            MeshError::NonPositiveCellCount { got } => {
84                write!(f, "number_of_cells must be ≥ 1, got {got}")
85            }
86            MeshError::CyclicPairMismatch { name, reason } => {
87                write!(f, "cyclic patch '{name}': {reason}")
88            }
89            MeshError::AmiCouplingInvalid {
90                target_face,
91                reason,
92            } => {
93                write!(f, "AMI coupling at target face {target_face}: {reason}")
94            }
95        }
96    }
97}
98
99impl std::error::Error for MeshError {}