From a3f18dc377d149bd0366638638bfce794427a13d Mon Sep 17 00:00:00 2001 From: Anto01 Date: Sat, 24 Jan 2026 15:17:34 -0500 Subject: [PATCH] chore: Project cleanup and Canvas UX improvements (Phase 7-9) ## Cleanup (v0.5.0) - Delete 102+ orphaned MCP session temp files - Remove build artifacts (htmlcov, dist, __pycache__) - Archive superseded plan docs (RALPH_LOOP V2/V3, CANVAS V3, etc.) - Move debug/analysis scripts from tests/ to tools/analysis/ - Archive redundant NX journals to archive/nx_journals/ - Archive monolithic PROTOCOL.md to docs/archive/ - Update .gitignore with missing patterns - Clean old study files (optimization_log_old.txt, run_optimization_old.py) ## Canvas UX (Phases 7-9) - Phase 7: Resizable panels with localStorage persistence - Left sidebar: 200-400px, Right panel: 280-600px - New useResizablePanel hook and ResizeHandle component - Phase 8: Enable all palette items - All 8 node types now draggable - Singleton logic for model/solver/algorithm/surrogate - Phase 9: Solver configuration - Add SolverEngine type (nxnastran, mscnastran, python, etc.) - Add NastranSolutionType (SOL101-SOL200) - Engine/solution dropdowns in config panel - Python script path support ## Documentation - Update CHANGELOG.md with recent versions - Update docs/00_INDEX.md - Create examples/README.md - Add docs/plans/CANVAS_UX_IMPROVEMENTS.md --- .claude-mcp-06fea803.json | 1 - .claude-mcp-3e104790.json | 1 - .claude-prompt-06fea803.md | 45 - .claude-prompt-3e104790.md | 45 - .gitignore | 12 + CHANGELOG.md | 58 + CLAUDE.md | 43 + .../extract_expressions_standalone.py | 0 .../nx_journals}/list_expressions_simple.py | 0 .../nx_journals}/test_write.py | 0 .../src/components/canvas/ResizeHandle.tsx | 67 + .../src/components/canvas/SpecRenderer.tsx | 73 +- .../components/canvas/nodes/SolverNode.tsx | 38 +- .../components/canvas/palette/NodePalette.tsx | 13 +- .../canvas/panels/NodeConfigPanelV2.tsx | 110 +- .../frontend/src/hooks/useResizablePanel.ts | 156 ++ .../frontend/src/lib/canvas/schema.ts | 10 +- .../frontend/src/pages/CanvasView.tsx | 59 +- .../frontend/src/types/atomizer-spec.ts | 66 +- docs/00_INDEX.md | 8 +- .../archive/PROTOCOL_V1_MONOLITHIC.md | 0 docs/{ => archive}/plans/CANVAS_UX_DESIGN.md | 0 docs/{ => archive}/plans/CANVAS_V3_PLAN.md | 0 .../plans/RALPH_LOOP_CANVAS_V2.md | 0 .../plans/RALPH_LOOP_CANVAS_V3.md | 0 docs/plans/CANVAS_UX_IMPROVEMENTS.md | 445 ++++ examples/README.md | 49 + .../optimization_log_old.txt | 2160 ----------------- .../run_optimization_old.py | 283 --- {tests => tools/analysis}/analyze_v11.py | 0 {tests => tools/analysis}/audit_v10_fix.py | 0 .../analysis}/audit_v10_method_diff.py | 0 {tests => tools/analysis}/audit_v10_wfe.py | 0 {tests => tools/analysis}/check_api_routes.py | 0 .../analysis}/compare_v8_zernike_methods.py | 0 .../analysis}/debug_figure_coords.py | 0 {tests => tools/analysis}/debug_insights.py | 0 .../analysis}/debug_lateral_discrepancy.py | 0 38 files changed, 1172 insertions(+), 2570 deletions(-) delete mode 100644 .claude-mcp-06fea803.json delete mode 100644 .claude-mcp-3e104790.json delete mode 100644 .claude-prompt-06fea803.md delete mode 100644 .claude-prompt-3e104790.md rename {nx_journals => archive/nx_journals}/extract_expressions_standalone.py (100%) rename {nx_journals => archive/nx_journals}/list_expressions_simple.py (100%) rename {nx_journals => archive/nx_journals}/test_write.py (100%) create mode 100644 atomizer-dashboard/frontend/src/components/canvas/ResizeHandle.tsx create mode 100644 atomizer-dashboard/frontend/src/hooks/useResizablePanel.ts rename PROTOCOL.md => docs/archive/PROTOCOL_V1_MONOLITHIC.md (100%) rename docs/{ => archive}/plans/CANVAS_UX_DESIGN.md (100%) rename docs/{ => archive}/plans/CANVAS_V3_PLAN.md (100%) rename docs/{ => archive}/plans/RALPH_LOOP_CANVAS_V2.md (100%) rename docs/{ => archive}/plans/RALPH_LOOP_CANVAS_V3.md (100%) create mode 100644 docs/plans/CANVAS_UX_IMPROVEMENTS.md create mode 100644 examples/README.md delete mode 100644 studies/bracket_displacement_maximizing/optimization_log_old.txt delete mode 100644 studies/bracket_displacement_maximizing/run_optimization_old.py rename {tests => tools/analysis}/analyze_v11.py (100%) rename {tests => tools/analysis}/audit_v10_fix.py (100%) rename {tests => tools/analysis}/audit_v10_method_diff.py (100%) rename {tests => tools/analysis}/audit_v10_wfe.py (100%) rename {tests => tools/analysis}/check_api_routes.py (100%) rename {tests => tools/analysis}/compare_v8_zernike_methods.py (100%) rename {tests => tools/analysis}/debug_figure_coords.py (100%) rename {tests => tools/analysis}/debug_insights.py (100%) rename {tests => tools/analysis}/debug_lateral_discrepancy.py (100%) diff --git a/.claude-mcp-06fea803.json b/.claude-mcp-06fea803.json deleted file mode 100644 index effbc3f3..00000000 --- a/.claude-mcp-06fea803.json +++ /dev/null @@ -1 +0,0 @@ -{"mcpServers": {"atomizer": {"command": "node", "args": ["C:\\Users\\antoi\\Atomizer\\mcp-server\\atomizer-tools\\dist\\index.js"], "env": {"ATOMIZER_MODE": "user", "ATOMIZER_ROOT": "C:\\Users\\antoi\\Atomizer"}}}} \ No newline at end of file diff --git a/.claude-mcp-3e104790.json b/.claude-mcp-3e104790.json deleted file mode 100644 index effbc3f3..00000000 --- a/.claude-mcp-3e104790.json +++ /dev/null @@ -1 +0,0 @@ -{"mcpServers": {"atomizer": {"command": "node", "args": ["C:\\Users\\antoi\\Atomizer\\mcp-server\\atomizer-tools\\dist\\index.js"], "env": {"ATOMIZER_MODE": "user", "ATOMIZER_ROOT": "C:\\Users\\antoi\\Atomizer"}}}} \ No newline at end of file diff --git a/.claude-prompt-06fea803.md b/.claude-prompt-06fea803.md deleted file mode 100644 index 66409582..00000000 --- a/.claude-prompt-06fea803.md +++ /dev/null @@ -1,45 +0,0 @@ -# Atomizer Assistant - -You are the Atomizer Assistant - an expert system for structural optimization using FEA. - -**Current Mode**: USER - -Your role: -- Help engineers with FEA optimization workflows -- Create, configure, and run optimization studies -- Analyze results and provide insights -- Explain FEA concepts and methodology - -Important guidelines: -- Be concise and professional -- Use technical language appropriate for engineers -- You are "Atomizer Assistant", not a generic AI -- Use the available MCP tools to perform actions -- When asked about studies, use the appropriate tools to get real data - - ---- - -# Current Study: m1_mirror_flatback_lateral - -**Status**: Study directory not found. - ---- - -# User Mode Instructions - -You can help with optimization workflows: -- Create and configure studies -- Run optimizations -- Analyze results -- Generate reports -- Explain FEA concepts - -**For code modifications**, suggest switching to Power Mode. - -Available tools: -- `list_studies`, `get_study_status`, `create_study` -- `run_optimization`, `stop_optimization`, `get_optimization_status` -- `get_trial_data`, `analyze_convergence`, `compare_trials`, `get_best_design` -- `generate_report`, `export_data` -- `explain_physics`, `recommend_method`, `query_extractors` diff --git a/.claude-prompt-3e104790.md b/.claude-prompt-3e104790.md deleted file mode 100644 index 66409582..00000000 --- a/.claude-prompt-3e104790.md +++ /dev/null @@ -1,45 +0,0 @@ -# Atomizer Assistant - -You are the Atomizer Assistant - an expert system for structural optimization using FEA. - -**Current Mode**: USER - -Your role: -- Help engineers with FEA optimization workflows -- Create, configure, and run optimization studies -- Analyze results and provide insights -- Explain FEA concepts and methodology - -Important guidelines: -- Be concise and professional -- Use technical language appropriate for engineers -- You are "Atomizer Assistant", not a generic AI -- Use the available MCP tools to perform actions -- When asked about studies, use the appropriate tools to get real data - - ---- - -# Current Study: m1_mirror_flatback_lateral - -**Status**: Study directory not found. - ---- - -# User Mode Instructions - -You can help with optimization workflows: -- Create and configure studies -- Run optimizations -- Analyze results -- Generate reports -- Explain FEA concepts - -**For code modifications**, suggest switching to Power Mode. - -Available tools: -- `list_studies`, `get_study_status`, `create_study` -- `run_optimization`, `stop_optimization`, `get_optimization_status` -- `get_trial_data`, `analyze_convergence`, `compare_trials`, `get_best_design` -- `generate_report`, `export_data` -- `explain_physics`, `recommend_method`, `query_extractors` diff --git a/.gitignore b/.gitignore index ed39cf62..22a01ef6 100644 --- a/.gitignore +++ b/.gitignore @@ -110,5 +110,17 @@ _dat_run*.dat .claude-mcp-*.json .claude-prompt-*.md +# Backend logs +backend_stdout.log +backend_stderr.log +*.log.bak + +# Linter/formatter caches +.ruff_cache/ +.mypy_cache/ + # Auto-generated documentation (regenerate with: python -m optimization_engine.auto_doc all) docs/generated/ + +# Malformed filenames (Windows path used as filename) +C:* diff --git a/CHANGELOG.md b/CHANGELOG.md index ffc9e355..f582c34d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,64 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +## [0.5.0] - 2025-01-24 + +### Project Cleanup & Organization +- Deleted 102+ orphaned MCP session temp files +- Removed build artifacts (htmlcov, dist, __pycache__) +- Archived superseded plan documents (RALPH_LOOP V2/V3, CANVAS V3, etc.) +- Moved debug/analysis scripts from tests/ to tools/analysis/ +- Updated .gitignore with missing patterns +- Cleaned empty directories + +## [0.4.0] - 2025-01-22 + +### Canvas UX Improvements (Phases 7-9) +- **Resizable Panels**: Left sidebar (200-400px) and right panel (280-600px) with localStorage persistence +- **All Palette Items Enabled**: All 8 node types now draggable (model, solver, designVar, extractor, objective, constraint, algorithm, surrogate) +- **Solver Configuration**: Engine selection (NX Nastran, MSC Nastran, Python Script) with solution type dropdowns (SOL101-SOL200) + +### AtomizerSpec v2.0 +- Unified JSON configuration schema for all studies +- Added SolverEngine and NastranSolutionType types +- Canvas position persistence for all nodes +- Migration support from legacy optimization_config.json + +## [0.3.0] - 2025-01-18 + +### Dashboard V3.1 - Canvas Builder +- Visual workflow builder with 9 node types +- Spec ↔ ReactFlow bidirectional converter +- WebSocket real-time synchronization +- Claude chat integration +- Custom extractors with in-canvas code editor +- Model introspection panel + +### Learning Atomizer Core (LAC) +- Persistent memory system for accumulated knowledge +- Session insights recording (failures, workarounds, patterns) +- Optimization outcome tracking + +## [0.2.5] - 2025-01-16 + +### GNN Surrogate for Zernike Optimization +- PolarMirrorGraph with fixed 3000-node polar grid +- ZernikeGNN model with design-conditioned convolutions +- Differentiable GPU-accelerated Zernike fitting +- Training pipeline with multi-task loss + +### DevLoop Automation +- Closed-loop development system with AI agents +- Gemini planning, Claude implementation +- Playwright browser testing for dashboard UI + +## [0.2.1] - 2025-01-07 + +### Optimization Engine v2.0 Restructure +- Reorganized into modular subpackages (core/, nx/, study/, config/) +- SpecManager for AtomizerSpec handling +- Deprecation warnings for old import paths + ### Phase 3.3 - Dashboard & Multi-Solution Support (November 23, 2025) #### Added diff --git a/CLAUDE.md b/CLAUDE.md index 5445ecc4..d28cad03 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -55,6 +55,49 @@ If working directory is inside a study (`studies/*/`): - If no study context: Offer to create one or list available studies - After code changes: Update documentation proactively (SYS_12, cheatsheet) +### Step 5: Use DevLoop for Multi-Step Development Tasks + +**CRITICAL: For any development task with 3+ steps, USE DEVLOOP instead of manual work.** + +DevLoop is the closed-loop development system that coordinates AI agents for autonomous development: + +```bash +# Plan a task with Gemini +python tools/devloop_cli.py plan "fix extractor exports" + +# Implement with Claude +python tools/devloop_cli.py implement + +# Test filesystem/API +python tools/devloop_cli.py test --study support_arm + +# Test dashboard UI with Playwright +python tools/devloop_cli.py browser --level full + +# Analyze failures +python tools/devloop_cli.py analyze + +# Full autonomous cycle +python tools/devloop_cli.py start "add new stress extractor" +``` + +**When to use DevLoop:** +- Fixing bugs that require multiple file changes +- Adding new features or extractors +- Debugging optimization failures +- Testing dashboard UI changes +- Any task that would take 3+ manual steps + +**Browser test levels:** +- `quick` - Smoke test (1 test) +- `home` - Home page verification (2 tests) +- `full` - All UI tests (5+ tests) +- `study` - Canvas/dashboard for specific study + +**DO NOT default to manual debugging** - use the automation we built! + +**Full documentation**: `docs/guides/DEVLOOP.md` + --- ## Quick Start - Protocol Operating System diff --git a/nx_journals/extract_expressions_standalone.py b/archive/nx_journals/extract_expressions_standalone.py similarity index 100% rename from nx_journals/extract_expressions_standalone.py rename to archive/nx_journals/extract_expressions_standalone.py diff --git a/nx_journals/list_expressions_simple.py b/archive/nx_journals/list_expressions_simple.py similarity index 100% rename from nx_journals/list_expressions_simple.py rename to archive/nx_journals/list_expressions_simple.py diff --git a/nx_journals/test_write.py b/archive/nx_journals/test_write.py similarity index 100% rename from nx_journals/test_write.py rename to archive/nx_journals/test_write.py diff --git a/atomizer-dashboard/frontend/src/components/canvas/ResizeHandle.tsx b/atomizer-dashboard/frontend/src/components/canvas/ResizeHandle.tsx new file mode 100644 index 00000000..968c6517 --- /dev/null +++ b/atomizer-dashboard/frontend/src/components/canvas/ResizeHandle.tsx @@ -0,0 +1,67 @@ +/** + * ResizeHandle - Visual drag handle for resizable panels + * + * A thin vertical bar that can be dragged to resize panels. + * Shows visual feedback on hover and during drag. + */ + +import { memo } from 'react'; + +interface ResizeHandleProps { + /** Mouse down handler to start dragging */ + onMouseDown: (e: React.MouseEvent) => void; + /** Double click handler to reset size */ + onDoubleClick?: () => void; + /** Whether panel is currently being dragged */ + isDragging?: boolean; + /** Position of the handle ('left' or 'right' edge of the panel) */ + position?: 'left' | 'right'; +} + +function ResizeHandleComponent({ + onMouseDown, + onDoubleClick, + isDragging = false, + position = 'right', +}: ResizeHandleProps) { + return ( +
+ {/* Wider hit area for easier grabbing */} +
+ + {/* Visual indicator dots (shown on hover via CSS) */} +
+
+
+
+
+
+ ); +} + +export const ResizeHandle = memo(ResizeHandleComponent); +export default ResizeHandle; diff --git a/atomizer-dashboard/frontend/src/components/canvas/SpecRenderer.tsx b/atomizer-dashboard/frontend/src/components/canvas/SpecRenderer.tsx index 3472407f..41b0d56e 100644 --- a/atomizer-dashboard/frontend/src/components/canvas/SpecRenderer.tsx +++ b/atomizer-dashboard/frontend/src/components/canvas/SpecRenderer.tsx @@ -49,16 +49,23 @@ import { validateSpec, canRunOptimization } from '../../lib/validation/specValid // Drag-Drop Helpers // ============================================================================ -/** Addable node types via drag-drop */ -const ADDABLE_NODE_TYPES = ['designVar', 'extractor', 'objective', 'constraint'] as const; +import { SINGLETON_TYPES } from './palette/NodePalette'; + +/** All node types that can be added via drag-drop */ +const ADDABLE_NODE_TYPES = ['model', 'solver', 'designVar', 'extractor', 'objective', 'constraint', 'algorithm', 'surrogate'] as const; type AddableNodeType = typeof ADDABLE_NODE_TYPES[number]; function isAddableNodeType(type: string): type is AddableNodeType { return ADDABLE_NODE_TYPES.includes(type as AddableNodeType); } +/** Check if a node type is a singleton (only one allowed) */ +function isSingletonType(type: string): boolean { + return SINGLETON_TYPES.includes(type as typeof SINGLETON_TYPES[number]); +} + /** Maps canvas NodeType to spec API type */ -function mapNodeTypeToSpecType(type: AddableNodeType): 'designVar' | 'extractor' | 'objective' | 'constraint' { +function mapNodeTypeToSpecType(type: AddableNodeType): 'designVar' | 'extractor' | 'objective' | 'constraint' | 'model' | 'solver' | 'algorithm' | 'surrogate' { return type; } @@ -67,6 +74,22 @@ function getDefaultNodeData(type: AddableNodeType, position: { x: number; y: num const timestamp = Date.now(); switch (type) { + case 'model': + return { + name: 'Model', + sim: { + path: '', + solver: 'nastran', + }, + canvas_position: position, + }; + case 'solver': + return { + name: 'Solver', + engine: 'nxnastran', + solution_type: 'SOL101', + canvas_position: position, + }; case 'designVar': return { name: `variable_${timestamp}`, @@ -130,6 +153,23 @@ function getDefaultNodeData(type: AddableNodeType, position: { x: number; y: num enabled: true, canvas_position: position, }; + case 'algorithm': + return { + name: 'Algorithm', + type: 'TPE', + budget: { + max_trials: 100, + }, + canvas_position: position, + }; + case 'surrogate': + return { + name: 'Surrogate', + enabled: false, + model_type: 'MLP', + min_trials: 20, + canvas_position: position, + }; } } @@ -602,6 +642,18 @@ function SpecRendererInner({ return; } + // Check if this is a singleton type that already exists + if (isSingletonType(type)) { + const existingNode = localNodes.find(n => n.type === type); + if (existingNode) { + // Select the existing node instead of creating a duplicate + selectNode(existingNode.id); + // Show a toast notification would be nice here + console.log(`${type} already exists - selected existing node`); + return; + } + } + // Convert screen position to flow position const position = reactFlowInstance.current.screenToFlowPosition({ x: event.clientX, @@ -612,8 +664,19 @@ function SpecRendererInner({ const nodeData = getDefaultNodeData(type, position); const specType = mapNodeTypeToSpecType(type); + // For structural types (model, solver, algorithm, surrogate), these are + // part of the spec structure rather than array items. Handle differently. + const structuralTypes = ['model', 'solver', 'algorithm', 'surrogate']; + if (structuralTypes.includes(type)) { + // These nodes are derived from spec structure - they shouldn't be "added" + // They already exist if the spec has that section configured + console.log(`${type} is a structural node - configure via spec directly`); + setError(`${type} nodes are configured via the spec. Use the config panel to edit.`); + return; + } + try { - const nodeId = await addNode(specType, nodeData); + const nodeId = await addNode(specType as 'designVar' | 'extractor' | 'objective' | 'constraint', nodeData); // Select the newly created node selectNode(nodeId); } catch (err) { @@ -621,7 +684,7 @@ function SpecRendererInner({ setError(err instanceof Error ? err.message : 'Failed to add node'); } }, - [editable, addNode, selectNode, setError] + [editable, addNode, selectNode, setError, localNodes] ); // Loading state diff --git a/atomizer-dashboard/frontend/src/components/canvas/nodes/SolverNode.tsx b/atomizer-dashboard/frontend/src/components/canvas/nodes/SolverNode.tsx index 2ecef9a8..e31f5e38 100644 --- a/atomizer-dashboard/frontend/src/components/canvas/nodes/SolverNode.tsx +++ b/atomizer-dashboard/frontend/src/components/canvas/nodes/SolverNode.tsx @@ -1,14 +1,44 @@ import { memo } from 'react'; import { NodeProps } from 'reactflow'; -import { Cpu } from 'lucide-react'; +import { Cpu, Terminal } from 'lucide-react'; import { BaseNode } from './BaseNode'; -import { SolverNodeData } from '../../../lib/canvas/schema'; +import { SolverNodeData, SolverEngine } from '../../../lib/canvas/schema'; + +// Human-readable engine names +const ENGINE_LABELS: Record = { + nxnastran: 'NX Nastran', + mscnastran: 'MSC Nastran', + python: 'Python Script', + abaqus: 'Abaqus', + ansys: 'ANSYS', +}; function SolverNodeComponent(props: NodeProps) { const { data } = props; + + // Build display string: "Engine - SolutionType" or just one + const engineLabel = data.engine ? ENGINE_LABELS[data.engine] : null; + const solverTypeLabel = data.solverType || null; + + let displayText: string; + if (engineLabel && solverTypeLabel) { + displayText = `${engineLabel} (${solverTypeLabel})`; + } else if (engineLabel) { + displayText = engineLabel; + } else if (solverTypeLabel) { + displayText = solverTypeLabel; + } else { + displayText = 'Configure solver'; + } + + // Use Terminal icon for Python, Cpu for others + const icon = data.engine === 'python' + ? + : ; + return ( - } iconColor="text-violet-400"> - {data.solverType || 'Select solution'} + + {displayText} ); } diff --git a/atomizer-dashboard/frontend/src/components/canvas/palette/NodePalette.tsx b/atomizer-dashboard/frontend/src/components/canvas/palette/NodePalette.tsx index d2d2a24d..406b531c 100644 --- a/atomizer-dashboard/frontend/src/components/canvas/palette/NodePalette.tsx +++ b/atomizer-dashboard/frontend/src/components/canvas/palette/NodePalette.tsx @@ -54,6 +54,9 @@ export interface NodePaletteProps { // Constants // ============================================================================ +/** Singleton node types - only one of each allowed on canvas */ +export const SINGLETON_TYPES: NodeType[] = ['model', 'solver', 'algorithm', 'surrogate']; + export const PALETTE_ITEMS: PaletteItem[] = [ { type: 'model', @@ -61,15 +64,15 @@ export const PALETTE_ITEMS: PaletteItem[] = [ icon: Box, description: 'NX model file (.prt, .sim)', color: 'text-blue-400', - canAdd: false, // Synthetic - derived from spec + canAdd: true, // Singleton - only one allowed }, { type: 'solver', label: 'Solver', icon: Cpu, - description: 'Nastran solution type', + description: 'Analysis solver config', color: 'text-violet-400', - canAdd: false, // Synthetic - derived from model + canAdd: true, // Singleton - only one allowed }, { type: 'designVar', @@ -109,7 +112,7 @@ export const PALETTE_ITEMS: PaletteItem[] = [ icon: BrainCircuit, description: 'Optimization method', color: 'text-indigo-400', - canAdd: false, // Synthetic - derived from spec.optimization + canAdd: true, // Singleton - only one allowed }, { type: 'surrogate', @@ -117,7 +120,7 @@ export const PALETTE_ITEMS: PaletteItem[] = [ icon: Rocket, description: 'Neural acceleration', color: 'text-pink-400', - canAdd: false, // Synthetic - derived from spec.optimization.surrogate + canAdd: true, // Singleton - only one allowed }, ]; diff --git a/atomizer-dashboard/frontend/src/components/canvas/panels/NodeConfigPanelV2.tsx b/atomizer-dashboard/frontend/src/components/canvas/panels/NodeConfigPanelV2.tsx index 173bb3d6..aa677d5b 100644 --- a/atomizer-dashboard/frontend/src/components/canvas/panels/NodeConfigPanelV2.tsx +++ b/atomizer-dashboard/frontend/src/components/canvas/panels/NodeConfigPanelV2.tsx @@ -315,18 +315,106 @@ function ModelNodeConfig({ spec }: SpecConfigProps) { } function SolverNodeConfig({ spec }: SpecConfigProps) { + const { patchSpec } = useSpecStore(); + const [isUpdating, setIsUpdating] = useState(false); + + const engine = spec.model.sim?.engine || 'nxnastran'; + const solutionType = spec.model.sim?.solution_type || 'SOL101'; + const scriptPath = spec.model.sim?.script_path || ''; + const isPython = engine === 'python'; + + const handleEngineChange = async (newEngine: string) => { + setIsUpdating(true); + try { + await patchSpec('model.sim.engine', newEngine); + } catch (err) { + console.error('Failed to update engine:', err); + } finally { + setIsUpdating(false); + } + }; + + const handleSolutionTypeChange = async (newType: string) => { + setIsUpdating(true); + try { + await patchSpec('model.sim.solution_type', newType); + } catch (err) { + console.error('Failed to update solution type:', err); + } finally { + setIsUpdating(false); + } + }; + + const handleScriptPathChange = async (newPath: string) => { + setIsUpdating(true); + try { + await patchSpec('model.sim.script_path', newPath); + } catch (err) { + console.error('Failed to update script path:', err); + } finally { + setIsUpdating(false); + } + }; + return ( -
- - -

