Skip to content

Commit

Permalink
#692 adding features to base solver to allow external variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Scottmar93 committed Nov 9, 2019
1 parent 065d6e0 commit 9fe3a3d
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 13 deletions.
12 changes: 11 additions & 1 deletion pybamm/discretisations/discretisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,17 @@ def process_model(self, model, inplace=True):
model_disc.bcs = self.bcs

self.external_variables = model.external_variables
# find where external variables begin in state vector
start_vals = []
for var in self.external_variables:
if isinstance(var, pybamm.Concatenation):
for child in var.children:
start_vals += [self.y_slices[child.id][0].start]
elif isinstance(var, pybamm.Variable):
start_vals += [self.y_slices[var.id][0].start]

self.external_start = min(start_vals)

# Process initial condtions
pybamm.logger.info("Discretise initial conditions for {}".format(model.name))
ics, concat_ics = self.process_initial_conditions(model)
model_disc.initial_conditions = ics
Expand Down Expand Up @@ -223,6 +232,7 @@ def set_variable_slices(self, variables):
start = end

self.y_slices = y_slices
self.y_length = end

# reset discretised_symbols
self._discretised_symbols = {}
Expand Down
21 changes: 21 additions & 0 deletions pybamm/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,27 @@ def solve(self, t_eval=None, solver=None):

self._solution = solver.solve(self.built_model, t_eval)

def step(self, dt, solver=None, external_variables=None):
"""
A method to step the model forward one timestep. This method will
automatically build and set the model parameters if not already done so.
Parameters
----------
dt : numeric type
The timestep over which to step the solution
solver : :class:`pybamm.BaseSolver`
The solver to use to solve the model.
external_variables : dict
A dictionary of external variables and their corresponding
values at the current time
"""

if solver is None:
solver = self.solver

self._solution = solver.step(self.built_model, dt, external_variables)

def plot(self, quick_plot_vars=None):
"""
A method to quickly plot the outputs of the simulation.
Expand Down
20 changes: 19 additions & 1 deletion pybamm/solvers/base_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def solve(self, model, t_eval):
)
return solution

def step(self, model, dt, npts=2, log=True):
def step(self, model, dt, npts=2, log=True, external_variables=None):
"""
Step the solution of the model forward by a given time increment. The
first time this method is called it executes the necessary setup by
Expand All @@ -113,6 +113,9 @@ def step(self, model, dt, npts=2, log=True):
npts : int, optional
The number of points at which the solution will be returned during
the step dt. default is 2 (returns the solution at t0 and t0 + dt).
external_variables : dict
A dictionary of external variables and their corresponding
values at the current time
Raises
------
Expand Down Expand Up @@ -147,6 +150,21 @@ def step(self, model, dt, npts=2, log=True):
else:
set_up_time = None

# load external variables into a state vector
self.y_ext = np.zeros((model.y_length, 1))
for var_name, var_vals in external_variables.items():
var = model.variables[var_name]
if isinstance(var, pybamm.Concatenation):
start = model.y_slices[var.children[0].id][0].start
stop = model.y_slices[var.children[-1].id][-1].stop
y_slice = slice(start, stop)

elif isinstance(var, pybamm.Variable):
start = model.y_slices[var.id][0].start
stop = model.y_slices[var.id][-1].stop
y_slice = slice(start, stop)
self.y_ext[y_slice] = var_vals

# Step
t_eval = np.linspace(self.t, self.t + dt, npts)
solution, solve_time, termination = self.compute_solution(model, t_eval)
Expand Down
9 changes: 0 additions & 9 deletions pybamm/spatial_methods/finite_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,6 @@ def preprocess_external_variables(self, var):
A dictionary containing the new boundary conditions
"""

if isinstance(var, pybamm.Concatenation):
left_var = var.children[0]
right_var = var.children[-1]
else:
left_var = var
right_var = var

print("hello")

new_bcs = {
var: {
"left": (pybamm.BoundaryGradient(var, "left"), "Neumann"),
Expand Down
3 changes: 3 additions & 0 deletions pybamm/spatial_methods/spatial_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ def internal_neumann_condition(

raise NotImplementedError

def preprocess_external_variables(self, var):
return {}

def boundary_value_or_flux(self, symbol, discretised_child):
"""
Returns the boundary value or flux using the approriate expression for the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,43 @@
#
import pybamm
import unittest
import numpy as np


# only works for statevector inputs
class TestExternalSubmodel(unittest.TestCase):
def test_external_temperature(self):

model_options = {"thermal": "x-full", "external submodels": ["thermal"]}
model_options = {
"thermal": "x-full",
"external submodels": ["thermal"],
}

model = pybamm.lithium_ion.SPMe(model_options)

sim = pybamm.Simulation(model)
neg_pts = 5
sep_pts = 3
pos_pts = 5
tot_pts = neg_pts + sep_pts + pos_pts

var_pts = {
pybamm.standard_spatial_vars.x_n: neg_pts,
pybamm.standard_spatial_vars.x_s: sep_pts,
pybamm.standard_spatial_vars.x_p: pos_pts,
pybamm.standard_spatial_vars.r_n: 5,
pybamm.standard_spatial_vars.r_p: 5,
}

sim = pybamm.Simulation(model, var_pts=var_pts)
sim.build()

t_eval = np.linspace(0, 0.17, 100)

for t in t_eval:
T = np.zeros((tot_pts, 1))
external_variables = {"Cell temperature": T}
sim.step(external_variables=external_variables)


if __name__ == "__main__":
print("Add -v for more debug output")
Expand Down

0 comments on commit 9fe3a3d

Please sign in to comment.