Skip to main content

Channel

Struct Channel 

Source
pub struct Channel { /* private fields */ }
Expand description

A rectangular box of incompressible fluid.

§The grid

Velocities on cell faces and pressure at cell centres. u sits on the x faces, v on the y faces and w on the z faces, so a divergence lands at a cell centre and a pressure gradient lands on a face, with no interpolation in either.

x and z are always periodic. y is periodic or walled, by Walls.

Implementations§

Source§

impl Channel

Source

pub fn new( name: impl Into<String>, counts: (usize, usize, usize), cell: Length, fluid: Fluid, walls: Walls, ) -> Channel

A box of counts cubic cells of side cell, at rest.

Source

pub fn counts(&self) -> (usize, usize, usize)

Cells along each axis.

Source

pub fn cell(&self) -> Length

The cell side.

Source

pub fn size(&self) -> LengthVec

The box’s dimensions.

Source

pub fn fluid(&self) -> Fluid

What it is full of.

Source

pub fn gap(&self) -> Length

The gap between the walls, for a walled box.

Source

pub fn drive(&mut self, force: DVec3) -> &mut Channel

Drive the flow with a uniform body force per unit mass, in m/s².

A pressure gradient in disguise, and the form every closed form for channel flow is written in: a periodic box cannot carry a mean pressure gradient, so the drive has to be a force.

Source

pub fn set_velocity(&mut self, field: impl Fn(DVec3) -> DVec3) -> &mut Channel

Set every u face from a function of position, for releasing an exact solution.

The callback is handed the face’s own centre. v and w are set the same way by Channel::set_velocity, which takes all three at once and samples each component where that component lives — the staggering is the whole point and a function evaluated at one place for all three would be a different field.

Source

pub fn velocity_at(&self, i: usize, j: usize, k: usize) -> DVec3

The velocity at a cell centre, by averaging the faces around it.

Source

pub fn mean_speed(&self) -> Velocity

The mean x velocity of the whole box.

Source

pub fn layer_speed(&self, j: usize) -> Velocity

The mean x velocity of one layer of cells, which is what a profile is made of.

Source

pub fn kinetic_energy(&self) -> Energy

Kinetic energy, ½∫ρ|u|²dV, from the face values.

Source

pub fn momentum_x(&self) -> f64

Total x momentum, ρ∫u dV.

Conserved exactly in a periodic box with no force and no walls: the advection is in flux form, so every face’s contribution appears twice with opposite signs, and the pressure gradient of a periodic field sums to zero. That is a machine-precision statement and it is what a decay rate is too coarse to check.

Source

pub fn divergence(&self) -> f64

The largest |∇·u| anywhere, times the cell — a velocity, so it compares to the flow.

After the projection this is the pressure solve’s residual and nothing else. Weaker than electromagnetism’s divergence identity, which holds exactly; here it holds to whatever the solve was asked for, and reporting it is the difference between knowing that and assuming it.

Source

pub fn cell_reynolds(&self) -> f64

The cell Reynolds number, |u|dx/ν.

A property of the mesh and the flow in it, not of the step. See CELL_REYNOLDS_LIMIT.

Source

pub fn peak_speed(&self) -> f64

The fastest face velocity anywhere.

Source

pub fn viscous_limit(&self) -> Time

The viscous limit, dx²/(6ν) — the same Fourier number conduction has.

Source

pub fn courant_limit(&self) -> Time

The advective limit, dx/|u|max. Infinite for a fluid at rest.

Source

pub fn converged(&self) -> bool

Whether the last pressure solve met its tolerance.

Source

pub fn residual(&self) -> f64

The relative residual the last pressure solve reached.

Trait Implementations§

Source§

impl Clone for Channel

Source§

fn clone(&self) -> Channel

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 Channel

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Domain for Channel

Source§

fn ledger(&self) -> Ledger

The kinetic energy the box is holding. The kinetic energy it holds, less the work the drive has put in.

Two contributions rather than their difference: Ledger::add raises an entry’s scale to the largest thing added to it and the audit judges a change against that, so pre-summing a near-zero net would leave no scale at all. A channel starting from rest holds exactly zero, and the first 2.9e-12 J the drive did was judged a hundred-percent change and stopped a correct run on its first step.

Source§

fn as_field(&self) -> Option<&dyn ScalarField>

