Close the heat-transfer and electrical gaps against ShipSIM - #6
Merged
Conversation
Ports the four ConvectionFactors, rebuilds ConvRadSunWall as a composition, adds a ship compartment and an environment boundary, and closes the electrical and fatigue gaps. Heat transfer - ConvectionBaseClass extends ThermalComponents.Interfaces.ConvectiveElement1D, which is upstream's ConvectionBaseClass with the same ports, ΔT and sign convention. All four factors extend it, so upstream's two different shapes become one. - ConvRadSunWall composes two view-factor-split BodyRadiation paths, ExternalConvection, IrradiationOnPlane, SunScreen and two PrescribedHeatFlows, in place of a flattened algebraic approximation that took h_c as an input and radiated the whole surface to the sky. - ShipCompartment is MultiportLumpedRoom with its fixed U_inner/U_outer replaced by the two convection factors, so a compartment's heat loss follows the ship's apparent wind. - EnvironmentHeatTransfer derives cloud cover from the irradiance shortfall on a clocked moving average with a night latch, plus sky temperature, wind vector and Magnus dew point. Electrical and fatigue - RandomStart is upstream's when-event scheduler as clocked logic on DiscreteComponents.UniformNoise, seeded and reproducible. ElectricalLoad is the EPLA: N consumers as parameter arrays rather than 177 hand-written instances. - src/Rainflow.jl counts cycles and accumulates Miner damage over the turning points EventPeakSampler emits. Upstream runs this inside the model on an algorithm section; it is post-processing, and clocked array state does not cross-compile. Fixes found on the way - sun_vector_world returned the northward component of the direction to the sun while negating the other two, so the sun stood in the northern sky. Nothing consumed SunVector_y before, so no earlier result changes. - ExternalConvection's wind speed is now sqrt(|u|² + u_reg²): sqrt(Σu²) has no gradient at the origin and |u|^0.78 an unbounded one, either of which kills the first step once the coefficient feeds a wall face with no capacitance. - OnOffConsumer takes its work signal behind a switching lag. A ZeroOrderHold's output collapses to its final value under symbolic indexing, and so does everything algebraically derived from it. 136 assertions across scripts/validate_heattransfer.jl (93) and scripts/validate_machinery.jl (43), on a clean regenerate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e reproducer The sun-vector sign error was filed under "corrections relative to upstream", which is where upstream's own defects go. It is ours: ShipSIM's SolarIrradiation negates all three components correctly. Moved to its own section. The MultiportVolume initialisation reproducer said "no component of ours in it" while using our SourceMoistAir. Rebuilt from library components only — MassFlowSource_TPhi and Boundary_pTPhi — and verified: solves at 20 C, returns InitialFailure at 0 C. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the remaining ShipSIM components that had been left out, plus three bugs the work exposed. Every claim below is checked by an assertion in one of the two validation scripts.
Heat transfer
The four
ConvectionFactors. Upstream'sInternal.ConvectionBaseClassisThermalComponents.Interfaces.ConvectiveElement1D— samesolid/fluidports, sameΔT,same sign convention — so
Thermal.ConvectionBaseClassextends the library interface andadds only
A,h,TavgandQ_flow = h·A·ΔT. The porting notes had blamedBuildingsHeatTransfernot resolving; it was never the blocker. Upstream gives its fourfactors two different shapes (two extend the base class, two wrap a
Convectionand driveits
Gc); all four extend the base class here, so they reporthandAthe same way —which is what
ShipCompartmentthen consumes.ConvRadSunWallrebuilt as a composition. The previous port flattened it into onealgebraic flux and took
h_cas an input. It now composes what upstream composes: twoBodyRadiationpaths split by view factor,ExternalConvection,IrradiationOnPlane,SunScreenand twoPrescribedHeatFlows. The flattened version had radiated the wholesurface to the sky, overstating night-time cooling on a vertical wall by a factor of two,
and had no transmission port, no sun-screen wiring and no sun-height gate.
ShipCompartmentisMultiportLumpedRoomwith its constantU_inner/U_outerreplaced by the two convection factors. A building's outside film coefficient is near
enough constant; a ship carries its own weather. Alongside, the two models agree (the
fixed
U_outer = 5really is the still-air 5.36); at sea the fixed-Umodel runs 2.75 Khot behind insulation, and 9.30 K on bare steel where the films are nearly the whole
resistance.
EnvironmentHeatTransferderives cloud cover from the irradiance shortfall againstclear sky — a clocked moving average with a night latch, where upstream uses
Mean(f=1/1800)and awhen IsDay == false— plus sky temperature, wind vector and aMagnus dew point (upstream's linear form
asserts it is only valid above 50 % RH).Electrical and fatigue
RandomStartis upstream'swhen time >= pre(NextStep)scheduler written in theclocked sublanguage on
DiscreteComponents.UniformNoise— seeded and reproducible. Thenote in
OnOffConsumersaying this could not be expressed in Dyad predatedDiscreteComponents.ElectricalLoadis the EPLA thatMiscSamples.Balanceperforms, with the consumerlist as parameter arrays rather than 177 hand-written instances. Six consumers over six
hours: bus load 0–67 kW across 51 distinct levels, 24.9 kW average against 79.1 kW
installed, diversity factor 0.314.
Rainflow as Julia, not a component.
src/Rainflow.jlcounts cycles (ASTM E1049three-point), bins the matrix and accumulates Miner damage over the turning points
EventPeakSampleralready emits. Upstream runs it inside the model on analgorithmsection with two stacks and
whileloops. The clocked layer could express a boundedversion, but counting cycles is post-processing over a series: it has no state the rest of
the model can see, it needs an unbounded stack to be exact, and clocked array state does
not cross-compile (SynchToolkit #212), so a model carrying one could not be deployed.
Three bugs this exposed
sun_vector_worldhad the sun in the northern sky. It negated the east and upcomponents to turn direction-to-sun into ray direction, but not the north one. A
south-facing wall was lit at dawn and dusk and dark at noon. Latent since the solar port:
IrradianceOnPaneluses only the vertical component and nothing else consumedSunVector_y. The two solstice analyses are the regression check — in winter the southwall takes the whole gain and the north none; in summer that inverts, which is the real
behaviour of a vertical wall at 43°N.
ExternalConvectionwas not differentiable at rest.sqrt(u_x²+u_y²+u_z²)has nogradient at the origin (
0/0) and|u|^0.78an unbounded one; amax(|u|, tiny)floorbounds neither. Either puts a NaN or a 2400 W/(m²·K) per m/s entry in the Jacobian at
t = 0. Between two ideal temperature sources neither shows — which is why the §1 suitepassed — but with a wall face that has no capacitance the integrator drives
dtbelowfloating-point epsilon and reports only "unstable". A steady wind of any speed hides
it, zero included; it is passing through zero that fails, which is what a ship leaving
harbour does.
ZeroOrderHoldcollapses everything downstream of it, not just itself. The knowncaveat is that its continuous output reads back as its final value under symbolic
indexing. It also collapses anything algebraically derived from it. An
ElectricalLoadbank read back as a flat line, every consumer that happened to be off at the end
reporting zero for the whole run, while the model had integrated all six correctly. Fixed
by putting a state in the path in both places it bit — a switching lag in
OnOffConsumer,a one-tick lag on the cloud ratio.
Library findings, recorded in
PORTING_NOTES.mdHVACComponents0.3.0 will not initialise aMultiportVolumewhose moist-air fluidboundary is below about 15 °C. Minimal reproducer with no component of ours in it; the
media's own property functions are exact down to −5 °C, so it is in the assembled DAE.
Only fluid ports are affected, so the deckhouse still runs its 0 °C winter case on a
preheated supply — which is what a ship does anyway.
ThreeTempWall1D.m_wallandOneTempWall1D.m_wallare documented as the total massacross N surfaces but each surface's balance divides by the whole of it.
Validation
scripts/validate_heattransfer.jl— 93 assertions.scripts/validate_machinery.jl— 43.Both green on a clean
rm -rf generated && dyad compile. Correlations are recomputed fromthe literature in the test rather than read off the port; the wall's radiation split is
checked against the view factors on the solver's own saved steps; rainflow is checked
against hand-worked sequences.
Not ported, and why, is in
PORTING_NOTES.md:TriggerConsumer/StartGenerator(variantsof
RandomStart, writable the same way),SunIrradianceMultibody,SubComponents.Ikeda(a stub upstream) and
VariableTranslation.🤖 Generated with Claude Code