253 lines
8.6 KiB
Python
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) |