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

#1080 require t_eval #1086

Merged
merged 8 commits into from
Jun 30, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- Added some new solvers for algebraic models ([#1059](https://github.com/pybamm-team/PyBaMM/pull/1059))
- Added `length_scales` attribute to models ([#1058](https://github.com/pybamm-team/PyBaMM/pull/1058))
- Added averaging in secondary dimensions ([#1057](https://github.com/pybamm-team/PyBaMM/pull/1057))
- Added SEI reaction based on Yang et. al. 2017 and reduction in porosity ([#1009](https://github.com/pybamm-team/PyBaMM/issues/1009))
- Added SEI reaction based on Yang et. al. 2017 and reduction in porosity ([#1009](https://github.com/pybamm-team/PyBaMM/issues/1009))

## Optimizations

Expand All @@ -22,6 +22,8 @@

## Breaking changes

- The solution times `t_eval` must now be provided when solving a simulation without an experiment or drive cycle data ([]())

# [v0.2.2](https://github.com/pybamm-team/PyBaMM/tree/v0.2.2) - 2020-06-01

New SEI models, simplification of submodel structure, as well as optimisations and general bug fixes.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ PyBaMM (Python Battery Mathematical Modelling) solves physics-based electrochemi
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
model = pybamm.lithium_ion.DFN() # Doyle-Fuller-Newman model
sim = pybamm.Simulation(model)
sim.solve()
sim.solve([0, 3600]) # solve for 1 hour
sim.plot()
```
or simulate an experiment such as CCCV:
Expand All @@ -42,7 +42,7 @@ For new users we recommend the [Getting Started](examples/notebooks/Getting%20St

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).
hosted on [Read The Docs](readthedocs.io).
Additional supporting material can be found
[here](https://github.com/pybamm-team/pybamm-supporting-material/).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We can then call 'solve' on our simulation object to solve the model (by default the the model is solved for a 1C constant current discharge):"
"We can then call 'solve' on our simulation object to solve the model, passing the window of time to solve for in seconds (here 1 hour):"
]
},
{
Expand All @@ -73,7 +73,7 @@
"metadata": {},
"outputs": [],
"source": [
"sim.solve()"
"sim.solve([0, 3600])"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
"source": [
"model = pybamm.lithium_ion.SPMe()\n",
"sim = pybamm.Simulation(model, parameter_values=parameter_values)\n",
"sim.solve()\n",
"sim.solve([0, 3600])\n",
"sim.plot()"
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"import pybamm\n",
"model = pybamm.lithium_ion.SPMe()\n",
"sim = pybamm.Simulation(model)\n",
"sim.solve()"
"sim.solve([0, 3600])"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"parameter_values.update({\"Typical current [A]\": 3})\n",
"sim.specs(parameter_values=parameter_values)\n",
"\n",
"sim.solve()"
"sim.solve([0, 3600])"
]
},
{
Expand Down
12 changes: 10 additions & 2 deletions examples/notebooks/rate-capability.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"%pip install pybamm -q # install PyBaMM if it is not installed\n",
"import pybamm\n",
Expand Down Expand Up @@ -153,7 +161,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
"version": "3.6.9"
},
"mimetype": "text/x-python",
"name": "python",
Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/compare_lead_acid.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
sims = []
for model in models:
sim = pybamm.Simulation(model)
sim.solve()
sim.solve([0, 3600])
sims.append(sim)

# plot
Expand Down
8 changes: 2 additions & 6 deletions examples/scripts/compare_lithium_ion.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,13 @@
# pybamm.set_logging_level("INFO")

# load models
models = [
pybamm.lithium_ion.SPM(),
pybamm.lithium_ion.SPMe(),
pybamm.lithium_ion.DFN(),
]
models = [pybamm.lithium_ion.SPM(), pybamm.lithium_ion.SPMe(), pybamm.lithium_ion.DFN()]

# create and run simulations
sims = []
for model in models:
sim = pybamm.Simulation(model)
sim.solve()
sim.solve([0, 3600])
sims.append(sim)

# plot
Expand Down
2 changes: 1 addition & 1 deletion examples/scripts/nca_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
parameter_values = pb.ParameterValues(chemistry=chemistry)

sim = pb.Simulation(model, parameter_values=parameter_values, C_rate=1)
sim.solve()
sim.solve([0, 3600])
sim.plot()
2 changes: 1 addition & 1 deletion examples/scripts/run_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
model = pybamm.lithium_ion.SPM()

sim = pybamm.Simulation(model)
sim.solve()
sim.solve([0, 3600])
sim.plot()
112 changes: 66 additions & 46 deletions pybamm/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Simulation:
A list of variables to plot automatically
C_rate: float (optional)
The C_rate at which you would like to run a constant current
experiment at.
(dis)charge at.
"""

def __init__(
Expand All @@ -87,15 +87,20 @@ def __init__(
self.parameter_values = parameter_values or model.default_parameter_values

if experiment is None:
self.operating_mode = "without experiment"
if C_rate:
self.C_rate = C_rate
self._parameter_values.update(
{
"Current function [A]": self.C_rate
* self._parameter_values["Cell capacity [A.h]"]
}
)
# Check to see if the current is provided as data (i.e. drive cycle)
current = self._parameter_values.get("Current function [A]")
if isinstance(current, tuple):
self.operating_mode = "drive cycle"
else:
self.operating_mode = "without experiment"
if C_rate:
self.C_rate = C_rate
self._parameter_values.update(
{
"Current function [A]": self.C_rate
* self._parameter_values["Cell capacity [A.h]"]
}
)
self.model = model
else:
self.set_up_experiment(model, experiment)
Expand Down Expand Up @@ -324,11 +329,21 @@ def solve(
Parameters
----------
t_eval : numeric type, optional
The times at which to compute the solution. If None and the parameter
"Current function [A]" is not read from data the model will
be solved for a full discharge (1 hour / C_rate). If None and the
parameter "Current function [A]" is read from data the model will be
solved at the times provided in the data.
The times (in seconds) at which to compute the solution. Can be
provided as an array of times at which to return the solution, or as a
list `[t0, tf]` where `t0` is the initial time and `tf` is the final time.
If provided as a list the solution is returned at 100 points within the
interval `[t0, tf]`.

If not using an experiment or running a drive cycle simulation (current
provided as data) `t_eval` *must* be provided.

If running an experiment the values in `t_eval` are ignored, and the
solution times are specified by the experiment.

If None and the parameter "Current function [A]" is read from data
(i.e. drive cycle simulation) the model will be solved at the times
provided in the data.
solver : :class:`pybamm.BaseSolver`
The solver to use to solve the model.
external_variables : dict
Expand All @@ -347,14 +362,36 @@ def solve(
if solver is None:
solver = self.solver

if self.operating_mode == "without experiment":
# For drive cycles (current provided as data) we perform additional tests
# on t_eval (if provided) to ensure the returned solution captures the
# input. If the current is provided as data then the "Current function [A]"
# is the tuple (filename, data).
# First, read the current function (if provided, otherwise return None)
current = self._parameter_values.get("Current function [A]")
if isinstance(current, tuple):
if self.operating_mode in ["without experiment", "drive cycle"]:
# If t_eval is provided as [t0, tf] return the solution at 100 points
if isinstance(t_eval, list):
if len(t_eval) != 2:
raise pybamm.SolverError(
"'t_eval' can be provided as an array of times at which to "
"return the solution, or as a list [t0, tf] where t0 is the "
"initial time and tf is the final time, but has been provided "
"as a list of length {}.".format(len(t_eval))
)
else:
t_eval = np.linspace(t_eval[0], t_eval[-1], 100)

if self.operating_mode == "without experiment":
if t_eval is None:
raise pybamm.SolverError(
"'t_eval' must be provided if not using an experiment or "
"simulating a drive cycle. 't_eval' can be provided as an "
"array of times at which to return the solution, or as a "
"list [t0, tf] where t0 is the initial time and tf is the "
"final time. "
"For a constant current (dis)charge the suggested 't_eval' "
"is [0, 4000/C] where C is the C-rate."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Played around a little bit with this and I think we should suggest something closer to 3600 (e.g. 3700)

)

elif self.operating_mode == "drive cycle":
# For drive cycles (current provided as data) we perform additional
# tests on t_eval (if provided) to ensure the returned solution
# captures the input. If the current is provided as data then the
# "Current function [A]" is the tuple (filename, data).
filename = self._parameter_values["Current function [A]"][0]
time_data = self._parameter_values["Current function [A]"][1][:, 0]
# If no t_eval is provided, we use the times provided in the data.
Expand All @@ -363,10 +400,10 @@ def solve(
"Setting t_eval as specified by the data '{}'".format(filename)
)
t_eval = time_data
# If t_eval is provided we first check if it contains all of the times
# in the data to within 10-12. If it doesn't, we then check
# that the largest gap in t_eval is smaller than the smallest gap in the
# time data (to ensure the resolution of t_eval is fine enough).
# If t_eval is provided we first check if it contains all of the
# times in the data to within 10-12. If it doesn't, we then check
# that the largest gap in t_eval is smaller than the smallest gap in
# the time data (to ensure the resolution of t_eval is fine enough).
# We only raise a warning here as users may genuinely only want
# the solution returned at some specified points.
elif (
Expand Down Expand Up @@ -398,24 +435,6 @@ def solve(
),
pybamm.SolverWarning,
)
# If not using a drive cycle and t_eval is not provided, set t_eval
# to correspond to a single discharge
elif t_eval is None:
if current is None:
t_end = 1
else:
# Get C-rate, return None if it doesn't exist
capacity = self.parameter_values["Cell capacity [A.h]"]
if isinstance(current, pybamm.InputParameter):
C_rate = inputs["Current function [A]"] / capacity
t_end = 3600 / C_rate
else:
try:
C_rate = current / capacity
t_end = 3600 / C_rate
except TypeError:
t_end = 3600
t_eval = np.linspace(0, t_end, 100)

self.t_eval = t_eval
self._solution = solver.solve(
Expand Down Expand Up @@ -472,6 +491,7 @@ def solve(
timer.format(timer.time())
)
)

return self.solution

def step(
Expand All @@ -489,7 +509,7 @@ def step(
The solver to use to solve the model.
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).
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. The variables must correspond to
Expand Down
Loading