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

24 KiB
Raw Permalink Blame History

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.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

# 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:

  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