chore: remove BMAD framework files and IDE configuration artifacts
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>
This commit is contained in:
142
crates/entropyk/tests/constraints_api.rs
Normal file
142
crates/entropyk/tests/constraints_api.rs
Normal file
@@ -0,0 +1,142 @@
|
||||
//! Integration tests for SystemBuilder constraints API (Story 13-3).
|
||||
//!
|
||||
//! Verifies that constraints and bounded variables can be added via the builder,
|
||||
//! linked for inverse control, and that the built system passes DoF validation.
|
||||
|
||||
use entropyk::{
|
||||
BoundedVariable, BoundedVariableId, ComponentOutput, Constraint, ConstraintId, SystemBuilder,
|
||||
};
|
||||
use entropyk_components::{
|
||||
Component, ComponentError, ConnectedPort, JacobianBuilder, ResidualVector,
|
||||
};
|
||||
|
||||
struct MockComponent {
|
||||
n_eqs: usize,
|
||||
}
|
||||
|
||||
impl Component for MockComponent {
|
||||
fn compute_residuals(
|
||||
&self,
|
||||
_state: &[f64],
|
||||
_residuals: &mut ResidualVector,
|
||||
) -> Result<(), ComponentError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn jacobian_entries(
|
||||
&self,
|
||||
_state: &[f64],
|
||||
_jacobian: &mut JacobianBuilder,
|
||||
) -> Result<(), ComponentError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn n_equations(&self) -> usize {
|
||||
self.n_eqs
|
||||
}
|
||||
|
||||
fn get_ports(&self) -> &[ConnectedPort] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_builder_constraints_link_and_validate_dof() {
|
||||
let constraint = Constraint::new(
|
||||
ConstraintId::new("superheat"),
|
||||
ComponentOutput::Superheat {
|
||||
component_id: "evap".to_string(),
|
||||
},
|
||||
5.0,
|
||||
);
|
||||
let valve = BoundedVariable::new(
|
||||
BoundedVariableId::new("valve"),
|
||||
0.5,
|
||||
0.0,
|
||||
1.0,
|
||||
)
|
||||
.expect("valid bounds");
|
||||
|
||||
// Minimal topology: 2 nodes, 1 edge → 2 edge unknowns (P,h). With 1 constraint and 1 control
|
||||
// we need 3 equations total: 2 component eqs + 1 constraint = 3 = 2 + 1 unknowns.
|
||||
let system = SystemBuilder::new()
|
||||
.component("evap", Box::new(MockComponent { n_eqs: 1 }))
|
||||
.unwrap()
|
||||
.component("other", Box::new(MockComponent { n_eqs: 1 }))
|
||||
.unwrap()
|
||||
.edge("evap", "other")
|
||||
.unwrap()
|
||||
.with_constraint(constraint)
|
||||
.unwrap()
|
||||
.with_bounded_variable(valve)
|
||||
.unwrap()
|
||||
.link_constraint_to_control(
|
||||
&ConstraintId::new("superheat"),
|
||||
&BoundedVariableId::new("valve"),
|
||||
)
|
||||
.unwrap()
|
||||
.build()
|
||||
.expect("build should succeed");
|
||||
|
||||
// DoF validation should pass: 1 constraint, 1 control variable (balanced).
|
||||
let dof_result = system.validate_inverse_control_dof();
|
||||
assert!(
|
||||
dof_result.is_ok(),
|
||||
"validate_inverse_control_dof should pass when constraint and control are linked: {:?}",
|
||||
dof_result.err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_builder_dof_imbalance_two_constraints_one_control() {
|
||||
let c1 = Constraint::new(
|
||||
ConstraintId::new("superheat"),
|
||||
ComponentOutput::Superheat {
|
||||
component_id: "evap".to_string(),
|
||||
},
|
||||
5.0,
|
||||
);
|
||||
let c2 = Constraint::new(
|
||||
ConstraintId::new("subcooling"),
|
||||
ComponentOutput::Superheat {
|
||||
component_id: "evap".to_string(),
|
||||
},
|
||||
3.0,
|
||||
);
|
||||
let valve = BoundedVariable::new(
|
||||
BoundedVariableId::new("valve"),
|
||||
0.5,
|
||||
0.0,
|
||||
1.0,
|
||||
)
|
||||
.expect("valid bounds");
|
||||
|
||||
let system = SystemBuilder::new()
|
||||
.component("evap", Box::new(MockComponent { n_eqs: 1 }))
|
||||
.unwrap()
|
||||
.component("other", Box::new(MockComponent { n_eqs: 1 }))
|
||||
.unwrap()
|
||||
.edge("evap", "other")
|
||||
.unwrap()
|
||||
.with_constraint(c1)
|
||||
.unwrap()
|
||||
.with_constraint(c2)
|
||||
.unwrap()
|
||||
.with_bounded_variable(valve)
|
||||
.unwrap()
|
||||
.link_constraint_to_control(
|
||||
&ConstraintId::new("superheat"),
|
||||
&BoundedVariableId::new("valve"),
|
||||
)
|
||||
.unwrap()
|
||||
.build()
|
||||
.expect("build should succeed");
|
||||
|
||||
// DoF validation should fail: 2 constraints but only 1 control (unbalanced).
|
||||
let dof_result = system.validate_inverse_control_dof();
|
||||
assert!(
|
||||
dof_result.is_err(),
|
||||
"validate_inverse_control_dof should fail with 2 constraints and 1 control, got: {:?}",
|
||||
dof_result
|
||||
);
|
||||
}
|
||||
64
crates/entropyk/tests/multi_circuit_builder.rs
Normal file
64
crates/entropyk/tests/multi_circuit_builder.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
//! Integration tests for SystemBuilder multi-circuit API (Story 13-1).
|
||||
//!
|
||||
//! Verifies that a minimal two-circuit system can be built via the builder,
|
||||
//! finalized, and exposes the expected circuit topology.
|
||||
|
||||
use entropyk::{CircuitId, SystemBuilder};
|
||||
use entropyk_components::{
|
||||
Component, ComponentError, JacobianBuilder, ResidualVector,
|
||||
};
|
||||
|
||||
struct MockComponent {
|
||||
n_eqs: usize,
|
||||
}
|
||||
|
||||
impl Component for MockComponent {
|
||||
fn compute_residuals(
|
||||
&self,
|
||||
_state: &[f64],
|
||||
_residuals: &mut ResidualVector,
|
||||
) -> Result<(), ComponentError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn jacobian_entries(
|
||||
&self,
|
||||
_state: &[f64],
|
||||
_jacobian: &mut JacobianBuilder,
|
||||
) -> Result<(), ComponentError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn n_equations(&self) -> usize {
|
||||
self.n_eqs
|
||||
}
|
||||
|
||||
fn get_ports(&self) -> &[entropyk_components::ConnectedPort] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_builder_two_circuits_build_and_finalize() {
|
||||
let system = SystemBuilder::new()
|
||||
.component_in_circuit("a", Box::new(MockComponent { n_eqs: 1 }), CircuitId::ZERO)
|
||||
.unwrap()
|
||||
.component_in_circuit("b", Box::new(MockComponent { n_eqs: 1 }), CircuitId::ZERO)
|
||||
.unwrap()
|
||||
.component_in_circuit("c", Box::new(MockComponent { n_eqs: 1 }), CircuitId(1))
|
||||
.unwrap()
|
||||
.component_in_circuit("d", Box::new(MockComponent { n_eqs: 1 }), CircuitId(1))
|
||||
.unwrap()
|
||||
.edge("a", "b")
|
||||
.unwrap()
|
||||
.edge("c", "d")
|
||||
.unwrap()
|
||||
.build()
|
||||
.expect("build should succeed");
|
||||
|
||||
assert_eq!(system.circuit_count(), 2);
|
||||
assert_eq!(system.circuit_nodes(CircuitId::ZERO).count(), 2);
|
||||
assert_eq!(system.circuit_nodes(CircuitId(1)).count(), 2);
|
||||
assert_eq!(system.node_count(), 4);
|
||||
assert_eq!(system.edge_count(), 2);
|
||||
}
|
||||
202
crates/entropyk/tests/port_validated_edges.rs
Normal file
202
crates/entropyk/tests/port_validated_edges.rs
Normal file
@@ -0,0 +1,202 @@
|
||||
//! Integration tests for SystemBuilder::edge_with_ports()
|
||||
|
||||
use entropyk::SystemBuilder;
|
||||
use entropyk_components::{ComponentError, ConnectedPort, JacobianBuilder, ResidualVector};
|
||||
|
||||
/// A minimal mock component with configurable ports for testing.
|
||||
struct MockComponentWithPorts {
|
||||
n_eqs: usize,
|
||||
ports: Vec<ConnectedPort>,
|
||||
}
|
||||
|
||||
impl MockComponentWithPorts {
|
||||
fn new(n_eqs: usize) -> Self {
|
||||
Self {
|
||||
n_eqs,
|
||||
ports: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn with_ports(n_eqs: usize, ports: Vec<ConnectedPort>) -> Self {
|
||||
Self { n_eqs, ports }
|
||||
}
|
||||
}
|
||||
|
||||
impl entropyk_components::Component for MockComponentWithPorts {
|
||||
fn compute_residuals(
|
||||
&self,
|
||||
_state: &[f64],
|
||||
_residuals: &mut ResidualVector,
|
||||
) -> Result<(), ComponentError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn jacobian_entries(
|
||||
&self,
|
||||
_state: &[f64],
|
||||
_jacobian: &mut JacobianBuilder,
|
||||
) -> Result<(), ComponentError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn n_equations(&self) -> usize {
|
||||
self.n_eqs
|
||||
}
|
||||
|
||||
fn get_ports(&self) -> &[ConnectedPort] {
|
||||
&self.ports
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edge_with_ports_component_not_found() {
|
||||
let result = SystemBuilder::new()
|
||||
.component("a", Box::new(MockComponentWithPorts::new(1)))
|
||||
.unwrap()
|
||||
.edge_with_ports("missing", "outlet", "a", "inlet");
|
||||
|
||||
assert!(result.is_err());
|
||||
if let Err(ref err) = result {
|
||||
assert!(
|
||||
err.to_string().contains("not found"),
|
||||
"Expected ComponentNotFound error, got: {}",
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edge_with_ports_target_not_found() {
|
||||
let result = SystemBuilder::new()
|
||||
.component("a", Box::new(MockComponentWithPorts::new(1)))
|
||||
.unwrap()
|
||||
.edge_with_ports("a", "outlet", "missing", "inlet");
|
||||
|
||||
assert!(result.is_err());
|
||||
if let Err(ref err) = result {
|
||||
assert!(
|
||||
err.to_string().contains("not found"),
|
||||
"Expected ComponentNotFound error, got: {}",
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edge_with_ports_cross_circuit_rejected() {
|
||||
use entropyk_core::CircuitId;
|
||||
|
||||
let result = SystemBuilder::new()
|
||||
.component_in_circuit(
|
||||
"a",
|
||||
Box::new(MockComponentWithPorts::new(1)),
|
||||
CircuitId::ZERO,
|
||||
)
|
||||
.unwrap()
|
||||
.component_in_circuit("b", Box::new(MockComponentWithPorts::new(1)), CircuitId(1))
|
||||
.unwrap()
|
||||
.edge_with_ports("a", "outlet", "b", "inlet");
|
||||
|
||||
assert!(result.is_err());
|
||||
if let Err(ref err) = result {
|
||||
assert!(
|
||||
err.to_string().contains("different circuits"),
|
||||
"Expected CrossCircuitEdge error, got: {}",
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edge_with_ports_convention_based_names() {
|
||||
let builder = SystemBuilder::new()
|
||||
.component("a", Box::new(MockComponentWithPorts::new(2)))
|
||||
.unwrap()
|
||||
.component("b", Box::new(MockComponentWithPorts::new(2)))
|
||||
.unwrap()
|
||||
.edge_with_ports("a", "outlet", "b", "inlet")
|
||||
.expect("edge_with_ports should resolve convention-based port names");
|
||||
|
||||
assert_eq!(builder.edge_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edge_with_ports_suction_discharge_names() {
|
||||
let builder = SystemBuilder::new()
|
||||
.component("comp", Box::new(MockComponentWithPorts::new(2)))
|
||||
.unwrap()
|
||||
.component("pipe", Box::new(MockComponentWithPorts::new(2)))
|
||||
.unwrap()
|
||||
.edge_with_ports("comp", "discharge", "pipe", "inlet")
|
||||
.expect("edge_with_ports should resolve suction/discharge convention names");
|
||||
|
||||
assert_eq!(builder.edge_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edge_with_ports_unknown_port_name_error() {
|
||||
use entropyk::SystemBuilderError;
|
||||
|
||||
let result = SystemBuilder::new()
|
||||
.component("a", Box::new(MockComponentWithPorts::new(2)))
|
||||
.unwrap()
|
||||
.component("b", Box::new(MockComponentWithPorts::new(2)))
|
||||
.unwrap()
|
||||
.edge_with_ports("a", "bogus_port", "b", "inlet");
|
||||
|
||||
assert!(result.is_err());
|
||||
if let Err(SystemBuilderError::PortNotFound {
|
||||
component,
|
||||
port_name,
|
||||
}) = result
|
||||
{
|
||||
assert_eq!(component, "a");
|
||||
assert!(port_name.starts_with("bogus_port"), "port_name should start with the port name, got: {port_name}");
|
||||
} else {
|
||||
panic!("Expected PortNotFound error");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_edge_with_ports_same_circuit_succeeds() {
|
||||
use entropyk_core::CircuitId;
|
||||
|
||||
let builder = SystemBuilder::new()
|
||||
.component_in_circuit(
|
||||
"a",
|
||||
Box::new(MockComponentWithPorts::new(2)),
|
||||
CircuitId::ZERO,
|
||||
)
|
||||
.unwrap()
|
||||
.component_in_circuit(
|
||||
"b",
|
||||
Box::new(MockComponentWithPorts::new(2)),
|
||||
CircuitId::ZERO,
|
||||
)
|
||||
.unwrap()
|
||||
.edge_with_ports("a", "outlet", "b", "inlet")
|
||||
.expect("edge_with_ports should succeed for same-circuit components");
|
||||
|
||||
assert_eq!(builder.edge_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_system_with_port_validated_edges() {
|
||||
let system = SystemBuilder::new()
|
||||
.component("a", Box::new(MockComponentWithPorts::new(2)))
|
||||
.unwrap()
|
||||
.component("b", Box::new(MockComponentWithPorts::new(2)))
|
||||
.unwrap()
|
||||
.component("c", Box::new(MockComponentWithPorts::new(2)))
|
||||
.unwrap()
|
||||
.edge_with_ports("a", "outlet", "b", "inlet")
|
||||
.unwrap()
|
||||
.edge_with_ports("b", "outlet", "c", "inlet")
|
||||
.unwrap()
|
||||
.build()
|
||||
.expect("build should succeed");
|
||||
|
||||
assert_eq!(system.node_count(), 3);
|
||||
assert_eq!(system.edge_count(), 2);
|
||||
}
|
||||
Reference in New Issue
Block a user