English
Español
中文
Português
العربية
हिन्दी
Русский
×
sandbattery
A simulation of a cheap way to heat a house with sunshine stored in sand. Solar panels heat steel
wires buried in a box of sand, and the hot sand warms the house for days afterwards. The design is
meant for places where people are poor, winters are cold, and imported equipment is hard to get and
harder to repair. The simulation follows the box, its wires, the panels and the house through weeks
of synthetic winter weather by solving the heat equation ; a web page shows the result in
3-D, and every step of a run can be exported, so that anyone can check the result without having to
trust the program.
This is a design study: the box has not been built and measured yet.
Why store heat?
Solar panels have become very cheap. Their price has followed Swanson's law , falling about 20 % for every
doubling of the number ever made: from about US$77 per watt for the cells alone in 1977 to about
US$0.09 per watt for whole panels, wholesale,
in 2025 . Where the sun shines, the panels are no longer the expensive part of solar energy. The
expensive part is having the energy when the sun is down.
Batteries store electricity, but the battery packs alone cost about US$19 per MJ of capacity
(US$70 per kilowatt-hour , the
2025 average for stationary storage ), before the inverters and chargers that go with them.
Most of the energy a home in a cold climate uses, though, is heat, and heat is far cheaper to store.
Sensible heat , stored by making a material
hotter rather than by melting or boiling it ,
needs only something cheap that stands being hot, and insulation around it. The box simulated here
holds about 970 MJ in 2.3 t of quartz sand heated
from 20 to 450 °C. Its sand, bricks and wire cost about US$170, and its plaster and insulation about
US$230 more: about US$410 in all, or US$0.42 per MJ of capacity, about forty-five times less than
battery packs. The insulation is a thin layer of LECA , lightweight expanded clay
aggregate (pellets of clay fired in a kiln until they bloat with bubbles, sold for gardens and
lightweight concrete), with fiberglass outside it, where it stays cool enough for the fiberglass.
Where wood ash or rice-husk ash is at hand, it can take the LECA's place on the sides and top for
nothing. Sand is so cheap that most of its price is the cost of trucking it to the site, so it
varies with how far the truck has to go. Electricity from panels turns into heat without loss in a
plain resistance wire , so the cheap
storage costs nothing in conversion. A heat
pump would get about three
times as much heat from the same electricity, but it costs far more, and needs the kind of
repairs that are hardest to get where this design is aimed.
Storing heat is old. Masonry stoves have kept the heat of a fire
for a day for centuries, and in Finland, Polar Night
Energy's "sand batteries" now feed district heating networks: one at
Pornainen, running since 2025, holds 100 MWh (360 GJ) in about 2 000 t of crushed soapstone , ten times as much as its first, at
Kankaanpää in 2022. What is new is how cheap solar heat has become, which makes the idea worth
trying for a single house.
How big is the problem?
Heat is the world's largest use of energy: almost half of all the energy used at its point of use
(final energy ) goes to heat . Buildings use about 30 % of the world's final energy,
and about half of that goes to heating
rooms and water , so keeping buildings and their water warm takes roughly a seventh of all final
energy. Over 60 % of the energy for heating still comes from burning fossil fuels. Cooling is
smaller but growing fast: air conditioners and fans used about 7.6 EJ of electricity in 2022 (2 100
terawatt-hours), about
7 % of the world's electricity . These totals include the firewood, dung and crop waste that
people gather rather than buy, which is much of what the poorest households burn.
Burning fuel indoors also kills. Smoke from cooking on open fires and stoves fueled by wood,
dung, crop waste, coal and kerosene causes about 2.9
million deaths a year , and heating with them adds to it where winters are cold. In Ulaanbaatar , Mongolia, where about 60 % of the
city's 1.5 million people lived in gers , each household burned 3 to 6 tonnes of raw
coal a winter , and next to a ger district particulate levels (PM2.5 ) peaked above 2 000 µg/m³, 80
times the 25 µg/m³ that the World Health Organization then recommended as a daily limit.
Who needs it?
In 2022, about 838 million people, one in ten, lived on less than US$3.00 a day, and about 3.8
billion, nearly half of humanity, on less than US$8.30 a day, at 2021 purchasing-power prices (World
Bank ). A household with that much to live on cannot buy a heat pump or a bank of batteries, nor
pay for repairs, and a season's fuel can take a large share of its income. Many of the world's poor
live in the tropics and need cooling more than heating, but many others live where winters are cold:
on the Altiplano of Peru and Bolivia, around
Puno and El Alto , nearly 4 000 m up; in southern Chile and
Patagonia , where towns such as Temuco heat with firewood; in the Himalaya , Afghanistan, Central Asia and Mongolia; in northern China;
and in parts of Eastern Europe and southern Africa, such as Lesotho .
For them, a heater that burns nothing, made mostly of sand, bricks and wire, fed by panels whose
price keeps falling, could replace much of what they now burn, saving both money and smoke. This
simulation is a way to find out how much it could replace, at what size and cost, before anyone
builds one.
Building where supply chains are thin
In many poor countries, specialized equipment has to be imported, paid for in foreign currency
and cleared through customs, and installed and repaired by technicians who are few and far between;
spare parts are scarce. Systems built around batteries and inverters suffer for it. Nearly half of
Bangladesh's household solar systems have stopped working, according to a survey by
the Centre for Policy Dialogue and the newspaper Samakal ; failed batteries were the most common
problem, reported by 77 % of respondents, and inverters were among the others.
So this design has neither batteries nor an inverter. The panels are wired straight to the
heating elements, and a small controller switches elements on and off so that their total resistance
keeps the panels near the point where they give the most power, a simple form of maximum power point tracking .
The box is sand, which is everywhere; hollow clay bricks , which are made in
most countries; baling wire , sold wherever
farmers bale hay; and loose insulation such as LECA, perlite , rice-husk ash or wood ash, with fiberglass
outside it where that is sold. The panels are the one specialized part, and they are a mass-produced
commodity that lasts decades.
The design
A box of quartz sand, 2.4 × 0.6 × 1.0 m in the default case, holds runs of mild-steel baling wire
through its middle. Septa, walls across the box, divide the sand into sections about 0.6 m long,
four by default. The septa and the box's own walls are hollow clay bricks stood on end, so that
their cores line up into vertical flues : room air
rises through them, takes heat from the bricks and warms the room. The septa's flues draw heat from
deep in the sand, which conducts heat poorly. Air comes into each flue at the bottom through bricks
laid flat. Each bottom brick of the outer walls is cut through at 45°, and the cut-off piece turned
half a turn on its cut face and mortared back, the mortar on the webs and the cores left open, which
makes an elbow whose cores lead out through the insulation at the floor. Each column of a septum
turns the same way into a brick laid on edge, as wide as the septum, which runs out through the
nearer long wall; the farther columns' bricks run lower, beneath the nearer ones, so that each
septum stands on a stack of them at each side, topped by a brick laid flat that feeds the long
wall's flues above. Every flue so has an elbow of its own as wide as itself, and no inlet is
narrower than its flue. A baffle over the
inlets lets a thermostat start and stop the
flow; it fails open , so the house still gets
heat if the control fails. Only room air touches it, so it can be light and cheap, even cardboard.
With the inlets shut, though, the flues' open tops would still let hot air rise out and cool air
sink in, so the flues need a hood: for instance a countertop of lime-sand mortar on steel mesh, a
few centimeters thick, on pillars a few centimeters above the box and overhanging it, with a skirt
reaching a few centimeters below the flues' tops. It holds the hot air in, like an upturned cup,
while the inlets are shut, lets it out under the skirt while they are open, and makes the box a work
table. The model stops the flow when the baffle is shut, as the hood would, but leaves the brick
tops open to the room, about a fifth of the heat the box leaks into the room. A few centimeters of
clay-sand plaster on the outside of the brick walls seal the flues, so that air moves through them
only from their inlets to their tops. Outside the plaster, and over the sand, 2 cm of LECA and then
10 cm of fiberglass keep the rest of the heat in; the LECA keeps the fiberglass below the 230 °C its
binder stands. Underneath, 0.2 m of LECA carries the sand. A resistance heater in the room can take the
panels' power directly whenever the house is cold and the sun is out. The controller keeps the wire
below 600 °C and the sand below 450 °C, and stops heating while any layer of plaster or insulation
is within 30 K of the most it stands. When it is mild outdoors, it holds the sand cooler, so that
the heat leaking through the insulation does not overheat the house. Nichrome wire can take the
baling wire's place.
What the simulation shows
The default case is a small, well-insulated house that loses 55 W for each kelvin it is warmer than outdoors: about 1 kW on
average when it is 18 °C inside and 0 °C out. It has 6.3 kW of panels and the box above, with 2.3 t
of sand, starting cold at 20 °C. The weather is 14 synthetic winter days averaging 0 °C, 5 K warmer
in the afternoon and 5 K colder before dawn, with 10 hours of daylight; a quarter of the days are
cloudy, with a fifth of a clear day's sun. Over those 14 days:
the panels could have given 1 622 MJ; 1 267 MJ went into the sand, and 272 MJ went straight into
the room through the room heater;
the box gave the house 901 MJ, 708 MJ of it through the flues, and lost 74 MJ into the
ground;
the house stayed between 14.8 and 18.7 °C and burned no fuel at all; without the room heater it
would have burned 4 MJ, the heat in about a tenth of a liter of diesel;
the sand reached 317 °C, the fiberglass 171 °C, below the 230 °C its binder stands, and the
outside of the box 46 °C.
Changing the weather:
a cloudy spell of 5 days from the eighth day: 122 MJ of fuel (3.4 liters of diesel);
30 days: no fuel;
30 days with a cloudy spell of 7 days from the 21st: 223 MJ (6.2 liters);
30 days averaging −10 °C: 699 MJ (20 liters), 20 % of the heat the house lost; the box and
panels are too small for that climate;
14 days averaging 8 °C: no fuel, and the house stays below 19 °C, because the controller holds
the sand to about 250 °C; holding it to 450 °C, as in cold weather, would let the box warm the house
to 21.1 °C, and the fiberglass would reach 214 °C, close to its limit, even though the layer limit
stopped the heating whenever it passed 200 °C, 33 ks of sunshine in all;
45 days whose mean falls steadily from 8 to −10 °C, as autumn turns into winter: 143 MJ (4.0
liters), with the house at 18.9 °C at the warmest.
So a box 3.2 × 1.1 × 1.3 m outside, holding 2.3 t of sand, with fourteen 450 W panels, can keep a
small, well-insulated house between 14 and 19 °C through a mild winter without fuel, and through
cloudy spells with a few liters' worth. For comparison, the same house through 150 such days would
lose about 12 GJ, the heat in about 340 liters of diesel. Without any panels, the same house burns
859 MJ of fuel in the 14 days, the heat in 24 liters of diesel, and 3 360 MJ (94 liters) in 30 days
averaging −10 °C, only to stay at 14 °C, the temperature below which the simulation burns fuel;
setting the array size to 0 on the page shows this. At the default prices, which are retail and
assume panels at US$0.28 per watt, LECA at US$0.20 a liter and fiberglass at US$0.026, the panels
cost US$1 764, the sand, bricks and wire US$174, and the plaster and insulation US$141: US$2 079 in
all, US$315 of it the storage.
The previous design here had no septa or plaster and a single layer of LECA, 0.1 m on the sides
and 0.2 m on top. Modeled with the same inlets, its storage costs US$453, US$138 more than this
one's. This one burns 31 MJ less fuel in the month at −10 °C and keeps the house from overheating in
mild weather, but it burns 25 MJ more in the 7-day spell, which it enters with cooler sand. The
plaster makes little difference to the heat (lime-sand, clay-sand or none burn within 2 MJ of the
same fuel); it is there to seal the flues. The outer walls' legs, crossing the insulation at the
floor, cost 5 to 7 MJ of fuel a month. Keeping the wire 0.15 m from the walls and septa, instead of
0.1 m, would save about 15 MJ in the spell, but packs it 3 cm apart; 0.2 m would cost 66 MJ, because
the sand by the wire then reaches its limit. Wood ash, free wherever people heat with wood, gives
the same results in place of the 2 cm of LECA, since the model takes its conductivity to be about
LECA's (a guess that wants measuring); the storage then costs US$272, and with 15 cm more ash in
place of the fiberglass, US$248.
Nichrome instead of baling wire, 1 mm thick at 100 W/m (73 W/m as built) with the wire limit at
1 000 °C, burns 179 MJ in the 7-day spell and 632 MJ at −10 °C. Its resistance hardly changes with
temperature, whereas steel's, sized for wire at 500 °C, is a quarter of that when cold and about
half at 250 °C, so that in dim light even one steel element can load the panels too heavily and pull
them below their best voltage. Nichrome used 96 % of the panels' energy in the month with the spell,
against 93 % for steel. Its 72 m cost about US$13 at US$0.18 a meter.
The limits of these numbers: the house is a single lump of heat capacity , the weather is synthetic, the
flue model is a simple balance of buoyancy
against friction, and the material properties come from handbooks rather than from measurements of
local sand and bricks. The ground under the box is a fixed 10 °C reached through 2 W/(m²·K), more
like damp soil near the water table than dry ground, which would warm up and lose less. Every run
starts with cold sand, whereas a real box would start the winter charged by autumn sun. And none of
it has been checked against a real box.
Checking the results without trusting the code
Almost all of this program was written by an AI model (Claude , made by Anthropic ) at its author's direction. Code
written that way can contain mistakes that look plausible, as code written by people can. The
program checks itself: the energy
budget closes to about 10⁻¹⁵ of the heat that came in and went out, the solver's error on a problem with a known answer shrinks by a factor
approaching four each time the cells are halved, as it should, and the wire model matches an exact
solution. But those checks are part of the same program.
So the page can export a whole run. "Prepare the whole run as CSV" gives a zip of CSV files (plain text that any
spreadsheet or program can read) with every cell's temperature at the start of every step of the
solver, the heat put into every cell during the step, each cell's material, the materials'
properties, each step's length and boundary temperatures, and a README that states the rule every
step must obey. A short program of your own, in any language, can read the files and redo every
step. If, in every cell and at every step, the change in heat content equals the heat that flowed in
through the cell's faces plus the heat put into it, within the rounding of the export, then the
temperatures are a correct solution of the heat equation for those materials and heat inputs,
whatever mistakes the program may contain. One of the program's own tests does exactly that, and the
default run's export is about 233 MB.
What the files cannot settle by themselves is whether the heat inputs, from the wire, the flues
and the room, and the material properties are right. Those are in the files too, where they can be
compared with what the panels can deliver, with each other and with published values. Whether the
model matches a real box takes building one and measuring it.
Building and running
It needs Node 22 or later and TypeScript (tsc), and no
npm packages.
make test # compile to build/ and run the tests (about 40 s)
make bundle # compile and write the page
make # both
make bundle writes dist/sandbattery.html, one
self-contained file with no external resources; open it in a browser. It has two scripts, both
readable in View Source: the simulation's worker , in a <script
type="text/js-worker"> that the browser does not run, and the page's own script,
which reads the worker's text and starts it. Each script holds only the modules its code requires.
This README and its translations are in the page too, under "Read me".
The simulation also runs without the page:
node build/src/cli.js --days-table
node build/src/cli.js --set cell=0.03 --set days=3 --check
node build/src/cli.js --set sandWidth=1 --set sandLength=1.6 --set wireMargin=0.2
node build/src/cli.js --set cell=0.08 --set days=2 --csv run
--set takes any key from PARAM_SPECS in src/params.ts; --check also runs the manufactured-solution
and wire-row checks. Units are SI throughout: energies in MJ, rates per second. Digits are grouped
in threes with narrow spaces, never commas. Burned fuel is also given as liters of diesel.
--csv writes the whole run into a directory, as the page's CSV export
does.
The thermal circuit (see "The model") has a command line of its own:
node build/src/circuit-cli.js --svg circuit.svg
node build/src/circuit-cli.js --set arrayPower=9 --set innerTop=0.1 --compare
It lists the circuit's elements for the settings, what the box comes to seen from the house, and
a run; --svg draws the schematic with that run's temperatures and the heat
each part carried, --compare runs the full model beside it, and --fit changes one of its fitted factors.
The page
Every change to a setting starts a new run in the worker, which sends each simulated day as soon
as it is done. The view, the charts and the time slider grow as the days arrive, and the view
follows the newest snapshot unless you move the slider back. The sizes, quantities and costs under
"As built" and "Materials and costs", and the input data, come from the settings
directly and change at once; the prices change only the costs, so they start no run. When a run
ends, the results give the hottest point of each layer of plaster and insulation, against the
temperature it stands, and how long the layer limit stopped the heating.
The "Circuit model" tab shows the thermal circuit described under "The
model": its schematic, with sliders for each capacitance and resistance in the order of the
circuit, and for the run's weather. They start from the design in the settings, with the sand at 150
°C. Under each capacitor its temperature through the run is drawn, and by each resistor and current
source the heat it carried, all redrawn as a slider moves, since a month takes the circuit a few
milliseconds. There the values are fixed: the sand's heat capacity and the insulation's conductivity
no longer change with temperature, and with the insulation one resistor, no layer limit applies.
"Take the design from the settings" starts again from the settings.
The view has three modes. Temperature colors the slice and draws translucent isotherms ;
Mismatch colors the slice by the residual check described
below; Materials shows the box as you would see it cut open along the slice. The part on your side
of the slice is gone, and the rest is solid and lit: the sand in its sections; the walls and septa
of hollow bricks stood on end, with their cores in line from course to course (each stack of cores
is a flue, open at the top) and mortar in the joints; the bricks laid in the inlets, with every
flue's elbow mitered at 45° and its cores open through the joint, and under each septum the stacks
of bricks on edge that feed its columns; the plaster; the two layers of insulation, fiberglass drawn
as batts; and the LECA underneath. The legend lists the materials the box has. The cores are open:
you see into them, their walls lit by the light that comes in through the cut, and shadowed where
another wall is in the way. The wires are drawn as lines where they stick out of the cut toward you:
each element a serpentine in each section, its leads through the septa and out through the end walls
drawn paler. The textures are only drawn; the solver treats each material as uniform.
Drag to turn the view. Drag with the right button, with shift held, or with two fingers to move
it. The wheel or a pinch zooms toward the surface under the pointer, close enough to see grains of
sand. A double-click resets the view.
Besides the time series, a chart shows the solar array's current and power
against voltage at the moment on show: the operating point the controller chose, the load line through it and the
maximum power point, over the faint curves for noon on a clear day. Hovering over it gives the
values. "Input data" lists the material properties, the wire's resistivity, the brick and
flue assumptions, the surface coefficients and the module data, read from the same constants the
solver uses.
"Prepare the whole run as CSV" runs the simulation again and offers a zip of CSV files:
every cell's temperature at the start of every solver step and the heat put into it during the step,
with the grid, the materials, the steps, and a README that says how to read them and redo the steps.
Temperatures (to 0.1 mK) and heat input (to 0.1 mW) are written alike, a row of cells along the box
per line, as second differences along the row, so any step reads on its own and two cumulative sums
along a line give the values back. The default run comes to about 233 MB, the two big files gzipped as they are written.
The model
Grid. Cubic cells of side cell cover the sand, the brick
walls and septa, the plaster and the two layers of insulation outside them, the lid and the base.
The septa divide the sand into equal sections, as many as make each about the "septa about
every" length. The brick walls stand on the floor and the septa on their stacks of inlet
bricks, and both rise through the lid, so the flues open at the top; the base and the lid cover the
sand and the septa. The inlets are bricks laid flat, a brick's thickness high, since the miter turns
the brick's thickness into the leg's height. The outer walls' legs cross the plaster and the
insulation at the floor. Each septum's columns stand on their elbows, at the levels of the bricks on
edge that feed them, a brick's length apart; where a stack crosses a long wall, that wall's flues
start above it, at the flat brick's elbow. The plaster and the insulation keep their true
thicknesses, which need not be whole cells: each cell of the walls and lid holds the pieces of the
layers that fall in it, conducting as they would in series, k = dx/Σ(t/k), fitted to the solver's a
+ b·T + c·(T/573 K)³ within 2.6 % from −20 to 700 °C, and holding their heat added up. The page
reports the sizes as built.
Heat equation. ∂H/∂t = ∇·(k(T)∇T) + q, by finite volumes with forward Euler steps. The state is enthalpy H (J/m³), turned back into temperature
through each material's table, so the energy budget closes exactly even though quartz's heat
capacity grows by half between 25 and 450 °C and jumps at the 573 °C inversion . Faces use the harmonic mean of the two cells'
conductivities. The step is the largest the Gershgorin bound allows (times
0.9), recomputed every snapshot.
Materials (src/materials.ts). Sand: bulk density and
conductivity at 20 °C from the settings, conductivity rising
3.5·10⁻⁴ W/(m·K) per kelvin, heat capacity from the NIST Shomate fits for
quartz . Hollow brick: 700 kg/m³ gross, conductivity including radiation across the cores. Insulation,
in two layers on the sides and top: the inner one LECA, perlite (rice-husk ash is similar), Kaowool
or wood ash; the outer one fiberglass, rockwool, Kaowool, LECA, perlite or wood ash. Fiberglass's
binder stands about 230 °C and rockwool's about 250 °C, so the inner layer has to keep them cooler;
the results give the hottest point of each layer against such limits. LECA bears the sand's weight,
so it is always the fill underneath. The plaster, clay-sand or lime-sand, conducts heat about as
well as sand, 0.8 to 0.9 W/(m·K), so a few centimeters of it barely change the flows. Fiberglass
holds so little heat (16 kg/m³), and a cell that spreads a thin layer over its whole width conducts
so well for what it holds, that they would cut the solver's step from about 500 s to 15 s with the
defaults. So no layer diffuses heat faster than 5·10⁻⁷ m²/s: the light ones get the heat capacity to
stay below it, fiberglass about six times its own. That slows them: a layer L thick lags a daily
swing by about ωL²/(6α) of the swing (ω being 2π a day), a quarter through 10 cm of fiberglass at
the limit against a twenty-fifth as it is. Run side by side with the true layers at their short
step, two weeks' heat through the outside of the box came out 2 to 3 % lower, and up to a quarter
lower in some hours, the flues making up the difference; the warmest the room got moved by 0.2 K.
The page lists all the densities, conductivities and specific heats.
Heating wire (src/heater.ts). There are as many elements
as it takes for each to carry the current that heats the wire by the "wire loading" per
meter, so their number follows the array size: 8 for the default 6.3 kW. They are sized so that all
of them in parallel match the array's maximum power point when the wire is at the "sized
for" temperature, and laid out in runs along the box through each section's heated zone, evenly
spaced across it and up it at their true positions. Each element is a serpentine in each section,
joined to its serpentine in the next section by a lead through the septum, which the model leaves
cold; with septa, each element has an odd number of runs in a section, so that each serpentine ends
at the far side. The wire can be baling wire or nichrome, whose resistance changes only a few
percent between cold and 1 000 °C, where steel's grows fourfold by 500 °C. Each element is one wire,
so its current is uniform while its resistance follows the temperature of each piece. Every step the
controller takes the elements whose sand is below the limit, coolest first, and picks how many to
switch on for the most power from the array. It drops any whose wire would pass the wire limit, or
whose sand would pass the sand limit within the step. And it switches none on while any layer of
plaster or insulation, where it is hottest, is within the layer margin (30 K by default) of the most
its material stands: in a box, a thermometer at that spot. The heat already in the sand carries the
layer about 20 K further after the heating stops, so 30 K keeps fiberglass, rated for 230 °C, within
its rating. The results say how long the limit stopped the heating. The bus voltage is where the
array's I-V curve (a single-diode
model of a 450 W module, src/pv.ts) meets the elements' conductance.
The grid cannot resolve a 1.6 mm wire. Each piece of wire shares its heat among the four cells
around it, with bilinear weights,
and reads the sand temperature back from them with the same weights. The wire is hotter than that by
q'·ln(r_eq/r_w)/(2πk) across the sand, plus the rise across the gas gap where grains touch the wire.
For a wire at a cell's center r_eq is Peaceman's
0.1985·dx (e^−γ/2√2, γ being Euler's
constant ). Spreading the heat lowers the temperature read back, which moves r_eq out by a factor
e^(2πΔ), with Δ from the square lattice's Green's function : r_eq is 0.435·dx for a
wire on the face between two cells and 0.718·dx on the corner of four.
Sand limit. The controller averages the outdoor temperature over about a day,
exponentially, with a time constant of 86 400 s. Below the "full limit below" temperature,
0 °C by default, the sand limit is the full one, 450 °C; when it is milder, the limit falls in
proportion to the heat the house needs, setpoint − outdoor, down to the thermostat setting when it
is as warm outdoors as that. At 8 °C outdoors it is about 250 °C. The heat that leaks out through
the insulation is the one flow the baffle cannot stop, and this keeps it from overheating the house
in mild weather without holding back the store when it is cold. The sand chart shows the limit.
Flues (src/flue.ts). Each vertical stack of standing
brick cells, from the bottom of its flue to the top, is a bundle of cores: room air enters at the
bottom through its inlet and approaches each cell's temperature exponentially (laminar Nusselt number 5), and the flow balances the
column's buoyancy against laminar friction plus inlet, outlet and baffle losses. Each inlet adds a
mitered right-angle turn, 1.1 velocity heads at the speed up the flue, since every elbow is as wide
as its flue, and the friction of its length: out through the layers, or for a septum's column out
through the nearer long wall. A shut baffle stops the flow. The inlets conduct heat as brick does,
but the air takes no heat from them.
House. One heat capacity (the thermal mass setting) gaining the flue air, the
heat from the box's outer surface and the room heater's output, and losing UA·(T − T_outdoor). Fuel
holds it at "burn fuel below"; the fuel's heat is also given as liters of diesel at 35.8
MJ per liter (diesel's lower heating
value ), as if burned with no heat lost up a flue. The thermostat opens the baffle below the
setpoint − 0.5 K and shuts it above + 0.5 K; the baffle can also be forced open (the failed-safe
state) or shut.
Room heater. A resistance heater in the room (nichrome , so of fixed resistance, rated at the
array's maximum-power voltage) on the same bus as the elements. While the thermostat calls for heat
and the sun is up, it is switched on first and the controller chooses elements for what is left. On
the default settings it brings the fuel burned over the 14 days from 3 MJ to none.
Weather (src/weather.ts). Clear or cloudy days from a
seeded generator, optionally with a forced cloudy spell; a sinusoidal day of sun and of outdoor
temperature, around a mean that can drift steadily through the run, as from autumn into winter.
Thermal circuit (src/circuit.ts). The same box as a
circuit of five heat capacities joined by thermal resistances, for reasoning about the design and
for sweeping it, with temperature standing for voltage and heat flow for current. The capacities are
the wire zone (the sand among the wires, 36 % of it by default), the shell of sand around it, the
bricks, the plaster with the inner layer of insulation, and the house. The wire, a current source,
heats the zone; the heat goes through the shell, the bricks, the plaster and the insulation to the
house. The shell also loses heat through the lid to the house and through the base to the soil, a
source of fixed temperature. The bricks lose heat through the flues while the baffle is open (a
switch), through bridges in the insulation to the house, and through their feet to the soil. The
house loses heat through its own loss, the load, to the outdoors, a source that follows the weather.
Each element comes from the design by a formula:
the zone's mean stands 0.0351·Q/(k·h) over its edges, Q being its heat and h its height (a
uniformly heated square);
the shell conducts as its four sides, 2(c_x + c_y)/margin, plus 0.54 for each corner;
the walls, the lid and the base conduct as their layers do in one dimension, with each
material's k(T) exactly (by Kirchhoff's transformation, ∫k dT across each layer equaling the flux
times its thickness), over areas fitted to steady solutions of the full model: 0.81, 0.92 and 0.83
of the geometric areas, for the corners and edges;
the bridges (the brick tops through the lid, the legs, the septa's stacks, the plaster's top
edge) and the feet, from steady solutions too, scale with the geometry;
the open flues' 100 W/K come from draining hot sand with the baffle open;
and the share of the array's power that the switched elements take, which falls in dim light,
comes from the full model, against the irradiance times the number of elements.
Each step is backward Euler ,
one 5 × 5 linear solve, which is stable however fast the bricks settle once the flues open (about an
hour), so the step need only follow the sun and the thermostat. At the default 900 s the fuel is
within 0.1 % of what 60 s steps give, and a month takes about 5 ms, against half a minute for the
full model. Against 22 runs of the full model the circuit's fuel came within 12 %, and its hottest
point of the fiberglass 10 to 20 K high, or up to 66 K with the wire kept farther from the walls.
That point is on the lid above the wire zones, and the circuit follows it from the zone's
temperature, delayed about six hours by the sand above.
Seen from the house, the box is one conductance from the sand's mean temperature that the baffle
switches: with the defaults, about 4.4 W/K shut and 20 W/K open. The sand's own conduction, not the
flues, limits the open value. So the baffle alone can keep the house within a band only while the
sand's mean stays between two temperatures, which follow the weather; the circuit's command line
prints them, with the cap that the layers set.
The checks
Energy budget. The grid's change in enthalpy against the heat put in minus the
heat that left; it closes to about 10⁻¹⁵ of the heat that came in and went out, or 10⁻¹³ with no
panels, when much less heat moves.
Mismatch with the heat equation (src/residual.ts). At
each snapshot the stored solution is put back into the heat equation using fourth-order central
differences in space and a three-point difference in time, over every cell with two neighbors of
the same material on each side. The leftover, divided by the heat capacity, is a heating rate in
K/s. It is large next to the wires, whose line sources the grid cannot resolve, and small elsewhere:
at 3 cm cells, about 3·10⁻⁵ K/s more than two cells from any wire. At the default 5 cm grid no
checkable cell is that far from a wire.
Manufactured solution (src/verify.ts). A chosen T(x, y, z, t) in a cube of sand with the real k(T) and
heat capacity, the source that makes it exact, and the solver's error against it at 8³, 16³ and 32³
cells: 1.33, 0.47 and 0.14 K after a day, orders 1.50 and 1.76, rising toward 2
(1.87 at 48³).
Wire row. Parallel wires midway between two 0 °C planes have an exact wire
temperature. With the wire at a cell's center, on the face between two cells or two layers, or on
the corner of four cells, the sub-grid model matches it within 0.32 % at 5 or 6 cells per pitch and
within 0.12 % at 9 or 10.
The thermal circuit (test/circuit.test.ts). The heated
square's constant and the shell's shape factor against direct numerical solutions of the same
problems (which showed a textbook correlation for the shell, from a square annulus, to be 5.6 % high
here); the layers' flux by Kirchhoff's transformation against a fine one-dimensional solution with
k(T); the circuit's energy budget; its fuel and flows against the full model on short runs; and the
layer limit, in both models, on a run that would otherwise take fiberglass past its rating.
The CSV export. A test writes a short run, reads it back from the files alone,
and checks every cell at every step against the solver's rule as the export's README states it, to
within the rounding. It integrates the specific heat over each step's change in temperature: the
specific heat at the mean temperature times the change, which is quicker, is off by up to about
2·10⁻⁴ in the steps that heat the sand by the wire the most.
Carbon monoxide from charcoal in the sand
There is no charcoal in the simulated box. One design that was considered mixes charcoal into the
sand around the wires: the charcoal would take up the oxygen that reaches the steel, making a reducing atmosphere in which the baling
wire could run much hotter without oxidizing away, so that the sand could be heated further and
store more, without a costlier wire. But charcoal starved of oxygen makes carbon monoxide , which is poisonous, and
the gas in the sand's pores reaches the room by diffusion. src/charcoal.ts is
a separate model for whether that CO burns to CO2 on its way up, where it meets the oxygen coming
in. At the published reaction rate, it finds that about three quarters of the CO gets through a 0.3
m cap of sand whose bottom is at 450 °C, unless a barrier layer slows the gas.
The model is one-dimensional and steady: it covers the cap of charcoal-free sand between the
charcoal and the room. Oxygen, CO and CO2 diffuse through the pore gas (Fick's law in mole fractions , diffusivities scaled by
T^1.75 and a pore factor of 0.27). The temperature falls linearly across the cap. In the gas, CO +
½O2 → CO2 at Dryer and Glassman's (1973)
global rate for moist CO, times an adjustable factor. The charcoal takes all the oxygen that reaches
it and gives CO and CO2 in Arthur's ratio, and
can reduce CO2 to CO (the Boudouard
reaction ) at a given rate per unit CO2 concentration. The outer part of the cap can be a barrier
layer with its own, lower diffusivity (barrier in m, barrierFactor), for broken tiles or dishes. It is solved by Newton's method with a block-tridiagonal solver on a
grid packed toward the charcoal, raising the rate from zero in steps, with a time-marching
fallback.
node build/src/charcoal-cli.js --profile --tables
node build/src/charcoal-cli.js --set hot=800 --set boudouard=6e-4 --set thickness=1
node build/src/charcoal-cli.js --area 6 --ventilation 0.0208 --tables
node build/src/charcoal-cli.js --set barrier=0.05 --set barrierFactor=0.0027
The room figures assume the given cap area and ventilation (default 1 m² and 0.0208 m³/s). Rates
are per second throughout. The tests check oxygen and carbon atom balances, the exact no-reaction
flux, and convergence under grid refinement.
Translations
README.es.md, README.zh.md, README.pt.md, README.ar.md, README.hi.md and README.ru.md translate this file into
Spanish, Mandarin Chinese, Portuguese, Arabic, Hindi and Russian; the page shows them under
"Read me". Where a translation and this file differ, this file is current.
Files
src/params.ts: parameters and their defaults
src/materials.ts: material properties, enthalpy tables, steel
resistivity, air
src/model.ts: the grid, the wire layout and the sub-grid wire radius
src/heat.ts: the finite-volume solver
src/heater.ts, src/pv.ts: elements, controller and
the solar array
src/flue.ts: convection in the brick cores
src/weather.ts: synthetic weather
src/simulate.ts: the time loop, snapshots, series and the energy
budget
src/residual.ts, src/verify.ts: the checks
src/export.ts, src/zip.ts: the whole run as CSV,
and the zip it comes in
src/encoding.ts: how snapshots are packed for the page
src/format.ts: grouped digits, and fuel as diesel
src/charcoal.ts, src/charcoal-cli.ts: the CO model
and its tables
src/marching.ts: marching cubes with a generated case
table
src/circuit.ts, src/circuit-svg.ts, src/circuit-cli.ts: the thermal circuit, its schematic and its command line
src/cli.ts: the command line
src/web/: the page template, UI, charts, WebGL2 renderer, input-data
listing, the circuit's tab and worker
tools/bundle.ts, tools/markdown.ts: build the
page, with this README and its translations
README.*.md: the translations
build/ and dist/ are generated.
Sources
What each source gave this README or the model, with what was taken from it.
The background
Wikipedia, "Swanson's
law" . The law as stated in "Why store heat?": the price of solar modules
tends to fall about 20 % for every doubling of the number shipped. Also its figure for
crystalline-silicon cells in 1977, US$76.67 per watt, rounded to US$77. The article's newest price,
US$0.36 per watt in 2014, is long out of date, hence the next source.
pv magazine (2025), "China
TOPCon solar module market awaits Q4 policy signals" , 26 September 2025. A weekly
market report built on OPIS's price assessments. Used: TOPCon modules from China at US$0.088 per
watt free on board, that is, wholesale and before shipping, rounded to US$0.09. Retail prices where
the box would be built are higher; the simulator's default of US$0.28 per watt is meant as a retail
price.
BloombergNEF (2025), "Lithium-Ion
Battery Pack Prices Fall to $108 Per Kilowatt-Hour, Despite Rising Metal Prices" , 9
December 2025. BloombergNEF's yearly survey of battery prices. Used: the average price of
battery packs for stationary storage in 2025, US$70 per kilowatt-hour, which is US$19 per MJ of
capacity; over all uses the average was US$108 per kilowatt-hour. These are prices of packs alone,
without inverters, installation or replacement.
Polar Night Energy (2025), "World's
largest Sand Battery now in operation" , 11 June 2025. The company's announcement
of its storage at Pornainen, Finland. Used: 1 MW of heat, 100 MWh of storage, about 2 000 t of
crushed soapstone as the medium, and that it is ten times the size of the company's first sand
battery, at Kankaanpää in 2022. It shows sensible heat stored in a granular material working at the
scale of a town's heating network, in a cold climate.
International Energy Agency (2019), Renewables 2019 ,
"Heat" . The source of "almost half of all final energy goes to
heat": heating is the world's largest use of energy, almost half of final energy consumption.
Industry uses 53 % of that heat, and buildings 44 %, for heating rooms and water and, to a lesser
extent, cooking.
REN21 (2025), Renewables
2025 Global Status Report , "Buildings" . Used: buildings took 31 % of the
world's total final energy consumption in 2022, "about 30 %" in the text. It also says
that heating, hot water, cooking and space cooling together were 74 % of the energy buildings used
that year, and that space cooling is the fastest-growing use, up 4 % a year on average since
2000.
International Energy Agency, "Heating" (a page
in its tracking of buildings' energy). Used: almost half of the energy buildings used in 2022 went
to heating rooms and water, and fossil fuels still met over 60 % of the energy used for heating. Its
"almost half" excludes cooking and cooling, which is why it is smaller than REN21's 74 %;
the README uses it to estimate that heating buildings and their water takes roughly a seventh of the
world's final energy.
Our World in Data, "Air
conditioning causes around 3% of greenhouse gas emissions. How will this change in the
future?" Used: the International Energy Agency's estimate that space cooling,
mostly air conditioning but also fans, used about 2 100 terawatt-hours of electricity in 2022, about
7 % of the world's 29 000 terawatt-hours. The README gives it as 7.6 EJ.
World Health Organization, "Household
air pollution" (fact sheet). Used: household air pollution from cooking caused an
estimated 2.9 million deaths in 2021, including over 309 000 children under five, and about 2.1
billion people cook on open fires or stoves burning kerosene, wood, dung, crop waste or coal. The
figure is for cooking; heating with the same fuels adds to the harm but is not counted in it.
Badarch, J., Harding, J., Dickinson-Craig, E., Azen, C., Ong, H., Hunter, S., Pannaraj,
P. S., Szepesi, B., Sereenendorj, T., Davaa, S., Ochir, C., Warburton, D., and Readhead, C. (2021),
"Winter Air Pollution from Domestic Coal Fired
Heating in Ulaanbaatar, Mongolia, Is Strongly Associated with a Major Seasonal Cyclic Decrease in
Successful Fecundity" , International Journal of Environmental Research and Public
Health 18(5), 2750. Used: about 60 % of Ulaanbaatar's 1.5 million people lived in
gers; each household burned 3 to 6 tonnes of raw coal during the winter; coal burned in home stoves
is the main source of the city's winter air pollution; and PM2.5 peaks above 2 000 µg/m³ were
recorded next to the northern ger district, 80 times the 25 µg/m³ that the World Health Organization
then recommended as a daily mean. The paper's own finding, that the winter pollution goes with a
large seasonal drop in successful conception, shows how far the harm of heating with coal
reaches.
Cansino, J. M., Moreno, R., Quintana, D., and Román-Collado, R. (2019), "Health and Heating in the City of Temuco (Chile).
Monetary Savings of Replacing Biomass with PV System in the Residential Sector" ,
Sustainability 11(19), 5205. Used: 80 % of Temuco's households heat with firewood,
and the authorities have declared the city saturated with suspended particles. The paper asks a
question close to this project's. It sets the cost of replacing wood stoves with solar panels and
batteries against the money value of the deaths and illness that the smoke causes, and finds that in
all its scenarios the savings outweigh the costs. A box of sand would store the heat far more
cheaply than the batteries it assumes.
World Bank (2025), "June
2025 Update to Global Poverty Lines" , fact sheet, 5 June 2025. Used: the new
poverty lines of US$3.00 a person a day (extreme poverty), US$4.20 and US$8.30, at 2021
purchasing-power parity, and the counts for 2022: about 838 million people below US$3.00, and about
3.8 billion below US$8.30.
The Climate Watch, "Half
of Bangladesh solar homes fail, rural power risk" . A news report of a survey by
the Centre for Policy Dialogue and the daily newspaper Samakal. Used: nearly half of Bangladesh's
household solar systems have stopped working; battery failures were the most common problem, cited
by 77 % of respondents; and inverter faults, lightning, loose connections and poor components were
the other main ones. It reports a survey, not a peer-reviewed study.
Material data used in the model
NIST Chemistry WebBook, "Quartz (SiO2)",
condensed phase thermochemistry , from Chase, M. W., Jr. (1998), NIST-JANAF Thermochemical
Tables , 4th edition, Journal of Physical and Chemical Reference Data , Monograph
9. The sand's heat capacity in the model is that of quartz, from here. The page gives the
coefficients A to E of the Shomate equation for α-quartz (298 to 847 K) and β-quartz (847 to 1 996
K): the heat capacity is A + B·t + C·t² + D·t³ + E/t² J/(mol·K), with t the temperature in kelvins
divided by 1 000. src/materials.ts uses those coefficients as they are,
divides by quartz's molar mass of 0.06008 kg/mol, and multiplies by the sand's bulk density from the
settings. The fits' enthalpy constants, F and H, put the two phases' enthalpies 729 J/mol apart at
847 K. That is the heat the α-β inversion absorbs, which the model takes as 730 J/mol, 12.2 kJ/kg,
at 573 °C. Two liberties: the α fit is used below its range, down to −60 °C in the tables, though
the sand never gets that cold; and real sand is not pure quartz but holds other minerals and some
water, which a measurement of local sand would show.
Methods used in the model
Peaceman, D. W. (1978), "Interpretation
of Well-Block Pressures in Numerical Reservoir Simulation" , Society of Petroleum
Engineers Journal 18(3), 183–194. Written for oil wells, whose pressure a reservoir
model's coarse grid cannot resolve. It shows that the pressure computed for the grid block holding a
well equals the true pressure at a distance of about 0.2 times the block's width from the well. The
heat equation has the same form, so the same result gives a heating wire's temperature from its
cell's: the wire is hotter by q'·ln(r_eq/r_w)/(2πk), with r_eq the equivalent radius. For a square
grid the exact value is r_eq = e^−γ/(2√2) times the cell's width, which is 0.1985 of it. This
project extends the idea to wires lying anywhere in their cells (see "Heating wire"
above), and checks both against an exact solution.
Roache, P. J. (2002), "Code
Verification by the Method of Manufactured Solutions" , Journal of Fluids
Engineering 124(1), 4–10. The method behind the manufactured-solution check in src/verify.ts. You choose any smooth T(x, y, z, t), put it into the heat equation
with the real temperature-dependent conductivity and heat capacity to find the heat source that
makes it an exact solution, run the solver with that source, and see whether the error shrinks at
the expected rate as the cells get smaller. It tests whether the code solves its equations
correctly, not whether the equations describe the box.
The carbon monoxide model
Dryer, F. L., and Glassman, I. (1973), "High-temperature oxidation of CO and
CH4" , Symposium (International) on Combustion 14(1), 987–1003. The rate
at which carbon monoxide burns in moist gas, used in src/charcoal.ts:
−d[CO]/dt = 10^14.6·exp(−40 000 cal/mol / RT)·[CO]·[H2O]^0.5·[O2]^0.25, in moles, cubic centimeters
and seconds. With concentrations in mol/m³ instead, the factor 10^14.6 becomes 10^10.1. They
measured it in a turbulent flow reactor at 1 030 to 1 230 K, with a little water vapor, at
atmospheric pressure. The cap of sand above charcoal is at 80 to 450 °C, hundreds of kelvins colder,
so the model applies the rate far outside the range it was measured in. That is why it multiplies
the rate by an adjustable factor, and why its tables show how the CO that escapes depends on that
factor.
Arthur, J. R. (1951), "Reactions
between carbon and oxygen" , Transactions of the Faraday Society 47,
164–178. The ratio of carbon monoxide to carbon dioxide that carbon gives off as it burns,
CO/CO2 = 10^3.4·exp(−12 400 cal/mol / RT), written in src/charcoal.ts as
2 500·exp(−6 240 K/T). At 450 °C it is about 0.45: the charcoal gives off about one molecule of CO
for every two of CO2.
Further reading on the same questions
Matuska, T., and Sourek, B. (2017), "Performance Analysis of Photovoltaic Water Heating
System" , International Journal of Photoenergy 2017, 7540250. Not used in
the model, but close to its controller. The paper studies solar panels wired straight to resistive
heating elements with no converter, as this design does. It finds the best fixed load resistance for
each climate, and that tracking the panels' maximum power point instead raises the yearly yield by
20 to 35 %; the controller here tracks by switching elements in and out. It also finds that solar
thermal collectors give more than three times as much heat as panels driving resistances. Panels win
where their low price matters more than the area they cover, and where, as here, the heat must reach
450 °C, which simple flat-plate collectors cannot.
Ma, Z., Gifford, J., Wang, X., and Martinek, J. (2023), "Electric-thermal energy storage using solid
particles as storage media" , Joule 7(5), 843–848, and the National Renewable
Energy Laboratory's feature on the same work, "Solution
to Energy Storage May Be Beneath Your Feet" (2024). Not used in the model. The
laboratory's design stores electricity as heat in silica sand, α-quartz from the United States
Midwest, heated to about 1 100 °C, and turns it back into electricity. The paper's abstract gives
the sand's price as US$30–40 a tonne, about the default here (US$30). The feature says a store at
commercial scale would keep more than 95 % of its heat for at least five days, and that sand would
cost US$4 to US$10 per kilowatt-hour of storage (US$1.1 to US$2.8 per MJ), against US$150 to US$300
for lithium-ion batteries. It is the same material at a much larger scale and temperature, storing
for longer than this design needs.
Tetteh, S., Juul, G., Järvinen, M., and Santasalo-Aarnio, A. (2024), "Improved effective thermal conductivity of
sand bed in thermal energy storage systems" , Journal of Energy Storage 86,
111350. Not used in the model, but about one of its main limits. Sand conducts heat poorly,
which is why the default box is a long, thin slab and why the runs of wire must be close together.
The paper compares formulas for the effective conductivity of a bed of sand with experiments, and
tries mixing scrap metal chips into the sand: 20 % of aluminum chips by volume raised the rate of
heat transfer to 1.7 times that of pure sand. The model's sand conductivity setting is where to try
such a mixture, though its conductivity would need measuring.
Inputs without a source here
Several of the model's inputs are estimates of the kind found in engineering handbooks and
makers' data sheets, chosen for this study rather than taken from a particular source:
the wires' resistivity at each temperature, typical of low-carbon steels such as AISI 1008–1010
and of 80/20 nichrome;
the densities, heat capacities and conductivities of the hollow brick, the insulations and the
plasters, and the temperatures they stand: LECA's typical of the 4 to 10 mm grade, fiberglass's and
rockwool's of batts sold for houses, Kaowool's of a 128 kg/m³ blanket, and wood ash's a guess, about
LECA's;
the plaster mixes, 1 to 3 by volume: about 170 kg of slaked lime and 1.5 t of sand to the cubic
meter for lime-sand, and 1.9 t of clay soil and sand for clay-sand, at the price of sand;
how fast the sand's conductivity rises with temperature, 3.5·10⁻⁴ W/(m·K) per kelvin;
the flues' Nusselt number, hydraulic diameter and loss coefficients, and 1.1 velocity heads for
a mitered right-angle turn at the inlets;
the thermal circuit's factors, fitted to the full model rather than to measurements;
the grain size and emissivity in the wire's contact with the sand;
the surface coefficients to the room and to the ground;
the 450 W module's data-sheet values;
the prices, which are the project author's estimates of retail prices: LECA at about US$0.20 a
liter, perlite at US$0.40 to US$0.80, Kaowool at US$0.60, rockwool at US$0.31 and fiberglass at
US$0.026; wood ash free; slaked lime at US$0.70 a kilogram; nichrome at US$0.18 a meter, the price
of 0.1 mm wire; and the rest as under Settings.
The page lists them all under "Input data", and measuring the materials actually used
would be the first improvement to make.
sandbattery
Traducción al español del README en inglés. Donde difieran, vale el inglés. Los nombres de
los controles de la página aparecen en inglés, como en la página.
Una simulación del flujo de calor en un almacén térmico de arena calentado directamente por
paneles solares: una caja de arena de cuarzo con resistencias de alambre de enfardar de acero dulce,
paredes de ladrillos huecos puestos de pie cuyos huecos son conductos de convección natural tras una
compuerta termostática, aislamiento por fuera de los conductos, y una casa alrededor. La ecuación
del calor se resuelve en una malla regular; una página web muestra el resultado en 3-D y lo
comprueba contra la ecuación del calor.
Compilar y ejecutar
Necesita Node 22 o posterior y TypeScript (tsc), y ningún paquete de
npm.
make test # compile to build/ and run the tests (about 25 s)
make bundle # compile and write the page
make # both
make bundle escribe dist/sandbattery.html, un solo
archivo autónomo sin recursos externos; ábralo en un navegador. Tiene dos scripts, ambos legibles
con «ver código fuente»: el worker de la simulación, en un <script
type="text/js-worker"> que el navegador no ejecuta, y el script propio de la
página, que lee el texto del worker y lo arranca. Cada script contiene solo los módulos que su
código necesita. Este README y sus traducciones también están en la página, bajo "Read
me".
La simulación también funciona sin la página:
node build/src/cli.js --days-table
node build/src/cli.js --set cell=0.03 --set days=3 --check
node build/src/cli.js --set sandWidth=1 --set sandLength=1.6 --set wireMargin=0.2
node build/src/cli.js --set cell=0.08 --set days=2 --csv run
--set acepta cualquier clave de PARAM_SPECS en
src/params.ts; --check ejecuta además las
comprobaciones de la solución manufacturada y de la fila de alambres. Las unidades son SI en todo:
energías en MJ, tasas por segundo. Las cifras se agrupan de tres en tres con espacios finos, nunca
con comas. El combustible quemado se da también en litros de diésel.
--csv escribe la simulación entera en un directorio, como la exportación
CSV de la página.
La página
Cada cambio de un ajuste lanza una nueva simulación en el worker, que envía cada día simulado en
cuanto termina. La vista, los gráficos y el control deslizante del tiempo crecen a medida que llegan
los días, y la vista sigue a la instantánea más reciente salvo que usted mueva el control hacia
atrás. Las medidas, cantidades y costos bajo "As built" (tal como se construye) y
"Materials and costs" (materiales y costos), y los datos de entrada, salen directamente de
los ajustes y cambian al instante; los precios solo cambian los costos, así que no lanzan ninguna
simulación.
La vista tiene tres modos. Temperature colorea el corte por temperatura y dibuja isotermas
translúcidas; Mismatch colorea el corte según la comprobación del residuo descrita más abajo;
Materials muestra la caja como usted la vería abierta por el corte. La parte de su lado del corte
desaparece, y el resto queda sólido e iluminado: la arena, los ladrillos huecos puestos de pie con
sus huecos alineados de hilada en hilada (cada columna de huecos es un conducto, abierto en el suelo
y arriba), las juntas de mortero, la perlita por fuera y la arcilla expandida debajo. Los huecos
están abiertos: se ve su interior, con las paredes iluminadas por la luz que entra por el corte y en
sombra donde otra pared se interpone. Los alambres se dibujan como líneas donde salen del corte
hacia usted. Las texturas solo se dibujan; el cálculo trata cada material como uniforme.
Arrastre para girar la vista. Arrastre con el botón derecho, con mayúsculas pulsadas o con dos
dedos para desplazarla. La rueda o el pellizco acercan hacia la superficie bajo el puntero, tanto
como para ver los granos de arena. Un doble clic restablece la vista.
Además de las series temporales, un gráfico muestra la corriente y la potencia del campo solar
frente a la tensión en el momento mostrado: el punto de operación que eligió el controlador, la
recta de carga que pasa por él y el punto de máxima potencia, sobre las curvas tenues del mediodía
de un día despejado. Al pasar el puntero por encima se ven los valores. "Input data"
(datos de entrada) lista las propiedades de los materiales, la resistividad del acero, las hipótesis
sobre ladrillos y conductos, los coeficientes de superficie y los datos del módulo, leídos de las
mismas constantes que usa el cálculo.
"Prepare the whole run as CSV" (preparar la simulación entera como CSV) repite la
simulación y ofrece un zip de archivos CSV: la temperatura de cada celda al comienzo de cada paso
del cálculo y el calor que recibe durante el paso, con la malla, los materiales, los pasos y un
README que explica cómo leerlos y rehacer los pasos. Las temperaturas (a 0.1 mK) y el calor aportado
(a 0.1 mW) se escriben igual: una fila de celdas a lo largo de la caja por línea, como segundas
diferencias a lo largo de la fila, de modo que cada paso se lee por sí solo y dos sumas acumuladas a
lo largo de una línea devuelven los valores. La simulación por defecto ocupa unos 83 MB, con los dos
archivos grandes comprimidos con gzip a medida que se escriben.
El modelo
Malla. Celdas cúbicas de lado cell cubren la arena, las
paredes de ladrillo, el aislamiento por fuera de ellas, y el aislamiento encima y debajo. Las
paredes de ladrillo se apoyan en el suelo y atraviesan la tapa, de modo que los conductos están
abiertos por ambos extremos; el aislamiento de la base y la tapa cubren solo la arena. Los espesores
de las capas se redondean a celdas enteras; la página informa las medidas redondeadas.
Ecuación del calor. ∂H/∂t = ∇·(k(T)∇T) + q, por volúmenes finitos con pasos de
Euler explícito. El estado es la entalpía H (J/m³), que se convierte en temperatura mediante la
tabla de cada material, así que el balance de energía cierra exactamente aunque la capacidad
calorífica del cuarzo aumenta un 50 % entre 25 y 450 °C y salta en la inversión de 573 °C. Las caras
usan la media armónica de las conductividades de las dos celdas. El paso es el mayor que permite la
cota de Gershgorin (por 0.9), recalculado en cada instantánea.
Materiales (src/materials.ts). Arena: densidad aparente y
conductividad a 20 °C según los ajustes, conductividad que sube 3.5·10⁻⁴ W/(m·K) por kelvin,
capacidad calorífica según los ajustes de Shomate del NIST para el cuarzo. Ladrillo hueco: 700 kg/m³
en bruto, con una conductividad que incluye la radiación a través de los huecos. Aislamiento suelto
(perlita, ceniza de cascarilla de arroz) y un relleno portante para la base. La página lista sus
densidades, conductividades y calores específicos.
Alambre calefactor (src/heater.ts). Las resistencias se
dimensionan para que todas juntas en paralelo coincidan con el punto de máxima potencia del campo
solar cuando el alambre está a la temperatura de "sized for" (dimensionado para), y se
tienden en tramos a lo largo de la caja por la zona calentada, igualmente espaciados a lo ancho y a
lo alto, en sus posiciones reales. Cada resistencia es un solo alambre, así que su corriente es
uniforme mientras su resistencia sigue la temperatura de cada trozo. En cada paso el controlador
toma las resistencias cuya arena está por debajo del límite, de la más fría a la más caliente, y
elige cuántas encender para sacar la mayor potencia del campo solar. Descarta las que harían pasar
al alambre de su límite, o a la arena del suyo, dentro del paso. La tensión del bus es donde la
curva I-V del campo (un modelo de un diodo de un módulo de 450 W, src/pv.ts)
corta la conductancia de las resistencias.
La malla no puede resolver un alambre de 1.6 mm. Cada trozo de alambre reparte su calor entre las
cuatro celdas que lo rodean, con pesos bilineales, y lee de vuelta la temperatura de la arena con
los mismos pesos. El alambre está más caliente que eso en q'·ln(r_eq/r_w)/(2πk) a través de la
arena, más el salto a través del hueco de gas donde los granos tocan el alambre. Para un alambre en
el centro de una celda, r_eq es el 0.1985·dx de Peaceman (e^−γ/2√2). Repartir el calor baja la
temperatura que se lee de vuelta, lo que aleja r_eq en un factor e^(2πΔ), con Δ obtenido de la
función de Green de la red cuadrada: r_eq es 0.435·dx para un alambre sobre la cara entre dos celdas
y 0.718·dx sobre la esquina de cuatro.
Conductos (src/flue.ts). Cada columna vertical de celdas
de ladrillo, del suelo hasta arriba, es un haz de huecos: el aire de la habitación entra por abajo y
se acerca exponencialmente a la temperatura de cada celda (número de Nusselt laminar 5), y el caudal
equilibra el empuje de la columna contra la fricción laminar más las pérdidas de entrada, salida y
compuerta. Una compuerta cerrada detiene el flujo.
Casa. Una capacidad calorífica (el ajuste de masa térmica) que gana el aire de
los conductos, el calor de la superficie exterior de la caja y lo que da el calefactor de ambiente,
y pierde UA·(T − T_exterior). El combustible la mantiene en "burn fuel below" (quemar
combustible por debajo de); el calor del combustible se da también en litros de diésel a 35.8 MJ por
litro (el poder calorífico inferior del diésel), como si se quemara sin perder calor por una
chimenea. El termostato abre la compuerta por debajo de la consigna − 0.5 K y la cierra por encima
de + 0.5 K; la compuerta también puede forzarse abierta (el estado seguro ante fallas) o
cerrada.
Calefactor de ambiente. Una resistencia en la habitación (de nicromo, así que de
resistencia fija, calculada para la tensión de máxima potencia del campo) en el mismo bus que las
resistencias. Mientras el termostato pide calor y hay sol, se enciende primero y el controlador
elige resistencias para lo que queda. Con los ajustes por defecto, lleva el combustible quemado en
los 14 días de 29 MJ (0.8 litros de diésel) a nada.
Clima (src/weather.ts). Días despejados o nublados de un
generador con semilla, opcionalmente con una racha forzada de días nublados; un día sinusoidal de
sol y de temperatura exterior.
Las comprobaciones
Balance de energía. El cambio de entalpía de la malla frente al calor aportado
menos el calor que salió; cierra a unos 10⁻¹⁵ del aporte.
Discrepancia con la ecuación del calor (src/residual.ts). En cada instantánea, la solución guardada se vuelve a introducir
en la ecuación del calor usando diferencias centradas de cuarto orden en el espacio y una diferencia
de tres puntos en el tiempo, en cada celda con dos vecinas del mismo material a cada lado. Lo que
sobra, dividido por la capacidad calorífica, es una tasa de calentamiento en K/s. Es grande junto a
los alambres, cuyas fuentes lineales la malla no puede resolver, y pequeña en el resto: con celdas
de 3 cm, unos 2·10⁻⁵ K/s a más de dos celdas de cualquier alambre. Con la malla de 5 cm por defecto,
ninguna celda comprobable está tan lejos de un alambre.
Solución manufacturada (src/verify.ts). Una T(x, y, z,
t) elegida en un cubo de arena con la k(T) y la capacidad calorífica reales, la fuente que la hace
exacta, y el error del cálculo frente a ella con 8³, 16³ y 32³ celdas: 1.33, 0.47 y 0.14 K tras un
día, órdenes 1.50 y 1.76, que suben hacia 2 (1.87 con 48³).
Fila de alambres. Alambres paralelos a medio camino entre dos planos a 0 °C
tienen una temperatura exacta. Con el alambre en el centro de una celda, sobre la cara entre dos
celdas o dos capas, o sobre la esquina de cuatro celdas, el modelo de subcelda coincide con ella
dentro del 0.32 % con 5 o 6 celdas por paso de alambre y dentro del 0.12 % con 9 o 10.
La exportación CSV. Una prueba escribe una simulación corta, la vuelve a leer
solo desde los archivos y comprueba cada celda en cada paso contra la regla del cálculo tal como la
enuncia el README de la exportación, dentro del redondeo.
Monóxido de carbono del carbón vegetal en la arena
src/charcoal.ts es un modelo aparte, estacionario y unidimensional, de la
capa de arena sin carbón entre carbón vegetal enterrado en la arena caliente y la habitación, para
la pregunta de si el CO que produce el carbón se quema a CO2 donde se encuentra con el oxígeno que
entra. El oxígeno, el CO y el CO2 se difunden por el gas de los poros (ley de Fick en fracciones
molares, difusividades escaladas con T^1.75 y un factor de poro de 0.27). La temperatura cae
linealmente a través de la capa. En el gas, CO + ½O2 → CO2 a la tasa global de Dryer y Glassman
(1973) para CO húmedo, por un factor ajustable. El carbón toma todo el oxígeno que le llega y da CO
y CO2 en la proporción de Arthur, y puede reducir CO2 a CO (la reacción de Boudouard) a una tasa
dada por unidad de concentración de CO2. La parte exterior de la capa puede ser una capa de barrera
con su propia difusividad, más baja (barrier en m, barrierFactor), para tejas o platos rotos. Se resuelve por el método de Newton con
un solucionador tridiagonal por bloques sobre una malla concentrada hacia el carbón, subiendo la
tasa desde cero por etapas, con una alternativa de avance en el tiempo.
node build/src/charcoal-cli.js --profile --tables
node build/src/charcoal-cli.js --set hot=800 --set boudouard=6e-4 --set thickness=1
node build/src/charcoal-cli.js --area 6 --ventilation 0.0208 --tables
node build/src/charcoal-cli.js --set barrier=0.05 --set barrierFactor=0.0027
Las cifras para la habitación suponen el área de capa y la ventilación dadas (por defecto 1 m² y
0.0208 m³/s). Las tasas son por segundo en todo. Las pruebas comprueban los balances de átomos de
oxígeno y de carbono, el flujo exacto sin reacción y la convergencia al refinar la malla.
Traducciones
README.es.md, README.zh.md, README.pt.md, README.ar.md, README.hi.md y README.ru.md traducen el README en inglés al
español, al chino mandarín, al portugués, al árabe, al hindi y al ruso; la página las muestra bajo
"Read me". Donde una traducción y el original difieran, vale el original.
Archivos
src/params.ts: los parámetros y sus valores por defecto
src/materials.ts: propiedades de los materiales, tablas de entalpía,
resistividad del acero, aire
src/model.ts: la malla, la disposición del alambre y el radio de subcelda
del alambre
src/heat.ts: el solucionador de volúmenes finitos
src/heater.ts, src/pv.ts: las resistencias, el
controlador y el campo solar
src/flue.ts: la convección en los huecos de los ladrillos
src/weather.ts: clima sintético
src/simulate.ts: el bucle temporal, las instantáneas, las series y el
balance de energía
src/residual.ts, src/verify.ts: las
comprobaciones
src/export.ts, src/zip.ts: la simulación entera
como CSV, y el zip que la contiene
src/encoding.ts: cómo se empaquetan las instantáneas para la página
src/format.ts: cifras agrupadas, y el combustible como diésel
src/charcoal.ts, src/charcoal-cli.ts: el modelo de
CO y sus tablas
src/marching.ts: marching cubes con una tabla de casos generada
src/cli.ts: la línea de órdenes
src/web/: la plantilla de la página, la interfaz, los gráficos, el
renderizador WebGL2, la lista de datos de entrada y el worker
tools/bundle.ts, tools/markdown.ts: construyen la
página, con este README y sus traducciones
README.*.md: las traducciones
build/ y dist/ se generan.
sandbattery
本文是英文 README 的中文译本。两者不一致时,以英文为准。页面上的控件名称照页面保留英文。
这是一个沙子储热装置的传热模拟。装置由太阳能板直接加热:一箱石英砂,里面埋着低碳钢打包铁丝做的加热元件;四壁是竖立的空心砖,砖孔作为自然对流风道,风道口有温控风门;风道外面是保温层;四周是一栋房子。热传导方程在规则网格上求解;一个网页用三维显示结果,并用热传导方程对结果进行检验。
构建与运行
需要 Node 22 或更新版本和 TypeScript(tsc),不需要任何 npm 包。
make test # compile to build/ and run the tests (about 25 s)
make bundle # compile and write the page
make # both
make bundle 生成 dist/sandbattery.html,这是一个不依赖任何外部资源的独立文件,用浏览器打开即可。它包含两段脚本,都能在“查看源代码”中直接阅读:一段是模拟用的
worker,放在浏览器不会执行的 <script type="text/js-worker">
里;另一段是页面自己的脚本,它读取 worker 的文本并启动它。每段脚本只包含其代码实际需要的模块。本 README 及其各语言译本也包含在页面中,点“Read me”即可阅读。
模拟也可以脱离页面运行:
node build/src/cli.js --days-table
node build/src/cli.js --set cell=0.03 --set days=3 --check
node build/src/cli.js --set sandWidth=1 --set sandLength=1.6 --set wireMargin=0.2
node build/src/cli.js --set cell=0.08 --set days=2 --csv run
--set 接受 src/params.ts 中 PARAM_SPECS 的任何键;--check 另外运行构造解检验和导线排检验。单位一律采用国际单位制:能量用
MJ,速率按每秒计。数字每三位用窄空格分组,从不用逗号。燃料消耗还会折算成柴油的升数。
--csv 把整次模拟写入一个目录,与页面上的 CSV 导出相同。
页面
每改一项设置,worker 就开始一次新的模拟,每模拟完一天就立即发送这一天的结果。三维视图、图表和时间滑块随着结果的到来而增长;除非你把滑块往回拖,视图会一直跟着最新的快照。“As
built”(建成尺寸)和“Materials and
costs”(材料与费用)中的尺寸、用量和费用,以及输入数据,都直接由设置算出,改设置后立即更新;价格只影响费用,所以改价格不会重新模拟。
视图有三种模式。Temperature 按温度给剖切面着色,并画出半透明的等温面;Mismatch 按下文所述的残差检验给剖切面着色;Materials
显示箱子沿剖切面剖开后人眼看到的样子。剖切面靠你这一侧的部分被去掉,其余部分是实心的、有光照的:沙子;竖立的空心砖,砖孔逐层对齐(每一列砖孔就是一条风道,在地面和顶部都是开口的);灰缝;外面的珍珠岩和底下的陶粒。砖孔是空的:你能看进孔里,孔壁被从剖切面照进来的光照亮,被别的孔壁挡住的地方则处在阴影中。导线画成线条,只画从剖切面伸出来、朝向你的部分。这些纹理只是画出来的;计算中把每种材料当作均匀的。
拖动可以旋转视图。用右键拖动、按住 shift 拖动或用两根手指拖动,可以平移视图。滚轮或双指缩放会朝指针下方的表面放大,可以近到看清沙粒。双击恢复初始视图。
除了时间序列图,还有一张图显示所示时刻太阳能阵列的电流和功率随电压的变化:控制器选择的工作点、经过该点的负载线和最大功率点,背景中淡淡的曲线是晴天正午的情形。指针悬停在图上可以看到数值。“Input
data”(输入数据)列出材料性质、钢的电阻率、关于砖和风道的假设、表面换热系数和光伏组件数据,这些数据取自计算所用的同一组常数。
“Prepare the whole run as CSV”(把整次模拟准备成 CSV)会重新运行模拟,并提供一个由 CSV 文件组成的
zip:每个单元格在每个计算步开始时的温度和这一步中输入它的热量,附带网格、材料、各计算步,以及一份说明如何读取这些文件并重算各步的 README。温度(精确到 0.1 mK)和输入热量(精确到
0.1 mW)用同一种方式写出:每行是沿箱子长度方向的一排单元格,写成沿这一排的二阶差分,因此每一步都可以单独读取,沿一行做两次累加就能还原数值。默认的模拟约为 83 MB,两个大文件在写出时就用
gzip 压缩。
模型
网格。 边长为 cell
的立方体单元覆盖沙子、砖墙、砖墙外的保温层,以及顶部和底部的保温层。砖墙立在地面上,一直穿过顶盖,所以风道两端都是开口的;底部保温层和顶盖只覆盖沙子。各层厚度取整为整数个单元;页面上报告的是取整后的尺寸。
热传导方程。 ∂H/∂t = ∇·(k(T)∇T) + q,用有限体积法和显式欧拉时间步求解。状态量是焓
H(J/m³),通过每种材料的表换算回温度,所以即使石英的热容在 25 到 450 °C 之间增大一半、并在 573 °C
的晶型转变处跳变,能量收支仍然精确闭合。单元界面上的导热系数取两侧单元的调和平均。时间步取 Gershgorin 界所允许的最大值(乘以 0.9),每个快照重新计算一次。
材料 (src/materials.ts)。沙子:堆积密度和 20 °C
时的导热系数由设置给出,导热系数每升高一开尔文增加 3.5·10⁻⁴ W/(m·K),热容采用 NIST 对石英的 Shomate 拟合式。空心砖:毛体积密度 700
kg/m³,导热系数包含穿过砖孔的辐射。松散保温材料(珍珠岩、稻壳灰)和承重的底部填料。页面列出了它们的密度、导热系数和比热容。
加热导线 (src/heater.ts)。加热元件的尺寸这样确定:导线处于“sized
for”(设计温度)时,全部元件并联正好与阵列的最大功率点匹配。导线沿箱子长度方向分段穿过加热区,在宽度和高度方向上等间距排列,位置按实际位置计算。每个元件是一根导线,所以其中电流处处相同,而电阻随每一小段的温度变化。每一步,控制器从沙温低于上限的元件中按从冷到热的顺序挑选,决定开启几个,使阵列输出的功率最大。如果在这一步内某个元件的导线会超过导线温度上限,或者它周围的沙子会超过沙温上限,就把它去掉。母线电压由阵列的
I-V 曲线(450 W 组件的单二极管模型,src/pv.ts)与元件电导的交点决定。
网格分辨不出直径 1.6 mm 的导线。每一小段导线把它的热量按双线性权重分给周围四个单元,并用同样的权重读回沙子的温度。导线比这个温度高出穿过沙子的
q'·ln(r_eq/r_w)/(2πk),再加上沙粒与导线接触处气隙上的温升。导线位于单元中心时, r_eq 就是 Peaceman 的
0.1985·dx(e^−γ/2√2)。把热量分散开会降低读回的温度,相当于把 r_eq 向外推了 e^(2πΔ) 倍,其中 Δ 由正方形点阵的格林函数得出:导线位于两个单元之间的界面上时 r_eq
为 0.435·dx,位于四个单元的公共角上时为 0.718·dx。
风道 (src/flue.ts)。从地面到顶部的每一竖列砖单元都是一束砖孔:室内空气从底部进入,以指数方式趋近每个单元的温度(层流努塞尔数取
5),流量由气柱的浮升力与层流摩擦以及进口、出口和风门的局部损失相平衡来决定。风门关闭时气流停止。
房屋。 用一个热容(热质量设置)表示,它得到风道送出的热空气、箱子外表面散出的热和室内电暖器的输出,并损失 UA·(T −
T_室外)。燃料把室温保持在“burn fuel below”(低于此温度烧燃料);燃料提供的热量还会按每升 35.8
MJ(柴油的低位热值)折算成柴油的升数,即假定燃烧时没有热量从烟囱散失。恒温器在低于设定温度 0.5 K 时打开风门,高于设定温度 0.5 K
时关闭;风门也可以强制常开(故障时的安全状态)或常闭。
室内电暖器。
房间里的一个电阻加热器(镍铬合金,所以电阻固定,按阵列最大功率点电压设计),与加热元件接在同一条母线上。当恒温器要求供热而又有阳光时,先开启它,控制器再用剩余的功率选择加热元件。在默认设置下,它使
14 天内烧掉的燃料从 29 MJ (0.8 升柴油)降为零。
天气 (src/weather.ts)。晴天或阴天由带种子的随机数发生器决定,可以选择加入一段连续阴天;日照和室外温度按正弦规律逐日变化。
检验
能量收支。 把网格焓的变化与输入热量减去散失热量相比较;误差约为输入量的 10⁻¹⁵。
与热传导方程的偏差 (src/residual.ts)。在每个快照上,把保存下来的解代回热传导方程,空间上用四阶中心差分,时间上用三点差分,检验所有每侧都有两个同材料邻居的单元。剩余项除以热容就是以
K/s 计的加热速率。它在导线附近很大,因为网格分辨不出导线的线热源;在其他地方很小:单元为 3 cm 时,距任何导线两个单元以外约为 2·10⁻⁵ K/s。在默认的 5 cm
网格上,没有可检验的单元离导线那么远。
构造解 (src/verify.ts)。在一立方体沙子中选定 T(x, y, z, t),使用真实的 k(T)
和热容,加上使之成为精确解的热源,再看计算在 8³、16³ 和 32³ 个单元上的误差:一天后分别为 1.33、0.47 和 0.14 K,收敛阶为 1.50 和 1.76,并趋向 2(48³ 时为
1.87)。
导线排。 位于两块 0 °C
平板正中的一排平行导线有精确的导线温度。无论导线位于单元中心、两个单元或两层之间的界面上,还是四个单元的公共角上,子网格模型与精确解的偏差在每个间距 5 或 6 个单元时都在 0.32 % 以内,9
或 10 个单元时在 0.12 % 以内。
CSV 导出。 有一项测试写出一次短模拟,只凭这些文件把它读回来,并按导出的 README
所述的计算规则检查每个计算步的每个单元格,误差在舍入范围之内。
沙中木炭产生的一氧化碳
src/charcoal.ts 是一个独立的一维稳态模型,描述埋在热沙中的木炭与房间之间那层不含木炭的沙子,用来回答这样一个问题:木炭产生的 CO
在与渗入的氧气相遇的地方会不会燃烧成 CO2。氧气、CO 和 CO2 在孔隙气体中扩散(以摩尔分数表示的菲克定律,扩散系数按 T^1.75 换算,孔隙系数取
0.27)。温度在这层沙子中线性下降。气相中 CO + ½O2 → CO2 的速率取 Dryer 和 Glassman(1973)对潮湿 CO
的总包速率,再乘以一个可调系数。木炭吸收到达它的全部氧气,按 Arthur 比例生成 CO 和 CO2,还可以按给定的单位 CO2 浓度速率把 CO2 还原成
CO(布杜阿尔反应)。这层沙子的外侧部分可以设为扩散系数较低的阻挡层(barrier 以 m 计,barrierFactor),用来代表碎瓦片或碎碗碟。求解用牛顿法和块三对角求解器,网格向木炭一侧加密,反应速率从零开始分步增大,并以时间推进法作为后备。
node build/src/charcoal-cli.js --profile --tables
node build/src/charcoal-cli.js --set hot=800 --set boudouard=6e-4 --set thickness=1
node build/src/charcoal-cli.js --area 6 --ventilation 0.0208 --tables
node build/src/charcoal-cli.js --set barrier=0.05 --set barrierFactor=0.0027
房间内的数字假定给定的沙层面积和通风量(默认为 1 m² 和 0.0208 m³/s)。速率一律按每秒计。测试检查氧原子和碳原子的守恒、无反应时的精确通量,以及网格加密时的收敛性。
译本
README.es.md、README.zh.md、README.pt.md、README.ar.md、README.hi.md 和 README.ru.md 分别是英文 README
的西班牙语、中文(普通话)、葡萄牙语、阿拉伯语、印地语和俄语译本;页面上点“Read me”可以阅读。译本与原文不一致时,以原文为准。
文件
src/params.ts:参数及其默认值
src/materials.ts:材料性质、焓表、钢的电阻率、空气
src/model.ts:网格、导线布置和导线的子网格半径
src/heat.ts:有限体积求解器
src/heater.ts、src/pv.ts:加热元件、控制器和太阳能阵列
src/flue.ts:砖孔中的对流
src/weather.ts:合成天气
src/simulate.ts:时间循环、快照、时间序列和能量收支
src/residual.ts、src/verify.ts:各项检验
src/export.ts、src/zip.ts:把整次模拟写成 CSV,以及装它的
zip
src/encoding.ts:快照如何打包传给页面
src/format.ts:数字分组,以及燃料的柴油折算
src/charcoal.ts、src/charcoal-cli.ts:一氧化碳模型及其表格
src/marching.ts:带自动生成情形表的 marching cubes 算法
src/cli.ts:命令行
src/web/:页面模板、界面、图表、WebGL2 渲染器、输入数据列表和 worker
tools/bundle.ts、tools/markdown.ts:构建页面,并附上本 README
及其译本
README.*.md:各语言译本
build/ 和 dist/ 是生成的目录。
sandbattery
Tradução para o português do README em inglês. Onde diferirem, vale o inglês. Os nomes dos
controles da página aparecem em inglês, como na página.
Uma simulação do fluxo de calor num armazenamento térmico de areia aquecido diretamente por
painéis solares: uma caixa de areia de quartzo com resistências de arame de enfardar de aço doce,
paredes de tijolos furados postos em pé cujos furos são dutos de convecção natural atrás de uma
comporta termostática, isolamento por fora dos dutos, e uma casa em volta. A equação do calor é
resolvida numa malha regular; uma página web mostra o resultado em 3-D e o confere com a equação do
calor.
Compilar e executar
Precisa do Node 22 ou mais recente e do TypeScript (tsc), e de nenhum
pacote do npm.
make test # compile to build/ and run the tests (about 25 s)
make bundle # compile and write the page
make # both
make bundle grava dist/sandbattery.html, um único
arquivo autossuficiente sem recursos externos; abra-o num navegador. Ele tem dois scripts, ambos
legíveis com «exibir código-fonte»: o worker da simulação, num <script
type="text/js-worker"> que o navegador não executa, e o script da própria
página, que lê o texto do worker e o inicia. Cada script contém só os módulos de que seu código
precisa. Este README e suas traduções também estão na página, em "Read me".
A simulação também roda sem a página:
node build/src/cli.js --days-table
node build/src/cli.js --set cell=0.03 --set days=3 --check
node build/src/cli.js --set sandWidth=1 --set sandLength=1.6 --set wireMargin=0.2
node build/src/cli.js --set cell=0.08 --set days=2 --csv run
--set aceita qualquer chave de PARAM_SPECS em src/params.ts; --check também executa as verificações da
solução manufaturada e da fileira de arames. As unidades são SI em tudo: energias em MJ, taxas por
segundo. Os algarismos são agrupados de três em três com espaços finos, nunca com vírgulas. O
combustível queimado também é dado em litros de diesel.
--csv grava a simulação inteira num diretório, como a exportação CSV da
página.
A página
Cada mudança de um ajuste inicia uma nova simulação no worker, que envia cada dia simulado assim
que termina. A vista, os gráficos e o controle deslizante do tempo crescem à medida que os dias
chegam, e a vista acompanha o instantâneo mais recente, a menos que você mova o controle para trás.
As medidas, quantidades e custos em "As built" (como construído) e "Materials and
costs" (materiais e custos), e os dados de entrada, saem diretamente dos ajustes e mudam na
hora; os preços só mudam os custos, então não iniciam simulação nenhuma.
A vista tem três modos. Temperature colore o corte pela temperatura e desenha isotermas
translúcidas; Mismatch colore o corte pela verificação do resíduo descrita abaixo; Materials mostra
a caixa como você a veria aberta pelo corte. A parte do seu lado do corte some, e o resto fica
sólido e iluminado: a areia, os tijolos furados postos em pé com os furos alinhados de fiada em
fiada (cada coluna de furos é um duto, aberto no chão e em cima), as juntas de argamassa, a perlita
por fora e a argila expandida embaixo. Os furos são abertos: dá para ver dentro deles, com as
paredes iluminadas pela luz que entra pelo corte e na sombra onde outra parede está no caminho. Os
arames são desenhados como linhas onde saem do corte na sua direção. As texturas são só desenho; o
cálculo trata cada material como uniforme.
Arraste para girar a vista. Arraste com o botão direito, com a tecla shift apertada ou com dois
dedos para deslocá-la. A roda do mouse ou o gesto de pinça aproximam em direção à superfície sob o
ponteiro, o bastante para ver os grãos de areia. Um clique duplo restaura a vista.
Além das séries temporais, um gráfico mostra a corrente e a potência do arranjo solar em função
da tensão no momento mostrado: o ponto de operação escolhido pelo controlador, a reta de carga que
passa por ele e o ponto de máxima potência, sobre as curvas apagadas do meio-dia de um dia de céu
limpo. Passar o ponteiro por cima mostra os valores. "Input data" (dados de entrada) lista
as propriedades dos materiais, a resistividade do aço, as hipóteses sobre tijolos e dutos, os
coeficientes de superfície e os dados do módulo, lidos das mesmas constantes que o cálculo usa.
"Prepare the whole run as CSV" (preparar a simulação inteira como CSV) refaz a
simulação e oferece um zip de arquivos CSV: a temperatura de cada célula no início de cada passo do
cálculo e o calor que ela recebe durante o passo, com a malha, os materiais, os passos e um README
que explica como lê-los e refazer os passos. As temperaturas (a 0.1 mK) e o calor fornecido (a 0.1
mW) são escritos do mesmo jeito: uma fileira de células ao longo da caixa por linha, como segundas
diferenças ao longo da fileira, de modo que cada passo se lê sozinho e duas somas acumuladas ao
longo de uma linha devolvem os valores. A simulação padrão dá cerca de 83 MB, com os dois arquivos
grandes comprimidos com gzip à medida que são gravados.
O modelo
Malha. Células cúbicas de lado cell cobrem a areia, as
paredes de tijolo, o isolamento por fora delas, e o isolamento em cima e embaixo. As paredes de
tijolo se apoiam no chão e atravessam a tampa, de modo que os dutos ficam abertos nas duas pontas; o
isolamento da base e a tampa cobrem só a areia. As espessuras das camadas são arredondadas para
células inteiras; a página informa as medidas arredondadas.
Equação do calor. ∂H/∂t = ∇·(k(T)∇T) + q, por volumes finitos com passos de
Euler explícito. O estado é a entalpia H (J/m³), convertida em temperatura pela tabela de cada
material, de modo que o balanço de energia fecha exatamente, embora a capacidade térmica do quartzo
aumente 50 % entre 25 e 450 °C e salte na inversão de 573 °C. As faces usam a média harmônica das
condutividades das duas células. O passo é o maior que o limite de Gershgorin permite (vezes 0.9),
recalculado a cada instantâneo.
Materiais (src/materials.ts). Areia: densidade aparente e
condutividade a 20 °C pelos ajustes, condutividade que sobe 3.5·10⁻⁴ W/(m·K) por kelvin, capacidade
térmica pelos ajustes de Shomate do NIST para o quartzo. Tijolo furado: 700 kg/m³ em bruto, com uma
condutividade que inclui a radiação através dos furos. Isolamento solto (perlita, cinza de casca de
arroz) e um enchimento portante para a base. A página lista suas densidades, condutividades e
calores específicos.
Arame de aquecimento (src/heater.ts). As resistências são
dimensionadas para que todas juntas em paralelo casem com o ponto de máxima potência do arranjo
quando o arame está na temperatura de "sized for" (dimensionado para), e são estendidas em
trechos ao longo da caixa pela zona aquecida, igualmente espaçados na largura e na altura, nas suas
posições reais. Cada resistência é um só arame, então sua corrente é uniforme, enquanto sua
resistência acompanha a temperatura de cada pedaço. A cada passo o controlador pega as resistências
cuja areia está abaixo do limite, da mais fria para a mais quente, e escolhe quantas ligar para
tirar a maior potência do arranjo. Descarta as que levariam o arame além do seu limite, ou a areia
além do dela, dentro do passo. A tensão do barramento é onde a curva I-V do arranjo (um modelo de um
diodo de um módulo de 450 W, src/pv.ts) cruza a condutância das
resistências.
A malha não consegue resolver um arame de 1.6 mm. Cada pedaço de arame reparte seu calor entre as
quatro células em volta dele, com pesos bilineares, e lê de volta a temperatura da areia com os
mesmos pesos. O arame está mais quente que isso por q'·ln(r_eq/r_w)/(2πk) através da areia, mais o
salto através da camada de gás onde os grãos tocam o arame. Para um arame no centro de uma célula,
r_eq é o 0.1985·dx de Peaceman (e^−γ/2√2). Repartir o calor abaixa a temperatura lida de volta, o
que afasta r_eq por um fator e^(2πΔ), com Δ tirado da função de Green da rede quadrada: r_eq é
0.435·dx para um arame na face entre duas células e 0.718·dx no canto de quatro.
Dutos (src/flue.ts). Cada coluna vertical de células de
tijolo, do chão até em cima, é um feixe de furos: o ar do cômodo entra por baixo e se aproxima
exponencialmente da temperatura de cada célula (número de Nusselt laminar 5), e a vazão equilibra o
empuxo da coluna contra o atrito laminar mais as perdas de entrada, de saída e da comporta. Uma
comporta fechada para o fluxo.
Casa. Uma capacidade térmica (o ajuste de massa térmica) que ganha o ar dos
dutos, o calor da superfície externa da caixa e o que o aquecedor do cômodo fornece, e perde UA·(T −
T_externa). O combustível a mantém em "burn fuel below" (queimar combustível abaixo de); o
calor do combustível também é dado em litros de diesel a 35.8 MJ por litro (o poder calorífico
inferior do diesel), como se queimado sem perder calor por uma chaminé. O termostato abre a comporta
abaixo do ponto de ajuste − 0.5 K e a fecha acima de + 0.5 K; a comporta também pode ser forçada
aberta (o estado seguro em caso de falha) ou fechada.
Aquecedor do cômodo. Uma resistência no cômodo (de níquel-cromo, portanto de
resistência fixa, calculada para a tensão de máxima potência do arranjo) no mesmo barramento que as
resistências. Enquanto o termostato pede calor e há sol, ele é ligado primeiro e o controlador
escolhe resistências para o que sobra. Com os ajustes padrão, ele leva o combustível queimado nos 14
dias de 29 MJ (0.8 litro de diesel) a zero.
Clima (src/weather.ts). Dias de céu limpo ou nublados de
um gerador com semente, opcionalmente com uma sequência forçada de dias nublados; um dia senoidal de
sol e de temperatura externa.
As verificações
Balanço de energia. A variação de entalpia da malha contra o calor fornecido
menos o calor que saiu; fecha em cerca de 10⁻¹⁵ do fornecido.
Discrepância com a equação do calor (src/residual.ts). A
cada instantâneo, a solução guardada é posta de volta na equação do calor com diferenças centradas
de quarta ordem no espaço e uma diferença de três pontos no tempo, em toda célula com duas vizinhas
do mesmo material de cada lado. O que sobra, dividido pela capacidade térmica, é uma taxa de
aquecimento em K/s. Ela é grande junto aos arames, cujas fontes lineares a malha não consegue
resolver, e pequena no resto: com células de 3 cm, cerca de 2·10⁻⁵ K/s a mais de duas células de
qualquer arame. Com a malha padrão de 5 cm, nenhuma célula verificável fica tão longe de um
arame.
Solução manufaturada (src/verify.ts). Uma T(x, y, z, t)
escolhida num cubo de areia com a k(T) e a capacidade térmica reais, a fonte que a torna exata, e o
erro do cálculo contra ela com 8³, 16³ e 32³ células: 1.33, 0.47 e 0.14 K depois de um dia, ordens
1.50 e 1.76, subindo para 2 (1.87 com 48³).
Fileira de arames. Arames paralelos a meio caminho entre dois planos a 0 °C têm
uma temperatura exata. Com o arame no centro de uma célula, na face entre duas células ou duas
camadas, ou no canto de quatro células, o modelo de subcélula bate com ela dentro de 0.32 % com 5 ou
6 células por espaçamento e dentro de 0.12 % com 9 ou 10.
A exportação CSV. Um teste grava uma simulação curta, lê-a de volta só a partir
dos arquivos e confere cada célula em cada passo com a regra do cálculo como o README da exportação
a enuncia, dentro do arredondamento.
Monóxido de carbono do carvão vegetal na areia
src/charcoal.ts é um modelo à parte, estacionário e unidimensional, da
camada de areia sem carvão entre o carvão vegetal enterrado na areia quente e o cômodo, para a
pergunta de se o CO que o carvão produz queima a CO2 onde encontra o oxigênio que entra. O oxigênio,
o CO e o CO2 se difundem pelo gás dos poros (lei de Fick em frações molares, difusividades escaladas
por T^1.75 e um fator de poro de 0.27). A temperatura cai linearmente através da camada. No gás, CO
+ ½O2 → CO2 à taxa global de Dryer e Glassman (1973) para CO úmido, vezes um fator ajustável. O
carvão toma todo o oxigênio que chega até ele e dá CO e CO2 na proporção de Arthur, e pode reduzir
CO2 a CO (a reação de Boudouard) a uma taxa dada por unidade de concentração de CO2. A parte externa
da camada pode ser uma camada de barreira com difusividade própria, mais baixa (barrier em m, barrierFactor), para telhas ou pratos
quebrados. Resolve-se pelo método de Newton com um solucionador tridiagonal por blocos numa malha
concentrada perto do carvão, subindo a taxa a partir de zero em etapas, com uma alternativa de
avanço no tempo.
node build/src/charcoal-cli.js --profile --tables
node build/src/charcoal-cli.js --set hot=800 --set boudouard=6e-4 --set thickness=1
node build/src/charcoal-cli.js --area 6 --ventilation 0.0208 --tables
node build/src/charcoal-cli.js --set barrier=0.05 --set barrierFactor=0.0027
Os números para o cômodo supõem a área de camada e a ventilação dadas (padrão 1 m² e 0.0208
m³/s). As taxas são por segundo em tudo. Os testes conferem os balanços de átomos de oxigênio e de
carbono, o fluxo exato sem reação e a convergência ao refinar a malha.
Traduções
README.es.md, README.zh.md, README.pt.md, README.ar.md, README.hi.md e README.ru.md traduzem o README em inglês para
o espanhol, o chinês mandarim, o português, o árabe, o híndi e o russo; a página as mostra em
"Read me". Onde uma tradução e o original diferirem, vale o original.
Arquivos
src/params.ts: os parâmetros e seus valores padrão
src/materials.ts: propriedades dos materiais, tabelas de entalpia,
resistividade do aço, ar
src/model.ts: a malha, o arranjo do arame e o raio de subcélula do
arame
src/heat.ts: o solucionador de volumes finitos
src/heater.ts, src/pv.ts: as resistências, o
controlador e o arranjo solar
src/flue.ts: a convecção nos furos dos tijolos
src/weather.ts: clima sintético
src/simulate.ts: o laço no tempo, os instantâneos, as séries e o balanço
de energia
src/residual.ts, src/verify.ts: as
verificações
src/export.ts, src/zip.ts: a simulação inteira
como CSV, e o zip que a contém
src/encoding.ts: como os instantâneos são empacotados para a página
src/format.ts: algarismos agrupados, e o combustível como diesel
src/charcoal.ts, src/charcoal-cli.ts: o modelo de
CO e suas tabelas
src/marching.ts: marching cubes com uma tabela de casos gerada
src/cli.ts: a linha de comando
src/web/: o modelo da página, a interface, os gráficos, o renderizador
WebGL2, a lista de dados de entrada e o worker
tools/bundle.ts, tools/markdown.ts: montam a
página, com este README e suas traduções
README.*.md: as traduções
build/ e dist/ são gerados.
sandbattery
هذه ترجمة عربية لملف README الإنجليزي. حيثما اختلفا فالنص الإنجليزي هو المعتمد. تبقى أسماء
عناصر التحكم في الصفحة بالإنجليزية كما تظهر فيها.
محاكاة لانتقال الحرارة في مخزن حراري رملي يُسخَّن مباشرةً بالألواح الشمسية: صندوق من رمل الكوارتز
فيه عناصر تسخين من سلك الربط المصنوع من الفولاذ الطري، وجدرانه من طوب مفرَّغ موضوع قائمًا تعمل
تجاويفه مجاريَ للحمل الحراري الطبيعي خلف حاجز هوائي يتحكم فيه منظم الحرارة، وعزل حراري خارج المجاري،
ومنزل حول ذلك كله. تُحَل معادلة الحرارة على شبكة منتظمة، وتعرض صفحة ويب النتيجة بثلاثة أبعاد وتتحقق
منها بمعادلة الحرارة.
البناء والتشغيل
يحتاج إلى Node 22 أو أحدث وإلى TypeScript (tsc)، ولا يحتاج إلى أي حزمة من
npm.
make test # compile to build/ and run the tests (about 25 s)
make bundle # compile and write the page
make # both
ينشئ make bundle الملف dist/sandbattery.html، وهو
ملف واحد مكتفٍ بذاته لا يعتمد على أي موارد خارجية؛ افتحه في متصفح. فيه نصّان برمجيان، كلاهما مقروء
في «عرض المصدر»: الـ worker الخاص بالمحاكاة، داخل <script
type="text/js-worker"> الذي لا ينفذه المتصفح، والنص البرمجي الخاص بالصفحة، الذي
يقرأ نص الـ worker ويشغّله. ولا يحوي كل نص برمجي إلا الوحدات التي تحتاجها شيفرته. هذا الملف وترجماته
موجودة في الصفحة أيضًا، تحت "Read me".
تعمل المحاكاة أيضًا من دون الصفحة:
node build/src/cli.js --days-table
node build/src/cli.js --set cell=0.03 --set days=3 --check
node build/src/cli.js --set sandWidth=1 --set sandLength=1.6 --set wireMargin=0.2
node build/src/cli.js --set cell=0.08 --set days=2 --csv run
يقبل --set أي مفتاح من PARAM_SPECS في src/params.ts، ويشغّل --check أيضًا اختبارَي الحل المصنَّع
وصف الأسلاك. الوحدات كلها من النظام الدولي: الطاقة بالميغاجول (MJ)، والمعدلات لكل ثانية. تُجمَّع
الأرقام ثلاثةً ثلاثةً بمسافات ضيقة، ولا تُستعمل الفاصلة لذلك أبدًا. ويُعطى الوقود المحروق أيضًا
باللترات من الديزل.
ويكتب --csv المحاكاة كاملة في مجلد، كما يفعل تصدير CSV في الصفحة.
الصفحة
كل تغيير في أحد الإعدادات يبدأ محاكاة جديدة في الـ worker، الذي يرسل كل يوم محاكى بمجرد انتهائه.
يكبر العرض والرسوم البيانية ومنزلق الزمن مع وصول الأيام، ويتبع العرض أحدث لقطة ما لم تُرجع المنزلق
إلى الوراء. أما الأبعاد والكميات والتكاليف تحت "As built" (كما يُبنى) و"Materials and
costs" (المواد والتكاليف)، وكذلك البيانات المدخلة، فتُحسب من الإعدادات مباشرة وتتغير فورًا؛
والأسعار لا تغيّر إلا التكاليف، فلا تبدأ أي محاكاة.
للعرض ثلاثة أوضاع. يلوّن Temperature المقطع بحسب درجة الحرارة ويرسم أسطحًا شفافة متساوية الحرارة؛
ويلوّن Mismatch المقطع بحسب اختبار البواقي الموصوف أدناه؛ ويعرض Materials الصندوق كما تراه لو قُطع
مفتوحًا على امتداد المقطع. الجزء الذي في جهتك من المقطع مُزال، والباقي صلب ومضاء: الرمل، والطوب
المفرَّغ القائم وتجاويفه متطابقة من مدماك إلى مدماك (كل عمود من التجاويف مجرى مفتوح عند الأرض وفي
الأعلى)، وفواصل المونة، والبيرلايت من الخارج والطين الممدد من الأسفل. التجاويف مفتوحة: ترى داخلها،
وجدرانها مضاءة بالضوء الداخل من المقطع، ومظللة حيث يعترضه جدار آخر. تُرسم الأسلاك خطوطًا حيث تبرز من
المقطع نحوك. النقوش مرسومة فقط؛ أما الحساب فيعامل كل مادة على أنها متجانسة.
اسحب لتدوير العرض. اسحب بالزر الأيمن، أو مع الضغط على shift، أو بإصبعين لتحريكه. عجلة الفأرة أو
القرص بإصبعين يقرّبان نحو السطح الذي تحت المؤشر، إلى حد رؤية حبات الرمل. النقر المزدوج يعيد العرض
إلى وضعه الأول.
إلى جانب السلاسل الزمنية، يعرض رسم بياني تيار المصفوفة الشمسية وقدرتها مقابل الجهد في اللحظة
المعروضة: نقطة التشغيل التي اختارها المتحكم، وخط الحمل المار بها، ونقطة القدرة القصوى، فوق المنحنيات
الباهتة لظهيرة يوم صافٍ. والتمرير بالمؤشر فوقه يُظهر القيم. وتسرد "Input data" (البيانات
المدخلة) خواص المواد، والمقاومة النوعية للفولاذ، وافتراضات الطوب والمجاري، ومعاملات انتقال الحرارة
عند الأسطح، وبيانات الوحدة الشمسية، مقروءة من الثوابت نفسها التي يستعملها الحساب.
يعيد "Prepare the whole run as CSV" (تحضير المحاكاة كاملة بصيغة CSV) تشغيل المحاكاة
ويقدّم ملف zip من ملفات CSV: درجة حرارة كل خلية في بداية كل خطوة حسابية والحرارة الداخلة إليها خلال
الخطوة، ومعها الشبكة والمواد والخطوات وملف README يشرح كيف تُقرأ وكيف تُعاد الخطوات. تُكتب درجات
الحرارة (بدقة 0.1 mK) والحرارة الداخلة (بدقة 0.1 mW) بالطريقة نفسها: صف من الخلايا على طول الصندوق
في كل سطر، على هيئة فروق ثانية على امتداد الصف، فتُقرأ كل خطوة وحدها، ويعيد جمعان تراكميان على
امتداد السطر القيمَ. تبلغ المحاكاة الافتراضية نحو 83 MB، ويُضغط الملفان الكبيران بـ gzip أثناء
كتابتهما.
النموذج
الشبكة. خلايا مكعبة طول ضلعها cell تغطي الرمل، وجدران
الطوب، والعزل خارجها، والعزل من الأعلى والأسفل. تقوم جدران الطوب على الأرض وتخترق الغطاء، فتكون
المجاري مفتوحة من طرفيها؛ ولا يغطي عزلُ القاعدة والغطاءُ إلا الرمل. تُقرَّب سماكات الطبقات إلى عدد
صحيح من الخلايا، وتعرض الصفحة الأبعاد بعد التقريب.
معادلة الحرارة. ∂H/∂t = ∇·(k(T)∇T) + q، بطريقة الحجوم
المحدودة مع خطوات أويلر الصريحة. متغير الحالة هو المحتوى الحراري H (J/m³)،
ويُحوَّل إلى درجة حرارة عبر جدول كل مادة، فيُغلق ميزان الطاقة بدقة مع أن السعة الحرارية للكوارتز
تزيد بمقدار النصف بين 25 و450 °C وتقفز عند تحول ألفا–بيتا في 573 °C. تُستعمل على الأوجه المتوسطُ
التوافقي لموصليتي الخليتين. والخطوة هي أكبر خطوة يسمح بها حد غيرشغورين (مضروبةً في 0.9)، ويُعاد
حسابها عند كل لقطة.
المواد (src/materials.ts). الرمل: الكثافة الظاهرية
والموصلية عند 20 °C من الإعدادات، وتزيد الموصلية 3.5·10⁻⁴ W/(m·K) لكل كلفن،
والسعة الحرارية من معادلات شوميت التي نشرها NIST للكوارتز. الطوب المفرَّغ: 700 kg/m³ إجمالًا،
بموصلية تشمل الإشعاع عبر التجاويف. عزل سائب (بيرلايت، رماد قشر الأرز) وحشوة حاملة للقاعدة. وتسرد
الصفحة كثافاتها وموصلياتها وحرارتها النوعية.
سلك التسخين (src/heater.ts). تُحدَّد مقاسات العناصر بحيث
تطابق كلُّها معًا على التوازي نقطةَ القدرة القصوى للمصفوفة حين يكون السلك عند درجة حرارة "sized
for" (المصمَّم لها)، وتُمَد مقاطعَ على طول الصندوق عبر المنطقة المسخَّنة، متساويةَ التباعد
عرضًا وارتفاعًا، في مواضعها الحقيقية. كل عنصر سلك واحد، فتياره واحد على طوله، بينما تتبع مقاومته
درجة حرارة كل قطعة منه. في كل خطوة يأخذ المتحكم العناصر التي رملها دون الحد، من الأبرد إلى الأسخن،
ويختار كم منها يشغّل ليحصل على أكبر قدرة من المصفوفة. ويُسقط أي عنصر قد يتجاوز سلكه حدَّه، أو رمله
حدَّه، خلال الخطوة. وجهد الناقل هو النقطة التي يتقاطع فيها منحنى التيار والجهد للمصفوفة (نموذج
الصمام الثنائي الواحد لوحدة قدرتها 450 W، src/pv.ts) مع موصلية العناصر.
لا تستطيع الشبكة أن تُظهر سلكًا قطره 1.6 mm. كل قطعة من السلك توزع حرارتها على الخلايا الأربع
المحيطة بها بأوزان ثنائية الخطية، وتقرأ درجة حرارة الرمل منها بالأوزان نفسها. والسلك أسخن من ذلك
بمقدار q'·ln(r_eq/r_w)/(2πk) عبر الرمل، يضاف إليه الفرق عبر الفجوة الغازية
حيث تلامس حبات الرمل السلك. للسلك الواقع في مركز خلية، r_eq هو 0.1985·dx لبيسمان (e^−γ/2√2). وتوزيع الحرارة يخفض درجة
الحرارة المقروءة، وهذا يُبعد r_eq بعامل e^(2πΔ)، حيث
تُستخرج Δ من دالة غرين للشبكة المربعة: r_eq يساوي
0.435·dx لسلك على الوجه بين خليتين، و0.718·dx على
الركن المشترك بين أربع.
المجاري (src/flue.ts). كل عمود رأسي من خلايا الطوب، من
الأرض إلى الأعلى، حزمة من التجاويف: يدخل هواء الغرفة من الأسفل ويقترب أُسّيًا من درجة حرارة كل خلية
(عدد نسلت للجريان الصفائحي 5)، ويوازن التدفق بين قوة طفو العمود والاحتكاك الصفائحي مع فواقد المدخل
والمخرج والحاجز. الحاجز المغلق يوقف التدفق.
المنزل. سعة حرارية واحدة (إعداد الكتلة الحرارية) تكسب هواء المجاري، والحرارة من
السطح الخارجي للصندوق، وما تعطيه مدفأة الغرفة، وتفقد UA·(T − T_outdoor).
يُبقي الوقودُ درجةَ حرارة المنزل عند "burn fuel below" (احرق الوقود دون هذه الدرجة)؛
وتُعطى حرارة الوقود أيضًا باللترات من الديزل بمعدل 35.8 MJ لكل لتر (القيمة الحرارية الدنيا للديزل)،
كأنه يحترق دون أن تضيع حرارة عبر مدخنة. يفتح منظم الحرارة الحاجز تحت نقطة الضبط بمقدار 0.5 K ويغلقه
فوقها بمقدار 0.5 K، ويمكن أيضًا فرض فتح الحاجز (الحالة الآمنة عند العطل) أو إغلاقه.
مدفأة الغرفة. مدفأة كهربائية بالمقاومة داخل الغرفة (من النيكروم، فمقاومتها
ثابتة، ومصممة لجهد القدرة القصوى للمصفوفة) على الناقل نفسه الذي عليه العناصر. ما دام منظم الحرارة
يطلب حرارة والشمس ساطعة، تُشغَّل أولًا ثم يختار المتحكم العناصر لما يتبقى. وبالإعدادات الافتراضية
تخفض الوقود المحروق خلال الأيام الأربعة عشر من 29 MJ (0.8 لتر من الديزل) إلى لا شيء.
الطقس (src/weather.ts). أيام صافية أو غائمة من مولّد
أرقام عشوائية ذي بذرة، مع فترة غائمة متصلة مفروضة إن أُريد؛ ويوم جيبي الشكل للشمس ولدرجة الحرارة
الخارجية.
الاختبارات
ميزان الطاقة. يُقارَن تغير المحتوى الحراري للشبكة بالحرارة الداخلة ناقص الحرارة
الخارجة؛ ويُغلق في حدود نحو 10⁻¹⁵ من الداخل.
عدم المطابقة مع معادلة الحرارة (src/residual.ts). عند كل
لقطة يُعاد الحل المحفوظ إلى معادلة الحرارة باستعمال فروق مركزية من الرتبة الرابعة في المكان وفرق
ثلاثي النقاط في الزمن، في كل خلية لها جاران من المادة نفسها على كل جانب. وما يتبقى، مقسومًا على
السعة الحرارية، معدلُ تسخين بوحدة K/s. وهو كبير قرب الأسلاك، التي لا تستطيع الشبكة إظهار مصادرها
الخطية، وصغير في غيرها: عند خلايا من 3 cm، نحو 2·10⁻⁵ K/s على بعد أكثر من
خليتين من أي سلك. وعلى الشبكة الافتراضية ذات 5 cm لا توجد خلية قابلة للاختبار بهذا البعد عن
سلك.
الحل المصنَّع (src/verify.ts). دالة T(x,
y, z, t) مختارة في مكعب من الرمل بموصلية k(T) وسعة حرارية حقيقيتين،
والمصدر الذي يجعلها حلًا دقيقًا، وخطأ الحساب مقارنةً بها عند 8³ و16³ و32³ خلية: 1.33 و0.47 و0.14 K بعد يوم، برتب 1.50 و1.76
تقترب من 2 (1.87 عند 48³).
صف الأسلاك. للأسلاك المتوازية الواقعة في منتصف المسافة بين مستويين عند 0 °C
درجةُ حرارة دقيقة. سواء كان السلك في مركز خلية، أو على الوجه بين خليتين أو طبقتين، أو على الركن
المشترك بين أربع خلايا، يطابقها النموذج دون الشبكي في حدود 0.32 % عند 5 أو 6 خلايا لكل تباعد، وفي
حدود 0.12 % عند 9 أو 10.
تصدير CSV. يكتب أحد الاختبارات محاكاة قصيرة، ثم يقرؤها من الملفات وحدها، ويتحقق
من كل خلية في كل خطوة وفق قاعدة الحساب كما يذكرها ملف README في التصدير، في حدود التقريب.
أول أكسيد الكربون من الفحم النباتي في الرمل
src/charcoal.ts نموذج مستقل، أحادي البعد ومستقر، لطبقة الرمل الخالية من
الفحم بين فحم نباتي مدفون في الرمل الساخن وبين الغرفة، للإجابة عن سؤال: هل يحترق أول أكسيد الكربون
الذي ينتجه الفحم إلى ثاني أكسيد الكربون حيث يلتقي الأكسجين الداخل؟ ينتشر الأكسجين وCO وCO2 في غاز المسام (قانون فيك بالكسور المولية، مع معاملات
انتشار متدرجة وفق T^1.75 ومعامل مسامية 0.27). وتنخفض درجة الحرارة خطيًا عبر
الطبقة. وفي الغاز يجري CO + ½O2 → CO2 بالمعدل الكلي لدراير وغلاسمان (1973)
لأول أكسيد الكربون الرطب، مضروبًا في معامل قابل للضبط. يأخذ الفحم كل الأكسجين الذي يصل إليه ويعطي
CO وCO2 بنسبة آرثر، ويمكنه اختزال CO2 إلى CO (تفاعل بودوار) بمعدل معطى لكل وحدة من تركيز CO2. ويمكن أن يكون الجزء الخارجي من الطبقة طبقةً عازلة بانتشار خاص أقل (barrier بالمتر، وbarrierFactor)، لتمثيل قطع البلاط أو
الأطباق المكسورة. وتُحَل بطريقة نيوتن مع حلّال ثلاثي الأقطار كتلي على شبكة مكثفة نحو الفحم، مع رفع
المعدل من الصفر على مراحل، وبديل يعتمد التقدم في الزمن.
node build/src/charcoal-cli.js --profile --tables
node build/src/charcoal-cli.js --set hot=800 --set boudouard=6e-4 --set thickness=1
node build/src/charcoal-cli.js --area 6 --ventilation 0.0208 --tables
node build/src/charcoal-cli.js --set barrier=0.05 --set barrierFactor=0.0027
تفترض أرقام الغرفة مساحة الطبقة والتهوية المعطاتين (الافتراضي 1 m² و 0.0208 m³/s). والمعدلات كلها
لكل ثانية. وتتحقق الاختبارات من ميزاني ذرات الأكسجين والكربون، ومن التدفق الدقيق في غياب التفاعل،
ومن التقارب عند تنعيم الشبكة.
الترجمات
README.es.md وREADME.zh.md وREADME.pt.md وREADME.ar.md وREADME.hi.md وREADME.ru.md ترجمات لملف README الإنجليزي إلى
الإسبانية والصينية (الماندرين) والبرتغالية والعربية والهندية والروسية، وتعرضها الصفحة تحت "Read
me". وحيثما اختلفت ترجمة عن الأصل فالأصل هو المعتمد.
الملفات
src/params.ts: المعاملات وقيمها الافتراضية
src/materials.ts: خواص المواد، وجداول المحتوى الحراري، والمقاومة النوعية
للفولاذ، والهواء
src/model.ts: الشبكة، وتوزيع السلك، ونصف القطر دون الشبكي للسلك
src/heat.ts: حلّال الحجوم المحدودة
src/heater.ts، src/pv.ts: العناصر، والمتحكم،
والمصفوفة الشمسية
src/flue.ts: الحمل الحراري في تجاويف الطوب
src/weather.ts: طقس مصطنع
src/simulate.ts: الحلقة الزمنية، واللقطات، والسلاسل، وميزان الطاقة
src/residual.ts، src/verify.ts: الاختبارات
src/export.ts، src/zip.ts: المحاكاة كاملة بصيغة
CSV، وملف zip الذي يحويها
src/encoding.ts: طريقة حزم اللقطات للصفحة
src/format.ts: تجميع الأرقام، والوقود مقدَّرًا بالديزل
src/charcoal.ts، src/charcoal-cli.ts: نموذج أول
أكسيد الكربون وجداوله
src/marching.ts: خوارزمية marching cubes بجدول حالات مولَّد
src/cli.ts: سطر الأوامر
src/web/: قالب الصفحة، والواجهة، والرسوم البيانية، ومُصيِّر WebGL2،
وقائمة البيانات المدخلة، والـ worker
tools/bundle.ts، tools/markdown.ts: تبني الصفحة،
ومعها هذا الملف وترجماته
README.*.md: الترجمات
يُنشأ build/ وdist/ تلقائيًا.
sandbattery
यह अंग्रेज़ी README का हिंदी अनुवाद है। जहाँ दोनों में अंतर हो, वहाँ अंग्रेज़ी पाठ मान्य है।
पेज के नियंत्रणों के नाम पेज की तरह अंग्रेज़ी में ही दिए गए हैं।
रेत के एक ऊष्मा भंडार में ऊष्मा-प्रवाह का सिमुलेशन, जिसे सीधे सौर पैनलों से गर्म किया जाता है:
क्वार्ट्ज़ रेत का एक बक्सा, जिसमें माइल्ड स्टील के बेलिंग तार (बाँधने वाले तार) के हीटिंग एलिमेंट
हैं; सिरे के बल खड़ी खोखली ईंटों की दीवारें, जिनके छेद थर्मोस्टैट से चलने वाले डैम्पर के पीछे
प्राकृतिक संवहन की नलिकाएँ हैं; नलिकाओं के बाहर ऊष्मारोधन; और चारों ओर एक घर। ऊष्मा समीकरण एक नियमित
ग्रिड पर हल किया जाता है; एक वेब पेज परिणाम को 3-D में दिखाता है और उसे ऊष्मा समीकरण से जाँचता
है।
बनाना और चलाना
इसके लिए Node 22 या नया और TypeScript (tsc) चाहिए; कोई npm पैकेज नहीं
चाहिए।
make test # compile to build/ and run the tests (about 25 s)
make bundle # compile and write the page
make # both
make bundle फ़ाइल dist/sandbattery.html लिखता है,
जो बिना किसी बाहरी संसाधन के एक स्वतंत्र फ़ाइल है; इसे ब्राउज़र में खोलें। इसमें दो स्क्रिप्ट हैं,
दोनों "सोर्स देखें" में पढ़ी जा सकती हैं: सिमुलेशन का worker, एक <script type="text/js-worker"> में, जिसे ब्राउज़र नहीं चलाता; और
पेज की अपनी स्क्रिप्ट, जो worker का पाठ पढ़कर उसे शुरू करती है। हर स्क्रिप्ट में केवल वे मॉड्यूल हैं
जिनकी उसके कोड को ज़रूरत है। यह README और इसके अनुवाद भी पेज में "Read me" के अंतर्गत
हैं।
सिमुलेशन पेज के बिना भी चलता है:
node build/src/cli.js --days-table
node build/src/cli.js --set cell=0.03 --set days=3 --check
node build/src/cli.js --set sandWidth=1 --set sandLength=1.6 --set wireMargin=0.2
node build/src/cli.js --set cell=0.08 --set days=2 --csv run
--set फ़ाइल src/params.ts में PARAM_SPECS की कोई भी कुंजी लेता है; --check निर्मित हल और
तारों की पंक्ति वाली जाँचें भी चलाता है। इकाइयाँ हर जगह SI हैं: ऊर्जा MJ में, दरें प्रति सेकंड।
अंकों को तीन-तीन के समूहों में पतली जगह से बाँटा जाता है, अल्पविराम से कभी नहीं। जलाया गया ईंधन
डीज़ल के लीटरों में भी दिया जाता है।
--csv पूरे सिमुलेशन को एक डायरेक्टरी में लिखता है, जैसे पेज का CSV
निर्यात।
पेज
किसी सेटिंग में हर बदलाव worker में एक नया सिमुलेशन शुरू करता है, जो हर सिमुलेट किया गया दिन पूरा
होते ही भेज देता है। दिन आने के साथ दृश्य, चार्ट और समय का स्लाइडर बढ़ते जाते हैं, और दृश्य सबसे नए
स्नैपशॉट के साथ चलता है, जब तक आप स्लाइडर को पीछे न ले जाएँ। "As built" (जैसा बना) और
"Materials and costs" (सामग्री और लागत) के अंतर्गत माप, मात्राएँ और लागत, और इनपुट डेटा,
सीधे सेटिंग्स से निकलते हैं और तुरंत बदलते हैं; क़ीमतें केवल लागत बदलती हैं, इसलिए उनसे कोई सिमुलेशन
शुरू नहीं होता।
दृश्य के तीन मोड हैं। Temperature काट (स्लाइस) को तापमान के अनुसार रंगता है और अर्धपारदर्शी
समतापी सतहें बनाता है; Mismatch काट को नीचे वर्णित अवशेष जाँच के अनुसार रंगता है; Materials बक्से को
वैसा दिखाता है जैसा वह काट के साथ खोलने पर आपको दिखेगा। काट के आपकी ओर वाला हिस्सा हटा दिया जाता है,
और बाकी ठोस और प्रकाशित रहता है: रेत; सिरे के बल खड़ी खोखली ईंटें, जिनके छेद एक रद्दे से दूसरे रद्दे
तक एक सीध में हैं (छेदों का हर स्तंभ एक नलिका है, जो फ़र्श पर और ऊपर खुली है); गारे के जोड़; बाहर
पर्लाइट और नीचे फैली हुई मिट्टी (एक्सपैंडेड क्ले)। छेद खुले हैं: आप उनके अंदर देख सकते हैं; उनकी
दीवारें काट से आने वाली रोशनी से प्रकाशित हैं, और जहाँ कोई दूसरी दीवार रास्ते में हो वहाँ छाया में
हैं। तार रेखाओं के रूप में वहाँ बनाए जाते हैं जहाँ वे काट से निकलकर आपकी ओर आते हैं। बनावटें केवल
चित्रित हैं; गणना हर सामग्री को एकसमान मानती है।
दृश्य घुमाने के लिए खींचें। उसे खिसकाने के लिए दाएँ बटन से, shift दबाकर, या दो उँगलियों से
खींचें। माउस का पहिया या चुटकी पॉइंटर के नीचे की सतह की ओर ज़ूम करते हैं, इतना पास कि रेत के कण
दिखने लगें। डबल-क्लिक दृश्य को पहले जैसा कर देता है।
समय-श्रृंखलाओं के अलावा, एक चार्ट दिखाए गए क्षण पर सौर ऐरे की धारा और शक्ति को वोल्टेज के सापेक्ष
दिखाता है: नियंत्रक द्वारा चुना गया संचालन बिंदु, उससे गुज़रने वाली लोड लाइन और अधिकतम शक्ति बिंदु,
साफ़ दिन की दोपहर के हल्के वक्रों के ऊपर। उस पर पॉइंटर ले जाने से मान दिखते हैं। "Input
data" (इनपुट डेटा) सामग्रियों के गुण, स्टील की प्रतिरोधकता, ईंटों और नलिकाओं से जुड़ी
मान्यताएँ, सतहों के ऊष्मा-स्थानांतरण गुणांक और मॉड्यूल का डेटा सूचीबद्ध करता है, जो उन्हीं
स्थिरांकों से पढ़े जाते हैं जिनका उपयोग गणना करती है।
"Prepare the whole run as CSV" (पूरे सिमुलेशन को CSV के रूप में तैयार करें) सिमुलेशन को
दोबारा चलाता है और CSV फ़ाइलों का एक zip देता है: हर गणना-चरण की शुरुआत में हर सेल का तापमान और उस
चरण में उसमें डाली गई ऊष्मा, साथ में ग्रिड, सामग्रियाँ, चरण, और एक README जो बताता है कि इन्हें कैसे
पढ़ें और चरणों को दोबारा कैसे करें। तापमान (0.1 mK तक) और डाली गई ऊष्मा (0.1 mW तक) एक ही तरह लिखे
जाते हैं: हर पंक्ति में बक्से की लंबाई के साथ सेलों की एक कतार, उस कतार के साथ दूसरे अंतरों के रूप
में, ताकि हर चरण अपने-आप पढ़ा जा सके और किसी पंक्ति पर दो संचयी योग मान लौटा दें। डिफ़ॉल्ट सिमुलेशन
लगभग 83 MB का होता है; दोनों बड़ी फ़ाइलें लिखते समय ही gzip से संकुचित की जाती हैं।
मॉडल
ग्रिड। cell भुजा वाले घनाकार सेल रेत, ईंटों की दीवारों,
उनके बाहर के ऊष्मारोधन, और ऊपर व नीचे के ऊष्मारोधन को ढकते हैं। ईंटों की दीवारें फ़र्श पर खड़ी हैं
और ढक्कन के पार ऊपर तक जाती हैं, इसलिए नलिकाएँ दोनों सिरों पर खुली हैं; आधार का ऊष्मारोधन और ढक्कन
केवल रेत को ढकते हैं। परतों की मोटाई पूरे सेलों तक पूर्णांकित की जाती है; पेज पूर्णांकित माप बताता
है।
ऊष्मा समीकरण। ∂H/∂t = ∇·(k(T)∇T) + q, परिमित आयतन विधि से, स्पष्ट (फ़ॉरवर्ड)
ऑयलर चरणों के साथ। अवस्था एन्थैल्पी H (J/m³) है, जिसे हर सामग्री की तालिका से वापस तापमान में बदला
जाता है, इसलिए ऊर्जा का हिसाब बिल्कुल ठीक बैठता है, भले ही क्वार्ट्ज़ की ऊष्मा धारिता 25 और 450 °C
के बीच डेढ़ गुनी हो जाती है और 573 °C के रूपांतरण पर उछलती है। फलकों पर दोनों सेलों की चालकताओं का
हरात्मक माध्य लिया जाता है। चरण वह सबसे बड़ा है जिसकी गेर्शगोरिन सीमा अनुमति देती है (0.9 से गुणा
करके), और हर स्नैपशॉट पर दोबारा गिना जाता है।
सामग्रियाँ (src/materials.ts)। रेत: थोक घनत्व और 20 °C पर
चालकता सेटिंग्स से; चालकता प्रति केल्विन 3.5·10⁻⁴ W/(m·K) बढ़ती है; ऊष्मा धारिता क्वार्ट्ज़ के लिए
NIST के शोमेट फ़िट से। खोखली ईंट: कुल 700 kg/m³, चालकता में छेदों के आर-पार विकिरण शामिल है। ढीला
भरा ऊष्मारोधन (पर्लाइट, धान की भूसी की राख) और आधार के लिए भार सहने वाला भराव। पेज इनके घनत्व,
चालकताएँ और विशिष्ट ऊष्माएँ सूचीबद्ध करता है।
हीटिंग तार (src/heater.ts)। एलिमेंटों का आकार ऐसे चुना
जाता है कि जब तार "sized for" (जिसके लिए आकार चुना गया) तापमान पर हो, तब सब एलिमेंट
समानांतर में मिलकर ऐरे के अधिकतम शक्ति बिंदु से मेल खाएँ। उन्हें बक्से की लंबाई में, गर्म किए जाने
वाले क्षेत्र से होकर, खंडों में बिछाया जाता है: चौड़ाई और ऊँचाई में बराबर दूरी पर, अपनी असली
स्थितियों पर। हर एलिमेंट एक ही तार है, इसलिए उसमें धारा हर जगह समान है, जबकि उसका प्रतिरोध हर टुकड़े
के तापमान के साथ बदलता है। हर चरण में नियंत्रक वे एलिमेंट लेता है जिनकी रेत सीमा से नीचे है, सबसे
ठंडे से शुरू करके, और चुनता है कि कितने चालू करें ताकि ऐरे से सबसे अधिक शक्ति मिले। वह ऐसे किसी भी
एलिमेंट को छोड़ देता है जिसका तार उस चरण में तार की सीमा पार कर जाए, या जिसकी रेत रेत की सीमा पार कर
जाए। बस वोल्टेज वह बिंदु है जहाँ ऐरे का I-V वक्र (450 W मॉड्यूल का एकल-डायोड मॉडल, src/pv.ts) एलिमेंटों की चालकता से मिलता है।
ग्रिड 1.6 mm के तार को अलग से नहीं दिखा सकता। तार का हर टुकड़ा अपनी ऊष्मा अपने आसपास के चार सेलों
में द्विरैखिक भारों से बाँटता है, और उन्हीं भारों से रेत का तापमान वापस पढ़ता है। तार इससे रेत के
आर-पार q'·ln(r_eq/r_w)/(2πk) अधिक गर्म है, और साथ में उस गैस-अंतराल का तापांतर भी जुड़ता है जहाँ रेत
के कण तार को छूते हैं। सेल के केंद्र में स्थित तार के लिए r_eq पीसमैन का 0.1985·dx (e^−γ/2√2) है।
ऊष्मा को बाँटने से वापस पढ़ा गया तापमान घटता है, जिससे r_eq गुणक e^(2πΔ) से बाहर खिसकता है, जहाँ Δ
वर्ग जालक के ग्रीन फलन से मिलता है: दो सेलों के बीच के फलक पर स्थित तार के लिए r_eq 0.435·dx है और
चार सेलों के साझा कोने पर 0.718·dx।
नलिकाएँ (src/flue.ts)। फ़र्श से ऊपर तक ईंट-सेलों का हर
ऊर्ध्वाधर स्तंभ छेदों का एक गुच्छा है: कमरे की हवा नीचे से घुसती है और हर सेल के तापमान की ओर
चरघातांकी रूप से बढ़ती है (लैमिनर नसेल्ट संख्या 5), और प्रवाह स्तंभ के उत्प्लावन को लैमिनर घर्षण तथा
प्रवेश, निकास और डैम्पर के नुकसानों से संतुलित करता है। बंद डैम्पर प्रवाह रोक देता है।
घर। एक ऊष्मा धारिता (ऊष्मीय द्रव्यमान की सेटिंग), जो नलिकाओं की हवा, बक्से की
बाहरी सतह की ऊष्मा और कमरे के हीटर का उत्पादन पाती है, और UA·(T − T_बाहर) खोती है। ईंधन उसे
"burn fuel below" (इससे नीचे ईंधन जलाएँ) पर बनाए रखता है; ईंधन की ऊष्मा 35.8 MJ प्रति लीटर
(डीज़ल का निम्न ऊष्मीय मान) की दर से डीज़ल के लीटरों में भी दी जाती है, मानो उसे इस तरह जलाया गया हो
कि कोई ऊष्मा चिमनी से न निकले। थर्मोस्टैट सेटपॉइंट से 0.5 K नीचे डैम्पर खोलता है और 0.5 K ऊपर बंद
करता है; डैम्पर को ज़बरन खुला (ख़राबी में सुरक्षित अवस्था) या बंद भी रखा जा सकता है।
कमरे का हीटर। कमरे में एक प्रतिरोधी हीटर (नाइक्रोम का, इसलिए स्थिर प्रतिरोध
वाला, ऐरे के अधिकतम-शक्ति वोल्टेज के लिए निर्धारित), जो एलिमेंटों वाली उसी बस पर है। जब तक
थर्मोस्टैट ऊष्मा माँगता है और धूप है, इसे पहले चालू किया जाता है और नियंत्रक बची हुई शक्ति के लिए
एलिमेंट चुनता है। डिफ़ॉल्ट सेटिंग्स पर यह 14 दिनों में जलने वाले ईंधन को 29 MJ (0.8 लीटर डीज़ल) से
शून्य कर देता है।
मौसम (src/weather.ts)। साफ़ या बादल वाले दिन एक बीज (सीड)
वाले जनरेटर से, चाहें तो लगातार बादल वाले दिनों की एक अवधि के साथ; धूप और बाहरी तापमान का ज्यावक्रीय
दैनिक क्रम।
जाँचें
ऊर्जा का हिसाब। ग्रिड की एन्थैल्पी में बदलाव की तुलना डाली गई ऊष्मा घटा बाहर गई
ऊष्मा से; यह डाली गई ऊर्जा के लगभग 10⁻¹⁵ तक मेल खाता है।
ऊष्मा समीकरण से अंतर (src/residual.ts)। हर स्नैपशॉट पर
सहेजे गए हल को वापस ऊष्मा समीकरण में रखा जाता है: स्थान में चौथे क्रम के केंद्रीय अंतर और समय में
तीन-बिंदु अंतर के साथ, हर उस सेल पर जिसके हर ओर उसी सामग्री के दो पड़ोसी हों। जो बचता है, उसे ऊष्मा
धारिता से भाग देने पर K/s में तापन दर मिलती है। यह तारों के पास बड़ी है, जिनके रेखीय स्रोत ग्रिड अलग
से नहीं दिखा सकता, और बाकी जगह छोटी: 3 cm के सेलों पर, किसी भी तार से दो सेल से अधिक दूर लगभग 2·10⁻⁵
K/s। डिफ़ॉल्ट 5 cm ग्रिड पर कोई जाँचने योग्य सेल तार से इतना दूर नहीं है।
निर्मित हल (src/verify.ts)। रेत के एक घन में चुना गया
T(x, y, z, t), असली k(T) और ऊष्मा धारिता के साथ, वह स्रोत जो इसे सटीक हल बनाता है, और 8³, 16³ तथा
32³ सेलों पर इसके सापेक्ष गणना की त्रुटि: एक दिन बाद 1.33, 0.47 और 0.14 K, कोटि 1.50 और 1.76, जो 2
की ओर बढ़ती है (48³ पर 1.87)।
तारों की पंक्ति। 0 °C पर रखे दो समतलों के ठीक बीच समानांतर तारों का एक सटीक
तापमान होता है। तार चाहे सेल के केंद्र में हो, दो सेलों या दो परतों के बीच के फलक पर हो, या चार
सेलों के साझा कोने पर, उप-ग्रिड मॉडल प्रति अंतराल 5 या 6 सेलों पर 0.32 % के भीतर और 9 या 10 सेलों पर
0.12 % के भीतर इससे मेल खाता है।
CSV निर्यात। एक परीक्षण एक छोटा सिमुलेशन लिखता है, उसे केवल फ़ाइलों से वापस
पढ़ता है, और निर्यात के README में बताए गए गणना-नियम के अनुसार हर चरण पर हर सेल की जाँच करता है,
पूर्णांकन की सीमा के भीतर।
रेत में लकड़ी के कोयले से कार्बन मोनोऑक्साइड
src/charcoal.ts एक अलग, एक-आयामी स्थिर मॉडल है: गर्म रेत में दबे लकड़ी के
कोयले और कमरे के बीच रेत की उस परत का, जिसमें कोयला नहीं है। यह इस प्रश्न के लिए है कि क्या कोयले से
बनने वाली CO वहाँ जलकर CO2 बन जाती है जहाँ वह भीतर आती ऑक्सीजन से मिलती है। ऑक्सीजन, CO और CO2
छिद्रों की गैस में विसरित होती हैं (मोल-अंशों में फ़िक का नियम, विसरण गुणांक T^1.75 के अनुसार मापे
गए और छिद्र गुणक 0.27)। परत के आर-पार तापमान रैखिक रूप से गिरता है। गैस में CO + ½O2 → CO2 नम CO के
लिए ड्रायर और ग्लासमैन (1973) की समग्र दर से होती है, एक समायोज्य गुणक से गुणा करके। कोयला उस तक
पहुँचने वाली सारी ऑक्सीजन ले लेता है और आर्थर के अनुपात में CO और CO2 देता है, और CO2 को CO में
अपचयित भी कर सकता है (बुडुआर अभिक्रिया), CO2 की प्रति इकाई सांद्रता पर दी गई दर से। परत का बाहरी भाग
अपनी, कम विसरणशीलता वाली अवरोधक परत हो सकता है (barrier मीटर में, barrierFactor), टूटी टाइलों या बर्तनों के लिए। इसे न्यूटन विधि से हल किया जाता है,
कोयले की ओर सघन ग्रिड पर ब्लॉक-त्रिविकर्णी सॉल्वर के साथ; अभिक्रिया दर को शून्य से चरणों में बढ़ाया
जाता है, और समय में आगे बढ़ने वाली विधि विकल्प के रूप में रहती है।
node build/src/charcoal-cli.js --profile --tables
node build/src/charcoal-cli.js --set hot=800 --set boudouard=6e-4 --set thickness=1
node build/src/charcoal-cli.js --area 6 --ventilation 0.0208 --tables
node build/src/charcoal-cli.js --set barrier=0.05 --set barrierFactor=0.0027
कमरे के आँकड़े दी गई परत-क्षेत्रफल और वेंटिलेशन मानते हैं (डिफ़ॉल्ट 1 m² और 0.0208 m³/s)। दरें हर
जगह प्रति सेकंड हैं। परीक्षण ऑक्सीजन और कार्बन परमाणुओं के संतुलन, बिना अभिक्रिया के सटीक प्रवाह, और
ग्रिड को महीन करने पर अभिसरण की जाँच करते हैं।
अनुवाद
README.es.md, README.zh.md, README.pt.md, README.ar.md, README.hi.md और README.ru.md अंग्रेज़ी README के स्पेनिश,
चीनी (मंदारिन), पुर्तगाली, अरबी, हिंदी और रूसी अनुवाद हैं; पेज इन्हें "Read me" के अंतर्गत
दिखाता है। जहाँ किसी अनुवाद और मूल में अंतर हो, वहाँ मूल मान्य है।
फ़ाइलें
src/params.ts: पैरामीटर और उनके डिफ़ॉल्ट मान
src/materials.ts: सामग्रियों के गुण, एन्थैल्पी तालिकाएँ, स्टील की
प्रतिरोधकता, हवा
src/model.ts: ग्रिड, तार का विन्यास और तार की उप-ग्रिड त्रिज्या
src/heat.ts: परिमित आयतन सॉल्वर
src/heater.ts, src/pv.ts: एलिमेंट, नियंत्रक और सौर
ऐरे
src/flue.ts: ईंटों के छेदों में संवहन
src/weather.ts: कृत्रिम मौसम
src/simulate.ts: समय का लूप, स्नैपशॉट, श्रृंखलाएँ और ऊर्जा का हिसाब
src/residual.ts, src/verify.ts: जाँचें
src/export.ts, src/zip.ts: पूरा सिमुलेशन CSV के
रूप में, और उसे रखने वाला zip
src/encoding.ts: पेज के लिए स्नैपशॉट कैसे पैक किए जाते हैं
src/format.ts: अंकों का समूहन, और ईंधन डीज़ल के रूप में
src/charcoal.ts, src/charcoal-cli.ts: CO मॉडल और
उसकी तालिकाएँ
src/marching.ts: उत्पन्न केस-तालिका के साथ marching cubes
src/cli.ts: कमांड लाइन
src/web/: पेज का साँचा, इंटरफ़ेस, चार्ट, WebGL2 रेंडरर, इनपुट डेटा की
सूची और worker
tools/bundle.ts, tools/markdown.ts: पेज बनाते हैं,
इस README और इसके अनुवादों के साथ
README.*.md: अनुवाद
build/ और dist/ अपने-आप बनते हैं।
sandbattery
Перевод английского README на русский язык. Где они расходятся, верен английский текст.
Названия элементов управления страницы даны по-английски, как на самой странице.
Моделирование теплопереноса в песчаном тепловом аккумуляторе, который нагревается напрямую от
солнечных панелей: ящик кварцевого песка с нагревательными элементами из вязальной проволоки из
низкоуглеродистой стали, стены из пустотелых кирпичей, поставленных на торец, пустоты которых служат
каналами естественной конвекции за термостатической заслонкой, теплоизоляция снаружи каналов и дом
вокруг. Уравнение теплопроводности решается на регулярной сетке; веб-страница показывает результат в
3-D и проверяет его по уравнению теплопроводности.
Сборка и запуск
Нужны Node 22 или новее и TypeScript (tsc); пакеты npm не нужны.
make test # compile to build/ and run the tests (about 25 s)
make bundle # compile and write the page
make # both
make bundle записывает dist/sandbattery.html — один
самодостаточный файл без внешних ресурсов; откройте его в браузере. В нём два скрипта, оба читаемые
через «просмотр исходного кода»: worker моделирования в <script
type="text/js-worker">, который браузер не исполняет, и собственный скрипт
страницы, который читает текст worker'а и запускает его. Каждый скрипт содержит только те модули,
которые нужны его коду. Этот README и его переводы тоже есть на странице, в разделе "Read
me".
Моделирование работает и без страницы:
node build/src/cli.js --days-table
node build/src/cli.js --set cell=0.03 --set days=3 --check
node build/src/cli.js --set sandWidth=1 --set sandLength=1.6 --set wireMargin=0.2
node build/src/cli.js --set cell=0.08 --set days=2 --csv run
--set принимает любой ключ из PARAM_SPECS в src/params.ts; --check вдобавок выполняет проверки по
искусственному решению и по ряду проволок. Единицы везде СИ: энергия в МДж, скорости в расчёте на
секунду. Разряды цифр разделяются узкими пробелами по три, никогда запятыми. Сожжённое топливо
указывается также в литрах дизельного топлива.
--csv записывает весь расчёт в каталог, как экспорт CSV на странице.
Страница
Каждое изменение настройки запускает новый расчёт в worker'е, который отправляет каждый
смоделированный день, как только тот готов. Вид, графики и ползунок времени растут по мере
поступления дней, и вид следует за самым свежим снимком, если только вы не сдвинете ползунок назад.
Размеры, количества и стоимость в разделах "As built" (как построено) и "Materials
and costs" (материалы и стоимость), а также входные данные берутся прямо из настроек и меняются
сразу; цены меняют только стоимость, поэтому расчёт не запускают.
У вида три режима. Temperature окрашивает срез по температуре и рисует полупрозрачные изотермы;
Mismatch окрашивает срез по проверке невязки, описанной ниже; Materials показывает ящик таким, каким
вы увидели бы его вскрытым по срезу. Часть с вашей стороны среза убрана, а остальное сплошное и
освещённое: песок, пустотелые кирпичи на торце с пустотами, совпадающими от ряда к ряду (каждый
столбец пустот — канал, открытый у пола и сверху), растворные швы, перлит снаружи и керамзит снизу.
Пустоты открыты: в них видно стенки, освещённые светом, проходящим через срез, и затенённые там, где
на пути другая стенка. Проволоки нарисованы линиями там, где они выходят из среза к вам. Текстуры
только нарисованы; расчёт считает каждый материал однородным.
Перетаскивание поворачивает вид. Перетаскивание правой кнопкой, с нажатой клавишей shift или
двумя пальцами сдвигает его. Колесо мыши или щипок приближают к поверхности под указателем —
настолько, что видны песчинки. Двойной щелчок возвращает исходный вид.
Кроме временных рядов, график показывает ток и мощность солнечной батареи в зависимости от
напряжения в показанный момент: рабочую точку, выбранную контроллером, линию нагрузки через неё и
точку максимальной мощности поверх бледных кривых для полудня ясного дня. При наведении указателя
видны значения. "Input data" (входные данные) перечисляет свойства материалов, удельное
сопротивление стали, допущения о кирпичах и каналах, коэффициенты теплоотдачи поверхностей и данные
модуля, взятые из тех же констант, что использует расчёт.
"Prepare the whole run as CSV" (подготовить весь расчёт в CSV) повторяет расчёт и
предлагает zip-архив CSV-файлов: температуру каждой ячейки в начале каждого шага расчёта и
подведённое к ней за шаг тепло, вместе с сеткой, материалами, шагами и README, где сказано, как их
читать и как повторить шаги. Температуры (с точностью 0.1 мК) и подведённое тепло (с точностью 0.1
мВт) записываются одинаково: один ряд ячеек вдоль ящика на строку файла, в виде вторых разностей
вдоль ряда, так что каждый шаг читается сам по себе, а две накопленные суммы вдоль строки возвращают
значения. Расчёт по умолчанию занимает около 83 МБ; два больших файла сжимаются gzip по мере
записи.
Модель
Сетка. Кубические ячейки со стороной cell покрывают
песок, кирпичные стены, изоляцию снаружи них, а также изоляцию сверху и снизу. Кирпичные стены стоят
на полу и проходят сквозь крышку, так что каналы открыты с обоих концов; изоляция основания и крышка
покрывают только песок. Толщины слоёв округляются до целого числа ячеек; страница показывает
округлённые размеры.
Уравнение теплопроводности. ∂H/∂t = ∇·(k(T)∇T) + q, методом конечных объёмов с
явными шагами Эйлера. Состояние — энтальпия H (Дж/м³), которая переводится обратно в температуру по
таблице каждого материала, так что энергетический баланс сходится точно, хотя теплоёмкость кварца
растёт в полтора раза между 25 и 450 °C и скачком меняется при инверсии при 573 °C. На гранях
берётся среднее гармоническое теплопроводностей двух ячеек. Шаг — наибольший, какой допускает оценка
Гершгорина (умноженный на 0.9), и пересчитывается на каждом снимке.
Материалы (src/materials.ts). Песок: насыпная плотность и
теплопроводность при 20 °C из настроек, теплопроводность растёт на 3.5·10⁻⁴ Вт/(м·К) на кельвин,
теплоёмкость — по аппроксимациям Шомейта NIST для кварца. Пустотелый кирпич: 700 кг/м³ брутто,
теплопроводность с учётом излучения через пустоты. Засыпная изоляция (перлит, зола рисовой шелухи) и
несущая засыпка основания. Страница перечисляет их плотности, теплопроводности и удельные
теплоёмкости.
Нагревательная проволока (src/heater.ts). Элементы
рассчитаны так, чтобы все вместе, включённые параллельно, соответствовали точке максимальной
мощности батареи, когда проволока нагрета до температуры "sized for" (рассчитано на), и
уложены участками вдоль ящика через нагреваемую зону, равномерно по ширине и по высоте, в своих
истинных положениях. Каждый элемент — одна проволока, поэтому ток в нём одинаков, а сопротивление
следует за температурой каждого куска. На каждом шаге контроллер берёт элементы, песок у которых
ниже предела, от самого холодного, и выбирает, сколько из них включить, чтобы взять от батареи
наибольшую мощность. Он отбрасывает те, у которых за шаг проволока превысила бы свой предел или
песок — свой. Напряжение шины — это точка, где вольт-амперная характеристика батареи (однодиодная
модель модуля на 450 Вт, src/pv.ts) пересекается с проводимостью
элементов.
Сетка не может разрешить проволоку толщиной 1.6 мм. Каждый кусок проволоки делит своё тепло между
четырьмя окружающими его ячейками с билинейными весами и считывает температуру песка обратно с теми
же весами. Проволока горячее этого на q'·ln(r_eq/r_w)/(2πk) через песок плюс перепад через газовый
зазор там, где песчинки касаются проволоки. Для проволоки в центре ячейки r_eq — это 0.1985·dx
Писмена (e^−γ/2√2). Распределение тепла понижает считываемую температуру, что отодвигает r_eq в
e^(2πΔ) раз, где Δ получается из функции Грина квадратной решётки: r_eq равен 0.435·dx для проволоки
на грани между двумя ячейками и 0.718·dx в углу четырёх.
Каналы (src/flue.ts). Каждый вертикальный столбец
кирпичных ячеек, от пола до верха, — это пучок пустот: комнатный воздух входит снизу и
экспоненциально приближается к температуре каждой ячейки (ламинарное число Нуссельта 5), а расход
уравновешивает подъёмную силу столба с ламинарным трением и потерями на входе, выходе и заслонке.
Закрытая заслонка останавливает поток.
Дом. Одна теплоёмкость (настройка тепловой массы), которая получает воздух из
каналов, тепло с наружной поверхности ящика и отдачу комнатного обогревателя и теряет UA·(T −
T_наружн). Топливо удерживает её на уровне "burn fuel below" (жечь топливо ниже); тепло
топлива указывается также в литрах дизельного топлива при 35.8 МДж на литр (низшая теплота сгорания
дизельного топлива), как если бы оно сгорало без потерь тепла в дымоход. Термостат открывает
заслонку ниже уставки − 0.5 К и закрывает её выше + 0.5 К; заслонку также можно принудительно
открыть (безопасное при отказе состояние) или закрыть.
Комнатный обогреватель. Резистивный нагреватель в комнате (нихромовый, поэтому с
постоянным сопротивлением, рассчитанный на напряжение максимальной мощности батареи) на той же шине,
что и элементы. Пока термостат требует тепла и светит солнце, он включается первым, а контроллер
выбирает элементы для того, что остаётся. При настройках по умолчанию он снижает сожжённое за 14
дней топливо с 29 МДж (0.8 литра дизельного топлива) до нуля.
Погода (src/weather.ts). Ясные или пасмурные дни от
генератора с затравкой, по желанию с принудительной полосой пасмурных дней; синусоидальный суточный
ход солнца и наружной температуры.
Проверки
Энергетический баланс. Изменение энтальпии сетки сравнивается с подведённым
теплом за вычетом ушедшего; он сходится примерно до 10⁻¹⁵ от подведённого.
Невязка уравнения теплопроводности (src/residual.ts). На
каждом снимке сохранённое решение подставляется обратно в уравнение теплопроводности с центральными
разностями четвёртого порядка по пространству и трёхточечной разностью по времени, во всех ячейках,
у которых с каждой стороны по два соседа из того же материала. Остаток, делённый на теплоёмкость, —
это скорость нагрева в К/с. Она велика рядом с проволоками, линейные источники которых сетка
разрешить не может, и мала в остальных местах: при ячейках 3 см — около 2·10⁻⁵ К/с дальше двух ячеек
от любой проволоки. На сетке 5 см по умолчанию ни одна проверяемая ячейка не находится так далеко от
проволоки.
Искусственное решение (src/verify.ts). Заданная T(x, y,
z, t) в кубе песка с настоящими k(T) и теплоёмкостью, источник, делающий её точной, и ошибка расчёта
относительно неё на 8³, 16³ и 32³ ячейках: 1.33, 0.47 и 0.14 К через сутки, порядки 1.50 и 1.76,
растущие к 2 (1.87 на 48³).
Ряд проволок. У параллельных проволок посередине между двумя плоскостями при 0
°C есть точная температура. С проволокой в центре ячейки, на грани между двумя ячейками или двумя
слоями или в углу четырёх ячеек подсеточная модель совпадает с ней в пределах 0.32 % при 5 или 6
ячейках на шаг и в пределах 0.12 % при 9 или 10.
Экспорт CSV. Тест записывает короткий расчёт, читает его обратно только из
файлов и проверяет каждую ячейку на каждом шаге по правилу расчёта, как его излагает README
экспорта, в пределах округления.
Угарный газ от древесного угля в песке
src/charcoal.ts — отдельная одномерная стационарная модель слоя песка без
угля между древесным углём, зарытым в горячем песке, и комнатой — для вопроса о том, сгорает ли CO,
который выделяет уголь, до CO2 там, где встречает поступающий кислород. Кислород, CO и CO2
диффундируют через газ в порах (закон Фика в мольных долях, коэффициенты диффузии масштабированы по
T^1.75 и с коэффициентом пор 0.27). Температура падает поперёк слоя линейно. В газе CO + ½O2 → CO2
идёт со скоростью по глобальной кинетике Драйера и Глассмана (1973) для влажного CO, умноженной на
настраиваемый множитель. Уголь забирает весь дошедший до него кислород и даёт CO и CO2 в соотношении
Артура, а также может восстанавливать CO2 до CO (реакция Будуара) с заданной скоростью на единицу
концентрации CO2. Наружная часть слоя может быть барьерным слоем со своей, более низкой диффузией
(barrier в м, barrierFactor), — для битой черепицы или
посуды. Задача решается методом Ньютона с блочно-трёхдиагональным решателем на сетке, сгущённой к
углю, с поэтапным подъёмом скорости реакции от нуля и с запасным вариантом в виде интегрирования по
времени.
node build/src/charcoal-cli.js --profile --tables
node build/src/charcoal-cli.js --set hot=800 --set boudouard=6e-4 --set thickness=1
node build/src/charcoal-cli.js --area 6 --ventilation 0.0208 --tables
node build/src/charcoal-cli.js --set barrier=0.05 --set barrierFactor=0.0027
Цифры для комнаты предполагают заданные площадь слоя и вентиляцию (по умолчанию 1 м² и 0.0208
м³/с). Скорости везде даны в расчёте на секунду. Тесты проверяют балансы атомов кислорода и
углерода, точный поток без реакции и сходимость при измельчении сетки.
Переводы
README.es.md, README.zh.md, README.pt.md, README.ar.md, README.hi.md и README.ru.md — переводы английского README на
испанский, китайский (путунхуа), португальский, арабский, хинди и русский; страница показывает их в
разделе "Read me". Где перевод расходится с оригиналом, верен оригинал.
Файлы
src/params.ts: параметры и их значения по умолчанию
src/materials.ts: свойства материалов, таблицы энтальпии, удельное
сопротивление стали, воздух
src/model.ts: сетка, раскладка проволоки и подсеточный радиус
проволоки
src/heat.ts: решатель методом конечных объёмов
src/heater.ts, src/pv.ts: элементы, контроллер и
солнечная батарея
src/flue.ts: конвекция в пустотах кирпичей
src/weather.ts: синтетическая погода
src/simulate.ts: цикл по времени, снимки, ряды и энергетический
баланс
src/residual.ts, src/verify.ts: проверки
src/export.ts, src/zip.ts: весь расчёт в CSV и
zip-архив для него
src/encoding.ts: как снимки упаковываются для страницы
src/format.ts: группировка разрядов и топливо в пересчёте на
дизельное
src/charcoal.ts, src/charcoal-cli.ts: модель CO и
её таблицы
src/marching.ts: marching cubes со сгенерированной таблицей случаев
src/cli.ts: командная строка
src/web/: шаблон страницы, интерфейс, графики, рендерер WebGL2, список
входных данных и worker
tools/bundle.ts, tools/markdown.ts: собирают
страницу вместе с этим README и его переводами
README.*.md: переводы
build/ и dist/ создаются при сборке.