Implements NX solver integration that connects to running Simcenter3D GUI to solve simulations using the journal API. This approach handles licensing properly and ensures fresh output files are generated for each iteration. **New Components:** - optimization_engine/nx_solver.py: Main solver wrapper with auto-detection - optimization_engine/solve_simulation.py: NX journal script for batch solving - examples/test_journal_optimization.py: Complete optimization workflow test - examples/test_nx_solver.py: Solver integration tests - tests/journal_*.py: Reference journal files for NX automation **Key Features:** - Auto-detects NX installation and version - Connects to running NX GUI session (uses existing license) - Closes/reopens .sim files to force reload of updated .prt files - Deletes old output files to force fresh solves - Waits for background solve completion - Saves simulation to ensure all outputs are written - ~4 second solve time per iteration **Workflow:** 1. Update parameters in .prt file (nx_updater.py) 2. Close any open parts in NX session 3. Open .sim file fresh from disk (loads updated .prt) 4. Reload components and switch to FEM component 5. Solve in background mode 6. Save .sim file 7. Wait for .op2/.f06 to appear 8. Extract results from fresh .op2 **Tested:** - Multiple iteration loop (3+ iterations) - Files regenerated fresh each time (verified by timestamps) - Complete parameter update -> solve -> extract workflow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
295 lines
6.7 KiB
Markdown
295 lines
6.7 KiB
Markdown
# NX Solver Integration Guide
|
|
|
|
## Overview
|
|
|
|
The NX solver integration allows Atomizer to automatically run Siemens NX Nastran simulations in batch mode during optimization loops.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Optimization Loop:
|
|
1. Update parameters in .prt file → nx_updater.py
|
|
2. Run NX solver in batch mode → nx_solver.py ← NEW!
|
|
3. Extract results from OP2 → op2_extractor_example.py
|
|
4. Evaluate objectives/constraints → runner.py
|
|
5. Optuna suggests next parameters → repeat
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### Test 1: Verify Solver Integration
|
|
|
|
```bash
|
|
conda activate test_env
|
|
python examples/test_nx_solver.py
|
|
```
|
|
|
|
This tests:
|
|
- NX installation detection
|
|
- Batch solver execution
|
|
- OP2 file generation
|
|
- Error handling
|
|
|
|
**Expected**: Solver runs and produces .op2 file in ~1-2 minutes
|
|
|
|
### Test 2: Run Optimization with Real Solver
|
|
|
|
```bash
|
|
conda activate test_env
|
|
python examples/test_optimization_with_solver.py
|
|
```
|
|
|
|
This runs 3 optimization trials with REAL simulations!
|
|
|
|
**Expected time**: ~5-10 minutes (depends on model complexity)
|
|
|
|
## Usage in Your Code
|
|
|
|
### Simple Usage (Convenience Function)
|
|
|
|
```python
|
|
from optimization_engine.nx_solver import run_nx_simulation
|
|
from pathlib import Path
|
|
|
|
sim_file = Path("path/to/model.sim")
|
|
op2_file = run_nx_simulation(
|
|
sim_file=sim_file,
|
|
nastran_version="2412",
|
|
timeout=600, # 10 minutes
|
|
cleanup=True # Remove temp files
|
|
)
|
|
|
|
# op2_file now contains path to results
|
|
```
|
|
|
|
### Advanced Usage (Full Control)
|
|
|
|
```python
|
|
from optimization_engine.nx_solver import NXSolver
|
|
|
|
solver = NXSolver(
|
|
nastran_version="2412",
|
|
timeout=600
|
|
)
|
|
|
|
result = solver.run_simulation(
|
|
sim_file=sim_file,
|
|
working_dir=None, # Defaults to sim file directory
|
|
cleanup=True
|
|
)
|
|
|
|
if result['success']:
|
|
print(f"OP2: {result['op2_file']}")
|
|
print(f"Time: {result['elapsed_time']:.1f}s")
|
|
else:
|
|
print(f"Errors: {result['errors']}")
|
|
```
|
|
|
|
### Integration with Optimization Runner
|
|
|
|
```python
|
|
from optimization_engine.nx_solver import run_nx_simulation
|
|
|
|
def my_simulation_runner() -> Path:
|
|
"""Simulation runner for optimization."""
|
|
sim_file = Path("my_model.sim")
|
|
|
|
# Run solver
|
|
op2_file = run_nx_simulation(
|
|
sim_file=sim_file,
|
|
nastran_version="2412",
|
|
timeout=600,
|
|
cleanup=True
|
|
)
|
|
|
|
return op2_file
|
|
|
|
# Use in OptimizationRunner
|
|
runner = OptimizationRunner(
|
|
config_path=config_path,
|
|
model_updater=my_model_updater,
|
|
simulation_runner=my_simulation_runner, # Uses real solver!
|
|
result_extractors=extractors
|
|
)
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Auto-Detection
|
|
|
|
By default, NXSolver auto-detects NX installation:
|
|
|
|
```python
|
|
solver = NXSolver(nastran_version="2412")
|
|
# Searches:
|
|
# - C:/Program Files/Siemens/NX2412
|
|
# - C:/Program Files/Siemens/Simcenter3D_2412
|
|
# - C:/Program Files (x86)/Siemens/NX2412
|
|
```
|
|
|
|
### Manual Configuration
|
|
|
|
```python
|
|
from pathlib import Path
|
|
|
|
solver = NXSolver(
|
|
nx_install_dir=Path("C:/Program Files/Siemens/NX2412"),
|
|
nastran_version="2412",
|
|
timeout=1200 # 20 minutes
|
|
)
|
|
```
|
|
|
|
## Solver Output Files
|
|
|
|
### Files Created
|
|
- `model.op2` - Binary results (kept)
|
|
- `model.f06` - Text output (kept)
|
|
- `model.log` - Solver log (kept)
|
|
- `model.f04` - Intermediate (cleaned up)
|
|
- `model.dat` - Intermediate (cleaned up)
|
|
- `model.diag` - Diagnostic (cleaned up)
|
|
|
|
### Cleanup Behavior
|
|
|
|
With `cleanup=True` (recommended):
|
|
- Keeps: .op2, .f06, .log
|
|
- Removes: .f04, .dat, .diag, .master, .dball, plots
|
|
|
|
With `cleanup=False`:
|
|
- Keeps all files for debugging
|
|
|
|
## Error Handling
|
|
|
|
### Common Issues
|
|
|
|
**Issue**: `FileNotFoundError: NX Nastran solver not found`
|
|
|
|
**Solution**:
|
|
- Check NX is installed at standard location
|
|
- Specify `nx_install_dir` manually
|
|
- Verify nastran.exe exists in NXNASTRAN/bin/
|
|
|
|
**Issue**: `RuntimeError: NX simulation failed`
|
|
|
|
**Solution**:
|
|
- Check .f06 file for error messages
|
|
- Verify .sim file is valid
|
|
- Check NX license is available
|
|
- Ensure model can solve in NX GUI first
|
|
|
|
**Issue**: `TimeoutExpired`
|
|
|
|
**Solution**:
|
|
- Increase `timeout` parameter
|
|
- Simplify model (fewer elements, linear analysis)
|
|
- Check solver isn't stuck (memory issues)
|
|
|
|
### Checking Solver Success
|
|
|
|
The solver checks for completion by:
|
|
1. Looking for "NORMAL TERMINATION" in .f06
|
|
2. Checking for "FATAL MESSAGE" errors
|
|
3. Verifying .op2 file was created recently
|
|
|
|
## Performance Tips
|
|
|
|
### Speed Up Optimization
|
|
|
|
1. **Reduce Model Complexity**
|
|
- Use coarser mesh for initial exploration
|
|
- Simplify geometry in non-critical areas
|
|
- Use linear analysis if possible
|
|
|
|
2. **Parallel Trials (Future)**
|
|
- Run multiple trials simultaneously
|
|
- Requires separate working directories
|
|
- Use Optuna's parallelization features
|
|
|
|
3. **Smart Sampling**
|
|
- Use TPE sampler (default) for efficiency
|
|
- Increase `n_startup_trials` for better initial sampling
|
|
- Use constraints to avoid infeasible regions
|
|
|
|
4. **Cleanup Strategy**
|
|
- Use `cleanup=True` to save disk space
|
|
- Only keep .op2 and .log files
|
|
- Archive results after optimization
|
|
|
|
### Typical Solve Times
|
|
|
|
| Model Size | Analysis Type | Time per Trial |
|
|
|------------|---------------|----------------|
|
|
| Small (<10k nodes) | Linear Static | 30-60s |
|
|
| Medium (10-50k) | Linear Static | 1-3 min |
|
|
| Large (>50k) | Linear Static | 3-10 min |
|
|
| Any | Nonlinear | 5-30 min |
|
|
|
|
## Batch Processing
|
|
|
|
For running many optimizations:
|
|
|
|
```python
|
|
# Save solver instance to reuse
|
|
solver = NXSolver(nastran_version="2412", timeout=600)
|
|
|
|
for trial_params in parameter_sets:
|
|
# Update model
|
|
update_nx_model(prt_file, trial_params)
|
|
|
|
# Solve
|
|
result = solver.run_simulation(sim_file, cleanup=True)
|
|
|
|
if result['success']:
|
|
# Extract and analyze
|
|
results = extract_all_results(result['op2_file'])
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Enable Debug Output
|
|
|
|
```python
|
|
solver = NXSolver(nastran_version="2412")
|
|
|
|
result = solver.run_simulation(
|
|
sim_file=sim_file,
|
|
cleanup=False # Keep all files
|
|
)
|
|
|
|
# Check detailed output
|
|
print(result['errors'])
|
|
|
|
# Manually inspect files
|
|
# - Check .f06 for solver messages
|
|
# - Check .log for execution details
|
|
# - Check .f04 for input deck
|
|
```
|
|
|
|
### Verify NX Installation
|
|
|
|
```python
|
|
from optimization_engine.nx_solver import NXSolver
|
|
|
|
solver = NXSolver(nastran_version="2412")
|
|
print(f"NX Dir: {solver.nx_install_dir}")
|
|
print(f"Solver: {solver.solver_exe}")
|
|
print(f"Exists: {solver.solver_exe.exists()}")
|
|
```
|
|
|
|
## Next Steps
|
|
|
|
1. **Test solver integration**: Run `test_nx_solver.py`
|
|
2. **Test optimization loop**: Run `test_optimization_with_solver.py`
|
|
3. **Customize for your model**: Modify simulation_runner function
|
|
4. **Run real optimization**: Increase n_trials to 50-150
|
|
5. **Analyze results**: Use history.csv to understand parameter sensitivity
|
|
|
|
## Support
|
|
|
|
For issues:
|
|
1. Check this guide
|
|
2. Verify NX installation
|
|
3. Test .sim file in NX GUI first
|
|
4. Check solver logs (.f06, .log files)
|
|
5. Review error messages in result['errors']
|