Skip to main content
Glama
test_capacity.py9.21 kB
""" Unit tests for capacity analysis functionality. """ import pytest from opendss_mcp.tools.feeder_loader import load_ieee_test_feeder from opendss_mcp.tools.power_flow import run_power_flow from opendss_mcp.tools.capacity import analyze_feeder_capacity def test_basic_capacity_analysis(): """Test basic capacity analysis functionality.""" # Load feeder and run power flow load_result = load_ieee_test_feeder("IEEE13") assert load_result["success"], f"Failed to load feeder: {load_result.get('errors')}" pf_result = run_power_flow("IEEE13") assert pf_result["success"], f"Power flow failed: {pf_result.get('errors')}" # Run capacity analysis on a bus result = analyze_feeder_capacity( bus_id="675", der_type="solar", increment_kw=100, max_capacity_kw=2000 ) # Verify operation succeeded assert result["success"], f"Capacity analysis failed: {result.get('errors')}" # Verify data structure assert "data" in result data = result["data"] assert "bus_id" in data assert "der_type" in data assert "max_capacity_kw" in data assert "limiting_constraint" in data assert "capacity_curve" in data assert "baseline" in data assert "constraints" in data assert "analysis_parameters" in data # Verify max capacity is non-negative assert data["max_capacity_kw"] >= 0 def test_capacity_with_constraints(): """Test capacity analysis with custom constraints.""" # Load and solve load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") # Run with strict voltage constraints constraints = { "min_voltage_pu": 0.98, "max_voltage_pu": 1.02, "max_line_loading_pct": 90.0, } result = analyze_feeder_capacity( bus_id="675", der_type="solar", increment_kw=50, max_capacity_kw=1500, constraints=constraints, ) assert result["success"] # Verify constraints were applied assert result["data"]["constraints"]["min_voltage_pu"] == 0.98 assert result["data"]["constraints"]["max_voltage_pu"] == 1.02 assert result["data"]["constraints"]["max_line_loading_pct"] == 90.0 def test_return_format(): """Test that return format has all required fields.""" # Load and solve load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") # Run capacity analysis result = analyze_feeder_capacity( bus_id="675", der_type="solar", increment_kw=100, max_capacity_kw=1000 ) # Check top-level structure assert "success" in result assert "data" in result assert "metadata" in result assert "errors" in result # Check data structure data = result["data"] required_fields = [ "bus_id", "der_type", "max_capacity_kw", "limiting_constraint", "violation_details", "capacity_curve", "baseline", "constraints", "analysis_parameters", ] for field in required_fields: assert field in data, f"Missing required field: {field}" # Check capacity curve structure assert isinstance(data["capacity_curve"], list) if data["capacity_curve"]: curve_point = data["capacity_curve"][0] assert "capacity_kw" in curve_point assert "converged" in curve_point assert "voltage_violations" in curve_point assert "max_line_loading_pct" in curve_point assert "has_violations" in curve_point # Check baseline structure baseline = data["baseline"] assert "voltage_violations" in baseline assert "max_line_loading_pct" in baseline # Check constraints structure constraints = data["constraints"] assert "min_voltage_pu" in constraints assert "max_voltage_pu" in constraints assert "max_line_loading_pct" in constraints # Check analysis parameters params = data["analysis_parameters"] assert "increment_kw" in params assert "max_capacity_tested_kw" in params assert "iterations_performed" in params # Check metadata metadata = result["metadata"] assert "circuit_name" in metadata assert "analysis_type" in metadata assert metadata["analysis_type"] == "hosting_capacity" def test_capacity_with_invalid_bus(): """Test capacity analysis with non-existent bus.""" load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") result = analyze_feeder_capacity( bus_id="NONEXISTENT_BUS", der_type="solar", increment_kw=100, max_capacity_kw=1000, ) assert result["success"] is False assert len(result["errors"]) > 0 assert "not found" in result["errors"][0].lower() def test_capacity_with_invalid_der_type(): """Test capacity analysis with unsupported DER type.""" load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") result = analyze_feeder_capacity( bus_id="675", der_type="nuclear", # Invalid type increment_kw=100, max_capacity_kw=1000, ) assert result["success"] is False assert "unsupported" in result["errors"][0].lower() def test_capacity_with_battery(): """Test capacity analysis with battery DER.""" load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") result = analyze_feeder_capacity( bus_id="675", der_type="battery", increment_kw=100, max_capacity_kw=500 ) assert result["success"] assert result["data"]["der_type"] == "battery" def test_capacity_with_wind(): """Test capacity analysis with wind DER.""" load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") result = analyze_feeder_capacity( bus_id="675", der_type="wind", increment_kw=100, max_capacity_kw=500 ) assert result["success"] assert result["data"]["der_type"] == "wind" def test_capacity_with_negative_increment(): """Test that negative increment raises error.""" load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") result = analyze_feeder_capacity( bus_id="675", der_type="solar", increment_kw=-100, max_capacity_kw=1000 ) assert result["success"] is False def test_capacity_with_invalid_max_capacity(): """Test that negative max capacity raises error.""" load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") result = analyze_feeder_capacity( bus_id="675", der_type="solar", increment_kw=100, max_capacity_kw=-1000 ) assert result["success"] is False def test_capacity_increment_greater_than_max(): """Test that increment > max_capacity raises error.""" load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") result = analyze_feeder_capacity( bus_id="675", der_type="solar", increment_kw=2000, max_capacity_kw=1000 ) assert result["success"] is False assert "cannot be greater than" in result["errors"][0].lower() def test_capacity_without_loaded_circuit(): """Test capacity analysis without loading a circuit first.""" import opendssdirect as dss # Clear any loaded circuit dss.Text.Command("Clear") result = analyze_feeder_capacity( bus_id="675", der_type="solar", increment_kw=100, max_capacity_kw=1000 ) assert result["success"] is False # Accept either "no circuit loaded" or OpenDSS's "no active circuit" message assert ( "no circuit" in result["errors"][0].lower() or "active circuit" in result["errors"][0].lower() ) def test_capacity_with_small_increment(): """Test capacity analysis with very small increment for detailed curve.""" load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") result = analyze_feeder_capacity( bus_id="675", der_type="solar", increment_kw=25, max_capacity_kw=500 ) assert result["success"] # Should have at least 1 point in capacity curve (baseline or first increment) assert len(result["data"]["capacity_curve"]) >= 1 # Verify increment was recorded correctly assert result["data"]["analysis_parameters"]["increment_kw"] == 25 def test_capacity_limiting_constraint_detected(): """Test that limiting constraint is properly identified.""" load_ieee_test_feeder("IEEE13") run_power_flow("IEEE13") # Use strict constraints to ensure we hit a limit result = analyze_feeder_capacity( bus_id="675", der_type="solar", increment_kw=200, max_capacity_kw=3000, constraints={ "min_voltage_pu": 0.99, "max_voltage_pu": 1.01, "max_line_loading_pct": 80.0, }, ) assert result["success"] # Should have identified a limiting constraint if result["data"]["max_capacity_kw"] < 3000: assert result["data"]["limiting_constraint"] is not None assert result["data"]["violation_details"] is not None if __name__ == "__main__": pytest.main([__file__, "-v"])

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ahmedelshazly27/opendss-mcp-server1'

If you have feedback or need assistance with the MCP directory API, please join our Discord server