"""
Data classes passed around WallGo
"""
from dataclasses import dataclass
import numpy as np
from .fields import Fields
from .freeEnergy import FreeEnergyValueType
from .helpers import boostVelocity
from .polynomial import Polynomial
[docs]
@dataclass
class PhaseInfo:
""" Object describing coexisting phases.
"""
phaseLocation1: Fields
"""Field value of the starting phase."""
phaseLocation2: Fields
"""Field value of the ending phase."""
temperature: float
"""Temperature of transition."""
[docs]
@dataclass
class FreeEnergyArrays:
"""Object containing temperatures, positions of the minimum and value of the effective potential.
"""
temperatures: np.ndarray[float] # 1D array
"""Array of temperatures."""
freeEnergyList: np.ndarray[FreeEnergyValueType] # 1D array of FreeEnergyValueType objects
"""Array of field(s) and potential value at the minimum."""
allowedDiscrepancy: float | None
"""Allowed discrepancy between the effective potential at the minimum and the user-provided value"""
[docs]
def __init__(
self,
temperatures: np.ndarray[float],
minimumList: np.ndarray[float],
potentialEffList: np.ndarray[float],
allowedDiscrepancy: float | None = None,
) -> None:
"""Initialisation of FreeEnergyArrays, based on passing 3 arrays
and a float. """
temperatures = np.asarray(temperatures)
minimumList = np.asarray(minimumList)
potentialEffList = np.asarray(potentialEffList)
if temperatures.ndim != 1:
raise ValueError("temperatures must be a 1D array.")
if temperatures.shape[0] != minimumList.shape[0]:
raise ValueError(
"The temperatures and minimumList must have the same length."
)
if temperatures.shape[0] != potentialEffList.shape[0]:
raise ValueError(
"The temperatures and potentialEffList must have the same length."
)
if allowedDiscrepancy is not None and allowedDiscrepancy < 0:
raise ValueError("allowedDiscrepancy must not be negative.")
self.temperatures = temperatures
self.freeEnergyList = FreeEnergyValueType.fromArray(
np.concatenate(
(minimumList, potentialEffList[:, np.newaxis]), axis=1,
)
)
self.allowedDiscrepancy = allowedDiscrepancy
[docs]
@dataclass
class WallParams:
"""
Holds wall widths and wall offsets for all fields
"""
widths: np.ndarray # 1D array
"""Bubble wall widths in each field direction. Should be expressed in physical units
(the units used in EffectivePotential)."""
offsets: np.ndarray # 1D array
"""Bubble wall offsets in each field direction."""
def __add__(self, other: "WallParams") -> "WallParams":
return WallParams(
widths=(self.widths + other.widths), offsets=(self.offsets + other.offsets)
)
def __sub__(self, other: "WallParams") -> "WallParams":
return WallParams(
widths=(self.widths - other.widths), offsets=(self.offsets - other.offsets)
)
def __mul__(self, number: float) -> "WallParams":
## does not work if other = WallParams type
return WallParams(widths=self.widths * number, offsets=self.offsets * number)
def __rmul__(self, number: float) -> "WallParams":
return self.__mul__(number)
def __truediv__(self, number: float) -> "WallParams":
## does not work if other = WallParams type
return WallParams(widths=self.widths / number, offsets=self.offsets / number)
[docs]
class BoltzmannBackground:
"""
Container for holding velocity, temperature and field backgrounds on which
out-of-equilibrium fluctuations live.
"""
velocityWall: float
"""Bubble wall velocity."""
velocityMid: float
"""The average between the asymptotic velocities inside and outside the bubble."""
velocityProfile: np.ndarray
"""Fluid velocity as a function of position."""
fieldProfiles: Fields
"""Field profile as a function of position."""
temperatureProfile: np.ndarray
"""Temperarture profile as a function of position."""
polynomialBasis: str
"""Type of polynomial basis used, e.g. Chebyshev, Cardinal."""
[docs]
def __init__(
self,
velocityMid: float,
velocityProfile: np.ndarray,
fieldProfiles: Fields,
temperatureProfile: np.ndarray,
polynomialBasis: str = "Cardinal",
):
# assumes input is in the wall frame
self.velocityWall = 0
self.velocityProfile = np.asarray(velocityProfile)
self.fieldProfiles = fieldProfiles.view(Fields) ## NEEDS to be Fields object
self.temperatureProfile = np.asarray(temperatureProfile)
self.polynomialBasis = polynomialBasis
self.velocityMid = velocityMid
[docs]
def boostToPlasmaFrame(self) -> None:
"""
Boosts background to the plasma frame
"""
self.velocityProfile = boostVelocity(self.velocityProfile, self.velocityMid)
self.velocityWall = boostVelocity(self.velocityWall, self.velocityMid)
[docs]
def boostToWallFrame(self) -> None:
"""
Boosts background to the wall frame
"""
self.velocityProfile = boostVelocity(self.velocityProfile, self.velocityWall)
self.velocityWall = 0
[docs]
@dataclass
class BoltzmannDeltas:
"""
Integrals of the out-of-equilibrium particle densities,
defined in equation (15) of arXiv:2204.13120.
"""
Delta00: Polynomial # pylint: disable=invalid-name
r"""Relativistically invariant integral over :math:`\delta f`."""
Delta02: Polynomial # pylint: disable=invalid-name
r"""Relativistically invariant integral over
:math:`\mathcal{P}^2_\text{pl}\delta f`."""
Delta20: Polynomial # pylint: disable=invalid-name
r"""Relativistically invariant integral over
:math:`\mathcal{E}^2_\text{pl}\delta f`."""
Delta11: Polynomial # pylint: disable=invalid-name
r"""Relativistically invariant integral over
:math:`\mathcal{E}_\text{pl}\mathcal{P}_\text{pl}\delta f`."""
# string literal type hints as class not defined yet
def __mul__(self, number: float) -> "BoltzmannDeltas":
"""
Multiply a BoltzmannDeltas object with a scalar.
"""
return BoltzmannDeltas(
Delta00=number * self.Delta00,
Delta02=number * self.Delta02,
Delta20=number * self.Delta20,
Delta11=number * self.Delta11,
)
def __rmul__(self, number: float) -> "BoltzmannDeltas":
"""
Multiply a BoltzmannDeltas object with a scalar.
"""
return BoltzmannDeltas(
Delta00=number * self.Delta00,
Delta02=number * self.Delta02,
Delta20=number * self.Delta20,
Delta11=number * self.Delta11,
)
def __add__(self, other: "BoltzmannDeltas") -> "BoltzmannDeltas":
"""
Add two BoltzmannDeltas objects.
"""
return BoltzmannDeltas(
Delta00=other.Delta00 + self.Delta00,
Delta02=other.Delta02 + self.Delta02,
Delta20=other.Delta20 + self.Delta20,
Delta11=other.Delta11 + self.Delta11,
)
def __sub__(self, other: "BoltzmannDeltas") -> "BoltzmannDeltas":
"""
Substract two BoltzmannDeltas objects.
"""
return self.__add__((-1) * other)