Esempio n. 1
0
    def set_integrators(self):
        """
        Generate continuous time high-precision integrators.
        """

        # Set CasADi variables
        x = ca.MX.sym('x', 4)
        u = ca.MX.sym('u', 1)

        # Integration method - integrator options an be adjusted
        options = {
            "abstol": 1e-5,
            "reltol": 1e-9,
            "max_num_steps": 100,
            "tf": self.dt
        }

        # Create linear dynamics integrator
        dae = {'x': x, 'ode': self.model(x, u), 'p': ca.vertcat(u)}
        self.Integrator_lin = ca.integrator('integrator_lin', 'cvodes', dae,
                                            options)

        # Create nonlinear dynamics integrator
        dae_nl = {'x': x, 'ode': self.model_nl(x, u), 'p': ca.vertcat(u)}
        self.Integrator = ca.integrator('integrator', 'cvodes', dae_nl,
                                        options)
Esempio n. 2
0
    def __prepare_dynamics(self, nlp):
        """
        Builds CasaDI dynamics function.
        :param dynamics_func: A selected method handler of the class dynamics.Dynamics.
        :param ode_solver: Name of chosen ode, available in OdeSolver enum class.
        """

        dynamics = nlp["dynamics_func"]
        ode_opt = {"t0": 0, "tf": nlp["dt"]}
        if nlp["ode_solver"] == OdeSolver.RK or nlp[
                "ode_solver"] == OdeSolver.COLLOCATION:
            ode_opt["number_of_finite_elements"] = 5

        ode = {
            "x": nlp["x"],
            "p": nlp["u"],
            "ode": dynamics(nlp["x"], nlp["u"])
        }
        nlp["dynamics"] = []
        nlp["par_dynamics"] = {}
        if nlp["ode_solver"] == OdeSolver.RK:
            ode_opt["idx"] = 0
            ode["ode"] = dynamics
            if "external_forces" in nlp:
                for idx in range(len(nlp["external_forces"])):
                    ode_opt["idx"] = idx
                    nlp["dynamics"].append(RK4(ode, ode_opt))
            else:
                nlp["dynamics"].append(RK4(ode, ode_opt))
        elif nlp["ode_solver"] == OdeSolver.COLLOCATION:
            if isinstance(nlp["tf"], casadi.MX):
                raise RuntimeError(
                    "OdeSolver.COLLOCATION cannot be used while optimizing the time parameter"
                )
            if "external_forces" in nlp:
                raise RuntimeError(
                    "COLLOCATION cannot be used with external_forces")
            nlp["dynamics"].append(
                casadi.integrator("integrator", "collocation", ode, ode_opt))
        elif nlp["ode_solver"] == OdeSolver.CVODES:
            if isinstance(nlp["tf"], casadi.MX):
                raise RuntimeError(
                    "OdeSolver.CVODES cannot be used while optimizing the time parameter"
                )
            if "external_forces" in nlp:
                raise RuntimeError(
                    "CVODES cannot be used with external_forces")
            nlp["dynamics"].append(
                casadi.integrator("integrator", "cvodes", ode, ode_opt))

        if len(nlp["dynamics"]) == 1:
            if self.nb_threads > 1:
                nlp["par_dynamics"] = nlp["dynamics"][0].map(
                    nlp["ns"], "thread", self.nb_threads)
            nlp["dynamics"] = nlp["dynamics"] * nlp["ns"]
Esempio n. 3
0
def simulate(x0: State, f_control, p: Parameters, t0: float, tf: float,
             dt: float):
    """
    Simulate the aircraft for a given control function and initial state.

    Parameters:
    x0: initial state (see State)
    f_control: A function of the form f(t, x), which returns the control u
    p: Aircraft parameters
    t0: initial time
    tf: fintal time
    dt: The discrete sampling time of the controller.
    """
    xs = ca.MX.sym('x', 16)
    x = State.from_casadi(xs)
    us = ca.MX.sym('u', 4)
    u = Control.from_casadi(us)
    dae = {'x': xs, 'p': us, 'ode': dynamics(x, u, p).to_casadi()}
    F = ca.integrator('F', 'idas', dae, {'t0': 0, 'tf': dt, 'jit': True})
    x = np.array(x0.to_casadi()).reshape(-1)
    u0 = f_control(t0, x0)
    u = np.array(u0.to_casadi()).reshape(-1)
    data = {'t': [0], 'x': [x]}
    t_vect = np.arange(t0, tf, dt)
    for t in t_vect:
        u0 = f_control(t, x)
        u = np.array(u0.to_casadi()).reshape(-1)
        x = np.array(F(x0=x, p=u)['xf']).reshape(-1)
        data['t'].append(t)
        data['x'].append(x)
    for k in data.keys():
        data[k] = np.array(data[k])
    return data
