I don't remember
This commit is contained in:
@@ -10,11 +10,13 @@ import {
|
||||
} from '../engine/engineExportImport.js'
|
||||
import DesignSection from '../components/engine/DesignSection.jsx'
|
||||
import EngineModel3D from '../components/engine/EngineModel3D.jsx'
|
||||
import NozzleDiagram from '../components/engine/NozzleDiagram.jsx'
|
||||
import PerformanceCharts from '../components/engine/PerformanceCharts.jsx'
|
||||
import ErrorBoundary from '../components/ErrorBoundary.jsx'
|
||||
import { formatValue } from '../engine/format.js'
|
||||
import { getUnitsForFamily } from '../engine/units.js'
|
||||
import { ENGINE_FIELD_INFO } from '../engine/engineFieldInfo.js'
|
||||
import { ABLATIVE_MATERIALS } from '../engine/knowledgebaseData.js'
|
||||
import { ABLATIVE_MATERIALS, STRUCTURAL_MATERIALS } from '../engine/knowledgebaseData.js'
|
||||
|
||||
/* ── Info popup ───────────────────────────────────────────────────── */
|
||||
|
||||
@@ -234,6 +236,8 @@ function ResultSection({ title, children }) {
|
||||
export default function EnginePage() {
|
||||
const importRef = useRef(null)
|
||||
const [showPropellants, setShowPropellants] = useState(false)
|
||||
const [showNozzleModal, setShowNozzleModal] = useState(false)
|
||||
const [showChartsModal, setShowChartsModal] = useState(false)
|
||||
const {
|
||||
thermoInputs, setThermoInput,
|
||||
chamber, setChamber,
|
||||
@@ -242,21 +246,23 @@ export default function EnginePage() {
|
||||
cooling, setCooling,
|
||||
feedSystem, setFeedSystem,
|
||||
burnTime, setBurnTime,
|
||||
structure, setStructure,
|
||||
allThermo,
|
||||
chamberGeometry: cg,
|
||||
nozzleGeometry: ng,
|
||||
injectorGeometry: ig,
|
||||
coolingResults: cr,
|
||||
feedResults: fr,
|
||||
structureResults: sr,
|
||||
loadDesign,
|
||||
applyPropellant,
|
||||
} = useEngineDesign()
|
||||
|
||||
function handleExportJSON() {
|
||||
const blob = exportEngineJSON({
|
||||
thermoInputs, chamber, nozzle, injector, cooling, feedSystem, burnTime,
|
||||
thermoInputs, chamber, nozzle, injector, cooling, feedSystem, burnTime, structure,
|
||||
allThermo, chamberGeometry: cg, nozzleGeometry: ng,
|
||||
injectorGeometry: ig, coolingResults: cr, feedResults: fr,
|
||||
injectorGeometry: ig, coolingResults: cr, feedResults: fr, structureResults: sr,
|
||||
})
|
||||
downloadBlob(blob, 'engine-design.json')
|
||||
}
|
||||
@@ -657,13 +663,54 @@ export default function EnginePage() {
|
||||
step="1"
|
||||
/>
|
||||
</DesignSection>
|
||||
|
||||
<DesignSection title="Structural">
|
||||
<SelectInput
|
||||
label="Material"
|
||||
value={structure.materialId}
|
||||
onChange={v => setStructure(s => ({ ...s, materialId: v }))}
|
||||
options={STRUCTURAL_MATERIALS.map(m => ({ value: m.id, label: m.name }))}
|
||||
infoKey="structuralMaterial"
|
||||
/>
|
||||
<NumInput
|
||||
label="Safety Factor"
|
||||
value={structure.safetyFactor}
|
||||
onChange={v => setStructure(s => ({ ...s, safetyFactor: v }))}
|
||||
infoKey="safetyFactor"
|
||||
step="0.1"
|
||||
placeholder="2.0"
|
||||
/>
|
||||
</DesignSection>
|
||||
</div>
|
||||
|
||||
{/* ── Centre: 3D Model ── */}
|
||||
<div className="flex-1 relative border-r border-slate-700 bg-slate-950/50">
|
||||
<ErrorBoundary>
|
||||
<EngineModel3D chamberGeometry={cg} nozzleGeometry={ng} />
|
||||
</ErrorBoundary>
|
||||
{/* ── Centre: 3D Model + Visualization Buttons ── */}
|
||||
<div className="flex-1 border-r border-slate-700 bg-slate-950/50 flex flex-col overflow-hidden">
|
||||
{/* 3D Model */}
|
||||
<div className="flex-1 relative flex flex-col">
|
||||
<ErrorBoundary>
|
||||
<EngineModel3D chamberGeometry={cg} nozzleGeometry={ng} />
|
||||
</ErrorBoundary>
|
||||
|
||||
{/* Quick access buttons overlay */}
|
||||
<div className="absolute bottom-4 left-4 right-4 flex gap-2 pointer-events-auto">
|
||||
{cg && ng && (
|
||||
<button
|
||||
onClick={() => setShowNozzleModal(true)}
|
||||
className="px-3 py-2 text-xs bg-blue-700 hover:bg-blue-600 text-white rounded transition-colors whitespace-nowrap"
|
||||
>
|
||||
📐 Nozzle Cross-Section
|
||||
</button>
|
||||
)}
|
||||
{allThermo?.gamma && allThermo?.R && allThermo?.T0 && allThermo?.p0 && (
|
||||
<button
|
||||
onClick={() => setShowChartsModal(true)}
|
||||
className="px-3 py-2 text-xs bg-indigo-700 hover:bg-indigo-600 text-white rounded transition-colors whitespace-nowrap"
|
||||
>
|
||||
📊 Performance Charts
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── Right: Results ── */}
|
||||
@@ -796,6 +843,39 @@ export default function EnginePage() {
|
||||
<p className="text-xs text-slate-600">—</p>
|
||||
)}
|
||||
</ResultSection>
|
||||
|
||||
<ResultSection title="Structural Sizing">
|
||||
{sr ? (
|
||||
<>
|
||||
<div className="text-sm mb-2">
|
||||
<span className="text-slate-400">Material: </span>
|
||||
<span className="text-slate-100 font-semibold">{sr.material.name}</span>
|
||||
</div>
|
||||
<ResultRow label="Safety Factor" value={sr.safetyFactor} unit="—" />
|
||||
<ResultRow label="Allowable Stress" value={sr.allowableStress / 1e6} unit="MPa" />
|
||||
<div className="border-t border-slate-700 my-2 pt-2">
|
||||
<ResultRow label="Chamber Wall Thickness" value={sr.t_chamber * 1000} unit="mm" />
|
||||
<ResultRow label="Throat Wall Thickness" value={sr.t_throat * 1000} unit="mm" />
|
||||
<ResultRow label="Nozzle Exit Wall Thickness" value={sr.t_nozzle_exit * 1000} unit="mm" />
|
||||
</div>
|
||||
<div className="border-t border-slate-700 my-2 pt-2">
|
||||
<ResultRow label="Chamber Mass" value={sr.m_chamber_cyl + sr.m_convergent} unitFamily="mass" defaultUnitId="kg" />
|
||||
<ResultRow label="Nozzle Mass" value={sr.m_nozzle} unitFamily="mass" defaultUnitId="kg" />
|
||||
<ResultRow label="Injector Plate Mass" value={sr.m_injector} unitFamily="mass" defaultUnitId="kg" />
|
||||
</div>
|
||||
<div className="border-t border-slate-700 mt-2 pt-2">
|
||||
<div className="flex items-center gap-2 text-sm bg-blue-900/30 border border-blue-700 rounded px-3 py-2">
|
||||
<span className="text-slate-400">Engine Dry Mass</span>
|
||||
<span className="font-mono font-semibold text-blue-300">
|
||||
{formatValue(sr.m_total)} kg
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs text-slate-600">—</p>
|
||||
)}
|
||||
</ResultSection>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -806,6 +886,55 @@ export default function EnginePage() {
|
||||
description="Select a propellant to pre-fill γ, R, T₀, O/F, and densities."
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Nozzle Diagram Modal */}
|
||||
{showNozzleModal && (
|
||||
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
||||
<div className="bg-slate-900 rounded-lg shadow-2xl border border-slate-700 w-full max-w-4xl max-h-[90vh] flex flex-col">
|
||||
<div className="flex items-center justify-between p-4 border-b border-slate-700 shrink-0">
|
||||
<h2 className="text-lg font-semibold text-slate-100">Nozzle Cross-Section</h2>
|
||||
<button
|
||||
onClick={() => setShowNozzleModal(false)}
|
||||
className="text-slate-400 hover:text-slate-200 text-xl"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto p-6 bg-slate-800">
|
||||
<ErrorBoundary>
|
||||
<NozzleDiagram chamberGeometry={cg} nozzleGeometry={ng} nozzleType={nozzle.type} />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Performance Charts Modal */}
|
||||
{showChartsModal && (
|
||||
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
||||
<div className="bg-slate-900 rounded-lg shadow-2xl border border-slate-700 w-full max-w-5xl max-h-[90vh] flex flex-col">
|
||||
<div className="flex items-center justify-between p-4 border-b border-slate-700 shrink-0">
|
||||
<h2 className="text-lg font-semibold text-slate-100">Performance Analysis</h2>
|
||||
<button
|
||||
onClick={() => setShowChartsModal(false)}
|
||||
className="text-slate-400 hover:text-slate-200 text-xl"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto p-6 bg-slate-800">
|
||||
<ErrorBoundary>
|
||||
<PerformanceCharts
|
||||
allThermo={allThermo}
|
||||
coolingResults={cr}
|
||||
burnTime={burnTime}
|
||||
nozzleType={nozzle.type}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user