Source code for struphy.models.two_fluid_quasi_neutral_toy

import copy

from feectools.ddm.mpi import mpi as MPI

from struphy.io.options import BaseUnits, LiteralOptions
from struphy.models.base import StruphyModel
from struphy.models.species import (
    FieldSpecies,
    FluidSpecies,
)
from struphy.models.variables import FEECVariable
from struphy.propagators.two_fluid_quasi_neutral_full import TwoFluidQuasiNeutralFull

rank = MPI.COMM_WORLD.Get_rank()


[docs] class TwoFluidQuasiNeutralToy(StruphyModel): """Linearized, quasi-neutral two-fluid model with zero electron inertia. Parameters ---------- base_units: BaseUnits Base units for normalization (default: BaseUnits(kBT=1.0)) ion_charge_number: int Charge number (in units of the positive elementary charge) of the ion species (default: 1) ion_mass_number: float Mass number (in units of Proton mass) of the ion species (default: 1.0) ion_epsilon: float, optional Normalized cyclotron period of the ion species. If None, computed from units and charge/mass numbers. electron_charge_number: int Charge number (in units of the positive elementary charge) of the electron species (default: 1) electron_mass_number: float Mass number (in units of Proton mass) of the electron species (default: 1.0) electron_epsilon: float, optional Normalized cyclotron period of the electron species. If None, computed from units and charge/mass numbers. """ @classmethod def model_type(cls) -> LiteralOptions.ModelTypes: return "Fluid" ## species class EMfields(FieldSpecies): def __init__(self): self.phi = FEECVariable(space="L2") self.init_variables() class Ions(FluidSpecies): def __init__( self, charge_number: int = 1, mass_number: float = 1.0, epsilon: float = None, ): self.u = FEECVariable(space="Hdiv") self.init_variables( charge_number=charge_number, mass_number=mass_number, epsilon=epsilon, ) class Electrons(FluidSpecies): def __init__( self, charge_number: int = 1, mass_number: float = 1.0, epsilon: float = None, ): self.u = FEECVariable(space="Hdiv") self.init_variables( charge_number=charge_number, mass_number=mass_number, epsilon=epsilon, ) ## propagators class Propagators: def __init__(self): self.qn_full = TwoFluidQuasiNeutralFull() ## abstract methods def __init__( self, base_units: BaseUnits = BaseUnits(kBT=1.0), ion_charge_number: int = 1, ion_mass_number: float = 1.0, ion_epsilon: float = None, electron_charge_number: int = 1, electron_mass_number: float = 1.0, electron_epsilon: float = None, ): # 0. store input parameters self.params = copy.deepcopy(locals()) # 1. instantiate all species self.em_fields = self.EMfields() self.ions = self.Ions( charge_number=ion_charge_number, mass_number=ion_mass_number, epsilon=ion_epsilon, ) self.electrons = self.Electrons( charge_number=electron_charge_number, mass_number=electron_mass_number, epsilon=electron_epsilon, ) # 2. derive units (must be done after instantiating species to access charge and mass numbers) self.setup_equation_params(base_units=base_units) # 3. instantiate all propagators self.propagators = self.Propagators() # 4. assign variables to propagators self.propagators.qn_full.variables.u = self.ions.u self.propagators.qn_full.variables.ue = self.electrons.u self.propagators.qn_full.variables.phi = self.em_fields.phi # 5. define scalars to be tracked during simulation @property def bulk_species(self): return self.ions @property def velocity_scale(self): return "thermal" def allocate_helpers(self): pass ## default parameters def generate_default_parameter_file(self, path=None, prompt=True): params_path = super().generate_default_parameter_file(path=path, prompt=prompt) new_file = [] with open(params_path, "r") as f: for line in f: if "BaseUnits()" in line: new_file += ["base_units = BaseUnits(kBT=1.0)\n"] else: new_file += [line] with open(params_path, "w") as f: for line in new_file: f.write(line)
[docs] @classmethod def doc_pde(cls): r"""**PDEs solved by model:** Ion momentum: .. math:: \frac{\partial \mathbf{u}}{\partial t} = -\nabla \phi + \frac{\mathbf{u} \times \mathbf{B}_0}{\varepsilon} + \nu \Delta \mathbf{u} + \mathbf{f} Electron momentum: .. math:: 0 = \nabla \phi - \frac{\mathbf{u}_e \times \mathbf{B}_0}{\varepsilon} + \nu_e \Delta \mathbf{u}_e + \mathbf{f}_e Quasi-neutrality constraint: .. math:: \nabla \cdot (\mathbf{u} - \mathbf{u}_e) = 0 where :math:`\mathbf{B}_0` is a static magnetic field and :math:`\mathbf{f}, \mathbf{f}_e` are given forcing terms. """
[docs] @classmethod def doc_normalization(cls): r"""Thermal-speed scaling is used: .. math:: \hat u = \hat v_\mathrm{th},\qquad e\hat\phi = m \hat v_\mathrm{th}^2. """
[docs] @classmethod def doc_scalar_quantities(cls): r"""**The following scalars are tracked during simulation:** - No default scalar diagnostics are defined by this model."""
[docs] @classmethod def doc_discretization(cls): """Time integration is performed by the following propagators (in sequence): 1. :class:`~struphy.propagators.two_fluid_quasi_neutral_full.TwoFluidQuasiNeutralFull` """ doc = rf"""**1. TwoFluidQuasiNeutralFull:** {TwoFluidQuasiNeutralFull.__doc__} """ return doc
[docs] @classmethod def doc_long_description(cls): r"""TwoFluidQuasiNeutralToy is a reduced linear two-fluid benchmark with zero electron inertia. It is meant for studying the quasi-neutral solve and the coupled ion/electron velocity response in a simplified setting. References ---------- [1] Juan Vicente Gutiérrez-Santacreu, Omar Maj, Marco Restelli: Finite element discretization of a Stokes-like model arising in plasma physics, Journal of Computational Physics 2018."""
[docs] @classmethod def doc_examples(cls): r"""Create and initialize the quasi-neutral toy model: .. code-block:: python from struphy.models import TwoFluidQuasiNeutralToy model = TwoFluidQuasiNeutralToy() model.em_fields.phi model.ions.u model.electrons.u """
[docs] @classmethod def doc_use_cases(cls): r"""This model is appropriate for: - linear quasi-neutral two-fluid benchmarks - Stokes-like plasma model verification - testing coupled velocity-potential FEEC solvers"""
[docs] @classmethod def doc_cannot_be_used_for(cls): r"""This model is not suitable for: - nonlinear two-fluid dynamics - finite electron inertia effects - kinetic phase-space phenomena - self-consistent electromagnetic wave propagation"""