Esempio n. 4
0
def calc_xs_full_ode(Ex, Ey, e_hat, y_hat, state_compressor):

    t = cs.SX.sym('t', 1)
    x_sym = cs.SX.sym('x', sc.nm)
    y_sym = cs.SX.sym('y', ny)
    e_sym = cs.SX.sym('e', sc.nr)
    Ex_sym = cs.SX.sym('Ex', sc.nr, sc.nm)
    Ey_sym = cs.SX.sym('Ex', sc.nr, Ey.shape[1])

    v = e_sym * v_star * (1 + Ex_sym @ cs.log(x_sym / sc.x_star) +
                          Ey @ np.log(y_hat))
    v_fun = cs.Function('v', [x_sym, e_sym, Ex_sym], [v])

    ode = cs.mtimes(cs.DM(N), v_fun(x_sym, e_sym, Ex_sym))

    integrator = cs.integrator(
        'full', 'cvodes', {
            't': t,
            'x': x_sym,
            'p': cs.vertcat(e_sym, Ex_sym.reshape((-1, 1))),
            'ode': ode,
        }, {
            'tf': 2000,
            'regularity_check': True,
        })

    p = np.hstack([e_hat, Ex.reshape((-1, 1), order='F').squeeze()])
    xs = np.array(integrator(x0=sc.x_star, p=p)['xf']).flatten()

    return xs
Esempio n. 5
0
def test_parallelization():
    N = 300
    x = cd.MX.sym('x'); z = cd.MX.sym('z'); p = cd.MX.sym('p')
    dae = {'x': x, 'z': z, 'p': p, 'ode': 0, 'alg': z}
    func = cd.integrator('func', 'idas', dae)
    F = func.map(N, 'openmp')
    F(x0=0, z0=0, p=0)
Esempio n. 6
0
    def solve_ode(self, ts=None):
        """ Solve the ODE using casadi's CVODES wrapper to ensure that the
        collocated dynamics match the error-controlled dynamics of the ODE

        """
        if ts is None:
            ts = self.ts
            check_err = True
        else:
            check_err = False

        ts.sort()  # Assert ts is increasing

        integrator = cs.integrator('int', 'cvodes', self._model_dict, {
            'grid': ts,
            'output_t0': True,
        })

        x_sim = np.array(integrator(x0=self.sol[0], p=self.var.p_op)['xf']).T

        if check_err:

            err = ((self.sol - x_sim).mean(0) / (self.sol.mean(0))).mean()

            if err > 1E-3:
                warn('Collocation does not match ODE Solution: '
                     '{:.2%} Error'.format(err))

        return x_sim
Esempio n. 7
0
    def _simulate_with_casadi_no_inputs(self, initcon, tsim, integrator,
                                        integrator_options):
        # Old way (10 times faster, but can't incorporate time
        # varying parameters/controls)
        xalltemp = [self._templatemap[i] for i in self._diffvars]
        xall = casadi.vertcat(*xalltemp)

        odealltemp = [convert_pyomo2casadi(self._rhsdict[i])
                      for i in self._derivlist]
        odeall = casadi.vertcat(*odealltemp)
        dae = {'x': xall, 'ode': odeall}

        if len(self._algvars) != 0:
            zalltemp = [self._templatemap[i] for i in self._simalgvars]
            zall = casadi.vertcat(*zalltemp)

            algalltemp = [convert_pyomo2casadi(i) for i in self._alglist]
            algall = casadi.vertcat(*algalltemp)
            dae['z'] = zall
            dae['alg'] = algall

        integrator_options['grid'] = tsim
        integrator_options['output_t0'] = True
        F = casadi.integrator('F', integrator, dae, integrator_options)
        sol = F(x0=initcon)
        profile = sol['xf'].full().T

        if len(self._algvars) != 0:
            algprofile = sol['zf'].full().T
            profile = np.concatenate((profile, algprofile), axis=1)

        return [tsim, profile]
Esempio n. 8
0
def dynamics(x, u, data):
    """ System dynamics function (discrete time)
    """

    # state derivative expression
    xdot = ca.vertcat(
        u['Vdot'] * (data['cA0'] - x['cA']) -
        arrhenius(x, u, data, 1) * x['cA'] -
        arrhenius(x, u, data, 3) * x['cA'] * x['cA'],
        -u['Vdot'] * x['cB'] + arrhenius(x, u, data, 1) * x['cA'] -
        arrhenius(x, u, data, 2) * x['cB'], u['Vdot'] *
        (data['theta0'] - x['theta']) - 1.0 / (data['rho'] * data['Cp']) *
        (arrhenius(x, u, data, 1) * x['cA'] * data['DH_AB'] +
         arrhenius(x, u, data, 2) * x['cB'] * data['DH_BC'] +
         arrhenius(x, u, data, 3) * x['cA'] * x['cA'] * data['DH_AD']) +
        data['kw'] * data['AR'] / (data['rho'] * data['Cp'] * data['VR']) *
        (x['thetaK'] - x['theta']), 1.0 / (data['mK'] * data['CPK']) *
        (u['QdotK'] + data['kw'] * data['AR'] * (x['theta'] - x['thetaK'])))

    # create ode for integrator
    ode = {'x': x, 'p': u, 'ode': xdot / 3600}

    return ca.integrator('F', data['integrator'], ode, {
        'tf': data['ts'],
        'number_of_finite_elements': data['num_steps']
    })
