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

#958 added export_csv to parameter values and relevant tests #959

Merged
merged 3 commits into from
May 18, 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: 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