pyflightstream 0.34.0__tar.gz → 0.35.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 (317) hide show
  1. {pyflightstream-0.34.0/src/pyflightstream.egg-info → pyflightstream-0.35.0}/PKG-INFO +2 -2
  2. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/README.md +1 -1
  3. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/pyproject.toml +3 -3
  4. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_digest.py +11 -0
  5. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/ccs_wing.py +10 -4
  6. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/__init__.py +25 -0
  7. pyflightstream-0.35.0/src/pyflightstream/cases/workflows/_batch_actions.py +468 -0
  8. pyflightstream-0.35.0/src/pyflightstream/cases/workflows/_batch_script.py +630 -0
  9. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_rows.py +29 -0
  10. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_skeleton.py +70 -11
  11. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_unsteady.py +40 -1
  12. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_vocabulary.py +14 -1
  13. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/acoustics.yaml +9 -9
  14. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/advanced_settings.yaml +1 -1
  15. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/ccs_fuselage_mesh.yaml +10 -10
  16. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/ccs_revolve_mesh.yaml +10 -10
  17. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/ccs_wing_mesh.yaml +12 -12
  18. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/mesh_import_export.yaml +2 -9
  19. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/mesh_operations.yaml +1 -1
  20. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/unsteady_solver.yaml +1 -3
  21. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/overview.py +5 -0
  22. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/_tables.py +34 -2
  23. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/diagnostics.py +2 -14
  24. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/input_template.py +4 -4
  25. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/products.py +30 -8
  26. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/writers.py +4 -1
  27. pyflightstream-0.35.0/src/pyflightstream/qa/_spec_ccs_mesh.py +402 -0
  28. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/_spec_ccs_noise.py +30 -8
  29. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/compat.py +15 -4
  30. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/probes.py +35 -3
  31. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/log.py +114 -3
  32. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/tables.py +29 -2
  33. pyflightstream-0.35.0/src/pyflightstream/run/_alias.py +410 -0
  34. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_assemble.py +2 -1
  35. pyflightstream-0.35.0/src/pyflightstream/run/_batch_collect.py +548 -0
  36. pyflightstream-0.35.0/src/pyflightstream/run/_batch_exec.py +364 -0
  37. pyflightstream-0.35.0/src/pyflightstream/run/_batch_plan.py +555 -0
  38. pyflightstream-0.35.0/src/pyflightstream/run/_batch_run.py +644 -0
  39. pyflightstream-0.35.0/src/pyflightstream/run/_batch_split.py +477 -0
  40. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_campaign.py +2 -5
  41. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_cli_parsers.py +126 -17
  42. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_cli_print.py +22 -3
  43. pyflightstream-0.35.0/src/pyflightstream/run/_cli_query.py +302 -0
  44. pyflightstream-0.35.0/src/pyflightstream/run/_cli_query_history.py +113 -0
  45. pyflightstream-0.35.0/src/pyflightstream/run/_cli_query_point.py +262 -0
  46. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_continuation.py +48 -1
  47. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_continuation_frame.py +4 -38
  48. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_executors.py +11 -2
  49. pyflightstream-0.35.0/src/pyflightstream/run/_grouped.py +234 -0
  50. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_ids.py +13 -1
  51. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_plan.py +13 -4
  52. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_rebuild.py +29 -4
  53. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_rebuild_evidence.py +40 -180
  54. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_record_files.py +55 -0
  55. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/cli.py +37 -13
  56. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/collect.py +210 -46
  57. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/matrix.py +2 -2
  58. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/records.py +19 -4
  59. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/__init__.py +9 -9
  60. pyflightstream-0.35.0/src/pyflightstream/workspace/_batch_life.py +387 -0
  61. pyflightstream-0.35.0/src/pyflightstream/workspace/_batch_relocate.py +240 -0
  62. pyflightstream-0.35.0/src/pyflightstream/workspace/_batches.py +366 -0
  63. pyflightstream-0.35.0/src/pyflightstream/workspace/_effective.py +206 -0
  64. pyflightstream-0.35.0/src/pyflightstream/workspace/_ledger_api.py +351 -0
  65. pyflightstream-0.35.0/src/pyflightstream/workspace/_ledger_history.py +290 -0
  66. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/_matrix_homes.py +3 -0
  67. pyflightstream-0.35.0/src/pyflightstream/workspace/_query_files.py +181 -0
  68. pyflightstream-0.35.0/src/pyflightstream/workspace/_query_logs.py +209 -0
  69. pyflightstream-0.35.0/src/pyflightstream/workspace/_query_point.py +221 -0
  70. pyflightstream-0.35.0/src/pyflightstream/workspace/_script_comparison.py +202 -0
  71. pyflightstream-0.35.0/src/pyflightstream/workspace/costs.py +461 -0
  72. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/hpc.py +110 -13
  73. pyflightstream-0.35.0/src/pyflightstream/workspace/ledger.py +803 -0
  74. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/storage.py +10 -10
  75. {pyflightstream-0.34.0 → pyflightstream-0.35.0/src/pyflightstream.egg-info}/PKG-INFO +2 -2
  76. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream.egg-info/SOURCES.txt +24 -0
  77. pyflightstream-0.34.0/src/pyflightstream/qa/_spec_ccs_mesh.py +0 -257
  78. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/LICENSE +0 -0
  79. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/setup.cfg +0 -0
  80. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/__init__.py +0 -0
  81. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_atmosphere.py +0 -0
  82. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_cli.py +0 -0
  83. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_console.py +0 -0
  84. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_decimal.py +0 -0
  85. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_deprecations.py +0 -0
  86. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_errors.py +0 -0
  87. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_expressions.py +0 -0
  88. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_fsi_calibration.py +0 -0
  89. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_fsm.py +0 -0
  90. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_fsm_fresh.py +0 -0
  91. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_lengths.py +0 -0
  92. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_mesh.py +0 -0
  93. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_progress.py +0 -0
  94. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_retired_names.py +0 -0
  95. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_signature.py +0 -0
  96. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_textio.py +0 -0
  97. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_tokens.py +0 -0
  98. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/_yamlflow.py +0 -0
  99. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/__init__.py +0 -0
  100. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/_ccs.py +0 -0
  101. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/_setup_keys.py +0 -0
  102. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/_setup_link.py +0 -0
  103. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/_skipped_families.py +0 -0
  104. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/_unsteady_actions.py +0 -0
  105. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/acoustics.py +0 -0
  106. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/ccs_fuselage.py +0 -0
  107. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/ccs_revolution.py +0 -0
  108. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/corrections.py +0 -0
  109. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/field_coverage.py +0 -0
  110. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/freestream.py +0 -0
  111. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/fsi_workspace.py +0 -0
  112. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/matrix.py +0 -0
  113. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/mesh.py +0 -0
  114. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/naming.py +0 -0
  115. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/pproc.py +0 -0
  116. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/qsteady.py +0 -0
  117. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/reference_blocks.py +0 -0
  118. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/selection.py +0 -0
  119. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/settings.py +0 -0
  120. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/setup_surfaces.py +0 -0
  121. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/windows.py +0 -0
  122. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_actuator.py +0 -0
  123. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_additional.py +0 -0
  124. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_clock.py +0 -0
  125. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_conventions.py +0 -0
  126. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_exports.py +0 -0
  127. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_frames.py +0 -0
  128. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_freestream.py +0 -0
  129. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_geometry.py +0 -0
  130. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_motion.py +0 -0
  131. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_names.py +0 -0
  132. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_pproc.py +0 -0
  133. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_probes.py +0 -0
  134. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_qsteady_rotor.py +0 -0
  135. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_reductions.py +0 -0
  136. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_registry.py +0 -0
  137. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_rotor.py +0 -0
  138. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_solver_settings.py +0 -0
  139. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_steady.py +0 -0
  140. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/cases/workflows/_timing.py +0 -0
  141. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/__init__.py +0 -0
  142. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/_meta.yaml +0 -0
  143. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/actuators.yaml +0 -0
  144. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/aeroelastic_coupling.yaml +0 -0
  145. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/base_regions.yaml +0 -0
  146. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/boundary_conditions.yaml +0 -0
  147. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/cad.yaml +0 -0
  148. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/cad_create.yaml +0 -0
  149. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/coordinate_systems.yaml +0 -0
  150. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/file_io.yaml +0 -0
  151. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/inlets_outlets.yaml +0 -0
  152. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/mesh_unite.yaml +0 -0
  153. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/mesh_wrapper.yaml +0 -0
  154. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/motion_definitions.yaml +0 -0
  155. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/plots.yaml +0 -0
  156. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/probe_points.yaml +0 -0
  157. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/runtime_settings.yaml +0 -0
  158. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/scene_settings.yaml +0 -0
  159. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/scenes.yaml +0 -0
  160. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/script_controls.yaml +0 -0
  161. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/simulation_controls.yaml +0 -0
  162. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/solver_analysis.yaml +0 -0
  163. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/solver_contours.yaml +0 -0
  164. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/solver_export.yaml +0 -0
  165. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/solver_initialization.yaml +0 -0
  166. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/solver_settings.yaml +0 -0
  167. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/stability_toolbox.yaml +0 -0
  168. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/streamlines.yaml +0 -0
  169. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/surface_sections.yaml +0 -0
  170. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/sweeper.yaml +0 -0
  171. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/transition_trips.yaml +0 -0
  172. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/commands/volume_sections.yaml +0 -0
  173. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/exceptions.py +0 -0
  174. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/extras.py +0 -0
  175. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/farfield/__init__.py +0 -0
  176. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/__init__.py +0 -0
  177. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/beam.py +0 -0
  178. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/calibration.py +0 -0
  179. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/centrifugal.py +0 -0
  180. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/cli.py +0 -0
  181. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/config.py +0 -0
  182. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/driver.py +0 -0
  183. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/errors.py +0 -0
  184. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/kinematics.py +0 -0
  185. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/loads.py +0 -0
  186. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/materials.py +0 -0
  187. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/nodes.py +0 -0
  188. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/sections.py +0 -0
  189. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/state.py +0 -0
  190. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/fsi/wing.py +0 -0
  191. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/options.py +0 -0
  192. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/__init__.py +0 -0
  193. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/_additional.py +0 -0
  194. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/_admit.py +0 -0
  195. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/_condition.py +0 -0
  196. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/_reduction_stage.py +0 -0
  197. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/_rotor_plan.py +0 -0
  198. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/_rotor_products.py +0 -0
  199. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/_sim.py +0 -0
  200. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/_stage.py +0 -0
  201. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/acoustics.py +0 -0
  202. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/axes.py +0 -0
  203. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/boundary_layer.py +0 -0
  204. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/corrections.py +0 -0
  205. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/custom_polar.py +0 -0
  206. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/disc_maps.py +0 -0
  207. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/equations.py +0 -0
  208. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/field_frames.py +0 -0
  209. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/glossary.py +0 -0
  210. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/guides.py +0 -0
  211. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/harmonics.py +0 -0
  212. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/inflow_tools.py +0 -0
  213. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/point_tables.py +0 -0
  214. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/polar.py +0 -0
  215. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/probe_fields.py +0 -0
  216. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/provenance.py +0 -0
  217. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/qsteady.py +0 -0
  218. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/qsteady_noise.py +0 -0
  219. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/reductions.py +0 -0
  220. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/rotor_table.py +0 -0
  221. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/section_distributions.py +0 -0
  222. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/series.py +0 -0
  223. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/settings_table.py +0 -0
  224. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/superfile.py +0 -0
  225. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/surfaces.py +0 -0
  226. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/unsteady.py +0 -0
  227. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/post/unsteady_polar.py +0 -0
  228. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/probes/__init__.py +0 -0
  229. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/probes/errors.py +0 -0
  230. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/probes/geometry.py +0 -0
  231. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/probes/planar.py +0 -0
  232. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/__init__.py +0 -0
  233. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/_spec_catalog_b.py +0 -0
  234. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/_spec_kit.py +0 -0
  235. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/_spec_t1.py +0 -0
  236. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/cli.py +0 -0
  237. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/cost.py +0 -0
  238. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/drift.py +0 -0
  239. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/errors.py +0 -0
  240. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/geometry.py +0 -0
  241. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/matrix.py +0 -0
  242. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/physics.py +0 -0
  243. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/references/PHY-01.yaml +0 -0
  244. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/references/PHY-02.yaml +0 -0
  245. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/references/PHY-05.yaml +0 -0
  246. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/references/PHY-06.yaml +0 -0
  247. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/references/SMI-01.yaml +0 -0
  248. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/references/SMI-02.yaml +0 -0
  249. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/reports.py +0 -0
  250. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/qa/specs.py +0 -0
  251. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/reference.py +0 -0
  252. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/__init__.py +0 -0
  253. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/conditions.py +0 -0
  254. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/core.py +0 -0
  255. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/exports.py +0 -0
  256. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/loads.py +0 -0
  257. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/native_surface.py +0 -0
  258. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/sectional_loads.py +0 -0
  259. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/results/surface.py +0 -0
  260. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/__init__.py +0 -0
  261. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_actions_counter.py +0 -0
  262. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_assessment.py +0 -0
  263. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_field_motion.py +0 -0
  264. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_identity.py +0 -0
  265. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_pending.py +0 -0
  266. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_points.py +0 -0
  267. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_solver_windows.py +0 -0
  268. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_step_exports.py +0 -0
  269. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_sweep.py +0 -0
  270. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/_wake_edge_verdict.py +0 -0
  271. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/run/rename.py +0 -0
  272. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/__init__.py +0 -0
  273. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/_relaxed_te.py +0 -0
  274. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/_settings.py +0 -0
  275. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/_surface_averaging.py +0 -0
  276. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/entities.py +0 -0
  277. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/helpers.py +0 -0
  278. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/motion.py +0 -0
  279. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/rotor_vocabulary.py +0 -0
  280. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/solver_setup.py +0 -0
  281. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/script/toggles.py +0 -0
  282. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/support.py +0 -0
  283. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/testing.py +0 -0
  284. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/utils/__init__.py +0 -0
  285. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/utils/cli.py +0 -0
  286. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/utils/database.py +0 -0
  287. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/utils/errors.py +0 -0
  288. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/utils/manual.py +0 -0
  289. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/versions.py +0 -0
  290. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/_degenerate.py +0 -0
  291. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/_geometry_clean.py +0 -0
  292. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/_links.py +0 -0
  293. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/_row_setup.py +0 -0
  294. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/actuator_profiles.py +0 -0
  295. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/builds.py +0 -0
  296. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/cli.py +0 -0
  297. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/excel.py +0 -0
  298. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/excel_bridge.py +0 -0
  299. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/excel_file.py +0 -0
  300. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/excel_sync.py +0 -0
  301. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/fields.py +0 -0
  302. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/flight_condition.py +0 -0
  303. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/fsi_setup.py +0 -0
  304. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/inputs.py +0 -0
  305. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/matrix.py +0 -0
  306. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/naming.py +0 -0
  307. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/rename_groups.py +0 -0
  308. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/selections.py +0 -0
  309. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/setup_inspection.py +0 -0
  310. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/setup_standards.py +0 -0
  311. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/sidecars.py +0 -0
  312. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/trailing_edges.py +0 -0
  313. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream/workspace/wake_edges.py +0 -0
  314. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream.egg-info/dependency_links.txt +0 -0
  315. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream.egg-info/entry_points.txt +0 -0
  316. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream.egg-info/requires.txt +0 -0
  317. {pyflightstream-0.34.0 → pyflightstream-0.35.0}/src/pyflightstream.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyflightstream
3
- Version: 0.34.0
3
+ Version: 0.35.0
4
4
  Summary: Version-aware, didactic Python driver for the FlightStream panel-method solver
5
5
  Author: Geovana Neves
6
6
  License: MIT
@@ -61,7 +61,7 @@ Version-aware Python driver for the FlightStream panel-method solver: write a
61
61
  run matrix, and pyflightstream plans, runs and post-processes every point,
62
62
  from your workstation or a cluster. MIT licensed.
63
63
 
64
- Status: v0.34.0 is the current release; CHANGELOG.md carries the history.
64
+ Status: v0.35.0 is the current release; CHANGELOG.md carries the history.
65
65
 
66
66
  **Documentation: [nevesgeovana.github.io/pyflightstream](https://nevesgeovana.github.io/pyflightstream/)**
67
67
 
@@ -8,7 +8,7 @@ Version-aware Python driver for the FlightStream panel-method solver: write a
8
8
  run matrix, and pyflightstream plans, runs and post-processes every point,
9
9
  from your workstation or a cluster. MIT licensed.
10
10
 
11
- Status: v0.34.0 is the current release; CHANGELOG.md carries the history.
11
+ Status: v0.35.0 is the current release; CHANGELOG.md carries the history.
12
12
 
13
13
  **Documentation: [nevesgeovana.github.io/pyflightstream](https://nevesgeovana.github.io/pyflightstream/)**
14
14
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyflightstream"
7
- version = "0.34.0"
7
+ version = "0.35.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"}
@@ -249,7 +249,7 @@ exclude_also = [
249
249
  # RE-COUNTED at 0.8.0.dev0 (OPS-2006.11.01), because the sentence above is a
250
250
  # fact about 2026-08-03 and was being read as a fact about today. With every
251
251
  # override below turned off:
252
- # mypy recount 2026-10-02: 160 errors in 16 of 236 modules, the
252
+ # mypy recount 2026-10-02: 160 errors in 16 of 260 modules, the
253
253
  # 0.34.0 branch rel/0-34 with the wave-2 packages merged: two modules
254
254
  # more than the wave-1 tip, both clean (the wave-1 tip read 160 in 16 of
255
255
  # 234: fifteen modules more than 0.33.0, each clean, the cuts of WP8,
@@ -259,7 +259,7 @@ exclude_also = [
259
259
  # of 219, when pyflightstream.run left the exempted set (decision 7)
260
260
  # with its 930 errors; 1122 in 18 of 196 before WP5 and WP6, and 1122
261
261
  # in 18 of 173 before WP4)
262
- # The package has grown from the 53 modules of the first run to 236, and no
262
+ # The package has grown from the 53 modules of the first run to 260, and no
263
263
  # module outside the exempted set is dirty. THE EXEMPTED SET DID MOVE, and
264
264
  # down: `pyflightstream.results.tables` was excused on 2026-08-03 and is
265
265
  # clean now, so its override was deleted on evidence (see the note where it
@@ -137,6 +137,11 @@ CANONICAL_FORMS = {
137
137
  "grid counts, then space-separated .17g finite values, LF between rows "
138
138
  "and one final LF. Source/effective paths are provenance, not hash input."
139
139
  ),
140
+ "run/_batch_exec.py": (
141
+ "the UTF-8 encoding of the grouping receipt's JSON form, rendered with "
142
+ "sorted keys and ASCII escaping, so the same receipt always hashes alike. "
143
+ "No path or clock enters the text."
144
+ ),
140
145
  "run/_continuation_frame.py": (
141
146
  "pending input bytes unchanged, or UTF-8 encoded pending text. For text, "
142
147
  "both the unmodified encoding and its LF-to-CRLF replacement are compared "
@@ -174,6 +179,12 @@ CANONICAL_FORMS = {
174
179
  "storage recipe (inputs/management/m<id>.toml), always the source file's "
175
180
  "bytes and never a JSON rendering of its parsed content."
176
181
  ),
182
+ "workspace/_ledger_history.py": (
183
+ "the raw bytes of a recorded script file, read whole and never decoded, "
184
+ "compared with the script_sha256 the run record states: the same "
185
+ "canonical form as the manifest checksum above. It selects which script "
186
+ "to compare and writes nothing."
187
+ ),
177
188
  }
178
189
 
179
190
  __all__ = [
@@ -338,13 +338,16 @@ def _emit_file_route(script: Script, case: SimCase, names: Sequence[str]) -> Non
338
338
 
339
339
 
340
340
  def _refuse_the_real_control_surface_form(case: SimCase, spec: CcsImportOptions) -> None:
341
- """Refuse a control surface written with REAL spanwise limits (RPT-097, POL 3205).
341
+ """Refuse a control surface written with REAL spanwise limits (RPT-097, POL 3205, RPT-126).
342
342
 
343
343
  Licensed round 2 on FlightStream 26.124 ran the same aileron in the two
344
344
  forms through the package route: the PARAMETRIC form completed and saved a
345
345
  simulation that differs from the wing without it (POL 3204), and the REAL
346
346
  form ended ``FAILED_EXECUTION`` with no saved simulation (POL 3205). No
347
347
  other build measured the REAL form, so it is refused on every build.
348
+ RPT-126 then separated the cause (FR-336 R4, ``refusal_stays``): the limits
349
+ 2.0 and 3.6 end the solver process in both spaces, the REAL token does not,
350
+ and the message states it.
348
351
  """
349
352
  for surface in spec.control_surfaces:
350
353
  if surface.space != "REAL":
@@ -353,9 +356,12 @@ def _refuse_the_real_control_surface_form(case: SimCase, spec: CcsImportOptions)
353
356
  f"case {case.sim_id!r}: the control surface {surface.name!r} is written with REAL "
354
357
  "spanwise limits, and the plan refuses that form. On FlightStream 26.124 the REAL "
355
358
  "form ended FAILED_EXECUTION with no saved simulation, where the same surface in "
356
- "the PARAMETRIC form completed (licensed round 2, RPT-097), and no other build "
357
- "measured it. Write the limits as fractions of the span between 0 and 1 and "
358
- 'space = "PARAMETRIC" (the default) in the sidecar\'s [[import.ccs.control_surfaces]].'
359
+ "the PARAMETRIC form completed (licensed round 2, RPT-097). RPT-126 measured the "
360
+ "cause: the limits 2.0 and 3.6 end the solver process (0xC0000005) in both spaces, "
361
+ "so the REAL token is not the cause; the refusal stays because that row neither "
362
+ "solved nor saved, and no other build measured the form. Write the limits as "
363
+ 'fractions of the span between 0 and 1 and space = "PARAMETRIC" (the default) in '
364
+ "the sidecar's [[import.ccs.control_surfaces]]."
359
365
  )
360
366
 
361
367
 
@@ -310,6 +310,12 @@ from ._vocabulary import (
310
310
  from ._vocabulary import (
311
311
  ALPHA_VARIABLE as ALPHA_VARIABLE,
312
312
  )
313
+ from ._vocabulary import (
314
+ BATCH_DIR as BATCH_DIR,
315
+ )
316
+ from ._vocabulary import (
317
+ BATCH_STEM_PREFIX as BATCH_STEM_PREFIX,
318
+ )
313
319
  from ._vocabulary import (
314
320
  BETA_VARIABLE as BETA_VARIABLE,
315
321
  )
@@ -334,6 +340,9 @@ from ._vocabulary import (
334
340
  from ._vocabulary import (
335
341
  CONVERTER_PREFIX as CONVERTER_PREFIX,
336
342
  )
343
+ from ._vocabulary import (
344
+ CUMULATIVE_LOG_SUFFIX as CUMULATIVE_LOG_SUFFIX,
345
+ )
337
346
  from ._vocabulary import (
338
347
  FLAT_RPM_KEY as FLAT_RPM_KEY,
339
348
  )
@@ -343,6 +352,15 @@ from ._vocabulary import (
343
352
  from ._vocabulary import (
344
353
  FREESTREAM_UNITS_VARIABLE as FREESTREAM_UNITS_VARIABLE,
345
354
  )
355
+ from ._vocabulary import (
356
+ FULL_POLAR_STEM as FULL_POLAR_STEM,
357
+ )
358
+ from ._vocabulary import (
359
+ JOB_END_SUFFIX as JOB_END_SUFFIX,
360
+ )
361
+ from ._vocabulary import (
362
+ JOB_LOG_SUFFIX as JOB_LOG_SUFFIX,
363
+ )
346
364
  from ._vocabulary import (
347
365
  MOVING_BC_ALIAS_VARIABLE as MOVING_BC_ALIAS_VARIABLE,
348
366
  )
@@ -429,6 +447,12 @@ from ._vocabulary import (
429
447
  )
430
448
 
431
449
  __all__ = [
450
+ "BATCH_DIR",
451
+ "BATCH_STEM_PREFIX",
452
+ "CUMULATIVE_LOG_SUFFIX",
453
+ "FULL_POLAR_STEM",
454
+ "JOB_END_SUFFIX",
455
+ "JOB_LOG_SUFFIX",
432
456
  "row_symmetry_loads",
433
457
  "ACTUATOR_KEYS",
434
458
  "ACTUATOR_PROFILE_COPY_SUFFIX",
@@ -477,6 +501,7 @@ __all__ = [
477
501
  "SYMMETRY_VARIABLE",
478
502
  "TIME_ITERATIONS_VARIABLE",
479
503
  "VELOCITY_VARIABLE",
504
+ "WALLTIME_VARIABLE",
480
505
  "LAST_ITERS_AVG_VARIABLE",
481
506
  "LAST_REVS_AVG_VARIABLE",
482
507
  "WORKFLOWS",
@@ -0,0 +1,468 @@
1
+ """The action programs of a grouped job: one counter and one clock for many points (FR-B5a, FR-B19).
2
+
3
+ A grouped job (``--batch`` or ``--polar-sweep``, 0.35.0) runs several points
4
+ in ONE solver instance. The unsteady actions are registered ONCE per instance
5
+ (MEASURED, DESIGN-0350 Test 2: the actions survive ``REMOVE_INITIALIZATION``
6
+ and ``NEW_SIMULATION``, and a second registration runs every action twice per
7
+ step), so the counter and the clock the job registers serve every point of it.
8
+ The solver hands an action nothing, so these programs re-index the job's
9
+ invocation count into (point, the point's own step) from a schedule written
10
+ beside them, and write each point's own count and clock state into the
11
+ point's own folder, in the shape a point run alone leaves.
12
+
13
+ Both programs stand alone: no package import, every path taken from their
14
+ own file's folder (the job's ``actions/``) and from the schedule, every write
15
+ with an explicit LF, like ``run/_actions_counter.py:TEMPLATE``.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ from collections.abc import Iterable, Sequence
21
+ from pathlib import PurePath, PureWindowsPath
22
+ from typing import Protocol
23
+
24
+ from pyflightstream.cases._unsteady_actions import (
25
+ UNSTEADY_ACTION_COUNT,
26
+ UNSTEADY_ACTION_SCRIPT,
27
+ WALLTIME_CLOCK_STATE,
28
+ WALLTIME_STOP_SCRIPT,
29
+ )
30
+
31
+ from ._vocabulary import CUMULATIVE_LOG_SUFFIX
32
+
33
+ __all__ = [
34
+ "JOB_CURRENT",
35
+ "JOB_PROGRESS",
36
+ "JOB_SCHEDULE",
37
+ "SchedulePoint",
38
+ "absolute_output_lines",
39
+ "is_absolute_target",
40
+ "job_schedule",
41
+ "render_job_clock_program",
42
+ "render_job_counter_program",
43
+ ]
44
+
45
+ #: The schedule the two programs read, relative to the job folder.
46
+ JOB_SCHEDULE = "actions/pfs_batch_schedule.json"
47
+ #: The configuration of the point now running, rewritten at its first step.
48
+ JOB_CURRENT = "actions/pfs_batch_current.json"
49
+ #: The job's progress, rewritten at every step; collect reads its mismatches.
50
+ JOB_PROGRESS = "actions/pfs_batch_progress.json"
51
+
52
+ #: The schema of the schedule, so a reader refuses one it does not know.
53
+ SCHEDULE_SCHEMA = "pyfs-batch-schedule/1"
54
+
55
+
56
+ class SchedulePoint(Protocol):
57
+ """The fields of a job point the schedule reads (``JobPoint`` satisfies it)."""
58
+
59
+ @property
60
+ def run_id(self) -> str:
61
+ """The point's run id."""
62
+ ...
63
+
64
+ @property
65
+ def datapoint_dir(self) -> PurePath:
66
+ """The point's absolute datapoint folder."""
67
+ ...
68
+
69
+ @property
70
+ def outputs(self) -> tuple[str, ...]:
71
+ """The outputs its script names, relative."""
72
+ ...
73
+
74
+ @property
75
+ def action_exports(self) -> str:
76
+ """Its per-step export lines, relative."""
77
+ ...
78
+
79
+ @property
80
+ def first_export_step(self) -> int | None:
81
+ """The first step of its per-step exports, from its own step 1."""
82
+ ...
83
+
84
+ @property
85
+ def stop_text(self) -> str:
86
+ """What the clock writes when it stops this point, relative."""
87
+ ...
88
+
89
+ @property
90
+ def time_steps(self) -> int:
91
+ """The time steps the point marches."""
92
+ ...
93
+
94
+
95
+ def is_absolute_target(target: str) -> bool:
96
+ """Whether a script's path argument is absolute, on Windows or on a POSIX cluster.
97
+
98
+ Parameters
99
+ ----------
100
+ target : str
101
+ A path argument as the script writes it.
102
+
103
+ Returns
104
+ -------
105
+ bool
106
+ True for a drive or UNC path and for a path from the POSIX root.
107
+ """
108
+ return target.startswith("/") or PureWindowsPath(target).is_absolute()
109
+
110
+
111
+ def _log_stem(name: str) -> str:
112
+ """Return the stem of a point's log name: ``<stem>_log.txt`` gives ``<stem>``."""
113
+ return name.removesuffix("_log.txt") if name.endswith("_log.txt") else PurePath(name).stem
114
+
115
+
116
+ def absolute_output_lines(text: str, datapoint_dir: PurePath, names: Iterable[str]) -> str:
117
+ """Return ``text`` with every line naming an output made absolute under ``datapoint_dir``.
118
+
119
+ A line equal to one of ``names`` becomes ``<datapoint_dir>/<name>``. The
120
+ target of an ``EXPORT_LOG`` (the line after it) becomes
121
+ ``<datapoint_dir>/<stem>`` followed by
122
+ :data:`~pyflightstream.cases.workflows._vocabulary.CUMULATIVE_LOG_SUFFIX`,
123
+ because a log exported inside a job holds every point run before it
124
+ (MEASURED); collect writes the point's own log from its slice.
125
+
126
+ Parameters
127
+ ----------
128
+ text : str
129
+ A script text, an exports script or a stop text.
130
+ datapoint_dir : PurePath
131
+ The point's absolute datapoint folder.
132
+ names : iterable of str
133
+ The point's output names as its script names them, relative.
134
+
135
+ Returns
136
+ -------
137
+ str
138
+ The text with those lines replaced; every other line unchanged.
139
+ """
140
+ wanted = set(names)
141
+ lines = text.split("\n")
142
+ out: list[str] = []
143
+ for index, line in enumerate(lines):
144
+ bare = line.strip()
145
+ after_log = index > 0 and lines[index - 1].strip() == "EXPORT_LOG"
146
+ if after_log and bare and not is_absolute_target(bare):
147
+ out.append(str(datapoint_dir / (_log_stem(bare) + CUMULATIVE_LOG_SUFFIX)))
148
+ elif bare in wanted:
149
+ out.append(str(datapoint_dir / bare))
150
+ else:
151
+ out.append(line)
152
+ return "\n".join(out)
153
+
154
+
155
+ def _saved_simulation(point: SchedulePoint) -> str | None:
156
+ """Return the absolute path of the simulation the point saves, or None when it saves none."""
157
+ for name in point.outputs:
158
+ if name.lower().endswith(".fsm"):
159
+ return str(point.datapoint_dir / name)
160
+ return None
161
+
162
+
163
+ def job_schedule(points: Sequence[SchedulePoint], *, deadline_s: float | None) -> dict[str, object]:
164
+ """Return the schedule the job's counter and clock read, every path absolute.
165
+
166
+ Parameters
167
+ ----------
168
+ points : sequence of SchedulePoint
169
+ The job's points in the order the job runs them (``JobPoint``).
170
+ deadline_s : float or None
171
+ The job's elapsed time at which the clock stops the current point
172
+ (the job's walltime minus its margin); None for a job without one.
173
+
174
+ Returns
175
+ -------
176
+ dict
177
+ ``{"schema", "deadline_s", "total_steps", "points": [...]}``, each
178
+ point with ``run_id``, ``datapoint_dir``, ``time_steps``,
179
+ ``first_export_step``, ``exports``, ``stop_text`` and ``fsm``.
180
+ """
181
+ entries: list[dict[str, object]] = []
182
+ for point in points:
183
+ entries.append(
184
+ {
185
+ "run_id": point.run_id,
186
+ "datapoint_dir": str(point.datapoint_dir),
187
+ "time_steps": point.time_steps,
188
+ "first_export_step": point.first_export_step,
189
+ "exports": absolute_output_lines(
190
+ point.action_exports, point.datapoint_dir, point.outputs
191
+ ),
192
+ "stop_text": absolute_output_lines(
193
+ point.stop_text, point.datapoint_dir, point.outputs
194
+ ),
195
+ "fsm": _saved_simulation(point),
196
+ }
197
+ )
198
+ return {
199
+ "schema": SCHEDULE_SCHEMA,
200
+ "deadline_s": deadline_s,
201
+ "total_steps": sum(point.time_steps for point in points),
202
+ "points": entries,
203
+ }
204
+
205
+
206
+ #: The job's counter. Registered FIRST, so it runs before the exports SCRIPT
207
+ #: and the clock of the same step: it decides which point is running and
208
+ #: which of its steps this is, and everything after it reads that.
209
+ COUNTER_TEMPLATE = '''"""Counter of the unsteady solver actions of one pyflightstream grouped job.
210
+
211
+ Written by pyflightstream (FR-B5a, FR-B19). The solver runs this program after
212
+ every unsteady time step of the job and passes it nothing. The job count kept
213
+ in COUNT_FILE is the job's step; the schedule turns it into the point running
214
+ and that point's own step, writes the point's own count where a point run
215
+ alone writes it, and rewrites the exports script with that point's exports
216
+ from its own first export step. At a point's first step it records the point
217
+ as current, empties the exports and the stop scripts, and checks that the
218
+ previous point saved its simulation. Every path is taken from this file's own
219
+ location and from the schedule, never from the working directory.
220
+ """
221
+
222
+ import json
223
+ import time
224
+ from pathlib import Path
225
+
226
+ #: Written by pyflightstream when the job was assembled.
227
+ TIME_ITERATIONS = <TIME_ITERATIONS>
228
+ INTERPRETER = <INTERPRETER>
229
+
230
+ HERE = Path(__file__).resolve().parent
231
+ JOB = HERE.parent
232
+ SCHEDULE = JOB / <SCHEDULE>
233
+ CURRENT = JOB / <CURRENT>
234
+ PROGRESS = JOB / <PROGRESS>
235
+ COUNT_FILE = JOB / <COUNT>
236
+ EXPORTS_FILE = JOB / <EXPORTS>
237
+ STOP_FILE = JOB / <STOP>
238
+ POINT_COUNT = <COUNT>
239
+
240
+
241
+ def read(path, default):
242
+ if not path.is_file():
243
+ return default
244
+ try:
245
+ return json.loads(path.read_text(encoding="utf-8"))
246
+ except ValueError:
247
+ return default
248
+
249
+
250
+ def write(path, text):
251
+ path.parent.mkdir(parents=True, exist_ok=True)
252
+ path.write_text(text, encoding="utf-8", newline="\\n")
253
+
254
+
255
+ def locate(points, count):
256
+ """Return (index, step): the point the job count falls in and its own step."""
257
+ before = 0
258
+ for index, point in enumerate(points):
259
+ if count <= before + int(point["time_steps"]):
260
+ return index, count - before
261
+ before += int(point["time_steps"])
262
+ last = len(points) - 1
263
+ return last, count - (before - int(points[last]["time_steps"]))
264
+
265
+
266
+ def start_point(points, index, now):
267
+ """The point's first step: record it, empty both scripts, check the previous save."""
268
+ point = points[index]
269
+ write(EXPORTS_FILE, "")
270
+ write(STOP_FILE, "")
271
+ current = {
272
+ "point": index + 1,
273
+ "run_id": point["run_id"],
274
+ "datapoint_dir": point["datapoint_dir"],
275
+ "first_export_step": point["first_export_step"],
276
+ "exports": point["exports"],
277
+ "stop_text": point["stop_text"],
278
+ "started_at": now,
279
+ }
280
+ write(CURRENT, json.dumps(current, indent=2))
281
+ if index == 0:
282
+ return None
283
+ saved = points[index - 1]["fsm"]
284
+ if saved is not None and not Path(saved).is_file():
285
+ return {"previous": index, "point": index + 1, "missing": saved}
286
+ return None
287
+
288
+
289
+ def main():
290
+ points = read(SCHEDULE, {})["points"]
291
+ count = int(read(COUNT_FILE, {"count": 0})["count"]) + 1
292
+ write(COUNT_FILE, json.dumps({"count": count}))
293
+ index, step = locate(points, count)
294
+ point = points[index]
295
+ progress = read(PROGRESS, {})
296
+ mismatches = list(progress.get("mismatches", []))
297
+ if step == 1:
298
+ found = start_point(points, index, time.time())
299
+ if found is not None:
300
+ mismatches.append(found)
301
+ write(Path(point["datapoint_dir"]) / POINT_COUNT, json.dumps({"count": step}))
302
+ first = point["first_export_step"]
303
+ exporting = first is not None and step >= int(first)
304
+ write(EXPORTS_FILE, point["exports"] if exporting else "")
305
+ progress = {
306
+ "point": index + 1,
307
+ "run_id": point["run_id"],
308
+ "step": step,
309
+ "job_count": count,
310
+ "mismatch": bool(mismatches),
311
+ "mismatches": mismatches,
312
+ }
313
+ write(PROGRESS, json.dumps(progress, indent=2))
314
+ return 0
315
+
316
+
317
+ if __name__ == "__main__":
318
+ raise SystemExit(main())
319
+ '''
320
+
321
+ #: The job's clock (D3). Its start is its first invocation; when the job's
322
+ #: elapsed time reaches the schedule's deadline it writes the CURRENT point's
323
+ #: stop text into the stop script, once, and records where it stopped in the
324
+ #: job's state and in the point's own, in the shape a point run alone leaves.
325
+ CLOCK_TEMPLATE = '''"""Wall clock of one pyflightstream grouped job.
326
+
327
+ Written by pyflightstream (FR-B5a, D3). The solver cannot be asked how long
328
+ the job has been going, so this program keeps its own state: the first
329
+ invocation writes the start, every later one asks whether the job's elapsed
330
+ time reached the schedule's deadline. When it does, the CURRENT point's stop
331
+ text goes into the stop script, once, and the point's own clock state records
332
+ the step it stopped at. Every path is taken from this file's own location and
333
+ from the schedule and the counter's current point, never from the working
334
+ directory.
335
+ """
336
+
337
+ import json
338
+ import time
339
+ from pathlib import Path
340
+
341
+ INTERPRETER = <INTERPRETER>
342
+
343
+ HERE = Path(__file__).resolve().parent
344
+ JOB = HERE.parent
345
+ SCHEDULE = JOB / <SCHEDULE>
346
+ CURRENT = JOB / <CURRENT>
347
+ PROGRESS = JOB / <PROGRESS>
348
+ STATE = JOB / <STATE>
349
+ STOP_FILE = JOB / <STOP>
350
+ POINT_STATE = <STATE>
351
+
352
+
353
+ def read(path, default):
354
+ if not path.is_file():
355
+ return default
356
+ try:
357
+ return json.loads(path.read_text(encoding="utf-8"))
358
+ except ValueError:
359
+ return default
360
+
361
+
362
+ def write(path, text):
363
+ path.parent.mkdir(parents=True, exist_ok=True)
364
+ path.write_text(text, encoding="utf-8", newline="\\n")
365
+
366
+
367
+ def main():
368
+ deadline = read(SCHEDULE, {}).get("deadline_s")
369
+ current = read(CURRENT, None)
370
+ step = int(read(PROGRESS, {}).get("step", 0))
371
+ now = time.time()
372
+ state = {"started_at": None, "steps": 0, "fired": False}
373
+ state.update(read(STATE, {}))
374
+ if state["started_at"] is None:
375
+ state["started_at"] = now
376
+ state["steps"] = int(state["steps"]) + 1
377
+ elapsed = now - float(state["started_at"])
378
+ state["elapsed_s"] = elapsed
379
+ fire = deadline is not None and not state["fired"] and elapsed >= float(deadline)
380
+ if fire and current is not None:
381
+ write(STOP_FILE, current["stop_text"])
382
+ state["fired"] = True
383
+ state["stopped_at"] = {
384
+ "step": state["steps"], "elapsed_s": elapsed, "point": current["point"]
385
+ }
386
+ write(STATE, json.dumps(state, indent=2))
387
+ if current is None:
388
+ return 0
389
+ own_path = Path(current["datapoint_dir"]) / POINT_STATE
390
+ own = read(own_path, {"fired": False})
391
+ own["started_at"] = current["started_at"]
392
+ own["steps"] = step
393
+ own["elapsed_s"] = now - float(current["started_at"])
394
+ if fire:
395
+ own["fired"] = True
396
+ own["stopped_at"] = {"step": step, "elapsed_s": own["elapsed_s"]}
397
+ write(own_path, json.dumps(own, indent=2))
398
+ return 0
399
+
400
+
401
+ if __name__ == "__main__":
402
+ raise SystemExit(main())
403
+ '''
404
+
405
+
406
+ def _filled(template: str, values: dict[str, object]) -> str:
407
+ """Return ``template`` with each ``<NAME>`` replaced by the repr of its value."""
408
+ text = template
409
+ for name, value in values.items():
410
+ text = text.replace(f"<{name}>", repr(value))
411
+ return text
412
+
413
+
414
+ def render_job_counter_program(*, total_steps: int, interpreter: str) -> str:
415
+ """Return the job's counter program, written where the counter registration points.
416
+
417
+ Parameters
418
+ ----------
419
+ total_steps : int
420
+ The time steps of every point of the job, summed: the local progress
421
+ bar reads ``TIME_ITERATIONS`` off the program as it reads a point's.
422
+ interpreter : str
423
+ The Python the registration line names, recorded in the program.
424
+
425
+ Returns
426
+ -------
427
+ str
428
+ The program text.
429
+ """
430
+ return _filled(
431
+ COUNTER_TEMPLATE,
432
+ {
433
+ "TIME_ITERATIONS": int(total_steps),
434
+ "INTERPRETER": interpreter,
435
+ "SCHEDULE": JOB_SCHEDULE,
436
+ "CURRENT": JOB_CURRENT,
437
+ "PROGRESS": JOB_PROGRESS,
438
+ "COUNT": UNSTEADY_ACTION_COUNT,
439
+ "EXPORTS": UNSTEADY_ACTION_SCRIPT,
440
+ "STOP": WALLTIME_STOP_SCRIPT,
441
+ },
442
+ )
443
+
444
+
445
+ def render_job_clock_program(*, interpreter: str) -> str:
446
+ """Return the job's clock program, written where the clock registration points.
447
+
448
+ Parameters
449
+ ----------
450
+ interpreter : str
451
+ The Python the registration line names, recorded in the program.
452
+
453
+ Returns
454
+ -------
455
+ str
456
+ The program text; its deadline is read from the schedule.
457
+ """
458
+ return _filled(
459
+ CLOCK_TEMPLATE,
460
+ {
461
+ "INTERPRETER": interpreter,
462
+ "SCHEDULE": JOB_SCHEDULE,
463
+ "CURRENT": JOB_CURRENT,
464
+ "PROGRESS": JOB_PROGRESS,
465
+ "STATE": WALLTIME_CLOCK_STATE,
466
+ "STOP": WALLTIME_STOP_SCRIPT,
467
+ },
468
+ )