Esempio n. 9
0
    def _create_integrator(self, options=None, integrator_type='implicit'):
        """
            Create casadi.integrator for the DAESystem.

        :param dict options: casadi.integrator options
        :param str integrator_type: integrator type, options available are: 'cvodes', 'idas',
            'implicit' (default, auto-select between 'idas' and 'cvodes'), 'rk', and 'collocation'.
        :return:
        """
        if options is None:
            options = {}

        # Integrator Function name
        if 'name' in options:
            name = options.pop('name')
        else:
            name = 'integrator'

        # Load default options from the config file, if a 'options' dict was passed use that to override the default.
        for k in config.INTEGRATOR_OPTIONS:
            if k not in options:
                options[k] = config.INTEGRATOR_OPTIONS[k]

        # For backwards compatibility, previously option 'explicit' was a custom Runge-Kutta. CasADi now has it built-in
        if integrator_type == 'explicit':
            integrator_type = 'rk'

        # Return the specified integrator
        if integrator_type == 'implicit' and self.is_ode:
            return integrator(name, "cvodes", self.dae_system_dict, options)
        if integrator_type == 'implicit' and self.is_dae:
            return integrator(name, "idas", self.dae_system_dict, options)
        if integrator_type == 'rk4':
            if self.is_ode:
                return self._create_explicit_integrator(
                    'explicit_integrator', 'rk4', self.dae_system_dict,
                    options)
            else:
                raise Exception(
                    'Explicit integrator not implemented for DAE systems')
        if integrator_type in ['rk', 'collocation', 'cvodes', 'idas']:
            return integrator(name, integrator_type, self.dae_system_dict,
                              options)
        raise ValueError(
            "'integrator_type'={} not available. Options available are: 'cvodes', 'idas', implicit "
            "(default, auto-select between 'idas' and 'cvodes'), 'rk',"
            " and 'collocation'.".format(integrator_type))
Esempio n. 10
0
    def __init__(self, params):

        self.model = KinematicBicycleCar(N=params["N"], step=params["step"])
        self.sys = self.model.getDae()
        self.cost = 0
        self.Uk_prev = None
        self.indices_to_stop = None
        self.indices_to_start = None
        # hack

        simparams = {
            'x': self.sys.x[0],
            'p': self.sys.u[0],
            'ode': self.sys.ode[0]
        }
        self.sim = ca.integrator('F', 'idas', simparams, {
            't0': 0,
            'tf': self.model.step
        })

        # Set up collocation (from direct_collocation example)

        # Degree of interpolating polynomial
        self._d = 3

        # Get collocation points
        tau_root = np.append(0, ca.collocation_points(self._d, 'legendre'))

        # Coefficients of the collocation equation
        self._C = np.zeros((self._d + 1, self._d + 1))

        # Coefficients of the continuity equation
        self._D = np.zeros(self._d + 1)

        # Coefficients of the quadrature function
        self._B = np.zeros(self._d + 1)

        # Construct polynomial basis
        for j in range(self._d + 1):
            # Construct Lagrange polynomials to get the polynomial basis at the collocation point
            p = np.poly1d([1])
            for r in range(self._d + 1):
                if r != j:
                    p *= np.poly1d([1, -tau_root[r]
                                    ]) / (tau_root[j] - tau_root[r])

            # Evaluate the polynomial at the final time to get the coefficients of the continuity equation
            self._D[j] = p(1.0)

            # Evaluate the time derivative of the polynomial at all collocation points to get the coefficients of the continuity equation
            pder = np.polyder(p)
            for r in range(self._d + 1):
                self._C[j, r] = pder(tau_root[r])

            # Evaluate the integral of the polynomial to get the coefficients of the quadrature function
            pint = np.polyint(p)
            self._B[j] = pint(1.0)
Esempio n. 11
0
def create_test_data(model, x_labels):

    ts = np.linspace(0, 100, 100)
    opts = {'grid': ts, 'output_t0': True}

    integrator = cs.integrator('integrator', 'cvodes', model, opts)
    xf = np.asarray(integrator(x0=[0., 0., 1.], p=[0.4, 0.05, 0.1])['xf']).T
    xf_noise = xf * (1 + .1 * np.random.randn(*xf.shape))

    return pd.DataFrame(xf_noise, index=ts, columns=x_labels)
Esempio n. 12
0
    def _initialize_ekf_for_arrival_cost_update(self):

        self.hfcn = ca.Function("h", [self.x, self.c], [self.h])
        self.H = self.hfcn.jac()

        ode = {"x": self.x, "p": ca.veccat(self.c, self.u, self.b, self.w), \
            "ode": self.f}

        self.phi = ca.integrator("integrator", "cvodes", ode, \
            {"t0": 0.0, "tf": self._timing.dt_day})
        self.Phi = self.phi.jac()
