1111from emmet .core .openff import MoleculeSpec
1212from pymatgen .core import Element , Molecule
1313from pymatgen .io .openff import create_openff_mol
14+ from scipy .constants import Avogadro
1415
1516if TYPE_CHECKING :
1617 import pathlib
1718
19+ DEFAULT_ATOMIC_MASSES = {el .Z : el .atomic_mass for el in Element }
20+
1821
1922def create_mol_spec (
2023 smiles : str ,
@@ -145,6 +148,7 @@ def calculate_elyte_composition(
145148 salts : dict [str , float ],
146149 solvent_densities : dict = None ,
147150 solvent_ratio_dimension : Literal ["mass" , "volume" ] = "mass" ,
151+ atomic_masses : dict [int , float ] | None = None ,
148152) -> dict [str , float ]:
149153 """Calculate the normalized mass ratios of an electrolyte solution.
150154
@@ -158,6 +162,9 @@ def calculate_elyte_composition(
158162 Dictionary of solvent SMILES strings and their densities (g/ml).
159163 solvent_ratio_dimension: optional, str
160164 Whether the solvents are included with a ratio of "mass" or "volume"
165+ atomic_masses : dict[int,float] or None (Default)
166+ The mass of each element in the species dict. Defaults to the
167+ most recent data from pymatgen.core.periodic_table.Element
161168
162169 Returns
163170 -------
@@ -186,11 +193,11 @@ def calculate_elyte_composition(
186193 }
187194
188195 # Calculate the molecular weights of the solvent
189- masses = { el . Z : el . atomic_mass for el in Element }
196+ atomic_masses = atomic_masses or DEFAULT_ATOMIC_MASSES
190197 salt_mws = {}
191198 for smile in salts :
192199 mol = tk .Molecule .from_smiles (smile , allow_undefined_stereo = True )
193- salt_mws [smile ] = sum (masses [atom .atomic_number ] for atom in mol .atoms )
200+ salt_mws [smile ] = sum (atomic_masses [atom .atomic_number ] for atom in mol .atoms )
194201
195202 # Convert salt mole ratios to mass ratios
196203 salt_mass_ratio = {
@@ -207,7 +214,9 @@ def calculate_elyte_composition(
207214 return {species : mass / total_mass for species , mass in combined_mass_ratio .items ()}
208215
209216
210- def counts_from_masses (species : dict [str , float ], n_mol : int ) -> dict [str , float ]:
217+ def counts_from_masses (
218+ species : dict [str , float ], n_mol : int , atomic_masses : dict [int , float ] | None = None
219+ ) -> dict [str , float ]:
211220 """Calculate the number of mols needed to yield a given mass ratio.
212221
213222 Parameters
@@ -216,19 +225,21 @@ def counts_from_masses(species: dict[str, float], n_mol: int) -> dict[str, float
216225 Dictionary of species SMILES strings and their relative mass fractions.
217226 n_mol : float
218227 Total number of mols. Returned array will sum to near n_mol.
219-
228+ atomic_masses : dict[int,float] or None (Default)
229+ The mass of each element in the species dict. Defaults to the
230+ most recent data from pymatgen.core.periodic_table.Element
220231
221232 Returns
222233 -------
223234 numpy.ndarray
224235 n_mols: Number of each SMILES needed for the given mass ratio.
225236 """
226- masses = { el . Z : el . atomic_mass for el in Element }
237+ atomic_masses = atomic_masses or DEFAULT_ATOMIC_MASSES
227238
228239 mol_weights = []
229240 for smile in species :
230241 mol = tk .Molecule .from_smiles (smile , allow_undefined_stereo = True )
231- mol_weights .append (sum (masses [atom .atomic_number ] for atom in mol .atoms ))
242+ mol_weights .append (sum (atomic_masses [atom .atomic_number ] for atom in mol .atoms ))
232243
233244 mol_ratio = np .array (list (species .values ())) / np .array (mol_weights )
234245 mol_ratio /= sum (mol_ratio )
@@ -239,7 +250,10 @@ def counts_from_masses(species: dict[str, float], n_mol: int) -> dict[str, float
239250
240251
241252def counts_from_box_size (
242- species : dict [str , float ], side_length : float , density : float = 0.8
253+ species : dict [str , float ],
254+ side_length : float ,
255+ density : float = 0.8 ,
256+ atomic_masses : dict [int , float ] | None = None ,
243257) -> dict [str , float ]:
244258 """Calculate the number of molecules needed to fill a box.
245259
@@ -251,25 +265,27 @@ def counts_from_box_size(
251265 Side length of the cubic simulation box in nm.
252266 density : int, optional
253267 Density of the system in g/cm^3. Default is 1 g/cm^3.
268+ atomic_masses : dict[int,float] or None (Default)
269+ The mass of each element in the species dict. Defaults to the
270+ most recent data from pymatgen.core.periodic_table.Element
254271
255272 Returns
256273 -------
257274 dict of str, float
258275 Number of each species needed to fill the box with the given density.
259276 """
260- masses = { el . Z : el . atomic_mass for el in Element }
277+ atomic_masses = atomic_masses or DEFAULT_ATOMIC_MASSES
261278
262- na = 6.02214076e23 # Avogadro's number
263279 volume = (side_length * 1e-7 ) ** 3 # Convert from nm3 to cm^3
264280 total_mass = volume * density # grams
265281
266282 # Calculate molecular weights
267283 mol_weights = []
268284 for smile in species :
269285 mol = tk .Molecule .from_smiles (smile , allow_undefined_stereo = True )
270- mol_weights .append (sum (masses [atom .atomic_number ] for atom in mol .atoms ))
286+ mol_weights .append (sum (atomic_masses [atom .atomic_number ] for atom in mol .atoms ))
271287 mean_mw = np .mean (mol_weights )
272- n_mol = (total_mass / mean_mw ) * na
288+ n_mol = (total_mass / mean_mw ) * Avogadro
273289
274290 # Calculate the number of moles needed for each species
275291 mol_ratio = np .array (list (species .values ())) / np .array (mol_weights )
0 commit comments