Input file format

Top-level keys

Every turbigen command takes an input YAML file describing a turbomachine. The file holds one top-level key for each phase of the design pipeline. Only fluid: and mean_line: are required; every other key is optional and turbigen will simply halt if it does not have the data to proceed any further. Every key and subkey is described in full the Schema reference below. The following table lists which key is read by which command.

Key

Read by

fluid:, mean_line:, annulus:, blades:

every command, listed in Command-line interface

mesh:, solver:, operating_point:, inlet_profile:

commands that run CFD: run, iterate and chic

iterate:, database:

iterative geometry updates in iterate

chic:

running a characteristic in chic

batch:

configuration sweeping in batch

post_process:

all commands excluding design and batch

job:

any command given --queue, described in Command-line interface

A key of the file is written with the trailing colon it carries there; a command typed at the shell is not. That tells apart the three names that are both, so iterate: is what the file holds and iterate is what runs it.

Two more top-level keys are not phases of the design: include:, described below, and result:, which a finished run writes.

Duplicate keys or subkeys are refused.

The whole file is checked early before anything is designed, so a typo will show up at the earliest opportunity.

A typical configuration file looks something like this:

# Turbine cascade

fluid:
  type: perfect
  cp: 1005.0
  gamma: 1.4
  mu: 1.8e-5

mean_line:
  type: turbine_cascade
  span: [0.1, 0.11]
  Alpha: [40.0, -65.0]
  Ma2: 0.6
  Ys: 0.029
  htr: 0.95
  Po1: 1.0e5
  To1: 300.0

annulus:
  type: aspect_ratio
  AR_row: [2.0]
  AR_gap: [1.0, 1.0]

blades:
  - count:
      type: Co
      Co: 0.7
    sections:
      - spf: 0.5
        dchi_LE: 10.0
        dchi_TE: -2.0
        camber:
          type: quadratic
          aft_loading: 0.0
        thickness:
          type: taylor
          R_LE: 0.05
          t_max: 0.12
          m_tmax: 0.3
          kappa_max: 0.0
          t_TE: 0.03
          tanwedge: 0.18

mesh:
  type: h
  yplus: 30.0
  dm_TE: 0.0
  AR_cusp: 2.0
  ni_cusp: 5

iterate:
  correct:
    - type: Re_surf
      target: 4.0e5
    - type: deviation
      tolerance: 0.5
    - type: mean_line
      variables: [Ys]
      clip: 0.01
      tolerance: 0.05

solver:
  type: ember
  n_step: 1000
  n_step_avg: 250
  n_step_log: 50
  cfl: 4
  n_stage: 4
  sf_resid: 1
  fac_mgrid: 0.2
  n_levels: 3
  gain_filt: 0
  delta_filt: 0.1

Includes

A top-level include: names other files whose keys are merged underneath this one’s, so a site’s job: settings or a standard solver: can be written once and shared across many cases:

include:
  - common.yaml

solver:
  n_step: 2000

The merging rules are: later beats earlier, the including file beats everything it includes, and mappings merge exactly one level deep. So the solver: above keeps everything common.yaml set and changes n_step: alone. Lists replace whole, since merging blades: by index is never the row you meant.

File names are resolved relative to the file that names them, never to the directory you ran from, so a case directory and its fragments can be copied anywhere together. Two files in one include: list that both set the same top-level key is an error.

Overriding values from the command line

Any value in the file can be replaced from the command line with -s, which is repeatable:

$ turbigen design input.yaml -s mean_line.psi=1.8
$ turbigen design input.yaml -s mean_line.Ys=0.03 -s blades[0].count.Co=0.8

The value after the = is read as YAML, so lists and mappings work as well as numbers. Keys are joined with dots, and entries in a list are indexed with brackets — blades[0].sections[1].dchi_TE — or with a bare number between dots, blades.0.sections.1.dchi_TE, if that is easier to quote in a shell. A path names a key without giving it a value, so it carries no colon.

Schema reference

What follows is generated from the code that reads the file, so it lists every key and what it may be written with. A key with a default may be left out, and takes that default; a key with no default has to be written. A key that is a link holds further keys of its own, listed in the section it points to.

Designs of your own, found in a turbigen_plugins directory, do not appear here: this is what turbigen ships with.

Key

Value

Description

fluid:

mapping; one of perfect, real

Working fluid and its equation of state.

mean_line:

mapping; one of axial_turbine, turbine_cascade

Mean-line design.

annulus:

mapping, default null; one of aspect_ratio, fixed_axial_chord

Annulus design. Omit it to design the mean line alone.

blades:

list of mappings, default []

Blade designs, one per row. Omit them to design the annulus alone.

mesh:

mapping, default null; one of h

Mesh generation. Only needed by the commands that make a grid.

solver:

mapping, default null; one of ember

Flow solver. Only needed by the commands that solve.

operating_point:

mapping, default null

Where to run the machine, as a departure from its design point. Read by no design stage: the same geometry runs at every point of its characteristic, so this changes the boundary conditions and nothing else.

inlet_profile:

mapping, default null; one of legendre, sampled

What feeds the machine, if not a uniform flow.

