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

ParameterValues: write_to_bpx method #2594

Open
ejfdickinson opened this issue Jan 6, 2023 · 5 comments
Open

ParameterValues: write_to_bpx method #2594

ejfdickinson opened this issue Jan 6, 2023 · 5 comments
Labels
difficulty: medium Will take a few days feature priority: medium To be resolved if time allows

Comments

@ejfdickinson
Copy link

ejfdickinson commented Jan 6, 2023

Description

A method to write a valid BPX .json to file from a ParameterValues instance.

May require options for:

  • BPX metadata
  • optional variables in the BPX standard, such as stoichiometry limits, evaluated quantities
  • incorporation of validation data according to BPX standard

This is recommended as a meaningful paired functionality to the ParameterValues.create_from_bpx() static method.

Motivation

No response

Possible Implementation

No response

Additional context

No response

@jaskiratsingh2000
Copy link

@jeromtom @rtimms @tinosulzer @ejfdickinson Can you let me know more about this? I have the basic function ready below.

def write_bpx_file(param_values, filename, metadata):
    # Create a dictionary with the necessary data
    bpx_data = {
        "metadata": metadata,
        "parameters": param_values.as_dict()
    }
    
    # Serialize the dictionary into a JSON-formatted string
    bpx_json = json.dumps(bpx_data, indent=2)
    
    # Write the JSON-formatted string to a file
    with open(filename, "w") as f:
        f.write(bpx_json)

@ejfdickinson
Copy link
Author

ejfdickinson commented Feb 20, 2023

@jaskiratsingh2000

That's the basic idea. When it comes to practical implementation, there are some small items and some more substantial challenges though:

  • Control scientific notation and rounding in the output.
  • Conversion between ParameterValues fields and BPX fields. There are several non-trivial mathematical conversions, as well as name mapping.
  • Temperature-dependent functions - BPX only allows single-parameter functions and embeds temperature-dependence with constant values of parameter derivatives, whereas PyBaMM frequently uses functions of a variable and temperature.
  • Handling look-up fields.
  • Handling callables. ParameterValues fields can be callable handles which in turn can be any valid Python, written dynamically. This is not true of BPX functional expressions.

@rtimms @tinosulzer

I made a start on this and could share the code I have at present, which does the easier things but not the harder things (viz lookups, functions). I doubt I'll have time to take it further while remaining aligned to the main branch, so it would be a good time for someone else to round this out for general use. I'll DM to make sure I understand the GitHub alignment properly.

@rtimms
Copy link
Contributor

rtimms commented Feb 20, 2023

Thanks @ejfdickinson this is a good summary. I agree, mapping the constant is easy. The functions are more complicated. Tackling this probably requires some battery knowledge too. As highlighted, the really hard part is that functions in ParameterValues can contain arbitrary expressions. What do I do if I have a function like

def electrolyte_conductivity_base_Landesfeind2019(c_e, T):
    coeffs = np.array([5.21e-1, 2.28e2, -1.06, 3.53e-1, -3.59e-3, 1.48e-3])
    c = c_e / 1000  # mol.m-3 -> mol.l
    p1, p2, p3, p4, p5, p6 = coeffs
    A = p1 * (1 + (T - p2))
    B = 1 + p3 * pybamm.sqrt(c) + p4 * (1 + p5 * pybamm.exp(1000 / T)) * c
    C = 1 + c**4 * (p6 * pybamm.exp(1000 / T))
    sigma_e = A * c * B / C  # mS.cm-1

    return sigma_e / 10

but BPX expects a function of concentration only, multiplied by an Arrhenius dependence?

@ejfdickinson it would be great if you could push what you have so far to a branch somewhere.

@ejfdickinson
Copy link
Author

@rtimms @tinosulzer

Please see code here:

bpx_out.py
Demo notebook

@jaskiratsingh2000 If you can support the core team, please liaise with them!

At this stage I think it's better to take it up at your side - we are aiming for some workaround approaches here but they are based on imposing upstream restrictions on what can go into a ParameterValues object in the first place, on which this method would be called - so they're not generalisable. I don't have the skills to do the remainder efficiently.

I guess that a successful solution will be able to strictly analyse callables and refuse to convert them to BPX unless they are sufficiently simple (e.g., no recursion or function nesting). At that level, handling a function like the above becomes just a case of token substitution with values.

As BPX only allows linear temperature dependence, maybe it could be handled by taking numerical derivatives from the functions i.e. evaluate (f(T+dT) - f(T-dT)) / 2 / dT.

@rtimms rtimms added the priority: medium To be resolved if time allows label May 15, 2023
@valentinsulzer valentinsulzer added the difficulty: medium Will take a few days label May 15, 2023
@kratman
Copy link
Contributor

kratman commented Jun 5, 2024

Related to #3909

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty: medium Will take a few days feature priority: medium To be resolved if time allows
Projects
None yet
Development

No branches or pull requests

5 participants