///|
/// Total scalar quantity in the domain.
pub fn ScalarSolver::mass(self : ScalarSolver) -> Double {
sum_values(self.values)
}
///|
/// Scalar variance over all cells.
pub fn ScalarSolver::variance(self : ScalarSolver) -> Double {
variance_value(self.values)
}
///|
/// True when every stored scalar is finite.
pub fn ScalarSolver::is_finite(self : ScalarSolver) -> Bool {
let mut finite = true
for value in self.values {
finite = finite && !value.is_nan() && !value.is_inf()
}
finite
}
///|
/// Absolute error between the current mean and a target state.
pub fn ScalarSolver::steady_state_error(
self : ScalarSolver,
target~ : Double,
) -> Double {
abs_double(self.mean() - target)
}
///|
/// Return the position of the first maximum scalar cell.
pub fn ScalarSolver::maximum_location(self : ScalarSolver) -> Point {
let location = self.field().maximum_location()
Point::new(x=location.x.to_double(), y=location.y.to_double())
}
///|
/// Return the position of the first minimum scalar cell.
pub fn ScalarSolver::minimum_location(self : ScalarSolver) -> Point {
let location = self.field().minimum_location()
Point::new(x=location.x.to_double(), y=location.y.to_double())
}
///|
/// Return the current scalar gradient field magnitude.
pub fn ScalarSolver::gradient_magnitude(self : ScalarSolver) -> Field2D {
let field = self.field()
let result = Field2D::new(size=self.size)
for y in 0.. Field2D {
self.field().laplacian()
}
///|
/// Count cells above a scalar threshold.
pub fn ScalarSolver::count_above(self : ScalarSolver, level~ : Double) -> Int {
self.field().count_above(level~)
}
///|
/// True when no scalar is below a supplied lower bound.
pub fn ScalarSolver::is_above(self : ScalarSolver, lower~ : Double) -> Bool {
let mut result = true
for value in self.values {
result = result && value >= lower
}
result
}
///|
/// Total absolute source strength currently configured.
pub fn ScalarSolver::source_mass(self : ScalarSolver) -> Double {
let mut total = 0.0
for value in self.source {
total += abs_double(value)
}
total
}
///|
/// Difference between two scalar solver states.
pub fn scalar_state_error(left : ScalarSolver, right : ScalarSolver) -> Double {
l2_error(left.values, right.values)
}
///|
/// Compute the scalar Péclet number for a characteristic length.
pub fn scalar_peclet_number(
velocity~ : Double,
length~ : Double,
diffusivity~ : Double,
) -> Double {
safe_divide(velocity * length, diffusivity, fallback=0.0)
}
///|
/// Compute the scalar diffusion time for a characteristic length.
pub fn scalar_diffusion_time(length~ : Double, diffusivity~ : Double) -> Double {
safe_divide(length * length, diffusivity, fallback=0.0)
}
///|
/// Return a bounded scalar field with a new lower and upper range.
pub fn ScalarSolver::clamped_field(
self : ScalarSolver,
low~ : Double,
high~ : Double,
) -> Field2D {
self.field().clamp(low~, high~)
}
///|
/// Return the sum of scalar changes between two solver states.
pub fn scalar_mass_change(
before : ScalarSolver,
after : ScalarSolver,
) -> Double {
after.mass() - before.mass()
}
///|
/// Return a finite scalar value or a fallback for diagnostics.
pub fn scalar_finite_or(value : Double, fallback~ : Double) -> Double {
finite_or(value, fallback~)
}