"""Utils that help running simulations with ASE."""importfunctoolsimporttypingimportaseimportnumpyasnpfromaseimportunitsfromase.calculators.singlepointimportSinglePointCalculator
[docs]defget_energy(atoms:ase.Atoms)->typing.Tuple[float,float]:"""Compute the temperature and the total energy. Parameters ---------- atoms: ase.Atoms Atoms objects for which energy will be calculated Returns ------- temperature: float temperature of the system np.squeeze(total): float total energy of the system """epot=atoms.get_potential_energy()/len(atoms)ekin=atoms.get_kinetic_energy()/len(atoms)temperature=ekin/(1.5*units.kB)total=epot+ekinreturntemperature,np.squeeze(total).item()
[docs]defget_desc(temperature:float,total_energy:float):"""TQDM description."""returnf"Temp: {temperature:.3f} K \t Energy {total_energy:.3f} eV - (TQDM in fs)"
[docs]@functools.singledispatchdeffreeze_copy_atoms(atoms)->ase.Atoms:# TODO can we add the name of the original calculator?result=atoms.copy()result.calc=SinglePointCalculator(result)result.calc.results.update(atoms.calc.results)returnresult
[docs]defget_box_from_density(data:list[list[ase.Atoms]],count:list[int],density:float)->list[float]:"""Get the box size from the molar volume. Attributes ---------- data: list[list[ase.Atoms]] List of list of atoms objects. The last atoms object is used to compute the molar volume. count: list[int] Number of molecules for each entry in data. density: float Density of the system in kg/m^3. """molar_mass=[sum(atoms[0].get_masses())*countforatoms,countinzip(data,count)]molar_mass=sum(molar_mass)# g / molmolar_volume=molar_mass/density/1000# m^3 / mol# convert to particles / A^3volume=molar_volume*(ase.units.m**3)/ase.units.molbox=[volume**(1/3)for_inrange(3)]returnbox
[docs]defget_density_from_atoms(atoms:ase.Atoms)->float:"""Compute the density of the atoms in kg/m3."""volume=atoms.get_volume()molar_volume=volume/(units.m**3/units.mol)returnatoms.get_masses().sum()/1000/molar_volume