chore: remove deprecated flow_boundary and update docs to match new architecture
This commit is contained in:
208
crates/solver/tests/real_cycle_inverse_integration.rs
Normal file
208
crates/solver/tests/real_cycle_inverse_integration.rs
Normal file
@@ -0,0 +1,208 @@
|
||||
use entropyk_components::port::{Connected, FluidId, Port};
|
||||
use entropyk_components::state_machine::CircuitId;
|
||||
use entropyk_components::{
|
||||
Component, ComponentError, ConnectedPort, JacobianBuilder, MchxCondenserCoil, Polynomial2D,
|
||||
ResidualVector, ScrewEconomizerCompressor, ScrewPerformanceCurves, StateSlice,
|
||||
};
|
||||
use entropyk_core::{Enthalpy, MassFlow, Power, Pressure};
|
||||
use entropyk_solver::inverse::{BoundedVariable, BoundedVariableId, ComponentOutput, Constraint, ConstraintId};
|
||||
use entropyk_solver::system::System;
|
||||
|
||||
type CP = Port<Connected>;
|
||||
|
||||
fn make_port(fluid: &str, p_bar: f64, h_kj_kg: f64) -> ConnectedPort {
|
||||
let a = Port::new(
|
||||
FluidId::new(fluid),
|
||||
Pressure::from_bar(p_bar),
|
||||
Enthalpy::from_joules_per_kg(h_kj_kg * 1000.0),
|
||||
);
|
||||
let b = Port::new(
|
||||
FluidId::new(fluid),
|
||||
Pressure::from_bar(p_bar),
|
||||
Enthalpy::from_joules_per_kg(h_kj_kg * 1000.0),
|
||||
);
|
||||
a.connect(b).expect("port connection ok").0
|
||||
}
|
||||
|
||||
fn make_screw_curves() -> ScrewPerformanceCurves {
|
||||
ScrewPerformanceCurves::with_fixed_eco_fraction(
|
||||
Polynomial2D::bilinear(1.20, 0.003, -0.002, 0.000_01),
|
||||
Polynomial2D::bilinear(55_000.0, 200.0, -300.0, 0.5),
|
||||
0.12,
|
||||
)
|
||||
}
|
||||
|
||||
struct Mock {
|
||||
n: usize,
|
||||
circuit_id: CircuitId,
|
||||
}
|
||||
|
||||
impl Mock {
|
||||
fn new(n: usize, circuit: u16) -> Self {
|
||||
Self {
|
||||
n,
|
||||
circuit_id: CircuitId(circuit),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Mock {
|
||||
fn compute_residuals(
|
||||
&self,
|
||||
_state: &StateSlice,
|
||||
residuals: &mut ResidualVector,
|
||||
) -> Result<(), ComponentError> {
|
||||
for r in residuals.iter_mut().take(self.n) {
|
||||
*r = 0.0;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn jacobian_entries(
|
||||
&self,
|
||||
_state: &StateSlice,
|
||||
_jacobian: &mut JacobianBuilder,
|
||||
) -> Result<(), ComponentError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn n_equations(&self) -> usize {
|
||||
self.n
|
||||
}
|
||||
|
||||
fn get_ports(&self) -> &[ConnectedPort] {
|
||||
&[]
|
||||
}
|
||||
|
||||
fn port_mass_flows(&self, _state: &StateSlice) -> Result<Vec<MassFlow>, ComponentError> {
|
||||
Ok(vec![MassFlow::from_kg_per_s(1.0)])
|
||||
}
|
||||
|
||||
fn energy_transfers(&self, _state: &StateSlice) -> Option<(Power, Power)> {
|
||||
Some((Power::from_watts(0.0), Power::from_watts(0.0)))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_cycle_inverse_control_integration() {
|
||||
let mut sys = System::new();
|
||||
|
||||
// 1. Create components
|
||||
let comp_suc = make_port("R134a", 3.2, 400.0);
|
||||
let comp_dis = make_port("R134a", 12.8, 440.0);
|
||||
let comp_eco = make_port("R134a", 6.4, 260.0);
|
||||
|
||||
let comp = ScrewEconomizerCompressor::new(
|
||||
make_screw_curves(),
|
||||
"R134a",
|
||||
50.0,
|
||||
0.92,
|
||||
comp_suc,
|
||||
comp_dis,
|
||||
comp_eco,
|
||||
).unwrap();
|
||||
|
||||
let coil = MchxCondenserCoil::for_35c_ambient(15_000.0, 0);
|
||||
let exv = Mock::new(2, 0); // Expansion Valve
|
||||
let evap = Mock::new(2, 0); // Evaporator
|
||||
|
||||
// 2. Add components to system
|
||||
let comp_node = sys.add_component_to_circuit(Box::new(comp), CircuitId::ZERO).unwrap();
|
||||
let coil_node = sys.add_component_to_circuit(Box::new(coil), CircuitId::ZERO).unwrap();
|
||||
let exv_node = sys.add_component_to_circuit(Box::new(exv), CircuitId::ZERO).unwrap();
|
||||
let evap_node = sys.add_component_to_circuit(Box::new(evap), CircuitId::ZERO).unwrap();
|
||||
|
||||
sys.register_component_name("compressor", comp_node);
|
||||
sys.register_component_name("condenser", coil_node);
|
||||
sys.register_component_name("expansion_valve", exv_node);
|
||||
sys.register_component_name("evaporator", evap_node);
|
||||
|
||||
// 3. Connect components
|
||||
sys.add_edge(comp_node, coil_node).unwrap();
|
||||
sys.add_edge(coil_node, exv_node).unwrap();
|
||||
sys.add_edge(exv_node, evap_node).unwrap();
|
||||
sys.add_edge(evap_node, comp_node).unwrap();
|
||||
|
||||
// 4. Add Inverse Control Elements (Constraints and BoundedVariables)
|
||||
// Constraint 1: Superheat at evaporator = 5K
|
||||
sys.add_constraint(Constraint::new(
|
||||
ConstraintId::new("superheat_control"),
|
||||
ComponentOutput::Superheat {
|
||||
component_id: "evaporator".to_string(),
|
||||
},
|
||||
5.0,
|
||||
)).unwrap();
|
||||
|
||||
// Constraint 2: Capacity at compressor = 50000 W
|
||||
sys.add_constraint(Constraint::new(
|
||||
ConstraintId::new("capacity_control"),
|
||||
ComponentOutput::Capacity {
|
||||
component_id: "compressor".to_string(),
|
||||
},
|
||||
50000.0,
|
||||
)).unwrap();
|
||||
|
||||
// Control 1: Valve Opening
|
||||
let bv_valve = BoundedVariable::with_component(
|
||||
BoundedVariableId::new("valve_opening"),
|
||||
"expansion_valve",
|
||||
0.5,
|
||||
0.0,
|
||||
1.0,
|
||||
).unwrap();
|
||||
sys.add_bounded_variable(bv_valve).unwrap();
|
||||
|
||||
// Control 2: Compressor Speed
|
||||
let bv_comp = BoundedVariable::with_component(
|
||||
BoundedVariableId::new("compressor_speed"),
|
||||
"compressor",
|
||||
0.7,
|
||||
0.3,
|
||||
1.0,
|
||||
).unwrap();
|
||||
sys.add_bounded_variable(bv_comp).unwrap();
|
||||
|
||||
// Link constraints to controls
|
||||
sys.link_constraint_to_control(
|
||||
&ConstraintId::new("superheat_control"),
|
||||
&BoundedVariableId::new("valve_opening"),
|
||||
).unwrap();
|
||||
|
||||
sys.link_constraint_to_control(
|
||||
&ConstraintId::new("capacity_control"),
|
||||
&BoundedVariableId::new("compressor_speed"),
|
||||
).unwrap();
|
||||
|
||||
// 5. Finalize the system
|
||||
sys.finalize().unwrap();
|
||||
|
||||
// Verify system state size and degrees of freedom
|
||||
assert_eq!(sys.constraint_count(), 2);
|
||||
assert_eq!(sys.bounded_variable_count(), 2);
|
||||
|
||||
// Validate DoF
|
||||
sys.validate_inverse_control_dof().expect("System should be balanced for inverse control");
|
||||
|
||||
// Evaluate the total system residual and jacobian capability
|
||||
let state_len = sys.state_vector_len();
|
||||
assert!(state_len > 0, "System should have state variables");
|
||||
|
||||
// Create mock state and control values
|
||||
let state = vec![400_000.0; state_len];
|
||||
let control_values = vec![0.5, 0.7]; // Valve, Compressor speeds
|
||||
|
||||
let mut residuals = vec![0.0; state_len + 2];
|
||||
|
||||
// Evaluate constraints
|
||||
let measured = sys.extract_constraint_values_with_controls(&state, &control_values);
|
||||
let count = sys.compute_constraint_residuals(&state, &mut residuals[state_len..], &measured);
|
||||
|
||||
assert_eq!(count, 2, "Should have computed 2 constraint residuals");
|
||||
|
||||
// Evaluate jacobian
|
||||
let jacobian_entries = sys.compute_inverse_control_jacobian(&state, state_len, &control_values);
|
||||
|
||||
assert!(!jacobian_entries.is_empty(), "Jacobian should have entries for inverse control");
|
||||
|
||||
println!("System integration with inverse control successful!");
|
||||
}
|
||||
Reference in New Issue
Block a user