///|
fn fixture_species(
name : String,
charge : Int32,
stoich : Array[Double],
terms : Array[ComponentTerm],
base : Int32?,
alkalinity : Double,
source : String,
) -> SpeciesDef {
let log_k = match thermo_record(builtin_thermodynamics(), source) {
Some(record) => record.log_k
None => 0.0 // All builtin identifiers are checked by validation and tests.
}
{
name,
charge,
element_stoich: stoich,
component_terms: terms,
base_component: base,
log_k,
alkalinity,
source,
}
}
///|
fn term(component : Int32, coefficient : Double) -> ComponentTerm {
{ component, coefficient, }
}
///|
fn fixture_mineral(
name : String,
terms : Array[ComponentTerm],
source : String,
) -> MineralDef {
let log_ksp = match thermo_record(builtin_thermodynamics(), source) {
Some(record) => record.log_k
None => 0.0
}
{ name, component_terms: terms, log_ksp, source, }
}
///|
fn fixture_problem(
elements : Array[ElementDef],
species : Array[SpeciesDef],
minerals : Array[MineralDef],
alkalinity : Double?,
) -> Problem {
let thermodynamics = builtin_thermodynamics()
{
temperature_k: 298.15,
volume_l: 1.0,
elements,
species,
minerals,
hydrogen_component: 0,
fixed_p_h: None,
alkalinity_mol_l: alkalinity,
activity_model: "Davies",
database_version: thermodynamics.version,
thermodynamics,
}
}
///|
/// Calcium-carbonate water, 2 mM Ca, 3 mM dissolved inorganic carbon,
/// 3 meq/L alkalinity and 1 mM chloride. The counterion closes charge.
pub fn demo_problem() -> Problem {
fixture_problem(
[
{ name: "Ca", total_mol_l: 0.002, },
{ name: "C", total_mol_l: 0.003, },
{ name: "Cl", total_mol_l: 0.001, },
],
[
fixture_species("H+", 1, [0, 0, 0], [], Some(0), -1, "identity"),
fixture_species("Ca2+", 2, [1, 0, 0], [], Some(1), 0, "identity"),
fixture_species("CO3--", -2, [0, 1, 0], [], Some(2), 2, "identity"),
fixture_species("Cl-", -1, [0, 0, 1], [], Some(3), 0, "identity"),
fixture_species(
"HCO3-",
-1,
[0, 1, 0],
[term(0, 1), term(2, 1)],
None,
1,
"bicarbonate",
),
fixture_species(
"CO2(aq)",
0,
[0, 1, 0],
[term(0, 2), term(2, 1)],
None,
0,
"carbon-dioxide",
),
fixture_species("OH-", -1, [0, 0, 0], [term(0, -1)], None, 1, "water"),
fixture_species(
"CaHCO3+",
1,
[1, 1, 0],
[term(0, 1), term(1, 1), term(2, 1)],
None,
1,
"calcium-bicarbonate",
),
fixture_species(
"CaCO3(aq)",
0,
[1, 1, 0],
[term(1, 1), term(2, 1)],
None,
2,
"calcium-carbonate",
),
fixture_species(
"CaOH+",
1,
[1, 0, 0],
[term(1, 1), term(0, -1)],
None,
1,
"calcium-hydrolysis",
),
],
[fixture_mineral("Calcite", [term(1, 1), term(2, 1)], "calcite")],
Some(0.003),
)
}
///|
/// A closed, electroneutral 10 mM CaSO4 solution; includes bisulfate,
/// CaSO4(aq), CaHSO4+ and CaOH+, with gypsum saturation diagnostics.
pub fn sulfate_problem() -> Problem {
fixture_problem(
[{ name: "Ca", total_mol_l: 0.010, }, { name: "S", total_mol_l: 0.010, }],
[
fixture_species("H+", 1, [0, 0], [], Some(0), -1, "identity"),
fixture_species("Ca2+", 2, [1, 0], [], Some(1), 0, "identity"),
fixture_species("SO4--", -2, [0, 1], [], Some(2), 0, "identity"),
fixture_species(
"HSO4-",
-1,
[0, 1],
[term(0, 1), term(2, 1)],
None,
-1,
"bisulfate",
),
fixture_species("OH-", -1, [0, 0], [term(0, -1)], None, 1, "water"),
fixture_species(
"CaSO4(aq)",
0,
[1, 1],
[term(1, 1), term(2, 1)],
None,
0,
"calcium-sulfate",
),
fixture_species(
"CaHSO4+",
1,
[1, 1],
[term(0, 1), term(1, 1), term(2, 1)],
None,
-1,
"calcium-bisulfate",
),
fixture_species(
"CaOH+",
1,
[1, 0],
[term(1, 1), term(0, -1)],
None,
1,
"calcium-hydrolysis",
),
],
[fixture_mineral("Gypsum", [term(1, 1), term(2, 1)], "gypsum")],
None,
)
}
///|
/// Dilute zinc nitrate titrated with 19 micromol/L NaOH. All counterions
/// are explicit; pH follows charge balance. No carbonate or other ligands.
pub fn hydrolysis_problem() -> Problem {
fixture_problem(
[
{ name: "Zn", total_mol_l: 1.0e-5, },
{ name: "N", total_mol_l: 2.0e-5, },
{ name: "Na", total_mol_l: 1.9e-5, },
],
[
fixture_species("H+", 1, [0, 0, 0], [], Some(0), -1, "identity"),
fixture_species("Zn2+", 2, [1, 0, 0], [], Some(1), 0, "identity"),
fixture_species("NO3-", -1, [0, 1, 0], [], Some(2), 0, "identity"),
fixture_species("Na+", 1, [0, 0, 1], [], Some(3), 0, "identity"),
fixture_species("OH-", -1, [0, 0, 0], [term(0, -1)], None, 1, "water"),
fixture_species(
"ZnOH+",
1,
[1, 0, 0],
[term(1, 1), term(0, -1)],
None,
1,
"zinc-oh-1",
),
fixture_species(
"Zn(OH)2(aq)",
0,
[1, 0, 0],
[term(1, 1), term(0, -2)],
None,
2,
"zinc-oh-2",
),
fixture_species(
"Zn(OH)3-",
-1,
[1, 0, 0],
[term(1, 1), term(0, -3)],
None,
3,
"zinc-oh-3",
),
fixture_species(
"Zn(OH)4--",
-2,
[1, 0, 0],
[term(1, 1), term(0, -4)],
None,
4,
"zinc-oh-4",
),
],
[
fixture_mineral(
"Zn(OH)2(e)",
[term(1, 1), term(0, -2)],
"zinc-hydroxide-solid",
),
],
None,
)
}
///|
pub fn pure_water_problem() -> Problem {
fixture_problem(
[],
[
fixture_species("H+", 1, [], [], Some(0), -1, "identity"),
fixture_species("OH-", -1, [], [term(0, -1)], None, 1, "water"),
],
[],
None,
)
}
///|
pub fn named_problem(name : String) -> Result[Problem, SolveError] {
match name {
"carbonate" => Ok(demo_problem())
"sulfate" => Ok(sulfate_problem())
"hydrolysis" => Ok(hydrolysis_problem())
"water" => Ok(pure_water_problem())
_ =>
Err(
InvalidInput("fixture must be carbonate, sulfate, hydrolysis or water"),
)
}
}