Skip to main content

FvMesh

Struct FvMesh 

Source
pub struct FvMesh {
Show 13 fields pub n_cells: usize, pub n_internal_faces: usize, pub n_faces: usize, pub owner: Vec<usize>, pub neighbour: Vec<usize>, pub patches: Vec<BoundaryPatch>, pub cyclic_couplings: Vec<CyclicCoupling>, pub ami_couplings: Vec<AmiCoupling>, pub cell_volumes: Vec<f64>, pub cell_centres: Vec<Vector3>, pub face_area_vectors: Vec<Vector3>, pub face_areas: Vec<f64>, pub face_centres: Vec<Vector3>,
}
Expand description

Finite-volume mesh — topology and geometry in a flat data structure.

Mirrors Foam::fvMesh (src/finiteVolume/fvMesh/fvMesh.H) but without the C++ inheritance chain (polyMesh → primitiveMesh → lduMesh). Only the data required by the FV operators is stored.

§Face ordering (OpenFOAM convention)

[0 .. n_internal_faces)         ← internal faces (have both owner & neighbour)
[n_internal_faces .. n_faces)   ← boundary faces (owner only)

The neighbour array has length n_internal_faces; boundary faces have no entry in neighbour.

§Getting one

This was a documented friction point in an API dogfood run (gh #58): the prelude exports FvMesh, but nothing told the reader how to obtain one, and they ended up reading the test suite to find out. The ready-made constructors are listed here so that is not necessary:

  • FvMesh::periodic_1d — a 1-D periodic column of n cells. The usual choice for verifying an operator against an analytic solution, since periodicity removes boundary treatment from the comparison.
  • FvMesh::periodic_ring_ami — a periodic ring with a non-conformal AMI interface, for exercising the AMI paths.
  • FvMeshBuilder — build one face by face when neither fits.

Meshes are shared by the field types via Arc, so wrap it once:

use outram_foam_basic_lib::prelude::*;
use std::sync::Arc;

// 16 cells over a unit length, unit cross-sectional area.
let mesh = Arc::new(FvMesh::periodic_1d(16, 1.0, 1.0));
assert_eq!(mesh.n_cells, 16);   // a public field, not a method

// A field is then built on that mesh.
let phi = VolScalarField::uniform("phi", mesh.clone(), 0.0);
assert_eq!(phi.internal.len(), 16);

Fields§

§n_cells: usize

Number of cells.

§n_internal_faces: usize

Number of internal faces (both owner and neighbour defined).

§n_faces: usize

Total number of faces (internal + boundary).

§owner: Vec<usize>

owner[f] — cell that owns face f (for all faces).

§neighbour: Vec<usize>

neighbour[f] — cell on the other side of internal face f. Length == n_internal_faces; boundary faces have no neighbour.

§patches: Vec<BoundaryPatch>

Boundary patch descriptors (one per patch, in face-index order).

§cyclic_couplings: Vec<CyclicCoupling>

Across-seam cell couplings from PatchKind::Cyclic (periodic) patch pairs, one entry per matched boundary-face pair. Empty for a mesh with no (resolved) cyclic pairs. Each entry is treated by the FV operators and the LDU matrix exactly like an internal face joining CyclicCoupling::owner and CyclicCoupling::neighbour, appended to the LDU face addressing after the n_internal_faces internal faces.

§ami_couplings: Vec<AmiCoupling>

Across-seam couplings from PatchKind::CyclicAmi (non-conformal periodic) patch pairs, one entry per target seam face. Empty for a mesh with no AMI pairs. Each entry couples its target cell to a weighted set of source cells (the geometric face overlaps); the FV operators and the LDU matrix append one LDU face per AmiWeight after the internal faces and the cyclic_couplings (see ami_ldu_start). Mirrors OpenFOAM cyclicAMIFvPatchField.

§cell_volumes: Vec<f64>

Cell volumes V[c] [m³].

§cell_centres: Vec<Vector3>

Cell centres C[c] [m].

§face_area_vectors: Vec<Vector3>

Face area vectors Sf[f] [m²], pointing from owner toward neighbour (or outward for boundary faces).

§face_areas: Vec<f64>

Face area magnitudes |Sf[f]| [m²].

§face_centres: Vec<Vector3>

Face centres Cf[f] [m].

Implementations§

Source§

impl FvMesh

Source

pub fn ami_ldu_start(&self) -> usize

First LDU face index occupied by AMI seam couplings.

AMI partial-seam faces live after the internal faces and the CyclicCouplings, so the AMI block starts at n_internal_faces + cyclic_couplings.len(). Operators and FvMatrix::new both iterate the AMI couplings in order from this base, one LDU face per AmiWeight, so the addressing lines up.

Source

pub fn n_ami_faces(&self) -> usize

Total number of AMI partial-seam LDU faces — the sum of each AMI target face’s number of weighted source contributions.

Source

pub fn periodic_ring_ami( n_a: usize, n_b: usize, lx: f64, ly: f64, depth: f64, ) -> FvMesh

Build a non-conformal periodic ring with two cyclicAMI seams, programmatically (no polyMesh parser).

The mesh is a closed loop of two cell columns, periodic in x, whose two column-joining interfaces are both AMI seams so the two halves may be subdivided differently in the transverse (y) direction — the defining non-conformality AMI exists to handle:

       wrap seam (x = 0 ≡ x = lx, period +lx·x̂)
  ┌──────────────────────────────────────────────┐
  │                                               │
 A column (n_a cells in y)     B column (n_b cells in y)
  │      x ∈ [0, lx/2]           x ∈ [lx/2, lx]   │
  └────────── mid seam (x = lx/2) ────────────────┘
  • A column — n_a cells stacked in y ∈ [0, ly], centres at x = lx/4; each cell owns a mid-seam face (x = lx/2, target of the mid AMI) and a wrap-seam face (x = 0, source of the wrap AMI).
  • B column — n_b cells stacked in y ∈ [0, ly], centres at x = 3lx/4; each cell owns a mid-seam face (x = lx/2, source of the mid AMI) and a wrap-seam face (x = lx, target of the wrap AMI).

There are no internal faces: every coupling is through one of the two AMI seams. Each cell has equal in-/out-seam face area, so a uniform field advects around the loop conservatively (A·1 = 0), and the diffusion stencil is the periodic circulant one. Cell-to-cell distance across either seam is lx/2 (a quarter-width from each owner to the seam plane on both sides), matching an interior face of that spacing.

When n_a == n_b and the two halves align (equal transverse tiling), every AMI weight is 1 and the couplings reduce to the plain CyclicCoupling one-to-one seam — the mesh then decomposes into n_a independent 2-cell periodic loops, each identical to periodic_1d(2, lx, (ly/n_a)·depth) (the matching-mesh limit used in this crate’s AMI V&V).

§Parameters
  • n_a — transverse cell count of the A (mid-target / wrap-source) column (≥ 1);
  • n_b — transverse cell count of the B (mid-source / wrap-target) column (≥ 1);
  • lx — periodic (x) domain length [m] (> 0);
  • ly — transverse (y) domain extent [m] (> 0);
  • depth — out-of-plane (z) face depth [m] (> 0).

Cells are ordered A_0 … A_{n_a-1}, B_0 … B_{n_b-1}. Patches are, in order: "A_right" (mid target), "B_left" (mid source), "B_right" (wrap target), "A_left" (wrap source), all PatchKind::CyclicAmi.

§Panics

Panics if any of n_a, n_b is 0 or any of lx, ly, depth is not positive.

OpenFOAM analogue: a blockMesh with a cyclicAMI patch pair on two non-conformal column interfaces.

Source§

impl FvMesh

Source

pub fn n_boundary_faces(&self) -> usize

Total number of boundary faces.

Source

pub fn n_patches(&self) -> usize

Number of patches.

Source

pub fn is_internal_face(&self, f: usize) -> bool

True if face f is an internal face (has a neighbour cell).

Source

pub fn patch_for_face(&self, f: usize) -> Option<(usize, usize)>

Given a global face index f that is a boundary face, return (patch_index, local_face_index_within_patch). Returns None if f is an internal face.

Source

pub fn n_cyclic_couplings(&self) -> usize

Number of across-seam cyclic couplings (length of cyclic_couplings).

Source

pub fn cyclic_coupling_face(&self, i: usize) -> usize

LDU face index of cyclic coupling i.

Cyclic couplings live after the internal faces in the LDU addressing, so coupling i occupies face n_internal_faces + i. The FV operators use this to write the off-diagonal coefficient of a periodic seam into the matrix.

Source

pub fn cyclic_partner_face(&self, global_face: usize) -> Option<usize>

Given a global boundary face index on a resolved PatchKind::Cyclic patch, return the global face index of its matching partner face across the periodic seam.

Returns None for internal faces, for non-cyclic boundary faces, and for cyclic faces whose partner patch is unresolved. Local face i of a cyclic patch maps to local face i of its partner (OpenFOAM half0/half1 ordering).

Source

pub fn periodic_1d(n: usize, length: f64, area: f64) -> FvMesh

Build a uniform 1-D periodic (cyclic) mesh: n equal cells along the x-axis over [0, length], with the two ends joined by a cyclic patch pair so the domain wraps around.

This is the programmatic constructor for a periodic seam (the first-pass path — the polyMesh parser does not yet read cyclic neighbourPatch ordering). The resulting mesh has:

  • n cells of width h = length / n, centres at (i + 0.5)·h, volume h·area [m³];
  • n − 1 internal faces (area vector +x·area [m²]);
  • two 1-face cyclic patches — "left" at x = 0 (patch 0, outward normal −x) and "right" at x = length (patch 1, outward normal +x) — that are each other’s partners.

The derived CyclicCoupling joins cell 0 (left owner) to cell n − 1 (right owner) with the same cell-to-cell distance h as an interior face, so a periodic problem discretised on this mesh reproduces the equivalent all-internal ring mesh (see the crate’s cyclic V&V tests).

§Parameters
  • n — number of cells (must be ≥ 2 for a meaningful periodic loop);
  • length — domain length [m];
  • area — uniform cross-sectional face area [m²].
§Panics

Panics if n < 2 (a periodic loop needs at least two cells) or if length/area are not positive.

OpenFOAM analogue: a blockMesh block with a cyclic patch pair on its two x-normal faces.

Source

pub fn validate(&self) -> Result<(), MeshError>

Validate basic mesh consistency. Returns Err on the first problem found.

Trait Implementations§

Source§

impl Clone for FvMesh

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FvMesh

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.