Scope and purpose
PYroMat is a Python package for conveniently retrieving the thermodynamic properties of substances. PYroMat is and will always be free and open. The original source data will always be fully disclosed.
Providing the properties of substances is an awfully broad mandate; so we have to start somewhere. As of version 2.0.1, PYroMat had over 390 substances and it's very first multi-phase substance - water. By version 2.1.0, it had nearly 1,000 unique substances. By version 2.2.0, it included two-phase models for multiple refrigerants, methane, carbon dioxide, nitrogen, and oxygen. Work continues today.
If you find out that PYroMat doesn't do something you need, don't stay silent! My favorite way for users to make feature requests is on the Github issues page. You can also just email me. Many of the features available in PYroMat today are because users told us they wanted it.
We really like PYroMat because it does things a little differently (mostly, because it is open, free, and pythonic). Still, if PYroMat just doesn't do what you need it to, there are some excellent alternatives out there that do some similar things. REFPROP is a widely recognized standard in the thermal sciences licensed by NIST. CoolProp is an excellent package that extends REFPROP to numerous languages while also implementing its own models.
Who maintains PYroMat?
Hi, I'm Chris Martin, an Associate Professor of Mechanical Engineering at Penn State Altoona. I wrote the core of the PYroMat package in 2015.
It wasn't long thereafter, though, that Joe Ranalli picked up a keen interest in the project. Today, he pours in effort and code alike to helping PYroMat be as reliable as we can make it.
Jacob Moore is our team's pedagogist. A non-Python user (we'll convert him one day!), he keeps us honest - forcing us to keep the interface simple, clean, and clearly documented. Not least of all, he has helped us run multiple user studies in thermodynamics classrooms.
A little poem
There once was a student with work ethic prudent she scripted to speed her work. In Python t'was coded, so when it was loaded, she could all the tedium shirk. A thermodynamic fluid mechanic problem she had solved. Her colleagues were avid she share the package frustration to resolve. Good, was the mood. Researchers all cooed, until she read her mail. With no contradiction, viscosity-friction; with it her package would sail. She furiously typed new modules to write. The people, they must be heard. What thanks had it gotten? why, STEAM she'd forgotten! Without it, the code was absurd. Downtrodden indeed, she sat at the screen, multiphase soon to add. Though coffee was drunk and sleepless nights sunk, her code, it really was bad! The syntax was rambling no hope of unscrambling the endless nonsensical edits. Compatible, reverse, a programmer's curse no fixing - it's time to shred it. "I'm done," she then plead. To the airport, she fled. "I'll fly off to someplace that's random." Her useful creation was once a sensation; forgotten and now is abandoned. Her colleagues still moan, "Please pick up your phone! Your software, it just isn't working." Ye coders beware the fate most unfair, within all your projects is lurking.
The story behind PYroMat
If you're still reading, you are probably pretty curious. Good for you!
Origins: In 2006, I needed to calculate enthalpies of lots of ideal gases for combustion modeling, and I was disappointed with my options. I created HOT for Matlab and Octave, and it's still available from Sourceforge and the Mathworks File Exchange. In my opinion, that code is a mess, and I haven't supported it since 2010. I moved to Python for all my scientific computing in 2011, and I've never looked back.
In 2015, I shared version 1.1 on Sourceforge. Even though the back-end has changed massively over the years since then, users have only had to tolerate small changes in the interface. I have a policy of never breaking reverse compatibility without a major revision change, and there has only ever been one of those. The only release to deliberately break reverse compatibility was 2.0.1.
The name: PYroMat is constructed from "PY" for PYthon, the Greek "pyro" for fire, and the suffix "Mat", doubling both as a reference to "automat" and a shortening of "material." When I first shared my earliest working codes, I was very proud of my cute working title for the package, "PYro." Pyro is a popular remote object toolkit for Python, with which my working title collided.
The evolution of the substance models: The first release of PYroMat only supported ideal gas data through two classes; igfit and igtab. The igfit class supplied properties through the so-called NASA polynomials. Meanwhile, igtab objects simply performed interpolation on tabulated data.
At the close of 2017, I abandoned table look-ups altogether, and version 2.0.1 marked a total transition to the Shomate Equation for ideal gas data. Even though this let me dramatically expand the number of substances PYroMat offered, I quickly regretted the transition. The folks at NIST do a great job, but the temperature ranges on these fits are narrower, and I even identified the occasional discontinuity in the specific heat functions. The ig class still implements a number of species using the Shomate Equation, but, given a choice, I prefer the old NASA polynomials, which are provided by the ig2 class.
In 2018, the first multi-phase substances found their debut in PYroMat, and I began experimenting with different back-end codes. The first liquid-vapor substance model was the IF-97 industrial steam formulation implemented in the if97 class. The IF-97 formulation is especially useful for engineers, because it provides direct functions for calculating properties both "forward" and "backwards," but is built on a piece-wise formulation that makes its implementation tricky and highly substance dependent. By version 2.0.7, the Span and Wagner model was implemented in the mp1 class, which replaced if97, and allowed the inclusion of many more substances. Today, the inclusion of more multi-phase models is the highest priority of work on the back-end.
Units: Version 2.0.1 also saw the addition of a user-configurable system of units. Because unit conversion is dangerously more complicated than one might expect at first glance, the PYroMat unit conversion system is carefully documented in the PYroMat User and Developer Handbook.
Numerical methods: Numerical iteration to invert functions is an essential part of evaluating these property models, and that is especially trick when phase changes. PYroMat has always implemented its own custom numerical codes written in pure Python. A number of programmers out there are screaming, "WHY!?" (1) It reduces the number of back-end dependencies that need to be installed and working correctly, (2) these algorithms have been studied and tuned specifically for the types of functions one is likely to get in thermodynamic property calculations, (3) design control over the algorithm makes studying and correcting numerical convergence issues much easier, (4) I've been able to very carefully engineer a balance between speed and reliable numerical convergence, and (5) because it's fun! OK, that last one is a bad reason.
In PYroMat version 1, psolve, was exposed to the user alongside the methods that calculated properties. The user was expected to just "figure it out." It was slow, buggy, had no array support, and required quite a bit from the user. By version 1.4, I abandoned this approach in favor of class- and property-specific methods like T_h(). By version 2.2.0, those methods are still in the core code for reverse compatibility, but now we use a different approach.
The oldest codes used in PYroMat were variations on Newton-Rhapson iteration with maximum and minimum guesses set to guard against divergence. That approach is still implemented in the back-end _iter1 method. That works pretty well with ideal gas properties, but it fails miserably with multi-phase properties. Tests with bisection methods were highly stable, but disappointingly slow. The _hybrid1 back-end method was introduced in version 2.1.0, which implements a custom hybrid of Newton and bisection iteration. It is described in detail in the User and Developer Handbook.
PYroMat even uses its own codes for efficiently evaluating polynomials and their derivatives. Of course, Numpy has algorithms for this, but they use a "dense" list of coefficients. In multi-phase models with polynomials on both temperature and density, there might be hundreds of possible combinations of powers of the two, but most of them will not be represented in the model. PYroMat implements a "sparse" polynomial representation, where only non-zero terms are stored and dealt with.
Big front-end improvements Version 2.1.0 represented the single largest rewrite of the back-end since PYroMat's original release. It was released in 2021 after a long delay of writing and testing, and it made a number of important improvements to back-end numerical methods, added a number of new multi-phase substances, and finally exceeded 1,000 total substances. With more substances came better methods to search them; the info() function was improved as well, allowing users to search for substances by class, collection, atomic contents, name, and more.
Released in 2022, version 2.2.0 competes with 2.1.0 for the biggest back-end rewrite. The most substantial change was that all inverse property methods are now hidden from the user in a generic back-end argument parsing system, _argparse(). Instead of calculating temperature with T_h(), users can simply call T(h=...), and the argument parsing automatically handles the property inversion. A new search() and info() function were added to the package front-end, which allow users to view and search the database entries more easily. Substance meta-data were added to the back-end like common name lists, InChI, and CAS designations, and these fields were made searchable. Finally, a number of redundant ideal gas entries were eliminated by converting to the Hill naming convention, so the substance total dipped just below 1,000.
The PYroMat logo is entirely thanks to the wonderful and talented Janet Montgomery. I mentioned to her that the package needed an icon, and before I had time to think I had a multitude of options of every color and shape. Together, we whittled it down to a snake's head combined with a flame to represent the union of Python and thermal properties. Thanks, Janet.
My first priority is to broaden the number of multi-phase substances supported. As of version 2.1.0, only five were supported (R134a, CH4, CO2, H2O, and N2). Now that the mp1 class is mature with stable numerical tools, the work required to add these sophisticated models should be much less than in the past.
I would like to add viscosity, heat transfer, and other transport models to the ideal gas and possibly the multi-phase classes. This has long been a goal of mine, but so far people have not been requesting it.
A web-based GUI for PYroMat is under active development and will be released just as soon as we can complete it. We look forward to a launch!
PYroMat is released under the GNU Public License version 3. You, the user, are free to copy the code. You are free to edit the program (please do). You are free to share your changes with anyone you like as long as you tell people you made changes. In fact, I'd really love to hear about it if you make your own additions!
While I will continue to pour effort into verifying the integrity of the code and the data I maintain, PYroMat is distributed without any warranty; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.