Skip to content

Commit

Permalink
Merge pull request #959 from pybamm-team/issue-958-parameter-values-csv
Browse files Browse the repository at this point in the history
#958 added export_csv to parameter values and relevant tests
  • Loading branch information
valentinsulzer authored May 18, 2020
2 parents bdc5151 + 1ef960d commit 7d99e2a
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 142 deletions.
1 change: 0 additions & 1 deletion docs/source/parameters/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@ Parameters
thermal_parameters
standard_parameters_lithium_ion
standard_parameters_lead_acid
print_parameters
parameter_sets
6 changes: 0 additions & 6 deletions docs/source/parameters/print_parameters.rst

This file was deleted.

31 changes: 21 additions & 10 deletions examples/notebooks/parameter-values.ipynb

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion pybamm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ def version(formatted=False):
from .parameters import thermal_parameters
from .parameters import standard_parameters_lithium_ion, standard_parameters_lead_acid
from .parameters import sei_parameters
from .parameters.print_parameters import print_parameters, print_evaluated_parameters
from .parameters import parameter_sets


Expand Down
135 changes: 135 additions & 0 deletions pybamm/parameters/parameter_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import os
import numbers
from pprint import pformat
from collections import defaultdict


class ParameterValues:
Expand Down Expand Up @@ -602,3 +603,137 @@ def evaluate(self, symbol):

def _ipython_key_completions_(self):
return list(self._dict_items.keys())

def export_csv(self, filename):

# process functions and data to output
# like they appear in inputs csv files
parameter_output = {}
for key, val in self.items():
if callable(val):
val = "[function]" + val.__name__
elif isinstance(val, tuple):
val = "[data]" + val[0]
parameter_output[key] = [val]

df = pd.DataFrame(parameter_output)
df = df.transpose()
df.to_csv(filename, header=None)

def print_parameters(self, parameters, output_file=None):
"""
Return dictionary of evaluated parameters, and optionally print these evaluated
parameters to an output file.
For dimensionless parameters that depend on the C-rate, the value is given as a
function of the C-rate (either x * Crate or x / Crate depending on the
dependence)
Parameters
----------
parameters : class or dict containing :class:`pybamm.Parameter` objects
Class or dictionary containing all the parameters to be evaluated
output_file : string, optional
The file to print parameters to. If None, the parameters are not printed,
and this function simply acts as a test that all the parameters can be
evaluated, and returns the dictionary of evaluated parameters.
Returns
-------
evaluated_parameters : defaultdict
The evaluated parameters, for further processing if needed
Notes
-----
A C-rate of 1 C is the current required to fully discharge the battery in 1
hour, 2 C is current to discharge the battery in 0.5 hours, etc
"""
# Set list of attributes to ignore, for when we are evaluating parameters from
# a class of parameters
ignore = [
"__name__",
"__doc__",
"__package__",
"__loader__",
"__spec__",
"__file__",
"__cached__",
"__builtins__",
"absolute_import",
"division",
"print_function",
"unicode_literals",
"pybamm",
"constants",
"np",
]

# If 'parameters' is a class, extract the dict
if not isinstance(parameters, dict):
parameters = {
k: v for k, v in parameters.__dict__.items() if k not in ignore
}

evaluated_parameters = defaultdict(list)
# Calculate parameters for each C-rate
for Crate in [1, 10]:
# Update Crate
capacity = self.get("Cell capacity [A.h]")
if capacity is not None:
self.update(
{"Current function [A]": Crate * capacity},
check_already_exists=False,
)
for name, symbol in parameters.items():
if not callable(symbol):
proc_symbol = self.process_symbol(symbol)
if not (
callable(proc_symbol)
or proc_symbol.has_symbol_of_classes(
(pybamm.Concatenation, pybamm.Broadcast)
)
):
evaluated_parameters[name].append(proc_symbol.evaluate(t=0))

# Calculate C-dependence of the parameters based on the difference between the
# value at 1C and the value at C / 10
for name, values in evaluated_parameters.items():
if values[1] == 0 or abs(values[0] / values[1] - 1) < 1e-10:
C_dependence = ""
elif abs(values[0] / values[1] - 10) < 1e-10:
C_dependence = " * Crate"
elif abs(values[0] / values[1] - 0.1) < 1e-10:
C_dependence = " / Crate"
evaluated_parameters[name] = (values[0], C_dependence)
# Print the evaluated_parameters dict to output_file
if output_file:
self.print_evaluated_parameters(evaluated_parameters, output_file)

return evaluated_parameters

