Clean up unused BMAD workflow, agent, and command files across all IDE configurations (.agent, .clinerules, .cursor, .gemini, .github, .kilocode, .opencode) and internal module files (_bmad/bmb, _bmad/bmm). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
130 lines
4.0 KiB
Rust
130 lines
4.0 KiB
Rust
use entropyk_components::port::{FluidId, Port};
|
|
use entropyk_components::{Component, ComponentError, ConnectedPort, JacobianBuilder, StateSlice};
|
|
use entropyk_core::{Enthalpy, Pressure};
|
|
use entropyk_solver::solver::{NewtonConfig, Solver};
|
|
use entropyk_solver::system::System;
|
|
|
|
struct DummyComponent {
|
|
ports: Vec<ConnectedPort>,
|
|
/// Fluid label used in signature() so input_hash reflects fluid configuration.
|
|
fluid_label: String,
|
|
}
|
|
|
|
impl Component for DummyComponent {
|
|
fn compute_residuals(
|
|
&self,
|
|
_state: &StateSlice,
|
|
residuals: &mut entropyk_components::ResidualVector,
|
|
) -> Result<(), ComponentError> {
|
|
residuals[0] = 0.0;
|
|
residuals[1] = 0.0;
|
|
Ok(())
|
|
}
|
|
|
|
fn jacobian_entries(
|
|
&self,
|
|
_state: &StateSlice,
|
|
jacobian: &mut JacobianBuilder,
|
|
) -> Result<(), ComponentError> {
|
|
jacobian.add_entry(0, 0, 1.0);
|
|
jacobian.add_entry(1, 1, 1.0);
|
|
Ok(())
|
|
}
|
|
|
|
fn n_equations(&self) -> usize {
|
|
2
|
|
}
|
|
|
|
fn get_ports(&self) -> &[ConnectedPort] {
|
|
&self.ports
|
|
}
|
|
|
|
fn signature(&self) -> String {
|
|
format!("DummyComponent({})", self.fluid_label)
|
|
}
|
|
}
|
|
|
|
fn make_dummy_component() -> Box<dyn Component> {
|
|
make_dummy_component_with_fluid("R134a")
|
|
}
|
|
|
|
fn make_dummy_component_with_fluid(fluid: &str) -> Box<dyn Component> {
|
|
let inlet = Port::new(
|
|
FluidId::new(fluid),
|
|
Pressure::from_pascals(100_000.0),
|
|
Enthalpy::from_joules_per_kg(400_000.0),
|
|
);
|
|
let outlet = Port::new(
|
|
FluidId::new(fluid),
|
|
Pressure::from_pascals(100_000.0),
|
|
Enthalpy::from_joules_per_kg(400_000.0),
|
|
);
|
|
let (connected_inlet, connected_outlet) = inlet.connect(outlet).unwrap();
|
|
let ports = vec![connected_inlet, connected_outlet];
|
|
Box::new(DummyComponent {
|
|
ports,
|
|
fluid_label: fluid.to_string(),
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn test_simulation_metadata_outputs() {
|
|
let mut sys = System::new();
|
|
let n0 = sys.add_component(make_dummy_component());
|
|
let n1 = sys.add_component(make_dummy_component());
|
|
sys.add_edge_with_ports(n0, 1, n1, 0).unwrap();
|
|
sys.add_edge_with_ports(n1, 1, n0, 0).unwrap();
|
|
|
|
sys.finalize().unwrap();
|
|
|
|
let input_hash = sys.input_hash();
|
|
|
|
let mut solver = NewtonConfig {
|
|
max_iterations: 5,
|
|
..Default::default()
|
|
};
|
|
let result = solver.solve(&mut sys).unwrap();
|
|
|
|
assert!(result.is_converged());
|
|
|
|
let metadata = result.metadata;
|
|
assert_eq!(metadata.input_hash, input_hash);
|
|
assert_eq!(metadata.solver_version, env!("CARGO_PKG_VERSION"));
|
|
assert_eq!(metadata.fluid_backend_version, "0.1.0");
|
|
}
|
|
|
|
/// Same topology (two nodes, two edges) but different fluid → different input_hash.
|
|
#[test]
|
|
fn test_input_hash_different_fluid_same_topology() {
|
|
let mut sys_r134a = System::new();
|
|
let n0 = sys_r134a.add_component(make_dummy_component_with_fluid("R134a"));
|
|
let n1 = sys_r134a.add_component(make_dummy_component_with_fluid("R134a"));
|
|
sys_r134a.add_edge_with_ports(n0, 1, n1, 0).unwrap();
|
|
sys_r134a.add_edge_with_ports(n1, 1, n0, 0).unwrap();
|
|
sys_r134a.finalize().unwrap();
|
|
|
|
let mut sys_r410a = System::new();
|
|
let n0 = sys_r410a.add_component(make_dummy_component_with_fluid("R410A"));
|
|
let n1 = sys_r410a.add_component(make_dummy_component_with_fluid("R410A"));
|
|
sys_r410a.add_edge_with_ports(n0, 1, n1, 0).unwrap();
|
|
sys_r410a.add_edge_with_ports(n1, 1, n0, 0).unwrap();
|
|
sys_r410a.finalize().unwrap();
|
|
|
|
assert_ne!(
|
|
sys_r134a.input_hash(),
|
|
sys_r410a.input_hash(),
|
|
"input_hash must differ when only fluid configuration differs"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_metadata_to_json() {
|
|
use entropyk_solver::SimulationMetadata;
|
|
let meta = SimulationMetadata::new("abc123".to_string());
|
|
let json = meta.to_json().unwrap();
|
|
assert!(json.contains("\"solver_version\""));
|
|
assert!(json.contains("\"fluid_backend_version\""));
|
|
assert!(json.contains("\"input_hash\""));
|
|
assert!(json.contains("abc123"));
|
|
}
|