fullflow 2.0.3__tar.gz → 3.0.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 (119) hide show
  1. {fullflow-2.0.3 → fullflow-3.0.0}/CHANGELOG.md +19 -0
  2. {fullflow-2.0.3 → fullflow-3.0.0}/PKG-INFO +1 -1
  3. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/0function_lookup.py +8 -2
  4. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/2compressible_flow.py +5 -5
  5. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/3custom_component.py +3 -2
  6. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/4cavitating_venturi.py +7 -1
  7. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/5heat_exchanger.py +11 -12
  8. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/8turbopump.py +5 -8
  9. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/9equilibrium_nozzle.py +15 -17
  10. {fullflow-2.0.3 → fullflow-3.0.0}/examples/testing/1test_data_anchoring.py +15 -7
  11. {fullflow-2.0.3 → fullflow-3.0.0}/examples/testing/2sensor_events.py +10 -2
  12. {fullflow-2.0.3 → fullflow-3.0.0}/examples/testing/3sequences_and_commands.py +10 -2
  13. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/10custom_component.py +12 -3
  14. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/11heat_transfer.py +12 -4
  15. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/12heat_exchanger.py +23 -17
  16. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/13force_steady_heat_transfer.py +19 -11
  17. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/14force_steady_fluid.py +23 -12
  18. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/15piston_cylinder.py +15 -16
  19. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/16balloon.py +13 -5
  20. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/17relief_valve.py +21 -12
  21. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/18combustion_nozzle.py +19 -10
  22. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/19cavitating_venturi.py +35 -28
  23. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/1simple_pipe.py +13 -4
  24. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/20gas_turbine.py +13 -6
  25. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/21heatsink_tca.py +24 -18
  26. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/22water_hammer.py +27 -35
  27. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/23pid_throttle.py +35 -37
  28. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/24sudden_valve_opening.py +14 -18
  29. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/25engine_startup.py +25 -22
  30. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/2node_inertia.py +12 -4
  31. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/3shock_tube.py +11 -3
  32. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/4copv_blowdown.py +15 -12
  33. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/5bang_bang_control.py +20 -13
  34. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/6pump_transient.py +27 -38
  35. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/7flow_mixer.py +13 -4
  36. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/8flow_splitter.py +13 -4
  37. {fullflow-2.0.3 → fullflow-3.0.0}/examples/transient/9model_options.py +21 -21
  38. {fullflow-2.0.3 → fullflow-3.0.0}/pyproject.toml +1 -1
  39. {fullflow-2.0.3 → fullflow-3.0.0}/pyproject.toml.orig +1 -1
  40. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Exports/HDF5.py +8 -105
  41. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/balance_filtering.py +1 -8
  42. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/equations.py +5 -47
  43. fullflow-3.0.0/src/fullflow/Solvers/steady_state/__init__.py +5 -0
  44. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/steady_state/diagnostics.py +4 -24
  45. fullflow-3.0.0/src/fullflow/Solvers/steady_state/evaluation.py +87 -0
  46. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/steady_state/models.py +6 -41
  47. fullflow-3.0.0/src/fullflow/Solvers/steady_state/operations.py +322 -0
  48. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/steady_state/runtime.py +108 -85
  49. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/steady_state/settings.py +3 -19
  50. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/steady_state/solver.py +14 -288
  51. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/steady_state/statistics.py +2 -14
  52. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/transient/diagnostics.py +2 -16
  53. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/transient/evaluation.py +25 -30
  54. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/transient/models.py +4 -29
  55. fullflow-3.0.0/src/fullflow/Solvers/transient/newton.py +227 -0
  56. fullflow-3.0.0/src/fullflow/Solvers/transient/operations.py +807 -0
  57. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/transient/results.py +2 -15
  58. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/transient/runtime.py +182 -214
  59. fullflow-3.0.0/src/fullflow/Solvers/transient/settings.py +36 -0
  60. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/transient/solver.py +7 -160
  61. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Balance.py +3 -39
  62. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Component.py +35 -139
  63. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/Actuators.py +3 -27
  64. fullflow-3.0.0/src/fullflow/System/Components/Composition.py +127 -0
  65. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/CompressibleFlow.py +16 -81
  66. fullflow-3.0.0/src/fullflow/System/Components/Controllers.py +270 -0
  67. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/ConvectionCoefficients.py +40 -160
  68. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/FrictionFactors.py +16 -63
  69. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/GeneralFlow.py +49 -256
  70. fullflow-3.0.0/src/fullflow/System/Components/HeatTransfer.py +231 -0
  71. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/Lookup.py +23 -218
  72. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/Maps.py +51 -73
  73. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/Nodes.py +19 -115
  74. fullflow-3.0.0/src/fullflow/System/Components/RocketPerformance.py +56 -0
  75. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/Sensor.py +16 -84
  76. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/Sequence.py +10 -111
  77. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/Turbomachinery.py +24 -108
  78. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Model.py +5 -40
  79. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Network.py +5 -55
  80. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/State.py +31 -131
  81. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/__init__.py +1 -1
  82. {fullflow-2.0.3 → fullflow-3.0.0}/tests/test_imports.py +1 -1
  83. fullflow-2.0.3/src/fullflow/Solvers/steady_state/__init__.py +0 -23
  84. fullflow-2.0.3/src/fullflow/Solvers/steady_state/evaluation.py +0 -149
  85. fullflow-2.0.3/src/fullflow/Solvers/steady_state/operations.py +0 -363
  86. fullflow-2.0.3/src/fullflow/Solvers/transient/operations.py +0 -499
  87. fullflow-2.0.3/src/fullflow/Solvers/transient/settings.py +0 -70
  88. fullflow-2.0.3/src/fullflow/System/Components/Composition.py +0 -214
  89. fullflow-2.0.3/src/fullflow/System/Components/Controllers.py +0 -559
  90. fullflow-2.0.3/src/fullflow/System/Components/HeatTransfer.py +0 -355
  91. fullflow-2.0.3/src/fullflow/System/Components/RocketPerformance.py +0 -92
  92. {fullflow-2.0.3 → fullflow-3.0.0}/LICENSE +0 -0
  93. {fullflow-2.0.3 → fullflow-3.0.0}/README.md +0 -0
  94. {fullflow-2.0.3 → fullflow-3.0.0}/THIRD_PARTY_LICENSES.md +0 -0
  95. {fullflow-2.0.3 → fullflow-3.0.0}/docs/system_reference.md +0 -0
  96. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/0state_basics.py +0 -0
  97. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/1state_bounds_tracking.py +0 -0
  98. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/2balance_basic.py +0 -0
  99. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/3balance_multiple.py +0 -0
  100. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/4composition_mixer.py +0 -0
  101. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/5composition_splitter.py +0 -0
  102. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/6lookup_function.py +0 -0
  103. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/7lookup_class_chaining.py +0 -0
  104. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/8map_manual.py +0 -0
  105. {fullflow-2.0.3 → fullflow-3.0.0}/examples/general/9map_hdf5.py +0 -0
  106. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/1simple_pipe.py +0 -0
  107. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/6flow_splitter.py +0 -0
  108. {fullflow-2.0.3 → fullflow-3.0.0}/examples/steady_state/7flow_mixer.py +0 -0
  109. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Exceptions.py +0 -0
  110. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Exports/EXPORTS.md +0 -0
  111. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Exports/__init__.py +0 -0
  112. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/STEADY_STATE_SOLVER.md +0 -0
  113. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/TRANSIENT_SOLVER.md +0 -0
  114. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/__init__.py +0 -0
  115. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/steady_state/results.py +0 -0
  116. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/Solvers/transient/__init__.py +0 -0
  117. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/Components/__init__.py +0 -0
  118. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/SYSTEM.md +0 -0
  119. {fullflow-2.0.3 → fullflow-3.0.0}/src/fullflow/System/__init__.py +0 -0
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.0.0
4
+
5
+ FullFlow 3.0.0 focuses on solver performance, transient robustness, consistent
6
+ examples, and concise user-facing documentation.
7
+
8
+ ### Solver performance
9
+
10
+ * Added a safeguarded modified-Newton transient solver with numerical Jacobian
11
+ construction, Broyden updates, backtracking, and automatic SciPy fallback.
12
+ * Added guarded Jacobian reuse between compatible transient timesteps.
13
+ * Added accepted-step prediction and validation to improve transient initial
14
+ guesses without reusing stale state or control information.
15
+ * Reduced repeated state discovery, allocation, conversion, and component
16
+ evaluation work in steady-state and transient residual calculations.
17
+ * Added compact state snapshots and cached runtime metadata with network-version
18
+ invalidation.
19
+ * Improved invalid-trial handling so temporary property-evaluation failures can
20
+ be rejected without immediately terminating a nonlinear solve.
21
+
3
22
  ## 2.0.3
