pyEQL 0.12.2__py2.py3-none-any.whl → 0.14.0__py2.py3-none-any.whl

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/solution.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
2
  pyEQL Solution Class.
3
3
 
4
- :copyright: 2013-2023 by Ryan S. Kingsbury
4
+ :copyright: 2013-2024 by Ryan S. Kingsbury
5
5
  :license: LGPL, see LICENSE for more details.
6
6
 
7
7
  """
@@ -61,50 +61,55 @@ class Solution(MSONable):
61
61
  Instantiate a Solution from a composition.
62
62
 
63
63
  Args:
64
- solutes : dict, optional. Keys must be the chemical formula, while values must be
65
- str Quantity representing the amount. For example:
66
-
67
- {"Na+": "0.1 mol/L", "Cl-": "0.1 mol/L"}
68
-
69
- Note that an older "list of lists" syntax is also supported; however this
70
- will be deprecated in the future and is no longer recommended. The equivalent
71
- list syntax for the above example is
72
-
73
- [["Na+", "0.1 mol/L"], ["Cl-", "0.1 mol/L"]]
74
-
75
- Defaults to empty (pure solvent) if omitted
76
- volume : str, optional
77
- Volume of the solvent, including the unit. Defaults to '1 L' if omitted.
78
- Note that the total solution volume will be computed using partial molar
79
- volumes of the respective solutes as they are added to the solution.
80
- temperature : str, optional
81
- The solution temperature, including the ureg. Defaults to '25 degC' if omitted.
82
- pressure : Quantity, optional
83
- The ambient pressure of the solution, including the unit.
84
- Defaults to '1 atm' if omitted.
85
- pH : number, optional
86
- Negative log of H+ activity. If omitted, the solution will be
87
- initialized to pH 7 (neutral) with appropriate quantities of
88
- H+ and OH- ions
89
- pe: the pE value (redox potential) of the solution. Lower values = more reducing,
64
+ solutes: dict, optional. Keys must be the chemical formula, while values must be
65
+ str Quantity representing the amount. For example:
66
+
67
+ {"Na+": "0.1 mol/L", "Cl-": "0.1 mol/L"}
68
+
69
+ Note that an older "list of lists" syntax is also supported; however this
70
+ will be deprecated in the future and is no longer recommended. The equivalent
71
+ list syntax for the above example is
72
+
73
+ [["Na+", "0.1 mol/L"], ["Cl-", "0.1 mol/L"]]
74
+
75
+ Defaults to empty (pure solvent) if omitted
76
+ volume: str, optional
77
+ Volume of the solvent, including the unit. Defaults to '1 L' if omitted.
78
+ Note that the total solution volume will be computed using partial molar
79
+ volumes of the respective solutes as they are added to the solution.
80
+ temperature: str, optional
81
+ The solution temperature, including the ureg. Defaults to '25 degC' if omitted.
82
+ pressure: Quantity, optional
83
+ The ambient pressure of the solution, including the unit.
84
+ Defaults to '1 atm' if omitted.
85
+ pH: number, optional
86
+ Negative log of H+ activity. If omitted, the solution will be
87
+ initialized to pH 7 (neutral) with appropriate quantities of
88
+ H+ and OH- ions
89
+ pE: the pE value (redox potential) of the solution. Lower values = more reducing,
90
90
  higher values = more oxidizing. At pH 7, water is stable between approximately
91
91
  -7 to +14. The default value corresponds to a pE value typical of natural
92
92
  waters in equilibrium with the atmosphere.
93
- balance_charge: The strategy for balancing charge during init and equilibrium calculations. Valid options are
94
- 'pH', which will adjust the solution pH to balance charge, 'pE' which will adjust the
95
- redox equilibrium to balance charge, or the name of a dissolved species e.g. 'Ca+2' or 'Cl-' that will be
96
- added/subtracted to balance charge. If set to None, no charge balancing will be performed either on init
97
- or when equilibrate() is called. Note that in this case, equilibrate() can distort the charge balance!
98
- solvent: Formula of the solvent. Solvents other than water are not supported at
99
- this time.
93
+ balance_charge: The strategy for balancing charge during init and equilibrium calculations. Valid options
94
+ are 'pH', which will adjust the solution pH to balance charge, 'pE' which will adjust the
95
+ redox equilibrium to balance charge, or the name of a dissolved species e.g. 'Ca+2' or 'Cl-'
96
+ that will be added/subtracted to balance charge. If set to None, no charge balancing will be
97
+ performed either on init or when equilibrate() is called. Note that in this case, equilibrate()
98
+ can distort the charge balance!
99
+ solvent: Formula of the solvent. Solvents other than water are not supported at this time.
100
100
  engine: Electrolyte modeling engine to use. See documentation for details on the available engines.
101
101
  database: path to a .json file (str or Path) or maggma Store instance that
102
102
  contains serialized SoluteDocs. `None` (default) will use the built-in pyEQL database.
103
103
  default_diffusion_coeff: Diffusion coefficient value in m^2/s to use in
104
- calculations when there is no diffusion coefficient for a species in the database. This affects several important property calculations including conductivity and transport number, which are related to the weighted sums of diffusion coefficients of all species. Setting this argument to zero will exclude any species that does not have a tabulated diffusion coefficient from these calculations, possibly resulting in underestimation of the conductivity and/or inaccurate transport numbers.
104
+ calculations when there is no diffusion coefficient for a species in the database. This affects several
105
+ important property calculations including conductivity and transport number, which are related to the
106
+ weighted sums of diffusion coefficients of all species. Setting this argument to zero will exclude any
107
+ species that does not have a tabulated diffusion coefficient from these calculations, possibly resulting
108
+ in underestimation of the conductivity and/or inaccurate transport numbers.
105
109
 
106
- Missing diffusion coefficients are especially likely in complex electrolytes containing, for example, complexes or paired species such as NaSO4[-1]. In such cases, setting default_diffusion_coeff to zero is likely to result in the above
107
- errors.
110
+ Missing diffusion coefficients are especially likely in complex electrolytes containing, for example,
111
+ complexes or paired species such as NaSO4[-1]. In such cases, setting default_diffusion_coeff to zero
112
+ is likely to result in the above errors.
108
113
 
109
114
  By default, this argument is set to the diffusion coefficient of NaCl salt, 1.61x10^-9 m2/s.
110
115
 
@@ -149,25 +154,28 @@ class Solution(MSONable):
149
154
  if isinstance(balance_charge, str) and balance_charge not in ["pH", "pE"]:
150
155
  self.balance_charge = standardize_formula(balance_charge)
151
156
  else:
152
- self.balance_charge = balance_charge
157
+ self.balance_charge = balance_charge #: Standardized formula of the species used for charge balancing.
153
158
 
154
159
  # instantiate a water substance for property retrieval
155
160
  self.water_substance = create_water_substance(self.temperature, self.pressure)
161
+ """IAPWS instance describing water properties."""
156
162
 
157
163
  # create an empty dictionary of components. This dict comprises {formula: moles}
158
164
  # where moles is the number of moles in the solution.
159
165
  self.components = FormulaDict({})
166
+ """Special dictionary where keys are standardized formula and values are the moles present in Solution."""
160
167
 
161
168
  # connect to the desired property database
162
169
  if database is None:
163
170
  # load the default database, which is a JSONStore
164
171
  db_store = IonDB
165
- elif isinstance(database, str | Path):
172
+ elif isinstance(database, (str, Path)):
166
173
  db_store = JSONStore(str(database), key="formula")
167
174
  logger.info(f"Created maggma JSONStore from .json file {database}")
168
175
  else:
169
176
  db_store = database
170
177
  self.database = db_store
178
+ """`Store` instance containing the solute property database."""
171
179
  self.database.connect()
172
180
  logger.info(f"Connected to property database {self.database!s}")
173
181
 
@@ -193,6 +201,7 @@ class Solution(MSONable):
193
201
  if solvent[0] not in ["H2O", "H2O(aq)", "water", "Water", "HOH"]:
194
202
  raise ValueError("Non-aqueous solvent detected. These are not yet supported!")
195
203
  self.solvent = standardize_formula(solvent[0])
204
+ """Formula of the component that is set as the solvent (currently only H2O(aq) is supported)."""
196
205
 
197
206
  # TODO - do I need the ability to specify the solvent mass?
198
207
  # # raise an error if the solvent volume has also been given
@@ -220,7 +229,8 @@ class Solution(MSONable):
220
229
  self.add_solute(k, v)
221
230
  elif isinstance(self._solutes, list):
222
231
  logger.warning(
223
- 'List input of solutes (e.g., [["Na+", "0.5 mol/L]]) is deprecated! Use dictionary formatted input (e.g., {"Na+":"0.5 mol/L"} instead.)'
232
+ 'List input of solutes (e.g., [["Na+", "0.5 mol/L]]) is deprecated! Use dictionary formatted input '
233
+ '(e.g., {"Na+":"0.5 mol/L"} instead.)'
224
234
  )
225
235
  for item in self._solutes:
226
236
  self.add_solute(*item)
@@ -241,7 +251,8 @@ class Solution(MSONable):
241
251
  ions = set().union(*[self.cations, self.anions]) # all ions
242
252
  if self.balance_charge not in ions:
243
253
  raise ValueError(
244
- f"Charge balancing species {self.balance_charge} was not found in the solution!. Species {ions} were found."
254
+ f"Charge balancing species {self.balance_charge} was not found in the solution!. "
255
+ f"Species {ions} were found."
245
256
  )
246
257
  z = self.get_property(balance_charge, "charge")
247
258
  self.components[balance_charge] += -1 * cb / z * self.volume.to("L").magnitude
@@ -256,13 +267,8 @@ class Solution(MSONable):
256
267
  Return the total mass of the solution.
257
268
 
258
269
  The mass is calculated each time this method is called.
259
- Parameters
260
- ----------
261
- None
262
270
 
263
- Returns:
264
- -------
265
- Quantity: the mass of the solution, in kg
271
+ Returns: The mass of the solution, in kg
266
272
 
267
273
  """
