def _solve_cvode(f, t, y0, args, console=False, max_steps=1000, terminate=False): """Wrapper for Assimulo's CVODE-Sundials routine """ def rhs(t, u): return f(u, t, *args) prob = Explicit_Problem(rhs, y0) sim = CVode(prob) sim.rtol = 1e-15 sim.atol = 1e-12 sim.discr = 'BDF' sim.maxord = 5 sim.maxsteps = max_steps if not console: sim.verbosity = 50 else: sim.report_continuously = True t_end = t[-1] steps = len(t) try: print t_end, steps t, x = sim.simulate(t_end, steps) except CVodeError, e: raise ValueError("Something broke in CVode: %r" % e) return None, False
def _setup_sim(self, **kwargs): """ Create a simulation interface to Assimulo using CVODE, given a problem definition """ # Create Assimulo interface sim = CVode(self.prob) sim.discr = 'BDF' sim.maxord = 5 # Setup some default arguments for the ODE solver, or override # if available. This is very hackish, but it's fine for now while # the number of anticipated tuning knobs is small. if 'maxh' in kwargs: sim.maxh = kwargs['maxh'] else: sim.maxh = np.min([0.1, self.output_dt]) if 'minh' in kwargs: sim.minh = kwargs['minh'] # else: sim.minh = 0.001 if "iter" in kwargs: sim.iter = kwargs['iter'] else: sim.iter = 'Newton' if "linear_solver" in kwargs: sim.linear_solver = kwargs['linear_solver'] if "max_steps" in kwargs: # DIFFERENT NAME!!!! sim.maxsteps = kwargs['max_steps'] else: sim.maxsteps = 1000 if "time_limit" in kwargs: sim.time_limit = kwargs['time_limit'] sim.report_continuously = True else: sim.time_limit = 0.0 # Don't save the [t_-, t_+] around events sim.store_event_points = False # Setup tolerances nr = self.args[0] sim.rtol = state_rtol sim.atol = state_atol + [1e-12] * nr if not self.console: sim.verbosity = 50 else: sim.verbosity = 40 # sim.report_continuously = False # Save the Assimulo interface return sim
def _setup_sim(self, **kwargs): """ Create a simulation interface to Assimulo using CVODE, given a problem definition """ # Create Assimulo interface sim = CVode(self.prob) sim.discr = 'BDF' sim.maxord = 5 # Setup some default arguments for the ODE solver, or override # if available. This is very hackish, but it's fine for now while # the number of anticipated tuning knobs is small. if 'maxh' in kwargs: sim.maxh = kwargs['maxh'] else: sim.maxh = np.min([0.1, self.output_dt]) if 'minh' in kwargs: sim.minh = kwargs['minh'] # else: sim.minh = 0.001 if "iter" in kwargs: sim.iter = kwargs['iter'] else: sim.iter = 'Newton' if "linear_solver" in kwargs: sim.linear_solver = kwargs['linear_solver'] if "max_steps" in kwargs: # DIFFERENT NAME!!!! sim.maxsteps = kwargs['max_steps'] else: sim.maxsteps = 1000 if "time_limit" in kwargs: sim.time_limit = kwargs['time_limit'] sim.report_continuously = True else: sim.time_limit = 0.0 # Don't save the [t_-, t_+] around events sim.store_event_points = False # Setup tolerances nr = self.args[0] sim.rtol = state_rtol sim.atol = state_atol + [1e-12]*nr if not self.console: sim.verbosity = 50 else: sim.verbosity = 40 # sim.report_continuously = False # Save the Assimulo interface return sim
def run_example(with_plots=True): def curl(v): return array([[0, v[2], -v[1]], [-v[2], 0, v[0]], [v[1], -v[0], 0]]) #Defines the rhs def f(t, u): """ Simulations for the Gyro (Heavy Top) example in Celledoni/Safstrom: Journal of Physics A, Vol 39, 5463-5478, 2006 """ I1 = 1000. I2 = 5000. I3 = 6000. u0 = [0, 0, 1.] pi = u[0:3] Q = (u[3:12]).reshape((3, 3)) Qu0 = dot(Q, u0) f = array([Qu0[1], -Qu0[0], 0.]) f = 0 omega = array([pi[0] / I1, pi[1] / I2, pi[2] / I3]) pid = dot(curl(omega), pi) + f Qd = dot(curl(omega), Q) return hstack([pid, Qd.reshape((9, ))]) def energi(state): energi = [] for st in state: Q = (st[3:12]).reshape((3, 3)) pi = st[0:3] u0 = [0, 0, 1.] Qu0 = dot(Q, u0) V = Qu0[2] # potential energy T = 0.5 * (pi[0]**2 / 1000. + pi[1]**2 / 5000. + pi[2]**2 / 6000.) energi.append([T]) return energi #Initial conditions y0 = hstack([[1000. * 10, 5000. * 10, 6000 * 10], eye(3).reshape((9, ))]) #Create an Assimulo explicit problem gyro_mod = Explicit_Problem(f, y0) #Create an Assimulo explicit solver (CVode) gyro_sim = CVode(gyro_mod) #Sets the parameters gyro_sim.discr = 'BDF' gyro_sim.iter = 'Newton' gyro_sim.maxord = 2 #Sets the maxorder gyro_sim.atol = 1.e-10 gyro_sim.rtol = 1.e-10 #Simulate t, y = gyro_sim.simulate(0.1) #Basic tests nose.tools.assert_almost_equal(y[-1][0], 692.800241862) nose.tools.assert_almost_equal(y[-1][8], 7.08468221e-1) #Plot if with_plots: P.plot(t, y) P.show()
def integration_assimulo(self, **kwargs): """ Perform time integration for ODEs with the assimulo package """ assert self.set_time_setting == 1, 'Time discretization must be specified first' if self.tclose > 0: close = True else: close = False # Control vector self.U = interpolate(self.boundary_cntrl_space, self.Vb).vector()[self.bndr_i_b] if self.discontinous_boundary_values == 1: self.U[self.Corner_indices] = self.U[self.Corner_indices]/2 # Definition of the sparse solver for the ODE rhs function to # be defined next #my_solver = factorized(csc_matrix(self.M)) my_solver = factorized(self.M) #my_jac_o = csr_matrix(my_solver(self.J @ self.Q)) #my_jac_c = csr_matrix(my_solver((self.J - self.R) @ self.Q)) # Definition of the rhs function required in assimulo def rhs(t,y): """ Definition of the rhs function required in the ODE part of assimulo """ if close: if t < self.tclose: z = self.my_mult(self.J, self.my_mult(self.Q,y)) + self.my_mult(self.Bext,self.U* self.boundary_cntrl_time(t,self.tclose)) else: z = self.my_mult((self.J - self.R), self.my_mult(self.Q,y)) else: z = self.my_mult(self.J, self.my_mult(self.Q,y)) + self.my_mult(self.Bext,self.U* self.boundary_cntrl_time(t,self.tclose)) return my_solver(z) def jacobian(t,y): """ Jacobian related to the ODE formulation """ if close: if t < self.tclose: my_jac = my_jac_o else: my_jac = my_jac_c else: my_jac = my_jac_o return my_jac def jacv(t,y,fy,v): """ Jacobian matrix-vector product related to the ODE formulation """ if close: if t < self.tclose: z = self.my_mult(self.J, self.my_mult(self.Q,v) ) else: z = self.my_mult((self.J - self.R), self.my_mult(self.Q,v)) else: z = self.my_mult(self.J, self.my_mult(self.Q,v)) return my_solver(z) print('ODE Integration using assimulo built-in functions:') # # https://jmodelica.org/assimulo/_modules/assimulo/examples/cvode_with_preconditioning.html#run_example # model = Explicit_Problem(rhs,self.A0,self.tinit) #model.jac = jacobian model.jacv = jacv sim = CVode(model,**kwargs) sim.atol = 1e-3 sim.rtol = 1e-3 sim.linear_solver = 'SPGMR' sim.maxord = 3 #sim.usejac = True #sim = RungeKutta34(model,**kwargs) time_span, ODE_solution = sim.simulate(self.tfinal) A_ode = ODE_solution.transpose() # Hamiltonian self.Nt = A_ode.shape[1] self.tspan = np.array(time_span) Ham_ode = np.zeros(self.Nt) for k in range(self.Nt): #Ham_ode[k] = 1/2 * A_ode[:,k] @ self.M @ self.Q @ A_ode[:,k] Ham_ode[k] = 1/2 * self.my_mult(A_ode[:,k].T, \ self.my_mult(self.M, self.my_mult(self.Q, A_ode[:,k]))) # Get q variables Aq_ode = A_ode[:self.Nq,:] # Get p variables Ap_ode = A_ode[self.Nq:,:] # Get Deformation Rho = np.zeros(self.Np) for i in range(self.Np): Rho[i] = self.rho(self.coord_p[i]) W_ode = np.zeros((self.Np,self.Nt)) theta = .5 for k in range(self.Nt-1): W_ode[:,k+1] = W_ode[:,k] + self.dt * 1/Rho[:] * ( theta * Ap_ode[:,k+1] + (1-theta) * Ap_ode[:,k] ) self.Ham_ode = Ham_ode return Aq_ode, Ap_ode, Ham_ode, W_ode, np.array(time_span)
def run_example(with_plots=True): def curl(v): return array([[0,v[2],-v[1]],[-v[2],0,v[0]],[v[1],-v[0],0]]) #Defines the rhs def f(t,u): """ Simulations for the Gyro (Heavy Top) example in Celledoni/Safstrom: Journal of Physics A, Vol 39, 5463-5478, 2006 """ I1=1000. I2=5000. I3=6000. u0=[0,0,1.] pi=u[0:3] Q=(u[3:12]).reshape((3,3)) Qu0=dot(Q,u0) f=array([Qu0[1],-Qu0[0],0.]) f=0 omega=array([pi[0]/I1,pi[1]/I2,pi[2]/I3]) pid=dot(curl(omega),pi)+f Qd=dot(curl(omega),Q) return hstack([pid,Qd.reshape((9,))]) def energi(state): energi=[] for st in state: Q=(st[3:12]).reshape((3,3)) pi=st[0:3] u0=[0,0,1.] Qu0=dot(Q,u0) V=Qu0[2] # potential energy T=0.5*(pi[0]**2/1000.+pi[1]**2/5000.+pi[2]**2/6000.) energi.append([T]) return energi #Initial conditions y0=hstack([[1000.*10,5000.*10,6000*10],eye(3).reshape((9,))]) #Create an Assimulo explicit problem gyro_mod = Explicit_Problem(f,y0) #Create an Assimulo explicit solver (CVode) gyro_sim=CVode(gyro_mod) #Sets the parameters gyro_sim.discr='BDF' gyro_sim.iter='Newton' gyro_sim.maxord=2 #Sets the maxorder gyro_sim.atol=1.e-10 gyro_sim.rtol=1.e-10 #Simulate t, y = gyro_sim.simulate(0.1) #Basic tests nose.tools.assert_almost_equal(y[-1][0],692.800241862) nose.tools.assert_almost_equal(y[-1][8],7.08468221e-1) #Plot if with_plots: P.plot(t,y) P.show()
def integration_assimulo(self, **kwargs): """ Perform time integration for ODEs with the assimulo package """ assert self.set_time_setting == 1, 'Time discretization must be specified first' if self.tclose > 0: close = True else: close = False # Control vector self.U = interpolate(self.boundary_cntrl_space, self.Vb).vector()[self.bndr_i_b] if self.discontinous_boundary_values == 1: self.U[self.Corner_indices] = self.U[self.Corner_indices]/2 # Definition of the sparse solver for the ODE rhs function to # be defined next my_solver = factorized(csc_matrix(self.Mp_rho_Cv)) C = self.A if self.sparse == 1: my_jac_o = csr_matrix(my_solver(C.toarray())) else: my_jac_o = my_solver(C) # Definition of the rhs function required in assimulo def rhs(t,y): """ Definition of the rhs function required in the ODE part of assimulo """ z = self.my_mult(self.A, y) + self.my_mult(self.Bext,self.U* self.boundary_cntrl_time(t,self.tclose)) return my_solver(z) #z = np.zeros(shape=y.shape[:]) #z[0:self.Np] = self.my_mult(self.Mp, yd[0:self.Np]) - self.my_mult(D, y[self.Np+self.Nq:self.Np+2*self.Nq]) #z[self.Np:self.Np+self.Nq] = self.my_mult(self.Mq, y[self.Np:self.Np+self.Nq]) + self.my_mult(D.T, y[0:self.Np]) - self.my_mult(self.Bp, self.U* self.boundary_cntrl_time(t,self.tclose)) #z[self.Np+self.Nq:self.Np+2*self.Nq] = self.my_mult(self.Mq, y[self.Np+self.Nq:self.Np+2*self.Nq]) - self.my_mult(self.L,y[self.Np:self.Np+self.Nq]) #return z def jacobian(t,y): """ Jacobian related to the ODE formulation """ my_jac = my_jac_o return my_jac def jacv(t,y,fy,v): """ Jacobian matrix-vector product related to the ODE formulation """ return None print('ODE Integration using assimulo built-in functions:') # # https://jmodelica.org/assimulo/_modules/assimulo/examples/cvode_with_preconditioning.html#run_example # model = Explicit_Problem(rhs,self.Tp0,self.tinit) sim = CVode(model,**kwargs) sim.atol = 1e-3 sim.rtol = 1e-3 sim.linear_solver = 'SPGMR' sim.maxord = 3 #sim.usejac = True #sim = RungeKutta34(model,**kwargs) time_span, ODE_solution = sim.simulate(self.tfinal) A_ode = ODE_solution.transpose() # Hamiltonian self.Nt = A_ode.shape[1] self.tspan = np.array(time_span) Ham_ode = np.zeros(self.Nt) for k in range(self.Nt): Ham_ode[k] = 1/2 * self.my_mult(A_ode[:,k].T, \ self.my_mult(self.Mp_rho_Cv, A_ode[:,k])) self.Ham_ode = Ham_ode return Ham_ode, np.array(time_span)