Speed, so a flow can be looked at.

The honest caveat is in the unit and in this sentence rather than in a refusal to draw one: velocity is a vector and this is its magnitude, so a picture of it shows where the fluid is moving fast and not which way it is going. The components are in the JSON, and layer_speed is what a profile should be read from.

Drawn at all because a domain nobody can see is a domain nobody trusts, and this crate’s own documentation says why that matters here more than anywhere: “it looks like a fluid” is the easiest wrong answer in computational physics to accept, and the answer to that is closed forms and a picture, not one instead of the other.

Source§

fn as_any_mut(&mut self) -> Option<&mut dyn Any>

And mutably, because a domain that can be read and not written is one a coupling can only fail at silently. Simulation::domain_as_mut returns None when this is not implemented, and a caller that wrote through it would do nothing and report nothing — which is how a whole coupled body came back reporting zero strain that read as no stress rather than as not connected.

Source§

fn name(&self) -> &str

What this domain is called. Used to look it up and to name it in a violation. Read more
Source§

fn kind(&self) -> Kind

Whether it has state to roll forward. Defaults to Kind::Evolving.
Source§

fn max_stable_dt(&self, _now: Time) -> Time

The largest step this domain can take from now and stay stable — a CFL condition, a diffusion limit, a contact penetration budget. Read more
Source§

fn step( &mut self, _t: Time, dt: Time, _bus: &mut Exchange, ) -> Result<(), Violation>

Advance by dt from t, reading inputs from bus and publishing outputs to it. A quasi-static domain ignores dt. Read more
Source§

fn readings(&self) -> Vec<Reading>

The named scalars this domain reports, for a table, a chart or a caption. Read more
Source§

fn as_any(&self) -> Option<&dyn Any>

This domain as Any, so a caller can get the concrete type back out of a Simulation — see Simulation::domain_as. Read more
Source§

fn checkpoint(&mut self)

Save state so an iterative sweep can be re-run from the same starting point. A domain that does not implement this cannot take part in Schedule::Iterative, and Simulation::advance says so rather than silently iterating from the wrong state.
Source§

fn restore(&mut self)

Restore the last Domain::checkpoint.
Source§

fn residual(&self) -> f64

How far this domain still is from agreeing with its neighbours, for Schedule::Iterative. Zero means converged.
Source§

fn books_balance(&self) -> bool

Whether this domain’s books are exact: its ledger changes by precisely what it takes from the bus minus what it publishes, every step. Read more
Source§

fn supports_restore(&self) -> bool

Whether Domain::checkpoint and Domain::restore actually do something. Read more
Source§

fn as_bodies(&self) -> Option<&dyn Bodies>

This domain as a countable set of bodies, if that is what it is. Read more
Source§

impl ScalarField for Channel

Source§

fn unit(&self) -> &'static str

Metres per second — a speed, not a velocity. See Channel::as_field.

Source§

fn at(&self, p: LengthVec, _t: Time) -> f64

The speed at p, from the cell it falls in.

Nearest cell rather than trilinear, and the reason is the grid: velocity lives on the faces and velocity_at already averages the pair across each cell to get a centred vector. Interpolating that average again would smooth a field that has already been smoothed once, and a viewer would be looking at a blur of a blur.

Source§

fn gradient( &self, p: QVec3<1, 0, 0, 0, 0, 0, 0>, t: Qty<0, 0, 1, 0, 0, 0, 0>, h: Qty<1, 0, 0, 0, 0, 0, 0>, ) -> DVec3

∇f, by central differences over h. Units are the field’s per metre.
Source§

fn laplacian( &self, p: QVec3<1, 0, 0, 0, 0, 0, 0>, t: Qty<0, 0, 1, 0, 0, 0, 0>, h: Qty<1, 0, 0, 0, 0, 0, 0>, ) -> f64

∇²f — the operator that makes diffusion diffuse. A point hotter than the average of its neighbours has a negative Laplacian and cools; that is the whole content of the heat equation.
Source§

fn rate( &self, p: QVec3<1, 0, 0, 0, 0, 0, 0>, t: Qty<0, 0, 1, 0, 0, 0, 0>, dt: Qty<0, 0, 1, 0, 0, 0, 0>, ) -> f64

∂f/∂t, by a central difference in time.

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> 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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.