Contributing to aquasol is possible in several ways. Here we show how to add formulas (i.e., sources) to a given property, and how to add a new property for water or solutions.
Formulas are managed by the aquasol.formulas module.
All formulas are described by classes that inherit from Formula, defined in aquasol.formulas.general.
-
Formulas for water are present in the
aquasol.formulas.watermodule and inherit fromWaterFormula; they depend only on temperature (T) -
Formulas for solutions are present in the
aquasol.formulas.solutionsmodule and inherit fromSolutionFormula(dependence on T and concentration), orSaturatedSolutionFormula(dependence on T only)
Important NOTE: If the formula uses other formulas (e.g. solution formula using water quantity as reference), or conversions between concentration units (including ionic_strength()), please only import functions, classes etc. that are contained in the aquasol.formulas module (including basic_conversions or ionic in aquasol.formulas.solutions), or in the aquasol.constants module; DO NOT import from aquasol, aquasol.water or aquasol.solutions. This is to keep modules as independent from each other and prevent circular imports problems.
-
OK Examples:
from aquasol.constants import R, Mw, Patm, Pc, Tc from aquasol.formulas.water.vapor_pressure import VaporPressure_IAPWS from aquasol.formulas.solutions.ionic import ionic strength from aquasol.formulas.solutions.basic_conversions import basic_convert
-
NOT OK Examples:
from aquasol import ps, dp, cv from aquasol.water import vapor_pressure from aquasol.solutions import ionic strength from aquasol.solutions import convert
-
Go to the module of the specific property where you want to add a formula (e.g.
aquasol/formulas/water/surface_tension.py). -
Add class for the formula, inheriting from
WaterFormula, with the following characteristics :-
Class attributes:
source[str]: short name describing the source for the formulatemperature_range[tuple of floats]: validity Tmin, Tmax for the formula)temperature_unit[str]:'C'or'K'
-
Method
calculate(self, T), which takes temperature as an input (in the units defined above) and returns the calculated property in SI units.
-
-
Add the class to the tuple gathering all formulas at the end of file of the property module (e.g.
aquasol/formulas/water/surface_tension.py)
The strategy is similar to that for water, but with a few extra steps.
-
Go to the module of the specific property where you want to add a formula (e.g.
aquasol/formulas/solutions/surface_tension). -
Decide where to add the formula:
-
If the formula is for just one specific solute, add it directly to the file bearing the name of the solute (e.g.,
aquasol/formulas/solutions/surface_tension/NaCl.py) -
If the solute file does not exist (solute not documented before), add it and use the file for NaCl as a template.
-
If the formula can describe different solutes (e.g. same equation with different coefficients), it is preferrable to create a new, single file gathering all formulas for different solutes, then import the formulas in each solute file (see e.g. how it is done for LiCl and CaCl2 in the
conde.py,LiCl.pyandCaCl2.pyfiles inaquasol/formulas/solutions/surface_tension/)
-
-
Add class for the formula, inheriting from
SolutionFormulaorSaturatedSolutionFormula, with the following characteristics :-
Class attributes:
source,temperature_range,temperature_unit(same as for water)concentration_range[tuple of floats]: validity c_min, c_max for the formulaconcentration_unit: [str], any concentration type accepted byaquasol.convert(), e.g. molality ('m'), weight fraction ('w'), etc.)- if formula returns both the value and a reference value (value at zero concentration), set
with_water_reference = True.
-
Method
calculate(self, c, T), which takes concentration and temperature as an input (in the units defined above) and returns the calculated property in SI units; ifwith_water_reference, the method should return a tuple(v0, v)withv0the value of the property at zero concentration.
-
-
Add the class to the tuple gathering all formulas at the end of file of each solute file (e.g.
aquasol/formulas/solutions/surface_tension/NaCl.py) -
If adding solutes that were not documented before for the considered property, also add the tuple to the init file of the property module (e.g.
aquasol/formulas/solutions/surface_tension/__init__.py), similarly to other existing solutes.
-
Update README.md with new entry in the Sources reference list, and for solutions with adequate crosses in the Available Solutes table.
-
Add tests in tests folder and run all tests of aquasol to make sure nothing is broken (type
pytestin console while being in the root folder of the aquasol project).
-
Create new file in
aquasol.formulas.water, which will contain the formulas for the new property. -
Add formulas in that file (see Add formula (to existing property) section above)
-
One of the formulas has to be designed as the default formula to use for the particular property. This is achieved by setting the class attribute
default=Truein the formula class. -
Create a tuple containing all formula classes at the end of the file (see other property files for examples), e.g. in
vapor_pressuremodule:VaporPressureFormulas = ( VaporPressure_IAPWS, VaporPressure_Wexler, VaporPressure_Bridgeman, )
- Create new class inheriting from
WaterPropertyinaquasol/water/properties.py, which will describe the new property and gather all available formulas. Then, go to Final steps section below.
-
Create new folder in
aquasol.formulas.waterwith an__init__.pyempty file. This module will contain all formulas for the new property. -
In that new folder, also create one python file per solute (e.g.
NaCl.py) that will be defined. -
Add formulas in the module (see Add formula (to existing property) section above).
-
One of the formulas in each solute file has to be designed as the default formula to use for the particular property and given solute. This is achieved by setting the class attribute
default=Truein the formula class. -
Create a tuple containing all formula classes at the end of each solute file (see other property files for examples), e.g. in
aquasol/formulas/solutions/density/NaCl.py:Density_NaCl_Formulas = ( Density_NaCl_Simion, Density_NaCl_Tang, Density_NaCl_AlGhafri, )
-
In the empty
__init__.pyfile previously created in the property module, import all solute formulas and create a new tuple with all formulas for all solutes, e.g. inaquasol/formulas/solutions/density/__init__.py:from .KCl import Density_KCl_Formulas from .LiCl import Density_LiCl_Formulas from .NaCl import Density_NaCl_Formulas DensityFormulas = ( Density_KCl_Formulas + Density_LiCl_Formulas + Density_NaCl_Formulas )
- Create new class inheriting from
SolutionProperty(or equivalent, e.g.SolubilityProperty) inaquasol/solution/properties.py, which will describe the new property and gather all available formulas. Then, go to Final steps section below.
-
In the new property class, define the following class attributes:
quantity[str]: short title for the propertyunit[str]: what is the physical unit (SI) of the quantityFormulas[tuple]: put here the tuple of formulas defined above, e.g.orFormulas = VaporPressureFormulas
with the examples aboveFormulas = DensityFormulas
-
Also include a docstring in that new class, with a one-liner describing the property and some examples; a more general docstring describing possible inputs etc. is automatically added by
Propertybase classes. -
At the end of the
properties.pyfile, instantiate an object of the class; this object will be the function accessible to the user for the specific property(*). -
Import that object in the
__init__.pyfile of the module (waterorsolutions) so that it is accessible to the user by callingfrom aquasol.water import ...orfrom aquasol.solutions import ... -
Update README.md with descriptions of the new property and some examples.
-
Add a plot of the new property data in the _main_.py file in
aquasol. -
Go to the root folder of
aquasoland run the two following commands to make sure nothing is broken:- Run tests [requires pytest installed]
pytest
- Check graphs [requires matplotlib installed]
python -m aquasol
- Run tests [requires pytest installed]
(*) These objects are not true python functions but objects from callable classes, which act as functions but with extra attributes, e.g. all sources available can be accessed with .sources attribute.