The science
The duck curve. Solar output follows the sun, load follows people. The grid operator sees the net load that conventional plants must cover:
P_net(t) = P_load(t) - P_solar(t) - P_wind(t)
With a lot of solar, P_net sags around noon and then rises very fast when the sun sets just as evening demand peaks - the neck of the "duck" (named in a 2013 California ISO study of its daily net load). The sag can touch a must-run floor (12 % of peak here), where extra solar is curtailed. Load, solar and wind shapes are smooth illustrative curves, not data of any real grid; solar is scaled so it supplies the chosen share of daily energy, wind a fixed 8 %. The price follows the net load, 12 + (P_high - 12) u^1.6, with u the net load scaled between its day minimum and maximum.
The battery. Power rating P (MW) limits charging and discharging, energy E (MWh) sets the store, and the state of charge is kept between 10 % and 90 %. The round-trip efficiency eta is split evenly, each way sqrt(eta): the store loses P dt / sqrt(eta) when delivering P dt to the grid and gains P dt sqrt(eta) when drawing P dt. Power electronics respond in a fraction of a second, so ramp rate is unlimited at the 5-minute dispatch step and a 0.2 s lag in the frequency model.
Arbitrage. Buy when the price is low, sell when it is high. The schedule is the exact optimum of a dynamic program over 240 state-of-charge levels in 15-minute steps, starting and ending the day at 25 %: V_t(e) = max_k [ price_t * grid energy(k) - c |k| + V_t+1(e + k delta) ], with a throughput cost c = 4 per MWh delivered (degradation and wear, illustrative). Losses mean a price spread must exceed about 1/eta - 1 before cycling pays.
Peak shaving. The battery discharges whenever P_net exceeds a cap and recharges whenever the net load is below it, never pushing the net load above the cap. The grid-side energy needed is
E_grid = integral of ( P_net(t) - P_cap )+ dt (largest contiguous excess)
and the nameplate size follows as E = E_grid / ( sqrt(eta) (SOC_max - SOC_min) ). This assumes the battery can recharge between separate excesses and that its power rating is at least max(P_net) - P_cap. The utility benefit is a demand charge, taken as 12 per kW-month (illustrative) on the reduced peak.
Frequency regulation. A single-area swing equation describes how imbalance moves system frequency. With S the online synchronous rating (1.3 x peak load here), H the inertia constant (s) and a generation loss P_trip:
(2 H S / f0) d(df)/dt = P_gov + P_bat - P_trip - D P_L df / f0
RoCoF, the initial rate of change of frequency, is -f0 P_trip / (2 H S). At the instant of the trip the deviation is zero, so only inertia responds: the battery does not change the initial RoCoF unless it provides synthetic inertia (not modelled). Governors then act through a droop R_g = 5 % and a 4 s lag, T_g dP_gov/dt = -(S_g / (R_g f0)) df - P_gov, limited to 20 % of S, with S_g = 60 % of S on droop. The battery follows a fast droop P_bat = -(P_rated / (R_b f0)) (df - deadband), clamped to its rating, with a 15 mHz deadband and 0.2 s lag. Load damping D = 1 %/% lowers demand slightly as frequency falls. The nadir is the minimum of f(t): the battery lifts it by supplying power during the seconds before governors catch up. Equations are integrated with fourth-order Runge-Kutta, 10 ms step. Load shedding, which real grids start near 48.8 Hz, is not modelled.
Closed form. Without governor, lag or deadband and with the battery unsaturated, the swing equation is linear: df(t) = -(P_trip / K)(1 - e^(-t/tau)) with K = D P_L / f0 + P_rated / (R_b f0) and tau = 2 H S / (f0 K). If the battery saturates at df = P_rated / K_b, the solution continues as a second exponential towards (P_rated - P_trip) f0 / (D P_L). Experiment 2 compares this exact solution with the simulation. The inertia option uses an illustrative H_eff = H (1 - 0.6 s), where s is the solar plus wind share of load at the event hour (at most 0.8), showing why sunny hours carry a larger RoCoF.
Wear and money. A full equivalent cycle is a throughput of one usable window of energy (0.8 E); capacity fade is taken as 0.01 % per cycle (about 20 % after 2000 cycles). Frequency response earns a capacity payment, taken as 14 per MW per hour (illustrative); it is shown as a separate value because that power is not free to arbitrage at the same time.
What the 3D scene shows. Up to 60 generic containers; for larger plants each container stands for more MWh (shown in the legend). Container lights are amber when discharging, blue when charging and green when idle; the share of lit containers is the state of charge. Orange, yellow and blue-white particles are battery, solar and grid power flows; the town lights follow load; turbines turn with the wind profile. Publicly reported grid batteries use containers of roughly 3 to 4 MWh each; the shapes here are generic.
Sources and simplifications. Kundur, Power System Stability and Control (1994), for the swing equation and governor droop; California ISO, What the duck curve tells us about managing a green grid (2013); fast frequency response from batteries has been publicly reported on several grids (for example a 100 MW system in South Australia, 2017). Not modelled: network congestion, transformer limits, voltage, temperature, calendar ageing, reserve markets, forecast errors, inverter current limits during faults, black start and islanding. All parameters are illustrative.
Independent educational model, not affiliated with or endorsed by any company named here; trademarks belong to their owners. Numbers are textbook-level/publicly reported approximations.