Repository navigation
(0.21.0) Fix the pH scales of the CarbonChemistry outputs - #457
Merged
Merged
Conversation
CarbonChemistry solves for the total-scale [H⁺] (its K₁, K₂, K_B, ... are total-scale constants), but its pH outputs treated it as the free [H⁺]: `Val(:pHᶠ)` returned the total pH, and `Val(:pHᵗ)` and `Val(:pHˢ)` added [HSO₄⁻] to an [H⁺] that already includes it, so they were 0.04 to 0.13 too low. A `pH` input was documented as the free pH but has always been used as the total pH. The outputs now treat [H⁺] as the total [H⁺]: `Val(:pHᵗ)` is -log10(H), `Val(:pHᶠ)` takes out the H⁺ in HSO₄⁻, H / (1 + S_T / K_S), and `Val(:pHˢ)` adds [HF], using the same free [H⁺] and [HF] as the alkalinity balance. `Val(:pHᵗ)` returns exactly what `Val(:pHᶠ)` used to, so the CODAP-NA test, the GLODAP validation and the MARBL test, which used `Val(:pHᶠ)` as the total pH, now use `Val(:pHᵗ)`. The docstrings and docs now say a `pH` input is the total pH. Adds a "pH scales" testset: the free and total pH match PyCO2SYS with the same constants, the seawater pH is the total pH plus [HF], a total pH input reproduces the fCO₂ and calcite saturation from DIC and Alk, and the outputs agree inside a kernel on the architecture. The CODAP-NA mean pH error check is now two-sided. Fixes #455 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CarbonChemistry outputsCarbonChemistry outputs
`Val(:pHᶠ)` now returns the free pH rather than the total pH (#455). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Thanks for the quick review @jagoosw! I'll wait a bit until a few more PRs are merged before tagging v0.21.0 if that's okay. Hoping to merge in the customer replicate tracer names (+ associated bug fixes). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #455.
The three pH scales
In seawater, some hydrogen ions are free and some are bound in bisulfate (HSO₄⁻) and hydrogen fluoride (HF). The three pH scales differ in which of them they count:
Val(:pHᶠ)Val(:pHᵗ)Val(:pHˢ)Counting more ions gives a larger [H⁺] and so a lower pH. The free pH is 0.04–0.13 above the total pH (more in warm, salty water), and the seawater pH is about 0.01 below it.
What was wrong
CarbonChemistrysolves for the total [H⁺]. Its equilibrium constants (e.g. K₁ and K₂ from Lueker et al. (2000), K_B from Dickson (1990)) are total-scale constants, following Dickson et al. (2007). The pH outputs, however, treated that [H⁺] as the free one:Val(:pHᶠ)returned-log10(H), which is the total pH.Val(:pHᵗ)added [HSO₄⁻] to an [H⁺] that already includes it. HSO₄⁻ was counted twice, so the pH was 0.04–0.13 too low.Val(:pHˢ)counted HSO₄⁻ twice too.pH =input was documented as the free pH, but it has always been used as the total pH.The fix
Treat the solved [H⁺] as the total [H⁺] in all three outputs:
These use the same free [H⁺] and [HF] as the alkalinity balance in
alkalinity_residual.jl. The docstrings and docs now say that apH =input is the total pH, and the docs explain the three scales.What this changes for users
Val(:pHᵗ)now returns exactly whatVal(:pHᶠ)used to return.Val(:pHᶠ)now returns the actual free pH, which is 0.04–0.13 higher.Val(:pHᵗ)is usually the one to compare against.Val(:pHᶠ)now returns a different number, so this is a breaking change.fCO₂, pCO₂,
Val(:CO₂)(and so the air–sea CO₂ flux) andcalcium_carbonate_saturationuse [H⁺] directly, so they don't change.