Reputation: 117
This function that calculates the pressure loss in a pipe given its diameter, flowrate, and length.
hazwil2 <- function(diam, flow, leng){
psi2=((1/(2.31*100))*1050*((flow/140)^1.852)*leng*diam^-4.87)
return(psi2)
}
I'm looking for the smallest diameter that will keep the pressure loss within 2 psi. The range of diameters is between 2 and 12 inches. Using uniroot() and two arbitrary values for flow and length:
intercept = 2L
uniroot(
function(x) hazwil2(x, 100, 400) - intercept ,
interval = c(2, 12)
)$root
Now I'm trying to loop uniroot on this dataset of values of flow and length
data <- read.csv(
text =
"leng,flow
100, 100
200, 100
300, 100
100, 150
200, 150
300, 150
100, 200
200, 200
300, 200",
stringsAsFactors = FALSE
)
Upvotes: 3
Views: 488
Reputation: 107687
Consider generalizing your unitroot call for f and l params, and pass it in mapply
(multiple apply) to iterate elementwise down the equal length vectors (i.e., columns, flow and length of dataframe):
find_root <- function(f, l) {
intercept <- 2L
uniroot(
function(x) hazwil2(x, f, l) - intercept ,
interval = c(2, 12)
)$root
}
data$root <- mapply(find_root, data$flow, data$leng)
data
# leng flow root
# 1 100 100 2.681145
# 2 200 100 3.091243
# 3 300 100 3.359606
# 4 100 150 3.128141
# 5 200 150 3.606602
# 6 300 150 3.919727
# 7 100 200 3.489780
# 8 200 200 4.023564
# 9 300 200 4.372916
For a larger set which can potentially yield root issues, consider wrapping function call in tryCatch
to return NA
:
data <- expand.grid(leng = seq(100, 1000, by=100), flow = seq(10, 200, by=10))
data$root <- mapply(function(l,f) tryCatch(find_root(l,f), error=function(e) NA),
data$flow, data$leng)
Output
head(data, 20)
# leng flow root
# 1 100 10 NA
# 2 200 10 NA
# 3 300 10 NA
# 4 400 10 NA
# 5 500 10 NA
# 6 600 10 NA
# 7 700 10 NA
# 8 800 10 NA
# 9 900 10 NA
# 10 1000 10 NA
# 11 100 20 NA
# 12 200 20 NA
# 13 300 20 NA
# 14 400 20 NA
# 15 500 20 2.023187
# 16 600 20 2.100367
# 17 700 20 2.167915
# 18 800 20 2.228178
# 19 900 20 2.282705
# 20 1000 20 2.332653
Upvotes: 2
Reputation: 5287
This based on @Parfait's answer, and includes some graphs that came to mind during the previous question. The first graph sets the x & y coordinates to flow
and leng
and displays the min diameter required to drop below 2 PSI.
data$diam_min <- purrr::map2_dbl(.x=data$flow, .y=data$leng, ~find_root(f=.x, l=.y))
data$diam_min_pretty <- sprintf("diam min:\n%0.2f", data$diam_min)
library(ggplot2); library(magrittr)
ggplot(data, aes(x=flow, y=leng, label=diam_min_pretty)) +
geom_text()
The second graph make each value of leng
a contour line, and the min diameter replaces it on the y axis. That open dot represents the solution to Optimize function in R with constraints.
tidyr::crossing(leng=c(100, 200, 300, 400), flow=100:200) %>%
dplyr::mutate(
diam_min = purrr::map2_dbl(.x=flow, .y=leng, ~find_root(.x, .y)),
leng = factor(leng)
) %>%
ggplot(aes(x=flow, y=diam_min, color=leng)) +
geom_line() +
annotate("point", x=100, y=find_root(f=100, l=400), size=4, shape=1)
I'm still not sure how you're going to choose the most desirable value (out of this set that achieves <2 psi), but maybe these visual relationships will help.
Upvotes: 1