Ana Sayfa / MATLAB / Python / Problem 8

Kabuk Kırılması — Sonlu Fark mı, Kesin Çözüm mü?

1 m kalınlığında duvar, kısa ve şiddetli darbe (Pr = 5 MPa, td = 0,1 ms). Basınç dalgası serbest arka yüzden çekme olarak yansır. Kuram açıktır: kalın duvar ve kısa darbede yansıyan çekme, gelen tepeye eşittir — σt/σ0 = 1.

Kod çalışıyor ama yanlış. Açık sonlu fark şeması keskin darbe cephesinde sahte salınım üretir ve σt/σ0 = 1,211 verir — doğrusal elastik bir dalgada fiziksel olarak imkânsız bir değer: yansıyan çekme gelen tepeyi aşamaz. Kesin d'Alembert çözümü ise 1,000 verir. Bu, bir patlama analiz paketinin kabuk kırılması rutininde bulunan gerçek bir hatadır; site aracı artık kesin çözümü kullanır.

İkinci ders — denetimin kendisi de yanlış olabilir. Bu hatayı ararken önce "ince duvarda çekme σ0·2t/λ ile sönümlenir" diye analitik bir kontrol yazıldı. O formül yalnızca ilk yansımayı sayıyordu; sönümsüz bir levhada çoklu yansımalar çekmeyi gelen tepeye yaklaştırır. Kesin çözüm hem koddaki hatayı hem de denetimdeki hatayı birlikte ortaya çıkardı.

Kullanılan fiziksel sınır: "yansıyan çekme ≤ gelen tepe". Sayısal bir sonucu bir fiziksel sınırla karşılaştırmak, en ucuz ve en güçlü doğrulama araçlarından biridir.

PYTHON spall_fd_vs_exact.py

# spall_fd_vs_exact.py -- Kabuk kirilmasi: acik sonlu fark semasi vs KESIN cozum
# Ayni problem iki yolla. Dogrusal elastik bir dalgada yansiyan cekme gelen
# tepeyi ASAMAZ; kalin duvar + kisa darbede kesin sonuc sigma_t/sigma_0 = 1.
import numpy as np

E, nu, rho = 30e9, 0.2, 2400.0
t  = 1.0                     # m, duvar kalinligi
Pr, ir = 5e6, 250.0          # Pa, Pa.s  -> td = 0.1 ms (kisa darbe)
td = 2*ir/Pr
M  = E*(1-nu)/((1+nu)*(1-2*nu))      # kisitli modul
c  = np.sqrt(M/rho); T = t/c
load = lambda s: np.where((s >= 0) & (s <= td), Pr*(1 - s/td), 0.0)

# --- 1) Acik sonlu fark (orijinal spallCheck.m semasi) ---
nel = 80; he = t/nel; dt = 0.5*he/c
mN = np.full(nel+1, rho*he); mN[[0, -1]] /= 2
u = np.zeros(nel+1); v = np.zeros(nel+1); smin_fd = 0.0
for tt in np.arange(0, td + 4*T, dt):
    s = M*(u[:-1] - u[1:])/he            # basinc +
    f = np.zeros(nel+1); f[0] = load(tt)
    f[:-1] -= s; f[1:] += s
    v += dt*f/mN; u += dt*v
    smin_fd = min(smin_fd, s.min())

# --- 2) KESIN cozum (d'Alembert):  sigma = f(tau - x/c) - f(tau + x/c - 2T),
#        f(tau) = p(tau) + f(tau - 2T)   ->   f(tau) = sum_k p(tau - 2kT)
def F(tau):
    out = np.zeros_like(tau)
    for kk in range(int(np.max(tau)/(2*T)) + 2):
        out += load(tau - 2*kk*T)
    return out
x = np.linspace(0, t, 81); smin_ex = 0.0
for tau in np.linspace(0, td + 6*T, 3001):
    sig = F(tau - x/c) - F(tau + x/c - 2*T)
    smin_ex = min(smin_ex, sig.min())

