""" ANSYS Mechanical Database (.mechdb) Reader This module provides functionality to read mesh statistics from ANSYS Mechanical database files using PyMechanical. """ import logging import os from typing import Dict, Any, Optional from pathlib import Path logger = logging.getLogger(__name__) class MechDBReader: """ Reader for ANSYS Mechanical database files This class can open .mechdb files and extract mesh statistics including element count, node count, and other mesh information. """ def __init__(self): """ Initialize MechDB reader for real ANSYS integration """ self.mechanical = None def read_mesh_statistics(self, mechdb_path: str) -> Dict[str, Any]: """ Read mesh statistics from a .mechdb file Args: mechdb_path: Path to the .mechdb file Returns: Dictionary with mesh statistics """ try: if not os.path.exists(mechdb_path): logger.error(f"MechDB file not found: {mechdb_path}") return {"error": "File not found", "success": False} return self._read_real_mechdb(mechdb_path) except Exception as e: logger.error(f"Error reading MechDB file: {str(e)}") return {"error": str(e), "success": False} def _read_real_mechdb(self, mechdb_path: str) -> Dict[str, Any]: """ Read actual MechDB file using PyMechanical Args: mechdb_path: Path to the .mechdb file Returns: Real mesh statistics from ANSYS """ try: logger.info(f"Reading MechDB file with ANSYS: {mechdb_path}") # Import PyMechanical import ansys.mechanical.core as pymechanical # Launch ANSYS Mechanical logger.info("Launching ANSYS Mechanical for MechDB reading...") mechanical = pymechanical.launch_mechanical(batch=True, cleanup_on_exit=True) # Open the MechDB file logger.info(f"Opening MechDB file: {mechdb_path}") # Script to open MechDB and read mesh statistics read_script = f''' # Open MechDB file and read mesh statistics import os try: # Open the MechDB file mechdb_path = r"{mechdb_path}" print("Opening MechDB file: " + mechdb_path) # Open the project ExtAPI.Application.Open(mechdb_path) print("MechDB file opened successfully") # Get mesh object mesh = Model.Mesh print("Mesh object obtained: " + str(mesh is not None)) # Initialize statistics stats = {{ "element_count": 0, "node_count": 0, "has_mesh": False, "mesh_type": "Unknown" }} if mesh: # Get element count try: if hasattr(mesh, 'Elements') and mesh.Elements: elements = mesh.Elements if hasattr(elements, 'Count'): stats["element_count"] = elements.Count print("Element count: " + str(stats["element_count"])) elif hasattr(elements, '__len__'): stats["element_count"] = len(elements) print("Element count (len): " + str(stats["element_count"])) except Exception as e: print("Error getting element count: " + str(e)) # Get node count try: if hasattr(mesh, 'Nodes') and mesh.Nodes: nodes = mesh.Nodes if hasattr(nodes, 'Count'): stats["node_count"] = nodes.Count print("Node count: " + str(stats["node_count"])) elif hasattr(nodes, '__len__'): stats["node_count"] = len(nodes) print("Node count (len): " + str(stats["node_count"])) except Exception as e: print("Error getting node count: " + str(e)) # Check if mesh exists stats["has_mesh"] = stats["element_count"] > 0 # Get mesh type information try: if hasattr(mesh, 'ElementType'): stats["mesh_type"] = str(mesh.ElementType) else: stats["mesh_type"] = "Mixed" except: stats["mesh_type"] = "Mixed" # Print final statistics print("=== MESH STATISTICS ===") print("Elements: " + str(stats["element_count"])) print("Nodes: " + str(stats["node_count"])) print("Has mesh: " + str(stats["has_mesh"])) print("Mesh type: " + stats["mesh_type"]) print("=== END STATISTICS ===") except Exception as e: print("ERROR reading MechDB: " + str(e)) print("Elements: 0") print("Nodes: 0") print("Has mesh: False") ''' # Execute the script result = mechanical.run_python_script(read_script) logger.info(f"MechDB read script result: {result}") # Parse the results statistics = self._parse_mechdb_results(result, mechdb_path) # Close ANSYS mechanical.exit() return statistics except ImportError: logger.error("PyMechanical not available") return {"error": "PyMechanical not available", "success": False} except Exception as e: logger.error(f"Error reading MechDB with ANSYS: {str(e)}") return {"error": str(e), "success": False} def _parse_mechdb_results(self, script_output: str, mechdb_path: str) -> Dict[str, Any]: """ Parse mesh statistics from ANSYS script output Args: script_output: Output from ANSYS script mechdb_path: Path to the MechDB file Returns: Parsed mesh statistics """ statistics = { "success": False, "element_count": 0, "node_count": 0, "file_path": mechdb_path, "file_size": os.path.getsize(mechdb_path), "has_mesh": False, "mesh_type": "Unknown", "simulation": False, "read_method": "ANSYS PyMechanical" } try: if script_output: lines = script_output.split('\n') for line in lines: if line.startswith("Elements: "): try: count = int(line.split(':')[1].strip()) statistics["element_count"] = count except: pass elif line.startswith("Nodes: "): try: count = int(line.split(':')[1].strip()) statistics["node_count"] = count except: pass elif line.startswith("Has mesh: "): try: has_mesh = line.split(':')[1].strip().lower() == 'true' statistics["has_mesh"] = has_mesh except: pass elif line.startswith("Mesh type: "): try: mesh_type = line.split(':')[1].strip() statistics["mesh_type"] = mesh_type except: pass # Check if we got valid data if statistics["element_count"] > 0 and statistics["node_count"] > 0: statistics["success"] = True logger.info(f"✓ Successfully read MechDB: {statistics['element_count']} elements, {statistics['node_count']} nodes") else: logger.warning("MechDB read completed but no valid mesh data found") statistics["success"] = False else: logger.warning("No output from MechDB read script") except Exception as e: logger.error(f"Error parsing MechDB results: {str(e)}") statistics["error"] = str(e) return statistics def read_mechdb_statistics(mechdb_path: str) -> Dict[str, Any]: """ Convenience function to read mesh statistics from MechDB file Args: mechdb_path: Path to the .mechdb file Returns: Dictionary with mesh statistics """ reader = MechDBReader() return reader.read_mesh_statistics(mechdb_path)