4
23
 
5
24
  ### Sequence inputs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fullflow
3
- Version: 2.0.3
3
+ Version: 3.0.0
4
4
  Summary: Python-native fluid, thermal, propulsion, control, and transient network simulation.
5
5
  Keywords: fluid-dynamics,fluid-network,network-analysis,thermodynamics,thermal-analysis,heat-transfer,propulsion,rocket-propulsion,rocket-engine,compressible-flow,turbomachinery,control-systems,transient-simulation,simulation,engineering,scientific-computing
6
6
  Author: Saaketh Ramoju
@@ -39,6 +39,13 @@ import math
39
39
  from fullflow import *
40
40
 
41
41
 
42
+ # -----------------------------------------------------------------------------
43
+ # Run options
44
+ # -----------------------------------------------------------------------------
45
+
46
+ filename = '0function_lookup'
47
+
48
+
42
49
  # -----------------------------------------------------------------------------
43
50
  # User-defined callable lookup
44
51
  # -----------------------------------------------------------------------------
@@ -141,9 +148,8 @@ ColumnDesign.track("Applied Stress [Pa]", AppliedStress)
141
148
  # Solve
142
149
  # -----------------------------------------------------------------------------
143
150
 
144
- filename = "0function_lookup"
145
151
 
146
152
  SteadyState(ColumnDesign).solve(
147
153
  verbose=True,
148
154
  filename=filename,
149
- )
155
+ )
@@ -74,6 +74,7 @@ Demonstrates
74
74
  """
75
75
 
76
76
  import numpy as np
77
+ from scipy.constants import *
77
78
 
78
79
  from fullflow import *
79
80
  from thermoprop import *
@@ -125,11 +126,10 @@ NodeFluid = Lookup(
125
126
  # These values are only the initial geometry guesses / fixed downstream geometry.
126
127
  # -----------------------------------------------------------------------------
127
128
 
128
- IN_TO_M = 0.0254
129
129
 
130
- D_diff_in = 0.75 * IN_TO_M
131
- D_diff_out = 1.00 * IN_TO_M
132
- D_nozzle = 0.75 * IN_TO_M
130
+ D_diff_in = 0.75 * inch
131
+ D_diff_out = 1.00 * inch
132
+ D_nozzle = 0.75 * inch
133
133
 
134
134
  A_diff_in = np.pi * D_diff_in**2 / 4.0
135
135
  A_diff_out = np.pi * D_diff_out**2 / 4.0
@@ -226,4 +226,4 @@ InletBalance = Balance(
226
226
  # Solve network
227
227
  # -----------------------------------------------------------------------------
228
228
 
229
- SteadyState(CompressibleNetwork).solve(verbose=True)
229
+ SteadyState(CompressibleNetwork).solve(verbose=True)
@@ -71,6 +71,7 @@ Demonstrates
71
71
  """
