def test_processed_variable_ode_pde_solution(self): # without space model = pybamm.BaseBatteryModel() c = pybamm.Variable("conc") model.rhs = {c: -c} model.initial_conditions = {c: 1} model.variables = {"c": c} modeltest = tests.StandardModelTest(model) modeltest.test_all() t_sol, y_sol = modeltest.solution.t, modeltest.solution.y processed_vars = pybamm.post_process_variables(model.variables, t_sol, y_sol) np.testing.assert_array_almost_equal(processed_vars["c"](t_sol), np.exp(-t_sol)) # with space # set up and solve model whole_cell = ["negative electrode", "separator", "positive electrode"] model = pybamm.BaseBatteryModel() c = pybamm.Variable("conc", domain=whole_cell) c_s = pybamm.Variable( "particle conc", domain="negative particle", auxiliary_domains={"secondary": ["negative electrode"]}, ) model.rhs = {c: -c, c_s: 1 - c_s} model.initial_conditions = {c: 1, c_s: 0.5} model.boundary_conditions = { c: { "left": (0, "Neumann"), "right": (0, "Neumann") }, c_s: { "left": (0, "Neumann"), "right": (0, "Neumann") }, } model.variables = { "c": c, "N": pybamm.grad(c), "c_s": c_s, "N_s": pybamm.grad(c_s), } modeltest = tests.StandardModelTest(model) modeltest.test_all() # set up testing t_sol, y_sol = modeltest.solution.t, modeltest.solution.y x = pybamm.SpatialVariable("x", domain=whole_cell) x_sol = modeltest.disc.process_symbol(x).entries[:, 0] processed_vars = pybamm.post_process_variables(model.variables, t_sol, y_sol, modeltest.disc.mesh) # test np.testing.assert_array_almost_equal( processed_vars["c"](t_sol, x_sol), np.ones_like(x_sol)[:, np.newaxis] * np.exp(-t_sol), )
def __init__(self, model, parameter_values, disc, solution): # Process variables model.variables = pybamm.post_process_variables( model.variables, solution.t, solution.y, disc.mesh ) # Assign attributes self.model = model self.parameter_values = parameter_values self.disc = disc self.solution = solution if isinstance(self.model, pybamm.lithium_ion.BaseModel): self.chemistry = "Lithium-ion" elif isinstance(self.model, pybamm.lead_acid.BaseModel): self.chemistry = "Lead acid" # Only for constant current current_sign = np.sign( parameter_values["Current function"].parameters_eval["Current [A]"] ) if current_sign == 1: self.operating_condition = "discharge" elif current_sign == -1: self.operating_condition = "charge" else: self.operating_condition = "off"
def model_comparison(models, Crates, t_eval, extra_parameter_values=None): " Solve models at a range of Crates " # load parameter values and geometry geometry = models[0].default_geometry extra_parameter_values = extra_parameter_values or {} param = models[0].default_parameter_values param.update(extra_parameter_values) # Process parameters (same parameters for all models) for model in models: param.process_model(model) param.process_geometry(geometry) # set mesh var = pybamm.standard_spatial_vars var_pts = {var.x_n: 20, var.x_s: 20, var.x_p: 20} mesh = pybamm.Mesh(geometry, models[-1].default_submesh_types, var_pts) # discretise models discs = {} for model in models: disc = pybamm.Discretisation(mesh, model.default_spatial_methods) disc.process_model(model) # Store discretisation discs[model] = disc # solve model for range of Crates all_variables = {} for Crate in Crates: all_variables[Crate] = {} current = Crate * 17 pybamm.logger.info("Setting typical current to {} A".format(current)) param.update({"Typical current [A]": current}) for model in models: param.update_model(model, discs[model]) solution = model.default_solver.solve(model, t_eval) variables = pybamm.post_process_variables( model.variables, solution.t, solution.y, mesh ) variables["solution"] = solution all_variables[Crate][model.name] = variables return all_variables, t_eval
def __init__(self, models, discs, solutions): # Process variables for model in models: disc = discs[model] solution = solutions[model] model.variables = pybamm.post_process_variables( model.variables, solution.t, solution.y, disc.mesh) self.models = models self.discs = discs self.solutions = solutions if isinstance(self.models[0], pybamm.lithium_ion.BaseModel): self.chemistry = "Lithium-ion" elif isinstance(self.models[0], pybamm.lead_acid.BaseModel): self.chemistry = "Lead acid" self.t = self.get_output_times() self.mesh = self.get_mesh()
def set_output_variables(self, output_variables, solutions, models, meshes): # Set up output variables self.variables = {} self.spatial_variable = {} # Calculate subplot positions based on number of variables supplied self.subplot_positions = {} self.n_rows = int(len(output_variables) // np.sqrt(len(output_variables))) self.n_cols = int(np.ceil(len(output_variables) / self.n_rows)) # Process output variables into a form that can be plotted processed_variables = {} for i, model in enumerate(models): variables_to_process = {} for variable_list in output_variables: # Make sure we always have a list of lists of variables if isinstance(variable_list, str): variable_list = [variable_list] # Add all variables to the list of variables that should be processed variables_to_process.update( {var: model.variables[var] for var in variable_list} ) processed_variables[model] = pybamm.post_process_variables( variables_to_process, solutions[i].t, solutions[i].y, meshes[i] ) # Prepare dictionary of variables for k, variable_list in enumerate(output_variables): # Make sure we always have a list of lists of variables if isinstance(variable_list, str): variable_list = [variable_list] # Prepare list of variables key = tuple(variable_list) self.variables[key] = [None] * len(models) # process each variable in variable_list for each model for i, model in enumerate(models): # self.variables is a dictionary of lists of lists self.variables[key][i] = [ processed_variables[model][var] for var in variable_list ] # Make sure variables have the same dimensions and domain domain = self.variables[key][0][0].domain for variable in self.variables[key][0]: if variable.domain != domain: raise ValueError("mismatching variable domains") # Set the x variable for any two-dimensional variables if self.variables[key][0][0].dimensions == 2: variable_key = self.variables[key][0][0].spatial_var_name variable_value = meshes[0].combine_submeshes(*domain)[0].edges self.spatial_variable[key] = (variable_key, variable_value) # Don't allow 3D variables elif any(var.dimensions == 3 for var in self.variables[key][0]): raise NotImplementedError("cannot plot 3D variables") # Define subplot position self.subplot_positions[key] = (self.n_rows, self.n_cols, k + 1)
var.x_p: 5, var.r_n: 5, var.r_p: 5, var.y: 5, var.z: 5, } mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts) disc = pybamm.Discretisation(mesh, model.default_spatial_methods) disc.process_model(model) # solve model solutions = [None] * len(models) t_eval = np.linspace(0, 3, 1000) for i, model in enumerate(models): solution = model.default_solver.solve(model, t_eval) solutions[i] = solution pybamm.post_process_variables(model.variables, solution.t, solution.y, mesh=mesh) # plot output_variables = [ "Local current collector potential difference [V]", "Negative current collector potential [V]", "Positive current collector potential [V]", "X-averaged electrolyte concentration", # "Leading-order current collector current density", "Current collector current density", "Terminal voltage [V]", ] plot = pybamm.QuickPlot(models, mesh, solutions, output_variables) plot.dynamic_plot()