From 97f9a67d2b0aeeb04e212f64498bb0e4ab6506fe Mon Sep 17 00:00:00 2001 From: Scott Marquis Date: Sat, 9 Nov 2019 18:10:58 +0000 Subject: [PATCH] #692 structure for external variables in place but need to debug --- pybamm/discretisations/discretisation.py | 5 ++++- pybamm/simulation.py | 4 +++- pybamm/solvers/base_solver.py | 19 +++++++++++++++++++ pybamm/solvers/dae_solver.py | 2 ++ pybamm/solvers/ode_solver.py | 6 ++++++ .../test_use_external_submodel.py | 5 +++-- 6 files changed, 37 insertions(+), 4 deletions(-) diff --git a/pybamm/discretisations/discretisation.py b/pybamm/discretisations/discretisation.py index 55e0416e28..57e5726c95 100644 --- a/pybamm/discretisations/discretisation.py +++ b/pybamm/discretisations/discretisation.py @@ -150,7 +150,10 @@ def process_model(self, model, inplace=True): elif isinstance(var, pybamm.Variable): start_vals += [self.y_slices[var.id][0].start] - self.external_start = min(start_vals) + model_disc.external_variables = model.external_variables + model_disc.external_start = min(start_vals) + model_disc.y_length = self.y_length + model_disc.y_slices = self.y_slices pybamm.logger.info("Discretise initial conditions for {}".format(model.name)) ics, concat_ics = self.process_initial_conditions(model) diff --git a/pybamm/simulation.py b/pybamm/simulation.py index 01674881f3..148c83976b 100644 --- a/pybamm/simulation.py +++ b/pybamm/simulation.py @@ -134,7 +134,9 @@ def step(self, dt, solver=None, external_variables=None): if solver is None: solver = self.solver - self._solution = solver.step(self.built_model, dt, external_variables) + self._solution = solver.step( + self.built_model, dt, external_variables=external_variables + ) def plot(self, quick_plot_vars=None): """ diff --git a/pybamm/solvers/base_solver.py b/pybamm/solvers/base_solver.py index 690086aca4..17e9f38a28 100644 --- a/pybamm/solvers/base_solver.py +++ b/pybamm/solvers/base_solver.py @@ -22,6 +22,9 @@ def __init__(self, method=None, rtol=1e-6, atol=1e-6): self._atol = atol self.name = "Base solver" + self.y_pad = None + self.y_ext = None + @property def method(self): return self._method @@ -147,9 +150,16 @@ def step(self, model, dt, npts=2, log=True, external_variables=None): self.set_up(model) self.t = 0.0 set_up_time = timer.time() + + # create a y_pad vector of the correct size: + self.y_pad = np.zeros((model.external_start)) + else: set_up_time = None + if external_variables is None: + external_variables = {} + # 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(): @@ -193,6 +203,15 @@ def step(self, model, dt, npts=2, log=True, external_variables=None): ) return solution + def add_external(self, y): + """ + Pad the state vector and then add the external variables so that + it is of the correct shape for evaluate + """ + if self.y_pad and self.y_ext: + y = np.concatenate(y, self.y_pad) + self.y_ext + return y + def compute_solution(self, model, t_eval): """Calculate the solution of the model at specified times. Note: this does *not* execute the solver setup. diff --git a/pybamm/solvers/dae_solver.py b/pybamm/solvers/dae_solver.py index 74001b7b9c..1839329e45 100644 --- a/pybamm/solvers/dae_solver.py +++ b/pybamm/solvers/dae_solver.py @@ -188,6 +188,7 @@ def residuals(t, y, ydot): pybamm.logger.debug( "Evaluating residuals for {} at t={}".format(model.name, t) ) + y = self.add_external(y) y = y[:, np.newaxis] rhs_eval, known_evals = concatenated_rhs.evaluate(t, y, known_evals={}) # reuse known_evals @@ -202,6 +203,7 @@ def residuals(t, y, ydot): # Create event-dependent function to evaluate events def event_fun(event): def eval_event(t, y): + y = self.add_external(y) return event.evaluate(t, y) return eval_event diff --git a/pybamm/solvers/ode_solver.py b/pybamm/solvers/ode_solver.py index a1655d745f..bc779b24ec 100644 --- a/pybamm/solvers/ode_solver.py +++ b/pybamm/solvers/ode_solver.py @@ -121,6 +121,7 @@ def set_up(self, model): # Create function to evaluate rhs def dydt(t, y): pybamm.logger.debug("Evaluating RHS for {} at t={}".format(model.name, t)) + y = self.add_external(y) y = y[:, np.newaxis] dy = concatenated_rhs.evaluate(t, y, known_evals={})[0] return dy[:, 0] @@ -128,6 +129,7 @@ def dydt(t, y): # Create event-dependent function to evaluate events def event_fun(event): def eval_event(t, y): + y = self.add_external(y) return event.evaluate(t, y) return eval_event @@ -138,6 +140,7 @@ def eval_event(t, y): if jac_rhs is not None: def jacobian(t, y): + y = self.add_external(y) return jac_rhs.evaluate(t, y, known_evals={})[0] else: @@ -193,6 +196,7 @@ def set_up_casadi(self, model): def dydt(t, y): pybamm.logger.debug("Evaluating RHS for {} at t={}".format(model.name, t)) + y = self.add_external(y) dy = concatenated_rhs_fn(t, y).full() return dy[:, 0] @@ -201,6 +205,7 @@ def event_fun(event): casadi_event_fn = casadi.Function("event", [t_casadi, y_casadi], [event]) def eval_event(t, y): + y = self.add_external(y) return casadi_event_fn(t, y) return eval_event @@ -216,6 +221,7 @@ def eval_event(t, y): ) def jacobian(t, y): + y = self.add_external(y) return casadi_jac_fn(t, y) else: diff --git a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_use_external_submodel.py b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_use_external_submodel.py index f1e1976891..fee8cd3582 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_use_external_submodel.py +++ b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_use_external_submodel.py @@ -35,10 +35,11 @@ def test_external_temperature(self): t_eval = np.linspace(0, 0.17, 100) - for t in t_eval: + for i, t in enumerate(t_eval): + dt = t_eval[i + 1] - t_eval[i] T = np.zeros((tot_pts, 1)) external_variables = {"Cell temperature": T} - sim.step(external_variables=external_variables) + sim.step(dt, external_variables=external_variables) if __name__ == "__main__":