72
72
 
73
73
  import numpy as np
74
+ from scipy.constants import *
74
75
 
75
76
  from fullflow import *
76
77
  from thermoprop import *
@@ -235,7 +236,7 @@ class CustomPump(Component):
235
236
  density: State,
236
237
  upstream_pressure: State,
237
238
  discharge_pressure: State,
238
- gravitational_acceleration: float = 9.80665
239
+ gravitational_acceleration: float = g
239
240
  ):
240
241
  # The balances property below reads pressure_error. Initialize it once
241
242
  # so the component is safe to inspect before the first evaluate_states()
@@ -531,4 +532,4 @@ LOXPumpSystem.track("Pressure Rise [psid]", dP/6894.76)
531
532
  # verbose=True prints the solver summary and final network solution.
532
533
  # -----------------------------------------------------------------------------
533
534
 
534
- SteadyState(LOXPumpSystem).solve(verbose=True)
535
+ SteadyState(LOXPumpSystem).solve(verbose=True)
@@ -96,13 +96,19 @@ from fullplot import Axis, generate_map
96
96
  from thermoprop import *
97
97
 
98
98
 
99
+ # -----------------------------------------------------------------------------
100
+ # Run options
101
+ # -----------------------------------------------------------------------------
102
+
103
+ filename = '4cavitating_venturi'
104
+
105
+
99
106
  # -----------------------------------------------------------------------------
100
107
  # Map file settings
101
108
  # -----------------------------------------------------------------------------
102
109
  # The chamber gas property map is expected to live in RP1_LOX.h5. The map is
103
110
  # generated separately from the solve because equilibrium calculations are much
104
111
  # more expensive than interpolation during each network evaluation.
105
- filename = "4cavitating_venturi"
106
112
 
107
113
 
108
114
  # -----------------------------------------------------------------------------
