nim Integration¶
This example demonstrates how to use fluids from nim.
Source Code¶
1import nimpy
2import times
3import strformat
4import math
5
6# Initialize Python and import fluids
7let fluids = pyImport("fluids")
8
9proc test_fluids() =
10 try:
11 # Test basic module import
12 echo "Running fluids tests from Nim..."
13 echo "✓ Successfully imported fluids"
14 echo &"✓ Fluids version: {fluids.getAttr(\"__version__\").to(string)}"
15
16 # Test basic Reynolds number calculation
17 let Re = fluids.Reynolds(V=2.5, D=0.1, rho=1000, mu=0.001).to(float)
18 echo &"✓ Reynolds number calculation successful: {Re}"
19 assert Re > 0
20
21 # Test friction factor calculation
22 let fd = fluids.friction_factor(Re=1e5, eD=0.0001).to(float)
23 echo &"✓ Friction factor calculation successful: {fd}"
24 assert 0 < fd and fd < 1
25
26 echo "\nAll basic tests completed successfully!"
27
28 except:
29 echo "Error in fluids tests: ", getCurrentExceptionMsg()
30 raise
31
32proc test_atmosphere() =
33 try:
34 # Test ATMOSPHERE_1976 class
35 let atm = fluids.ATMOSPHERE_1976(Z=5000)
36
37 echo "\nTesting atmosphere at 5000m elevation:"
38 echo &"✓ Temperature: {atm.T.to(float):.4f}"
39 echo &"✓ Pressure: {atm.P.to(float):.4f}"
40 echo &"✓ Density: {atm.rho.to(float):.6f}"
41
42 # Test derived properties
43 echo &"✓ Gravity: {atm.g.to(float):.6f}"
44 echo &"✓ Viscosity: {atm.mu.to(float):.6e}"
45 echo &"✓ Thermal conductivity: {atm.k.to(float):.6f}"
46 echo &"✓ Sonic velocity: {atm.v_sonic.to(float):.4f}"
47
48 # Test static methods
49 let g_high = fluids.ATMOSPHERE_1976.gravity(Z=1E5).to(float)
50 echo &"✓ High altitude gravity: {g_high:.6f}"
51
52 let v_sonic = fluids.ATMOSPHERE_1976.sonic_velocity(T=300).to(float)
53 echo &"✓ Sonic velocity at 300K: {v_sonic:.4f}"
54
55 let mu_400 = fluids.ATMOSPHERE_1976.viscosity(T=400).to(float)
56 echo &"✓ Viscosity at 400K: {mu_400:.6e}"
57
58 let k_400 = fluids.ATMOSPHERE_1976.thermal_conductivity(T=400).to(float)
59 echo &"✓ Thermal conductivity at 400K: {k_400:.6f}"
60
61 except:
62 echo "Error in atmosphere tests: ", getCurrentExceptionMsg()
63 raise
64
65proc test_tank() =
66 try:
67 # Test basic tank creation
68 let T1 = fluids.TANK(V=10, L_over_D=0.7, sideB="conical", horizontal=false)
69 echo "\nTesting tank calculations:"
70 echo &"✓ Tank length: {T1.L.to(float):.6f}"
71 echo &"✓ Tank diameter: {T1.D.to(float):.6f}"
72
73 # Test ellipsoidal tank
74 let tank_ellip = fluids.TANK(
75 D=10, V=500, horizontal=false,
76 sideA="ellipsoidal", sideB="ellipsoidal",
77 sideA_a=1, sideB_a=1
78 )
79 echo &"✓ Ellipsoidal tank L: {tank_ellip.L.to(float):.6f}"
80
81 # Test torispherical tank
82 let DIN = fluids.TANK(
83 L=3, D=5, horizontal=false,
84 sideA="torispherical", sideB="torispherical",
85 sideA_f=1, sideA_k=0.1, sideB_f=1, sideB_k=0.1
86 )
87
88 echo &"✓ Tank representation: {$DIN}"
89 echo &"✓ Tank max height: {DIN.h_max.to(float):.6f}"
90 echo &"✓ Height at V=40: {DIN.h_from_V(40).to(float):.6f}"
91 echo &"✓ Volume at h=4.1: {DIN.V_from_h(4.1).to(float):.5f}"
92 echo &"✓ Surface area at h=2.1: {DIN.SA_from_h(2.1).to(float):.5f}"
93
94 except:
95 echo "Error in tank tests: ", getCurrentExceptionMsg()
96 raise
97
98proc test_reynolds() =
99 try:
100 echo "\nTesting Reynolds number calculations:"
101
102 # Test with density and viscosity
103 let Re1 = fluids.Reynolds(V=2.5, D=0.25, rho=1.1613, mu=1.9E-5).to(float)
104 echo &"✓ Re (with rho, mu): {Re1:.4f}"
105 assert abs(Re1 - 38200.6579) < 0.1
106
107 # Test with kinematic viscosity
108 let Re2 = fluids.Reynolds(V=2.5, D=0.25, nu=1.636e-05).to(float)
109 echo &"✓ Re (with nu): {Re2:.4f}"
110 assert abs(Re2 - 38202.934) < 0.1
111
112 except:
113 echo "Error in Reynolds tests: ", getCurrentExceptionMsg()
114 raise
115
116proc test_psd() =
117 try:
118 echo "\nTesting particle size distribution functionality:"
119
120 # Create a discrete PSD
121 let ds = @[240.0, 360.0, 450.0, 562.5, 703.0, 878.0, 1097.0, 1371.0,
122 1713.0, 2141.0, 2676.0, 3345.0, 4181.0, 5226.0, 6532.0]
123 let numbers = @[65.0, 119.0, 232.0, 410.0, 629.0, 849.0, 990.0, 981.0,
124 825.0, 579.0, 297.0, 111.0, 21.0, 1.0]
125
126 let psd = fluids.particle_size_distribution.ParticleSizeDistribution(
127 ds=ds,
128 fractions=numbers,
129 order=0
130 )
131 echo "✓ Created discrete PSD"
132
133 # Test mean sizes
134 let d21 = psd.mean_size(2, 1).to(float)
135 echo &"✓ Size-weighted mean diameter: {d21:.4f}"
136 assert abs(d21 - 1857.788) < 0.1
137
138 let d10 = psd.mean_size(1, 0).to(float)
139 echo &"✓ Arithmetic mean diameter: {d10:.4f}"
140 assert abs(d10 - 1459.372) < 0.1
141
142 # Test percentile calculations
143 let d10_percentile = psd.dn(0.1).to(float)
144 let d90_percentile = psd.dn(0.9).to(float)
145 echo &"✓ D10: {d10_percentile:.4f}"
146 echo &"✓ D90: {d90_percentile:.4f}"
147
148 # Test probability functions
149 let pdf_val = psd.pdf(1000).to(float)
150 let cdf_val = psd.cdf(5000).to(float)
151 echo &"✓ PDF at 1000: {pdf_val:.4e}"
152 echo &"✓ CDF at 5000: {cdf_val:.6f}"
153
154 # Test lognormal distribution
155 let psd_log = fluids.particle_size_distribution.PSDLognormal(s=0.5, d_characteristic=5E-6)
156 echo "✓ Created lognormal PSD"
157
158 let vssa = psd_log.vssa.to(float)
159 echo &"✓ Volume specific surface area: {vssa:.2f}"
160
161 let span = psd_log.dn(0.9).to(float) - psd_log.dn(0.1).to(float)
162 echo &"✓ Span: {span:.4e}"
163
164 let ratio_7525 = psd_log.dn(0.75).to(float) / psd_log.dn(0.25).to(float)
165 echo &"✓ D75/D25 ratio: {ratio_7525:.6f}"
166
167 except:
168 echo "Error in PSD tests: ", getCurrentExceptionMsg()
169 raise
170
171proc benchmark_fluids() =
172 echo "\nRunning benchmarks:"
173
174 # Benchmark friction factor calculation
175 echo "\nBenchmarking friction_factor:"
176 let start = epochTime()
177
178 for i in 1..1_000_000:
179 discard fluids.friction_factor(Re=1e5, eD=0.0001)
180
181 let duration = (epochTime() - start) * 1_000_000 # Convert to microseconds
182 echo &"Time for 1e6 friction_factor calls: {duration.int} microseconds"
183 echo &"Average time per call: {duration / 1_000_000:.6f} microseconds"
184
185 # Benchmark tank creation
186 echo "\nBenchmarking TANK creation:"
187 let tank_start = epochTime()
188
189 for i in 1..1000:
190 discard fluids.TANK(
191 L=3, D=5, horizontal=false,
192 sideA="torispherical", sideB="torispherical",
193 sideA_f=1, sideA_k=0.1,
194 sideB_f=1, sideB_k=0.1
195 )
196
197 let tank_duration = (epochTime() - tank_start) * 1_000_000 # Convert to microseconds
198 echo &"Average time per tank creation: {tank_duration / 1000:.6f} microseconds"
199
200when isMainModule:
201 try:
202 test_fluids()
203 test_atmosphere()
204 test_tank()
205 test_reynolds()
206 test_psd()
207 benchmark_fluids()
208 echo "\nAll tests completed!"
209 except:
210 echo "Fatal error: ", getCurrentExceptionMsg()
211 quit(1)
Requirements¶
Python with fluids installed
Usage Notes¶
Nim has a great package manager and is easy to read/write. This example took 10 minutes to develop.
1.5 microsecond friction factor, 9 microsecond tank creation observed by author; very comparable to pybind11