Rで有限要素法:片持ち梁-自由端に集中モーメント:たわみ量

本ポストはこちらの続きです。

Rで有限要素法:梁要素の剛性行列
const typesetMath = (el) => { if (window.MathJax) { // MathJax Typeset window.MathJax.typeset(); } else if (window.katex...

片持ち梁-自由端に集中モーメント

Figure 1

片持ち梁のたわみ:FEM(オイラー・ベルヌーイ梁要素) vs 厳密解

# ============================================================
# 片持ち梁のたわみ(自由端に集中モーメント):FEM vs 厳密解
# ============================================================
#
# 厳密解(xは自由端Aから測った距離):
#   w(x)  = -(M0/2EI)(x-l)^2
#   w_max = -(M0 l^2)/(2EI)     [x = 0, 自由端]
#   θ(x)  = -(M0 l/EI)(1-x/l)
#   θ_A   = -(M0 l)/EI
#
#   s   : FEM座標(固定端起点、s=0で固定端、s=lで自由端)
#   x   : 厳密解の座標(自由端起点、x = l - s)
#
# 集中モーメントの載荷のため、分布荷重のような積分は不要。
# 自由端節点(s=l)の「傾き」自由度に、直接モーメントを与えるだけでよい。
# ただし、厳密解のx方向とFEMのs方向が逆向きのため、
# 載荷するモーメントの符号は -M0 とする必要がある。

library(ggplot2)

# ------------------------------------------------------------
# 1. 梁の諸元と荷重の設定
# ------------------------------------------------------------
l <- 2.0
M0 <- 2000 # 自由端に作用する集中モーメント [N・m]
E <- 210e9
I <- 4.1667e-6
EI <- E * I

# ------------------------------------------------------------
# 2. 梁要素の剛性行列
# ------------------------------------------------------------
beam_element_k <- function(Le) {
  (EI / Le^3) * matrix(c(
    12, 6 * Le, -12, 6 * Le,
    6 * Le, 4 * Le^2, -6 * Le, 2 * Le^2,
    -12, -6 * Le, 12, -6 * Le,
    6 * Le, 2 * Le^2, -6 * Le, 4 * Le^2
  ), nrow = 4, byrow = TRUE)
}

# ------------------------------------------------------------
# 3. メッシュ生成・全体行列への組み込み
# ------------------------------------------------------------
n_elem <- 4L
Le <- l / n_elem
n_node <- n_elem + 1L
n_dof <- 2L * n_node

K <- matrix(0, n_dof, n_dof)
F <- numeric(n_dof)
K_e <- beam_element_k(Le)

for (e in seq_len(n_elem)) {
  dofs <- c(2 * e - 1, 2 * e, 2 * e + 1, 2 * e + 2)
  K[dofs, dofs] <- K[dofs, dofs] + K_e
}

# ------------------------------------------------------------
# 4. 荷重の載荷:自由端(最終節点)の傾き自由度に直接モーメントを与える
# ------------------------------------------------------------
F[n_dof] <- F[n_dof] - M0 # 符号は座標の向きの違いにより -M0

# ------------------------------------------------------------
# 5. 境界条件(固定端: w=0, θ=0)
# ------------------------------------------------------------
fixed_dofs <- c(1, 2)
free_dofs <- setdiff(seq_len(n_dof), fixed_dofs)

u <- numeric(n_dof)
u[free_dofs] <- solve(K[free_dofs, free_dofs], F[free_dofs])

w_fem <- u[seq(1, n_dof, by = 2)]
th_fem <- u[seq(2, n_dof, by = 2)]

s_nodes <- seq(0, l, length.out = n_node)
x_nodes <- l - s_nodes

# ------------------------------------------------------------
# 6. 厳密解との比較
# ------------------------------------------------------------
w_exact_fn <- function(x) -(M0 / (2 * EI)) * (x - l)^2

comparison <- data.frame(
  自由端起点_x_m = round(x_nodes, 3),
  FEM近似解_mm = round(w_fem * 1000, 8),
  厳密解_mm = round(w_exact_fn(x_nodes) * 1000, 8),
_mm = w_fem * 1000 - w_exact_fn(x_nodes) * 1000
)
print(comparison)

cat("\n自由端でのたわみ量:\n")
cat("  FEM近似解:", w_fem[n_node] * 1000, "mm\n")
cat("  厳密解    :", -(M0 * l^2) / (2 * EI) * 1000, "mm  (公式: w_max = -M0 l^2 / 2EI)\n")

# ------------------------------------------------------------
# 7. 可視化
# ------------------------------------------------------------
hermite_w <- function(xi, Le, w1, th1, w2, th2) {
  N1 <- 1 - 3 * xi^2 + 2 * xi^3
  N2 <- Le * (xi - 2 * xi^2 + xi^3)
  N3 <- 3 * xi^2 - 2 * xi^3
  N4 <- Le * (-xi^2 + xi^3)
  N1 * w1 + N2 * th1 + N3 * w2 + N4 * th2
}

fem_curve <- do.call(rbind, lapply(seq_len(n_elem), function(e) {
  xi_seq <- seq(0, 1, length.out = 20)
  w1 <- w_fem[e]
  th1 <- th_fem[e]
  w2 <- w_fem[e + 1]
  th2 <- th_fem[e + 1]
  s_local <- s_nodes[e] + xi_seq * Le
  data.frame(x = l - s_local, w_mm = hermite_w(xi_seq, Le, w1, th1, w2, th2) * 1000)
}))

x_fine <- seq(0, l, length.out = 300)
exact_curve <- data.frame(x = x_fine, w_mm = w_exact_fn(x_fine) * 1000)

p <- ggplot() +
  geom_line(data = exact_curve, aes(x = x, y = w_mm, color = "厳密解"), linewidth = 1.2) +
  geom_line(
    data = fem_curve, aes(x = x, y = w_mm, color = "FEM(要素内補間)"),
    linetype = "dashed", linewidth = 0.8
  ) +
  geom_point(
    data = data.frame(x = x_nodes, w_mm = w_fem * 1000),
    aes(x = x, y = w_mm, color = "FEM(節点)"), size = 2
  ) +
  scale_color_manual(values = c(
    "厳密解" = "gray40", "FEM(要素内補間)" = "steelblue",
    "FEM(節点)" = "firebrick"
  ), name = "") +
  labs(
    title = "自由端に集中モーメントを受ける片持ち梁:FEM vs 厳密解",
    subtitle = "厳密解が2次式のため、要素内部も含めて完全に一致する",
    x = "自由端からの距離 x [m]", y = "たわみ量 w [mm]"
  ) +
  theme_minimal(base_size = 12)

print(p)
  自由端起点_x_m FEM近似解_mm 厳密解_mm         差_mm
1            2.0     0.000000  0.000000  0.000000e+00
2            1.5    -0.285712 -0.285712 -2.053913e-15
3            1.0    -1.142848 -1.142848 -2.442491e-15
4            0.5    -2.571408 -2.571408 -4.440892e-16
5            0.0    -4.571392 -4.571392  0.000000e+00

自由端でのたわみ量:
  FEM近似解: -4.571392 mm
  厳密解    : -4.571392 mm  (公式: w_max = -M0 l^2 / 2EI)
Figure 2

厳密解の公式

  • 出典 : 「構造力学公式集 昭和61年版」(土木学会)

反力・せん断力

\[\begin{eqnarray}R_B &=& 0\\M_B &=& M_0\\Q &=& 0\end{eqnarray}\]

曲げモーメント

\[\begin{eqnarray}M &=& M_0 = M_{\max}\end{eqnarray}\]

たわみ

\[\begin{eqnarray}
w &=& -\frac{M_0}{2EI}(x-l)^2\\
w_{\max} &=& -\frac{M_0 l^2}{2EI}, \quad [x = 0]
\end{eqnarray}\]

たわみ角

\[\begin{eqnarray}
\theta &=& -\frac{M_0 l}{EI}\left(1-\frac{x}{l}\right)\\
\theta_A &=& -\frac{M_0 l}{EI}
\end{eqnarray}\]

以上です。