478 lines
15 KiB
Python
478 lines
15 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
CAE Mesh Generator - Demo Launcher
|
||
演示版本启动器,包含完整的系统检查和演示数据准备
|
||
"""
|
||
import os
|
||
import sys
|
||
import shutil
|
||
import subprocess
|
||
import webbrowser
|
||
import time
|
||
from pathlib import Path
|
||
from datetime import datetime
|
||
|
||
class DemoLauncher:
|
||
def __init__(self):
|
||
self.project_root = Path(__file__).parent.parent # 上一级目录
|
||
self.demo_data_dir = self.project_root / 'demo_data'
|
||
self.demo_port = 5000
|
||
self.demo_url = f'http://localhost:{self.demo_port}'
|
||
|
||
def print_banner(self):
|
||
"""打印演示横幅"""
|
||
print("=" * 70)
|
||
print("🚀 CAE网格生成助手 - 演示版本")
|
||
print(" 基于AI的自动化涡扇叶片网格生成系统")
|
||
print("=" * 70)
|
||
print(f"启动时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||
print(f"项目目录: {self.project_root}")
|
||
print(f"演示地址: {self.demo_url}")
|
||
print("=" * 70)
|
||
|
||
def check_python_version(self):
|
||
"""检查Python版本"""
|
||
print("\n📋 检查Python版本...")
|
||
version = sys.version_info
|
||
if version.major < 3 or (version.major == 3 and version.minor < 8):
|
||
print(f"❌ Python版本过低: {version.major}.{version.minor}")
|
||
print(" 需要Python 3.8或更高版本")
|
||
return False
|
||
|
||
print(f"✅ Python版本: {version.major}.{version.minor}.{version.micro}")
|
||
return True
|
||
|
||
def check_dependencies(self):
|
||
"""检查依赖包"""
|
||
print("\n📦 检查依赖包...")
|
||
|
||
required_packages = [
|
||
('flask', 'Flask'),
|
||
('werkzeug', 'Werkzeug'),
|
||
]
|
||
|
||
optional_packages = [
|
||
('ansys.mechanical.core', 'ANSYS Mechanical'),
|
||
]
|
||
|
||
missing_required = []
|
||
missing_optional = []
|
||
|
||
# 检查必需包
|
||
for package, name in required_packages:
|
||
try:
|
||
__import__(package)
|
||
print(f"✅ {name}: 已安装")
|
||
except ImportError:
|
||
print(f"❌ {name}: 未安装")
|
||
missing_required.append(package)
|
||
|
||
# 检查可选包
|
||
for package, name in optional_packages:
|
||
try:
|
||
__import__(package)
|
||
print(f"✅ {name}: 已安装 (完整功能)")
|
||
except ImportError:
|
||
print(f"⚠️ {name}: 未安装 (将使用演示模式)")
|
||
missing_optional.append(package)
|
||
|
||
if missing_required:
|
||
print(f"\n❌ 缺少必需依赖: {', '.join(missing_required)}")
|
||
print("请运行: pip install -r requirements.txt")
|
||
return False
|
||
|
||
if missing_optional:
|
||
print(f"\n⚠️ 缺少可选依赖: {', '.join(missing_optional)}")
|
||
print("系统将在演示模式下运行")
|
||
|
||
return True
|
||
|
||
def setup_directories(self):
|
||
"""设置目录结构"""
|
||
print("\n📁 设置目录结构...")
|
||
|
||
directories = [
|
||
'uploads',
|
||
'results',
|
||
'temp',
|
||
'static/css',
|
||
'static/js',
|
||
'static/visualizations',
|
||
'templates',
|
||
'demo_data',
|
||
'logs'
|
||
]
|
||
|
||
for directory in directories:
|
||
dir_path = self.project_root / directory
|
||
dir_path.mkdir(parents=True, exist_ok=True)
|
||
print(f"✅ {directory}/")
|
||
|
||
return True
|
||
|
||
def create_demo_data(self):
|
||
"""创建演示数据"""
|
||
print("\n🎯 准备演示数据...")
|
||
|
||
# 创建示例STEP文件
|
||
sample_step_files = [
|
||
('simple_blade.step', self.create_simple_blade_step()),
|
||
('complex_blade.step', self.create_complex_blade_step()),
|
||
('test_geometry.step', self.create_test_geometry_step())
|
||
]
|
||
|
||
for filename, content in sample_step_files:
|
||
file_path = self.demo_data_dir / filename
|
||
with open(file_path, 'w', encoding='utf-8') as f:
|
||
f.write(content)
|
||
print(f"✅ 创建示例文件: {filename}")
|
||
|
||
# 创建演示说明文件
|
||
demo_guide = self.create_demo_guide()
|
||
guide_path = self.demo_data_dir / 'DEMO_GUIDE.md'
|
||
with open(guide_path, 'w', encoding='utf-8') as f:
|
||
f.write(demo_guide)
|
||
print(f"✅ 创建演示指南: DEMO_GUIDE.md")
|
||
|
||
return True
|
||
|
||
def create_simple_blade_step(self):
|
||
"""创建简单叶片STEP文件"""
|
||
return """ISO-10303-21;
|
||
HEADER;
|
||
FILE_DESCRIPTION(('Simple Turbine Blade for CAE Mesh Generator Demo'),'2;1');
|
||
FILE_NAME('simple_blade.step','2025-01-01T00:00:00',('Demo'),('CAE Mesh Generator'),'Demo System','ANSYS','');
|
||
FILE_SCHEMA(('AUTOMOTIVE_DESIGN'));
|
||
ENDSEC;
|
||
DATA;
|
||
/* 简单涡扇叶片几何定义 */
|
||
#1 = CARTESIAN_POINT('Origin',(0.0,0.0,0.0));
|
||
#2 = DIRECTION('X-Axis',(1.0,0.0,0.0));
|
||
#3 = DIRECTION('Y-Axis',(0.0,1.0,0.0));
|
||
#4 = DIRECTION('Z-Axis',(0.0,0.0,1.0));
|
||
#5 = AXIS2_PLACEMENT_3D('Global Coordinate System',#1,#4,#2);
|
||
|
||
/* 叶片轮廓点 */
|
||
#10 = CARTESIAN_POINT('Leading Edge Root',(0.0,0.0,0.0));
|
||
#11 = CARTESIAN_POINT('Trailing Edge Root',(50.0,0.0,0.0));
|
||
#12 = CARTESIAN_POINT('Leading Edge Tip',(5.0,0.0,100.0));
|
||
#13 = CARTESIAN_POINT('Trailing Edge Tip',(45.0,0.0,100.0));
|
||
|
||
/* 叶片表面定义 */
|
||
#20 = CARTESIAN_POINT('Pressure Side 1',(0.0,5.0,0.0));
|
||
#21 = CARTESIAN_POINT('Pressure Side 2',(25.0,8.0,0.0));
|
||
#22 = CARTESIAN_POINT('Pressure Side 3',(50.0,5.0,0.0));
|
||
#23 = CARTESIAN_POINT('Suction Side 1',(0.0,-5.0,0.0));
|
||
#24 = CARTESIAN_POINT('Suction Side 2',(25.0,-8.0,0.0));
|
||
#25 = CARTESIAN_POINT('Suction Side 3',(50.0,-5.0,0.0));
|
||
|
||
ENDSEC;
|
||
END-ISO-10303-21;"""
|
||
|
||
def create_complex_blade_step(self):
|
||
"""创建复杂叶片STEP文件"""
|
||
return """ISO-10303-21;
|
||
HEADER;
|
||
FILE_DESCRIPTION(('Complex Turbine Blade with Cooling Channels for CAE Mesh Generator Demo'),'2;1');
|
||
FILE_NAME('complex_blade.step','2025-01-01T00:00:00',('Demo'),('CAE Mesh Generator'),'Demo System','ANSYS','');
|
||
FILE_SCHEMA(('AUTOMOTIVE_DESIGN'));
|
||
ENDSEC;
|
||
DATA;
|
||
/* 复杂涡扇叶片几何定义 - 包含冷却通道 */
|
||
#1 = CARTESIAN_POINT('Origin',(0.0,0.0,0.0));
|
||
#2 = DIRECTION('X-Axis',(1.0,0.0,0.0));
|
||
#3 = DIRECTION('Y-Axis',(0.0,1.0,0.0));
|
||
#4 = DIRECTION('Z-Axis',(0.0,0.0,1.0));
|
||
#5 = AXIS2_PLACEMENT_3D('Global Coordinate System',#1,#4,#2);
|
||
|
||
/* 主叶片几何 */
|
||
#10 = CARTESIAN_POINT('LE Root',(0.0,0.0,0.0));
|
||
#11 = CARTESIAN_POINT('TE Root',(60.0,0.0,0.0));
|
||
#12 = CARTESIAN_POINT('LE Tip',(8.0,0.0,120.0));
|
||
#13 = CARTESIAN_POINT('TE Tip',(52.0,0.0,120.0));
|
||
|
||
/* 冷却通道几何 */
|
||
#30 = CARTESIAN_POINT('Cooling Channel 1 Start',(15.0,0.0,10.0));
|
||
#31 = CARTESIAN_POINT('Cooling Channel 1 End',(15.0,0.0,110.0));
|
||
#32 = CARTESIAN_POINT('Cooling Channel 2 Start',(30.0,0.0,10.0));
|
||
#33 = CARTESIAN_POINT('Cooling Channel 2 End',(30.0,0.0,110.0));
|
||
#34 = CARTESIAN_POINT('Cooling Channel 3 Start',(45.0,0.0,10.0));
|
||
#35 = CARTESIAN_POINT('Cooling Channel 3 End',(45.0,0.0,110.0));
|
||
|
||
/* 叶片根部连接 */
|
||
#40 = CARTESIAN_POINT('Root Connection 1',(-5.0,0.0,-10.0));
|
||
#41 = CARTESIAN_POINT('Root Connection 2',(65.0,0.0,-10.0));
|
||
#42 = CARTESIAN_POINT('Root Connection 3',(30.0,0.0,-15.0));
|
||
|
||
ENDSEC;
|
||
END-ISO-10303-21;"""
|
||
|
||
def create_test_geometry_step(self):
|
||
"""创建测试几何STEP文件"""
|
||
return """ISO-10303-21;
|
||
HEADER;
|
||
FILE_DESCRIPTION(('Test Geometry for CAE Mesh Generator Validation'),'2;1');
|
||
FILE_NAME('test_geometry.step','2025-01-01T00:00:00',('Test'),('CAE Mesh Generator'),'Test System','ANSYS','');
|
||
FILE_SCHEMA(('AUTOMOTIVE_DESIGN'));
|
||
ENDSEC;
|
||
DATA;
|
||
/* 测试几何 - 简单立方体用于验证 */
|
||
#1 = CARTESIAN_POINT('Origin',(0.0,0.0,0.0));
|
||
#2 = DIRECTION('X-Axis',(1.0,0.0,0.0));
|
||
#3 = DIRECTION('Y-Axis',(0.0,1.0,0.0));
|
||
#4 = DIRECTION('Z-Axis',(0.0,0.0,1.0));
|
||
#5 = AXIS2_PLACEMENT_3D('Global Coordinate System',#1,#4,#2);
|
||
|
||
/* 立方体顶点 */
|
||
#10 = CARTESIAN_POINT('Vertex 1',(0.0,0.0,0.0));
|
||
#11 = CARTESIAN_POINT('Vertex 2',(10.0,0.0,0.0));
|
||
#12 = CARTESIAN_POINT('Vertex 3',(10.0,10.0,0.0));
|
||
#13 = CARTESIAN_POINT('Vertex 4',(0.0,10.0,0.0));
|
||
#14 = CARTESIAN_POINT('Vertex 5',(0.0,0.0,10.0));
|
||
#15 = CARTESIAN_POINT('Vertex 6',(10.0,0.0,10.0));
|
||
#16 = CARTESIAN_POINT('Vertex 7',(10.0,10.0,10.0));
|
||
#17 = CARTESIAN_POINT('Vertex 8',(0.0,10.0,10.0));
|
||
|
||
ENDSEC;
|
||
END-ISO-10303-21;"""
|
||
|
||
def create_demo_guide(self):
|
||
"""创建演示指南"""
|
||
return """# CAE网格生成助手 - 演示指南
|
||
|
||
## 欢迎使用演示版本!
|
||
|
||
本演示系统展示了基于AI的自动化涡扇叶片网格生成功能。
|
||
|
||
### 🎯 演示目标
|
||
|
||
- 展示STEP文件上传和验证功能
|
||
- 演示自动化网格生成流程
|
||
- 展示网格质量检查和评估
|
||
- 展示结果可视化和导出功能
|
||
|
||
### 📁 演示文件说明
|
||
|
||
1. **simple_blade.step**
|
||
- 简单涡扇叶片几何
|
||
- 适合快速演示基本功能
|
||
- 预计处理时间:30-60秒
|
||
|
||
2. **complex_blade.step**
|
||
- 复杂叶片几何,包含冷却通道
|
||
- 展示高级网格控制功能
|
||
- 预计处理时间:2-5分钟
|
||
|
||
3. **test_geometry.step**
|
||
- 简单测试几何(立方体)
|
||
- 用于功能验证
|
||
- 预计处理时间:10-30秒
|
||
|
||
### 🚀 演示流程
|
||
|
||
#### 步骤1:文件上传
|
||
1. 打开演示网页界面
|
||
2. 点击上传区域或拖拽文件
|
||
3. 选择演示文件(推荐从simple_blade.step开始)
|
||
4. 等待文件验证完成
|
||
|
||
#### 步骤2:网格生成
|
||
1. 文件上传成功后,点击"开始生成"按钮
|
||
2. 观察实时进度显示和处理日志
|
||
3. 系统将自动完成以下步骤:
|
||
- 几何导入和验证
|
||
- 自动识别关键区域
|
||
- 应用网格控制
|
||
- 生成网格
|
||
- 质量检查
|
||
|
||
#### 步骤3:结果查看
|
||
1. 查看网格统计信息
|
||
2. 查看质量评估报告
|
||
3. 查看可视化结果(如果可用)
|
||
4. 下载结果文件
|
||
|
||
### 🔧 演示模式说明
|
||
|
||
- **完整模式**:如果安装了ANSYS Mechanical,将使用真实的网格生成功能
|
||
- **演示模式**:如果未安装ANSYS,将使用模拟数据展示完整流程
|
||
|
||
### 📊 预期结果
|
||
|
||
#### Simple Blade (简单叶片)
|
||
- 单元数量:约8,000-12,000
|
||
- 节点数量:约12,000-18,000
|
||
- 质量评分:75-85分
|
||
- 生成时间:30-60秒
|
||
|
||
#### Complex Blade (复杂叶片)
|
||
- 单元数量:约25,000-40,000
|
||
- 节点数量:约35,000-55,000
|
||
- 质量评分:70-80分
|
||
- 生成时间:2-5分钟
|
||
|
||
#### Test Geometry (测试几何)
|
||
- 单元数量:约1,000-2,000
|
||
- 节点数量:约1,500-3,000
|
||
- 质量评分:85-95分
|
||
- 生成时间:10-30秒
|
||
|
||
### 🎨 界面功能
|
||
|
||
#### 侧边栏
|
||
- 处理流程步骤显示
|
||
- 系统状态监控
|
||
- 实时进度更新
|
||
|
||
#### 主界面
|
||
- 文件上传区域
|
||
- 进度显示和日志
|
||
- 结果统计和可视化
|
||
- 导出选项
|
||
|
||
### 🔍 故障排除
|
||
|
||
#### 常见问题
|
||
|
||
1. **文件上传失败**
|
||
- 确认文件格式为.step或.stp
|
||
- 确认文件大小不超过100MB
|
||
- 检查文件是否损坏
|
||
|
||
2. **网格生成失败**
|
||
- 检查几何文件完整性
|
||
- 查看错误日志信息
|
||
- 尝试使用测试几何文件
|
||
|
||
3. **界面无响应**
|
||
- 刷新浏览器页面
|
||
- 检查网络连接
|
||
- 查看浏览器控制台错误
|
||
|
||
#### 技术支持
|
||
|
||
如遇到问题,请:
|
||
1. 查看浏览器控制台错误信息
|
||
2. 查看应用日志文件
|
||
3. 尝试重启演示系统
|
||
|
||
### 📈 性能优化建议
|
||
|
||
1. **文件选择**:首次使用建议从simple_blade.step开始
|
||
2. **浏览器**:推荐使用Chrome或Firefox最新版本
|
||
3. **系统资源**:确保有足够的内存和CPU资源
|
||
|
||
### 🎉 演示完成后
|
||
|
||
演示完成后,您可以:
|
||
1. 查看生成的网格文件
|
||
2. 分析质量报告
|
||
3. 了解系统架构和技术实现
|
||
4. 探索更多高级功能
|
||
|
||
---
|
||
|
||
**祝您演示愉快!**
|
||
|
||
如有任何问题或建议,欢迎反馈。
|
||
"""
|
||
|
||
def check_port_availability(self):
|
||
"""检查端口可用性"""
|
||
print(f"\n🌐 检查端口 {self.demo_port} 可用性...")
|
||
|
||
import socket
|
||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||
result = s.connect_ex(('localhost', self.demo_port))
|
||
if result == 0:
|
||
print(f"⚠️ 端口 {self.demo_port} 已被占用")
|
||
print("请关闭占用端口的程序或修改配置")
|
||
return False
|
||
else:
|
||
print(f"✅ 端口 {self.demo_port} 可用")
|
||
return True
|
||
|
||
def start_application(self):
|
||
"""启动应用程序"""
|
||
print(f"\n🚀 启动CAE网格生成助手...")
|
||
print(f"访问地址: {self.demo_url}")
|
||
print("按 Ctrl+C 停止应用")
|
||
print("-" * 50)
|
||
|
||
try:
|
||
# 添加项目根目录到Python路径
|
||
sys.path.insert(0, str(self.project_root))
|
||
|
||
# 启动Flask应用
|
||
from app import create_app
|
||
app = create_app()
|
||
|
||
# 延迟打开浏览器
|
||
def open_browser():
|
||
time.sleep(2)
|
||
print(f"\n🌐 正在打开浏览器: {self.demo_url}")
|
||
webbrowser.open(self.demo_url)
|
||
|
||
import threading
|
||
browser_thread = threading.Thread(target=open_browser, daemon=True)
|
||
browser_thread.start()
|
||
|
||
# 启动应用
|
||
app.run(
|
||
host='0.0.0.0',
|
||
port=self.demo_port,
|
||
debug=False,
|
||
use_reloader=False
|
||
)
|
||
|
||
except KeyboardInterrupt:
|
||
print("\n\n👋 演示已停止")
|
||
print("感谢使用CAE网格生成助手演示版本!")
|
||
except Exception as e:
|
||
print(f"\n❌ 启动失败: {e}")
|
||
return False
|
||
|
||
return True
|
||
|
||
def run_demo(self):
|
||
"""运行完整演示"""
|
||
self.print_banner()
|
||
|
||
# 系统检查
|
||
checks = [
|
||
("Python版本", self.check_python_version),
|
||
("依赖包", self.check_dependencies),
|
||
("目录结构", self.setup_directories),
|
||
("演示数据", self.create_demo_data),
|
||
("端口可用性", self.check_port_availability)
|
||
]
|
||
|
||
for check_name, check_func in checks:
|
||
if not check_func():
|
||
print(f"\n❌ {check_name}检查失败,演示无法启动")
|
||
return False
|
||
|
||
print("\n✅ 所有检查通过,准备启动演示...")
|
||
print("\n📖 演示指南已创建在 demo_data/DEMO_GUIDE.md")
|
||
print("建议先阅读演示指南了解使用方法")
|
||
|
||
# 询问是否继续
|
||
try:
|
||
response = input("\n是否现在启动演示?(y/N): ").strip().lower()
|
||
if response in ['y', 'yes', '是']:
|
||
return self.start_application()
|
||
else:
|
||
print("\n演示已取消。您可以稍后运行此脚本启动演示。")
|
||
return True
|
||
except KeyboardInterrupt:
|
||
print("\n\n演示已取消。")
|
||
return True
|
||
|
||
def main():
|
||
"""主函数"""
|
||
launcher = DemoLauncher()
|
||
success = launcher.run_demo()
|
||
return 0 if success else 1
|
||
|
||
if __name__ == '__main__':
|
||
sys.exit(main()) |