AnsysLink/backend/utils/mechdb_reader.py
2025-08-11 13:58:59 +08:00

253 lines
8.6 KiB
Python

"""
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)