Source code for pybamm.expression_tree.parameter
#
# Parameter classes
#
import numbers
import numpy as np
import pybamm
[docs]class Parameter(pybamm.Symbol):
"""A node in the expression tree representing a parameter
This node will be replaced by a :class:`.Scalar` node
Parameters
----------
name : str
name of the node
domain : iterable of str, optional
list of domains the parameter is valid over, defaults to empty list
"""
def __init__(self, name, domain=[]):
super().__init__(name, domain=domain)
[docs] def new_copy(self):
""" See :meth:`pybamm.Symbol.new_copy()`. """
return Parameter(self.name, self.domain)
def _evaluate_for_shape(self):
"""
Returns the scalar 'NaN' to represent the shape of a parameter.
See :meth:`pybamm.Symbol.evaluate_for_shape()`
"""
return np.nan
[docs] def is_constant(self):
""" See :meth:`pybamm.Symbol.is_constant()`. """
# Parameter is not constant since it can become an InputParameter
return False
[docs]class FunctionParameter(pybamm.Symbol):
"""A node in the expression tree representing a function parameter
This node will be replaced by a :class:`pybamm.Function` node if a callable function
is passed to the parameter values, and otherwise (in some rarer cases, such as
constant current) a :class:`pybamm.Scalar` node.
Parameters
----------
name : str
name of the node
inputs : dict
A dictionary with string keys and :class:`pybamm.Symbol` values representing
the function inputs. The string keys should provide a reasonable description
of what the input to the function is
(e.g. "Electrolyte concentration [mol.m-3]")
diff_variable : :class:`pybamm.Symbol`, optional
if diff_variable is specified, the FunctionParameter node will be replaced by a
:class:`pybamm.Function` and then differentiated with respect to diff_variable.
Default is None.
"""
def __init__(
self,
name,
inputs,
diff_variable=None,
):
# assign diff variable
self.diff_variable = diff_variable
children_list = list(inputs.values())
# Turn numbers into scalars
for idx, child in enumerate(children_list):
if isinstance(child, numbers.Number):
children_list[idx] = pybamm.Scalar(child)
domain = self.get_children_domains(children_list)
auxiliary_domains = self.get_children_auxiliary_domains(children_list)
super().__init__(
name,
children=children_list,
domain=domain,
auxiliary_domains=auxiliary_domains,
)
self.input_names = list(inputs.keys())
@property
def input_names(self):
return self._input_names
def print_input_names(self):
if self._input_names:
for inp in self._input_names:
print(inp)
@input_names.setter
def input_names(self, inp=None):
if inp:
if inp.__class__ is list:
for i in inp:
if i.__class__ is not str:
raise TypeError(
"Inputs must be a provided as"
+ "a dictionary of the form:"
+ "{{str: :class:`pybamm.Symbol`}}"
)
else:
raise TypeError(
"Inputs must be a provided as"
+ " a dictionary of the form:"
+ "{{str: :class:`pybamm.Symbol`}}"
)
self._input_names = inp
[docs] def set_id(self):
"""See :meth:`pybamm.Symbol.set_id` """
self._id = hash(
(self.__class__, self.name, self.diff_variable)
+ tuple([child.id for child in self.children])
+ tuple(self.domain)
)
[docs] def get_children_domains(self, children_list):
"""Obtains the unique domain of the children. If the
children have different domains then raise an error"""
domains = [child.domain for child in children_list if child.domain != []]
# check that there is one common domain amongst children
distinct_domains = set(tuple(dom) for dom in domains)
if len(distinct_domains) > 1:
raise pybamm.DomainError(
"Functions can only be applied to variables on the same domain"
)
elif len(distinct_domains) == 0:
domain = []
else:
domain = domains[0]
return domain
[docs] def diff(self, variable):
""" See :meth:`pybamm.Symbol.diff()`. """
# return a new FunctionParameter, that knows it will need to be differentiated
# when the parameters are set
children_list = self.orphans
input_names = self._input_names
input_dict = {input_names[i]: children_list[i] for i in range(len(input_names))}
return FunctionParameter(self.name, input_dict, diff_variable=variable)
[docs] def new_copy(self):
""" See :meth:`pybamm.Symbol.new_copy()`. """
return self._function_parameter_new_copy(self._input_names, self.orphans)
def _function_parameter_new_copy(self, input_names, children):
"""Returns a new copy of the function parameter.
Inputs
------
input_names : : list
A list of str of the names of the children/function inputs
children : : list
A list of the children of the function
Returns
-------
: :pybamm.FunctionParameter
A new copy of the function parameter
"""
input_dict = {input_names[i]: children[i] for i in range(len(input_names))}
return FunctionParameter(
self.name, input_dict, diff_variable=self.diff_variable
)
def _evaluate_for_shape(self):
"""
Returns the sum of the evaluated children
See :meth:`pybamm.Symbol.evaluate_for_shape()`
"""
return sum(child.evaluate_for_shape() for child in self.children)