R/b36mass.R

Defines functions b36wth b36d b36mass

Documented in b36d b36mass b36wth

#' @title
#'  Estimate pipe mass
#'
#' @family utils
#'
#' @description
#'  Estimate mass or geometric specifications of the manufactured pipes
#'
#' @details
#' The mass of a one-meter pipe segment is determined by linear interpolation based on
#' the tabular data provided in the specified origins (see \code{\link{b36pipedata}}). If 
#' the \code{origin} of the initial data is \code{NULL} (default), the mass of the pipe is calculated using a formula:
#' \deqn{M = 10^{-3} \pi \rho w \left(d - w \right ) \cdot l}
#' where
#' \itemize{
#'    \item \eqn{M} - mass of a pipe, [\emph{kg}]
#'    \item \eqn{\rho} - mass density of pipe material, [\emph{g/cm^3}]
#'    \item \eqn{w} - nominal wall thickness of the manufactured pipe, [\emph{mm}]
#'    \item \eqn{d} - nominal outside diameter of the manufactured pipe, [\emph{mm}]
#'    \item \eqn{l} - actual pipe length, [\emph{m}]
#'  }
#' For \code{origin} in \code{c(1, 2, 4, 5)} the values provided in the 
#' \code{\link{b36pipedata}} match the calculated values obtained from the formula
#' with an accuracy of 1 \%. 
#' 
#' Inverse calculations \code{\link{b36wth}} and \code{\link{b36d}} are performed using 
#' algebraically derived formulas.
#'
#' @param d
#'  nominal outside diameter of pipe, [\emph{mm}]. Type: \code{\link{assert_double}}
#'
#' @param wth
#'  nominal wall thickness of pipe, [\emph{mm}]. Type: \code{\link{assert_double}}.
#'
#' @param len
#'  pipe length, [\emph{m}]. Type: \code{\link{assert_double}}.
#'
#' @param rho
#'  mass density of pipe material, [\emph{g/cm^3}]. Type: \code{\link{assert_double}}.
#'
#' @param origin
#'  identifier for the information origin regarding the specifications of pipe. 
#'  Type: \code{\link{assert_integer}}.
#'
#' @param mass
#'  actual mass of pipe, [\emph{kg}]. Type: \code{\link{assert_double}}.
#'
#' @return
#'  \describe{
#'   \item{for \code{\link{b36mass}}}{pipe mass, [\emph{kg}]}
#'   \item{for \code{\link{b36wth}}}{pipe wall thickness, [\emph{mm}]}
#'   \item{for \code{\link{b36d}}}{outside diameter of pipe, [\emph{mm}]}
#'  }
#'
#' @examples
#'  library(pipenostics)
#'  # Since some specification origins provide the mass of a one-meter pipe segment taking
#'  # into account possible deviations during its production process, when the user 
#'  # specifies the origin ID directly, the mass values are calculated using linear 
#'  # interpolation:
#'  b36mass(68, 13, rho = 7.9, origin = 7L)
#'  # [1] 16.43 
#'  
#'  # The discrepancy with the calculations based on the formula can be more than 7 %:
#'  b36mass(68, 13, rho = 7.9, origin = NULL)
#'  # [1] 17.74529
#'  
#'  # For origins which are ASME B36 standards such differences should be minimal:
#'  b36mass(965, 10.31, origin = 1L) - b36mass(965, 10.31, origin = NULL)
#'  # [1] 0.0004356046
#'  
#'  # The calculations of diameter and wall thickness are straightforward and use 
#'  # only inverse formulas without origin references:
#'  b36d(10.31, 242.74)
#'  # [1] 965.0017
#'
#'  b36wth(965, 242.74)
#'  # [1] 10.31002
#'
#' @rdname b36mass
#' @export
b36mass <- function(d, wth, len = 1, rho = 7.85, origin = NULL) {
  L_ORIGIN    <- "origin"
  L_DIAMETER  <- "d"
  L_THICKNESS <- "wth"
  L_LENGTH    <- "len"
  L_DENSITY   <- "rho"
  L_MASS      <- "mass"
  L_ONE       <- L_FIRST <- 1L
  L_TWO       <- 2
  D_OFFSET    <-  .4  # Pipe diameter tolerance, [mm]

  md <- pipenostics::b36pipedata
  checkmate::assert_double(
    d,
    lower = min(md[[L_DIAMETER]]) - D_OFFSET, upper = max(md[[L_DIAMETER]]) + D_OFFSET,
    any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_double(
    wth,
    lower = min(md[[L_THICKNESS]]), upper = max(md[[L_THICKNESS]]),
    any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_double(
    len,
    lower = 0, finite = TRUE, any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_double(
    rho,
    lower = 7.75, upper =  8.05, any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_true(commensurable(c(length(d), length(wth), length(len), length(rho))))
  checkmate::assert_double(
    wth/d,
    lower = .Machine[["double.eps"]], upper = max(md[[L_THICKNESS]]/md[[L_DIAMETER]])
  )
  checkmate::assert_integer(
    origin,
    lower = min(md[[L_ORIGIN]]), upper = max(md[[L_ORIGIN]]),
    any.missing = FALSE, min.len = L_ONE, max.len = length(unique(md[[L_ORIGIN]])),
    unique = TRUE, null.ok = TRUE
  )

  pipe_mass <- (d - wth) * 1e-3 * wth * rho * len * base::pi
  if (is.null(origin)) return(pipe_mass)

  C <- data.frame(
    a = c(
       1.34639486196096e-05, -0.269421768471856, -0.543828305826526,
      -0.32040873191324    , -0.001023302221079,  0.000750308148511,
      -8.88387684950809e-05
    ),
    b = c(
       0.99993868472687, 1.06490339805795,  1.07025471029979    ,
       1.04765386422189, 1.00035194161928,  0.999990376939387   ,
       1.00000056550023
    )
  )
  pipe <- data.frame(d = d, wth = wth, len = len, rho = rho)
  md   <- md[md[[L_ORIGIN]] %in% origin, ]
  vapply(
    seq_len(nrow(pipe)),
    function(i){
      m <- md[
        md[[L_DIAMETER ]] == pipe[i, L_DIAMETER ] &
        md[[L_THICKNESS]] == pipe[i, L_THICKNESS] &
        md[[L_DENSITY  ]] == pipe[i, L_DENSITY  ]
        ,
        L_MASS
      ]
      if (isTRUE(as.logical(length(m)))) return(m[[L_FIRST]])
      if (
        pipe[i, L_DIAMETER] < min(md[[L_DIAMETER]]) - D_OFFSET |
        pipe[i, L_DIAMETER] > max(md[[L_DIAMETER]]) + D_OFFSET
      ) return(NA_real_)
      dst <- (md[[L_DIAMETER ]] - pipe[i, L_DIAMETER ])^L_TWO +
             (md[[L_THICKNESS]] - pipe[i, L_THICKNESS])^L_TWO +
             (md[[L_DENSITY  ]] - pipe[i, L_DENSITY  ])^L_TWO
      oid <- md[which.min(dst), L_ORIGIN]
      pipe_mass[[i]] * C[oid, "b"] + C[oid, "a"]
    },
    double(L_ONE)
  ) * pipe[[L_LENGTH]]
}

#' @rdname b36mass
#' @export
b36d <- function(wth, mass, len = 1, rho = 7.85) {
  L_THICKNESS <- "wth"
  L_MASS      <- "mass"
  L_ONE       <- 1L

  md <- pipenostics::b36pipedata
  checkmate::assert_double(
    wth,
    lower = min(md[[L_THICKNESS]]), upper = max(md[[L_THICKNESS]]),
    any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_double(
    mass,
    lower = 0, finite = TRUE, any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_double(
    len,
    lower = 0.1, finite = TRUE, any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_double(
    rho,
    lower = 7.75, upper =  8.05, any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_true(commensurable(c(length(wth), length(mass), length(len), length(rho))))

  unit_mass <- mass/len
  checkmate::assert_double(
    unit_mass,
    lower = min(md[[L_MASS]]), upper = max(md[[L_MASS]]),
    any.missing = FALSE, min.len = L_ONE
  )
  1e3 * unit_mass/base::pi/wth/rho + wth
}

#' @rdname b36mass
#' @export
b36wth <- function(d, mass, len = 1, rho = 7.85) {
  L_DIAMETER  <- "d"
  L_MASS      <- "mass"
  L_ONE       <- 1L
  D_OFFSET    <-  .4  # Pipe diameter tolerance, [mm]

  md <- pipenostics::b36pipedata
  checkmate::assert_double(
    d,
    lower = min(md[[L_DIAMETER]]) - D_OFFSET, upper = max(md[[L_DIAMETER]]) + D_OFFSET,
    any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_double(
    mass,
    lower = 0, finite = TRUE, any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_double(
    len,
    lower = 0.1, finite = TRUE, any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_double(
    rho,
    lower = 7.75, upper =  8.05, any.missing = FALSE, min.len = L_ONE
  )
  checkmate::assert_true(commensurable(c(length(d), length(mass), length(len), length(rho))))

  unit_mass <- mass/len
  checkmate::assert_double(
    unit_mass,
    lower = min(md[[L_MASS]]), upper = max(md[[L_MASS]]),
    any.missing = FALSE, min.len = L_ONE
  )

  r <- .5 * d
  D <- r^2 - unit_mass/base::pi/rho * 1e3
  D[D < 0] <- NA_real_
  r - sqrt(D)
}
omega1x/pipenostics documentation built on May 13, 2024, 4:14 a.m.