R Integration

This example demonstrates how to use fluids from R.

Source Code

  1 
  2# Install and load reticulate
  3library(reticulate)
  4
  5# Function to run all tests
  6test_fluids <- function() {
  7  tryCatch({
  8    # 1. Test import
  9    fluids <- import("fluids")
 10    print("✓ Successfully imported fluids")
 11    
 12    # 2. Test version access
 13    version <- py_get_attr(fluids, "__version__")
 14    print(paste("✓ Fluids version:", version))
 15    
 16    # 3. Test basic Reynolds number calculation
 17    Re <- fluids$Reynolds(V=2.5, D=0.1, rho=1000, mu=0.001)
 18    print(paste("✓ Reynolds number calculation successful:", Re))
 19    stopifnot(Re > 0)  # Basic sanity check
 20    
 21    # 4. Test friction factor calculation
 22    fd <- fluids$friction_factor(Re=1e5, eD=0.0001)
 23    print(paste("✓ Friction factor calculation successful:", fd))
 24    stopifnot(fd > 0 && fd < 1)  # Basic range check
 25    
 26    print("\nAll tests completed successfully!")
 27    
 28  }, error = function(e) {
 29    print(paste("Error occurred:", e$message))
 30    stop("Test suite failed")
 31  })
 32}
 33test_atmosphere <- function() {
 34  tryCatch({
 35    fluids <- import("fluids")
 36    # Test ATMOSPHERE_1976 class
 37    atm <- fluids$ATMOSPHERE_1976(Z=5000)
 38    
 39    # Test basic properties
 40    print("Testing atmosphere at 5000m elevation:")
 41    print(paste("✓ Temperature:", round(atm$T, 4)))
 42    print(paste("✓ Pressure:", round(atm$P, 4)))
 43    print(paste("✓ Density:", round(atm$rho, 6)))
 44    
 45    # Test derived properties
 46    print(paste("✓ Gravity:", round(atm$g, 6)))
 47    print(paste("✓ Viscosity:", formatC(atm$mu, format="e", digits=6)))
 48    print(paste("✓ Thermal conductivity:", round(atm$k, 6)))
 49    print(paste("✓ Sonic velocity:", round(atm$v_sonic, 4)))
 50    
 51    # Test static methods
 52    g_high <- fluids$ATMOSPHERE_1976$gravity(Z=1E5)
 53    print(paste("✓ High altitude gravity:", round(g_high, 6)))
 54    
 55    v_sonic <- fluids$ATMOSPHERE_1976$sonic_velocity(T=300)
 56    print(paste("✓ Sonic velocity at 300K:", round(v_sonic, 4)))
 57    
 58    mu_400 <- fluids$ATMOSPHERE_1976$viscosity(T=400)
 59    print(paste("✓ Viscosity at 400K:", formatC(mu_400, format="e", digits=6)))
 60    
 61    k_400 <- fluids$ATMOSPHERE_1976$thermal_conductivity(T=400)
 62    print(paste("✓ Thermal conductivity at 400K:", round(k_400, 6)))
 63  }, error = function(e) {
 64    print(paste("Error in atmosphere tests:", e$message))
 65    stop("Atmosphere test suite failed")
 66  })
 67}
 68test_tank <- function() {
 69  tryCatch({
 70    fluids <- import("fluids")
 71    # Test basic tank creation
 72    T1 <- fluids$TANK(V=10, L_over_D=0.7, sideB='conical', horizontal=FALSE)
 73    print("\nTesting tank calculations:")
 74    print(paste("✓ Tank length:", round(T1$L, 6)))
 75    print(paste("✓ Tank diameter:", round(T1$D, 6)))
 76    
 77    # Test ellipsoidal tank
 78    tank_ellip <- fluids$TANK(D=10, V=500, horizontal=FALSE, 
 79                             sideA='ellipsoidal', sideB='ellipsoidal', 
 80                             sideA_a=1, sideB_a=1)
 81    print(paste("✓ Ellipsoidal tank L:", round(tank_ellip$L, 6)))
 82    
 83    # Test torispherical tank
 84    DIN <- fluids$TANK(L=3, D=5, horizontal=FALSE, 
 85                       sideA='torispherical', sideB='torispherical',
 86                       sideA_f=1, sideA_k=0.1, sideB_f=1, sideB_k=0.1)
 87    print(paste("✓ Tank representation:", capture.output(print(DIN))))
 88    print(paste("✓ Tank max height:", round(DIN$h_max, 6)))
 89    print(paste("✓ Height at V=40:", round(DIN$h_from_V(40), 6)))
 90    print(paste("✓ Volume at h=4.1:", round(DIN$V_from_h(4.1), 5)))
 91    print(paste("✓ Surface area at h=2.1:", round(DIN$SA_from_h(2.1), 5)))
 92    
 93  }, error = function(e) {
 94    print(paste("Error in tank tests:", e$message))
 95    stop("Tank test suite failed")
 96  })
 97}
 98# Test function for Reynolds number calculations
 99test_reynolds <- function() {
100  tryCatch({
101    print("\nTesting Reynolds number calculations:")
102    fluids <- import("fluids")
103    
104    # Test with density and viscosity
105    Re1 <- fluids$Reynolds(V=2.5, D=0.25, rho=1.1613, mu=1.9E-5)
106    print(paste("✓ Re (with rho, mu):", round(Re1, 4)))
107    stopifnot(abs(Re1 - 38200.6579) < 0.1)
108    
109    # Test with kinematic viscosity
110    Re2 <- fluids$Reynolds(V=2.5, D=0.25, nu=1.636e-05)
111    print(paste("✓ Re (with nu):", round(Re2, 4)))
112    stopifnot(abs(Re2 - 38202.934) < 0.1)
113    
114  }, error = function(e) {
115    print(paste("Error in Reynolds tests:", e$message))
116    stop("Reynolds test suite failed")
117  })
118}
119
120# Test function for particle size distributions
121test_psd <- function() {
122  tryCatch({
123    print("\nTesting particle size distribution functionality:")
124    fluids <- import("fluids")
125
126    # Create a discrete PSD
127    ds <- c(240, 360, 450, 562.5, 703, 878, 1097, 1371, 1713, 2141, 2676, 3345, 4181, 5226, 6532)
128    numbers <- c(65, 119, 232, 410, 629, 849, 990, 981, 825, 579, 297, 111, 21, 1)
129    
130    psd <- fluids$particle_size_distribution$ParticleSizeDistribution(
131      ds=ds, 
132      fractions=numbers, 
133      order=0
134    )
135    print("✓ Created discrete PSD")
136    
137    # Test mean sizes
138    d21 <- psd$mean_size(2, 1)
139    print(paste("✓ Size-weighted mean diameter:", round(d21, 4)))
140    stopifnot(abs(d21 - 1857.788) < 0.1)
141    
142    d10 <- psd$mean_size(1, 0)
143    print(paste("✓ Arithmetic mean diameter:", round(d10, 4)))
144    stopifnot(abs(d10 - 1459.372) < 0.1)
145    
146    # Test percentile calculations
147    d10_percentile <- psd$dn(0.1)
148    d90_percentile <- psd$dn(0.9)
149    print(paste("✓ D10:", round(d10_percentile, 4)))
150    print(paste("✓ D90:", round(d90_percentile, 4)))
151    
152    # Test probability functions
153    pdf_val <- psd$pdf(1000)
154    cdf_val <- psd$cdf(5000)
155    print(paste("✓ PDF at 1000:", formatC(pdf_val, format="e", digits=4)))
156    print(paste("✓ CDF at 5000:", round(cdf_val, 6)))
157    
158    # Test lognormal distribution
159    psd_log <- fluids$particle_size_distribution$PSDLognormal(s=0.5, d_characteristic=5E-6)
160    print("✓ Created lognormal PSD")
161    
162    vssa <- psd_log$vssa
163    print(paste("✓ Volume specific surface area:", round(vssa, 2)))
164    
165    span <- psd_log$dn(0.9) - psd_log$dn(0.1)
166    print(paste("✓ Span:", formatC(span, format="e", digits=4)))
167    
168    ratio_7525 <- psd_log$dn(0.75)/psd_log$dn(0.25)
169    print(paste("✓ D75/D25 ratio:", round(ratio_7525, 6)))
170    
171  }, error = function(e) {
172    print(paste("Error in PSD tests:", e$message))
173    stop("PSD test suite failed")
174  })
175}
176benchmark_fluids <- function() {
177  fluids <- import("fluids")
178  cat("\nRunning benchmarks:\n")
179  
180  # Benchmark friction factor calculation
181  cat("\nBenchmarking friction_factor:\n")
182  t1 <- system.time({
183    for(i in 1:10000) {
184      fluids$friction_factor(Re=1e5, eD=0.0001)
185    }
186  })
187  cat(sprintf("Time for 10000 friction_factor calls: %.6f seconds\n", t1["elapsed"]))
188  cat(sprintf("Average time per call: %.6f seconds\n", t1["elapsed"]/10000))
189  
190  # Benchmark tank creation
191  cat("\nBenchmarking TANK creation:\n")
192  t2 <- system.time({
193    for(i in 1:1000) {
194      fluids$TANK(L=3, D=5, horizontal=FALSE,
195                  sideA="torispherical", sideB="torispherical",
196                  sideA_f=1, sideA_k=0.1, sideB_f=1, sideB_k=0.1)
197    }
198  })
199  cat(sprintf("Time for 1000 TANK creations: %.6f seconds\n", t2["elapsed"]))
200  cat(sprintf("Average time per creation: %.6f seconds\n", t2["elapsed"]/1000))
201}
202
203# Run the tests
204test_fluids()
205test_atmosphere()
206test_tank()
207test_reynolds()
208test_psd()
209benchmark_fluids()

Requirements

Usage Notes

  • The example demonstrates basic integration with fluids

  • 90 microsecond friction factor, 170 microsecond tank creation observed by author