From pnge-geochem-pw
Run PHREEQC (USGS geochemical modeling code) to compute aqueous speciation, mineral saturation indices, and scaling/precipitation predictions for produced waters and oilfield brines. Use this skill whenever the user asks about brine chemistry modeling, scaling prediction (barite, calcite, gypsum, celestite, halite, anhydrite), saturation index (SI), aqueous speciation, activity coefficients, ion interference in direct lithium extraction (DLE), produced water treatability, or any question needing thermodynamic equilibrium calculations. Trigger phrases: PHREEQC, speciation, saturation index, SI, scaling prediction, scaling tendency, barite scaling, calcite scaling, gypsum scaling, brine chemistry, aqueous geochemistry, Pitzer model, activity coefficient, high-TDS brine, will this brine scale, DLE interference, equilibrium speciation, mineral solubility, sulfate scaling, carbonate scaling. Selects the right thermodynamic database for the ionic strength, builds the input deck, runs PHREEQC, and interprets the SI table.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pnge-geochem-pw:phreeqc-geochemThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Runs the USGS PHREEQC (pH-REdox-EQuilibrium in C) geochemical code to compute
Runs the USGS PHREEQC (pH-REdox-EQuilibrium in C) geochemical code to compute
speciation, activity coefficients, and mineral saturation indices for produced
waters and high-TDS oilfield brines. This skill is the chemistry complement to
the usgs-produced-waters skill: once you know the brine composition, use this
to decide whether it will scale, whether DLE is viable, and which minerals
control Li/Mg recovery.
None required. PHREEQC is free, open-source USGS software. No API key,
no login, no rate limits. The only prerequisite is a local phreeqc binary.
# Template for consistency with other skills; not used here:
# KEY=$(grep '^api_key=' ~/.config/usgs/credentials 2>/dev/null | cut -d= -f2)
PHREEQC must be installed locally. This skill does not install it for you — ask the user to pick one of the methods below.
| Platform | Method | Command |
|---|---|---|
| macOS (Homebrew tap) | brew via geo-smart or third-party tap | No official homebrew-core formula. Build from source or use conda. |
| macOS / Linux (conda) | conda-forge | conda install -c conda-forge phreeqc (verify with conda search phreeqc -c conda-forge) |
| Linux (apt) | Debian/Ubuntu | sudo apt install phreeqc (may lag USGS release) |
| All platforms | Official USGS build | Download from https://www.usgs.gov/software/phreeqc-version-3 |
| Source | Autotools / CMake | ./configure && make && sudo make install |
Current version (as of Jan 2025): PHREEQC 3.8.6 (build 17100), released January 7, 2025. USGS releases 1-2 builds per year; check the official page for the latest.
Verify install:
phreeqc --version
# or
phreeqc -v
Find the database directory:
# Standard install locations:
ls /usr/local/share/doc/phreeqc/database/ # Linux source build
ls /opt/homebrew/share/phreeqc/database/ # Homebrew ARM
ls $CONDA_PREFIX/share/doc/phreeqc/database/ # conda
ls "C:\Program Files\USGS\phreeqc-3.8.6\database\" # Windows
# Or search:
find / -name "pitzer.dat" 2>/dev/null | head
Set PHREEQC_DATABASE_DIR env var (or pass the full path as the second CLI
argument) so input decks don't need to hardcode paths.
PHREEQC is a single binary invoked with up to four positional arguments:
phreeqc [input_file] [output_file] [database_file] [screen_output_file]
| Position | Meaning | Example |
|---|---|---|
| 1 | Input deck | marcellus_brine.pqi |
| 2 | Main output (long) | marcellus_brine.pqo |
| 3 | Thermodynamic database | /opt/homebrew/share/phreeqc/database/pitzer.dat |
| 4 | Screen log (short) | marcellus_brine.log |
Minimal run:
phreeqc input.pqi output.pqo $DB/pitzer.dat
Exit code: 0 on success, non-zero on parse or convergence errors. Stderr captures most diagnostics; parse errors also appear at the top of the output file.
Map the user's question to a PHREEQC simulation type:
| User asks about... | PHREEQC block |
|---|---|
| "Will this brine scale?" | SOLUTION + EQUILIBRIUM_PHASES or SELECTED_OUTPUT with -saturation_indices |
| "What's the SI of barite in sample X?" | SOLUTION + SELECTED_OUTPUT |
| "Speciation of this produced water" | SOLUTION (then read output) |
| "Will calcite precipitate if I raise pH?" | SOLUTION + REACTION (add NaOH) + EQUILIBRIUM_PHASES |
| "What if I dilute this 10:1?" | SOLUTION + MIX |
| "What happens as I heat this to 90 C?" | SOLUTION + REACTION_TEMPERATURE |
| "DLE feedstock check" | Compute SI for barite, celestite, calcite, gypsum, halite; report Ca/Li, Mg/Li, SO4/Li ratios |
Critical decision. The wrong database produces nonsense at oilfield ionic
strengths. See references/thermo_databases.md for the full matrix.
| Database | TDS range | Best for | Key limitation |
|---|---|---|---|
phreeqc.dat | < 30,000 mg/L | Fresh / brackish water | Davies / extended Debye-Huckel; unreliable above seawater ionic strength |
wateq4f.dat | < 30,000 mg/L | Natural waters with many trace metals | Same activity model limits as phreeqc.dat; more elements |
pitzer.dat | > 30,000 mg/L, up to halite saturation | Produced waters, Smackover, Marcellus, Bakken, seawater evaporites | Limited element set; Li, Sr, Ba parameters incomplete at high T |
sit.dat | Intermediate ionic strength | Mid-salinity, nuclear waste studies | Less mature than Pitzer for Cl brines |
llnl.dat | < 30,000 mg/L but wider T/P | High-temperature geothermal | B-dot activity model; not for hypersaline |
minteq.v4.dat | Dilute | EPA MINTEQA2 port; contamination / sorption | Not for brines |
frezchem.dat | Sub-zero to moderate T | Cryogenic / sea-ice chemistry | Niche |
Default for produced-water work: pitzer.dat. Produced waters from
Marcellus, Utica, Bakken, and Smackover routinely exceed 100,000 mg/L TDS —
well outside the Debye-Huckel range of phreeqc.dat.
PHREEQC input is block-structured. Each block starts with a keyword. Minimum
useful deck has SOLUTION, SELECTED_OUTPUT, and END.
TITLE Marcellus produced water - scaling check
SOLUTION 1
temp 60 # deg C
pH 5.8
pe 4.0
redox pe
units mg/l
density 1.12 # optional; Pitzer calculates if omitted
Na 45000
K 600
Ca 12000
Mg 1200
Sr 2500
Ba 2000
Li 80
Cl 95000 charge # balance charge on Cl
Alkalinity 120 as HCO3
S(6) 50 # SO4 as sulfate-S(6)
Br 800
Fe(2) 30
B 20
Si 15
SELECTED_OUTPUT
-file marcellus.sel
-reset false
-saturation_indices Barite Calcite Celestite Gypsum Anhydrite Halite \
Strontianite Witherite Siderite Dolomite
-molalities Li+ Mg+2 Ca+2 Ba+2 Sr+2 SO4-2
-totals Li Mg Ca Ba Sr S(6)
-ionic_strength true
-temperature true
-pH true
END
Key gotchas in the deck:
mg/L is per liter of solution; mg/kgs is per kg of solution
(better for hypersaline). ppm is ambiguous — avoid.charge to one major ion (usually Cl or Na). PHREEQC
will adjust that concentration to balance.as HCO3 or as CaCO3; PHREEQC computes the carbonate
speciation at the input pH.pe 4 or lower is realistic; highly reducing
formations may need pe -2 to 0. The skill should ask if the user cares
about Fe/sulfide redox.-molalities and -saturation_indices are
whitespace-separated; use \ for line continuation.DB=/opt/homebrew/share/phreeqc/database # adjust for your install
phreeqc marcellus.pqi marcellus.pqo $DB/pitzer.dat marcellus.log
# Check exit code
if [ $? -ne 0 ]; then
grep -i 'error\|warning' marcellus.pqo | head -20
fi
Two output streams:
marcellus.pqo): human-readable, contains every block
executed. Big but browsable. Look for the Saturation indices table and
the Distribution of species table.marcellus.sel): tab-delimited; one row per
simulation. Easy to pipe into awk, pandas, or Go.Extracting SI values from marcellus.sel:
# Header row has si_<mineral> columns
head -1 marcellus.sel | tr '\t' '\n' | grep -n '^si_'
awk -F'\t' 'NR==1 || NR==2' marcellus.sel | cut -f $(header_cols)
Go wrapper — see references/golang_wrapper.go — shells out, captures
both output files, parses the SELECTED_OUTPUT TSV, and returns a SIReport
struct with SI values keyed by mineral name.
The saturation index is:
SI = log10(IAP / Ksp)
where IAP is the ion activity product and Ksp is the solubility product at the given T and P.
| SI range | Interpretation | Action in produced-water context |
|---|---|---|
| SI > 1 | Strongly supersaturated | Likely already precipitating; scale forming downhole or at surface |
| 0 < SI < 1 | Supersaturated | Will precipitate given nucleation sites / time; add scale inhibitor |
| -0.3 < SI < 0 | Near equilibrium | Watch on T/P/pH change; borderline |
| SI < -0.3 | Undersaturated | Dissolution if mineral present; safe from that scale |
Practical thresholds from oilfield experience:
Barite, BaSO4): SI > 0.5 = real scaling risk; inhibitor requiredCalcite, CaCO3): SI > 0.5 triggers scale with CO2 lossHalite, NaCl): SI ~ 0 means brine is at salt saturation; rare but
seen in some evaporite-hosted produced watersCelestite, SrSO4): track when Sr > 500 mg/L and SO4 detectableFor DLE assessment:
Input (smackover_example.pqi):
TITLE Smackover Formation brine - Columbia County, AR - DLE screening
SOLUTION 1
temp 80
pH 5.5
pe 2.0
redox pe
units mg/l
density 1.20
Na 85000
K 3500
Ca 40000
Mg 3000
Sr 1500
Ba 50
Li 400
Cl 180000 charge
Alkalinity 50 as HCO3
S(6) 200
Br 5000
B 200
SELECTED_OUTPUT
-file smackover.sel
-reset false
-saturation_indices Barite Calcite Celestite Gypsum Anhydrite Halite \
Dolomite Strontianite Witherite
-molalities Li+ LiCl Mg+2 MgCl+ Ca+2 CaCl+ Ba+2 Sr+2 SO4-2
-totals Li Mg Ca Ba Sr S(6) Cl
-ionic_strength true
END
Run:
DB=/opt/homebrew/share/phreeqc/database
phreeqc smackover_example.pqi smackover.pqo $DB/pitzer.dat
Expected output highlights (smackover.pqo):
Saturation indices
--------------------
Phase SI** log IAP log K(T, P)
Anhydrite -0.12 -4.54 -4.42 CaSO4
Barite 0.34 -9.63 -9.97 BaSO4
Calcite -0.45 -10.00 -9.55 CaCO3
Celestite -0.72 -7.22 -6.50 SrSO4
Dolomite -1.10 -18.10 -17.00 CaMg(CO3)2
Gypsum -0.01 -4.59 -4.58 CaSO4:2H2O
Halite -0.85 -2.43 -1.58 NaCl
Strontianite -1.40 -10.50 -9.10 SrCO3
Witherite -2.90 -11.50 -8.60 BaCO3
Ionic strength = 5.9 mol/kgw
Density = 1.198 g/cm3
Interpretation: This Smackover brine is slightly supersaturated with
respect to barite (SI = 0.34) — mild scaling risk, manageable with inhibitor.
Gypsum is at equilibrium (SI ~ 0) — any cooling or CO2 loss will push it
over. Calcite is undersaturated, so CO2 loss / pH rise from atmospheric
exposure would flip it positive. Ionic strength of 5.9 mol/kgw is firmly in
Pitzer territory — phreeqc.dat would have been wrong by 0.5-1.5 log units
on most SIs.
Present PHREEQC results as SI table + narrative + action items:
## Smackover Brine — Speciation and Scaling Analysis (Pitzer, 80 deg C)
Inputs: TDS ~320,000 mg/L; Ca 40,000; Mg 3,000; Li 400; Ba 50; SO4 200 mg/L.
Database: pitzer.dat (ionic strength 5.9 mol/kgw — Pitzer required).
| Mineral | SI | Status | Action |
|--------------|-------|---------------------|---------------------------------|
| Barite | +0.34 | Supersaturated | Inhibitor (phosphonate) needed |
| Gypsum | -0.01 | At equilibrium | Monitor; any cooling precipitates |
| Anhydrite | -0.12 | Near saturation | Scaling risk if T rises |
| Calcite | -0.45 | Undersaturated | Watch pH / CO2 degassing |
| Celestite | -0.72 | Undersaturated | OK |
| Halite | -0.85 | Undersaturated | OK (no evaporation concentration) |
**Speciation:** Li+ free ion fraction = 97%; LiCl0 ion pair = 3%. Mg/Li
molar ratio = 29 — manageable for modern DLE sorbents (<40 threshold).
Ca/Li = 173 — high but tolerable for lithium-ion-sieve or solvent
extraction processes.
**Summary:** DLE-viable feedstock. Primary concern is barite scaling during
sorbent regeneration when SO4 concentrates. Gypsum is the second-priority
scale if the process includes any evaporative step. Ionic strength is high
enough that only Pitzer-based models should be trusted for plant design;
re-run in OLI or equivalent commercial code before final engineering.
| Issue | Cause | Action |
|---|---|---|
phreeqc: command not found | Binary not installed or not in PATH | See Install section; run which phreeqc |
ERROR: Could not open database file | Wrong path or missing .dat file | find / -name "pitzer.dat"; set PHREEQC_DATABASE_DIR or pass full path as 3rd arg |
ERROR: Unknown element | Element not in selected database | Switch database (e.g., Li is in pitzer.dat but limited in sit.dat); check references/thermo_databases.md |
WARNING: Charge imbalance > 5% | Input analysis not electroneutral | Append charge to Cl or Na concentration; check for missing major ion |
ERROR: Numerical method failed | Convergence failure; often from contradictory constraints | Remove charge flag from multiple ions; relax pe constraint; check for negative concentrations |
| SI values wildly different from expected | Wrong database for ionic strength | Recheck: hypersaline needs pitzer.dat; phreeqc.dat fails above ~1 mol/kg |
| No SI for a mineral | Mineral not defined in database | Check PHASES block in the .dat file; some minerals (e.g., specific Li minerals) exist only in llnl.dat or require manual definition |
pe and redox contradict | Both specified incorrectly | Use redox pe with a pe value, or use a redox couple like redox O(0)/O(-2) with dissolved O2 |
| Output file contains only echo of input | Parse error stopped execution | Look for first ERROR in .pqo; usually a syntax error in one block |
Pitzer parameter gaps for Li at high T and I. The Pitzer interaction
coefficients for Li-Cl, Li-SO4, and Li-HCO3 in pitzer.dat are
well-calibrated at 25 deg C but extrapolate with larger uncertainty above
80-100 deg C and ionic strengths above 6 mol/kgw. For Smackover-style
brines at reservoir temperature (90-110 deg C), SI values on
Li-bearing minerals carry ~0.3-0.5 log unit uncertainty.
Limited element set in pitzer.dat. Not every element is parameterized.
Notably weak/absent: Al, Si, Fe(III), trace metals beyond the majors.
If those matter, run parallel phreeqc.dat for comparison (accepting the
ionic strength caveat) or switch to llnl.dat (accepting its limits at
high I).
Temperature limits. pitzer.dat is solid up to ~200 deg C for the
major-ion system; extrapolation above that is unreliable without
independent validation.
Equilibrium != kinetics. An SI > 0 says a mineral can precipitate, not that it will quickly. Barite nucleates fast; calcite and dolomite often do not. Field-observed scale is biased toward fast-kinetic phases even when slower phases are more supersaturated. Report SI alongside known-kinetic notes; do not substitute for reactive-transport modeling.
Input data quality drives output quality. A produced-water analysis
with 10% charge imbalance produces SI values that look precise but rest on
a badly constrained solution. Always report the charge balance from the
SOLUTION echo. Treat SI differences < 0.3 log units as noise.
pH measurement on hot brines. Wellhead pH is often measured after cooling and depressurization, at which point CO2 has degassed and Fe(II) has partially oxidized. The measured pH is not the reservoir pH. For reservoir-condition modeling, adjust pH upward ~0.5-1 unit and re-run.
CBI / self-reported chemistry. If the brine composition comes from industry disclosures (FracFocus, operator reports), sulfate and bicarbonate are frequently reported as "< detection limit" without the limit value. PHREEQC treats these as exactly the numeric value given; set a realistic detection-limit value rather than zero.
No coupled flow. This skill runs batch equilibrium. Real produced water changes composition as it flows through pipe, heat exchangers, and tanks. For design work, couple to a reactive-transport code (PhreeqcRM, PHT3D) or commercial OLI / Multiflash.
Commercial-software comparison. OLI Studio and Multiflash use proprietary parameter sets that can disagree with PHREEQC Pitzer by 0.2-0.5 log units on SI at hypersaline conditions. Use PHREEQC for screening and open-science work; expect a commercial cross-check before capex decisions.
bash_tool to shell out to phreeqc; parse the TSV
SELECTED_OUTPUT rather than the long .pqo for machine use.references/golang_wrapper.go for a reference
implementation: runs the binary, reads the .sel file, returns a typed
struct with SIs and key molalities.references/thermo_databases.md for the full
matrix of which database to use at which ionic strength, element coverage,
and known limitations.references/brine_recipes.md for sample
input decks for Smackover, Marcellus, Utica/Point Pleasant, and Bakken
chemistries with typical Li/Mg/Ca/Sr/Ba/Cl/SO4 values. Use these as
starting points and overwrite with sample-specific numbers.~/.config/phreeqc/config so repeated runs skip the find step.pitzer.dat;
otherwise default to phreeqc.dat.Windows-style paths; resolve via env var or shell
find.npx claudepluginhub jpfielding/claude.pnge --plugin pnge-geochem-pwProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.