def print_evaluated_parameters(self, evaluated_parameters, output_file):
"""
Print a dictionary of evaluated parameters to an output file
Parameters
----------
evaluated_parameters : defaultdict
The evaluated parameters, for further processing if needed
output_file : string, optional
The file to print parameters to. If None, the parameters are not printed,
and this function simply acts as a test that all the parameters can be
evaluated
"""
# Get column width for pretty printing
column_width = max(len(name) for name in evaluated_parameters.keys())
s = "{{:>{}}}".format(column_width)
with open(output_file, "w") as file:
for name, (value, C_dependence) in sorted(evaluated_parameters.items()):
if 0.001 < abs(value) < 1000:
file.write(
(s + " : {:10.4g}{!s}\n").format(name, value, C_dependence)
)
else:
file.write(
(s + " : {:10.3E}{!s}\n").format(name, value, C_dependence)
)
118 changes: 0 additions & 118 deletions pybamm/parameters/print_parameters.py

This file was deleted.

22 changes: 22 additions & 0 deletions tests/unit/test_parameters/test_parameter_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import unittest
import tests.shared as shared

import pandas as pd


class TestParameterValues(unittest.TestCase):
def test_read_parameters_csv(self):
Expand Down Expand Up @@ -587,6 +589,26 @@ def test_evaluate(self):
with self.assertRaises(ValueError):
parameter_values.evaluate(array)

def test_export_csv(self):
def some_function(self):
return None

example_data = ("some_data", [0, 1, 2])

parameter_values = pybamm.ParameterValues(
{"a": 0.1, "b": some_function, "c": example_data}
)

filename = "parameter_values_test.csv"

parameter_values.export_csv(filename)

df = pd.read_csv(filename, index_col=0, header=None)

self.assertEqual(df[1]["a"], "0.1")
self.assertEqual(df[1]["b"], "[function]some_function")
self.assertEqual(df[1]["c"], "[data]some_data")


if __name__ == "__main__":
print("Add -v for more debug output")
Expand Down
12 changes: 6 additions & 6 deletions tests/unit/test_parameters/test_standard_parameters_lead_acid.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ def test_all_defined(self):
parameters = pybamm.standard_parameters_lead_acid
parameter_values = pybamm.lead_acid.BaseModel().default_parameter_values
output_file = "lead_acid_parameters.txt"
pybamm.print_parameters(parameters, parameter_values, output_file)
parameter_values.print_parameters(parameters, output_file)
# test print_parameters with dict and without C-rate
del parameter_values["Cell capacity [A.h]"]
parameters = {
"C_e": pybamm.standard_parameters_lead_acid.C_e,
"sigma_n": pybamm.standard_parameters_lead_acid.sigma_n,
}
pybamm.print_parameters(parameters, parameter_values)
parameter_values.print_parameters(parameters)

def test_parameters_defaults_lead_acid(self):
# Load parameters to be tested
parameters = pybamm.standard_parameters_lead_acid
parameter_values = pybamm.lead_acid.BaseModel().default_parameter_values
param_eval = pybamm.print_parameters(parameters, parameter_values)
param_eval = parameter_values.print_parameters(parameters)
param_eval = {k: v[0] for k, v in param_eval.items()}

# Diffusional C-rate should be smaller than C-rate
Expand Down Expand Up @@ -131,7 +131,7 @@ def test_functions_lead_acid(self):
parameter_values = pybamm.ParameterValues(
chemistry=pybamm.parameter_sets.Sulzer2019
)
param_eval = pybamm.print_parameters(parameters, parameter_values)
param_eval = parameter_values.print_parameters(parameters)
param_eval = {k: v[0] for k, v in param_eval.items()}

# Known values for dimensionless functions
Expand All @@ -146,12 +146,12 @@ def test_update_initial_state_of_charge(self):
# Load parameters to be tested
parameters = pybamm.standard_parameters_lead_acid
parameter_values = pybamm.lead_acid.BaseModel().default_parameter_values
param_eval = pybamm.print_parameters(parameters, parameter_values)
param_eval = parameter_values.print_parameters(parameters)
param_eval = {k: v[0] for k, v in param_eval.items()}

# Update initial state of charge
parameter_values.update({"Initial State of Charge": 0.2})
param_eval_update = pybamm.print_parameters(parameters, parameter_values)
param_eval_update = parameter_values.print_parameters(parameters)
param_eval_update = {k: v[0] for k, v in param_eval_update.items()}

# Test that relevant parameters have changed as expected
Expand Down

0 comments on commit 7d99e2a

Please sign in to comment.