bluemira.equilibria.profiles ============================ .. py:module:: bluemira.equilibria.profiles .. autoapi-nested-parse:: Plasma profile objects, shape functions, and associated tools Classes ------- .. autoapisummary:: bluemira.equilibria.profiles.SinglePowerFunc bluemira.equilibria.profiles.DoublePowerFunc bluemira.equilibria.profiles.LaoPolynomialFunc bluemira.equilibria.profiles.LuxonExpFunc bluemira.equilibria.profiles.BetaIpProfile bluemira.equilibria.profiles.CustomProfile Module Contents --------------- .. py:class:: SinglePowerFunc(args) Bases: :py:obj:`ShapeFunction` .. autoapi-inheritance-diagram:: bluemira.equilibria.profiles.SinglePowerFunc :parts: 1 :private-bases: Function object for a single power profile .. py:attribute:: _order :value: 1 .. py:attribute:: _fact :value: 1 .. py:attribute:: coeffs .. py:method:: _dfunc(x: float, *args) -> float :staticmethod: .. py:class:: DoublePowerFunc(args) Bases: :py:obj:`ShapeFunction` .. autoapi-inheritance-diagram:: bluemira.equilibria.profiles.DoublePowerFunc :parts: 1 :private-bases: Function object for a double power profile .. py:attribute:: _order :value: 2 .. py:attribute:: _fact :value: 1 .. py:attribute:: coeffs .. py:method:: _dfunc(x: float, *args) -> float :staticmethod: .. py:class:: LaoPolynomialFunc(coeffs: numpy.typing.ArrayLike) Bases: :py:obj:`ShapeFunction` .. autoapi-inheritance-diagram:: bluemira.equilibria.profiles.LaoPolynomialFunc :parts: 1 :private-bases: Function object for a Lao polynomial profile .. py:attribute:: _fact :value: 1 .. py:attribute:: _order :value: 3 .. py:attribute:: n .. py:attribute:: coeffs .. py:method:: _dfunc(x: float, *args) -> float :staticmethod: .. py:class:: LuxonExpFunc(coeffs: numpy.typing.ArrayLike) Bases: :py:obj:`ShapeFunction` .. autoapi-inheritance-diagram:: bluemira.equilibria.profiles.LuxonExpFunc :parts: 1 :private-bases: Function object for a Luxon exponential profile .. py:attribute:: _fact :value: 1 .. py:attribute:: _order :value: 1 .. py:method:: _dfunc(x: float, *args) -> float :staticmethod: .. py:class:: BetaIpProfile(betap: float, I_p: float, R_0: float, B_0: float, shape: ShapeFunction | None = None) Bases: :py:obj:`Profile` .. autoapi-inheritance-diagram:: bluemira.equilibria.profiles.BetaIpProfile :parts: 1 :private-bases: Constrain poloidal Beta and plasma current following logic as laid out in :doi:`Jeon, 2015 <10.3938/jkps.67.843>` and following some implementation in B. Dudson, FreeGS: https://github.com/bendudson/freegs :param betap: Plasma poloidal beta constraint :param I_p: Plasma current constraint [A] :param R_0: Reactor major radius [m] (used in p' and ff' components) :param B_0: Toroidal field at reactor major radius [T] :param shape: Shape parameterisation to use .. rubric:: Notes :math:`J_{\phi} = {\lambda}\bigg({\beta}_{0}\dfrac{X}{R_{0}}+` :math:`(1-\beta_{0})\dfrac{R_{0}}{X}\bigg)j_{\phi_{shape}}(m, n, ..)` :math:`I_{p}=\int_{{\Omega}_{pl}} J_{{\phi},pl}({\lambda},{\beta_{0}})` :math:`d{\Omega}` :math:`{\beta}_{p}=\dfrac{\langle p({\beta_{0}})\rangle}{\langle B_{p}^{2}\rangle_{\psi_{a}}/2\mu_{0}}` Please be careful, the beta_p approximation used here is less good for higher elongation plasmas, see _calc_beta_p_approx. .. py:attribute:: betap .. py:attribute:: I_p .. py:attribute:: _fvac .. py:attribute:: R_0 .. py:attribute:: _B_0 .. py:attribute:: scale :value: 1.0 .. py:method:: jtor(x: numpy.typing.NDArray[numpy.float64], z: numpy.typing.NDArray[numpy.float64], psi: numpy.typing.NDArray[numpy.float64], o_points: list[bluemira.equilibria.find.Opoint], x_points: list[bluemira.equilibria.find.Xpoint], *, o_point_fallback: bluemira.equilibria.find.OPointCalcOptions = OPointCalcOptions.RAISE) -> numpy.typing.NDArray[numpy.float64] Calculate toroidal plasma current array. :math:`I_{p} =\int\int {\lambda}\bigg({\beta}_{0}\dfrac{X}{R_{0}}j_{\phi_{shape}}+` :math:`(1-\beta_{0})\dfrac{R_{0}}{X}j_{\phi_{shape}}\bigg)` :math:`{\beta}_{p}=\dfrac{8\pi}{{\mu}_{0}{I_{p}^{2}}}\int\int pdXdZ` :math:`= -\dfrac{8\pi}{{\mu}_{0}{I_{p}^{2}}}\dfrac{\lambda{\beta}_{0}}{R_{0}}\int\int p_{shape}dXdZ` :math:`p(\psi_{N})=-\dfrac{\lambda\beta_{0}}{R_{0}}p_{shape}(\psi_{N})` :math:`\lambda{\beta_{0}}=-\dfrac{\beta_{p}I_{p}^{2}R_{0}\mu_{0}}{8\pi \int\int p_{shape}}` :math:`\lambda=\dfrac{I_{p}-\lambda{\beta_{0}}\bigg(\int\int\dfrac{X}{R_{0}}f+\int\int\dfrac{R_{0}}{X}f\bigg)}{\int\int\dfrac{R_{0}}{X}f}` Derivation: book 10, p 120 .. note:: Please be careful, the beta_p approximation used here is not good for high elongation plasmas, see _calc_beta_p_approx. .. py:method:: pprime(pn: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] dp/dpsi as a function of normalised psi .. py:method:: ffprime(pn: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] f*df/dpsi as a function of normalised psi .. py:class:: CustomProfile(pprime_func: numpy.typing.NDArray[numpy.float64] | collections.abc.Callable[[float]] | float, ffprime_func: numpy.typing.NDArray[numpy.float64] | collections.abc.Callable[[float]] | float, R_0: float, B_0: float, p_func: numpy.typing.NDArray[numpy.float64] | collections.abc.Callable[[float]] | float | None = None, f_func: numpy.typing.NDArray[numpy.float64] | collections.abc.Callable[[float]] | float | None = None, I_p: float | None = None) Bases: :py:obj:`Profile` .. autoapi-inheritance-diagram:: bluemira.equilibria.profiles.CustomProfile :parts: 1 :private-bases: User-specified profile functions p'(psi), ff'(psi) jtor = R*p' + ff'/(R*MU_0) :param pprime_func: Pressure prime profile - dp/dpsi(psi_N) :param ffprime_func: Force-Force prime profile f*df/dpsi(psi_N) :param R_0: Reactor major radius [m] :param B_0: Field at major radius [T] :param I_p: Plasma current [A]. If None, the plasma current will be calculated from p' and ff'. .. py:attribute:: _pprime_in .. py:attribute:: _ffprime_in .. py:attribute:: p_func :value: None .. py:attribute:: f_func :value: None .. py:attribute:: _fvac .. py:attribute:: R_0 .. py:attribute:: _B_0 .. py:attribute:: I_p :value: None .. py:attribute:: scale :value: 1.0 .. py:attribute:: shape .. py:method:: parse_to_callable(unknown) :staticmethod: Make a callable out of an unknown input type :raises TypeError: Cannot make opject callable .. py:method:: pprime(pn: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] dp/dpsi as a function of normalised psi .. py:method:: ffprime(pn: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] f*df/dpsi as a function of normalised psi .. py:method:: jtor(x: numpy.typing.NDArray[numpy.float64], z: numpy.typing.NDArray[numpy.float64], psi: numpy.typing.NDArray[numpy.float64], o_points: list[bluemira.equilibria.find.Opoint], x_points: list[bluemira.equilibria.find.Xpoint], lcfs: numpy.typing.NDArray[numpy.float64] | None = None, *, o_point_fallback: bluemira.equilibria.find.OPointCalcOptions = OPointCalcOptions.RAISE) -> numpy.typing.NDArray[numpy.float64] Calculate toroidal plasma current :math:`J_{\phi}=Xp^{'}+\dfrac{FF^{'}}{\mu_{0}X}` .. py:method:: pressure(psinorm: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] :returns: Pressure [Pa] at given value(s) of normalised psi .. py:method:: fRBpol(psinorm: numpy.typing.ArrayLike) -> float | numpy.typing.NDArray[numpy.float64] :returns: f=R*Bt at given value(s) of normalised psi .. py:method:: from_eqdsk_file(filename: pathlib.Path | str, from_cocos: int | None = 11, to_cocos: int | None = BLUEMIRA_DEFAULT_COCOS, *, qpsi_positive: bool | None = None, **kwargs) -> CustomProfile :classmethod: Initialises a CustomProfile object from an eqdsk file .. py:method:: from_eqdsk(eq: eqdsk.EQDSKInterface) -> CustomProfile :classmethod: Initialises a CustomProfile object from an eqdsk object