@@ -104,6 +104,7 @@ Approximate cross section:
104
104
  """
105
105
 
106
106
  import numpy as np
107
+ from scipy.constants import *
107
108
 
108
109
  from fullflow import *
109
110
  from thermoprop import *
@@ -233,22 +234,21 @@ gasoline_specific_heat_cp = (
233
234
  # The current network uses three hydraulic tube elements per side, so Nseg is 3.
234
235
  # -----------------------------------------------------------------------------
235
236
 
236
- IN_TO_M = 0.0254
237
237
 
238
238
  # Total heat-exchanger length and length of each model segment.
239
- L_total = 40.0 * IN_TO_M
239
+ L_total = 40.0 * inch
240
240
  Nseg = 3
241
241
  L = L_total / Nseg
242
242
 
243
243
  # Inner-tube inside diameter. This is the hot-fluid flow diameter.
244
- D_inner = 0.50 * IN_TO_M
244
+ D_inner = 0.50 * inch
245
245
 
246
246
  # Tube wall thickness and resulting tube outside diameter.
247
- wall_thickness = 0.035 * IN_TO_M
247
+ wall_thickness = 0.035 * inch
248
248
  D_tube_outer = D_inner + 2.0 * wall_thickness
249
249
 
250
250
  # Outer diameter of the annulus. Coolant flows between D_tube_outer and this ID.
251
- D_annulus_outer = 0.875 * IN_TO_M
251
+ D_annulus_outer = 0.875 * inch
252
252
 
253
253
  # Basic geometry check to avoid a negative annular area.
254
254
  if D_tube_outer >= D_annulus_outer:
@@ -952,15 +952,14 @@ CoolantNode2.heat_rate = -Coolant2Solid1Convection.heat_rate
952
952
  # exchanger.
953
953
  # -----------------------------------------------------------------------------
954
954
 
955
- PA_TO_PSIA = 1.0 / 6894.757293
956
955
 
957
- HeatExchanger.track("Hot Fluid Source Pressure [psia]", hot_fluid_source_pressure * PA_TO_PSIA)
958
- HeatExchanger.track("Hot Fluid Node 1 Pressure [psia]", hot_fluid_node1_pressure * PA_TO_PSIA)
959
- HeatExchanger.track("Hot Fluid Node 2 Pressure [psia]", hot_fluid_node2_pressure * PA_TO_PSIA)
956
+ HeatExchanger.track("Hot Fluid Source Pressure [psia]", hot_fluid_source_pressure * (1.0 / psi))
957
+ HeatExchanger.track("Hot Fluid Node 1 Pressure [psia]", hot_fluid_node1_pressure * (1.0 / psi))
958
+ HeatExchanger.track("Hot Fluid Node 2 Pressure [psia]", hot_fluid_node2_pressure * (1.0 / psi))
960
959
 
961
- HeatExchanger.track("Coolant Source Pressure [psia]", CoolantSource.pressure * PA_TO_PSIA)
962
- HeatExchanger.track("Coolant Node 1 Pressure [psia]", CoolantNode1Fluid.pressure * PA_TO_PSIA)
963
- HeatExchanger.track("Coolant Node 2 Pressure [psia]", CoolantNode2Fluid.pressure * PA_TO_PSIA)
960
+ HeatExchanger.track("Coolant Source Pressure [psia]", CoolantSource.pressure * (1.0 / psi))
961
+ HeatExchanger.track("Coolant Node 1 Pressure [psia]", CoolantNode1Fluid.pressure * (1.0 / psi))
962
+ HeatExchanger.track("Coolant Node 2 Pressure [psia]", CoolantNode2Fluid.pressure * (1.0 / psi))
964
963
 
965
964
  HeatExchanger.track("Hot Fluid Source Temperature [K]", hot_fluid_source_temperature)
966
965
  HeatExchanger.track("Hot Fluid Node 1 Temperature [K]", hot_fluid_node1_temperature)
@@ -115,6 +115,7 @@ user-generated performance maps rather than detailed hardware-calibrated maps.
115
115
  """
116
116
 
117
117
  import numpy as np
118
+ from scipy.constants import *
118
119
 
119
120
  from fullflow import *
120
121
  from fullplot import Axis, generate_map
@@ -132,8 +133,6 @@ Turbopump = Network("Turbopump")
132
133
  # Units
133
134
  # -----------------------------------------------------------------------------
134
135
 
135
- bar = 100000.0
136
-
137
136
 
138
137
  # -----------------------------------------------------------------------------
139
138
  # Design point