Esempio n. 13
0
    def _initialize_polynomial_coefs(self):
        """ Setup radau polynomials and initialize the weight factor matricies
        """
        self.col_vars['tau_root'] = [0] + cs.collocation_points(
            self.d, "radau")

        # Dimensionless time inside one control interval
        tau = cs.SX.sym("tau")

        # For all collocation points
        L = [[]] * (self.d + 1)
        for j in range(self.d + 1):
            # Construct Lagrange polynomials to get the polynomial basis at the
            # collocation point
            L[j] = 1
            for r in range(self.d + 1):
                if r != j:
                    L[j] *= ((tau - self.col_vars['tau_root'][r]) /
                             (self.col_vars['tau_root'][j] -
                              self.col_vars['tau_root'][r]))

        self.col_vars['lfcn'] = lfcn = cs.Function('lfcn', [tau],
                                                   [cs.vertcat(*L)])

        # Evaluate the polynomial at the final time to get the coefficients of
        # the continuity equation
        # Coefficients of the continuity equation
        self.col_vars['D'] = np.asarray(lfcn(1.0)).squeeze()

        # Evaluate the time derivative of the polynomial at all collocation
        # points to get the coefficients of the continuity equation
        tfcn = lfcn.tangent()

        # Coefficients of the collocation equation
        self.col_vars['C'] = np.zeros((self.d + 1, self.d + 1))
        for r in range(self.d + 1):
            self.col_vars['C'][:, r] = np.asarray(
                tfcn(self.col_vars['tau_root'][r])[0]).squeeze()

        # Find weights for gaussian quadrature: approximate int_0^1 f(x) by
        # Sum(
        xtau = cs.SX.sym("xtau")

        Phi = [[]] * (self.d + 1)

        for j in range(self.d + 1):
            dae = dict(t=tau, x=xtau, ode=L[j])
            tau_integrator = cs.integrator("integrator", "cvodes", dae, {
                't0': 0.,
                'tf': 1
            })
            Phi[j] = np.asarray(tau_integrator(x0=0)['xf'])

        self.col_vars['Phi'] = np.array(Phi)
Esempio n. 14
0
    def createTimeDiscreteFun(ode, stepSize, NX, NU, integratorType='rk'):
        x = ca.SX.sym('x', NX)
        u = ca.SX.sym('u', NU)
        modelProps = {'x': x, 'p': u, 'ode': ode(x, u)}

        if integratorType == 'rk':
            return ca.Function('intg', [x, u], [rk4step(ode, x, u, stepSize)])
        else:
            return lambda x0, u: ca.integrator('intg', integratorType,
                                               modelProps, {'tf': stepSize})(
                                                   x0=x0, p=u)['xf']
Esempio n. 15
0
def dynamics(x, u, data):
    """ System dynamics function (discrete time)
    """

    # state derivative expression
    xdot = ca.vertcat(
        (data['F1'] * data['X1'] - data['F2'] * x['X2']) / data['M'],
        (data['F4'] - data['F5']) / data['C'])

    # create ode for integrator
    ode = {'x': x, 'p': u, 'ode': xdot}

    return [ca.integrator('F', 'collocation', ode, {'tf': 1}), ode]
Esempio n. 16
0
 def intg_builtin(self, f, X, U, P, Z):
     # A single CVODES step
     DT = MX.sym("DT")
     t = MX.sym("t")
     t0 = MX.sym("t0")
     res = f(x=X, u=U, p=P, t=t0+t*DT, z=Z)
     data = {'x': X, 'p': vertcat(U, DT, P, t0), 'z': Z, 't': t, 'ode': DT * res["ode"], 'quad': DT * res["quad"], 'alg': res["alg"]}
     options = dict(self.intg_options)
     if self.intg in ["collocation"]:
         options["number_of_finite_elements"] = 1
     I = integrator('intg_cvodes', self.intg, data, options)
     res = I.call({'x0': X, 'p': vertcat(U, DT, P, t0)})
     return Function('F', [X, U, t0, DT, P], [res["xf"], MX(), res["qf"]], ['x0', 'u', 't0', 'DT', 'p'], ['xf', 'poly_coeff','qf'])
