Files
Atomizer/hq/workspaces/nx-expert/MODEL_INTROSPECTION_RESEARCH.md
Antoine 3289a76e19 feat: add Atomizer HQ multi-agent cluster infrastructure
- 8-agent OpenClaw cluster (Manager, Tech-Lead, Secretary, Auditor,
  Optimizer, Study-Builder, NX-Expert, Webster)
- Orchestration engine: orchestrate.py (sync delegation + handoffs)
- Workflow engine: YAML-defined multi-step pipelines
- Agent workspaces: SOUL.md, AGENTS.md, MEMORY.md per agent
- Shared skills: delegate, orchestrate, atomizer-protocols
- Capability registry (AGENTS_REGISTRY.json)
- Cluster management: cluster.sh, systemd template
- All secrets replaced with env var references
2026-02-15 21:18:18 +00:00

793 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Model Introspection Research — Full Data Picture for Optimization Setup
**Author:** NX Expert 🖥️
**Date:** 2026-02-14
**For:** Antoine Letarte, Atomizer Engineering Co.
**Purpose:** Comprehensive framework for extracting complete model knowledge before optimization
---
## Executive Summary
This document defines a **master introspection framework** that captures the full data picture of CAD/FEA models before optimization setup. The goal is to give Atomizer HQ complete knowledge of:
- What can be optimized (design variables, constraints)
- What physics governs the problem (BCs, loads, subcases, solver config)
- What the baseline state is (geometry, mesh, materials, results)
- How to extract objectives and constraints (result fields, quality metrics)
**Output Format:** JSON schema (future-proof, efficient)
**Integration Point:** Pre-optimization / Study setup phase
**Extraction Methods:** NXOpen Python API + pyNastran + result file parsing
---
## 1. Current State Analysis
### 1.1 Existing Atomizer Introspection
Atomizer already has three introspection scripts:
| Script | Coverage | Gaps |
|--------|----------|------|
| `introspect_part.py` | Expressions, mass, materials, bodies, features, datums, units | No parametric relationships, no feature dependencies, no sketches |
| `introspect_sim.py` | Solutions, BCs (partial), subcases (exploratory) | Limited BC extraction, no load details, no output requests |
| `discover_model.py` | Intelligent scanning of expressions + solutions | Surface-level only, no deep FEA structure |
**Strengths:**
- Good coverage of geometric parameters (expressions)
- Mass properties extraction working
- Material assignments captured
**Weaknesses:**
- **No mesh quality metrics** (aspect ratio, jacobian, warpage, skew)
- **No BC details** (applied nodes/elements, magnitudes, DOFs constrained)
- **No load details** (force vectors, pressure values, enforced displacements)
- **No solver configuration** (solution sequence, analysis type, convergence settings, output requests)
- **No parametric dependencies** (which expressions drive which features)
- **No sensitivity context** (mass vs stiffness vs frequency targets)
- **No result baseline** (pre-optimization stress/displacement state)
---
## 2. Comprehensive Introspection Framework
### 2.1 Five Introspection Layers
To capture the full data picture, introspection must cover five layers:
```
┌─────────────────────────────────────────────────────────────┐
│ Layer 1: GEOMETRIC PARAMETERS │
│ What can change? Expressions, sketches, features │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Layer 2: FEA MODEL STRUCTURE │
│ Mesh, elements, materials, properties, quality │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Layer 3: SOLVER CONFIGURATION │
│ Solutions, subcases, BCs, loads, analysis types │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Layer 4: DEPENDENCIES & RELATIONSHIPS │
│ Feature tree, expression graph, BC-mesh links │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Layer 5: BASELINE RESULTS & SENSITIVITIES │
│ Pre-opt stress/displacement, mass sensitivities │
└─────────────────────────────────────────────────────────────┘
```
---
## 3. JSON Schema Design
### 3.1 Top-Level Structure
```json
{
"introspection_version": "1.0.0",
"timestamp": "2026-02-14T18:37:00-05:00",
"model_id": "bracket_v2",
"files": {
"geometry": "bracket.prt",
"simulation": "bracket_sim1.sim",
"fem": "bracket_fem1.fem",
"idealized": "bracket_fem1_i.prt"
},
"geometric_parameters": { ... },
"fea_model": { ... },
"solver_configuration": { ... },
"dependencies": { ... },
"baseline_results": { ... },
"optimization_context": { ... }
}
```
### 3.2 Layer 1: Geometric Parameters
```json
"geometric_parameters": {
"expressions": [
{
"name": "thickness",
"value": 3.0,
"units": "mm",
"formula": "3.0",
"type": "scalar",
"category": "user_defined",
"is_constant": false,
"part": "bracket.prt",
"dependencies": ["p47", "p52"], // Internal expressions that reference this
"driven_features": ["Extrude(2)", "Shell(1)"] // Features that use this expression
}
],
"sketches": [
{
"name": "Sketch(1)",
"constraints": [
{
"type": "dimensional",
"driven_by": "width",
"entities": ["Line(1)"]
}
],
"parametric_dimensions": ["width", "height", "fillet_rad"]
}
],
"features": [
{
"name": "Extrude(2)",
"type": "NXOpen.Features.Extrude",
"parameters": {
"distance": "thickness * 2",
"direction": [0, 0, 1]
},
"suppressed": false,
"parent_features": ["Sketch(1)"]
}
],
"mass_properties": {
"mass_kg": 0.234,
"volume_mm3": 85000.0,
"surface_area_mm2": 15000.0,
"center_of_gravity_mm": [12.3, 45.6, 78.9],
"computed_at": "2026-02-14T18:37:00-05:00"
},
"units": {
"length": "Millimeter",
"mass": "Kilogram",
"force": "Newton",
"system": "Metric (mm)"
}
}
```
### 3.3 Layer 2: FEA Model Structure
```json
"fea_model": {
"mesh": {
"total_nodes": 12450,
"total_elements": 8234,
"element_types": {
"CTETRA": 7800,
"CQUAD4": 434
},
"quality_metrics": {
"aspect_ratio": {
"min": 1.02,
"max": 8.34,
"average": 2.45,
"std_dev": 1.23,
"failed_elements": [] // Element IDs exceeding threshold
},
"jacobian": {
"min": 0.62,
"max": 1.0,
"failed_elements": [12, 456, 789]
},
"warpage_degrees": {
"max": 5.2,
"threshold": 10.0,
"failed_elements": []
},
"skew_degrees": {
"max": 45.2,
"threshold": 60.0
}
}
},
"materials": [
{
"name": "Aluminum 6061-T6",
"assigned_to": {
"bodies": ["Body(1)"],
"elements": "all"
},
"properties": {
"density_kg_mm3": 2.7e-6,
"youngs_modulus_MPa": 68900.0,
"poisson_ratio": 0.33,
"yield_strength_MPa": 276.0,
"ultimate_strength_MPa": 310.0,
"thermal_expansion_K": 2.36e-5,
"thermal_conductivity_W_mK": 167.0
},
"nastran_card": "MAT1"
}
],
"properties": [
{
"id": 1,
"name": "Shell_Prop_3mm",
"type": "PSHELL",
"element_type": "CQUAD4",
"thickness_mm": 3.0,
"material_id": 1,
"assigned_elements": [1, 2, 3, "..."]
}
],
"collectors": [
{
"name": "Shell_Mesh",
"type": "2D_mesh",
"element_count": 434,
"property_assignment": "Shell_Prop_3mm"
}
]
}
```
### 3.4 Layer 3: Solver Configuration
```json
"solver_configuration": {
"solutions": [
{
"name": "Solution 1",
"solution_sequence": "SOL 101",
"analysis_type": "Static Linear",
"solver": "NX Nastran",
"subcases": [
{
"id": 1,
"name": "Subcase - Static 1",
"load_set": "LoadSet 1",
"constraint_set": "ConstraintSet 1",
"output_requests": [
{
"type": "DISPLACEMENT",
"format": "OP2",
"all_nodes": true
},
{
"type": "STRESS",
"format": "OP2",
"element_types": ["CTETRA", "CQUAD4"],
"stress_type": "von_mises"
}
]
}
],
"convergence_criteria": {
"displacement_tolerance": 0.001,
"force_tolerance": 0.01,
"max_iterations": 100
},
"output_files": {
"op2": "bracket_sim1_s1.op2",
"f06": "bracket_sim1_s1.f06",
"log": "bracket_sim1_s1.log"
}
}
],
"boundary_conditions": {
"constraints": [
{
"name": "Fixed Constraint 1",
"type": "SPC",
"target": {
"geometry_type": "face",
"geometry_name": "Face(12)",
"node_count": 145,
"node_ids": [1, 2, 3, "..."]
},
"constrained_dofs": [1, 2, 3, 4, 5, 6], // TX, TY, TZ, RX, RY, RZ
"dof_names": ["TX", "TY", "TZ", "RX", "RY", "RZ"]
}
],
"loads": [
{
"name": "Force 1",
"type": "concentrated_force",
"target": {
"geometry_type": "vertex",
"geometry_name": "Vertex(5)",
"node_ids": [456]
},
"magnitude_N": 1000.0,
"direction": [0, -1, 0],
"components": {
"FX": 0.0,
"FY": -1000.0,
"FZ": 0.0
}
},
{
"name": "Pressure 1",
"type": "surface_pressure",
"target": {
"geometry_type": "face",
"geometry_name": "Face(8)",
"element_count": 25,
"element_ids": [100, 101, 102, "..."]
},
"magnitude_MPa": 5.0,
"direction": "normal"
}
]
}
}
```
### 3.5 Layer 4: Dependencies & Relationships
```json
"dependencies": {
"expression_graph": {
"nodes": [
{
"name": "thickness",
"type": "root_parameter"
},
{
"name": "p47",
"type": "derived",
"formula": "thickness * 2"
}
],
"edges": [
{
"from": "thickness",
"to": "p47",
"relationship": "drives"
}
]
},
"feature_tree": {
"root": "Part",
"children": [
{
"name": "Sketch(1)",
"driven_by": ["width", "height"],
"children": [
{
"name": "Extrude(2)",
"driven_by": ["thickness"],
"affects_mass": true,
"affects_mesh": true
}
]
}
]
},
"mesh_geometry_links": {
"Face(12)": {
"mesh_collectors": ["Shell_Mesh"],
"elements": [1, 2, 3, "..."],
"boundary_conditions": ["Fixed Constraint 1"]
}
},
"parameter_sensitivities": {
"thickness": {
"affects": {
"mass": "linear",
"stiffness": "nonlinear",
"frequency": "sqrt"
},
"estimated_impact": "high"
}
}
}
```
### 3.6 Layer 5: Baseline Results & Context
```json
"baseline_results": {
"pre_optimization_run": {
"solution": "Solution 1",
"subcase": 1,
"timestamp": "2026-02-14T17:00:00-05:00",
"converged": true,
"iterations": 12
},
"displacement": {
"max_magnitude_mm": 2.34,
"max_node": 4567,
"max_location": [45.2, 67.8, 12.3],
"average_mm": 0.45
},
"stress": {
"von_mises": {
"max_MPa": 145.6,
"max_element": 2345,
"max_location": [12.1, 34.5, 56.7],
"average_MPa": 45.2,
"margin_of_safety": 0.89 // (Yield - Max) / Max
}
},
"frequency": {
"mode_1_Hz": 123.4,
"mode_2_Hz": 234.5,
"mode_3_Hz": 456.7
}
},
"optimization_context": {
"potential_design_variables": [
{
"name": "thickness",
"current_value": 3.0,
"units": "mm",
"suggested_bounds": [1.5, 6.0],
"rationale": "Drives mass and stiffness directly"
}
],
"potential_objectives": [
{
"type": "minimize",
"metric": "mass",
"current_value": 0.234,
"units": "kg"
},
{
"type": "minimize",
"metric": "max_displacement",
"current_value": 2.34,
"units": "mm"
}
],
"potential_constraints": [
{
"metric": "max_von_mises_stress",
"limit": 200.0,
"units": "MPa",
"rationale": "Safety factor 1.5 on yield"
},
{
"metric": "min_frequency",
"limit": 100.0,
"units": "Hz",
"rationale": "Avoid resonance below 100 Hz"
}
],
"recommended_study_type": "single_objective_mass_min",
"estimated_fea_runtime_seconds": 45
}
```
---
## 4. Extraction Methods — NXOpen & pyNastran Mapping
### 4.1 Geometric Parameters
| Data | NXOpen API | Notes |
|------|------------|-------|
| Expressions | `part.Expressions` | Filter user vs internal (p0, p1, ...) |
| Expression values | `expr.Value` | Current numeric value |
| Expression formulas | `expr.RightHandSide` | String formula |
| Expression units | `expr.Units.Name` | Unit object |
| Feature list | `part.Features` | Iterator over all features |
| Feature parameters | Feature-specific builders | Requires feature type dispatch |
| Sketch constraints | `sketch.Constraints` | Dimensional, geometric, etc. |
| Mass properties | `part.MeasureManager.NewMassProperties()` | Requires body list |
| Body list | `part.Bodies` | Filter solid vs sheet |
| Material assignment | `body.GetPhysicalMaterial()` | Per-body material |
**Key Script:** Enhance `introspect_part.py` with:
- Expression dependency graph (parse RHS formulas)
- Feature-to-expression links (traverse feature parameters)
- Sketch dimension extraction
### 4.2 FEA Model Structure
| Data | NXOpen/pyNastran API | Notes |
|------|----------------------|-------|
| Node count | `femPart.FEModel.FenodeLabelMap.Size` | NXOpen CAE |
| Element count | `femPart.FEModel.FeelementLabelMap.Size` | NXOpen CAE |
| Element types | `pyNastran: bdf.elements` | Parse BDF for CTETRA, CQUAD4, etc. |
| Mesh quality | `QualityAuditBuilder` | NXOpen CAE mesh audit |
| Material properties | `pyNastran: bdf.materials[mat_id]` | Extract MAT1, MAT2 cards |
| Property cards | `pyNastran: bdf.properties[prop_id]` | PSHELL, PSOLID, etc. |
| Mesh collectors | `femPart.FEModel.MeshCollectors` | NXOpen CAE |
**Key Script:** New `introspect_fem.py` using:
- pyNastran BDF reading for full element/material data
- NXOpen QualityAudit for mesh metrics
- Mesh collector iteration
### 4.3 Solver Configuration
| Data | NXOpen/BDF API | Notes |
|------|----------------|-------|
| Solutions | `simPart.Simulation.FindObject("Solution[...]")` | Pattern-based search |
| Solution type | `solution.SolutionType` | SOL 101, 103, etc. |
| Subcases | BDF parsing: `SUBCASE` cards | pyNastran |
| Load sets | BDF parsing: `LOAD` cards | pyNastran |
| Constraint sets | BDF parsing: `SPC` cards | pyNastran |
| Output requests | BDF parsing: `DISPLACEMENT`, `STRESS` | pyNastran |
| BC details | `simPart.Simulation` BC objects | NXOpen (limited) |
| Load magnitudes | BDF parsing: `FORCE`, `PLOAD4` | pyNastran |
**Key Script:** Enhance `introspect_sim.py` + new `introspect_bdf.py`:
- Full BDF parsing for subcases, loads, BCs
- Solution property extraction (convergence, output)
### 4.4 Dependencies & Relationships
| Data | Extraction Method | Notes |
|------|-------------------|-------|
| Expression graph | Parse `expr.RightHandSide` | Regex to find referenced expressions |
| Feature tree | `feature.GetParents()` | NXOpen feature relationships |
| Feature-expression links | Feature parameter inspection | Type-specific (Extrude, Shell, etc.) |
| Mesh-geometry links | `meshCollector.GetElements()` + geometry | NXOpen CAE |
**Key Script:** New `build_dependency_graph.py`:
- Graph structure (nodes = expressions/features, edges = dependencies)
- Export as JSON adjacency list
### 4.5 Baseline Results
| Data | Extraction Method | Notes |
|------|-------------------|-------|
| Displacement | `pyNastran: op2.displacements[subcase]` | OP2 result reading |
| Stress | `pyNastran: op2.stress[subcase]` | Von Mises, principal |
| Frequency | `pyNastran: op2.eigenvalues[subcase]` | Modal analysis |
| Convergence | Parse `.f06` log file | Text parsing |
**Key Script:** Use existing Atomizer extractors:
- `extract_displacement.py`
- `extract_von_mises_stress.py`
- `extract_frequency.py`
---
## 5. Implementation Roadmap
### Phase 1: Enhanced Part Introspection (1-2 days)
**Goal:** Capture full geometric parameter knowledge
**Tasks:**
1. Enhance `introspect_part.py`:
- Add expression dependency parsing (RHS formula analysis)
- Add feature parameter extraction
- Add sketch constraint extraction
- Build parametric relationship graph
**Output:** `part_introspection_v2.json`
### Phase 2: FEM Model Deep Dive (2-3 days)
**Goal:** Full mesh, material, property extraction
**Tasks:**
1. Create `introspect_fem.py`:
- pyNastran BDF parsing for elements, materials, properties
- NXOpen mesh quality audit
- Mesh collector iteration
- Element type distribution
**Output:** `fem_introspection.json`
### Phase 3: Solver Configuration Capture (2-3 days)
**Goal:** Complete BC, load, subcase, solution data
**Tasks:**
1. Enhance `introspect_sim.py`:
- BDF-based subcase extraction
- Load/BC detail parsing (magnitudes, DOFs, targets)
- Output request cataloging
- Solution property extraction
**Output:** `solver_introspection.json`
### Phase 4: Dependency Mapping (2 days)
**Goal:** Build relationship graphs
**Tasks:**
1. Create `build_dependency_graph.py`:
- Expression graph construction
- Feature tree traversal
- Mesh-geometry linking
- Sensitivity estimation (heuristic)
**Output:** `dependency_graph.json`
### Phase 5: Baseline Results Integration (1 day)
**Goal:** Pre-optimization state capture
**Tasks:**
1. Create `extract_baseline_results.py`:
- Run existing Atomizer extractors
- Aggregate into baseline JSON
- Compute margins of safety
**Output:** `baseline_results.json`
### Phase 6: Master Introspection Orchestrator (2 days)
**Goal:** Single command to run all introspection
**Tasks:**
1. Create `run_full_introspection.py`:
- Orchestrate all 5 phases
- Merge JSON outputs into master schema
- Validate schema completeness
- Generate human-readable summary report
**Output:** `model_introspection_FULL.json` + `introspection_summary.md`
**Total Estimate:** 10-13 days for full implementation
---
## 6. Integration with Atomizer HQ
### 6.1 Usage Workflow
```bash
# Pre-optimization introspection
cd /path/to/study/1_setup/model
python /atomizer/nx_journals/run_full_introspection.py bracket.prt bracket_sim1.sim
# Output
# → model_introspection_FULL.json
# → introspection_summary.md
```
### 6.2 Knowledge Base Population
The full introspection JSON feeds Atomizer HQ with:
- **Study Builder:** What design variables are available, suggested bounds
- **Optimizer:** What constraints/objectives make sense, expected runtimes
- **Reporter:** Baseline state for comparison, sensitivity context
- **Manager:** Study complexity assessment, resource allocation
### 6.3 Automated Study Suggestions
With full introspection, Atomizer can:
- **Auto-suggest design variables** based on expression analysis
- **Estimate optimization difficulty** based on parameter count, mesh size
- **Recommend solver sequences** based on analysis type
- **Validate study setup** before expensive FEA runs
---
## 7. Example: Bracket Study Introspection Output
**Input:**
- `bracket.prt` (geometry with expressions: thickness, width, height)
- `bracket_sim1.sim` (static analysis, fixed face, force applied)
- `bracket_fem1.fem` (CTETRA mesh, 8234 elements)
**Introspection Output Highlights:**
```json
{
"model_id": "bracket_v2",
"geometric_parameters": {
"expressions": [
{"name": "thickness", "value": 3.0, "units": "mm", "driven_features": ["Extrude(2)", "Shell(1)"]},
{"name": "width", "value": 50.0, "units": "mm", "driven_features": ["Sketch(1)"]},
{"name": "height", "value": 100.0, "units": "mm", "driven_features": ["Sketch(1)"]}
],
"mass_properties": {"mass_kg": 0.234}
},
"fea_model": {
"mesh": {
"total_elements": 8234,
"element_types": {"CTETRA": 8234},
"quality_metrics": {
"aspect_ratio": {"average": 2.45, "max": 8.34}
}
}
},
"solver_configuration": {
"solutions": [
{
"name": "Solution 1",
"solution_sequence": "SOL 101",
"subcases": [{"id": 1, "name": "Static 1"}]
}
],
"boundary_conditions": {
"constraints": [{"name": "Fixed Constraint 1", "constrained_dofs": ["TX", "TY", "TZ", "RX", "RY", "RZ"]}],
"loads": [{"name": "Force 1", "magnitude_N": 1000.0, "direction": [0, -1, 0]}]
}
},
"optimization_context": {
"potential_design_variables": [
{"name": "thickness", "suggested_bounds": [1.5, 6.0]},
{"name": "width", "suggested_bounds": [30.0, 70.0]},
{"name": "height", "suggested_bounds": [80.0, 120.0]}
],
"potential_objectives": [
{"type": "minimize", "metric": "mass", "current_value": 0.234}
],
"recommended_study_type": "single_objective_mass_min"
}
}
```
**Human-Readable Summary:**
```
INTROSPECTION SUMMARY — bracket_v2
===================================
DESIGN SPACE
- 3 user-defined expressions detected
- Recommended design variables: thickness, width, height
- Suggested bounds: thickness [1.5-6.0] mm, width [30-70] mm, height [80-120] mm
FEA MODEL
- Mesh: 8,234 CTETRA elements, 12,450 nodes
- Quality: Avg aspect ratio 2.45 (acceptable), max 8.34 (borderline)
- Material: Aluminum 6061-T6, E=68.9 GPa, ρ=2.7e-6 kg/mm³
PHYSICS
- Analysis: SOL 101 (Static Linear)
- Boundary conditions: 1 fixed constraint (Face 12), 1 force (1000 N, -Y direction)
- Baseline: Max displacement 2.34 mm, Max stress 145.6 MPa (MoS = 0.89)
OPTIMIZATION CONTEXT
- Recommended study: Minimize mass
- Constraints: Keep max stress < 200 MPa (safety factor 1.5)
- Estimated FEA runtime: ~45 seconds per trial
```
---
## 8. Future Enhancements
### 8.1 Advanced Introspection
- **Topology optimization regions:** Identify design vs non-design space
- **Composite layups:** Ply stack introspection for composite parts
- **Thermal-structural coupling:** Multi-physics BC detection
- **Contact detection:** Identify contact pairs, friction coefficients
- **Dynamic loads:** PSD, time-history, random vibration
### 8.2 AI-Powered Analysis
- **Sensitivity prediction:** ML model to estimate parameter sensitivities without running FEA
- **Design variable clustering:** Auto-group correlated parameters
- **Failure mode prediction:** Identify likely failure locations based on geometry/BCs
### 8.3 Live Introspection
- **NX session monitoring:** Real-time introspection as model is edited
- **Change detection:** Diff between introspection snapshots
- **Validation alerts:** Warn when mesh degrades, BCs become invalid
---
## 9. Conclusion
This master introspection framework transforms Atomizer from a study executor to an intelligent optimization assistant. By capturing the **full data picture**:
1. **Study setup becomes conversational** — "What can I optimize?" gets a real answer
2. **Validation is automatic** — Catch invalid BCs, bad mesh, missing materials before FEA runs
3. **Knowledge accumulates** — Every introspection feeds the Atomizer HQ knowledge base
4. **Optimization is smarter** — Suggested variables, bounds, objectives based on model analysis
**Next Steps:**
1. Review this plan with Antoine
2. Prioritize phases (likely start with Phase 1-2)
3. Implement enhanced `introspect_part.py` + new `introspect_fem.py`
4. Test on existing Atomizer studies (M1 mirror, bracket, beam)
5. Iterate schema based on real-world usage
---
**Status:** Research complete — awaiting approval to proceed with implementation.
**Contact:** NX Expert 🖥️ | #nx-cad