bluemira.equilibria.optimisation.constraints ============================================ .. py:module:: bluemira.equilibria.optimisation.constraints .. autoapi-nested-parse:: Equilibrium optimisation constraint classes Classes ------- .. autoapisummary:: bluemira.equilibria.optimisation.constraints.UpdateableConstraint bluemira.equilibria.optimisation.constraints.FieldConstraints bluemira.equilibria.optimisation.constraints.CoilFieldConstraints bluemira.equilibria.optimisation.constraints.CoilForceConstraints bluemira.equilibria.optimisation.constraints.MagneticConstraint bluemira.equilibria.optimisation.constraints.AbsoluteMagneticConstraint bluemira.equilibria.optimisation.constraints.RelativeMagneticConstraint bluemira.equilibria.optimisation.constraints.FieldNullConstraint bluemira.equilibria.optimisation.constraints.VerticalFieldConstraint bluemira.equilibria.optimisation.constraints.PsiConstraint bluemira.equilibria.optimisation.constraints.IsofluxConstraint bluemira.equilibria.optimisation.constraints.PsiBoundaryConstraint bluemira.equilibria.optimisation.constraints.MagneticConstraintSet bluemira.equilibria.optimisation.constraints.AutoConstraints Functions --------- .. autoapisummary:: bluemira.equilibria.optimisation.constraints._get_dummy_equilibrium Module Contents --------------- .. py:function:: _get_dummy_equilibrium(equilibrium: bluemira.equilibria.equilibrium.Equilibrium) :returns: a dummy equilibrium for current optimisation where the background response is solely due to the plasma and passive coils. .. rubric:: Notes When we do dI (current gradient) optimisation, the background vector includes the contributions from the whole coilset (including active coils). When we do I (current vector) optimisation, the background vector only includes contributions from the passive coils (plasma). .. py:class:: UpdateableConstraint Bases: :py:obj:`abc.ABC` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.UpdateableConstraint :parts: 1 :private-bases: Abstract base mixin class for an equilibrium optimisation constraint that is updateable. .. py:method:: __init_subclass__(**kwargs) :classmethod: Create constraint name on definition of subclass .. py:property:: name :type: str The name of the constraint .. py:method:: prepare(equilibrium: bluemira.equilibria.equilibrium.Equilibrium, *, I_not_dI=False, fixed_coils=False) :abstractmethod: Prepare the constraint for use in an equilibrium optimisation problem. .. py:method:: control_response(coilset: bluemira.equilibria.coils.CoilSet) :abstractmethod: Calculate control response of a CoilSet to the constraint. .. py:method:: evaluate(equilibrium: bluemira.equilibria.equilibrium.Equilibrium) :abstractmethod: Calculate the value of the constraint in an Equilibrium. .. py:method:: f_constraint() -> bluemira.equilibria.optimisation.constraint_funcs.ConstraintFunction :abstractmethod: The numerical non-linear part of the constraint. .. py:class:: FieldConstraints(x: float | numpy.ndarray, z: float | numpy.ndarray, B_max: float | numpy.ndarray, tolerance: float | numpy.ndarray | None = None, constraint_type: str = 'inequality') Bases: :py:obj:`UpdateableConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.FieldConstraints :parts: 1 :private-bases: Inequality constraints for the poloidal field at certain locations. :param x: Radial coordinate(s) at which to constrain the poloidal field :param z: Vertical coordinate(s) at which to constrain the poloidal field :param B_max: Maximum poloidal field value(s) at location(s) :param tolerance: Tolerance with which the constraint(s) will be met :param constraint_type: Type of constraint .. py:attribute:: x .. py:attribute:: z .. py:attribute:: _args .. py:attribute:: tolerance :value: None .. py:attribute:: f_constraint_type :value: 'inequality' .. py:method:: prepare(equilibrium: bluemira.equilibria.equilibrium.Equilibrium, *, I_not_dI: bool = False, fixed_coils: bool = False) Prepare the constraint for use in an equilibrium optimisation problem. .. py:method:: control_response(coilset: bluemira.equilibria.coils.CoilSet) -> tuple[numpy.ndarray, numpy.ndarray] Calculate control response of a CoilSet to the constraint. :returns: * Bx response * Bz response .. py:method:: evaluate(equilibrium: bluemira.equilibria.equilibrium.Equilibrium) -> tuple[numpy.ndarray, numpy.ndarray] Calculate the value of the constraint in an Equilibrium. :returns: * Bx of equilibrium * Bz of equilibrium .. py:method:: f_constraint() -> bluemira.equilibria.optimisation.constraint_funcs.FieldConstraintFunction Calculate the constraint function .. py:method:: __len__() -> int Length of field constraints. .. py:class:: CoilFieldConstraints(coilset: bluemira.equilibria.coils.CoilSet, B_max: float | numpy.ndarray, tolerance: float | numpy.ndarray | None = None) Bases: :py:obj:`FieldConstraints` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.CoilFieldConstraints :parts: 1 :private-bases: Inequality constraints on the poloidal field at the middle of the inside edge of the coils, where the field is usually highest. :param coilset: Coilset for which to constrain the fields in the coils :param B_max: Maximum field allowed in the coils :param tolerance: Tolerance with which the inequality constraints will be met .. rubric:: Notes This is a fast approximation constraint, and does not solve for the peak field at all points in the coils. Use with caution. TODO: Presently only handles CoilSets with Coils (SymmetricCircuits not yet supported) TODO: Presently only accounts for poloidal field contributions from PF coils and plasma (TF from TF coils not accounted for if PF coils are inside the TF coils.) .. py:method:: _get_constraint_points(coilset) :staticmethod: .. py:method:: prepare(equilibrium: bluemira.equilibria.equilibrium.Equilibrium, *, I_not_dI: bool = False, fixed_coils: bool = False) Prepare the constraint for use in an equilibrium optimisation problem. .. py:class:: CoilForceConstraints(coilset: bluemira.equilibria.coils.CoilSet, PF_Fz_max: float, CS_Fz_sum_max: float, CS_Fz_sep_max: float, tolerance: float | numpy.ndarray | None = None) Bases: :py:obj:`UpdateableConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.CoilForceConstraints :parts: 1 :private-bases: Inequality constraints on the vertical forces in the PF and CS coils. :param coilset: Coilset for which to constrain the fields in the coils :param PF_Fz_max: Maximum absolute vertical force in a PF coil [MN] :param CS_Fz_sum_max: Maximum absolute vertical force sum in the CS stack [MN] :param CS_Fz_sep_max: Maximum separation vertical force between two CS modules [MN] :param tolerance: Tolerance with which the inequality constraints will be met .. rubric:: Notes TODO: Presently only handles CoilSets with Coils (SymmetricCircuits not yet supported) .. py:attribute:: _args .. py:attribute:: tolerance :value: None .. py:method:: prepare(equilibrium: bluemira.equilibria.equilibrium.Equilibrium, *, I_not_dI: bool = False, fixed_coils: bool = False) Prepare the constraint for use in an equilibrium optimisation problem. .. py:method:: control_response(coilset: bluemira.equilibria.coils.CoilSet) -> numpy.ndarray :staticmethod: Calculate control response of a CoilSet to the constraint. .. py:method:: evaluate(equilibrium: bluemira.equilibria.equilibrium.Equilibrium) -> numpy.ndarray :staticmethod: Calculate the value of the constraint in an Equilibrium. :returns: The force evaluation .. py:method:: f_constraint() -> bluemira.equilibria.optimisation.constraint_funcs.CoilForceConstraint Calculate the constraint function .. py:class:: MagneticConstraint(target_value: float = 0.0, weights: float | numpy.ndarray = 1.0, tolerance: float | numpy.ndarray | None = None, f_constraint: type[bluemira.equilibria.optimisation.constraint_funcs.ConstraintFunction] = L2NormConstraint, constraint_type: str = 'inequality') Bases: :py:obj:`UpdateableConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.MagneticConstraint :parts: 1 :private-bases: Abstract base class for a magnetic optimisation constraint. Can be used as a standalone constraint for use in an optimisation problem. In which case the constraint is of the form: ||(Ax - b)||² < target_value Can be used in a MagneticConstraintSet .. py:attribute:: target_value .. py:attribute:: weights :value: 1.0 .. py:attribute:: _f_constraint .. py:attribute:: _args .. py:attribute:: tolerance :value: None .. py:attribute:: constraint_type :value: 'inequality' .. py:method:: prepare(equilibrium: bluemira.equilibria.equilibrium.Equilibrium, *, I_not_dI: bool = False, fixed_coils: bool = False) Prepare the constraint for use in an equilibrium optimisation problem. .. py:method:: update_target(equilibrium: bluemira.equilibria.equilibrium.Equilibrium) Update the target value of the magnetic constraint. .. py:method:: plot(ax) :abstractmethod: Plot the constraint onto an Axes. .. py:method:: __len__() -> int The mathematical size of the constraint. .. rubric:: Notes Length of the array if an array is specified, otherwise 1 for a float. .. py:method:: f_constraint() -> bluemira.equilibria.optimisation.constraint_funcs.ConstraintFunction :returns: The non-linear, numerical, part of the constraint. .. py:class:: AbsoluteMagneticConstraint(x: float | numpy.ndarray, z: float | numpy.ndarray, target_value: float, weights: float | numpy.ndarray = 1.0, tolerance: float | numpy.ndarray | None = None, f_constraint: type[bluemira.equilibria.optimisation.constraint_funcs.ConstraintFunction] = AxBConstraint, constraint_type: str = 'equality') Bases: :py:obj:`MagneticConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.AbsoluteMagneticConstraint :parts: 1 :private-bases: Abstract base class for absolute magnetic constraints, where the target value is prescribed in absolute terms. .. py:attribute:: x .. py:attribute:: z .. py:class:: RelativeMagneticConstraint(x: float | numpy.ndarray, z: float | numpy.ndarray, ref_x: float, ref_z: float, constraint_value: float = 0.0, weights: float | numpy.ndarray = 1.0, tolerance: float | numpy.ndarray | None = None, f_constraint: type[bluemira.equilibria.optimisation.constraint_funcs.ConstraintFunction] = L2NormConstraint, constraint_type: str = 'inequality') Bases: :py:obj:`MagneticConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.RelativeMagneticConstraint :parts: 1 :private-bases: Abstract base class for relative magnetic constraints, where the target value is prescribed with respect to a reference point. .. py:attribute:: x .. py:attribute:: z .. py:attribute:: ref_x .. py:attribute:: ref_z .. py:method:: update_target(equilibrium: bluemira.equilibria.equilibrium.Equilibrium) :abstractmethod: Update the target value of the magnetic constraint. .. py:class:: FieldNullConstraint(x: float | numpy.ndarray, z: float | numpy.ndarray, weights: float | numpy.ndarray = 1.0, tolerance: float | None = None) Bases: :py:obj:`AbsoluteMagneticConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.FieldNullConstraint :parts: 1 :private-bases: Magnetic field null constraint. In practice sets the Bx and Bz field components to be 0 at the specified location. .. py:method:: control_response(coilset: bluemira.equilibria.coils.CoilSet) -> numpy.ndarray Calculate control response of a CoilSet to the constraint. :returns: Bx and Bz response of the coilset .. py:method:: evaluate(eq: bluemira.equilibria.equilibrium.Equilibrium) -> numpy.ndarray Calculate the value of the constraint in an Equilibrium. :returns: Bx and Bz response of the equilibrium .. py:method:: plot(ax) Plot the constraint onto an Axes. .. py:method:: __len__() -> int The mathematical size of the constraint. .. py:class:: VerticalFieldConstraint(x: float | numpy.ndarray, z: float | numpy.ndarray, target_value: float, weights: float | numpy.ndarray = 1.0, tolerance: float | numpy.ndarray = 1e-06) Bases: :py:obj:`AbsoluteMagneticConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.VerticalFieldConstraint :parts: 1 :private-bases: Absolute vertical field (Bz) constraint. .. py:method:: control_response(coilset: bluemira.equilibria.coils.CoilSet) -> numpy.ndarray Calculate control response of a CoilSet to the constraint. :returns: Bz response of the coilset .. py:method:: evaluate(eq: bluemira.equilibria.equilibrium.Equilibrium) -> numpy.ndarray Calculate the value of the constraint in an Equilibrium. :returns: Bz value of the equilibrium .. py:method:: plot(ax) Plot the constraint onto an Axes. .. py:class:: PsiConstraint(x: float | numpy.ndarray, z: float | numpy.ndarray, target_value: float, weights: float | numpy.ndarray = 1.0, tolerance: float | numpy.ndarray | None = None) Bases: :py:obj:`AbsoluteMagneticConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.PsiConstraint :parts: 1 :private-bases: Absolute psi value constraint. .. py:method:: control_response(coilset: bluemira.equilibria.coils.CoilSet) -> numpy.ndarray Calculate control response of a CoilSet to the constraint. :returns: The coilset psi response .. py:method:: evaluate(eq: bluemira.equilibria.equilibrium.Equilibrium) -> numpy.ndarray Calculate the value of the constraint in an Equilibrium. :returns: The equilibrium psi .. py:method:: plot(ax) Plot the constraint onto an Axes. .. py:class:: IsofluxConstraint(x: float | numpy.ndarray, z: float | numpy.ndarray, ref_x: float, ref_z: float, constraint_value: float = 0.0, weights: float | numpy.ndarray = 1.0, tolerance: float | None = None) Bases: :py:obj:`RelativeMagneticConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.IsofluxConstraint :parts: 1 :private-bases: Isoflux constraint for a set of points relative to a reference point. .. py:method:: control_response(coilset: bluemira.equilibria.coils.CoilSet) -> numpy.ndarray Calculate control response of a CoilSet to the constraint. :returns: The difference in coilset psi response with the reference .. py:method:: evaluate(eq: bluemira.equilibria.equilibrium.Equilibrium) -> numpy.ndarray Calculate the value of the constraint in an Equilibrium. :returns: The equilibrium psi .. py:method:: update_target(eq: bluemira.equilibria.equilibrium.Equilibrium) We need to update the target value, as it is a relative constraint. .. py:method:: plot(ax) Plot the constraint onto an Axes. .. py:class:: PsiBoundaryConstraint(x: float | numpy.ndarray, z: float | numpy.ndarray, target_value: float, weights: float | numpy.ndarray = 1.0, tolerance: float | numpy.ndarray | None = None) Bases: :py:obj:`AbsoluteMagneticConstraint` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.PsiBoundaryConstraint :parts: 1 :private-bases: Absolute psi value constraint on the plasma boundary. Gets updated when the plasma boundary flux value is changed. .. py:method:: control_response(coilset: bluemira.equilibria.coils.CoilSet) -> numpy.ndarray Calculate control response of a CoilSet to the constraint. :returns: The coilset psi response .. py:method:: evaluate(eq: bluemira.equilibria.equilibrium.Equilibrium) -> numpy.ndarray Calculate the value of the constraint in an Equilibrium. :returns: The equilibrium psi .. py:method:: plot(ax) Plot the constraint onto an Axes. .. py:class:: MagneticConstraintSet(constraints: list[MagneticConstraint]) A set of magnetic constraints to be applied to an equilibrium. The optimisation problem is of the form: [A][x] = [b] where: [b] = [target] - [background] The target vector is the vector of desired values. The background vector is the vector of values due to uncontrolled current terms (plasma and passive coils). Use of class: - Inherit from this class - Add a __init__(args) method - Populate constraints with super().__init__(List[MagneticConstraint]) .. py:attribute:: __slots__ :value: ('A', 'background', 'coilset', 'constraints', 'eq', 'target', 'w') .. py:attribute:: constraints .. py:attribute:: eq :value: None .. py:attribute:: A :value: None .. py:attribute:: target :value: None .. py:attribute:: background :value: None .. py:method:: __call__(equilibrium: bluemira.equilibria.equilibrium.Equilibrium, *, I_not_dI: bool = False, fixed_coils: bool = False) Update the MagneticConstraintSet .. py:method:: __len__() -> int The mathematical size of the constraint set. .. py:method:: get_weighted_arrays() -> tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray] Get [A] and [b] scaled by weight matrix. Weight matrix assumed to be diagonal. :returns: * *weights* -- the weight matrix * *weighted_a* -- A scaled by the weight matrix * *weighted_b* -- b scaled by the weight matrix .. py:method:: build_weight_matrix() Build the weight matrix used in optimisation. Assumed to be diagonal. .. py:method:: build_control_matrix() Build the control response matrix used in optimisation. .. py:method:: build_target() Build the target value vector. .. py:method:: build_background() Build the background value vector. .. py:property:: b :type: numpy.ndarray The b vector of target - background values. .. py:method:: update_psi_boundary(psi_bndry: float) Update the target value for all PsiBoundaryConstraints. :param psi_bndry: The target psi boundary value [V.s/rad] .. py:method:: plot(ax=None) Plots constraints :returns: The plot axis .. py:class:: AutoConstraints(x: numpy.ndarray, z: numpy.ndarray, psi_boundary: float | None = None, n_points: int = 40) Bases: :py:obj:`MagneticConstraintSet` .. autoapi-inheritance-diagram:: bluemira.equilibria.optimisation.constraints.AutoConstraints :parts: 1 :private-bases: Utility class for crude reconstruction of magnetic constraints from a specified LCFS set of coordinates. :param x: The x coordinates of the LCFS :param z: The z coordinates of the LCFS :param psi_boundary: The psi boundary value to use as a constraint. If None, an isoflux constraint is used. :param n_points: The number of interpolated points to use