Esempio n. 17
0
    def _setup_simulator(self):

        self._setup_model()

        dt = ca.MX.sym("dt")

        ode = {"x": self.x, "p": ca.veccat(dt, self.c, self.u, self.b, self.w), \
        "ode": dt * self.f}

        self._integrator = ca.integrator("integrator", "cvodes", ode, \
            {"t0": 0.0, "tf": 1.0})

        self._remove_unserializable_attributes()
    def _initialize_polynomial_coefs(self):
        """ Setup radau polynomials and initialize the weight factor matricies
        """
        self.col_vars['tau_root'] = [0] + cs.collocation_points(self.d, "radau")

        # Dimensionless time inside one control interval
        tau = cs.SX.sym("tau")

        # For all collocation points
        L = [[]]*(self.d+1)
        for j in range(self.d+1):
            # Construct Lagrange polynomials to get the polynomial basis at the
            # collocation point
            L[j] = 1
            for r in range(self.d+1):
                if r != j:
                    L[j] *= (
                        (tau - self.col_vars['tau_root'][r]) / 
                        (self.col_vars['tau_root'][j] -
                         self.col_vars['tau_root'][r]))

        self.col_vars['lfcn'] = lfcn = cs.Function(
            'lfcn', [tau], [cs.vertcat(*L)])

        # Evaluate the polynomial at the final time to get the coefficients of
        # the continuity equation
        # Coefficients of the continuity equation
        self.col_vars['D'] = np.asarray(lfcn(1.0)).squeeze()

        # Evaluate the time derivative of the polynomial at all collocation
        # points to get the coefficients of the continuity equation
        tfcn = lfcn.tangent()

        # Coefficients of the collocation equation
        self.col_vars['C'] = np.zeros((self.d+1, self.d+1))
        for r in range(self.d+1):
            self.col_vars['C'][:,r] = np.asarray(tfcn(self.col_vars['tau_root'][r])[0]).squeeze()

        # Find weights for gaussian quadrature: approximate int_0^1 f(x) by
        # Sum(
        xtau = cs.SX.sym("xtau")

        Phi = [[]] * (self.d+1)

        for j in range(self.d+1):
            dae = dict(t=tau, x=xtau, ode=L[j])
            tau_integrator = cs.integrator(
                "integrator", "cvodes", dae, {'t0':0., 'tf':1})
            Phi[j] = np.asarray(tau_integrator(x0=0)['xf'])

        self.col_vars['Phi'] = np.array(Phi)
Esempio n. 19
0
    def get_integrator(self, model, t_eval, inputs):
        # Only set up problem once
        if model not in self.problems:
            y0 = model.y0
            rhs = model.casadi_rhs
            algebraic = model.casadi_algebraic

            # When not in DEBUG mode (level=10), suppress warnings from CasADi
            if (pybamm.logger.getEffectiveLevel() == 10
                    or pybamm.settings.debug_mode is True):
                show_eval_warnings = True
            else:
                show_eval_warnings = False

            options = {
                **self.extra_options_setup,
                "grid": t_eval,
                "reltol": self.rtol,
                "abstol": self.atol,
                "output_t0": True,
                "show_eval_warnings": show_eval_warnings,
            }

            # set up and solve
            t = casadi.MX.sym("t")
            p = casadi.MX.sym("p", inputs.shape[0])
            y_diff = casadi.MX.sym("y_diff", rhs(t_eval[0], y0, p).shape[0])
            problem = {"t": t, "x": y_diff, "p": p}
            if algebraic(t_eval[0], y0, p).is_empty():
                method = "cvodes"
                problem.update({"ode": rhs(t, y_diff, p)})
            else:
                options["calc_ic"] = True
                method = "idas"
                y_alg = casadi.MX.sym("y_alg",
                                      algebraic(t_eval[0], y0, p).shape[0])
                y_full = casadi.vertcat(y_diff, y_alg)
                problem.update({
                    "z": y_alg,
                    "ode": rhs(t, y_full, p),
                    "alg": algebraic(t, y_full, p),
                })
            self.problems[model] = problem
            self.options[model] = options
            self.methods[model] = method
        else:
            # problem stays the same
            # just update options
            self.options[model]["grid"] = t_eval
        return casadi.integrator("F", self.methods[model],
                                 self.problems[model], self.options[model])
    def __prepare_dynamics(self, nlp):
        """
        Builds CasaDI dynamics function.
        :param dynamics_func: A selected method handler of the class dynamics.Dynamics.
        :param ode_solver: Name of chosen ode, available in OdeSolver enum class.
        """

        dynamics = casadi.Function(
            "ForwardDyn",
            [self.symbolic_states, self.symbolic_controls],
            [
                nlp["dynamics_func"](self.symbolic_states,
                                     self.symbolic_controls, nlp)
            ],
            ["x", "u"],
            ["xdot"],
        ).expand()  # .map(nlp["ns"], "thread", 2)

        ode = {
            "x": nlp["x"],
            "p": nlp["u"],
            "ode": dynamics(nlp["x"], nlp["u"])
        }

        ode_opt = {"t0": 0, "tf": nlp["dt"]}
        if nlp["ode_solver"] == OdeSolver.RK or nlp[
                "ode_solver"] == OdeSolver.COLLOCATION:
            ode_opt["number_of_finite_elements"] = 5

        if nlp["ode_solver"] == OdeSolver.RK:
            nlp["dynamics"] = casadi.integrator("integrator", "rk", ode,
                                                ode_opt)
        elif nlp["ode_solver"] == OdeSolver.COLLOCATION:
            nlp["dynamics"] = casadi.integrator("integrator", "collocation",
                                                ode, ode_opt)
        elif nlp["ode_solver"] == OdeSolver.CVODES:
            nlp["dynamics"] = casadi.integrator("integrator", "cvodes", ode,
                                                ode_opt)
Esempio n. 21
0
 def arclength(self, s):
     if s == 0:
         return 0.0
     length = cas.integrator(
         'integrator', 'rk', {
             'x': cas.MX.sym('null'),
             't': self._s,
             'ode': 0,
             'quad': cas.norm_2(cas.jacobian(self._expr, self._s))
         }, {
             't0': 0.0,
             'tf': s
         }).call({})['qf']
     return length
