bluemira.equilibria.equilibrium =============================== .. py:module:: bluemira.equilibria.equilibrium .. autoapi-nested-parse:: Plasma MHD equilibrium and state objects Classes ------- .. autoapisummary:: bluemira.equilibria.equilibrium.VerticalPositionControlType bluemira.equilibria.equilibrium.MHDState bluemira.equilibria.equilibrium.FixedPlasmaEquilibrium bluemira.equilibria.equilibrium.CoilSetMHDState bluemira.equilibria.equilibrium.Breakdown bluemira.equilibria.equilibrium.QpsiCalcMode bluemira.equilibria.equilibrium.Equilibrium Module Contents --------------- .. py:class:: VerticalPositionControlType(*args, **kwds) Bases: :py:obj:`enum.Enum` .. autoapi-inheritance-diagram:: bluemira.equilibria.equilibrium.VerticalPositionControlType :parts: 1 :private-bases: Stabilisation strategies for vertical position control .. py:attribute:: VIRTUAL .. py:attribute:: FEEDBACK .. py:method:: _missing_(value: str) :classmethod: .. py:class:: MHDState(grid: bluemira.equilibria.grid.Grid, *, o_point_fallback: bluemira.equilibria.profiles.OPointCalcOptions = OPointCalcOptions.GRID_CENTRE) Base class for magneto-hydrodynamic states .. py:attribute:: x :type: numpy.typing.NDArray[numpy.float64] | None :value: None .. py:attribute:: z :type: numpy.typing.NDArray[numpy.float64] | None :value: None .. py:attribute:: dx :type: float | None :value: None .. py:attribute:: dz :type: float | None :value: None .. py:attribute:: limiter :type: bluemira.equilibria.limiter.Limiter | None :value: None .. py:attribute:: _o_point_fallback .. py:attribute:: _label :type: str | None :value: None .. py:property:: label :type: str A name used to identify the MHD state. .. py:method:: set_grid(grid: bluemira.equilibria.grid.Grid) Sets a Grid object for an Equilibrium, and sets the G-S operator and G-S solver on the grid. :param grid: The grid upon which to solve the Equilibrium .. py:method:: _get_eqdsk(filename: pathlib.Path | str, from_cocos: int | None = 11, *, qpsi_positive: bool | None = None, full_coil: bool = False, regrid_nx_nz: tuple[int, int] | None = None, **kwargs) -> tuple[eqdsk.EQDSKInterface, bluemira.equilibria.grid.Grid, tuple[int, int] | None] :classmethod: Get eqdsk data from file for read in :param filename: Filename :param from_cocos: The COCOS index of the EQDSK file. Used when the determined COCOS is ambiguous. Will raise if given and not one of the determined COCOS indices. :param qpsi_positive: Whether qpsi is positive or not, required for identification when qpsi is not present in the file. :param full_coil: Whether the eqdsk dxc and dzc represents the full coil width or half coil width :param regrid_nx_nz: Modify grid to use new nx and nz values :returns: * *e* -- Instance if EQDSKInterface with the EQDSK file read in * *psi* -- psi array * *coilset* -- Coilset from eqdsk * *grid* -- Grid from eqdsk * *limiter* -- Limiter instance if any limiters are in file .. py:method:: _prepare_eqdsk(data: dict[str, Any], filename: pathlib.Path | str, header: str = 'bluemira_equilibria', directory: str | None = None, filetype: str = 'json') -> eqdsk.EQDSKInterface Prepares the Equilibrium Object eqdsk file :returns: The initial EQDSKInterface data structure :rtype: EQDSKInterface :raises ValueError: Cant find data directory .. py:class:: FixedPlasmaEquilibrium(grid: bluemira.equilibria.grid.Grid, lcfs: bluemira.geometry.coordinates.Coordinates, profiles: bluemira.equilibria.profiles.Profile, psi: numpy.typing.NDArray[numpy.float64], psi_ax: float, psi_b: float, filename: pathlib.Path | str | None = None, *, label: str = 'Fixed Plasma Equilibrium', o_point_fallback: bluemira.equilibria.profiles.OPointCalcOptions = OPointCalcOptions.GRID_CENTRE) Bases: :py:obj:`MHDState` .. autoapi-inheritance-diagram:: bluemira.equilibria.equilibrium.FixedPlasmaEquilibrium :parts: 1 :private-bases: Class for loading a fixed boundary plasma equilibrium. .. py:attribute:: _psi .. py:attribute:: _jtor .. py:attribute:: profiles .. py:attribute:: plasma .. py:attribute:: _lcfs .. py:attribute:: filename :value: None .. py:attribute:: _label :value: 'Fixed Plasma Equilibrium' .. py:method:: from_eqdsk(filename: pathlib.Path | str, from_cocos: int | None = 11, *, qpsi_positive: bool | None = None, full_coil: bool = False, regrid_nx_nz: tuple[int, int] | None = None, **kwargs) :classmethod: Initialises a Breakdown Object from an eqdsk file. Note that this will involve recalculation of the magnetic flux. :param filename: Filename :param from_cocos: The COCOS index of the EQDSK file. Used when the determined COCOS is ambiguous. Will raise if given and not one of the determined COCOS indices. :param qpsi_positive: Whether qpsi is positive or not, required for identification when qpsi is not present in the file. :param full_coil: Whether the eqdsk dxc and dzc represents the full coil width or half coil width :param regrid_nx_nz: Modify grid to use new nx and nz values .. py:method:: to_eqdsk(data, filename, header='bluemira_equilibria', directory=None, filetype='json', to_cocos=BLUEMIRA_DEFAULT_COCOS, **kwargs) Writes the FixedPlasmaEquilibrium Object to an eqdsk file .. py:method:: get_LCFS() -> bluemira.geometry.coordinates.Coordinates Get the Last Closed FLux Surface (LCFS). :returns: The Coordinates of the LCFS .. py:method:: Bx(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total radial magnetic field at point (x, z) from coils :param x: Radial coordinates for which to return Bx. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bx. If None, returns values at all grid points :returns: Radial magnetic field at x, z .. py:method:: Bz(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total vertical magnetic field at point (x, z) from coils :param x: Radial coordinates for which to return Bz. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bz. If None, returns values at all grid points :returns: Vertical magnetic field at x, z .. py:method:: Bp(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total poloidal magnetic field at point(s) (x, z) :param x: Radial coordinates for which to return Bp. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bp. If None, returns values at all grid points :returns: Poloidal magnetic field at x, z .. py:method:: psi(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total poloidal magnetic flux, either for the whole grid, or for specified x, z coordinates. :param x: Radial coordinates for which to return psi. If None, returns values at all grid points :param z: Vertical coordinates for which to return psi. If None, returns values at all grid points :returns: Poloidal magnetic flux at x, z .. py:method:: plot(ax: matplotlib.axes.Axes | None = None, *, field: bluemira.equilibria.diagnostics.EqBPlotParam = EqBPlotParam.PSI) Plots the FixedPlasmaEquilibrium object onto `ax` :returns: the plot axis .. py:class:: CoilSetMHDState(grid: bluemira.equilibria.grid.Grid, coilset: bluemira.equilibria.coils.CoilSet, *, o_point_fallback: bluemira.equilibria.profiles.OPointCalcOptions = OPointCalcOptions.GRID_CENTRE) Bases: :py:obj:`MHDState` .. autoapi-inheritance-diagram:: bluemira.equilibria.equilibrium.CoilSetMHDState :parts: 1 :private-bases: Base class for magneto-hydrodynamic states with a CoilSet .. py:attribute:: _psi_green :value: None .. py:attribute:: _bx_green :value: None .. py:attribute:: _bz_green :value: None .. py:attribute:: _coilset .. py:property:: coilset Equilibria coilset .. py:method:: _get_eqdsk(filename: pathlib.Path | str, from_cocos: int | None = 11, *, qpsi_positive: bool | None = None, full_coil: bool = False, regrid_nx_nz: tuple[int, int] | None = None, user_coils: bluemira.equilibria.coils.CoilSet | None = None, force_symmetry: bool = False, force_symmetry_rtol: float | None = None, **kwargs) -> tuple[eqdsk.EQDSKInterface, bluemira.equilibria.grid.Grid, tuple[int, int] | None, bluemira.equilibria.coils.CoilSet, bluemira.equilibria.limiter.Limiter | None] :classmethod: Get eqdsk data from file for read in :param filename: Filename :param from_cocos: The COCOS index of the EQDSK file. Used when the determined COCOS is ambiguous. Will raise if given and not one of the determined COCOS indices. :param qpsi_positive: Whether qpsi is positive or not, required for identification when qpsi is not present in the file. :param full_coil: Whether the eqdsk dxc and dzc represents the full coil width or half coil width :param regrid_nx_nz: Modify grid to use new nx and nz values :param user_coils: Coilset provided by the user. Set current, j_max and b_max to zero in user_coils. :param force_symmetry: Whether or not to force symmetrisation in the CoilSet :param force_symmetry_rtol: Relative tolerance used when comparing coil values. The values for the secondary coil in the pair will be set to be equal to the primary coil values if they are within force_symmetry_rtol. :returns: * *e* -- Instance if EQDSKInterface with the EQDSK file read in * *psi* -- psi array * *regrid_nx_nz* -- modified regrid argument, possibly overwritten if previous grid states matched * *coilset* -- Coilset from eqdsk * *grid* -- Grid from eqdsk * *limiter* -- Limiter instance if any limiters are in file .. py:method:: _remap_greens() Stores Green's functions arrays in a dictionary of coils. Used upon initialisation and must be called after meshing of coils. .. rubric:: Notes Modifies: ._pgreen: Greens function coil mapping for psi ._bxgreen: Greens function coil mapping for Bx .bzgreen: Greens function coil mapping for Bz .. py:method:: get_coil_forces() -> numpy.typing.NDArray[numpy.float64] Returns the Fx and Fz force at the centre of the control coils :returns: Fx, Fz array of forces on coils [N] .. rubric:: Notes Will not work for symmetric circuits .. py:method:: get_coil_fields() -> numpy.typing.NDArray[numpy.float64] Returns the poloidal magnetic fields on the control coils (approximate peak at the middle inner radius of the coil) :returns: The Bp array of fields on coils [T] .. py:method:: reset_grid(grid: bluemira.equilibria.grid.Grid, psi: numpy.typing.NDArray[numpy.float64] | None = None) Reset the grid for the MHDState. :param grid: The grid to set the MHDState on :param psi: Initial psi array to use .. py:method:: _set_init_plasma(grid: bluemira.equilibria.grid.Grid, psi: numpy.typing.NDArray[numpy.float64] | None = None) .. py:class:: Breakdown(coilset: bluemira.equilibria.coils.CoilSet, grid: bluemira.equilibria.grid.Grid, psi: numpy.typing.NDArray[numpy.float64] | None = None, filename: pathlib.Path | str | None = None, **kwargs) Bases: :py:obj:`CoilSetMHDState` .. autoapi-inheritance-diagram:: bluemira.equilibria.equilibrium.Breakdown :parts: 1 :private-bases: Represents the breakdown state :param coilset: The set of coil objects which the equilibrium will be solved with :param grid: The grid which to solve over :param psi: The initial psi array (optional) :param filename: The filename of the breakdown (optional) .. py:attribute:: plasma .. py:attribute:: limiter .. py:attribute:: breakdown_point .. py:attribute:: filename :value: None .. py:method:: from_eqdsk(filename: pathlib.Path | str, from_cocos: int | None = 11, *, qpsi_positive: bool | None = None, full_coil: bool = False, regrid_nx_nz: tuple[int, int] | None = None, force_symmetry: bool, user_coils: bluemira.equilibria.coils.CoilSet | None = None, **kwargs) :classmethod: Initialises a Breakdown Object from an eqdsk file. Note that this will involve recalculation of the magnetic flux. :param filename: Filename :param from_cocos: The COCOS index of the EQDSK file. Used when the determined COCOS is ambiguous. Will raise if given and not one of the determined COCOS indices. :param qpsi_positive: Whether qpsi is positive or not, required for identification when qpsi is not present in the file. :param full_coil: Whether the eqdsk dxc and dzc represents the full coil width or half coil width :param regrid_nx_nz: Modify grid to use new nx and nz values :param force_symmetry: Whether or not to force symmetrisation in the CoilSet :param user_coils: Coilset provided by the user. Set current, j_max and b_max to zero in user_coils. .. py:method:: to_dict() -> dict[str, Any] Creates a dictionary for a Breakdown object :returns: A dictionary for the Breakdown object .. py:method:: to_eqdsk(filename: pathlib.Path | str, header: str = 'bluemira_breakdown', directory: str | None = None, filetype: str = 'json', to_cocos: int = BLUEMIRA_DEFAULT_COCOS, **kwargs) Writes the Breakdown Object to an eqdsk file .. py:method:: set_breakdown_point(x_bd: float, z_bd: float) Set the point at which the centre of the breakdown region is defined. :param x_bd: The x coordinate of the centre of the breakdown region :param z_bd: The z coordinate of the centre of the breakdown region .. py:property:: breakdown_psi :type: float The poloidal magnetic flux at the centre of the breakdown region. :returns: The minimum poloidal magnetic flux at the edge of the breakdown region [V.s/rad] .. py:method:: Bx(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total radial magnetic field at point (x, z) from coils :param x: Radial coordinates for which to return Bx. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bx. If None, returns values at all grid points :returns: Radial magnetic field at x, z .. py:method:: Bz(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total vertical magnetic field at point (x, z) from coils :param x: Radial coordinates for which to return Bz. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bz. If None, returns values at all grid points :returns: Vertical magnetic field at x, z .. py:method:: Bp(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total poloidal magnetic field at point (x, z) from coils :param x: Radial coordinates for which to return Bp. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bp. If None, returns values at all grid points :returns: Poloidal magnetic field at x, z .. py:method:: dBx_dz(x: numpy.typing.ArrayLike, z: numpy.typing.ArrayLike) Total differential of the radial magnetic field at point (x, z) from coils :param x: Radial coordinates for which to return Bz. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bz. If None, returns values at all grid points :returns: Differential of the radial magnetic field at x, z .. rubric:: Notes As there is not plasma this is equivalent to dBz_dx .. py:method:: dBz_dx(x: numpy.typing.ArrayLike, z: numpy.typing.ArrayLike) Total differential of the vertical magnetic field at point (x, z) from coils :param x: Radial coordinates for which to return Bz. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bz. If None, returns values at all grid points :returns: Differential of the vertical magnetic field at x, z .. rubric:: Notes As there is not plasma this is equivalent to dBx_dz .. py:method:: psi(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Returns the poloidal magnetic flux, either for the whole grid, or for specified x, z coordinates, including contributions from the coilset. :param x: Radial coordinates for which to return psi. If None, returns values at all grid points :param z: Vertical coordinates for which to return psi. If None, returns values at all grid points :returns: Poloidal magnetic flux at x, z .. py:method:: get_coil_Bp() -> numpy.typing.NDArray[numpy.float64] :returns: The poloidal field within each coil .. py:method:: plot(ax: matplotlib.axes.Axes | None = None, *, Bp: bool = False) Plots the breakdown object onto `ax` :returns: The plotting axis .. py:class:: QpsiCalcMode(*args, **kwds) Bases: :py:obj:`enum.Enum` .. autoapi-inheritance-diagram:: bluemira.equilibria.equilibrium.QpsiCalcMode :parts: 1 :private-bases: Modes for how to calculate qpsi :param 0: Don't Calculate qpsi :param 1: Calculate qpsi :param 2: Fill qpsi grid with Zeros .. py:attribute:: NO_CALC :value: 0 .. py:attribute:: CALC :value: 1 .. py:attribute:: ZEROS :value: 2 .. py:class:: Equilibrium(coilset: bluemira.equilibria.coils.CoilSet, grid: bluemira.equilibria.grid.Grid, profiles: bluemira.equilibria.profiles.Profile, *, force_symmetry: bool = False, vcontrol: str | None = None, limiter: bluemira.equilibria.limiter.Limiter | None = None, psi: numpy.typing.NDArray[numpy.float64] | None = None, jtor: numpy.typing.NDArray[numpy.float64] | None = None, filename: pathlib.Path | str | None = None, label: str = 'Equilibrium', o_point_fallback: bluemira.equilibria.profiles.OPointCalcOptions = OPointCalcOptions.GRID_CENTRE) Bases: :py:obj:`CoilSetMHDState` .. autoapi-inheritance-diagram:: bluemira.equilibria.equilibrium.Equilibrium :parts: 1 :private-bases: Represents the equilibrium state, including plasma and coil currents :param coilset: The set of coil objects which the equilibrium will be solved with :param grid: The grid on which to calculate the Equilibrium :param profiles: The plasma profiles to use in the Equilibrium :param force_symmetry: Controls whether symmetry of the plasma contribution to psi across z=0 is strictly enforced in the linear system formed during solve step. :param vcontrol: Type of virtual plasma control to enact :param limiter: Limiter conditions to apply to equilibrium :param psi: Magnetic flux [V.s] applied to X, Z grid :param jtor: The toroidal current density array of the plasma. Default = None will cause the jtor array to be constructed later as necessary. :param filename: The filename of the Equilibrium. Default = None (no file) :param label: The name used to identify this equilibrium .. py:attribute:: force_symmetry :type: bool :value: False .. py:attribute:: _jtor :value: None .. py:attribute:: profiles .. py:attribute:: _o_points :value: None .. py:attribute:: _x_points :value: None .. py:attribute:: _eqdsk :value: None .. py:attribute:: _li_flag :type: bool :value: False .. py:attribute:: plasma :value: None .. py:attribute:: controller :value: None .. py:attribute:: boundary :type: bluemira.equilibria.boundary.FreeBoundary .. py:attribute:: limiter :type: bluemira.equilibria.limiter.Limiter | None :value: None .. py:attribute:: filename :type: pathlib.Path | str | None :value: None .. py:attribute:: _label :type: str :value: 'Equilibrium' .. py:attribute:: _kwargs :type: dict[str, str | None] .. py:method:: from_eqdsk(filename: pathlib.Path | str, from_cocos: int | None = 11, *, qpsi_positive: bool | None = None, full_coil: bool = False, regrid_nx_nz: tuple[int, int] | None = None, force_symmetry: bool = False, user_coils: bluemira.equilibria.coils.CoilSet | None = None, o_point_fallback: bluemira.equilibria.profiles.OPointCalcOptions = OPointCalcOptions.GRID_CENTRE, **kwargs) :classmethod: Initialises an Equilibrium Object from an eqdsk file. Note that this will involve recalculation of the magnetic flux. Because of the nature of the (non-linear) Grad-Shafranov equation, values of psi may differ from those stored in eqdsk. NOTE: Need to solve again with some profiles in order to re-find... :param filename: Filename :param from_cocos: The COCOS index of the EQDSK file. Used when the determined COCOS is ambiguous. Will raise if given and not one of the determined COCOS indices. :param qpsi_positive: Whether qpsi is positive or not, required for identification when qpsi is not present in the file. :param full_coil: Whether the eqdsk dxc and dzc represents the full coil width or half coil width :param regrid_nx_nz: Modify grid to use new nx and nz values :param force_symmetry: Whether or not to force symmetrisation in the CoilSet :param user_coils: Coilset provided by the user. Set current, j_max and b_max to zero in user_coils. .. py:method:: to_dict(qpsi_calcmode: int | QpsiCalcMode = QpsiCalcMode.NO_CALC, to_cocos: int = BLUEMIRA_DEFAULT_COCOS) -> dict[str, Any] Creates dictionary for equilibrium object, in preparation for saving to a file format :param qpsi_calcmode: don't calculate: 0, calculate qpsi: 1, fill with zeros: 2 :returns: A dictionary of the Equilibrium object values, sufficient for EQDSK .. py:method:: to_eqdsk(filename: pathlib.Path | str, header: str = 'bluemira_equilibria', directory: str | None = None, filetype: str = 'json', qpsi_calcmode: int | QpsiCalcMode = QpsiCalcMode.NO_CALC, to_cocos: int = BLUEMIRA_DEFAULT_COCOS, **kwargs) Writes the Equilibrium Object to an eqdsk file .. py:method:: __getstate__() Get the state of the Equilibrium object. Used in pickling. .. py:method:: __setstate__(d) Get the state of the Equilibrium object. Used in unpickling. .. py:method:: set_grid(grid: bluemira.equilibria.grid.Grid) Sets a Grid object for an Equilibrium, and sets the G-S operator and G-S solver on the grid. :param grid: The grid upon which to solve the Equilibrium .. py:method:: _calculate_jtor(grid, psi_plasma) Compute jtor from plasma psi. :returns: Recalculated jtor. .. py:method:: reset_grid(grid: bluemira.equilibria.grid.Grid, psi: numpy.typing.NDArray[numpy.float64] | None = None, **kwargs) Reset the grid for the Equilibrium. :param grid: The grid to set the Equilibrium on :param psi: Psi array to use .. py:method:: _set_init_plasma(grid: bluemira.equilibria.grid.Grid, psi: numpy.typing.NDArray[numpy.float64] | None = None, j_tor: numpy.typing.NDArray[numpy.float64] | None = None) .. py:method:: set_vcontrol(vcontrol_str: str | None = None) Sets the vertical position controller :param vcontrol_str: Vertical control strategy .. py:method:: solve(jtor: numpy.ndarray | None = None, psi: numpy.ndarray | None = None) Re-calculates the plasma equilibrium given new profiles Linear Grad-Shafranov solve :param jtor: The toroidal current density on the finite difference grid [A/m^2] :param psi: The poloidal magnetic flux on the finite difference grid [V.s/rad] :raises EquilibriaError: No O-point found .. rubric:: Notes Modifies the following in-place: .plasma_psi .psi_func ._I_p ._Jtor .. py:method:: solve_li(jtor: numpy.typing.NDArray[numpy.float64] | None = None, psi: numpy.typing.NDArray[numpy.float64] | None = None) Optimises profiles to match input li Re-calculates the plasma equilibrium given new profiles Linear Grad-Shafranov solve :param jtor: The 2-D array toroidal current at each (x, z) point (optional) :param psi: The 2-D array of poloidal magnetic flux at each (x, z) point (optional) :raises EquilibriaError: No BetaLiIpProfile found :raises StopIteration: stop iterating .. rubric:: Notes Modifies the following in-place: .plasma_psi .psi_func ._I_p ._Jtor jtor argument input is not used but kept for consistency with `solve` .. py:method:: _update_plasma(plasma_psi: numpy.typing.NDArray[numpy.float64], j_tor: numpy.typing.NDArray[numpy.float64]) Update the plasma .. py:method:: _int_dxdz(func: numpy.typing.NDArray[numpy.float64]) -> float Returns the double-integral of a function over the space :math:`\int_Z\int_X f(x, z) dXdZ` :param func: a 2-D function map :returns: The integral value of the field in 2-D .. py:method:: effective_centre() -> tuple[float, float] Jeon calculation for the effective current centre of the plasma :math:`X_{cur}^{2}=\dfrac{1}{I_{p}}\int X^{2}J_{\phi,pl}(X, Z)d{\Omega}_{pl}` :math:`Z_{cur}=\dfrac{1}{I_{p}}\int ZJ_{\phi,pl}(X, Z)d{\Omega}_{pl}` :returns: * *xcur* -- The radial position of the effective current centre * *zcur* -- The vertical position of the effective current centre .. py:method:: Bx(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total radial magnetic field at point (x, z) from coils and plasma :param x: Radial coordinates for which to return Bx. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bx. If None, returns values at all grid points :returns: Radial magnetic field at x, z .. py:method:: Bz(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total vertical magnetic field at point (x, z) from coils and plasma :param x: Radial coordinates for which to return Bz. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bz. If None, returns values at all grid points :returns: Vertical magnetic field at x, z .. py:method:: Bp(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Total poloidal magnetic field at point (x, z) from coils and plasma :param x: Radial coordinates for which to return Bp. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bp. If None, returns values at all grid points :returns: Poloidal magnetic field at x, z .. py:method:: Bt(x: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] Toroidal magnetic field at point (x, z) from TF coils :param x: Radial coordinates for which to return Bt. :returns: Toroidal magnetic field at x .. py:method:: psi(x: numpy.typing.ArrayLike | None = None, z: numpy.typing.ArrayLike | None = None) -> float | numpy.typing.NDArray[numpy.float64] Returns the poloidal magnetic flux, either for the whole grid, or for specified x, z coordinates, including contributions from: plasma, coilset, and vertical stabilisation controller (default None) :param x: Radial coordinates for which to return psi. If None, returns values at all grid points :param z: Vertical coordinates for which to return psi. If None, returns values at all grid points :returns: Poloidal magnetic flux at x, z .. py:method:: psi_norm() -> numpy.typing.NDArray[numpy.float64] :returns: 2-D x-z normalised poloidal flux map .. py:method:: pressure_map(psi_n: float | None = None) -> numpy.typing.NDArray[numpy.float64] :param psi_n: The normalised psi value for masking. Values outside the closed psi_n flux surface will be masked. Default is psi_n of the LCFS. :returns: Plasma pressure map. .. py:method:: dBx_dz(x: numpy.typing.ArrayLike, z: numpy.typing.ArrayLike) Total differential of the radial magnetic field at point (x, z) from coils :param x: Radial coordinates for which to return Bz. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bz. If None, returns values at all grid points :returns: Differential of the radial magnetic field at x, z .. py:method:: dBz_dx(x: numpy.typing.ArrayLike, z: numpy.typing.ArrayLike) Total differential of the vertical magnetic field at point (x, z) from coils :param x: Radial coordinates for which to return Bz. If None, returns values at all grid points :param z: Vertical coordinates for which to return Bz. If None, returns values at all grid points :returns: Differential of the vertical magnetic field at x, z .. py:method:: _get_core_mask(psi_n: float | None = None) -> numpy.typing.NDArray[numpy.float64] :param psi_n: The normalised psi value for masking. Values outside the closed psi_n flux surface will be masked. Default is psi_n of the LCFS. :returns: A 2-D masking array for the plasma core. .. py:method:: q(psinorm: float | collections.abc.Iterable[float], o_points: collections.abc.Iterable | None = None, x_points: collections.abc.Iterable | None = None) -> float | numpy.typing.NDArray[numpy.float64] :returns: The safety factor at given psinorm. .. py:method:: fRBpol(psinorm: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] :returns: f = R*Bt at specified values of normalised psi. .. py:method:: fvac() -> numpy.typing.NDArray[numpy.float64] :returns: The vacuum f = R*Bt. .. py:method:: pprime(psinorm: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] :returns: p' at given normalised psi .. py:method:: ffprime(psinorm: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] :returns: ff' at given normalised psi .. py:method:: pressure(psinorm: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] :returns: Plasma pressure at specified values of normalised psi .. py:method:: get_flux_surface(psi_n: float, psi: numpy.typing.NDArray[numpy.float64] | None = None, o_points: collections.abc.Iterable | None = None, x_points: collections.abc.Iterable | None = None) -> bluemira.geometry.coordinates.Coordinates Get a flux surface Coordinates. NOTE: Continuous surface (bridges grid) :param psi_n: Normalised flux value of surface :param psi: Flux map :returns: Flux surface Coordinates .. py:method:: get_LCFS(psi: numpy.ndarray | None = None, psi_n_tol: float = 1e-06, delta_start=0.01) -> bluemira.geometry.coordinates.Coordinates Get the Last Closed FLux Surface (LCFS). :param psi: The psi field on which to compute the LCFS. Will re-calculate if set to None :param psi_n_tol: The normalised psi tolerance to use when finding the LCFS :returns: The Coordinates of the LCFS .. py:method:: get_separatrix(psi: numpy.typing.NDArray[numpy.float64] | None = None, psi_n_tol: float = 1e-06) -> bluemira.geometry.coordinates.Coordinates | list[bluemira.geometry.coordinates.Coordinates] Get the plasma separatrix(-ices). :param psi: The flux array. Will re-calculate if set to None :param psi_n_tol: The normalised psi tolerance to use when finding the separatrix :returns: The separatrix coordinates (Coordinates for SN, List[Coordinates]] for DN) .. py:method:: _clear_OX_points() Speed optimisation for storing OX point searches in a single iteration of the solve. Large grids can cause OX finding to be expensive.. .. py:method:: get_OX_points(psi: numpy.typing.NDArray[numpy.float64] | None = None, *, force_update: bool = False, o_point_fallback: bluemira.equilibria.profiles.OPointCalcOptions | None = None) -> tuple[list[bluemira.equilibria.find.Opoint], list[bluemira.equilibria.find.Xpoint | bluemira.equilibria.find.Lpoint]] :returns: * The O-points * The X-points .. py:method:: get_OX_psis(psi: numpy.typing.NDArray[numpy.float64] | None = None) -> tuple[float, float] The psi at the base :returns: * psi at O-point * psi at X-point .. py:method:: get_midplane(x: float, z: float, x_psi: float) -> tuple[float, float] Get the position at the midplane for a given psi value. :param x: Starting x coordinate about which to search for a psi surface :param z: Starting z coordinate about which to search for a psi surface :param x_psi: Flux value :returns: * *xMP* -- x coordinate of the midplane point with flux value Xpsi * *zMP* -- z coordinate of the midplane point with flux value Xpsi .. py:method:: analyse_core(n_points: int = 50, *, plot: bool = True, ax=None) -> tuple[bluemira.equilibria.flux_surfaces.CoreResults, matplotlib.axes.Axes] Analyse the shape and characteristics of the plasma core. :param n_points: Number of points in normalised psi space to analyse :returns: Result dataclass .. py:method:: analyse_plasma() -> bluemira.equilibria.physics.EqSummary Analyse the energetic and magnetic characteristics of the plasma. .. py:method:: analyse_coils(print_table=True) -> tuple[dict[str, Any], float, float] Analyse and summarise the electro-magneto-mechanical characteristics of the equilibrium and coilset. :returns: * *table* -- Tabulated currents fields and forces * *fz_c_stot* -- The sum of the forces on the CS * *fsep* -- CS separation force .. py:property:: is_double_null :type: bool Whether or not the Equilibrium is a double-null Equilibrium. :rtype: Whether or not the Equilibrium is a double-null Equilibrium. .. py:method:: plot(ax: matplotlib.axes.Axes | None = None, *, plasma: bool = False, show_ox: bool = True) Plot the equilibrium magnetic flux surfaces object onto `ax`. :returns: The plot axis .. py:method:: plot_field(ax: matplotlib.axes.Axes | None = None, *, show_ox: bool = True) Plot the equilibrium field structure onto `ax`. :returns: The plot axis .. py:method:: plot_core(ax=None) Plot a 1-D section through the magnetic axis. :returns: The plot axis