Introduction
All water industry people know that wastewater treatment is an aerated process. Air is used to provide the oxygen required for cellular respiration of the biomass, which is what consumes the carbon (as COD and BOD) and nitrifies ammonia. Getting the aeration right is critical to the efficient operation of the plant. Both over and under aeration are just as fatal to the process as each other and control of the aeration is often overlooked.
Conventional aerobic processes design for a 2 mg/L dissolved oxygen (DO) content throughout the aeration zones for complete nitrification. In reality, this is too high for normal operation and provides some over-design for peaking. Dependent on the influent, the air is often set to 1.2 to 1.5 mg/L, but designing to 2 mg/L is still recommended.
Over Aeration Risks
Over aeration can lead to growth of the wrong bacteria within the secondary treatment process, which greatly compromises the process. Filamentous bacteria such as Microthrix and Nocardia can proliferate in high-DO environments as they outcompete other bacteria with their incredibly high surface area to mass ratio. This forms foaming, bulking and poor settleability of the biomass in the secondary clarifiers. Filamentous bacteria can largely be solved with correcting aeration control.
Over aeration can also lead to DO carryover into the non-aerated zones (anoxic and anaerobic) leading to ineffective denitrification or phosphorous-release, meaning that nutrients are not adequately removed from the wastewater. Measuring the Oxidation Reduction Potential (ORP) in the unaerated zones is an indication of oxygen carryover.
Last but not least, over aeration simply wastes power by running the blowers too hard.
Oxygen Demand
The Actual Oxygen Demand (AOD) is the rate at which oxygen is consumed by the process. This is the absolute oxygen usage to supply the biomass for both respiration and for treatment (of nitrogen and carbon). Oxygen is provided back to the process by denitrification credit. The ultimate equation is:
$$ \text{AOD} = \text{AOD}_{\text{Carbon}} + \text{AOD}_{\text{Nitrogen}} – \text{AOD}_{\text{WAS}} – \text{AOD}_{\text{Denit}} $$
\( \text{AOD} \) = Actual Oxygen Demand \( ( \text{kgO}_2 \cdot \text{h}^{-1} ) \)
Carbonaceous Demand
The demand to oxidise the carbon sources, COD or BOD, is a straightforward demand of oxygen. This is a simple mass balance of oxygen demand through the secondary treatment process. Either COD or BOD can be used, but in this case BOD requires further consideration as there is some additional COD that is hydrolysed to BOD requiring an extra term in the equation.
Carbonaceous Oxygen Demand (COD) is often simply reduced across secondary treatment by 90%, or down to 50 mg/L.
$$ \text{AOD}_{\text{Carbon}} = Q \cdot (S_{\text{COD}in} – S_{\text{COD}out} ) $$
$$ \text{AOD}_{\text{Carbon}} = Q \cdot S_{\text{COD}in} \cdot 0.9 $$
\( Q \) = Influent flowrate \( (\text{ML} \cdot \text{d}^{-1}) \)
\( S_{\text{COD}} \) = COD Concentration \( (\text{mg} \cdot \text{L}^{-1}) \)
Biochemical Oxygen Demand (BOD) similarly is a reduction across the secondary treatment with an extra term for the addition of hydrolysed COD. In BOD testing, \( \text{BOD}_5 \) is the oxygen consumed over 5 days, which asymptotes to the ultimate \( \text{BOD}_U \), which represents the total amount of material which is biologically available. In general, \( F_{\text{BOD}} \) is the ratio of \( \text{BOD}_U \) to \( \text{BOD}_5 \), which is typically 1.4 to 1.5.
$$ \text{AOD}_{\text{Carbon}} = Q \cdot (S_{\text{BOD}in} – S_{\text{BOD}out} ) \cdot F_{\text{BOD}} $$
\( S_{\text{BOD}} \) = \( \text{BOD}_5 \) Concentration \( (\text{mg} \cdot \text{L}^{-1}) \)
\( F_{\text{BOD}} \) = Conversion of \( \text{BOD}_5 \) to \( \text{BOD}_U \)
Nitrogenous Demand
To convert Ammonia (\( \text{NH}_3 \)) to Nitrate (\( \text{NO}^{-}_{3} \)) requires oxidation. By the redox half-reactions:
$$ \begin{align*}
\text{NH}_3 + \frac{3}{2} \text{O}_2 &\rightarrow \text{NO}^-_2 + \text{H}_2 \text{O} + 2 \text{H}^+ \\
\text{NO}^-_2 + \frac{1}{2} \text{O}_2 &\rightarrow \text{NO}^{-}_{3}
\end{align*} $$
Which means that to convert 1 mole of ammonia to nitrite, 1.5 moles of oxygen is consumed, and to convert this nitrite to nitrate consumes a further 0.5 moles.
$$ \text{NH}_3 + 2 \text{O}_2 \rightarrow \text{NO}^-_3 + 2 \text{H}^+ + \text{H}_2 \text{O} $$
Ultimately, for 1 gram of ammonia to be oxidised all the way to nitrate consumes 4.57 grams of oxygen (as O2).
$$ 2 \text{mol} \cdot \frac{32 \text{g/mol} \text{O}_2}{14 \text{g/mol} \text{N as NH}_3} = 4.57 \text{g O}_2 $$
Which gives the nitrogenous oxygen demand of,
$$ \text{AOD}_{\text{Nitrogen}} = 4.57 \cdot Q \cdot \Delta S_{ \text{NH}_3 } $$
\( Q \) = Influent flowrate \( (\text{ML} \cdot \text{d}^{-1}) \)
\( \Delta S_{\text{NH}_3} \) = Change in ammonia concentration \( (\text{mg} \cdot \text{L}^{-1}) \)
Noting that this is the oxygen for complete nitrification. Less oxygen is required to produce nitrite only. Referring to the redox half reactions above, there is 25% less oxygen needed.
Biomass Production
As the biomass multiplies (consuming carbon), there is a portion of the oxygen that is retained within the cell mass. This is a minor term in the calculation, but a credit nonetheless. The term solves for the mass of cellular material wasted from the plant (WAS or SAS), which is essentially the biological growth rate. The net wastage rate \( P_x \) measured as \( \text{kgVSS} / \text{d} \), which is dependent on the sludge age. The generalised formula is:
$$ P_x = \left( \frac{Y}{1 + k_d \cdot \text{SRT}} \right) \cdot Q \cdot ( S_{in} – S_{out} ) $$
\( Y \) = Sludge yield \( ( \text{kgVSS} \cdot \text{kgCOD}^{-1} ) \) which is itself a function of sludge age, (typically 0.35 to 0.4 based on COD).
\( k_d \) = Endogenous respiration rate (decay coefficient), the rate at which biomass consumes itself (typically \( 0.06 \) to \( 0.10 \) \( \text{d}^{-1} \) at \( 20^{\circ} \text{C} \)).
\( \text{SRT} \) = Solids Retention Time \( \text{d} \)
\( S \) = Substrate as per Sludge Yeild \( Y \), as COD or BOD (\( \text{kgCOD} \cdot \text{d}^{-1} \))
The theoretical oxygen release of biomass is from the magical stoichiometric ratio of biomass. The empirical formula of a bacteria is \( \text{C}_5 \text{H}_7 \text{O}_2 \text{N} \).
Where the oxidation is,
$$ \text{C}_5 \text{H}_7 \text{O}_2 \text{N} + 5 \text{O}_2 \rightarrow 5 \text{CO}_2 + 2 \text{H}_2 \text{O} + \text{NH}_3 $$
This oxidation is 5 moles of oxygen per mole of biomass,
$$ \frac{160 \text{g} / \text{mol O}_2 }{113 \text{g} / \text{mol Biomass} } = 1.4159 $$
The ultimate effect to oxygen demand is a reduction of,
$$ \text{AOD}_\text{WAS} = 1.4159 \cdot P_x $$
Denitrification Credit
The denitrification of nitrate (and nitrite) releases oxygen to form nitrogen gas. This is oxygen re-released back to the process in terms of credit. Of note, denitrification consumes carbon, in this example a simple carbohydrate will be used to demonstrate this.
$$ \text{C}_{10} \text{H}_{19} \text{O}_3 \text{N} + 10 \text{NO}^-_3 + 10 \text{H}^+ \rightarrow 5 \text{N}_2 + 10 \text{CO}_2 + \text{NH}_3 + 8 \text{H}_2 \text{O} $$
The redox half reaction is
$$ \begin{align*}
\text{O}_2 + 4 \text{H}^+ + 4 \text{e}^- &\rightarrow 2 \text{H}_2 \text{O} \\
\text{NO}^-_3 + 6 \text{H}^+ + 5 \text{e}^- &\rightarrow \frac{1}{2} \text{N}_2 + 3 \text{H}_2 \text{O}
\end{align*} $$
Balancing the reactions for the transfer of 5 and 4 electrons, there are 1.25 moles of oxygen released for every mole of N.
$$ \text{Oxygen Credit} = 1.25 \left( \frac{32 \text{gO}_2}{14 \text{gN}} \right) = 2.857 \frac{\text{gO}_2}{\text{gN as NO}^{-}_{3}} $$
Therefore, finally
$$ \text{AOD}_{\text{Denit}} = 2.857 \cdot Q \cdot ( \Delta S_{\text{NH}_3} – S_{\text{NO}^{-}_{3out}} ) $$
Of note, this denitrification credit is only available when the ammonia is oxidised to nitrate. Less is available when ammonia is nitrated (to nitrite) only.
Oxygen Transfer
Standard Oxygen Transfer Rate
The Standard Oxygen Transfer Rate (SOTR) is how much air is required to transfer enough oxygen to meet the Actual Oxygen Transfer Rate (AOTR) in real conditions. This converts actual demand to what the blowers are required to deliver. What goes into it?
- Atmospheric oxygen concentration and pressure (site altitude)
- Dissolved oxygen concentration target
- Water salinity (beta factor)
- Mass transfer reduction (alpha factor)
- Water temperature
- Water depth (height above the diffusers)
The basic formula is as follows:
$$ \frac{\text{AOTR}}{\text{SOTR}} = \alpha \cdot \left( \frac{\beta \cdot C^*_{sw} – C}{C^*_{s20}} \right) \theta^{(T-20)} $$
\( \text{AOTR} \) = Actual Oxygen Transfer Rate \( ( \text{kgO}_2 \cdot h^{-1}) \)
\( \text{SOTR} \) = Standard Oxygen Transfer Rate \( ( \text{kgO}_2 \cdot h^{-1}) \)
\( \alpha \) = Alpha Factor (typically between \(0.3\) to \(1.0\))
\( \beta \) = Beta Factor (typically between \(0.95\) to \(1.0\))
\( \theta \) = Theta Factor (typically \(1.024\))
\( C \) = Target dissolved oxygen concentration (typically designed to achieve \( 2.0 \text{mg}/\text{L} \))
\( C^*_{s20} \) = Concentration of oxygen at saturation in \( 20^{\circ} \text{C} \) water at sea level (typically \( 9.09 \text{mg}/\text{L} \))
\( C^*_{sw} \) = Concentration of oxygen at saturation in site specific water temperature and pressure
\( T \) = The operating water temperature (\( {}^{\circ} \text{C} \))
Alpha Factor (\(\alpha\)) is the ratio of the oxygen mass transfer coefficient (\(K_{L}a\)) in process wastewater to the oxygen mass transfer coefficient (\(K_{L}a\)) in clean water, thus a dimensionless unit. Note that because the Alpha Factor can range from 0.3 to 1.0, this factor could halve or double the SOTR. Alpha Factor testing is recommended for existing plants. Beta Factor (\(\beta\)) is the ratio of the oxygen saturation concentration in wastewater to the oxygen saturation concentration in clean water.
Theta Factor (\(\theta\)) is a temperature correction coefficient used to adjust the transfer rate based on water temperature. It acts as a base for an exponent in the Arrhenius-type equation used to correct the transfer rate. Because it is a coefficient in an exponential relationship used to adjust a rate to a standard temperature (\( 20^{\circ} \text{C} \)), it is considered a dimensionless constant (typically 1.024). Noting that at higher temperatures, more air is required as the saturation decreases. Therefore, when calculating the maximum air demand, use the warmer summer temperatures and conversly, the minimum uses the colder winter temperature.
To calculate the DO saturation concentration following Henry’s Law, solubility is proportional to the partial pressure of the oxygen the water is exposed to. The local pressure is depends on the altitude of the site, expressed as a ratio standardised to sea level pressure, such that the pressure at sea level is 1.
$$ \frac{P_b}{P_s} = (1 – 2.2557 \times 10^{-5} \times H_{alt})^{5.2559} $$
\( H_{alt} \) = Altitude of the site \( ( \text{m} ) \)
The hydrostatic pressure of the bubble as it progresses up the water column increases by 1 atm for every 10.33m of depth, so the extra pressure is \( \Delta P_{\text{Diffuser}} = H_s / 10.33 \). But, as the bubble moves up the column, it progressively experiences less pressure and therefore it is assumed that the ‘average’ condition of the bubble is at the middle of the height, therefore \( \Delta P_{\text{Average}} = H_s / 20.66 \), which gives the formula:
$$ C^*_{sw} = C_{s(T)} \left( \frac{P_{alt}}{P_{sea}} + \frac{H_s}{20.66} \right) $$
\( H_s \) = Height of water above diffuser \( ( \text{m} ) \)
By designing to the mid-depth of the bubble, this assumes the rise rate of the bubble is constant and thus the arithmetic mean applies. In reality, oxygen is transfered at a marginally higher rate nearer the diffuser as the driving force is higher. For standard use, \( H_s / 2 \) will suffice.
Standard Oxygen Transfer Efficiency
The Standard Oxygen Transfer Efficiency (SOTE) is the effective transfer per metre as the aeration bubbles rise. This has the units of percent Oxygen transfer per meter (%O2/m). New or unfouled diffusers produce the smallest bubbles, which have the highest surface area to volume ratio (and the highest total surface area), which produces the highest transfer. In general, the best performing fine bubble diffusers can achieve up to 6% per metre.
One method of varifying the SOTE is simply measuring the concentration of oxygen in the off gas from the surface of the aeration zone (in a hood). The difference in concentration between the ambient and measured, divided by the height of water over the diffusers shows the absorption rate into the bulk liquid. Air being 23.14% oxygen by mass (or 20.95% by volume) means that a 5 metre deep tank at 6% would absorb 30% of the oxygen, such that the off-gas should have only 16.2% oxygen by mass.
Calculator
To use the following calculator, a range of flowrates are required for design. This calculates only a single state, so to capture a range of conditions, a range of inputs are required. This is: the low-end range, top of range and median demand rates.
| Input | Low | Median | High |
|---|---|---|---|
| Design Horizon | Early | Mid-point | End |
| Flow and Load | Low load Dry weather diurnal trough (hourly load) | Average daily load | High Load Peak condition (hourly load) |
| Dissolved Oxygen Target (mg/L) | 1.2 | 1.5 | 2.0 |
| Sludge Age (d) | Minimum (least biomass to support) | Average | Maximum (most biomass to support) |
| Effluent BOD or COD (mg/L) | Highest concentration (least treatment) | Average | Lowest concentration (most treatment) |
| Effluent Ammonia (mg/L) | Highest concentration (least treatment) | Average | Lowest concentration (most treatment) |
| Effluent Nitrate (mg/L) | Lowest concentration (most denitrification credit) | Average | Highest concentration (least denitrification credit) |
| Temperature (oC) | Coldest | Average | Warmest |
| SOTE (%/m) | Highest (New) | Average | Lowest (Fouled) |
| Mixing (m3 m-2 h-1) | Pass/Fail check | – | – |
| Result AOTR (kgO2 h-1) Result SOTR (kgO2 h-1) Result Airflow (Nm3 h-1) | Solves for turn down requirement and duty/assist configuration | Solves for most efficient operating point | Solves for peak demand |
Actual Oxygen Demand (AOD)
Oxygen Transfer Conditions
Aeration Requirements
Advanced Factors
Mixing
Aeration is not only to supply oxygen to supply the process, but to suspend the mixed liquor. In general, \( 4 \text{W} \text{m}^{-3} \) is required to keep the MLSS suspended. By aerating the tanks this can be achieved. In general, the minimum mixing requirement is \( 1.2 \text{m}^{3} \text{m}^{-2} \text{h}^{-1} \). Shallower tanks have air spread more thinly across the tanks and thus less mixing energy. For processes with intermittent air, shallow tanks or very low DO, additional mixing may be required.
Authors Note
When using the calculations you should reference the page version (and date) as the page is being continuously updated. I hope that you learn both how to design aeration systems and how to code in HTML. The raw HTML is available below.
Aeration Calculation Code
<div class="flux-calculator-container"> <h4>Actual Oxygen Demand (AOD)</h4> <div class="flux-inputs-wrapper"> <div class="input-group"> <label for="organic-type">Organic Input Type:</label> <select id="organic-type"> <option value="BOD">BOD</option> <option value="COD">COD</option> </select> </div> <div class="input-group"> <label for="flow-q">Influent Flowrate, <em>Q</em> (ML/d):</label> <input type="number" id="flow-q" value="5" min="0" step="0.1"> </div> <div class="input-group"> <label for="org-in" id="org-in-label">BOD In (mg/L):</label> <input type="number" id="org-in" value="300" min="0" step="1"> </div> <div class="input-group"> <label for="org-out" id="org-out-label">BOD Out (mg/L):</label> <input type="number" id="org-out" value="10" min="0" step="1"> </div> <div class="input-group"> <label for="nh3-in">Ammonia In (mg/L):</label> <input type="number" id="nh3-in" value="50" min="0" step="1"> </div> <div class="input-group"> <label for="nh3-out">Ammonia Out (mg/L):</label> <input type="number" id="nh3-out" value="1" min="0" step="0.1"> </div> <div class="input-group"> <label for="no3-out">Nitrate Out (mg/L):</label> <input type="number" id="no3-out" value="10" min="0" step="1"> </div> <div class="input-group"> <label for="srt">Sludge Age, <em>SRT</em> (d):</label> <input type="number" id="srt" value="15" min="0.1" step="0.5"> </div> </div> <div class="assessment-data"> <div>Carbonaceous AOD: <strong><span id="res-aod-c">0.0</span> kg O₂/h</strong></div> <div>Nitrogenous AOD: <strong><span id="res-aod-n">0.0</span> kg O₂/h</strong></div> <div>Denitrification Credit: –<strong><span id="res-aod-denit">0.0</span> kg O₂/h</strong></div> <div>Biomass Production Credit (P<sub>x</sub>): –<strong><span id="res-aod-was">0.0</span> kg O₂/h</strong></div> <div>Target AOTR: <strong><span id="res-aotr">0.0</span> kg O₂/h</strong></div> </div> <h4>Oxygen Transfer Conditions</h4> <div class="flux-inputs-wrapper"> <div class="input-group"> <label for="do">Target DO (mg/L):</label> <input type="number" id="do" value="2.0" min="0" step="0.1"> </div> <div class="input-group"> <label for="temp">Temp (°C):</label> <input type="number" id="temp" value="20" min="0" step="0.5"> </div> <div class="input-group"> <label for="alt">Altitude (m):</label> <input type="number" id="alt" value="0" min="0" step="10"> </div> <div class="input-group"> <label for="depth">Water Depth (m):</label> <input type="number" id="depth" value="5.0" min="0.1" step="0.1"> </div> <div class="input-group"> <label for="sote">Base SOTE/m (%):</label> <input type="number" id="sote" value="6.5" min="0.1" step="0.1"> </div> </div> <h4>Aeration Requirements</h4> <div class="assessment-data"> <div>Calculated SOTE: <span id="out-sote">0.0</span>%</div> <div>Standard O₂ Rate (SOTR): <strong><span id="out-sotr">0.00</span> kg O₂/h</strong></div> <div>Required Airflow: <strong><span id="out-air">0</span> Nm³/h</strong></div> </div> <h4>Advanced Factors</h4> <div class="flux-inputs-wrapper"> <div class="input-group"> <label for="alpha">Alpha (α):</label> <input type="number" id="alpha" value="0.65" min="0.1" max="1.0" step="0.05"> </div> <div class="input-group"> <label for="beta">Beta (β):</label> <input type="number" id="beta" value="0.95" min="0.1" max="1.0" step="0.01"> </div> <div class="input-group" id="fbod-container"> <label for="f-bod">F_BOD (Conversion to BOD<sub>U</sub>):</label> <input type="number" id="f-bod" value="1.5" min="1.0" step="0.1"> </div> <div class="input-group"> <label for="yield-y">Yield, <em>Y</em> (kgVSS/kgCOD):</label> <input type="number" id="yield-y" value="0.4" min="0" step="0.01"> </div> <div class="input-group"> <label for="kd">Decay Coefficient, <em>k<sub>d</sub></em> (d⁻¹):</label> <input type="number" id="kd" value="0.08" min="0" step="0.01"> </div> </div></div><style>.flux-calculator-container { width: 100%; margin: 1.5em 0; font-family: inherit; }.flux-inputs-wrapper { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 20px; }.input-group label { display: block; font-weight: 600; font-size: 0.9em; margin-bottom: 5px; }.input-group input,.input-group select { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }.assessment-data { display: flex; flex-direction: column; gap: 6px; font-size: 0.95em; margin-bottom: 20px; }</style><script>(function() { const inputs = document.querySelectorAll('.flux-calculator-container input, .flux-calculator-container select'); function calc() { // 1. Gather AOD Inputs const q = parseFloat(document.getElementById('flow-q').value) || 0; const orgType = document.getElementById('organic-type').value; const orgIn = parseFloat(document.getElementById('org-in').value) || 0; const orgOut = parseFloat(document.getElementById('org-out').value) || 0; const nh3In = parseFloat(document.getElementById('nh3-in').value) || 0; const nh3Out = parseFloat(document.getElementById('nh3-out').value) || 0; const no3Out = parseFloat(document.getElementById('no3-out').value) || 0; const srt = parseFloat(document.getElementById('srt').value) || 0; const fBod = parseFloat(document.getElementById('f-bod').value) || 1; const yieldY = parseFloat(document.getElementById('yield-y').value) || 0; const kd = parseFloat(document.getElementById('kd').value) || 0; // Update UI labels based on organic toggle document.getElementById('org-in-label').innerText = orgType + " In (mg/L):"; document.getElementById('org-out-label').innerText = orgType + " Out (mg/L):"; document.getElementById('fbod-container').style.display = (orgType === 'BOD') ? 'block' : 'none'; // 2. Calculate AOD Components (Note: Q * mg/L = kg/d, dividing by 24 gives kg/h) const deltaOrg = Math.max(0, orgIn - orgOut); // Effective substrate consumed on a COD-equivalent basis - shared by the // carbonaceous demand term and the biomass yield term below. const effectiveOrg = (orgType === 'BOD') ? deltaOrg * fBod : deltaOrg; // COD: 1:1 to Oxygen const aodC = (q * effectiveOrg) / 24; const deltaNh3 = Math.max(0, nh3In - nh3Out); const aodN = (4.57 * q * deltaNh3) / 24; const denitAmount = Math.max(0, deltaNh3 - no3Out); const aodDenit = (2.857 * q * denitAmount) / 24; // Biomass production (Px) and its associated oxygen credit // Px (kgVSS/d) = [ Y / (1 + kd . SRT) ] . Q . deltaS const pxDenominator = 1 + (kd * srt); const px = pxDenominator > 0 ? (yieldY / pxDenominator) * q * effectiveOrg : 0; const aodWas = (1.4159 * px) / 24; // kg O2/h, from C5H7O2N stoichiometry const aotr = Math.max(0, aodC + aodN - aodDenit - aodWas); // Update AOD UI document.getElementById('res-aod-c').innerText = isFinite(aodC) ? aodC.toFixed(1) : "0.0"; document.getElementById('res-aod-n').innerText = isFinite(aodN) ? aodN.toFixed(1) : "0.0"; document.getElementById('res-aod-denit').innerText = isFinite(aodDenit) ? aodDenit.toFixed(1) : "0.0"; document.getElementById('res-aod-was').innerText = isFinite(aodWas) ? aodWas.toFixed(1) : "0.0"; document.getElementById('res-aotr').innerText = isFinite(aotr) ? aotr.toFixed(1) : "0.0"; // 3. Gather Oxygen Transfer Inputs const DO = parseFloat(document.getElementById('do').value) || 0; const T = parseFloat(document.getElementById('temp').value) || 0; const alt = parseFloat(document.getElementById('alt').value) || 0; const alpha = parseFloat(document.getElementById('alpha').value) || 0; const beta = parseFloat(document.getElementById('beta').value) || 0; const depth = parseFloat(document.getElementById('depth').value) || 0; const sote_m = parseFloat(document.getElementById('sote').value) || 0; // 4. Calculate Transfer Model const p_ratio = Math.pow(1 - 2.25577e-5 * alt, 5.2559); const Cs_T = 14.652 - 0.41022 * T + 0.007991 * Math.pow(T, 2) - 0.000077774 * Math.pow(T, 3); const Csw = Cs_T * (p_ratio + (depth / 20.66)); const Cs20_depth = 9.09 * (1 + (depth / 20.66)); const factor = alpha * ((beta * Csw - DO) / Cs20_depth) * Math.pow(1.024, T - 20); const sote = depth * sote_m; const sotr = factor > 0 ? aotr / factor : 0; const airflow = sote > 0 ? sotr / ((sote / 100) * 0.279) : 0; // 5. Update Final Transfer UI document.getElementById('out-sote').innerText = isFinite(sote) ? sote.toFixed(1) : "0.0"; document.getElementById('out-sotr').innerText = isFinite(sotr) ? sotr.toFixed(2) : "0.00"; document.getElementById('out-air').innerText = isFinite(airflow) ? Math.round(airflow).toLocaleString() : "0"; } inputs.forEach(i => i.addEventListener('input', calc)); inputs.forEach(i => i.addEventListener('change', calc)); // For dropdown calc();})();</script>
Version Control and Updates
Version 1.0 updated on 4 July 2026
This is ready to use. I suspect that there will be code updates required as I make this more complicated in the future.
Version 0.2 updated on 2 July 2026
Okay, nearly there. Pretty sure all of the code is okay and the theory is all down. I’m genuinely quite proud of this page and the calculation. I love HTML.
Version 0.1 updated on 1 July 2026
This one is way harder than I thought it would be. So much information, so little time!