# 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

- Python with fluids installed

- reticulate https://cran.r-project.org/web/packages/reticulate/index.html

## Usage Notes

- The example demonstrates basic integration with fluids

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