Snapshot WIP: Probe calibration path, faer LU backend, and BPHX phase-change duty.
Some checks failed
CI / check (push) Has been cancelled
Some checks failed
CI / check (push) Has been cancelled
Checkpoint incomplete calibration work (cond SDT green, evap SST failing) plus related solver/UI changes so the next pass can fix and extend safely. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
190
crates/cli/tests/calibration_sdt.rs
Normal file
190
crates/cli/tests/calibration_sdt.rs
Normal file
@@ -0,0 +1,190 @@
|
||||
//! Calibration redesign (WS-2/WS-3/WS-4) — AC#1: BPHX condenser SDT
|
||||
//! calibration via plain inverse embedding converges and back-solves z_ua
|
||||
//! (the case that diverged with a singular Jacobian before the redesign).
|
||||
|
||||
use entropyk_cli::run::{run_simulation, SimulationResult, SimulationStatus};
|
||||
use tempfile::tempdir;
|
||||
|
||||
fn run_config(json: &str) -> SimulationResult {
|
||||
let dir = tempdir().unwrap();
|
||||
let path = dir.path().join("bphx_sdt_calib.json");
|
||||
std::fs::write(&path, json).unwrap();
|
||||
run_simulation(&path, None, false).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bphx_condenser_sdt_calibration_converges_and_solves_z_ua() {
|
||||
let json = r#"
|
||||
{
|
||||
"name": "BPHX Water-Cooled Chiller R134a",
|
||||
"description": "Full vapor-compression cycle with brazed-plate evaporator and condenser (4-port). Both Bphx units use emergent_pressure so outlet closures (superheat / subcooling) square the DoF like Condenser/Evaporator.",
|
||||
"fluid": "R134a",
|
||||
"fluid_backend": "CoolProp",
|
||||
"circuits": [
|
||||
{
|
||||
"id": 0,
|
||||
"name": "Refrigerant + water loops",
|
||||
"components": [
|
||||
{
|
||||
"type": "IsentropicCompressor",
|
||||
"name": "comp",
|
||||
"isentropic_efficiency": 0.7,
|
||||
"t_cond_k": 318.15,
|
||||
"t_evap_k": 278.15,
|
||||
"superheat_k": 5.0,
|
||||
"emergent_pressure": true,
|
||||
"displacement_m3": 6.5e-05,
|
||||
"speed_hz": 50.0,
|
||||
"volumetric_efficiency": 0.92
|
||||
},
|
||||
{
|
||||
"type": "BphxCondenser",
|
||||
"name": "cond",
|
||||
"refrigerant": "R134a",
|
||||
"secondary_fluid": "Water",
|
||||
"n_plates": 40,
|
||||
"plate_length_m": 0.4,
|
||||
"plate_width_m": 0.12,
|
||||
"target_subcooling_k": 5.0,
|
||||
"emergent_pressure": true,
|
||||
"correlation": "Longo2004",
|
||||
"dp_correlation": "SimplifiedChannel",
|
||||
"ua": 2500.0
|
||||
},
|
||||
{
|
||||
"type": "IsenthalpicExpansionValve",
|
||||
"name": "exv",
|
||||
"t_evap_k": 278.15,
|
||||
"emergent_pressure": true
|
||||
},
|
||||
{
|
||||
"type": "BphxEvaporator",
|
||||
"name": "evap",
|
||||
"refrigerant": "R134a",
|
||||
"secondary_fluid": "Water",
|
||||
"n_plates": 40,
|
||||
"plate_length_m": 0.4,
|
||||
"plate_width_m": 0.12,
|
||||
"target_superheat_k": 5.0,
|
||||
"emergent_pressure": true,
|
||||
"correlation": "Longo2004",
|
||||
"dp_correlation": "SimplifiedChannel",
|
||||
"ua": 2000.0
|
||||
},
|
||||
{
|
||||
"type": "BrineSource",
|
||||
"name": "cond_water_in",
|
||||
"fluid": "Water",
|
||||
"p_set_bar": 2.0,
|
||||
"t_set_c": 30.0,
|
||||
"m_flow_kg_s": 0.4,
|
||||
"fix_pressure": false,
|
||||
"fix_temperature": true,
|
||||
"fix_mass_flow": true
|
||||
},
|
||||
{
|
||||
"type": "BrineSink",
|
||||
"name": "cond_water_out",
|
||||
"fluid": "Water",
|
||||
"p_back_bar": 2.0,
|
||||
"fix_pressure": true
|
||||
},
|
||||
{
|
||||
"type": "BrineSource",
|
||||
"name": "evap_water_in",
|
||||
"fluid": "Water",
|
||||
"p_set_bar": 3.0,
|
||||
"t_set_c": 12.0,
|
||||
"m_flow_kg_s": 0.5,
|
||||
"fix_pressure": false,
|
||||
"fix_temperature": true,
|
||||
"fix_mass_flow": true
|
||||
},
|
||||
{
|
||||
"type": "BrineSink",
|
||||
"name": "evap_water_out",
|
||||
"fluid": "Water",
|
||||
"p_back_bar": 3.0,
|
||||
"fix_pressure": true
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"from": "comp:outlet",
|
||||
"to": "cond:inlet"
|
||||
},
|
||||
{
|
||||
"from": "cond:outlet",
|
||||
"to": "exv:inlet"
|
||||
},
|
||||
{
|
||||
"from": "exv:outlet",
|
||||
"to": "evap:inlet"
|
||||
},
|
||||
{
|
||||
"from": "evap:outlet",
|
||||
"to": "comp:inlet"
|
||||
},
|
||||
{
|
||||
"from": "cond_water_in:outlet",
|
||||
"to": "cond:secondary_inlet"
|
||||
},
|
||||
{
|
||||
"from": "cond:secondary_outlet",
|
||||
"to": "cond_water_out:inlet"
|
||||
},
|
||||
{
|
||||
"from": "evap_water_in:outlet",
|
||||
"to": "evap:secondary_inlet"
|
||||
},
|
||||
{
|
||||
"from": "evap:secondary_outlet",
|
||||
"to": "evap_water_out:inlet"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"solver": {
|
||||
"strategy": "fallback",
|
||||
"max_iterations": 300,
|
||||
"tolerance": 1e-06,
|
||||
"timeout_ms": 60000
|
||||
},
|
||||
"controls": [
|
||||
{
|
||||
"type": "SaturatedController",
|
||||
"id": "sdt_calib",
|
||||
"measure": {
|
||||
"component": "cond",
|
||||
"output": "saturationTemperature"
|
||||
},
|
||||
"actuator": {
|
||||
"component": "cond",
|
||||
"factor": "z_ua",
|
||||
"initial": 0.3,
|
||||
"min": 0.05,
|
||||
"max": 2.0
|
||||
},
|
||||
"target": 315.0
|
||||
}
|
||||
]
|
||||
}
|
||||
"#;
|
||||
let result = run_config(json);
|
||||
assert!(
|
||||
matches!(result.status, SimulationStatus::Converged),
|
||||
"BPHX SDT calibration must converge (was the singular-Jacobian case): {:?} ({:?})",
|
||||
result.status,
|
||||
result.error
|
||||
);
|
||||
let solved = result
|
||||
.solved_variables
|
||||
.iter()
|
||||
.find(|v| v.variable == "z_ua" && v.component.as_deref() == Some("cond"))
|
||||
.expect("solved_variables must contain cond/z_ua");
|
||||
assert!(
|
||||
solved.value > 0.05 && solved.value < 2.0,
|
||||
"z_ua must solve within bounds, got {}",
|
||||
solved.value
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user