Release notes¶
What each release from v0.8.1 to v0.17.0 changed for someone who already had a workspace: what moved, what broke, and the one command that carries a file across. These notes stood on the home page until 0.24.0 and are kept here unchanged, newest first.
This page is not the changelog. The complete record of every release,
including the ones after v0.17.0, is
CHANGELOG.md
in the repository. The releases that ask you to change a file you already have
each have a page of their own under Migrating to newer versions:
0.23.0, 0.22.0 and
0.21.0.
v0.17.0¶
v0.17.0 is the release that makes a sweep ONE RUN. A steady matrix row
is one job: every point of it runs in one script and one solver process, and
the solver is never cleared between them, so each angle begins from the
previous one's converged solution and the sweep costs one setup instead of one
per point. That is the warm start, and it is what a polar sweep IS rather than
a switch on top of it; a row that wants the other behaviour writes
COLD_START: True. One job leaves ONE record, naming every point it ran IN
THE ORDER IT RAN THEM, because a warm sweep's order is part of its result.
The run matrix carries nineteen columns. CONFIGURATION, GEOMETRY,
SYMMETRY, SYMMETRY_LOADS, NCPUS and WALLTIME become columns of their
own, and HIDDEN | RUN moves to sit directly after POL. Each of the six was
expressible before, four inside the free variables cell and two inside the
setup artifact, so the release moves WHERE a fact lives and makes no fact
required: a row that states none of them reads exactly as it did. A file in
any older layout is upgraded on read, and the upgrade RENAMES NO RUN, because
the point tag is run identity and ends every run id in every existing
manifest. A column says nothing with -, and where one of the six says
nothing the older home still answers.
A run needs a plan, pinned to the matrix it read. pyfs-matrix plan
spends no solver time, pre-flights every point, and writes the receipt run
now refuses to start without; the receipt carries the matrix digest, so a
matrix edited between planning and running is visible rather than silent.
A product is archived before it is rewritten, never lost. A rebuild moves
the old product into archive/<day and hour>/ beside it and writes the new one
in its place. --overwrite is gone: --force-overwrite keeps no copy and asks
for a confirmation, so it cannot be reached by habit.
An unsteady row can state a wall clock. WALLTIME arms a pair of
solver-side actions: a program that keeps its own clock and fires once, and a
script it rewrites that does nothing until the clock and the margin meet, and
then writes the run's exports. The margin is the setup's, twenty minutes by
default. A run the clock stopped is recorded WALLTIME_REACHED, which is NOT
a failure: the numbers up to that step are real and the record says where it
stopped. What is NOT measured, and is said here rather than only in a source
comment: whether the stop verb inside an action's script ends the RUN or only
that script. Settling it needs a licensed probe that moves one thing.
Linux is the cluster, and no cell says so. On Linux with a profile in
inputs/hpc/h<>.toml the run path renders that cluster's descriptor, hands the
job to the scheduler and returns without waiting, and the record is
SUBMITTED. The setup artifact stays multiplatform, so the same matrix,
unchanged in every cell, runs locally on Windows and submits on Linux, and
NCPUS is one number for both. v0.17.0 had no collect stage, so a submitted
job's outputs were collected by hand; 0.18.0 added pyfs-matrix collect.
v0.16.0¶
v0.16.0 was the sweep release. A surface-section distribution is created
AFTER the solver is initialised; created before, the distribution returns the
declared number of sections and every one of them is empty. A steady row now
CREATES the probe points it exports, instead of asking the solver to export
something nobody made; a probe entry prescribes a rectangular
or a circular plane, point by point, or cites a points file the user wrote; and
[probes] became [[probes]], a list of tables, so one artifact can probe
several frames.
What a campaign WRITES moved with it. A simulation's collected outputs live
under sims/<sim>/datapoints/DP-<point>/, the per-polar tables under
post/<matrix>/polars/, and the flow-field samples under
post/<matrix>/probes/ whatever the run type was. Each polar and group also
gets one derived file, SUPER-...csv, whose columns are a superset of
everything the workspace knows about that simulation: if you have to open a
second file to know something about it, that file failed.
Two new answers a study wants before it is run and after. pyfs-matrix plan
--cost tables what each POINT will cost: mesh size, trailing edges marked,
farfield layers, viscous coupling, run type, time steps, processors, an
expected time, and the number of recorded runs that estimate was fitted
from. The table says under every printing that the time is an extrapolation
from this workspace's own recorded wall times and not a measurement, and a
point with no comparable recorded run gets no number at all. And a probe
table now says WHERE each sample is, with the frame it is measured in,
which an unsteady export never stated at all.
A swept row now runs and is judged end to end. Each point collects its
outputs into its own folder, sims/<sim>/datapoints/DP-<point>/, named by the
same point tag that ends the run id and names the generated script. Until this
release every point of a row wrote into one shared folder, so from the second
point onward the standard assessor found two files that both read as loads
tables and refused rather than guess between them. Name your outputs per
point, as before: two points of one row still may not share a file name,
because the per-point products are named after it and would collide there
even though the folders no longer do. A workspace recorded under the older
layout is read exactly as before.
What changes for you at v0.16.0. This is the most breaking release of
the set, and the break is first: [probes] IS NOW [[probes]], a list of
tables, and the old spelling is REFUSED BY NAME, so every 0.15.0 artifact
that declares probe lines must be edited. That is a recorded decision rather
than an accident. Beside it: the five names the 0.14.0 polar rename
deprecated are gone; a simulation's collected outputs are under
sims/<sim>/datapoints/DP-<point>/, one folder per point, and a workspace
holding either older folder is still read;
the per-polar tables moved to post/<matrix>/polars/ and are named by the
point convention with the swept variable written literally as sweep; and
sweep.csv is gone in favour of campaign_sweep.csv, which it duplicated
byte for byte.
v0.15.0¶
What changes for you at v0.15.0. The run matrix LOSES A COLUMN:
SWEEP_TYPE is gone, because a sweep is applied to a variable that DEFINES
the flight condition and the FLIGHT_CONDITION cell says which by carrying
the word sweep where that key's value would be. Run pyfs-matrix upgrade
<path> --in-place, which folds the cell and DOES NOT RENAME A RUN: a held
angle is carried at every point, so the point tags that end every run_id
in your manifests are the ones the converted file plans under, and a resume
after the upgrade finds its records. The one row it refuses to convert is
one that sweeps BOTH angles, which is one row per sideslip and each needs a
POL of its own. CLOCK_MOTION is now REQUIRED on a row that states a
MOTIONS list, naming the rotor that owns the time step; the flat
pre-0.15.0 form is exempt. The airframe and blades family SELECTORS are
REFUSED since 0.15.0, not warned about: declare the set in your reference's
[aliases] table and cite it by name, because those two decided what a
blade IS from a pattern over the family name and a mesh spelled another way
was guessed wrong in silence. An alias of the same name is read FIRST and
keeps its own meaning, so a reference that already declares airframe is
untouched. New: --ignore-missing-families false on plan and run turns
a family the opened mesh does not carry from a skip into a refusal, for a
run against the one geometry you believe carries everything.
v0.13.0 and v0.14.0¶
One refusal below no longer stands: since 0.23.0 a [groups] table keyed by a
word is accepted, and the product file carries the word. See
what the post-processing artifact holds.
What changes for you, and what you must do. v0.13.0 changes no
column of the run-matrix file. Two inputs that used to plan are refused at
plan time now, each naming the cell: a row carrying a key its run type does
not register (a misspelt key planned READY and reached the solver as
nothing), and a pproc artifact whose [groups] table is keyed by a word or
whose groups cite a boundary name the opened geometry does not carry.
Python 3.11 leaves the supported window: the floor follows SPEC 0, the
scientific-python schedule, computed on 2026-09-09 as Python 3.12, numpy
2.2 and pandas 2.3, and the window now moves by a published rule rather
than by choice. The hand-built physics runner is gone: run_physics,
run_drift and the four build_phy*_script builders are removed, and
pyfs-qa physics --workspace <root> and pyfs-qa drift --workspace <root>
read the physics cases as rows of a campaign workspace; an import of a
removed name says so and names the replacement. Anything you wrote against
runs.json or the campaign products meets three moves: the manifest key
broken_commands is waived_commands and the schema stamp is
pyfs-manifest/3 (the old key is still read; its removal is promised for
0.18.0 and has moved three times, each move on a re-count of the recorded
manifests that still carry it); plan.json,
campaign_sweep.csv and the product tables live under
post/<matrix stem>/, one folder per matrix; and a registered post stage is
called with a third keyword, matrix_stem. sweep_editions is
manual_editions and propose_type takes its two strings by keyword; the
old spellings warn and name the release that removes them. A simulation
folder has three managed subfolders, since parsed/ was never written to;
an empty one left by an earlier release is left alone. At v0.14.0 one
artifact key is renamed: [products] her_polar_format is
custom_polar_format, and the four Python names HerPolarTable,
her_polar_file_name, write_her_polar_format and
read_her_polar_format are spelled custom; the old spellings were read
and warned until 0.16.0, WHICH REMOVES THEM. The format itself is untouched:
only the spelling that named a person was ever deprecated.
What it adds. An unsteady row may say when its exports begin,
EXPORT_UNSTEADY_AFTER_REV or EXPORT_UNSTEADY_AFTER_ITER, and the run
registers the two solver actions that make the solver export from that
step on, measured on 26.123. The products stage writes a PROV-JSON
provenance document per point, every reduction of an unsteady row (the
time average over the window the row states, the phase-locked passages,
the per-blade split), and the polar tables in the custom polar format
when the pproc artifact asks for it. The geometry library may hold one
folder per geometry beside the flat layout, pyfs-workspace
migrate-geometries moves a library into it, and pyfs-workspace archive
<root> <sim_id> zips one recorded simulation. Every command-line option
states what it reads, the run record says how the solver was called
(executor, export_window, the waived commands by their name), and the
whole test suite is organized by tier, with the licensed tier a campaign
workspace of eleven run matrices whose goldens are rendered offline on every
commit.
v0.12.0¶
v0.12.0 changed no column of the run-matrix file and no cell already in
one. It added two ways to say what you were already saying. A setup
artifact may carry a
[flight_condition] table holding the fluid pins (RHOkgm3, MUPas,
ASMPS, TK, PPA), so a thirteen-point polar states its campaign's
constants once instead of thirteen times; a row that states a pin still
overrides the setup's, and the resolved state is the same state either way,
which a test holds to the rendered script BYTE FOR BYTE. And an unsteady run
that meshes nothing turning may state its clock as DELTA_THETA and
REVOLUTIONS, resolved against the rotor speed whose azimuth the step
measures, where before only the seconds and the step count were accepted.
The reproduction workspace of the reference campaign needs both,
which is why that release existed.
Two derived numbers moved with it, and a row already written felt
them. A rotor speed derived from ADVANCE_RATIO is emitted at four
decimals, the reference precision: 473.1723 rev/min where the unrounded
derivation gives 473.17227304. And the default loads assessor judged a
point's OWN declared outputs, so a two-point sweep whose points name their
own tables is judged where it used to be refused as ambiguous. Re-baseline
against v0.12.0 rather than comparing its tables with v0.11.0's.
v0.11.0¶
v0.11.0 changed the run-matrix FILE FORMAT, and one command moved a
workspace. The ENTRY column is now PPROC and names the post-processing
artifact, the FS_SCRIPT column is gone and a LEGACY row carries its recipe
code in its cell, and the GEOMETRY cell names the file with its extension.
Run pyfs-matrix upgrade matriz.fs --in-place --inputs inputs once in the
workspace: it rewrites the matrix, moves the groups library to inputs/pproc/
and strips the four rotor facts from the reference artifact. What you get is
the study stated once, in the workspace: the campaign is named after its
directory, the post-processing artifact says which exports, sections, plots,
probes and products every point leaves, the products are CSV tables the run
writes itself (pyfs-matrix post rewrites them with no solver), the boundary
order of a geometry is read from the file (pyfs-matrix inventory), a row may
state several rotors, and every point opens its geometry through a link
rather than a copy. The reproduction of the reference campaign, script
by script and product by product, is the exit condition of GOAL-011 and is
what that release was built against.
v0.10.1¶
v0.10.1 changed no column of the run-matrix file and no cell you had
already written. What it changed is what one cell MEANS. A rotor row's
MOVING_BOUNDARIES used to cite boundaries by their POSITION in one
geometry's order; those positions were right for the file they were
written against and named different surfaces in any file that ordered
them differently, and nothing said so. Write the names now, or the
FAMILY they belong to, and the package reads the geometry and resolves
them. Positions still work and now warn, naming what they actually
selected.
It also carries a third run type, unsteady, an unsteady run with
nothing turning, which is a new capability under a patch number, by
an explicit exception. It is named here because a patch number
will not carry that news on its own, and it asks nothing of you: no
existing row changes. See the workspace and workflows page.
v0.10.0¶
v0.10.0 changes no column of the run-matrix file. Two things still
want a look. Your solver preset now REACHES THE SCRIPT: twelve settings
and eleven of the solver's own spellings that used to be dropped are now
emitted, silently and with no warning, so a campaign whose preset states
anything non-default will move its numbers and wants re-baselining. And
five names became the package's inside VAR_NAMES_VALUES:
ADVANCE_RATIO, RPM_SIGN, DELTA_THETA, REVOLUTIONS and
LOG_OUTPUT, matched on the exact key, with a row spelling
ADVANCE_RATIO beside an existing RPM refused for stating the rotor
speed twice. (RPM_SIGN beside RPM was refused for the same reason
until v0.21.1; since v0.22.0 a row's speed is a magnitude and the hand of
the rotation is rpm_sign on the rotor's block in the reference.)
v0.9.0¶
v0.9.0 breaks the run-matrix file format, and it is the one
upgrade action that cannot be skipped: the RE and MACH columns are
replaced by one mandatory FLIGHT_CONDITION cell. An older file is
recognised and refused rather than misread, and
pyfs-matrix upgrade your_matrix.fs --in-place converts it. The
conversion is lossless as a file and not neutral as a result,
because a Reynolds number stops being recorded metadata and becomes a
constraint that solves for density: an upgraded row emits a fluid state
it never emitted before and its numbers move. Flight
conditions is the whole grammar and the
migration.
v0.8.1 and earlier¶
v0.8.1 before it was a patch: a run
matrix can name its geometry, so a workflow no longer builds a script
that opens nothing and solves whatever the solver already had in memory,
and a row can declare the symmetry a periodic sector needs. It reserves
three names inside the matrix's free cell, GEOMETRY, SYMMETRY and
PERIODIC_COPIES, which was its own upgrade action. Earlier releases,
and what each of them registered or broke, are in the changelog rather
than re-threaded here.