Skip to main content
Glama

Constrained Optimization MCP Server

chemical_engineering.py9.38 kB
""" Chemical Engineering Pipeline Design Example This module demonstrates solving a chemical engineering optimization problem using Z3. The problem involves designing an optimal pipeline for fluid transport considering: - Flow continuity equations - Pressure drop constraints - Reynolds number requirements - Economic optimization (pipe cost vs pumping cost) This demonstrates engineering optimization using Z3 SMT solving over real numbers. """ from returns.result import Failure, Success from usolver_mcp.models.z3_models import ( Z3Constraint, Z3Problem, Z3Variable, Z3VariableType, ) from usolver_mcp.solvers.z3_solver import solve_problem def create_pipeline_problem(): """ Create a chemical engineering pipeline design optimization problem. Problem parameters: - Volumetric flow rate: 0.05 m³/s - Pipe length: 100 m - Water density: 1000 kg/m³ - Maximum allowable pressure drop: 50 kPa - Friction factor: 0.02 (turbulent flow) Returns: tuple: (variables, constraints) for the Z3 solver """ # Design variables variables = [ {"name": "D", "type": "real"}, # Pipe diameter (m) {"name": "v", "type": "real"}, # Flow velocity (m/s) ] # Problem constants q = 0.05 # Volumetric flow rate (m³/s) length = 100.0 # Pipe length (m) rho = 1000.0 # Water density (kg/m³) f = 0.02 # Friction factor (dimensionless) max_pressure_drop = 50000.0 # Maximum pressure drop (Pa) pi = 3.14159265359 constraints = [] # Practical limits constraints.append("D >= 0.05") # Minimum diameter: 5 cm constraints.append("D <= 0.5") # Maximum diameter: 50 cm constraints.append("v >= 0.5") # Minimum velocity: 0.5 m/s constraints.append("v <= 8.0") # Maximum velocity: 8 m/s # Flow continuity equation: Q = pi(D/2)^2 * v # Rearranged: pi * D² * v / 4 = Q # Simplified: D² * v = 4Q/pi ≈ 0.0637 flow_constant = 4 * q / pi constraints.append(f"D * D * v == {flow_constant:.6f}") # Pressure drop constraint: ΔP = f(L/D)(rho*v²/2) <= max_pressure_drop # Simplified: f * L * rho * v² / (2 * D) <= max_pressure_drop pressure_coeff = f * length * rho / 2.0 constraints.append(f"{pressure_coeff:.2f} * v * v / D <= {max_pressure_drop:.1f}") # Reynolds number constraint for turbulent flow (Re > 4000) # Re = rho*v*D/mu, assuming mu ≈ 0.001 Pa·s for water mu = 0.001 # Dynamic viscosity (Pa·s) reynolds_min = 4000 reynolds_coeff = rho / mu constraints.append(f"{reynolds_coeff:.1f} * v * D >= {reynolds_min}") # Economic constraint: minimize pipe cost (proportional to D²L) + pumping cost (proportional to ΔP*Q) # This is handled as additional constraints rather than objective in Z3 # Assume maximum acceptable pipe cost relative to pumping cost pipe_cost_factor = 1000 # Cost per m³ of pipe material pumping_cost_factor = 0.1 # Cost per Pa·m³/s max_total_cost = 6000 # Maximum acceptable total cost (increased to be feasible) # Pipe cost = pipe_cost_factor * pi * D² * L / 4 # Pumping cost = pumping_cost_factor * pressure_drop * Q pipe_cost_coeff = pipe_cost_factor * pi * length / 4 pumping_cost_expr = ( f"{pumping_cost_factor * q:.6f} * {pressure_coeff:.2f} * v * v / D" ) constraints.append( f"{pipe_cost_coeff:.2f} * D * D + {pumping_cost_expr} <= {max_total_cost}" ) return variables, constraints def solve_pipeline_design(): """ Solve the pipeline design problem and return results. Returns: dict: Solution results including optimal diameter, velocity, and performance metrics """ variables, constraints = create_pipeline_problem() # Convert to Z3Problem model z3_variables = [ Z3Variable(name=var["name"], type=Z3VariableType(var["type"])) for var in variables ] z3_constraints = [Z3Constraint(expression=constraint) for constraint in constraints] problem = Z3Problem( variables=z3_variables, constraints=z3_constraints, description="Chemical engineering pipeline design optimization", ) result = solve_problem(problem) # Parse the result match result: case Success(solution): if solution.is_satisfiable: # Extract solution values diameter = solution.values.get("D") v = solution.values.get("v") if diameter is not None and v is not None: return { "status": "satisfiable", "diameter": float(diameter), "velocity": float(v), } else: return {"status": "error", "error": "Missing solution values"} else: return {"status": "unsatisfiable", "error": "No solution found"} case Failure(error): return {"status": "error", "error": str(error)} case _: return {"status": "error", "error": "Unexpected result type"} def analyze_design(results): """Analyze the pipeline design solution and calculate performance metrics.""" if results["status"] != "satisfiable": return None diameter = results["diameter"] v = results["velocity"] # Problem constants q = 0.05 length = 100.0 rho = 1000.0 f = 0.02 pi = 3.14159265359 mu = 0.001 # Calculate derived quantities area = pi * (diameter / 2) ** 2 actual_flow_rate = area * v # Pressure drop pressure_drop = f * (length / diameter) * (rho * v**2 / 2) # Reynolds number reynolds = rho * v * diameter / mu # Costs pipe_cost_factor = 1000 pumping_cost_factor = 0.1 pipe_cost = pipe_cost_factor * pi * diameter**2 * length / 4 pumping_cost = pumping_cost_factor * pressure_drop * q total_cost = pipe_cost + pumping_cost return { "area": area, "actual_flow_rate": actual_flow_rate, "flow_rate_error": abs(actual_flow_rate - q) / q, "pressure_drop": pressure_drop, "reynolds_number": reynolds, "pipe_cost": pipe_cost, "pumping_cost": pumping_cost, "total_cost": total_cost, "is_turbulent": reynolds > 4000, } def print_results(results) -> None: """Print pipeline design results in a formatted way.""" if results["status"] != "satisfiable": print(f"Problem Status: {results['status']}") if "error" in results: print(f"Error: {results['error']}") return diameter = results["diameter"] v = results["velocity"] print("Chemical Engineering Pipeline Design Results") print("=" * 60) print("\nOptimal Design Parameters:") print(f" Pipe diameter: {diameter:.4f} m ({diameter*100:.2f} cm)") print(f" Flow velocity: {v:.3f} m/s") # Performance analysis analysis = analyze_design(results) if analysis: print("\nPerformance Analysis:") print("-" * 30) print(f" Cross-sectional area: {analysis['area']:.6f} m²") print(f" Actual flow rate: {analysis['actual_flow_rate']:.6f} m³/s") print(f" Flow rate error: {analysis['flow_rate_error']:.1%}") print( f" Pressure drop: {analysis['pressure_drop']:.0f} Pa ({analysis['pressure_drop']/1000:.1f} kPa)" ) print(f" Reynolds number: {analysis['reynolds_number']:.0f}") print( f" Flow regime: {'Turbulent' if analysis['is_turbulent'] else 'Laminar'}" ) print("\nCost Analysis:") print("-" * 20) print(f" Pipe cost: ${analysis['pipe_cost']:.2f}") print(f" Pumping cost: ${analysis['pumping_cost']:.2f}") print(f" Total cost: ${analysis['total_cost']:.2f}") # Verify constraints print("\nConstraint Verification:") print("-" * 25) print(f" Diameter limits: 0.05 ≤ {diameter:.3f} ≤ 0.5 m ✓") print(f" Velocity limits: 0.5 ≤ {v:.3f} ≤ 8.0 m/s ✓") print(f" Pressure drop: {analysis['pressure_drop']:.0f} ≤ 50,000 Pa ✓") print(f" Reynolds number: {analysis['reynolds_number']:.0f} ≥ 4,000 ✓") def main() -> None: """Main function to run the chemical engineering example.""" print(__doc__) results = solve_pipeline_design() print_results(results) def test_chemical_engineering() -> None: """Test function for pytest.""" results = solve_pipeline_design() # Test that we get a satisfiable solution assert results["status"] == "satisfiable" diameter = results["diameter"] v = results["velocity"] # Test design constraints assert 0.05 <= diameter <= 0.5 # Diameter limits assert 0.5 <= v <= 8.0 # Velocity limits # Test derived constraints analysis = analyze_design(results) assert analysis is not None # Flow continuity (should be very close to target) assert analysis["flow_rate_error"] < 0.01 # Less than 1% error # Pressure drop constraint assert analysis["pressure_drop"] <= 50000 # Less than 50 kPa # Reynolds number constraint (turbulent flow) assert analysis["reynolds_number"] >= 4000 # Cost constraint assert analysis["total_cost"] <= 6000 if __name__ == "__main__": main()

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/Sharmarajnish/MCP-Constrained-Optimization'

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