Skip to content

Thermally perfect gas as an AbstractEquationOfState#3079

Draft
DanielDoehring wants to merge 28 commits into
trixi-framework:mainfrom
DanielDoehring:ThermallyPerfGas
Draft

Thermally perfect gas as an AbstractEquationOfState#3079
DanielDoehring wants to merge 28 commits into
trixi-framework:mainfrom
DanielDoehring:ThermallyPerfGas

Conversation

@DanielDoehring

@DanielDoehring DanielDoehring commented Jun 13, 2026

Copy link
Copy Markdown
Member

For high temperature flows, $c_p$ and $\gamma$ should no longer be treated as constant. In turn, they can modeled as functions of only temperature ("thermally perfect") while preserving the ideal gas relation $p = R_\text{spec} \rho T$ which makes them very attractive.
The go-to data that relates $c_p$ to $T$ is given by the NASA piecewise 9-degree polynomials.

This is an experimental implementation that implements thermally perfect gases as an equation of state.
However, I would like to not restrict this to NonIdealCompressibleEulerEquations since the original CompressibleEulerEquations could readily be extended with a non-constant gamma = gamma(T) . In fact, we already have this behaviour for the viscosity:

# In the simplest cases, the user passed in `mu` or `mu()`
# (which returns just a constant) but
# more complex functions like Sutherland's law are possible.
# `dynamic_viscosity` is a helper function that handles both cases
# by dispatching on the type of `equations.mu`.
mu = dynamic_viscosity(u, equations)

"""
dynamic_viscosity(u, equations)
Wrapper for the dynamic viscosity that calls
`dynamic_viscosity(u, equations.mu, equations)`, which dispatches on the type of
`equations.mu`.
For constant `equations.mu`, i.e., `equations.mu` is of `Real`-type it is returned directly.
In all other cases, `equations.mu` is assumed to be a function with arguments
`u` and `equations` and is called with these arguments.
"""
dynamic_viscosity(u, equations) = dynamic_viscosity(u, equations.mu, equations)
dynamic_viscosity(u, mu::Real, equations) = mu
dynamic_viscosity(u, mu::T, equations) where {T} = mu(u, equations)

I also added varnames for cons2thermo (this is probably something for a different PR) to be able to save the thermal variables to get e.g. plots of temperature conveniently:

Screenshot from 2026-06-13 18-26-09 Screenshot from 2026-06-20 10-58-19

Comparison to ideal gas:
One can see that the shock is slightly further away from the cylinder compared to the real gas case.

Screenshot from 2026-06-23 22-40-48

@DanielDoehring DanielDoehring requested a review from jlchan June 13, 2026 08:59
@DanielDoehring DanielDoehring added enhancement New feature or request discussion labels Jun 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Review checklist

This checklist is meant to assist creators of PRs (to let them know what reviewers will typically look for) and reviewers (to guide them in a structured review process). Items do not need to be checked explicitly for a PR to be eligible for merging.

Purpose and scope

  • The PR has a single goal that is clear from the PR title and/or description.
  • All code changes represent a single set of modifications that logically belong together.
  • No more than 500 lines of code are changed or there is no obvious way to split the PR into multiple PRs.

Code quality

  • The code can be understood easily.
  • Newly introduced names for variables etc. are self-descriptive and consistent with existing naming conventions.
  • There are no redundancies that can be removed by simple modularization/refactoring.
  • There are no leftover debug statements or commented code sections.
  • The code adheres to our conventions and style guide, and to the Julia guidelines.

Documentation

  • New functions and types are documented with a docstring or top-level comment.
  • Relevant publications are referenced in docstrings (see example for formatting).
  • Inline comments are used to document longer or unusual code sections.
  • Comments describe intent ("why?") and not just functionality ("what?").
  • If the PR introduces a significant change or new feature, it is documented in NEWS.md with its PR number.

Testing

  • The PR passes all tests.
  • New or modified lines of code are covered by tests.
  • New or modified tests run in less then 10 seconds.

Performance

  • There are no type instabilities or memory allocations in performance-critical parts.
  • If the PR intent is to improve performance, before/after time measurements are posted in the PR.

Verification

  • The correctness of the code was verified using appropriate tests.
  • If new equations/methods are added, a convergence test has been run and the results
    are posted in the PR.

Created with ❤️ by the Trixi.jl community.

@DanielDoehring DanielDoehring changed the title Thermally perfect gas as Equation of state Thermally perfect gas as AbstractEquationOfState Jun 13, 2026
@DanielDoehring DanielDoehring changed the title Thermally perfect gas as AbstractEquationOfState Thermally perfect gas as an AbstractEquationOfState Jun 13, 2026
@codecov

codecov Bot commented Jun 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 63.63636% with 44 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.81%. Comparing base (1d411ba) to head (8832995).

