pyEQL 1.0.3__tar.gz → 1.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyeql-1.0.3 → pyeql-1.1.1}/.github/dependabot.yml +5 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.pre-commit-config.yaml +5 -5
- {pyeql-1.0.3 → pyeql-1.1.1}/CHANGELOG.md +25 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/MANIFEST.in +0 -1
- {pyeql-1.0.3/src/pyEQL.egg-info → pyeql-1.1.1}/PKG-INFO +3 -3
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/changelog.md +25 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/pyproject.toml +2 -3
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/__init__.py +1 -4
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/database/pyeql_db.json +2 -2
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/engines.py +39 -34
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/solution.py +25 -84
- {pyeql-1.0.3 → pyeql-1.1.1/src/pyEQL.egg-info}/PKG-INFO +3 -3
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL.egg-info/SOURCES.txt +0 -1
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL.egg-info/requires.txt +1 -1
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_solution.py +32 -10
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_volume_concentration.py +7 -0
- pyeql-1.0.3/src/pyEQL/pint_custom_units.txt +0 -52
- {pyeql-1.0.3 → pyeql-1.1.1}/.coveragerc +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.gitattributes +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.github/pull_request_template.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.github/release.yml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.github/workflows/post-process.yml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.github/workflows/release.yml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.github/workflows/testing.yaml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.github/workflows/upgrade_dependencies.yml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.gitignore +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.readthedocs.yml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/.zenodo.json +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/AUTHORS.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/CITATION.cff +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/COPYING +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/LICENSE.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/README.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/Makefile +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/_static/.gitignore +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/amounts.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/arithmetic.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/authors.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/chemistry.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/class_solution.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/conf.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/contributing.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/creating.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/database.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/engines.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/.ipynb_checkpoints/pyEQL_demo_1-checkpoint.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/.ipynb_checkpoints/pyeql_demo-checkpoint.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/.ipynb_checkpoints/pyeql_tutorial_database-checkpoint.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/.ipynb_checkpoints/pyeql_tutorial_osmotic_pressure-checkpoint.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/.ipynb_checkpoints/speedup-checkpoint.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/pyEQL_demo_1.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/pyeql_demo.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/pyeql_tutorial_database.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/pyeql_tutorial_osmotic_pressure.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/examples/speedup.ipynb +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/index.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/installation.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/internal.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/license.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/mixing.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/quickstart.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/readme.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/requirements.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/serialization.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/tutorials.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/docs/units.md +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/pyeql-logo.png +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/pyeql-logo.svg +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/macos-latest_py3.10.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/macos-latest_py3.10_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/macos-latest_py3.11.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/macos-latest_py3.11_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/macos-latest_py3.12.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/macos-latest_py3.12_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/macos-latest_py3.9.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/macos-latest_py3.9_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/ubuntu-latest_py3.10.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/ubuntu-latest_py3.10_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/ubuntu-latest_py3.11.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/ubuntu-latest_py3.11_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/ubuntu-latest_py3.12.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/ubuntu-latest_py3.12_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/ubuntu-latest_py3.9.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/ubuntu-latest_py3.9_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/windows-latest_py3.10.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/windows-latest_py3.10_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/windows-latest_py3.11.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/windows-latest_py3.11_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/windows-latest_py3.12.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/windows-latest_py3.12_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/windows-latest_py3.9.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/requirements/windows-latest_py3.9_extras.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/setup.cfg +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/setup.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/activity_correction.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/database/geothermal.dat +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/database/llnl.dat +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/database/phreeqc_license.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/equilibrium.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/functions.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/presets/Ringers lactate.yaml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/presets/normal saline.yaml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/presets/rainwater.yaml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/presets/seawater.yaml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/presets/urine.yaml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/presets/wastewater.yaml +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/salt_ion_match.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/solute.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL/utils.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL.egg-info/dependency_links.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/src/pyEQL.egg-info/top_level.txt +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/conftest.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_activity.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_bulk_properties.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_debye_length.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_density.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_dielectric.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_effective_pitzer.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_equilibrium.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_functions.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_logging.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_mixed_electrolyte_activity.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_osmotic_coeff.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_phreeqc.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_salt_matching.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_solute.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_solute_properties.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tests/test_utils.py +0 -0
- {pyeql-1.0.3 → pyeql-1.1.1}/tox.ini +0 -0
|
@@ -12,18 +12,18 @@ ci:
|
|
|
12
12
|
|
|
13
13
|
repos:
|
|
14
14
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
15
|
-
rev: v0.
|
|
15
|
+
rev: v0.5.5
|
|
16
16
|
hooks:
|
|
17
17
|
- id: ruff
|
|
18
18
|
args: [--fix, --ignore, "D,E501", "--show-fixes"]
|
|
19
19
|
|
|
20
|
-
- repo: https://github.com/psf/black
|
|
21
|
-
rev: 24.2
|
|
20
|
+
- repo: https://github.com/psf/black-pre-commit-mirror
|
|
21
|
+
rev: 24.4.2
|
|
22
22
|
hooks:
|
|
23
23
|
- id: black
|
|
24
24
|
|
|
25
25
|
- repo: https://github.com/codespell-project/codespell
|
|
26
|
-
rev: v2.
|
|
26
|
+
rev: v2.3.0
|
|
27
27
|
hooks:
|
|
28
28
|
- id: codespell
|
|
29
29
|
stages: [commit, commit-msg]
|
|
@@ -31,7 +31,7 @@ repos:
|
|
|
31
31
|
additional_dependencies: [tomli] # needed to read pyproject.toml below py3.11
|
|
32
32
|
|
|
33
33
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
34
|
-
rev: v4.
|
|
34
|
+
rev: v4.6.0
|
|
35
35
|
hooks:
|
|
36
36
|
- id: check-case-conflict
|
|
37
37
|
- id: check-symlinks
|
|
@@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.1] - 2024-07-27
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- `equilibrate`: Fixed a bug that could cause an `AttributeError` when pH was used for charge
|
|
13
|
+
balancing.
|
|
14
|
+
- Database: `size.radius_ionic` was missing units for `Ni[+2]` and `Cr[+3]`. Correct units have been added.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `Solution`: New automatic charge balancing method will automatically identify the majority (highest concentration)
|
|
19
|
+
cation or anion as appropriate (depending on the charge balance) for charge balancing. To use this mode, set
|
|
20
|
+
`balance_charge='auto'` when instantiating a `Solution`.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- `Solution.add_amount`: This method will now add solutes that are absent from the Solution. Previously, calling, e.g.,
|
|
25
|
+
`add_amount('Na+', '1 mol')` on a `Solution` that did not contain any sodium would result in an error. A warning
|
|
26
|
+
is logged if the method has to add a new solute.
|
|
27
|
+
- Units: use the upstream chemistry context from `pint` instead of the custom one from 2013.
|
|
28
|
+
- `pre-commit autoupdate`
|
|
29
|
+
- Misc. linting and code quality improvements.
|
|
30
|
+
- Unit tests: update `tmpdir` to `tmp_path` text fixture.
|
|
31
|
+
- CI: Small updates to pre-commit and GitHub actions per scientific python [repo review](https://scientific-python.github.io/repo-review/?repo=kingsburylab%2FpyEQL&branch=main).
|
|
32
|
+
|
|
8
33
|
## [1.0.3] - 2024-07-20
|
|
9
34
|
|
|
10
35
|
### Fixed
|
|
@@ -2,6 +2,5 @@ include README COPYING CHANGELOG LICENSE README.md README.rst README.txt CHANGES
|
|
|
2
2
|
recursive-include src/pyEQL/database/ *
|
|
3
3
|
recursive-include src/pyEQL/presets/ *
|
|
4
4
|
recursive-include docs/ *
|
|
5
|
-
include src/pyEQL/pint_custom_units.txt
|
|
6
5
|
prune docs/build
|
|
7
6
|
global-exclude *.pyc *~ .DS_Store *__pycache__* *.pyo
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyEQL
|
|
3
|
-
Version: 1.
|
|
4
|
-
Summary: A python
|
|
3
|
+
Version: 1.1.1
|
|
4
|
+
Summary: A python interface for solution chemistry
|
|
5
5
|
Author-email: Ryan Kingsbury <kingsbury@princeton.edu>
|
|
6
6
|
Project-URL: Docs, https://pyeql.readthedocs.io/
|
|
7
7
|
Project-URL: Repo, https://github.com/KingsburyLab/pyEQL
|
|
@@ -25,7 +25,7 @@ Requires-Dist: numpy<2
|
|
|
25
25
|
Requires-Dist: scipy
|
|
26
26
|
Requires-Dist: pymatgen==2024.5.1
|
|
27
27
|
Requires-Dist: iapws
|
|
28
|
-
Requires-Dist: monty
|
|
28
|
+
Requires-Dist: monty>=2024.7.12
|
|
29
29
|
Requires-Dist: maggma>=0.67.0
|
|
30
30
|
Requires-Dist: phreeqpython
|
|
31
31
|
Provides-Extra: testing
|
|
@@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.1] - 2024-07-27
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- `equilibrate`: Fixed a bug that could cause an `AttributeError` when pH was used for charge
|
|
13
|
+
balancing.
|
|
14
|
+
- Database: `size.radius_ionic` was missing units for `Ni[+2]` and `Cr[+3]`. Correct units have been added.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- `Solution`: New automatic charge balancing method will automatically identify the majority (highest concentration)
|
|
19
|
+
cation or anion as appropriate (depending on the charge balance) for charge balancing. To use this mode, set
|
|
20
|
+
`balance_charge='auto'` when instantiating a `Solution`.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- `Solution.add_amount`: This method will now add solutes that are absent from the Solution. Previously, calling, e.g.,
|
|
25
|
+
`add_amount('Na+', '1 mol')` on a `Solution` that did not contain any sodium would result in an error. A warning
|
|
26
|
+
is logged if the method has to add a new solute.
|
|
27
|
+
- Units: use the upstream chemistry context from `pint` instead of the custom one from 2013.
|
|
28
|
+
- `pre-commit autoupdate`
|
|
29
|
+
- Misc. linting and code quality improvements.
|
|
30
|
+
- Unit tests: update `tmpdir` to `tmp_path` text fixture.
|
|
31
|
+
- CI: Small updates to pre-commit and GitHub actions per scientific python [repo review](https://scientific-python.github.io/repo-review/?repo=kingsburylab%2FpyEQL&branch=main).
|
|
32
|
+
|
|
8
33
|
## [1.0.3] - 2024-07-20
|
|
9
34
|
|
|
10
35
|
### Fixed
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name = "pyEQL"
|
|
3
3
|
readme = "README.md"
|
|
4
4
|
dynamic = ["version"]
|
|
5
|
-
description="A python
|
|
5
|
+
description="A python interface for solution chemistry"
|
|
6
6
|
authors =[
|
|
7
7
|
{name = "Ryan Kingsbury", email = "kingsbury@princeton.edu"}
|
|
8
8
|
]
|
|
@@ -25,7 +25,7 @@ dependencies = [
|
|
|
25
25
|
"scipy",
|
|
26
26
|
"pymatgen==2024.5.1",
|
|
27
27
|
"iapws",
|
|
28
|
-
"monty",
|
|
28
|
+
"monty>=2024.7.12",
|
|
29
29
|
"maggma>=0.67.0",
|
|
30
30
|
"phreeqpython",
|
|
31
31
|
]
|
|
@@ -72,7 +72,6 @@ version_scheme = "no-guess-dev"
|
|
|
72
72
|
line-length = 120
|
|
73
73
|
|
|
74
74
|
[tool.ruff]
|
|
75
|
-
target-version = "py39"
|
|
76
75
|
line-length = 120
|
|
77
76
|
exclude = [".dat"]
|
|
78
77
|
src = ["src"]
|
|
@@ -37,11 +37,8 @@ ureg = UnitRegistry(cache_folder=":auto:")
|
|
|
37
37
|
# convert "offset units" so that, e.g. Quantity('25 degC') works without error
|
|
38
38
|
# see https://pint.readthedocs.io/en/0.22/user/nonmult.html?highlight=offset#temperature-conversion
|
|
39
39
|
ureg.autoconvert_offset_to_baseunit = True
|
|
40
|
-
# append custom unit definitions and contexts
|
|
41
|
-
fname = files("pyEQL") / "pint_custom_units.txt"
|
|
42
|
-
ureg.load_definitions(fname)
|
|
43
40
|
# activate the "chemistry" context globally
|
|
44
|
-
ureg.enable_contexts("
|
|
41
|
+
ureg.enable_contexts("chemistry")
|
|
45
42
|
# set the default string formatting for pint quantities
|
|
46
43
|
ureg.default_format = "P~"
|
|
47
44
|
|
|
@@ -6698,7 +6698,7 @@
|
|
|
6698
6698
|
"n_elements": 1,
|
|
6699
6699
|
"size": {
|
|
6700
6700
|
"radius_ionic": {
|
|
6701
|
-
"value": "0.755",
|
|
6701
|
+
"value": "0.755 Å",
|
|
6702
6702
|
"reference": "pymatgen",
|
|
6703
6703
|
"data_type": "experimental"
|
|
6704
6704
|
},
|
|
@@ -24663,7 +24663,7 @@
|
|
|
24663
24663
|
"n_elements": 1,
|
|
24664
24664
|
"size": {
|
|
24665
24665
|
"radius_ionic": {
|
|
24666
|
-
"value": "0.83",
|
|
24666
|
+
"value": "0.83 Å",
|
|
24667
24667
|
"reference": "pymatgen",
|
|
24668
24668
|
"data_type": "experimental"
|
|
24669
24669
|
},
|
|
@@ -11,7 +11,7 @@ import os
|
|
|
11
11
|
import warnings
|
|
12
12
|
from abc import ABC, abstractmethod
|
|
13
13
|
from pathlib import Path
|
|
14
|
-
from typing import Literal
|
|
14
|
+
from typing import TYPE_CHECKING, Literal
|
|
15
15
|
|
|
16
16
|
from phreeqpython import PhreeqPython
|
|
17
17
|
|
|
@@ -26,6 +26,9 @@ SPECIAL_ELEMENTS = ["S", "C", "N", "Cu", "Fe", "Mn"]
|
|
|
26
26
|
|
|
27
27
|
logger = logging.getLogger(__name__)
|
|
28
28
|
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from pyEQL import Solution
|
|
31
|
+
|
|
29
32
|
|
|
30
33
|
class EOS(ABC):
|
|
31
34
|
"""
|
|
@@ -38,7 +41,7 @@ class EOS(ABC):
|
|
|
38
41
|
"""
|
|
39
42
|
|
|
40
43
|
@abstractmethod
|
|
41
|
-
def get_activity_coefficient(self, solution, solute):
|
|
44
|
+
def get_activity_coefficient(self, solution: "Solution", solute: str) -> ureg.Quantity:
|
|
42
45
|
"""
|
|
43
46
|
Return the *molal scale* activity coefficient of solute, given a Solution
|
|
44
47
|
object.
|
|
@@ -55,7 +58,7 @@ class EOS(ABC):
|
|
|
55
58
|
"""
|
|
56
59
|
|
|
57
60
|
@abstractmethod
|
|
58
|
-
def get_osmotic_coefficient(self, solution):
|
|
61
|
+
def get_osmotic_coefficient(self, solution: "Solution") -> ureg.Quantity:
|
|
59
62
|
"""
|
|
60
63
|
Return the *molal scale* osmotic coefficient of a Solution.
|
|
61
64
|
|
|
@@ -70,7 +73,7 @@ class EOS(ABC):
|
|
|
70
73
|
"""
|
|
71
74
|
|
|
72
75
|
@abstractmethod
|
|
73
|
-
def get_solute_volume(self):
|
|
76
|
+
def get_solute_volume(self, solution: "Solution") -> ureg.Quantity:
|
|
74
77
|
"""
|
|
75
78
|
Return the volume of only the solutes.
|
|
76
79
|
|
|
@@ -85,7 +88,7 @@ class EOS(ABC):
|
|
|
85
88
|
"""
|
|
86
89
|
|
|
87
90
|
@abstractmethod
|
|
88
|
-
def equilibrate(self, solution):
|
|
91
|
+
def equilibrate(self, solution: "Solution") -> None:
|
|
89
92
|
"""
|
|
90
93
|
Adjust the speciation and pH of a Solution object to achieve chemical equilibrium.
|
|
91
94
|
|
|
@@ -105,25 +108,25 @@ class EOS(ABC):
|
|
|
105
108
|
class IdealEOS(EOS):
|
|
106
109
|
"""Ideal solution equation of state engine."""
|
|
107
110
|
|
|
108
|
-
def get_activity_coefficient(self, solution, solute):
|
|
111
|
+
def get_activity_coefficient(self, solution: "Solution", solute: str) -> ureg.Quantity:
|
|
109
112
|
"""
|
|
110
113
|
Return the *molal scale* activity coefficient of solute, given a Solution
|
|
111
114
|
object.
|
|
112
115
|
"""
|
|
113
116
|
return ureg.Quantity(1, "dimensionless")
|
|
114
117
|
|
|
115
|
-
def get_osmotic_coefficient(self, solution):
|
|
118
|
+
def get_osmotic_coefficient(self, solution: "Solution") -> ureg.Quantity:
|
|
116
119
|
"""
|
|
117
120
|
Return the *molal scale* osmotic coefficient of solute, given a Solution
|
|
118
121
|
object.
|
|
119
122
|
"""
|
|
120
123
|
return ureg.Quantity(1, "dimensionless")
|
|
121
124
|
|
|
122
|
-
def get_solute_volume(self, solution):
|
|
125
|
+
def get_solute_volume(self, solution: "Solution") -> ureg.Quantity:
|
|
123
126
|
"""Return the volume of the solutes."""
|
|
124
127
|
return ureg.Quantity(0, "L")
|
|
125
128
|
|
|
126
|
-
def equilibrate(self, solution):
|
|
129
|
+
def equilibrate(self, solution: "Solution") -> None:
|
|
127
130
|
"""Adjust the speciation of a Solution object to achieve chemical equilibrium."""
|
|
128
131
|
warnings.warn("equilibrate() has no effect in IdealEOS!")
|
|
129
132
|
return
|
|
@@ -138,7 +141,9 @@ class NativeEOS(EOS):
|
|
|
138
141
|
|
|
139
142
|
def __init__(
|
|
140
143
|
self,
|
|
141
|
-
phreeqc_db: Literal[
|
|
144
|
+
phreeqc_db: Literal[
|
|
145
|
+
"phreeqc.dat", "vitens.dat", "wateq4f_PWN.dat", "pitzer.dat", "llnl.dat", "geothermal.dat"
|
|
146
|
+
] = "llnl.dat",
|
|
142
147
|
) -> None:
|
|
143
148
|
"""
|
|
144
149
|
Args:
|
|
@@ -172,7 +177,7 @@ class NativeEOS(EOS):
|
|
|
172
177
|
# store the solution composition to see whether we need to re-instantiate the solution
|
|
173
178
|
self._stored_comp = None
|
|
174
179
|
|
|
175
|
-
def _setup_ppsol(self, solution):
|
|
180
|
+
def _setup_ppsol(self, solution: "Solution") -> None:
|
|
176
181
|
"""Helper method to set up a PhreeqPython solution for subsequent analysis."""
|
|
177
182
|
self._stored_comp = solution.components.copy()
|
|
178
183
|
solv_mass = solution.solvent_mass.to("kg").magnitude
|
|
@@ -244,13 +249,13 @@ class NativeEOS(EOS):
|
|
|
244
249
|
|
|
245
250
|
self.ppsol = ppsol
|
|
246
251
|
|
|
247
|
-
def _destroy_ppsol(self):
|
|
248
|
-
"""Remove the PhreeqPython solution from memory"""
|
|
252
|
+
def _destroy_ppsol(self) -> None:
|
|
253
|
+
"""Remove the PhreeqPython solution from memory."""
|
|
249
254
|
if self.ppsol is not None:
|
|
250
255
|
self.ppsol.forget()
|
|
251
256
|
self.ppsol = None
|
|
252
257
|
|
|
253
|
-
def get_activity_coefficient(self, solution, solute):
|
|
258
|
+
def get_activity_coefficient(self, solution: "Solution", solute: str):
|
|
254
259
|
r"""
|
|
255
260
|
Whenever the appropriate parameters are available, the Pitzer model [may]_ is used.
|
|
256
261
|
If no Pitzer parameters are available, then the appropriate equations are selected
|
|
@@ -329,7 +334,7 @@ class NativeEOS(EOS):
|
|
|
329
334
|
|
|
330
335
|
# show an error if no salt can be found that contains the solute
|
|
331
336
|
if salt is None:
|
|
332
|
-
logger.error("No salts found that contain solute
|
|
337
|
+
logger.error(f"No salts found that contain solute {solute}. Returning unit activity coefficient.")
|
|
333
338
|
return ureg.Quantity(1, "dimensionless")
|
|
334
339
|
|
|
335
340
|
# use the Pitzer model for higher ionic strength, if the parameters are available
|
|
@@ -344,14 +349,14 @@ class NativeEOS(EOS):
|
|
|
344
349
|
# alpha1 and alpha2 based on charge
|
|
345
350
|
if salt.nu_cation >= 2 and salt.nu_anion <= -2:
|
|
346
351
|
if salt.nu_cation >= 3 or salt.nu_anion <= -3:
|
|
347
|
-
alpha1 = 2
|
|
348
|
-
alpha2 = 50
|
|
352
|
+
alpha1 = 2.0
|
|
353
|
+
alpha2 = 50.0
|
|
349
354
|
else:
|
|
350
355
|
alpha1 = 1.4
|
|
351
356
|
alpha2 = 12
|
|
352
357
|
else:
|
|
353
|
-
alpha1 = 2
|
|
354
|
-
alpha2 = 0
|
|
358
|
+
alpha1 = 2.0
|
|
359
|
+
alpha2 = 0.0
|
|
355
360
|
|
|
356
361
|
# determine the average molality of the salt
|
|
357
362
|
# this is necessary for solutions inside e.g. an ion exchange
|
|
@@ -427,7 +432,7 @@ class NativeEOS(EOS):
|
|
|
427
432
|
|
|
428
433
|
return molal
|
|
429
434
|
|
|
430
|
-
def get_osmotic_coefficient(self, solution):
|
|
435
|
+
def get_osmotic_coefficient(self, solution: "Solution") -> ureg.Quantity:
|
|
431
436
|
r"""
|
|
432
437
|
Return the *molal scale* osmotic coefficient of solute, given a Solution
|
|
433
438
|
object.
|
|
@@ -574,7 +579,7 @@ class NativeEOS(EOS):
|
|
|
574
579
|
# this means the solution is empty
|
|
575
580
|
return 1
|
|
576
581
|
|
|
577
|
-
def get_solute_volume(self, solution):
|
|
582
|
+
def get_solute_volume(self, solution: "Solution") -> ureg.Quantity:
|
|
578
583
|
"""Return the volume of the solutes."""
|
|
579
584
|
# identify the predominant salt in the solution
|
|
580
585
|
salt = solution.get_salt()
|
|
@@ -596,14 +601,14 @@ class NativeEOS(EOS):
|
|
|
596
601
|
# alpha1 and alpha2 based on charge
|
|
597
602
|
if salt.nu_cation >= 2 and salt.nu_anion >= 2:
|
|
598
603
|
if salt.nu_cation >= 3 or salt.nu_anion >= 3:
|
|
599
|
-
alpha1 = 2
|
|
600
|
-
alpha2 = 50
|
|
604
|
+
alpha1 = 2.0
|
|
605
|
+
alpha2 = 50.0
|
|
601
606
|
else:
|
|
602
607
|
alpha1 = 1.4
|
|
603
608
|
alpha2 = 12
|
|
604
609
|
else:
|
|
605
|
-
alpha1 = 2
|
|
606
|
-
alpha2 = 0
|
|
610
|
+
alpha1 = 2.0
|
|
611
|
+
alpha2 = 0.0
|
|
607
612
|
|
|
608
613
|
apparent_vol = ac.get_apparent_volume_pitzer(
|
|
609
614
|
solution.ionic_strength,
|
|
@@ -633,7 +638,7 @@ class NativeEOS(EOS):
|
|
|
633
638
|
|
|
634
639
|
pitzer_calc = True
|
|
635
640
|
|
|
636
|
-
logger.debug("Updated solution volume using Pitzer model for solute
|
|
641
|
+
logger.debug(f"Updated solution volume using Pitzer model for solute {salt.formula}")
|
|
637
642
|
|
|
638
643
|
# add the partial molar volume of any other solutes, except for water
|
|
639
644
|
# or the parent salt, which is already accounted for by the Pitzer parameters
|
|
@@ -649,7 +654,7 @@ class NativeEOS(EOS):
|
|
|
649
654
|
part_vol = solution.get_property(solute, "size.molar_volume")
|
|
650
655
|
if part_vol is not None:
|
|
651
656
|
solute_vol += part_vol * ureg.Quantity(mol, "mol")
|
|
652
|
-
logger.debug("Updated solution volume using direct partial molar volume for solute
|
|
657
|
+
logger.debug(f"Updated solution volume using direct partial molar volume for solute {solute}")
|
|
653
658
|
|
|
654
659
|
else:
|
|
655
660
|
logger.warning(
|
|
@@ -658,7 +663,7 @@ class NativeEOS(EOS):
|
|
|
658
663
|
|
|
659
664
|
return solute_vol.to("L")
|
|
660
665
|
|
|
661
|
-
def equilibrate(self, solution):
|
|
666
|
+
def equilibrate(self, solution: "Solution") -> None:
|
|
662
667
|
"""Adjust the speciation of a Solution object to achieve chemical equilibrium."""
|
|
663
668
|
if self.ppsol is not None:
|
|
664
669
|
self.ppsol.forget()
|
|
@@ -699,7 +704,7 @@ class NativeEOS(EOS):
|
|
|
699
704
|
if solution.balance_charge is None:
|
|
700
705
|
pass
|
|
701
706
|
elif solution.balance_charge == "pH":
|
|
702
|
-
solution.components["H+"] += charge_adjust
|
|
707
|
+
solution.components["H+"] += charge_adjust
|
|
703
708
|
elif solution.balance_charge == "pE":
|
|
704
709
|
raise NotImplementedError
|
|
705
710
|
else:
|
|
@@ -734,7 +739,7 @@ class PhreeqcEOS(NativeEOS):
|
|
|
734
739
|
def __init__(
|
|
735
740
|
self,
|
|
736
741
|
phreeqc_db: Literal[
|
|
737
|
-
"vitens.dat", "wateq4f_PWN.dat", "pitzer.dat", "llnl.dat", "geothermal.dat"
|
|
742
|
+
"phreeqc.dat", "vitens.dat", "wateq4f_PWN.dat", "pitzer.dat", "llnl.dat", "geothermal.dat"
|
|
738
743
|
] = "phreeqc.dat",
|
|
739
744
|
) -> None:
|
|
740
745
|
"""
|
|
@@ -751,12 +756,12 @@ class PhreeqcEOS(NativeEOS):
|
|
|
751
756
|
"""
|
|
752
757
|
super().__init__(phreeqc_db=phreeqc_db)
|
|
753
758
|
|
|
754
|
-
def get_activity_coefficient(self, solution, solute):
|
|
759
|
+
def get_activity_coefficient(self, solution: "Solution", solute: str) -> ureg.Quantity:
|
|
755
760
|
"""
|
|
756
761
|
Return the *molal scale* activity coefficient of solute, given a Solution
|
|
757
762
|
object.
|
|
758
763
|
"""
|
|
759
|
-
if self.ppsol is None or solution.components != self._stored_comp:
|
|
764
|
+
if (self.ppsol is None) or (solution.components != self._stored_comp):
|
|
760
765
|
self._destroy_ppsol()
|
|
761
766
|
self._setup_ppsol(solution)
|
|
762
767
|
|
|
@@ -775,7 +780,7 @@ class PhreeqcEOS(NativeEOS):
|
|
|
775
780
|
|
|
776
781
|
return ureg.Quantity(act, "dimensionless")
|
|
777
782
|
|
|
778
|
-
def get_osmotic_coefficient(self, solution):
|
|
783
|
+
def get_osmotic_coefficient(self, solution: "Solution") -> ureg.Quantity:
|
|
779
784
|
"""
|
|
780
785
|
Return the *molal scale* osmotic coefficient of solute, given a Solution
|
|
781
786
|
object.
|
|
@@ -787,7 +792,7 @@ class PhreeqcEOS(NativeEOS):
|
|
|
787
792
|
# TODO - find a way to access or calculate osmotic coefficient
|
|
788
793
|
return ureg.Quantity(1, "dimensionless")
|
|
789
794
|
|
|
790
|
-
def get_solute_volume(self, solution):
|
|
795
|
+
def get_solute_volume(self, solution: "Solution") -> ureg.Quantity:
|
|
791
796
|
"""Return the volume of the solutes."""
|
|
792
797
|
# TODO - phreeqc seems to have no concept of volume, but it does calculate density
|
|
793
798
|
return ureg.Quantity(0, "L")
|
|
@@ -92,11 +92,15 @@ class Solution(MSONable):
|
|
|
92
92
|
-7 to +14. The default value corresponds to a pE value typical of natural
|
|
93
93
|
waters in equilibrium with the atmosphere.
|
|
94
94
|
balance_charge: The strategy for balancing charge during init and equilibrium calculations. Valid options
|
|
95
|
-
are
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
are
|
|
96
|
+
- 'pH', which will adjust the solution pH to balance charge,
|
|
97
|
+
- 'auto' which will use the majority cation or anion (i.e., that with the largest concentration)
|
|
98
|
+
as needed,
|
|
99
|
+
- 'pE' (not currently implemented) which will adjust the redox equilibrium to balance charge, or
|
|
100
|
+
the name of a dissolved species e.g. 'Ca+2' or 'Cl-' that will be added/subtracted to balance
|
|
101
|
+
charge.
|
|
102
|
+
- None (default), in which case no charge balancing will be performed either on init or when
|
|
103
|
+
equilibrate() is called. Note that in this case, equilibrate() can distort the charge balance!
|
|
100
104
|
solvent: Formula of the solvent. Solvents other than water are not supported at this time.
|
|
101
105
|
engine: Electrolyte modeling engine to use. See documentation for details on the available engines.
|
|
102
106
|
database: path to a .json file (str or Path) or maggma Store instance that
|
|
@@ -171,7 +175,7 @@ class Solution(MSONable):
|
|
|
171
175
|
self._pE = pE
|
|
172
176
|
self._pH = pH
|
|
173
177
|
self.pE = self._pE
|
|
174
|
-
if isinstance(balance_charge, str) and balance_charge not in ["pH", "pE"]:
|
|
178
|
+
if isinstance(balance_charge, str) and balance_charge not in ["pH", "pE", "auto"]:
|
|
175
179
|
self.balance_charge = standardize_formula(balance_charge)
|
|
176
180
|
else:
|
|
177
181
|
self.balance_charge = balance_charge #: Standardized formula of the species used for charge balancing.
|
|
@@ -273,13 +277,19 @@ class Solution(MSONable):
|
|
|
273
277
|
raise NotImplementedError("Balancing charge via redox (pE) is not yet implemented!")
|
|
274
278
|
else:
|
|
275
279
|
ions = set().union(*[self.cations, self.anions]) # all ions
|
|
280
|
+
if self.balance_charge == "auto":
|
|
281
|
+
# add the most abundant ion of the opposite charge
|
|
282
|
+
if cb <= 0:
|
|
283
|
+
self.balance_charge = max(self.cations, key=self.cations.get)
|
|
284
|
+
elif cb > 0:
|
|
285
|
+
self.balance_charge = max(self.anions, key=self.anions.get)
|
|
276
286
|
if self.balance_charge not in ions:
|
|
277
287
|
raise ValueError(
|
|
278
288
|
f"Charge balancing species {self.balance_charge} was not found in the solution!. "
|
|
279
289
|
f"Species {ions} were found."
|
|
280
290
|
)
|
|
281
|
-
z = self.get_property(balance_charge, "charge")
|
|
282
|
-
self.components[balance_charge] += -1 * cb / z * self.volume.to("L").magnitude
|
|
291
|
+
z = self.get_property(self.balance_charge, "charge")
|
|
292
|
+
self.components[self.balance_charge] += -1 * cb / z * self.volume.to("L").magnitude
|
|
283
293
|
balanced = True
|
|
284
294
|
|
|
285
295
|
if not balanced:
|
|
@@ -1282,81 +1292,12 @@ class Solution(MSONable):
|
|
|
1282
1292
|
Returns:
|
|
1283
1293
|
Nothing. The concentration of solute is modified.
|
|
1284
1294
|
"""
|
|
1285
|
-
#
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
):
|
|
1292
|
-
# store the original volume for later
|
|
1293
|
-
orig_volume = self.volume
|
|
1294
|
-
|
|
1295
|
-
# change the amount of the solute present to match the desired amount
|
|
1296
|
-
self.components[solute] += (
|
|
1297
|
-
ureg.Quantity(amount)
|
|
1298
|
-
.to(
|
|
1299
|
-
"moles",
|
|
1300
|
-
"chem",
|
|
1301
|
-
mw=self.get_property(solute, "molecular_weight"),
|
|
1302
|
-
volume=self.volume,
|
|
1303
|
-
solvent_mass=self.solvent_mass,
|
|
1304
|
-
)
|
|
1305
|
-
.magnitude
|
|
1306
|
-
)
|
|
1307
|
-
|
|
1308
|
-
# set the amount to zero and log a warning if the desired amount
|
|
1309
|
-
# change would result in a negative concentration
|
|
1310
|
-
if self.get_amount(solute, "mol").magnitude < 0:
|
|
1311
|
-
self.logger.error(
|
|
1312
|
-
"Attempted to set a negative concentration for solute %s. Concentration set to 0" % solute
|
|
1313
|
-
)
|
|
1314
|
-
self.set_amount(solute, "0 mol")
|
|
1315
|
-
|
|
1316
|
-
# calculate the volume occupied by all the solutes
|
|
1317
|
-
solute_vol = self._get_solute_volume()
|
|
1318
|
-
|
|
1319
|
-
# determine the volume of solvent that will preserve the original volume
|
|
1320
|
-
target_vol = orig_volume - solute_vol
|
|
1321
|
-
|
|
1322
|
-
# adjust the amount of solvent
|
|
1323
|
-
# volume in L, density in kg/m3 = g/L
|
|
1324
|
-
target_mass = target_vol * ureg.Quantity(self.water_substance.rho, "g/L")
|
|
1325
|
-
|
|
1326
|
-
mw = self.get_property(self.solvent, "molecular_weight")
|
|
1327
|
-
target_mol = target_mass / mw
|
|
1328
|
-
self.components[self.solvent] = target_mol.magnitude
|
|
1329
|
-
|
|
1330
|
-
else:
|
|
1331
|
-
# change the amount of the solute present
|
|
1332
|
-
self.components[solute] += (
|
|
1333
|
-
ureg.Quantity(amount)
|
|
1334
|
-
.to(
|
|
1335
|
-
"moles",
|
|
1336
|
-
"chem",
|
|
1337
|
-
mw=self.get_property(solute, "molecular_weight"),
|
|
1338
|
-
volume=self.volume,
|
|
1339
|
-
solvent_mass=self.solvent_mass,
|
|
1340
|
-
)
|
|
1341
|
-
.magnitude
|
|
1342
|
-
)
|
|
1343
|
-
|
|
1344
|
-
# set the amount to zero and log a warning if the desired amount
|
|
1345
|
-
# change would result in a negative concentration
|
|
1346
|
-
if self.get_amount(solute, "mol").magnitude < 0:
|
|
1347
|
-
self.logger.error(
|
|
1348
|
-
"Attempted to set a negative concentration for solute %s. Concentration set to 0" % solute
|
|
1349
|
-
)
|
|
1350
|
-
self.set_amount(solute, "0 mol")
|
|
1351
|
-
|
|
1352
|
-
# update the volume to account for the space occupied by all the solutes
|
|
1353
|
-
# make sure that there is still solvent present in the first place
|
|
1354
|
-
if self.solvent_mass <= ureg.Quantity(0, "kg"):
|
|
1355
|
-
self.logger.error("All solvent has been depleted from the solution")
|
|
1356
|
-
return
|
|
1357
|
-
|
|
1358
|
-
# set the volume recalculation flag
|
|
1359
|
-
self.volume_update_required = True
|
|
1295
|
+
# Get the current amount of the solute
|
|
1296
|
+
current_amt = self.get_amount(solute, amount.split(" ")[1])
|
|
1297
|
+
if current_amt.magnitude == 0:
|
|
1298
|
+
self.logger.warning(f"Add new solute {solute} to the solution")
|
|
1299
|
+
new_amt = ureg.Quantity(amount) + current_amt
|
|
1300
|
+
self.set_amount(solute, new_amt)
|
|
1360
1301
|
|
|
1361
1302
|
def set_amount(self, solute: str, amount: str):
|
|
1362
1303
|
"""
|
|
@@ -2465,7 +2406,7 @@ class Solution(MSONable):
|
|
|
2465
2406
|
"""
|
|
2466
2407
|
str_filename = str(filename)
|
|
2467
2408
|
if not ("yaml" in str_filename.lower() or "json" in str_filename.lower()):
|
|
2468
|
-
self.logger.error("Invalid file extension entered -
|
|
2409
|
+
self.logger.error("Invalid file extension entered - {str_filename}")
|
|
2469
2410
|
raise ValueError("File extension must be .json or .yaml")
|
|
2470
2411
|
if "yaml" in str_filename.lower():
|
|
2471
2412
|
solution_dict = self.as_dict()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyEQL
|
|
3
|
-
Version: 1.
|
|
4
|
-
Summary: A python
|
|
3
|
+
Version: 1.1.1
|
|
4
|
+
Summary: A python interface for solution chemistry
|
|
5
5
|
Author-email: Ryan Kingsbury <kingsbury@princeton.edu>
|
|
6
6
|
Project-URL: Docs, https://pyeql.readthedocs.io/
|
|
7
7
|
Project-URL: Repo, https://github.com/KingsburyLab/pyEQL
|
|
@@ -25,7 +25,7 @@ Requires-Dist: numpy<2
|
|
|
25
25
|
Requires-Dist: scipy
|
|
26
26
|
Requires-Dist: pymatgen==2024.5.1
|
|
27
27
|
Requires-Dist: iapws
|
|
28
|
-
Requires-Dist: monty
|
|
28
|
+
Requires-Dist: monty>=2024.7.12
|
|
29
29
|
Requires-Dist: maggma>=0.67.0
|
|
30
30
|
Requires-Dist: phreeqpython
|
|
31
31
|
Provides-Extra: testing
|