feat: add adaptive isogrid tool — project foundations
- Python Brain: density field, constrained Delaunay triangulation, pocket profiles, profile assembly, validation modules - NX Hands: skeleton scripts for geometry extraction, AFEM setup, per-iteration solve (require NX environment to develop) - Atomizer integration: 15-param space definition, objective function - Technical spec, README, sample test geometry, requirements.txt - Architecture: Python Brain + NX Hands + Atomizer Manager
This commit is contained in:
6
tools/adaptive-isogrid/src/nx/__init__.py
Normal file
6
tools/adaptive-isogrid/src/nx/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
"""
|
||||
Adaptive Isogrid — NX Hands
|
||||
|
||||
NXOpen journal scripts for geometry extraction, AFEM setup, and per-iteration solve.
|
||||
These scripts run inside NX Simcenter via the NXOpen Python API.
|
||||
"""
|
||||
28
tools/adaptive-isogrid/src/nx/build_interface_model.py
Normal file
28
tools/adaptive-isogrid/src/nx/build_interface_model.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
NXOpen script — Build Interface Model (Model A) for Assembly FEM.
|
||||
|
||||
ONE-TIME: Creates spider elements (RBE2/RBE3) at each hole + edge BC nodes.
|
||||
Exports interface_nodes.json for the iteration script.
|
||||
|
||||
NOTE: Skeleton — requires NX environment for development.
|
||||
See docs/technical-spec.md Section 4.2 for full pseudocode.
|
||||
"""
|
||||
|
||||
|
||||
def build_interface_model(geometry_json_path, fem_part):
|
||||
"""
|
||||
Build Model A: spider elements at each hole + edge BC nodes.
|
||||
|
||||
For each hole:
|
||||
- Center node (master)
|
||||
- N circumference nodes (~1 per 2mm of circumference)
|
||||
- RBE2 (rigid) or RBE3 (distributing) spider
|
||||
|
||||
For plate boundary:
|
||||
- Edge nodes at ~3mm spacing
|
||||
|
||||
Exports interface_nodes.json with all node IDs and coordinates.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"Develop inside NX Simcenter. See docs/technical-spec.md Section 4.2."
|
||||
)
|
||||
54
tools/adaptive-isogrid/src/nx/extract_geometry.py
Normal file
54
tools/adaptive-isogrid/src/nx/extract_geometry.py
Normal file
@@ -0,0 +1,54 @@
|
||||
"""
|
||||
NXOpen script — Extract plate geometry from selected face.
|
||||
|
||||
ONE-TIME: Run inside NX. User selects plate face, assigns hole weights.
|
||||
Exports geometry.json for the Python brain.
|
||||
|
||||
NOTE: This is pseudocode / skeleton. Actual NXOpen API calls need
|
||||
NX environment to develop and test.
|
||||
"""
|
||||
|
||||
# This script runs inside NX — NXOpen is available at runtime
|
||||
# import NXOpen
|
||||
# import json
|
||||
# import math
|
||||
|
||||
|
||||
def extract_plate_geometry(face, hole_weights):
|
||||
"""
|
||||
Extract plate geometry from an NX face.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
face : NXOpen.Face
|
||||
The selected plate face.
|
||||
hole_weights : dict
|
||||
{loop_index: weight} from user input.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict : geometry definition for export.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"This script must be developed and tested inside NX Simcenter. "
|
||||
"See docs/technical-spec.md Section 2 for full pseudocode."
|
||||
)
|
||||
|
||||
|
||||
def sample_edge(edge, tolerance=0.1):
|
||||
"""Sample edge curve as polyline with given chord tolerance."""
|
||||
# NXOpen: edge.GetCurve(), evaluate at intervals
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def fit_circle(points):
|
||||
"""Fit a circle to boundary points. Returns (center, diameter)."""
|
||||
# Least-squares circle fit
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def export_geometry(geometry, filepath='geometry.json'):
|
||||
"""Export geometry dict to JSON."""
|
||||
import json
|
||||
with open(filepath, 'w') as f:
|
||||
json.dump(geometry, f, indent=2)
|
||||
35
tools/adaptive-isogrid/src/nx/iteration_solve.py
Normal file
35
tools/adaptive-isogrid/src/nx/iteration_solve.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
NXOpen script — Per-iteration Model B rebuild + solve + extract.
|
||||
|
||||
LOOP: Called by Atomizer for each trial.
|
||||
1. Delete old Model B geometry + mesh
|
||||
2. Import new 2D ribbed profile from rib_profile.json
|
||||
3. Mesh with hard-point seeds at interface node locations
|
||||
4. Merge nodes in Assembly FEM
|
||||
5. Solve (Nastran)
|
||||
6. Extract results → results.json
|
||||
|
||||
NOTE: Skeleton — requires NX environment for development.
|
||||
See docs/technical-spec.md Section 4.3 for full pseudocode.
|
||||
"""
|
||||
|
||||
|
||||
def iteration_solve(profile_path, interface_nodes_path, afem_part):
|
||||
"""
|
||||
Single optimization iteration.
|
||||
|
||||
Returns dict with status, mass, stress/displacement fields.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"Develop inside NX Simcenter. See docs/technical-spec.md Section 4.3."
|
||||
)
|
||||
|
||||
|
||||
def extract_results(afem, solution):
|
||||
"""
|
||||
Extract field results from solved assembly FEM.
|
||||
Only from Model B elements (plate mesh), ignoring spiders.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"Develop inside NX Simcenter. See docs/technical-spec.md Section 4.3."
|
||||
)
|
||||
Reference in New Issue
Block a user