feat(canvas): Add Phase 3+4 - Bidirectional sync, templates, and visual polish
Phase 3 - Bidirectional Sync: - Add loadFromIntent and loadFromConfig to canvas store - Create useIntentParser hook for parsing Claude messages - Create ConfigImporter component (file upload, paste JSON, load study) - Add import/clear buttons to CanvasView header Phase 4 - Templates & Polish: - Create template library with 5 presets: - Mass Minimization (single-objective) - Multi-Objective Pareto (NSGA-II) - Turbo Mode (with MLP surrogate) - Mirror Zernike (optical optimization) - Frequency Optimization (modal) - Create TemplateSelector component with category filters - Enhanced BaseNode with animations, glow effects, status indicators - Add colorBg to all node types for visual distinction - Add notification toast system - Update all exports Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
5
atomizer-dashboard/frontend/src/lib/canvas/index.ts
Normal file
5
atomizer-dashboard/frontend/src/lib/canvas/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
// Canvas Library Exports
|
||||
export * from './schema';
|
||||
export * from './intent';
|
||||
export * from './validation';
|
||||
export * from './templates';
|
||||
278
atomizer-dashboard/frontend/src/lib/canvas/templates.ts
Normal file
278
atomizer-dashboard/frontend/src/lib/canvas/templates.ts
Normal file
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* Canvas Templates - Pre-built optimization workflow templates
|
||||
*
|
||||
* Each template provides a complete starting point for common optimization scenarios.
|
||||
*/
|
||||
|
||||
import { OptimizationIntent } from './intent';
|
||||
|
||||
export interface CanvasTemplate {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
category: 'structural' | 'optical' | 'general';
|
||||
icon: string;
|
||||
intent: OptimizationIntent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template 1: Mass Minimization
|
||||
* Single-objective optimization to minimize structural mass while maintaining stiffness
|
||||
*/
|
||||
const massMinimizationTemplate: CanvasTemplate = {
|
||||
id: 'mass_minimization',
|
||||
name: 'Mass Minimization',
|
||||
description: 'Minimize structural mass while maintaining stiffness constraints. Ideal for brackets, housings, and weight-critical components.',
|
||||
category: 'structural',
|
||||
icon: '⚖️',
|
||||
intent: {
|
||||
version: '1.0',
|
||||
source: 'canvas',
|
||||
timestamp: new Date().toISOString(),
|
||||
model: {
|
||||
path: undefined,
|
||||
type: 'prt',
|
||||
},
|
||||
solver: {
|
||||
type: 'SOL101',
|
||||
},
|
||||
design_variables: [
|
||||
{ name: 'wall_thickness', min: 1.0, max: 10.0, unit: 'mm' },
|
||||
{ name: 'rib_height', min: 5.0, max: 25.0, unit: 'mm' },
|
||||
{ name: 'fillet_radius', min: 1.0, max: 5.0, unit: 'mm' },
|
||||
],
|
||||
extractors: [
|
||||
{ id: 'E4', name: 'BDF Mass', config: {} },
|
||||
{ id: 'E1', name: 'Max Displacement', config: { node_set: 'ALL' } },
|
||||
],
|
||||
objectives: [
|
||||
{ name: 'mass', direction: 'minimize', weight: 1.0, extractor: 'E4' },
|
||||
],
|
||||
constraints: [
|
||||
{ name: 'max_displacement', operator: '<=', value: 0.5, extractor: 'E1' },
|
||||
],
|
||||
optimization: {
|
||||
method: 'TPE',
|
||||
max_trials: 100,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Template 2: Multi-Objective Pareto
|
||||
* Trade-off between mass and stiffness using NSGA-II
|
||||
*/
|
||||
const multiObjectiveTemplate: CanvasTemplate = {
|
||||
id: 'multi_objective',
|
||||
name: 'Multi-Objective Pareto',
|
||||
description: 'Explore trade-offs between competing objectives. Generates a Pareto front for informed decision-making.',
|
||||
category: 'structural',
|
||||
icon: '📊',
|
||||
intent: {
|
||||
version: '1.0',
|
||||
source: 'canvas',
|
||||
timestamp: new Date().toISOString(),
|
||||
model: {
|
||||
path: undefined,
|
||||
type: 'prt',
|
||||
},
|
||||
solver: {
|
||||
type: 'SOL101',
|
||||
},
|
||||
design_variables: [
|
||||
{ name: 'thickness', min: 2.0, max: 15.0, unit: 'mm' },
|
||||
{ name: 'width', min: 10.0, max: 50.0, unit: 'mm' },
|
||||
{ name: 'height', min: 20.0, max: 80.0, unit: 'mm' },
|
||||
],
|
||||
extractors: [
|
||||
{ id: 'E4', name: 'BDF Mass', config: {} },
|
||||
{ id: 'E1', name: 'Max Displacement', config: { node_set: 'ALL' } },
|
||||
{ id: 'E3', name: 'Max Stress', config: { element_set: 'ALL' } },
|
||||
],
|
||||
objectives: [
|
||||
{ name: 'mass', direction: 'minimize', weight: 1.0, extractor: 'E4' },
|
||||
{ name: 'displacement', direction: 'minimize', weight: 1.0, extractor: 'E1' },
|
||||
],
|
||||
constraints: [
|
||||
{ name: 'max_stress', operator: '<=', value: 250.0, extractor: 'E3' },
|
||||
],
|
||||
optimization: {
|
||||
method: 'NSGA-II',
|
||||
max_trials: 200,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Template 3: Turbo Mode with Surrogate
|
||||
* High-efficiency optimization using neural network surrogates
|
||||
*/
|
||||
const turboModeTemplate: CanvasTemplate = {
|
||||
id: 'turbo_mode',
|
||||
name: 'Turbo Mode',
|
||||
description: 'Accelerated optimization using neural network surrogates. Run thousands of virtual trials with periodic FEA validation.',
|
||||
category: 'general',
|
||||
icon: '🚀',
|
||||
intent: {
|
||||
version: '1.0',
|
||||
source: 'canvas',
|
||||
timestamp: new Date().toISOString(),
|
||||
model: {
|
||||
path: undefined,
|
||||
type: 'prt',
|
||||
},
|
||||
solver: {
|
||||
type: 'SOL101',
|
||||
},
|
||||
design_variables: [
|
||||
{ name: 'param_1', min: 0.0, max: 100.0 },
|
||||
{ name: 'param_2', min: 0.0, max: 100.0 },
|
||||
{ name: 'param_3', min: 0.0, max: 100.0 },
|
||||
{ name: 'param_4', min: 0.0, max: 100.0 },
|
||||
],
|
||||
extractors: [
|
||||
{ id: 'E1', name: 'Objective Extractor', config: {} },
|
||||
],
|
||||
objectives: [
|
||||
{ name: 'objective', direction: 'minimize', weight: 1.0, extractor: 'E1' },
|
||||
],
|
||||
constraints: [],
|
||||
optimization: {
|
||||
method: 'TPE',
|
||||
max_trials: 50,
|
||||
},
|
||||
surrogate: {
|
||||
enabled: true,
|
||||
type: 'MLP',
|
||||
min_trials: 20,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Template 4: Mirror Zernike Optimization
|
||||
* Optical surface optimization using Zernike polynomial decomposition
|
||||
*/
|
||||
const mirrorZernikeTemplate: CanvasTemplate = {
|
||||
id: 'mirror_zernike',
|
||||
name: 'Mirror Zernike',
|
||||
description: 'Optimize optical mirror surface quality using Zernike wavefront error metrics. Specialized for precision optics.',
|
||||
category: 'optical',
|
||||
icon: '🔭',
|
||||
intent: {
|
||||
version: '1.0',
|
||||
source: 'canvas',
|
||||
timestamp: new Date().toISOString(),
|
||||
model: {
|
||||
path: undefined,
|
||||
type: 'prt',
|
||||
},
|
||||
solver: {
|
||||
type: 'SOL101',
|
||||
},
|
||||
design_variables: [
|
||||
{ name: 'rib_thickness', min: 5.0, max: 30.0, unit: 'mm' },
|
||||
{ name: 'back_thickness', min: 10.0, max: 50.0, unit: 'mm' },
|
||||
{ name: 'cell_count', min: 6, max: 24 },
|
||||
{ name: 'lightweighting_ratio', min: 0.3, max: 0.8 },
|
||||
],
|
||||
extractors: [
|
||||
{ id: 'E8', name: 'Zernike WFE', config: { terms: [4, 5, 6, 7, 8, 9, 10, 11], method: 'op2' } },
|
||||
{ id: 'E4', name: 'BDF Mass', config: {} },
|
||||
],
|
||||
objectives: [
|
||||
{ name: 'wfe_rms', direction: 'minimize', weight: 0.7, extractor: 'E8' },
|
||||
{ name: 'mass', direction: 'minimize', weight: 0.3, extractor: 'E4' },
|
||||
],
|
||||
constraints: [
|
||||
{ name: 'max_mass', operator: '<=', value: 150.0, extractor: 'E4' },
|
||||
],
|
||||
optimization: {
|
||||
method: 'TPE',
|
||||
max_trials: 150,
|
||||
},
|
||||
surrogate: {
|
||||
enabled: true,
|
||||
type: 'GNN',
|
||||
min_trials: 30,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Template 5: Frequency Optimization
|
||||
* Maximize natural frequencies for dynamic performance
|
||||
*/
|
||||
const frequencyOptimizationTemplate: CanvasTemplate = {
|
||||
id: 'frequency_optimization',
|
||||
name: 'Frequency Optimization',
|
||||
description: 'Maximize natural frequencies to avoid resonance. Essential for rotating machinery and vibration-sensitive equipment.',
|
||||
category: 'structural',
|
||||
icon: '📈',
|
||||
intent: {
|
||||
version: '1.0',
|
||||
source: 'canvas',
|
||||
timestamp: new Date().toISOString(),
|
||||
model: {
|
||||
path: undefined,
|
||||
type: 'prt',
|
||||
},
|
||||
solver: {
|
||||
type: 'SOL103',
|
||||
},
|
||||
design_variables: [
|
||||
{ name: 'base_thickness', min: 5.0, max: 25.0, unit: 'mm' },
|
||||
{ name: 'stiffener_height', min: 10.0, max: 40.0, unit: 'mm' },
|
||||
{ name: 'stiffener_spacing', min: 20.0, max: 80.0, unit: 'mm' },
|
||||
],
|
||||
extractors: [
|
||||
{ id: 'E2', name: 'First Frequency', config: { mode: 1 } },
|
||||
{ id: 'E4', name: 'BDF Mass', config: {} },
|
||||
],
|
||||
objectives: [
|
||||
{ name: 'frequency_1', direction: 'maximize', weight: 1.0, extractor: 'E2' },
|
||||
],
|
||||
constraints: [
|
||||
{ name: 'max_mass', operator: '<=', value: 50.0, extractor: 'E4' },
|
||||
],
|
||||
optimization: {
|
||||
method: 'TPE',
|
||||
max_trials: 100,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* All available templates
|
||||
*/
|
||||
export const templates: CanvasTemplate[] = [
|
||||
massMinimizationTemplate,
|
||||
multiObjectiveTemplate,
|
||||
turboModeTemplate,
|
||||
mirrorZernikeTemplate,
|
||||
frequencyOptimizationTemplate,
|
||||
];
|
||||
|
||||
/**
|
||||
* Get template by ID
|
||||
*/
|
||||
export function getTemplate(id: string): CanvasTemplate | undefined {
|
||||
return templates.find(t => t.id === id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get templates by category
|
||||
*/
|
||||
export function getTemplatesByCategory(category: CanvasTemplate['category']): CanvasTemplate[] {
|
||||
return templates.filter(t => t.category === category);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fresh copy of a template's intent with updated timestamp
|
||||
*/
|
||||
export function instantiateTemplate(template: CanvasTemplate): OptimizationIntent {
|
||||
return {
|
||||
...template.intent,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user