Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Documentation
on:
push:
branches:
- master
- main
permissions:
contents: read
pages: write
id-token: write
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/configure-pages@v6
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: 3.x
- run: pip install zensical mkdocstrings-python markdown-exec
- run: zensical build --clean
- uses: actions/upload-pages-artifact@v5
with:
path: site
- uses: actions/deploy-pages@v5
id: deployment
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@
#*.dll
*.DS_Store

# Setuptools distribution folder.
# Setuptools build and distribution folders.
/dist/
/build/

# Python egg metadata, regenerated from source files by setuptools
/*.egg-info

# Jupyter notebook
testing.ipynb
.ipynb_checkpoints/
.coverage

.vscode/*
dump.gz

.venv
/site/
74 changes: 74 additions & 0 deletions convertnb.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Convert notebooks\n",
"Read notebooks and convert to html."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from mkdocs_jupyter import nbconvert2\n",
"import os"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"nbdir = \"docs\\\\notebooks\\\\\"\n",
"notebooks = [file for file in os.listdir(nbdir) if file.endswith(\"ipynb\")]"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"targetdir = \"docs\\\\nb_html\\\\\"\n",
"for notebook in notebooks:\n",
" content = nbconvert2.nb2html(nb_path=nbdir + notebook)\n",
" target = targetdir + notebook.replace(\".ipynb\", \".html\") \n",
" with open(target, \"w\", encoding=\"utf-8\") as f:\n",
" f.write(content) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv (3.12.6)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.6"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
4 changes: 0 additions & 4 deletions docs/README.md

This file was deleted.

19 changes: 19 additions & 0 deletions docs/examples/aluminium-limit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
icon: lucide/beaker
---

# Aluminium drinking-water limit

Al concentration exceeds a 0.2 mg/kgw drinking-water limit at low and high pH, after [Appelo's aluminium example](http://hydrochemistry.eu/exmpls/al_conc.html). The pH values below are where that Al total is in equilibrium with gibbsite.

???+ info "You can run these examples"

Click **Run** (or Ctrl+Enter).

```pyodide session="al" height="8-12" install="../../wheels/phreeqpython-1.6.2+pyodide-py3-none-any.whl"
from phreeqpython import PhreeqPython

pp = PhreeqPython('phreeqc.dat')
print('Lower limit pH', pp.add_solution({'Al': '0.2 mg/kgw', 'pH': '4 Gibbsite'}).pH)
print('Upper limit pH', pp.add_solution({'Al': '0.2 mg/kgw', 'pH': '8 Gibbsite'}).pH)
```
57 changes: 57 additions & 0 deletions docs/examples/ca-f-fluorite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
icon: lucide/beaker
---

# Ca–F equilibrium with fluorite

The relation between fluoride and calcium in water, after [Appelo's fluorite example](http://hydrochemistry.eu/exmpls/ca_f.html). Calcite and fluorite stay at equilibrium while albite dissolves.

???+ info "You can run these examples"

Click **Run** (or Ctrl+Enter), or **Run all** to execute every editor in order. Editors on this page **share a session**.

```pyodide session="caf" height="18-28" install="matplotlib,numpy,../../wheels/phreeqpython-1.6.2+pyodide-py3-none-any.whl"
from phreeqpython import PhreeqPython
import matplotlib.pyplot as plt

pp = PhreeqPython()
solution1 = pp.add_solution({
'pH': '7 charge',
'C': '1 CO2(g) -1',
'Ca': '1 Calcite',
'F': '1 Fluorite',
})

x, y, yy = [], [], []

for i in range(16):
x.append(solution1.total_element('Ca', 'mg'))
y.append(solution1.total_element('F', 'mg'))
yy.append(solution1.pH)
solution1.add('NaAlSi3O8', 7.5 / 15)
solution1.equalize(
['Fluorite', 'Calcite', 'Quartz', 'Kaolinite'],
['', '', 0, 0],
['', '', 0, 0],
)

print('points', len(x), 'final pH', round(yy[-1], 2))
```

```pyodide session="caf" height="14-22" install="matplotlib,numpy,../../wheels/phreeqpython-1.6.2+pyodide-py3-none-any.whl"
fig = plt.figure(figsize=[10, 5])
ax = plt.gca()
ax2 = ax.twinx()
ax.plot(x, y, 'rs-', label='F')
ax2.plot(x, yy, 'gd-', label='pH')
ax.set_ylim([0, 10])
ax.set_xlim([0, 160])
ax2.set_ylim([6.5, 7.5])
ax.set_xlabel('Ca (mg/l)')
ax.set_ylabel('F (mg/l)')
ax2.set_ylabel('pH (-)')
ax.grid()
plt.title('Fluorite equilibrium during Na-feldspar dissolution')
fig.legend(loc=1, bbox_to_anchor=(1, 1), bbox_transform=ax.transAxes)
show_plot(fig)
```
54 changes: 54 additions & 0 deletions docs/examples/calcite-dissolution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
icon: lucide/beaker
---

# Calcite dissolution

Calcite dissolution as a function of CO₂ pressure, after [Appelo's calcite example](http://hydrochemistry.eu/exmpls/calcite.html). Equilibrium along a CO₂ titration is compared with mixing two end members.

???+ info "You can run these examples"

Click **Run** (or Ctrl+Enter), or **Run all** to execute every editor in order. Editors on this page **share a session**.

!!! warning "Changes are additive"

The loop adds CO₂ to `solution0` in place. Run it once. To start over, rerun from the first editor.

```pyodide session="calcite" height="16-24" install="matplotlib,numpy,../../wheels/phreeqpython-1.6.2+pyodide-py3-none-any.whl"
from phreeqpython import PhreeqPython
import matplotlib.pyplot as plt

pp = PhreeqPython(database='phreeqc.dat')

solution0 = pp.add_solution({})
solution1 = pp.add_solution({}).equalize(['Calcite', 'CO2(g)'], [0, -1.7])
solution2 = pp.add_solution({}).equalize(['Calcite', 'CO2(g)'], [0, -3.5])
solution3 = solution1 * 0.5 + solution2 * 0.5

x, y = [], []
for i in range(30):
solution0.add('CO2', 3.5 / 30)
solution0.saturate('Calcite')
x.append(solution0.sr('CO2(g)') * 100)
y.append(solution0.total_element('Ca'))

print('points', len(x))
```

```pyodide session="calcite" height="12-18" install="matplotlib,numpy,../../wheels/phreeqpython-1.6.2+pyodide-py3-none-any.whl"
fig = plt.figure(figsize=[7, 7])
plt.plot(x, y, 'rs-', label='equilibrium')
plt.plot(
[solution1.sr('CO2(g)') * 1e2, solution2.sr('CO2(g)') * 1e2],
[solution1.total_element('Ca'), solution2.total_element('Ca')],
'-gx',
label='mixing line',
)
plt.plot(solution3.sr('CO2(g)') * 1e2, solution3.total_element('Ca'), '-b^', label='1:1')
plt.xlim([0, 3])
plt.ylim([0, 3])
plt.grid()
plt.legend()
plt.title('Calcite equilibrium')
show_plot(fig)
```
52 changes: 52 additions & 0 deletions docs/examples/carbonic-acid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
icon: lucide/beaker
---

# Carbonic acid equilibrium

Carbonic acid (H₂CO₃), bicarbonate (HCO₃⁻) and carbonate (CO₃²⁻) form in water through:

- CO₂ + H₂O ⇌ H₂CO₃
- H₂CO₃ ⇌ HCO₃⁻ + H⁺
- HCO₃⁻ ⇌ CO₃²⁻ + H⁺

The distribution depends on pH. This example titrates 1 mmol NaHCO₃ from pH 0 to 14.

???+ info "You can run these examples"

Click **Run** (or Ctrl+Enter), or **Run all** to execute every editor in order. Editors on this page **share a session**. The loop has many pH steps and can take a short while in the browser.

```pyodide session="carbonic" height="8-14" install="matplotlib,numpy,../../wheels/phreeqpython-1.6.2+pyodide-py3-none-any.whl"
from phreeqpython import PhreeqPython
import numpy as np
import matplotlib.pyplot as plt

pp = PhreeqPython()
solution = pp.add_solution_simple({'NaHCO3': 1.0})
print('pH {:.2f}, SC {:.2f} uS/cm'.format(solution.pH, solution.sc))
```

!!! warning "Changes are additive"

`change_ph` doses acid or base **into the same solution**. Run the loop once. To start over, rerun the first editor.

```pyodide session="carbonic" height="14-22" install="matplotlib,numpy,../../wheels/phreeqpython-1.6.2+pyodide-py3-none-any.whl"
phs, co2, hco3, co3 = [], [], [], []

for pH in np.arange(0, 14.1, 0.2):
solution.change_ph(pH)
phs.append(pH)
co2.append(solution.total('CO2') * 1000)
hco3.append(solution.total('HCO3') * 1000)
co3.append(solution.total('CO3') * 1000)

fig = plt.figure(figsize=[10, 5])
plt.plot(phs, co2, label='CO2')
plt.plot(phs, hco3, label='HCO3-')
plt.plot(phs, co3, label='CO3-2')
plt.xlabel('pH')
plt.ylabel('Concentration (mmol)')
plt.title('Carbonic acid, bicarbonate, carbonate')
plt.legend()
show_plot(fig)
```
Loading
Loading