@@ -211,8 +210,6 @@ Preburner = Equilibrium(
211
210
 
212
211
  LOX = Propellant("lox", temperature=90)
213
212
 
214
- g = 9.80665
215
-
216
213
  LOXPumpDensity = State(LOX.density)
217
214
  LOXPumpDesignVolumetricFlow = LOXPumpDesignMassFlow / LOX.density
218
215
  LOXPumpDesignHead = (LOXPumpDesignDischargePressure - LOXPumpDesignInletPressure) / (LOX.density * g)
@@ -255,8 +252,9 @@ OxRichTurbineDesignMassFlow = LOXPumpDesignShaftPower / (OxRichTurbineDesignEffi
255
252
 
256
253
  turbopump_map_filename = "8turbopump"
257
254
 
255
+ # Set this to True to generate both maps in 8turbopump.h5 before loading them.
256
+ generate_maps = False
258
257
 
259
- '''
260
258
  # -----------------------------------------------------------------------------
261
259
  # Turbine map generation
262
260
  # -----------------------------------------------------------------------------
@@ -327,7 +325,7 @@ def turbine_map_point(
327
325
  }
328
326
 
329
327
 
330
- generate_map(
328
+ generate_maps and generate_map(
331
329
  turbopump_map_filename,
332
330
  group="turbine",
333
331
  axes=[
@@ -421,7 +419,7 @@ def lox_pump_map_point(rotor_speed, volumetric_flow):
421
419
  }
422
420
 
423
421
 
424
- generate_map(
422
+ generate_maps and generate_map(
425
423
  turbopump_map_filename,
426
424
  group="lox_pump",
427
425
  axes=[
@@ -452,7 +450,6 @@ generate_map(
452
450
  overwrite=True,
453
451
  raise_errors=True,
454
452
  )
455
- '''
456
453
 
457
454
 
458
455
  # -----------------------------------------------------------------------------
@@ -97,6 +97,7 @@ from concurrent.futures import ProcessPoolExecutor
97
97
  import os
98
98
 
99
99
  import numpy as np
100
+ from scipy.constants import *
100
101
 
101
102
  from fullflow import *
102
103
  from fullplot import Axis, generate_map
@@ -107,7 +108,6 @@ from thermoprop import *
107
108
  # Constants and script options
108
109
  # ---------------------------------------------------------------------------
109
110
 
110
- psia_to_pa = 6894.76
111
111
 
112
112
  # All generated map groups are stored in this one HDF5 file.
113
113
  filename = "9equilibrium_nozzle"
@@ -275,7 +275,6 @@ def rp1_lox_sp_map(pressure, entropy, mixture_ratio, guess_temperature):
275
275
  "gas_constant": eq.gas_constant,
276
276
  "density": eq.density,
277
277
  "enthalpy": eq.enthalpy,
278
- "entropy": eq.entropy,
279
278
  "speed_of_sound": eq.speed_of_sound,
280
279
  "temperature": eq.temperature,
281
280
  }
@@ -312,7 +311,6 @@ def rp1_lox_tp_map(pressure, temperature, mixture_ratio):
312
311
  "enthalpy": eq.enthalpy,
313
312
  "entropy": eq.entropy,
314
313
  "speed_of_sound": eq.speed_of_sound,
315
- "temperature": eq.temperature,
316
314
  }
317
315
 
318
316
 
@@ -327,7 +325,7 @@ if __name__ == "__main__":
327
325
  # -----------------------------------------------------------------------
328
326
 
329
327
  mixture_ratio = State(2.3)
330
- injector_face_pressure = State(400 * psia_to_pa)
328
+ injector_face_pressure = State(400 * psi)
331
329
  ambient_pressure = State(101325.0)
332
330
 
333
331
  fuel = Propellant("rp-1", temperature=298.15)