Esempio n. 22
0
    def set_integrators_augmented(self):
        """
        Generate continuous time high-precision integrators.
        """
        
        # Set CasADi variables
        u = ca.MX.sym('u', 4)
        options = {"abstol" : 1e-5, "reltol" : 1e-9, "max_num_steps": 100, 
                   "tf" : self.dt}

        # Create augmented system dynamics integrator
        x_ag = ca.MX.sym('x', 15)
        dae = {'x': x_ag, 'ode': self.model_nl_ag(x_ag,u), 'p':ca.vertcat(u)}
        self.Integrator_nl_ag = ca.integrator('integrator', 'cvodes', dae, options)
        
        print("Augmented integraters are set perfectly !")
Esempio n. 23
0
	def run_reaction(self,species_dict,reactions,t_i=0,t_f=20,t_step=0.1):

		# ODE and Bounds
		t= np.arange(t_i,t_f,t_step)
		ode = {'x':vertcat(*[v['sx'] for v in species_dict.values()]),
			   'ode':reactions}

		# Solving
		opts = {'grid':t, 'output_t0':True}
		F = cas.integrator('F','cvodes',ode,opts)
		results = F(x0=[v['Ci'] for v in species_dict.values()])
		
		# Clean results
		dfresults = pd.DataFrame(np.array(results['xf']),index=species_dict.keys()).T.set_index(t)

		return dfresults, results
Esempio n. 24
0
def dynamics(x, u, data, h=1.0):
    """ System dynamics formulation (discrete time)
    """
    # state derivative
    xdot = ca.vertcat(
        data['v'] * x['ez'], data['v'] * x['ey'], -u['u'] * x['ey'] -
        data['rho'] * x['ez'] * (x['ez']**2 + x['ey']**2 - 1.0),
        u['u'] * x['ez'] - data['rho'] * x['ey'] *
        (x['ez']**2 + x['ey']**2 - 1.0))

    # set-up ode system
    f = ca.Function('f', [x, u], [xdot])
    ode = {'x': x, 'p': u, 'ode': f(x, u)}

    return ca.integrator('F', 'rk', ode, {
        'tf': h,
        'number_of_finite_elements': 50
    })
Esempio n. 25
0
def simulate(x0, u0, t0, tf, dt):
    xs = ca.MX.sym('x', 13)
    x = f16.State.from_casadi(xs)
    us = ca.MX.sym('u', 4)
    u = f16.Control.from_casadi(us)
    dae = {'x': xs, 'p': us, 'ode': f16.dynamics(x, u, p).to_casadi()}
    F = ca.integrator('F', 'idas', dae, {'t0': 0, 'tf': dt, 'jit': True})
    x = np.array(x0.to_casadi()).reshape(-1)
    u = np.array(u0.to_casadi()).reshape(-1)
    data = {'t': [0], 'x': [x]}
    t_vect = np.arange(t0, tf, dt)
    for t in t_vect:
        x = np.array(F(x0=x, p=u)['xf']).reshape(-1)
        data['t'].append(t)
        data['x'].append(x)
    for k in data.keys():
        data[k] = np.array(data[k])
    return data
Esempio n. 26
0
        def integrator(self, ocp, nlp) -> list:
            """
            The interface of the OdeSolver to the corresponding integrator

            Parameters
            ----------
            ocp: OptimalControlProgram
                A reference to the ocp
            nlp: NonLinearProgram
                A reference to the nlp

            Returns
            -------
            A list of integrators
            """

            if not isinstance(ocp.cx(), casadi.MX):
                raise RuntimeError(
                    "CVODES integrator can only be used with MX graphs")
            if len(ocp.v.params.size) != 0:
                raise RuntimeError(
                    "CVODES cannot be used while optimizing parameters")
            if nlp.external_forces:
                raise RuntimeError(
                    "CVODES cannot be used with external_forces")
            if nlp.control_type == ControlType.LINEAR_CONTINUOUS:
                raise RuntimeError(
                    "CVODES cannot be used with piece-wise linear controls (only RK4)"
                )
            if not isinstance(nlp.ode_solver, OdeSolver.RK4):
                raise RuntimeError("CVODES is only implemented with RK4")

            ode = {
                "x": nlp.x,
                "p": nlp.u,
                "ode": nlp.dynamics_func(nlp.x, nlp.u, nlp.p)
            }
            ode_opt = {
                "t0": 0,
                "tf": nlp.dt,
                "number_of_finite_elements": nlp.ode_solver.steps
            }

            return [casadi.integrator("integrator", "cvodes", ode, ode_opt)]