Beside the operating point rather than inside it, because the same profile applies at every point of a characteristic — a rig’s intake or the stage upstream does not change because you moved along the map. Nested, a batch over operating_point.DP_adjust would copy the whole profile into every member.

iterate:

mapping, default Iteration(correct=(), max_iter=10)

Closing the loop between the design and its CFD. Only needed by the command that iterates, but the errors it names are measured by every run that solves.

database:

mapping, default null

Finished runs to start the iterators from, instead of from whatever this file says. Read once, by the command that iterates.

chic:

mapping, default null

How to sweep a characteristic to its stability limit. Read only by the command that sweeps, which holds the geometry fixed and moves the operating point alone.

batch:

mapping, default null

Design variables to vary, for covering a space with runs. Read only by the command that writes a batch, and stripped from the configs it emits: a member is one design, not a design of experiments.

post_process:

list of mappings, default []; each one of annulus, contour, convergence, sections, surface, triangle

Post-processors to run. Nothing is added implicitly: what the config asks for is what runs.

job:

mapping, default null; one of slurm, tsp

Where to execute, when --queue asks for it. Read by no design stage: a partition is a property of where you are, not of the machine.

fluid:

Base for equations of state.

Takes one of perfect, real as its type:.

type: perfect

A perfect gas with constant specific heats.

Key

Value

Description

cp:

float

Specific heat at constant pressure [J/kg/K].

gamma:

float

Ratio of specific heats [–].

mu:

float

Dynamic viscosity [kg/m/s].

Pr:

float, default 0.7

Prandtl number [–].

type: real

A real gas defined by a fitted entropy surface.

Key

Value

Description

alpha:

list of lists of floats

Legendre coefficients of the compressibility factor Z(rho, u) [–].

beta:

list of floats

Legendre coefficients of s/R along the reference isochor [–].

delta:

list of lists of floats

Legendre coefficients of the viscosity surface [–], normalised by mu_c.

gamma:

list of lists of floats

Legendre coefficients of the conductivity surface [–], normalised by kappa_c.

rho_lim:

list of two floats

Density bounds of the fit box [kg/m^3].

u_lim:

list of two floats

Internal energy bounds of the fit box [J/kg], on the datum the coefficients were fitted against.

Rgas:

float

Specific gas constant [J/kg/K].

mu_c:

float

Dynamic viscosity at the centre of the fit box [kg/m/s], the scale the delta surface is normalised by.

kappa_c:

float

Thermal conductivity at the centre of the fit box [W/m/K], the scale the gamma surface is normalised by.

scale_visc:

float, default 1.0

Factor multiplying the viscosity, for sweeping Reynolds number without touching the fit [–].

P_dtm:

float, default null

Datum pressure where u = s = 0 [Pa]. Must lie in the fit box.

Omit it and ember places the datum at the centre of the box, which is inside it by construction.

T_dtm:

float, default null

Datum temperature where u = s = 0 [K]. As P_dtm.

mean_line:

Base for mean-line designers.

Takes one of axial_turbine, turbine_cascade as its type:.

type: axial_turbine

An axial turbine stage: a stator row followed by a rotor row.

Note the use of ml.flat. A mean line is stored as (2, n_row), station by row, but the physics of a stage reads naturally in streamwise order, so this design takes the flat view once and indexes it 0, 1, 2, 3 from machine inlet to machine outlet. That view shares storage with the mean line, so writes through it land in the design being built.

Key

Value

Description

psi:

float

Stage loading coefficient [–].

phi2:

float

Flow coefficient at rotor inlet [–].

Ma2:

float

Stator exit Mach number [–].

fac_Ma3_rel:

float

Rotor exit relative Mach number, as a multiple of Ma2: [–].

mdot:

float

Mass flow rate [kg/s].

Ys:

list of floats

Pseudo entropy loss coefficient at each row exit [–].

r_rms:

float

Mean radius, constant through the stage [m].

zeta:

list of two floats, default [1.0, 1.0]

Axial velocity at stage inlet and outlet, relative to rotor inlet [–].

Po1:

float, default 100000.0

Inlet stagnation pressure [Pa].

To1:

float, default 300.0

Inlet stagnation temperature [K].

type: turbine_cascade

A single turbine blade row at fixed inlet stagnation conditions.

Key

Value

Description

span:

list of two floats

Annulus span at inlet and outlet [m].

Alpha:

list of two floats

Yaw angle at inlet and outlet [deg].

Ma2:

float

Outlet Mach number [–].

Ys:

float

Pseudo entropy loss coefficient [–], see loss_coefficient().

htr:

float, default 0.95

Outlet hub-to-tip ratio [–].

Po1:

float, default 100000.0

Inlet stagnation pressure [Pa].

To1:

float, default 300.0

Inlet stagnation temperature [K].

annulus:

Base for annulus designs.

Unlike a mean-line design, an annulus declares no n_row: it is generic over row count, which comes from the mean line handed to forward().

Takes one of aspect_ratio, fixed_axial_chord as its type:.

type: aspect_ratio

Annulus with a prescribed span-to-chord ratio for each row and gap.

The chord is meridional, and the span it is measured against is the average over the segment, so a row’s aspect ratio is set by the mean line on both sides of it. This is the specification the design correlations are written in — an aspect ratio is a number a designer carries between machines, where an axial chord in metres is not.

