def run_example(with_plots=True): """ This is the same example from the Sundials package (idasRoberts_FSA_dns.c) This simple example problem for IDA, due to Robertson, is from chemical kinetics, and consists of the following three equations:: dy1/dt = -p1*y1 + p2*y2*y3 dy2/dt = p1*y1 - p2*y2*y3 - p3*y2**2 0 = y1 + y2 + y3 - 1 """ def f(t, y, yd, p): res1 = -p[0]*y[0]+p[1]*y[1]*y[2]-yd[0] res2 = p[0]*y[0]-p[1]*y[1]*y[2]-p[2]*y[1]**2-yd[1] res3 = y[0]+y[1]+y[2]-1 return N.array([res1,res2,res3]) #The initial conditons y0 = [1.0, 0.0, 0.0] #Initial conditions for y yd0 = [0.1, 0.0, 0.0] #Initial conditions for dy/dt p0 = [0.040, 1.0e4, 3.0e7] #Initial conditions for parameters #Create an Assimulo implicit problem imp_mod = Implicit_Problem(f, y0, yd0,p0=p0) #Create an Assimulo implicit solver (IDA) imp_sim = IDA(imp_mod) #Create a IDA solver #Sets the paramters imp_sim.atol = N.array([1.0e-8, 1.0e-14, 1.0e-6]) imp_sim.algvar = [1.0,1.0,0.0] imp_sim.suppress_alg = False #Suppres the algebraic variables on the error test imp_sim.continuous_output = True #Store data continuous during the simulation imp_sim.pbar = p0 imp_sim.suppress_sens = False #Dont suppress the sensitivity variables in the error test. #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(4,400) #Simulate 4 seconds with 400 communication points print imp_sim.p_sol[0][-1] , imp_sim.p_sol[1][-1], imp_sim.p_sol[0][-1] #Basic test nose.tools.assert_almost_equal(y[-1][0], 9.05518032e-01, 4) nose.tools.assert_almost_equal(y[-1][1], 2.24046805e-05, 4) nose.tools.assert_almost_equal(y[-1][2], 9.44595637e-02, 4) nose.tools.assert_almost_equal(imp_sim.p_sol[0][-1][0], -1.8761, 2) #Values taken from the example in Sundials nose.tools.assert_almost_equal(imp_sim.p_sol[1][-1][0], 2.9614e-06, 8) nose.tools.assert_almost_equal(imp_sim.p_sol[2][-1][0], -4.9334e-10, 12) #Plot if with_plots: P.plot(t,y) P.show()
def run_example(with_plots=True): """ This is the same example from the Sundials package (idasRoberts_FSA_dns.c) This simple example problem for IDA, due to Robertson, is from chemical kinetics, and consists of the following three equations:: dy1/dt = -p1*y1 + p2*y2*y3 dy2/dt = p1*y1 - p2*y2*y3 - p3*y2**2 0 = y1 + y2 + y3 - 1 """ def f(t, y, yd, p): res1 = -p[0] * y[0] + p[1] * y[1] * y[2] - yd[0] res2 = p[0] * y[0] - p[1] * y[1] * y[2] - p[2] * y[1]**2 - yd[1] res3 = y[0] + y[1] + y[2] - 1 return N.array([res1, res2, res3]) #The initial conditons y0 = [1.0, 0.0, 0.0] #Initial conditions for y yd0 = [0.1, 0.0, 0.0] #Initial conditions for dy/dt p0 = [0.040, 1.0e4, 3.0e7] #Initial conditions for parameters #Create an Assimulo implicit problem imp_mod = Implicit_Problem(f, y0, yd0, p0=p0) #Create an Assimulo implicit solver (IDA) imp_sim = IDA(imp_mod) #Create a IDA solver #Sets the paramters imp_sim.atol = N.array([1.0e-8, 1.0e-14, 1.0e-6]) imp_sim.algvar = [1.0, 1.0, 0.0] imp_sim.suppress_alg = False #Suppres the algebraic variables on the error test imp_sim.continuous_output = True #Store data continuous during the simulation imp_sim.pbar = p0 imp_sim.suppress_sens = False #Dont suppress the sensitivity variables in the error test. #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( 4, 400) #Simulate 4 seconds with 400 communication points print imp_sim.p_sol[0][-1], imp_sim.p_sol[1][-1], imp_sim.p_sol[0][-1] #Basic test nose.tools.assert_almost_equal(y[-1][0], 9.05518032e-01, 4) nose.tools.assert_almost_equal(y[-1][1], 2.24046805e-05, 4) nose.tools.assert_almost_equal(y[-1][2], 9.44595637e-02, 4) nose.tools.assert_almost_equal( imp_sim.p_sol[0][-1][0], -1.8761, 2) #Values taken from the example in Sundials nose.tools.assert_almost_equal(imp_sim.p_sol[1][-1][0], 2.9614e-06, 8) nose.tools.assert_almost_equal(imp_sim.p_sol[2][-1][0], -4.9334e-10, 12) #Plot if with_plots: P.plot(t, y) P.show()
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