- 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
24 KiB
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
{
"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
"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
"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
"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
"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
"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.pyextract_von_mises_stress.pyextract_frequency.py
5. Implementation Roadmap
Phase 1: Enhanced Part Introspection (1-2 days)
Goal: Capture full geometric parameter knowledge
Tasks:
- 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:
- 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:
- 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:
- 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:
- 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:
- 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
# 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:
{
"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:
- Study setup becomes conversational — "What can I optimize?" gets a real answer
- Validation is automatic — Catch invalid BCs, bad mesh, missing materials before FEA runs
- Knowledge accumulates — Every introspection feeds the Atomizer HQ knowledge base
- Optimization is smarter — Suggested variables, bounds, objectives based on model analysis
Next Steps:
- Review this plan with Antoine
- Prioritize phases (likely start with Phase 1-2)
- Implement enhanced
introspect_part.py+ newintrospect_fem.py - Test on existing Atomizer studies (M1 mirror, bracket, beam)
- Iterate schema based on real-world usage
Status: Research complete — awaiting approval to proceed with implementation.
Contact: NX Expert 🖥️ | #nx-cad