Key

Value

Description

nozzle_ratio:

float, default 1.0

Scaling applied to the exit span, for a nozzle area ratio [–].

merge_weight:

float, default 0.0

Blend towards a curve fitted through the endpoints only [–].

At 0 the hub and casing pass through every station. At 1 they follow a curve fitted through the first and last segments alone, which smooths curvature across the rows at the cost of missing the intermediate stations. Values between blend the two.

AR_row:

list of floats

Span-to-meridional-chord ratio of each blade row [–], length n_row.

AR_gap:

list of floats

Span-to-meridional-chord ratio of each gap, including the inlet and exit ducts [–], length n_row + 1.

type: fixed_axial_chord

Annulus with a prescribed axial chord for each row and gap.

Note that an axial chord cannot describe a segment at 90 degrees pitch angle: the arc length it implies is the chord divided by cos(Beta), so a radial segment asks for an infinite one. AspectRatio states the arc length directly and has no such limit.

Key

Value

Description

nozzle_ratio:

float, default 1.0

Scaling applied to the exit span, for a nozzle area ratio [–].

merge_weight:

float, default 0.0

Blend towards a curve fitted through the endpoints only [–].

At 0 the hub and casing pass through every station. At 1 they follow a curve fitted through the first and last segments alone, which smooths curvature across the rows at the cost of missing the intermediate stations. Values between blend the two.

cx_row:

list of floats

Axial chord of each blade row [m], length n_row.

cx_gap:

list of floats

Axial chord of each gap, including the inlet and exit ducts [m], length n_row + 1.

blades:

Design variables for one blade row.

Key

Value

Description

sections:

list of mappings

Spanwise sections, in increasing span fraction.

count:

mapping; one of Co, DFL, Nb

How many blades this row has.

tip_span:

float, default 0.0

Tip clearance as a fraction of span [–].

tip_chord:

float, default 0.0

Tip clearance as a fraction of meridional chord [–].

tip_metre:

float, default 0.0

Tip clearance as an absolute length [m].

vortex_exponent:

float, default -1.0

Spanwise swirl distribution, with tangential velocity varying as radius to this power. The default is a free vortex.

theta_offset:

float, default 0.0

Rotate the whole blade through this angle [rad].

m_stack:

float, default 0.5

Normalised meridional position the sections are stacked at [–].

sections:

One spanwise section of a blade.

Key

Value

Description

spf:

float

Span fraction this section is defined at, 0 at hub and 1 at casing.

dchi_LE:

float

Recamber of the leading edge from the local flow angle [deg].

dchi_TE:

float

Recamber of the trailing edge from the local flow angle [deg].

camber:

mapping; one of quadratic

Shape of the camber line between the end angles.

thickness:

mapping; one of taylor

Thickness distribution, normalised by meridional chord.

camber:

Base for camber line shapes.

A shape knows nothing of the blade angles: it interpolates between them.

Takes one of quadratic as its type:.

type: quadratic

Quadratic variation of camber line slope.

Key

Value

Description

aft_loading:

float, default 0.0

Shift of the camber towards the trailing edge [–].

Zero gives a linear slope distribution, positive values move the turning aft, negative values forward.

thickness:

Base for thickness distributions, normalised by meridional chord.

Takes one of taylor as its type:.

type: taylor

After Taylor (2016), two cubic splines in shape space.

The splines meet at the point of maximum thickness, where the value, slope and curvature are all continuous.

Key

Value

Description

R_LE:

float

Leading edge radius, normalised by meridional chord [–].

t_max:

float

Maximum thickness, normalised by meridional chord [–].

m_tmax:

float

Normalised meridional position of maximum thickness [–].

kappa_max:

float, default 0.0

Curvature in shape space at maximum thickness [–].

t_TE:

float, default 0.0

Trailing edge thickness, the total due to both sides [–].

tanwedge:

float, default 0.0

Tangent of the trailing edge wedge angle [–].

count:

Base for rules setting the number of blades in a row.

Takes one of Co, DFL, Nb as its type:.

type: Co

Set the number of blades using a circulation coefficient.

Key

Value

Description

Co:

float

Circulation coefficient [–].

spf:

float, default 0.5

Span fraction to take the surface length from.

type: DFL

Set the number of blades using the Lieblein diffusion factor.

Key

Value

Description

DFL:

float

Lieblein diffusion factor [–]. A typical value is 0.45; the flow separates above about 0.6.

spf:

float, default 0.5

Span fraction to take the chord from.

type: Nb

Directly specify the number of blades.

Key

Value

Description

Nb:

integer

Number of blades [–].

mesh:

Base for meshers.

Takes one of h as its type:.

type: h

Generate a mesh using H topology for each row.

Key

Value

Description

yplus:

float, default 30.0

Target wall distance in viscous units, which sets the near-wall cell size [–].

ER_stream:

float, default 1.2

Expansion ratio of streamwise grid from first LE to inlet boundary.

AR_stream:

float, default 2.0

Aspect ratio in blade-to-blade plane of cells at outlet boundary.

AR_passage:

float, default 1.0

