pyflightstream 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. pyflightstream-0.3.0/PKG-INFO +191 -0
  2. pyflightstream-0.3.0/README.md +146 -0
  3. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/pyproject.toml +27 -2
  4. pyflightstream-0.3.0/src/pyflightstream/__init__.py +79 -0
  5. pyflightstream-0.3.0/src/pyflightstream/_deprecations.py +121 -0
  6. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/cases/__init__.py +3 -3
  7. pyflightstream-0.3.0/src/pyflightstream/cases/cli.py +165 -0
  8. pyflightstream-0.3.0/src/pyflightstream/cases/matrix.py +747 -0
  9. pyflightstream-0.3.0/src/pyflightstream/cases/matrix_legacy.py +40 -0
  10. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/__init__.py +43 -0
  11. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/advanced_settings.yaml +4 -0
  12. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/boundary_conditions.yaml +153 -153
  13. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/motion_definitions.yaml +1 -1
  14. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/solver_analysis.yaml +3 -2
  15. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/solver_settings.yaml +8 -2
  16. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/streamlines.yaml +1 -1
  17. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/surface_sections.yaml +4 -4
  18. pyflightstream-0.3.0/src/pyflightstream/exceptions.py +91 -0
  19. pyflightstream-0.3.0/src/pyflightstream/files/__init__.py +31 -0
  20. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/__init__.py +57 -57
  21. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/driver.py +4 -9
  22. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/state.py +194 -181
  23. pyflightstream-0.3.0/src/pyflightstream/options.py +334 -0
  24. pyflightstream-0.3.0/src/pyflightstream/overview.py +292 -0
  25. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/probes/geometry.py +3 -1
  26. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/cli.py +405 -364
  27. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/physics.py +43 -3
  28. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/reference.py +319 -9
  29. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/results/__init__.py +36 -0
  30. pyflightstream-0.3.0/src/pyflightstream/results/tables.py +574 -0
  31. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/run/__init__.py +347 -15
  32. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/script/__init__.py +167 -67
  33. pyflightstream-0.3.0/src/pyflightstream/script/entities.py +444 -0
  34. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/script/helpers.py +469 -51
  35. pyflightstream-0.3.0/src/pyflightstream/script/solver_setup.py +441 -0
  36. pyflightstream-0.3.0/src/pyflightstream/testing.py +176 -0
  37. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/versions.py +28 -2
  38. {pyflightstream-0.2.0/src/pyflightstream/files → pyflightstream-0.3.0/src/pyflightstream/workspace}/__init__.py +189 -11
  39. pyflightstream-0.3.0/src/pyflightstream/workspace/cli.py +60 -0
  40. pyflightstream-0.3.0/src/pyflightstream/workspace/inputs.py +532 -0
  41. pyflightstream-0.3.0/src/pyflightstream/workspace/naming.py +265 -0
  42. pyflightstream-0.3.0/src/pyflightstream.egg-info/PKG-INFO +191 -0
  43. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream.egg-info/SOURCES.txt +33 -3
  44. pyflightstream-0.3.0/src/pyflightstream.egg-info/entry_points.txt +5 -0
  45. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream.egg-info/requires.txt +2 -1
  46. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_command_db.py +32 -0
  47. pyflightstream-0.3.0/tests/test_conventions.py +135 -0
  48. pyflightstream-0.3.0/tests/test_deprecation_deadline.py +142 -0
  49. pyflightstream-0.3.0/tests/test_error_messages.py +169 -0
  50. pyflightstream-0.3.0/tests/test_examples_isolation.py +61 -0
  51. pyflightstream-0.3.0/tests/test_exceptions_catalog.py +105 -0
  52. pyflightstream-0.3.0/tests/test_matrix.py +224 -0
  53. pyflightstream-0.3.0/tests/test_matrix_cli.py +154 -0
  54. pyflightstream-0.3.0/tests/test_matrix_run.py +337 -0
  55. pyflightstream-0.3.0/tests/test_metadata_currency.py +77 -0
  56. pyflightstream-0.3.0/tests/test_options.py +174 -0
  57. pyflightstream-0.3.0/tests/test_overview.py +110 -0
  58. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_package_imports.py +2 -2
  59. pyflightstream-0.3.0/tests/test_public_api.py +173 -0
  60. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_qa_physics.py +39 -1
  61. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_reference.py +51 -0
  62. pyflightstream-0.3.0/tests/test_registry_hygiene.py +63 -0
  63. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_run_campaign.py +189 -2
  64. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_script.py +1 -1
  65. pyflightstream-0.3.0/tests/test_script_entities.py +220 -0
  66. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_script_helpers.py +10 -4
  67. pyflightstream-0.3.0/tests/test_solver_setup.py +329 -0
  68. pyflightstream-0.3.0/tests/test_tables.py +292 -0
  69. pyflightstream-0.3.0/tests/test_testing.py +92 -0
  70. pyflightstream-0.3.0/tests/test_workspace.py +426 -0
  71. pyflightstream-0.2.0/PKG-INFO +0 -88
  72. pyflightstream-0.2.0/README.md +0 -55
  73. pyflightstream-0.2.0/src/pyflightstream/__init__.py +0 -27
  74. pyflightstream-0.2.0/src/pyflightstream/cases/matrix_legacy.py +0 -337
  75. pyflightstream-0.2.0/src/pyflightstream.egg-info/PKG-INFO +0 -88
  76. pyflightstream-0.2.0/src/pyflightstream.egg-info/entry_points.txt +0 -3
  77. pyflightstream-0.2.0/tests/test_files.py +0 -144
  78. pyflightstream-0.2.0/tests/test_matrix_legacy.py +0 -106
  79. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/LICENSE +0 -0
  80. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/setup.cfg +0 -0
  81. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/_meta.yaml +0 -0
  82. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/actuators.yaml +0 -0
  83. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/aeroelastic_coupling.yaml +0 -0
  84. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/ccs_wing_mesh.yaml +0 -0
  85. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/coordinate_systems.yaml +0 -0
  86. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/file_io.yaml +0 -0
  87. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/mesh_import_export.yaml +0 -0
  88. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/probe_points.yaml +0 -0
  89. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/runtime_settings.yaml +0 -0
  90. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/scenes.yaml +0 -0
  91. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/script_controls.yaml +0 -0
  92. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/simulation_controls.yaml +0 -0
  93. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/solver_export.yaml +0 -0
  94. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/solver_initialization.yaml +0 -0
  95. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/sweeper.yaml +0 -0
  96. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/unsteady_solver.yaml +0 -0
  97. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/commands/volume_sections.yaml +0 -0
  98. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/farfield/__init__.py +0 -0
  99. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/beam.py +0 -0
  100. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/centrifugal.py +0 -0
  101. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/cli.py +0 -0
  102. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/config.py +0 -0
  103. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/kinematics.py +0 -0
  104. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/loads.py +0 -0
  105. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/fsi/nodes.py +0 -0
  106. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/post/__init__.py +0 -0
  107. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/post/writers.py +0 -0
  108. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/probes/__init__.py +0 -0
  109. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/probes/planar.py +0 -0
  110. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/__init__.py +0 -0
  111. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/compat.py +0 -0
  112. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/drift.py +0 -0
  113. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/geometry.py +0 -0
  114. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/probes.py +0 -0
  115. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/references/PHY-01.yaml +0 -0
  116. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/references/PHY-02.yaml +0 -0
  117. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/references/PHY-05.yaml +0 -0
  118. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/references/PHY-06.yaml +0 -0
  119. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/references/SMI-01.yaml +0 -0
  120. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/references/SMI-02.yaml +0 -0
  121. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream/qa/specs.py +0 -0
  122. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream.egg-info/dependency_links.txt +0 -0
  123. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/src/pyflightstream.egg-info/top_level.txt +0 -0
  124. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_cases.py +0 -0
  125. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_farfield.py +0 -0
  126. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_fsi_beam.py +0 -0
  127. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_fsi_centrifugal.py +0 -0
  128. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_fsi_cli.py +0 -0
  129. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_fsi_config.py +0 -0
  130. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_fsi_driver.py +0 -0
  131. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_fsi_kinematics.py +0 -0
  132. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_fsi_loads.py +0 -0
  133. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_fsi_sources.py +0 -0
  134. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_fsi_wing.py +0 -0
  135. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_house_style.py +0 -0
  136. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_post_writers.py +0 -0
  137. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_probes.py +0 -0
  138. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_probes_geometry.py +0 -0
  139. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_probes_planar.py +0 -0
  140. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_qa_compat.py +0 -0
  141. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_qa_drift.py +0 -0
  142. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_qa_geometry.py +0 -0
  143. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_qa_probes.py +0 -0
  144. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_results.py +0 -0
  145. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_run.py +0 -0
  146. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_run_preproc.py +0 -0
  147. {pyflightstream-0.2.0 → pyflightstream-0.3.0}/tests/test_versions.py +0 -0
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyflightstream
3
+ Version: 0.3.0
4
+ Summary: Version-aware, didactic Python driver for the FlightStream panel-method solver
5
+ Author: Geovana Neves
6
+ License: MIT
7
+ Project-URL: Repository, https://github.com/nevesgeovana/pyflightstream
8
+ Project-URL: Documentation, https://nevesgeovana.github.io/pyflightstream/
9
+ Project-URL: Changelog, https://github.com/nevesgeovana/pyflightstream/blob/main/CHANGELOG.md
10
+ Project-URL: Issues, https://github.com/nevesgeovana/pyflightstream/issues
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Physics
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: numpy
23
+ Requires-Dist: pandas
24
+ Requires-Dist: pydantic
25
+ Requires-Dist: pyyaml
26
+ Requires-Dist: xarray
27
+ Provides-Extra: plot
28
+ Requires-Dist: matplotlib; extra == "plot"
29
+ Provides-Extra: geom
30
+ Requires-Dist: trimesh; extra == "geom"
31
+ Requires-Dist: rtree; extra == "geom"
32
+ Requires-Dist: scipy; extra == "geom"
33
+ Provides-Extra: fsi
34
+ Requires-Dist: PyNiteFEA>=3.0; extra == "fsi"
35
+ Provides-Extra: dev
36
+ Requires-Dist: pytest; extra == "dev"
37
+ Requires-Dist: sybil; extra == "dev"
38
+ Requires-Dist: ruff; extra == "dev"
39
+ Requires-Dist: pre-commit; extra == "dev"
40
+ Requires-Dist: properdocs; extra == "dev"
41
+ Requires-Dist: mkdocs-material; extra == "dev"
42
+ Requires-Dist: mkdocs-gen-files; extra == "dev"
43
+ Requires-Dist: mkdocs-literate-nav; extra == "dev"
44
+ Dynamic: license-file
45
+
46
+ # pyflightstream
47
+
48
+ [![ci](https://github.com/nevesgeovana/pyflightstream/actions/workflows/ci.yml/badge.svg)](https://github.com/nevesgeovana/pyflightstream/actions/workflows/ci.yml)
49
+ [![PyPI](https://img.shields.io/pypi/v/pyflightstream)](https://pypi.org/project/pyflightstream/)
50
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21482925.svg)](https://doi.org/10.5281/zenodo.21482925)
51
+
52
+ Version-aware, didactic Python driver for the FlightStream panel-method
53
+ solver. Successor of the author's legacy research scripts. MIT licensed.
54
+
55
+ Status: v0.2.0 is public on [PyPI](https://pypi.org/project/pyflightstream/)
56
+ with the archived release on Zenodo (DOI recorded in CITATION.cff).
57
+ Development continues toward v0.3.0; CHANGELOG.md carries the release
58
+ history.
59
+
60
+ ```
61
+ pip install pyflightstream
62
+ ```
63
+
64
+ A first taste, no solver required (build time is where errors surface):
65
+
66
+ ```python
67
+ from pyflightstream.commands import CommandNotInVersionError
68
+ from pyflightstream.script import Script
69
+
70
+ script = Script(version="26.12") # the FlightStream version is explicit input
71
+ script.emit("NEW_SIMULATION")
72
+ script.emit("IMPORT", "METER", "STL", "wing.stl", clear=True)
73
+ script.emit("SOLVER_SET_AOA", 4.0)
74
+ script.emit("START_SOLVER")
75
+ print(script.render()) # validated ASCII script, ready for the solver
76
+
77
+ try:
78
+ Script(version="26.0").emit("SOLVER_SET_AOA", 4.0)
79
+ except CommandNotInVersionError as error:
80
+ print(error) # refused: no recorded evidence for that version
81
+ ```
82
+
83
+ The worked examples in `examples/` take it from here to executed
84
+ polars, campaigns, and coupled aeroelastic runs.
85
+
86
+ Optional extras: `[fsi]` (aeroelastic coupling, PyNiteFEA), `[geom]`
87
+ (probe-survey geometry gating, trimesh/rtree/scipy), `[plot]`
88
+ (matplotlib for the plotting examples).
89
+
90
+ ## Why this package
91
+
92
+ FlightStream is scripted through an ASCII command file, and the solver
93
+ is under active development: the FlightStream team is responsive to
94
+ user requests and works with intermediate hotfix builds that
95
+ consolidate into stable releases. A fast-moving solver naturally means
96
+ a scripting command set that evolves from version to version, faster
97
+ than any single document can track. This package makes the
98
+ FlightStream version an explicit input: every command it emits is
99
+ validated against a per-version command database, and old versions are
100
+ only ever added, never dropped, so campaigns stay reproducible across
101
+ that evolution.
102
+
103
+ Every database entry carries a manual page citation, and its status per
104
+ version (documented, verified, broken) can only be promoted by citing a
105
+ committed probe report from a licensed machine. Nothing is guessed; the
106
+ honest gaps are reported as such.
107
+
108
+ ## What ships
109
+
110
+ - Command database with per-version evidence and a manual citation on
111
+ every entry, browsable offline via `pyflightstream.help()` (including
112
+ a manual-coverage section) and as a generated docs site; the
113
+ compatibility matrix carries the live counts.
114
+ - Validating script builder with curated helpers: phase ordering,
115
+ didactic refusals at build time, entity labels (recipes can name
116
+ frames, actuators, motions, and boundaries instead of raw indices),
117
+ and a solver-setup provenance snapshot recording the effective value
118
+ of every solver flag per run.
119
+ - Campaign workspace: an input-artifact library (references, solver
120
+ presets, boundary groups, geometries, profiles, executables by build
121
+ id), a run manifest as the single identity authority, output naming
122
+ templates, campaign pre-flight with zero solver time, and resumable
123
+ incremental sweeps.
124
+ - Runner and parsers: headless execution, anchor-based parsers for the
125
+ solver outputs, and a pandas table layer (per-result tables, one wide
126
+ row per run, whole-sweep DataFrame straight from the manifest).
127
+ - Run-matrix support as a first-class interface: read, convert,
128
+ pre-flight, and run the pipe-delimited 15-column matrix format.
129
+ - Far-field probe surveys (planar grids, geometry gating, VTK/Tecplot
130
+ writers, conservation ledgers on xarray) and an aeroelastic coupling
131
+ subpackage (structural beam, coupled driver, replay harness).
132
+ - Architecture overview from the live module docstrings via
133
+ `pyflightstream.overview()`.
134
+ - Predictable surfaces: a declared-options registry
135
+ (`pyflightstream.options`), one public exception catalog
136
+ (`pyflightstream.exceptions`), test assertions with quantified
137
+ reports (`pyflightstream.testing`), and the house conventions
138
+ rendered by `help()`.
139
+
140
+ ## Command-line tools
141
+
142
+ | Tool | Purpose |
143
+ |---|---|
144
+ | `pyfs-qa` | Tier 2 command-validity probes, Tier 3 physics regression and cross-version drift, status promotion from committed reports |
145
+ | `pyfs-workspace` | Initialize the managed campaign workspace tree |
146
+ | `pyfs-matrix` | Convert and pre-flight run matrices |
147
+ | `pyfs-fsi` | The structural executable of the aeroelastic coupling loop |
148
+
149
+ ## Supported FlightStream versions
150
+
151
+ Registered: 26.000, 26.100, 26.120 (canonical 26.XXX scheme; the last
152
+ digit indexes vendor hotfix builds). The ordered list in
153
+ `src/pyflightstream/commands/_meta.yaml` is the only ordering
154
+ authority. Evidence is strongest on 26.120 (probed on a licensed
155
+ machine); 26.100 is partially backfilled from the manuals; the 26.000
156
+ column is honestly empty until probed. The compatibility matrix in the
157
+ docs is generated from the database at build time.
158
+
159
+ ## What is each folder?
160
+
161
+ | Folder | Purpose in plain language |
162
+ |---|---|
163
+ | `src/pyflightstream/` | The package, one subpackage per pipeline stage (versions, commands, script, results, cases, run, workspace, post, qa, plus fsi, probes, farfield) |
164
+ | `src/pyflightstream/commands/` | The command database: what exists in which FlightStream version, with manual page citations |
165
+ | `tests/` | Tier 1 tests, runnable anywhere, no FlightStream needed |
166
+ | `reports/` | Committed evidence from licensed machines: command validity (compat), physics regression, drift, and research cards |
167
+ | `docs/` | Documentation source (ProperDocs); reference pages are generated from the database, never committed |
168
+ | `examples/` | Runnable example scripts in percent format |
169
+ | `guide/` | LaTeX source of the user guide (the built pdf never enters Git) |
170
+ | `deprecated/` | Discontinued public items, grouped here instead of scattered at the top level |
171
+ | `.claude/skills/` | Maintenance procedures (version updates, command additions, QA runs, releases) |
172
+ | `_private/` | Local only, never committed: FlightStream manuals, executables, research geometry |
173
+
174
+ ## Development setup
175
+
176
+ ```
177
+ pip install -e .[dev,fsi,geom]
178
+ pre-commit install
179
+ pytest
180
+ ```
181
+
182
+ Tier 1 (the pytest suite) runs anywhere. Tier 2 (command validity
183
+ probes) and Tier 3 (physics regression) require a local FlightStream
184
+ license and are documented in CONTRIBUTING.md. The docs build with
185
+ `properdocs build --strict`.
186
+
187
+ ## License
188
+
189
+ MIT. Contributions must be original or MIT-compatible; code derived
190
+ from the AGPL pyFlightscript package is not accepted. See
191
+ CONTRIBUTING.md.
@@ -0,0 +1,146 @@
1
+ # pyflightstream
2
+
3
+ [![ci](https://github.com/nevesgeovana/pyflightstream/actions/workflows/ci.yml/badge.svg)](https://github.com/nevesgeovana/pyflightstream/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/pyflightstream)](https://pypi.org/project/pyflightstream/)
5
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21482925.svg)](https://doi.org/10.5281/zenodo.21482925)
6
+
7
+ Version-aware, didactic Python driver for the FlightStream panel-method
8
+ solver. Successor of the author's legacy research scripts. MIT licensed.
9
+
10
+ Status: v0.2.0 is public on [PyPI](https://pypi.org/project/pyflightstream/)
11
+ with the archived release on Zenodo (DOI recorded in CITATION.cff).
12
+ Development continues toward v0.3.0; CHANGELOG.md carries the release
13
+ history.
14
+
15
+ ```
16
+ pip install pyflightstream
17
+ ```
18
+
19
+ A first taste, no solver required (build time is where errors surface):
20
+
21
+ ```python
22
+ from pyflightstream.commands import CommandNotInVersionError
23
+ from pyflightstream.script import Script
24
+
25
+ script = Script(version="26.12") # the FlightStream version is explicit input
26
+ script.emit("NEW_SIMULATION")
27
+ script.emit("IMPORT", "METER", "STL", "wing.stl", clear=True)
28
+ script.emit("SOLVER_SET_AOA", 4.0)
29
+ script.emit("START_SOLVER")
30
+ print(script.render()) # validated ASCII script, ready for the solver
31
+
32
+ try:
33
+ Script(version="26.0").emit("SOLVER_SET_AOA", 4.0)
34
+ except CommandNotInVersionError as error:
35
+ print(error) # refused: no recorded evidence for that version
36
+ ```
37
+
38
+ The worked examples in `examples/` take it from here to executed
39
+ polars, campaigns, and coupled aeroelastic runs.
40
+
41
+ Optional extras: `[fsi]` (aeroelastic coupling, PyNiteFEA), `[geom]`
42
+ (probe-survey geometry gating, trimesh/rtree/scipy), `[plot]`
43
+ (matplotlib for the plotting examples).
44
+
45
+ ## Why this package
46
+
47
+ FlightStream is scripted through an ASCII command file, and the solver
48
+ is under active development: the FlightStream team is responsive to
49
+ user requests and works with intermediate hotfix builds that
50
+ consolidate into stable releases. A fast-moving solver naturally means
51
+ a scripting command set that evolves from version to version, faster
52
+ than any single document can track. This package makes the
53
+ FlightStream version an explicit input: every command it emits is
54
+ validated against a per-version command database, and old versions are
55
+ only ever added, never dropped, so campaigns stay reproducible across
56
+ that evolution.
57
+
58
+ Every database entry carries a manual page citation, and its status per
59
+ version (documented, verified, broken) can only be promoted by citing a
60
+ committed probe report from a licensed machine. Nothing is guessed; the
61
+ honest gaps are reported as such.
62
+
63
+ ## What ships
64
+
65
+ - Command database with per-version evidence and a manual citation on
66
+ every entry, browsable offline via `pyflightstream.help()` (including
67
+ a manual-coverage section) and as a generated docs site; the
68
+ compatibility matrix carries the live counts.
69
+ - Validating script builder with curated helpers: phase ordering,
70
+ didactic refusals at build time, entity labels (recipes can name
71
+ frames, actuators, motions, and boundaries instead of raw indices),
72
+ and a solver-setup provenance snapshot recording the effective value
73
+ of every solver flag per run.
74
+ - Campaign workspace: an input-artifact library (references, solver
75
+ presets, boundary groups, geometries, profiles, executables by build
76
+ id), a run manifest as the single identity authority, output naming
77
+ templates, campaign pre-flight with zero solver time, and resumable
78
+ incremental sweeps.
79
+ - Runner and parsers: headless execution, anchor-based parsers for the
80
+ solver outputs, and a pandas table layer (per-result tables, one wide
81
+ row per run, whole-sweep DataFrame straight from the manifest).
82
+ - Run-matrix support as a first-class interface: read, convert,
83
+ pre-flight, and run the pipe-delimited 15-column matrix format.
84
+ - Far-field probe surveys (planar grids, geometry gating, VTK/Tecplot
85
+ writers, conservation ledgers on xarray) and an aeroelastic coupling
86
+ subpackage (structural beam, coupled driver, replay harness).
87
+ - Architecture overview from the live module docstrings via
88
+ `pyflightstream.overview()`.
89
+ - Predictable surfaces: a declared-options registry
90
+ (`pyflightstream.options`), one public exception catalog
91
+ (`pyflightstream.exceptions`), test assertions with quantified
92
+ reports (`pyflightstream.testing`), and the house conventions
93
+ rendered by `help()`.
94
+
95
+ ## Command-line tools
96
+
97
+ | Tool | Purpose |
98
+ |---|---|
99
+ | `pyfs-qa` | Tier 2 command-validity probes, Tier 3 physics regression and cross-version drift, status promotion from committed reports |
100
+ | `pyfs-workspace` | Initialize the managed campaign workspace tree |
101
+ | `pyfs-matrix` | Convert and pre-flight run matrices |
102
+ | `pyfs-fsi` | The structural executable of the aeroelastic coupling loop |
103
+
104
+ ## Supported FlightStream versions
105
+
106
+ Registered: 26.000, 26.100, 26.120 (canonical 26.XXX scheme; the last
107
+ digit indexes vendor hotfix builds). The ordered list in
108
+ `src/pyflightstream/commands/_meta.yaml` is the only ordering
109
+ authority. Evidence is strongest on 26.120 (probed on a licensed
110
+ machine); 26.100 is partially backfilled from the manuals; the 26.000
111
+ column is honestly empty until probed. The compatibility matrix in the
112
+ docs is generated from the database at build time.
113
+
114
+ ## What is each folder?
115
+
116
+ | Folder | Purpose in plain language |
117
+ |---|---|
118
+ | `src/pyflightstream/` | The package, one subpackage per pipeline stage (versions, commands, script, results, cases, run, workspace, post, qa, plus fsi, probes, farfield) |
119
+ | `src/pyflightstream/commands/` | The command database: what exists in which FlightStream version, with manual page citations |
120
+ | `tests/` | Tier 1 tests, runnable anywhere, no FlightStream needed |
121
+ | `reports/` | Committed evidence from licensed machines: command validity (compat), physics regression, drift, and research cards |
122
+ | `docs/` | Documentation source (ProperDocs); reference pages are generated from the database, never committed |
123
+ | `examples/` | Runnable example scripts in percent format |
124
+ | `guide/` | LaTeX source of the user guide (the built pdf never enters Git) |
125
+ | `deprecated/` | Discontinued public items, grouped here instead of scattered at the top level |
126
+ | `.claude/skills/` | Maintenance procedures (version updates, command additions, QA runs, releases) |
127
+ | `_private/` | Local only, never committed: FlightStream manuals, executables, research geometry |
128
+
129
+ ## Development setup
130
+
131
+ ```
132
+ pip install -e .[dev,fsi,geom]
133
+ pre-commit install
134
+ pytest
135
+ ```
136
+
137
+ Tier 1 (the pytest suite) runs anywhere. Tier 2 (command validity
138
+ probes) and Tier 3 (physics regression) require a local FlightStream
139
+ license and are documented in CONTRIBUTING.md. The docs build with
140
+ `properdocs build --strict`.
141
+
142
+ ## License
143
+
144
+ MIT. Contributions must be original or MIT-compatible; code derived
145
+ from the AGPL pyFlightscript package is not accepted. See
146
+ CONTRIBUTING.md.
@@ -4,12 +4,26 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyflightstream"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "Version-aware, didactic Python driver for the FlightStream panel-method solver"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
11
11
  authors = [{name = "Geovana Neves"}]
12
12
  requires-python = ">=3.11"
13
+ # PyPA well-known metadata (audit 2026-07-23). The SPDX license
14
+ # expression form is deferred with the VCS-versioning item: it needs a
15
+ # setuptools floor bump, and the build toolchain does not move in a
16
+ # release week (PLN-024).
17
+ classifiers = [
18
+ "Development Status :: 4 - Beta",
19
+ "Intended Audience :: Science/Research",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: OS Independent",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: Scientific/Engineering :: Physics",
26
+ ]
13
27
  # xarray confirmed as a runtime dependency by the author's far-field
14
28
  # extraction instruction of 2026-07-21 (PLN-006 closed): the farfield
15
29
  # ledgers live on labeled (station, r, psi) arrays.
@@ -31,10 +45,16 @@ geom = ["trimesh", "rtree", "scipy"]
31
45
  fsi = ["PyNiteFEA>=3.0"]
32
46
  dev = [
33
47
  "pytest",
48
+ # Executable examples in CI: docstring doctests and markdown code
49
+ # blocks (INB-006 item 1e, decision Q-007). Config in conftest.py.
50
+ "sybil",
34
51
  "ruff",
35
52
  "pre-commit",
53
+ # Docs build tool (license evidence: reports/RPT-009). The material
54
+ # theme and the nav plugins keep their mkdocs package names and
55
+ # still pull the mkdocs library during the ecosystem transition.
56
+ "properdocs",
36
57
  "mkdocs-material",
37
- "mkdocstrings[python]",
38
58
  "mkdocs-gen-files",
39
59
  "mkdocs-literate-nav",
40
60
  ]
@@ -42,9 +62,14 @@ dev = [
42
62
  [project.scripts]
43
63
  pyfs-qa = "pyflightstream.qa.cli:main"
44
64
  pyfs-fsi = "pyflightstream.fsi.cli:main"
65
+ pyfs-workspace = "pyflightstream.workspace.cli:main"
66
+ pyfs-matrix = "pyflightstream.cases.cli:main"
45
67
 
46
68
  [project.urls]
47
69
  Repository = "https://github.com/nevesgeovana/pyflightstream"
70
+ Documentation = "https://nevesgeovana.github.io/pyflightstream/"
71
+ Changelog = "https://github.com/nevesgeovana/pyflightstream/blob/main/CHANGELOG.md"
72
+ Issues = "https://github.com/nevesgeovana/pyflightstream/issues"
48
73
 
49
74
  [tool.setuptools.packages.find]
50
75
  where = ["src"]
@@ -0,0 +1,79 @@
1
+ """pyflightstream: version-aware, didactic Python driver for FlightStream.
2
+
3
+ The package automates the FlightStream panel-method solver through its
4
+ ASCII scripting interface. The FlightStream version is an explicit
5
+ input: every command emitted is validated against the per-version
6
+ command database in ``pyflightstream.commands``, where each entry
7
+ carries a manual page citation and, when probed on a licensed machine,
8
+ empirical evidence of its status. The script builder refuses at build
9
+ time what the solver would reject (or silently ignore) at run time.
10
+
11
+ Pipeline layers, dependencies flowing strictly downward:
12
+
13
+ - ``versions``: canonical 26.XXX version identifiers and ordering.
14
+ - ``commands``: the evidence-backed per-version command database.
15
+ - ``script``: the validating ASCII script builder.
16
+ - ``results``: anchor-based parsers for solver output files.
17
+ - ``cases``: simulation and campaign definitions.
18
+ - ``run`` and ``workspace``: execution, run manifest, and the managed
19
+ workspace (input-artifact library plus run layout); the old
20
+ ``files`` name survives as a deprecation shim.
21
+ - ``post``: results into engineering data (sweep assembly, exports).
22
+ - ``qa``: probe harness and physics regression tooling.
23
+
24
+ Side packages follow the same downward-only rule:
25
+
26
+ - ``fsi``: the structural executable of the aeroelastic coupling loop.
27
+ - ``probes`` and ``farfield``: probe lattices for far-field surveys and
28
+ the conservation ledgers computed on them.
29
+ - ``reference``: the command reference renderer behind ``help()``.
30
+
31
+ Cross-cutting support modules, importable from any layer:
32
+
33
+ - ``options``: the declared, validated machine and QA knobs
34
+ (``get_option``/``set_option`` also re-exported here at top level).
35
+ - ``exceptions``: the single catalog of every exception and warning.
36
+ - ``testing``: public assertions with quantified violation reports.
37
+
38
+ Where to start:
39
+
40
+ - :func:`pyflightstream.help` opens the offline HTML command reference,
41
+ rendered from the installed command database.
42
+ - :func:`pyflightstream.overview` opens the offline HTML architecture
43
+ overview, rendered from the live module docstrings.
44
+ - The published docs site carries the same reference and overview plus
45
+ the compatibility matrix and worked examples.
46
+ """
47
+
48
+ from importlib import metadata
49
+
50
+ try:
51
+ __version__ = metadata.version("pyflightstream")
52
+ except metadata.PackageNotFoundError:
53
+ # Source tree imported without an installation (for example a
54
+ # checkout placed on sys.path): no distribution metadata exists, so
55
+ # the version is honestly unknown instead of a stale hardcoded
56
+ # string. Install the package (pip install -e .) to expose the real
57
+ # version.
58
+ __version__ = "0.0.0+uninstalled"
59
+
60
+ from pyflightstream.options import ( # noqa: E402
61
+ describe_option,
62
+ get_option,
63
+ option_context,
64
+ reset_option,
65
+ set_option,
66
+ )
67
+ from pyflightstream.overview import overview # noqa: E402
68
+ from pyflightstream.reference import help # noqa: E402
69
+
70
+ __all__ = [
71
+ "__version__",
72
+ "describe_option",
73
+ "get_option",
74
+ "help",
75
+ "option_context",
76
+ "overview",
77
+ "reset_option",
78
+ "set_option",
79
+ ]
@@ -0,0 +1,121 @@
1
+ """Deprecation ledger: every shim's recorded removal promise.
2
+
3
+ Pipeline role: cross-cutting support module (no solver semantics). A
4
+ deprecation is a versioned promise: the old name keeps working until a
5
+ stated package version and disappears at that version, never silently
6
+ later. This module is the single home of those promises; the shim
7
+ modules build their DeprecationWarning text from their ledger entry, so
8
+ the message users see and the deadline the Tier 1 guard enforces
9
+ (``tests/test_deprecation_deadline.py``) can never disagree (NFR-11).
10
+
11
+ Lifecycle of an entry: it is added in the commit that creates the shim,
12
+ its ``removal_version`` is cited by the shim's warning, and the entry
13
+ is deleted together with the shim in the release that reaches that
14
+ version. The Tier 1 guard fails the suite when a shim survives past its
15
+ promise, so a release cannot ship an expired shim unnoticed.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ from dataclasses import dataclass
21
+
22
+
23
+ def parse_version(version: str) -> tuple[int, int, int]:
24
+ """Parse a plain SemVer string into a comparable tuple.
25
+
26
+ Parameters
27
+ ----------
28
+ version : str
29
+ A ``MAJOR.MINOR.PATCH`` string with integer fields, as used by
30
+ ``pyproject.toml``. Pre-release or local suffixes are not
31
+ accepted: removal promises are made against plain releases.
32
+
33
+ Returns
34
+ -------
35
+ tuple of int
36
+ ``(major, minor, patch)``, ordered like SemVer precedence.
37
+
38
+ Raises
39
+ ------
40
+ ValueError
41
+ If the string is not three dot-separated integers.
42
+ """
43
+ parts = version.split(".")
44
+ if len(parts) != 3 or not all(part.isdigit() for part in parts):
45
+ raise ValueError(
46
+ f"Expected a plain MAJOR.MINOR.PATCH version, got {version!r}; "
47
+ "deprecation promises are recorded against plain SemVer releases."
48
+ )
49
+ major, minor, patch = (int(part) for part in parts)
50
+ return (major, minor, patch)
51
+
52
+
53
+ @dataclass(frozen=True)
54
+ class DeprecatedModule:
55
+ """One deprecated module and its recorded removal promise.
56
+
57
+ Attributes
58
+ ----------
59
+ module : str
60
+ Dotted name of the shim module (the old import path).
61
+ replacement : str
62
+ Dotted name of the module that supersedes it.
63
+ deprecated_since : str
64
+ Package version (SemVer) whose release introduced the shim.
65
+ removal_version : str
66
+ First package version (SemVer) that must no longer carry the
67
+ shim. The Tier 1 deadline guard fails once ``pyproject.toml``
68
+ reaches this version with the shim still present.
69
+ extra : str
70
+ Optional extra sentence appended to the warning message, for
71
+ renames that involve more than the module path.
72
+ """
73
+
74
+ module: str
75
+ replacement: str
76
+ deprecated_since: str
77
+ removal_version: str
78
+ extra: str = ""
79
+
80
+ def message(self) -> str:
81
+ """Render the DeprecationWarning text emitted by the shim.
82
+
83
+ Returns
84
+ -------
85
+ str
86
+ One message stating the rename, the version that made the
87
+ promise, and the exact version that removes the old name.
88
+ """
89
+ text = (
90
+ f"{self.module} was renamed to {self.replacement} in "
91
+ f"v{self.deprecated_since} and will be removed in "
92
+ f"v{self.removal_version}; update the import to "
93
+ f"{self.replacement}."
94
+ )
95
+ if self.extra:
96
+ text = f"{text} {self.extra}"
97
+ return text
98
+
99
+
100
+ #: Every live deprecation shim of the package, one entry each. The
101
+ #: Tier 1 deadline guard iterates this tuple; an empty tuple means the
102
+ #: package currently makes no deprecation promises.
103
+ DEPRECATED_MODULES: tuple[DeprecatedModule, ...] = (
104
+ DeprecatedModule(
105
+ module="pyflightstream.files",
106
+ replacement="pyflightstream.workspace",
107
+ deprecated_since="0.3.0",
108
+ removal_version="0.4.0",
109
+ extra="The API is unchanged.",
110
+ ),
111
+ DeprecatedModule(
112
+ module="pyflightstream.cases.matrix_legacy",
113
+ replacement="pyflightstream.cases.matrix",
114
+ deprecated_since="0.3.0",
115
+ removal_version="0.4.0",
116
+ extra=(
117
+ "LegacyMatrixError is now MatrixError and LegacyRow is now "
118
+ "MatrixRow; everything else is unchanged."
119
+ ),
120
+ ),
121
+ )
@@ -5,9 +5,9 @@ by ``sim_id``) is one solver configuration with its sweep; a
5
5
  :class:`Campaign` groups cases with the FlightStream version and the
6
6
  executable path, both required and explicit: nothing is read from
7
7
  environment variables or guessed (SAD Section 5). Native persistence
8
- is ``campaign.toml``; the legacy pipe-delimited ``matriz.fs`` matrix
9
- of the predecessor scripts will be read unchanged, forever, by the
10
- legacy reader (FR-10, next step of milestone M2).
8
+ is ``campaign.toml``; the pipe-delimited ``matrix.fs`` run matrix
9
+ is read unchanged, forever, by the matrix reader
10
+ (:mod:`pyflightstream.cases.matrix`, FR-10).
11
11
 
12
12
  Script recipes are explicitly imported functions satisfying the
13
13
  :class:`ScriptRecipe` protocol: ``build(case, script) -> None``. The