spectre.converters.fix2free =========================== .. py:module:: spectre.converters.fix2free .. autoapi-nested-parse:: Convert a fixed-boundary SPECTRE InputParameters to free-boundary. The workflow separates boundary-shape generation from field computation so the user can supply any simsopt SurfaceRZFourier as the computational boundary (e.g. one extended with :meth:`~simsopt.geo.SurfaceRZFourier.extend_via_normal`). Module Contents --------------- .. py:function:: params_to_simsopt_boundary(params, which='plasma', ntheta=248, nzeta_per_period=252) Convert InputParameters boundary to a simsopt SurfaceRZFourier. Args: params: :class:`~spectre.file_io.input_parameters.InputParameters` pydantic object. which: ``'plasma'`` → uses ``rbc``/``zbs``; ``'comp'`` → uses ``rwc``/``zws``. ntheta: number of theta quadrature points for the full torus. nzeta_per_period: number of zeta quadrature points per field period. Returns: simsopt :class:`~simsopt.geo.SurfaceRZFourier`. .. py:function:: fix2free(params, bs, comp_boundary, nvns_mpol=None, nvns_ntor=None, filename=None, curpol=None, vacuum=False) Convert a fixed-boundary SPECTRE InputParameters to free-boundary. The caller is responsible for building the computational boundary — e.g. via :func:`params_to_simsopt_boundary` followed by :meth:`~simsopt.geo.SurfaceRZFourier.extend_via_normal`. If ``params.physics.lfreebound == 1`` on input, the function replaces the existing computational boundary and vacuum field while leaving all other fields unchanged. The output ``lconstraint`` is chosen as follows: * ``vacuum=True`` → ``lconstraint=3`` (toroidal-current constraint; the transform is not meaningful in a vacuum equilibrium). * input ``lconstraint == 1`` → preserved (rotational-transform constraint). * otherwise → ``lconstraint=3`` (default for free-boundary). The sign convention is anchored to the **actual coil field**: B_φ is evaluated from ``bs`` at :math:`R=R_{00}, \phi=0, Z=0` and its sign is given to BOTH ``curpol`` and ``phiedge``. This prevents VMEC fixed boundary runs with unsigned Phiedge giving beleivable-but-wrong results, and ensures consistency with VNS, which is directly evaluated from the same biot-savart evaluation. if ``curpol`` (μ₀ × net poloidal linking current) is not specified, it is calculated from the sum of all coil currents. This assumes every coil in your set links the plasma exactly once in the same direction. All the ways coils can (un) link the plasma cannot be captured in a neat algorithm, so we ask you to compute this yourself. The output ``phiedge`` keeps the **magnitude** of ``params.physics.phiedge`` but takes its **sign** from the coil field. The coils also set the comp/plasma flux *ratio* that fills the vacuum-slot ``tflux[nvol]``. A good sanity check can be performed against a ground truth, buy running this with `vacuum=True`, and comparing the converged state with the Biot-Savart field directly from the coils. Args: params: :class:`~spectre.file_io.input_parameters.InputParameters` object (fixed- or free-boundary). bs: simsopt :class:`~simsopt.field.BiotSavart` built from the full coil set including all symmetry copies. comp_boundary: simsopt :class:`~simsopt.geo.SurfaceRZFourier` representing the computational (outer) boundary, already extended beyond the plasma. Its quadrature resolution is used for the B·n evaluation grid. nvns_mpol: poloidal Fourier resolution for the B·n modes. Defaults to ``params.physics.mpol``. nvns_ntor: toroidal Fourier resolution for the B·n modes. Defaults to ``params.physics.ntor``. filename: if given, write the result as a TOML file at this path. curpol: μ₀ × total poloidal linking current [T·m]. If ``None`` (default), computed automatically from ``bs.coils`` as ``sign(B_φ_coils) × μ₀ × Σ|I_coil|``. That formula assumes every coil is a modular coil that links the plasma exactly once (a warning is issued); pass ``curpol`` explicitly for coil sets that include poloidal field coils or coils linking the plasma more than once. When given, only its magnitude is used. vacuum: if ``True``, produce a vacuum free-boundary equilibrium. A vacuum field carries no plasma pressure and no plasma current, this sets ``pressure``, ``pscale``, ``curtor``, ``ivolume`` and ``isurf`` to zero, and ``lbnszero`` Returns: Validated :class:`~spectre.file_io.input_parameters.InputParameters` with ``lfreebound = 1``. Raises: ImportError: if simsopt is not installed. .. py:function:: plot_freeboundary_modes(bs, params, ntheta=248, nzeta=252, log_scale=False, vns_rtol=0.001) Plot B·n mode spectrum and B·n map for a free-boundary setup. Evaluates B·n on the computational boundary, FFTs it at twice the stored resolution (−2·ntor … 2·ntor × 0 … 2·mpol), and draws a red box around the modes that are actually stored in ``params`` (−ntor … ntor × 0 … mpol). The truncation error — the fraction of the B·n spectral RMS that falls outside that box — is printed, and the freshly evaluated modes are checked against the ``vns`` already stored in ``params``. Args: bs: simsopt :class:`~simsopt.field.BiotSavart`. params: :class:`~spectre.file_io.input_parameters.InputParameters` with ``lfreebound == 1`` (``rwc``/``zws`` populated). ntheta: theta quadrature points for the B·n evaluation. nzeta: zeta quadrature points per field period for the B·n evaluation. log_scale: if ``True``, colour-map shows log₁₀ of the mode amplitude, floored at ``1e-7``. Default ``False`` plots the raw amplitude, which makes the spectrum decay and the dominant modes easier to compare. vns_rtol: tolerance for the ``vns`` consistency check, as a peak-normalised max deviation between the stored and re-evaluated modes. The match is not bitwise: B·n is quadrature-sampled and the comp boundary is rebuilt from the stored (truncated) ``rwc``/``zws``, so the modes shift slightly when this grid or resolution differs from the one used at creation. For the standard same-resolution workflow the deviation is ~1e-5; raise this if the comp boundary was built at higher resolution than ``mpol``/``ntor``. Returns: matplotlib Figure with two panels: mode spectrum (left) and B·n map (right). Raises: ValueError: if ``params.physics.vns`` deviates from the B·n modes evaluated here by more than ``vns_rtol`` (peak-normalised).