Nominal aspect ratio in blade-to-blade plane of mid-passage cells.

AR_merid:

float, default 1.0

Aspect ratio of mid-chord cells in meridional plane.

ER_span:

float, default 1.2

Expansion ratio of spanwise grid away from hub and casing.

dm_LE:

float, default 0.001

Streamwise grid spacing at LE, normalised by meridional chord.

ni_TE:

integer, default 9

Number of streamwise points across trailing edge.

dm_TE:

float, default 0.05

Normalised meridional length over which to cluster the TE points, 0. for the true actual TE.

dspf_mid:

float, default 0.03

Spanwise grid spacing at midspan, as a fraction of span.

ER_pitch:

float, default 1.2

Expansion ratio away from aerofoil surfaces.

nk_min:

integer, default 37

Minimum number of pitchwise grid points per row.

nchord_relax:

float, default 1.0

Number of meridional chords over which pitchwise clustering is relaxed.

resolution_factor:

float, default 1.0

Multiply the number of points in each direction, keeping relative spacings.

skew_max:

float, default 45.0

Largest angle the mesh is skewed to, upstream and downstream [deg].

deswirl:

true or false, default false

If True, blend skew to axial over the outer 50% of the downstream gap of the last row (fully skewed at TE, fully axial at the domain exit). Only affects the downstream side of the final row.

AR_cusp:

float, default 0.0

Length of the trailing edge cusp, as a multiple of TE thickness.

ni_cusp:

integer, default 0

Number of streamwise points along the trailing edge cusp.

gap_contraction:

float, default 0.6

Fraction of the tip gap over which the blade is pinched to zero thickness.

solver:

Base for flow solvers.

Deliberately fieldless. Everything a solver needs is its own, and a convergence verdict belongs to the history a run produces rather than to the settings that produced it.

Takes one of ember as its type:.

type: ember

The ember explicit time-marching solver.

Every field and run itself come from ember.solver.Solver, so the settings this accepts are whatever ember accepts, always, and Solver.options() lists them.

Five defaults are restated below. ember tunes its own for large machine meshes; turbigen also meshes small cascades with thin boundary cells, where ember’s cfl = 5 is far past the stability limit its own docstring gives for the default n_stage = 0 scheme (cfl ~ 0.6). These pick the bare, single-grid scree march that holds together on those: no multigrid, no implicit residual smoothing, a Courant number inside the documented limit. A config that knows its case can raise any of them.

Key

Value

Description

n_step:

integer

Number of time steps to march [–].

n_step_log:

integer, default 10

Number of steps between convergence log messages.

n_step_avg:

integer, default 1

Number of steps at the end of the march to average the solution over.

cfl:

float, default 0.4

Constant CFL number for the march

turbigen changes this default; ember’s own is 5.0.

sf4:

float, default 0.008

Fourth-order smoothing factor.

sf2:

float, default 0.002

Second-order smoothing factor.

inviscid:

true or false, default false

Skip viscous terms in the sources evaluation.

fac_visc:

float, default 1.0

Multiplier on the turbulent-diffusion timestep radius; >1 tightens the viscous limit to recover the inviscid stable CFL.

sf_resid:

float, default 0.0

Implicit residual smoothing factor. Applied to the fine residual by update_residual() (sf) and, on both integrators, to the coarse block-restricted residual of the multigrid correction (advance_rk_stage_mg()’s sf_irs for RK, scree_step()’s sf_irs for scree). The coarse smoothing needs n_levels > 0 to have any effect.

turbigen changes this default; ember’s own is 1.0.

gain_filt:

float, default 0.0

Selective frequency damping gain.

delta_filt:

float, default 1.0

Selective frequency damping filter width (higher is smoother).

n_stage:

integer, default 0

Number of time integration stages per step. 0 for scree, >=1 for RK.

n_levels:

integer, default 0

Number of coarse multigrid levels; 0 disables multigrid. Honored by both integrators (scree_step() and rk_step()).

turbigen changes this default; ember’s own is 3.

fac_mgrid:

float, default 0.0

Scaling factor on multigrid corrections. Honored by both integrators (scree_step() and rk_step()).

turbigen changes this default; ember’s own is 0.2.

expon_mgrid:

float, default 1.414

Base of the per-level multigrid decay, coef_l ~ expon_mgrid**-(l-1). Honored by both integrators (scree_step() and rk_step()).

dampin:

float, default 0.0

Negative-feedback change limiter (multall’s DAMP); 0 disables it.

rf_inlet:

float or null, default 0.05

Characteristic under-relaxation (sigma) on every InletPatch. Imposed on every such patch at the start of the run, so the default overrides a value the patches carried in; pass None to leave whatever they already hold.

rf_outlet:

float or null, default 0.05

As rf_inlet, for every OutletPatch. This is the characteristic relaxation only; the spanwise radial-equilibrium profile has its own, set via set_adjustment(rf=...).

rf_mix:

float or null, default 0.01

As rf_inlet, for every MixingPatch. This is each side’s own characteristic relaxation; rf_exchange is the separate factor on the cross-plane exchange between them.

rf_exchange:

float or null, default 0.01

Relaxation of the cross-plane mismatch on every MixingPatch. Read from the patches by MixingCommunicator at each exchange. As rf_inlet, the default is imposed and None leaves each plane’s own value alone.