Esempio n. 27
0
    def get_integrator(self, model, t_eval, inputs):
        # Only set up problem once
        if model not in self.problems:
            y0 = model.y0
            rhs = model.casadi_rhs
            algebraic = model.casadi_algebraic
            u_stacked = casadi.vertcat(*[x for x in inputs.values()])

            options = {
                "grid": t_eval,
                "reltol": self.rtol,
                "abstol": self.atol,
                "output_t0": True,
                "max_num_steps": self.max_steps,
            }

            # set up and solve
            t = casadi.MX.sym("t")
            u = casadi.MX.sym("u", u_stacked.shape[0])
            y_diff = casadi.MX.sym("y_diff", rhs(t_eval[0], y0, u).shape[0])
            problem = {"t": t, "x": y_diff, "p": u}
            if algebraic(t_eval[0], y0, u).is_empty():
                method = "cvodes"
                problem.update({"ode": rhs(t, y_diff, u)})
            else:
                options["calc_ic"] = True
                method = "idas"
                y_alg = casadi.MX.sym("y_alg",
                                      algebraic(t_eval[0], y0, u).shape[0])
                y_full = casadi.vertcat(y_diff, y_alg)
                problem.update({
                    "z": y_alg,
                    "ode": rhs(t, y_full, u),
                    "alg": algebraic(t, y_full, u),
                })
            self.problems[model] = problem
            self.options[model] = options
            self.methods[model] = method
        else:
            # problem stays the same
            # just update options
            self.options[model]["grid"] = t_eval
        return casadi.integrator("F", self.methods[model],
                                 self.problems[model], self.options[model])
Esempio n. 28
0
    def setup_integrator(self, integration_method='cvodes', opts=None):
        """Setup casadi integrator."""

        #: Generate Options for integration
        self.generate_opts(opts)
        #: Initialize states of the integrator
        self.fin['x0'] = self.dae.x
        self.fin['p'] = self.dae.u +\
            self.dae.p + self.dae.c
        self.fin['z0'] = self.dae.z
        self.fin['rx0'] = cas.DM([])
        self.fin['rp'] = cas.DM([])
        self.fin['rz0'] = cas.DM([])

        self.dae.print_dae()
        #: Set up the integrator
        self.integrator = cas.integrator('pendulum', integration_method,
                                         self.dae.generate_dae(), self.opts)
        return self.integrator
Esempio n. 29
0
    def integrate_casadi(self, problem, y0, t_eval, mass_matrix=None):
        """
        Solve a DAE model defined by residuals with initial conditions y0.

        Parameters
        ----------
        residuals : method
            A function that takes in t, y and ydot and returns the residuals of the
            equations
        y0 : numeric type
            The initial conditions
        t_eval : numeric type
            The times at which to compute the solution
        mass_matrix : array_like, optional
            The (sparse) mass matrix for the chosen spatial method. This is only passed
            to check that the mass matrix is diagonal with 1s for the odes and 0s for
            the algebraic equations, as CasADi does not allow to pass mass matrices.
        """
        options = {
            "grid": t_eval,
            "reltol": self.rtol,
            "abstol": self.atol,
            "output_t0": True,
        }
        options.update(self.extra_options)
        if self.method == "idas":
            options["calc_ic"] = True

        # set up and solve
        integrator = casadi.integrator("F", self.method, problem, options)
        try:
            # Try solving
            len_rhs = problem["x"].size()[0]
            y0_diff, y0_alg = np.split(y0, [len_rhs])
            sol = integrator(x0=y0_diff, z0=y0_alg)
            y_values = np.concatenate([sol["xf"].full(), sol["zf"].full()])
            return pybamm.Solution(t_eval, y_values, None, None, "final time")
        except RuntimeError as e:
            # If it doesn't work raise error
            raise pybamm.SolverError(e.args[0])
