Source code for pyPRISM.util.UnitConverter

import warnings
import pint

[docs]class UnitConverter(object): r'''Unit conversion utility **Description** pyPRISM operates in a system of reduced units commonly called 'Lennard Jones units'. In this unit system, all measures are reported relative to characteristic values: length = :math:`d_c`, mass = :math:`m_c`, and energy = :math:`e_c`. This class is designed to make some common conversions between reduced and real units easier. See the Theory.General notebook of the :ref:`tutorial` for a more detailed discussion of these units and how to work with the UnitConverter utility. .. note:: The methods prefixed with "to" all expect floating point values in reduced units and convert to real units. .. warning:: This class uses the `Pint <https://pint.readthedocs.io>`_ package. While the rest of pyPRISM will function without Pint, this class will not be available without this dependency installed in the current environment. Example ------- .. code-block:: python import pyPRISM domain = pyPRISM.Domain(length=4096,dr=0.25) # create unit converter utility uc = pyPRISM.util.UnitConverter(dc=1.5,dc_unit='nm') # convert wavenumber from LJ units to real units # using built-in conversion real_k = uc.toInvAngstrom(domain.k) real_k_magnitudes = real_k.magnitude # convert radius in real units to reduced units # manually using pint real_radius = 123.5 # angstrom reduced_radius = real_radius * uc('angstrom').to('dc').magnitude '''
[docs] def __init__(self, dc=1.0, dc_unit='nanometer', mc=14.02, mc_unit='gram/mole', ec=2.48, ec_unit='kilojoule/mole'): r''' Constructor Arguments --------- dc,dc_unit: float,str Magnitude and unit of characteristic distance mc,mc_unit: float,str Magnitude and unit of characteristic mass ec,ec_unit: float,str Magnitude and unit of characteristic energy Attributes ---------- d,dc: Pint Quantity The defined characteristic distance as a defined Pint Quantity. m,mc: Pint Quantity The defined characteristic mass as a defined Pint Quantity. e,ec: Pint Quantity The defined characteristic energy as a defined Pint Quantity. ''' self.pint = pint.UnitRegistry() dString = 'dchar = {} {} = dc'.format(dc,dc_unit) mString = 'mchar = {} {} = mc'.format(mc,mc_unit) eString = 'echar = {} {} = ec'.format(ec,ec_unit) # print('--> Defining reduced unit {}'.format(dString)) # print('--> Defining reduced unit {}'.format(mString)) # print('--> Defining reduced unit {}'.format(eString)) self.pint.define(dString) self.pint.define(mString) self.pint.define(eString) self.d = self.dc = self.pint.Quantity(1,'dc') self.m = self.mc = self.pint.Quantity(1,'mc') self.e = self.ec = self.pint.Quantity(1,'ec')
def __repr__(self): return '<UnitConverter dc:{} | mc:{} | ec:{}>'.format(self.dc.to_base_units(),self.mc.to_base_units(),self.ec.to_base_units())
[docs] def __call__(self,unit_string): '''Convenience method for accessing the pint UnitRegistry''' return self.pint(unit_string)
[docs] def toKelvin(self,temperature): r'''Convert thermal energy to temperature units in :math:`K` Arguments --------- temperature: float or np.ndarray of floats Value of thermal energy (:math:`k_{B}T`) to be converted Returns ------- temperature: Pint Quantity temperature in :math:`K` as a Pint Quantity. Use the magnitude attribute (temperature.magnitude) to obtain the numerical value of the temperature as a floating point value. ''' new_value = (temperature*self.e)/self.pint('boltzmann_constant') # need to handle both the molar and non-molar characteristic energy try: return new_value.to('K') except pint.errors.DimensionalityError: new_value /= self.pint('N_A') return new_value.to('K')
[docs] def toCelcius(self,temperature): r'''Convert thermal energy to temperature units in Celcius Arguments --------- temperature: float or np.ndarray of floats Value of thermal energy (:math:`k_{B}T`) to be converted Returns ------- temperature: Pint Quantity temperature in Kelvin as a Pint Quantity. Use the magnitude attribute (temperature.magnitude) to obtain the numerical value of the temperature as a floating point value. ''' return self.toKelvin(temperature).to('C')
[docs] def toInvAngstrom(self,wavenumber): r'''Convert wavenumbers to real units Arguments --------- wavenumber: float, or np.ndarray of floats Value(s) of wavenumbers to be converted Returns ------- wavenumber: Pint Quantity wavenumbers in :math:`AA^{-1}` as a Pint Quantity. Use the magnitude attribute (wavenumber.magnitude) to obtain the numerical value of the wavenumber as a floating point value. ''' new_value = wavenumber*(1.0/self.d) return new_value.to('angstrom^-1')
[docs] def toInvNanometer(self,wavenumber): r'''Convert wavenumbers to real units Arguments --------- wavenumber: float, or np.ndarray of floats Value(s) of wavenumbers to be converted Returns ------- wavenumber: Pint Quantity wavenumbers in :math:`nm^{-1}` as a Pint Quantity. Use the magnitude attribute (wavenumber.magnitude) to obtain the numerical value of the wavenumber as a floating point value. ''' return self.toInvAngstrom(wavenumber).to('nanometer^-1')
[docs] def toConcentration(self,density): r'''Convert reduced number density to real concentration units Arguments --------- density: float, or np.ndarray of floats Value(s) of density to be converted Returns ------- concentration: Pint Quantity density in :math:`mol/L` as a Pint Quantity. Use the magnitude attribute (concentration.magnitude) to obtain the numerical value of the contration as a floating point value. ''' new_value = density/(self.d**3.0)/self.pint('N_A') return new_value.to('mol/L')
[docs] def toVolumeFraction(self,density,diameter): r'''Convert reduced number density to volume fraction Arguments --------- density: float, or np.ndarray of floats Value(s) of density to be converted diameter: float diameter of the site associated with the density Returns ------- vol_fraction: Pint Quantity unitless volume as a Pint Quantity. Use the magnitude attribute (vol_fraction.magnitude) to obtain the numerical value of the volume fraction as a floating point value. ''' new_value = density*4.0/3.0 * self.pint('pi') * (diameter/2.0)**(3.0) return new_value*self.pint('unitless')