mix_reflective:

true or false, or null, default false

Run every mixing plane as a reflective one, imposing the mixed-out state directly instead of the characteristic exchange.

operating_point:

Where a fixed machine is run, as a departure from its design point.

A design states one condition; a machine has a whole characteristic. This is how to reach the rest of it without redesigning anything, which is why it is read here and not by any design stage — and why it sits outside turbigen.database.SUBTREE, so that two runs of one machine at different back pressures are not read as two different designs.

Key

Value

Description

DP_adjust:

float, default 0.0

Change in the design pressure change through the machine, as a fraction [–].

mdot_adjust:

float, default null

Change in the design mass flow, as a fraction [–]; null for no throttle.

inlet_profile:

A non-uniform inlet, as a spanwise perturbation from the mean line.

Every field is a departure from what the design asked for, so zero is uniform and an absent section is exactly what this package did before there was one. Interpolated onto whatever span fractions the inlet patch has, so a profile does not have to know the mesh.

Non-dimensionalised by inlet quantities that vanish with the flow rather than by the absolute level, for the reason OperatingPoint.DP_adjust is a pressure change and not a ratio: at low speed \(p_0\) and \(p\) converge, so a fraction of \(p_0\) is not a fraction of anything physical, while \(p_0 - p\) stays meaningful at every Mach number. A boundary layer therefore reads as DPo running from 0 in the free stream to -1 at the wall — the fraction of dynamic head lost, which is a number that carries between machines.

The two scales are the same scale in disguise, since \((p_0-p)/p \simeq \gamma \mathit{Ma}^2/2\) and \((T_0-T)/T = (\gamma-1)\mathit{Ma}^2/2\). So equal perturbations in DPo and DTo are isentropic, which makes each physical case a clean statement:

a clean velocity distortion

DPo and DTo equal

a boundary layer or wake

DPo alone

a hot streak

DTo alone

Scaling DTo by the machine’s temperature rise instead — the closer analogue of DP_adjust — was considered and rejected: it breaks that property, needs to know the machine’s duty, and divides by zero for a cascade.

Spanwise only. ember refuses a pitchwise-varying prescription at an inlet patch rather than averaging it, so there is nothing here to express one with.

Two members, differing only in how a column is written down. Sampled is values at span fractions, which is what a person writes from rig data. Legendre is the coefficients of a series, which is what anything producing a profile analytically should write — storing such a profile as samples and interpolating it back is pure loss, and measurably so: a degree-3 profile kept at 21 span points comes back with a maximum error of 2.7e-3, a quarter of the tolerance turbigen.iterate.Repeat converges to, and at 11 points the error exceeds the tolerance outright.

Takes one of legendre, sampled as its type:.

type: legendre

A profile given as the coefficients of a Legendre series over the span.

Evaluated at whatever span fractions the inlet patch has, so nothing is resampled and the mesh’s own resolution is what the profile is applied at. That is the point of the member: anything producing a profile analytically — turbigen.iterate.Repeat above all — would otherwise have to write it out as samples and lose accuracy doing so.

Shifted to the span, so mode n is \(P_n(2\,\mathit{spf} - 1)\). Orthogonal, so the coefficients are independent: truncating drops a mode rather than redistributing the others, which is what makes a low order a statement rather than a fit artefact.

There is no constant term. The lists start at mode 1, so a profile cannot carry a level. A level is the mean line’s business, and one here would fight the design it is supposed to perturb — the whole point of the node being that it redistributes and nothing else.

There is no order field either: the order is the length of the lists, so nothing can contradict them.

Key

Value

Description

DPo:

list of floats, default []

Coefficients of modes 1 upwards, in fractions of inlet dynamic head.

DTo:

list of floats, default []

Coefficients of modes 1 upwards, in fractions of dynamic temperature.

DAlpha:

list of floats, default []

Coefficients of modes 1 upwards, in degrees.

DBeta:

list of floats, default []

Coefficients of modes 1 upwards, in degrees.

type: sampled

A profile given as values at span fractions.

What a person writes from rig data or a measured traverse. Interpolated linearly onto the patch, so the span fractions given are the resolution the profile has.

Key

Value

Description

spf:

list of floats

Span fractions the profile is given at, hub to casing [–].

Must run from exactly 0 to exactly 1. Interpolation clamps outside the range it is given, so a profile stated over [0.1, 0.9] would quietly hold its end values across the rest of the span instead of saying it was incomplete.

DPo:

list of floats, default []

Stagnation pressure deficit, as a fraction of inlet dynamic head [–].

DTo:

list of floats, default []

Stagnation temperature excess, as a fraction of inlet dynamic temperature [–].

DAlpha:

list of floats, default []

Yaw angle added to the design value [deg].

DBeta:

list of floats, default []

Pitch angle added to the design value [deg].

iterate:

Closing the loop between a design and the CFD that tests it.

A mapping rather than the bare list of iterators it used to be, because the loop has a setting of its own — how many passes to allow — and a list has nowhere to put one. It lived at the top of the file instead, where it read as a property of the case rather than of the iteration, and where it was the one top-level key belonging to no stage of the design.