Esempio n. 30
0
def expm(a_matrix):
    """Since casadi does not have native support for matrix exponential, this is a trick to computing it.
    It can be quite expensive, specially for large matrices.
    THIS ONLY SUPPORT NUMERIC MATRICES AND MX VARIABLES, DOES NOT SUPPORT SX SYMBOLIC VARIABLES.

    :param DM a_matrix: matrix
    :return:
    """
    dim = a_matrix.shape[1]

    # Create the integrator
    x_mx = MX.sym('x', a_matrix.shape[1])
    a_mx = MX.sym('x', a_matrix.shape)
    ode = mtimes(a_mx, x_mx)
    dae_system_dict = {'x': x_mx, 'ode': ode, 'p': vec(a_mx)}

    integrator_ = integrator("integrator", "cvodes", dae_system_dict,
                             {'tf': 1})
    integrator_map = integrator_.map(a_matrix.shape[1], 'thread')

    res = integrator_map(x0=DM.eye(dim),
                         p=repmat(vec(a_matrix), (1, a_matrix.shape[1])))['xf']

    return res
    def __prepare_dynamics(self, nlp):
        """
        Builds CasaDI dynamics function.
        :param nlp: The nlp problem
        """

        ode_opt = {"t0": 0, "tf": nlp["dt"]}
        if nlp["ode_solver"] == OdeSolver.COLLOCATION or nlp[
                "ode_solver"] == OdeSolver.RK:
            ode_opt["number_of_finite_elements"] = nlp["nb_integration_steps"]

        dynamics = nlp["dynamics_func"]
        ode = {
            "x": nlp["x"],
            "p": nlp["u"],
            "ode": dynamics(nlp["x"], nlp["u"], nlp["p"])
        }
        nlp["dynamics"] = []
        nlp["par_dynamics"] = {}
        if nlp["ode_solver"] == OdeSolver.RK:
            ode_opt["model"] = nlp["model"]
            ode_opt["param"] = nlp["p"]
            ode_opt["CX"] = nlp["CX"]
            ode_opt["idx"] = 0
            ode["ode"] = dynamics
            ode_opt["control_type"] = nlp["control_type"]
            if "external_forces" in nlp:
                for idx in range(len(nlp["external_forces"])):
                    ode_opt["idx"] = idx
                    nlp["dynamics"].append(RK4(ode, ode_opt))
            else:
                if self.nb_threads > 1 and nlp[
                        "control_type"] == ControlType.LINEAR_CONTINUOUS:
                    raise RuntimeError(
                        "Piece-wise linear continuous controls cannot be used with multiple threads"
                    )
                nlp["dynamics"].append(RK4(ode, ode_opt))
        elif nlp["ode_solver"] == OdeSolver.COLLOCATION:
            if not isinstance(self.CX(), MX):
                raise RuntimeError(
                    "COLLOCATION integrator can only be used with MX graphs")
            if len(self.param_to_optimize) != 0:
                raise RuntimeError(
                    "COLLOCATION cannot be used while optimizing parameters")
            if "external_forces" in nlp:
                raise RuntimeError(
                    "COLLOCATION cannot be used with external_forces")
            if nlp["control_type"] == ControlType.LINEAR_CONTINUOUS:
                raise RuntimeError(
                    "COLLOCATION cannot be used with piece-wise linear controls (only RK4)"
                )
            nlp["dynamics"].append(
                casadi.integrator("integrator", "collocation", ode, ode_opt))
        elif nlp["ode_solver"] == OdeSolver.CVODES:
            if not isinstance(self.CX(), MX):
                raise RuntimeError(
                    "CVODES integrator can only be used with MX graphs")
            if len(self.param_to_optimize) != 0:
                raise RuntimeError(
                    "CVODES cannot be used while optimizing parameters")
            if "external_forces" in nlp:
                raise RuntimeError(
                    "CVODES cannot be used with external_forces")
            if nlp["control_type"] == ControlType.LINEAR_CONTINUOUS:
                raise RuntimeError(
                    "CVODES cannot be used with piece-wise linear controls (only RK4)"
                )
            nlp["dynamics"].append(
                casadi.integrator("integrator", "cvodes", ode, ode_opt))

        if len(nlp["dynamics"]) == 1:
            if self.nb_threads > 1:
                nlp["par_dynamics"] = nlp["dynamics"][0].map(
                    nlp["ns"], "thread", self.nb_threads)
            nlp["dynamics"] = nlp["dynamics"] * nlp["ns"]
Esempio n. 32
0
    def _simulate_with_casadi_with_inputs(self, initcon, tsim, varying_inputs,
                                          integrator, integrator_options):

        xalltemp = [self._templatemap[i] for i in self._diffvars]
        xall = casadi.vertcat(*xalltemp)

        time = casadi.SX.sym('time')

        odealltemp = [time * convert_pyomo2casadi(self._rhsdict[i])
                      for i in self._derivlist]
        odeall = casadi.vertcat(*odealltemp)

        # Time-varying inputs
        ptemp = [self._templatemap[i]
                 for i in self._siminputvars.values()]
        pall = casadi.vertcat(time, *ptemp)

        dae = {'x': xall, 'p': pall, 'ode': odeall}

        if len(self._algvars) != 0:
            zalltemp = [self._templatemap[i] for i in self._simalgvars]
            zall = casadi.vertcat(*zalltemp)
            # Need to do anything special with time scaling??
            algalltemp = [convert_pyomo2casadi(i) for i in self._alglist]
            algall = casadi.vertcat(*algalltemp)
            dae['z'] = zall
            dae['alg'] = algall

        integrator_options['tf'] = 1.0
        F = casadi.integrator('F', integrator, dae, integrator_options)
        N = len(tsim)

        # This approach removes the time scaling from tsim so must
        # create an array with the time step between consecutive
        # time points
        tsimtemp = np.hstack([0, tsim[1:] - tsim[0:-1]])
        tsimtemp.shape = (1, len(tsimtemp))

        palltemp = [casadi.DM(tsimtemp)]

        # Need a similar np array for each time-varying input
        for p in self._siminputvars.keys():
            profile = varying_inputs[p]
            tswitch = list(profile.keys())
            tswitch.sort()
            tidx = [tsim.searchsorted(i) for i in tswitch] + \
                   [len(tsim) - 1]
            ptemp = [profile[0]] + \
                    [casadi.repmat(profile[tswitch[i]], 1,
                                   tidx[i + 1] - tidx[i])
                     for i in range(len(tswitch))]
            temp = casadi.horzcat(*ptemp)
            palltemp.append(temp)

        I = F.mapaccum('simulator', N)
        sol = I(x0=initcon, p=casadi.vertcat(*palltemp))
        profile = sol['xf'].full().T

        if len(self._algvars) != 0:
            algprofile = sol['zf'].full().T
            profile = np.concatenate((profile, algprofile), axis=1)

        return [tsim, profile]