Files with missing lines Patch % Lines
...elixir_euler_therm_perf_cylinder_bowshock_mach6.jl 0.00% 39 Missing ⚠️
...uations/equation_of_state_thermally_perfect_gas.jl 93.55% 4 Missing ⚠️
...e_1d_dgsem/elixir_euler_therm_perf_density_wave.jl 95.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3079      +/-   ##
==========================================
- Coverage   96.89%   96.81%   -0.08%     
==========================================
  Files         647      650       +3     
  Lines       50024    50145     +121     
==========================================
+ Hits        48466    48543      +77     
- Misses       1558     1602      +44     
Flag Coverage Δ
unittests 96.81% <63.64%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

@jlchan

jlchan commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

This is great to see, @DanielDoehring; I was hoping to add this myself eventually.

Agreed that standard CompressibleEulerEquations could be extended with gamma(T), but the associated routines (EC fluxes, etc) may still assume gamma is constant.

What about adding type parameters to NonIdealCompressibleEulerEquations which identify whether the pressure EOS is non-ideal? This could differentiate between CPG, TPG, and fully non-ideal EOS?

@DanielDoehring

Copy link
Copy Markdown
Member Author

Agreed that standard CompressibleEulerEquations could be extended with gamma(T), but the associated routines (EC fluxes, etc) may still assume gamma is constant.

I noticed since there are flux_terashima_etal and flux_terashima_etal_central this might not be required since we can reuse a lot of machinery. 👍

What about adding type parameters to NonIdealCompressibleEulerEquations which identify whether the pressure EOS is non-ideal? This could differentiate between CPG, TPG, and fully non-ideal EOS?

We could think about that, does this change something in the implementation/allow for simplifications? I did not go through the entire equation of state and nonideal Euler equations, so maybe there are some spots where things could be more efficient for an ideal gas pressure/density/temperature relation.

@jlchan

jlchan commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

I think of thermally perfect as modifying the internal energy/temperature relationship, while a nonideal EOS modifies the pressure equation.

Specializing on thermally perfect this way might not make too much of a difference computationally, however.

Comment on lines +89 to +100
tol = 100 * eps(Float64)
dp = pressure(V, T, eos()) - p
iter = 1
while abs(dp) / abs(p) > tol && iter < 100
dp = pressure(V, T, eos()) - p
dpdT_V = ForwardDiff.derivative(T -> pressure(V, T, eos()), T)
T = max(tol, T - dp / dpdT_V)
iter += 1
end
if iter == 100
@warn "Solver for temperature(V, p) did not converge"
end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use this fairly often for non ideal fluids; maybe it makes sense to factor this into a helper function? Happy to also do it if you file an issue

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed👍 - then we should also query eos as equations.eos or unpack it (this is why I added eos() as a function up there (albeit unnecessary convoluted)

@DanielDoehring DanielDoehring Jun 16, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do the following: You @jlchan prepare this change across the repository, and I dedicate some time to adding documentation for the thermally perfect gas and the specific 9degree piecewise polynomial (following your suggestion below?)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. To clarify, are you thinking of making a separate PR for AbstractThermallyPerfectGas <: AbstractEquationOfState first, or making a PR to this PR?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would change this PR I think 👍

# Fetch temperature interval index for a given temperature to select the correct polynomial coefficients.
# `clamp` ensures that even for temperatures outside the provided bounds,
# a valid index is returned to prevent a bounds error.
return clamp(searchsortedlast(eos.temperature_bounds, T), 1, N)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How efficient is searchsortedlast here?

@knstmrd

knstmrd commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

A bit of an outsider's comment: the naming is a bit confusing (to me, at least), as the equations implement a specific (NASA 9th degree polynomial) model; so maybe something like ThermallyPerfectGas9PolyFit?

@jlchan

jlchan commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

A bit of an outsider's comment: the naming is a bit confusing (to me, at least), as the equations implement a specific (NASA 9th degree polynomial) model; so maybe something like ThermallyPerfectGas9PolyFit?

I drafted a comment on this last night but looks like it didn't send.

I think something like an AbstractThermallyPerfectGas <: AbstractEquationOfState with ThermallyPerfectGas9PolyFit <: AbstractThermallyPerfectGas would make sense, and allow one to just specialize on a smaller number of non-ideal EOS subroutines.

@DanielDoehring

Copy link
Copy Markdown
Member Author

A bit of an outsider's comment: the naming is a bit confusing (to me, at least), as the equations implement a specific (NASA 9th degree polynomial) model; so maybe something like ThermallyPerfectGas9PolyFit?

I drafted a comment on this last night but looks like it didn't send.

I think something like an AbstractThermallyPerfectGas <: AbstractEquationOfState with ThermallyPerfectGas9PolyFit <: AbstractThermallyPerfectGas would make sense, and allow one to just specialize on a smaller number of non-ideal EOS subroutines.

Fine with me 👍

@DanielDoehring

Copy link
Copy Markdown
Member Author

Should wait for #3093

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

Labels

discussion enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants