def simulate(self, Tend, nIntervals, gridWidth): problem = Explicit_Problem(self.rhs, self.y0) problem.name = 'CVode' # 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 simulation = CVode(problem) # Change multistep method: 'adams' or 'VDF' if self.discr == 'Adams': simulation.discr = 'Adams' simulation.maxord = 12 else: simulation.discr = 'BDF' simulation.maxord = 5 # Change iteration algorithm: functional(FixedPoint) or newton if self.iter == 'FixedPoint': simulation.iter = 'FixedPoint' else: simulation.iter = 'Newton' # Sets additional parameters 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 # '''Initialize problem ''' # self.t_cur = self.t0 # self.y_cur = self.y0 # 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 = simulation.simulate
def simulate(self, Tend, nIntervals, gridWidth): problem = Explicit_Problem(self.rhs, self.y0) problem.name = 'CVode' # 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 simulation = CVode(problem) # Change multistep method: 'adams' or 'VDF' if self.discr == 'Adams': simulation.discr = 'Adams' simulation.maxord = 12 else: simulation.discr = 'BDF' simulation.maxord = 5 # Change iteration algorithm: functional(FixedPoint) or newton if self.iter == 'FixedPoint': simulation.iter = 'FixedPoint' else: simulation.iter = 'Newton' # Sets additional parameters 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 # '''Initialize problem ''' # self.t_cur = self.t0 # self.y_cur = self.y0 # 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 = simulation.simulate
def simulate_ode(fun, y_initial, tf, opts): "function to run CVode solver on given problem" # get options ode_opts, ode_system_options = opts # iter, discretization_method, atol, rtol, time_points = ode_opts iter = ode_opts["iter"] discretization_method = ode_opts["discr"] atol = ode_opts["atol"] rtol = ode_opts["rtol"] time_points = ode_opts["time_points"] try: display_progress = ode_opts["display_progress"] except KeyError: display_progress = True try: verbosity = ode_opts["verbosity"] except KeyError: verbosity = 10 # define explicit assimulo problem prob = Explicit_Problem(lambda t, x: fun(t, x, ode_system_options), y0=y_initial) # create solver instance solver = CVode(prob) # set solver options solver.iter, solver.discr, solver.atol, solver.rtol, solver.display_progress, solver.verbosity = \ iter, discretization_method, atol, rtol, display_progress, verbosity # simulate system time_course, y_result = solver.simulate(tf, time_points) return time_course, y_result, prob, solver
def run_example(with_plots=True): r""" Demonstration of the use of CVode by solving the linear test equation :math:`\dot y = - y` on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ #Define the rhs def f(t, y): ydot = -y[0] return N.array([ydot]) #Define an Assimulo problem exp_mod = Explicit_Problem(f, y0=4, name=r'CVode Test Example: $\dot y = - y$') #Define an explicit solver exp_sim = CVode(exp_mod) #Create a CVode solver #Sets the parameters exp_sim.iter = 'Newton' #Default 'FixedPoint' exp_sim.discr = 'BDF' #Default 'Adams' exp_sim.atol = [1e-4] #Default 1e-6 exp_sim.rtol = 1e-4 #Default 1e-6 #Simulate t1, y1 = exp_sim.simulate(5, 100) #Simulate 5 seconds t2, y2 = exp_sim.simulate(7) #Simulate 2 seconds more #Plot if with_plots: import pylab as P P.plot(t1, y1, color="b") P.plot(t2, y2, color="r") P.title(exp_mod.name) P.ylabel('y') P.xlabel('Time') P.show() #Basic test nose.tools.assert_almost_equal(float(y2[-1]), 0.00347746, 5) nose.tools.assert_almost_equal(exp_sim.get_last_step(), 0.0222169642893, 3) return exp_mod, exp_sim
def run_example(with_plots=True): """ The same as example :doc:`EXAMPLE_cvode_basic` but now integrated backwards in time. on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ #Define the rhs def f(t, y): ydot = -y[0] return N.array([ydot]) #Define an Assimulo problem exp_mod = Explicit_Problem( f, t0=5, y0=0.02695, name=r'CVode Test Example (reverse time): $\dot y = - y$ ') #Define an explicit solver exp_sim = CVode(exp_mod) #Create a CVode solver #Sets the parameters exp_sim.iter = 'Newton' #Default 'FixedPoint' exp_sim.discr = 'BDF' #Default 'Adams' exp_sim.atol = [1e-8] #Default 1e-6 exp_sim.rtol = 1e-8 #Default 1e-6 exp_sim.backward = True #Simulate t, y = exp_sim.simulate(0) #Simulate 5 seconds (t0=5 -> tf=0) #print 'y(5) = {}, y(0) ={}'.format(y[0][0],y[-1][0]) #Basic test nose.tools.assert_almost_equal(float(y[-1]), 4.00000000, 3) #Plot if with_plots: P.plot(t, y, color="b") P.title(exp_mod.name) P.ylabel('y') P.xlabel('Time') P.show() return exp_mod, exp_sim
def make_explicit_sim(self): explicit_sim = CVode(self.explicit_problem) explicit_sim.iter = 'Newton' explicit_sim.discr = 'BDF' explicit_sim.rtol = 1e-7 explicit_sim.atol = 1e-7 explicit_sim.sensmethod = 'SIMULTANEOUS' explicit_sim.suppress_sens = True explicit_sim.report_continuously = False explicit_sim.usesens = False explicit_sim.verbosity = 50 if self.use_jac and self.model_jac is not None: explicit_sim.usejac = True else: explicit_sim.usejac = False return explicit_sim
def setUp(self): """ Configures the solver """ #Define an explicit solver simSolver = CVode(self) #Create a CVode solver #Sets the parameters #simSolver.verbosity = LOUD #simSolver.report_continuously = True simSolver.iter = 'Newton' #Default 'FixedPoint' simSolver.discr = 'BDF' #Default 'Adams' #simSolver.discr = 'Adams' simSolver.atol = [1e-6] #Default 1e-6 simSolver.rtol = 1e-6 #Default 1e-6 #simSolver.problem_info['step_events'] = True # activates step events #simSolver.maxh = 1.0 #simSolver.store_event_points = True self.simSolver = simSolver
def prepareSimulation(self, params = None): if params == None: params = AttributeDict({ 'absTol' : 1e-6, 'relTol' : 1e-6, }) #Define an explicit solver simSolver = CVode(self) #Create a CVode solver #Sets the parameters #simSolver.verbosity = LOUD simSolver.report_continuously = True simSolver.iter = 'Newton' #Default 'FixedPoint' simSolver.discr = 'BDF' #Default 'Adams' #simSolver.discr = 'Adams' simSolver.atol = [params.absTol] #Default 1e-6 simSolver.rtol = params.relTol #Default 1e-6 simSolver.problem_info['step_events'] = True # activates step events #simSolver.maxh = 1.0 simSolver.store_event_points = True self.simSolver = simSolver
def prepareSimulation(self, params=None): if params == None: params = AttributeDict({ 'absTol': 1e-6, 'relTol': 1e-6, }) #Define an explicit solver simSolver = CVode(self) #Create a CVode solver #Sets the parameters #simSolver.verbosity = LOUD simSolver.report_continuously = True simSolver.iter = 'Newton' #Default 'FixedPoint' simSolver.discr = 'BDF' #Default 'Adams' #simSolver.discr = 'Adams' simSolver.atol = [params.absTol] #Default 1e-6 simSolver.rtol = params.relTol #Default 1e-6 simSolver.problem_info['step_events'] = True # activates step events #simSolver.maxh = 1.0 simSolver.store_event_points = True self.simSolver = simSolver
def simulate(self, Tend, nIntervals, gridWidth): # define assimulo problem:(has to be done here because of the starting value in Explicit_Problem solver = Explicit_Problem(self.rhs, self.y0) ''' *******DELETE LATER ''''''''' # problem.handle_event = handle_event # problem.state_events = state_events # problem.init_mode = init_mode solver.handle_result = self.handle_result solver.name = 'Simple Explicit Example' simulation = CVode(solver) # Create a RungeKutta34 solver # simulation.inith = 0.1 #Sets the initial step, default = 0.01 # Change multistep method: 'adams' or 'VDF' if self.discr == 'Adams': simulation.discr = 'Adams' simulation.maxord = 12 else: simulation.discr = 'BDF' simulation.maxord = 5 # Change iteration algorithm: functional(FixedPoint) or newton if self.iter == 'FixedPoint': simulation.iter = 'FixedPoint' else: simulation.iter = 'Newton' # Sets additional parameters simulation.atol = self.atol simulation.rtol = self.rtol simulation.verbosity = 0 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 # Create Solver and set settings # noRootFunctions = np.size(self.state_events(self.t0, np.array(self.y0))) # solver = sundials.CVodeSolver(RHS = self.f, ROOT = self.rootf, SW = [False]*noRootFunctions, # abstol = self.atol, reltol = self.rtol) # solver.settings.JAC = None #Add user-dependent jacobian here '''Initialize problem ''' # solver.init(self.t0, self.y0) self.handle_result(self.t0, self.y0) nextTimeEvent = self.time_events(self.t0, self.y0) self.t_cur = self.t0 self.y_cur = self.y0 state_event = False # # if gridWidth <> None: nOutputIntervals = int((Tend - self.t0) / gridWidth) else: nOutputIntervals = nIntervals # Define step length depending on if gridWidth or nIntervals has been chosen if nOutputIntervals > 0: # Last point on grid (does not have to be Tend:) if(gridWidth <> None): dOutput = gridWidth else: dOutput = (Tend - self.t0) / nIntervals else: dOutput = Tend outputStepCounter = long(1) nextOutputPoint = min(self.t0 + dOutput, Tend) while self.t_cur < Tend: # Time-Event detection and step time adjustment if nextTimeEvent is None or nextOutputPoint < nextTimeEvent: time_event = False self.t_cur = nextOutputPoint else: time_event = True self.t_cur = nextTimeEvent try: # #Integrator step # self.y_cur = solver.step(self.t_cur) # self.y_cur = np.array(self.y_cur) # state_event = False # Simulate # take a step to next output point: t_new, y_new = simulation.simulate(self.t_cur) # 5, 10) #5, 10 self.t_cur self.t_cur 2. argument nsteps Simulate 5 seconds # t_new, y_new are both vectors of the time and states at t_cur and all intermediate # points before it! So take last values: self.t_cur = t_new[-1] self.y_cur = y_new[-1] state_event = False except: import sys print "Unexpected error:", sys.exc_info()[0] # except CVodeRootException, info: # self.t_cur = info.t # self.y_cur = info.y # self.y_cur = np.array(self.y_cur) # time_event = False # state_event = True # # # Depending on events have been detected do different tasks if time_event or state_event: event_info = [state_event, time_event] if not self.handle_event(self, event_info): break solver.init(self.t_cur, self.y_cur) nextTimeEvent = self.time_events(self.t_cur, self.y_cur) # If no timeEvent happens: if nextTimeEvent <= self.t_cur: nextTimeEvent = None if self.t_cur == nextOutputPoint: # Write output if not happened before: if not time_event and not state_event: self.handle_result(nextOutputPoint, self.y_cur) outputStepCounter += 1 nextOutputPoint = min(self.t0 + outputStepCounter * dOutput, Tend) self.finalize()
switches0 = [True] #Initial switches #Create an Assimulo Problem mod = Explicit_Problem(pendulum, y0, t0, sw0=switches0) mod.state_events = state_events #Sets the state events to the problem mod.handle_event = handle_event #Sets the event handling to the problem mod.name = 'Pendulum with events' #Sets the name of the problem #Create an Assimulo solver (CVode) sim = CVode(mod) #Specifies options sim.discr = 'Adams' #Sets the discretization method sim.iter = 'FixedPoint' #Sets the iteration method sim.rtol = 1.e-8 #Sets the relative tolerance sim.atol = 1.e-6 #Sets the absolute tolerance #Simulation ncp = 200 #Number of communication points tfinal = 10.0 #Final time t, y = sim.simulate(tfinal, ncp) #Simulate #Plots the result P.plot(t,y)
gamma = p[3] flux = np.array( [alpha * y[0], beta * y[0] * y[1], delta * y[0] * y[1], gamma * y[1]]) rhs = np.array([flux[0] - flux[1], flux[2] - flux[3]]) return rhs if __name__ == '__main__': p = np.array([.5, .02, .4, .004]) ode_function = lambda t, x: rhs_fun(t, x, p) # define explicit assimulo problem prob = Explicit_Problem(ode_function, y0=np.array([10, .0001])) # create solver instance solver = CVode(prob) solver.iter = 'Newton' solver.discr = 'Adams' solver.atol = 1e-10 solver.rtol = 1e-10 solver.display_progress = True solver.verbosity = 10 # simulate system time_course, y_result = solver.simulate(10, 200) print time_course print y_result
def run_example(with_plots=True): """ Simulations for the Gyro (Heavy Top) example in Celledoni/Safstrom: Journal of Physics A, Vol 39, 5463-5478, 2006 on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ 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 exp_mod = Explicit_Problem(f, y0, name="Gyroscope Example") #Create an Assimulo explicit solver (CVode) exp_sim = CVode(exp_mod) #Sets the parameters exp_sim.discr = 'BDF' exp_sim.iter = 'Newton' exp_sim.maxord = 2 #Sets the maxorder exp_sim.atol = 1.e-10 exp_sim.rtol = 1.e-10 #Simulate t, y = exp_sim.simulate(0.1) #Plot if with_plots: import pylab as P P.plot(t, y / 10000.) P.xlabel('Time') P.ylabel('States, scaled by $10^4$') P.title(exp_mod.name) P.show() #Basic tests nose.tools.assert_almost_equal(y[-1][0], 692.800241862) nose.tools.assert_almost_equal(y[-1][8], 7.08468221e-1) return exp_mod, exp_sim
def run_example(with_plots=True): """ This is the same example from the Sundials package (cvsRoberts_FSA_dns.c) This simple example problem for CVode, due to Robertson, is from chemical kinetics, and consists of the following three equations: .. math:: \dot y_1 &= -p_1 y_1 + p_2 y_2 y_3 \\ \dot y_2 &= p_1 y_1 - p_2 y_2 y_3 - p_3 y_2^2 \\ \dot y_3 &= p_3 y_2^2 on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ def f(t, y, p): p3 = 3.0e7 yd_0 = -p[0] * y[0] + p[1] * y[1] * y[2] yd_1 = p[0] * y[0] - p[1] * y[1] * y[2] - p3 * y[1]**2 yd_2 = p3 * y[1]**2 return N.array([yd_0, yd_1, yd_2]) #The initial conditions y0 = [1.0, 0.0, 0.0] #Initial conditions for y #Create an Assimulo explicit problem exp_mod = Explicit_Problem(f, y0, name='Sundials test example: Chemical kinetics') #Sets the options to the problem exp_mod.p0 = [0.040, 1.0e4] #Initial conditions for parameters exp_mod.pbar = [0.040, 1.0e4] #Create an Assimulo explicit solver (CVode) exp_sim = CVode(exp_mod) #Sets the paramters exp_sim.iter = 'Newton' exp_sim.discr = 'BDF' exp_sim.rtol = 1.e-4 exp_sim.atol = N.array([1.0e-8, 1.0e-14, 1.0e-6]) exp_sim.sensmethod = 'SIMULTANEOUS' #Defines the sensitvity method used exp_sim.suppress_sens = False #Dont suppress the sensitivity variables in the error test. exp_sim.report_continuously = True #Simulate t, y = exp_sim.simulate( 4, 400) #Simulate 4 seconds with 400 communication points #Plot if with_plots: import pylab as P P.plot(t, y) P.xlabel('Time') P.ylabel('State') P.title(exp_mod.name) P.show() #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( exp_sim.p_sol[0][-1][0], -1.8761, 2) #Values taken from the example in Sundials nose.tools.assert_almost_equal(exp_sim.p_sol[1][-1][0], 2.9614e-06, 8) return exp_mod, exp_sim
def run_example(with_plots=True): r""" Example for demonstrating the use of a user supplied Jacobian (sparse). Note that this will only work if Assimulo has been configured with Sundials + SuperLU. Based on the SUNDIALS example cvRoberts_sps.c ODE: .. math:: \dot y_1 &= -0.04y_1 + 1e4 y_2 y_3 \\ \dot y_2 &= - \dot y_1 - \dot y_3 \\ \dot y_3 &= 3e7 y_2^2 on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ #Defines the rhs def f(t, y): yd_0 = -0.04 * y[0] + 1e4 * y[1] * y[2] yd_2 = 3e7 * y[1] * y[1] yd_1 = -yd_0 - yd_2 return N.array([yd_0, yd_1, yd_2]) #Defines the Jacobian def jac(t, y): colptrs = [0, 3, 6, 9] rowvals = [0, 1, 2, 0, 1, 2, 0, 1, 2] data = [ -0.04, 0.04, 0.0, 1e4 * y[2], -1e4 * y[2] - 6e7 * y[1], 6e7 * y[1], 1e4 * y[1], -1e4 * y[1], 0.0 ] J = SP.csc_matrix((data, rowvals, colptrs)) return J #Defines an Assimulo explicit problem y0 = [1.0, 0.0, 0.0] #Initial conditions exp_mod = Explicit_Problem(f, y0, name='Example using analytic (sparse) Jacobian') exp_mod.jac = jac #Sets the Jacobian exp_mod.jac_nnz = 9 exp_sim = CVode(exp_mod) #Create a CVode solver #Set the parameters exp_sim.iter = 'Newton' #Default 'FixedPoint' exp_sim.discr = 'BDF' #Default 'Adams' exp_sim.atol = [1e-8, 1e-14, 1e-6] #Default 1e-6 exp_sim.rtol = 1e-4 #Default 1e-6 exp_sim.linear_solver = "sparse" #Simulate t, y = exp_sim.simulate(0.4) #Simulate 0.4 seconds #Basic tests nose.tools.assert_almost_equal(y[-1][0], 0.9851, 3) #Plot if with_plots: P.plot(t, y[:, 1], linestyle="dashed", marker="o") #Plot the solution P.xlabel('Time') P.ylabel('State') P.title(exp_mod.name) P.show() return exp_mod, exp_sim
### Mesh N = 60 X = 165e-6 # [m] ### Initial conditions c_init = 1000.0 # [mol/m^3] c_centered = c_init*numpy.ones( N, dtype='d' ) exp_mod = MyProblem( N, X, c_centered, 'ce only model, explicit CVode' ) #exp_mod = MyProblem( N, X, numpy.linspace(c_init-c_init/5.,c_init+c_init/5.,N), 'ce only model, explicit CVode' ) # Set the ODE solver exp_sim = CVode(exp_mod) #Create a CVode solver #Set the parameters exp_sim.iter = 'Newton' #Default 'FixedPoint' exp_sim.discr = 'BDF' #Default 'Adams' exp_sim.atol = 1e-5 #Default 1e-6 exp_sim.rtol = 1e-5 #Default 1e-6 #Simulate exp_mod.set_j_vec( 1.e-4 ) t1, y1 = exp_sim.simulate(100, 100) exp_mod.set_j_vec( 0.0 ) t2, y2 = exp_sim.simulate(200, 100) #exp_mod.set_j_vec( 0.0 ) #t3, y3 = exp_sim.simulate(10000, 200) #Plot
def run_example(with_plots=True): r""" Example for demonstrating the use of a user supplied Jacobian ODE: .. math:: \dot y_1 &= y_2 \\ \dot y_2 &= -9.82 on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ #Defines the rhs def f(t, y): yd_0 = y[1] yd_1 = -9.82 return N.array([yd_0, yd_1]) #Defines the Jacobian def jac(t, y): j = N.array([[0, 1.], [0, 0]]) return j #Defines an Assimulo explicit problem y0 = [1.0, 0.0] #Initial conditions exp_mod = Explicit_Problem(f, y0, name='Example using analytic Jacobian') exp_mod.jac = jac #Sets the Jacobian exp_sim = CVode(exp_mod) #Create a CVode solver #Set the parameters exp_sim.iter = 'Newton' #Default 'FixedPoint' exp_sim.discr = 'BDF' #Default 'Adams' exp_sim.atol = 1e-5 #Default 1e-6 exp_sim.rtol = 1e-5 #Default 1e-6 #Simulate t, y = exp_sim.simulate( 5, 1000) #Simulate 5 seconds with 1000 communication points #Plot if with_plots: import pylab as P P.plot(t, y, linestyle="dashed", marker="o") #Plot the solution P.xlabel('Time') P.ylabel('State') P.title(exp_mod.name) P.show() #Basic tests nose.tools.assert_almost_equal(y[-1][0], -121.75000000, 4) nose.tools.assert_almost_equal(y[-1][1], -49.100000000) return exp_mod, exp_sim
def run_example(with_plots=True): r""" Example to demonstrate the use of a preconditioner .. math:: \dot y_1 & = 2 t \sin y_1 + t \sin y_2 \\ \dot y_2 & = 3 t \sin y_1 + 2 t \sin y_2 on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ #Define the rhs def rhs(t, y): A = np.array([[2.0, 1.0], [3.0, 2.0]]) yd = np.dot(A * t, np.sin(y)) return yd #Define the preconditioner setup function def prec_setup(t, y, fy, jok, gamma, data): A = np.array([[2.0, 1.0], [3.0, 2.0]]) #If jok is false the jacobian data needs to be recomputed if jok == False: #Extract the diagonal of the jacobian to form a Jacobi preconditioner a0 = A[0, 0] * t * np.cos(y[0]) a1 = A[1, 1] * t * np.cos(y[1]) a = np.array([(1. - gamma * a0), (1. - gamma * a1)]) #Return true (jacobian data was recomputed) and the new data return [True, a] #If jok is true the existing jacobian data can be reused if jok == True: #Return false (jacobian data was reused) and the old data return [False, data] #Define the preconditioner solve function def prec_solve(t, y, fy, r, gamma, delta, data): #Solve the system Pz = r z0 = r[0] / data[0] z1 = r[1] / data[1] z = np.array([z0, z1]) return z #Initial conditions y0 = [1.0, 2.0] #Define an Assimulo problem exp_mod = Explicit_Problem( rhs, y0, name="Example of using a preconditioner in SUNDIALS") #Set the preconditioner setup and solve function for the problem exp_mod.prec_setup = prec_setup exp_mod.prec_solve = prec_solve #Create a CVode solver exp_sim = CVode(exp_mod) #Set the parameters for the solver exp_sim.iter = 'Newton' exp_sim.discr = 'BDF' exp_sim.atol = 1e-5 exp_sim.rtol = 1e-5 exp_sim.linear_solver = 'SPGMR' exp_sim.precond = "PREC_RIGHT" #Set the desired type of preconditioning #Simulate t, y = exp_sim.simulate(5) if with_plots: exp_sim.plot() #Basic verification nose.tools.assert_almost_equal(y[-1, 0], 3.11178295, 4) nose.tools.assert_almost_equal(y[-1, 1], 3.19318992, 4) return exp_mod, exp_sim
def run_example(with_plots=True): r""" An example for CVode with scaled preconditioned GMRES method as a special linear solver. Note, how the operation Jacobian times vector is provided. ODE: .. math:: \dot y_1 &= y_2 \\ \dot y_2 &= -9.82 on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ #Defines the rhs def f(t, y): yd_0 = y[1] yd_1 = -9.82 return N.array([yd_0, yd_1]) #Defines the Jacobian*vector product def jacv(t, y, fy, v): j = N.array([[0, 1.], [0, 0]]) return N.dot(j, v) y0 = [1.0, 0.0] #Initial conditions #Defines an Assimulo explicit problem exp_mod = Explicit_Problem( f, y0, name='Example using the Jacobian Vector product') exp_mod.jacv = jacv #Sets the Jacobian exp_sim = CVode(exp_mod) #Create a CVode solver #Set the parameters exp_sim.iter = 'Newton' #Default 'FixedPoint' exp_sim.discr = 'BDF' #Default 'Adams' exp_sim.atol = 1e-5 #Default 1e-6 exp_sim.rtol = 1e-5 #Default 1e-6 exp_sim.linear_solver = 'SPGMR' #Change linear solver #exp_sim.options["usejac"] = False #Simulate t, y = exp_sim.simulate( 5, 1000) #Simulate 5 seconds with 1000 communication points #Basic tests nose.tools.assert_almost_equal(y[-1][0], -121.75000000, 4) nose.tools.assert_almost_equal(y[-1][1], -49.100000000) #Plot if with_plots: P.plot(t, y) P.xlabel('Time') P.ylabel('State') P.title(exp_mod.name) P.show() return exp_mod, exp_sim
def run_sim_ice(Y, YLIQ): def dy_dt_func(t, Y): dy_dt = np.zeros(len(Y)) svp = f.svp_liq(Y[ITEMP]) svp_ice = f.svp_ice(Y[ITEMP]) # vapour mixing ratio WV = c.eps * Y[IRH_ICE] * svp / (Y[IPRESS_ICE] - svp) # liquid mixing ratio WL = sum(YLIQ[IND1:IND2] * YLIQ[0:IND1]) # ice mixing ratio WI = sum(Y[IND1:IND2] * Y[0:IND1]) Cpm = c.CP + WV * c.CPV + WL * c.CPW + WI * c.CPI # RH with respect to ice RH_ICE = WV / (c.eps * svp_ice / (Y[IPRESS_ICE] - svp_ice)) # ------------------------- growth rate of ice -------------------------- RH_EQ = 1e0 # from ACPIM, FPARCELCOLD - MICROPHYSICS.f90 CAP = f.CAPACITANCE01(Y[0:IND1], np.exp(Y[IND2:IND3])) growth_rate = f.ICEGROWTHRATE(Y[ITEMP_ICE], Y[IPRESS_ICE], RH_ICE, RH_EQ, Y[0:IND1], np.exp(Y[IND2:IND3]), CAP) growth_rate[np.isnan(growth_rate)] = 0 # get rid of nans growth_rate = np.where(Y[IND1:IND2] < 1e-6, 0.0, growth_rate) # Mass of water condensing dy_dt[:IND1] = growth_rate #---------------------------aspect ratio--------------------------------------- DELTA_RHO = c.eps * svp / (Y[IPRESS_ICE] - svp) DELTA_RHOI = c.eps * svp_ice / (Y[IPRESS_ICE] - svp_ice) DELTA_RHO = Y[IRH_ICE] * DELTA_RHO - DELTA_RHOI DELTA_RHO = DELTA_RHO * Y[IPRESS_ICE] / Y[ITEMP_ICE] / c.RA RHO_DEP = f.DEP_DENSITY(DELTA_RHO, Y[ITEMP_ICE]) # this is the rate of change of LOG of the aspect ratio dy_dt[IND2:IND3] = (dy_dt[0:IND1] * ((f.INHERENTGROWTH(Y[ITEMP_ICE]) - 1) / (f.INHERENTGROWTH(Y[ITEMP_ICE]) + 2)) / (Y[0:IND1] * c.rhoi * RHO_DEP)) #------------------------------------------------------------------------------ # Change in vapour content dwv_dt = -1 * sum(Y[IND1:IND2] * dy_dt[0:IND1]) # change in water vapour mixing ratio DRI = -1 * dwv_dt dy_dt[ITEMP_ICE] = 0.0 #+c.LS/Cpm*DRI # if n.Simulation_type.lower() == 'parcel': # dy_dt[ITEMP_ICE]=dy_dt[ITEMP_ICE] + c.LS/Cpm*DRI #---------------------------RH change------------------------------------------ dy_dt[IRH_ICE] = (Y[IPRESS_ICE] - svp) * svp * dwv_dt dy_dt[IRH_ICE] = ( dy_dt[IRH_ICE] - WV * Y[IPRESS_ICE] * derivative(f.svp_liq, Y[ITEMP_ICE], dx=1.0) * dy_dt[ITEMP_ICE]) dy_dt[IRH_ICE] = dy_dt[IRH_ICE] / (c.eps * svp**2) #------------------------------------------------------------------------------ return dy_dt #--------------------- SET-UP solver -------------------------------------- y0 = Y t0 = 0.0 #define assimulo problem exp_mod = Explicit_Problem(dy_dt_func, y0, t0) # define an explicit solver exp_sim = CVode(exp_mod) exp_sim.iter = 'Newton' exp_sim.discr = 'BDF' # set tolerance for each dydt function tol_list = np.zeros_like(Y) tol_list[0:IND1] = 1e-30 # mass tol_list[IND1:IND2] = 10 # number tol_list[IND2:IND3] = 1e-30 # aspect ratio # tol_list[IND3:IRH_SV_ICE] = 1e-26 #tol_list[IRH_SV_ICE] = 1e-26 tol_list[IPRESS_ICE] = 10 tol_list[ITEMP_ICE] = 1e-4 tol_list[IRH_ICE] = 1e-8 exp_sim.atol = tol_list exp_sim.rtol = 1.0e-8 exp_sim.inith = 1.0e-2 # initial time step-size exp_sim.usejac = False exp_sim.maxncf = 100 # max number of convergence failures allowed by solver exp_sim.verbosity = 40 t_output, y_output = exp_sim.simulate(1) return y_output[-1, :]
def run_example(with_plots=True): r""" This example shows how to use Assimulo and CVode for simulating sensitivities for initial conditions. .. math:: \dot y_1 &= -(k_{01}+k_{21}+k_{31}) y_1 + k_{12} y_2 + k_{13} y_3 + b_1\\ \dot y_2 &= k_{21} y_1 - (k_{02}+k_{12}) y_2 \\ \dot y_3 &= k_{31} y_1 - k_{13} y_3 with the parameter dependent inital conditions :math:`y_1(0) = 0, y_2(0) = 0, y_3(0) = 0` . The initial values are taken as parameters :math:`p_1,p_2,p_3` for the computation of the sensitivity matrix, see http://sundials.2283335.n4.nabble.com/Forward-sensitivities-for-initial-conditions-td3239724.html on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ def f(t, y, p): y1, y2, y3 = y k01 = 0.0211 k02 = 0.0162 k21 = 0.0111 k12 = 0.0124 k31 = 0.0039 k13 = 0.000035 b1 = 49.3 yd_0 = -(k01 + k21 + k31) * y1 + k12 * y2 + k13 * y3 + b1 yd_1 = k21 * y1 - (k02 + k12) * y2 yd_2 = k31 * y1 - k13 * y3 return N.array([yd_0, yd_1, yd_2]) #The initial conditions y0 = [0.0, 0.0, 0.0] #Initial conditions for y p0 = [0.0, 0.0, 0.0] #Initial conditions for parameters yS0 = N.array([[1, 0, 0], [0, 1, 0], [0, 0, 1.]]) #Create an Assimulo explicit problem exp_mod = Explicit_Problem(f, y0, p0=p0, name='Example: Computing Sensitivities') #Sets the options to the problem exp_mod.yS0 = yS0 #Create an Assimulo explicit solver (CVode) exp_sim = CVode(exp_mod) #Sets the paramters exp_sim.iter = 'Newton' exp_sim.discr = 'BDF' exp_sim.rtol = 1e-7 exp_sim.atol = 1e-6 exp_sim.pbar = [ 1, 1, 1 ] #pbar is used to estimate the tolerances for the parameters exp_sim.report_continuously = True #Need to be able to store the result using the interpolate methods exp_sim.sensmethod = 'SIMULTANEOUS' #Defines the sensitvity method used exp_sim.suppress_sens = False #Dont suppress the sensitivity variables in the error test. #Simulate t, y = exp_sim.simulate(400) #Simulate 400 seconds #Basic test nose.tools.assert_almost_equal(y[-1][0], 1577.6552477, 5) nose.tools.assert_almost_equal(y[-1][1], 611.9574565, 5) nose.tools.assert_almost_equal(y[-1][2], 2215.88563217, 5) nose.tools.assert_almost_equal(exp_sim.p_sol[0][1][0], 1.0) #Plot if with_plots: title_text = r"Sensitivity w.r.t. ${}$" legend_text = r"$\mathrm{{d}}{}/\mathrm{{d}}{}$" P.figure(1) P.subplot(221) P.plot(t, N.array(exp_sim.p_sol[0])[:, 0], t, N.array(exp_sim.p_sol[0])[:, 1], t, N.array(exp_sim.p_sol[0])[:, 2]) P.title(title_text.format('p_1')) P.legend((legend_text.format('y_1', 'p_1'), legend_text.format('y_1', 'p_2'), legend_text.format('y_1', 'p_3'))) P.subplot(222) P.plot(t, N.array(exp_sim.p_sol[1])[:, 0], t, N.array(exp_sim.p_sol[1])[:, 1], t, N.array(exp_sim.p_sol[1])[:, 2]) P.title(title_text.format('p_2')) P.legend((legend_text.format('y_2', 'p_1'), legend_text.format('y_2', 'p_2'), legend_text.format('y_2', 'p_3'))) P.subplot(223) P.plot(t, N.array(exp_sim.p_sol[2])[:, 0], t, N.array(exp_sim.p_sol[2])[:, 1], t, N.array(exp_sim.p_sol[2])[:, 2]) P.title(title_text.format('p_3')) P.legend((legend_text.format('y_3', 'p_1'), legend_text.format('y_3', 'p_2'), legend_text.format('y_3', 'p_3'))) P.subplot(224) P.title('ODE Solution') P.plot(t, y) P.suptitle(exp_mod.name) P.show() return exp_mod, exp_sim
def run_sim(Y, time, Y_AER1, YICE): def dy_dt_func(t, Y): dy_dt = np.zeros(len(Y)) # add condensed semi-vol mass into bins if n.SV_flag: MBIN2[-1 * n.n_sv:, :] = np.reshape(Y[INDSV1:INDSV2], [n.n_sv, nbins * nmodes]) # calculate saturation vapour pressure over liquid svp1 = f.svp_liq(Y[ITEMP]) # saturation ratio SL = svp1 * Y[IRH] / (Y[IPRESS] - svp1) SL = (SL * Y[IPRESS] / (1 + SL)) / svp1 # water vapour mixing ratio WV = c.eps * Y[IRH] * svp1 / (Y[IPRESS] - svp1) WL = np.sum(Y[IND1:IND2] * Y[:IND1]) # LIQUID MIXING RATIO WI = np.sum(YICE[IND1:IND2] * YICE[:IND1]) # ice mixing ratio RM = c.RA + WV * c.RV CPM = c.CP + WV * c.CPV + WL * c.CPW + WI * c.CPI if simulation_type.lower() == 'chamber': # CHAMBER MODEL - pressure change dy_dt[IPRESS] = -100 * PRESS1 * PRESS2 * np.exp(-PRESS2 * (time + t)) elif simulation_type.lower() == 'parcel': # adiabatic parcel dy_dt[IPRESS] = -Y[IPRESS] / RM / Y[ ITEMP] * c.g * w #! HYDROSTATIC EQUATION else: print('simulation type unknown') return # ----------------------------change in vapour content: ----------------------- # 1. equilibruim size of particles if n.kappa_flag: #if n.SV_flag: # need to recalc kappa taking into acount the condensed semi-vols Kappa = np.sum( (MBIN2[:, :] / RHOBIN2[:, :]) * KAPPABIN2[:, :], axis=0) / np.sum(MBIN2[:, :] / RHOBIN2[:, :], axis=0) # print(Kappa) # print(MBIN2/RHOBIN2) KK01 = f.kk01(Y[0:IND1], Y[ITEMP], MBIN2, RHOBIN2, Kappa) else: KK01 = f.K01(Y[0:IND1], Y[ITEMP], MBIN2, n.n_sv, RHOBIN2, NUBIN2, MOLWBIN2) # print(KK01[0]) Dw = KK01[2] # wet diameter RHOAT = KK01[1] # density of particles inc water and aerosol mass RH_EQ = KK01[0] # equilibrium RH # print(MBIN2/MOLWBIN2) # 2. growth rate of particles, Jacobson p455 # rate of change of radius growth_rate = f.DROPGROWTHRATE(Y[ITEMP], Y[IPRESS], SL, RH_EQ, RHOAT, Dw) growth_rate[np.isnan(growth_rate)] = 0 # get rid of nans growth_rate = np.where(Y[IND1:IND2] < 1e-9, 0.0, growth_rate) # 3. Mass of water condensing # change in mass of water per particle dy_dt[:IND1] = (np.pi * RHOAT * Dw**2) * growth_rate # 4. Change in vapour content # change in water vapour mixing ratio dwv_dt = -1 * np.sum( Y[IND1:IND2] * dy_dt[:IND1]) # change to np.sum for speed # mass # ----------------------------------------------------------------------------- if simulation_type.lower() == 'chamber': # CHAMBER MODEL - temperature change dy_dt[ITEMP] = -Temp1 * Temp2 * np.exp(-Temp2 * (time + t)) elif simulation_type.lower() == 'parcel': # adiabatic parcel dy_dt[ITEMP] = RM / Y[IPRESS] * dy_dt[IPRESS] * Y[ ITEMP] / CPM # TEMPERATURE CHANGE: EXPANSION dy_dt[ITEMP] = dy_dt[ITEMP] - c.LV / CPM * dwv_dt else: print('simulation type unknown') return # --------------------------------RH change------------------------------------ dy_dt[IRH] = svp1 * dwv_dt * (Y[IPRESS] - svp1) dy_dt[IRH] = dy_dt[IRH] + svp1 * WV * dy_dt[IPRESS] dy_dt[IRH] = ( dy_dt[IRH] - WV * Y[IPRESS] * derivative(f.svp_liq, Y[ITEMP], dx=1.0) * dy_dt[ITEMP]) dy_dt[IRH] = dy_dt[IRH] / (c.eps * svp1**2) # ----------------------------------------------------------------------------- # ------------------------------ SEMI-VOLATILES ------------------------------- if n.SV_flag: # SV_mass = np.reshape(Y[INDSV1:INDSV2],[n.n_sv,n.nmodes*n.nbins]) # SV_mass = np.where(SV_mass == 0.0,1e-30,SV_mass) # MBIN2[n.n_sv*-1:,:] = SV_mass RH_EQ_SV = f.K01SV(Y[:IND1], Y[ITEMP], MBIN2, n.n_sv, RHOBIN2, NUBIN2, MOLWBIN2) RH_EQ = RH_EQ_SV[0] RHOAT = RH_EQ_SV[1] DW = RH_EQ_SV[2] SVP_ORG = f.SVP_GASES(n.semi_vols, Y[ITEMP], n.n_sv) #C-C equation #RH_ORG = [x*Y[IPRESS]/c.RA/Y[ITEMP] for x in Y[IRH_SV]] RH_ORG = [x for x in Y[IRH_SV]] RH_ORG = [(x / c.aerosol_dict[key][0]) * c.R * Y[ITEMP] for x, key in zip(RH_ORG, n.semi_vols[:n.n_sv]) ] # just for n_sv keys in dictionary RH_ORG = [RH_ORG[x] / SVP_ORG[x] for x in range(n.n_sv)] dy_dt[INDSV1:INDSV2] = f.SVGROWTHRATE(Y[ITEMP], Y[IPRESS], SVP_ORG, RH_ORG, RH_EQ, DW, n.n_sv, n.nbins, n.nmodes, MOLWBIN2) dy_dt[IRH_SV] = -np.sum(np.reshape( dy_dt[INDSV1:INDSV2], [n.n_sv, IND1]) * Y[IND1:IND2], axis=1) #see line 137 return dy_dt #--------------------- SET-UP solver ------------------------------------------ y0 = Y t0 = 0.0 #define assimulo problem exp_mod = Explicit_Problem(dy_dt_func, y0, t0) # define an explicit solver exp_sim = CVode(exp_mod) exp_sim.iter = 'Newton' exp_sim.discr = 'BDF' #set parameters tol_list = np.zeros_like(Y) tol_list[0:IND1] = 1e-40 # this is now different to ACPIM (1e-25) tol_list[IND1:IND2] = 10 # number tol_list[IND2:IND3] = 1e-30 # capacitance tol_list[IND3:INDSV2] = 1e-26 #condendensed semi-vol mass tol_list[IRH_SV] = 1e-26 # RH of each semi-vol compound tol_list[IPRESS] = 10 tol_list[ITEMP] = 1e-4 tol_list[IRH] = 1e-8 # set tolerance for each dydt function exp_sim.atol = tol_list exp_sim.rtol = 1.0e-8 exp_sim.inith = 0 # initial time step-size exp_sim.usejac = False exp_sim.maxncf = 100 # max number of convergence failures allowed by solver exp_sim.verbosity = 40 t_output, y_output = exp_sim.simulate(1) return y_output[-1, :], t_output[:]
def run_example(with_plots=True): r""" This is the same example from the Sundials package (cvsRoberts_FSA_dns.c) Its purpose is to demonstrate the use of parameters in the differential equation. This simple example problem for CVode, due to Robertson see http://www.dm.uniba.it/~testset/problems/rober.php, is from chemical kinetics, and consists of the system: .. math:: \dot y_1 &= -p_1 y_1 + p_2 y_2 y_3 \\ \dot y_2 &= p_1 y_1 - p_2 y_2 y_3 - p_3 y_2^2 \\ \dot y_3 &= p_3 y_ 2^2 on return: - :dfn:`exp_mod` problem instance - :dfn:`exp_sim` solver instance """ def f(t, y, p): yd_0 = -p[0]*y[0]+p[1]*y[1]*y[2] yd_1 = p[0]*y[0]-p[1]*y[1]*y[2]-p[2]*y[1]**2 yd_2 = p[2]*y[1]**2 return N.array([yd_0,yd_1,yd_2]) def jac(t,y, p): J = N.array([[-p[0], p[1]*y[2], p[1]*y[1]], [p[0], -p[1]*y[2]-2*p[2]*y[1], -p[1]*y[1]], [0.0, 2*p[2]*y[1],0.0]]) return J def fsens(t, y, s, p): J = N.array([[-p[0], p[1]*y[2], p[1]*y[1]], [p[0], -p[1]*y[2]-2*p[2]*y[1], -p[1]*y[1]], [0.0, 2*p[2]*y[1],0.0]]) P = N.array([[-y[0],y[1]*y[2],0], [y[0], -y[1]*y[2], -y[1]**2], [0,0,y[1]**2]]) return J.dot(s)+P #The initial conditions y0 = [1.0,0.0,0.0] #Initial conditions for y #Create an Assimulo explicit problem exp_mod = Explicit_Problem(f,y0, name='Robertson Chemical Kinetics Example') exp_mod.rhs_sens = fsens exp_mod.jac = jac #Sets the options to the problem exp_mod.p0 = [0.040, 1.0e4, 3.0e7] #Initial conditions for parameters exp_mod.pbar = [0.040, 1.0e4, 3.0e7] #Create an Assimulo explicit solver (CVode) exp_sim = CVode(exp_mod) #Sets the solver paramters exp_sim.iter = 'Newton' exp_sim.discr = 'BDF' exp_sim.rtol = 1.e-4 exp_sim.atol = N.array([1.0e-8, 1.0e-14, 1.0e-6]) exp_sim.sensmethod = 'SIMULTANEOUS' #Defines the sensitvity method used exp_sim.suppress_sens = False #Dont suppress the sensitivity variables in the error test. exp_sim.report_continuously = True #Simulate t, y = exp_sim.simulate(4,400) #Simulate 4 seconds with 400 communication points #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(exp_sim.p_sol[0][-1][0], -1.8761, 2) #Values taken from the example in Sundials nose.tools.assert_almost_equal(exp_sim.p_sol[1][-1][0], 2.9614e-06, 8) nose.tools.assert_almost_equal(exp_sim.p_sol[2][-1][0], -4.9334e-10, 12) #Plot if with_plots: P.plot(t, y) P.title(exp_mod.name) P.xlabel('Time') P.ylabel('State') P.show() return exp_mod, exp_sim
def stiff_ode_solver(matrix, y_initial, forward_rate, rev_rate, third_body=None, iteration='Newton', discr='BDF', atol=1e-10, rtol=1e-6, sim_time=0.001, num_data_points=500): """ Sets up the initial condition for solving the odes Parameters ---------- matrix : ndarray stoichiometric matrix y_initial : list A list of initial concentrations forward_rate : list A list of forward reaction rates for all the reactions in the mechanism rev_rate : list A list of reverse reaction rates for all the reactions in the mechanism sim_time : float total time to simulate in seconds third_body : ndarray third body matrix, default = None iteration : str determines the iteration method that is be used by the solver, default='Newton' discr : determines the discretization method, default='BDF' atol : float absolute tolerance(s) that is to be used by the solver, default=1e-10 rtol : float relative tolerance that is to be used by the solver, default= 1e-7 num_data_points : integer number of even space data points in output arrays, default = 500 Returns ---------- t1 : list A list of time-points at which the system of ODEs is solved [t1, t2, t3,...] y1 : list of lists A list of concentrations of all the species at t1 time-points [[y1(t1), y2(t1),...], [y1(t2), y2(t2),...],...] """ # y0[0] = 0 # y0[0] = 0 # dydt = np.zeros((len(species_list)), dtype=float) # Define the rhs kf = forward_rate kr = rev_rate mat_reac = np.abs(np.asarray(np.where(matrix < 0, matrix, 0))) mat_prod = np.asarray(np.where(matrix > 0, matrix, 0)) # d = kf * np.prod(y0**np.abs(mat_reac), axis = 1) - kr * np.prod(y0**mat_prod, axis = 1) def rhs(t, concentration): # print(t) y = concentration if third_body is not None: third_body_eff = np.dot(third_body, y) third_body_eff = np.where(third_body_eff > 0, third_body_eff, 1) # print(third_body_eff) else: third_body_eff = np.ones(len(forward_rate)) # print(len(third_body_matrix)) rate_concentration = (kf * np.prod(np.power(y, mat_reac), axis=1) - kr * np.prod(np.power(y, mat_prod), axis=1)) dydt = np.dot( third_body_eff, np.multiply(matrix, rate_concentration.reshape(matrix.shape[0], 1))) # dydt = [np.sum(third_body_eff * (matrix[:, i] * rate_concentration)) for i in # range(len(species_list))] del t del y return dydt t0 = 0 # Define an Assimulo problem exp_mod = Explicit_Problem(rhs, y_initial, t0) # Define an explicit solver exp_sim = CVode(exp_mod) # Create a CVode solver # Sets the parameters exp_sim.iter = iteration # Default 'FixedPoint' exp_sim.discr = discr # Default 'Adams' exp_sim.atol = [atol] # Default 1e-6 exp_sim.rtol = rtol # Default 1e-6 exp_sim.maxh = 0.1 exp_sim.minh = 1e-18 exp_sim.num_threads = 1 while True: try: t1, y1 = exp_sim.simulate(sim_time, num_data_points) break except CVodeError: # reduce absolute error by two orders of magnitude # and try to solve again. print("next process started") atol = atol * 1e-2 exp_sim.atol = atol # if atol < 1e-15: # t1 = 0 # y1 = 0 # break # print(exp_sim.atol) return t1, y1