///|
/// Advance a scalar solver several times.
pub fn ScalarSolver::step_many(self : ScalarSolver, steps : Int) -> Unit {
for _ in 0.. ScalarReport {
let stats = self.statistics()
{
name,
size: self.size,
steps: self.step_count,
mass: self.mass(),
mean: stats.mean,
minimum: stats.minimum,
maximum: stats.maximum,
variance: stats.variance,
finite: self.is_finite(),
}
}
///|
/// Export a scalar report as CSV.
pub fn ScalarReport::to_csv(self : ScalarReport) -> String {
"\{self.name},\{self.size.width},\{self.size.height},\{self.steps},\{self.mass},\{self.mean},\{self.minimum},\{self.maximum},\{self.variance},\{self.finite}\n"
}
///|
/// Export a scalar report as a Markdown row.
pub fn ScalarReport::to_markdown(self : ScalarReport) -> String {
"| \{self.name} | \{self.size.width}x\{self.size.height} | \{self.steps} | \{self.mass} | \{self.mean} | \{self.minimum} | \{self.maximum} | \{self.variance} | \{self.finite} |"
}
///|
/// Return the fraction of the initial mass remaining.
pub fn ScalarSolver::mass_ratio(
self : ScalarSolver,
initial_mass~ : Double,
) -> Double {
safe_divide(self.mass(), initial_mass, fallback=0.0)
}
///|
/// Return the L2 energy of scalar gradients.
pub fn ScalarSolver::gradient_energy(self : ScalarSolver) -> Double {
let gradient = self.gradient_magnitude()
dot_product(gradient.data, gradient.data)
}
///|
/// Return the sum of absolute scalar values.
pub fn ScalarSolver::absolute_mass(self : ScalarSolver) -> Double {
self.field().absolute_integral()
}
///|
/// Return the mean source contribution.
pub fn ScalarSolver::mean_source(self : ScalarSolver) -> Double {
mean_value(self.source)
}
///|
/// Return the maximum source magnitude.
pub fn ScalarSolver::maximum_source(self : ScalarSolver) -> Double {
min_max(self.source).1
}
///|
/// Return the dimensionless diffusion stability number.
pub fn ScalarSolver::stability_number(self : ScalarSolver) -> Double {
self.diffusion_number() * 4.0
}
///|
/// Return true when an explicit scalar step is within the five-point limit.
pub fn ScalarSolver::explicitly_stable(self : ScalarSolver) -> Bool {
self.stability_number() <= 0.5
}
///|
/// Return the scalar state as normalized output.
pub fn ScalarSolver::normalized_field(self : ScalarSolver) -> Field2D {
self.field().normalize()
}