268
274
  mass = np.sum([self.get_amount(item, "kg").magnitude for item in self.components])
@@ -280,8 +286,7 @@ class Solution(MSONable):
280
286
  The mass of the solvent, in kg
281
287
 
282
288
  See Also:
283
- --------
284
- :py:meth:`get_amount()`
289
+ :py:meth:`get_amount()`
285
290
  """
286
291
  return self.get_amount(self.solvent, "kg")
287
292
 
@@ -291,8 +296,7 @@ class Solution(MSONable):
291
296
  Return the volume of the solution.
292
297
 
293
298
  Returns:
294
- -------
295
- Quantity: the volume of the solution, in L
299
+ Quantity: the volume of the solution, in L
296
300
  """
297
301
  # if the composition has changed, recalculate the volume first
298
302
  if self.volume_update_required is True:
@@ -310,17 +314,16 @@ class Solution(MSONable):
310
314
  volume : Total volume of the solution, including the unit, e.g. '1 L'
311
315
 
312
316
  Examples:
313
- ---------
314
- >>> mysol = Solution([['Na+','2 mol/L'],['Cl-','0.01 mol/L']],volume='500 mL')
315
- >>> print(mysol.volume)
316
- 0.5000883925072983 l
317
- >>> mysol.list_concentrations()
318
- {'H2O': '55.508435061791985 mol/kg', 'Cl-': '0.00992937605907076 mol/kg', 'Na+': '2.0059345573880325 mol/kg'}
319
- >>> mysol.volume = '200 mL')
320
- >>> print(mysol.volume)
321
- 0.2 l
322
- >>> mysol.list_concentrations()
323
- {'H2O': '55.50843506179199 mol/kg', 'Cl-': '0.00992937605907076 mol/kg', 'Na+': '2.0059345573880325 mol/kg'}
317
+ >>> mysol = Solution([['Na+','2 mol/L'],['Cl-','0.01 mol/L']],volume='500 mL')
318
+ >>> print(mysol.volume)
319
+ 0.5000883925072983 l
320
+ >>> mysol.list_concentrations()
321
+ {'H2O': '55.508435061791985 mol/kg', 'Cl-': '0.00992937605907076 mol/kg', 'Na+': '2.0059345573880325 mol/kg'}
322
+ >>> mysol.volume = '200 mL')
323
+ >>> print(mysol.volume)
324
+ 0.2 l
325
+ >>> mysol.list_concentrations()
326
+ {'H2O': '55.50843506179199 mol/kg', 'Cl-': '0.00992937605907076 mol/kg', 'Na+': '2.0059345573880325 mol/kg'}
324
327
 
325
328
  """
326
329
  # figure out the factor to multiply the old concentrations by
@@ -392,19 +395,17 @@ class Solution(MSONable):
392
395
 
393
396
  Generally used for expressing concentration of hydrogen ions (pH)
394
397
 
395
- Parameters
396
- ----------
397
- solute : str
398
- String representing the formula of the solute
399
- activity: bool, optional
400
- If False, the function will use the molar concentration rather
401
- than the activity to calculate p. Defaults to True.
398
+ Args:
399
+ solute : str
400
+ String representing the formula of the solute
401
+ activity: bool, optional
402
+ If False, the function will use the molar concentration rather
403
+ than the activity to calculate p. Defaults to True.
402
404
 
403
405
  Returns:
404
- -------
405
- Quantity
406
- The negative log10 of the activity (or molar concentration if
407
- activity = False) of the solute.
406
+ Quantity
407
+ The negative log10 of the activity (or molar concentration if
408
+ activity = False) of the solute.
408
409
  """
409
410
  try:
410
411
  if activity is True:
@@ -422,40 +423,35 @@ class Solution(MSONable):
422
423
  Density is calculated from the mass and volume each time this method is called.
423
424
 
424
425
  Returns:
425
- -------
426
- Quantity: The density of the solution.
426
+ Quantity: The density of the solution.
427
427
  """
428
428
  return self.mass / self.volume
429
429
 
430
430
  @property
431
431
  def dielectric_constant(self) -> Quantity:
432
- """
432
+ r"""
433
433
  Returns the dielectric constant of the solution.
434
434
 
435
- Parameters
436
- ----------
437
- None
435
+ Args:
436
+ None
438
437
 
439
438
  Returns:
440
- -------
441
- Quantity: the dielectric constant of the solution, dimensionless.
439
+ Quantity: the dielectric constant of the solution, dimensionless.
442
440
 
443
441
  Notes:
444
- -----
445
- Implements the following equation as given by Zuber et al.
442
+ Implements the following equation as given by Zuber et al.
446
443
 
447
- .. math:: \\epsilon = \\epsilon_{solvent} \\over 1 + \\sum_i \\alpha_i x_i
444
+ .. math:: \epsilon = \epsilon_{solvent} \over 1 + \sum_i \alpha_i x_i
448
445
 
449
- where :math:`\\alpha_i` is a coefficient specific to the solvent and ion, and :math:`x_i`
450
- is the mole fraction of the ion in solution.
446
+ where :math:`\alpha_i` is a coefficient specific to the solvent and ion, and :math:`x_i`
447
+ is the mole fraction of the ion in solution.
451
448
 
452
449
 
453
450
  References:
454
- ----------
455
- .A. Zuber, L. Cardozo-Filho, V.F. Cabral, R.F. Checoni, M. Castier,
456
- An empirical equation for the dielectric constant in aqueous and nonaqueous
457
- electrolyte mixtures, Fluid Phase Equilib. 376 (2014) 116-123.
458
- doi:10.1016/j.fluid.2014.05.037.
451
+ A. Zuber, L. Cardozo-Filho, V.F. Cabral, R.F. Checoni, M. Castier,
452
+ An empirical equation for the dielectric constant in aqueous and nonaqueous
453
+ electrolyte mixtures, Fluid Phase Equilib. 376 (2014) 116-123.
454
+ doi:10.1016/j.fluid.2014.05.037.
459
455
  """
460
456
  di_water = self.water_substance.epsilon
461
457
 
@@ -486,8 +482,9 @@ class Solution(MSONable):
486
482
  @property
487
483
  def elements(self) -> list:
488
484
  """
489
- Return a list of elements that are present in the solution. For example,
490
- a solution containing CaCO3 would return ["C", "Ca", "H", "O"]
485
+ Return a list of elements that are present in the solution.
486
+
487
+ For example, a solution containing CaCO3 would return ["C", "Ca", "H", "O"]
491
488
  """
492
489
  els = []
493
490
  for s in self.components:
@@ -497,24 +494,27 @@ class Solution(MSONable):
497
494
  @property
498
495
  def cations(self) -> dict[str, float]:
499
496
  """
500
- Returns the subset of `components` {formula: moles} that are cations. The returned dict is sorted by
501
- amount in descending order.
497
+ Returns the subset of `components` that are cations.
498
+
499
+ The returned dict is sorted by amount in descending order.
502
500
  """
503
501
  return {k: v for k, v in self.components.items() if self.get_property(k, "charge") > 0}
504
502
 
505
503
  @property
506
504
  def anions(self) -> dict[str, float]:
507
505
  """
508
- Returns the subset of `components` {formula: moles} that are anions. The returned dict is sorted by
509
- amount in descending order.
506
+ Returns the subset of `components` that are anions.
507
+
508
+ The returned dict is sorted by amount in descending order.
510
509
  """
511
510
  return {k: v for k, v in self.components.items() if self.get_property(k, "charge") < 0}
512
511
 
513
512
  @property
514
513
  def neutrals(self) -> dict[str, float]:
515
514
  """
516
- Returns the subset of `components` {formula: moles} that are neutral (not charged). The returned dict is sorted by
517
- amount in descending order.
515
+ Returns the subset of `components` that are neutral (not charged).
516
+
517
+ The returned dict is sorted by amount in descending order.
518
518
  """
519
519
  return {k: v for k, v in self.components.items() if self.get_property(k, "charge") == 0}
520
520
 
@@ -527,8 +527,7 @@ class Solution(MSONable):
527
527
  Calculated from the kinematic viscosity
528
528
 
529
529
  See Also:
530
- --------
531
- viscosity_kinematic
530
+ :attr:`viscosity_kinematic`
532
531
  """
533
532
  return self.viscosity_kinematic * self.density
534
533
 
@@ -555,37 +554,35 @@ class Solution(MSONable):
555
554
  # )
556
555
  @property
557
556
  def viscosity_kinematic(self) -> Quantity:
558
- """
557
+ r"""
559
558
  Return the kinematic viscosity of the solution.
560
559
 
561
560
  Notes:
562
- -----
563
- The calculation is based on a model derived from the Eyring equation
564
- and presented in
561
+ The calculation is based on a model derived from the Eyring equation
562
+ and presented in
565
563
 
566
- .. math::
564
+ .. math::
567
565
 
568
- \\ln \\nu = \\ln {\\nu_w MW_w \\over \\sum_i x_i MW_i } +
569
- 15 x_+^2 + x_+^3 \\delta G^*_{123} + 3 x_+ \\delta G^*_{23} (1-0.05x_+)
566
+ \ln \nu = \ln {\nu_w MW_w \over \sum_i x_i MW_i } +
567
+ 15 x_+^2 + x_+^3 \delta G^*_{123} + 3 x_+ \delta G^*_{23} (1-0.05x_+)
570
568
 
571
- Where:
569
+ Where:
572
570
 
573
- .. math:: \\delta G^*_{123} = a_o + a_1 (T)^{0.75}
574
- .. math:: \\delta G^*_{23} = b_o + b_1 (T)^{0.5}
571
+ .. math:: \delta G^*_{123} = a_o + a_1 (T)^{0.75}
572
+ .. math:: \delta G^*_{23} = b_o + b_1 (T)^{0.5}
575
573
 
576
- In which :math:`\\nu` is the kinematic viscosity, MW is the molecular weight,
577
- :math:`x_{+}` is the mole fraction of cations, and :math:`T` is the temperature in degrees C.
574
+ In which :math:`\nu` is the kinematic viscosity, MW is the molecular weight,
575
+ :math:`x_{+}` is the mole fraction of cations, and :math:`T` is the temperature in degrees C.
578
576
 
579
- The a and b fitting parameters for a variety of common salts are included in the
580
- database.
577
+ The a and b fitting parameters for a variety of common salts are included in the
578
+ database.
581
579
 
582
580
  References:
583
- ----------
584
- 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.
581
+ Vásquez-Castillo, G.; Iglesias-Silva, G. a.; Hall, K. R. An extension of the McAllister model to correlate
582
+ kinematic viscosity of electrolyte solutions. Fluid Phase Equilib. 2013, 358, 44-49.
585
583
 
586
584
  See Also:
587
- --------
588
- :py:meth:`viscosity_dynamic`
585
+ :py:meth:`viscosity_dynamic`
589
586
  """
