feat: Add Phase 2 & 3 physics extractors for multi-physics optimization

Phase 2 - Structural Analysis:
- extract_principal_stress: σ1, σ2, σ3 principal stresses from OP2
- extract_strain_energy: Element and total strain energy
- extract_spc_forces: Reaction forces at boundary conditions

Phase 3 - Multi-Physics:
- extract_temperature: Nodal temperatures from thermal OP2 (SOL 153/159)
- extract_temperature_gradient: Thermal gradient approximation
- extract_heat_flux: Element heat flux from thermal analysis
- extract_modal_mass: Modal effective mass from F06 (SOL 103)
- get_first_frequency: Convenience function for first natural frequency

Documentation:
- Updated SYS_12_EXTRACTOR_LIBRARY.md with E12-E18 specifications
- Updated NX_OPEN_AUTOMATION_ROADMAP.md marking Phase 3 complete
- Added test_phase3_extractors.py for validation

All extractors follow consistent API pattern returning Dict with
success, data, and error fields for robust error handling.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Antoine
2025-12-06 13:40:14 -05:00
parent 5fb94fdf01
commit 0cb2808c44
9 changed files with 3395 additions and 2 deletions

View File

@@ -0,0 +1,717 @@
# Atomizer NX Open Automation Roadmap
## Plan de Match: Hooks, Extractors & Manipulators pour Optimisation FEA
**Date**: 2025-12-06
**Version**: 2.0 (merged with ATOMIZER_NXOPEN_MASTER_PLAN.md)
**Objectif**: Définir l'ensemble des fonctionnalités NX Open à implémenter pour un framework d'optimisation structurelle/thermique complet, basé sur la règle 80/20.
---
## Quick Reference: NX Open API Index
### Core Classes (verified via MCP)
| Class | Page ID | Primary Use |
|-------|---------|-------------|
| `NXOpen.Session` | a03318.html | Session singleton, part access |
| `NXOpen.Part` | a02434.html | Part operations, expressions |
| `NXOpen.BasePart` | a00266.html | Base class, common methods |
| `NXOpen.CAE.CaeSession` | a10510.html | CAE session, utilities |
| `NXOpen.CAE.FemPart` | - | FEM part, mesh access |
| `NXOpen.CAE.SimPart` | - | Simulation part, solutions |
### Key Collections & Managers (from NXOpen.Part)
| Manager | Access | Purpose |
|---------|--------|---------|
| `Expressions` | `part.Expressions` | Expression management |
| `MeasureManager` | `part.MeasureManager()` | Mass properties |
| `Bodies` | `part.Bodies()` | Body collection |
| `Features` | `part.Features()` | Feature collection |
| `MaterialManager` | `part.MaterialManager()` | Material assignment |
### CAE Managers (from NXOpen.CAE.CaeSession)
| Manager | Access | Purpose |
|---------|--------|---------|
| `MaterialUtils` | `cae_session.MaterialUtils()` | CAE material utilities |
| `AssociationUtils` | `cae_session.AssociationUtils()` | Geometry-FEM association |
| `PenetrationCheckManager` | `cae_session.PenetrationCheckManager()` | Contact check |
---
## 1. Analyse de l'Industrie MDO
### Fonctionnalités Standard (ce que font les concurrents)
| Fonctionnalité | HyperStudy | modeFRONTIER | HEEDS | OpenMDAO | Atomizer (actuel) |
|----------------|------------|--------------|-------|----------|-------------------|
| DOE (LHS, Sobol, etc.) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Optimisation mono-objectif | ✓ | ✓ | ✓ | ✓ | ✓ |
| Multi-objectif (Pareto) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Surrogate Models | ✓ | ✓ | ✓ | ✓ | ✓ (NN) |
| Kriging/Gaussian Process | ✓ | ✓ | ✓ | ✓ | ❌ |
| Robustesse/Fiabilité (RBDO) | ✓ | ✓ | ❌ | ✓ | ❌ |
| Sensibilité paramétrique | ✓ | ✓ | ✓ | ✓ | Partiel |
| Topology Optimization | ✓ | ❌ | ❌ | ❌ | ❌ |
| Workflow visuel | ✓ | ✓ | ✓ | ❌ | ❌ |
| Interface NX native | ❌ | ❌ | ✓ | ❌ | ✓ |
### Sources
- [Altair HyperStudy](https://altair.com/hyperstudy/)
- [modeFRONTIER](https://engineering.esteco.com/modefrontier/)
- [OpenMDAO](https://openmdao.org/)
- [M4 Engineering NXOpen Example](https://www.m4-engineering.com/automating-load-case-combination-and-enveloping-in-simcenter-3d-using-nxopen-python/)
---
## 2. Capacités Simcenter 13500
### Modules Disponibles avec ta Licence
| Module | Description | Utilisable pour Optimisation |
|--------|-------------|------------------------------|
| **NX Nastran Basic** | Static, Modal, Buckling | ✓ Priorité haute |
| **NX Nastran Dynamic** | Frequency/Transient Response | ✓ Priorité moyenne |
| **NX Nastran Thermal** | Heat Transfer (steady/transient) | ✓ Priorité haute |
| **NX Nastran Optimization** | SOL 200 (taille, forme) | ✓ Priorité moyenne |
| **Simcenter 3D Pre/Post** | Meshing, Results | ✓ Indispensable |
### Types d'Analyses Supportées
1. **Structurel Linéaire** (SOL 101)
- Static stress/displacement
- Reaction forces
2. **Modal** (SOL 103)
- Natural frequencies
- Mode shapes
- Modal effective mass
3. **Buckling** (SOL 105)
- Critical load factors
- Buckling mode shapes
4. **Thermique** (SOL 153/159)
- Steady-state heat transfer
- Transient thermal
- Thermal stress coupling
5. **Dynamique** (SOL 108/109/111/112)
- Frequency response
- Transient response
- Random response
---
## 3. Architecture des Hooks NX Open
### 3.1 Hooks de Manipulation CAD (Priorité 1)
```
optimization_engine/
└── hooks/
└── nx_cad/
├── __init__.py
├── part_manager.py # Open/Save/Close parts
├── expression_manager.py # Get/Set expressions
├── feature_manager.py # Suppress/Unsuppress features
├── geometry_query.py # Query geometry (mass, volume, area)
└── assembly_manager.py # Component positioning
```
| Hook | Description | API NX Open | Priorité |
|------|-------------|-------------|----------|
| `open_part(path)` | Ouvrir une pièce | `Session.Parts.OpenBase()` | P1 |
| `close_part(save=False)` | Fermer une pièce | `Part.Close()` | P1 |
| `set_expression(name, value)` | Modifier expression | `Expression.SetValue()` | P1 |
| `get_expression(name)` | Lire expression | `Expression.Value` | P1 |
| `update_model()` | Mettre à jour le modèle | `Session.UpdateManager.DoUpdate()` | P1 |
| `suppress_feature(name)` | Supprimer feature | `Feature.Suppress()` | P2 |
| `get_mass_properties()` | Masse, CG, inertie | `MeasureManager.NewMassProperties()` | P1 |
| `export_parasolid(path)` | Exporter géométrie | `Part.SaveAs()` | P2 |
### 3.2 Hooks FEM/Meshing (Priorité 2)
```
optimization_engine/
└── hooks/
└── nx_fem/
├── __init__.py
├── mesh_manager.py # Create/Update mesh
├── material_manager.py # Assign materials
├── property_manager.py # Shell/Solid properties
├── boundary_conditions.py # Loads & constraints
└── connection_manager.py # Connectors, contacts
```
| Hook | Description | API NX Open | Priorité |
|------|-------------|-------------|----------|
| `create_tet_mesh(body, size)` | Mailler en tétra | `MeshManager.CreateMesh3d()` | P1 |
| `update_mesh()` | Régénérer maillage | `FEModel.UpdateMesh()` | P1 |
| `set_material(mesh, mat_name)` | Assigner matériau | `PhysicalProperty.SetMaterial()` | P1 |
| `create_shell_property(t)` | Propriété shell | `PhysicalPropertyCollection.CreateShellProperty()` | P2 |
| `apply_force(nodes, vector)` | Appliquer force | `LoadCollection.CreateForce()` | P1 |
| `apply_constraint(nodes, dof)` | Appliquer contrainte | `ConstraintCollection.CreateConstraint()` | P1 |
| `create_contact(faces1, faces2)` | Contact surfaces | `ConnectionCollection.CreateSurfaceContact()` | P2 |
### 3.3 Hooks Simulation/Solve (Priorité 1)
```
optimization_engine/
└── hooks/
└── nx_sim/
├── __init__.py
├── solution_manager.py # Create/Run solutions
├── solve_manager.py # Submit solver jobs
└── result_manager.py # Access results
```
| Hook | Description | API NX Open | Priorité |
|------|-------------|-------------|----------|
| `create_solution(type, name)` | Créer solution | `SimSolutionCollection.CreateSolution()` | P1 |
| `solve(solution)` | Lancer solveur | `SimSolution.Solve()` | P1 |
| `solve_batch(bdf_path)` | Nastran en batch | `subprocess` + run_nastran | P1 |
| `get_solve_status()` | Statut du solve | `SimSolution.SolveStatus` | P1 |
| `export_bdf(path)` | Exporter deck Nastran | `SimSolution.ExportSolver()` | P1 |
---
## 4. Architecture des Extractors
### 4.0 Current Implementation Status (as of 2025-12-06)
```
optimization_engine/extractors/
├── __init__.py
├── extract_displacement.py # ✓ extract_displacement()
├── extract_von_mises_stress.py # ✓ extract_solid_stress()
├── extract_frequency.py # ✓ extract_frequency()
├── extract_mass.py # ✓ extract_generic()
├── extract_mass_from_bdf.py # ✓ extract_mass_from_bdf()
├── extract_mass_from_expression.py # ✓ extract_mass_from_expression()
├── extract_part_mass_material.py # ✓ PartMassExtractor (NX Open via journal)
├── bdf_mass_extractor.py # ✓ BDFMassExtractor class
├── op2_extractor.py # ✓ OP2Extractor class (mass, grid forces, loads)
├── field_data_extractor.py # ✓ FieldDataExtractor class
├── extract_zernike.py # ✓ ZernikeExtractor class (advanced)
├── extract_zernike_surface.py # ✓ SurfaceZernikeExtractor class
└── zernike_helpers.py # ✓ Helper functions
```
### 4.1 Extractors Structurels (Priorité 1)
| Extractor | Output | Source | Priorité | Status | File |
|-----------|--------|--------|----------|--------|------|
| `extract_displacement(op2, subcase)` | mm | OP2 | P1 | ✓ | extract_displacement.py |
| `extract_solid_stress(op2, subcase, elem_type)` | MPa | OP2 | P1 | ✓ | extract_von_mises_stress.py |
| `extract_mass_from_bdf(bdf)` | kg | BDF | P1 | ✓ | bdf_mass_extractor.py |
| `extract_mass_from_op2(op2)` | kg | OP2 | P1 | ✓ | op2_extractor.py |
| `extract_grid_point_forces(op2)` | N | OP2 | P1 | ✓ | op2_extractor.py |
| `extract_displacement_field(op2)` | [mm] | OP2 | P1 | ✓ | field_data_extractor.py |
| `extract_principal_stress(elem)` | MPa | OP2 | P2 | ❌ | - |
| `extract_strain(elem)` | - | OP2 | P2 | ❌ | - |
| `extract_strain_energy(elem)` | J | OP2 | P2 | ❌ | - |
### 4.2 Extractors Modaux (Priorité 2)
| Extractor | Output | Source | Priorité | Status | File |
|-----------|--------|--------|----------|--------|------|
| `extract_frequency(op2, subcase, mode)` | Hz | OP2 | P1 | ✓ | extract_frequency.py |
| `extract_modal_mass(mode)` | kg | F06 | P2 | ❌ | - |
| `extract_mode_shape(mode, nodes)` | [mm] | OP2 | P3 | ❌ | - |
| `extract_mac_matrix(modes)` | [0-1] | Calc | P3 | ❌ | - |
### 4.3 Extractors Thermiques (Priorité 2)
| Extractor | Output | Source | Priorité | Status | File |
|-----------|--------|--------|----------|--------|------|
| `extract_temperature(node)` | °C/K | OP2/F06 | P2 | ❌ | - |
| `extract_max_temperature()` | °C/K | OP2/F06 | P2 | ❌ | - |
| `extract_heat_flux(elem)` | W/m² | OP2/F06 | P2 | ❌ | - |
| `extract_thermal_stress(elem)` | MPa | OP2/F06 | P2 | ❌ | - |
### 4.4 Extractors Géométriques (CAD) (Priorité 1) - NX Open
| Extractor | Output | Source | Priorité | Status | File |
|-----------|--------|--------|----------|--------|------|
| `extract_part_mass_material(prt)` | kg, material | NX Open | P1 | ✓ | extract_part_mass_material.py |
| `extract_part_mass(prt)` | kg | NX Open | P1 | ✓ | extract_part_mass_material.py |
| `extract_part_material(prt)` | string | NX Open | P1 | ✓ | extract_part_mass_material.py |
| `extract_mass_from_expression(prt)` | kg | NX Open | P1 | ✓ | extract_mass_from_expression.py |
| `extract_volume()` | mm³ | NX Open | P2 | ❌ | - |
| `extract_surface_area()` | mm² | NX Open | P2 | ❌ | - |
| `extract_center_of_gravity()` | [mm] | NX Open | P2 | ❌ | - |
| `extract_inertia_tensor()` | kg·mm² | NX Open | P3 | ❌ | - |
**NX Open APIs for CAD Extraction**:
- `part.MeasureManager()` - Main entry point for mass properties
- `MeasureManager.NewMassProperties()` - Create mass measurement
- `MasProperties.Mass`, `.CenterOfGravity`, `.MomentsOfInertia`
### 4.5 Extractors Buckling (Priorité 3)
| Extractor | Output | Source | Priorité | Status | File |
|-----------|--------|--------|----------|--------|------|
| `extract_buckling_factor(mode)` | - | F06 | P3 | ❌ | - |
| `extract_critical_load()` | N | F06 | P3 | ❌ | - |
### 4.6 Extractors Zernike (Spécialisé Optique) ✓
| Extractor | Output | Source | Priorité | Status | File |
|-----------|--------|--------|----------|--------|------|
| `ZernikeExtractor.extract_subcase()` | coeffs | OP2 | P1 | ✓ | extract_zernike.py |
| `ZernikeExtractor.extract_relative()` | delta_coeffs | OP2 | P1 | ✓ | extract_zernike.py |
| `extract_zernike_from_op2()` | coeffs | OP2 | P1 | ✓ | extract_zernike.py |
| `extract_zernike_filtered_rms()` | RMS(nm) | OP2 | P1 | ✓ | extract_zernike.py |
| `SurfaceZernikeExtractor.extract_from_op2()` | coeffs | OP2 | P1 | ✓ | extract_zernike_surface.py |
**Usage**: Mirror/lens deformation optimization using Zernike polynomial decomposition
---
## 5. Manipulateurs Avancés
### 5.1 Manipulateurs de Forme (Shape Optimization)
```
optimization_engine/
└── manipulators/
├── morpher.py # Morphing mesh/géométrie
├── ffd.py # Free-Form Deformation
└── surface_offset.py # Offset surfaces
```
| Manipulator | Description | Priorité |
|-------------|-------------|----------|
| `morph_nodes(nodes, displacements)` | Morphing direct | P3 |
| `ffd_box(control_points)` | Déformation FFD | P3 |
| `offset_faces(faces, distance)` | Offset paramétrique | P2 |
### 5.2 Manipulateurs Topologiques (Future)
| Manipulator | Description | Priorité |
|-------------|-------------|----------|
| `apply_density_filter(elements)` | SIMP filtering | P4 |
| `extract_iso_surface(density)` | Topology to geometry | P4 |
| `create_lattice_infill(region)` | Lattice génération | P4 |
---
## 6. Plan d'Implémentation 80/20
### Phase 1: Fondations ✓ COMPLETED
**Objectif**: Stabiliser le workflow de base
| # | Tâche | Fichier | Status |
|---|-------|---------|--------|
| 1.1 | Expression manipulation via .exp file | `nx_updater.py` | ✓ |
| 1.2 | Mass extraction from BDF | `bdf_mass_extractor.py` | ✓ |
| 1.3 | Mass extraction from NX Open | `extract_part_mass_material.py` | ✓ |
| 1.4 | Displacement extraction | `extract_displacement.py` | ✓ |
| 1.5 | Von Mises stress extraction | `extract_von_mises_stress.py` | ✓ |
| 1.6 | Frequency extraction | `extract_frequency.py` | ✓ |
### Phase 1b: NX Open Hooks ✓ COMPLETED (2025-12-06)
**Objectif**: Create direct NX Open Python hooks for CAD/FEM operations
**Location**: `optimization_engine/hooks/nx_cad/`
| # | Tâche | API (verified via MCP) | Status | File |
|---|-------|------------------------|--------|------|
| 1b.1 | Hook: `open_part` / `close_part` / `save_part` | `Session.Parts.OpenBase()`, `Part.Close()`, `Part.Save()` | ✓ | part_manager.py |
| 1b.2 | Hook: `get_expression` / `set_expression` / `set_expressions` | `part.Expressions`, `Expressions.Edit()` | ✓ | expression_manager.py |
| 1b.3 | Hook: `update_model` (integrated) | `Session.UpdateManager.DoUpdate()` | ✓ | expression_manager.py |
| 1b.4 | Hook: `get_mass_properties` / `get_bodies` / `get_volume` | `MeasureManager.NewMassProperties()` | ✓ | geometry_query.py |
| 1b.5 | Hook: `suppress_feature` / `unsuppress_feature` | `Feature.Suppress()`, `Feature.Unsuppress()` | ✓ | feature_manager.py |
| 1b.6 | Hook: `save_part_as` (export) | `Part.SaveAs()` | ✓ | part_manager.py |
### Phase 2: Workflow Complet ✓ COMPLETED
**Objectif**: Automatiser le cycle CAD → FEM → Results
| # | Tâche | API / Fichier | Status |
|---|-------|---------------|--------|
| 2.1 | BDF export via NX Open | `solver_manager.export_bdf()` | ✓ |
| 2.2 | Batch solver launch | `subprocess` + NX run_solver | ✓ (external) |
| 2.3 | Principal stress extraction | `extract_principal_stress()` | ✓ |
| 2.4 | Strain energy extraction | `extract_strain_energy()` | ✓ |
| 2.5 | Reaction force extraction | `extract_spc_forces()` | ✓ |
| 2.6 | **Model Introspection** | `model_introspection.py` | ✓ |
**Files Created (2025-12-06):**
- `optimization_engine/hooks/nx_cae/solver_manager.py` - BDF export & solve hooks
- `optimization_engine/extractors/extract_principal_stress.py` - Principal stress (σ1, σ2, σ3)
- `optimization_engine/extractors/extract_strain_energy.py` - Element strain energy
- `optimization_engine/extractors/extract_spc_forces.py` - Reaction forces at BCs
- `optimization_engine/hooks/nx_cad/model_introspection.py` - **Comprehensive model introspection**
**Phase 2 Introspection Feature (2025-12-06):**
The model introspection module provides comprehensive extraction of:
- **Part (.prt)**: Expressions, bodies, mass properties, features, materials
- **Simulation (.sim)**: Solutions, boundary conditions, loads, materials, mesh info, output requests
- **Results (.op2)**: Available results (displacement, stress, strain, SPC forces, frequencies), subcases
Usage:
```python
from optimization_engine.hooks.nx_cad.model_introspection import (
introspect_part,
introspect_simulation,
introspect_op2,
introspect_study
)
# Introspect entire study
study_info = introspect_study("studies/my_study/")
```
### Phase 3: Multi-Physique ✓ COMPLETED (Core Extractors)
**Objectif**: Support thermique et dynamique
**Priority**: P1 (High) - Extends optimization to thermal/dynamic domains
| # | Tâche | API / Fichier | Status | Priority |
|---|-------|---------------|--------|----------|
| 3.1 | Temperature extraction | `extract_temperature.py` | ✓ | P1 |
| 3.2 | Thermal gradient extraction | `extract_temperature_gradient()` | ✓ | P1 |
| 3.3 | Thermal stress extraction | OP2 + thermal subcase | ✓ (via E3) | P1 |
| 3.4 | Modal mass extraction | `extract_modal_mass.py` | ✓ | P1 |
| 3.5 | Heat flux extraction | `extract_heat_flux()` | ✓ | P2 |
| 3.6 | Thermal BC setup hook | `NXOpen.CAE.LoadCollection` | ❌ | P2 |
| 3.7 | Thermo-mechanical coupling | Multi-step solve | ❌ | P3 |
**Files Created (2025-12-06):**
- `optimization_engine/extractors/extract_temperature.py` - Temperature, gradient, heat flux (E15-E17)
- `optimization_engine/extractors/extract_modal_mass.py` - Modal effective mass from F06 (E18)
- `optimization_engine/extractors/test_phase3_extractors.py` - Phase 3 test suite
**Phase 3 Implementation Guide:**
#### 3.1 Temperature Extraction
```python
# Target API (pyNastran)
from pyNastran.op2.op2 import read_op2
op2 = read_op2(op2_file)
temperatures = op2.temperatures # TEMP subcase results
def extract_temperature(op2_file, subcase=1, nodes=None):
"""Extract nodal temperatures from thermal analysis.
Returns:
dict: {
'max_temperature': float (°C or K),
'min_temperature': float,
'avg_temperature': float,
'temperatures': {node_id: temp, ...}
}
"""
```
#### 3.2 Thermal Gradient Extraction
```python
def extract_thermal_gradient(op2_file, subcase=1):
"""Extract temperature gradients from thermal analysis.
Returns:
dict: {
'max_gradient': float (K/mm),
'avg_gradient': float,
'gradient_location': int (element_id)
}
"""
```
#### 3.3 Thermal Stress Extraction
```python
def extract_thermal_stress(op2_file, subcase=1, element_type='ctetra'):
"""Extract stress from thermal-mechanical analysis.
Notes:
- Requires coupled thermal-structural solution
- Uses temperature field as load
Returns:
dict: Similar to extract_solid_stress but from thermal loading
"""
```
#### 3.4 Modal Mass Extraction
```python
def extract_modal_mass(f06_file, mode_number=1):
"""Extract modal effective mass from F06 file.
Returns:
dict: {
'modal_mass_x': float (kg),
'modal_mass_y': float,
'modal_mass_z': float,
'participation_factor': float
}
"""
```
**Expected Outputs After Phase 3:**
- New extractors: `extract_temperature.py`, `extract_thermal_gradient.py`, `extract_modal_mass.py`
- Updated protocol SYS_12: Add E15-E18 for thermal extractors
- New study templates: Thermal optimization, thermo-mechanical optimization
### Phase 4: AtomizerField Integration (from Master Plan)
**Objectif**: Neural network surrogate for field prediction
| # | Tâche | Description | Status |
|---|-------|-------------|--------|
| 4.1 | Mesh Graph Builder | GNN graph from FEM mesh | ❌ |
| 4.2 | Training Data Exporter | Mesh + BC + results package | ❌ |
| 4.3 | Field Mapper | GNN predictions → NX format | ❌ |
| 4.4 | Sample Validation | Check convergence/quality | ❌ |
### Phase 5: Surrogates & Advanced
**Objectif**: Kriging, topology, lattice
| # | Tâche | Status |
|---|-------|--------|
| 5.1 | Gaussian Process / Kriging surrogate | ❌ |
| 5.2 | SOL 200 interface (native topo) | ❌ |
| 5.3 | Lattice infill generation | ❌ |
| 5.4 | FFD morphing | ❌ |
---
## 7. Classes NX Open Clés (Verified via MCP)
### Session & Part Access
```python
import NXOpen
# Session singleton
session = NXOpen.Session.GetSession()
# Part access
work_part = session.Parts.Work # Current work part (Part object)
display_part = session.Parts.Display # Display part
all_parts = session.Parts # PartCollection
# Key Part methods (from a02434.html):
expressions = work_part.Expressions # ExpressionCollection
bodies = work_part.Bodies() # BodyCollection
features = work_part.Features() # FeatureCollection
measure_mgr = work_part.MeasureManager() # For mass properties
material_mgr = work_part.MaterialManager() # Material assignment
```
### Expression Manipulation
```python
# Find expression by name
expr = work_part.Expressions.FindObject("width")
# Get value
value = expr.Value # float
units = expr.Units # Unit object
# Set value (with units)
unit = work_part.UnitCollection.FindObject("MilliMeter")
work_part.Expressions.EditWithUnits(expr, unit, "50.0")
# Import from .exp file (batch update - robust method)
work_part.Expressions.ImportFromFile(
exp_path,
NXOpen.ExpressionCollection.ExportMode.Replace
)
# Update model after changes
session.UpdateManager.DoUpdate(session.SetUndoMark(...))
```
### Mass Properties
```python
# Create mass measurement
mass_props = work_part.MeasureManager().NewMassProperties(
accuracy, # int: 0.97-0.99 typical
infoUnits, # MassPropertiesInfo for units
bodies # Array of Body objects
)
# Get properties
mass = mass_props.Mass # float (kg)
cog = mass_props.CenterOfGravity # Point3d (x,y,z)
inertia = mass_props.MomentsOfInertia # Matrix3x3
volume = mass_props.Volume # float (mm³)
area = mass_props.SurfaceArea # float (mm²)
```
### CAE/FEM Access
```python
from NXOpen.CAE import CaeSession
# CAE session utilities (from a10510.html)
cae_session = session.CaeSession() # Returns CaeSession
# Key CaeSession methods:
material_utils = cae_session.MaterialUtils() # MaterialUtilities
association_utils = cae_session.AssociationUtils() # AssociationUtilities
mesh_mapping = cae_session.MeshMappingUtils() # MeshMapping.Utils
penetration_mgr = cae_session.PenetrationCheckManager() # PenetrationCheck.Manager
# FEM/SIM parts
fem_part = work_part # When .fem is work part
sim_part = work_part # When .sim is work part
# Access mesh (from FemPart)
mesh_manager = fem_part.MeshManager
for mesh in mesh_manager.GetMeshes():
nodes = mesh.GetNodes()
elements = mesh.GetElements()
# Access solutions (from SimPart)
sim_simulation = sim_part.FindObject("Simulation")
for solution in sim_simulation.Solutions:
name = solution.Name
sol_type = solution.SolutionType
solution.Solve() # Run solver
```
### Feature Manipulation
```python
# Get feature by name
feature = work_part.Features.FindObject("FEATURE_NAME")
# Suppress/unsuppress
feature.Suppress()
feature.Unsuppress()
# Get expression-linked features
for expr in feature.GetExpressions():
print(expr.Name, expr.Value)
```
---
## 8. Structure de Fichiers Finale
```
optimization_engine/
├── hooks/
│ ├── __init__.py
│ ├── nx_cad/
│ │ ├── __init__.py
│ │ ├── part_manager.py
│ │ ├── expression_manager.py
│ │ ├── feature_manager.py
│ │ ├── geometry_query.py
│ │ └── assembly_manager.py
│ ├── nx_fem/
│ │ ├── __init__.py
│ │ ├── mesh_manager.py
│ │ ├── material_manager.py
│ │ ├── property_manager.py
│ │ ├── boundary_conditions.py
│ │ └── connection_manager.py
│ └── nx_sim/
│ ├── __init__.py
│ ├── solution_manager.py
│ ├── solve_manager.py
│ └── result_manager.py
├── extractors/
│ ├── __init__.py
│ ├── displacement.py # ✓
│ ├── stress.py # À améliorer
│ ├── strain.py # Nouveau
│ ├── frequency.py # ✓
│ ├── modal_mass.py # Nouveau
│ ├── temperature.py # Nouveau
│ ├── reaction_force.py # Nouveau
│ ├── cad_mass.py # Nouveau (NX Open)
│ ├── cad_volume.py # Nouveau
│ └── zernike/ # ✓
└── manipulators/
├── __init__.py
├── morpher.py # Future
└── ffd.py # Future
```
---
## 9. Métriques de Succès
### Phase 1 Complete When: ✓ ACHIEVED
- [x] Peut ouvrir/fermer pièce NX via Python ✓ (part_manager.py)
- [x] Peut modifier expressions et update ✓ (expression_manager.py)
- [x] Peut extraire masse depuis CAD (pas BDF) ✓ (geometry_query.py)
- [x] Extrait stress max fiable de tous les éléments ✓ (extract_von_mises_stress.py)
### Phase 2 Complete When: ✓ ACHIEVED (2025-12-06)
- [x] Workflow complet: expression → BDF → solve → extract ✓
- [x] Support de toutes les contraintes mécaniques ✓ (principal stress, SPC forces)
- [x] Extraction de strain energy fonctionnelle ✓ (extract_strain_energy.py)
- [x] **Model Introspection**: Full model analysis capability ✓ (model_introspection.py)
### Phase 3 Complete When: ✓ CORE ACHIEVED (2025-12-06)
- [x] Temperature extraction from OP2 functional ✓ (extract_temperature.py)
- [x] Thermal gradient extraction functional ✓ (extract_temperature_gradient)
- [x] Heat flux extraction functional ✓ (extract_heat_flux)
- [x] Modal mass extraction from F06 functional ✓ (extract_modal_mass.py)
- [ ] At least one thermal optimization study runs successfully
- [ ] Thermo-mechanical coupling documented
- [ ] Thermal BC setup hook (NXOpen.CAE)
---
## 10. Références
### Documentation NX Open (via MCP)
**MCP Tools for NX Open Documentation**:
```
mcp__siemens-docs__nxopen_get_class(className) # Get class doc
mcp__siemens-docs__nxopen_get_index(indexType) # Browse class index
mcp__siemens-docs__nxopen_fetch_page(pagePath) # Fetch any page
mcp__siemens-docs__siemens_docs_list() # List available resources
```
**Key Page IDs**:
| Class | Page ID | URL Path |
|-------|---------|----------|
| Session | a03318.html | `/nxopen_python_ref/a03318.html` |
| Part | a02434.html | `/nxopen_python_ref/a02434.html` |
| BasePart | a00266.html | `/nxopen_python_ref/a00266.html` |
| CaeSession | a10510.html | `/nxopen_python_ref/a10510.html` |
| Class Index | classes.html | `/nxopen_python_ref/classes.html` |
| Function Index | functions_*.html | `/nxopen_python_ref/functions_m.html` (etc.) |
### Ressources Externes
- [NXJournaling.com](https://nxjournaling.com/) - NX Open examples and tutorials
- [NXOpen TSE](https://nxopentsedocumentation.thescriptingengineer.com/) - The Scripting Engineer docs
- [PyNastran Documentation](https://pynastran-git.readthedocs.io/) - OP2/BDF parsing
- [NAFEMS Python FEA Course](https://www.nafems.org/training/e-learning/python-for-fea-automation-and-optimization/)
### Papers & Academic
- Kriging for FEA Optimization: [Springer](https://link.springer.com/article/10.1007/s00158-019-02211-z)
- OpenMDAO Framework: [NASA Technical Report](https://openmdao.org/)
- SIMP Topology Optimization: Bendsøe & Sigmund methods
### Related Atomizer Documentation
- [ATOMIZER_NXOPEN_MASTER_PLAN.md](../07_DEVELOPMENT/ATOMIZER_NXOPEN_MASTER_PLAN.md) - Detailed API specs
- [SYS_12_EXTRACTOR_LIBRARY.md](../protocols/system/SYS_12_EXTRACTOR_LIBRARY.md) - Extractor catalog
- [MCP Server README](../../mcp-server/README.md) - Siemens docs proxy setup
---
## 11. Version History
| Version | Date | Changes |
|---------|------|---------|
| 1.0 | 2025-12-06 | Initial roadmap from industry research |
| 2.0 | 2025-12-06 | Merged with ATOMIZER_NXOPEN_MASTER_PLAN.md, added verified MCP API mappings, updated extractor status |
| 2.1 | 2025-12-06 | **Phase 1b Complete**: NX Open hooks implemented (part_manager, expression_manager, geometry_query, feature_manager) |
| 2.2 | 2025-12-06 | **Phase 2 Complete**: Principal stress, strain energy, SPC forces extractors + solver_manager |
| 2.3 | 2025-12-06 | **Model Introspection**: Added comprehensive model_introspection.py for full part/sim/op2 analysis |
| 2.4 | 2025-12-06 | **Phase 3 Prepared**: Detailed roadmap for thermal/dynamic extractors with implementation guide |
| 2.5 | 2025-12-06 | **Phase 3 Core Complete**: Temperature (E15-E17) and modal mass (E18) extractors implemented |
---
*Generated with assistance from Claude Code using MCP Siemens Documentation tools*