Custom equations

Note

This method is used to add equations to the governing system of equations, e.g., the system of equations describing the physics. For computing input variables such as control inputs in the Python code, see the example Tracking a Setpoint.

This example illustrates how to implement custom equations in Python. This could be used to implement equations that are not supported by Modelica.

Consider the following model:

\[\begin{split}\frac{dx}{dt} &= y, \\ y &= -\frac{2}{3600}x.\end{split}\]

The equation for x is given in the Modelica file, while the equation for y is implemented in the Python code.

The Modelica file is given below.

model SimpleModel
    Real y;  // Depends on x through a formula that is implemented in Python.
    output Real x;
equation
    der(x) = y;
end SimpleModel;

To add custom equations to the simulation problem, the method extra_equations is overwritten. This is illustrated in the optimiziation problem below.

class SimpleModel(CSVMixin, SimulationProblem):
    """
    Simple model class to illustrate implementing a custom equation.

    This class illustrates how to implement a custom equation in python
    instead of Modelica.

    The model of this class is given by

    .. math::
        \frac{dx}{dt} &= y, \\
        y &= -\frac{2}{3600}x.

    The equation for :math:`x` is given in Modelica,
    while the equation for :math:`y` is implemented in this class.
    """

    def extra_equations(self):
        variables = self.get_variables()

        y = variables["y"]
        x = variables["x"]

        # A scale to improve the performance of the solver.
        # It has the average order of magnitude of the term y and 2/3600 x.
        constraint_nominal = (
            2 / 3600 * self.get_variable_nominal("x") * self.get_variable_nominal("y")
        ) ** 0.5

        return [(y - (-2 / 3600 * x)) / constraint_nominal]

The method extra_equations returns a list of equations given in the form of residuals, i.e. expressions that should equal zero. For the equation \(y = -(2/3600) x\), for example, the residual is of the form \((y - (-(2/3600) x)) / \text{some_nominal}\).