Solution Class Reference¶
This page contains detailed information on each of the methods, attributes, and properties in Solution. Use the sidebar on the right for easier navigation.
Solution¶
-
class pyEQL.Solution(solutes: list[list[str]] | dict[str, str] | None =
None, volume: str | None =None, temperature: str ='298.15 K', pressure: str ='1 atm', pH: float =7, pE: float =8.5, balance_charge: str | None =None, solvent: str | list ='H2O', engine: EOS | 'native' | 'ideal' | 'phreeqc' | 'phreeqc2026' ='native', database: str | Path | Store | None =None, default_diffusion_coeff: float =1.6106e-09, log_level: 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL' | None ='ERROR')[source]¶ Class representing the properties of a solution. Instances of this class contain information about the solutes, solvent, and bulk properties.
- balance_charge¶
Standardized formula of the species used for charge balancing.
- water_substance¶
IAPWS instance describing water properties.
- components¶
Special dictionary where keys are standardized formula and values are the moles present in Solution.
- database¶
Store instance containing the solute property database.
- solvent¶
Formula of the component that is set as the solvent (currently only H2O(aq) is supported).
- property mass : Quantity¶
Return the total mass of the solution.
The mass is calculated each time this method is called.
Returns: The mass of the solution, in kg
- property solvent_mass : Quantity¶
Return the mass of the solvent.
This property is used whenever mol/kg (or similar) concentrations are requested by get_amount()
- Returns:¶
The mass of the solvent, in kg
See also
- property volume : Quantity¶
Return the volume of the solution.
- property temperature : Quantity¶
Return the temperature of the solution in Kelvin.
- property pressure : Quantity¶
Return the hydrostatic pressure of the solution in atm.
-
p(solute: str, activity=
True) float[source]¶ Return the negative log of the activity of solute.
Generally used for expressing concentration of hydrogen ions (pH)
- property density : Quantity¶
Return the density of the solution.
Density is calculated from the mass and volume each time this method is called.
- property dielectric_constant : Quantity¶
Returns the dielectric constant of the solution.
Notes
Implements the following equation as given by Zuber et al.
\[\epsilon = \epsilon_{solvent} \over 1 + \sum_i \alpha_i x_i\]where \(\alpha_i\) is a coefficient specific to the solvent and ion, and \(x_i\) is the mole fraction of the ion in solution.
References
A. Zuber, L. Cardozo-Filho, V.F. Cabral, R.F. Checoni, M. Castier, An empirical equation for the dielectric constant in aqueous and nonaqueous electrolyte mixtures, Fluid Phase Equilib. 376 (2014) 116-123. doi:10.1016/j.fluid.2014.05.037.
- property chemical_system : str¶
Return the chemical system of the Solution as a “-” separated list of elements, sorted alphabetically. For example, a solution containing CaCO3 would have a chemical system of “C-Ca-H-O”.
- property elements : list¶
Return a list of elements that are present in the solution.
For example, a solution containing CaCO3 would return [“C”, “Ca”, “H”, “O”]
- property cations : dict[str, float]¶
Returns the subset of components that are cations.
The returned dict is sorted by amount in descending order.
- property anions : dict[str, float]¶
Returns the subset of components that are anions.
The returned dict is sorted by amount in descending order.
- property neutrals : dict[str, float]¶
Returns the subset of components that are neutral (not charged).
The returned dict is sorted by amount in descending order.
- property viscosity_dynamic : Quantity¶
Return the dynamic (absolute) viscosity of the solution.
Calculated from the kinematic viscosity
See also
- property viscosity_kinematic : Quantity¶
Return the kinematic viscosity of the solution.
Notes
The calculation is based on a model derived from the Eyring equation and presented in
\[\ln \nu = \ln {\nu_w MW_w \over \sum_i x_i MW_i } + 15 x_+^2 + x_+^3 \delta G^*_{123} + 3 x_+ \delta G^*_{23} (1-0.05x_+)\]Where:
\[\delta G^*_{123} = a_o + a_1 (T)^{0.75}\]\[\delta G^*_{23} = b_o + b_1 (T)^{0.5}\]In which \(\nu\) is the kinematic viscosity, MW is the molecular weight, \(x_{+}\) is the mole fraction of cations, and \(T\) is the temperature in degrees C.
The a and b fitting parameters for a variety of common salts are included in the database.
References
Vásquez-Castillo, G.; Iglesias-Silva, G. a.; Hall, K. R. An extension of the McAllister model to correlate kinematic viscosity of electrolyte solutions. Fluid Phase Equilib. 2013, 358, 44-49.
See also
- property conductivity : Quantity¶
Compute the electrical conductivity of the solution.
- Returns:¶
The electrical conductivity of the solution in Siemens / meter.
Notes
Conductivity is calculated by summing the molar conductivities of the respective solutes.
\[EC = {F^2 \over R T} \sum_i D_i z_i ^ 2 m_i = \sum_i \lambda_i m_i\]Where \(D_i\) is the diffusion coefficient, \(m_i\) is the molal concentration, \(z_i\) is the charge, and the summation extends over all species in the solution. Alternatively, \(\lambda_i\) is the molar conductivity of solute i.
Diffusion coefficients \(D_i\) (and molar conductivities \(\lambda_i\)) are adjusted for the effects of temperature and ionic strength using the method implemented in PHREEQC >= 3.4. [aq] [hc] See get_diffusion_coefficient for further details.
References
See also
ionic_strengthget_diffusion_coefficient()get_molar_conductivity()
- property ionic_strength : Quantity¶
Return the ionic strength of the solution.
Return the ionic strength of the solution, calculated as 1/2 * sum ( molality * charge ^2) over all the ions.
Molal (mol/kg) scale concentrations are used for compatibility with the activity correction formulas.
See also
Notes
The ionic strength is calculated according to:
\[I = \sum_i m_i z_i^2\]Where \(m_i\) is the molal concentration and \(z_i\) is the charge on species i.
Examples
>>> s1 = pyEQL.Solution([['Na+','0.2 mol/kg'],['Cl-','0.2 mol/kg']]) >>> s1.ionic_strength <Quantity(0.20000010029672785, 'mole / kilogram')>>>> s1 = pyEQL.Solution([['Mg+2','0.3 mol/kg'],['Na+','0.1 mol/kg'],['Cl-','0.7 mol/kg']],temperature='30 degC') >>> s1.ionic_strength <Quantity(1.0000001004383303, 'mole / kilogram')>
- property charge_balance : float¶
Return the signed charge balance of the solution, positive or negative.
Return the signed charge balance of the solution, positive or negative. The charge balance represents the net electric charge of the solution and SHOULD equal zero at all times, but due to numerical errors will usually have a small nonzero value. Positive values indicate excess cationic charge, while negative values indivate excess anionic charge. It is calculated according to:
\[CB = \sum_i C_i z_i\]where \(C_i\) is the molar concentration, and \(z_i\) is the charge on species i.
- property alkalinity : Quantity¶
Return the alkalinity or acid neutralizing capacity of a solution.
Notes
The alkalinity is calculated according to [stm]
\[Alk = \sum_{i} z_{i} C_{B} + \sum_{i} z_{i} C_{A}\]Where \(C_{B}\) and \(C_{A}\) are conservative cations and anions, respectively (i.e. ions that do not participate in acid-base reactions), and \(z_{i}\) is their signed charge. When conservative cations (Group I and II cations) or strong base anions are present, the alkalinity is calculated according to[stm]_
\[Alk = \sum_{i} z_{i} C_{B} + \sum_{i} z_{i} C_{A}\]Where \(C_{B}\) and \(C_{A}\) are conservative cations and strong base anions, respectively (i.e. ions that do not participate in acid-base reactions), and \(z_{i}\) is their signed charge.
Alternatively, if those species are not present, then alkalinity is calculated based on the concentrations of weak acid and base species according to [stm]
\[Alk = -\sum_{i} z_{i} C_{i}\]Where \(C_i\) is the molar concentration of species i, and \(z_i\) is its charge.
The summation should extend over all weak inorganic species that can participate in acid-base reactions. In this method, we consider HCO3[-1], CO3[-2], H2PO4[-1], HPO4[-2], PO4[-3], HS[-1], S[-2], H3SiO4[-1], H2SiO4[-2], B(OH)4[-1], NH3(aq), OH[-1], and H[+1] as the relevant weak acid/base species, while organics are excluded.
References
[stm]Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 165. Wiley Interscience, 1996.
- property hardness : Quantity¶
Return the hardness of a solution.
Hardness is defined as the sum of the equivalent concentrations of multivalent cations as calcium carbonate.
NOTE: at present pyEQL cannot distinguish between mg/L as CaCO3 and mg/L units. Use with caution.
- property total_dissolved_solids : Quantity¶
Total dissolved solids in mg/L (equivalent to ppm) including both charged and uncharged species.
The TDS is defined as the sum of the concentrations of all aqueous solutes (not including the solvent), except for H[+1] and OH[-1]].
- property TDS : Quantity¶
Alias of
total_dissolved_solids().
- property debye_length : Quantity¶
Return the Debye length of a solution.
Debye length is calculated as [wk3]
\[\kappa^{-1} = \sqrt({\epsilon_r \epsilon_o k_B T \over (2 N_A e^2 I)})\]where \(I\) is the ionic strength, \(\epsilon_r\) and \(\epsilon_r\) are the relative permittivity and vacuum permittivity, \(k_B\) is the Boltzmann constant, and \(T\) is the temperature, \(e\) is the elementary charge, and \(N_A\) is Avogadro’s number.
Returns The Debye length, in nanometers.
References
See also
- property bjerrum_length : Quantity¶
Return the Bjerrum length of a solution.
Bjerrum length represents the distance at which electrostatic interactions between particles become comparable in magnitude to the thermal energy.:math:lambda_B is calculated as
\[\lambda_B = {e^2 \over (4 \pi \epsilon_r \epsilon_o k_B T)}\]where \(e\) is the fundamental charge, \(\epsilon_r\) and \(\epsilon_r\) are the relative permittivity and vacuum permittivity, \(k_B\) is the Boltzmann constant, and \(T\) is the temperature.
References
https://en.wikipedia.org/wiki/Bjerrum_length
Examples
>>> s1 = pyEQL.Solution() >>> s1.bjerrum_length <Quantity(0.7152793009386953, 'nanometer')>See also
- property osmotic_pressure : Quantity¶
Return the osmotic pressure of the solution relative to pure water.
- Returns:¶
The osmotic pressure of the solution relative to pure water in Pa
Notes
Osmotic pressure is calculated based on the water activity [sata] [wk]
\[\Pi = -\frac{RT}{V_{w}} \ln a_{w}\]Where \(\Pi\) is the osmotic pressure, \(V_{w}\) is the partial molar volume of water (18.2 cm**3/mol), and \(a_{w}\) is the water activity.
References
[sata]Sata, Toshikatsu. Ion Exchange Membranes: Preparation, Characterization, and Modification. Royal Society of Chemistry, 2004, p. 10.
Examples
>>> s1=pyEQL.Solution() >>> s1.osmotic_pressure <Quantity(0.495791416, 'pascal')>>>> s1 = pyEQL.Solution([['Na+','0.2 mol/kg'],['Cl-','0.2 mol/kg']]) >>> soln.osmotic_pressure <Quantity(906516.7318131207, 'pascal')>
-
get_amount(solute: str, units: str =
'mol/L') Quantity[source]¶ Return the amount of ‘solute’ in the parent solution.
The amount of a solute can be given in a variety of unit types. 1. substance per volume (e.g., ‘mol/L’, ‘M’) 2. equivalents (i.e., moles of charge) per volume (e.g., ‘eq/L’, ‘meq/L’) 3. substance per mass of solvent (e.g., ‘mol/kg’, ‘m’) 4. mass of substance (e.g., ‘kg’) 5. moles of substance (‘mol’) 6. mole fraction (‘fraction’) 7. percent by weight (%) 8. number of molecules (‘count’) 9. “parts-per-x” units, where ppm = mg/L, ppb = ug/L ppt = ng/L
-
get_components_by_element(nested: bool =
False) dict[str, list[str]] | dict[str, dict[float | str, list[str]]][source]¶ Return a list of all species associated with a given element.
- Parameters:¶
- Returns:¶
A mapping of element to a list of species in the solution.
If nested is False (default), elements (keys) are suffixed with their oxidation state in parentheses, e.g.,
{“Na(1.0)”:[“Na[+1]”, “NaOH(aq)”]}
If nested is True, the dictionary is nested, e.g.,
{“Na”: [{1:[“Na[+1]”, “NaOH(aq)”]}]}.
Note that the valence may be a string, assuming the value “unk” denoting an unknown oxidation state.
Species associated with each element are sorted in descending order of the amount present (i.e., the first species listed is the most abundant).
-
get_el_amt_dict(nested: bool =
False) dict[str, float] | dict[str, dict[float | str, float]][source]¶ Return a dict of Element: amount in mol.
- Parameters:¶
- Returns:¶
A mapping of element to its amount in moles in the solution.
If nested is False (default), elements (keys) are suffixed with their oxidation state in parentheses, e.g.,
{“Fe(2.0)”: 0.354, “Cl(-1.0)”: 0.708}
If nested is True, the dictionary is nested, e.g.,
{“Fe”: {2.0: 0.354}, “Cl”: {-1.0: 0.708}}.}
Note that the valence may be a string, assuming the value “unk” denoting an unknown oxidation state.
- get_total_amount(element: str, units: str) Quantity[source]¶
Return the total amount of ‘element’ (across all solutes) in the solution.
- Parameters:¶
- element: str¶
The symbol of the element of interest. The symbol can optionally be followed by the oxidation state in parentheses, e.g., “Na(1.0)”, “Fe(2.0)”, or “O(0.0)”. If no oxidation state is given, the total concentration of the element (over all oxidation states) is returned.
- units: str¶
str Units desired for the output. Any unit understood by get_amount can be used. Examples of valid units are ‘mol/L’,’mol/kg’,’mol’, ‘kg’, and ‘g/L’.
- Returns:¶
The total amount of the element in the solution, in the specified units
- add_solute(formula: str, amount: str)[source]¶
Primary method for adding substances to a pyEQL solution.
- Parameters:¶
- formula : str¶
Chemical formula for the solute. Charged species must contain a+ or - and (for polyvalent solutes) a number representing the net charge (e.g. ‘SO4-2’).
- amount : str¶
The amount of substance in the specified unit system. The string should contain both a quantity and a pint-compatible representation of a ureg. e.g. ‘5 mol/kg’ or ‘0.1 g/L’.
- add_amount(solute: str, amount: str)[source]¶
Add the amount of ‘solute’ to the parent solution.
- Parameters:¶
- solute: str¶
str String representing the name of the solute of interest
- amount: str¶
str quantity String representing the concentration desired, e.g. ‘1 mol/kg’ If the units are given on a per-volume basis, the solution volume is not recalculated If the units are given on a mass, substance, per-mass, or per-substance basis, then the solution volume is recalculated based on the new composition
- Returns:¶
Nothing. The concentration of solute is modified.
- set_amount(solute: str, amount: str)[source]¶
Set the amount of ‘solute’ in the parent solution.
- Parameters:¶
- solute: str¶
str String representing the name of the solute of interest
- amount: str¶
str Quantity String representing the concentration desired, e.g. ‘1 mol/kg’ If the units are given on a per-volume basis, the solution volume is not recalculated and the molar concentrations of other components in the solution are not altered, while the molal concentrations are modified.
If the units are given on a mass, substance, per-mass, or per-substance basis, then the solution volume is recalculated based on the new composition and the molal concentrations of other components are not altered, while the molar concentrations are modified.
- Returns:¶
Nothing. The concentration of solute is modified.
- get_moles_solvent() Quantity[source]¶
Return the moles of solvent present in the solution.
- Returns:¶
The moles of solvent in the solution.
-
get_osmolarity(activity_correction=
False) Quantity[source]¶ Return the osmolarity of the solution in Osm/L.
-
get_osmolality(activity_correction=
False) Quantity[source]¶ Return the osmolality of the solution in Osm/kg.
- get_salt() Salt[source]¶
Determine the predominant salt in a solution of ions.
Many empirical equations for solution properties such as activity coefficient, partial molar volume, or viscosity are based on the concentration of single salts (e.g., NaCl). When multiple ions are present (e.g., a solution containing Na+, Cl-, and Mg+2), it is generally not possible to directly model these quantities. pyEQL works around this problem by treating such solutions as single salt solutions.
The get_salt() method examines the ionic composition of a solution and returns an object that identifies the single most predominant salt in the solution, defined by the cation and anion with the highest mole fraction. The Salt object contains information about the stoichiometry of the salt to enable its effective concentration to be calculated (e.g., if a solution contains 0.5 mol/kg of Na+ and Cl-, plus traces of H+ and OH-, the matched salt is 0.5 mol/kg NaCl).
- Returns:¶
Salt object containing information about the parent salt.
See also
get_activity()get_activity_coefficient()get_water_activity()get_osmotic_coefficient()osmotic_pressureviscosity_kinematicExamples
>>> s1 = Solution([['Na+','0.5 mol/kg'],['Cl-','0.5 mol/kg']]) >>> s1.get_salt() <pyEQL.salt_ion_match.Salt object at 0x7fe6d3542048> >>> s1.get_salt().formula 'NaCl' >>> s1.get_salt().nu_cation 1 >>> s1.get_salt().z_anion -1>>> s2 = pyEQL.Solution([['Na+','0.1 mol/kg'],['Mg+2','0.2 mol/kg'],['Cl-','0.5 mol/kg']]) >>> s2.get_salt().formula 'MgCl2' >>> s2.get_salt().nu_anion 2 >>> s2.get_salt().z_cation 2
-
get_salt_dict(cutoff: float =
1e-06, use_totals: bool =True) dict[str, dict[str, float | Salt]][source]¶ Returns a dict that represents the salts of the Solution by pairing anions and cations.
The
get_salt_dict()method examines the ionic composition of a solution and approximates it as a set of salts instead of individual ions. The method returns a dictionary of Salt objects where the keys are the salt formulas (e.g., ‘NaCl’). The Salt object contains information about the stoichiometry of the salt to enable its effective concentration to be calculated (e.g., 1 M MgCl2 yields 1 M Mg+2 and 2 M Cl-).- Parameters:¶
- cutoff: float =
1e-06¶ Lowest molal concentration to consider. No salts below this value will be included in the output. Useful for excluding analysis of trace anions. Defaults to 1e-6 (1 part per million).
- use_totals: bool =
True¶ Whether or not to base the analysis on the concentration of the predominant species of each element. Note that species in which a given element assumes a different oxidation state are always treated separately.
- cutoff: float =
- Returns:¶
- dict
A dictionary of representing salts in the solution, keyed by the salt formula.
Notes
The dict maps salt formulas to dictionaries containing their amounts and composition. The amount is stored in moles under the key “mol”, and a
pyEQL.salt_ion_match.Saltobject stored under the “salt” key represents the composition. Salts are identified by pairing the predominant cations and anions in the solution, in descending order of their respective equivalent amounts.Many empirical equations for solution properties such as activity coefficient, partial molar volume, or viscosity are based on the concentration of single salts (e.g., NaCl). When multiple ions are present (e.g., a solution containing Na+, Cl-, and Mg+2), it is generally not possible to directly model these quantities.
Examples
>>> from pyEQL import Solution >>> from pyEQL.salt_ion_match import Salt >>> s1 = Solution( ... solutes={ ... 'Na[+1]': '1 mol/L', ... 'Cl[-1]': '1 mol/L', ... 'Ca[+2]': '0.01 mol/kg', ... 'HCO3[-1]': '0.007 mol/kg', ... 'CO3[-2]': '0.001 mol/kg', ... 'ClO[-1]': '0.001 mol/kg', ... } ... ) >>> salt_dict = s1.get_salt_dict() >>> list(salt_dict) # Only returns salts with concentrations > 1e-3 m ['NaCl', 'Ca(HCO3)2'] >>> salt_dict['NaCl']['salt'] <pyEQL.salt_ion_match.Salt object at ...> >>> salt_dict['NaCl']['mol'] 1.0 >>> salt_dict = s1.get_salt_dict(cutoff=1e-4) >>> list(salt_dict) # Returns 'Ca(ClO)2' because of reduced cutoff and Cl has different oxidation state ['NaCl', 'Ca(HCO3)2', 'Ca(ClO)2'] >>> salt_dict = s1.get_salt_dict(cutoff=1e-4, use_totals=False) >>> list(salt_dict) # Returns salts with minor (same oxidation state) species since use_totals=False ['NaCl', 'Ca(HCO3)2', 'CaCO3', 'Ca(ClO)2']
-
equilibrate(atmosphere: bool =
False, solids: list[str] | None =None, gases: dict[str, str | float] | None =None, **kwargs) None[source]¶ This method follows the equilibrate logic used in the NativeEOS engine, adapted as the default behavior for this class.
Adjust the speciation of a Solution object to achieve chemical equilibrium.
- Keyword Arguments:¶
- atmosphere: bool =
False¶ Boolean indicating whether to equilibrate the solution w.r.t atmospheric gases. By default, this considers equilibrium with atmospheric CO2 (420 ppm) and O2 (0.21 atm). N2 is typically not considered due to its low solubility and limited impact on aqueous speciation.
- solids: list[str] | None =
None¶ A list of solids used to achieve liquid-solid equilibrium. Each solid in this list should be the name of a mineral phase present in the Phreeqc database (e.g. “Calcite”). We assume a target saturation index of 0 and an infinite amount of material.
- gases: dict[str, str | float] | None =
None¶ A dictionary of gases used to achieve liquid-gas equilibrium. Each key denotes the gas species, and the corresponding value denotes its concentration, as a log partial pressure value or other interpretable pressure units. For example, the following are equivalent (log10(0.000316) = -3.5) {“CO2”: “0.000316 atm”} {“CO2”: -3.5}
- **kwargs¶
Additional engine-specific options passed to the underlying equilbrium solver. These may include solver tolerances, or other advanced configuration parameters introduced in v1.4.0.
- atmosphere: bool =
-
get_activity_coefficient(solute: str, scale: 'molal' | 'molar' | 'fugacity' | 'rational' =
'molal') Quantity[source]¶ Return the activity coefficient of a solute in solution.
The model used to calculate the activity coefficient is determined by the Solution’s equation of state engine.
-
get_activity(solute: str, scale: 'molal' | 'molar' | 'rational' =
'molal') Quantity[source]¶ Return the thermodynamic activity of the solute in solution on the chosen concentration scale.
- Parameters:¶
- Returns:¶
The thermodynamic activity of the solute in question (dimensionless Quantity)
Notes
The thermodynamic activity depends on the concentration scale used [rs] . By default, the ionic strength, activity coefficients, and activities are all calculated based on the molal (mol/kg) concentration scale.
References
[rs]Robinson, R. A.; Stokes, R. H. Electrolyte Solutions: Second Revised Edition; Butterworths: London, 1968, p.32.
-
get_osmotic_coefficient(scale: 'molal' | 'molar' | 'rational' =
'molal') Quantity[source]¶ Return the osmotic coefficient of an aqueous solution.
The method used depends on the Solution object’s equation of state engine.
- get_water_activity() Quantity[source]¶
Return the water activity.
Notes
Water activity is related to the osmotic coefficient in a solution containing i solutes by:
\[\ln a_{w} = - \Phi M_{w} \sum_{i} m_{i}\]Where \(M_{w}\) is the molar mass of water (0.018015 kg/mol) and \(m_{i}\) is the molal concentration of each species.
If appropriate Pitzer model parameters are not available, the water activity is assumed equal to the mole fraction of water.
References
Blandamer, Mike J., Engberts, Jan B. F. N., Gleeson, Peter T., Reis, Joao Carlos R., 2005. “Activity of water in aqueous systems: A frequently neglected property.” Chemical Society Review 34, 440-458.
Examples
>>> s1 = pyEQL.Solution([['Na+','0.3 mol/kg'],['Cl-','0.3 mol/kg']]) >>> s1.get_water_activity() <Quantity(0.9900944932888518, 'dimensionless')>
-
get_chemical_potential_energy(activity_correction: bool =
True) Quantity[source]¶ Return the total chemical potential energy of a solution (not including pressure or electric effects).
- Parameters:¶
- Returns:¶
- Quantity
The actual or ideal chemical potential energy of the solution, in Joules.
Notes
The chemical potential energy (related to the Gibbs mixing energy) is calculated as follows: [koga]
\[E = R T \sum_i n_i \ln a_i\]or
\[E = R T \sum_i n_i \ln x_i\]Where \(n\) is the number of moles of substance, \(T\) is the temperature in kelvin, \(R\) the ideal gas constant, \(x\) the mole fraction, and \(a\) the activity of each component.
Note that dissociated ions must be counted as separate components, so a simple salt dissolved in water is a three component solution (cation, anion, and water).
References
[koga]Koga, Yoshikata, 2007. Solution Thermodynamics and its Application to Aqueous Solutions: A differential approach. Elsevier, 2007, pp. 23-37.
- _get_property(solute: str, name: str) Any | None[source]¶
Retrieve a thermodynamic property (such as diffusion coefficient) for solute, and adjust it from the reference conditions to the conditions of the solution.
- get_transference_number(solute: str) Quantity[source]¶
Alias of get_transport_number(). Note that the transference number is only equal to the transport number if there are no concentration or pressure gradients.
- get_transport_number(solute: str) Quantity[source]¶
Calculate the transference number of a solute in the solution. Note that this is the same as the _transport_ number if (and only if) there are no concentration or pressure gradients.
Notes
Transference number is calculated according to :
\[t_i = {D_i z_i^2 C_i \over \sum D_i z_i^2 C_i}\]Where \(C_i\) is the concentration in mol/L, \(D_i\) is the diffusion coefficient, and \(z_i\) is the charge, and the summation extends over all species in the solution.
Diffusion coefficients \(D_i\) are adjusted for the effects of temperature and ionic strength using the method implemented in PHREEQC >= 3.4. See get_diffusion_coefficient for further details.
References
Bieusheuvel, P.M.; Dykstra, J.E.; Introduction to Physical Processes in Environmental Technology, Section 6.2. https://www.physicsofelectrochemicalprocesses.com/book.pdf.
Geise, G. M.; Cassady, H. J.; Paul, D. R.; Logan, E.; Hickner, M. A. “Specific ion effects on membrane potential and the permselectivity of ion exchange membranes.”” Phys. Chem. Chem. Phys. 2014, 16, 21673-21681.
See also
get_transference_number()get_diffusion_coefficient()get_molar_conductivity()
- _get_molar_conductivity(solute: str) Quantity[source]¶
Calculate the molar (equivalent) conductivity for a solute.
- Parameters:¶
- Returns:¶
The molar or equivalent conductivity of the species in the solution. Zero if the solute is not charged.
Notes
Molar conductivity is calculated from the Nernst-Einstein relation [smed]
\[\lambda_i = \frac{F^2}{RT} D_i z_i^2\]Diffusion coefficients \(D_i\) are adjusted for the effects of temperature and ionic strength using the method implemented in PHREEQC >= 3.4. See get_diffusion_coefficient for further details.
References
- [smed]
Smedley, Stuart. The Interpretation of Ionic Conductivity in Liquids, pp 1-9. Plenum Press, 1980.
Appelo, C.A.J. Solute transport solved with the Nernst-Planck equation for concrete pores with ‘free’ water and a double layer. Cement and Concrete Research 101, 2017. https://dx.doi.org/10.1016/j.cemconres.2017.08.030
CRC Handbook of Chemistry and Physics
See also
get_diffusion_coefficient()
-
_get_diffusion_coefficient(solute: str, activity_correction: bool =
True) Quantity[source]¶ Get the temperature-adjusted diffusion coefficient of a solute.
- Parameters:¶
Notes
This method is equivalent to self.get_property(solute, “transport.diffusion_coefficient”) ONLY when the Solution temperature is the same as the reference temperature for the diffusion coefficient in the database (usually 25 C).
Otherwise, the reference D value is adjusted based on the Solution temperature and (optionally), ionic strength. The adjustments are
\[D_T = D_{298} \exp(\frac{d}{T} - \frac{d}{298}) \frac{\nu_{298}}{\nu_T}\]\[D_{\gamma} = D^0 \exp(\frac{-a1 A |z_i| \sqrt{I}}{1+\kappa a})\]\[\kappa a = B \sqrt{I} \frac{a2}{1+I^{0.75}}\]where a1, a2, and d are parameters from Ref. 2, A and B are the parameters used in the Debye Huckel equation, and I is the ionic strength. If the model parameters for a particular solute are not available, default values of d=0, a1=1.6, and a2=4.73 (as recommended in Ref. 2) are used instead.
References
Appelo, C.A.J. Solute transport solved with the Nernst-Planck equation for concrete pores with ‘free’ water and a double layer. Cement and Concrete Research 101, 2017. https://dx.doi.org/10.1016/j.cemconres.2017.08.030
CRC Handbook of Chemistry and Physics
See also
pyEQL.activity_correction._debye_parameter_B pyEQL.activity_correction._debye_parameter_activity
- _get_mobility(solute: str) Quantity[source]¶
Calculate the ionic mobility of the solute.
Note
This function uses the Einstein relation to convert a diffusion coefficient into an ionic mobility [smed]
\[\mu_i = {F |z_i| D_i \over RT}\]References
Smedley, Stuart I. The Interpretation of Ionic Conductivity in Liquids. Plenum Press, 1980.
- get_lattice_distance(solute: str) Quantity[source]¶
Calculate the average distance between molecules.
Calculate the average distance between molecules of the given solute, assuming that the molecules are uniformly distributed throughout the solution.
Examples
>>> soln = Solution([['Na+','0.5 mol/kg'],['Cl-','0.5 mol/kg']]) >>> soln.get_lattice_distance('Na+') 1.492964.... nanometerNotes
The lattice distance is related to the molar concentration as follows:
\[d = ( C_i N_A ) ^ {-{1 \over 3}}\]
- as_dict() dict[source]¶
Convert the Solution into a dict representation that can be serialized to .json or other format.
- classmethod from_dict(d: dict, **kwargs) Solution[source]¶
Instantiate a Solution from a dictionary generated by as_dict().
- Kwargs:
Any kwargs passed to this method will be passed to the Solution __init__ method, and will override any values in the dict.
- classmethod from_preset(preset: 'ash' | 'batt_mfg' | 'batt_recycling' | 'coal_washing' | 'CRL' | 'drilling' | 'excavation' | 'FGD' | 'flotation' | 'gasification' | 'geothermal' | 'leachate' | 'mine_drainage' | 'mine_tailings' | 'normal saline' | 'plating' | 'pw_conv' | 'pw_unconv' | 'rainwater' | 'refining' | 'Ringers lactate' | 'seawater' | 'semiconductor' | 'smelting' | 'tanning' | 'urine' | 'waste_gas' | 'wastewater', **kwargs) Solution[source]¶
Instantiate a solution from a preset composition.
- Parameters:¶
- Kwargs:
Any kwargs passed to this method will be passed to the Solution __init__ method, and will override any values in the preset file. This allows you to use a preset as a starting point and then modify it as needed by, e.g., changing the modeling engine or database.
- Returns:¶
A pyEQL Solution object.
- Raises:¶
FileNotFoundError – If the given preset file doesn’t exist on the file system.
Notes
The following sections explain the different solution options:
‘ash’ - bottom ash transport wastewater from fossil fuel combustion [kwptr2026]
‘batt_mfg’ - wastewater from lead-acid and legacy battery manufacturing processes [kwptr2026]
‘batt_recycling’ - wastewater from lithium ion battery recycling operations [kwptr2026]
‘coal_washing’ - wastewater generated from coal preparation and washing [kwptr2026]
‘CRL’ - combustion residual leachate (CRL) from fossil fuel combustion landfills [kwptr2026]
‘drilling’ - oil and gas drilling wastewater from drilling fluids and cuttings [kwptr2026]
‘excavation’ - wastewater from excavation in metal ore mining operations [kwptr2026]
‘FGD’ - flue gas desulfurization wastewater from SO2 removal from fossil fuel combustion [kwptr2026]
‘flotation’ - milling and flotation wastewater from metal ore extraction [kwptr2026]
‘gasification’ - wastewater from gasification of carbon-based feedstocks to syngas [kwptr2026]
‘geothermal’ - geothermal produced water from geothermal power generation [kwptr2026]
‘leachate’ - leachate from metal ore mining wastes [kwptr2026]
‘mine_drainage’ - acid mine drainage wastewater from coal and metal ore mining operations [kwptr2026]
‘mine_tailings’ - mine tailings pond water from collective metal ore and mining wastes [kwptr2026]
‘normal saline’ or ‘NS’ - normal saline solution used in medicine [saline]
‘plating’ - typical wastewater from metal electroplating operations [kwptr2026]
‘pw_conv’ - produced water from conventional hydrocarbon production [kwptr2026]
‘pw_unconv’ - produced water from unconventional hydrocarbon production [kwptr2026]
‘rainwater’ - pure water in equilibrium with atmospheric CO2 at pH 6
‘refining’ - petroleum refining wastewater from crude oil refineries [kwptr2026]
‘Ringers lacatate’ or ‘RL’ - Ringer’s lactate solution used in medicine [lactate]
‘seawater’ or ‘SW’- Standard Seawater. See Table 4 of the Reference for Composition [mf08]
‘semiconductor’ - semiconductor and electronics manufacturing wastewater [kwptr2026]
‘smelting’ - wastewater from metal ore smelting and refining from pyrometallurgical slags [kwptr2026]
‘tanning’ - wastewater from leather tanning and finishing operations [kwptr2026]
‘urine’ - typical human urine. See Table 3-15 of [me13]
‘waste_gas’ - wastewater from waste gas treatment during pyrometallurgical processing in metal ore and mining operations [kwptr2026]
‘wastewater’ or ‘WW’ - medium strength domestic wastewater. See Table 3-18 of [me13]
References
[mf08]Millero, Frank J. “The composition of Standard Seawater and the definition of the Reference-Composition Salinity Scale.” Deep-sea Research. Part I 55(1), 2008, 50-72.
[me13]Metcalf & Eddy, Inc. et al. Wastewater Engineering: Treatment and Resource Recovery, 5th Ed. McGraw-Hill, 2013.
[kwptr2026]Ryan S. Kingsbury, Monong Wang, Jaebeom Park et al. Composition and Critical Mineral Content of Major Industrial Wastewaters: Implications for Treatment and Resource Recovery Technologies, 05 February 2026, PREPRINT (Version 2) available at Research Square [https://www.researchsquare.com/article/rs-8743330/v2]
- classmethod from_file(filename: str | Path, **kwargs) Solution[source]¶
Loading from a .yaml or .json file.
- Parameters:¶
- Kwargs:
Any kwargs passed to this method will be passed to the Solution __init__ method, and will override any values in the file. This allows you to use a file as a starting point and then modify it as needed by, e.g., changing the modeling engine or database. NOTE: CURRENTLY ONLY SUPPORTED FOR YAML FILES!
- Returns:¶
A pyEQL Solution object.
- Raises:¶
FileNotFoundError – If the given filename doesn’t exist on the file system.
-
print(mode: 'all' | 'ions' | 'cations' | 'anions' | 'neutrals' =
'all', units: 'ppm' | 'mol' | 'mol/kg' | 'mol/L' | '%' | 'activity' ='mol', places=4)[source]¶ Print details about the Solution.
- Parameters:¶
- mode: 'all' | 'ions' | 'cations' | 'anions' | 'neutrals' =
'all'¶ Whether to list the amounts of all solutes, or only anions, cations, any ion, or any neutral solute.
- units: 'ppm' | 'mol' | 'mol/kg' | 'mol/L' | '%' | 'activity' =
'mol'¶ The units to list solute amounts in. “activity” will list dimensionless activities instead of concentrations.
- places=
4¶ The number of decimal places to round the solute amounts.
- mode: 'all' | 'ions' | 'cations' | 'anions' | 'neutrals' =
- add_solvent(formula: str, amount: str)[source]¶
Same as add_solute but omits the need to pass solvent mass to pint.
-
get_saturation_index(get_plot=
None) dict[source]¶ Calculate the saturation index of a solute in the solution. .. rubric:: Notes
The saturation index (\(\mathrm{SI}\)) is defined as log10(IAP/Ksp), where IAP is the ion activity product and Ksp is the solubility product constant. This method calculates the saturation index based on the active engine and database from __init__. The interpretation of the saturation index values is as follows:
\(\mathrm{SI} < 0\): The solution is undersaturated. The solid tends to dissolve if present.
\(\mathrm{SI} = 0\): The solution is at saturation equilibrium. Therefore, at the saturation limit, the SI is zero.
\(\mathrm{SI} > 0\): The solution is supersaturated. Precipitation is thermodynamically favored, although kinetic factors may delay or prevent it.