The other two commands with settings of their own, chic: and batch:, are mappings for the same reason; this makes the three alike.

Key

Value

Description

correct:

list of mappings, default []; each one of Re_surf, deviation, incidence, mean_line, repeat

The mismatches to correct, one iterator each.

max_iter:

integer, default 10

Most design iterations before giving up.

A budget, not a target: a design that converges stops without reaching it. Here rather than beside the design it bounds, because it says how hard to try rather than what to build — and an archived case still records what it was run under, which is why it is a key at all rather than a flag.

correct:

Base for design iterators.

A member declares the knobs it owns, measures the error those knobs should null, and leaves every decision about how far to move to step().

Takes one of Re_surf, deviation, incidence, mean_line, repeat as its type:.

type: Re_surf

Set the viscosity to reach a surface Reynolds number.

A Reynolds number is what a cascade is actually specified at — it is the number a designer carries between machines, where a viscosity in kg/m/s is not. But it cannot simply be inverted for mu:: it is measured against a blade surface length and a mean-line reference state, so it needs a whole design, which needs a viscosity to exist first.

That circularity is what makes this an iterator rather than a formula, and the reason it is this kind of iterator is that closing it costs no CFD. Everything it reads — turbigen.machine.Machine.Re_surf() — comes off the design, so resolve() converges it in pure numpy inside every pass, and the solution iterators never see it.

The package this replaces meant to do this arithmetically and never finished: turbigen.config.set_mu_from_Re_surf raises NotImplementedError on its first line and is called whenever a config names Re_surf, so every configuration that asks for one has been dead. There is accordingly nothing to stay bug-compatible with.

Key

Value

Description

gain:

float, default -1.0

Exactly the Newton step, rather than an approximation to one.

At fixed geometry Re_surf is exactly proportional to 1/mu, so in the logarithmic knob below the residual is linear with unit slope, and the stepper’s u -= gain * e at gain = -1 lands on the answer in one move. Negative because the Reynolds number falls as the viscosity rises, which is the sign convention Iterator.gain documents.

clip:

float, default 0.0

Largest change in one iteration, in the units of the unknown.

Zero for no limit. A clip is what keeps a bad early step — taken on a field that has not settled — from throwing the design somewhere it cannot be meshed.

tolerance:

float, default 0.01

Converged inside this fractional error on the Reynolds number.

In log units, so it reads directly as a relative error to within a percent of itself.

target:

float

Surface Reynolds number to design for [–].

i_row:

integer, default 0

Index of the blade row whose Reynolds number meets the target.

There is one viscosity and one Reynolds number per row, so only one row can be placed exactly and the rest follow from the design. The first row by default, which is what the abandoned implementation indexed.

type: deviation

Match the exit flow angle to the design by moving the trailing edge.

Flow leaves a blade less turned than the metal. Recambering the trailing edge by the shortfall is the classical fix, and one iteration of CFD measures the shortfall exactly rather than correlating it.

Key

Value

Description

gain:

float, default 1.0

How much of the error to subtract from the unknown.

Carries the sign of the local sensitivity as well as its size: the step is always u -= gain * e, so an iterator whose error falls as its knob rises declares a negative gain. Reciprocal of an assumed slope, so it is the crudest possible Newton step.

clip:

float, default 2.0

Largest change in one iteration, in the units of the unknown.

Zero for no limit. A clip is what keeps a bad early step — taken on a field that has not settled — from throwing the design somewhere it cannot be meshed.

tolerance:

float, default 1.0

Permissible error on exit flow angle [deg].

type: incidence

Set the leading edge to meet the flow at a chosen incidence.

Measured on the three-dimensional field at one span fraction rather than from the mixed-out mean line, because incidence is a local property of the leading edge and the whole point of moving it is that the mean line does not see what the tip and the hub are doing.

Key

Value

Description

gain:

float, default -0.1

How much of the error to subtract from the unknown.

Carries the sign of the local sensitivity as well as its size: the step is always u -= gain * e, so an iterator whose error falls as its knob rises declares a negative gain. Reciprocal of an assumed slope, so it is the crudest possible Newton step.

clip:

float, default 2.0

Largest change in one iteration, in the units of the unknown.

Zero for no limit. A clip is what keeps a bad early step — taken on a field that has not settled — from throwing the design somewhere it cannot be meshed.

tolerance:

float, default 1.0

Permissible error on local incidence [deg].

target:

float, default 0.0

Incidence to aim for [deg].

spf:

float, default 0.5

Span fraction to measure the incidence at.

upstream:

float, default 0.05

Where to read the flow angle, as a fraction of the gap ahead of the row.

type: mean_line

Relax nominal design variables towards what the CFD achieved.

Loss, blockage and the like are guesses when a mean line is drawn, and the solution measures them. Moving the design onto its own answer is what makes the mean line describe the machine that was built rather than the one that was assumed.

Key

Value

Description

gain:

float, default 0.5

How much of the error to subtract from the unknown.

Carries the sign of the local sensitivity as well as its size: the step is always u -= gain * e, so an iterator whose error falls as its knob rises declares a negative gain. Reciprocal of an assumed slope, so it is the crudest possible Newton step.

clip:

float, default 0.0

Largest change in one iteration, in the units of the unknown.

Zero for no limit. A clip is what keeps a bad early step — taken on a field that has not settled — from throwing the design somewhere it cannot be meshed.

tolerance:

float, default 0.01

Permissible error, as a fraction of the nominal value.

variables:

list of text, default []

Names of the design variables to relax, as the mean-line design spells them.

type: repeat

Pass the exit profile back to the inlet, until the stage feeds itself.

A repeating stage — the middle of a multistage machine — is fed by its own exit. So the inlet profile is not something to state but something to find, and finding it is a fixed point.

The copy is the existing step rule. With the error taken as inlet - outlet, step()’s own u -= gain * e at gain = 1 gives exactly u_new = outlet, so this needs no loop and no stepper of its own; gain below one is the relaxation the package this replaces called relaxation_factor.

What is passed upstream is Legendre coefficients rather than a sampled profile. A sampled one is three columns over as many span stations as the mesh has, which would make a dense Broyden Jacobian of that size squared and archive a mesh artefact into every output.yaml; the coefficients of a low-order fit are few, independent, smooth over mesh noise, and a resolution somebody chose.

Low order is a claim about the physics. A Legendre fit to an endwall boundary layer is pointwise poor and integrally good: order 4 recovers only a third of the wall deficit but gets the blockage to within 4 per cent, and the blockage stops improving past order 8 while the pointwise error keeps falling. That is the right trade only if what propagates round a repeating loop is the integrated deficit rather than the wall value — which it should be, the near-wall flow being re-established by the no-slip wall just downstream of the inlet plane. If that turns out to be wrong the answer is a wall-clustered fitting coordinate, not a higher order.

DBeta is not carried: pitch angle at a repeating station is essentially zero, and a fourth column would be noise.

Key

Value

Description

gain:

float, default 1.0

One copies the exit profile outright; less under-relaxes it.

clip:

float, default 0.0

Largest change in one iteration, in the units of the unknown.

Zero for no limit. A clip is what keeps a bad early step — taken on a field that has not settled — from throwing the design somewhere it cannot be meshed.

tolerance:

float, default 1.0

Error below which this iterator is converged, in the units of the error.

order:

integer, default 3

Highest Legendre mode passed upstream, the modes starting at 1.

offset:

float, default 0.5

Where to read the exit profile, in blade chords past the trailing edge.

Far enough that the blade wakes have begun to mix but the plane is still in the machine. The package this replaces reads at the same distance.

atol_head:

float, default 0.01

Converged when DPo and DTo are within this [–].

In fractions of dynamic head and of dynamic temperature, which is what those columns are measured in.

atol_angle:

float, default 0.1

Converged when DAlpha is within this [deg].

clip_head:

float, default 0.2

Most DPo and DTo may move in one iteration [–].

clip_angle:

float, default 5.0

Most DAlpha may move in one iteration [deg].

database:

Finished runs to start an iteration from.

Key

Value

Description

path:

text, default ''

Glob matching the case files to read, relative to the config file.

Recursive patterns are the point: ../runs/**/output.yaml. Matching the per-iteration subdirectories of an earlier iterate as well as its final answer is harmless, because what makes a match a sample is read from its result: rather than from where it sits.

output.yaml is written by any command with something to record, report included, so matching one is not by itself evidence that a run happened there. What makes a match a sample is its result:, and a report that reached no answer writes the config alone — which _sample() skips, on the same line that skips a march which blew up.

power:

float, default 2.0

Exponent on inverse distance. Higher weights the nearest sample more.

variables:

list of text, default []

Design variables to use, as node.flatten spells them.

Empty, and normally left so: the point of this module is that they are deduced. An escape hatch for a database whose runs happen to differ in something that is not a design variable.

chic:

How to march a characteristic, and how finely to pin its limit.

Key

Value

Description

step:

float, default 0.05

Increment in DP_adjust between points [–].

Positive is always towards the limit — more throttled for a compressor, more expanded for a turbine — because DP_adjust already carries that meaning through the sign of the design’s own pressure change. There is no direction to configure, and no machine type named anywhere.

step_min:

float, default 0.01

Refine until the bracket around the limit is narrower than this [–].

The resolution of the answer, in the units the answer is given in. Reaching it takes about log2(step / step_min) extra points beyond the march.

max_points:

integer, default 20

Most points to run before giving up.

A machine that never destabilises would otherwise march until the exit pressure went negative, which bconds.exit_pressure refuses — an error about a pressure, several minutes in, rather than a budget stated here.

batch:

A set of related runs, and how to choose them.

Key

Value

Description

bounds:

mapping of your own keys, default {}

Range of each design variable, keyed by path: {path: [lo, hi]}.

Points are drawn from the box quasi-randomly, in an order whose every prefix fills it, so a batch can be extended without being regenerated.

Paths are spelled as flatten() writes them, the same as database.variables, so a design variable is named identically wherever it appears.

A mapping rather than a list of triples because this is the one section a user writes by hand and mean_line.psi: [1.2, 2.0] is the shortest honest spelling of it. The cost is that a Config holding one is no longer hashable, dict not being; nothing hashes a config, and equality and round-tripping — which plenty relies on — are unaffected.

values:

mapping of your own keys, default {}

Values of each design variable to run at: {path: [v0, v1, ...]}.

The members are the full factorial over these lists: every combination, once. A mapping says that each variable takes each of its values, and the product is the only reading of that which does not silently require the lists to be the same length.

Named rather than drawn, so the batch is the same every time it is written and no seed enters into it. This is the parameter study — three values of one variable, and a trend to plot — as against bounds:, which fills a space to be interpolated in later.

seed:

integer, default 0

Seed for the scrambled sequence. The space, so it lives in the file.

Read only when bounds: is what varies: a grid of named values is already the same every time.

post_process:

Base for post-processors.

Takes one of annulus, contour, convergence, sections, surface, triangle as its type:.

type: annulus

Meridional view of the annulus.

Key

Value

Description

m_cut:

list of floats, default []

Normalised meridional positions at which to draw a cut plane.

show_axis:

true or false, default false

Draw the axis of rotation.

show_blades:

true or false, default true

Outline each blade row with its leading and trailing edges and diagonals.

type: contour

Contours of a flow variable on a constant-span surface.

Key

Value

Description

spf:

list of floats, default [0.5]

Span fractions to cut at.

variable:

text, default 'Ma_rel'

Block property to contour, e.g. Ma_rel, P, s.

n_passage:

integer, default 2

Passages to draw, repeated pitchwise.

n_level:

integer, default 21

Upper bound on the number of filled bands. The band edges are rounded to a sensible step, so the actual count follows from that step and the range.

clip_percentile:

float, default 1.0

Percentile trimmed from each end of the field before the level range is rounded. A stagnation cell or a corner artefact should colour one pixel, not rescale the whole plot; 0 disables the trim.

cmap:

text, default 'viridis'

Colour map to fill with.

margin:

float, default 1.0

How far to look either side of a row, as a fraction of its meridional length (leading to trailing edge) – so the default frames roughly one chord of approach and wake either side. Raise it for a highly staggered row, whose true chord runs well past its meridional extent.

type: convergence

Residuals and integral errors over the course of a march.

This mapping takes no keys.

type: sections

Blade-to-blade sections of each row.

Key

Value

Description

spf:

list of floats, default []

Span fractions to draw. Empty for the designed sections.

type: surface

Isentropic Mach number around the blade surfaces.

Key

Value

Description

spf:

list of floats, default []

Span fractions to plot at. Empty for the designed sections.

offset:

integer, default 0

Cells away from the wall to take the distribution at.

type: triangle

Mean-line velocity triangles at inlet and exit of each row.

Drawn from the mean line alone, so this is the one flow plot that has something to show at every pipeline depth – a design that never meshed still has its triangles.

The triangles are to scale against each other but carry no annulus or blade geometry: meridional velocity runs along x, swirl along y, and the stations are spread along x by a fixed pitch so neighbours do not overlap. The absolute velocity is C0 and the relative velocity C1; blade speed closes the two, tip to tip, and is only drawn where the row rotates.

This mapping takes no keys.

job:

Base for queue systems.

Takes one of slurm, tsp as its type:.

type: slurm

Submit to SLURM as a single job array.

Zero or empty means unstated, and an unstated setting is left out of the script entirely, so sbatch’s own SBATCH_ACCOUNT, SBATCH_PARTITION and friends still apply. A cluster that already sets those in your profile therefore needs nothing here but type: slurm.

One array rather than one submission per config, and the array indexes lines of a file rather than directory names. The package this replaces indexes numbered directories and so refuses anything but a consecutive range — which the batches turbigen batch writes are not, since a point that will not design is skipped and never retried.

Key

Value

Description

command:

text, default ''

The turbigen executable a submitted job should run. Empty means the one running now, which is right whenever the queue shares this filesystem and this environment; name it when a compute node needs a different path.

hours:

float, default 0.0

Wall-clock time limit [hr].

account:

text, default ''

Account to charge the compute time to.

partition:

text, default ''

Partition to run in.

qos:

text, default ''

Quality of service level.

gres:

text, default ''

Generic consumable resources, as in gpu:1.

nodes:

integer, default 0

Nodes per job.

tasks:

integer, default 0

Tasks per job.

cpus:

integer, default 0

CPUs per task.

mail_type:

text, default ''

When to send mail, as in FAIL.

max_concurrent:

integer, default 0

Most array members to run at once.

type: tsp

Queue locally through task-spooler.

A real queue — slots, job ids, listing, cancellation — for the price of a small Debian package, in place of the flock’d text file, PID file, SIGHUP cancel-all and systemd unit that the package this replaces hand-rolls to the same end. Watch it with tsp -l, read a job with tsp -c ID, stop the rest with tsp -C.

Key

Value

Description

command:

text, default ''

The turbigen executable a submitted job should run. Empty means the one running now, which is right whenever the queue shares this filesystem and this environment; name it when a compute node needs a different path.

slots:

integer, default 4

Jobs to run at once. Set on the queue itself, so it outlives this submission and applies to whatever is already waiting.

cpus:

integer, default 0

Slots one job occupies, for work that wants more than one core. Zero leaves it at task-spooler’s own default of one.