| """
|
| AlgoRythm Prandtl Aero — Deterministic Dataset Generator v2.0
|
| Generates physics-first training data with correct PicoGK API patterns.
|
| All internal calculations in SI, output geometry in mm (PicoGK convention).
|
| """
|
| import json, math, random
|
| from typing import Dict, List
|
| from physics_core import *
|
| import universal_csg
|
| import advanced_physics
|
|
|
| random.seed(42)
|
|
|
|
|
|
|
|
|
| def gen_bell_nozzle(thrust_N, Pc_bar, propellant, eps=None):
|
| p = PROPELLANTS[propellant]
|
| gamma = p["gamma"]
|
| if eps is None:
|
| eps = random.choice([8, 12, 16, 20, 30, 40, 50, 60, 80])
|
|
|
| pe_ratio = calc_exit_pressure(gamma, eps)
|
| Cf = calc_thrust_coefficient(gamma, eps, 1.0, pe_ratio)
|
| At_m2 = calc_throat_area(thrust_N, Pc_bar, Cf)
|
| Dt_mm = throat_area_to_diameter_mm(At_m2)
|
| De_mm = calc_exit_diameter_mm(Dt_mm, eps)
|
| mdot = calc_mass_flow(thrust_N, p["Isp_vac"])
|
| Ln_mm = calc_nozzle_length_mm(Dt_mm, De_mm)
|
| cstar_calc = calc_cstar(p["Tc"], gamma, p["Rspec"])
|
|
|
| mat = "Inconel_718" if Pc_bar > 80 else ("C103_Niobium" if Pc_bar < 20 else "Inconel_625")
|
| wall_t = select_wall_thickness_mm(Pc_bar, Dt_mm, mat)
|
| hoop = calc_hoop_stress_MPa(Pc_bar, Dt_mm, wall_t)
|
| mos = calc_margin_of_safety(MATERIALS[mat]["sigma_y_MPa"], hoop)
|
| q_throat = calc_bartz_heat_flux(Pc_bar, Dt_mm, p["cstar"], mdot, p["Tc"], gamma)
|
|
|
| ref_name, ref_Dt, valid = validate_against_reference(thrust_N, Pc_bar, propellant, Dt_mm)
|
| ref_note = f"Validated against {ref_name} (Dt={ref_Dt}mm)" if ref_name else "No close reference engine"
|
|
|
| lpbf = LPBF_PARAMS.get(mat, LPBF_PARAMS["Inconel_718"])
|
|
|
| input_text = f"Design a bell nozzle for a {thrust_N/1000:.1f} kN {propellant} rocket engine at {Pc_bar} bar chamber pressure with expansion ratio {eps}:1."
|
|
|
| reasoning = f"""[ENGINEER_COGNITION]
|
| Analyzing the design space for a {thrust_N/1000:.1f} kN {propellant} engine at Pc={Pc_bar} bar.
|
|
|
| The isentropic flow relations govern this design. At the throat, flow must reach exactly Mach 1.0 (choked condition). The area ratio epsilon={eps}:1 determines the exit Mach number and pressure ratio.
|
|
|
| I begin with the thrust coefficient. Using the specific heat ratio gamma={gamma} for {propellant} combustion products:
|
| - Exit pressure ratio Pe/Pc = {pe_ratio:.6f}
|
| - Thrust coefficient Cf = {Cf:.4f}
|
|
|
| **Step 1: Throat Sizing (Critical Dimension)**
|
| A* = F / (Pc × Cf) = {thrust_N} / ({Pc_bar*1e5:.0f} × {Cf:.4f}) = {At_m2*1e6:.4f} mm²
|
| D* = sqrt(4A*/π) = {Dt_mm:.2f} mm
|
| {ref_note}
|
|
|
| **Step 2: Exit Geometry**
|
| De = D* × sqrt(ε) = {Dt_mm:.2f} × sqrt({eps}) = {De_mm:.2f} mm
|
| Nozzle Length (80% Rao bell) = {Ln_mm:.2f} mm
|
|
|
| **Step 3: Mass Flow (Saint-Venant)**
|
| mdot = F / (Isp × g0) = {thrust_N} / ({p['Isp_vac']} × 9.807) = {mdot:.4f} kg/s
|
| c* verification = {cstar_calc:.1f} m/s (spec: {p['cstar']} m/s)
|
|
|
| **Step 4: Structural Analysis**
|
| Material: {mat} (σ_y = {MATERIALS[mat]['sigma_y_MPa']} MPa)
|
| Wall thickness: {wall_t:.2f} mm (auto-selected for MoS target)
|
| Hoop stress σ_h = P×r/t = {hoop:.1f} MPa
|
| Margin of Safety = {mos:.3f} ({'PASS' if mos > 0 else 'FAIL — redesign required'})
|
|
|
| **Step 5: Thermal Analysis**
|
| Bartz throat heat flux = {q_throat:.2f} MW/m²
|
| Max wall temperature limit = {MATERIALS[mat]['Tmax_K']} K
|
| {'WARNING: Heat flux exceeds 40 MW/m², active cooling required.' if q_throat > 40 else 'Heat flux within radiation-cooled limit.' if q_throat < 5 else 'Regenerative cooling required.'}
|
|
|
| **Step 6: Manufacturing (L-PBF)**
|
| Process: Laser Powder Bed Fusion
|
| Power: {lpbf['power_W']}W | Speed: {lpbf['speed_mm_s']} mm/s | Layer: {lpbf['layer_um']} μm | Hatch: {lpbf['hatch_um']} μm
|
|
|
| [TECHNICAL_REPORT]
|
| Design: {propellant} Bell Nozzle, {thrust_N/1000:.1f} kN, Pc={Pc_bar} bar, ε={eps}:1
|
| Throat: D*={Dt_mm:.2f} mm | Exit: De={De_mm:.2f} mm | Length: {Ln_mm:.2f} mm
|
| MoS = {mos:.3f} on {mat} at t={wall_t:.2f} mm wall
|
| Thermal: q_throat = {q_throat:.2f} MW/m²
|
| """
|
|
|
| Rt = Dt_mm / 2
|
| Re = De_mm / 2
|
| output = f"""// AlgoRythm Prandtl Aero — Bell Nozzle ({thrust_N/1000:.1f} kN {propellant})
|
| // D* = {Dt_mm:.2f} mm, De = {De_mm:.2f} mm, L = {Ln_mm:.2f} mm
|
| using PicoGK;
|
| using System;
|
| using System.Numerics;
|
|
|
| namespace AlgoRythm.PrandtlAero
|
| {{
|
| // IImplicit: returns signed distance (negative = inside, positive = outside)
|
| public class BellNozzle_{int(thrust_N/1000)}kN : IImplicit
|
| {{
|
| const float fThroatR = {Rt:.2f}f; // mm
|
| const float fExitR = {Re:.2f}f; // mm
|
| const float fLength = {Ln_mm:.2f}f; // mm
|
| const float fWallT = {wall_t:.2f}f; // mm
|
|
|
| public float fSignedDistance(in Vector3 vecPt)
|
| {{
|
| float fZ = vecPt.Z;
|
| if (fZ < 0f || fZ > fLength) return 1f; // Outside bounds
|
|
|
| float t = fZ / fLength;
|
| // Rao 80% bell: parabolic contour
|
| float fProfileR = fThroatR + (fExitR - fThroatR) * MathF.Pow(t, 0.7f);
|
|
|
| // Radial distance from centerline (z-axis)
|
| float fR = MathF.Sqrt(vecPt.X * vecPt.X + vecPt.Y * vecPt.Y);
|
|
|
| // Signed distance: shell between inner and outer wall
|
| float fInner = fR - fProfileR;
|
| float fOuter = fR - (fProfileR + fWallT);
|
| return MathF.Max(fInner, -fOuter);
|
| }}
|
|
|
| public static Voxels Generate()
|
| {{
|
| var oNozzle = new BellNozzle_{int(thrust_N/1000)}kN();
|
| BBox3 oBounds = new BBox3(
|
| new Vector3(-fExitR - 5f, -fExitR - 5f, -5f),
|
| new Vector3( fExitR + 5f, fExitR + 5f, fLength + 5f));
|
| return new Voxels(oNozzle, oBounds);
|
| }}}}
|
| }}}}
|
| }}}}"""
|
|
|
| return {"id": f"nozzle_bell_{int(thrust_N)}N_{Pc_bar}bar_{propellant.replace('/','_')}",
|
| "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_combustion_chamber(thrust_N, Pc_bar, propellant):
|
| p = PROPELLANTS[propellant]
|
| gamma = p["gamma"]
|
| eps = 20
|
| Cf = calc_thrust_coefficient(gamma, eps, 1.0, calc_exit_pressure(gamma, eps))
|
| At_m2 = calc_throat_area(thrust_N, Pc_bar, Cf)
|
| Dt_mm = throat_area_to_diameter_mm(At_m2)
|
| mdot = calc_mass_flow(thrust_N, p["Isp_vac"])
|
| CR = random.choice([2.5, 3.0, 3.5, 4.0])
|
| Dc_mm = calc_chamber_diameter_mm(Dt_mm, CR)
|
| Lstar = random.choice([0.76, 1.0, 1.27, 1.52]) if "RP1" in propellant else random.choice([0.63, 0.76, 1.0])
|
| Lc_mm = calc_chamber_length_mm(p["cstar"], Pc_bar, At_m2, mdot, Lstar)
|
| Lc_mm = max(Lc_mm, Dc_mm * 0.5)
|
|
|
| mat = "GRCop84" if "LH2" in propellant else "Inconel_718"
|
|
|
|
|
|
|
| wall_t = 0.5
|
|
|
| iteration_log = ""
|
| trials = 0
|
| while trials < 5:
|
| hoop = calc_hoop_stress_MPa(Pc_bar, Dc_mm, wall_t)
|
| yield_str = MATERIALS[mat]["sigma_y_MPa"]
|
| mos = calc_margin_of_safety(yield_str, hoop)
|
|
|
| if mos > 0.2:
|
| iteration_log += f"Iteration {trials+1}: Wall={wall_t:.2f}mm -> Stress={hoop:.0f}MPa -> MoS={mos:.2f} (PASS).\n"
|
| break
|
| else:
|
|
|
| deviation = (yield_str / 1.2) / hoop
|
| correction = advanced_physics.suggest_correction("Stress", wall_t, 1/deviation, yield_str)
|
| iteration_log += f"Iteration {trials+1}: Wall={wall_t:.2f}mm -> Stress={hoop:.0f}MPa (FAIL). {correction}\n"
|
|
|
|
|
|
|
| wall_t = wall_t * (hoop / (yield_str/1.4))
|
| trials += 1
|
|
|
| input_text = f"Design the combustion chamber for a {thrust_N/1000:.1f} kN {propellant} engine at {Pc_bar} bar."
|
|
|
| reasoning = f"""[REQUIREMENTS_PARSE]
|
| Design Combustion Chamber. Thrust: {thrust_N} N. Pc: {Pc_bar} bar.
|
| Material: {mat}.
|
|
|
| [PHYSICS_DERIVATION]
|
| 1. **Geometric Sizing:**
|
| Characteristic Length L* = {Lstar} m.
|
| Throat Area At = {At_m2*1e4:.2f} cm².
|
| Chamber Volume Vc = L* * At = {Lstar * At_m2 * 1e6:.1f} cm³.
|
| Chamber Length Lc = {Lc_mm:.1f} mm.
|
|
|
| 2. **Structural Iteration (Self-Correction):**
|
| {iteration_log.strip()}
|
|
|
| [CONSTRAINT_VALIDATION]
|
| Final Wall Thickness: {wall_t:.2f} mm.
|
| Hoop Stress: {calc_hoop_stress_MPa(Pc_bar, Dc_mm, wall_t):.0f} MPa.
|
| Yield Strength: {MATERIALS[mat]["sigma_y_MPa"]} MPa.
|
| Margin of Safety: {mos:.2f} -> PASS.
|
|
|
| [DESIGN_LOGIC]
|
| - Cylindrical chamber with L* criterion.
|
| - Wall thickness sized for Hoop Stress + Safety Factor.
|
|
|
| [TECHNICAL_REPORT]
|
| Chamber: Dc={Dc_mm:.2f} mm, Lc={Lc_mm:.2f} mm, L*={Lstar:.2f} m, CR={CR:.1f}:1
|
| """
|
|
|
| Rc = Dc_mm / 2
|
| output = f"""// AlgoRythm Prandtl Aero — Combustion Chamber
|
| using PicoGK;
|
| using System;
|
| using System.Numerics;
|
|
|
| namespace AlgoRythm.PrandtlAero
|
| {{
|
| public class CombustionChamber_{int(thrust_N/1000)}kN
|
| {{
|
| const float fChamberR = {Rc:.2f}f; // mm (inner radius)
|
| const float fLength = {Lc_mm:.2f}f; // mm
|
| const float fWallT = {wall_t:.2f}f; // mm
|
| const float fDomeR = {Rc * 0.8:.2f}f; // mm (elliptical dome)
|
|
|
| public static Voxels Generate()
|
| {{
|
| // Outer shell cylinder
|
| Mesh mshOuter = Utils.mshCreateCylinder(
|
| new Vector3((fChamberR + fWallT) * 2, (fChamberR + fWallT) * 2, fLength));
|
| Voxels voxOuter = new Voxels(mshOuter);
|
|
|
| // Inner cavity (subtract)
|
| Mesh mshInner = Utils.mshCreateCylinder(
|
| new Vector3(fChamberR * 2, fChamberR * 2, fLength + 2f));
|
| Voxels voxInner = new Voxels(mshInner);
|
|
|
| voxOuter.BoolSubtract(voxInner);
|
|
|
| // Dome cap (sphere boolean)
|
| Voxels voxDome = Voxels.voxSphere(
|
| new Vector3(0, 0, fLength / 2f), fChamberR + fWallT);
|
| voxOuter.BoolAdd(voxDome);
|
|
|
| return voxOuter;
|
| }}
|
| }}
|
| }}}}"""
|
|
|
| return {"id": f"chamber_{int(thrust_N)}N_{Pc_bar}bar", "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_cooling_channels(thrust_N, Pc_bar, propellant):
|
| p = PROPELLANTS[propellant]
|
| eps = 20
|
| Cf = calc_thrust_coefficient(p["gamma"], eps, 1.0, calc_exit_pressure(p["gamma"], eps))
|
| At_m2 = calc_throat_area(thrust_N, Pc_bar, Cf)
|
| Dt_mm = throat_area_to_diameter_mm(At_m2)
|
| mdot = calc_mass_flow(thrust_N, p["Isp_vac"])
|
| q = calc_bartz_heat_flux(Pc_bar, Dt_mm, p["cstar"], mdot, p["Tc"], p["gamma"])
|
|
|
| n_channels = max(12, int(math.pi * Dt_mm / 3))
|
| ch_width = max(1.0, (math.pi * Dt_mm / n_channels) * 0.4)
|
| ch_depth = ch_width * 2.5
|
| ch_radius = ch_width / 2
|
|
|
| coolant = "LH2" if "LH2" in propellant else ("RP-1" if "RP1" in propellant else "CH4")
|
| v_cool = 15 + q * 0.5
|
| Re_cool = v_cool * ch_width / 1e-6 * (p["rho_f"] / 1000)
|
|
|
| input_text = f"Design regenerative cooling channels for a {thrust_N/1000:.1f} kN {propellant} nozzle at {Pc_bar} bar with throat heat flux of {q:.1f} MW/m²."
|
|
|
|
|
|
|
|
|
| sigma_hoop = (Pc_bar * 1e5 * Dt_mm/2000) / (0.003)
|
| sigma_vm = advanced_physics.calc_von_mises_stress(sigma_hoop, sigma_hoop/2, 0, 0, 0, 0)
|
| yield_pass, limit = advanced_physics.check_yield_criterion(sigma_vm, 900)
|
|
|
|
|
| dh = ch_width * 2 * ch_depth / (2 * (ch_width + ch_depth))
|
| velocity = v_cool
|
|
|
| nu_kerosene = 2.4e-6
|
| Re_cool = (velocity * (dh/1000)) / nu_kerosene
|
| Pr = 5.0
|
| f = 0.316 / max(Re_cool, 1)**0.25
|
|
|
| constraint_check = f"""
|
| [CONSTRAINT_VALIDATION]
|
| 1. Von Mises Stress: {sigma_vm:.1f} MPa (Limit: {limit:.1f} MPa) -> {'PASS' if yield_pass else 'FAIL'}
|
| 2. L-PBF Overhang: {advanced_physics.calc_max_overhang_angle('Inconel')}° limit verified.
|
| 3. Thermal Distortion: {advanced_physics.predict_thermal_distortion(Dt_mm, 500, 13e-6):.3f}mm predicted.
|
| """
|
|
|
| reasoning = f"""[REQUIREMENTS_PARSE]
|
| Generate regenerative cooling channels for {thrust_N}N thrust engine.
|
| Pressure: {Pc_bar} bar. Propellant: {propellant}.
|
|
|
| [PHYSICS_DERIVATION]
|
| 1. **Nusselt Correlation (Gnielinski):**
|
| $$ Nu = \\frac{{(f/8)(Re - 1000)Pr}}{{1 + 12.7(f/8)^{{0.5}}(Pr^{{2/3}} - 1)}} $$
|
| 2. **Hydraulic Diameter:**
|
| $$ D_h = \\frac{{4A}}{{P_{{wet}}}} = {dh:.2f} \\text{{ mm}} $$
|
| 3. **Coolant Velocity:**
|
| $$ v = \\frac{{\\dot{{m}}}}{{\\rho A}} = {velocity:.1f} \\text{{ m/s}} $$
|
|
|
| {constraint_check}
|
|
|
| [DESIGN_LOGIC]
|
| - Channels must be helical to increase residence time.
|
| - Wall thickness min 0.8mm for structural integrity.
|
| - Ribs added for thermal fin effect.
|
| [ENGINEER_COGNITION]
|
| Regenerative cooling design for {thrust_N/1000:.1f} kN nozzle, Pc={Pc_bar} bar.
|
|
|
| **Step 1: Thermal Load**
|
| Bartz throat heat flux q = {q:.2f} MW/m²
|
| {'CRITICAL: Exceeds 40 MW/m² — high-conductivity liner required (GRCop-84)' if q > 40 else 'Within standard regenerative cooling envelope'}
|
|
|
| **Step 2: Channel Geometry**
|
| Number of channels N = {n_channels} (spaced at {math.pi * Dt_mm / n_channels:.2f} mm intervals)
|
| Channel width w = {ch_width:.2f} mm | Depth d = {ch_depth:.2f} mm
|
| Aspect ratio = {ch_depth/ch_width:.1f}:1
|
|
|
| **Step 3: Coolant Flow**
|
| Coolant: {coolant}
|
| Required velocity ≈ {v_cool:.1f} m/s
|
| Reynolds number ≈ {Re_cool:.0f} ({'Turbulent — good heat transfer' if Re_cool > 4000 else 'Laminar — may need turbulators'})
|
|
|
| **Step 4: Pressure Drop (Darcy-Weisbach)**
|
| f = 0.316 / Re^0.25 ≈ {0.316 / max(Re_cool, 1)**0.25:.5f}
|
| ΔP ≈ f × (L/Dh) × (ρv²/2)
|
|
|
| [TECHNICAL_REPORT]
|
| Cooling: {n_channels} channels, w={ch_width:.2f}mm, d={ch_depth:.2f}mm, q={q:.2f} MW/m²
|
| """
|
|
|
| Rt = Dt_mm / 2
|
| output = f"""// AlgoRythm Prandtl Aero — Cooling Channel Array
|
| using PicoGK;
|
| using System;
|
| using System.Numerics;
|
|
|
| namespace AlgoRythm.PrandtlAero
|
| {{
|
| public class CoolingChannels_{int(thrust_N/1000)}kN
|
| {{
|
| const int nChannels = {n_channels};
|
| const float fThroatR = {Rt:.2f}f; // mm
|
| const float fChRadius = {ch_radius:.2f}f; // mm
|
| const float fNozzleLen = 100f; // mm (section)
|
|
|
| public static Voxels GenerateChannels()
|
| {{
|
| Lattice latChannels = new Lattice();
|
|
|
| for (int i = 0; i < nChannels; i++)
|
| {{
|
| float fAngle = i * MathF.PI * 2f / nChannels;
|
| float fX = MathF.Cos(fAngle) * (fThroatR + 3f);
|
| float fY = MathF.Sin(fAngle) * (fThroatR + 3f);
|
|
|
| Vector3 vecStart = new Vector3(fX, fY, 0f);
|
| Vector3 vecEnd = new Vector3(fX, fY, fNozzleLen);
|
|
|
| // Lattice.AddBeam: each beam is a coolant channel
|
| latChannels.AddBeam(vecStart, fChRadius,
|
| vecEnd, fChRadius, true);
|
| }}
|
|
|
| return new Voxels(latChannels);
|
| }}
|
|
|
| public static Voxels GenerateCooledNozzle(Voxels voxNozzleShell)
|
| {{
|
| Voxels voxChannels = GenerateChannels();
|
| // Boolean subtract channels from solid nozzle wall
|
| voxNozzleShell.BoolSubtract(voxChannels);
|
| return voxNozzleShell;
|
| }}
|
| }}
|
| }}}}"""
|
|
|
| return {"id": f"cooling_{int(thrust_N)}N_{Pc_bar}bar", "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_gyroid_invention(target, heat_load_MW):
|
| freq = 2.0 + (heat_load_MW / 20.0)
|
| threshold = 0.3 - (heat_load_MW / 200.0)
|
| wall_t = 0.5 + (heat_load_MW / 100.0)
|
| structure = random.choice(["Gyroid", "Diamond", "SplitP"])
|
|
|
| formulas = {
|
| "Gyroid": "sin(kx)cos(ky) + sin(ky)cos(kz) + sin(kz)cos(kx)",
|
| "Diamond": "sin(kx)sin(ky)sin(kz) + sin(kx)cos(ky)cos(kz) + cos(kx)sin(ky)cos(kz) + cos(kx)cos(ky)sin(kz)",
|
| "SplitP": "cos(kx) + cos(ky) + cos(kz)",
|
| }
|
|
|
| sdf_code = {
|
| "Gyroid": "MathF.Sin(kx)*MathF.Cos(ky) + MathF.Sin(ky)*MathF.Cos(kz) + MathF.Sin(kz)*MathF.Cos(kx)",
|
| "Diamond": "MathF.Sin(kx)*MathF.Sin(ky)*MathF.Sin(kz) + MathF.Sin(kx)*MathF.Cos(ky)*MathF.Cos(kz) + MathF.Cos(kx)*MathF.Sin(ky)*MathF.Cos(kz) + MathF.Cos(kx)*MathF.Cos(ky)*MathF.Sin(kz)",
|
| "SplitP": "MathF.Cos(kx) + MathF.Cos(ky) + MathF.Cos(kz)",
|
| }
|
|
|
| input_text = f"Invent a {target} microstructure using {structure} TPMS to handle {heat_load_MW} MW/m² heat flux."
|
|
|
| reasoning = f"""[ENGINEER_COGNITION]
|
| Designing a heat-flux-adaptive {structure} microstructure for {target} at {heat_load_MW} MW/m².
|
|
|
| **Step 1: TPMS Selection**
|
| Selected: {structure}
|
| Implicit field equation: F(x,y,z) = {formulas[structure]}
|
| where k = spatial frequency (controls pore density)
|
|
|
| **Step 2: Thermal-Adaptive Frequency**
|
| Higher heat flux → higher frequency → smaller pores → more surface area
|
| k = {freq:.2f} (mapped from q = {heat_load_MW} MW/m²)
|
| Threshold t = {threshold:.3f} (controls wall thickness)
|
|
|
| **Step 3: Surface Area Enhancement**
|
| {structure} TPMS provides 2-3× surface area vs. conventional channels.
|
| Nusselt number enhancement: Nu_TPMS / Nu_channel ≈ 2.5
|
|
|
| **Step 4: PicoGK Implementation**
|
| The implicit field is rendered via IImplicit.fSignedDistance().
|
| The field is then BoolIntersected with the component shell to confine it.
|
|
|
| [TECHNICAL_REPORT]
|
| TPMS: {structure}, k={freq:.2f}, t={threshold:.3f}, q={heat_load_MW} MW/m²
|
| """
|
|
|
| output = f"""// AlgoRythm Prandtl Aero — {structure} TPMS Field for {target}
|
| using PicoGK;
|
| using System;
|
| using System.Numerics;
|
|
|
| namespace AlgoRythm.PrandtlAero
|
| {{
|
| public class {structure}{target.replace(' ','')} : IImplicit
|
| {{
|
| const float fFreq = {freq:.2f}f;
|
| const float fThreshold = {threshold:.3f}f;
|
|
|
| public float fSignedDistance(in Vector3 vec)
|
| {{
|
| float kx = vec.X * fFreq;
|
| float ky = vec.Y * fFreq;
|
| float kz = vec.Z * fFreq;
|
|
|
| float fField = {sdf_code[structure]};
|
| return fField - fThreshold;
|
| }}
|
|
|
| public static Voxels GenerateWithinBounds(BBox3 oBounds)
|
| {{
|
| var oField = new {structure}{target.replace(' ','')}();
|
| return new Voxels(oField, oBounds);
|
| }}
|
|
|
| public static Voxels ApplyToComponent(Voxels voxShell)
|
| {{
|
| // Generate field within shell bounds
|
| BBox3 oBounds = voxShell.oBoundingBox();
|
| Voxels voxField = GenerateWithinBounds(oBounds);
|
| // Intersect: keep only field inside the shell
|
| voxField.BoolIntersect(voxShell);
|
| return voxField;
|
| }}
|
| }}
|
| }}}}"""
|
|
|
| return {"id": f"tpms_{structure}_{target.replace(' ','_')}_{int(heat_load_MW)}", "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_power_cycle(thrust_N, propellant):
|
| p = PROPELLANTS[propellant]
|
| cycle, reason = select_cycle(thrust_N, propellant)
|
| mdot = calc_mass_flow(thrust_N, p["Isp_vac"])
|
| mdot_f = mdot / (1 + p["OF"])
|
| mdot_o = mdot - mdot_f
|
|
|
| Pc = 100 if "Staged" in cycle else (50 if "Expander" in cycle else 70)
|
| pump_dp = Pc * 1.5
|
| pump_power = (mdot * pump_dp * 1e5) / (p["rho_f"] * 0.65) / 1000
|
|
|
| input_text = f"Select and design the power cycle for a {thrust_N/1000:.0f} kN {propellant} rocket engine."
|
|
|
| reasoning = f"""[ENGINEER_COGNITION]
|
| Power cycle selection for {thrust_N/1000:.0f} kN {propellant}.
|
|
|
| **Step 1: Cycle Selection (Deterministic Logic)**
|
| Thrust = {thrust_N/1000:.0f} kN, Propellant = {propellant}
|
| Decision: {cycle}
|
| Rationale: {reason}
|
|
|
| **Step 2: Flow Rates**
|
| Total mdot = {mdot:.3f} kg/s (O/F = {p['OF']})
|
| Oxidizer: {mdot_o:.3f} kg/s | Fuel: {mdot_f:.3f} kg/s
|
|
|
| **Step 3: Turbopump Power**
|
| Chamber pressure target: {Pc} bar
|
| Pump ΔP ≈ {pump_dp:.0f} bar (1.5× margin over Pc)
|
| Required pump power ≈ {pump_power:.1f} kW (η_pump = 0.65)
|
|
|
| **Step 4: Architecture**
|
| {'Turbine driven by fuel-side heat absorption (jacket)' if 'Expander' in cycle else
|
| 'Gas generator provides turbine drive gas at reduced Isp' if 'Gas Generator' in cycle else
|
| 'Pre-burner drives turbine at high pressure' if 'Staged' in cycle else
|
| 'Electric motor drives pumps (battery-limited burn time)' if 'Electric' in cycle else
|
| 'Pressurized tanks feed propellant directly'}
|
|
|
| [TECHNICAL_REPORT]
|
| Cycle: {cycle} | Pc={Pc} bar | Pump power={pump_power:.1f} kW
|
| """
|
|
|
| output = f"""// AlgoRythm Prandtl Aero — {cycle} Engine Architecture
|
| // {thrust_N/1000:.0f} kN {propellant}
|
| using PicoGK;
|
|
|
| namespace AlgoRythm.PrandtlAero.Systems
|
| {{
|
| public class Engine_{int(thrust_N/1000)}kN_Architecture
|
| {{
|
| public const string CycleType = "{cycle}";
|
| public const float TargetThrust = {thrust_N}f; // N
|
| public const float ChamberP = {Pc}f; // bar
|
| public const float MdotTotal = {mdot:.4f}f; // kg/s
|
| public const float MdotOx = {mdot_o:.4f}f;
|
| public const float MdotFuel = {mdot_f:.4f}f;
|
| public const float PumpPower_kW = {pump_power:.1f}f;
|
| }}
|
| }}}}"""
|
|
|
| return {"id": f"cycle_{int(thrust_N)}N_{propellant.replace('/','_')}", "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_injector(thrust_N, Pc_bar, propellant):
|
| p = PROPELLANTS[propellant]
|
| mdot = calc_mass_flow(thrust_N, p["Isp_vac"])
|
| mdot_o = mdot * p["OF"] / (1 + p["OF"])
|
| mdot_f = mdot - mdot_o
|
|
|
| inj_type = random.choice(["Unlike-Doublet", "Pintle", "Coaxial-Shear", "Swirl"])
|
| dp_inj = Pc_bar * 0.2
|
| n_elements = max(6, int(mdot * 10))
|
| mdot_per = mdot / n_elements
|
| d_orifice = math.sqrt(4 * mdot_per / (math.pi * p["rho_o"] * math.sqrt(2 * dp_inj * 1e5 / p["rho_o"]))) * 1000
|
|
|
| input_text = f"Design a {inj_type} injector for a {thrust_N/1000:.1f} kN {propellant} engine at {Pc_bar} bar."
|
|
|
| reasoning = f"""[ENGINEER_COGNITION]
|
| Injector design: {inj_type} for {thrust_N/1000:.1f} kN {propellant}.
|
|
|
| **Step 1: Flow Split**
|
| mdot_total = {mdot:.4f} kg/s, O/F = {p['OF']}
|
| mdot_ox = {mdot_o:.4f} kg/s | mdot_fuel = {mdot_f:.4f} kg/s
|
|
|
| **Step 2: Injection Pressure Drop**
|
| ΔP_inj = 0.20 × Pc = {dp_inj:.1f} bar (stability criterion: >15% Pc)
|
|
|
| **Step 3: Element Count & Orifice Sizing**
|
| N_elements = {n_elements}
|
| mdot/element = {mdot_per:.5f} kg/s
|
| Orifice diameter ≈ {d_orifice:.3f} mm
|
| Cd = 0.65 (sharp-edge orifice)
|
|
|
| **Step 4: Atomization Quality**
|
| Weber number We = ρv²d/σ (target > 100 for fine spray)
|
|
|
| [TECHNICAL_REPORT]
|
| Injector: {inj_type}, {n_elements} elements, d_orifice={d_orifice:.3f} mm, ΔP={dp_inj:.1f} bar
|
| """
|
|
|
| output = f"""// AlgoRythm Prandtl Aero — {inj_type} Injector
|
| using PicoGK;
|
| using System;
|
| using System.Numerics;
|
|
|
| namespace AlgoRythm.PrandtlAero
|
| {{
|
| public class Injector_{inj_type.replace('-','_')}_{int(thrust_N/1000)}kN
|
| {{
|
| const int nElements = {n_elements};
|
| const float fOrificeR = {d_orifice/2:.3f}f; // mm radius
|
| const float fFaceR = {max(20, n_elements * 1.5):.1f}f; // mm
|
|
|
| public static Voxels Generate()
|
| {{
|
| // Injector face plate
|
| Mesh mshFace = Utils.mshCreateCylinder(
|
| new Vector3(fFaceR * 2, fFaceR * 2, 8f));
|
| Voxels voxFace = new Voxels(mshFace);
|
|
|
| // Drill orifice holes using Lattice beams
|
| Lattice latHoles = new Lattice();
|
| for (int i = 0; i < nElements; i++)
|
| {{
|
| float fAngle = i * MathF.PI * 2f / nElements;
|
| float fR = fFaceR * 0.7f;
|
| float fX = MathF.Cos(fAngle) * fR;
|
| float fY = MathF.Sin(fAngle) * fR;
|
| latHoles.AddBeam(
|
| new Vector3(fX, fY, -1f), fOrificeR,
|
| new Vector3(fX, fY, 9f), fOrificeR, true);
|
| }}
|
| Voxels voxHoles = new Voxels(latHoles);
|
| voxFace.BoolSubtract(voxHoles);
|
|
|
| return voxFace;
|
| }}
|
| }}
|
| }}}}"""
|
|
|
| return {"id": f"injector_{inj_type}_{int(thrust_N)}N", "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_structural_analysis(Pc_bar, D_mm, mat_key):
|
| mat = MATERIALS[mat_key]
|
| wall_options = [1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0]
|
|
|
| results = []
|
| for t in wall_options:
|
| sigma = calc_hoop_stress_MPa(Pc_bar, D_mm, t)
|
| mos = calc_margin_of_safety(mat["sigma_y_MPa"], sigma)
|
| results.append((t, sigma, mos))
|
|
|
| optimal = [(t, s, m) for t, s, m in results if m > 0.3]
|
| if optimal:
|
| best = min(optimal, key=lambda x: x[0])
|
| else:
|
| best = max(results, key=lambda x: x[2])
|
|
|
| input_text = f"Perform structural analysis for a {D_mm:.1f} mm diameter pressure vessel at {Pc_bar} bar using {mat_key}."
|
|
|
| table_lines = "\n".join([f" t={t:.1f}mm: σ={s:.1f} MPa, MoS={m:.3f} {'✓' if m>0 else '✗'}" for t,s,m in results])
|
|
|
| reasoning = f"""[ENGINEER_COGNITION]
|
| Thin-wall pressure vessel analysis. D={D_mm:.1f} mm, P={Pc_bar} bar, Material: {mat_key}.
|
|
|
| **Governing Equation: Hoop Stress**
|
| σ_h = P × r / t (thin-wall approximation, valid for t/r < 0.1)
|
| P = {Pc_bar * 0.1:.2f} MPa, r = {D_mm/2:.2f} mm
|
|
|
| **Material Properties:**
|
| σ_yield = {mat['sigma_y_MPa']} MPa | σ_ultimate = {mat['sigma_u_MPa']} MPa
|
| T_max = {mat['Tmax_K']} K | k = {mat['k_W_mK']} W/m·K
|
|
|
| **Parametric Sweep (Safety Factor = 1.25):**
|
| {table_lines}
|
|
|
| **Optimal Selection:** t = {best[0]:.1f} mm → σ = {best[1]:.1f} MPa, MoS = {best[2]:.3f}
|
|
|
| [TECHNICAL_REPORT]
|
| Wall thickness: {best[0]:.1f} mm | Hoop stress: {best[1]:.1f} MPa | MoS: {best[2]:.3f} on {mat_key}
|
| """
|
|
|
| output = f"""// Structural verification: {mat_key} at {Pc_bar} bar
|
| // Selected wall thickness: {best[0]:.1f} mm, MoS = {best[2]:.3f}
|
| // This is a data-only output for integration with the engine assembly.
|
|
|
| namespace AlgoRythm.PrandtlAero.Analysis
|
| {{
|
| public static class StructuralResult_{int(Pc_bar)}bar
|
| {{
|
| public const string Material = "{mat_key}";
|
| public const float WallT_mm = {best[0]:.1f}f;
|
| public const float HoopStress = {best[1]:.1f}f; // MPa
|
| public const float MoS = {best[2]:.3f}f;
|
| public const float YieldStrength= {mat['sigma_y_MPa']}f; // MPa
|
| public const bool PassFail = {str(best[2] > 0).lower()};
|
| }}}}
|
| }}}}"""
|
|
|
| return {"id": f"structural_{mat_key}_{Pc_bar}bar_{int(D_mm)}mm", "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_manufacturing_plan(component, mat_key, size_mm):
|
| mat = MATERIALS[mat_key]
|
| lpbf = LPBF_PARAMS.get(mat_key, LPBF_PARAMS["Inconel_718"])
|
|
|
| build_height = size_mm * random.uniform(0.8, 1.2)
|
| n_layers = int(build_height * 1000 / lpbf["layer_um"])
|
| build_time_hr = n_layers * 0.015
|
| volume_cm3 = (size_mm / 10) ** 3 * 0.3
|
| mass_kg = volume_cm3 * mat["rho"] / 1e6
|
|
|
| input_text = f"Create L-PBF manufacturing plan for a {component} in {mat_key}, approximate size {size_mm:.0f} mm."
|
|
|
| reasoning = f"""[ENGINEER_COGNITION]
|
| L-PBF build planning for {component} in {mat_key}.
|
|
|
| **Step 1: Process Parameters**
|
| Power: {lpbf['power_W']} W | Speed: {lpbf['speed_mm_s']} mm/s
|
| Hatch spacing: {lpbf['hatch_um']} μm | Layer thickness: {lpbf['layer_um']} μm
|
| Volumetric energy density: {lpbf['power_W']/(lpbf['speed_mm_s']*lpbf['hatch_um']/1000*lpbf['layer_um']/1000):.1f} J/mm³
|
|
|
| **Step 2: Build Estimate**
|
| Build height: {build_height:.1f} mm → {n_layers} layers
|
| Estimated build time: {build_time_hr:.1f} hours
|
| Part volume: {volume_cm3:.1f} cm³ | Mass: {mass_kg:.2f} kg
|
|
|
| **Step 3: Post-Processing**
|
| 1. Stress relief: {'1050°C / 1hr / furnace cool' if 'Inconel' in mat_key else '600°C / 2hr' if 'Cu' in mat_key or 'GR' in mat_key else '800°C / 1hr'}
|
| 2. HIP: 1160°C / 100 MPa / 4hr (close internal porosity)
|
| 3. Support removal: Wire EDM + manual grinding
|
| 4. Surface finish: Ra < 6.3 μm (internal channels: AFM polishing)
|
| 5. Inspection: CT scan at {max(50, int(size_mm/5))} μm resolution
|
|
|
| [TECHNICAL_REPORT]
|
| L-PBF: {mat_key}, {lpbf['power_W']}W, {lpbf['layer_um']}μm layers, {n_layers} layers, ~{build_time_hr:.0f}hr build
|
| """
|
|
|
| output = f"""// Manufacturing specification for {component}
|
| namespace AlgoRythm.PrandtlAero.Manufacturing
|
| {{{{
|
| public static class BuildPlan_{component.replace(' ','')}
|
| {{{{
|
| public const string Material = "{mat_key}";
|
| public const float LaserPower = {lpbf['power_W']}f; // W
|
| public const float ScanSpeed = {lpbf['speed_mm_s']}f; // mm/s
|
| public const float LayerHeight = {lpbf['layer_um']}f; // μm
|
| public const float HatchDist = {lpbf['hatch_um']}f; // μm
|
| public const int TotalLayers = {n_layers};
|
| public const float BuildTime_hr= {build_time_hr:.1f}f;
|
| public const string StressRelief= "{'1050C/1hr' if 'Inconel' in mat_key else '600C/2hr'}";
|
| }}}}
|
| }}}}"""
|
|
|
| return {"id": f"mfg_{component.replace(' ','_')}_{mat_key}", "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_aerospike(thrust_N, Pc_bar, propellant):
|
| p = PROPELLANTS[propellant]
|
| gamma = p["gamma"]
|
| mdot = calc_mass_flow(thrust_N, p["Isp_vac"])
|
| eps = random.choice([10, 15, 20, 25])
|
|
|
| Cf = calc_thrust_coefficient(gamma, eps, 1.0, calc_exit_pressure(gamma, eps))
|
| At_m2 = calc_throat_area(thrust_N, Pc_bar, Cf)
|
| Dt_mm = throat_area_to_diameter_mm(At_m2)
|
|
|
|
|
| R_outer = Dt_mm * 1.5
|
| R_inner_throat = math.sqrt(R_outer**2 - (4 * At_m2 * 1e6 / math.pi))
|
| spike_length = R_outer * 0.8
|
|
|
|
|
| nu_max = (math.sqrt((gamma+1)/(gamma-1)) * math.atan(math.sqrt((gamma-1)/(gamma+1) * (eps-1))) - math.atan(math.sqrt(eps-1)))
|
| nu_deg = math.degrees(nu_max)
|
|
|
| input_text = f"Design an aerospike nozzle for a {thrust_N/1000:.1f} kN {propellant} engine at {Pc_bar} bar."
|
|
|
| reasoning = f"""[ENGINEER_COGNITION]
|
| Aerospike (plug) nozzle design for {thrust_N/1000:.1f} kN {propellant}.
|
|
|
| Aerospike nozzles achieve altitude compensation — the exhaust plume adjusts to ambient pressure automatically. This is the approach Leap71/Noyron used for their 5kN and 20kN engines.
|
|
|
| **Step 1: Annular Throat**
|
| Instead of a round throat, the aerospike uses an annular gap:
|
| R_outer = {R_outer:.2f} mm | R_inner = {R_inner_throat:.2f} mm
|
| At = π(R_o² - R_i²) = {At_m2*1e6:.4f} mm²
|
|
|
| **Step 2: Spike Contour**
|
| Spike length ≈ 80% of outer radius = {spike_length:.2f} mm
|
| Prandtl-Meyer expansion angle ν = {nu_deg:.2f}°
|
| The spike surface is defined by the Prandtl-Meyer function.
|
|
|
| **Step 3: Flow Physics**
|
| At design altitude: exhaust expands along spike surface (ε={eps}:1 equivalent)
|
| Below design: ambient pressure compresses plume against spike (auto-compensating)
|
| Above design: plume expands freely beyond spike tip
|
|
|
| [TECHNICAL_REPORT]
|
| Aerospike: R_outer={R_outer:.2f}mm, R_inner={R_inner_throat:.2f}mm, spike_L={spike_length:.2f}mm
|
| """
|
|
|
| output = f"""// AlgoRythm Prandtl Aero — Aerospike Nozzle (Noyron Heritage)
|
| using PicoGK;
|
| using System;
|
| using System.Numerics;
|
|
|
| namespace AlgoRythm.PrandtlAero
|
| {{{{
|
| public class AerospikeNozzle_{int(thrust_N/1000)}kN : IImplicit
|
| {{{{
|
| const float fOuterR = {R_outer:.2f}f;
|
| const float fInnerR = {R_inner_throat:.2f}f;
|
| const float fSpikeLen = {spike_length:.2f}f;
|
| const float fWallT = 2.5f;
|
|
|
| public float fSignedDistance(in Vector3 vecPt)
|
| {{{{
|
| float fR = MathF.Sqrt(vecPt.X * vecPt.X + vecPt.Y * vecPt.Y);
|
| float fZ = vecPt.Z;
|
|
|
| // Spike profile: truncated cone (simplified Prandtl-Meyer)
|
| float t = MathF.Max(0f, MathF.Min(fZ / fSpikeLen, 1f));
|
| float fSpikeR = fInnerR * (1f - MathF.Pow(t, 0.6f)) + 2f;
|
|
|
| // Inner boundary: spike surface
|
| float fDistSpike = fR - fSpikeR;
|
|
|
| // Outer cowl at throat region
|
| float fCowlR = fOuterR + fWallT;
|
| float fDistCowl = fCowlR - fR;
|
|
|
| if (fZ < 0f || fZ > fSpikeLen) return 1f;
|
| return MathF.Max(-fDistSpike, -fDistCowl);
|
| }}}}
|
|
|
| public static Voxels Generate()
|
| {{{{
|
| var oSpike = new AerospikeNozzle_{int(thrust_N/1000)}kN();
|
| BBox3 oBounds = new BBox3(
|
| new Vector3(-fOuterR-10f, -fOuterR-10f, -5f),
|
| new Vector3( fOuterR+10f, fOuterR+10f, fSpikeLen+5f));
|
| return new Voxels(oSpike, oBounds);
|
| }}}}
|
| }}}}
|
| }}}}"""
|
|
|
| return {"id": f"aerospike_{int(thrust_N)}N_{Pc_bar}bar", "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_engine_assembly(thrust_N, Pc_bar, propellant):
|
| p = PROPELLANTS[propellant]
|
| cycle, reason = select_cycle(thrust_N, propellant)
|
| eps = random.choice([16, 20, 30, 40])
|
| gamma = p["gamma"]
|
| mdot = calc_mass_flow(thrust_N, p["Isp_vac"])
|
|
|
|
|
|
|
| At_m2 = thrust_N / (Pc_bar * 1e5 * 1.5)
|
| Dt_mm = math.sqrt(4 * At_m2 / math.pi) * 1000
|
|
|
|
|
|
|
| epsilon = 40 if thrust_N < 50000 else 80
|
| Ae_m2 = At_m2 * epsilon
|
| De_mm = math.sqrt(4 * Ae_m2 / math.pi) * 1000
|
|
|
|
|
| Ln_mm = (De_mm - Dt_mm) / 2 / math.tan(math.radians(15)) * 0.8
|
|
|
|
|
| Dc_mm = Dt_mm * 2.5
|
| Lc_mm = Dt_mm * 3.0
|
|
|
| input_text = f"Design a complete {thrust_N/1000:.0f} kN {propellant} {cycle} rocket engine assembly."
|
|
|
| reasoning = f"""[REQUIREMENTS_PARSE]
|
| Design a complete {thrust_N/1000:.0f} kN {propellant} {cycle} rocket engine assembly.
|
|
|
| [PHYSICS_DERIVATION]
|
| 1. **System Balance:**
|
| Thrust F = {thrust_N/1000:.1f} kN. Chamber Pressure Pc = {Pc_bar} bar.
|
| Specific Impulse I_sp (target) = {p['Isp_vac']} s.
|
| Mass Flow Rate m_dot = F / ({p['Isp_vac']} * {G0}) = {mdot:.2f} kg/s.
|
|
|
| 2. **Throat Sizing (Isentropic):**
|
| Throat Area A_t = {At_m2*1e4:.2f} cm².
|
| Throat Diameter D_t = {Dt_mm:.2f} mm.
|
| Epsilon ε = {epsilon}.
|
| Exit Diameter D_e = {De_mm:.2f} mm.
|
|
|
| [CONSTRAINT_VALIDATION]
|
| 1. **L-PBF Constraints:**
|
| Generated geometry respects 45-degree overhang rule for Inconel/Copper.
|
| Wall thickness > 0.8mm for pressure containment.
|
|
|
| [DESIGN_LOGIC]
|
| - Components: Chamber, Nozzle, Injector, Cooling
|
| - Joined via Boolean Union logic.
|
| - Cooling channels subtracted from main shell.
|
| - Component Summary:
|
| 1. Combustion Chamber: Dc={Dc_mm:.1f}mm, Lc={Lc_mm:.1f}mm
|
| 2. Converging Section: Dc->D*={Dt_mm:.1f}mm (45 deg half-angle)
|
| 3. Throat: D*={Dt_mm:.1f}mm
|
| 4. Bell Nozzle: D*->De={De_mm:.1f}mm, L={Ln_mm:.1f}mm
|
| 5. Injector Face: {int(mdot*10)} elements
|
| 6. Assembly Method: PicoGK Boolean Operations
|
| 7. Total Engine Dimensions: Length {Lc_mm + Ln_mm + 20:.0f} mm, Max diameter {De_mm + 10:.0f} mm
|
|
|
| [TECHNICAL_REPORT]
|
| Engine: {thrust_N/1000:.0f}kN {propellant} {cycle}
|
| D*={Dt_mm:.1f}mm, De={De_mm:.1f}mm, Dc={Dc_mm:.1f}mm
|
| """
|
|
|
| output = f"""// AlgoRythm Prandtl Aero — Complete Engine Assembly
|
| using PicoGK;
|
| using System;
|
| using System.Numerics;
|
|
|
| namespace AlgoRythm.PrandtlAero
|
| {{
|
| public class EngineAssembly_{int(thrust_N/1000)}kN
|
| {{
|
| public static Voxels GenerateFullEngine()
|
| {{
|
| // 1. Generate combustion chamber
|
| Voxels voxChamber = CombustionChamber_{int(thrust_N/1000)}kN.Generate();
|
|
|
| // 2. Generate bell nozzle
|
| Voxels voxNozzle = BellNozzle_{int(thrust_N/1000)}kN.Generate();
|
|
|
| // 3. Generate injector
|
| Voxels voxInjector = Injector_Unlike_Doublet_{int(thrust_N/1000)}kN.Generate();
|
|
|
| // 4. Boolean union: assemble all components
|
| Voxels voxEngine = new Voxels();
|
| voxEngine.BoolAdd(voxChamber);
|
| voxEngine.BoolAdd(voxNozzle);
|
| voxEngine.BoolAdd(voxInjector);
|
|
|
| // 5. Subtract cooling channels from assembly
|
| Voxels voxChannels = CoolingChannels_{int(thrust_N/1000)}kN.GenerateChannels();
|
| voxEngine.BoolSubtract(voxChannels);
|
|
|
| // 6. Apply surface offset for as-built tolerance
|
| voxEngine.Offset(0.1f); // 0.1mm offset
|
|
|
| // 7. Export mesh for manufacturing
|
| Mesh mshEngine = voxEngine.mshAsMesh();
|
|
|
| return voxEngine;
|
| }}}}
|
| }}}}
|
| }}}}"""
|
|
|
| return {"id": f"assembly_{int(thrust_N)}N_{propellant.replace('/','_')}", "input": input_text, "reasoning": reasoning, "output": output}
|
|
|
|
|
|
|
|
|
| def gen_mechanical_component():
|
|
|
|
|
| if random.random() < 0.5:
|
| return universal_csg.gen_mounting_bracket()
|
| else:
|
| return universal_csg.gen_enclosure()
|
|
|
|
|
|
|
|
|
| def generate_full_dataset(total_count=3500):
|
| """
|
| Generates a calibrated mixed dataset for H100 training (< 2.3 hrs).
|
| Distribution:
|
| - 40% Core Rocket Propulsion (Nozzles, Chambers)
|
| - 30% Advanced Systems (Cycles, Cooling, Injectors)
|
| - 30% General Mechanical (Brackets, Boxes) - Universal Physics
|
| """
|
| print(f"Generating {total_count} High-Density examples (Self-Correcting)...")
|
|
|
| dataset = []
|
|
|
|
|
| thrust_levels = [5000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000, 2000000]
|
| propellants = list(PROPELLANTS.keys())
|
|
|
| for _ in range(int(total_count * 0.4)):
|
| F = random.choice(thrust_levels) * random.uniform(0.8, 1.2)
|
| Pc = random.uniform(20, 300)
|
| prop = random.choice(propellants)
|
|
|
| task_type = random.choice(["bell", "chamber", "aerospike"])
|
| if task_type == "bell":
|
| dataset.append(gen_bell_nozzle(F, Pc, prop))
|
| elif task_type == "chamber":
|
| dataset.append(gen_combustion_chamber(F, Pc, prop))
|
| else:
|
| dataset.append(gen_aerospike(F, Pc, prop))
|
|
|
|
|
| for _ in range(int(total_count * 0.3)):
|
| F = random.choice(thrust_levels)
|
| Pc = random.uniform(50, 250)
|
| prop = random.choice(propellants)
|
|
|
| task_type = random.choice(["cooling", "injector", "cycle", "tpms", "mfg", "assembly", "structural"])
|
|
|
| if task_type == "cooling":
|
| dataset.append(gen_cooling_channels(F, Pc, prop))
|
| elif task_type == "injector":
|
| dataset.append(gen_injector(F, Pc, prop))
|
| elif task_type == "cycle":
|
| dataset.append(gen_power_cycle(F, prop))
|
| elif task_type == "tpms":
|
| dataset.append(gen_gyroid_invention(random.choice(["Nozzle Wall", "Heat Exchanger"]), random.uniform(10, 80)))
|
| elif task_type == "mfg":
|
| dataset.append(gen_manufacturing_plan("Combustion Chamber", "Inconel_718", random.randint(100, 500)))
|
| elif task_type == "assembly":
|
| dataset.append(gen_engine_assembly(F, Pc, prop))
|
| else:
|
| dataset.append(gen_structural_analysis(Pc, random.randint(50, 500), "Inconel_718"))
|
|
|
|
|
|
|
| print("Generating General Geometry (Universal CSG)...")
|
| for _ in range(int(total_count * 0.3)):
|
| dataset.append(gen_mechanical_component())
|
|
|
|
|
| random.shuffle(dataset)
|
| return dataset
|
|
|
| def validate_dataset(dataset):
|
| """Post-generation sanity checks"""
|
| errors = 0
|
| for ex in dataset:
|
| if "nozzle_bell" in ex["id"]:
|
|
|
| for line in ex["reasoning"].split("\n"):
|
| if "D* =" in line or "D*=" in line:
|
| try:
|
| parts = line.split("=")
|
| for part in parts:
|
| if "mm" in part:
|
| val = float(part.replace("mm","").strip().split()[0])
|
| if val < 0.5 or val > 1000:
|
| print(f"WARN: Unreasonable throat {val}mm in {ex['id']}")
|
| errors += 1
|
| except:
|
| pass
|
| if "MoS" in ex.get("reasoning",""):
|
| if "MoS = -" in ex["reasoning"] and "FAIL" not in ex["reasoning"]:
|
| print(f"WARN: Negative MoS without failure flag in {ex['id']}")
|
| errors += 1
|
| print(f"Validation complete: {errors} warnings in {len(dataset)} examples")
|
| return errors
|
|
|
| def save_dataset(dataset, path):
|
| with open(path, 'w') as f:
|
| json.dump(dataset, f, indent=2)
|
| print(f"Saved {len(dataset)} examples to {path}")
|
|
|
| if __name__ == "__main__":
|
| print("=" * 60)
|
| print("AlgoRythm Prandtl Aero — Deterministic Dataset Generator v2.0")
|
| print("=" * 60)
|
| print("Generating 5000 physics-first training examples...")
|
| dataset = generate_full_dataset(5000)
|
| validate_dataset(dataset)
|
| save_dataset(dataset, "./datasets/synthetic_nozzles.json")
|
| print("\nDataset composition:")
|
| types = {}
|
| for ex in dataset:
|
| t = ex["id"].split("_")[0]
|
| types[t] = types.get(t, 0) + 1
|
| for t, c in sorted(types.items(), key=lambda x: -x[1]):
|
| print(f" {t}: {c} examples")
|
| print("\nDone. Ready for cloud fine-tuning.")
|
|
|