print(f"dalga hizi c = {c:.0f} m/s   td = {td*1e3:.3f} ms   T = t/c = {T*1e6:.1f} us")
print(f"Sonlu fark : sigma_t/sigma_0 = {-smin_fd/Pr:.3f}")
print(f"Kesin cozum: sigma_t/sigma_0 = {-smin_ex/Pr:.3f}   (kuram: 1.000)")
print(f"Sonlu fark asimi = %{(smin_fd/smin_ex - 1)*100:.1f}")
dalga hizi c = 3727 m/s td = 0.100 ms T = t/c = 268.3 us Sonlu fark : sigma_t/sigma_0 = 1.211 Kesin cozum: sigma_t/sigma_0 = 1.000 (kuram: 1.000) Sonlu fark asimi = %21.1

✓ Bu kod Python 3 ile gerçekten çalıştırıldı — çıktı yukarıdaki kutudur.

MATLAB spall_fd_vs_exact.m

% spall_fd_vs_exact.m -- Kabuk kirilmasi: acik sonlu fark semasi vs KESIN cozum
% Dogrusal elastik dalgada yansiyan cekme gelen tepeyi ASAMAZ; kalin duvar +
% kisa darbede kesin sonuc sigma_t/sigma_0 = 1.
function spall_fd_vs_exact()
  E = 30e9; nu = 0.2; rho = 2400;
  t = 1.0;  Pr = 5e6; ir = 250;
  td = 2*ir/Pr;
  M  = E*(1-nu)/((1+nu)*(1-2*nu));
  c  = sqrt(M/rho); T = t/c;
  load = @(s) (s >= 0 & s <= td) .* Pr .* (1 - s/td);

  % --- 1) Acik sonlu fark (orijinal spallCheck.m semasi) ---
  nel = 80; he = t/nel; dt = 0.5*he/c;
  mN = rho*he*ones(nel+1,1); mN([1 end]) = mN([1 end])/2;
  u = zeros(nel+1,1); v = zeros(nel+1,1); smin_fd = 0;
  for tt = 0:dt:(td + 4*T)
    s = M*(u(1:end-1) - u(2:end))/he;
    f = zeros(nel+1,1); f(1) = load(tt);
    f(1:end-1) = f(1:end-1) - s;  f(2:end) = f(2:end) + s;
    v = v + dt*f./mN;  u = u + dt*v;
    smin_fd = min(smin_fd, min(s));
  end

  % --- 2) KESIN cozum (d'Alembert) ---
  x = linspace(0, t, 81); smin_ex = 0;
  for tau = linspace(0, td + 6*T, 3001)
    sig = F(tau - x/c, load, T) - F(tau + x/c - 2*T, load, T);
    smin_ex = min(smin_ex, min(sig));
  end
  fprintf('dalga hizi c = %.0f m/s   td = %.3f ms   T = t/c = %.1f us\n', c, td*1e3, T*1e6);
  fprintf('Sonlu fark : sigma_t/sigma_0 = %.3f\n', -smin_fd/Pr);
  fprintf('Kesin cozum: sigma_t/sigma_0 = %.3f   (kuram: 1.000)\n', -smin_ex/Pr);
  fprintf('Sonlu fark asimi = %%%.1f\n', (smin_fd/smin_ex - 1)*100);
end

function out = F(tau, load, T)
  out = zeros(size(tau));
  for kk = 0:(floor(max(tau)/(2*T)) + 1)
    out = out + load(tau - 2*kk*T);
  end
end
dalga hizi c = 3727 m/s td = 0.100 ms T = t/c = 268.3 us Sonlu fark : sigma_t/sigma_0 = 1.211 Kesin cozum: sigma_t/sigma_0 = 1.000 (kuram: 1.000) Sonlu fark asimi = %21.1

✓ Bu kod GNU Octave 8.4 (MATLAB uyumlu) ile gerçekten çalıştırıldı — çıktı Python ile karakter karakter aynıdır.

↓ spall_fd_vs_exact.py İndir ↓ spall_fd_vs_exact.m İndir ← MATLAB / Python ← Problem 7 Vaka: kod neden yanlıştı →