コールブルック・ホワイトの式とは
コールブルック・ホワイトの式(Colebrook-White の式)は、円管内の乱流における管摩擦係数 \(\lambda\) を求めるための経験式です。
\[
\begin{eqnarray}
\frac{1}{\sqrt{\lambda}} &=& -2\log_{10}\left(\frac{\varepsilon}{3.71\,D_H}+\frac{2.51}{Re\sqrt{\lambda}}\right)
\end{eqnarray}
\tag{1}\]
ここで、各変数の定義は次のとおりです。
- \(\lambda\)
- ダルシー・ワイスバッハの管摩擦係数(無次元)
- \(\varepsilon\)
- 管の絶対粗度 [m]
- \(D_H\)
- 管の水力直径 [m]
- \(Re\)
- レイノルズ数(無次元)
水力直径は、流れの断面積 \(A\) [m\(^2\)] と濡れ縁長(潤辺)\(P\) [m] から
\[
\begin{eqnarray}
D_H &=& \frac{4A}{P}
\end{eqnarray}
\tag{2}\]
で定義され、円管で満水の場合は管の内径に一致します。また、\(\varepsilon/D_H\) は相対粗度です。
括弧の中の第1項は管壁の粗さの効果、第2項は粘性の効果を表しています。この式には2つの極限があります。
- 滑面の極限(\(\varepsilon/D_H \to 0\))では、粗さの項が消えて \(\dfrac{1}{\sqrt{\lambda}} = -2\log_{10}\left(\dfrac{2.51}{Re\sqrt{\lambda}}\right)\) となり、\(\lambda\) は \(Re\) だけで決まります。
- 完全粗面の極限(\(Re \to \infty\))では、粘性の項が消えて \(\dfrac{1}{\sqrt{\lambda}} = -2\log_{10}\left(\dfrac{\varepsilon}{3.71\,D_H}\right)\) となり、\(\lambda\) は \(\varepsilon/D_H\) だけで決まります。
適用上の注意は次のとおりです。
- 対象は乱流域(目安として \(Re \gtrsim 4000\))です。層流では \(\lambda = 64/Re\) を用います。
- 相対粗度 \(\varepsilon/D_H\) が極端に大きい場合(目安として 0.05 を超える場合)は、実験の範囲を外れます。
- \(\lambda\) が両辺に現れる陰関数のため、\(\lambda\) を求めるには反復計算(数値的な求根)が必要です。一方、\(\varepsilon\)、\(D_H\)、\(Re\) を求める場合は、式を変形して陽に解くことができます。
陽に解いた式は次のとおりです。
\[
\begin{eqnarray}
Re &=& \frac{2.51}{\sqrt{\lambda}\left(10^{-\frac{1}{2\sqrt{\lambda}}}-\dfrac{\varepsilon}{3.71\,D_H}\right)} \\
\varepsilon &=& 3.71\,D_H\left(10^{-\frac{1}{2\sqrt{\lambda}}}-\frac{2.51}{Re\sqrt{\lambda}}\right) \\
D_H &=& \frac{\varepsilon}{3.71\left(10^{-\frac{1}{2\sqrt{\lambda}}}-\dfrac{2.51}{Re\sqrt{\lambda}}\right)}
\end{eqnarray}
\tag{3}\]
\(\lambda\) については、\(x = 1/\sqrt{\lambda}\) とおいて
\[
\begin{eqnarray}
g(x) &=& x + 2\log_{10}\left(\frac{\varepsilon}{3.71\,D_H}+\frac{2.51\,x}{Re}\right) \;=\; 0
\end{eqnarray}
\tag{4}\]
を解きます。
ここで \(x\) は \(1/\sqrt{\lambda}\) です。
\(g(x)\) は \(x>0\) で単調増加ですので、解は区間内にただ1つ存在し、uniroot() で求めることが可能です。
Rコード
管摩擦係数 lambda、管の絶対粗度 epsilon、管の水力直径 D_H、レイノルズ数 Re のうち、いずれか3つを指定すると、残りの1つを返す関数です。
指定しなかった(NULL の)引数が求める値になります。
# コールブルック・ホワイトの式で、4変数のうち未指定の1つを求める関数
# lambda : 管摩擦係数(無次元)
# epsilon: 管の絶対粗度 [m]
# D_H : 管の水力直径 [m]
# Re : レイノルズ数(無次元)
colebrook_white <- function(lambda = NULL, epsilon = NULL, D_H = NULL, Re = NULL) {
# 引数の指定状況を確認する
args <- list(lambda = lambda, epsilon = epsilon, D_H = D_H, Re = Re)
unknown <- names(args)[vapply(args, is.null, logical(1))]
if (length(unknown) != 1L) {
stop("lambda, epsilon, D_H, Re のうち、ちょうど3つを指定してください。")
}
# 指定された値の妥当性を確認する
given <- args[setdiff(names(args), unknown)]
if (!all(vapply(given, is.numeric, logical(1)))) {
stop("すべての引数は数値で指定してください。")
}
if (any(unlist(given) < 0, na.rm = TRUE)) {
stop("負の値は指定できません。")
}
if (any(unlist(given[setdiff(names(given), "epsilon")]) == 0, na.rm = TRUE)) {
stop("lambda, D_H, Re に 0 は指定できません(epsilon のみ 0 を許容します)。")
}
# 管摩擦係数を求める(陰関数のため uniroot で数値的に解く)
# x = 1 / sqrt(lambda) とおき、g(x) = 0 の解を求める
solve_lambda <- function(epsilon, D_H, Re) {
a <- epsilon / (3.71 * D_H) # 相対粗度に由来する項
b <- 2.51 / Re # 粘性に由来する項の係数
if (a >= 1) {
warning("epsilon / D_H が大きすぎるため、解を求められません。")
return(NA_real_)
}
g <- function(x) x + 2 * log10(a + b * x)
x <- uniroot(g, interval = c(1e-6, 1e3), tol = 1e-12)$root
1 / x^2
}
result <- if (identical(unknown, "lambda")) {
# 複数の値を同時に与えた場合も計算できるよう、mapply で要素ごとに解く
mapply(solve_lambda, epsilon, D_H, Re)
} else {
# 陽に解ける3変数は、共通の項 10^(-1/(2*sqrt(lambda))) を使う
s <- sqrt(lambda)
p <- 10^(-1 / (2 * s))
if (identical(unknown, "Re")) {
denom <- s * (p - epsilon / (3.71 * D_H))
invalid <- denom <= 0
value <- 2.51 / denom
} else if (identical(unknown, "epsilon")) {
value <- 3.71 * D_H * (p - 2.51 / (Re * s))
invalid <- value < 0
} else {
# 未指定が D_H の場合
k <- p - 2.51 / (Re * s)
invalid <- k <= 0 | epsilon == 0
value <- epsilon / (3.71 * k)
}
if (any(invalid, na.rm = TRUE)) {
warning(
"与えた3つの値に対して解が存在しない組み合わせがあるため、NA を返します。",
"(lambda が滑面管の値より小さい、または epsilon = 0 のときの D_H など)"
)
value[invalid] <- NA_real_
}
value
}
# 乱流域の外では式の適用範囲を外れるため、注意を促す
re_check <- if (identical(unknown, "Re")) result else Re
if (any(re_check < 4000, na.rm = TRUE)) {
warning("Re が 4000 未満の値を含みます。コールブルック・ホワイトの式は乱流域(Re >= 4000 程度)が対象です。")
}
result
}使用例
円管(\(D_H = 0.1\) m)、商業用鋼管(\(\varepsilon = 0.045\) mm)、\(Re = 10^5\) のときの管摩擦係数を求めます。
# 管摩擦係数 lambda を求める
lambda_value <- colebrook_white(epsilon = 0.045e-3, D_H = 0.1, Re = 1e5)
lambda_value[1] 0.02011523求めた \(\lambda\) を使って、残りの3変数を逆算し、元の値に戻ることを確認します。
# 逆算して元の値に戻るかを確認する
epsilon <- colebrook_white(lambda = lambda_value, D_H = 0.1, Re = 1e5) # epsilon
D_H <- colebrook_white(lambda = lambda_value, epsilon = 0.045e-3, Re = 1e5) # D_H
Re <- colebrook_white(lambda = lambda_value, epsilon = 0.045e-3, D_H = 0.1) # Re
list(epsilon = epsilon, D_H = D_H, Re = Re)$epsilon
[1] 4.5e-05
$D_H
[1] 0.1
$Re
[1] 1e+05複数の値を同時に与えることもできます。レイノルズ数を変えたときの \(\lambda\) の変化を見てみます。
# Re を変化させて lambda を求める
re_seq <- 10^(4:7)
data.frame(
Re = re_seq,
lambda = colebrook_white(epsilon = 0.045e-3, D_H = 0.1, Re = re_seq)
) Re lambda
1 1e+04 0.03156739
2 1e+05 0.02011523
3 1e+06 0.01684944
4 1e+07 0.01635936単調増加と解の一意性
方程式の形
コールブルック・ホワイトの式に \(x = 1/\sqrt{\lambda}\) を代入し、全てを左辺に移すと次のようになります。
\[
\begin{eqnarray}
g(x) &=& x + 2\log_{10}\left(a + b\,x\right) \;=\; 0
\end{eqnarray}
\tag{5}\]
\[
\begin{eqnarray}
a &=& \frac{\varepsilon}{3.71\,D_H} \;\ge\; 0, \qquad b \;=\; \frac{2.51}{Re} \;>\; 0
\end{eqnarray}
\tag{6}\]
\(a\) は相対粗度に由来する定数、\(b\) は粘性に由来する定数で、どちらも \(x\) には依存しません。
求める \(\lambda\) は、\(x>0\) の範囲にある \(g(x)=0\) の解から \(\lambda = 1/x^2\) で得られます。
単調増加であること
\(g(x)\) を \(x\) で微分します。
\(\log_{10} u = \ln u / \ln 10\) を使うと、次のようになります。
\[
\begin{eqnarray}
g'(x) &=& 1 + \frac{2}{\ln 10}\cdot\frac{b}{a + b\,x}
\end{eqnarray}
\tag{7}\]
\(x>0\) では \(a + b\,x > 0\) であり、\(b>0\) です。したがって第2項は正になり、
\[
\begin{eqnarray}
g'(x) &>& 1 \;>\; 0
\end{eqnarray}
\tag{8}\]
となります。つまり \(g(x)\) は \(x>0\) の全域で厳密に単調増加です。
解が少なくとも1つ存在すること
\(g(x)\) は \(x>0\) で連続です。区間の両端での符号を調べます。
- \(x \to 0^+\) のとき、\(g(x) \to 2\log_{10} a\) です。\(a<1\)(\(\varepsilon/D_H < 3.71\))なら負になります。\(a=0\) の滑面管では \(g(x) \to -\infty\) です。
- \(x \to \infty\) のとき、\(x\) の項が支配的になり、\(g(x) \to +\infty\) です。
両端で符号が異なるため、中間値の定理により \(g(x)=0\) となる \(x\) が少なくとも1つ存在します。
解がただ1つであること
厳密に単調増加な関数は、同じ値を2回とりません。
仮に \(x_1 < x_2\) がともに解なら \(g(x_1) < g(x_2)\) となり、\(g(x_1) = g(x_2) = 0\) と矛盾します。
よって解はちょうど1つです。
さらに、\(\lambda = 1/x^2\) は \(x>0\) で一対一の対応ですので、\(\lambda\) の解もただ1つに決まります。
コードとの対応
コードでは、探索区間を interval = c(1e-6, 1e3) としています。
この区間で符号が変わること(\(g(10^{-6})<0\) かつ \(g(10^3)>0\))が、uniroot() を使うための条件です。
- \(g(10^3)>0\) は、\(Re\) が極端に大きくない限り、常に成り立ちます。
- \(g(10^{-6})<0\) は、ほぼ \(a<1\) と同じ条件です。コードの
if (a >= 1)は、この条件を確認するためのものです。
実用上は、相対粗度 \(\varepsilon/D_H\) が 0.05 程度以下であれば、この条件には余裕があります。
式 7 の導出
\(g(x)\) は2つの項の和ですので、項ごとに微分します。
\[
\begin{eqnarray}
g(x) &=& x + 2\log_{10}\left(a + b\,x\right)
\end{eqnarray}
\tag{9}\]
ここで \(a = \dfrac{\varepsilon}{3.71\,D_H}\)、\(b = \dfrac{2.51}{Re}\) は \(x\) に依存しない定数です。
項ごとの微分
微分の線形性より、次のようになります。
\[
\begin{eqnarray}
g'(x) &=& \frac{d}{dx}\,x \;+\; 2\,\frac{d}{dx}\log_{10}\left(a + b\,x\right)
\end{eqnarray}
\tag{10}\]
第1項は \[\dfrac{d}{dx}\,x = 1 \tag{11}\] です。
常用対数を自然対数に直す
底の変換公式 \(\log_{10} u = \dfrac{\ln u}{\ln 10}\) を使います。\(\ln 10\) は定数です。
\[
\begin{eqnarray}
\frac{d}{dx}\log_{10}\left(a + b\,x\right) &=& \frac{1}{\ln 10}\cdot\frac{d}{dx}\ln\left(a + b\,x\right)
\end{eqnarray}
\tag{12}\]
合成関数の微分
\(u = a + b\,x\) とおくと、\(\ln u\) の微分は合成関数の微分(連鎖律)から、
\[
\begin{eqnarray}
\frac{d}{dx}\ln u &=& \frac{1}{u}\cdot\frac{du}{dx}
\end{eqnarray}
\tag{13}\]
となります。\(a\) と \(b\) は定数ですので、
\[
\begin{eqnarray}
\frac{du}{dx} &=& \frac{d}{dx}\left(a + b\,x\right) \;=\; b
\end{eqnarray}
\tag{14}\]
です。したがって、
\[
\begin{eqnarray}
\frac{d}{dx}\ln\left(a + b\,x\right) &=& \frac{b}{a + b\,x}
\end{eqnarray}
\tag{15}\]
となります。
最終導出
式 10 に 式 11 、式 12、式 15 を代入します。
\[
\begin{eqnarray}
g'(x) &=& 1 + 2\cdot\frac{1}{\ln 10}\cdot\frac{b}{a + b\,x} \\
&=& 1 + \frac{2}{\ln 10}\cdot\frac{b}{a + b\,x}
\end{eqnarray}
\tag{16}\]
式 7 が導出されます。
補足(符号の確認)
\(x>0\) では \(a + b\,x > 0\) です(\(a \ge 0\)、\(b>0\) のため)。また \(\ln 10 \approx 2.303 > 0\) です。そのため第2項は常に正になり、
\[
\begin{eqnarray}
g'(x) &>& 1
\end{eqnarray}
\tag{17}\]
が成り立ちます。これが「\(g(x)\) は単調増加」の根拠です。
\(a \ge 1\) のとき解がない理由
\(x \to 0^+\) のとき \(g(x) \to 2\log_{10} a\) です。\(a \ge 1\) ならこの極限値は \(0\) 以上になります。
\(g(x)\) は \(x>0\) で厳密に単調増加ですので、\(x>0\) の全てで \(g(x)\) は \(2\log_{10} a\) より大きくなり、
\[
\begin{eqnarray}
g(x) &>& 2\log_{10} a \;\ge\; 0 \qquad (x>0)
\end{eqnarray}
\tag{18}\]
となります。
したがって \(g(x)=0\) となる \(x>0\) は存在しません(\(a=1\) の場合も、\(x=0\) に近づくだけで \(x>0\) では \(g(x)>0\) です)。
よって、解が存在する条件は次のとおりです。
\[
\begin{eqnarray}
\text{解が存在する} &\Longleftrightarrow& a < 1 \;\Longleftrightarrow\; \frac{\varepsilon}{D_H} < 3.71
\end{eqnarray}
\tag{19}\]
なお、
- \(\varepsilon/D_H \ge 3.71\) は、粗さの高さが管の直径の3.7倍以上という意味で、物理的にありえません。円管では、粗さの高さが半径(\(\varepsilon/D_H = 0.5\))を超えることもほとんど想定されません。
- コールブルック・ホワイトの式が実験で裏付けられている範囲は、\(\varepsilon/D_H \lesssim 0.05\) 程度です。\(a = \varepsilon/(3.71\,D_H)\) に直すと約 \(0.013\) で、\(1\) にはまだ遠く離れています。
コードでの扱い
solve_lambda() には if (a >= 1) の確認を入れてあり、その場合は警告を出して NA を返します。
以上です。
