Skip to content

[#97] Introduce throttle control; tabulate JICF over momentum-flux ratio#108

Open
jjhans wants to merge 1 commit into
jicf-cleanup-deadcode-and-meshfrom
97-throttle-control
Open

[#97] Introduce throttle control; tabulate JICF over momentum-flux ratio#108
jjhans wants to merge 1 commit into
jicf-cleanup-deadcode-and-meshfrom
97-throttle-control

Conversation

@jjhans

@jjhans jjhans commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Closes #97.

Replaces the pre-specified mass flow rate schedule with a throttle-driven, dynamically-updatable injector, and tabulates the JICF model over a range of momentum-flux ratios J (at a user-specified resolution) rather than a schedule of mass flow rates — per issue #97. The original fixed-schedule behavior is recovered by setting the throttle as a function of time.

Design

Issue #97 requires both (a) generating the model over a J range at a resolution, and (b) a dynamically-updatable mass flow rate controlled by a throttle parameter. So JICModel becomes a throttle-agnostic library and the runtime throttle moves onto the injector.

The table is indexed by J only (1D). J and the injector "loading" are 1:1 under the current fixed inflow, and the issue/plan only call for a J range — so the second (loading) axis is intentionally out of scope here.

Changes

  • generate.pyJICModel keyed on a J grid instead of a time schedule. Takes J + per-J (rho_inj, u_inj, T_inj); sorts J ascending and reorders the injected-fluid state. All tables/interpolators keyed on J. J is written to the HDF5 groups and checked on load (_cached_J_matches) so a stale mdot-indexed cache is not silently reused.
  • source.pyFuelInjector now holds the runtime throttle schedule and derives J(t) from the live crossflow inflow + jet state (forward-compatible with variable inflow). Convected fluid tips carry [x, mdot, J] (plotting uses mdot, the variance lookup uses J).
  • combustor.pyinjector= now takes pre-built FuelInjector(s).
  • case_setup.pyget_injectors_fpv builds the J grid by sweeping the equivalence-ratio range at the requested resolution, plus a separate runtime throttle schedule, and returns a FuelInjector. plot.py, hyshot_ii_jic.py, and example 04 updated to the new interfaces.

Testing

  • ruff clean; full fast test suite passes (124 passed).
  • Targeted checks confirm J sort/reindex, J-keyed interpolation (incl. midpoint), J(t) computation, [x, mdot, J] tip layout, the J-axis variance lookup, and the cache guard.
  • Not run: full HyShot FPV end-to-end — still blocked by the pre-existing profile.py NaN divide-by-zero at the injector origin + ~10 min precompute (out of scope for Introduce throttle control for JICF #97).

Replace the pre-specified mass flow rate schedule with a throttle-driven,
dynamically-updatable injector, and tabulate the JICF model over a range of
momentum-flux ratios J (at a user-specified resolution) rather than a schedule
of mass flow rates. The original fixed-schedule behavior is recovered by
setting the throttle as a function of time.

- JICModel: throttle-agnostic library keyed on a J grid instead of a time
  schedule. Takes J + per-J (rho_inj, u_inj, T_inj); sorts J ascending and
  reorders the injected-fluid state to match. All tables and interpolators are
  keyed on J. J is stored in the HDF5 groups and guarded on load
  (_cached_J_matches) so a stale mdot-indexed cache is not silently reused.
- FuelInjector: now holds the runtime throttle schedule and derives J(t) from
  the live crossflow inflow and jet state, keeping lookups correct if the
  inflow is later allowed to vary. Convected fluid tips carry [x, mdot, J].
- Combustor: injector= now takes pre-built FuelInjector(s).
- get_injectors_fpv: builds the J grid by sweeping the equivalence-ratio range
  at the requested resolution, plus a separate runtime throttle schedule, and
  returns a FuelInjector. plot.py, hyshot_ii_jic.py, and example 04 updated to
  the new interfaces.

@TimothyEDawson TimothyEDawson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A good start, but still a lot of changes to be made here. Ideally the AnalyticJICF wouldn't know about much besides the input J, as most of the fuel and oxidizer flow info is simply used to ultimately compute J. There are a few exceptions, though, like Z_cl_int and Z_cl which need the density ratio rho_inj / rho. It doesn't appear that anything actually needs mdot_inj except for the calculation of phi_gl and Z_gl, and I think that could be reformulated in terms of J and the density ratio.

Likewise, once that is simplified, the JICModel can also be simplified as it only needs info like rho_inj for passing on to AnalyticJICF.

Currently the FuelInjector still requires a schedule of everything. I was thinking it would accept an mdot_f_interp function as an input and default to a constant, externally-settable, mdot value. I'm not sure exactly how I want to handle E_inj and u_inj just yet. Still need to do some thinking about that.

if injector is None:
self.injectors: list[FuelInjector] = []
elif isinstance(injector, list):
self.injectors = [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not strictly opposed to this change, but the reasoning behind creating the FuelInjector objects internally is to ensure they use the same FluidPhysics and Geometry objects as the Combustor.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants