Skip to content

Commit 059439a

Browse files
authored
Derivative re-factor and updated Example 7 validation (#110)
* refactored derivatives for cleaner formulation and faster solves * removed finite differences from smooth derivatives * updated example7 validation example * version patch increment
1 parent 4a917f4 commit 059439a

11 files changed

Lines changed: 199 additions & 102 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ All notable user-visible changes to this project are documented here.
44

55
## [Unreleased]
66

7+
### Changed
8+
9+
### Fixed
10+
11+
### Added
12+
13+
## [3.3.3] - 2026-08-24
14+
715
### Changed
816
- Reworked equilibrium total-derivative post-processing as a vector-valued
917
response Jacobian and reused one Jacobian factorization across all direct

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
88
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
99
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
1010
project(CEA
11-
VERSION 3.3.2
11+
VERSION 3.3.3
1212
LANGUAGES Fortran
1313
)
1414

Doxyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ PROJECT_NAME = "CEA"
4848
# could be handy for archiving the generated documentation or if some version
4949
# control system is used.
5050

51-
PROJECT_NUMBER = 3.3.2
51+
PROJECT_NUMBER = 3.3.3
5252

5353
# Using the PROJECT_BRIEF tag one can provide an optional one line description
5454
# for a project that appears at the top of each page and should give viewers a

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
copyright = ''
2323
author = 'Mark Leader'
2424
version = '3.3'
25-
release = '3.3.2'
25+
release = '3.3.3'
2626

2727
# -- General configuration ---------------------------------------------------
2828
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

project.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
project: CEA
3-
version: 3.3.2
3+
version: 3.3.3
44
src_dir: ./source
55
output_dir: ./docs
66
project_github: https://github.com/nasa/cea
@@ -18,4 +18,4 @@ search: true
1818
print_creation_date: false
1919
extra_filetypes:
2020
exclude: *.pf
21-
---
21+
---

source/bind/python/cea/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "3.3.2"
1+
__version__ = "3.3.3"
22

33
# initialize libcea, loading in the default data files
44
from cea.lib.libcea import init as libcea_init

source/main.f90

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ subroutine run_shock_problem(prob, thermo, solver, solutions, branch_codes)
556556
type(ShockSolution) :: solution
557557
real(dp) :: T0, P0, u1, mach1
558558
real(dp), allocatable :: weights(:)
559-
logical :: incident, input_reflected, frozen, equilibrium, incident_frozen, reflected_frozen, reflected, use_mach
559+
logical :: input_reflected, frozen, equilibrium, incident_frozen, reflected_frozen, reflected, use_mach
560560
logical :: stop_after_branch, branch_failed
561561
integer :: i, k, idx_P, idx_T, npts, num_u1, num_P, num_T
562562
integer, parameter :: BR_INCD_EQ = 1
@@ -585,21 +585,12 @@ subroutine run_shock_problem(prob, thermo, solver, solutions, branch_codes)
585585
products = Mixture(thermo, product_names, ions=prob%problem%include_ions)
586586

587587
! Get the problem flags
588-
if (prob%problem%shk_incident) then
589-
incident = .true.
590-
else
591-
incident = .false.
592-
end if
593-
594588
if (prob%problem%shk_reflected) then
595589
input_reflected = .true.
596590
reflected = .true.
597591
else
598592
input_reflected = .false.
599593
reflected = .false.
600-
if (.not. incident) then
601-
incident = .true. ! Incident by default
602-
end if
603594
end if
604595

605596
if (prob%problem%equilibrium) then
@@ -617,29 +608,16 @@ subroutine run_shock_problem(prob, thermo, solver, solutions, branch_codes)
617608
end if
618609
end if
619610

620-
! Match the SHCK branch sequencing. When the input explicitly requests
621-
! incident-shock output (`inc`), CEA2 reports only that incident branch,
622-
! with the reflected state attached if requested. The extra mixed
623-
! equilibrium/frozen permutations are only explored for reflected-only
624-
! request patterns.
625-
if (incident) then
626-
npts = 1
627-
else
628-
npts = 0
629-
if (equilibrium) then
630-
npts = npts + 1
631-
if (input_reflected .and. frozen) then
632-
npts = npts + 1
633-
else if (input_reflected) then
634-
! Equilibrium-only reflected shock prints incident and reflected states together.
635-
end if
636-
end if
637-
if (frozen) then
638-
npts = npts + 1
639-
if (input_reflected .and. equilibrium) npts = npts + 1
640-
end if
641-
if (npts == 0) npts = 1
642-
end if
611+
! Match the SHCK branch sequencing. Each requested composition model
612+
! produces an incident branch. A reflected request applies each
613+
! requested model to every incident branch, so requesting both
614+
! equilibrium and frozen models produces four incident/reflected
615+
! combinations.
616+
npts = 0
617+
if (equilibrium) npts = npts + 1
618+
if (frozen) npts = npts + 1
619+
if (npts == 0) npts = 1
620+
if (input_reflected) npts = npts*npts
643621

644622
! Get the loop sizes
645623
num_u1 = 1
@@ -740,7 +718,7 @@ subroutine run_shock_problem(prob, thermo, solver, solutions, branch_codes)
740718
if (.not. solution%converged .and. input_reflected) branch_failed = .true.
741719
end do
742720

743-
if ((.not. incident) .and. input_reflected .and. frozen) then
721+
if (input_reflected .and. frozen) then
744722
k = k + 1
745723
branch_codes(k) = BR_REFL_EQ_FROM_EQ
746724
incident_frozen = .false.
@@ -784,7 +762,7 @@ subroutine run_shock_problem(prob, thermo, solver, solutions, branch_codes)
784762
if (input_reflected .and. branch_failed) stop_after_branch = .true.
785763
end if
786764

787-
if (frozen .and. .not. stop_after_branch .and. (.not. incident .or. .not. equilibrium)) then
765+
if (frozen .and. .not. stop_after_branch) then
788766
k = k + 1
789767
if (input_reflected) then
790768
branch_codes(k) = BR_INCD_FRZ_REFL_FRZ
@@ -1101,7 +1079,9 @@ subroutine shock_output(ioout, prob, solver, solutions, branch_codes)
11011079
have_reflected_state = .false.
11021080
do i = 1, m
11031081
if (solutions(i, 1, k)%eq_soln(2)%T > 0.0d0) have_incident_state = .true.
1104-
if (solutions(i, 1, k)%eq_soln(3)%T > 0.0d0) have_reflected_state = .true.
1082+
if (size(solutions(i, 1, k)%eq_soln) >= 3) then
1083+
if (solutions(i, 1, k)%eq_soln(3)%T > 0.0d0) have_reflected_state = .true.
1084+
end if
11051085
end do
11061086
if (.not. have_incident_state) then
11071087
write_incd_frz = .false.

test/main_interface/example7.inp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,21 @@
66
! reactants at the temperature given (300 K) using the thermo.lib
77
! coefficients.
88
! (c) Reactants are given in moles (moles = ...).
9-
! (d) Initial gas pressures are 10 and 20 mm Hg (p,mmhg=10,20,)
10-
! (e) Seven initial gas velocities are assigned (u1=1000,1100,1200,
11-
! 1250,1300,1350,1400,). Note units of u1 are always m/s.
9+
! (d) The initial gas pressure is 10 mm Hg (p,mmhg=10,).
10+
! (e) Six initial gas velocities are assigned (u1=1100,1200,1250,
11+
! 1300,1350,1400,). Note units of u1 are always m/s.
1212
! (f) Equilibrium calculations are to be performed for incident shock
1313
! conditions (incd eql).
1414
! (g) Frozen calculations are to be performed for incident shock
1515
! conditions (incd froz).
16-
! (h) No 'outp' dataset is given since the default values of the
17-
! the parameters have the desired values (e.g. SI units).
16+
! (h) Long-format output is requested for validation.
1817

1918
reac name= H2 moles= 0.050 t(k) 300.00
2019
name= O2 moles= 0.050 t(k) 300.00
2120
name= Ar moles= 0.900 t(k) 300.00
2221

2322
problem case=7 p,mmhg=10, shock u1=1100,1200,1250,1300,1350,1400,
24-
incd refl eql
23+
incd eql froz
2524
output long
2625

27-
end
26+
end

test/main_interface/parse_output.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ def parse_output(fname):
7575
trace_next = False # Trace species get parsed on the next line
7676
frozen = False # Transport property type
7777
count_blank = 0 # Number of blank lines in a row
78+
shock_mode = "unknown"
79+
shock_state = "unknown"
7880

7981
# Parse the file
8082
f = open(fname, "r")
@@ -94,6 +96,17 @@ def parse_output(fname):
9496
if vals[0] == "!":
9597
continue
9698

99+
if vals[0].startswith("WARNING") or vals[0] == "ANSWERS":
100+
continue
101+
102+
upper_line = line.upper()
103+
if "EQUILIBRIUM COMPOSITION FOR INCIDENT SHOCKED" in upper_line:
104+
shock_mode = "equilibrium"
105+
continue
106+
if "FROZEN COMPOSITION FOR INCIDENT SHOCKED" in upper_line:
107+
shock_mode = "frozen"
108+
continue
109+
97110
# Check for data headings
98111
if vals[0] == "THERMODYNAMIC":
99112
if len(vals) > 1:
@@ -105,8 +118,18 @@ def parse_output(fname):
105118
parse_flag = Parse.THERMO
106119
continue
107120

108-
if (vals[0] == "INITIAL") or (vals[0] == "SHOCKED"):
121+
if vals[0] == "INITIAL":
109122
parse_flag = Parse.SHOCK
123+
shock_state = "initial"
124+
continue
125+
126+
if vals[0] == "SHOCKED":
127+
parse_flag = Parse.SHOCK
128+
shock_state = "reflected" if "REFLECTED" in upper_line else "incident"
129+
if "EQUILIBRIUM" in upper_line:
130+
shock_mode = "equilibrium"
131+
elif "FROZEN" in upper_line:
132+
shock_mode = "frozen"
110133
continue
111134

112135
if (vals[0] == "UNBURNED") or (vals[0] == "BURNED"):
@@ -200,11 +223,13 @@ def parse_output(fname):
200223
for i in range(len(vals)):
201224
vals[i] = parse_numeric(vals[i])
202225

226+
property_key = f"{shock_mode}:{shock_state}:{property_name}"
227+
203228
# Check if these values are already in the results dict; we are just adding more points
204-
if (property_name in shock): # Adding new entries to existing values
205-
shock[property_name]["vals"] = np.append(shock[property_name]["vals"], np.array(vals))
229+
if (property_key in shock): # Adding new entries to existing values
230+
shock[property_key]["vals"] = np.append(shock[property_key]["vals"], np.array(vals))
206231
else: # Adding a new property type
207-
shock[property_name] = {"units":unit_name, "vals":np.array(vals)}
232+
shock[property_key] = {"units":unit_name, "vals":np.array(vals)}
208233

209234
if parse_flag == Parse.DETON:
210235
# Parse the name and the units
@@ -250,6 +275,12 @@ def parse_output(fname):
250275
elif (name_vals[0] == "SHOCKED"):
251276
trace_next = False
252277
parse_flag = Parse.SHOCK
278+
upper_line = line.upper()
279+
shock_state = "reflected" if "REFLECTED" in upper_line else "incident"
280+
if "EQUILIBRIUM" in upper_line:
281+
shock_mode = "equilibrium"
282+
elif "FROZEN" in upper_line:
283+
shock_mode = "frozen"
253284
continue
254285
else:
255286
for species_name in name_vals:

0 commit comments

Comments
 (0)