mod selection;
mod semi_implicit;
mod solidification_melting;
mod solidification_porosity;
mod temperature_table;
mod vof_solidification_melting;
pub use selection::CellSelection;
pub use semi_implicit::SemiImplicitSource;
pub use solidification_melting::{SolidificationMelting, SolidificationMeltingCoefficients};
pub use solidification_porosity::{MomentumEquationForm, SolidificationPorosity};
pub use temperature_table::TemperatureTable;
pub use vof_solidification_melting::VofSolidificationMelting;
use crate::fields::{VolScalarField, VolVectorField};
use crate::ldu_matrix::{FvMatrix, FvVectorMatrix};
#[derive(Debug, Clone)]
pub enum FvModel {
SemiImplicit(SemiImplicitSource),
SolidificationMelting(SolidificationMelting),
SolidificationPorosity(SolidificationPorosity),
VofSolidificationMelting(VofSolidificationMelting),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EquationField<'n>(pub &'n str);
impl FvModel {
#[must_use]
pub fn name(&self) -> &str {
match self {
Self::SemiImplicit(m) => m.name(),
Self::SolidificationMelting(m) => m.name(),
Self::SolidificationPorosity(m) => m.name(),
Self::VofSolidificationMelting(m) => m.name(),
}
}
#[must_use]
pub fn contributes_to(&self, field: &str) -> bool {
match self {
Self::SemiImplicit(m) => m.field_name() == field,
Self::SolidificationMelting(m) => {
field == m.velocity_name() || field == m.energy_name()
}
Self::SolidificationPorosity(m) => field == m.velocity_name(),
Self::VofSolidificationMelting(m) => {
field == m.velocity_name() || field == m.energy_name()
}
}
}
}
#[derive(Debug, Clone, Default)]
pub struct FvModels {
models: Vec<FvModel>,
}
impl FvModels {
#[must_use]
pub fn new() -> Self {
Self { models: Vec::new() }
}
pub fn push(&mut self, model: FvModel) {
self.models.push(model);
}
#[must_use]
pub fn models(&self) -> &[FvModel] {
&self.models
}
pub fn models_mut(&mut self) -> &mut [FvModel] {
&mut self.models
}
#[must_use]
pub fn contributes_to(&self, field: &str) -> bool {
self.models.iter().any(|m| m.contributes_to(field))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct SourceContribution {
pub explicit: f64,
pub implicit: f64,
}
impl FvModels {
pub fn correct(
&mut self,
temperature: &VolScalarField,
vof_phase_fraction: Option<&VolScalarField>,
) {
for model in &mut self.models {
if let FvModel::VofSolidificationMelting(m) = model {
if let Some(alpha) = vof_phase_fraction {
m.correct(temperature, alpha);
}
}
}
}
pub fn advance_time(&mut self) {
for model in &mut self.models {
match model {
FvModel::SolidificationMelting(m) => m.advance_time(),
FvModel::VofSolidificationMelting(m) => m.advance_time(),
FvModel::SemiImplicit(_) | FvModel::SolidificationPorosity(_) => {
}
}
}
}
pub fn add_source_scalar(
&mut self,
field: &str,
rho: &VolScalarField,
temperature: &VolScalarField,
dt: f64,
eqn: &mut FvMatrix,
) {
let mesh = eqn.mesh.clone();
for model in &mut self.models {
if !model.contributes_to(field) {
continue;
}
match model {
FvModel::SemiImplicit(m) => {
for cell in m.selection().cells(mesh.n_cells) {
let v = mesh.cell_volumes[cell];
let c = m.contribution();
eqn.source[cell] += v * c.explicit;
eqn.ldu.diag[cell] -= v * c.implicit;
}
}
FvModel::SolidificationMelting(m) => {
m.add_energy_source(rho, temperature, dt, eqn);
}
FvModel::VofSolidificationMelting(m) => {
m.add_enthalpy_source(rho, dt, eqn);
}
FvModel::SolidificationPorosity(_) => {
}
}
}
}
pub fn add_source_vector(
&mut self,
field: &str,
rho: &VolScalarField,
temperature: &VolScalarField,
velocity: &VolVectorField,
phase_fraction: Option<&VolScalarField>,
dt: f64,
eqn: &mut FvVectorMatrix,
) {
let _ = (velocity, dt);
for model in &mut self.models {
if !model.contributes_to(field) {
continue;
}
match model {
FvModel::SemiImplicit(_) => {
}
FvModel::SolidificationMelting(m) => {
m.add_momentum_source(temperature, eqn);
}
FvModel::SolidificationPorosity(m) => {
m.add_momentum_source(temperature, rho, phase_fraction, eqn);
}
FvModel::VofSolidificationMelting(m) => {
m.add_momentum_source(rho, eqn);
}
}
}
}
}