Ejemplo n.º 1
0
    def simulate(self, Tend, nIntervals, gridWidth):

        problem = Implicit_Problem(self.rhs, self.y0, self.yd0)
        problem.name = 'IDA'
        # solver.rhs = self.right_hand_side
        problem.handle_result = self.handle_result
        problem.state_events = self.state_events
        problem.handle_event = self.handle_event
        problem.time_events = self.time_events
        problem.finalize = self.finalize
        # Create IDA object and set additional parameters
        simulation = IDA(problem)
        simulation.atol = self.atol
        simulation.rtol = self.rtol
        simulation.verbosity = self.verbosity
        if hasattr(simulation, 'continuous_output'):
            simulation.continuous_output = False  # default 0, if one step approach should be used
        elif hasattr(simulation, 'report_continuously'):
            simulation.report_continuously = False  # default 0, if one step approach should be used
        simulation.tout1 = self.tout1
        simulation.lsoff = self.lsoff

        # Calculate nOutputIntervals:
        if gridWidth <> None:
            nOutputIntervals = int((Tend - self.t0) / gridWidth)
        else:
            nOutputIntervals = nIntervals
        # Check for feasible input parameters
        if nOutputIntervals == 0:
            print 'Error: gridWidth too high or nIntervals set to 0! Continue with nIntervals=1'
            nOutputIntervals = 1
        # Perform simulation
        simulation.simulate(Tend, nOutputIntervals)  # to get the values: t_new, y_new,  yd_new = simulation.simulate
Ejemplo n.º 2
0
    def simulate(self, Tend, nIntervals, gridWidth):

        problem = Implicit_Problem(self.rhs, self.y0, self.yd0)
        problem.name = 'IDA'
        # solver.rhs = self.right_hand_side
        problem.handle_result = self.handle_result
        problem.state_events = self.state_events
        problem.handle_event = self.handle_event
        problem.time_events = self.time_events
        problem.finalize = self.finalize
        # Create IDA object and set additional parameters
        simulation = IDA(problem)
        simulation.atol = self.atol
        simulation.rtol = self.rtol
        simulation.verbosity = self.verbosity
        if hasattr(simulation, 'continuous_output'):
            simulation.continuous_output = False  # default 0, if one step approach should be used
        elif hasattr(simulation, 'report_continuously'):
            simulation.report_continuously = False  # default 0, if one step approach should be used
        simulation.tout1 = self.tout1
        simulation.lsoff = self.lsoff

        # Calculate nOutputIntervals:
        if gridWidth <> None:
            nOutputIntervals = int((Tend - self.t0) / gridWidth)
        else:
            nOutputIntervals = nIntervals
        # Check for feasible input parameters
        if nOutputIntervals == 0:
            print 'Error: gridWidth too high or nIntervals set to 0! Continue with nIntervals=1'
            nOutputIntervals = 1
        # Perform simulation
        simulation.simulate(Tend, nOutputIntervals)  # to get the values: t_new, y_new,  yd_new = simulation.simulate
Ejemplo n.º 3
0
 def solve(self):
     # Setup IDA
     assert self._initial_time is not None
     problem = Implicit_Problem(self._residual_vector_eval,
                                self.solution.vector(),
                                self.solution_dot.vector(),
                                self._initial_time)
     problem.jac = self._jacobian_matrix_eval
     problem.handle_result = self._monitor
     # Define an Assimulo IDA solver
     solver = IDA(problem)
     # Setup options
     assert self._time_step_size is not None
     solver.inith = self._time_step_size
     if self._absolute_tolerance is not None:
         solver.atol = self._absolute_tolerance
     if self._max_time_steps is not None:
         solver.maxsteps = self._max_time_steps
     if self._relative_tolerance is not None:
         solver.rtol = self._relative_tolerance
     if self._report:
         solver.verbosity = 10
         solver.display_progress = True
         solver.report_continuously = True
     else:
         solver.display_progress = False
         solver.verbosity = 50
     # Assert consistency of final time and time step size
     assert self._final_time is not None
     final_time_consistency = (
         self._final_time - self._initial_time) / self._time_step_size
     assert isclose(
         round(final_time_consistency), final_time_consistency
     ), ("Final time should be occuring after an integer number of time steps"
         )
     # Prepare monitor computation if not provided by parameters
     if self._monitor_initial_time is None:
         self._monitor_initial_time = self._initial_time
     assert isclose(
         round(self._monitor_initial_time / self._time_step_size),
         self._monitor_initial_time / self._time_step_size
     ), ("Monitor initial time should be a multiple of the time step size"
         )
     if self._monitor_time_step_size is None:
         self._monitor_time_step_size = self._time_step_size
     assert isclose(
         round(self._monitor_time_step_size / self._time_step_size),
         self._monitor_time_step_size / self._time_step_size
     ), ("Monitor time step size should be a multiple of the time step size"
         )
     monitor_t = arange(
         self._monitor_initial_time,
         self._final_time + self._monitor_time_step_size / 2.,
         self._monitor_time_step_size)
     # Solve
     solver.simulate(self._final_time, ncp_list=monitor_t)
