Methodology version: CL-METHODS-2026-11-09. This is an implementation account of core.py, filling.py, front.py, channel_design.py, feeding.py, web_adapter.py and field-view.js. Equations follow the actual code. A scientific citation identifies the underlying principle; it does not certify this particular implementation. Compare the run protocol's SHA-256 hashes when identifying modified code.
In everyday terms: the application estimates the amount of metal, cooling and solidification of an already filled casting, approximate filling times, and compression/escape of cavity gas. These are separate calculations. Cooling does not start by pouring into an empty mold. The filling/front model does not solidify flowing metal.
| Button | Actual calculation | Interpretation limit |
|---|---|---|
| Automatic channel/feeder design | Contraction volume, thermal-modulus/time inequalities, neck hydraulics and whole-assembly filling capacity; C3 and C4. | Not transient spatial feeding or a porosity guarantee. |
| Prepare geometry | Check, scale and orient STL; classify grid cells; propose channels; estimate mass and energy. | No physical filling simulation or optimized mold design. |
| Cooling and solidification | 3D conduction in metal and mold, latent heat, contact resistance and exterior heat loss. | No fluid motion, shrinkage, feeding, stress, porosity or alloy chemistry. |
| Hydraulic estimate | Graph reachability, equivalent circular-path resistance, ordered cell filling and approximate arrival times. | No resolved free surface, simultaneous branch flow or momentum field. |
| Front and trapped gas | Quasi-static cell invasion, gas pocket connectivity, isothermal compression and gas escape. | No Navier–Stokes/VOF solution and no evolving metal temperature. |
Always read the field title: °C means temperature; thermal liquid fraction describes phase; cavity filling fraction describes how much metal occupies a front-model cell. The two fractions are different physical quantities.
| Symbol | Meaning |
|---|---|
| Δx, Δt | Cubic cell edge [m], time step [s]. STL and channel coordinates are mm; Δx = pitch_mm/1000. |
| ρ, cₚ, k, L | Density [kg/m³], specific heat [J/(kg·K)], conductivity [W/(m·K)], latent heat [J/kg]. |
| T, Tₛ, Tₗ | Temperature, solidus, liquidus [°C]. Temperature differences have the same numerical value in K and °C; radiation and the gas law use T+273.15 [K]. |
| μ, ε, D, ℓ, K | Dynamic viscosity [Pa·s], roughness [m], equivalent diameter [m], path length [m], minor-loss coefficient [dimensionless]. K in the hydraulic equation is not kelvin. |
| p, pₐ, n, V, R | Absolute pressure [Pa], ambient absolute pressure [Pa], gas amount [mol], gas volume [m³], gas constant. |
| fₗ, α | Thermodynamic liquid fraction in the thermal model, and volume fill fraction in the front model, respectively; both range from 0 to 1. |
Implemented constants: g = 9.80665 m/s²; σ = 5.670374419×10⁻⁸ W/(m²·K⁴); R = 8.314462618 J/(mol·K); air molar mass = 0.02897 kg/mol; reference gas-source temperature = 293.15 K. Fundamental constants: NIST [R9]. Material properties are constant during a run. Presets are assumptions, not measured certificates or an automatic scrap analysis.
G1. Trimesh loads/processes a triangle mesh. Empty meshes, nonfinite vertices, non-watertight surfaces and inconsistent winding are rejected. Negative signed volume is inverted. Watertightness does not prove absence of self-intersections or correctness of the intended cavity. The browser additionally limits an STL to 20 MB.
Uniform scale uses the longest dimension before rotation; the library's default static XYZ Euler convention is then applied, followed by translation of the lower bounding corner to zero. Gravity acts toward −Z. Trimesh obtains volume and center of mass by surface integration. Its bundled triangles.mass_properties explicitly credits Eberly's polyhedral mass-properties derivation: [R1], library documentation [R2].
G2. Rays along +X classify cell centers by odd/even surface crossings. This local parity implementation is binary: it does not calculate cut-cell volume fractions. Barycentric triangle tests require u ≥ 0, v ≥ 0, u+v ≤ 1. Determinants ≤ 10⁻¹² in magnitude are excluded. Y/Z ray offsets are 1.234567×10⁻⁷ Δx and 2.345679×10⁻⁷ Δx; crossing positions closer than 10⁻⁹ Δx are merged. An odd remaining intersection count raises an error. These are numerical choices, not physical constants.
The mold has at least two padding cells. A preliminary size estimate uses the product of ceil((extent+2 margin)/pitch)+5 and rejects values above 300,000; it is not identical to the eventual grid size. Displayed grid.cells counts metal and mold. Features thinner than several cells may disappear, and small global volume error does not establish local channel accuracy.
The actual grid-shape product is also checked before allocation. If either actual or estimated count exceeds 300,000, a structured grid-limit response replaces a solver traceback. The proposed pitch targets at most 270,000 cells for both counts, leaving 10% headroom. An upper bracket grows by 1.25, followed by 48 bisection steps and rounding upward to 0.01 mm. Only the explicit retry button applies this coarser spatial resolution; other settings and requested snapshot timing are preserved.
G3. SciPy's Euclidean distance transform gives distance from a metal-cell center to the nearest nonmetal-cell center. Channel-placement thickness proxy is 2 max(d_EDT); flow diameter is D = max(Δx, 2d_EDT−Δx). This correction is not the exact hydraulic diameter 4A/P of an arbitrary cross-section. See [R3].
Mass uses material.rho. The Torricelli/Bernoulli-style expression is a simple gravity discharge estimate corrected by discharge = C_d. This coefficient does not enter the separate pipe_velocity calculation, which uses friction and minor losses. General ideal-flow energy balance: [R4].
Charge energy includes sensible and latent heat. Crucible, furnace walls, exhaust and openings have no separate dynamic model; their effects can only be lumped into the assumed efficiency. Furnace power does not control filling or casting cooling. Energy accounting background: [R5].
The illustrative Mg range uses f = cans_percent/100 and bounds 1.3f+0.35(1−f) and 1.6f+0.6(1−f), in mass %. This is only arithmetic mixing under the assumed input composition intervals. The code has no batch analysis, oxidation losses or validated universal can/profile composition. This estimate does not update material properties or calculate solidus/liquidus. Its assumed composition ranges have no batch-specific source in this application.
Plain explanation: every metal/mold cell stores energy and exchanges it with neighboring cells. Solidifying metal releases latent heat in addition to cooling, which increases the energy that must be removed through the freezing range.
The mold's ρL term is zero. Properties and dimensions stay constant during freezing. The entire cavity initially contains metal at one temperature; the surrounding mold starts at another uniform temperature. There is no advective heat transport. Enthalpy phase-change methods are described, for example, by Voller and Swaminathan (1991) [R6]; this application uses its own simple linear fₗ law, not that paper's complete verified implementation.
Example: Tₛ=580 °C and Tₗ=650 °C give fₗ=0.5 at 615 °C. With cₚ=1050 J/(kg·K) and L=390,000 J/kg, h=840,750 J/kg. The reference zero of h is arbitrary; differences matter. Apparent specific heat within this interval is cₚ+L/(Tₗ−Tₛ)≈6621.43 J/(kg·K). This is not a multicomponent phase diagram.
Half-cell conduction resistances and the optional metal–mold contact resistance act in series. Only face-sharing neighbors exchange heat. Symmetric sparse-matrix contributions ensure that an interior flux leaving one cell enters its neighbor. Finite-volume background: Patankar [R7]; conduction/resistance background: [R5].
The first term is convection to ambient air; the second is grey-surface radiation to large surroundings. Edges/corners contribute two/three exterior faces. The outer cell-center temperature substitutes for surface temperature; an additional outer half-cell resistance is not included. There is no air-flow field, radiative view-factor network or evolving emissivity. Heat-transfer principles: [R5].
Backward Euler advances time. The Newton-like iteration updates apparent heat capacity and radiation. dH/dT=ρcₚ+ρL/(Tₗ−Tₛ) strictly inside the freezing range and ρcₚ outside; the radiation derivative is 4εσ(T+273.15)³ times the exterior-face factor. Linear solves use conjugate gradients with diagonal preconditioning 1/diag(J): Hestenes and Stiefel [R8], SciPy cg [R10].
A small energy error establishes numerical balance of the chosen model, not experimental accuracy. freeze_time records the first accepted step with T≤Tₛ for a metal cell; it does not interpolate a precise crossing time. Unfrozen cells and mold cells remain NaN.
Gravity supplies pressure; friction and local restrictions consume it. The solver finds a velocity balancing those terms. A circular pipe is an engineering substitute for a complicated cavity, not its resolved flow geometry.
f is the Darcy friction factor, not Fanning's. The laminar branch corresponds to Hagen–Poiseuille flow; the turbulent formula is Haaland (1983) [R11]. Linear blending from Re=2300 to 4000 is this application's numerical choice, not a universal transition law. Viscosity/Reynolds-number background: [R12].
brentq solves for velocity with xtol=10⁻¹⁰ m/s. The upper bracket starts at max(1 m/s,√(2gh)) and doubles until it brackets a root; exceeding 10⁵ m/s raises an error. Nonpositive head returns zero. Root finding: Brent [R13], actual SciPy implementation [R14].
Metal cells form a six-neighbor graph. The start is the closest metal cell to gate. The fixed inlet level is the highest metal-cell center +Δx/2+head_mm. A priority queue uses a least-cost-path idea related to Dijkstra [R15]. However, length and bottleneck diameter depend on the already selected path; this is not a proof of optimal physical paths or a fixed-edge-weight graph.
This ordering proxy does not include roughness or Haaland friction. After ordering, each cell gets a fresh full F1 evaluation using roughness and effective length max(ℓ_path,Δx)+head_mm/1000+0.02 m. The extra 0.02 m is a fixed application assumption.
Arrival times accumulate cell by cell in the selected order. The model does not solve simultaneous branch-flow distribution or a local velocity vector field. Free venting is assumed; vent capacity and gas pressure are not evaluated in this mode.
The r/3 term is the volume-to-area ratio of a sphere used as a local-size substitute. The lumped energy-balance principle is standard ([R5]); this specific combination is an uncalibrated application screening heuristic. It is not coupled advective cooling, a defect probability or a rule that stops filling when metal freezes.
Initially α=0. One frontier cell is selected and filled partially; new neighbors become eligible when that cell is almost full. Priority starts with height Z and an auxiliary path length; blocked branches are postponed. Cells are queued on first discovery and paths are not subsequently globally optimized. This is a custom invasion heuristic. Wilkinson and Willemsen [R16] provide conceptual context for invasion and trapping, but their statistical invasion-percolation model is not implemented here.
Surface tension γ [N/m] and contact angle θ generate a positive barrier for nonwetting θ>90°. The nonnegative clamp excludes capillary suction for wetting surfaces. A circular diameter substitutes for actual meniscus curvature. Young–Laplace background: [R17].
F1 first estimates free-flow velocity and its Reynolds number. The resulting friction factor and blend are frozen during the subsequent pressure-root solve in that step:
For a=0, a linear branch uses Q=AΔp_net/max(b,10⁻¹²). Nonpositive net pressure gives Q=0. Freezing the friction coefficients is an additional approximation compared with resolving F1 at every trial gas pressure.
Metal entering a cavity cannot simply delete its air. Gas must either be compressed into a smaller volume or leave through vents/mold. The model tracks gas amount and infers pressure.
ndimage.label identifies six-neighbor pockets among cells with α<1−10⁻⁷. Each pocket has one user-assumed gas temperature and one uniform pressure; no internal pressure waves or velocity field. Gas inventory is redistributed according to remaining cell gas volumes after connectivity changes. Partly filled cells may overconnect gas regions.
κ is mold permeability [m²]. Wall area is counted from cavity-cell faces touching mold; one equivalent thickness substitutes for the full porous geometry. A vent is mapped to the nearest metal cell at its connection point and ceases to drain a pocket when its node is no longer a gas node. The pressure-squared form follows integration of Darcy/Poiseuille resistance for isothermal ideal gas. Porous-flow basis: Bear [R18]; viscous pipe-flow basis: [R12]. Uniform pocket pressure and equivalent geometry are application assumptions.
The tube-flow estimate for vents is capped by a simple orifice approximation with coefficient 0.65. This is not a compressible sonic-choking model; 0.65 is not calibrated for the user's vents. Subambient pressure permits modeled inflow. STL alone cannot determine permeability or actual vent performance.
The source is reference gas volume per interface area and second at 20 °C and pₐ, not binder chemistry or metal evaporation. Brent's method jointly solves pressure and displacement for the selected pocket with xtol=10⁻⁵ Pa. Other pockets use the same balance without displacement. The lower bracket is 1 Pa and the upper bracket expands by doubling. Root-finding sources: [R13], [R14].
After solving pressure, pocket inventory is n_pocket,new=V_pocket,new p_new/(RT_gas). Distribution uses new cell/pocket volumes.
The normal time step targets a quarter-cell displacement at the old rate; the lower time guard and rounding mean this is not an absolute bound. α>1−10⁻⁷ rounds to 1. Termination occurs at filled fraction ≥1−10⁻⁶, the time limit, an empty frontier or 60,000 steps. The gas-volume cap prevents numerical removal of all compressed gas. Escaped gas is a signed net quantity and can include inflow. Small molar balance error is a numerical check, not validation of bubble predictions. The helper gas_step implements an analytic quadratic step for a simpler single pocket; the current web run_front does not call it.
Array shifts estimate neighbor differences; the mold padding keeps the cavity away from the array boundary. This is a geometric interface-area/time indicator. No oxidation rate, film thickness, breaking or entrainment is calculated, and no calibrated conversion to oxide amount or casting defects exists.
Placement is an unvalidated geometric heuristic. The maximum distance-transform location is the thick-point proxy p. Gate minimizes squared X distance from p normalized by max(0.12 extent_x,1 mm), plus squared Z distance from the bottom normalized by max(0.25 extent_z,1 mm); Y distance does not enter this score.
The upper surface envelope uses XY bins of width max(pitch_mm,largest_extent/20). A vent candidate must be at least as high as eight neighboring bins. At most four highest candidates are retained with XY separation exceeding 15% of largest extent. Riser is the highest vertex within XY radius max(2pitch_mm,nearest_vertex_distance+0.01 mm) around p. These constants are application design choices.
| Part | Exact construction | Meaning |
|---|---|---|
| vtok_spojka / runner | Cylinder from gate shifted 0.4gate_mm toward the center of mass to elbow=[gate_x,min_model_y−20 mm,gate_z]. | Connects sprue to the casting; overlap assists union. |
| vtok_svisly / sprue | Cylinder from elbow vertically to max_model_z+head_mm. | Metal inlet, without taper or pouring basin. |
| odvzdusneni_N / vent_N | Cylinder from vents_N lowered by 0.4vent_mm to the same upper level. | Gas exit. Front physics uses its connection, diameter and equivalent length. |
| nalitek / riser + hrdlo_nalitku | Automatic: volume, modulus and neck according to C4. Manual: entered diameter and legacy geometry. | Reservoir for contraction feeding; sizing inequalities are not a spatial feeding simulation. |
Cylinders use 32 circumferential sections. The grid contains the input STL, not automatically the added channels. To include the unioned assembly in a subsequent calculation, import it as a new STL. Browser export calls Manifold union; failure leaves separate overlapping parts. Geometric union proves neither casting performance nor mold release. Library: [R19].
The physical thermal/front calculation is 3D, but the map is one XZ plane at Y index floor(N_y/2). Thermal history extrema concern all metal cells. Enhanced contrast uses extrema of the current section, which can differ from the 3D extrema. A span below 1 °C falls back to the full-run history range; a still-nearly-constant range expands by ±0.5 °C. Without enhanced contrast, the full-run scale stays fixed. Colors are not additional measurements.
For liquid fraction, temperature is interpolated first and then passed through the phase law. The separate model preview uses an orthographic triangle projection and average-depth ordering on Canvas. Its orange inlets, green vents and purple riser identify component types, not temperature.
Both temperature and filling use linear time interpolation. Intermediate images are not new solver solutions. Canvas spatial smoothing changes appearance, not grid accuracy. The seven interpolated RGB stops are [26,18,100], [40,85,203], [31,169,207], [106,212,123], [242,223,80], [242,135,38], [198,42,53]. Liquid/fill fraction scales are always 0–100%.
Default snapshot_dt is 0.25 s. Front planning uses max_time_s and may terminate early. Hydraulic snapshots use computed end time and arrival≤t, with ceil(t_end/interval)+1 frames. The target budget counts section values, not JSON overhead, other arrays or all browser memory; rounding and the final frame can slightly alter the count. Independent Python front calls can retain full 3D snapshots and then use N_xN_yN_z for the budget. Playback advances physical seconds multiplied by playback speed, not a fixed number of frame indices.
| Output | Exact meaning |
|---|---|
| objem_STL_cm3, hmotnost_scenar_kg | Transformed STL volume and mass using material.rho; proposed channels are not automatically included. |
| grid.volume_cm3, grid.cells | Metal-cell volume; all metal+mold cells. Volume error compares grid metal volume with surface STL volume. |
| liquid_fraction | Mean fₗ over equal-volume metal cells at final thermal time; not front α. |
| estimated_fill_s | Maximum finite hydraulic arrival time; null if no finite arrival exists. |
| geometrically_reached_fraction | Reachable cell count divided by metal-cell count; not proven casting success. |
| filled_fraction_reduced_model | Final Σα/N_metal in the front model. |
| maximum_gas_gauge_pa | Largest pocket pressure minus pₐ anywhere during the run, not just final pressure. |
| interface_exposure_m2_s | Estimated interface-area/time integral; not oxide mass. |
| settings.json, channels.json | Submitted configuration and actual channel points; effective dataclass defaults are also recorded in the protocol. |
| fields.npz | Common arrays: mask, origin_mm, pitch_mm. Thermal: temperature, freeze_time, history, snapshot_times, temperature_slices. Hydraulic: arrival_s, residence_s, thermal_ratio, local_diameter_mm. Front: fill_fraction, arrival_s, max_gas_gauge_pa, history, snapshot_times, snapshots. Web front snapshots are 2D sections. |
| history.csv — thermal | No header; time_s, T_min_C, T_mean_C, T_max_C, liquid_fraction, heat_out_J, energy_error_J. |
| history.csv — front | No header; time_s, filled_fraction, gas_gauge_pa, no_outlet_volume_cm3, interface_exposure_m2_s, gas_remaining_mol, gas_escaped_mol, gas_generated_mol. Normal records are made every 50 steps or when the heap empties. The last summary row uses historical maximum pressure and a placeholder zero for no-outlet volume; that zero is not proof of absent trapped gas. |
| front arrival_s | Time a cell becomes completely filled; partial cells can remain NaN. |
| assembly_union.stl | Unioned assembly only after successful Boolean union; individual STL parts can overlap. |
| run_protocol.json | Run identity, effective inputs, methods used, grid, scalar results, runtime versions, hashes and snapshot information. It is also downloadable from the technical panel. |
Nonfinite values become null in browser JSON; NPZ retains NaN. Hydraulic display history is generated from arrival times, not a separate solver history. Preview decimation takes approximately every max(1,floor(face_count/4000))-th body face; 4000 is not a strict face-count maximum and visual detail may be reduced.
Not implemented: coupled Navier–Stokes/energy equations, VOF/level-set free surfaces, turbulence, metal natural convection, temperature-dependent material properties, multicomponent/CALPHAD phase diagrams, dissolved hydrogen, evaporation, oxidation kinetics, oxide film entrainment, porosity, shrinkage, stress, mold deformation and transient spatial riser feeding. “Done” means algorithm completion, not a guaranteed sound casting.
Python/Pyodide executes in a browser worker. NumPy handles arrays; SciPy handles sparse systems, distance transforms and scalar roots; Trimesh handles meshes; Manifold handles union. Hashes identify input/code, not scientific correctness. Visitor/run counters are database counts of unique IDs, independent of physical prediction. Feedback and SMTP configuration are excluded from scientific run protocols.
The panel retains the last successfully completed protocol, including after a later failed operation. This is not a success claim about that later attempt. Before any run, an explanatory message replaces the previously empty area. Scientific protocols are generated locally in the browser.
| JSON field | Interpretation |
|---|---|
| methodology_version, methods_used, job | Documentation version, identifiers of active methods and actual job. E1 denotes the mass/energy estimates in chapter 4. |
| effective_config | Submitted inputs plus dataclass defaults. Inactive input groups are included for context; their presence does not mean they influenced that job. |
| packages, pyodide | Actual Python, NumPy, SciPy, Trimesh and Pyodide versions; online manuals may describe a different version. |
| input_file, input_sha256 | Input filename and hash of original STL bytes before transformation. No local filesystem path is read; hashes are neither an anonymity guarantee nor a geometry-similarity metric. |
| engine_sha256 | SHA-256 hashes of the downloaded core.py, filling.py, front.py and web_adapter.py. This does not fingerprint all library/browser/display code. |
| grid, channels, metrics, summary | Actual grid/origin, cell counts, connection points, simple estimates and scalar outcomes; see the output dictionary. |
| solver, snapshot_count, snapshot_largest_gap_s | Thermal accepted minimum step/rejected steps/energy checks where available, saved-frame count and largest actual interval, which may differ from requested snapshot_dt. |
| completed_at, elapsed_including_loading_ms | Computer-clock UTC completion time and worker elapsed time including first-run library loading; not pure solver CPU time. |
| events | Up to the last 100 session events in the separately downloaded protocol: readiness, start, module loading, completion, stop, export and errors. Library/Python error text may be English. Events are lost on reload. |
The protocol is separately downloadable as JSON and is included in new ZIP exports as run_protocol.json. ZIP metadata describes the completed calculation; additional UI events are included in the separate download. A protocol is not an independently replicated experiment.
These are original explanations of the application, not copied textbook chapters. Some articles require library access. None of the authors is claimed to have validated this application's custom heuristics.
The thermal calculation still starts with an already filled casting at a uniform metal temperature. It does not simulate solidification during filling. The user supplies a final temperature in °C, strictly between ambient and initial metal temperature. Integration stops after the first accepted step for which the maximum temperature of all metal cells is at or below this target, or at the maximum duration, whichever occurs first. Target completion is explicitly reported. A final snapshot is retained even if the target is reached between regular snapshot times. Reaching a target above solidus does not imply complete solidification.
At each accepted time step, the application counts metal cells with T ≤ solidus, solidus < T < liquidus, and T ≥ liquidus. These non-overlapping volume shares sum to one. The separately reported mean liquid fraction averages the linear phase fraction from T1; a partially solid cell therefore contributes to both solid and liquid material, while it belongs to the middle category in the cell-count bar. Neither quantity is a mass fraction. Temperatures and phase shares between recorded times are linearly interpolated for display, not recomputed by a new physical solve.
The default temperature palette has one fixed minimum and maximum over the entire run, so the same color means the same temperature at all times. Optional contrast enhancement rescales the current frame and must not be used to compare colors across time. The freezing map records the first accepted time at which each metal cell reaches T ≤ solidus. Blue marks earlier and red later recorded times; gray means the cell has not reached solidus by the selected time, including cells that never reach it within the run. This is not a continuous tracked interface or a prediction of shrinkage. The map is a central XZ slice; phase totals and minimum/mean/maximum temperature cover the entire casting. Exact full-grid fields remain in fields.npz. Thermal and numerical foundations are described in T1–T3 and N1, with [R5]–[R10].
Manifold Boolean union combines the full transformed casting mesh and channel solids; the preview is not used as manufacturing geometry. Disconnected unions are rejected. Ports are extended vertically to a common open top; the optional cup adds a flared inlet. A surrounding block is subtracted by the cavity and split at the requested percentage of the casting's extent on the chosen axis. Four alignment keys can be added; one has a larger radius to distinguish orientation. The mating holes include the entered radial clearance. The halves are rotated and translated onto Z = 0 with their cavities facing up. The combined layout separates them by 10 mm. Dimensions, transforms, ports, parameters and artifact hashes are retained in manufacturing_manifest.json. Operations use Manifold [R19].
Files: pattern_with_channels.stl is the joined positive; mold_A_print.stl and mold_B_print.stl are the negatives; mold_halves_layout.stl contains both printable halves. Units are millimeters. Automatic splitting does not resolve undercuts, removable cores, draft, print supports, refractory performance, structural strength or sealing. An ordinary plastic negative is not validated here for molten metal. The positive can be used in a suitable separate mold-making process. Changing casting size requires a new channel design before export; uniform slicer scaling changes actual channel capacity.
Revision 2026-11-11 replaces the reservoir/inlet diameter multiplier with C4. engine/channel_design.py first sizes the feeder and neck and then solves coupled filling-volume/capacity inequalities. The flow target is Qreq = Vfill,upper/τ, not casting volume alone. The volume upper bound includes casting, reservoir, the full neck including its penetration, runner, sprue, vents and funnel. Overlaps are deliberately counted twice. Circular areas bound polygonal channel volumes from above; the reservoir volume is the exact 64-sided prism volume. The manufactured reservoir reaches the common open pouring plane; its final height and volume are included in the calculation.
The external liquid path uses the actual runner and sprue lengths. The casting bounding-box diagonal is added as an explicitly unresolved internal-path proxy; it is not a 3D resistance network. Available static head is the elevation difference between the base pouring level and the casting inlet. Pressure losses subtract allowed gas pressure, hydraulic backpressure and the nonwetting Young–Laplace entry term. The existing Darcy–Weisbach/Haaland pipe solver calculates velocity. For the 32-sided channel, A = N D² sin(2π/N)/8 and hydraulic diameter Dh = D cos(π/N). Qcapacity = Au must satisfy Qcapacity ≥ Qreq. The separate front calculation remains necessary to examine internal bottlenecks and trapped gas; it does not simulate filling the feeder reservoir.
At gas pressure p = pa + Δp, each vent uses the lesser of isothermal compressible Poiseuille volume flow πr⁴(p²−pa²)/(16μLp) and orifice bound 0.65πr²√(2Δp/ρgas). The inscribed circular radius r = D cos(π/32)/2 gives a passage no larger than the printed polygon. Actual vent lengths extend from the attachment points to the final pouring plane. Summed capacity must exceed Qreq plus the entered gas-source allowance, converted to SI using casting surface area and Tgas/293.15. No porous escape is credited in sizing. All vents are assumed open; later closure/isolation can invalidate the separate front-model check.
The diameter search uses a growing bracket and 50 bisection iterations, then rounds upward to 0.1 mm and rechecks the inequality. A coupled outer iteration updates diameters, pouring plane, reservoir height, funnel/channel volumes and flow target until no diameter changes. An unsatisfied diameter bound of 500 mm or failure to converge produces an error; no geometric fallback is returned. Foundations: F1–F3 and P1–P3, [R11], [R12], [R17].
Implementation: engine/feeding.py. This is classical inequality-based feeder sizing, not a transient coupled shrinkage-flow simulation. The fed region is the entire casting plus the neck. Let Vc be casting volume, Vn neck volume, Vr reservoir volume, β the volumetric contraction on freezing, η the gross withdrawable reservoir fraction before its own contraction, and S the volume safety factor. All percentages are converted to fractions. The required reserve is obtained from
(η − β) Vr ≥ S β (Vc + Vn), with 0 < β < η ≤ 1 and S ≥ 1.
This explicitly subtracts contraction of the reservoir itself and includes the neck's contraction. Vn conservatively includes neck penetration and overlap. Neither β nor η is inferred from the STL or the metal's name. Defaults β = 6%, η = 25%, S = 1.15 are editable assumptions to verify for the alloy and mold. They are not certified values. The application rejects η ≤ β, nonpositive contraction, invalid safety factors and nonfinite values. This implementation does not cover expanding cast irons. The volume condition follows the form used in [R21]; its paper-specific aluminum/efficiency values are not imposed on other alloys.
Chvorinov's relation is t = B M², M = V/Acooling. The design casting modulus is the larger of the exact mesh V/A and a local inscribed-sphere lower bound Rmax/3. The grid distance transform selects an interior thick point; its radius is then measured by an exact closest-point calculation against all STL triangles, without an approximate voxel-to-surface distance conversion. Thin appendages can lower global V/A, hence this additional local check. It remains a geometric bound, not the actual modulus of every hot spot. With user reserve k > 1 and explicit ratio Br/Bc, require
tr/tc = (Br/Bc)(Mr/Mc)² ≥ k², equivalently Mr ≥ k Mc / √(Br/Bc).
Default k = 1.2 gives a required time ratio 1.44, under the stated constants. Default Br/Bc = 1 assumes comparable freezing constants; users must change it only with a justified calibration, especially for insulating/exothermic sleeves. No absolute freezing time is inferred without a calibrated B. Time/modulus principles and their limitations are covered by [R21], [R22].
The feeder is a cylinder with requested minimum H/D = 1.5. Actual geometry has 64 sides. With circumradius R, base area A0 = 32 R² sin(2π/64), perimeter P = 128 R sin(π/64), volume Vr = A0H and cooling area Ar = PH + 2A0 − Aneck. The top is counted as cooling and neck contact is removed from the bottom. Both ends of the neck are metal contacts, so its lateral-cooling modulus is Mn = d cos(π/64)/4. The design requires Mn ≥ Mc, assuming Bneck/Bcasting = 1. A single inlet-diameter multiplier is not used.
The neck base attaches to the selected casting point and penetrates it by 0.4d for a solid union. Its upper end reaches a reservoir base at least the user neck length above the casting's highest point; actual L is reported. The peak liquid feed demand is Qfeed = ppeak β(Vc+Vn)/τfeed. τfeed and ppeak are explicit inputs, not results of the separate thermal solve; defaults are 120 s and 2. Available head is conservatively evaluated at the end of gross usable withdrawal, h = L + H(1−η), less the capillary entry pressure divided by ρg. The Darcy–Weisbach/Haaland solver gives neck capacity, which must satisfy Qneck ≥ Qfeed. Increasing the neck changes its own shrinkage demand and reservoir contact area, so neck and reservoir are iterated together. The minimum neck diameter must satisfy geometric, thermal and hydraulic constraints simultaneously.
The positive STL includes the calculated neck and reservoir as separate connected solids. The open reservoir is extended to the common pouring plane, which can increase H above its requested minimum aspect ratio. Its actual polygonal volume, cooling area and modulus are recomputed and reported; this extension improves the volume and modulus inequalities. Neck-flow capacity reported at the minimum design height is conservative for the added head. The manufacturing manifest preserves feeding geometry and the complete calculation protocol. Export must use this same plane; it must not add another feeder-height increment.
Passing these conditions establishes the stated capacity/time inequalities only. A single feeder may still be unable to reach a remote hot spot through a freezing thin section. The separate thermal model includes the casting body, not the reservoir or transient metal withdrawal. There is no mushy-zone permeability, pressure-field solution, moving shrinkage cavity or calibrated porosity prediction here. The result therefore explicitly reports spatial_feeding_verified = false. Steel-specific feeding-distance rules in [R23] cannot be silently applied to arbitrary aluminum, lead or copper geometry. A successful whole-casting feeding simulation would require that additional calibrated model.
[R21] Optimal Design of the Gating and Riser System for Complex Casting Using an Evolutionary Algorithm, 2022, equations 12–13: modulus and volume conditions. The application's cylinder/neck search is its own implementation, not that paper's evolutionary optimizer.
[R22] NPTEL, Metal Casting, lectures 13–14: riser purpose, freezing-last condition and feeding distance.
[R23] SFSA / University of Iowa, Feeding and Risering Guidelines for Steel Castings: geometry, thermal conditions, feeding distance and Niyama-based validation. It is not universal alloy calibration.
A SHA-256 key identifies STL bytes, calculation method, canonically ordered complete input configuration, hashes of all six Python engine sources, runtime/library versions and cache schema. Only successful completed results are retained in IndexedDB on this origin. A cache hit returns the saved result without rerunning the solver or incrementing the completed-calculation counter. The locally generated Python state is retained alongside the input to restore geometry and numerical fields for subsequent STL/ZIP export. This state is not an import format: no uploaded pickle is accepted. Exports may still load Python/WebAssembly even when the displayed numerical result came from cache.
The cache retains at most six runs and a calculated budget of 192 MiB, evicting oldest entries. A run larger than the budget, denied storage, browser eviction or quota exhaustion can prevent persistence; the completed result is still shown and its cache status is reported. Clearing cache removes retained runs, not the currently displayed result. The browser may remove local data independently. Required user checks are source geometry, final size, metal properties, initial temperatures and thermal target. Other prefilled numbers are editable assumptions, not measured values. Changing physical inputs invalidates the displayed manufacturing source until preparation or simulation completes again. Zoom, language, playback and changing viewed quantities do not alter the calculation.