"""The core module for the crack model.
This module consist of the class :class:`Crack`
which, upon instantiation,
becomes a crack model instance with methods for calculating
quantities in either thermodynamic ensemble.
These thermodynamic quantities are calculated using an
asymptotic approach :footcite:`buche2021fundamental`,
:footcite:`buche2022freely`, :footcite:`buchegrutzikufjc2022`
or a Monte Carlo approach (see :class:`.CrackMonteCarlo`).
Basic mathematical capabilities are provided by
``numpy`` :footcite:`numpy` and ``scipy`` :footcite:`scipy`,
and ``matplotlib`` :footcite:`matplotlib` is often used
for displaying results.
"""
from .isotensional import CrackIsotensional
[docs]
class Crack(CrackIsotensional):
r"""The crack model class.
"""
def __init__(self, **kwargs):
"""Initializes the :class:`Crack` class.
Initialize and inherit all attributes and methods
from a :class:`.CrackIsotensional` class instance.
"""
CrackIsotensional.__init__(self, **kwargs)
[docs]
def beta_A(self, v, ensemble='isometric', approach='asymptotic',
absolute=False, **kwargs):
"""The nondimensional Helmholtz free energy
as a function of the nondimensional end separation.
Args:
v (array_like): The nondimensional end separation.
ensemble (str, optional, default='isometric'):
The thermodynamic ensemble. The `isotensional`
ensemble uses the Legendre transformation method.
approach (str, optional, default='asymptotic'):
The calculation approach.
absolute (bool, optional, default=False):
Whether not to use the absolute free energy.
**kwargs: Arbitrary keyword arguments.
Passed to :meth:`~.beta_A_isometric` or
:meth:`p` and :meth:`~.beta_G_isotensional`.
Returns:
numpy.ndarray: The nondimensional Helmholtz free energy.
"""
if ensemble == 'isometric':
if absolute is True:
beta_A = self.beta_A_abs_isometric(v, approach=approach)
else:
beta_A = self.beta_A_isometric(v, approach=approach, **kwargs)
elif ensemble == 'isotensional':
p = self.p(v, ensemble='isotensional', approach=approach, **kwargs)
if absolute is True:
beta_A = p*v + \
self.beta_G_abs_isotensional(p, approach=approach)
else:
beta_A = p*v + \
self.beta_G_isotensional(p, approach=approach, **kwargs)
return beta_A
[docs]
def beta_A_0(self, v, lambda_, ensemble='isometric', absolute=False):
"""The nondimensional Helmholtz free energy
as a function of the nondimensional end separation
for the reference system.
Args:
v (array_like): The nondimensional end separation.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isometric'):
The thermodynamic ensemble. The `isotensional`
ensemble uses the Legendre transformation method.
absolute (bool, optional, default=False):
Whether not to use the absolute free energy.
Returns:
numpy.ndarray: The nondimensional Helmholtz free energy.
"""
if ensemble == 'isometric':
if absolute is True:
beta_A_0 = self.beta_A_0_abs_isometric(v, lambda_)
else:
beta_A_0 = self.beta_A_0_isometric(v, lambda_)
elif ensemble == 'isotensional':
p = self.p_0(v, lambda_, ensemble='isotensional')
if absolute is True:
beta_A_0 = self.beta_G_0_abs_isotensional(p, lambda_) + p*v
else:
beta_A_0 = self.beta_G_0_isotensional(p, lambda_) + p*v
return beta_A_0
[docs]
def beta_A_b(self, v, lambda_, ensemble='isometric', absolute=False):
"""The nondimensional Helmholtz free energy
as a function of the nondimensional end separation
for the isolated bending system.
Args:
v (array_like): The nondimensional end separation.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isometric'):
The thermodynamic ensemble. The `isotensional`
ensemble uses the Legendre transformation method.
absolute (bool, optional, default=False):
Whether not to use the absolute free energy.
Returns:
numpy.ndarray: The nondimensional Helmholtz free energy.
"""
if ensemble == 'isometric':
if absolute is True:
beta_A_b = self.beta_A_b_isometric_abs(v, lambda_)
else:
beta_A_b = self.beta_A_b_isometric(v, lambda_)
elif ensemble == 'isotensional':
p = self.p_b(v, lambda_, ensemble='isotensional')
if absolute is True:
beta_A_b = self.beta_G_b_abs_isotensional(p, lambda_) + p*v
else:
beta_A_b = self.beta_G_b_isotensional(p, lambda_) + p*v
return beta_A_b
[docs]
def beta_G(self, p, ensemble='isotensional',
approach='asymptotic', absolute=False, **kwargs):
"""The nondimensional Gibbs free energy
as a function of the nondimensional end force.
Args:
p (array_like): The nondimensional end force.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble. The `isometric`
ensemble uses the Legendre transformation method.
approach (str, optional, default='asymptotic'):
The calculation approach.
absolute (bool, optional, default=False):
Whether not to use the absolute free energy.
**kwargs: Arbitrary keyword arguments.
Passed to :meth:`~.beta_G_isotensional` or
:meth:`v` and :meth:`~.beta_A_isometric`.
Returns:
numpy.ndarray: The nondimensional Gibbs free energy.
"""
if ensemble == 'isometric':
v = self.v(p, ensemble='isometric', approach=approach, **kwargs)
if absolute is True:
beta_G = -p*v + \
self.beta_A_abs_isometric(v, approach=approach)
else:
beta_G = -p*v + \
self.beta_A_isometric(v, approach=approach, **kwargs)
elif ensemble == 'isotensional':
if absolute is True:
beta_G = \
self.beta_G_abs_isotensional(p, approach=approach)
else:
beta_G = \
self.beta_G_isotensional(p, approach=approach, **kwargs)
return beta_G
[docs]
def beta_G_0(self, p, lambda_, ensemble='isotensional', absolute=False):
"""The nondimensional Gibbs free energy
as a function of the nondimensional end force
for the reference system.
Args:
p (array_like): The nondimensional end force.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble. The `isometric`
ensemble uses the Legendre transformation method.
absolute (bool, optional, default=False):
Whether not to use the absolute free energy.
Returns:
numpy.ndarray: The nondimensional Gibbs free energy.
"""
if ensemble == 'isometric':
v = self.v_0(p, lambda_, ensemble='isometric')
if absolute is True:
beta_G_0 = self.beta_A_0_abs_isometric(v, lambda_) - p*v
else:
beta_G_0 = self.beta_A_0_isometric(v, lambda_) - p*v
elif ensemble == 'isotensional':
if absolute is True:
beta_G_0 = self.beta_G_0_abs_isotensional(p, lambda_)
else:
beta_G_0 = self.beta_G_0_isotensional(p, lambda_)
return beta_G_0
[docs]
def beta_G_b(self, p, lambda_, ensemble='isotensional', absolute=False):
"""The nondimensional Gibbs free energy
as a function of the nondimensional end force
for the isolated bending system.
Args:
p (array_like): The nondimensional end force.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble. The `isometric`
ensemble uses the Legendre transformation method.
absolute (bool, optional, default=False):
Whether not to use the absolute free energy.
Returns:
numpy.ndarray: The nondimensional Gibbs free energy.
"""
if ensemble == 'isometric':
v = self.v_b(p, lambda_, ensemble='isometric')
if absolute is True:
beta_G_b = self.beta_A_b_isometric_abs(v, lambda_) - p*v
else:
beta_G_b = self.beta_A_b_isometric(v, lambda_) - p*v
elif ensemble == 'isotensional':
if absolute is True:
beta_G_b = self.beta_G_b_abs_isotensional(p, lambda_)
else:
beta_G_b = self.beta_G_b_isotensional(p, lambda_)
return beta_G_b
[docs]
def p(self, v, ensemble='isometric', approach='asymptotic', **kwargs):
r"""The nondimensional end force
as a function of the nondimensional end separation.
Args:
v (array_like): The nondimensional end separation.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble.
approach (str, optional, default='asymptotic'):
The calculation approach.
**kwargs: Arbitrary keyword arguments.
Passed to :meth:`~.p_isometric` or :meth:`~.v_isotensional`.
Returns:
numpy.ndarray: The nondimensional end force.
"""
if ensemble == 'isometric':
p = self.p_isometric(v, approach=approach, **kwargs)
elif ensemble == 'isotensional':
p = self.inv_fun(
lambda p:
self.v_isotensional(p, approach=approach, **kwargs), v
)
return p
[docs]
def p_0(self, v, lambda_, ensemble='isometric'):
"""The nondimensional end force
as a function of the nondimensional end separation
for the reference system.
Args:
v (array_like): The nondimensional end separation.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isometric'):
The thermodynamic ensemble.
Returns:
numpy.ndarray: The nondimensional end force.
"""
if ensemble == 'isometric':
p_0 = self.p_0_isometric(v, lambda_)
elif ensemble == 'isotensional':
p_0 = self.inv_fun(
lambda p: self.v_0_isotensional(p, lambda_), v
)
return p_0
[docs]
def p_b(self, v, lambda_, ensemble='isometric'):
"""The nondimensional end force
as a function of the nondimensional end separation
for the isolated bending system.
Args:
v (array_like): The nondimensional end separation.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isometric'):
The thermodynamic ensemble.
Returns:
numpy.ndarray: The nondimensional end force.
"""
if ensemble == 'isometric':
p_b = self.p_b_isometric(v, lambda_)
elif ensemble == 'isotensional':
p_b = self.inv_fun(
lambda p: self.v_b_isotensional(p, lambda_), v
)
return p_b
[docs]
def v(self, p, ensemble='isotensional', approach='asymptotic', **kwargs):
"""The nondimensional end separation
as a function of the nondimensional end force.
Args:
p (array_like): The nondimensional end force.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble.
approach (str, optional, default='asymptotic'):
The calculation approach.
**kwargs: Arbitrary keyword arguments.
Passed to :meth:`~.v_isotensional` or :meth:`~.p_isometric`.
Returns:
numpy.ndarray: The nondimensional end separation.
"""
if ensemble == 'isometric':
v = self.inv_fun(
lambda v:
self.p_isometric(v, approach=approach, **kwargs), p
)
elif ensemble == 'isotensional':
v = self.v_isotensional(p, approach=approach, **kwargs)
return v
[docs]
def v_0(self, p, lambda_, ensemble='isotensional'):
"""The nondimensional end separation
as a function of the nondimensional end force
for the reference system.
Args:
p (array_like): The nondimensional end force.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble.
Returns:
numpy.ndarray: The nondimensional end separation.
"""
if ensemble == 'isometric':
v_0 = self.inv_fun(
lambda v: self.p_0_isometric(v, lambda_), p
)
elif ensemble == 'isotensional':
v_0 = self.v_0_isotensional(p, lambda_)
return v_0
[docs]
def v_b(self, p, lambda_, ensemble='isotensional'):
"""The nondimensional end separation
as a function of the nondimensional end force
for the isolated bending system.
Args:
p (array_like): The nondimensional end force.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble.
Returns:
numpy.ndarray: The nondimensional end separation.
"""
if ensemble == 'isometric':
v_b = self.inv_fun(
lambda v: self.p_b_isometric(v, lambda_), p
)
elif ensemble == 'isotensional':
v_b = self.v_b_isotensional(p, lambda_)
return v_b
[docs]
def k(self, p_or_v, ensemble='isometric', approach='asymptotic', **kwargs):
r"""The nondimensional forward reaction rate coefficient
as a function of the nondimensional end force
or the nondimensional end separation.
Args:
p_or_v (array_like):
The nondimensional end force or position. Assumed to be
the end separation for the isometric ensemble and
the end force for the isotensional ensemble.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble.
approach (str, optional, default='asymptotic'):
The calculation approach.
**kwargs: Arbitrary keyword arguments.
Passed to :meth:`~.k_isometric` or :meth:`~.k_isotensional`.
Returns:
numpy.ndarray: The nondimensional forward reaction rate.
"""
if ensemble == 'isometric':
k = self.k_isometric(p_or_v, approach=approach, **kwargs)
elif ensemble == 'isotensional':
k = self.k_isotensional(p_or_v, approach=approach, **kwargs)
return k
[docs]
def k_0(self, p_or_v, lambda_, ensemble='isometric'):
r"""The nondimensional forward reaction rate coefficient
as a function of the nondimensional end force
or the nondimensional end separation
for the reference system.
Args:
p_or_v (array_like):
The nondimensional end force or position. Assumed to be
the end separation for the isometric ensemble and
the end force for the isotensional ensemble.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble.
Returns:
numpy.ndarray: The nondimensional forward reaction rate.
"""
if ensemble == 'isometric':
k_0 = self.k_0_isometric(p_or_v, lambda_)
elif ensemble == 'isotensional':
k_0 = self.k_0_isotensional(p_or_v, lambda_)
return k_0
[docs]
def k_b(self, p_or_v, lambda_, ensemble='isometric'):
r"""The nondimensional forward reaction rate coefficient
as a function of the nondimensional end force
or the nondimensional end separation
for the isolated bending system.
Args:
p_or_v (array_like):
The nondimensional end force or position. Assumed to be
the end separation for the isometric ensemble and
the end force for the isotensional ensemble.
lambda_ (array_like): The intact bond stretches.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble.
Returns:
numpy.ndarray: The nondimensional forward reaction rate.
"""
if ensemble == 'isometric':
k_b = self.k_b_isometric(p_or_v, lambda_)
elif ensemble == 'isotensional':
k_b = self.k_b_isotensional(p_or_v, lambda_)
return k_b
[docs]
def k_net(self, p_or_v, ensemble='isometric'):
r"""The nondimensional net reaction rate coefficient
as a function of the nondimensional end force
or the nondimensional end separation.
Args:
p_or_v (array_like):
The nondimensional end force or position. Assumed to be
the end separation for the isometric ensemble and
the end force for the isotensional ensemble.
ensemble (str, optional, default='isotensional'):
The thermodynamic ensemble.
Returns:
numpy.ndarray: The nondimensional net reaction rate.
Note:
Only the asymptotic approach is currently available.
"""
if ensemble == 'isometric':
k_net = self.k_net_isometric(p_or_v)
elif ensemble == 'isotensional':
k_net = self.k_net_isotensional(p_or_v)
return k_net