590
587
  # identify the main salt in the solution
591
588
  salt = self.get_salt()
@@ -631,7 +628,7 @@ class Solution(MSONable):
631
628
 
632
629
  @property
633
630
  def conductivity(self) -> Quantity:
634
- """
631
+ r"""
635
632
  Compute the electrical conductivity of the solution.
636
633
 
637
634
  Returns:
@@ -643,13 +640,13 @@ class Solution(MSONable):
643
640
 
644
641
  .. math::
645
642
 
646
- EC = {F^2 \\over R T} \\sum_i D_i z_i ^ 2 m_i = \\sum_i \\lambda_i m_i
643
+ EC = {F^2 \over R T} \sum_i D_i z_i ^ 2 m_i = \sum_i \lambda_i m_i
647
644
 
648
645
  Where :math:`D_i` is the diffusion coefficient, :math:`m_i` is the molal concentration,
649
646
  :math:`z_i` is the charge, and the summation extends over all species in the solution.
650
- Alternatively, :math:`\\lambda_i` is the molar conductivity of solute i.
647
+ Alternatively, :math:`\lambda_i` is the molar conductivity of solute i.
651
648
 
652
- Diffusion coefficients :math:`D_i` (and molar conductivities :math:`\\lambda_i`) are
649
+ Diffusion coefficients :math:`D_i` (and molar conductivities :math:`\lambda_i`) are
653
650
  adjusted for the effects of temperature and ionic strength using the method implemented
654
651
  in PHREEQC >= 3.4. [aq]_ [hc]_ See `get_diffusion_coefficient for` further details.
655
652
 
@@ -658,9 +655,9 @@ class Solution(MSONable):
658
655
  .. [hc] http://www.hydrochemistry.eu/exmpls/sc.html
659
656
 
660
657
  See Also:
661
- :py:attr:`get_diffusion_coefficient`
662
- :py:meth:`get_molar_conductivity`
663
658
  :py:attr:`ionic_strength`
659
+ :py:meth:`get_diffusion_coefficient`
660
+ :py:meth:`get_molar_conductivity`
664
661
  """
665
662
  EC = ureg.Quantity(
666
663
  np.asarray(
@@ -675,7 +672,7 @@ class Solution(MSONable):
675
672
 
676
673
  @property
677
674
  def ionic_strength(self) -> Quantity:
678
- """
675
+ r"""
679
676
  Return the ionic strength of the solution.
680
677
 
681
678
  Return the ionic strength of the solution, calculated as 1/2 * sum ( molality * charge ^2) over all the ions.
@@ -683,32 +680,28 @@ class Solution(MSONable):
683
680
  Molal (mol/kg) scale concentrations are used for compatibility with the activity correction formulas.
684
681
 
685
682
  Returns:
686
- -------
687
- Quantity :
688
- The ionic strength of the parent solution, mol/kg.
683
+ Quantity:
684
+ The ionic strength of the parent solution, mol/kg.
689
685
 
690
686
  See Also:
691
- --------
692
- :py:meth:`get_activity`
693
- :py:meth:`get_water_activity`
687
+ :py:meth:`get_activity`
688
+ :py:meth:`get_water_activity`
694
689
 
695
690
  Notes:
696
- -----
697
- The ionic strength is calculated according to:
691
+ The ionic strength is calculated according to:
698
692
 
699
- .. math:: I = \\sum_i m_i z_i^2
693
+ .. math:: I = \sum_i m_i z_i^2
700
694
 
701
- Where :math:`m_i` is the molal concentration and :math:`z_i` is the charge on species i.
695
+ Where :math:`m_i` is the molal concentration and :math:`z_i` is the charge on species i.
702
696
 
703
697
  Examples:
704
- --------
705
- >>> s1 = pyEQL.Solution([['Na+','0.2 mol/kg'],['Cl-','0.2 mol/kg']])
706
- >>> s1.ionic_strength
707
- <Quantity(0.20000010029672785, 'mole / kilogram')>
698
+ >>> s1 = pyEQL.Solution([['Na+','0.2 mol/kg'],['Cl-','0.2 mol/kg']])
699
+ >>> s1.ionic_strength
700
+ <Quantity(0.20000010029672785, 'mole / kilogram')>
708
701
 
709
- >>> s1 = pyEQL.Solution([['Mg+2','0.3 mol/kg'],['Na+','0.1 mol/kg'],['Cl-','0.7 mol/kg']],temperature='30 degC')
710
- >>> s1.ionic_strength
711
- <Quantity(1.0000001004383303, 'mole / kilogram')>
702
+ >>> s1 = pyEQL.Solution([['Mg+2','0.3 mol/kg'],['Na+','0.1 mol/kg'],['Cl-','0.7 mol/kg']],temperature='30 degC')
703
+ >>> s1.ionic_strength
704
+ <Quantity(1.0000001004383303, 'mole / kilogram')>
712
705
  """
713
706
  # compute using magnitudes only, for performance reasons