@@ -373,8 +371,8 @@ if __name__ == "__main__":
373
371
  axes=[
374
372
  Axis.linear(
375
373
  "pressure",
376
- start=385 * psia_to_pa,
377
- stop=405 * psia_to_pa,
374
+ start=385 * psi,
375
+ stop=405 * psi,
378
376
  count=41,
379
377
  units="Pa",
380
378
  ),
@@ -408,8 +406,8 @@ if __name__ == "__main__":
408
406
  axes=[
409
407
  Axis.log(
410
408
  "pressure",
411
- start=1 * psia_to_pa,
412
- stop=500 * psia_to_pa,
409
+ start=1 * psi,
410
+ stop=500 * psi,
413
411
  count=18,
414
412
  units="Pa",
415
413
  ),
@@ -451,12 +449,12 @@ if __name__ == "__main__":
451
449
 
452
450
  # Chamber pressure and temperature are solved by the combustion chamber
453
451
  # Volume. These are only initial guesses.
454
- chamber_pressure = State(393 * psia_to_pa)
452
+ chamber_pressure = State(393 * psi)
455
453
  chamber_temperature = State(3458.0)
456
454
 
457
455
  # Throat and exit pressures are also solved by the network.
458
- throat_pressure = State(300 * psia_to_pa)
459
- exit_pressure = State(10 * psia_to_pa)
456
+ throat_pressure = State(300 * psi)
457
+ exit_pressure = State(10 * psi)
460
458
 
461
459
 
462
460
  # -----------------------------------------------------------------------
@@ -689,11 +687,11 @@ if __name__ == "__main__":
689
687
  # Tracked outputs
690
688
  # -----------------------------------------------------------------------
691
689
 
692
- EquilibriumNozzle.track("Injector Face Pressure [psia]", InjectorFace.pressure / psia_to_pa)
693
- EquilibriumNozzle.track("Chamber Pressure [psia]", chamber_pressure / psia_to_pa)
694
- EquilibriumNozzle.track("Throat Pressure [psia]", throat_pressure / psia_to_pa)
695
- EquilibriumNozzle.track("Exit Pressure [psia]", exit_pressure / psia_to_pa)
696
- EquilibriumNozzle.track("Ambient Pressure [psia]", ambient_pressure / psia_to_pa)
690
+ EquilibriumNozzle.track("Injector Face Pressure [psia]", InjectorFace.pressure / psi)
691
+ EquilibriumNozzle.track("Chamber Pressure [psia]", chamber_pressure / psi)
692
+ EquilibriumNozzle.track("Throat Pressure [psia]", throat_pressure / psi)
693
+ EquilibriumNozzle.track("Exit Pressure [psia]", exit_pressure / psi)
694
+ EquilibriumNozzle.track("Ambient Pressure [psia]", ambient_pressure / psi)
697
695
 
698
696
  EquilibriumNozzle.track("Injector Face Temperature [K]", InjectorFace.temperature)
699
697
  EquilibriumNozzle.track("Chamber Temperature [K]", chamber_temperature)
@@ -736,4 +734,4 @@ if __name__ == "__main__":
736
734
 
737
735
  print(f"Predicted Line Loss: {ratio_predicted.value:.3f}")
738
736
  print(f"Rayleigh Line Loss: {ratio_rayleigh.value:.3f}")
739
- print(f"Empirical Loss: {ratio_empirical:.3f}")
737
+ print(f"Empirical Loss: {ratio_empirical:.3f}")
@@ -3,6 +3,7 @@ import math
3
3
 
4
4
  import h5py
5
5
  import numpy as np
6
+ from scipy.constants import *
6
7
 
7
8
  from fullflow import *
8
9
  import fullplot as fplt
@@ -51,6 +52,14 @@ loss, heat input, etc.
51
52
  """
52
53
 
53
54
 
55
+ # -----------------------------------------------------------------------------
56
+ # Run options
57
+ # -----------------------------------------------------------------------------
58
+
59
+ dt = 0.02
60
+ t_final = 6.5
61
+
62
+
54
63
  # ---------------------------------------------------------------------------
55
64
  # User options
56
65
  # ---------------------------------------------------------------------------
@@ -63,7 +72,6 @@ HERE = Path(__file__).resolve().parent
63
72
  TEST_DATA_FILE = HERE / "test_data_anchoring_hotfire.h5"
64
73
  RESULT_FILE = HERE / "test_data_anchoring_result.h5"
65
74
 
66
- psia_to_pa = 6894.76
67
75
 
68
76
 
69
77
  # ---------------------------------------------------------------------------
@@ -112,7 +120,7 @@ def generate_test_data(filename):
112
120
  density = 810.0
113
121
  area = (math.pi / 4.0) * (0.25 / 39.37) ** 2
114
122
  true_cd = 0.18 + 0.54 * run_level
115
- pressure_drop = np.maximum((ftpt - fipt) * psia_to_pa, 0.0)
123
+ pressure_drop = np.maximum((ftpt - fipt) * psi, 0.0)
116
124
  fuel_mdot = true_cd * area * np.sqrt(2.0 * density * pressure_drop)
117
125
  fuel_mdot += rng.normal(0.0, 0.006, len(time))
118
126
  fuel_mdot = np.maximum(fuel_mdot, 0.0)
@@ -155,8 +163,8 @@ fflow = data.trace(y="FUEL_MDOT", x=time, name="Fuel Flow Test Data", role="data
155
163
 
156
164
  # A user can process a test-data trace before anchoring to it. The filtered trace
157
165
  # keeps the same role as the source trace, so it is still valid Sensor.data.
158
- ftpt = ftpt_raw.filter("moving_average", window=0.04) * psia_to_pa
159
- fipt = fipt_raw.filter("moving_average", window=0.04) * psia_to_pa
166
+ ftpt = ftpt_raw.filter("moving_average", window=0.04) * psi
167
+ fipt = fipt_raw.filter("moving_average", window=0.04) * psi
160
168
 
161
169
  # All three traces share this TimeAxis, so one window selects the useful part of
162
170
  # the test for every attached trace.
@@ -181,7 +189,7 @@ fflow_redline = fplt.Trace.constant(
181
189
  # Plot the imported data before building the model. This is the normal first
182
190
  # sanity check when working with test data.
183
191
  data.plot(
184
- y=[ftpt / psia_to_pa, fipt / psia_to_pa],
192
+ y=[ftpt / psi, fipt / psi],
185
193
  y2=[fflow, fflow_warning, fflow_redline],
186
194
  xlabel="Time [s]",
187
195
  ylabel="Pressure [psia]",
@@ -255,8 +263,8 @@ Test.track("Estimated Fuel Cd", Line.discharge_coefficient)
255
263
  # ---------------------------------------------------------------------------
256
264
 
257
265
  Transient(Test).solve(
258
- dt=0.02,
259
- t_final=6.5,
266
+ dt=dt,
267
+ t_final=t_final,
260
268
  verbose=True,
261
269
  filename=str(RESULT_FILE),
262
270
  )
@@ -32,6 +32,14 @@ Sequence commands and aborts can respond to those events.
32
32
  """
33
33
 
34
34
 
35
+ # -----------------------------------------------------------------------------
36
+ # Run options
37
+ # -----------------------------------------------------------------------------
38
+
39
+ dt = 0.02
40
+ t_final = 5.2
41
+
42
+
35
43
  HERE = Path(__file__).resolve().parent
36
44
  RESULT_FILE = HERE / "sensor_events_result.h5"
37
45
 
@@ -109,8 +117,8 @@ Test.track("CHPT", chamber_pressure)
109
117
  # ---------------------------------------------------------------------------
110
118
 
111
119
  Transient(Test).solve(
112
- dt=0.02,
113
- t_final=5.2,
120
+ dt=dt,
121
+ t_final=t_final,
114
122
  verbose=True,
115
123
  filename=str(RESULT_FILE),
116
124
  )
@@ -35,6 +35,14 @@ combustion, nozzles, turbomachinery, etc. The Sequence API is the same.
35
35
  """
36
36
 
37
37
 
38
+ # -----------------------------------------------------------------------------
39
+ # Run options
40
+ # -----------------------------------------------------------------------------
41
+
42
+ dt = 0.01
43
+ t_final = 5.0
44
+
45
+
38
46
  HERE = Path(__file__).resolve().parent
39
47
  RESULT_FILE = HERE / "sequence_commands_abort_result.h5"
40
48
 
@@ -182,8 +190,8 @@ Test.track("Chamber Pressure", chamber_pressure)
182
190
  # ---------------------------------------------------------------------------
183
191
 
184
192
  Transient(Test).solve(
185
- dt=0.01,
186
- t_final=5.0,
193
+ dt=dt,
194
+ t_final=t_final,
187
195
  verbose=True,
188
196
  filename=str(RESULT_FILE),
189
197
  )
@@ -48,6 +48,15 @@ monotonically drains.
48
48
  from fullflow import *
49
49
 
50
50
 
51
+ # -----------------------------------------------------------------------------
52
+ # Run options
53
+ # -----------------------------------------------------------------------------
54
+
55
+ dt = 0.05
56
+ t_final = 20.0
57
+ filename = '10custom_component'
58
+
59
+
51
60
  # ---------------------------------------------------------------------------
52
61
  # Custom component 1: tank dynamics
53
62
  # ---------------------------------------------------------------------------
@@ -159,8 +168,8 @@ TankNetwork.track("Outlet Flow", outlet_flow)
159
168
  # Transient solve
160
169
  # ---------------------------------------------------------------------------
161
170
  Transient(TankNetwork).solve(
162
- dt=0.05,
163
- t_final=20.0,
164
- filename="10custom_component",
171
+ dt=dt,
172
+ t_final=t_final,
173
+ filename=filename,
165
174
  verbose=True,
166
175
  )
@@ -59,12 +59,20 @@ from fullflow import *
59
59
  from thermoprop import *
60
60
 
61
61
 
62
+ # -----------------------------------------------------------------------------
63
+ # Run options
64
+ # -----------------------------------------------------------------------------
65
+
66
+ dt = 1.0
67
+ t_final = 900.0
68
+ filename = '11heat_transfer'
69
+
70
+
62
71
  # ---------------------------------------------------------------------------
63
72
  # Network
64
73
  # ---------------------------------------------------------------------------
65
74
  HeatTransferNetwork = Network("Solid Heat Transfer Transient")
66
75
 
67
- filename = "11heat_transfer"
68
76
 
69
77
 
70
78
  # ---------------------------------------------------------------------------
@@ -203,9 +211,9 @@ HeatTransferNetwork.track("Biot Number", biot_number)
203
211
  # Transient solve
204
212
  # ---------------------------------------------------------------------------
205
213
  Transient(HeatTransferNetwork).solve(
206
- dt=1.0,
207
- t_final=900.0,
214
+ dt=dt,
215
+ t_final=t_final,
208
216
  filename=filename,
209
217
  save_dt=5.0,
210
218
  verbose=True,
211
- )
219
+ )
@@ -137,16 +137,25 @@ import re
137
137
  import h5py
138
138
  import matplotlib.pyplot as plt
139
139
  import numpy as np
140
+ from scipy.constants import *
140
141
 
141
142
  from fullflow import *
142
143
  from thermoprop import *
143
144
 
144
145
 
146
+ # -----------------------------------------------------------------------------
147
+ # Run options
148
+ # -----------------------------------------------------------------------------
149
+
150
+ dt = 0.1
151
+ t_final = 4.0
152
+ filename = '12heat_exchanger'
153
+
154
+
145
155
  # -----------------------------------------------------------------------------
146
156
  # Output file
147
157
  # -----------------------------------------------------------------------------
148
158
 
149
- filename = "12heat_exchanger"
150
159
 
151
160
 
152
161
  def harmonic_mean(a, b):
@@ -273,22 +282,21 @@ gasoline_specific_heat_cp = (
273
282
  # The current network uses three hydraulic tube elements per side, so Nseg is 3.
274
283
  # -----------------------------------------------------------------------------
275
284
 
276
- IN_TO_M = 0.0254
277
285
 
278
286
  # Total heat-exchanger length and length of each model segment.
279
- L_total = 40.0 * IN_TO_M
287
+ L_total = 40.0 * inch
280
288
  Nseg = 3
281
289
  L = L_total / Nseg
282
290
 
283
291
  # Inner-tube inside diameter. This is the hot-fluid flow diameter.
284
- D_inner = 0.50 * IN_TO_M
292
+ D_inner = 0.50 * inch
285
293
 
286
294
  # Tube wall thickness and resulting tube outside diameter.
287
- wall_thickness = 0.035 * IN_TO_M
295
+ wall_thickness = 0.035 * inch
288
296
  D_tube_outer = D_inner + 2.0 * wall_thickness
289
297
 
290
298
  # Outer diameter of the annulus. Coolant flows between D_tube_outer and this ID.
291
- D_annulus_outer = 0.875 * IN_TO_M
299
+ D_annulus_outer = 0.875 * inch
292
300
 
293
301
  # Basic geometry check to avoid a negative annular area.
294
302
  if D_tube_outer >= D_annulus_outer:
@@ -1040,15 +1048,14 @@ CoolantNode2.heat_rate = -Coolant2Solid1Convection.heat_rate
1040
1048
  # exchanger.
1041
1049
  # -----------------------------------------------------------------------------
1042
1050
 
1043
- PA_TO_PSIA = 1.0 / 6894.757293
1044
1051
 
1045
- HeatExchanger.track("Hot Fluid Source Pressure [psia]", hot_fluid_source_pressure * PA_TO_PSIA)
1046
- HeatExchanger.track("Hot Fluid Node 1 Pressure [psia]", hot_fluid_node1_pressure * PA_TO_PSIA)
1047
- HeatExchanger.track("Hot Fluid Node 2 Pressure [psia]", hot_fluid_node2_pressure * PA_TO_PSIA)
1052
+ HeatExchanger.track("Hot Fluid Source Pressure [psia]", hot_fluid_source_pressure * (1.0 / psi))
1053
+ HeatExchanger.track("Hot Fluid Node 1 Pressure [psia]", hot_fluid_node1_pressure * (1.0 / psi))
1054
+ HeatExchanger.track("Hot Fluid Node 2 Pressure [psia]", hot_fluid_node2_pressure * (1.0 / psi))
1048
1055
 
1049
- HeatExchanger.track("Coolant Source Pressure [psia]", CoolantSource.pressure * PA_TO_PSIA)
1050
- HeatExchanger.track("Coolant Node 1 Pressure [psia]", CoolantNode1Fluid.pressure * PA_TO_PSIA)
1051
- HeatExchanger.track("Coolant Node 2 Pressure [psia]", CoolantNode2Fluid.pressure * PA_TO_PSIA)
1056
+ HeatExchanger.track("Coolant Source Pressure [psia]", CoolantSource.pressure * (1.0 / psi))
1057
+ HeatExchanger.track("Coolant Node 1 Pressure [psia]", CoolantNode1Fluid.pressure * (1.0 / psi))
1058
+ HeatExchanger.track("Coolant Node 2 Pressure [psia]", CoolantNode2Fluid.pressure * (1.0 / psi))
1052
1059
 
1053
1060
  HeatExchanger.track("Hot Fluid Source Temperature [K]", hot_fluid_source_temperature)
1054
1061
  HeatExchanger.track("Hot Fluid Node 1 Temperature [K]", hot_fluid_node1_temperature)
@@ -1104,10 +1111,9 @@ SteadyState(HeatExchanger).solve(
1104
1111
  # A small timestep is used because the fluid residence time in this short,
1105
1112
  # small-diameter heat exchanger is much faster than the wall thermal response.
1106
1113
  Transient(HeatExchanger).solve(
1107
- dt=0.01,
1108
- t_final=4.0,
1109
- save_dt=0.02,
1114
+ dt=dt,
1115
+ t_final=t_final,
1110
1116
  filename=filename,
1111
1117
  verbose=True,
1112
1118
  statistics=True,
1113
- )
1119
+ )