Ejemplo n.º 4
0
    def initialize_ode_solver(self, y_0, yd_0, t_0):
        model = Implicit_Problem(self.residual, y_0, yd_0, t_0)
        model.handle_result = self.handle_result
        solver = IDA(model)
        solver.rtol = self.solver_rtol
        solver.atol = self.solver_atol  # * np.array([100, 10, 1e-4, 1e-4])
        solver.inith = 0.1  # self.wind.R_g / const.C
        solver.maxh = self.dt * self.wind.R_g / const.C
        solver.report_continuously = True
        solver.display_progress = False
        solver.verbosity = 50  # 50 = quiet
        solver.num_threads = 3

        # solver.display_progress = True
        return solver
Ejemplo n.º 5
0
    def test_handle_result(self):
        """
        This function tests the handle result.
        """
        f = lambda t,x,xd: x**0.25-xd
        def handle_result(solver, t ,y, yd):
            assert solver.t == t
        
        prob = Implicit_Problem(f, [1.0],[1.0])
        prob.handle_result = handle_result
        
        sim = IDA(prob)

        sim.continuous_output = True
        
        sim.simulate(10.)
Ejemplo n.º 6
0
    def test_handle_result(self):
        """
        This function tests the handle result.
        """
        f = lambda t,x,xd: x**0.25-xd
        def handle_result(solver, t ,y, yd):
            assert solver.t == t
        
        prob = Implicit_Problem(f, [1.0],[1.0])
        prob.handle_result = handle_result
        
        sim = IDA(prob)

        sim.report_continuously = True
        
        sim.simulate(10.)
