Source code for chemtrain.quantity.constants
# Copyright 2023 Multiscale Modeling of Fluid Materials, TU Munich
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Chemtrain unit conversion utilities.
This module provides classes to convert between different units in chemistry.
Through JAX, M.D., chemtrain mostly relies on a
`self-consistent unit system <https://hoomd-blue.readthedocs.io/en/stable/units.html>`_.
"""
import math
import jax
try:
from jax.typing import ArrayLike
except:
from typing import Any
ArrayLike = Any
class Constant:
def __init__(self, factor: float = 1.0, exponent: int = 0):
self.factor = factor
self.exponent = exponent
def __mul__(self, other):
if isinstance(other, Constant):
factor = other.factor * self.factor
exponent = other.exponent + self.exponent
exponent += int(math.log10(factor))
factor /= 10 ** int(math.log10(factor))
return Constant(factor, exponent)
else:
return self.multiply(other)
def __rmul__(self, other):
return self.multiply(other)
def __truediv__(self, other):
if isinstance(other, Constant):
factor = other.factor * self.factor
exponent = other.exponent + self.exponent
exponent += int(math.log10(factor))
factor /= 10 ** int(math.log10(factor))
return Constant(factor, exponent)
else:
return self.divide(other)
def __rtruediv__(self, other):
return self.divide(other)
def __pow__(self, power, modulo=None):
factor = self.factor ** power
exponent = power * self.exponent
exponent += int(math.log10(factor ** 0.1))
factor /= 10 ** int(math.log10(factor))
return Constant(factor, exponent)
def __repr__(self):
return f"{self.factor} * 10^{self.exponent}"
def multiply(self, value):
return value * self.factor * (10 ** self.exponent)
def divide(self, value):
return value / self.factor * (0.1 ** self.exponent)
[docs]
class Pressure:
def __init__(self):
self._pressure = 0.0
@property
def bar(self):
"""Pressure in bar."""
return self._pressure * 16.60539067
@bar.setter
def bar(self, pressure):
pressure = pressure / 16.60539067
self._pressure = pressure
@property
def pressure(self):
"""Pressure in the base unit. """
return self._pressure
@pressure.setter
def pressure(self, pressure):
self._pressure = pressure
def __repr__(self):
return f"{self._pressure} kJ/(mol * nm^3)"
[docs]
class Temperature:
def __init__(self):
self._temperature = 0.0
@property
def temperature(self):
"""Temperature in the base unit."""
return self._temperature
@temperature.setter
def temperature(self, temperature):
self._temperature = temperature
@property
def kelvin(self):
"""Temperature in kelvin. """
return self._temperature / kb
@kelvin.setter
def kelvin(self, temperature):
self._temperature = temperature * kb
[docs]
class Density:
def __init__(self):
self._density = 0.0
@property
def density(self):
"""Density in the base unit."""
return self._density
@density.setter
def density(self, density):
self._density = density
@property
def g_per_cm3(self):
"""Density in grams per cm cubed. """
return self._density * u.factor
@g_per_cm3.setter
def g_per_cm3(self, density):
self._density = density / u.factor
kb = 0.0083145107 # Boltzmann constant in kJ/(mol * K)
u = Constant(1.6605, -27) # In kg
mol = Constant(6.02214076, 23)