feat: Add Studio UI, intake system, and extractor improvements
Dashboard: - Add Studio page with drag-drop model upload and Claude chat - Add intake system for study creation workflow - Improve session manager and context builder - Add intake API routes and frontend components Optimization Engine: - Add CLI module for command-line operations - Add intake module for study preprocessing - Add validation module with gate checks - Improve Zernike extractor documentation - Update spec models with better validation - Enhance solve_simulation robustness Documentation: - Add ATOMIZER_STUDIO.md planning doc - Add ATOMIZER_UX_SYSTEM.md for UX patterns - Update extractor library docs - Add study-readme-generator skill Tools: - Add test scripts for extraction validation - Add Zernike recentering test Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,26 +1,30 @@
|
||||
"""
|
||||
Extract mass from Nastran BDF/DAT file as fallback when OP2 doesn't have GRDPNT
|
||||
Extract mass from Nastran BDF/DAT file.
|
||||
|
||||
This module provides a simple wrapper around the BDFMassExtractor class.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any
|
||||
import re
|
||||
|
||||
from optimization_engine.extractors.bdf_mass_extractor import BDFMassExtractor
|
||||
|
||||
|
||||
def extract_mass_from_bdf(bdf_file: Path) -> Dict[str, Any]:
|
||||
"""
|
||||
Extract mass from Nastran BDF file by parsing material and element definitions.
|
||||
|
||||
This is a fallback when OP2 doesn't have PARAM,GRDPNT output.
|
||||
Extract mass from Nastran BDF file.
|
||||
|
||||
Args:
|
||||
bdf_file: Path to .dat or .bdf file
|
||||
|
||||
Returns:
|
||||
dict: {
|
||||
'mass_kg': total mass in kg,
|
||||
'mass_g': total mass in grams,
|
||||
'method': 'bdf_calculation'
|
||||
'total_mass': mass in kg (primary key),
|
||||
'mass_kg': mass in kg,
|
||||
'mass_g': mass in grams,
|
||||
'cg': center of gravity [x, y, z],
|
||||
'num_elements': number of elements,
|
||||
'breakdown': mass by element type
|
||||
}
|
||||
"""
|
||||
bdf_file = Path(bdf_file)
|
||||
@@ -28,35 +32,23 @@ def extract_mass_from_bdf(bdf_file: Path) -> Dict[str, Any]:
|
||||
if not bdf_file.exists():
|
||||
raise FileNotFoundError(f"BDF file not found: {bdf_file}")
|
||||
|
||||
# Parse using pyNastran BDF reader
|
||||
from pyNastran.bdf.bdf import read_bdf
|
||||
extractor = BDFMassExtractor(str(bdf_file))
|
||||
result = extractor.extract_mass()
|
||||
|
||||
model = read_bdf(str(bdf_file), validate=False, xref=True, punch=False,
|
||||
encoding='utf-8', log=None, debug=False, mode='msc')
|
||||
# Add 'total_mass' as primary key for compatibility
|
||||
result["total_mass"] = result["mass_kg"]
|
||||
|
||||
# Calculate total mass by summing element masses
|
||||
# model.mass_properties() returns (mass, cg, inertia)
|
||||
mass_properties = model.mass_properties()
|
||||
mass_ton = mass_properties[0] # Mass in tons (ton-mm-sec)
|
||||
|
||||
# NX Nastran typically uses ton-mm-sec units
|
||||
mass_kg = mass_ton * 1000.0 # Convert tons to kg
|
||||
mass_g = mass_kg * 1000.0 # Convert kg to grams
|
||||
|
||||
return {
|
||||
'mass_kg': mass_kg,
|
||||
'mass_g': mass_g,
|
||||
'mass_ton': mass_ton,
|
||||
'method': 'bdf_calculation',
|
||||
'units': 'ton-mm-sec (converted to kg/g)'
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
bdf_file = Path(sys.argv[1])
|
||||
result = extract_mass_from_bdf(bdf_file)
|
||||
print(f"Mass from BDF: {result['mass_kg']:.6f} kg ({result['mass_g']:.3f} g)")
|
||||
print(f"CG: {result['cg']}")
|
||||
print(f"Elements: {result['num_elements']}")
|
||||
else:
|
||||
print(f"Usage: python {sys.argv[0]} <bdf_file>")
|
||||
|
||||
Reference in New Issue
Block a user