Source code for struphy.models.maxwell

from struphy import BaseUnits
from struphy.io.options import LiteralOptions
from struphy.models.base import StruphyModel
from struphy.models.scalars import BilinearEnergyFEEC
from struphy.models.species import (
    FieldSpecies,
)
from struphy.models.variables import FEECVariable
from struphy.propagators.maxwell_weak_ampere import MaxwellWeakAmpere


[docs] class Maxwell(StruphyModel): """Maxwell's equations in vacuum for electromagnetic field evolution. The models of the Maxwell family inherit from this model: they call ``super().__init__()`` and extend the hooks of :meth:`~struphy.models.base.StruphyModel._setup` (species, propagators, variable links, scalars). Parameters ---------- base_units: BaseUnits Base units for normalization (default: BaseUnits()) """ ## species class EMFields(FieldSpecies): """Electromagnetic fields of the Maxwell family (named ``em_fields`` in all models of the family). Models with more field variables declare them before calling ``super().__init__()``.""" def __init__(self): self.e_field = FEECVariable(space="Hcurl") self.b_field = FEECVariable(space="Hdiv") self.init_variables() ## propagators class Propagators: """Propagators of Maxwell's equations: ``maxwell`` (Faraday's and Ampère's law).""" def __init__(self): self.maxwell = MaxwellWeakAmpere() # attribute types for IDEs and type checkers: the classes of this model, not those of the parent em_fields: EMFields propagators: Propagators ## abstract methods def __init__(self, base_units: BaseUnits = BaseUnits()): # 0. store input parameters (a model inheriting from Maxwell stores its own before calling super().__init__) self._store_params(locals()) # 1.-5. species, units, propagators, variable links and scalars, see StruphyModel._setup self._setup(base_units) def _create_species(self): """:meta private:""" self.em_fields = self.EMFields() def _link_propagator_variables(self): """:meta private:""" self.propagators.maxwell.variables.e = self.em_fields.e_field self.propagators.maxwell.variables.b = self.em_fields.b_field def _create_scalars(self): """:meta private:""" en_E = BilinearEnergyFEEC(self.em_fields.e_field) en_B = BilinearEnergyFEEC(self.em_fields.b_field) return {"en_E": en_E, "en_B": en_B, "en_tot": en_E + en_B} @property def bulk_species(self): return None @property def velocity_scale(self): return "light" def post_allocate(self): pass ## abstract methods for documentation @classmethod def model_type(cls) -> LiteralOptions.ModelTypes: return "Toy"
[docs] @classmethod def doc_pde(cls): r"""**PDEs solved by model:** Ampère's law (no current): .. math:: \frac{\partial \mathbf{E}}{\partial t} - \nabla \times \mathbf{B} = 0 Faraday's law: .. math:: \frac{\partial \mathbf{B}}{\partial t} + \nabla \times \mathbf{E} = 0 **Conserved quantities** (for :math:`\mathbf E \times \mathbf n = 0` on the boundary, or periodic boundaries): Electromagnetic energy: .. math:: \frac{\textnormal d}{\textnormal d t} \frac 12 \int \left( |\mathbf E|^2 + |\mathbf B|^2 \right) \textnormal d \mathbf x = 0 """
[docs] @classmethod def doc_normalization(cls): r"""Velocity and fields are normalized as: .. math:: \hat v = c\,,\qquad \hat E = c \hat B where :math:`c` is the speed of light."""
[docs] @classmethod def doc_scalar_quantities(cls): r"""**The following scalars are tracked during simulation:** - Electric energy: :math:`E_E = \frac{1}{2} \int |\mathbf E|^2 \, dV` (``en_E``) - Magnetic energy: :math:`E_B = \frac{1}{2} \int |\mathbf B|^2 \, dV` (``en_B``) - Total energy: :math:`E_{tot} = E_E + E_B` (``en_tot``)"""
[docs] @classmethod def doc_long_description(cls): r"""This model simulates the propagation of electromagnetic waves in vacuum using Maxwell's equations without sources. It uses a finite element exterior calculus (FEEC) formulation with the electric field in H(curl) and the magnetic field in H(div) spaces. This is the parent model of the Maxwell family: :class:`~struphy.models.ColdPlasma` adds the current of a cold electron fluid, and :class:`~struphy.models.ColdPlasmaVlasov` adds a hot kinetic species; both inherit the species, propagators and scalars of this model."""
[docs] @classmethod def doc_examples(cls): r"""Create and initialize a Maxwell model: .. code-block:: python from struphy.models import Maxwell model = Maxwell() # Fields are accessible via: model.em_fields.e_field model.em_fields.b_field """
[docs] @classmethod def doc_use_cases(cls): """Propagation of electromagnetic waves in vacuum."""
[docs] @classmethod def doc_cannot_be_used_for(cls): """Plasma dynamics, plasma-field interactions, or any scenario involving charged particles. This model does not include any particle species or coupling to matter."""