Ejemplo n.º 7
0
def run_example(with_plots=True):
    r"""
    Example for demonstrating the use of a user supplied Jacobian
    
    ODE:
    
    .. math::
       
        \dot y_1-y_3 &= 0 \\
        \dot y_2-y_4 &= 0 \\
        \dot y_3+y_5 y_1 &= 0 \\
        \dot y_4+y_5 y_2+9.82&= 0 \\
        y_3^2+y_4^2-y_5(y_1^2+y_2^2)-9.82 y_2&= 0 
    
    on return:
    
       - :dfn:`imp_mod`    problem instance
    
       - :dfn:`imp_sim`    solver instance
       
    """
    global order
    order = []

    #Defines the residual
    def f(t, y, yd):

        res_0 = yd[0] - y[2]
        res_1 = yd[1] - y[3]
        res_2 = yd[2] + y[4] * y[0]
        res_3 = yd[3] + y[4] * y[1] + 9.82
        res_4 = y[2]**2 + y[3]**2 - y[4] * (y[0]**2 + y[1]**2) - y[1] * 9.82

        return N.array([res_0, res_1, res_2, res_3, res_4])

    def handle_result(solver, t, y, yd):
        global order
        order.append(solver.get_last_order())

        solver.t_sol.extend([t])
        solver.y_sol.extend([y])
        solver.yd_sol.extend([yd])

    #The initial conditons
    y0 = [1.0, 0.0, 0.0, 0.0, 5]  #Initial conditions
    yd0 = [0.0, 0.0, 0.0, -9.82, 0.0]  #Initial conditions

    #Create an Assimulo implicit problem
    imp_mod = Implicit_Problem(f,
                               y0,
                               yd0,
                               name='Example for plotting used order')
    imp_mod.handle_result = handle_result

    #Sets the options to the problem
    imp_mod.algvar = [1.0, 1.0, 1.0, 1.0, 0.0]  #Set the algebraic components

    #Create an Assimulo implicit solver (IDA)
    imp_sim = IDA(imp_mod)  #Create a IDA solver

    #Sets the paramters
    imp_sim.atol = 1e-6  #Default 1e-6
    imp_sim.rtol = 1e-6  #Default 1e-6
    imp_sim.suppress_alg = True  #Suppres the algebraic variables on the error test
    imp_sim.report_continuously = True

    #Let Sundials find consistent initial conditions by use of 'IDA_YA_YDP_INIT'
    imp_sim.make_consistent('IDA_YA_YDP_INIT')

    #Simulate
    t, y, yd = imp_sim.simulate(5)  #Simulate 5 seconds

    #Basic tests
    nose.tools.assert_almost_equal(y[-1][0], 0.9401995, places=4)
    nose.tools.assert_almost_equal(y[-1][1], -0.34095124, places=4)
    nose.tools.assert_almost_equal(yd[-1][0], -0.88198927, places=4)
    nose.tools.assert_almost_equal(yd[-1][1], -2.43227069, places=4)
    nose.tools.assert_almost_equal(order[-1], 5, places=4)

    #Plot
    if with_plots:
        P.figure(1)
        P.plot(t, y, linestyle="dashed", marker="o")  #Plot the solution
        P.xlabel('Time')
        P.ylabel('State')
        P.title(imp_mod.name)

        P.figure(2)
        P.plot([0] + N.add.accumulate(N.diff(t)).tolist(), order)
        P.title("Used order during the integration")
        P.xlabel("Time")
        P.ylabel("Order")
        P.show()

    return imp_mod, imp_sim
