feat: Add comprehensive study creation Claude skill
- New create-study.md skill for complete study scaffolding - Interactive discovery process for problem understanding - Automated generation of all study infrastructure: - optimization_config.json with protocol selection - workflow_config.json for future intelligent workflows - run_optimization.py with proper multi-objective/multi-solution support - reset_study.py for database management - README.md with comprehensive documentation - NX_FILE_MODIFICATIONS_REQUIRED.md when needed - Protocol selection guidance (Protocol 10 vs 11) - Extractor mapping to centralized library - Multi-solution workflow detection - Dashboard integration instructions - User interaction best practices with confirmation steps - Common patterns and critical reminders - Reference to existing studies as templates Enables users to create complete, working optimization studies from natural language descriptions with proper Claude-guided workflow. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
514
.claude/skills/create-study.md
Normal file
514
.claude/skills/create-study.md
Normal file
@@ -0,0 +1,514 @@
|
||||
# Create Optimization Study Skill
|
||||
|
||||
**Last Updated**: November 24, 2025
|
||||
**Version**: 1.0 - Complete Study Scaffolding
|
||||
|
||||
You are helping the user create a complete Atomizer optimization study from a natural language description.
|
||||
|
||||
## Your Role
|
||||
|
||||
Guide the user through an interactive conversation to:
|
||||
1. Understand their optimization problem
|
||||
2. Classify objectives, constraints, and design variables
|
||||
3. Create the complete study infrastructure
|
||||
4. Generate all required files with proper configuration
|
||||
5. Provide clear next steps for running the optimization
|
||||
|
||||
## Study Structure
|
||||
|
||||
A complete Atomizer study has this structure:
|
||||
|
||||
```
|
||||
studies/{study_name}/
|
||||
├── 1_setup/
|
||||
│ ├── model/
|
||||
│ │ ├── {Model}.prt # NX Part file (user provides)
|
||||
│ │ ├── {Model}_sim1.sim # NX Simulation file (user provides)
|
||||
│ │ └── {Model}_fem1.fem # FEM mesh file (auto-generated by NX)
|
||||
│ ├── optimization_config.json # YOU GENERATE THIS
|
||||
│ └── workflow_config.json # YOU GENERATE THIS
|
||||
├── 2_results/ # Created automatically during optimization
|
||||
│ ├── study.db # Optuna SQLite database
|
||||
│ ├── optimization_history_incremental.json
|
||||
│ └── [various analysis files]
|
||||
├── run_optimization.py # YOU GENERATE THIS
|
||||
├── reset_study.py # YOU GENERATE THIS
|
||||
├── README.md # YOU GENERATE THIS
|
||||
└── NX_FILE_MODIFICATIONS_REQUIRED.md # YOU GENERATE THIS (if needed)
|
||||
```
|
||||
|
||||
## Interactive Discovery Process
|
||||
|
||||
### Step 1: Problem Understanding
|
||||
|
||||
Ask clarifying questions to understand:
|
||||
|
||||
**Engineering Context**:
|
||||
- "What component are you optimizing?"
|
||||
- "What is the engineering application or scenario?"
|
||||
- "What are the real-world requirements or constraints?"
|
||||
|
||||
**Objectives**:
|
||||
- "What do you want to optimize?" (minimize/maximize)
|
||||
- "Is this single-objective or multi-objective?"
|
||||
- "What are the target values or acceptable ranges?"
|
||||
|
||||
**Constraints**:
|
||||
- "What limits must be satisfied?"
|
||||
- "What are the threshold values?"
|
||||
- "Are these hard constraints (must satisfy) or soft constraints (prefer to satisfy)?"
|
||||
|
||||
**Design Variables**:
|
||||
- "What parameters can be changed?"
|
||||
- "What are the min/max bounds for each parameter?"
|
||||
- "Are these NX expressions, geometry features, or material properties?"
|
||||
|
||||
**Simulation Setup**:
|
||||
- "What NX model files do you have?"
|
||||
- "What analysis types are needed?" (static, modal, thermal, etc.)
|
||||
- "What results need to be extracted?" (stress, displacement, frequency, mass, etc.)
|
||||
|
||||
### Step 2: Classification & Analysis
|
||||
|
||||
Use the `analyze-workflow` skill to classify the problem:
|
||||
|
||||
```bash
|
||||
# Invoke the analyze-workflow skill with user's description
|
||||
# This returns JSON with classified engineering features, extractors, etc.
|
||||
```
|
||||
|
||||
Review the classification with the user and confirm:
|
||||
- Are the objectives correctly identified?
|
||||
- Are constraints properly classified?
|
||||
- Are extractors mapped to the right result types?
|
||||
- Is the protocol selection appropriate?
|
||||
|
||||
### Step 3: Protocol Selection
|
||||
|
||||
Based on analysis, recommend protocol:
|
||||
|
||||
**Protocol 11 (Multi-Objective NSGA-II)**:
|
||||
- Use when: 2-3 conflicting objectives
|
||||
- Algorithm: NSGAIISampler
|
||||
- Output: Pareto front of optimal trade-offs
|
||||
- Example: Minimize mass + Maximize frequency
|
||||
|
||||
**Protocol 10 (Single-Objective with Intelligent Strategies)**:
|
||||
- Use when: 1 objective with constraints
|
||||
- Algorithm: TPE, CMA-ES, or adaptive
|
||||
- Output: Single optimal solution
|
||||
- Example: Minimize stress subject to displacement < 1.5mm
|
||||
|
||||
**Legacy (Basic TPE)**:
|
||||
- Use when: Simple single-objective problem
|
||||
- Algorithm: TPE
|
||||
- Output: Single optimal solution
|
||||
- Example: Quick exploration or testing
|
||||
|
||||
### Step 4: Extractor Mapping
|
||||
|
||||
Map each result extraction to centralized extractors:
|
||||
|
||||
| User Need | Extractor | Parameters |
|
||||
|-----------|-----------|------------|
|
||||
| Displacement | `extract_displacement` | `op2_file`, `subcase` |
|
||||
| Von Mises Stress | `extract_solid_stress` | `op2_file`, `subcase`, `element_type` |
|
||||
| Natural Frequency | `extract_frequency` | `op2_file`, `subcase`, `mode_number` |
|
||||
| FEM Mass | `extract_mass_from_bdf` | `bdf_file` |
|
||||
| CAD Mass | `extract_mass_from_expression` | `prt_file`, `expression_name` |
|
||||
|
||||
### Step 5: Multi-Solution Detection
|
||||
|
||||
Check if multi-solution workflow is needed:
|
||||
|
||||
**Indicators**:
|
||||
- Extracting both static results (stress, displacement) AND modal results (frequency)
|
||||
- User mentions "static + modal analysis"
|
||||
- Objectives/constraints require different solution types
|
||||
|
||||
**Action**:
|
||||
- Set `solution_name=None` in `run_optimization.py` to solve all solutions
|
||||
- Document requirement in `NX_FILE_MODIFICATIONS_REQUIRED.md`
|
||||
- Use `SolveAllSolutions()` protocol (see [NX_MULTI_SOLUTION_PROTOCOL.md](../docs/NX_MULTI_SOLUTION_PROTOCOL.md))
|
||||
|
||||
## File Generation
|
||||
|
||||
### 1. optimization_config.json
|
||||
|
||||
```json
|
||||
{
|
||||
"study_name": "{study_name}",
|
||||
"description": "{concise description}",
|
||||
"engineering_context": "{detailed real-world context}",
|
||||
|
||||
"optimization_settings": {
|
||||
"protocol": "protocol_11_multi_objective", // or protocol_10, etc.
|
||||
"n_trials": 30,
|
||||
"sampler": "NSGAIISampler", // or "TPESampler"
|
||||
"pruner": null,
|
||||
"timeout_per_trial": 600
|
||||
},
|
||||
|
||||
"design_variables": [
|
||||
{
|
||||
"parameter": "{nx_expression_name}",
|
||||
"bounds": [min, max],
|
||||
"description": "{what this controls}"
|
||||
}
|
||||
],
|
||||
|
||||
"objectives": [
|
||||
{
|
||||
"name": "{objective_name}",
|
||||
"goal": "minimize", // or "maximize"
|
||||
"weight": 1.0,
|
||||
"description": "{what this measures}",
|
||||
"target": {target_value},
|
||||
"extraction": {
|
||||
"action": "extract_{type}",
|
||||
"domain": "result_extraction",
|
||||
"params": {
|
||||
"result_type": "{type}",
|
||||
"metric": "{specific_metric}"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"constraints": [
|
||||
{
|
||||
"name": "{constraint_name}",
|
||||
"type": "less_than", // or "greater_than"
|
||||
"threshold": {value},
|
||||
"description": "{engineering justification}",
|
||||
"extraction": {
|
||||
"action": "extract_{type}",
|
||||
"domain": "result_extraction",
|
||||
"params": {
|
||||
"result_type": "{type}",
|
||||
"metric": "{specific_metric}"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"simulation": {
|
||||
"model_file": "{Model}.prt",
|
||||
"sim_file": "{Model}_sim1.sim",
|
||||
"fem_file": "{Model}_fem1.fem",
|
||||
"solver": "nastran",
|
||||
"analysis_types": ["static", "modal"] // or just ["static"]
|
||||
},
|
||||
|
||||
"reporting": {
|
||||
"generate_plots": true,
|
||||
"save_incremental": true,
|
||||
"llm_summary": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. workflow_config.json
|
||||
|
||||
```json
|
||||
{
|
||||
"workflow_id": "{study_name}_workflow",
|
||||
"description": "{workflow description}",
|
||||
"steps": [] // Can be empty for now, used by future intelligent workflow system
|
||||
}
|
||||
```
|
||||
|
||||
### 3. run_optimization.py
|
||||
|
||||
Generate a complete Python script based on protocol:
|
||||
|
||||
**Key sections**:
|
||||
- Import statements (centralized extractors, NXSolver, Optuna)
|
||||
- Configuration loading
|
||||
- Objective function with proper:
|
||||
- Design variable sampling
|
||||
- Simulation execution with multi-solution support
|
||||
- Result extraction using centralized extractors
|
||||
- Constraint checking
|
||||
- Return format (tuple for multi-objective, float for single-objective)
|
||||
- Study creation with proper:
|
||||
- Directions for multi-objective (`['minimize', 'maximize']`)
|
||||
- Sampler selection (NSGAIISampler or TPESampler)
|
||||
- Storage location
|
||||
- Results display and dashboard instructions
|
||||
|
||||
**Template**: Use [studies/drone_gimbal_arm_optimization/run_optimization.py](../studies/drone_gimbal_arm_optimization/run_optimization.py:1) as reference
|
||||
|
||||
### 4. reset_study.py
|
||||
|
||||
Simple script to delete Optuna database:
|
||||
|
||||
```python
|
||||
"""Reset {study_name} optimization study by deleting database."""
|
||||
import optuna
|
||||
from pathlib import Path
|
||||
|
||||
study_dir = Path(__file__).parent
|
||||
storage = f"sqlite:///{study_dir / '2_results' / 'study.db'}"
|
||||
study_name = "{study_name}"
|
||||
|
||||
try:
|
||||
optuna.delete_study(study_name=study_name, storage=storage)
|
||||
print(f"[OK] Deleted study: {study_name}")
|
||||
except KeyError:
|
||||
print(f"[WARNING] Study '{study_name}' not found (database may not exist)")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error: {e}")
|
||||
```
|
||||
|
||||
### 5. README.md
|
||||
|
||||
Comprehensive documentation including:
|
||||
- Engineering scenario and context
|
||||
- Problem statement with real-world constraints
|
||||
- Multi-objective trade-offs (if applicable)
|
||||
- Design variables and their effects
|
||||
- Expected outcomes
|
||||
- Study configuration details
|
||||
- File structure explanation
|
||||
- Running instructions
|
||||
- Dashboard monitoring guide
|
||||
- Results interpretation guide
|
||||
- Comparison with other studies
|
||||
- Technical notes
|
||||
|
||||
**Template**: Use [studies/drone_gimbal_arm_optimization/README.md](../studies/drone_gimbal_arm_optimization/README.md:1) as reference
|
||||
|
||||
### 6. NX_FILE_MODIFICATIONS_REQUIRED.md (if needed)
|
||||
|
||||
If multi-solution workflow or specific NX setup is required:
|
||||
|
||||
```markdown
|
||||
# NX File Modifications Required
|
||||
|
||||
Before running this optimization, you must modify the NX simulation files.
|
||||
|
||||
## Required Changes
|
||||
|
||||
### 1. Add Modal Analysis Solution (if needed)
|
||||
|
||||
Current: Only static analysis (SOL 101)
|
||||
Required: Static + Modal (SOL 101 + SOL 103)
|
||||
|
||||
Steps:
|
||||
1. Open `{Model}_sim1.sim` in NX
|
||||
2. Solution → Create → Modal Analysis
|
||||
3. Set frequency extraction parameters
|
||||
4. Save simulation
|
||||
|
||||
### 2. Update Load Cases (if needed)
|
||||
|
||||
Current: [describe current loads]
|
||||
Required: [describe required loads]
|
||||
|
||||
Steps: [specific instructions]
|
||||
|
||||
### 3. Verify Material Properties
|
||||
|
||||
Required: [material name and properties]
|
||||
|
||||
## Verification
|
||||
|
||||
After modifications:
|
||||
1. Run simulation manually in NX
|
||||
2. Verify OP2 files are generated
|
||||
3. Check solution_1.op2 and solution_2.op2 exist (if multi-solution)
|
||||
```
|
||||
|
||||
## User Interaction Best Practices
|
||||
|
||||
### Ask Before Generating
|
||||
|
||||
Always confirm with user:
|
||||
1. "Here's what I understand about your optimization problem: [summary]. Is this correct?"
|
||||
2. "I'll use Protocol {X} because [reasoning]. Does this sound right?"
|
||||
3. "I'll create extractors for: [list]. Are these the results you need?"
|
||||
4. "Should I generate the complete study structure now?"
|
||||
|
||||
### Provide Clear Next Steps
|
||||
|
||||
After generating files:
|
||||
```
|
||||
✓ Created study: studies/{study_name}/
|
||||
✓ Generated optimization config
|
||||
✓ Generated run_optimization.py with {protocol}
|
||||
✓ Generated README.md with full documentation
|
||||
|
||||
Next Steps:
|
||||
1. Place your NX files in studies/{study_name}/1_setup/model/
|
||||
- {Model}.prt
|
||||
- {Model}_sim1.sim
|
||||
2. [If NX modifications needed] Read NX_FILE_MODIFICATIONS_REQUIRED.md
|
||||
3. Test with 3 trials: cd studies/{study_name} && python run_optimization.py --trials 3
|
||||
4. Monitor in dashboard: http://localhost:3003
|
||||
5. Full run: python run_optimization.py --trials {n_trials}
|
||||
```
|
||||
|
||||
### Handle Edge Cases
|
||||
|
||||
**User has incomplete information**:
|
||||
- Suggest reasonable defaults based on similar studies
|
||||
- Document assumptions clearly in README
|
||||
- Mark as "REQUIRES USER INPUT" in generated files
|
||||
|
||||
**User wants custom extractors**:
|
||||
- Explain centralized extractor library
|
||||
- If truly custom, guide them to create in `optimization_engine/extractors/`
|
||||
- Inherit from `OP2Extractor` base class
|
||||
|
||||
**User unsure about bounds**:
|
||||
- Recommend conservative bounds based on engineering judgment
|
||||
- Suggest iterative approach: "Start with [bounds], then refine based on initial results"
|
||||
|
||||
**User doesn't have NX files yet**:
|
||||
- Generate all Python/JSON files anyway
|
||||
- Create placeholder model directory
|
||||
- Provide clear instructions for adding NX files later
|
||||
|
||||
## Integration with Dashboard
|
||||
|
||||
Always mention dashboard capabilities:
|
||||
|
||||
**For Multi-Objective Studies**:
|
||||
- "You'll see the Pareto front in real-time on the dashboard"
|
||||
- "Use parallel coordinates plot to explore trade-offs"
|
||||
- "Green lines = feasible, red lines = constraint violations"
|
||||
|
||||
**For Single-Objective Studies**:
|
||||
- "Monitor convergence in real-time"
|
||||
- "See best value improving over trials"
|
||||
- "Check parameter space exploration"
|
||||
|
||||
**Dashboard Access**:
|
||||
```bash
|
||||
# Terminal 1: Backend
|
||||
cd atomizer-dashboard/backend && python -m uvicorn api.main:app --reload
|
||||
|
||||
# Terminal 2: Frontend
|
||||
cd atomizer-dashboard/frontend && npm run dev
|
||||
|
||||
# Browser: http://localhost:3003
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Pattern 1: Mass Minimization with Constraints
|
||||
|
||||
```
|
||||
Objective: Minimize mass
|
||||
Constraints: Stress < limit, Displacement < limit, Frequency > limit
|
||||
Protocol: Protocol 10 (single-objective TPE)
|
||||
Extractors: extract_mass_from_expression, extract_solid_stress,
|
||||
extract_displacement, extract_frequency
|
||||
Multi-Solution: Yes (static + modal)
|
||||
```
|
||||
|
||||
### Pattern 2: Mass vs Frequency Trade-off
|
||||
|
||||
```
|
||||
Objectives: Minimize mass, Maximize frequency
|
||||
Constraints: Stress < limit, Displacement < limit
|
||||
Protocol: Protocol 11 (multi-objective NSGA-II)
|
||||
Extractors: extract_mass_from_expression, extract_frequency,
|
||||
extract_solid_stress, extract_displacement
|
||||
Multi-Solution: Yes (static + modal)
|
||||
```
|
||||
|
||||
### Pattern 3: Stress Minimization
|
||||
|
||||
```
|
||||
Objective: Minimize stress
|
||||
Constraints: Displacement < limit
|
||||
Protocol: Protocol 10 (single-objective TPE)
|
||||
Extractors: extract_solid_stress, extract_displacement
|
||||
Multi-Solution: No (static only)
|
||||
```
|
||||
|
||||
## Critical Reminders
|
||||
|
||||
### Multi-Objective Return Format
|
||||
|
||||
```python
|
||||
# ✅ CORRECT: Return tuple with proper semantic directions
|
||||
study = optuna.create_study(
|
||||
directions=['minimize', 'maximize'], # Semantic directions
|
||||
sampler=NSGAIISampler()
|
||||
)
|
||||
|
||||
def objective(trial):
|
||||
return (mass, frequency) # Return positive values
|
||||
```
|
||||
|
||||
```python
|
||||
# ❌ WRONG: Using negative values
|
||||
return (mass, -frequency) # Creates degenerate Pareto front
|
||||
```
|
||||
|
||||
### Multi-Solution NX Protocol
|
||||
|
||||
```python
|
||||
# ✅ CORRECT: Solve all solutions
|
||||
result = nx_solver.run_simulation(
|
||||
sim_file=sim_file,
|
||||
working_dir=model_dir,
|
||||
expression_updates=design_vars,
|
||||
solution_name=None # None = solve ALL solutions
|
||||
)
|
||||
```
|
||||
|
||||
```python
|
||||
# ❌ WRONG: Only solves first solution
|
||||
solution_name="Solution 1" # Multi-solution workflows will fail
|
||||
```
|
||||
|
||||
### Extractor Selection
|
||||
|
||||
Always use centralized extractors from `optimization_engine/extractors/`:
|
||||
- Standardized error handling
|
||||
- Consistent return formats
|
||||
- Well-tested and documented
|
||||
- No code duplication
|
||||
|
||||
## Output Format
|
||||
|
||||
After completing study creation, provide:
|
||||
|
||||
1. **Summary Table**:
|
||||
```
|
||||
Study Created: {study_name}
|
||||
Protocol: {protocol}
|
||||
Objectives: {list}
|
||||
Constraints: {list}
|
||||
Design Variables: {list}
|
||||
Multi-Solution: {Yes/No}
|
||||
```
|
||||
|
||||
2. **File Checklist**:
|
||||
```
|
||||
✓ studies/{study_name}/1_setup/optimization_config.json
|
||||
✓ studies/{study_name}/1_setup/workflow_config.json
|
||||
✓ studies/{study_name}/run_optimization.py
|
||||
✓ studies/{study_name}/reset_study.py
|
||||
✓ studies/{study_name}/README.md
|
||||
[✓] studies/{study_name}/NX_FILE_MODIFICATIONS_REQUIRED.md (if needed)
|
||||
```
|
||||
|
||||
3. **Next Steps** (as shown earlier)
|
||||
|
||||
## Remember
|
||||
|
||||
- Be conversational and helpful
|
||||
- Ask clarifying questions early
|
||||
- Confirm understanding before generating
|
||||
- Provide context for technical decisions
|
||||
- Make next steps crystal clear
|
||||
- Anticipate common mistakes
|
||||
- Reference existing studies as examples
|
||||
- Always test-run your generated code mentally
|
||||
|
||||
The goal is for the user to have a COMPLETE, WORKING study that they can run immediately after placing their NX files.
|
||||
Reference in New Issue
Block a user