Skip to content

Reformulation of Helmholtz energy expressions - #1799

Open
StephenBurroughs wants to merge 56 commits into
IDAES:mainfrom
waikato-ahuora-smart-energy-systems:HelmHoltzReformulated
Open

Reformulation of Helmholtz energy expressions#1799
StephenBurroughs wants to merge 56 commits into
IDAES:mainfrom
waikato-ahuora-smart-energy-systems:HelmHoltzReformulated

Conversation

@StephenBurroughs

@StephenBurroughs StephenBurroughs commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Overview of Reformulation

This pull request is the first of 3 refactors to reformulate the way in which General Helmholtz property packages are built. The full set of changes are as follows:

  1. (This PR) Refactor the way in which energy expressions are formulated to capture modular terms.
  2. Add Thermal Conductivity and Viscosity expressions so that they can be built using the fluid JSON file in the same manner as energy terms and surface tension.
  3. Add support for all fluids currently present within CoolProp.

I have already made some progress with regard to Tcx expressions and have actually integrated all of Coolprop (without surface tension, thermal conductivity, and viscosity), but thought that it might be a bit easier to deal with these changes in stages rather than submitting a single, giant PR.

Fixes

Provides a modular set of terms for building Helmholtz property packages.
Adds a set of tests to compare fluid properties against CoolProp

Summary/Motivation:

The existing implementation for general Helmholtz property packages is functional, but also rather painful to use when extending to support new fluids. This is primarily down to two reasons:

  1. Ideal and residual energy formulations are defined as whole expressions.
  2. These formulations capture the base expression, as well as multiple derivatives.

This is problematic, as it means that to add support for a new fluid, a user is required to essentially write out a whole new expression for ideal and residual terms, as well as evaluate, transcribe, and check the derivatives thereof.

A solution to this can be found in the modular approach that is used by CoolProp - energy formulations are essentially made up of a combination of terms. Under the status quo implementation within IDAES, any additional fluid for which an expression has not already been created must be explicitly defined, even if there is only one term that is altered from an existing expression. By switching to a modular approach that just relies on the terms being defined, fluids can be added quite rapidly by identifying the terms that are present and building the full expression in an on-demand fashion. It's also much easier to add new terms that aren't already supported, as they can be defined as standalone terms and automatically pulled into the expression builder with minimal effort.

This process is also much faster if we remove the need to explicitly define derivative terms. These are necessary because of the formulation of the backend c++ code within IDAES-extensions, which provides external functions to the property package. Thankfully, Pyomo actually provides a way to do symbolic differentiation, which means that we can generate these derivatives during the process of writing the property package files rather than having to define them explicitly. This is great, because it reduces the amount of effort required to add additional forms for energy terms, as well as reduces the number of possible sources of error within the calculations.

Finally,
I've added a test that compares enthalpy/entropy differences and density against coolprop. This is in part due to the next stage of this broader rework which brings in all coolprop fluids, as frankly it seemed far less painful than explicitly defining a set of properties to verify against for everything.

Changes proposed in this PR:

  • Replace General Helmholtz energy expressions with a set of modular terms.
  • Refactor the WriteParameters class to build expressions from these modular terms, and find derivatives using Pyomo symbolic differentiation.
  • Add a set of tests against CoolProp.

Legal Acknowledgement

By contributing to this software project, I agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the license terms described in the LICENSE.txt file at the top level of this directory.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

@adowling2

Copy link
Copy Markdown
Contributor

@snarasi2 Take a look

@StephenBurroughs

Copy link
Copy Markdown
Contributor Author

I'm somewhat unsure about the compatibility test - It seems like everything is fine except for the number of iterations for a few of the samples. If the absolute tolerance is adjusted to 2, this test passes.
Tolerance can be left as is if the following iteration changes are made:
Sample 8: 7->6
Sample 10: 5->6
Sample 16: 3-> 4
Sample 19: 5->6
Sample 28: 5->4
Sample 46: 3->4
Sample 55: 6->5
Sample 83: 4->5
Sample 98: 6->5

Arguably, this might somewhat defeat the spirit of a compatibility test, but given that the other assertions remain valid and the iteration changes are small and in both directions (4 decrease by 1, 5 increase by 1) it seems fairly acceptable?