Ejemplo n.º 8
0
def simulate(model, init_cond, start_time=0., final_time=1., input=(lambda t: []), ncp=500, blt=True,
             causalization_options=sp.CausalizationOptions(), expand_to_sx=True, suppress_alg=False,
             tol=1e-8, solver="IDA"):
    """
    Simulate model from CasADi Interface using CasADi.

    init_cond is a dictionary containing initial conditions for all variables.
    """
    if blt:
        t_0 = timing.time()
        blt_model = sp.BLTModel(model, causalization_options)
        blt_time = timing.time() - t_0
        print("BLT analysis time: %.3f s" % blt_time)
        blt_model._model = model
        model = blt_model
    
    if causalization_options['closed_form']:
        solved_vars = model._solved_vars
        solved_expr = model._solved_expr
        #~ for (var, expr) in itertools.izip(solved_vars, solved_expr):
            #~ print('%s := %s' % (var.getName(), expr))
        return model
        dh() # This is not a debug statement!

    # Extract model variables
    model_states = [var for var in model.getVariables(model.DIFFERENTIATED) if not var.isAlias()]
    model_derivatives = [var for var in model.getVariables(model.DERIVATIVE) if not var.isAlias()]
    model_algs = [var for var in model.getVariables(model.REAL_ALGEBRAIC) if not var.isAlias()]
    model_inputs = [var for var in model.getVariables(model.REAL_INPUT) if not var.isAlias()]
    states = [var.getVar() for var in model_states]
    derivatives = [var.getMyDerivativeVariable().getVar() for var in model_states]
    algebraics = [var.getVar() for var in model_algs]
    inputs = [var.getVar() for var in model_inputs]
    n_x = len(states)
    n_y = len(states) + len(algebraics)
    n_w = len(algebraics)
    n_u = len(inputs)

    # Create vectorized model variables
    t = model.getTimeVariable()
    y = MX.sym("y", n_y)
    yd = MX.sym("yd", n_y)
    u = MX.sym("u", n_u)

    # Extract the residuals and substitute the (x,z) variables for the old variables
    scalar_vars = states + algebraics + derivatives + inputs
    vector_vars = [y[k] for k in range(n_y)] + [yd[k] for k in range(n_x)] + [u[k] for k in range(n_u)]
    [dae] = substitute([model.getDaeResidual()], scalar_vars, vector_vars)

    # Fix parameters
    if not blt:
        # Sort parameters
        par_kinds = [model.BOOLEAN_CONSTANT,
                     model.BOOLEAN_PARAMETER_DEPENDENT,
                     model.BOOLEAN_PARAMETER_INDEPENDENT,
                     model.INTEGER_CONSTANT,
                     model.INTEGER_PARAMETER_DEPENDENT,
                     model.INTEGER_PARAMETER_INDEPENDENT,
                     model.REAL_CONSTANT,
                     model.REAL_PARAMETER_INDEPENDENT,
                     model.REAL_PARAMETER_DEPENDENT]
        pars = reduce(list.__add__, [list(model.getVariables(par_kind)) for
                                     par_kind in par_kinds])

        # Get parameter values
        model.calculateValuesForDependentParameters()
        par_vars = [par.getVar() for par in pars]
        par_vals = [model.get_attr(par, "_value") for par in pars]

        # Eliminate parameters
        [dae] = casadi.substitute([dae], par_vars, par_vals)

    # Extract initial conditions
    y0 = [init_cond[var.getName()] for var in model_states] + [init_cond[var.getName()] for var in model_algs]
    yd0 = [init_cond[var.getName()] for var in model_derivatives] + n_w * [0.]

    # Create residual CasADi functions
    dae_res = MXFunction([t, y, yd, u], [dae])
    dae_res.setOption("name", "complete_dae_residual")
    dae_res.init()

    ###################
    #~ import matplotlib.pyplot as plt
    #~ h = MX.sym("h")
    #~ iter_matrix_expr = dae_res.jac(2)/h + dae_res.jac(1)
    #~ iter_matrix = MXFunction([t, y, yd, u, h], [iter_matrix_expr])
    #~ iter_matrix.init()
    #~ n = 100;
    #~ hs = np.logspace(-8, 1, n);
    #~ conds = [np.linalg.cond(iter_matrix.call([0, y0, yd0, input(0), hval])[0].toArray()) for hval in hs]
    #~ plt.close(1)
    #~ plt.figure(1)
    #~ plt.loglog(hs, conds, 'b-')
    #~ #plt.gca().invert_xaxis()
    #~ plt.grid('on')

    #~ didx = range(4, 12) + range(30, 33)
    #~ aidx = [i for i in range(33) if i not in didx]
    #~ didx = range(10)
    #~ aidx = []
    #~ F = MXFunction([t, y, yd, u], [dae[didx]])
    #~ F.init()
    #~ G = MXFunction([t, y, yd, u], [dae[aidx]])
    #~ G.init()
    #~ dFddx = F.jac(2)[:, :n_x]
    #~ dFdx = F.jac(1)[:, :n_x]
    #~ dFdy = F.jac(1)[:, n_x:]
    #~ dGdx = G.jac(1)[:, :n_x]
    #~ dGdy = G.jac(1)[:, n_x:]
    #~ E_matrix = MXFunction([t, y, yd, u, h], [dFddx])
    #~ E_matrix.init()
    #~ E_cond = np.linalg.cond(E_matrix.call([0, y0, yd0, input(0), hval])[0].toArray())
    #~ iter_matrix_expr = vertcat([horzcat([dFddx + h*dFdx, h*dFdy]), horzcat([dGdx, dGdy])])
    #~ iter_matrix = MXFunction([t, y, yd, u, h], [iter_matrix_expr])
    #~ iter_matrix.init()
    #~ n = 100
    #~ hs = np.logspace(-8, 1, n)
    #~ conds = [np.linalg.cond(iter_matrix.call([0, y0, yd0, input(0), hval])[0].toArray()) for hval in hs]
    #~ plt.loglog(hs, conds, 'b--')
    #~ plt.gca().invert_xaxis()
    #~ plt.grid('on')
    #~ plt.xlabel('$h$')
    #~ plt.ylabel('$\kappa$')
    
    #~ plt.show()
    #~ dh()
    ###################

    # Expand to SX
    if expand_to_sx:
        dae_res = SXFunction(dae_res)
        dae_res.init()

    # Create DAE residual Assimulo function
    def dae_residual(t, y, yd):
        dae_res.setInput(t, 0)
        dae_res.setInput(y, 1)
        dae_res.setInput(yd, 2)
        dae_res.setInput(input(t), 3)
        dae_res.evaluate()
        return dae_res.getOutput(0).toArray().reshape(-1)

    # Set up simulator
    problem = Implicit_Problem(dae_residual, y0, yd0, start_time)
    if solver == "IDA":
        simulator = IDA(problem)
    elif solver == "Radau5DAE":
        simulator = Radau5DAE(problem)
    else:
        raise ValueError("Unknown solver %s" % solver)
    simulator.rtol = tol
    simulator.atol = 1e-4 * np.array([model.get_attr(var, "nominal") for var in model_states + model_algs])
    #~ simulator.atol = tol * np.ones([n_y, 1])
    simulator.report_continuously = True

    # Log method order
    if solver == "IDA":
        global order
        order = []
        def handle_result(solver, t, y, yd):
            global order
            order.append(solver.get_last_order())
            solver.t_sol.extend([t])
            solver.y_sol.extend([y])
            solver.yd_sol.extend([yd])
        problem.handle_result = handle_result

    # Suppress algebraic variables
    if suppress_alg:
        if isinstance(suppress_alg, bool):
            simulator.algvar = n_x * [True] + (n_y - n_x) * [False]
        else:
            simulator.algvar = n_x * [True] + suppress_alg
        simulator.suppress_alg = True

    # Simulate
    t_0 = timing.time()
    (t, y, yd) = simulator.simulate(final_time, ncp)
    simul_time = timing.time() - t_0
    stats = {'time': simul_time, 'steps': simulator.statistics['nsteps']}
    if solver == "IDA":
        stats['order'] = order

    # Generate result for time and inputs
    class SimulationResult(dict):
        pass
    res = SimulationResult()
    res.stats = stats
    res['time'] = t
    if u.numel() > 0:
        input_names = [var.getName() for var in model_inputs]
        for name in input_names:
            res[name] = []
        for time in t:
            input_val = input(time)
            for (name, val) in itertools.izip(input_names, input_val):
                res[name].append(val)

    # Create results for everything else
    if blt:
        # Iteration variables
        i = 0
        for var in model_states:
            res[var.getName()] = y[:, i]
            res[var.getMyDerivativeVariable().getName()] = yd[:, i]
            i += 1
        for var in model_algs:
            res[var.getName()] = y[:, i]
            i += 1

        # Create function for computing solved algebraics
        for (_, sol_alg) in model._explicit_solved_algebraics:
            res[sol_alg.name] = []
        alg_sol_f = casadi.MXFunction(model._known_vars + model._explicit_unsolved_vars, model._solved_expr)
        alg_sol_f.init()
        if expand_to_sx:
            alg_sol_f = casadi.SXFunction(alg_sol_f)
            alg_sol_f.init()

        # Compute solved algebraics
        for k in xrange(len(t)):
            for (i, var) in enumerate(model._known_vars + model._explicit_unsolved_vars):
                alg_sol_f.setInput(res[var.getName()][k], i)
            alg_sol_f.evaluate()
            for (j, sol_alg) in model._explicit_solved_algebraics:
                res[sol_alg.name].append(alg_sol_f.getOutput(j).toScalar())
    else:
        res_vars = model_states + model_algs
        for (i, var) in enumerate(res_vars):
            res[var.getName()] = y[:, i]
            der_var = var.getMyDerivativeVariable()
            if der_var is not None:
                res[der_var.getName()] = yd[:, i]

    # Add results for all alias variables (only treat time-continuous variables) and convert to array
    if blt:
        res_model = model._model
    else:
        res_model = model
    for var in res_model.getAllVariables():
        if var.getVariability() == var.CONTINUOUS:
            res[var.getName()] = np.array(res[var.getModelVariable().getName()])
    res["time"] = np.array(res["time"])
    res._blt_model = blt_model
    return res