Skip to content

Commit

Permalink
Documentation overhaul
Browse files Browse the repository at this point in the history
Documentation overhaul part 1
  • Loading branch information
rkingsbury authored Aug 14, 2023
2 parents 00ed21f + 9ff1ed6 commit 0003ee4
Show file tree
Hide file tree
Showing 35 changed files with 1,625 additions and 1,225 deletions.
7 changes: 6 additions & 1 deletion .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
# Required
version: 2

# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.10"

# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
Expand All @@ -17,6 +23,5 @@ formats:
- pdf

python:
version: 3.8
install:
- requirements: docs/requirements.txt
59 changes: 37 additions & 22 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,53 @@
# pyEQL Changelog

## 0.6.0 (in progress)
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- **BREAKING CHANGE** `Solute`: methods `get_formal_charge()`, `get_name()`, and `get_molecular_weight()` have been
replaced by direct access to the attributes `charge`, `formula`, and `mw`, respectively.
- **DEPRECATION NOTICE** `Solution`: new properties `pressure`, `temperature`, `pE`,
- `pH`, `mass`, `density`, `viscosity_dynamic`, `viscosity_kinematic`, `ionic_strength`,
- `conductivity`, `debye_length`, `bjerrum_length`, `alkalinity`, `hardness`,
- `dielectric_constant`, `charge_balance` have replaced the corresponding get_XXX and
set_XXX (for temperature and pressure) methods, which will be removed in a future
release. `get_viscosity_relative` will be removed entirely.
- `Solution`: add support for passing solutes as a `dict`
- Implement extensible system for connecting `Solution` to various activity and speciation
models. Models can be integrated into pyEQL by implementing an `EOS` class. The desired
activity model is selected on init. Currently available models are `native` (for pyEQL's
implementation of Pitzer, which decays gracefully into Debye-Huckel and other models if
parameters are not available) or `ideal` for a dummy engine that returns unit activity
coefficients. Support for additional external engines such as [`phreeqpython`](https://github.com/Vitens/phreeqpython) is planned.
- **BREAKING CHANGE** disable 'verbose' kwarg in `get_activity` and `get_activity_coefficient`
- Add `pymatgen`, `monty`, and `maggma` as dependencies
- Add pre-commit configuration and lint with `ruff`
- Add more comprehensive platform testing via `tox`

### Changed

- Replace `water_properties.py` with [iapws](https://github.com/jjgomera/iapws) package
- Replace elements.py with `pymatgen.core.periodic_table`
- Add `pymatgen` as a dependency
- Replace `elements.py`` with `pymatgen.core.periodic_table`
- Migrate all tests to `pytest`
- Add pre-commit configuration and lint with `black`
- Update packaging to use [pyscaffold](https://pyscaffold.org/en/stable/index.html)
- Update packaging format to use [pyscaffold](https://pyscaffold.org/en/stable/index.html)

### Deprecated

- `Solution`: new properties `pressure`, `temperature`, `pE`, `pH`, `mass`, `density`, `viscosity_dynamic`, `viscosity_kinematic`, `ionic_strength`, `conductivity`, `debye_length`, `bjerrum_length`, `alkalinity`, `hardness`, `dielectric_constant`, `charge_balance` have replaced the corresponding get_XXX and set_XXX (for temperature and pressure) methods, which will be removed in a future release. `get_viscosity_relative` will be removed entirely.
- `Solute`: methods `get_formal_charge()`, `get_name()`, and `get_molecular_weight()` have been
replaced by direct access to the attributes `charge`, `formula`, and `mw`, respectively.

### Removed

- disable 'verbose' kwarg in `get_activity` and `get_activity_coefficient`

### Fixed

- Fixed various documentation rendering issues

## 0.5.2 (2020-04-21)
## [0.5.2] - 2020-04-21

- Fix breaking bug introduced by upstream pint change to avogadro_number
- Format project with black
- Misc. linting and docstring changes

## 0.5.0 (2018-09-19)
## [0.5.0] 2018-09-19

- Implement the effective Pitzer model for improved activity calculations in multicomponent solutions
- Add support for calculation of activity and osmotic coefficients on different scales
Expand All @@ -46,7 +61,7 @@
- DEPRECATED get_mole_fraction. Use get_amount() instead
- Fix bug causing get_activity_coefficient to fail if the solute concentration was zero

## 0.4.0 (2016-07-14)
## [0.4.0] 2016-07-14

- Add ability to calculate dielectric constant based on solution composition for salts
- Add database entries for the viscosity 'B' parameter for 63 more inorganic ions
Expand All @@ -59,12 +74,12 @@
- Fix bug causing ValueError exceptions when a solute has zero concentration
- Numerous fixes and corrections in the documentation

## 0.3.1 (2016-02-24)
## [0.3.1] 2016-02-24

- Fix packaging problems preventing installation from PyPi
- Fix character encoding issue in Erying_viscosity database file

## 0.3.0 (2016-01-15)
## [0.3.0] 2016-01-15

- Add method to calculate the total concentration of an element in a solution
- Add method to automatically generate certain solutions (like seawater)
Expand All @@ -81,11 +96,11 @@
- Fix bug related to retrieval of water properties
- Documentation enhancements and fixes

## 0.2.2 (2015-08-28)
## [0.2.2] 2015-08-28

- Fix bug in get_amount() causing no output when mass-based units were specified.

## 0.2.1 (2015-05-06)
## [0.2.1] 2015-05-06

- Add 93 entries to diffusion coefficient database
- Add 93 entries to Pitzer partial molar volume parameters database
Expand All @@ -95,6 +110,6 @@
- Uploaded to the Python Package Index for easier installation
- Add this changelog

## 0.2.0 (2015-03-26)
## [0.2.0] 2015-03-26

- First public release
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[![testing](https://github.com/rkingsbury/pyeql/workflows/testing/badge.svg)](https://github.com/rkingsbury/pyeql/actions?query=workflow%3Atesting) [![codecov](https://codecov.io/gh/rkingsbury/pyeql/branch/main/graph/badge.svg?token=I7RP0QML6S)](https://codecov.io/gh/rkingsbury/pyeql)
[![testing](https://github.com/rkingsbury/pyeql/workflows/testing/badge.svg)](https://github.com/rkingsbury/pyeql/actions?query=workflow%3Atesting)
[![codecov](https://codecov.io/gh/rkingsbury/pyeql/branch/main/graph/badge.svg?token=I7RP0QML6S)](https://codecov.io/gh/rkingsbury/pyeql)
![Supported python versions](https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10%20%7C%203.11-blue)

# pyEQL

Expand Down
56 changes: 56 additions & 0 deletions docs/chemistry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
(chemistry)=

# Chemical Formulas

pyEQL interprets the chemical formula of a substance to calculate its molecular
weight and formal charge. The formula is also used as a key to search the
database for parameters (e.g. diffusion coefficient) that are used in subsequent
calculations.

## How to Enter Valid Chemical Formulas

Generally speaking, type the chemical formula of your solute the "normal" way
and `pyEQL` should be able to inerpret it. Internally, `pyEQL` uses the [`pymatgen.core.ion.Ion`](https://pymatgen.org/pymatgen.core.html#pymatgen.core.ion.Ion)
class to "translate" chemical formulas into a consistent format. Anything that the `Ion` class can understand will
be processed into a valid formula by `pyEQL`.

Here are some examples:

| Substance | You enter | `pyEQL` understands |
| :--- | :---: | :---: |
| Sodium Chloride | "NaCl", "NaCl(aq)", or "ClNa" | "NaCl(aq)" |
| Sodium Sulfate | "Na(SO4)2" or "NaS2O8" | "Na(SO4)2(aq)" |
| Sodium Ion | "Na+", "Na+1", "Na1+", or "Na[+]" | "Na[+1]" |
| Magnesium Ion | "Mg+2", "Mg++", or "Mg[++]" | "Mg[+2]" |
| Methanol | "CH3OH", "CH4O" | "'CH3OH(aq)'" |

Specifically, `pyEQL` uses `Ion.from_formula(<formula>).reduced_formla` (shown in the right hand column of the table) to
identify solutes. Notice that for charged species, the charges are always placed inside square brackets (e.g., `Na[+1]`)
and always include the charge number (even for monovalent ions). Uncharged species are always suffixed by `(aq)` to
disambiguate them from solids.

:::{important}
**When writing multivalent ion formulas, it is strongly recommended that you put the charge number AFTER the + or -
sign** (e.g., type "Mg+2" NOT "Mg2+"). The latter formula is ambiguous - it could mean $`Mg_2^+`$ or $`Mg^{+2}`$
:::

(manual-testing)=
## Manually testing a formula

If you want to make sure `pyEQL` is understanding your formula correctly, you can manually test it via `pymatgen` as
follows:

```
>>> from pymatgen.core.ion import Ion
>>> Ion.from_formula(<your_formula>).reduced_formula
...
```

## Formulas you will see when using `Solution`

When using the `Solution` class,

- When creating a `Solution`, you can enter chemical formulas in any format you prefer, as long as `pymatgen` can understand it (see [manual testing](#manually-testing-a-formula)).
- The keys (solute formulas) in `Solution.components` are preserved in the same format the user enters them. So if you entered `Na+` for sodium ion, it will stay that way.
- Arguments to `Solution.get_property` can be entered in any format you prefer. When `pyEQL` queries the database, it will automatically convert the formula to the canonical one from `pymatgen`
- Property data in the database is uniquely identified by the canonical ion formula (output of `Ion.from_formula(<formula>).reduced_formla`, e.g. "Na[+1]" for sodium ion).
58 changes: 0 additions & 58 deletions docs/chemistry.rst

This file was deleted.

7 changes: 0 additions & 7 deletions docs/class_solute.rst

This file was deleted.

80 changes: 80 additions & 0 deletions docs/class_solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
(class-solution)=

# The Solution Class

The `Solution` class defines a pythonic interface for **creating**, **modifying**, and **estimating properties** of
electrolyte solutions. It is the core feature of `pyEQL` and the primary user-facing class.

## Creating a solution

A `Solution` created with no arguments will default to pure water at pH=7, T=25 degrees Celsius, and 1 atm pressure.

```
>>> from pyEQL import Solution
>>> s1 = Solution()
>>> s1.pH
6.998877352386266
```

Alternatively, you can use the `autogenerate()` function to easily create common solutions like seawater:

```
>>> from pyEQL.functions import autogenerate
>>> s2 = autogenerate('seawater')
<pyEQL.solution.Solution object at 0x7f057de6b0a0>
```

You can inspect the solutes present in the solution via the `components` attribute. This comprises a dictionary of solute formula: moles, where 'moles' is the number of moles of that solute in the `Solution`. Note that the solvent (water) is present in `components`, too.

```
>>> s2.components
{'H2O': 55.34455401423017,
'H+': 7.943282347242822e-09,
'OH-': 8.207436858780226e-06,
'Na+': 0.46758273714962967,
'Mg+2': 0.052661180523467986,
'Ca+2': 0.010251594148212318,
'K+': 0.010177468379526856,
'Sr+2': 9.046483353663286e-05,
'Cl-': 0.54425785619973,
'SO4-2': 0.028151873448454025,
'HCO3-': 0.001712651176926199,
'Br-': 0.0008395244921424563,
'CO3-2': 0.00023825904349479546,
'B(OH)4': 0.0001005389715937341,
'F-': 6.822478260456777e-05,
'B(OH)3': 0.0003134669156396757,
'CO2': 9.515218476861175e-06
}
```

To get the amount of a specific solute, use `get_amount()` and specify the units you want:

```
>>> s2.get_amount('Na+', 'g/L')
<Quantity(10.6636539, 'gram / liter')>
```

Finally, you can manually create a solution with any list of solutes, temperature, pressure, etc. that you need:

```
>>> from pyEQL import Solution
>>> s1 = Solution(solutes={'Na+':'0.5 mol/kg', 'Cl-': '0.5 mol/kg'},
pH=8,
temperature = '20 degC',
volume='8 L'
)
```

## Class reference

The remainder of this page contains detailed information on each of the methods, attributes, and properties in `Solution`. Use the sidebar on the right for easier navigation.

```{eval-rst}
.. autoclass:: pyEQL.Solution
:members:
:inherited-members:
:private-members: _get_property
:special-members: __init__
:member-order: bysource
```
7 changes: 0 additions & 7 deletions docs/class_solution.rst

This file was deleted.

Loading

0 comments on commit 0003ee4

Please sign in to comment.