Source code for struphy.models.linear_mhd_curl_curl

from struphy.models.linear_mhd import LinearMHD
from struphy.models.species import FieldSpecies
from struphy.models.variables import FEECVariable
from struphy.propagators.magnetosonic import Magnetosonic
from struphy.propagators.shear_alfven_curl_curl_propagator import ShearAlfvenCurlCurlPropagator


[docs] class LinearMHDCurlCurl(LinearMHD): """Linear ideal MHD with zero-flow equilibrium, with the magnetic field in :math:`H(\\textnormal{curl})`. Same equations as :class:`~struphy.models.linear_mhd.LinearMHD`, but with a weak induction equation, such that the implicit shear-Alfvén step leads to a curl-curl system for the magnetic field, which is preconditioned by the Hiptmair-Xu preconditioner (as in :class:`~struphy.models.shear_alfven_curl_curl.ShearAlfvenCurlCurl`). Parameters ---------- base_units: BaseUnits Base units for normalization (default: BaseUnits()) mass_number: float Mass number (in units of Proton mass) of the ion species (default: 1.0) """ ## species class EMFields(FieldSpecies): def __init__(self): self.b_field = FEECVariable(space="Hcurl") self.init_variables() ## propagators class Propagators: def __init__(self, b_field: FEECVariable = None): self.shear_alf = ShearAlfvenCurlCurlPropagator() self.mag_sonic = Magnetosonic(b_field=b_field) ## abstract methods for documentation
[docs] @classmethod def doc_pde(cls): r"""**PDEs solved by model:** Continuity (mass conservation): .. math:: \frac{\partial \tilde{\rho}}{\partial t} + \nabla \cdot (\rho_0 \tilde{\mathbf{U}}) = 0 Momentum (Lorentz force): .. math:: \rho_0 \frac{\partial \tilde{\mathbf{U}}}{\partial t} + \nabla \tilde{p} = (\nabla \times \tilde{\mathbf{B}}) \times \mathbf{B}_0 + (\nabla \times \mathbf{B}_0) \times \tilde{\mathbf{B}} Energy (adiabatic process): .. math:: \frac{\partial \tilde{p}}{\partial t} + \nabla \cdot (p_0 \tilde{\mathbf{U}}) + \frac{2}{3} p_0 \nabla \cdot \tilde{\mathbf{U}} = 0 Induction (Faraday's law, solved weakly in :math:`H(\textnormal{curl})`): .. math:: \frac{\partial \tilde{\mathbf{B}}}{\partial t} - \nabla \times (\tilde{\mathbf{U}} \times \mathbf{B}_0) = 0. """
[docs] @classmethod def doc_normalization(cls): r"""All velocities are normalized by the Alfvén velocity: .. math:: \hat{U} = \hat{v}_\mathrm{A} = \frac{\hat{B}_0}{\sqrt{\mu_0 \rho_0}} The model therefore uses the Alfvén velocity as its characteristic speed scale."""
[docs] @classmethod def doc_scalar_quantities(cls): r"""**The following scalars are tracked during simulation:** - Kinetic energy (perturbation): :math:`E_U = \frac{1}{2} \int \rho_0 |\tilde{\mathbf{U}}|^2 \, \mathrm{d}V` - Magnetic energy (perturbation, magnetic field as a 1-form): :math:`E_B = \frac{1}{2} \int \frac{|\tilde{\mathbf{B}}|^2}{\mu_0} \, \mathrm{d}V` - Mean pressure perturbation: :math:`E_p = \int \frac{\tilde{p}}{\gamma - 1} \, \mathrm{d}V` (``en_p``). This is a linear diagnostic, not an energy. - Thermal perturbation energy: :math:`E_{\mathrm{thermal}} = \frac{1}{2}\int \frac{\tilde{p}^2}{\gamma p_0} \, \mathrm{d}V` (``en_thermal``), with :math:`\gamma = 5/3` - Total perturbed energy: :math:`E_{\mathrm{tot}} = E_U + E_B + E_{\mathrm{thermal}}` (``en_tot``). The shear-Alfvén step damps it numerically (the damping vanishes with the resolution along the background field; exactly conserving shear-Alfvén step in :class:`~struphy.models.linear_mhd_curl_curl_with_proj.LinearMHDCurlCurlwithProj`). - Equilibrium magnetic energy: :math:`E_{B0} = \frac{1}{2} \int \frac{|\mathbf{B}_0|^2}{\mu_0} \, \mathrm{d}V` (with :math:`\mathbf B_0` projected as a 1-form) - Equilibrium internal energy: :math:`E_{p0} = \int \frac{p_0}{\gamma - 1} \, \mathrm{d}V` - Total magnetic energy: :math:`E_{B,\mathrm{tot}} = \frac{1}{2} \int \frac{|\mathbf{B}_0 + \tilde{\mathbf{B}}|^2}{\mu_0} \, \mathrm{d}V`"""
[docs] @classmethod def doc_discretization(cls): """Time integration is performed by the following propagators (in sequence): 1. :class:`~struphy.propagators.shear_alfven_curl_curl_propagator.ShearAlfvenCurlCurlPropagator` 2. :class:`~struphy.propagators.magnetosonic.Magnetosonic`""" doc = rf"""**1. ShearAlfvenCurlCurlPropagator:** {ShearAlfvenCurlCurlPropagator.__doc__} **2. Magnetosonic:** {Magnetosonic.__doc__} """ return doc
[docs] @classmethod def doc_long_description(cls): r"""LinearMHDCurlCurl solves the same equations as :class:`~struphy.models.linear_mhd.LinearMHD`, with the perturbed magnetic field in :math:`H(\textnormal{curl})` instead of :math:`H(\textnormal{div})`. The splitting is the same: the shear-Alfvén step of :class:`~struphy.models.shear_alfven_curl_curl.ShearAlfvenCurlCurl` (weak induction equation, field-aligned curl-curl system for the magnetic field, Hiptmair-Xu preconditioner by default), followed by the magnetosonic step, in which the force :math:`(\nabla \times \mathbf B_0) \times \tilde{\mathbf B}` of the 1-form :math:`\tilde{\mathbf B}` enters through the mixed mass matrix :attr:`~struphy.feec.mass.WeightedMassOperators.M21J`. The shear-Alfvén step is not exactly energy conserving: it damps the waves numerically, with a damping that vanishes quickly with the resolution along the background field (see :class:`~struphy.models.linear_mhd_curl_curl_with_proj.LinearMHDCurlCurlwithProj` for the exactly energy conserving version). Boundary conditions: with essential boundary conditions in the de Rham sequence, the tangential components of the magnetic field (a 1-form) vanish on that boundary, which is unphysical at a wall with :math:`\mathbf B_0 \cdot \mathbf n = 0`. Free boundary conditions are therefore recommended: they impose :math:`\tilde{\mathbf U} \cdot \mathbf n = 0` weakly in the shear-Alfvén step and :math:`\tilde p = 0` weakly in the magnetosonic step (natural boundary condition of the pressure term). All evolved quantities are perturbations around a stationary equilibrium: - :math:`\tilde{\rho}` - density perturbation - :math:`\tilde{\mathbf{U}}` - velocity perturbation (2-form) - :math:`\tilde{p}` - pressure perturbation - :math:`\tilde{\mathbf{B}}` - magnetic field perturbation (1-form)"""
[docs] @classmethod def doc_examples(cls): r"""Create and initialize a linear MHD curl-curl model: .. code-block:: python from struphy.models import LinearMHDCurlCurl model = LinearMHDCurlCurl() # Access fields model.em_fields.b_field model.mhd.density model.mhd.velocity model.mhd.pressure # Access tracked scalar quantities model.scalars["en_U"] model.scalars["en_B"] model.scalars["en_tot"] """
[docs] @classmethod def doc_use_cases(cls): r"""This model is appropriate for: - linear MHD wave propagation with large time steps (fast curl-curl solve of the shear-Alfvén step) - comparison with :class:`~struphy.models.linear_mhd.LinearMHD` (magnetic field in :math:`H(\textnormal{div})`) - testing curl-curl (Hiptmair-Xu) preconditioning in linear MHD"""
[docs] @classmethod def doc_cannot_be_used_for(cls): r"""This model is not suitable for: - nonlinear MHD dynamics with finite-amplitude perturbations - equilibria with non-zero background flow - dissipative effects such as resistivity or viscosity - kinetic or particle-field effects beyond the fluid MHD description - polar splines with the Hiptmair-Xu preconditioner"""