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

Plot parameter functions #1465

Closed
rtimms opened this issue Apr 26, 2021 · 9 comments · Fixed by #1472
Closed

Plot parameter functions #1465

rtimms opened this issue Apr 26, 2021 · 9 comments · Fixed by #1472

Comments

@rtimms
Copy link
Contributor

rtimms commented Apr 26, 2021

Some parameters are provided as functions (e.g. diffusivity as a function of concentration and temperature). Currently, to plot them you have to do something like this

import pybamm

params = pybamm.ParameterValues(chemistry=pybamm.parameter_sets.Chen2020)
i0 = params["Negative electrode exchange-current density [A.m-2]"]
x = pybamm.linspace(3000,6000,100)
i0_eval = i0(1000,x,300)
i0_processed = params.process_symbol(i0_eval)
pybamm.plot(x, i0_processed)

We have to process the function "Negative electrode exchange-current density [A.m-2]" since its definition contains a pybamm.Parameter. It would be neat to be able to do something like params.plot("Negative electrode exchange-current density [A.m-2]", (1000, x, 300)) instead so you can quickly plot the functional dependence of parameters. We can use pybamm.plot and pybamm.plot2D to plot the resulting arrays.

Maybe you could pass a list or dict of parameter names and values so you can plot multiple parameters on the same plot.

@rtimms
Copy link
Contributor Author

rtimms commented Apr 26, 2021

This is actually listed as one of the bullet points in #1458 .

@Saransh-cpp , just some thoughts here on plotting parameters

@Saransh-cpp
Copy link
Member

This is actually listed as one of the bullet points in #1458 .

@Saransh-cpp , just some thoughts here on plotting parameters

I'll have a look and see if I can implement the plot function in ParameterValues

@valentinsulzer
Copy link
Member

Just a comment - when we provide custom plotting functions we need to be careful not to do so at the expense of matplotlib flexibility (specifying args and kwargs in the plot, adding xlabel and ylabel and legend, etc).

@rtimms
Copy link
Contributor Author

rtimms commented Apr 27, 2021

Good point re plotting. Maybe instead of adding extra plotting functionality, we could add something that makes it easier to get a callable function from ParameterValues?

E.g. you can do

import pybamm

def myfun(x):
    return pybamm.Parameter("D") * x

params = pybamm.ParameterValues({"D":2, "function":myfun})

def f(x):
    return params.process_symbol(params["function"](x))

x = pybamm.linspace(0,1,10)
pybamm.plot(x,f(x))

It would be handy to get f(x) directly without having to define it yourself. I couldn't figure out how to process the parameter and then call it, but maybe it doesn't matter too much. Also, it's not clear if we would want f(x) to return a pybamm array so we can use pybamm.plot or if it should just return a numpy array and people can do what they want with it.

It's not a huge effort to define f(x) yourself like this, but it's one extra step for new users to figure out.

PS I know this is a stupid example as you could just call myfun here, but in general you don't have the function defined locally.

@Saransh-cpp
Copy link
Member

Saransh-cpp commented Apr 27, 2021

This simple function does work but is, as it looks, limited to the above example (should be modified to add all plots in a single screen though). Should we generalize this or will it be better to just create a function for returning params.process_symbol()

    def plot(self, values, eval):

        self.check_parameter_values(values)

        for value in values:
            processed = self.process_symbol(self[value](eval[0], eval[1], eval[2]))
            pybamm.plot(eval[1], processed, xlabel="time", ylabel=value)

Driver code being

import pybamm

params = pybamm.ParameterValues(chemistry=pybamm.parameter_sets.Chen2020)
x = pybamm.linspace(3000,6000,100)
params.plot(values=["Negative electrode exchange-current density [A.m-2]"], eval=(1000, x, 300))

@rtimms
Copy link
Contributor Author

rtimms commented Apr 27, 2021

Yeah, I think maybe it is better to just create a function that returns the processed parameter function. Each of the parameter functions may have a different number of arguments, and maybe trying to be clever with the plotting will get out of hand.

Then pybamm.plot and pybamm.plot2D could be modified to take/return the axis (like pybamm.plot_voltage_components) to make it easier for people to customize the plots.

thoughts @tinosulzer ?

@valentinsulzer
Copy link
Member

Doesn't params["function"] already do exactly what you want (return the callable function object)?

Then pybamm.plot and pybamm.plot2D could be modified to take/return the axis (like pybamm.plot_voltage_components) to make it easier for people to customize the plots.

agreed

@rtimms
Copy link
Contributor Author

rtimms commented Apr 27, 2021

Almost, but it returns an expression tree rather than an array. If the function itself contains a Parameter then you have to process the result to set the values, which feels a little awkward since params already knows the values. Basically I want a callable function that returns an array, in which all the Parameter symbols have been replaced by the values in params

Soemthing like

def process_function(name):
    function_parameter = params[name]
    def function(*args):
        return params.process_symbol(function_parameter(*args))
    
    return function

but defined as a method of ParameterValues. Then you can do

g = process_function("Negative electrode exchange-current density [A.m-2]")
pybamm.plot(x,g(1000,x,300))

@valentinsulzer
Copy link
Member

I see the issue now. What about editing the .evaluate() function so it can return an array?

rtimms added a commit that referenced this issue Apr 29, 2021
rtimms added a commit that referenced this issue Apr 29, 2021
…n-parameters

#1465 allow evaluate parameter to return arrays
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants