def test_input_simulation(self): """ This tests that input simulation works. """ self.m_SENS = JMUModel('QuadTankSens.jmu') self.SENS = JMIDAESens(self.m_SENS) path_result = os.path.join(get_files_path(), 'Results', 'qt_par_est_data.mat') data = loadmat(path_result,appendmat=False) # Extract data series t_meas = data['t'][6000::100,0]-60 u1 = data['u1_d'][6000::100,0] u2 = data['u2_d'][6000::100,0] # Build input trajectory matrix for use in simulation u_data = N.transpose(N.vstack((t_meas,u1,u2))) u_traj = TrajectoryLinearInterpolation(u_data[:,0], u_data[:,1:]) input_object = (['u1','u2'], u_traj) qt_mod = JMIDAESens(self.m_SENS, input_object) qt_sim = IDA(qt_mod) #Store data continuous during the simulation, important when solving a #problem with sensitivites. qt_sim.report_continuously = True #Value used when IDA estimates the tolerances on the parameters qt_sim.pbar = qt_mod.p0 #Let Sundials find consistent initial conditions by use of 'IDA_YA_YDP_INIT' qt_sim.make_consistent('IDA_YA_YDP_INIT') #Simulate qt_sim.simulate(60) #Simulate 4 seconds with 400 communication points #write_data(qt_sim) res = ResultDymolaTextual('QuadTankSens_result.txt') dx1da1 = res.get_variable_data('dx1/da1') dx1da2 = res.get_variable_data('dx1/da2') dx4da1 = res.get_variable_data('dx4/da1') nose.tools.assert_almost_equal(dx1da2.x[0], 0.000000, 4) nose.tools.assert_almost_equal(dx1da2.x[-1], 0.00000, 4)
def main(): y0 = [1.0, 0.0, 0.0, 0.0, 5] yd0 = [0.0, 0.0, 0.0, -9.82, 0.0] # tout = [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 5.0] tout = np.linspace(0.0, 10.0, 500) implicit_model = Implicit_Problem(res, y0, yd0, name="Example problem") # implicit_model.jac = jac implicit_model.algvar = [1.0, 1.0, 1.0, 1.0, 0.0] implicit_solver = IDA(implicit_model) implicit_solver.atol = 1E-6 implicit_solver.rtol = 1E-6 implicit_solver.suppress_alg = True implicit_solver.make_consistent("IDA_YA_YDP_INIT") t, y, yd = implicit_solver.simulate(10.0, ncp=500) plt.plot(t, y, linestyle="dashed", marker="o") plt.xlabel("Time") plt.ylabel("State") plt.title(implicit_model.name) plt.show()
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 """ #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]) #Defines the Jacobian def jac(c, t, y, yd): jacobian = N.zeros([len(y), len(y)]) #Derivative jacobian[0, 0] = 1 * c jacobian[1, 1] = 1 * c jacobian[2, 2] = 1 * c jacobian[3, 3] = 1 * c #Differentiated jacobian[0, 2] = -1 jacobian[1, 3] = -1 jacobian[2, 0] = y[4] jacobian[3, 1] = y[4] jacobian[4, 0] = y[0] * 2 * y[4] * -1 jacobian[4, 1] = y[1] * 2 * y[4] * -1 - 9.82 jacobian[4, 2] = y[2] * 2 jacobian[4, 3] = y[3] * 2 #Algebraic jacobian[2, 4] = y[0] jacobian[3, 4] = y[1] jacobian[4, 4] = -(y[0]**2 + y[1]**2) return jacobian #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 using an analytic Jacobian') #Sets the options to the problem imp_mod.jac = jac #Sets the jacobian 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 #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, 1000) #Simulate 5 seconds with 1000 communication points #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) #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(imp_mod.name) P.show() return imp_mod, imp_sim
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 IDA, 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)&=0 \\ \dot y_2 -(p_1 y_1 - p_2 y_2 y_3 - p_3 y_2^2)&=0 \\ \dot y_3 -( p_3 y_ 2^2)&=0 on return: - :dfn:`imp_mod` problem instance - :dfn:`imp_sim` solver instance """ 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 = N.array([1.0, 0.0, 0.0]) # Initial conditions for y yd0 = N.array([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.report_continuously = 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.title(imp_mod.name) P.xlabel('Time') P.ylabel('State') P.show() return imp_mod, imp_sim
imp_sim = IDA(imp_mod) #Create a IDA solver #Sets the paramters imp_sim.atol = 1e-5 #Default 1e-6 imp_sim.rtol = 1e-5 #Default 1e-6 imp_sim.suppress_alg = True #Suppres the algebraic variables on the error test ### Simulate imp_mod.set_j_vec( I_app ) #res_test = imp_mod.res( 0.0, y0, yd0 ) #jac_test = imp_mod.jac( 2, 0.0, y0, yd0 ) #Let Sundials find consistent initial conditions by use of 'IDA_YA_YDP_INIT' imp_sim.make_consistent('IDA_YA_YDP_INIT') # Sim step 1 t1, y1, yd1 = imp_sim.simulate(100,100) #t1, y1, yd1 = imp_sim.simulate(1000,1000) imp_mod.set_j_vec( 0.0 ) imp_sim.make_consistent('IDA_YA_YDP_INIT') # Sim step 1 t2, y2, yd2 = imp_sim.simulate(200,100) #Plot # Plot through space f, ax = plt.subplots(2,3) ax[0,0].plot(imp_mod.x_m*1e6,y1.T[:N,:]) #Plot the solution
def main(): import numpy as np import time from matplotlib import pyplot as plt from li_ion_battery_p2d_functions import Extended_Problem from assimulo.solvers import IDA from li_ion_battery_p2d_inputs import Inputs as inp from li_ion_battery_p2d_init import anode, cathode, separator, SV_0, algvar from li_ion_battery_p2d_post_process import Label_Columns, tag_strings, plot_sims # Close any open pyplot objects: plt.close() # Start a timer: t_count = time.time() # Calculate the time span, which should be enough to charge or discharge fully # (i.e. 3600 seconds divided by the C-rate): t_0 = 0 t_f = 3600 / inp.C_rate # SV_0 = anode.SV_0 # SV_0 = np.concatenate((anode.SV_0, separator.SV_0, cathode.SV_0)) #SV_0 = np.concatenate((anode.SV_0, separator.SV_0)) SV_dot_0 = np.zeros_like(SV_0) """----------Equilibration----------""" # Equilibrate by integrating at zero current: print('\nEquilibrating...') # Create problem instance #Battery_equil = Extended_Problem(Battery_Func, SV_0, SV_dot_0, t_0) anode.i_ext = 0 cathode.i_ext = 0 Battery_equil = Extended_Problem.Battery_Func(t_0, SV_0, SV_dot_0, True) Battery_equil.external_event_detection = True # algvar = anode.algvar # algvar = np.concatenate((anode.algvar, separator.algvar, cathode.algvar)) #algvar = np.concatenate((anode.algvar, separator.algvar)) # Battery_equil.algvar = algvar # Simulation parameters equil_sim = IDA(Battery_equil) # Create simulation instance equil_sim.atol = atol1 # Solver absolute tolerance equil_sim.rtol = rtol1 # Solver relative tolerance equil_sim.verbosity = 50 equil_sim.make_consistent('IDA_YA_YDP_INIT') t_eq, SV_eq, SV_dot_eq = equil_sim.simulate(t_f) # Put solution into pandas dataframe with labeled columns SV_eq_df = Label_Columns(t_eq, SV_eq) # Obtain tag strings for dataframe columns tags = tag_strings(SV_eq_df) print('Done equilibrating\n') """---------------------------------""" """------------Charging-------------""" print('\nCharging...') # New initial conditions are the final equilibrium conditions t_0 = t_eq[-1] t_f1 = t_0 + t_f SV_0 = SV_eq[-1, :] SV_dot_0 = SV_dot_eq[-1:] # Charge the battery anode.params['i_ext'] = anode.i_ext cathode.params['i_ext'] = -cathode.i_ext # Create problem instance Battery_charge = Extended_Problem(Charge, SV_0, SV_dot_0, t_0) Battery_charge.external_event_detection = True Battery_charge.algvar = algvar # Simulation parameters charge_sim = IDA(Battery_charge) charge_sim.atol = atol2 charge_sim.rtol = rtol2 charge_sim.verbosity = 50 charge_sim.make_consistent('IDA_YA_YDP_INIT') # charge_sim.maxh = 0.5 t_charge, SV_charge, SV_dot_charge = charge_sim.simulate(t_f1) t_flag1 = anode.t_flag SV_charge_df = Label_Columns(t_charge, SV_charge) print('Done charging\n') """---------------------------------""" """------------Re_equilibrating-------------""" # New initial conditions are the final charge conditions t_0 = t_charge[-1] #anode.t_flag t_f2 = t_0 + t_f SV_0 = SV_charge[-1, :] SV_dot_0 = SV_dot_charge[-1, :] # Equilibrate again. Note - this is a specific choice to reflect # equilibration after the charging steps. We may want, at times, to # simulate a situation where the battery is not equilibrated between # charge and discharge, or is equilibrated for a shorter amount of time. print('\nRe-equilibrating...') Battery_re_equil = Extended_Problem(Re_equilibrate, SV_0, SV_dot_0, t_0) Battery_re_equil.external_event_detection = True Battery_re_equil.algvar = algvar # Simulation parameters re_equil_sim = IDA(Battery_re_equil) re_equil_sim.atol = atol3 re_equil_sim.rtol = rtol3 re_equil_sim.verbosity = 50 re_equil_sim.make_consistent('IDA_YA_YDP_INIT') t_req, SV_req, SV_dot_req = re_equil_sim.simulate(t_f2) SV_req_df = Label_Columns(t_req, SV_req) print('Done re-equilibrating\n') """---------------------------------""" """------------Discharging-------------""" print('\nDischarging...') t_0 = t_req[-1] t_f3 = t_f2 + t_f SV_0 = SV_req[-1, :] SV_dot_0 = SV_dot_req[-1, :] anode.params['i_ext'] = -anode.i_ext cathode.params['i_ext'] = cathode.i_ext Battery_discharge = Extended_Problem(Discharge, SV_0, SV_dot_0, t_0) Battery_discharge.external_event_detection = True Battery_discharge.algvar = algvar # Simulation parameters Battery_discharge = IDA(Battery_discharge) Battery_discharge.atol = atol4 Battery_discharge.rtol = rtol4 Battery_discharge.verbosity = 50 Battery_discharge.make_consistent('IDA_YA_YDP_INIT') t_discharge, SV_discharge, SV_dot_discharge = Battery_discharge.simulate( t_f3) t_flag2 = anode.t_flag SV_discharge_df = Label_Columns(t_discharge, SV_discharge) print('Done discharging\n') """---------------------------------""" SV_dict = {} SV_dict['SV_eq'] = SV_eq_df SV_dict['SV_charge'] = SV_charge_df SV_dict['SV_req'] = SV_req_df SV_dict['SV_discharge'] = SV_discharge_df # SV_charge_df = SV_charge_df.loc[SV_charge_df['Time'] <= t_flag1] # SV_discharge_df = SV_discharge_df.loc[SV_discharge_df['Time'] <= t_flag2] # dt_cap = t_flag1 - t_eq[-1] # t_80 = 0.8*dt_cap + t_eq[-1] # elyte80_charge = SV_charge_df.loc[SV_charge_df['Time'] <= t_80] # elyte75_charge = SV_charge_df.loc[SV_charge_df['X_an15'] <= 0.20] # el80 = elyte80_charge[X_elyte].iloc[0] # el80 = list(el80) # el80.append(inp.C_rate) # import openpyxl # book = openpyxl.load_workbook('Elyte_depth_profiles.xlsx') # sheet = book.active # sheet.append(el80) # book.save('Elyte_depth_profiles.xlsx') # print('Elyte Li+ at 80% SOC = ', elyte75_charge, '\n') plot_sims(tags['V_an'], tags['X_an'], tags['X_el_an'], SV_dict, t_f1, t_f3, t_flag1, t_flag2) # plot_sims(tags['V_cat'], tags['X_cat'], tags['X_el_cat'], SV_dict, t_f1, t_f3, t_flag1, t_flag2) # fig, axes = plt.subplots(sharey = "row", figsize = (18, 8), nrows=1, ncols=4) # plt.subplots_adjust(wspace=0, hspace=0.5) # # V_cell_plot = V_cell_eq.plot(ax = axes[0]) # V_cell_plot.set_title('Equilibration') # V_cell_plot.set_ylabel('Cell Voltage') # V_cell_plot.legend().set_visible(False) # # V_cell_plot = V_cell_charge.plot(ax = axes[1]) # V_cell_plot.set_title('Charging') # V_cell_plot.set_ylabel('Cell Voltage') # V_cell_plot.legend().set_visible(False) # # V_cell_plot = V_cell_req.plot(ax = axes[2]) # V_cell_plot.set_title('Re-Equilibration') # V_cell_plot.set_ylabel('Cell Voltage') # V_cell_plot.legend().set_visible(False) # # V_cell_plot = V_cell_discharge.plot(ax = axes[3]) # V_cell_plot.set_title('Discharge') # V_cell_plot.set_ylabel('Cell Voltage') # V_cell_plot.legend().set_visible(False) """---------------------------------""" # Post processing V_charge = np.array(SV_charge_df['V_dl1']) V_discharge = np.array(SV_discharge_df['V_dl1']) t_charge = np.array(SV_charge_df['Time']) t_discharge = np.array(SV_discharge_df['Time']) dt_charge = t_charge - t_charge[0] dt_discharge = t_discharge - t_discharge[0] # Plot charge-discharge curve Capacity_charge = -dt_charge * anode.i_ext / 3600 # A-h/m^2 Capacity_discharge = -dt_discharge * anode.i_ext / 3600 # A-h/m^2 fig1, ax1 = plt.subplots() ax1.plot(Capacity_charge, V_charge) ax1.plot(Capacity_discharge, V_discharge) # ax1.set_ylim((0, 1.2)) # ax1.set_xlim((-0.1, 18.5)) ax1.set_xlabel("Capacity [Ah/m^2]") ax1.set_ylabel("Voltage [V]") ax1.legend(("Charge capacity", "Discharge capacity")) # Calculate battery energy storage/recovery and calculate round-trip # efficiency. Anode voltage is referenced to its initial equilibrium # value (i.e. in the discharged state). # NOTE: This is in W-h/m^2, per unit area of battery. For the specific # capacity, you want W-h/g of anode material. # E_stored = 0 # E_recovered = 0 # for k in np.arange(1, len(t_charge)): # E_stored = (E_stored - (anode.V_cathode - 0.5*(V_charge[k] + V_charge[k-1])) # *ep.i_ext*(dt_charge[k] - dt_charge[k-1])) # # for k in np.arange(1, len(t_discharge)): # E_recovered = (E_recovered - (ep.V_cathode - # 0.5*(V_discharge[k] + V_discharge[k-1])) # *ep.i_ext*(dt_discharge[k] - dt_discharge[k-1])) # # Cap_recovered = Capacity_discharge[-1] # Eta_RT = E_recovered/E_stored # print('Cap_recovered = ', Cap_recovered, '\n') # print(E_stored, '\n') # print(E_recovered, '\n') # print('Eta_RT = ', Eta_RT, '\n') elapsed = time.time() - t_count print('t_cpu=', elapsed, '\n') plt.show() return t_req, SV_req, SV_dot_req
def main(): res_class = eval(inputs.test_type) # plt.close('all') t_count = time.time() SV_0 = sol_init.SV_0 SV_dot_0 = np.zeros_like(SV_0) t_0 = 0. t_f = 3600. / inputs.C_rate #63006.69900049 93633 algvar = sol_init.algvar atol = np.ones_like(SV_0) * 1e-6 atol[cat.ptr_vec['eps_S8']] = 1e-15 atol[cat.ptr_vec['eps_Li2S']] = 1e-15 atol[cat.ptr_vec['rho_k_el']] = 1e-16 # 1e-16 for Bessler rtol = 1e-6 sim_output = 50 rtol_ch = 1e-6 atol_ch = np.ones_like(SV_0) * 1e-6 atol_ch[cat.ptr_vec['eps_S8']] = 1e-15 atol_ch[cat.ptr_vec['eps_Li2S']] = 1e-15 atol_ch[cat.ptr_vec['rho_k_el']] = 1e-30 rate_tag = str(inputs.C_rate) + "C" # if 'cascade' in inputs.ctifile: # ncols = 2 + inputs.flag_req # else: ncols = 1 + inputs.flag_req fig, axes = plt.subplots(sharey="row", figsize=(9, 12), nrows=3, ncols=(ncols) * inputs.n_cycles, num=1) plt.subplots_adjust(wspace=0.15, hspace=0.4) fig.text(0.35, 0.85, rate_tag, fontsize=20, bbox=dict(facecolor='white', alpha=0.5)) # Set up user function to build figures based on inputs "----------Equilibration----------" print('\nEquilibrating...') # Set external current to 0 for equilibration cat.set_i_ext(0) # cat.nucleation_flag = 1 # Create problem object bat_eq = res_class(res_class.res_fun, SV_0, SV_dot_0, t_0) bat_eq.external_event_detection = True bat_eq.algvar = algvar # Create simulation object sim_eq = IDA(bat_eq) sim_eq.atol = atol sim_eq.rtol = rtol sim_eq.verbosity = sim_output sim_eq.make_consistent('IDA_YA_YDP_INIT') t_eq, SV_eq, SV_dot_eq = sim_eq.simulate(t_f) # Put solution into pandas dataframe with labeled columns SV_eq_df = label_columns(t_eq, SV_eq, an.npoints, sep.npoints, cat.npoints) # Obtain tag strings for dataframe columns tags = tag_strings(SV_eq_df) # plot_sim(tags, SV_eq_df, 'Equilibrating', 0, fig, axes) t_equilibrate = time.time() - t_count print("Equilibration time = ", t_equilibrate, '\n') print('Done equilibrating\n') for cycle_num in np.arange(0, inputs.n_cycles): "------------Discharging-------------" print('Discharging...') # cat.np_L = inputs.np_Li2S_init cat.nucleation_flag = np.zeros((inputs.npoints_cathode, 1)) # New initial conditions from previous simulation if cycle_num == 0: # SV_0 = SV_0 SV_0 = SV_eq[-1, :] # SV_dot_0 = SV_dot_0 SV_dot_0 = SV_dot_eq[-1, :] else: SV_0 = SV_0_cycle SV_dot_0 = SV_dot_0_cycle # Set external current cat.set_i_ext(cat.i_ext_amp) # Update problem instance initial conditions bat_dch = res_class(res_class.res_fun, SV_0, SV_dot_0, t_0) bat_dch.external_event_detection = True bat_dch.algvar = algvar # Re-initialize simulation object sim_dch = IDA(bat_dch) sim_dch.atol = atol sim_dch.rtol = rtol # sim_dch.maxh = 57 sim_dch.verbosity = sim_output sim_dch.make_consistent('IDA_YA_YDP_INIT') t_dch, SV_dch, SV_dot_dch = sim_dch.simulate(131865.32) SV_dch_df = label_columns(t_dch, SV_dch, an.npoints, sep.npoints, cat.npoints) # Obtain tag strings for dataframe columns tags = tag_strings(SV_dch_df) plot_sim(tags, SV_dch_df, 'Discharging', 0 + 2 * cycle_num, fig, axes) # plot_meanPS(SV_dch_df, tags, 'Discharging') print('Done Discharging\n') "--------Re-equilibration---------" if inputs.flag_req == 1: print('Re-equilibrating...') # New initial conditions from previous simulation SV_0 = SV_dch[-1, :] SV_dot_0 = SV_dot_dch[-1, :] # Set external current cat.set_i_ext(0) # Update problem instance initial conditions bat_req = res_class(res_class.res_fun, SV_0, SV_dot_0, t_0) bat_req.external_event_detection = True bat_req.algvar = algvar # Re-initialize simulation object sim_req = IDA(bat_req) sim_req.atol = atol sim_req.rtol = rtol sim_req.verbosity = sim_output sim_req.make_consistent('IDA_YA_YDP_INIT') t_req, SV_req, SV_dot_req = sim_req.simulate(t_f) SV_req_df = label_columns(t_req, SV_req, an.npoints, sep.npoints, cat.npoints) # plot_sim(tags, SV_req_df, 'Re-Equilibrating', 1, fig, axes) print('Done re-equilibrating\n') else: SV_req = SV_dch SV_dot_req = SV_dot_dch "-----------Charging-----------" if 'dog' in inputs.ctifile: print('Charging...') SV_0 = SV_req[-1, :] SV_dot_0 = SV_dot_req[-1, :] SV_0[cat.ptr_vec['eps_S8']] = cat.eps_cutoff cat.set_i_ext(-cat.i_ext_amp) # Update problem instance initial conditions bat_ch = res_class(res_class.res_fun, SV_0, SV_dot_0, t_0) bat_ch.external_event_detection = True bat_ch.algvar = algvar # Re-initialize simulation object sim_ch = IDA(bat_ch) sim_ch.atol = atol_ch sim_ch.rtol = rtol_ch if cycle_num > 0: sim_ch.maxh = 0.1 sim_ch.verbosity = sim_output sim_ch.make_consistent('IDA_YA_YDP_INIT') t_ch, SV_ch, SV_dot_ch = sim_ch.simulate(t_f) SV_ch_df = label_columns(t_ch, SV_ch, an.npoints, sep.npoints, cat.npoints) plot_sim(tags, SV_ch_df, 'Charging', 1 + inputs.flag_req + 2 * cycle_num, fig, axes) plot_meanPS(SV_ch_df, tags, 'Charging') SV_ch_df = 0 # # print('Max S_8(e) concentration = ', max(SV_ch[:, 6])) # SV_0_cycle = SV_ch[-1, :] # SV_dot_0_cycle = SV_ch[-1, :] print('Done Charging\n') exp_data_01C = pd.read_csv(r'0.1C Data.csv', header=None) exp_data_05C = pd.read_csv(r'0.5C Data.csv', header=None) exp_data_1C = pd.read_csv(r'1C Data.csv', header=None) Bessler = pd.read_csv(r'Bessler Dennis Data.csv', header=None) SV_copy = SV_dch_df.copy() SV_copy.loc[:, 'Time'] *= -cat.i_ext_amp * inputs.A_cat / 3600 / ( cat.m_S_tot_0) "Set up your figure" fig = plt.figure(3) ax = fig.add_axes([0.2, 0.2, 0.6, 0.75]) fig.set_size_inches((10., 5.0)) # ax2 = ax.twinx() "Formatting for the figure:" fs = 20 #font size for plots lw = 3.0 #line width for plots # font = plt.matplotlib.font_manager.FontProperties(family='Times New Roman',size=fs-1) for tick in ax.xaxis.get_major_ticks(): tick.label1.set_fontsize(fs) tick.label1.set_fontname('Times New Roman') for tick in ax.yaxis.get_major_ticks(): tick.label1.set_fontsize(fs) tick.label1.set_fontname('Times New Roman') color = matplotlib.cm.plasma(inputs.C_rate) p1, = plt.plot(SV_copy.loc[:, 'Time'], SV_copy.loc[:, 'Phi_ed1'], 'k-', linewidth=lw) # p2, = plt.plot(exp_data_01C.iloc[:,0], exp_data_01C.iloc[:,1], 'ro') # p3, = plt.plot(exp_data_05C.iloc[:,0], exp_data_05C.iloc[:,1], 'co') # p4, = plt.plot(exp_data_1C.iloc[:,0], exp_data_1C.iloc[:,1], 'ko') p5, = plt.plot(Bessler.iloc[:, 0], Bessler.iloc[:, 1], 'mo', ms=4) plt.xlim((0, 1700)) plt.xticks([0, 400, 800, 1200, 1600]) plt.ylim((1.8, 2.6)) plt.ylabel(r'Cell Voltage $[\mathrm{V}]$', fontstyle='normal', fontname='Times new Roman', fontsize=fs + 2, labelpad=5.0) plt.xlabel( r'Capacity $[\mathrm{Ah} \hspace{0.5} \mathrm{kg}^{-1}_{\mathrm{sulfur}}]$', fontstyle='normal', fontname='Times new Roman', fontsize=fs + 2, labelpad=5.0) # plt.legend(["Discharge", "Charge"]) file_name_dch = 'dch' + str(inputs.C_rate) + "C_" + inputs.mech + '.csv' SV_dch = SV_dch_df.copy() SV_dch.loc[:, 'Time'] *= -cat.i_ext_amp * inputs.A_cat / 3600 / (cat.m_S_0 + cat.m_S_el) SV_dch.to_csv(file_name_dch, index=False, header=True) t_elapsed = time.time() - t_count print('t_cpu=', t_elapsed, '\n') return SV_eq_df, SV_dch_df, SV_ch_df, tags
def main(): SV_0 = solver_inputs.SV_0 SV_dot_0 = np.zeros_like(SV_0) algvar = solver_inputs.algvar # Close any open pyplot objects: plt.close('all') atol = np.ones_like(SV_0)*1e-8 rtol = 1e-4 # Start a timer: t_count = time.time() # Calculate the time span, which should be enough to charge or discharge fully # (i.e. 3600 seconds divided by the C-rate): t_0 = 0 t_f = 3600/Inputs.C_rate rate_tag = str(Inputs.C_rate)+"C" """----------Figures----------""" if Inputs.plot_profiles_flag: fig1, axes1, fig2, axes2, fig3, axes3 = setup_plots(plt, rate_tag) for cycle in np.arange(0, Inputs.n_cycles): """----------Equilibration----------""" # Equilibrate by integrating at zero current: print('\nEquilibrating...') # Create problem instance current.set_i_ext(0) battery_eq = li_ion(li_ion.res_fun, SV_0, SV_dot_0, t_0) battery_eq.external_event_detection = True battery_eq.algvar = algvar # Simulation parameters sim_eq = IDA(battery_eq) # Create simulation instance sim_eq.atol = atol # Solver absolute tolerance sim_eq.rtol = rtol # Solver relative tolerance sim_eq.verbosity = 50 sim_eq.make_consistent('IDA_YA_YDP_INIT') t_eq, SV_eq, SV_dot_eq = sim_eq.simulate(0.1*t_f) # Put solution into pandas dataframe with labeled columns SV_eq_df = Label_Columns(t_eq, SV_eq, an.npoints, sep.npoints, cat.npoints) # Obtain tag strings for dataframe columns tags = tag_strings(SV_eq_df) print('Done equilibrating\n') """------------Charging-------------""" print('\nCharging...') # New initial conditions are the final equilibrium conditions t_0 = 0 SV_0 = SV_eq[-1, :] SV_dot_0 = SV_dot_eq[-1 :] # Charge the battery current.set_i_ext(current.i_ext_set) # Create problem instance battery_ch = li_ion(li_ion.res_fun, SV_0, SV_dot_0, t_0) battery_ch.external_event_detection = True battery_ch.algvar = algvar # Simulation parameters sim_ch = IDA(battery_ch) sim_ch.atol = atol sim_ch.rtol = rtol sim_ch.verbosity = 50 sim_ch.make_consistent('IDA_YA_YDP_INIT') t_ch, SV_ch, SV_dot_ch = sim_ch.simulate(t_f) SV_ch_df = Label_Columns(t_ch, SV_ch, an.npoints, sep.npoints, cat.npoints) if Inputs.plot_potential_profiles == 1: plot_potential(tags['Phi_an'], tags['Phi_cat'], SV_ch_df, 'Charging', 0, fig1, axes1) if Inputs.plot_electrode_profiles == 1: plot_electrode(tags['X_an'], tags['X_cat'], SV_ch_df, 'Charging', 0, fig2, axes2) if Inputs.plot_elyte_profiles == 1: plot_elyte(tags['X_el_an'], tags['X_el_cat'], tags['X_el_sep'], SV_ch_df, 'Charging', 0, fig3, axes3) print('Done charging\n') """------------Re_equilibrating-------------""" if Inputs.flag_re_equil == 1: # New initial conditions are the final charge conditions SV_0 = SV_ch[-2, :] SV_dot_0 = SV_dot_ch[-2, :] # Equilibrate again. Note - this is a specific choice to reflect # equilibration after the charging steps. We may want, at times, to # simulate a situation where the battery is not equilibrated between # charge and discharge, or is equilibrated for a shorter amount of time. print('\nRe-equilibrating...') current.set_i_ext(0) battery_req = li_ion(li_ion.res_fun, SV_0, SV_dot_0, t_0) battery_req.external_event_detection = True battery_req.algvar = algvar # Simulation parameters sim_req = IDA(battery_req) sim_req.atol = atol sim_req.rtol = rtol sim_req.verbosity = 50 sim_req.make_consistent('IDA_YA_YDP_INIT') t_req, SV_req, SV_dot_req = sim_req.simulate(t_f) SV_req_df = Label_Columns(t_req, SV_req, an.npoints, sep.npoints, cat.npoints) if Inputs.plot_potential_profiles*Inputs.phi_time == 1: plot_potential(tags['Phi_an'], tags['Phi_cat'], SV_req_df, 'Re-equilibrating', 1, None, fig1, axes1) if Inputs.plot_electrode_profiles == 1: plot_electrode(tags['X_an'], tags['X_cat'], SV_req_df, 'Re-equilibrating', 1, fig2, axes2) if Inputs.plot_elyte_profiles == 1: plot_elyte(tags['X_el_an'], tags['X_el_cat'], tags['X_el_sep'], SV_req_df, 'Re-equilibrating', 1, fig3, axes3) print('Done re-equilibrating\n') else: SV_req = SV_ch SV_dot_req = SV_dot_ch SV_req_df = SV_req """------------Discharging-------------""" print('\nDischarging...') SV_0 = SV_req[-1, :] SV_dot_0 = SV_dot_req[-1, :] current.set_i_ext(-current.i_ext_set) battery_dch = li_ion(li_ion.res_fun, SV_0, SV_dot_0, t_0) battery_dch.external_event_detection = True battery_dch.algvar = algvar # Simulation parameters sim_dch = IDA(battery_dch) sim_dch.atol = atol sim_dch.rtol = rtol sim_dch.verbosity = 50 sim_dch.make_consistent('IDA_YA_YDP_INIT') t_dch, SV_dch, SV_dot_dch = sim_dch.simulate(t_f) SV_dch_df = Label_Columns(t_dch, SV_dch, an.npoints, sep.npoints, cat.npoints) if Inputs.plot_potential_profiles == 1: plot_potential(tags['Phi_an'], tags['Phi_cat'], SV_dch_df, 'Discharging', 1+(Inputs.flag_re_equil*Inputs.phi_time), fig1, axes1) if Inputs.plot_electrode_profiles == 1: plot_electrode(tags['X_an'], tags['X_cat'], SV_dch_df, 'Discharging', 1+Inputs.flag_re_equil, fig2, axes2) if Inputs.plot_elyte_profiles == 1: plot_elyte(tags['X_el_an'], tags['X_el_cat'], tags['X_el_sep'], SV_dch_df, 'Discharging', 1+Inputs.flag_re_equil, fig3, axes3) print('Done discharging\n') """---------------------------------""" SV_0 = SV_dch[-1, :] SV_dot_0 = np.zeros_like(SV_0) # %% Plot capacity if flagged plt.show('all') plot_cap(SV_ch_df, SV_dch_df, rate_tag, current.i_ext_set, Inputs.plot_cap_flag, tags) elapsed = time.time() - t_count print('t_cpu=', elapsed, '\n') plt.show() return SV_eq_df, SV_ch_df, SV_req_df, SV_dch_df
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
def DAE_integration_assimulo_lagrangian(self, **kwargs): """ Perform time integration for DAEs with the assimulo package Lagrangian variant """ 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.Vl).vector()[self.bndr_i_l] if self.discontinous_boundary_values == 1: self.U[self.Corner_indices] = self.U[self.Corner_indices]/2 self.UU = np.zeros(self.Nb) for i in range(self.Nb): self.UU[i] = self.boundary_cntrl_space(self.coord_b[i]) # Definition of the sparse solver for the DAE res function to # be defined next M should be invertible !! #my_solver = factorized(csc_matrix(self.M)) #rhs = self.my_mult(self.J, self.my_mult(self.Q,self.A0)) + self.my_mult(self.Bext,self.U* self.boundary_cntrl_time(0.,self.tclose)) #self.AD0 = my_solver(rhs) # Definition of the rhs function required in assimulo def res(t,y,yd): """ Definition of the residual function required in the DAE part of assimulo """ z = np.zeros(self.Np+self.Nl) z[0:self.Np] = self.my_mult(self.M_class, yd[0:self.Np]) + self.my_mult(self.D_class, y[0:self.Np]) - self.my_mult(self.C_class, y[self.Np:]) z[self.Np:self.Np+self.Nl] = self.my_mult(self.C_class.T, y[0:self.Np]) - self.L_class * self.boundary_cntrl_time(t,self.tclose) return z # Definition of the jacobian function required in assimulo def jac(c,t,y,yd): """ Definition of the Jacobian matrix required in the DAE part of assimulo """ #Matrix = csr_matrix(self.my_mult(self.J,self.Q)) #if close and t > self.tclose: # Matrix = csr_matrix(self.my_mult(self.J - self.R, self.Q)) #return c*csr_matrix(self.M) - Matrix return None # Definition of the jacobian matrix vector function required in assimulo def jacv(t,y,yd,res,v,c): """ Jacobian matrix-vector product required in the DAE part of assimulo """ #w = self.my_mult(self.Q, v) #z = self.my_mult(self.J, w) #if close and t > self.tclose: # z -= self.my_mult(self.R, w) #return c*self.my_mult(self.M,v) - z return None print('DAE Integration using assimulo built-in functions:') #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 = np.concatenate(( self.Tp0, np.zeros(self.Nl) )) yd0 = np.zeros(self.Np + self.Nl) model = Implicit_Problem(res,y0,yd0,self.tinit) #model.handle_result = handle_result #model.jacv = jacv #sim = Radau5DAE(model,**kwargs) # # IDA method from Assimulo # sim = IDA(model,**kwargs) sim.algvar = list(np.concatenate((np.ones(self.Np), np.zeros(self.Nl) )) ) sim.atol = 1.e-6 sim.rtol = 1.e-6 sim.report_continuously = True ncp = self.Nt #sim.usejac = True sim.suppress_alg = True sim.inith = self.dt sim.maxord = 5 #sim.linear_solver = 'SPGMR' sim.make_consistent('IDA_YA_YDP_INIT') #time_span, DAE_y, DAE_yd = sim.simulate(self.tfinal,ncp, self.tspan) time_span, DAE_y, DAE_yd = sim.simulate(self.tfinal, 0, self.tspan) #print(sim.get_options()) print(sim.print_statistics()) A_dae = DAE_y[:,0:self.Np].transpose() # Hamiltonian self.Nt = A_dae.shape[1] self.tspan = np.array(time_span) Ham_dae = np.zeros(self.Nt) for k in range(self.Nt): Ham_dae[k] = 1/2 * self.my_mult(A_dae[:,k].T, \ self.my_mult(self.Mp_rho_Cv, A_dae[:,k])) self.Ham_dae = Ham_dae return Ham_dae, np.array(time_span)
class ReactorSolverAssimulo(ReactorSolverBase): def __init__(self,reactor,**params): #Initialize base solver class ReactorSolverBase.__init__(self,reactor,**params) #### SOLVER PARAMETERS ####: self.iter = params.get('iter','Newton') #Iteration method (Newton or FixedPoint) self.discr = params.get('discr','BDF') #Discretization method (BDF or Adams) #Set up the linear solver from the following list: # ['DENSE'(= default) or 'SPGMR'] self.linear_solver = params.get('linear_solver','DENSE') #Boolean value to turn OFF Sundials LineSearch when calculating #initial conditions (IDA only) self.lsoff = params.get('lsoff',False) def solve_ode(self): #Get initial conditions vector self.init_conditions() #Instantiate reactor as ODE class self._rode = AssimuloODE(self._r,self._r.z_in,self.y0) #Define the CVode solver self.solver = CVode(self._rode) #Solver parameters self.solver.atol = self.atol self.solver.rtol = self.rtol self.solver.iter = self.iter self.solver.discr = self.discr self.solver.linear_solver = self.linear_solver self.solver.maxord = self.order self.solver.maxsteps = self.max_steps self.solver.inith = self.first_step_size self.solver.minh = self.min_step_size self.solver.maxh = self.max_step_size self.solver.maxncf = self.max_conv_fails self.solver.maxnef = self.max_nonlin_iters self.solver.stablimdet = self.bdf_stability self.solver.verbosity = 50 #Solve the equations z, self.values = self.solver.simulate(self._r.z_out,self.grid-1) #Convert axial coordinates list to array self._z = np.array(z) def solve_dae(self): #Get initial conditions vector self.init_conditions() #Initial derivatives vector self.yd0 = np.zeros(len(self.y0)) #Instantiate reactor as DAE class self._rdae = AssimuloDAE(self._r,self._r.z_in, self.y0,self.yd0) #Get list of differential and algebraic variables varlist = np.ones(len(self.y0)) #Set algebraic variables varlist[self._rdae.p1:] = 0.0 #Set up the solver and its parameters self.solver = IDA(self._rdae) self.solver.atol = self.atol self.solver.rtol = self.rtol self.solver.linear_solver = self.linear_solver self.solver.maxord = self.order self.solver.maxsteps = self.max_steps self.solver.inith = self.first_step_size self.solver.maxh = self.max_step_size self.solver.algvar = varlist self.solver.make_consistent('IDA_YA_YDP_INIT') self.solver.tout1 = 1e-06 self.solver.suppress_alg = self.exclude_algvar_from_error self.solver.lsoff = self.lsoff self.solver.verbosity = 50 #Solve the DAE equation system z, self.values, self.valuesd = self.solver.simulate(self._r.z_out, self.grid-1) #Convert axial coordinates list to array self._z = np.array(z)
def main(): res_class = eval(inputs.test_type) # plt.close('all') t_count = time.time() SV_0 = sol_init.SV_0 SV_dot_0 = np.zeros_like(SV_0) t_0 = 0. t_f = 3600. / inputs.C_rate algvar = sol_init.algvar atol = np.ones_like(SV_0) * 1e-5 atol[cat.ptr_vec['eps_S8']] = 1e-25 atol[cat.ptr_vec['eps_Li2S']] = 1e-25 atol[cat.ptr_vec['rho_k_el']] = 1e-25 # atol = 1e-30; rtol = 1e-4 sim_output = 50 rate_tag = str(inputs.C_rate) + "C" fig, axes = plt.subplots(sharey="row", figsize=(9, 12), nrows=3, ncols=1) plt.subplots_adjust(wspace=0.15, hspace=0.4) fig.text(0.15, 0.8, rate_tag, fontsize=20, bbox=dict(facecolor='white', alpha=0.5)) # Set up user function to build figures based on inputs "----------Equilibration----------" print('\nEquilibrating...') # Set external current to 0 for equilibration cat.set_i_ext(0) # Create problem object bat_eq = res_class(res_class.res_fun, SV_0, SV_dot_0, t_0) bat_eq.external_event_detection = True bat_eq.algvar = algvar # Create simulation object sim_eq = IDA(bat_eq) sim_eq.atol = atol sim_eq.rtol = rtol sim_eq.verbosity = sim_output sim_eq.make_consistent('IDA_YA_YDP_INIT') t_eq, SV_eq, SV_dot_eq = sim_eq.simulate(t_f) # Put solution into pandas dataframe with labeled columns SV_eq_df = label_columns(t_eq, SV_eq, an.npoints, sep.npoints, cat.npoints) # SV_eq_df = [] # Obtain tag strings for dataframe columns tags = tag_strings(SV_eq_df) # plot_sim(tags, SV_eq_df, 'Equilibrating', 0, fig, axes) # print(SV_eq_df[tags['rho_el'][4:10]].iloc[-1]) print('Done equilibrating\n') "------------Discharging-------------" print('Discharging...') # New initial conditions from previous simulation SV_0 = SV_eq[-1, :] SV_dot_0 = SV_dot_eq[-1, :] # Set external current cat.set_i_ext(cat.i_ext_amp) # Update problem instance initial conditions bat_dch = res_class(res_class.res_fun, SV_0, SV_dot_0, t_0) bat_dch.external_event_detection = True bat_dch.algvar = algvar # Re-initialize simulation object sim_dch = IDA(bat_dch) sim_dch.atol = atol sim_dch.rtol = rtol sim_dch.maxh = 5 sim_dch.verbosity = sim_output sim_dch.make_consistent('IDA_YA_YDP_INIT') t_dch, SV_dch, SV_dot_dch = sim_dch.simulate(t_f) # if hasattr(cathode, 'get_tflag'): # t_flag_ch = cathode.get_tflag SV_dch_df = label_columns(t_dch, SV_dch, an.npoints, sep.npoints, cat.npoints) # SV_dch_df = [] # Obtain tag strings for dataframe columns # tags = tag_strings(SV_ch_df) plot_sim(tags, SV_dch_df, 'Discharging', 1, fig, axes) plot_meanPS(SV_dch_df, tags) print('Done Discharging\n') "--------Re-equilibration---------" # if inputs.flag_req == 1: # # print('Re-equilibrating...') # # # New initial conditions from previous simulation # SV_0 = SV_ch[-1, :] # SV_dot_0 = SV_dot_ch[-1, :] # # # Set external current # cat.set_i_ext(0) # # # Update problem instance initial conditions # bat_req = res_class(res_class.res_fun, SV_0, SV_dot_0, t_0) # bat_req.external_event_detection = True # bat_req.algvar = algvar # # # Re-initialize simulation object # sim_req = IDA(bat_req) # sim_req.atol = atol # sim_req.rtol = rtol # sim_req.verbosity = sim_output # sim_req.make_consistent('IDA_YA_YDP_INIT') # # t_req, SV_req, SV_dot_req = sim_req.simulate(t_f) # # SV_req_df = label_columns(t_req, SV_req, an.npoints, sep.npoints, cat.npoints) # ## plot_sim(tags, SV_req_df, 'Re-Equilibrating', 2-1, fig, axes) # # print('Done re-equilibrating\n') # else: # SV_req = SV_ch # SV_dot_req = SV_dot_ch "-----------Charging-----------" # print('Charging...') # # SV_0 = SV_req[-1, :] # SV_dot_0 = SV_dot_req[-1, :] # # cat.set_i_ext(-cat.i_ext_amp) # # # Update problem instance initial conditions # bat_dch = res_class(res_class.res_fun, SV_0, SV_dot_0, t_0) # bat_dch.external_event_detection = True # bat_dch.algvar = algvar # # # Re-initialize simulation object # sim_dch = IDA(bat_dch) # sim_dch.atol = atol # sim_dch.rtol = rtol # sim_dch.verbosity = sim_output # sim_dch.make_consistent('IDA_YA_YDP_INIT') # # t_dch, SV_dch, SV_dot_dch = sim_dch.simulate(t_f) # ## if hasattr(cathode, 'get_tflag'): ## t_flag_dch = cathode.get_tflag # # SV_dch_df = label_columns(t_dch, SV_dch, an.npoints, sep.npoints, cat.npoints) # # plot_sim(tags, SV_dch_df, 'Charging', 3, fig, axes) # # print('Done Charging\n') t_elapsed = time.time() - t_count print('t_cpu=', t_elapsed, '\n') return SV_eq_df, SV_dch_df, tags #SV_eq_df, SV_req_df #, SV_dch_df
raise Exception('Please select a valid simulation mode." + \ " Available options are "detailed", "homogeneous", and "reduced"') print('\n Running simulation\n') # Set up problem instance SEI_1D = Implicit_Problem(residual, SV_0, SV_dot_0) SEI_1D.algvar = algvar # Define simulation parameters simulation = IDA(SEI_1D) # Create simulation instance simulation.atol = 1e-8 # Solver absolute tolerance simulation.rtol = 1e-4 # Solver relative tolerance #simulation.maxh = 55 # Solver max step size simulation.make_consistent('IDA_YA_YDP_INIT') # Set simulation end time, slope flag (for anode voltage cycle), and run simulation t_f = times[-1] #ncp_list = np.arange(0, t_f, 0.15) #ncp = 10000 " Run the simulation " "------------------------------------------------------------------------------" t, SV, SV_dot = simulation.simulate(t_f) " Organize, plot, and save the data:" "----------------------------------------------------------------------------------" # This function creates a dataframe and adds labels to each element in the SV: