Files
Atomizer/projects/isogrid-dev-plate/BREAKDOWN.md
2026-02-20 08:00:17 +00:00

228 lines
10 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.
# Technical Breakdown — Adaptive Isogrid Plate Lightweighting
**Project:** Isogrid Dev Plate
**Author:** Technical Lead 🔧
**Date:** 2026-02-18
**Status:** Architecture complete — Campaign 01 ready to run
---
## 1. Problem Formulation
### 1.1 Structural Configuration
Flat plate with bolt holes, optimized by replacing solid material with an adaptive triangular isogrid.
- 2 sandbox regions (sandbox_1, sandbox_2) — where ribs are generated and changed each iteration
- Bolt holes: excluded from pocket generation (keepout zone around each hole)
- Plate material: AL7075-T6 (confirmed 2026-02-18 — see material discrepancy note in §4.2)
- 3D solid FEA already run (CHEXA/CTETRA, SOL 101)
### 1.2 Objective Function
**Single-objective: minimize total plate mass.**
```
minimize: mass(params)
subject to: max_von_mises ≤ σ_allow = 100.6 MPa
```
> **No displacement constraint** — confirmed by Antoine 2026-02-18.
The penalty approach:
```python
penalty = 0.0
if max_stress > sigma_allow:
penalty += 1e4 * ((max_stress / sigma_allow) - 1.0) ** 2
return mass_kg + penalty
```
---
## 2. Design Variable Classification
### 2.1 Optimized Variables (8) — Atomizer design space
These directly control rib pattern shape and density. Every trial samples all 8.
| Variable | Range | Description |
|----------|-------|-------------|
| `eta_0` | [0.0, 0.4] | Baseline density offset — global rib density floor |
| `alpha` | [0.3, 2.0] | Hole influence scale — how much ribs cluster around holes |
| `beta` | [0.0, 1.0] | Edge influence scale — how much ribs reinforce the perimeter |
| `gamma_stress` | [0.0, 1.5] | Stress feedback gain — how much FEA stress adds density |
| `R_0` | [10, 100] mm | Base influence radius — how far hole influence spreads |
| `R_edge` | [5, 40] mm | Edge influence radius — depth of perimeter reinforcement band |
| `s_min` | [15, 35] mm | Minimum triangle edge length → densest zone spacing (manufacturing floor: 15 mm) |
| `s_max` | [40, 60] mm | Maximum triangle edge length → sparsest zone spacing (lower bound 40 guarantees s_min < s_max) |
**Total: 8 continuous variables.** Manageable for Optuna TPE; expect useful signal in 50100 trials, convergence in 200500.
### 2.2 Manufacturing Constraints (Fixed) — NOT optimized
These are set from machining requirements and are fixed for the entire campaign.
They can be adjusted between campaigns if the process changes.
| Parameter | Fixed Value | Why Fixed | Manufacturing Basis |
|-----------|------------|-----------|---------------------|
| `t_min` | 2.5 mm | Minimum rib thickness: thinner ribs are not machinable and would break | CNC milling minimum land width |
| `t_0` | 3.5 mm | Nominal rib thickness: baseline starting width before density scaling | Design intent |
| `w_frame` | 5.0 mm | Perimeter frame width: solid band around the sandbox boundary | Edge seal, clamping, aesthetics |
| `r_f` | 1.5 mm | Pocket fillet radius: corner radius on each pocket. **Sole pocket size filter.** | = tool radius. Smaller → need smaller endmill |
| `d_keep` | 1.2× | Hole keepout multiplier: minimum clear distance = 1.2 × hole diameter | Prevents thin walls around bolt holes |
| `min_triangle_area` | 25.0 mm² | Minimum pocketable triangle area | Below this: too small to machine → skip as solid |
> To change manufacturing constraints for a campaign, edit `MANUFACTURING_CONSTRAINTS` in
> `optimization_engine/isogrid/study.py` and document the change here.
### 2.3 Math/Model Constants (Fixed) — NOT optimized
These govern the mathematical form of the density field. Fixed at well-behaved defaults.
Changing them would fundamentally change the shape of the density function.
| Parameter | Fixed Value | Description |
|-----------|------------|-------------|
| `p` | 2.0 | Gaussian decay exponent (p=2 → smooth Gaussian, p=1 → exponential, p=4 → box-like) |
| `kappa` | 1.0 | Weight-to-radius coupling: heavier holes get proportionally larger influence radius |
| `gamma` | 1.0 | Density-to-thickness coupling: t(x) = t₀ × (1 + γ·η) |
> Note: `gamma` here is the rib-thickness coupling, distinct from `gamma_stress` (stress feedback gain).
---
## 3. Density Field Formulation
The full adaptive formula with stress feedback:
```
η(x,y) = clamp(0, 1, η₀ + α·I(x) + β·E(x) + γ_stress·S_stress(x))
```
Where:
- `I(x) = Σᵢ wᵢ · exp(-(dᵢ/Rᵢ)^p)` — hole influence (sum over all bolt holes)
- `E(x) = exp(-(d_edge/R_edge)^p)` — edge reinforcement
- `S_stress(x)` — normalized FEA stress field from previous trial, ∈ [0..1]
- `Rᵢ = R₀ · (1 + κ · wᵢ)` — per-hole radius scales with hole weight
Local spacing: `s(x) = s_max - (s_max - s_min) · η(x)`
Local rib thickness: `t(x) = clip(t₀ · (1 + γ · η(x)), t_min, t_max)`
---
## 4. FEA Pipeline Status
### 4.1 What Is Done
| Step | Status | Notes |
|------|--------|-------|
| NX geometry extraction (`extract_sandbox.py`) | ✅ Done | geometry_sandbox_1.json, geometry_sandbox_2.json |
| Python Brain (density → profile) | ✅ Done | Gmsh Frontal-Delaunay, Shapely pockets |
| NX rib import (`import_profile.py`) | ✅ Done | Update-in-place, preserves extrude reference |
| 3D solid FEA (manual baseline) | ✅ Done | OP2 results available |
| Stress field extraction (OP2 → 2D) | ✅ Done | `optimization_engine/extractors/extract_stress_field_2d.py` |
| Stress feedback field | ✅ Done | `optimization_engine/isogrid/stress_feedback.py` |
| Atomizer study wiring | ✅ Done | `studies/01_v1_tpe/run_optimization.py` |
| Campaign 01 execution | 🔴 Not started | Run `run_optimization.py` |
### 4.2 FEA Configuration
- **Solver:** NX Nastran, SOL 101 (linear static)
- **Elements:** 3D solid (CHEXA, CTETRA, CPENTA)
- **Stress units:** NX kg-mm-s outputs kPa → extractor divides by 1000 → MPa
- **Material (optimization):** AL7075-T6 — σ_yield = 503 MPa, ρ = 2810 kg/m³, SF = 5 → σ_allow = 100.6 MPa
- **Sandbox regions:** 2 (sandbox_1 is larger, sandbox_2 is smaller patch)
> ⚠️ **Material discrepancy (Gap G-01):** The NX FEM model (MAT1 card in the DAT file) uses
> E = 68.98 GPa and ρ = 2.711×10⁻⁶ kg/mm³, which correspond to **AL6061-T6** properties.
> Optimization allowables and mass targets are based on **AL7075-T6** as confirmed by Antoine.
> This discrepancy means FEA stiffness/mass are slightly underestimated.
> Tracked as G-01 in CONTEXT.md — update MAT1 card before next FEA campaign.
### 4.3 Key FEA Files
**NX model (reference copies — do NOT modify):**
```
projects/isogrid-dev-plate/models/
├── ACS_Stack_Main_Plate_Iso_Project.prt ← Geometry part
├── ACS_Stack_Main_Plate_Iso_project_fem2_i.prt ← Idealized part (CRITICAL for mesh update)
├── ACS_Stack_Main_Plate_Iso_project_fem2.fem ← FEM (3D solid, CHEXA/CTETRA)
├── ACS_Stack_Main_Plate_Iso_project_sim2.sim ← SOL 101 simulation
└── acs_stack_main_plate_iso_project_sim2-solution_1.op2 ← Baseline FEA results
```
**Working copies (used by optimizer):**
```
studies/01_v1_tpe/1_setup/model/
├── ACS_Stack_Main_Plate_Iso_Project.prt
├── ACS_Stack_Main_Plate_Iso_project_fem2_i.prt
├── ACS_Stack_Main_Plate_Iso_project_fem2.fem
├── ACS_Stack_Main_Plate_Iso_project_sim2.sim
└── adaptive_isogrid_data/
├── geometry_sandbox_1.json ← Sandbox boundary + holes
└── geometry_sandbox_2.json
```
**Python Brain (canonical location):**
```
optimization_engine/isogrid/
├── density_field.py ← η(x) field computation
├── triangulation.py ← Gmsh Frontal-Delaunay mesh
├── pocket_profiles.py ← Inset + fillet pockets
├── stress_feedback.py ← StressFeedbackField (RBF interpolator)
└── study.py ← PARAM_SPACE, MANUFACTURING_CONSTRAINTS, MATERIAL
optimization_engine/extractors/
└── extract_stress_field_2d.py ← OP2+BDF → 2D stress field
```
---
## 5. Rib Pattern Variants Tested
Three density field configurations were tested for visual review in NX:
| Variant | α | β | Pockets (S1+S2) | Mass Est. | Character |
|---------|---|---|----------------|-----------|-----------|
| Balanced | 1.0 | 0.3 | 86 + 33 = 119 | ~2,790g | Good general pattern |
| Edge-focused | 0.3 | 1.5 | 167 + 10 = 177 | ~2,328g | Dense perimeter, sparse center |
| Hole-focused | 1.8 | 0.15 | 62 + 37 = 99 | ~3,025g | Dense around holes, thin edges |
All three were imported to NX using the update-in-place workflow (sketch preserved, extrude reference maintained).
---
## 6. Algorithm Recommendation
**Optuna TPE (Tree-structured Parzen Estimator)** — standard Atomizer configuration.
| Property | Value |
|----------|-------|
| Design variables | 8 continuous |
| Objective | 1 (minimize mass) |
| Constraint | 1 (stress — penalty-based; no displacement constraint) |
| Trials budget | 200 (Campaign 01) |
| Estimated iteration time | ~90120 sec (NX mesh + Nastran + extract) |
| Total runtime estimate | ~810 hours for 200 trials |
In V1, `gamma_stress` is sampled by TPE but has no effect (no S_prev stress field available).
In V2 (sequential seeding), S_prev is loaded from the globally best previous trial; `gamma_stress`
then actively reshapes the density field toward high-stress zones. No extra FEA per trial.
---
## 7. Next Steps
| Priority | Action | Status |
|----------|--------|--------|
| ✅ DONE | `studies/01_v1_tpe/run_optimization.py` created | — |
| ✅ DONE | Material confirmed: AL7075-T6, σ_allow = 100.6 MPa (SF=5) | — |
| ✅ DONE | Model files copied to `studies/01_v1_tpe/1_setup/model/` | — |
| ✅ DONE | Geometry JSONs in `1_setup/model/adaptive_isogrid_data/` | — |
| 🔴 HIGH | Run Campaign 01: `python studies/01_v1_tpe/run_optimization.py` | Pending |
| 🟡 MED | Update MAT1 card in NX model to AL7075-T6 properties (Gap G-01) | Pending |
| 🟡 MED | Extract baseline solid plate mass (Gap G-02) | Pending |
| 🟢 LOW | Benchmark single iteration time for runtime planning | Pending |
---
*Technical Lead 🔧 — 8 parameters, physics-driven, stress-only constraint, ready to run.*