@codecov

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.70%. Comparing base (6cf9299) to head (5efe5e5).
⚠️ Report is 11 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1799      +/-   ##
==========================================
- Coverage   73.82%   73.70%   -0.12%     
==========================================
  Files         419      425       +6     
  Lines       66392    67674    +1282     
  Branches    11170    11424     +254     
==========================================
+ Hits        49013    49881     +868     
- Misses      14839    15175     +336     
- Partials     2540     2618      +78     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@StephenBurroughs

Copy link
Copy Markdown
Contributor Author

I can also increase the code coverage by including some additional fluids which use other energy terms. I was intending to wait until the next pull request and merge them all, but can quite easily add them to the commit here and extend the coolprop comparison tests to include a call to the WriteParameters class to check enthalpy and density values, similarly to what is currently done in the test_parameter_util tests.

@ksbeattie

Copy link
Copy Markdown
Member

@StephenBurroughs this is a pretty large PR. Might you be available to talk through this over zoom? Our regular dev call is 11am Pacific Time (which is pretty early for you). We might be able to schedule another time.

@ksbeattie ksbeattie added the Priority:Normal Normal Priority Issue or PR label Jun 4, 2026
@StephenBurroughs

Copy link
Copy Markdown
Contributor Author

@StephenBurroughs this is a pretty large PR. Might you be available to talk through this over zoom? Our regular dev call is 11am Pacific Time (which is pretty early for you). We might be able to schedule another time.

Sure thing, I'll shoot you an email

@dallan-keylogic

Copy link
Copy Markdown
Contributor

Thank you so much for contributing this, @StephenBurroughs . However, I don't have a good enough grasp on the core Helmholtz code to feel comfortable replacing it wholesale. Unless @eslickj reappears from the aether to review this PR, I think the best path forward is to take this version of the Helmholtz properties and put it models_extra. I'm not sure how it should be branded---EvenMoreGeneralHelmholtz is a mouthful. KiwiHelmholtz may be a bit too on-the-nose.

Let me know what you think.

@StephenBurroughs

StephenBurroughs commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

I can see where you're coming from @dallan-keylogic. This could be an option - although I feel like possibly including it in modular properties instead could be appropriate - I have some other reasons for this as well, as Peng-Robinson is on my radar...
I think in the meantime, there may be an alternative option.
The code under general Helmholtz does two main things. First, it builds the terms for ideal/residual energy, as well as surface area, viscocity, tcx. From there though, it links the package to external functions within John Eslick's C++ code in ideas-extensions. Essentially, what I have changed is the first part, being the formulation of energy terms, while the underlying property package logic used to calculate and solve models remains untouched.
With this in mind, and in the hopes of avoiding having two places that basically do the same thing, would it be more acceptable if I instead kept backwards compatibility with the previous formulations? I could then keep the previous forms for all existing pure components (and people who have developed their own packages could also still use it as is), while future fluids could be added using the old way OR the new formulation.
If this seems more reasonable, I can make some modifications to bring back all of the previous forms of existing fluids, as well as support for the old expressions, and add in all of the new fluids I've got using the new formulation. This would mean that we can have certainty that existing formulations are still valid, while also expanding Helmholtz to be on par with CoolProp. It would also mean that the compatibility test passes, as it would use the old formulation of water.
Let me know what you think of this, I'm happy to have a meeting at some stage to chat about it if that would help as well.

@StephenBurroughs

Copy link
Copy Markdown
Contributor Author

@dallan-keylogic If you have time, have a look at the newer implementation here. It maintains compatibility with legacy fluids, but also brings in a whole heap of additional fluids through the new formulation.
On a side note, I'm pretty sure that the failing tests are now because CoolProp has updated to v8 and some fluid property formulations have changed. This may already be known given that the same tests are failing consistently....

@StephenBurroughs

Copy link
Copy Markdown
Contributor Author

I've updated the CoolProp test in a similar manner to the other pull request I opened for #1815 - This means that they pass with CoolPropv8 (and compatibility tests will pass if the relevant PR is merged in the compatibility repo). If you want to hold off on the CoolProp upgrade, I'll just roll back that test change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Priority:Normal Normal Priority Issue or PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants