Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 944 autodisc #947

Merged
merged 4 commits into from
Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Features

- Added functionality to solver to automatically discretise a 0D model ([#947](https://github.com/pybamm-team/PyBaMM/pull/947))
- Made `QuickPlot` compatible with Google Colab ([#935](https://github.com/pybamm-team/PyBaMM/pull/935))
- Added `BasicFull` model for lead-acid ([#932](https://github.com/pybamm-team/PyBaMM/pull/932))

Expand Down
10 changes: 10 additions & 0 deletions pybamm/discretisations/discretisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ def process_model(self, model, inplace=True, check_model=True):
# Prepare discretisation
# set variables (we require the full variable not just id)
variables = list(model.rhs.keys()) + list(model.algebraic.keys())
if self.spatial_methods == {} and any(var.domain != [] for var in variables):
for var in variables:
if var.domain != []:
raise pybamm.DiscretisationError(
"Spatial method has not been given "
"for variable {} with domain {}".format(var.name, var.domain)
)

# Set the y split for variables
pybamm.logger.info("Set variable slices for {}".format(model.name))
Expand Down Expand Up @@ -203,6 +210,9 @@ def process_model(self, model, inplace=True, check_model=True):

pybamm.logger.info("Finish discretising {}".format(model.name))

# Record that the model has been discretised
model_disc.is_discretised = True

return model_disc

def set_variable_slices(self, variables):
Expand Down
8 changes: 8 additions & 0 deletions pybamm/expression_tree/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,11 @@ class InputError(Exception):
"""

pass


class DiscretisationError(Exception):
"""
A model could not be discretised
"""

pass
3 changes: 3 additions & 0 deletions pybamm/models/base_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ def __init__(self, name="Unnamed model"):
self.use_simplify = True
self.convert_to_format = "casadi"

# Model is not initially discretised
self.is_discretised = False

# Default timescale is 1 second
self.timescale = pybamm.Scalar(1)

Expand Down
18 changes: 13 additions & 5 deletions pybamm/solvers/base_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ def set_up(self, model, inputs=None):
raise pybamm.SolverError(
"""Cannot use algebraic solver to solve model with time derivatives"""
)
# Discretise model if it isn't already discretised
# This only works with purely 0D models, as otherwise the mesh and spatial
# method should be specified by the user
if model.is_discretised is False:
try:
disc = pybamm.Discretisation()
disc.process_model(model)
except pybamm.DiscretisationError as e:
raise pybamm.DiscretisationError(
"Cannot automatically discretise model, "
"model should be discretised before solving ({})".format(e)
)

inputs = inputs or {}
y0 = model.concatenated_initial_conditions.evaluate(0, None, inputs=inputs)
Expand Down Expand Up @@ -564,11 +576,7 @@ def solve(self, model, t_eval=None, external_variables=None, inputs=None):
]

# remove any discontinuities after end of t_eval
discontinuities = [
v
for v in discontinuities
if v < t_eval_dimensionless[-1]
]
discontinuities = [v for v in discontinuities if v < t_eval_dimensionless[-1]]

if len(discontinuities) > 0:
pybamm.logger.info(
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/test_solvers/test_base_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,29 @@ def algebraic_eval(self, t, y, inputs):
):
solver.calculate_consistent_state(Model())

def test_discretise_model(self):
# Make sure 0D model is automatically discretised
model = pybamm.BaseModel()
v = pybamm.Variable("v")
model.rhs = {v: -1}
model.initial_conditions = {v: 1}

solver = pybamm.BaseSolver()
self.assertFalse(model.is_discretised)
solver.set_up(model, {})
self.assertTrue(model.is_discretised)

# 1D model cannot be automatically discretised
model = pybamm.BaseModel()
v = pybamm.Variable("v", domain="line")
model.rhs = {v: -1}
model.initial_conditions = {v: 1}

with self.assertRaisesRegex(
pybamm.DiscretisationError, "Cannot automatically discretise model"
):
solver.set_up(model, {})

def test_convert_to_casadi_format(self):
# Make sure model is converted to casadi format
model = pybamm.BaseModel()
Expand Down