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 688 add simulation class #693

Merged
merged 20 commits into from
Oct 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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 Simulation class ([#693](https://github.com/pybamm-team/PyBaMM/pull/693))
- Add interface to CasADi solver ([#687](https://github.com/pybamm-team/PyBaMM/pull/687))
- Add option to use CasADi's Algorithmic Differentiation framework to calculate Jacobians ([#687](https://github.com/pybamm-team/PyBaMM/pull/687))
- Add method to evaluate parameters more easily ([#669](https://github.com/pybamm-team/PyBaMM/pull/669))
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@ Python Battery Mathematical Modelling solves continuum models for batteries, usi

## How do I use PyBaMM?

PyBaMM comes with a number of [detailed examples](examples/notebooks/README.md), hosted here on
The easiest way to use PyBaMM is to run a 1C constant-current discharge with a model of your choice with all the default settings:
```python3
import pybamm
model = pybamm.lithium_ion.DFN() # Doyle-Fuller-Newman model
sim = pybamm.Simulation(model)
sim.solve()
sim.plot()
```
However, much greater customisation is available. It is possible to change the physics, parameter values, geometry, submesh type, number of submesh points, methods for spatial discretisation and solver for integration (see DFN [script](examples/scripts/DFN.py) or [notebook](examples/notebooks/models/dfn.ipynb)).

Further details can be found in a number of [detailed examples](examples/notebooks/README.md), hosted here on
github. In addition, there is a [full API documentation](http://pybamm.readthedocs.io/),
hosted on [Read The Docs](readthedocs.io). A set of slides giving an overview of PyBaMM
can be found
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Contents
source/solvers/index
source/processed_variable
source/util
source/simulation

Examples
========
Expand Down
5 changes: 5 additions & 0 deletions docs/source/simulation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Simulation
==========

.. autoclass:: pybamm.Simulation
:members:
2 changes: 1 addition & 1 deletion examples/notebooks/models/compare-lithium-ion.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
"version": "3.7.3"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion examples/notebooks/parameter-values.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
"version": "3.7.3"
}
},
"nbformat": 4,
Expand Down
7 changes: 7 additions & 0 deletions examples/scripts/run_simulation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import pybamm

model = pybamm.lithium_ion.SPM()

sim = pybamm.Simulation(model)
sim.solve()
sim.plot()
3 changes: 2 additions & 1 deletion pybamm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ def version(formatted=False):
from .solvers.scipy_solver import ScipySolver
from .solvers.idaklu_solver import IDAKLUSolver, have_idaklu


#
# Current profiles
#
Expand All @@ -285,6 +284,8 @@ def version(formatted=False):
from .processed_variable import post_process_variables, ProcessedVariable
from .quick_plot import QuickPlot, ax_min, ax_max

from .simulation import Simulation

#
# Remove any imported modules, so we don't expose them as part of pybamm
#
Expand Down
4 changes: 2 additions & 2 deletions pybamm/discretisations/discretisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ def process_model(self, model, inplace=True):
# since they point to the same object
model_disc = model
else:
# create a blank model so that original model is unchanged
model_disc = pybamm.BaseModel()
# create a model of the same class as the original model
model_disc = model.__class__(model.options)
model_disc.name = model.name
model_disc.options = model.options
model_disc.use_jacobian = model.use_jacobian
Expand Down
43 changes: 32 additions & 11 deletions pybamm/parameters/parameter_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,13 @@ def check_and_update_parameter_values(self, values):
values["C-rate"] = float(values["Typical current [A]"]) / capacity
return values

def process_model(self, model, processing="process"):
def process_model(self, unprocessed_model, processing="process", inplace=True):
"""Assign parameter values to a model.
Currently inplace, could be changed to return a new model.

Parameters
----------
model : :class:`pybamm.BaseModel`
unprocessed_model : :class:`pybamm.BaseModel`
Model to assign parameter values for
processing : str, optional
Flag to indicate how to process model (default 'process')
Expand All @@ -226,38 +226,57 @@ def process_model(self, model, processing="process"):
and replace any Parameter with a Value)
* 'update': Calls :meth:`update_scalars()` for use on already-processed \
model (update the value of any Scalars in the expression tree.)
inplace: bool, optional
If True, replace the parameters in the model in place. Otherwise, return a
new model with parameter values set. Default is True.

Raises
------
:class:`pybamm.ModelError`
If an empty model is passed (`model.rhs = {}` and `model.algebraic={}`)

"""
pybamm.logger.info("Start setting parameters for {}".format(model.name))

if len(model.rhs) == 0 and len(model.algebraic) == 0:
pybamm.logger.info(
"Start setting parameters for {}".format(unprocessed_model.name)
)

# set up inplace vs not inplace
if inplace:
# any changes to model_disc attributes will change model attributes
# since they point to the same object
model = unprocessed_model
else:
# create a blank model of the same class
model = unprocessed_model.__class__(unprocessed_model.options)
model.name = unprocessed_model.name
model.options = unprocessed_model.options
model.use_jacobian = unprocessed_model.use_jacobian
model.use_simplify = unprocessed_model.use_simplify
model.convert_to_format = unprocessed_model.convert_to_format

if len(unprocessed_model.rhs) == 0 and len(unprocessed_model.algebraic) == 0:
raise pybamm.ModelError("Cannot process parameters for empty model")

if processing == "process":
processing_function = self.process_symbol
elif processing == "update":
processing_function = self.update_scalars

for variable, equation in model.rhs.items():
for variable, equation in unprocessed_model.rhs.items():
pybamm.logger.debug(
"{} parameters for {!r} (rhs)".format(processing.capitalize(), variable)
)
model.rhs[variable] = processing_function(equation)

for variable, equation in model.algebraic.items():
for variable, equation in unprocessed_model.algebraic.items():
pybamm.logger.debug(
"{} parameters for {!r} (algebraic)".format(
processing.capitalize(), variable
)
)
model.algebraic[variable] = processing_function(equation)

for variable, equation in model.initial_conditions.items():
for variable, equation in unprocessed_model.initial_conditions.items():
pybamm.logger.debug(
"{} parameters for {!r} (initial conditions)".format(
processing.capitalize(), variable
Expand All @@ -270,7 +289,7 @@ def process_model(self, model, processing="process"):
# small number of variables, e.g. {"negative tab": neg. tab bc,
# "positive tab": pos. tab bc "no tab": no tab bc}.
new_boundary_conditions = {}
for variable, bcs in model.boundary_conditions.items():
for variable, bcs in unprocessed_model.boundary_conditions.items():
processed_variable = processing_function(variable)
new_boundary_conditions[processed_variable] = {}
for side in ["left", "right", "negative tab", "positive tab", "no tab"]:
Expand All @@ -288,21 +307,23 @@ def process_model(self, model, processing="process"):

model.boundary_conditions = new_boundary_conditions

for variable, equation in model.variables.items():
for variable, equation in unprocessed_model.variables.items():
pybamm.logger.debug(
"{} parameters for {!r} (variables)".format(
processing.capitalize(), variable
)
)
model.variables[variable] = processing_function(equation)
for event, equation in model.events.items():
for event, equation in unprocessed_model.events.items():
pybamm.logger.debug(
"{} parameters for event '{}''".format(processing.capitalize(), event)
)
model.events[event] = processing_function(equation)

pybamm.logger.info("Finish setting parameters for {}".format(model.name))

return model

def update_model(self, model, disc):
"""Process a discretised model.
Currently inplace, could be changed to return a new model.
Expand Down
Loading