Source code for struphy.models.linear_mhd_curl_curl_with_proj
from struphy.models.linear_mhd_curl_curl import LinearMHDCurlCurl
from struphy.models.variables import FEECVariable
from struphy.propagators.magnetosonic import Magnetosonic
from struphy.propagators.shear_alfven_curl_curl_propagator import ShearAlfvenCurlCurlwithProjPropagator
[docs]
class LinearMHDCurlCurlwithProj(LinearMHDCurlCurl):
"""Linear ideal MHD with zero-flow equilibrium, with the magnetic field in :math:`H(\\textnormal{curl})` and the
exactly energy conserving shear-Alfvén step.
Same as :class:`~struphy.models.linear_mhd_curl_curl.LinearMHDCurlCurl`, but the curl-curl term of the implicit
shear-Alfvén step contains the :math:`\\rho_0`-weighted :math:`L^2` projection of the Lorentz force onto
:math:`H(\\textnormal{div})` (as in :class:`~struphy.models.shear_alfven_curl_curl_with_proj.ShearAlfvenCurlCurlwithProj`),
at the price of an inner mass matrix solve in every application of the Schur operator (and no effective curl-curl
preconditioner).
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)
"""
class Propagators:
def __init__(self, b_field: FEECVariable = None):
self.shear_alf = ShearAlfvenCurlCurlwithProjPropagator()
self.mag_sonic = Magnetosonic(b_field=b_field)
[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``),
conserved by the shear-Alfvén step up to the solver tolerances
- 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.ShearAlfvenCurlCurlwithProjPropagator`
2. :class:`~struphy.propagators.magnetosonic.Magnetosonic`"""
doc = rf"""**1. ShearAlfvenCurlCurlwithProjPropagator:**
{ShearAlfvenCurlCurlwithProjPropagator.__doc__}
**2. Magnetosonic:**
{Magnetosonic.__doc__}
"""
return doc
[docs]
@classmethod
def doc_long_description(cls):
r"""LinearMHDCurlCurlwithProj solves the same equations as
:class:`~struphy.models.linear_mhd_curl_curl.LinearMHDCurlCurl` (magnetic field in
:math:`H(\textnormal{curl})`, weak induction equation, momentum equation projected onto
:math:`H(\textnormal{div})`), with the projection also in the curl-curl term of the implicit shear-Alfvén step,
such that this step conserves the perturbed energy exactly. The Schur complement then contains the inverse of
the density-weighted mass matrix of 2-forms. The magnetosonic step is that of
:class:`~struphy.models.linear_mhd_curl_curl.LinearMHDCurlCurl`. Free boundary conditions are recommended for
bounded domains (see :class:`~struphy.models.linear_mhd_curl_curl.LinearMHDCurlCurl`)."""
[docs]
@classmethod
def doc_examples(cls):
r"""Create and initialize the energy conserving linear MHD curl-curl model:
.. code-block:: python
from struphy.models import LinearMHDCurlCurlwithProj
model = LinearMHDCurlCurlwithProj()
model.em_fields.b_field
model.mhd.velocity
model.scalars["en_tot"]
"""
[docs]
@classmethod
def doc_use_cases(cls):
r"""This model is appropriate for:
- linear MHD wave propagation with exact energy conservation of the shear-Alfvén step
- comparison with :class:`~struphy.models.linear_mhd_curl_curl.LinearMHDCurlCurl` and
:class:`~struphy.models.linear_mhd.LinearMHD`"""
[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
- large problems where the inner mass matrix solves of the shear-Alfvén step are too expensive (use
:class:`~struphy.models.linear_mhd_curl_curl.LinearMHDCurlCurl`)"""