def simulate(self): """ Simulate the mechanism with RMS """ if not HAS_RMS: self.logger.error('Missing diffeqpy and/or pyrms. Please ensure these dependencies were' 'correctly installed.') if len(self.observable_list): self.logger.info('Running a simulation with SA using RMSConstantTP...') else: self.logger.info('Running a simulation using RMSConstantTP...') solver = de.CVODE_BDF() t_final = convert_termination_time_to_seconds(self.rmg['reactors'][0]['termination_time']) if len(self.observable_list): react = rms.Reactor(self.domain, self.y0, (0.0, t_final), forwardsensitivities=True, p=self.p) atol = [self.atol] * self.domain.indexes[-1] # set atol for the variables being simulated total_variables = self.domain.indexes[-1] + len(self.p) * self.domain.indexes[-1] atol.extend([self.sa_atol] * (total_variables - self.domain.indexes[-1])) # set atol for SA self.sol = de.solve(react.ode, solver, abstol=atol, reltol=self.rtol) else: react = rms.Reactor(self.domain, self.y0, (0.0, t_final), forwardsensitivities=False, p=self.p) self.sol = de.solve(react.ode, solver, abstol=self.atol, reltol=self.rtol) self.bsol = rms.Simulation(self.sol, self.domain)
def single_block_search(self): print() print( f'Search number {self.current_block + 1}/{self.number_of_blocks}. Solving for {self.tspan}.\n' ) print() start = tm.time() # CPU Clock begins # Stochastic integration using diffeqpy self.sol = de.solve(self.prob, de.SOSRI(), callback=self.transition_cb, saveat=self.dt, maxiters=self.max_iters) # Update results if we find a transition if self.sol.retcode == 'Terminated': print( f'Found transition in search number {self.current_block + 1}. Saving Results.\n' ) # CPU Time Since Last Success end = tm.time() cpu_time = end - start # Time results updated self.experiment_time_results['cpu_times(s)'].append(cpu_time) self.experiment_time_results['residence_times'].append( self.current_residence_time) self.experiment_time_results['number_of_transitions'] += 1 # Saving Path and Residence time print(self.current_residence_time) self.looker.look(self.sol) self.looker._parameters[ 'residence_time'] = self.current_residence_time print(self.looker.observations.attrs) self.save_results() # Check if we have found enough samples and can stop if self.experiment_time_results[ 'number_of_transitions'] == self.transition_limit: print( f'Found {self.transition_limit} transitions - will quit.') sys.exit() # Reset Experiment self.last_successful_block = self.current_block self.prob = de.remake(self.prob, u0=self.ic, tspan=self.tspan) # If we don't find a transition, remake the problem else: print(f'Exited due to {self.sol.retcode}\n') self.prob = de.remake(self.prob, u0=self.sol.u[-1], tspan=self.tspan) self.current_block += 1 return
def test_simulate(self): phaseDict = rms.readinput("pyrms/testing/superminimal.rms") spcs = phaseDict["gas"]["Species"] rxns = phaseDict["gas"]["Reactions"] ig = rms.IdealGas(spcs, rxns, name="gas") initialconds = {"T": 1000.0, "P": 10.0e5, "H2": 2.0, "O2": 1.0} domain, y0 = rms.ConstantTPDomain(phase=ig, initialconds=initialconds) react = rms.Reactor(domain, y0, (0.0, 10.001)) sol = de.solve(react.ode, de.CVODE_BDF(), abstol=1e-20, reltol=1e-8) sim = rms.Simulation(sol, domain) self.assertAlmostEqual(rms.molefractions(sim, "H2", 3.0), 0.34445669, places=3)
#################################### ### Running Experiment #################################### experiment_header([epsilon, delta]) start = tm.time() for i in range(number_of_searches): # Looped Search for Transitions print(f'Solving for {prob.tspan}\n') # Integrate only saving T variable sol = de.solve(prob, de.EM(), saveat=dt, callback=cb, save_idxs=np.array([K + 1]), maxiters=max_iters) # If we find a transtions, save the result if sol.retcode == 'Terminated': #i.e. callback ended the integration, so we save results end = tm.time() cpu_time = end - start integration_time = sol.t[-1] update_results() save_results() last_success_block = i # Check if we have found enough samples and can stop if experiment_results['number_of_transitions'] == 100:
return f(u, p, t) if __name__ == '__main__': u0 = [1.0, 0.0, 0.0] #u0 = 0.5 jul_f = Main.eval( "(u,p,t)->[p[1]*(u[2]-u[1]),u[1]*(p[2]-u[3])-u[2], u[1]*u[2]-p[3]*u[3]]" ) #jul_f = Main.eval("(u,p,t) -> -u") tspan = (0., 100.) p = [10.0, 28.0, 8 / 3] for i in range(10): t_start = time.time() prob = de.ODEProblem(jul_f, u0, tspan, p) sol = de.solve(prob) t_end = time.time() with open('out.txt', 'a') as f_out: s = f'julia took {t_end-t_start}\n' f_out.write(s) print(s) for i in range(10): t_start = time.time() eff_p = solve_ivp(wrapped, tspan, u0, method='BDF') t_end = time.time() with open('out.txt', 'a') as f_out: s = f'scipy took {t_end - t_start}\n' f_out.write(s) print(s) #prob = de.ODEProblem(jul_f, u0, tspan, p) #sol = de.solve(prob)
adj = nx.to_numpy_array(G, dtype=int) if __name__ == "__main__": ind_transition = int(T_trans/dt) theta_0 = np.random.uniform(-pi, pi, size=N) omega_0 = np.random.normal(mu, sigma, size=N) tspan = (0.0, T) p = [K/N, N, omega_0, adj] start = time() for i in range(len(K)): p[0] = K[i] / N prob = de.ODEProblem(julia_f, theta_0, tspan, p) sol = de.solve(prob, de.Tsit5(), saveat=dt, abstol=1e-6, reltol=1e-6); print("K = {:.3f}".format(K[i])) print("pyjulia Done in {} seconds.".format(time() - start)) # print(type(theta)) # print(sol.shape) # print(type(sol.t), len(sol.t)) # print(type(sol.u), len(sol.u), len(sol.u[0]), type(sol.u[0])) # print(type(sol.t), type(sol.u), type(sol.u[0]))
looker.dump_count = get_max_end_number(sd) ########################################## ## Looped Search For Transitions ########################################## for i in range(number_of_searches): print( f'Solving for {prob.tspan}. Search number {i + 1} of {number_of_searches}.\n' ) # Integrate sol = de.solve(prob, de.SRIW1(), reltol=1e-3, abstol=1e-3, callback=entry_cb, maxiters=1e20) print(f'Integration ended due to {sol.retcode}\n') # If callback ended the integration, save results if sol.retcode == 'Terminated': print(f'Found Transition during search number {i + 1}.') looker.look(sol) looker.dump(sd, name=file_name) # Reset Integration prob = de.remake(prob, u0=ic, tspan=tspan)
max_end_number = int(end_number) return max_end_number looker.dump_count = get_max_end_number(sd) ########################################## ## Looped Search For Transitions ########################################## from experiment_utilities import experiment_header experiment_header(eps, S, start_cold) for i in range(number_of_searches): print( f'Solving for {prob.tspan}. Search number {i + 1} of {number_of_searches}.\n' ) # Integrate sol = de.solve(prob, de.SOSRI(), callback=cb, maxiters=1e20) print(f'Integration ended due to {sol.retcode}\n') # If callback ended the integration, save results if sol.retcode == 'Terminated': print(f'Found Transition during search number {i + 1}.') looker.look(sol) looker.dump(sd, name=file_name) # Reset Integration prob = de.remake(prob, u0=ic, tspan=tspan)
pd = save_directory + 'cold_ic/' else: pd = save_directory + 'hot_ic/' sd = pd + f'{run_number}/' if not os.path.exists(sd): os.makedirs(sd) # Setting up diffeqpy solver t = 0. tspan = (0., block_length) prob = de.SDEProblem(numba_f, numba_g, u0, tspan, p) looker = SolutionObserver(prob.p) for i in range(number_of_blocks): print(prob.tspan) # Integrate sol = de.solve(prob, de.SRIW1(), reltol=1e-3, abstol=1e-3, saveat=0.1) looker.look(sol) # Save Observations looker.dump(sd) # Update Step t += block_length prob = de.remake(prob, u0=sol.u[-1], tspan=(t, t + block_length))
MaxDelay = max(Delay) DefaultStartTime = 0.0 DefaultVPEndTime = 1000.0 tspan = (DefaultStartTime, DefaultVPEndTime) vpinit = [ VP_tau1, VP_tau2, VP_tau3, VP_Gin, VP_di, VP_sig1, VP_a1, VP_r1, VP_sig2, VP_a2, VP_sig4, VP_U0, VP_a4, VP_sig5, VP_a5, VP_r5, 1 ] tmph, tmp0 = initData(MaxDelay) vp0 = vpinit + list(tmph) u0 = tmp0 prob0 = de.DDEProblem(mmodel, u0, history, tspan, p=vp0) sol0 = de.solve(prob0) ############################################## vp1 = vp0 u1 = u0 tspan1 = (DefaultStartTime, 500) prob1 = de.DDEProblem(mmodel, u1, history, tspan1, p=vp1) sol1 = de.solve(prob1) ut1 = np.transpose(sol1.u) tmp = SoltoInit(sol1.t, ut1, MaxDelay, 500) vp2 = vpinit + list(tmp) vp2[5] = 1.2 * vp2[5] u2 = sol1.u[len(sol1.u) - 1] tspan2 = (500, 1000) prob2 = de.DDEProblem(mmodel, u2, history, tspan1, p=vp2)
def run_experiment(S=10, epsilon=5, delta=1, cold=True): """ S, float - reduced solar constant. epsilon, float - noise strength. cold, boolean - whether we start on cold attractor or not. """ #################################### ### Fixed Experiment Settings #################################### # Time Set Up end_time = 1000. # Length of integration where we look for a transitions dt = 1.0 # How often output is saved, since we're not saving integrations it can be coarse number_of_searches = int(1.e4) # How many integration runs we do tspan = (0., end_time) max_iters = 1.e20 # Fixed L96 EBM Parameters K = 50 a0 = 0.5 a1 = 0.4 sigma = 1 / 180**4 F = 8. Tref = 270. delT = 60. alpha = 2. beta = 1. p = np.array( [K, S, a0, a1, sigma, F, Tref, delT, alpha, beta, epsilon, delta]) # Initialising Dictionary to Store Experiment Results global experiment_results global cpu_time global integration_time experiment_results = { 'epsilon': epsilon, 'delta': delta, 'S': S, 'cpu_times(s)': [], 'integration_times': [], 'number_of_transitions': 0, 'parameters': p } # Setting IC & Callbacks, File locations will need updating for cluster run if cold: ic = get_random_cold_point(S=S) cb_condition = get_entered_hot_condition(S, K) cb = de.DiscreteCallback(cb_condition, de.terminate_b) else: ic = get_random_hot_point(S=S) cb_condition = get_entered_cold_condition(S, K) cb = de.DiscreteCallback(cb_condition, de.terminate_b) # Setting up diffeqpy solver prob = de.SDEProblem(numba_f, numba_multiplicative_g, ic, tspan, p) #################################### ### Looped Search for Transitions #################################### experiment_header(epsilon, delta, S, cold) start = tm.time() # CPU Clock begins last_successful_block = -1 for i in range(number_of_searches): print() print( f'Search number {i + 1}/{number_of_searches}. Solving for {prob.tspan}.\n' ) # Integrate only saving T variable sol = de.solve(prob, de.SOSRI(), saveat=dt, callback=cb, maxiters=max_iters) # If we find a transition, save the result & reset experiment if sol.retcode == 'Terminated': print( f'Found transition in search number {i + 1}. Saving Results.\n' ) # CPU Time Since Last Success end = tm.time() cpu_time = end - start # Integration Time Since Last Success completed_blocks_since_last_success = i - (last_successful_block + 1) block_length = end_time integration_time_in_this_block = sol.t[-1] integration_time = completed_blocks_since_last_success * block_length + integration_time_in_this_block update_results() save_results(pd=experiment_results_pd, S=S, epsilon=epsilon, cold=cold, delta=delta) # Check if we have found enough samples and can stop if experiment_results['number_of_transitions'] == 100: print(f'Found 100 transitions - will quit.') quit() # Reset Experiment start = tm.time() last_successful_block = i if cold: ic = get_random_cold_point(S=S) else: ic = get_random_hot_point(S=S) prob = de.remake(prob, u0=ic, tspan=tspan) # If we don't find a transition, remake the problem else: print(f'Exited due to {sol.retcode}\n') prob = de.remake(prob, u0=sol.u[-1], tspan=(0, end_time)) return
def electron_onerxn(params, protocol, times, num_electrons=1, capacitance_func=lambda x: 1, u0=[0.5, 0.0], du0=[0.0, 0.0]): """Simulate current data from electron transfer reaction. Parameters ---------- params : list A list containing the parameter values. The first elements should take the form [e_0, alpha, k_0, rho, zeta, gamma,], followed by any extra parameters required for the capacitance model. protocol : function Function which takes as input times (float or 1d np.ndarray) and returns the value of the potential at that time times : np.ndarray Time points on which to solve for the current num_electrons : int, optional (1) Integer number of electrons transferred per reaction capacitance_func : function, optional (constant) The capacitance model. The first, required argument is the real potential, subsequent optional arguments are extra capacitance constants which must then be appended to params. Example of third order polynomial model for capacitive current: def capacitance_func(e, c1, c2, c3): return 1 + c1 * e + c2 * e**2 + c3 * e**3 By default, the capacitance function is just a constant 1, which corresponds to a single parameter capacitance model with the capacitance parameter gamma from params. u0 : list, optional ([0.5, 0.0]) Initial conditions for [theta, i]. Corresponds to t=0, not the first point in times du0 : list, optional ([0.0, 0.0]) Initial conditions for [dtheta/dt, di/dt]. Corresponds to t=0, not the first point in times Returns ------- np.ndarray Current over time np.ndarray Proportion of A over time """ def f(du, u, p, t): """Calculate the two equations. Parameters ---------- du : list time derivatives, [dtheta/dt, di/dt] u : list variables, [theta, i] p : list Model parameters t : float time value Returns ------- list The residuals for dtheta/dt and current """ # Unpack the parameters e0, alpha, k0, rho, zeta, gamma, *cap_params = p # Get the value of the protocol at given time e = protocol(t) # Approximate de/dt using finite differences dt = 1e-5 dedt = (protocol(t) - protocol(t - dt)) / dt # Calculate the equation for current resid1 = -u[1] + gamma \ * capacitance_func(e - rho * u[1], *cap_params) * dedt \ - gamma * capacitance_func(e - rho * u[1], *cap_params) \ * rho * du[1] + zeta * du[0] * num_electrons # Calculate the equation for proportion of A resid2 = -du[0] + k0 \ * ((1 - u[0]) * np.exp((1 - alpha) * (e - rho * u[1] - e0)) - u[0] * np.exp(-alpha * (e - rho * u[1] - e0))) return [resid1, resid2] differential_vars = [True, True] # Time points for solving, start at zero # It will return only on the user supplied time points in times tspan = (0, max(times)) problem = de.DAEProblem( f, du0, u0, tspan, params, differential_vars=differential_vars ) sol = de.solve(problem, saveat=times, reltol=1e-10) results = np.array(sol.u) theta = results[:, 0] i = results[:, 1] return i[1:], theta[1:]
def run_l96_ebm_multiplicative(p, u0, block_length, number_of_blocks, sd=None, dt=0.1): """ Use diffeqpy solver to stochastically integrate the L96 EBM Equations w multiplicative noise. Arguments ------------ p, list: Parameters for the model run. ic, np array: The intial condition for the model run. block_length, int: How often model output is saved. number_of_blocks, int: How many times we save model output. Note no. of obs = (blocklength * number of blocks)/dt sd, string: Where model output is saved. dt, float: Time between model observations. Note integrator uses adaptive timestepper that may be smaller. """ # Setting up diffeqpy solver t = 0. tspan = (0., block_length) prob = de.SDEProblem(numba_f, numba_g, u0, tspan, p) # Creating Observer Object to do saving looker = SolutionObserver(prob.p) # Loop with intermitment saves for i in range(number_of_blocks): print(f'Solving for {prob.tspan}\n') # Integrate sol = de.solve(prob, de.SRIW1(), reltol=1e-3, abstol=1e-3, saveat=dt) looker.look(sol) # Save Observations if sd is not None: looker.dump(sd) # Update Step t += block_length prob = de.remake(prob, u0=sol.u[-1], tspan=(t, t + block_length)) # Output results if no save directory if sd is None: return looker.observations else: return
def fiber_orientation(a0, t, L, ci, ar, kappa=1, D3=None, closure="orthotropic", method="RK45", debug=False, **kwargs): """ Compute fiber orientation tensor evolution using the Folgar-Tucker model as its variants Args: a0 (ndarray of shape (3, 3)): Initial fiber orientation tensor t (ndarray of shape (1, )): Time instants L (ndarray of shape (3, 3)): Velocity gradient ci (float): Interaction coefficient ar (float): Aspect ratio kappa (float): Reduction coefficient when using the RSC model, ``0 < kappa <= 1`` D3 (ndarray of shape (3, )): Coefficients :math:`(D_1,D_2,D_3)` when using the MRD model closure (str): 4th-order fiber orientation closure model ``A4_*``, see :py:mod:`fiberpy.closure` method (str): Numerical method to integrate the IVP, see :py:func:`scipy.integrate.solve_ivp`, or ``julia`` debug (bool): Return instead the ``sol`` object and ``dadt`` """ D_ = 0.5 * (L + L.T) W_ = 0.5 * (L - L.T) lmbda = (ar**2 - 1) / (ar**2 + 1) gamma = np.sqrt(2) * np.linalg.norm(D_) a0_ = a0.flatten() # MRD model if D3 is not None: trD3 = np.sum(D3) D3 = np.diag(D3) kappa = 1 def dadt(t, a): a_ = a.reshape((3, 3)) e, v = np.linalg.eigh(a_) e = e[::-1] v = v[:, ::-1] A = eval("A4_" + closure + "(e)") if not np.isclose(kappa, 1): A[:3, :3] = kappa * A[:3, :3] A[:3, :3] += (1 - kappa) * np.diag(e) # Folgar-Tucker or RSC if D3 is None: diffusion_part = np.eye(3) - 3 * a_ else: # MRD diffusion_part = v @ D3 @ v.T - trD3 * a_ dadt_ = (W_ @ a_ - a_ @ W_ + lmbda * (D_ @ a_ + a_ @ D_ - 2 * apply_Ax(v, A, D_)) + 2 * kappa * ci * gamma * diffusion_part) return dadt_.flatten() if method != "julia": sol = integrate.solve_ivp(dadt, (t[0], t[-1]), a0_, t_eval=t, method=method, **kwargs) y = sol.y else: from diffeqpy import de def dadt_julia(a, p, t): return dadt(t, a) prob = de.ODEProblem(dadt_julia, a0_, (t[0], t[-1])) sol = de.solve(prob) y = np.asarray(sol(t)) if not debug: return y else: return sol, dadt