714
707
  ionic_strength = np.sum(
@@ -720,21 +713,20 @@ class Solution(MSONable):
720
713
 
721
714
  @property
722
715
  def charge_balance(self) -> float:
723
- """
716
+ r"""
724
717
  Return the charge balance of the solution.
725
718
 
726
719
  Return the charge balance of the solution. The charge balance represents the net electric charge
727
720
  on the solution and SHOULD equal zero at all times, but due to numerical errors will usually
728
721
  have a small nonzero value. It is calculated according to:
729
722
 
730
- .. math:: CB = \\sum_i C_i z_i
723
+ .. math:: CB = \sum_i C_i z_i
731
724
 
732
725
  where :math:`C_i` is the molar concentration, and :math:`z_i` is the charge on species i.
733
726
 
734
727
  Returns:
735
- -------
736
- float :
737
- The charge balance of the solution, in equivalents (mol of charge) per L.
728
+ float :
729
+ The charge balance of the solution, in equivalents (mol of charge) per L.
738
730
 
739
731
  """
740
732
  charge_balance = 0
@@ -746,28 +738,24 @@ class Solution(MSONable):
746
738
  # TODO - consider adding guard statements to prevent alkalinity from being negative
747
739
  @property
748
740
  def alkalinity(self) -> Quantity:
749
- """
741
+ r"""
750
742
  Return the alkalinity or acid neutralizing capacity of a solution.
751
743
 
752
744
  Returns:
753
- -------
754
- Quantity :
755
- The alkalinity of the solution in mg/L as CaCO3
745
+ Quantity: The alkalinity of the solution in mg/L as CaCO3
756
746
 
757
747
  Notes:
758
- -----
759
- The alkalinity is calculated according to [stm]_
748
+ The alkalinity is calculated according to [stm]_
760
749
 
761
- .. math:: Alk = \\sum_{i} z_{i} C_{B} + \\sum_{i} z_{i} C_{A}
750
+ .. math:: Alk = \sum_{i} z_{i} C_{B} + \sum_{i} z_{i} C_{A}
762
751
 
763
- Where :math:`C_{B}` and :math:`C_{A}` are conservative cations and anions, respectively
764
- (i.e. ions that do not participate in acid-base reactions), and :math:`z_{i}` is their signed charge.
765
- In this method, the set of conservative cations is all Group I and Group II cations, and the
766
- conservative anions are all the anions of strong acids.
752
+ Where :math:`C_{B}` and :math:`C_{A}` are conservative cations and anions, respectively
753
+ (i.e. ions that do not participate in acid-base reactions), and :math:`z_{i}` is their signed charge.
754
+ In this method, the set of conservative cations is all Group I and Group II cations, and the
755
+ conservative anions are all the anions of strong acids.
767
756
 
768
757
  References:
769
- ----------
770
- .. [stm] Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 165. Wiley Interscience, 1996.
758
+ .. [stm] Stumm, Werner and Morgan, James J. Aquatic Chemistry, 3rd ed, pp 165. Wiley Interscience, 1996.
771
759
 
772
760
  """
773
761
  alkalinity = ureg.Quantity(0, "mol/L")
@@ -807,14 +795,9 @@ class Solution(MSONable):
807
795
  NOTE: at present pyEQL cannot distinguish between mg/L as CaCO3
808
796
  and mg/L units. Use with caution.
809
797
 
810
- Parameters
811
- ----------
812
- None
813
-
814
798
  Returns:
815
- -------
816
- Quantity
817
- The hardness of the solution in mg/L as CaCO3
799
+ Quantity:
800
+ The hardness of the solution in mg/L as CaCO3
818
801
 
819
802
  """
820
803
  hardness = ureg.Quantity(0, "mol/L")
@@ -832,7 +815,8 @@ class Solution(MSONable):
832
815
  """
833
816
  Total dissolved solids in mg/L (equivalent to ppm) including both charged and uncharged species.
834
817
 
835
- 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]].
818
+ The TDS is defined as the sum of the concentrations of all aqueous solutes (not including the solvent),
819
+ except for H[+1] and OH[-1]].
836
820
  """
837
821
  tds = ureg.Quantity(0, "mg/L")
838
822
  for s in self.components:
@@ -845,23 +829,21 @@ class Solution(MSONable):
845
829
 
846
830
  @property
847
831
  def TDS(self) -> Quantity:
848
- """
849
- Alias of :py:meth:`total_dissolved_solids`
850
- """
832
+ """Alias of :py:meth:`total_dissolved_solids`."""
851
833
  return self.total_dissolved_solids
852
834
 
853
835
  @property
854
836
  def debye_length(self) -> Quantity:
855
- """
837
+ r"""
856
838
  Return the Debye length of a solution.
857
839
 
858
840
  Debye length is calculated as [wk3]_
859
841
 
860
842
  .. math::
861
843
 
862
- \\kappa^{-1} = \\sqrt({\\epsilon_r \\epsilon_o k_B T \\over (2 N_A e^2 I)})
844
+ \kappa^{-1} = \sqrt({\epsilon_r \epsilon_o k_B T \over (2 N_A e^2 I)})
863
845
 
864
- where :math:`I` is the ionic strength, :math:`\\epsilon_r` and :math:`\\epsilon_r`
846
+ where :math:`I` is the ionic strength, :math:`\epsilon_r` and :math:`\epsilon_r`
865
847
  are the relative permittivity and vacuum permittivity, :math:`k_B` is the
866
848
  Boltzmann constant, and :math:`T` is the temperature, :math:`e` is the
867
849
  elementary charge, and :math:`N_A` is Avogadro's number.
@@ -869,7 +851,7 @@ class Solution(MSONable):
869
851
  Returns The Debye length, in nanometers.
870
852
 
871
853
  References:
872
- .. [wk3] https://en.wikipedia.org/wiki/Debye_length#Debye_length_in_an_electrolyte
854
+ .. [wk3] https://en.wikipedia.org/wiki/Debye_length#Debye_length_in_an_electrolyte
873
855
 
874
856
  See Also:
875
857
  :attr:`ionic_strength`
@@ -892,43 +874,35 @@ class Solution(MSONable):
892
874
 
893
875
  @property
894
876
  def bjerrum_length(self) -> Quantity:
895
- """
877
+ r"""
896
878
  Return the Bjerrum length of a solution.
897
879
 
898
880
  Bjerrum length represents the distance at which electrostatic
899
881
  interactions between particles become comparable in magnitude
900
- to the thermal energy.:math:`\\lambda_B` is calculated as
882
+ to the thermal energy.:math:`\lambda_B` is calculated as
901
883
 
902
884
  .. math::
903
885
 
904
- \\lambda_B = {e^2 \\over (4 \\pi \\epsilon_r \\epsilon_o k_B T)}
886
+ \lambda_B = {e^2 \over (4 \pi \epsilon_r \epsilon_o k_B T)}
905
887
 
906
- where :math:`e` is the fundamental charge, :math:`\\epsilon_r` and :math:`\\epsilon_r`
888
+ where :math:`e` is the fundamental charge, :math:`\epsilon_r` and :math:`\epsilon_r`
907
889
  are the relative permittivity and vacuum permittivity, :math:`k_B` is the
908
890
  Boltzmann constant, and :math:`T` is the temperature.
909
891
 
910
- Parameters
911
- ----------
912
- None
913
-
914
892
  Returns:
915
- -------
916
- Quantity
917
- The Bjerrum length, in nanometers.
893
+ Quantity:
894
+ The Bjerrum length, in nanometers.
918
895
 
919
896
  References:
920
- ----------
921
- https://en.wikipedia.org/wiki/Bjerrum_length
897
+ https://en.wikipedia.org/wiki/Bjerrum_length
922
898
 
923
899
  Examples:
924
- --------
925
- >>> s1 = pyEQL.Solution()
926
- >>> s1.bjerrum_length
927
- <Quantity(0.7152793009386953, 'nanometer')>
900
+ >>> s1 = pyEQL.Solution()
901
+ >>> s1.bjerrum_length
902
+ <Quantity(0.7152793009386953, 'nanometer')>
928
903
 
929
904
  See Also:
930
- --------
931
- :attr:`dielectric_constant`
905
+ :attr:`dielectric_constant`
932
906
 
933
907
  """