Detected from model file.

-
+ <> + {isUpdating && ( +
Updating...
+ )} + +
+ + +

+ {isPython ? 'Run custom Python analysis script' : 'Select FEA solver software'} +

+
+ + {!isPython && ( +
+ + +
+ )} + + {isPython && ( +
+ + handleScriptPathChange(e.target.value)} + placeholder="path/to/solver_script.py" + className={`${inputClass} font-mono text-sm`} + /> +

+ Python script must define solve(params) function +

+
+ )} + ); } diff --git a/atomizer-dashboard/frontend/src/hooks/useResizablePanel.ts b/atomizer-dashboard/frontend/src/hooks/useResizablePanel.ts new file mode 100644 index 00000000..7299fe85 --- /dev/null +++ b/atomizer-dashboard/frontend/src/hooks/useResizablePanel.ts @@ -0,0 +1,156 @@ +/** + * useResizablePanel - Hook for creating resizable panels with persistence + * + * Features: + * - Drag to resize + * - Min/max constraints + * - localStorage persistence + * - Double-click to reset to default + */ + +import { useState, useCallback, useEffect, useRef } from 'react'; + +export interface ResizablePanelConfig { + /** Unique key for localStorage persistence */ + storageKey: string; + /** Default width in pixels */ + defaultWidth: number; + /** Minimum width in pixels */ + minWidth: number; + /** Maximum width in pixels */ + maxWidth: number; + /** Side of the panel ('left' or 'right') - affects resize direction */ + side: 'left' | 'right'; +} + +export interface ResizablePanelState { + /** Current width in pixels */ + width: number; + /** Whether user is currently dragging */ + isDragging: boolean; + /** Start drag handler - attach to resize handle mousedown */ + startDrag: (e: React.MouseEvent) => void; + /** Reset to default width */ + resetWidth: () => void; + /** Set width programmatically */ + setWidth: (width: number) => void; +} + +const STORAGE_PREFIX = 'atomizer-panel-'; + +function getStoredWidth(key: string, defaultWidth: number): number { + if (typeof window === 'undefined') return defaultWidth; + + try { + const stored = localStorage.getItem(STORAGE_PREFIX + key); + if (stored) { + const parsed = parseInt(stored, 10); + if (!isNaN(parsed)) return parsed; + } + } catch { + // localStorage not available + } + return defaultWidth; +} + +function storeWidth(key: string, width: number): void { + if (typeof window === 'undefined') return; + + try { + localStorage.setItem(STORAGE_PREFIX + key, String(width)); + } catch { + // localStorage not available + } +} + +export function useResizablePanel(config: ResizablePanelConfig): ResizablePanelState { + const { storageKey, defaultWidth, minWidth, maxWidth, side } = config; + + // Initialize from localStorage + const [width, setWidthState] = useState(() => { + const stored = getStoredWidth(storageKey, defaultWidth); + return Math.max(minWidth, Math.min(maxWidth, stored)); + }); + + const [isDragging, setIsDragging] = useState(false); + + // Track initial position for drag calculation + const dragStartRef = useRef<{ x: number; width: number } | null>(null); + + // Clamp width within bounds + const clampWidth = useCallback((w: number) => { + return Math.max(minWidth, Math.min(maxWidth, w)); + }, [minWidth, maxWidth]); + + // Set width with clamping and persistence + const setWidth = useCallback((newWidth: number) => { + const clamped = clampWidth(newWidth); + setWidthState(clamped); + storeWidth(storageKey, clamped); + }, [clampWidth, storageKey]); + + // Reset to default + const resetWidth = useCallback(() => { + setWidth(defaultWidth); + }, [defaultWidth, setWidth]); + + // Start drag handler + const startDrag = useCallback((e: React.MouseEvent) => { + e.preventDefault(); + setIsDragging(true); + dragStartRef.current = { x: e.clientX, width }; + }, [width]); + + // Handle mouse move during drag + useEffect(() => { + if (!isDragging) return; + + const handleMouseMove = (e: MouseEvent) => { + if (!dragStartRef.current) return; + + const delta = e.clientX - dragStartRef.current.x; + + // For left panels, positive delta increases width + // For right panels, negative delta increases width + const newWidth = side === 'left' + ? dragStartRef.current.width + delta + : dragStartRef.current.width - delta; + + setWidthState(clampWidth(newWidth)); + }; + + const handleMouseUp = () => { + if (dragStartRef.current) { + // Persist the final width + storeWidth(storageKey, width); + } + setIsDragging(false); + dragStartRef.current = null; + }; + + // Add listeners to document for smooth dragging + document.addEventListener('mousemove', handleMouseMove); + document.addEventListener('mouseup', handleMouseUp); + + // Change cursor globally during drag + document.body.style.cursor = 'col-resize'; + document.body.style.userSelect = 'none'; + + return () => { + document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseup', handleMouseUp); + document.body.style.cursor = ''; + document.body.style.userSelect = ''; + }; + }, [isDragging, side, clampWidth, storageKey, width]); + + return { + width, + isDragging, + startDrag, + resetWidth, + setWidth, + }; +} + +export default useResizablePanel; diff --git a/atomizer-dashboard/frontend/src/lib/canvas/schema.ts b/atomizer-dashboard/frontend/src/lib/canvas/schema.ts index c3c45918..f20b1e9f 100644 --- a/atomizer-dashboard/frontend/src/lib/canvas/schema.ts +++ b/atomizer-dashboard/frontend/src/lib/canvas/schema.ts @@ -25,9 +25,17 @@ export interface ModelNodeData extends BaseNodeData { fileType?: 'prt' | 'fem' | 'sim'; } +export type SolverEngine = 'nxnastran' | 'mscnastran' | 'python' | 'abaqus' | 'ansys'; +export type NastranSolutionType = 'SOL101' | 'SOL103' | 'SOL105' | 'SOL106' | 'SOL111' | 'SOL112' | 'SOL200'; + export interface SolverNodeData extends BaseNodeData { type: 'solver'; - solverType?: 'SOL101' | 'SOL103' | 'SOL105' | 'SOL106' | 'SOL111' | 'SOL112'; + /** Solver engine (nxnastran, mscnastran, python, etc.) */ + engine?: SolverEngine; + /** Solution type for Nastran solvers */ + solverType?: NastranSolutionType; + /** Python script path (for python engine) */ + scriptPath?: string; } export interface DesignVarNodeData extends BaseNodeData { diff --git a/atomizer-dashboard/frontend/src/pages/CanvasView.tsx b/atomizer-dashboard/frontend/src/pages/CanvasView.tsx index 6ad1b265..947d1ba1 100644 --- a/atomizer-dashboard/frontend/src/pages/CanvasView.tsx +++ b/atomizer-dashboard/frontend/src/pages/CanvasView.tsx @@ -11,8 +11,10 @@ import { NodeConfigPanel } from '../components/canvas/panels/NodeConfigPanel'; import { NodeConfigPanelV2 } from '../components/canvas/panels/NodeConfigPanelV2'; import { ChatPanel } from '../components/canvas/panels/ChatPanel'; import { PanelContainer } from '../components/canvas/panels/PanelContainer'; +import { ResizeHandle } from '../components/canvas/ResizeHandle'; import { useCanvasStore } from '../hooks/useCanvasStore'; import { useSpecStore, useSpec, useSpecLoading, useSpecIsDirty, useSelectedNodeId } from '../hooks/useSpecStore'; +import { useResizablePanel } from '../hooks/useResizablePanel'; // usePanelStore is now used by child components - PanelContainer handles panels import { useSpecUndoRedo, useUndoRedoKeyboard } from '../hooks/useSpecUndoRedo'; import { useStudy } from '../context/StudyContext'; @@ -31,6 +33,23 @@ export function CanvasView() { const [paletteCollapsed, setPaletteCollapsed] = useState(false); const [leftSidebarTab, setLeftSidebarTab] = useState<'components' | 'files'>('components'); const navigate = useNavigate(); + + // Resizable panels + const leftPanel = useResizablePanel({ + storageKey: 'left-sidebar', + defaultWidth: 240, + minWidth: 200, + maxWidth: 400, + side: 'left', + }); + + const rightPanel = useResizablePanel({ + storageKey: 'right-panel', + defaultWidth: 384, + minWidth: 280, + maxWidth: 600, + side: 'right', + }); const [searchParams] = useSearchParams(); // Spec mode is the default (AtomizerSpec v2.0) @@ -423,7 +442,10 @@ export function CanvasView() {
{/* Left Sidebar with tabs (spec mode only - AtomizerCanvas has its own) */} {useSpecMode && ( -
+
{/* Tab buttons (only show when expanded) */} {!paletteCollapsed && (
@@ -469,6 +491,16 @@ export function CanvasView() { /> )}
+ + {/* Resize handle (only when not collapsed) */} + {!paletteCollapsed && ( + + )}
)} @@ -494,14 +526,35 @@ export function CanvasView() { {/* Shows INSTEAD of chat when a node is selected */} {selectedNodeId ? ( useSpecMode ? ( - useSpecStore.getState().clearSelection()} /> +
+ + useSpecStore.getState().clearSelection()} /> +
) : (
) ) : showChat ? ( -
+
+ {/* Resize handle */} + {/* Chat Header */}
diff --git a/atomizer-dashboard/frontend/src/types/atomizer-spec.ts b/atomizer-dashboard/frontend/src/types/atomizer-spec.ts index 868e1096..8432ba07 100644 --- a/atomizer-dashboard/frontend/src/types/atomizer-spec.ts +++ b/atomizer-dashboard/frontend/src/types/atomizer-spec.ts @@ -39,6 +39,10 @@ export interface SpecMeta { tags?: string[]; /** Real-world engineering context */ engineering_context?: string; + /** Current workflow status */ + status?: 'draft' | 'introspected' | 'configured' | 'validated' | 'ready' | 'running' | 'completed' | 'failed'; + /** Topic/folder for organization */ + topic?: string; } // ============================================================================ @@ -64,6 +68,29 @@ export interface FemConfig { } export type SolverType = 'nastran' | 'NX_Nastran' | 'abaqus'; + +/** + * SolverEngine - The actual solver software used for analysis + * - nxnastran: NX Nastran (built into Siemens NX) + * - mscnastran: MSC Nastran (external) + * - python: Custom Python script + * - abaqus: Abaqus (future) + * - ansys: ANSYS (future) + */ +export type SolverEngine = 'nxnastran' | 'mscnastran' | 'python' | 'abaqus' | 'ansys'; + +/** + * NastranSolutionType - Common Nastran solution types + */ +export type NastranSolutionType = + | 'SOL101' // Linear Statics + | 'SOL103' // Normal Modes + | 'SOL105' // Buckling + | 'SOL106' // Nonlinear Statics + | 'SOL111' // Modal Frequency Response + | 'SOL112' // Modal Transient Response + | 'SOL200'; // Design Optimization + export type SubcaseType = 'static' | 'modal' | 'thermal' | 'buckling'; export interface Subcase { @@ -75,10 +102,14 @@ export interface Subcase { export interface SimConfig { /** Path to .sim file */ path: string; - /** Solver type */ + /** Solver type (legacy, use engine instead) */ solver: SolverType; + /** Solver engine software */ + engine?: SolverEngine; /** Solution type (e.g., SOL101) */ - solution_type?: string; + solution_type?: NastranSolutionType | string; + /** Python script path (for python engine) */ + script_path?: string; /** Defined subcases */ subcases?: Subcase[]; } @@ -89,11 +120,40 @@ export interface NxSettings { auto_start_nx?: boolean; } +export interface IntrospectionExpression { + name: string; + value: number | null; + units: string | null; + formula: string | null; + is_candidate: boolean; + confidence: number; +} + +export interface IntrospectionData { + timestamp: string; + solver_type: string | null; + mass_kg: number | null; + volume_mm3: number | null; + expressions: IntrospectionExpression[]; + warnings: string[]; + baseline: { + timestamp: string; + solve_time_seconds: number; + mass_kg: number | null; + max_displacement_mm: number | null; + max_stress_mpa: number | null; + success: boolean; + error: string | null; + } | null; +} + export interface ModelConfig { nx_part?: NxPartConfig; + prt?: NxPartConfig; fem?: FemConfig; - sim: SimConfig; + sim?: SimConfig; nx_settings?: NxSettings; + introspection?: IntrospectionData; } // ============================================================================ diff --git a/docs/00_INDEX.md b/docs/00_INDEX.md index a987c121..6b7928f3 100644 --- a/docs/00_INDEX.md +++ b/docs/00_INDEX.md @@ -1,7 +1,7 @@ # Atomizer Documentation Index -**Last Updated**: 2026-01-20 -**Project Version**: 1.0.0 (AtomizerSpec v2.0 - Full LLM Integration) +**Last Updated**: 2026-01-24 +**Project Version**: 0.5.0 (AtomizerSpec v2.0 - Canvas Builder) --- @@ -201,6 +201,8 @@ Historical documents are preserved in `archive/`: - `archive/historical/` - Legacy documents, old protocols - `archive/marketing/` - Briefings, presentations - `archive/session_summaries/` - Past development sessions +- `archive/plans/` - Superseded plan documents (RALPH_LOOP V2/V3, CANVAS V3, etc.) +- `archive/PROTOCOL_V1_MONOLITHIC.md` - Original monolithic protocol (Nov 2025) --- @@ -216,5 +218,5 @@ For Claude/AI integration: --- -**Last Updated**: 2026-01-20 +**Last Updated**: 2026-01-24 **Maintained By**: Antoine / Atomaste diff --git a/PROTOCOL.md b/docs/archive/PROTOCOL_V1_MONOLITHIC.md similarity index 100% rename from PROTOCOL.md rename to docs/archive/PROTOCOL_V1_MONOLITHIC.md diff --git a/docs/plans/CANVAS_UX_DESIGN.md b/docs/archive/plans/CANVAS_UX_DESIGN.md similarity index 100% rename from docs/plans/CANVAS_UX_DESIGN.md rename to docs/archive/plans/CANVAS_UX_DESIGN.md diff --git a/docs/plans/CANVAS_V3_PLAN.md b/docs/archive/plans/CANVAS_V3_PLAN.md similarity index 100% rename from docs/plans/CANVAS_V3_PLAN.md rename to docs/archive/plans/CANVAS_V3_PLAN.md diff --git a/docs/plans/RALPH_LOOP_CANVAS_V2.md b/docs/archive/plans/RALPH_LOOP_CANVAS_V2.md similarity index 100% rename from docs/plans/RALPH_LOOP_CANVAS_V2.md rename to docs/archive/plans/RALPH_LOOP_CANVAS_V2.md diff --git a/docs/plans/RALPH_LOOP_CANVAS_V3.md b/docs/archive/plans/RALPH_LOOP_CANVAS_V3.md similarity index 100% rename from docs/plans/RALPH_LOOP_CANVAS_V3.md rename to docs/archive/plans/RALPH_LOOP_CANVAS_V3.md diff --git a/docs/plans/CANVAS_UX_IMPROVEMENTS.md b/docs/plans/CANVAS_UX_IMPROVEMENTS.md new file mode 100644 index 00000000..42f78eba --- /dev/null +++ b/docs/plans/CANVAS_UX_IMPROVEMENTS.md @@ -0,0 +1,445 @@ +# Canvas UX Improvements - Master Plan + +**Created:** January 2026 +**Status:** Planning +**Branch:** `feature/studio-enhancement` + +## Overview + +This plan addresses three major UX issues in the Canvas Builder: + +1. **Resizable Panels** - Right pane (chat/config) is fixed at 384px, cannot be adjusted +2. **Disabled Palette Items** - Model, Solver, Algorithm, Surrogate are grayed out and not draggable +3. **Solver Type Selection** - Solver node should allow selection of solver type (NX Nastran, Python, etc.) + +--- + +## Phase 7: Resizable Panels + +### Current State +- Left sidebar: Fixed 240px (expanded) or 56px (collapsed) +- Right panel (Chat/Config): Fixed 384px +- Canvas: Takes remaining space + +### Requirements +- Users should be able to drag panel edges to resize +- Minimum/maximum constraints for usability +- Persist panel sizes in localStorage +- Smooth resize with proper cursor feedback + +### Implementation + +#### 7.1 Create Resizable Panel Hook +```typescript +// hooks/useResizablePanel.ts +interface ResizablePanelState { + width: number; + isDragging: boolean; + startDrag: (e: React.MouseEvent) => void; +} + +function useResizablePanel( + key: string, + defaultWidth: number, + minWidth: number, + maxWidth: number +): ResizablePanelState +``` + +#### 7.2 Update CanvasView Layout +- Wrap left sidebar with resizer +- Wrap right panel with resizer +- Add visual drag handles (thin border that highlights on hover) +- Add cursor: col-resize on hover + +#### 7.3 Files to Modify +| File | Changes | +|------|---------| +| `hooks/useResizablePanel.ts` | NEW - Resize hook with localStorage persistence | +| `pages/CanvasView.tsx` | Add resizers to left/right panels | +| `components/canvas/ResizeHandle.tsx` | NEW - Visual resize handle component | + +#### 7.4 Constraints +| Panel | Min | Default | Max | +|-------|-----|---------|-----| +| Left (Palette/Files) | 200px | 240px | 400px | +| Right (Chat/Config) | 280px | 384px | 600px | + +--- + +## Phase 8: Enable All Palette Items + +### Current State +- Model, Solver, Algorithm, Surrogate are marked `canAdd: false` +- They appear grayed out with "Auto-created" text +- Users cannot drag them to canvas + +### Problem Analysis +These nodes were marked as "synthetic" because they're derived from: +- **Model**: From `spec.model.sim.path` +- **Solver**: From model's solution type +- **Algorithm**: From `spec.optimization.algorithm` +- **Surrogate**: From `spec.optimization.surrogate` + +However, users need to: +1. Add a Model node when creating a new study from scratch +2. Configure the Solver type +3. Choose an Algorithm +4. Enable/configure Surrogate + +### Solution: Make All Items Draggable + +#### 8.1 Update NodePalette +```typescript +// All items should be draggable +export const PALETTE_ITEMS: PaletteItem[] = [ + { + type: 'model', + label: 'Model', + canAdd: true, // Changed from false + description: 'NX/FEM model file', + }, + { + type: 'solver', + label: 'Solver', + canAdd: true, // Changed from false + description: 'Analysis solver', + }, + // ... etc +]; +``` + +#### 8.2 Handle "Singleton" Nodes +Some nodes should only exist once on the canvas: +- Model (only one model per study) +- Solver (one solver) +- Algorithm (one algorithm config) +- Surrogate (optional, one) + +When user drags a singleton that already exists: +- Option A: Show warning toast "Model already exists" +- Option B: Select the existing node instead of creating new +- **Recommended**: Option B (select existing) + +#### 8.3 Update SpecRenderer Drop Handler +```typescript +const onDrop = useCallback(async (event: DragEvent) => { + const type = event.dataTransfer.getData('application/reactflow'); + + // Check if singleton already exists + const SINGLETON_TYPES = ['model', 'solver', 'algorithm', 'surrogate']; + if (SINGLETON_TYPES.includes(type)) { + const existingNode = nodes.find(n => n.type === type); + if (existingNode) { + selectNode(existingNode.id); + showNotification(`${type} already exists - selected it`); + return; + } + } + + // Create new node... +}, [...]); +``` + +#### 8.4 Default Data for New Node Types +```typescript +function getDefaultNodeData(type: NodeType, position) { + switch (type) { + case 'model': + return { + name: 'Model', + sim: { path: '', solver: 'nastran' }, + canvas_position: position, + }; + case 'solver': + return { + name: 'Solver', + type: 'nxnastran', // Default solver + solution_type: 'SOL101', + canvas_position: position, + }; + case 'algorithm': + return { + name: 'Algorithm', + type: 'TPE', + budget: { max_trials: 100 }, + canvas_position: position, + }; + case 'surrogate': + return { + name: 'Surrogate', + enabled: false, + model_type: 'MLP', + min_trials: 20, + canvas_position: position, + }; + // ... existing cases + } +} +``` + +#### 8.5 Files to Modify +| File | Changes | +|------|---------| +| `components/canvas/palette/NodePalette.tsx` | Set `canAdd: true` for all items | +| `components/canvas/SpecRenderer.tsx` | Handle singleton logic in onDrop | +| `lib/spec/converter.ts` | Ensure synthetic nodes have proper IDs | +| `hooks/useSpecStore.ts` | Add model/solver/algorithm to addNode support | + +--- + +## Phase 9: Solver Type Selection + +### Current State +- Solver node shows auto-detected solution type (SOL101, etc.) +- No ability to change solver engine or configure it + +### Requirements +1. Allow selection of solver engine type +2. Configure solution type +3. Support future solver types + +### Solver Types to Support + +| Solver | Description | Status | +|--------|-------------|--------| +| `nxnastran` | NX Nastran (built-in) | Current | +| `mscnastran` | MSC Nastran (external) | Future | +| `python` | Python-based solver | Future | +| `abaqus` | Abaqus (via Python API) | Future | +| `ansys` | ANSYS (via Python API) | Future | + +### Solution Types per Solver + +**NX Nastran / MSC Nastran:** +- SOL101 - Linear Static +- SOL103 - Normal Modes +- SOL105 - Buckling +- SOL106 - Nonlinear Static +- SOL111 - Frequency Response +- SOL112 - Transient Response +- SOL200 - Design Optimization + +**Python Solver:** +- Custom (user-defined) + +### Schema Updates + +#### 9.1 Update AtomizerSpec Types +```typescript +// types/atomizer-spec.ts + +export type SolverEngine = + | 'nxnastran' + | 'mscnastran' + | 'python' + | 'abaqus' + | 'ansys'; + +export type NastranSolutionType = + | 'SOL101' + | 'SOL103' + | 'SOL105' + | 'SOL106' + | 'SOL111' + | 'SOL112' + | 'SOL200'; + +export interface SolverConfig { + /** Solver engine type */ + engine: SolverEngine; + + /** Solution type (for Nastran) */ + solution_type?: NastranSolutionType; + + /** Custom solver script path (for Python solver) */ + script_path?: string; + + /** Additional solver options */ + options?: Record; +} + +export interface Model { + sim?: { + path: string; + solver: SolverConfig; // Changed from just 'nastran' string + }; + // ... +} +``` + +#### 9.2 Update SolverNode Component +```typescript +// components/canvas/nodes/SolverNode.tsx + +function SolverNodeComponent(props: NodeProps) { + const { data } = props; + + return ( + } iconColor="text-violet-400"> +
+ {data.engine || 'nxnastran'} + + {data.solution_type || 'Auto-detect'} + +
+
+ ); +} +``` + +#### 9.3 Solver Configuration Panel +Add to `NodeConfigPanelV2.tsx`: + +```typescript +function SolverNodeConfig({ spec }: SpecConfigProps) { + const { patchSpec } = useSpecStore(); + const solver = spec.model?.sim?.solver || { engine: 'nxnastran' }; + + const handleEngineChange = (engine: SolverEngine) => { + patchSpec('model.sim.solver.engine', engine); + }; + + const handleSolutionTypeChange = (type: NastranSolutionType) => { + patchSpec('model.sim.solver.solution_type', type); + }; + + return ( + <> +
+ + +
+ + {(solver.engine === 'nxnastran' || solver.engine === 'mscnastran') && ( +
+ + +
+ )} + + {solver.engine === 'python' && ( +
+ + patchSpec('model.sim.solver.script_path', e.target.value)} + placeholder="/path/to/solver.py" + className={inputClass} + /> +

+ Python script that runs the analysis +

+
+ )} + + ); +} +``` + +#### 9.4 Files to Modify +| File | Changes | +|------|---------| +| `types/atomizer-spec.ts` | Add SolverEngine, SolverConfig types | +| `components/canvas/nodes/SolverNode.tsx` | Show engine and solution type | +| `components/canvas/panels/NodeConfigPanelV2.tsx` | Add SolverNodeConfig | +| `lib/canvas/schema.ts` | Update SolverNodeData | +| Backend: `config/spec_models.py` | Add SolverConfig Pydantic model | + +--- + +## Implementation Order + +| Phase | Effort | Priority | Dependencies | +|-------|--------|----------|--------------| +| **7.1** Resizable Panel Hook | 2h | High | None | +| **7.2** CanvasView Resizers | 2h | High | 7.1 | +| **8.1** Enable Palette Items | 1h | High | None | +| **8.2** Singleton Logic | 2h | High | 8.1 | +| **8.3** Default Node Data | 1h | High | 8.2 | +| **9.1** Schema Updates | 2h | Medium | None | +| **9.2** SolverNode UI | 1h | Medium | 9.1 | +| **9.3** Solver Config Panel | 2h | Medium | 9.1, 9.2 | + +**Total Estimated Effort:** ~13 hours + +--- + +## Success Criteria + +### Phase 7 (Resizable Panels) +- [ ] Left panel can be resized between 200-400px +- [ ] Right panel can be resized between 280-600px +- [ ] Resize handles show cursor feedback +- [ ] Panel sizes persist across page reload +- [ ] Double-click on handle resets to default + +### Phase 8 (Enable Palette Items) +- [ ] All 8 node types are draggable from palette +- [ ] Dragging singleton to canvas with existing node selects existing +- [ ] Toast notification explains the behavior +- [ ] New studies can start with empty canvas and add Model first + +### Phase 9 (Solver Selection) +- [ ] Solver node shows engine type (nxnastran, python, etc.) +- [ ] Clicking solver node opens config panel +- [ ] Can select solver engine from dropdown +- [ ] Nastran solvers show solution type dropdown +- [ ] Python solver shows script path input +- [ ] Changes persist to atomizer_spec.json + +--- + +## Future Considerations + +### Additional Solver Support +- ANSYS integration via pyANSYS +- Abaqus integration via abaqus-python +- OpenFOAM for CFD +- Custom Python solvers with standardized interface + +### Multi-Solver Workflows +- Support for chained solvers (thermal → structural) +- Co-simulation workflows +- Parallel solver execution + +### Algorithm Node Enhancement +- Similar to Solver, allow algorithm selection +- Show algorithm-specific parameters +- Support custom algorithms + +--- + +## Commit Strategy + +```bash +# Phase 7 +git commit -m "feat: Add resizable panels to canvas view" + +# Phase 8 +git commit -m "feat: Enable all palette items with singleton handling" + +# Phase 9 +git commit -m "feat: Add solver type selection and configuration" +``` diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..67446eeb --- /dev/null +++ b/examples/README.md @@ -0,0 +1,49 @@ +# Atomizer Examples + +This directory contains example configurations and scripts demonstrating Atomizer capabilities. + +## Configuration Examples + +| File | Description | +|------|-------------| +| `optimization_config_neural.json` | Neural surrogate-accelerated optimization | +| `optimization_config_protocol10.json` | IMSO (Intelligent Multi-Stage Optimization) example | +| `optimization_config_protocol12.json` | Custom extractor with Zernike analysis | +| `optimization_config_zernike_mirror.json` | Telescope mirror WFE optimization | + +## Scripts + +| File | Description | +|------|-------------| +| `llm_mode_simple_example.py` | Basic LLM-driven optimization setup | +| `interactive_research_session.py` | Interactive research mode with visualization | + +## Models + +The `Models/` directory contains sample FEA models for testing: +- Bracket geometries +- Beam structures +- Mirror assemblies + +## Zernike Reference + +The `Zernike_old_reference/` directory contains legacy Zernike extraction code for reference purposes. + +## Usage + +1. Copy a configuration file to your study directory +2. Modify paths and parameters for your model +3. Run optimization with: + +```bash +cd studies/your_study +python run_optimization.py +``` + +Or use the Canvas Builder in the dashboard (http://localhost:3003). + +## See Also + +- [Study Creation Guide](../docs/protocols/operations/OP_01_CREATE_STUDY.md) +- [Extractor Library](../docs/protocols/system/SYS_12_EXTRACTOR_LIBRARY.md) +- [Canvas Builder](../docs/guides/CANVAS.md) diff --git a/studies/bracket_displacement_maximizing/optimization_log_old.txt b/studies/bracket_displacement_maximizing/optimization_log_old.txt deleted file mode 100644 index 3cb24dd2..00000000 --- a/studies/bracket_displacement_maximizing/optimization_log_old.txt +++ /dev/null @@ -1,2160 +0,0 @@ -fatal: not a git repository (or any of the parent directories): .git - -================================================================================ - BRACKET DISPLACEMENT MAXIMIZATION STUDY -================================================================================ - -Study Configuration: - - Objective: Maximize displacement - - Constraint: Safety factor >= 4.0 - - Material: Aluminum 6061-T6 (Yield = 276 MPa) - - Design Variables: - * tip_thickness: 15-25 mm - * support_angle: 20-40 degrees - - Optimization trials: 20 - -Part file: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt -Simulation file: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket_sim1.sim - - -================================================================================ - STEP 1: INITIALIZATION -================================================================================ - -Initializing Optimization Setup Wizard... - [OK] Wizard initialized - - -================================================================================ - STEP 2: MODEL INTROSPECTION -================================================================================ - -Reading NX model expressions... -Found 4 expressions: - - support_angle: 38.0 degrees - - tip_thickness: 17.0 mm - - p3: 10.0 mm - - support_blend_radius: 10.0 mm - - -================================================================================ - STEP 3: BASELINE SIMULATION -================================================================================ - -Running baseline simulation to generate reference OP2... -(This validates that NX simulation works before optimization) - -[NX SOLVER] Starting simulation... - Input file: Bracket_sim1.sim - Working dir: c:\Users\antoi\Documents\Atomaste\Atomizer\tests - Mode: Journal - Deleted 1 old result file(s) to force fresh solve -[JOURNAL OUTPUT] - Mesh-Based Errors Summary - ------------------------- - - Total: 0 errors and 0 warnings - - - Material-Based Errors Summary - ----------------------------- - - Total: 0 errors and 0 warnings - - - Solution-Based Errors Summary - ----------------------------- - - Iterative Solver Option - More than 80 percent of the elements in this model are 3D elements. - It is therefore recommended that you turn ON the Element Iterative Solver in the "Edit - Solution" dialog. - - Total: 0 errors and 0 warnings - - - Load/BC-Based Errors Summary - ---------------------------- - - Total: 0 errors and 0 warnings - - - Nastran Model Setup Check completed - - - - - *** 20:43:54 *** - Starting Nastran Exporter - - *** 20:43:54 *** - Writing file - c:\Users\antoi\Documents\Atomaste\Atomizer\tests\bracket_sim1-solution_1.dat - - *** 20:43:54 *** - Writing SIMCENTER NASTRAN 2412.0 compatible deck - - *** 20:43:54 *** - Writing Nastran System section - - *** 20:43:54 *** - Writing File Management section - - *** 20:43:54 *** - Writing Executive Control section - - *** 20:43:54 *** - Writing Case Control section - - *** 20:43:54 *** - Writing Bulk Data section - - *** 20:43:54 *** - Writing Nodes - - *** 20:43:54 *** - Writing Elements - - *** 20:43:54 *** - Writing Physical Properties - - *** 20:43:54 *** - Writing Materials - - *** 20:43:54 *** - Writing Degree-of-Freedom Sets - - *** 20:43:54 *** - Writing Loads and Constraints - - *** 20:43:54 *** - Writing Coordinate Systems - - *** 20:43:54 *** - Validating Solution Setup - - *** 20:43:54 *** - Summary of Bulk Data cards written - - +----------+----------+ - | NAME | NUMBER | - +----------+----------+ - | CHEXA | 306 | - | CPENTA | 10 | - | FORCE | 3 | - | GRID | 585 | - | MAT1 | 1 | - | MATT1 | 1 | - | PARAM | 6 | - | PSOLID | 1 | - | SPC | 51 | - | TABLEM1 | 3 | - +----------+----------+ - - *** 20:43:54 *** - Nastran Deck Successfully Written - - [JOURNAL] Opening simulation: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket_sim1.sim - [JOURNAL] Checking for open parts... - [JOURNAL] Opening simulation fresh from disk... - [JOURNAL] STEP 1: Updating Bracket.prt geometry... - [JOURNAL] Rebuilding geometry with new expression values... - [JOURNAL] Bracket geometry updated (0 errors) - [JOURNAL] STEP 2: Opening Bracket_fem1.fem... - [JOURNAL] Updating FE Model... - [JOURNAL] FE Model updated with new geometry! - [JOURNAL] STEP 3: Switching back to sim part... - [JOURNAL] Switched back to sim part - [JOURNAL] Starting solve... - [JOURNAL] Solve submitted! - [JOURNAL] Solutions solved: -1786238346 - [JOURNAL] Solutions failed: 32764 - [JOURNAL] Solutions skipped: 2055733824 - [JOURNAL] Saving simulation to ensure output files are written... - [JOURNAL] Save complete! -[JOURNAL ERRORS] - Journal execution results for c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py... - Syntax errors: - Line 0: Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py", line 247, in - sys.exit(0 if success else 1) -[NX SOLVER] Waiting for solve to complete... -[NX SOLVER] Output files detected after 0.5s -[NX SOLVER] Complete in 4.3s -[NX SOLVER] Results: bracket_sim1-solution_1.op2 - [OK] Baseline OP2: bracket_sim1-solution_1.op2 - - -================================================================================ - STEP 4: OP2 INTROSPECTION -================================================================================ - -Analyzing OP2 file to auto-detect element types... -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 -OP2 Contents: - - Element types with stress: CHEXA, CPENTA - - Available result types: displacement, stress - - Subcases: [1] - - Nodes: 0 - - Elements: 0 - - -================================================================================ - STEP 5: WORKFLOW CONFIGURATION -================================================================================ - -Building LLM workflow with auto-detected element types... - Using detected element type: CHEXA - - -================================================================================ - STEP 6: PIPELINE VALIDATION -================================================================================ - -Validating complete pipeline with baseline OP2... -(Dry-run test of extractors, calculations, hooks, objective) - -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -Required input 'min_force' not found in context -Hook 'ratio_hook' failed: Missing required input: min_force -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\min_to_avg_ratio_hook.py", line 38, in ratio_hook - raise ValueError(f"Missing required input: min_force") -ValueError: Missing required input: min_force -Hook 'ratio_hook' failed: Missing required input: min_force -Required input 'max_stress' not found in context -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\safety_factor_hook.py", line 38, in safety_factor_hook - raise ValueError(f"Missing required input: max_stress") -ValueError: Missing required input: max_stress -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Required input 'norm_stress' not found in context -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\weighted_objective_test.py", line 38, in weighted_objective_hook - raise ValueError(f"Missing required input: norm_stress") -ValueError: Missing required input: norm_stress -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress - [WARNING] No explicit objective, using: max_displacement -[I 2025-11-16 20:43:58,153] A new study created in RDB with name: bracket_displacement_maximizing -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 -Validation Results: - [OK] extractor: ['max_displacement', 'max_disp_node', 'max_disp_x', 'max_disp_y', 'max_disp_z'] - [OK] extractor: ['max_von_mises', 'max_stress_element'] - [OK] calculation: Created ['safety_factor'] - [OK] calculation: Created ['safety_factor', 'neg_displacement'] - [OK] hook: 3 results - [OK] objective: 0.36178338527679443 - -[SUCCESS] All pipeline components validated! - - -================================================================================ - STEP 7: OPTIMIZATION SETUP -================================================================================ - -Creating model updater and simulation runner... - [OK] Model updater ready - [OK] Simulation runner ready - -Initializing LLM optimization runner... - [OK] Output directory: c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_results\bracket_displacement_maximizing - [OK] Extractors generated: 2 - [OK] Inline calculations: 2 - [OK] Hooks loaded: 9 - - -================================================================================ - STEP 8: RUNNING OPTIMIZATION -================================================================================ - -Starting 20-trial optimization... -(This will take several minutes) - - -Updating 2 expressions in Bracket.prt: -Updated: tip_thickness = 17 -> 24 -Updated: support_angle = 38 -> 25 -Successfully updated 2/2 expressions -Backup created: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt.bak_20251116_204358 -Saved to: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt - -[NX SOLVER] Starting simulation... - Input file: Bracket_sim1.sim - Working dir: c:\Users\antoi\Documents\Atomaste\Atomizer\tests - Mode: Journal - Warning: Could not delete bracket_sim1-solution_1.log: [WinError 32] The process cannot access the file because it is being used by another process: 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.log' - Deleted 2 old result file(s) to force fresh solve -[JOURNAL OUTPUT] - Mesh-Based Errors Summary - ------------------------- - - Total: 0 errors and 0 warnings - - - Material-Based Errors Summary - ----------------------------- - - Total: 0 errors and 0 warnings - - - Solution-Based Errors Summary - ----------------------------- - - Iterative Solver Option - More than 80 percent of the elements in this model are 3D elements. - It is therefore recommended that you turn ON the Element Iterative Solver in the "Edit - Solution" dialog. - - Total: 0 errors and 0 warnings - - - Load/BC-Based Errors Summary - ---------------------------- - - Total: 0 errors and 0 warnings - - - Nastran Model Setup Check completed - - - - - *** 20:44:01 *** - Starting Nastran Exporter - - *** 20:44:01 *** - Writing file - c:\Users\antoi\Documents\Atomaste\Atomizer\tests\bracket_sim1-solution_1.dat - - *** 20:44:01 *** - Writing SIMCENTER NASTRAN 2412.0 compatible deck - - *** 20:44:01 *** - Writing Nastran System section - - *** 20:44:01 *** - Writing File Management section - - *** 20:44:01 *** - Writing Executive Control section - - *** 20:44:01 *** - Writing Case Control section - - *** 20:44:01 *** - Writing Bulk Data section - - *** 20:44:01 *** - Writing Nodes - - *** 20:44:01 *** - Writing Elements - - *** 20:44:01 *** - Writing Physical Properties - - *** 20:44:01 *** - Writing Materials - - *** 20:44:01 *** - Writing Degree-of-Freedom Sets - - *** 20:44:01 *** - Writing Loads and Constraints - - *** 20:44:01 *** - Writing Coordinate Systems - - *** 20:44:01 *** - Validating Solution Setup - - *** 20:44:01 *** - Summary of Bulk Data cards written - - +----------+----------+ - | NAME | NUMBER | - +----------+----------+ - | CHEXA | 306 | - | CPENTA | 10 | - | FORCE | 3 | - | GRID | 585 | - | MAT1 | 1 | - | MATT1 | 1 | - | PARAM | 6 | - | PSOLID | 1 | - | SPC | 51 | - | TABLEM1 | 3 | - +----------+----------+ - - *** 20:44:01 *** - Nastran Deck Successfully Written - - [JOURNAL] Opening simulation: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket_sim1.sim - [JOURNAL] Checking for open parts... - [JOURNAL] Opening simulation fresh from disk... - [JOURNAL] STEP 1: Updating Bracket.prt geometry... - [JOURNAL] Rebuilding geometry with new expression values... - [JOURNAL] Bracket geometry updated (0 errors) - [JOURNAL] STEP 2: Opening Bracket_fem1.fem... - [JOURNAL] Updating FE Model... - [JOURNAL] FE Model updated with new geometry! - [JOURNAL] STEP 3: Switching back to sim part... - [JOURNAL] Switched back to sim part - [JOURNAL] Starting solve... - [JOURNAL] Solve submitted! - [JOURNAL] Solutions solved: -1472058762 - [JOURNAL] Solutions failed: 32764 - [JOURNAL] Solutions skipped: -630324672 - [JOURNAL] Saving simulation to ensure output files are written... - [JOURNAL] Save complete! -[JOURNAL ERRORS] - Journal execution results for c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py... - Syntax errors: - Line 0: Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py", line 247, in - sys.exit(0 if success else 1) -[NX SOLVER] Waiting for solve to complete... -[NX SOLVER] Output files detected after 0.5s -[NX SOLVER] Complete in 4.4s -[NX SOLVER] Results: bracket_sim1-solution_1.op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -Extraction failed: extract_solid_stress - 1 -Extraction failed for extract_solid_stress: 1 -Inline calculation failed: name 'max_von_mises' is not defined -Required input 'min_force' not found in context -Hook 'ratio_hook' failed: Missing required input: min_force -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\min_to_avg_ratio_hook.py", line 38, in ratio_hook - raise ValueError(f"Missing required input: min_force") -ValueError: Missing required input: min_force -Hook 'ratio_hook' failed: Missing required input: min_force -Required input 'max_stress' not found in context -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\safety_factor_hook.py", line 38, in safety_factor_hook - raise ValueError(f"Missing required input: max_stress") -ValueError: Missing required input: max_stress -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Required input 'norm_stress' not found in context -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\weighted_objective_test.py", line 38, in weighted_objective_hook - raise ValueError(f"Missing required input: norm_stress") -ValueError: Missing required input: norm_stress -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -No explicit objective found, using: max_displacement -[I 2025-11-16 20:44:03,240] Trial 0 finished with value: 0.36178338527679443 and parameters: {'tip_thickness': 24.057174360465407, 'support_angle': 25.35525889588185}. Best is trial 0 with value: 0.36178338527679443. -DEBUG: op2.py:648 finished reading op2 - -Updating 2 expressions in Bracket.prt: -Updated: tip_thickness = 24 -> 18 -Updated: support_angle = 25 -> 25 -Successfully updated 2/2 expressions -Backup created: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt.bak_20251116_204403 -Saved to: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt - -[NX SOLVER] Starting simulation... - Input file: Bracket_sim1.sim - Working dir: c:\Users\antoi\Documents\Atomaste\Atomizer\tests - Mode: Journal - Warning: Could not delete bracket_sim1-solution_1.log: [WinError 32] The process cannot access the file because it is being used by another process: 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.log' - Deleted 2 old result file(s) to force fresh solve -[JOURNAL OUTPUT] - Mesh-Based Errors Summary - ------------------------- - - Total: 0 errors and 0 warnings - - - Material-Based Errors Summary - ----------------------------- - - Total: 0 errors and 0 warnings - - - Solution-Based Errors Summary - ----------------------------- - - Iterative Solver Option - More than 80 percent of the elements in this model are 3D elements. - It is therefore recommended that you turn ON the Element Iterative Solver in the "Edit - Solution" dialog. - - Total: 0 errors and 0 warnings - - - Load/BC-Based Errors Summary - ---------------------------- - - Total: 0 errors and 0 warnings - - - Nastran Model Setup Check completed - - - - - *** 20:44:06 *** - Starting Nastran Exporter - - *** 20:44:06 *** - Writing file - c:\Users\antoi\Documents\Atomaste\Atomizer\tests\bracket_sim1-solution_1.dat - - *** 20:44:06 *** - Writing SIMCENTER NASTRAN 2412.0 compatible deck - - *** 20:44:06 *** - Writing Nastran System section - - *** 20:44:06 *** - Writing File Management section - - *** 20:44:06 *** - Writing Executive Control section - - *** 20:44:06 *** - Writing Case Control section - - *** 20:44:06 *** - Writing Bulk Data section - - *** 20:44:06 *** - Writing Nodes - - *** 20:44:06 *** - Writing Elements - - *** 20:44:06 *** - Writing Physical Properties - - *** 20:44:06 *** - Writing Materials - - *** 20:44:06 *** - Writing Degree-of-Freedom Sets - - *** 20:44:06 *** - Writing Loads and Constraints - - *** 20:44:06 *** - Writing Coordinate Systems - - *** 20:44:06 *** - Validating Solution Setup - - *** 20:44:06 *** - Summary of Bulk Data cards written - - +----------+----------+ - | NAME | NUMBER | - +----------+----------+ - | CHEXA | 306 | - | CPENTA | 10 | - | FORCE | 3 | - | GRID | 585 | - | MAT1 | 1 | - | MATT1 | 1 | - | PARAM | 6 | - | PSOLID | 1 | - | SPC | 51 | - | TABLEM1 | 3 | - +----------+----------+ - - *** 20:44:06 *** - Nastran Deck Successfully Written - - [JOURNAL] Opening simulation: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket_sim1.sim - [JOURNAL] Checking for open parts... - [JOURNAL] Opening simulation fresh from disk... - [JOURNAL] STEP 1: Updating Bracket.prt geometry... - [JOURNAL] Rebuilding geometry with new expression values... - [JOURNAL] Bracket geometry updated (0 errors) - [JOURNAL] STEP 2: Opening Bracket_fem1.fem... - [JOURNAL] Updating FE Model... - [JOURNAL] FE Model updated with new geometry! - [JOURNAL] STEP 3: Switching back to sim part... - [JOURNAL] Switched back to sim part - [JOURNAL] Starting solve... - [JOURNAL] Solve submitted! - [JOURNAL] Solutions solved: -1925305738 - [JOURNAL] Solutions failed: 32764 - [JOURNAL] Solutions skipped: 1225720384 - [JOURNAL] Saving simulation to ensure output files are written... - [JOURNAL] Save complete! -[JOURNAL ERRORS] - Journal execution results for c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py... - Syntax errors: - Line 0: Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py", line 247, in - sys.exit(0 if success else 1) -[NX SOLVER] Waiting for solve to complete... -[NX SOLVER] Output files detected after 0.5s -[NX SOLVER] Complete in 4.4s -[NX SOLVER] Results: bracket_sim1-solution_1.op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -Extraction failed: extract_solid_stress - 1 -Extraction failed for extract_solid_stress: 1 -Inline calculation failed: name 'max_von_mises' is not defined -Required input 'min_force' not found in context -Hook 'ratio_hook' failed: Missing required input: min_force -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\min_to_avg_ratio_hook.py", line 38, in ratio_hook - raise ValueError(f"Missing required input: min_force") -ValueError: Missing required input: min_force -Hook 'ratio_hook' failed: Missing required input: min_force -Required input 'max_stress' not found in context -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\safety_factor_hook.py", line 38, in safety_factor_hook - raise ValueError(f"Missing required input: max_stress") -ValueError: Missing required input: max_stress -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Required input 'norm_stress' not found in context -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\weighted_objective_test.py", line 38, in weighted_objective_hook - raise ValueError(f"Missing required input: norm_stress") -ValueError: Missing required input: norm_stress -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -No explicit objective found, using: max_displacement -[I 2025-11-16 20:44:08,320] Trial 1 finished with value: 0.36178338527679443 and parameters: {'tip_thickness': 18.304620477081855, 'support_angle': 25.394969100877468}. Best is trial 0 with value: 0.36178338527679443. -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 - -Updating 2 expressions in Bracket.prt: -Updated: tip_thickness = 18 -> 19 -Updated: support_angle = 25 -> 31 -Successfully updated 2/2 expressions -Backup created: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt.bak_20251116_204408 -Saved to: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt - -[NX SOLVER] Starting simulation... - Input file: Bracket_sim1.sim - Working dir: c:\Users\antoi\Documents\Atomaste\Atomizer\tests - Mode: Journal - Warning: Could not delete bracket_sim1-solution_1.log: [WinError 32] The process cannot access the file because it is being used by another process: 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.log' - Deleted 2 old result file(s) to force fresh solve -[JOURNAL OUTPUT] - Mesh-Based Errors Summary - ------------------------- - - Total: 0 errors and 0 warnings - - - Material-Based Errors Summary - ----------------------------- - - Total: 0 errors and 0 warnings - - - Solution-Based Errors Summary - ----------------------------- - - Iterative Solver Option - More than 80 percent of the elements in this model are 3D elements. - It is therefore recommended that you turn ON the Element Iterative Solver in the "Edit - Solution" dialog. - - Total: 0 errors and 0 warnings - - - Load/BC-Based Errors Summary - ---------------------------- - - Total: 0 errors and 0 warnings - - - Nastran Model Setup Check completed - - - - - *** 20:44:11 *** - Starting Nastran Exporter - - *** 20:44:11 *** - Writing file - c:\Users\antoi\Documents\Atomaste\Atomizer\tests\bracket_sim1-solution_1.dat - - *** 20:44:11 *** - Writing SIMCENTER NASTRAN 2412.0 compatible deck - - *** 20:44:11 *** - Writing Nastran System section - - *** 20:44:11 *** - Writing File Management section - - *** 20:44:11 *** - Writing Executive Control section - - *** 20:44:11 *** - Writing Case Control section - - *** 20:44:11 *** - Writing Bulk Data section - - *** 20:44:11 *** - Writing Nodes - - *** 20:44:11 *** - Writing Elements - - *** 20:44:11 *** - Writing Physical Properties - - *** 20:44:11 *** - Writing Materials - - *** 20:44:11 *** - Writing Degree-of-Freedom Sets - - *** 20:44:11 *** - Writing Loads and Constraints - - *** 20:44:11 *** - Writing Coordinate Systems - - *** 20:44:11 *** - Validating Solution Setup - - *** 20:44:11 *** - Summary of Bulk Data cards written - - +----------+----------+ - | NAME | NUMBER | - +----------+----------+ - | CHEXA | 306 | - | CPENTA | 10 | - | FORCE | 3 | - | GRID | 585 | - | MAT1 | 1 | - | MATT1 | 1 | - | PARAM | 6 | - | PSOLID | 1 | - | SPC | 51 | - | TABLEM1 | 3 | - +----------+----------+ - - *** 20:44:11 *** - Nastran Deck Successfully Written - - [JOURNAL] Opening simulation: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket_sim1.sim - [JOURNAL] Checking for open parts... - [JOURNAL] Opening simulation fresh from disk... - [JOURNAL] STEP 1: Updating Bracket.prt geometry... - [JOURNAL] Rebuilding geometry with new expression values... - [JOURNAL] Bracket geometry updated (0 errors) - [JOURNAL] STEP 2: Opening Bracket_fem1.fem... - [JOURNAL] Updating FE Model... - [JOURNAL] FE Model updated with new geometry! - [JOURNAL] STEP 3: Switching back to sim part... - [JOURNAL] Switched back to sim part - [JOURNAL] Starting solve... - [JOURNAL] Solve submitted! - [JOURNAL] Solutions solved: -1928254858 - [JOURNAL] Solutions failed: 32764 - [JOURNAL] Solutions skipped: -613678528 - [JOURNAL] Saving simulation to ensure output files are written... - [JOURNAL] Save complete! -[JOURNAL ERRORS] - Journal execution results for c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py... - Syntax errors: - Line 0: Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py", line 247, in - sys.exit(0 if success else 1) -[NX SOLVER] Waiting for solve to complete... -[NX SOLVER] Output files detected after 0.5s -[NX SOLVER] Complete in 4.5s -[NX SOLVER] Results: bracket_sim1-solution_1.op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -Extraction failed: extract_solid_stress - 1 -Extraction failed for extract_solid_stress: 1 -Inline calculation failed: name 'max_von_mises' is not defined -Required input 'min_force' not found in context -Hook 'ratio_hook' failed: Missing required input: min_force -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\min_to_avg_ratio_hook.py", line 38, in ratio_hook - raise ValueError(f"Missing required input: min_force") -ValueError: Missing required input: min_force -Hook 'ratio_hook' failed: Missing required input: min_force -Required input 'max_stress' not found in context -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\safety_factor_hook.py", line 38, in safety_factor_hook - raise ValueError(f"Missing required input: max_stress") -ValueError: Missing required input: max_stress -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Required input 'norm_stress' not found in context -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\weighted_objective_test.py", line 38, in weighted_objective_hook - raise ValueError(f"Missing required input: norm_stress") -ValueError: Missing required input: norm_stress -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -No explicit objective found, using: max_displacement -[I 2025-11-16 20:44:13,424] Trial 2 finished with value: 0.36178338527679443 and parameters: {'tip_thickness': 19.533548039349455, 'support_angle': 31.844371833801826}. Best is trial 0 with value: 0.36178338527679443. -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 - -Updating 2 expressions in Bracket.prt: -Updated: tip_thickness = 19 -> 22 -Updated: support_angle = 31 -> 22 -Successfully updated 2/2 expressions -Backup created: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt.bak_20251116_204413 -Saved to: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt - -[NX SOLVER] Starting simulation... - Input file: Bracket_sim1.sim - Working dir: c:\Users\antoi\Documents\Atomaste\Atomizer\tests - Mode: Journal - Warning: Could not delete bracket_sim1-solution_1.log: [WinError 32] The process cannot access the file because it is being used by another process: 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.log' - Deleted 2 old result file(s) to force fresh solve -[JOURNAL OUTPUT] - Mesh-Based Errors Summary - ------------------------- - - Total: 0 errors and 0 warnings - - - Material-Based Errors Summary - ----------------------------- - - Total: 0 errors and 0 warnings - - - Solution-Based Errors Summary - ----------------------------- - - Iterative Solver Option - More than 80 percent of the elements in this model are 3D elements. - It is therefore recommended that you turn ON the Element Iterative Solver in the "Edit - Solution" dialog. - - Total: 0 errors and 0 warnings - - - Load/BC-Based Errors Summary - ---------------------------- - - Total: 0 errors and 0 warnings - - - Nastran Model Setup Check completed - - - - - *** 20:44:16 *** - Starting Nastran Exporter - - *** 20:44:16 *** - Writing file - c:\Users\antoi\Documents\Atomaste\Atomizer\tests\bracket_sim1-solution_1.dat - - *** 20:44:16 *** - Writing SIMCENTER NASTRAN 2412.0 compatible deck - - *** 20:44:16 *** - Writing Nastran System section - - *** 20:44:16 *** - Writing File Management section - - *** 20:44:16 *** - Writing Executive Control section - - *** 20:44:16 *** - Writing Case Control section - - *** 20:44:16 *** - Writing Bulk Data section - - *** 20:44:16 *** - Writing Nodes - - *** 20:44:16 *** - Writing Elements - - *** 20:44:16 *** - Writing Physical Properties - - *** 20:44:16 *** - Writing Materials - - *** 20:44:16 *** - Writing Degree-of-Freedom Sets - - *** 20:44:16 *** - Writing Loads and Constraints - - *** 20:44:16 *** - Writing Coordinate Systems - - *** 20:44:16 *** - Validating Solution Setup - - *** 20:44:16 *** - Summary of Bulk Data cards written - - +----------+----------+ - | NAME | NUMBER | - +----------+----------+ - | CHEXA | 306 | - | CPENTA | 10 | - | FORCE | 3 | - | GRID | 585 | - | MAT1 | 1 | - | MATT1 | 1 | - | PARAM | 6 | - | PSOLID | 1 | - | SPC | 51 | - | TABLEM1 | 3 | - +----------+----------+ - - *** 20:44:16 *** - Nastran Deck Successfully Written - - [JOURNAL] Opening simulation: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket_sim1.sim - [JOURNAL] Checking for open parts... - [JOURNAL] Opening simulation fresh from disk... - [JOURNAL] STEP 1: Updating Bracket.prt geometry... - [JOURNAL] Rebuilding geometry with new expression values... - [JOURNAL] Bracket geometry updated (0 errors) - [JOURNAL] STEP 2: Opening Bracket_fem1.fem... - [JOURNAL] Updating FE Model... - [JOURNAL] FE Model updated with new geometry! - [JOURNAL] STEP 3: Switching back to sim part... - [JOURNAL] Switched back to sim part - [JOURNAL] Starting solve... - [JOURNAL] Solve submitted! - [JOURNAL] Solutions solved: -1930483082 - [JOURNAL] Solutions failed: 32764 - [JOURNAL] Solutions skipped: -1732705728 - [JOURNAL] Saving simulation to ensure output files are written... - [JOURNAL] Save complete! -[JOURNAL ERRORS] - Journal execution results for c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py... - Syntax errors: - Line 0: Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py", line 247, in - sys.exit(0 if success else 1) -[NX SOLVER] Waiting for solve to complete... -[NX SOLVER] Output files detected after 0.5s -[NX SOLVER] Complete in 4.7s -[NX SOLVER] Results: bracket_sim1-solution_1.op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -Extraction failed: extract_solid_stress - 1 -Extraction failed for extract_solid_stress: 1 -Inline calculation failed: name 'max_von_mises' is not defined -Required input 'min_force' not found in context -Hook 'ratio_hook' failed: Missing required input: min_force -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\min_to_avg_ratio_hook.py", line 38, in ratio_hook - raise ValueError(f"Missing required input: min_force") -ValueError: Missing required input: min_force -Hook 'ratio_hook' failed: Missing required input: min_force -Required input 'max_stress' not found in context -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\safety_factor_hook.py", line 38, in safety_factor_hook - raise ValueError(f"Missing required input: max_stress") -ValueError: Missing required input: max_stress -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Required input 'norm_stress' not found in context -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\weighted_objective_test.py", line 38, in weighted_objective_hook - raise ValueError(f"Missing required input: norm_stress") -ValueError: Missing required input: norm_stress -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -No explicit objective found, using: max_displacement -[I 2025-11-16 20:44:18,839] Trial 3 finished with value: 0.36178338527679443 and parameters: {'tip_thickness': 22.92830934942418, 'support_angle': 22.883083847442386}. Best is trial 0 with value: 0.36178338527679443. -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 - -Updating 2 expressions in Bracket.prt: -Updated: tip_thickness = 22 -> 23 -Updated: support_angle = 22 -> 32 -Successfully updated 2/2 expressions -Backup created: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt.bak_20251116_204418 -Saved to: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt - -[NX SOLVER] Starting simulation... - Input file: Bracket_sim1.sim - Working dir: c:\Users\antoi\Documents\Atomaste\Atomizer\tests - Mode: Journal - Warning: Could not delete bracket_sim1-solution_1.log: [WinError 32] The process cannot access the file because it is being used by another process: 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.log' - Deleted 2 old result file(s) to force fresh solve -[JOURNAL OUTPUT] - Mesh-Based Errors Summary - ------------------------- - - Total: 0 errors and 0 warnings - - - Material-Based Errors Summary - ----------------------------- - - Total: 0 errors and 0 warnings - - - Solution-Based Errors Summary - ----------------------------- - - Iterative Solver Option - More than 80 percent of the elements in this model are 3D elements. - It is therefore recommended that you turn ON the Element Iterative Solver in the "Edit - Solution" dialog. - - Total: 0 errors and 0 warnings - - - Load/BC-Based Errors Summary - ---------------------------- - - Total: 0 errors and 0 warnings - - - Nastran Model Setup Check completed - - - - - *** 20:44:22 *** - Starting Nastran Exporter - - *** 20:44:22 *** - Writing file - c:\Users\antoi\Documents\Atomaste\Atomizer\tests\bracket_sim1-solution_1.dat - - *** 20:44:22 *** - Writing SIMCENTER NASTRAN 2412.0 compatible deck - - *** 20:44:22 *** - Writing Nastran System section - - *** 20:44:22 *** - Writing File Management section - - *** 20:44:22 *** - Writing Executive Control section - - *** 20:44:22 *** - Writing Case Control section - - *** 20:44:22 *** - Writing Bulk Data section - - *** 20:44:22 *** - Writing Nodes - - *** 20:44:22 *** - Writing Elements - - *** 20:44:22 *** - Writing Physical Properties - - *** 20:44:22 *** - Writing Materials - - *** 20:44:22 *** - Writing Degree-of-Freedom Sets - - *** 20:44:22 *** - Writing Loads and Constraints - - *** 20:44:22 *** - Writing Coordinate Systems - - *** 20:44:22 *** - Validating Solution Setup - - *** 20:44:22 *** - Summary of Bulk Data cards written - - +----------+----------+ - | NAME | NUMBER | - +----------+----------+ - | CHEXA | 306 | - | CPENTA | 10 | - | FORCE | 3 | - | GRID | 585 | - | MAT1 | 1 | - | MATT1 | 1 | - | PARAM | 6 | - | PSOLID | 1 | - | SPC | 51 | - | TABLEM1 | 3 | - +----------+----------+ - - *** 20:44:22 *** - Nastran Deck Successfully Written - - [JOURNAL] Opening simulation: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket_sim1.sim - [JOURNAL] Checking for open parts... - [JOURNAL] Opening simulation fresh from disk... - [JOURNAL] STEP 1: Updating Bracket.prt geometry... - [JOURNAL] Rebuilding geometry with new expression values... - [JOURNAL] Bracket geometry updated (0 errors) - [JOURNAL] STEP 2: Opening Bracket_fem1.fem... - [JOURNAL] Updating FE Model... - [JOURNAL] FE Model updated with new geometry! - [JOURNAL] STEP 3: Switching back to sim part... - [JOURNAL] Switched back to sim part - [JOURNAL] Starting solve... - [JOURNAL] Solve submitted! - [JOURNAL] Solutions solved: -1932776842 - [JOURNAL] Solutions failed: 32764 - [JOURNAL] Solutions skipped: -1299054016 - [JOURNAL] Saving simulation to ensure output files are written... - [JOURNAL] Save complete! -[JOURNAL ERRORS] - Journal execution results for c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py... - Syntax errors: - Line 0: Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py", line 247, in - sys.exit(0 if success else 1) -[NX SOLVER] Waiting for solve to complete... -[NX SOLVER] Output files detected after 0.5s -[NX SOLVER] Complete in 4.7s -[NX SOLVER] Results: bracket_sim1-solution_1.op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:634 -------- reading op2 with read_mode=2 (array filling) -------- -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -Extraction failed: extract_solid_stress - 1 -Extraction failed for extract_solid_stress: 1 -Inline calculation failed: name 'max_von_mises' is not defined -Required input 'min_force' not found in context -Hook 'ratio_hook' failed: Missing required input: min_force -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\min_to_avg_ratio_hook.py", line 38, in ratio_hook - raise ValueError(f"Missing required input: min_force") -ValueError: Missing required input: min_force -Hook 'ratio_hook' failed: Missing required input: min_force -Required input 'max_stress' not found in context -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\safety_factor_hook.py", line 38, in safety_factor_hook - raise ValueError(f"Missing required input: max_stress") -ValueError: Missing required input: max_stress -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Required input 'norm_stress' not found in context -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\weighted_objective_test.py", line 38, in weighted_objective_hook - raise ValueError(f"Missing required input: norm_stress") -ValueError: Missing required input: norm_stress -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -No explicit objective found, using: max_displacement -[I 2025-11-16 20:44:24,252] Trial 4 finished with value: 0.36178338527679443 and parameters: {'tip_thickness': 23.722396426593477, 'support_angle': 32.99896902425434}. Best is trial 0 with value: 0.36178338527679443. -Extraction failed: extract_displacement - There was a Nastran FATAL Error. Check the F06. -last table=b'EQEXIN'; post=-1 version='nx' -Extraction failed for extract_displacement: There was a Nastran FATAL Error. Check the F06. -last table=b'EQEXIN'; post=-1 version='nx' -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) -DEBUG: op2_scalar.py:2173 table_name=b'OQG1' (spc/mpc forces) -DEBUG: op2_scalar.py:2173 table_name=b'BOUGV1' (g-set U in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'OES1' (linear stress) -DEBUG: oes.py:2840 numwide_real=193 -DEBUG: oes.py:2840 numwide_real=151 -DEBUG: op2.py:932 combine_results -DEBUG: op2.py:648 finished reading op2 - -Updating 2 expressions in Bracket.prt: -Updated: tip_thickness = 23 -> 21 -Updated: support_angle = 32 -> 28 -Successfully updated 2/2 expressions -Backup created: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt.bak_20251116_204424 -Saved to: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket.prt - -[NX SOLVER] Starting simulation... - Input file: Bracket_sim1.sim - Working dir: c:\Users\antoi\Documents\Atomaste\Atomizer\tests - Mode: Journal - Warning: Could not delete bracket_sim1-solution_1.log: [WinError 32] The process cannot access the file because it is being used by another process: 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.log' - Deleted 2 old result file(s) to force fresh solve -[JOURNAL OUTPUT] - Mesh-Based Errors Summary - ------------------------- - - Total: 0 errors and 0 warnings - - - Material-Based Errors Summary - ----------------------------- - - Total: 0 errors and 0 warnings - - - Solution-Based Errors Summary - ----------------------------- - - Iterative Solver Option - More than 80 percent of the elements in this model are 3D elements. - It is therefore recommended that you turn ON the Element Iterative Solver in the "Edit - Solution" dialog. - - Total: 0 errors and 0 warnings - - - Load/BC-Based Errors Summary - ---------------------------- - - Total: 0 errors and 0 warnings - - - Nastran Model Setup Check completed - - - - - *** 20:44:27 *** - Starting Nastran Exporter - - *** 20:44:27 *** - Writing file - c:\Users\antoi\Documents\Atomaste\Atomizer\tests\bracket_sim1-solution_1.dat - - *** 20:44:27 *** - Writing SIMCENTER NASTRAN 2412.0 compatible deck - - *** 20:44:27 *** - Writing Nastran System section - - *** 20:44:27 *** - Writing File Management section - - *** 20:44:27 *** - Writing Executive Control section - - *** 20:44:27 *** - Writing Case Control section - - *** 20:44:27 *** - Writing Bulk Data section - - *** 20:44:27 *** - Writing Nodes - - *** 20:44:27 *** - Writing Elements - - *** 20:44:27 *** - Writing Physical Properties - - *** 20:44:27 *** - Writing Materials - - *** 20:44:27 *** - Writing Degree-of-Freedom Sets - - *** 20:44:27 *** - Writing Loads and Constraints - - *** 20:44:27 *** - Writing Coordinate Systems - - *** 20:44:27 *** - Validating Solution Setup - - *** 20:44:27 *** - Summary of Bulk Data cards written - - +----------+----------+ - | NAME | NUMBER | - +----------+----------+ - | CHEXA | 306 | - | CPENTA | 10 | - | FORCE | 3 | - | GRID | 585 | - | MAT1 | 1 | - | MATT1 | 1 | - | PARAM | 6 | - | PSOLID | 1 | - | SPC | 51 | - | TABLEM1 | 3 | - +----------+----------+ - - *** 20:44:27 *** - Nastran Deck Successfully Written - - [JOURNAL] Opening simulation: c:\Users\antoi\Documents\Atomaste\Atomizer\tests\Bracket_sim1.sim - [JOURNAL] Checking for open parts... - [JOURNAL] Opening simulation fresh from disk... - [JOURNAL] STEP 1: Updating Bracket.prt geometry... - [JOURNAL] Rebuilding geometry with new expression values... - [JOURNAL] Bracket geometry updated (0 errors) - [JOURNAL] STEP 2: Opening Bracket_fem1.fem... - [JOURNAL] Updating FE Model... - [JOURNAL] FE Model updated with new geometry! - [JOURNAL] STEP 3: Switching back to sim part... - [JOURNAL] Switched back to sim part - [JOURNAL] Starting solve... - [JOURNAL] Solve submitted! - [JOURNAL] Solutions solved: -1934939530 - [JOURNAL] Solutions failed: 32764 - [JOURNAL] Solutions skipped: -803732928 - [JOURNAL] Saving simulation to ensure output files are written... - [JOURNAL] Save complete! -[JOURNAL ERRORS] - Journal execution results for c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py... - Syntax errors: - Line 0: Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\tests\_temp_solve_journal.py", line 247, in - sys.exit(0 if success else 1) -[NX SOLVER] Waiting for solve to complete... -[NX SOLVER] Output files detected after 0.5s -[NX SOLVER] Complete in 4.6s -[NX SOLVER] Results: bracket_sim1-solution_1.op2 -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) - -ndata = 0: - strings = (b'',) - ints = () - floats = () - -ERROR: op2_reader.py:2988 finished table_name = b'EQEXIN' -ERROR: op2_reader.py:2993 There was a Nastran FATAL Error. Check the F06. -last table=b'EQEXIN'; post=-1 version='nx' -DEBUG: op2.py:614 combine=True -DEBUG: op2.py:615 -------- reading op2 with read_mode=1 (array sizing) -------- -Extraction failed: extract_solid_stress - There was a Nastran FATAL Error. Check the F06. -last table=b'EQEXIN'; post=-1 version='nx' -Extraction failed for extract_solid_stress: There was a Nastran FATAL Error. Check the F06. -last table=b'EQEXIN'; post=-1 version='nx' -Inline calculation failed: name 'max_von_mises' is not defined -Inline calculation failed: name 'max_displacement' is not defined -Required input 'min_force' not found in context -Hook 'ratio_hook' failed: Missing required input: min_force -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\min_to_avg_ratio_hook.py", line 38, in ratio_hook - raise ValueError(f"Missing required input: min_force") -ValueError: Missing required input: min_force -Hook 'ratio_hook' failed: Missing required input: min_force -Required input 'max_stress' not found in context -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\safety_factor_hook.py", line 38, in safety_factor_hook - raise ValueError(f"Missing required input: max_stress") -ValueError: Missing required input: max_stress -Hook 'safety_factor_hook' failed: Missing required input: max_stress -Required input 'norm_stress' not found in context -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\hooks.py", line 72, in execute - result = self.function(context) - ^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\plugins\post_calculation\weighted_objective_test.py", line 38, in weighted_objective_hook - raise ValueError(f"Missing required input: norm_stress") -ValueError: Missing required input: norm_stress -Hook 'weighted_objective_hook' failed: Missing required input: norm_stress -[W 2025-11-16 20:44:29,500] Trial 5 failed with parameters: {'tip_thickness': 21.549788562837012, 'support_angle': 28.710108728807292} because of the following error: ValueError('Could not determine objective value from results/calculations/hooks'). -Traceback (most recent call last): - File "C:\Users\antoi\anaconda3\envs\test_env\Lib\site-packages\optuna\study\_optimize.py", line 201, in _run_trial - value_or_values = func(trial) - ^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\llm_optimization_runner.py", line 328, in _objective - raise ValueError("Could not determine objective value from results/calculations/hooks") -ValueError: Could not determine objective value from results/calculations/hooks -[W 2025-11-16 20:44:29,502] Trial 5 failed with value None. -INFO: op2_scalar.py:1960 op2_filename = 'c:\\Users\\antoi\\Documents\\Atomaste\\Atomizer\\tests\\bracket_sim1-solution_1.op2' -DEBUG: op2_reader.py:323 date = (11, 16, 25) -WARNING: version.py:88 nx version='2412' is not supported -DEBUG: op2_reader.py:403 mode='nx' version='2412' -DEBUG: op2_scalar.py:2173 table_name=b'IBULK' (explicit bulk data) -DEBUG: op2_scalar.py:2173 table_name=b'ICASE' (explicit case control) -DEBUG: op2_scalar.py:2173 table_name=b'CASECC' (case control) -DEBUG: op2_scalar.py:2173 table_name=b'PVT0' (PARAM cards) -DEBUG: op2_scalar.py:2173 table_name=b'GPL' (grid point list) -DEBUG: op2_scalar.py:2173 table_name=b'GPDT' (grid point locations) -DEBUG: op2_scalar.py:2173 table_name=b'EPT' (property cards) -DEBUG: op2_scalar.py:2173 table_name=b'MPT' (material cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM2' (element cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM3' (constraint cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM4' (load cards) -DEBUG: op2_scalar.py:2173 table_name=b'GEOM1' (grid/coord cards) -DEBUG: op2_scalar.py:2173 table_name=b'BGPDT' (grid points in cid=0 frame) -DEBUG: op2_scalar.py:2173 table_name=b'DIT' (TABLEx cards) -DEBUG: op2_scalar.py:2173 table_name=b'EQEXIN' (internal/external ids) -DEBUG: op2_reader.py:672 eqexin idata=(101, 585, 0, 0, 0, 0, 0) - -ndata = 0: - strings = (b'',) - ints = () - floats = () - -ERROR: op2_reader.py:2988 finished table_name = b'EQEXIN' -ERROR: op2_reader.py:2993 There was a Nastran FATAL Error. Check the F06. -last table=b'EQEXIN'; post=-1 version='nx' -Traceback (most recent call last): - File "c:\Users\antoi\Documents\Atomaste\Atomizer\studies\bracket_displacement_maximizing\run_optimization.py", line 283, in - main() - File "c:\Users\antoi\Documents\Atomaste\Atomizer\studies\bracket_displacement_maximizing\run_optimization.py", line 245, in main - results = runner.run_optimization(n_trials=20) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\llm_optimization_runner.py", line 368, in run_optimization - self.study.optimize(self._objective, n_trials=n_trials) - File "C:\Users\antoi\anaconda3\envs\test_env\Lib\site-packages\optuna\study\study.py", line 490, in optimize - _optimize( - File "C:\Users\antoi\anaconda3\envs\test_env\Lib\site-packages\optuna\study\_optimize.py", line 63, in _optimize - _optimize_sequential( - File "C:\Users\antoi\anaconda3\envs\test_env\Lib\site-packages\optuna\study\_optimize.py", line 160, in _optimize_sequential - frozen_trial_id = _run_trial(study, func, catch) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - File "C:\Users\antoi\anaconda3\envs\test_env\Lib\site-packages\optuna\study\_optimize.py", line 258, in _run_trial - raise func_err - File "C:\Users\antoi\anaconda3\envs\test_env\Lib\site-packages\optuna\study\_optimize.py", line 201, in _run_trial - value_or_values = func(trial) - ^^^^^^^^^^^ - File "c:\Users\antoi\Documents\Atomaste\Atomizer\optimization_engine\llm_optimization_runner.py", line 328, in _objective - raise ValueError("Could not determine objective value from results/calculations/hooks") -ValueError: Could not determine objective value from results/calculations/hooks diff --git a/studies/bracket_displacement_maximizing/run_optimization_old.py b/studies/bracket_displacement_maximizing/run_optimization_old.py deleted file mode 100644 index 053955a6..00000000 --- a/studies/bracket_displacement_maximizing/run_optimization_old.py +++ /dev/null @@ -1,283 +0,0 @@ -""" -Bracket Displacement Maximization Study -======================================== - -Complete optimization workflow using Phase 3.3 Wizard: -1. Setup wizard validates the complete pipeline -2. Auto-detects element types from OP2 -3. Runs 20-trial optimization -4. Generates comprehensive report - -Objective: Maximize displacement -Constraint: Safety factor >= 4.0 -Material: Aluminum 6061-T6 (Yield = 276 MPa) -Design Variables: tip_thickness (15-25mm), support_angle (20-40deg) -""" - -import sys -from pathlib import Path - -# Add parent directories to path -sys.path.insert(0, str(Path(__file__).parent.parent.parent)) - -from optimization_engine.config.setup_wizard import OptimizationSetupWizard -from optimization_engine.future.llm_optimization_runner import LLMOptimizationRunner -from optimization_engine.nx.solver import NXSolver -from optimization_engine.nx.updater import NXParameterUpdater -from datetime import datetime - - -def print_section(title: str): - """Print a section header.""" - print() - print("=" * 80) - print(f" {title}") - print("=" * 80) - print() - - -def main(): - print_section("BRACKET DISPLACEMENT MAXIMIZATION STUDY") - - print("Study Configuration:") - print(" - Objective: Maximize displacement") - print(" - Constraint: Safety factor >= 4.0") - print(" - Material: Aluminum 6061-T6 (Yield = 276 MPa)") - print(" - Design Variables:") - print(" * tip_thickness: 15-25 mm") - print(" * support_angle: 20-40 degrees") - print(" - Optimization trials: 20") - print() - - # File paths - base_dir = Path(__file__).parent.parent.parent - prt_file = base_dir / "tests" / "Bracket.prt" - sim_file = base_dir / "tests" / "Bracket_sim1.sim" - - if not prt_file.exists(): - print(f"ERROR: Part file not found: {prt_file}") - sys.exit(1) - - if not sim_file.exists(): - print(f"ERROR: Simulation file not found: {sim_file}") - sys.exit(1) - - print(f"Part file: {prt_file}") - print(f"Simulation file: {sim_file}") - print() - - # ========================================================================= - # PHASE 3.3: OPTIMIZATION SETUP WIZARD - # ========================================================================= - - print_section("STEP 1: INITIALIZATION") - - print("Initializing Optimization Setup Wizard...") - wizard = OptimizationSetupWizard(prt_file, sim_file) - print(" [OK] Wizard initialized") - print() - - print_section("STEP 2: MODEL INTROSPECTION") - - print("Reading NX model expressions...") - model_info = wizard.introspect_model() - - print(f"Found {len(model_info.expressions)} expressions:") - for name, info in model_info.expressions.items(): - print(f" - {name}: {info['value']} {info['units']}") - print() - - print_section("STEP 3: BASELINE SIMULATION") - - print("Running baseline simulation to generate reference OP2...") - print("(This validates that NX simulation works before optimization)") - baseline_op2 = wizard.run_baseline_simulation() - print(f" [OK] Baseline OP2: {baseline_op2.name}") - print() - - print_section("STEP 4: OP2 INTROSPECTION") - - print("Analyzing OP2 file to auto-detect element types...") - op2_info = wizard.introspect_op2() - - print("OP2 Contents:") - print(f" - Element types with stress: {', '.join(op2_info.element_types)}") - print(f" - Available result types: {', '.join(op2_info.result_types)}") - print(f" - Subcases: {op2_info.subcases}") - print(f" - Nodes: {op2_info.node_count}") - print(f" - Elements: {op2_info.element_count}") - print() - - print_section("STEP 5: WORKFLOW CONFIGURATION") - - print("Building LLM workflow with auto-detected element types...") - - # Use the FIRST detected element type (could be CHEXA, CPENTA, CTETRA, etc.) - detected_element_type = op2_info.element_types[0].lower() if op2_info.element_types else 'ctetra' - - print(f" Using detected element type: {detected_element_type.upper()}") - print() - - llm_workflow = { - 'engineering_features': [ - { - 'action': 'extract_displacement', - 'domain': 'result_extraction', - 'description': 'Extract displacement results from OP2 file', - 'params': {'result_type': 'displacement'} - }, - { - 'action': 'extract_solid_stress', - 'domain': 'result_extraction', - 'description': f'Extract von Mises stress from {detected_element_type.upper()} elements', - 'params': { - 'result_type': 'stress', - 'element_type': detected_element_type # AUTO-DETECTED! - } - } - ], - 'inline_calculations': [ - { - 'action': 'calculate_safety_factor', - 'params': { - 'input': 'max_von_mises', - 'yield_strength': 276.0, # MPa for Aluminum 6061-T6 - 'operation': 'divide' - }, - 'code_hint': 'safety_factor = 276.0 / max_von_mises' - }, - { - 'action': 'negate_displacement', - 'params': { - 'input': 'max_displacement', - 'operation': 'negate' - }, - 'code_hint': 'neg_displacement = -max_displacement' - } - ], - 'post_processing_hooks': [], # Using manual safety_factor_constraint hook - 'optimization': { - 'algorithm': 'TPE', - 'direction': 'minimize', # Minimize neg_displacement = maximize displacement - 'design_variables': [ - { - 'parameter': 'tip_thickness', - 'min': 15.0, - 'max': 25.0, - 'units': 'mm' - }, - { - 'parameter': 'support_angle', - 'min': 20.0, - 'max': 40.0, - 'units': 'degrees' - } - ] - } - } - - print_section("STEP 6: PIPELINE VALIDATION") - - print("Validating complete pipeline with baseline OP2...") - print("(Dry-run test of extractors, calculations, hooks, objective)") - print() - - validation_results = wizard.validate_pipeline(llm_workflow) - - all_passed = all(r.success for r in validation_results) - - print("Validation Results:") - for result in validation_results: - status = "[OK]" if result.success else "[FAIL]" - print(f" {status} {result.component}: {result.message.split(':')[-1].strip()}") - print() - - if not all_passed: - print("[FAILED] Pipeline validation failed!") - print("Fix the issues above before running optimization.") - sys.exit(1) - - print("[SUCCESS] All pipeline components validated!") - print() - - print_section("STEP 7: OPTIMIZATION SETUP") - - print("Creating model updater and simulation runner...") - - # Model updater - updater = NXParameterUpdater(prt_file_path=prt_file) - def model_updater(design_vars: dict): - updater.update_expressions(design_vars) - updater.save() - - # Simulation runner - solver = NXSolver(nastran_version='2412', use_journal=True) - def simulation_runner() -> Path: - result = solver.run_simulation(sim_file) - return result['op2_file'] - - print(" [OK] Model updater ready") - print(" [OK] Simulation runner ready") - print() - - print("Initializing LLM optimization runner...") - runner = LLMOptimizationRunner( - llm_workflow=llm_workflow, - model_updater=model_updater, - simulation_runner=simulation_runner, - study_name='bracket_displacement_maximizing' - ) - - print(f" [OK] Output directory: {runner.output_dir}") - print(f" [OK] Extractors generated: {len(runner.extractors)}") - print(f" [OK] Inline calculations: {len(runner.inline_code)}") - hook_summary = runner.hook_manager.get_summary() - print(f" [OK] Hooks loaded: {hook_summary['enabled_hooks']}") - print() - - print_section("STEP 8: RUNNING OPTIMIZATION") - - print("Starting 20-trial optimization...") - print("(This will take several minutes)") - print() - - start_time = datetime.now() - results = runner.run_optimization(n_trials=20) - end_time = datetime.now() - - duration = (end_time - start_time).total_seconds() - - print() - print_section("OPTIMIZATION COMPLETE!") - - print(f"Duration: {duration:.1f} seconds ({duration/60:.1f} minutes)") - print() - print("Best Design Found:") - print(f" - tip_thickness: {results['best_params']['tip_thickness']:.3f} mm") - print(f" - support_angle: {results['best_params']['support_angle']:.3f} degrees") - print(f" - Objective value: {results['best_value']:.6f}") - print() - - # Show best trial details - best_trial = results['history'][results['best_trial_number']] - best_results = best_trial['results'] - best_calcs = best_trial['calculations'] - - print("Best Design Performance:") - print(f" - Max displacement: {best_results.get('max_displacement', 0):.6f} mm") - print(f" - Max stress: {best_results.get('max_von_mises', 0):.3f} MPa") - print(f" - Safety factor: {best_calcs.get('safety_factor', 0):.3f}") - print(f" - Constraint: {'SATISFIED' if best_calcs.get('safety_factor', 0) >= 4.0 else 'VIOLATED'}") - print() - - print(f"Results saved to: {runner.output_dir}") - print() - - print_section("STUDY COMPLETE!") - print("Phase 3.3 Optimization Setup Wizard successfully guided the") - print("complete optimization from setup through execution!") - print() - - -if __name__ == '__main__': - main() diff --git a/tests/analyze_v11.py b/tools/analysis/analyze_v11.py similarity index 100% rename from tests/analyze_v11.py rename to tools/analysis/analyze_v11.py diff --git a/tests/audit_v10_fix.py b/tools/analysis/audit_v10_fix.py similarity index 100% rename from tests/audit_v10_fix.py rename to tools/analysis/audit_v10_fix.py diff --git a/tests/audit_v10_method_diff.py b/tools/analysis/audit_v10_method_diff.py similarity index 100% rename from tests/audit_v10_method_diff.py rename to tools/analysis/audit_v10_method_diff.py diff --git a/tests/audit_v10_wfe.py b/tools/analysis/audit_v10_wfe.py similarity index 100% rename from tests/audit_v10_wfe.py rename to tools/analysis/audit_v10_wfe.py diff --git a/tests/check_api_routes.py b/tools/analysis/check_api_routes.py similarity index 100% rename from tests/check_api_routes.py rename to tools/analysis/check_api_routes.py diff --git a/tests/compare_v8_zernike_methods.py b/tools/analysis/compare_v8_zernike_methods.py similarity index 100% rename from tests/compare_v8_zernike_methods.py rename to tools/analysis/compare_v8_zernike_methods.py diff --git a/tests/debug_figure_coords.py b/tools/analysis/debug_figure_coords.py similarity index 100% rename from tests/debug_figure_coords.py rename to tools/analysis/debug_figure_coords.py diff --git a/tests/debug_insights.py b/tools/analysis/debug_insights.py similarity index 100% rename from tests/debug_insights.py rename to tools/analysis/debug_insights.py diff --git a/tests/debug_lateral_discrepancy.py b/tools/analysis/debug_lateral_discrepancy.py similarity index 100% rename from tests/debug_lateral_discrepancy.py rename to tools/analysis/debug_lateral_discrepancy.py