934
908
  bjerrum_length = ureg.e**2 / (
@@ -938,23 +912,23 @@ class Solution(MSONable):
938
912
 
939
913
  @property
940
914
  def osmotic_pressure(self) -> Quantity:
941
- """
915
+ r"""
942
916
  Return the osmotic pressure of the solution relative to pure water.
943
917
 
944
918
  Returns:
945
919
  The osmotic pressure of the solution relative to pure water in Pa
946
920
 
947
921
  See Also:
948
- get_water_activity
949
- get_osmotic_coefficient
950
- get_salt
922
+ :attr:`get_water_activity`
923
+ :attr:`get_osmotic_coefficient`
924
+ :attr:`get_salt`
951
925
 
952
926
  Notes:
953
927
  Osmotic pressure is calculated based on the water activity [sata]_ [wk]_
954
928
 
955
- .. math:: \\Pi = -\\frac{RT}{V_{w}} \\ln a_{w}
929
+ .. math:: \Pi = -\frac{RT}{V_{w}} \ln a_{w}
956
930
 
957
- Where :math:`\\Pi` is the osmotic pressure, :math:`V_{w}` is the partial
931
+ Where :math:`\Pi` is the osmotic pressure, :math:`V_{w}` is the partial
958
932
  molar volume of water (18.2 cm**3/mol), and :math:`a_{w}` is the water
959
933
  activity.
960
934
 
@@ -1000,30 +974,26 @@ class Solution(MSONable):
1000
974
  8. number of molecules ('count')
1001
975
  9. "parts-per-x" units, where ppm = mg/L, ppb = ug/L ppt = ng/L
1002
976
 
1003
- Parameters
1004
- ----------
1005
- solute : str
1006
- String representing the name of the solute of interest
1007
- units : str
1008
- Units desired for the output. Examples of valid units are
1009
- 'mol/L','mol/kg','mol', 'kg', and 'g/L'
1010
- Use 'fraction' to return the mole fraction.
1011
- Use '%' to return the mass percent
977
+ Args:
978
+ solute : str
979
+ String representing the name of the solute of interest
980
+ units : str
981
+ Units desired for the output. Examples of valid units are
982
+ 'mol/L','mol/kg','mol', 'kg', and 'g/L'
983
+ Use 'fraction' to return the mole fraction.
984
+ Use '%' to return the mass percent
1012
985
 
1013
986
  Returns:
1014
- -------
1015
- The amount of the solute in question, in the specified units
1016
-
987
+ The amount of the solute in question, in the specified units
1017
988
 
1018
989
  See Also:
1019
- --------
1020
- add_amount
1021
- set_amount
1022
- get_total_amount
1023
- get_osmolarity
1024
- get_osmolality
1025
- get_mass
1026
- get_total_moles_solute
990
+ :attr:`mass`
991
+ :meth:`add_amount`
992
+ :meth:`set_amount`
993
+ :meth:`get_total_amount`
994
+ :meth:`get_osmolarity`
995
+ :meth:`get_osmolality`
996
+ :meth:`get_total_moles_solute`
1027
997
  """
1028
998
  z = 1
1029
999
  # sanitized unit to be passed to pint
@@ -1085,8 +1055,9 @@ class Solution(MSONable):
1085
1055
 
1086
1056
  def get_components_by_element(self) -> dict[str, list]:
1087
1057
  """
1088
- Return a list of all species associated with a given element. Elements (keys) are
1089
- suffixed with their oxidation state in parentheses, e.g.,
1058
+ Return a list of all species associated with a given element.
1059
+
1060
+ Elements (keys) are suffixed with their oxidation state in parentheses, e.g.,
1090
1061
 
1091
1062
  {"Na(1.0)":["Na[+1]", "NaOH(aq)"]}
1092
1063
 
@@ -1117,7 +1088,7 @@ class Solution(MSONable):
1117
1088
 
1118
1089
  def get_el_amt_dict(self):
1119
1090
  """
1120
- Return a dict of Element: amount in mol
1091
+ Return a dict of Element: amount in mol.
1121
1092
 
1122
1093
  Elements (keys) are suffixed with their oxidation state in parentheses,
1123
1094
  e.g. "Fe(2.0)", "Cl(-1.0)".
@@ -1153,17 +1124,15 @@ class Solution(MSONable):
1153
1124
  element: The symbol of the element of interest. The symbol can optionally be followed by the
1154
1125
  oxidation state in parentheses, e.g., "Na(1.0)", "Fe(2.0)", or "O(0.0)". If no oxidation state
1155
1126
  is given, the total concentration of the element (over all oxidation states) is returned.
1156
- units : str
1157
- Units desired for the output. Examples of valid units are
1158
- 'mol/L','mol/kg','mol', 'kg', and 'g/L'
1127
+ units : str
1128
+ Units desired for the output. Examples of valid units are
1129
+ 'mol/L','mol/kg','mol', 'kg', and 'g/L'
1159
1130
 
1160
1131
  Returns:
1161
- -------
1162
- The total amount of the element in the solution, in the specified units
1132
+ The total amount of the element in the solution, in the specified units
1163
1133
 
1164
- See Also
1165
- --------
1166
- get_amount
1134
+ See Also:
1135
+ :meth:`get_amount`
1167
1136
  """
1168
1137
  TOT: Quantity = 0
1169
1138
 
@@ -1211,14 +1180,11 @@ class Solution(MSONable):
1211
1180
  def add_solute(self, formula: str, amount: str):
1212
1181
  """Primary method for adding substances to a pyEQL solution.
1213
1182
 
1214
- Parameters
1215
- ----------
1216
- formula : str
1217
- Chemical formula for the solute.
1218
- Charged species must contain a + or - and (for polyvalent solutes) a number representing the net charge (e.g. 'SO4-2').
1219
- amount : str
1220
- The amount of substance in the specified unit system. The string should contain both a quantity and
1221
- a pint-compatible representation of a ureg. e.g. '5 mol/kg' or '0.1 g/L'
1183
+ Args:
1184
+ formula (str): Chemical formula for the solute. Charged species must contain a + or - and
1185
+ (for polyvalent solutes) a number representing the net charge (e.g. 'SO4-2').
1186
+ amount (str): The amount of substance in the specified unit system. The string should contain
1187
+ both a quantity and a pint-compatible representation of a ureg. e.g. '5 mol/kg' or '0.1 g/L'.
1222
1188
  """
1223
1189
  # if units are given on a per-volume basis,
1224
1190
  # iteratively solve for the amount of solute that will preserve the
@@ -1282,21 +1248,19 @@ class Solution(MSONable):
1282
1248
  """
1283
1249
  Add the amount of 'solute' to the parent solution.
1284
1250
 
1285
- Parameters
1286
- ----------
1287
- solute : str
1288
- String representing the name of the solute of interest
1289
- amount : str quantity
1290
- String representing the concentration desired, e.g. '1 mol/kg'
1291
- If the units are given on a per-volume basis, the solution
1292
- volume is not recalculated
1293
- If the units are given on a mass, substance, per-mass, or
1294
- per-substance basis, then the solution volume is recalculated
1295
- based on the new composition
1251
+ Args:
1252
+ solute : str
1253
+ String representing the name of the solute of interest
1254
+ amount : str quantity
1255
+ String representing the concentration desired, e.g. '1 mol/kg'
1256
+ If the units are given on a per-volume basis, the solution
1257
+ volume is not recalculated
1258
+ If the units are given on a mass, substance, per-mass, or
1259
+ per-substance basis, then the solution volume is recalculated
1260
+ based on the new composition
1296
1261
 
1297
1262
  Returns:
1298
- -------
1299
- Nothing. The concentration of solute is modified.
1263
+ Nothing. The concentration of solute is modified.
1300
1264
  """
1301
1265
  # if units are given on a per-volume basis,
1302
1266
  # iteratively solve for the amount of solute that will preserve the
@@ -1378,26 +1342,24 @@ class Solution(MSONable):
1378
1342
  """
1379
1343
  Set the amount of 'solute' in the parent solution.
1380
1344
 
1381
- Parameters
1382
- ----------
1383
- solute : str
1384
- String representing the name of the solute of interest
1385
- amount : str Quantity
1386
- String representing the concentration desired, e.g. '1 mol/kg'
1387
- If the units are given on a per-volume basis, the solution
1388
- volume is not recalculated and the molar concentrations of
1389
- other components in the solution are not altered, while the
1390
- molal concentrations are modified.
1391
-
1392
- If the units are given on a mass, substance, per-mass, or
1393
- per-substance basis, then the solution volume is recalculated
1394
- based on the new composition and the molal concentrations of
1395
- other components are not altered, while the molar concentrations
1396
- are modified.
1345
+ Args:
1346
+ solute : str
1347
+ String representing the name of the solute of interest
1348
+ amount : str Quantity
1349
+ String representing the concentration desired, e.g. '1 mol/kg'
1350
+ If the units are given on a per-volume basis, the solution
1351
+ volume is not recalculated and the molar concentrations of
1352
+ other components in the solution are not altered, while the
1353
+ molal concentrations are modified.
1354
+
1355
+ If the units are given on a mass, substance, per-mass, or
1356
+ per-substance basis, then the solution volume is recalculated
1357
+ based on the new composition and the molal concentrations of
1358
+ other components are not altered, while the molar concentrations
1359
+ are modified.
1397
1360
 
1398
1361
  Returns:
1399
- -------
1400
- Nothing. The concentration of solute is modified.
1362
+ Nothing. The concentration of solute is modified.
1401
1363
 
1402
1364
  """
1403
1365
  # raise an error if a negative amount is specified
@@ -1482,13 +1444,12 @@ class Solution(MSONable):
1482
1444
  def get_osmolarity(self, activity_correction=False) -> Quantity:
1483
1445
  """Return the osmolarity of the solution in Osm/L.
1484
1446
 
1485
- Parameters
1486
- ----------
1487
- activity_correction : bool
1488
- If TRUE, the osmotic coefficient is used to calculate the
1489
- osmolarity. This correction is appropriate when trying to predict
1490
- the osmolarity that would be measured from e.g. freezing point
1491
- depression. Defaults to FALSE if omitted.
1447
+ Args:
1448
+ activity_correction : bool
1449
+ If TRUE, the osmotic coefficient is used to calculate the
1450
+ osmolarity. This correction is appropriate when trying to predict
1451
+ the osmolarity that would be measured from e.g. freezing point
1452
+ depression. Defaults to FALSE if omitted.
1492
1453
  """
1493
1454
  factor = self.get_osmotic_coefficient() if activity_correction is True else 1
1494
1455
  return factor * self.get_total_moles_solute() / self.volume.to("L")
@@ -1496,13 +1457,12 @@ class Solution(MSONable):
1496
1457
  def get_osmolality(self, activity_correction=False) -> Quantity:
1497
1458
  """Return the osmolality of the solution in Osm/kg.
1498
1459
 
1499
- Parameters
1500
- ----------
1501
- activity_correction : bool
1502
- If TRUE, the osmotic coefficient is used to calculate the
1503
- osmolarity. This correction is appropriate when trying to predict
1504
- the osmolarity that would be measured from e.g. freezing point
1505
- depression. Defaults to FALSE if omitted.
1460
+ Args:
1461
+ activity_correction : bool
1462
+ If TRUE, the osmotic coefficient is used to calculate the
1463
+ osmolarity. This correction is appropriate when trying to predict
1464
+ the osmolarity that would be measured from e.g. freezing point
1465
+ depression. Defaults to FALSE if omitted.
1506
1466
  """
1507
1467
  factor = self.get_osmotic_coefficient() if activity_correction is True else 1
1508
1468
  return factor * self.get_total_moles_solute() / self.solvent_mass.to("kg")
@@ -1529,13 +1489,12 @@ class Solution(MSONable):
1529
1489
  Salt object containing information about the parent salt.
1530
1490
 
1531
1491
  See Also:
1532
- --------
1533
- :py:meth:`get_activity`
1534
- :py:meth:`get_activity_coefficient`
1535
- :py:meth:`get_water_activity`
1536
- :py:meth:`get_osmotic_coefficient`
1537
- :py:meth:`get_osmotic_pressure`
1538
- :py:meth:`get_viscosity_kinematic`
1492
+ :py:meth:`get_activity`
1493
+ :py:meth:`get_activity_coefficient`
1494
+ :py:meth:`get_water_activity`
1495
+ :py:meth:`get_osmotic_coefficient`
1496
+ :py:attr:`osmotic_pressure`
1497
+ :py:attr:`viscosity_kinematic`
1539
1498
 
1540
1499
  Examples:
1541
1500
  >>> s1 = Solution([['Na+','0.5 mol/kg'],['Cl-','0.5 mol/kg']])
@@ -1590,23 +1549,17 @@ class Solution(MSONable):
1590
1549
  enable its effective concentration to be calculated
1591
1550
  (e.g., 1 M MgCl2 yields 1 M Mg+2 and 2 M Cl-).
1592
1551
 
1593
- Parameters
1594
- ----------
1595
- None
1596
-
1597
1552
  Returns:
1598
- -------
1599
- dict
1600
- A dictionary of Salt objects, keyed to the salt formula
1553
+ dict
1554
+ A dictionary of Salt objects, keyed to the salt formula
1601
1555
 
1602
1556
  See Also:
1603
- --------
1604
- :py:meth:`get_activity`
1605
- :py:meth:`get_activity_coefficient`
1606
- :py:meth:`get_water_activity`
1607
- :py:meth:`get_osmotic_coefficient`
1608
- :py:meth:`get_osmotic_pressure`
1609
- :py:meth:`get_viscosity_kinematic`
1557
+ :py:attr:`osmotic_pressure`
1558
+ :py:attr:`viscosity_kinematic`
1559
+ :py:meth:`get_activity`
1560
+ :py:meth:`get_activity_coefficient`
1561
+ :py:meth:`get_water_activity`
1562
+ :py:meth:`get_osmotic_coefficient`
1610
1563
  """
1611
1564
  """
1612
1565
  Returns a dict of salts that approximates the composition of the Solution. Like `components`, the dict is
@@ -1617,9 +1570,9 @@ class Solution(MSONable):
1617
1570
  of their respective equivalent amounts.
1618
1571
 
1619
1572
  See Also:
1620
- Solution.components
1621
- Solution.cations
1622
- Solution.anions
1573
+ :attr:`components`
1574
+ :attr:`cations`
1575
+ :attr:`anions`
1623
1576
  """
1624
1577
  salt_dict: dict[str, float] = {}
1625
1578
 
@@ -1732,8 +1685,9 @@ class Solution(MSONable):
1732
1685
 
1733
1686
  def equilibrate(self, **kwargs) -> None:
1734
1687
  """
1735
- Update the composition of the Solution using the thermodynamic engine. Any kwargs specified are passed through
1736
- to self.engine.equilibrate()
1688
+ Update the composition of the Solution using the thermodynamic engine.
1689
+
1690
+ Any kwargs specified are passed through to self.engine.equilibrate()
1737
1691
 
1738
1692
  Returns:
1739
1693
  Nothing. The .components attribute of the Solution is updated.
@@ -1820,8 +1774,8 @@ class Solution(MSONable):
1820
1774
  Edition; Butterworths: London, 1968, p.32.
1821
1775
 
1822
1776
  See Also:
1823
- :py:meth:`get_activity_coefficient`
1824
1777
  :attr:`ionic_strength`
1778
+ :py:meth:`get_activity_coefficient`
1825
1779
  :py:meth:`get_salt`
1826
1780
 
1827
1781
  """
@@ -1873,42 +1827,37 @@ class Solution(MSONable):
1873
1827
  raise ValueError("Invalid scale argument. Pass 'molal', 'rational', or 'fugacity'.")
1874
1828
 
1875
1829
  def get_water_activity(self) -> Quantity:
1876
- """
1830
+ r"""
1877
1831
  Return the water activity.
1878
1832
 
1879
1833
  Returns:
1880
- -------
1881
- Quantity :
1882
- The thermodynamic activity of water in the solution.
1834
+ Quantity:
1835
+ The thermodynamic activity of water in the solution.
1883
1836
 
1884
1837
  See Also:
1885
- --------
1886
- :py:meth:`get_activity_coefficient`
1887
- :attr:`ionic_strength`
1888
- :py:meth:`get_salt`
1838
+ :attr:`ionic_strength`
1839
+ :py:meth:`get_activity_coefficient`
1840
+ :py:meth:`get_salt`
1889
1841
 
1890
1842
  Notes:
1891
- -----
1892
- Water activity is related to the osmotic coefficient in a solution containing i solutes by:
1843
+ Water activity is related to the osmotic coefficient in a solution containing i solutes by:
1893
1844
 
1894
- .. math:: \\ln a_{w} = - \\Phi M_{w} \\sum_{i} m_{i}
1845
+ .. math:: \ln a_{w} = - \Phi M_{w} \sum_{i} m_{i}
1895
1846
 
1896
- Where :math:`M_{w}` is the molar mass of water (0.018015 kg/mol) and :math:`m_{i}` is the molal concentration
1897
- of each species.
1847
+ Where :math:`M_{w}` is the molar mass of water (0.018015 kg/mol) and :math:`m_{i}` is the molal
1848
+ concentration of each species.
1898
1849
 
1899
- If appropriate Pitzer model parameters are not available, the
1900
- water activity is assumed equal to the mole fraction of water.
1850
+ If appropriate Pitzer model parameters are not available, the
1851
+ water activity is assumed equal to the mole fraction of water.
1901
1852
 
1902
1853
  References:
1903
- ----------
1904
- Blandamer, Mike J., Engberts, Jan B. F. N., Gleeson, Peter T., Reis, Joao Carlos R., 2005. "Activity of
1905
- water in aqueous systems: A frequently neglected property." *Chemical Society Review* 34, 440-458.
1854
+ Blandamer, Mike J., Engberts, Jan B. F. N., Gleeson, Peter T., Reis, Joao Carlos R., 2005. "Activity of
1855
+ water in aqueous systems: A frequently neglected property." *Chemical Society Review* 34, 440-458.
1906
1856
 
1907
1857
  Examples:
1908
- --------
1909
- >>> s1 = pyEQL.Solution([['Na+','0.3 mol/kg'],['Cl-','0.3 mol/kg']])
1910
- >>> s1.get_water_activity()
1911
- <Quantity(0.9900944932888518, 'dimensionless')>
1858
+ >>> s1 = pyEQL.Solution([['Na+','0.3 mol/kg'],['Cl-','0.3 mol/kg']])
1859
+ >>> s1.get_water_activity()
1860
+ <Quantity(0.9900944932888518, 'dimensionless')>
1912
1861
  """
1913
1862
  osmotic_coefficient = self.get_osmotic_coefficient()
1914
1863
 
@@ -1924,44 +1873,41 @@ class Solution(MSONable):
1924
1873
  return ureg.Quantity(np.exp(-osmotic_coefficient * 0.018015 * concentration_sum), "dimensionless")
1925
1874
 
1926
1875
  def get_chemical_potential_energy(self, activity_correction: bool = True) -> Quantity:
1927
- """
1876
+ r"""
1928
1877
  Return the total chemical potential energy of a solution (not including
1929
1878
  pressure or electric effects).
1930
1879
 
1931
- Parameters
1932
- ----------
1933
- activity_correction : bool, optional
1934
- If True, activities will be used to calculate the true chemical
1935
- potential. If False, mole fraction will be used, resulting in
1936
- a calculation of the ideal chemical potential.
1880
+ Args:
1881
+ activity_correction : bool, optional
1882
+ If True, activities will be used to calculate the true chemical
1883
+ potential. If False, mole fraction will be used, resulting in
1884
+ a calculation of the ideal chemical potential.
1937
1885
 
1938
1886
  Returns:
1939
- -------
1940
- Quantity
1941
- The actual or ideal chemical potential energy of the solution, in Joules.
1887
+ Quantity
1888
+ The actual or ideal chemical potential energy of the solution, in Joules.
1942
1889
 
1943
1890
  Notes:
1944
- -----
1945
- The chemical potential energy (related to the Gibbs mixing energy) is
1946
- calculated as follows: [koga]_
1891
+ The chemical potential energy (related to the Gibbs mixing energy) is
1892
+ calculated as follows: [koga]_
1947
1893
 
1948
- .. math:: E = R T \\sum_i n_i \\ln a_i
1894
+ .. math:: E = R T \sum_i n_i \ln a_i
1949
1895
 
1950
- or
1896
+ or
1951
1897
 
1952
- .. math:: E = R T \\sum_i n_i \\ln x_i
1898
+ .. math:: E = R T \sum_i n_i \ln x_i
1953
1899
 
1954
- Where :math:`n` is the number of moles of substance, :math:`T` is the temperature in kelvin,
1955
- :math:`R` the ideal gas constant, :math:`x` the mole fraction, and :math:`a` the activity of
1956
- each component.
1900
+ Where :math:`n` is the number of moles of substance, :math:`T` is the temperature in kelvin,
1901
+ :math:`R` the ideal gas constant, :math:`x` the mole fraction, and :math:`a` the activity of
1902
+ each component.
1957
1903
 
1958
- Note that dissociated ions must be counted as separate components,
1959
- so a simple salt dissolved in water is a three component solution (cation,
1960
- anion, and water).
1904
+ Note that dissociated ions must be counted as separate components,
1905
+ so a simple salt dissolved in water is a three component solution (cation,
1906
+ anion, and water).
1961
1907
 
1962
1908
  References:
1963
- ----------
1964
- .. [koga] Koga, Yoshikata, 2007. *Solution Thermodynamics and its Application to Aqueous Solutions: A differential approach.* Elsevier, 2007, pp. 23-37.
1909
+ .. [koga] Koga, Yoshikata, 2007. *Solution Thermodynamics and its Application to Aqueous Solutions:
1910
+ A differential approach.* Elsevier, 2007, pp. 23-37.
1965
1911
 
1966
1912
  """
1967
1913
  E = ureg.Quantity(0, "J")
@@ -1994,17 +1940,15 @@ class Solution(MSONable):
1994
1940
  for solute, and adjust it from the reference conditions to the conditions
1995
1941
  of the solution.
1996
1942
 
1997
- Parameters
1998
- ----------
1999
- solute: str
2000
- String representing the chemical formula of the solute species
2001
- name: str
2002
- The name of the property needed, e.g.
2003
- 'diffusion coefficient'
1943
+ Args:
1944
+ solute: str
1945
+ String representing the chemical formula of the solute species
1946
+ name: str
1947
+ The name of the property needed, e.g.
1948
+ 'diffusion coefficient'
2004
1949
 
2005
1950
  Returns:
2006
- -------
2007
- Quantity: The desired parameter or None if not found
1951
+ Quantity: The desired parameter or None if not found
2008
1952
 
2009
1953
  """
2010
1954
  base_temperature = ureg.Quantity(25, "degC")
@@ -2119,7 +2063,7 @@ class Solution(MSONable):
2119
2063
  return None
2120
2064
 
2121
2065
  def get_transport_number(self, solute: str) -> Quantity:
2122
- """Calculate the transport number of the solute in the solution.
2066
+ r"""Calculate the transport number of the solute in the solution.
2123
2067
 
2124
2068
  Args:
2125
2069
  solute: Formula of the solute for which the transport number is
@@ -2133,7 +2077,7 @@ class Solution(MSONable):
2133
2077
 
2134
2078
  .. math::
2135
2079
 
2136
- t_i = {D_i z_i^2 C_i \\over \\sum D_i z_i^2 C_i}
2080
+ t_i = {D_i z_i^2 C_i \over \sum D_i z_i^2 C_i}
2137
2081
 
2138
2082
  Where :math:`C_i` is the concentration in mol/L, :math:`D_i` is the diffusion
2139
2083
  coefficient, and :math:`z_i` is the charge, and the summation extends
@@ -2171,7 +2115,7 @@ class Solution(MSONable):
2171
2115
  return ureg.Quantity(numerator / denominator, "dimensionless")
2172
2116
 
2173
2117
  def _get_molar_conductivity(self, solute: str) -> Quantity:
2174
- """
2118
+ r"""
2175
2119
  Calculate the molar (equivalent) conductivity for a solute.
2176
2120
 
2177
2121
  Args:
@@ -2187,17 +2131,20 @@ class Solution(MSONable):
2187
2131
 
2188
2132
  .. math::
2189
2133
 
2190
- \\lambda_i = \\frac{F^2}{RT} D_i z_i^2
2134
+ \lambda_i = \frac{F^2}{RT} D_i z_i^2
2191
2135
 
2192
2136
  Diffusion coefficients :math:`D_i` are adjusted for the effects of temperature
2193
- and ionic strength using the method implemented in PHREEQC >= 3.4. See `get_diffusion_coefficient for` further details.
2137
+ and ionic strength using the method implemented in PHREEQC >= 3.4. See `get_diffusion_coefficient`
2138
+ for further details.
2194
2139
 
2195
2140
  References:
2196
2141
  1. .. [smed] Smedley, Stuart. The Interpretation of Ionic Conductivity in Liquids, pp 1-9. Plenum Press, 1980.
2197
2142
 
2198
2143
  2. https://www.hydrochemistry.eu/exmpls/sc.html
2199
2144
 
2200
- 3. 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
2145
+ 3. Appelo, C.A.J. Solute transport solved with the Nernst-Planck equation for concrete pores with `free'
2146
+ water and a double layer. Cement and Concrete Research 101, 2017.
2147
+ https://dx.doi.org/10.1016/j.cemconres.2017.08.030
2201
2148
 
2202
2149
  4. CRC Handbook of Chemistry and Physics
2203
2150
 
@@ -2218,7 +2165,7 @@ class Solution(MSONable):
2218
2165
  return molar_cond.to("mS / cm / (mol/L)")
2219
2166
 
2220
2167
  def _get_diffusion_coefficient(self, solute: str, activity_correction: bool = True) -> Quantity:
2221
- """
2168
+ r"""
2222
2169
  Get the **temperature-adjusted** diffusion coefficient of a solute.
2223
2170
 
2224
2171
  Args:
@@ -2231,28 +2178,30 @@ class Solution(MSONable):
2231
2178
  ONLY when the Solution temperature is the same as the reference temperature for the diffusion coefficient
2232
2179
  in the database (usually 25 C).
2233
2180
 
2234
- Otherwise, the reference D value is adjusted based on the Solution temperature and (optionally), ionic strength.
2235
- The adjustments are"
2181
+ Otherwise, the reference D value is adjusted based on the Solution temperature and (optionally),
2182
+ ionic strength. The adjustments are
2236
2183
 
2237
2184
  .. math::
2238
2185
 
2239
- D_T = D_{298} \\exp(\\frac{d}{T} - \\frac{d}{298}) \\frac{\\nu_{298}}{\\nu_T}
2186
+ D_T = D_{298} \exp(\frac{d}{T} - \frac{d}{298}) \frac{\nu_{298}}{\nu_T}
2240
2187
 
2241
2188
  .. math::
2242
2189
 
2243
- D_{\\gamma} = D^0 \\exp(\\frac{-a1 A |z_i| \\sqrt{I}}{1+\\kappa a}
2190
+ D_{\gamma} = D^0 \exp(\frac{-a1 A |z_i| \sqrt{I}}{1+\kappa a}
2244
2191
 
2245
2192
  .. math::
2246
2193
 
2247
- \\kappa a = B \\sqrt{I} \\frac{a2}{1+I^{0.75}}
2194
+ \kappa a = B \sqrt{I} \frac{a2}{1+I^{0.75}}
2248
2195
 
2249
- where a1, a2, and d are parameters from Ref. 2, A and B are the parameters used in the Debye Huckel equation, and
2250
- I is the ionic strength. If the model parameters for a particular solute are not available,
2196
+ where a1, a2, and d are parameters from Ref. 2, A and B are the parameters used in the Debye Huckel
2197
+ equation, and I is the ionic strength. If the model parameters for a particular solute are not available,
2251
2198
  default values of d=0, a1=1.6, and a2=4.73 (as recommended in Ref. 2) are used instead.
2252
2199
 
2253
2200
  References:
2254
2201
  1. https://www.hydrochemistry.eu/exmpls/sc.html
2255
- 2. 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
2202
+ 2. Appelo, C.A.J. Solute transport solved with the Nernst-Planck equation for concrete pores with `free'
2203
+ water and a double layer. Cement and Concrete Research 101, 2017.
2204
+ https://dx.doi.org/10.1016/j.cemconres.2017.08.030
2256
2205
  3. CRC Handbook of Chemistry and Physics
2257
2206
 
2258
2207
  See Also:
@@ -2264,7 +2213,8 @@ class Solution(MSONable):
2264
2213
  rform = standardize_formula(solute)
2265
2214
  if D is None or D.magnitude == 0:
2266
2215
  logger.info(
2267
- f"Diffusion coefficient not found for species {rform}. Using default value of {self.default_diffusion_coeff} m**2/s."
2216
+ f"Diffusion coefficient not found for species {rform}. Using default value of "
2217
+ f"{self.default_diffusion_coeff} m**2/s."
2268
2218
  )
2269
2219
  D = ureg.Quantity(self.default_diffusion_coeff, "m**2/s")
2270
2220
 
@@ -2317,33 +2267,24 @@ class Solution(MSONable):
2317
2267
  return D_final
2318
2268
 
2319
2269
  def _get_mobility(self, solute: str) -> Quantity:
2320
- """
2270
+ r"""
2321
2271
  Calculate the ionic mobility of the solute.
2322
2272
 
2323
- Parameters
2324
- ----------
2325
- solute : str
2326
- String identifying the solute for which the mobility is
2327
- to be calculated.
2273
+ Args:
2274
+ solute (str): String identifying the solute for which the mobility is to be calculated.
2328
2275
 
2329
2276
  Returns:
2330
- -------
2331
- float : The ionic mobility. Zero if the solute is not charged.
2332
-
2277
+ float: The ionic mobility. Zero if the solute is not charged.
2333
2278
 
2334
- Notes:
2335
- -----
2336
- This function uses the Einstein relation to convert a diffusion coefficient
2337
- into an ionic mobility [smed]_
2279
+ Note:
2280
+ This function uses the Einstein relation to convert a diffusion coefficient into an ionic mobility [smed]_
2338
2281
 
2339
- .. math::
2282
+ .. math::
2340
2283
 
2341
- \\mu_i = {F |z_i| D_i \\over RT}
2284
+ \mu_i = {F |z_i| D_i \over RT}
2342
2285
 
2343
2286
  References:
2344
- ----------
2345
- .. [smed] Smedley, Stuart I. The Interpretation of Ionic Conductivity in Liquids. Plenum Press, 1980.
2346
-
2287
+ Smedley, Stuart I. The Interpretation of Ionic Conductivity in Liquids. Plenum Press, 1980.
2347
2288
  """
2348
2289
  D = self.get_diffusion_coefficient(solute)
2349
2290
 
@@ -2354,33 +2295,29 @@ class Solution(MSONable):
2354
2295
  return mobility.to("m**2/V/s")
2355
2296
 
2356
2297
  def get_lattice_distance(self, solute: str) -> Quantity:
2357
- """
2298
+ r"""
2358
2299
  Calculate the average distance between molecules.
2359
2300
 
2360
2301
  Calculate the average distance between molecules of the given solute,
2361
2302
  assuming that the molecules are uniformly distributed throughout the
2362
2303
  solution.
2363
2304
 
2364
- Parameters
2365
- ----------
2366
- solute : str
2367
- String representing the name of the solute of interest
2305
+ Args:
2306
+ solute : str
2307
+ String representing the name of the solute of interest
2368
2308
 
2369
2309
  Returns:
2370
- -------
2371
- Quantity : The average distance between solute molecules
2310
+ Quantity: The average distance between solute molecules
2372
2311
 
2373
2312
  Examples:
2374
- --------
2375
- >>> soln = Solution([['Na+','0.5 mol/kg'],['Cl-','0.5 mol/kg']])
2376
- >>> soln.get_lattice_distance('Na+')
2377
- 1.492964.... nanometer
2313
+ >>> soln = Solution([['Na+','0.5 mol/kg'],['Cl-','0.5 mol/kg']])
2314
+ >>> soln.get_lattice_distance('Na+')
2315
+ 1.492964.... nanometer
2378
2316
 
2379
2317
  Notes:
2380
- -----
2381
- The lattice distance is related to the molar concentration as follows:
2318
+ The lattice distance is related to the molar concentration as follows:
2382
2319
 
2383
- .. math:: d = ( C_i N_A ) ^ {-{1 \\over 3}}
2320
+ .. math:: d = ( C_i N_A ) ^ {-{1 \over 3}}
2384
2321
 
2385
2322
  """
2386
2323
  # calculate the volume per particle as the reciprocal of the molar concentration
@@ -2563,7 +2500,8 @@ class Solution(MSONable):
2563
2500
 
2564
2501
  Args:
2565
2502
  mode: Whether to list the amounts of all solutes, or only anions, cations, any ion, or any neutral solute.
2566
- units: The units to list solute amounts in. "activity" will list dimensionless activities instead of concentrations.
2503
+ units: The units to list solute amounts in. "activity" will list dimensionless activities instead of
2504
+ concentrations.
2567
2505
  places: The number of decimal places to round the solute amounts.
2568
2506
  """
2569
2507
  print(self)
@@ -2832,12 +2770,12 @@ class Solution(MSONable):
2832
2770
 
2833
2771
  @deprecated(message="get_viscosity_relative() will be removed in the next release.")
2834
2772
  def get_viscosity_relative(self): # pragma: no cover
2835
- """
2773
+ r"""
2836
2774
  Return the viscosity of the solution relative to that of water.
2837
2775
 
2838
2776
  This is calculated using a simplified form of the Jones-Dole equation:
2839
2777
 
2840
- .. math:: \\eta_{rel} = 1 + \\sum_i B_i m_i
2778
+ .. math:: \eta_{rel} = 1 + \sum_i B_i m_i
2841
2779
 
2842
2780
  Where :math:`m` is the molal concentration and :math:`B` is an empirical parameter.
2843
2781
 
@@ -2895,7 +2833,7 @@ class Solution(MSONable):
2895
2833
 
2896
2834
  .. math::
2897
2835
 
2898
- \\ln \\nu = \\ln {\\nu_w MW_w \\over \\sum_i x_i MW_i } +
2836
+ \\ln \nu = \\ln {\nu_w MW_w \\over \\sum_i x_i MW_i } +
2899
2837
  15 x_+^2 + x_+^3 \\delta G^*_{123} + 3 x_+ \\delta G^*_{23} (1-0.05x_+)
2900
2838
 
2901
2839
  Where:
@@ -2903,7 +2841,7 @@ class Solution(MSONable):
2903
2841
  .. math:: \\delta G^*_{123} = a_o + a_1 (T)^{0.75}
2904
2842
  .. math:: \\delta G^*_{23} = b_o + b_1 (T)^{0.5}
2905
2843
 
2906
- In which :math:`\\nu` is the kinematic viscosity, MW is the molecular weight,
2844
+ In which :math:`\nu` is the kinematic viscosity, MW is the molecular weight,
2907
2845
  `x_+` is the mole fraction of cations, and T is the temperature in degrees C.
2908
2846
 
2909
2847
  The a and b fitting parameters for a variety of common salts are included in the
@@ -2948,13 +2886,13 @@ class Solution(MSONable):
2948
2886
 
2949
2887
  .. math::
2950
2888
 
2951
- EC = {F^2 \\over R T} \\sum_i D_i z_i ^ 2 \\gamma_i ^ {\\alpha} m_i
2889
+ EC = {F^2 \\over R T} \\sum_i D_i z_i ^ 2 \\gamma_i ^ {\alpha} m_i
2952
2890
 
2953
2891
  Where:
2954
2892
 
2955
2893
  .. math::
2956
2894
 
2957
- \\alpha = \\begin{cases} {0.6 \\over \\sqrt{|z_i|}} & {I < 0.36|z_i|} \\ {\\sqrt{I} \\over |z_i|} & otherwise \\end{cases}
2895
+ \alpha = \begin{cases} {0.6 \\over \\sqrt{|z_i|}} & {I < 0.36|z_i|} \\ {\\sqrt{I} \\over |z_i|} & otherwise \\end{cases}
2958
2896
 
2959
2897
  Note: PHREEQC uses the molal rather than molar concentration according to
2960
2898
  http://wwwbrr.cr.usgs.gov/projects/GWC_coupled/phreeqc/phreeqc3-html/phreeqc3-43.htm
@@ -2995,7 +2933,7 @@ class Solution(MSONable):
2995
2933
  message="get_ionic_strength() will be removed in the next release. Access directly via the property Solution.ionic_strength"
2996
2934
  )
2997
2935
  def get_ionic_strength(self): # pragma: no cover
2998
- """
2936
+ r"""
2999
2937
  Return the ionic strength of the solution.
3000
2938
 
3001
2939
  Return the ionic strength of the solution, calculated as 1/2 * sum ( molality * charge ^2) over all the ions.
@@ -3003,7 +2941,7 @@ class Solution(MSONable):
3003
2941
 
3004
2942
  Returns:
3005
2943
  -------
3006
- Quantity :
2944
+ Quantity:
3007
2945
  The ionic strength of the parent solution, mol/kg.
3008
2946
 
3009
2947
  See Also:
@@ -3015,7 +2953,7 @@ class Solution(MSONable):
3015
2953
  -----
3016
2954
  The ionic strength is calculated according to:
3017
2955
 
3018
- .. math:: I = \\sum_i m_i z_i^2
2956
+ .. math:: I = \sum_i m_i z_i^2
3019
2957
 
3020
2958
  Where :math:`m_i` is the molal concentration and :math:`z_i` is the charge on species i.
3021
2959
 
@@ -3037,7 +2975,7 @@ class Solution(MSONable):
3037
2975
  message="get_charge_balance() will be removed in the next release. Access directly via the property Solution.charge_balance"
3038
2976
  )
3039
2977
  def get_charge_balance(self): # pragma: no cover
3040
- """
2978
+ r"""
3041
2979
  Return the charge balance of the solution.
3042
2980
 
3043
2981
  Return the charge balance of the solution. The charge balance represents the net electric charge
@@ -3053,7 +2991,7 @@ class Solution(MSONable):
3053
2991
  -----
3054
2992
  The charge balance is calculated according to:
3055
2993
 
3056
- .. math:: CB = F \\sum_i n_i z_i
2994
+ .. math:: CB = F \sum_i n_i z_i
3057
2995
 
3058
2996
  Where :math:`n_i` is the number of moles, :math:`z_i` is the charge on species i, and :math:`F` is the Faraday constant.
3059
2997
 
@@ -3066,19 +3004,19 @@ class Solution(MSONable):
3066
3004
  message="get_alkalinity() will be removed in the next release. Access directly via the property Solution.alkalinity"
3067
3005
  )
3068
3006
  def get_alkalinity(self): # pragma: no cover
3069
- """
3007
+ r"""
3070
3008
  Return the alkalinity or acid neutralizing capacity of a solution.
3071
3009
 
3072
3010
  Returns:
3073
3011
  -------
3074
- Quantity :
3012
+ Quantity:
3075
3013
  The alkalinity of the solution in mg/L as CaCO3
3076
3014
 
3077
3015
  Notes:
3078
3016
  -----
3079
3017
  The alkalinity is calculated according to:
3080
3018
 
3081
- .. math:: Alk = F \\sum_i z_i C_B - \\sum_i z_i C_A
3019
+ .. math:: Alk = F \sum_i z_i C_B - \sum_i z_i C_A
3082
3020
 
3083
3021
  Where :math:`C_B` and :math:`C_A` are conservative cations and anions, respectively
3084
3022
  (i.e. ions that do not participate in acid-base reactions), and :math:`z_i` is their charge.
@@ -3125,14 +3063,14 @@ class Solution(MSONable):
3125
3063
  message="get_debye_length() will be removed in the next release. Access directly via the property Solution.debye_length"
3126
3064
  )
3127
3065
  def get_debye_length(self): # pragma: no cover
3128
- """
3066
+ r"""
3129
3067
  Return the Debye length of a solution.
3130
3068
 
3131
3069
  Debye length is calculated as
3132
3070
 
3133
3071
  .. math::
3134
3072
 
3135
- \\kappa^{-1} = \\sqrt({\\epsilon_r \\epsilon_o k_B T \\over (2 N_A e^2 I)})
3073
+ \kappa^{-1} = \sqrt({\epsilon_r \epsilon_o k_B T \over (2 N_A e^2 I)})
3136
3074
 
3137
3075
  where :math:`I` is the ionic strength, :math:`epsilon_r` and :math:`epsilon_r`
3138
3076
  are the relative permittivity and vacuum permittivity, :math:`k_B` is the
@@ -3166,16 +3104,16 @@ class Solution(MSONable):
3166
3104
  message="get_bjerrum_length() will be removed in the next release. Access directly via the property Solution.bjerrum_length"
3167
3105
  )
3168
3106
  def get_bjerrum_length(self): # pragma: no cover
3169
- """
3107
+ r"""
3170
3108
  Return the Bjerrum length of a solution.
3171
3109
 
3172
3110
  Bjerrum length represents the distance at which electrostatic
3173
3111
  interactions between particles become comparable in magnitude
3174
- to the thermal energy.:math:`\\lambda_B` is calculated as
3112
+ to the thermal energy.:math:`\lambda_B` is calculated as
3175
3113
 
3176
3114
  .. math::
3177
3115
 
3178
- \\lambda_B = {e^2 \\over (4 \\pi \\epsilon_r \\epsilon_o k_B T)}
3116
+ \lambda_B = {e^2 \over (4 \pi \epsilon_r \epsilon_o k_B T)}
3179
3117
 
3180
3118
  where :math:`e` is the fundamental charge, :math:`epsilon_r` and :math:`epsilon_r`
3181
3119
  are the relative permittivity and vacuum permittivity, :math:`k_B` is the
@@ -3228,9 +3166,9 @@ class Solution(MSONable):
3228
3166
  -----
3229
3167
  Implements the following equation as given by [zub]_
3230
3168
 
3231
- .. math:: \\epsilon = \\epsilon_solvent \\over 1 + \\sum_i \\alpha_i x_i
3169
+ .. math:: \\epsilon = \\epsilon_solvent \\over 1 + \\sum_i \alpha_i x_i
3232
3170
 
3233
- where :math:`\\alpha_i` is a coefficient specific to the solvent and ion, and :math:`x_i`
3171
+ where :math:`\alpha_i` is a coefficient specific to the solvent and ion, and :math:`x_i`
3234
3172
  is the mole fraction of the ion in solution.
3235
3173
 
3236
3174
 
@@ -3318,10 +3256,10 @@ class Solution(MSONable):
3318
3256
 
3319
3257
  References:
3320
3258
  .. [1] Millero, Frank J. "The composition of Standard Seawater and the definition of
3321
- the Reference-Composition Salinity Scale." *Deep-sea Research. Part I* 55(1), 2008, 50-72.
3259
+ the Reference-Composition Salinity Scale." *Deep-sea Research. Part I* 55(1), 2008, 50-72.
3322
3260
 
3323
3261
  .. [2] Metcalf & Eddy, Inc. et al. *Wastewater Engineering: Treatment and Resource Recovery*, 5th Ed.
3324
- McGraw-Hill, 2013.
3262
+ McGraw-Hill, 2013.
3325
3263
 
3326
3264
  .. [3] https://en.wikipedia.org/wiki/Saline_(medicine)
3327
3265
 
@@ -3362,6 +3300,7 @@ class Solution(MSONable):
3362
3300
  else:
3363
3301
  dumpfn(self, filename)
3364
3302
 
3303
+ @classmethod
3365
3304
  def from_file(self, filename: str | Path) -> Solution:
3366
3305
  """Loading from a .yaml or .json file.
3367
3306