পাঠ ৩৬ · ৫৭-এর মধ্যে · মডিউল ৭
Home / Courses / Numerical Methods / হিট ইকুয়েশন FD

হিট ইকুয়েশনের জন্য ফাইনাইট ডিফারেন্স

Finite difference for the heat equation
১২ মিনিট পড়া উচ্চতর · Advanced Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • FTCS এক্সপ্লিসিট স্কিম কীভাবে হিট ইকুয়েশনকে একটি ছোট গ্রিডে ধাপে ধাপে সমাধান করে
  • একটি সত্যিকারের, চলমান Python ডেমো — তাপমাত্রা প্রোফাইল সময়ের সাথে সত্যিকারভাবে ডিফিউজ হতে দেখা
  • ফলাফল একটি জানা বন্ধ-আকারের সমাধানের বিপরীতে যাচাই করা
  • CFL-সদৃশ স্থিতিশীলতা শর্ত এবং এটি লঙ্ঘন করলে সত্যিকারের সংখ্যাসূচক বিস্ফোরণ পর্যবেক্ষণ করা

১ · এক্সপ্লিসিট FTCS স্কিম

১ডি হিট ইকুয়েশন $u_t = \alpha u_{xx}$-এ সময়ের ডেরিভেটিভ ফরওয়ার্ড ডিফারেন্স দিয়ে ও স্থানের দ্বিতীয় ডেরিভেটিভ সেন্ট্রাল ডিফারেন্স দিয়ে (L34-এর মতো, M5/L21) আনুমানিক করলে:

$$\frac{u_i^{n+1} - u_i^n}{\Delta t} = \alpha \cdot \frac{u_{i+1}^n - 2u_i^n + u_{i-1}^n}{\Delta x^2}$$

এখান থেকে $u_i^{n+1}$-কে সরাসরি বিচ্ছিন্ন করা যায় (তাই "এক্সপ্লিসিট"):

$$u_i^{n+1} = u_i^n + r\left(u_{i+1}^n - 2u_i^n + u_{i-1}^n\right), \qquad r = \frac{\alpha \Delta t}{\Delta x^2}$$

এখানে $r$ হলো একটি মাত্রাহীন সংখ্যা যা সময়-ধাপ ও স্থান-ধাপের অনুপাত নিয়ন্ত্রণ করে। L34-এর BVP-এর মতো এখানেও গ্রিড list of lists হিসেবে রাখা হয়েছে — প্রতিটি সারি একটি সময়-মুহূর্তের সম্পূর্ণ স্থানিক প্রোফাইল।

ফরওয়ার্ড-টাইম
সময়ে একটি সরল ফরওয়ার্ড ডিফারেন্স — বর্তমান ধাপ থেকে পরবর্তী ধাপ সরাসরি গণনা করা যায় (M6/L27-এর Euler-এর সদৃশ)।
সেন্ট্রাল-স্পেস
স্থানে একটি সেন্ট্রাল ডিফারেন্স — L34-এর BVP-স্কিমের ঠিক একই ফর্মুলা, শুধু এখন প্রতিটি সময়-ধাপে পুনরায় প্রয়োগ করা হয়।
স্থিতিশীলতা শর্ত
$r \le 0.5$ — এটিই এই স্কিমের CFL-সদৃশ বাউন্ড, যা লঙ্ঘন করলে সমাধান সংখ্যাসূচকভাবে অস্থিতিশীল হয়ে ওঠে (নিচে সত্যিকারের ডেমো)।
CFL শর্ত সংক্ষেপে

একটি এক্সপ্লিসিট স্কিমে সময়-ধাপ Δt অবশ্যই স্থান-ধাপ Δx-এর সাপেক্ষে যথেষ্ট ছোট হতে হবে, নয়তো স্কিম প্রতি ধাপে যে তথ্য "প্রচার" করছে তা প্রকৃত ভৌত প্রক্রিয়ার চেয়ে দ্রুত ছড়িয়ে পড়ার চেষ্টা করে — এবং সংখ্যাসূচক গণনা ভেঙে পড়ে। এটিই Courant–Friedrichs–Lewy (CFL) শর্তের মূল ধারণা, M6/L32-এর ODE স্টিফনেস-স্ট্যাবিলিটি আলোচনার একটি PDE-সংস্করণ। হিট ইকুয়েশনের FTCS স্কিমে সুনির্দিষ্ট বাউন্ড $r \le 0.5$।

২ · একটি সত্যিকারের ডেমো — তাপমাত্রা প্রোফাইল ডিফিউজ হচ্ছে

ডোমেইন [0,1], α=1, 10টি স্থানিক ইন্টারভাল (11টি গ্রিড-বিন্দু, Δx=0.1), শুরুর প্রোফাইল u(x,0) = sin(πx), বাউন্ডারি u(0,t)=u(1,t)=0। নির্ভুল সমাধান জানা: $u(x,t) = \sin(\pi x)\,e^{-\pi^2 t}$ (যেহেতু $\sin(\pi x)$ হিট অপারেটরের একটি আইগেনফাংশন — M8-এ আইগেনভ্যালুর ধারণা বিস্তারিত)।

Python
import math

alpha = 1.0
Nx = 10                 # স্থানিক ইন্টারভাল সংখ্যা -> ১১টি গ্রিড-বিন্দু
dx = 1.0 / Nx
xs = [i*dx for i in range(Nx+1)]

def initial_condition(x):
    return math.sin(math.pi*x)

def run_ftcs(r, dt, steps):
    u = [initial_condition(x) for x in xs]
    u[0] = 0.0; u[-1] = 0.0
    history = [u[:]]                 # list of lists: প্রতিটি সারি এক সময়-ধাপের প্রোফাইল
    for n in range(steps):
        new = u[:]
        for i in range(1, Nx):
            new[i] = u[i] + r*(u[i+1] - 2*u[i] + u[i-1])
        new[0] = 0.0; new[-1] = 0.0
        u = new
        history.append(u[:])
    return history

r_stable = 0.4                       # CFL-সদৃশ শর্ত: r <= 0.5 (স্থিতিশীল)
dt_stable = r_stable * dx*dx / alpha
print(f"dx={dx}  dt={dt_stable:.6f}  r={r_stable}")

steps = 5
hist = run_ftcs(r_stable, dt_stable, steps)

print()
print("তাপমাত্রা প্রোফাইলের বিবর্তন (স্থিতিশীল, r=0.4):")
print("ধাপ  " + "".join(f"x={x:.1f}".rjust(9) for x in xs))
for n, row in enumerate(hist):
    print(f"{n:4d} " + "".join(f"{v:9.5f}" for v in row))

t_final = steps*dt_stable
print()
print(f"t_final = {t_final:.4f}")
print(f"{'x':>6} {'FD u(x,t)':>12} {'নির্ভুল':>12} {'|এরর|':>10}")
for i, x in enumerate(xs):
    exact = math.sin(math.pi*x) * math.exp(-math.pi**2 * alpha * t_final)
    fd = hist[-1][i]
    print(f"{x:6.2f} {fd:12.6f} {exact:12.6f} {abs(fd-exact):10.2e}")

max_err = max(abs(hist[-1][i] - math.sin(math.pi*xs[i])*math.exp(-math.pi**2*alpha*t_final)) for i in range(Nx+1))
print()
print("সর্বোচ্চ |এরর| t_final-এ:", max_err)

    
লক্ষ্য করুন — কেন্দ্রীয় বিন্দু x=0.5-এর মান প্রতিটি ধাপে কমছে: 1.00000 → 0.96085 → 0.92322 → 0.88707 → 0.85234 → 0.81897 — সাইন-আকৃতির প্রোফাইলটি সময়ের সাথে ধীরে ধীরে সমতল হয়ে যাচ্ছে, ঠিক ডিফিউশনের ভৌত প্রত্যাশা অনুযায়ী। ৫ ধাপ পর (t=0.02) FD ফলাফল নির্ভুল সমাধানের সাথে সর্বোচ্চ ১.৯০ × ১০⁻³ এরর-এ মেলে — একটি মাত্র 10×5 আকারের ছোট গ্রিডে চমৎকার নির্ভুলতা।

৩ · স্থিতিশীলতা শর্ত সত্যিই লঙ্ঘন করে দেখা

উপরের স্মুথ সাইন প্রোফাইলে r=0.6 ব্যবহার করলেও তাৎক্ষণিকভাবে অস্থিতিশীলতা দেখা যায় না, কারণ সবচেয়ে অস্থিতিশীল মোড (সর্বোচ্চ-ফ্রিকোয়েন্সি, বিকল্প-চিহ্ন প্যাটার্ন) স্মুথ সাইন প্রোফাইলে প্রায় অনুপস্থিত। তাই একটি স্পাইক (একটি বিন্দুতে ১, বাকি সব 0) শুরুর শর্ত হিসেবে ব্যবহার করা হয়েছে — এটি সব ফ্রিকোয়েন্সি মোড উত্তেজিত করে, ফলে অস্থিতিশীলতা দ্রুত দৃশ্যমান হয়।

Python
def run_ftcs_spike(r, steps):
    u = [0.0]*(Nx+1)
    u[Nx//2] = 1.0     # কেন্দ্রে স্পাইক -- সব ফ্রিকোয়েন্সি মোড উত্তেজিত করে
    history = [u[:]]
    for n in range(steps):
        new = u[:]
        for i in range(1, Nx):
            new[i] = u[i] + r*(u[i+1] - 2*u[i] + u[i-1])
        new[0] = 0.0; new[-1] = 0.0
        u = new
        history.append(u[:])
    return history

print(f"{'r':>6} {'কেন্দ্র বিন্দুর মান, ধাপ 0..8':<70} {'স্থিতিশীল?':>12}")
for r in [0.4, 0.6, 0.9]:
    hist = run_ftcs_spike(r, 8)
    center_vals = [row[Nx//2] for row in hist]
    stable = "হ্যাঁ (r<=0.5)" if r <= 0.5 else "না (r>0.5)"
    vals_str = ", ".join(f"{v:.4f}" for v in center_vals)
    print(f"{r:6.1f} {vals_str:<70} {stable:>12}")

    
ফলাফল স্পষ্ট — r=0.4-এ (স্থিতিশীল) কেন্দ্র বিন্দুর মান 1.0000 → 0.2000 → 0.3600 → 0.2000 → 0.2320 → ... — দুলছে কিন্তু বাউন্ডেড, এবং ধীরে ধীরে একটি ছোট মানের দিকে মিশে যাচ্ছে (≈0.155)। কিন্তু r=0.6-এ (অস্থিতিশীল) মান 1.0000 → -0.2000 → 0.7600 → -0.4400 → 0.9520 → -0.8355 → 1.4170 → -1.5289 → 2.3092 — চিহ্ন প্রতি ধাপে উল্টাচ্ছে এবং মান বাড়ছে, স্পষ্ট সংখ্যাসূচক অস্থিতিশীলতা। r=0.9-এ মাত্র ৮ ধাপে মান 345.53-এ পৌঁছায় — সম্পূর্ণ বিস্ফোরণ। এটিই $r \le 0.5$ শর্তের বাস্তব, পরিমাপযোগ্য পরিণতি — কোনো ধরনের "কল্পিত" সতর্কতা নয়, বরং একটি সত্যিকারের কোড রান করলে যা ঘটে তা-ই।
মূল কথা · Key takeaway

এক্সপ্লিসিট FTCS স্কিম সহজবোধ্য ও বাস্তবায়ন করা সহজ, কিন্তু r-এর উপর একটি কঠোর সীমা মেনে চলতে হয় — যা ছোট Δx-এর জন্য Δt-কে অত্যন্ত ছোট হতে বাধ্য করে (r ∝ Δt/Δx², তাই Δx অর্ধেক করলে Δt চার ভাগের এক ভাগ করতে হয়)। ইমপ্লিসিট স্কিম (যেমন Crank-Nicolson) — এই কোর্সের সুযোগের বাইরে — এই সীমাবদ্ধতা এড়াতে পারে, কিন্তু প্রতিটি ধাপে L34-এর মতো একটি ট্রাইডায়াগোনাল সিস্টেম সমাধান করার প্রয়োজন হয়।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ স্মুথ সাইন প্রোফাইলে r=0.6 ব্যবহার করলে (৫ ধাপে) কোনো দৃশ্যমান অস্থিতিশীলতা দেখা যায় না, কিন্তু স্পাইক প্রোফাইলে ৮ ধাপেই স্পষ্ট বিস্ফোরণ দেখা যায়। এই পার্থক্য কেন গুরুত্বপূর্ণ — অস্থিতিশীলতা নেই দেখলেই কি একটি স্কিমকে "স্থিতিশীল" বলা নিরাপদ?

না — এটিই এই ডেমোর মূল শিক্ষা। r=0.6 তাত্ত্বিকভাবে অস্থিতিশীল (r>0.5), কিন্তু অস্থিতিশীলতা প্রকাশ পায় সর্বোচ্চ-ফ্রিকোয়েন্সি মোডের মাধ্যমে, আর একটি স্মুথ শুরুর শর্তে সেই মোডের পরিমাণ এত কম যে অস্থিতিশীলতা দৃশ্যমান হতে অনেক বেশি ধাপ লাগতে পারে। তাই শুধু "কয়েক ধাপ চালিয়ে কিছু বিস্ফোরিত হলো না" দেখে একটি স্কিমকে স্থিতিশীল বলা বিপজ্জনক — তাত্ত্বিক স্থিতিশীলতা শর্ত ($r\le 0.5$) সবসময় স্বাধীনভাবে যাচাই করা উচিত, শুধু পর্যবেক্ষণের উপর ভরসা না করে।

প্র ০২ স্থিতিশীল ডেমোতে (r=0.4) সাইন প্রোফাইলের সর্বোচ্চ মান প্রতিটি ধাপে কমছে কিন্তু কখনো ঋণাত্মক হচ্ছে না, আর স্পাইক ডেমোর r=0.4 কেসে কেন্দ্র বিন্দুর মান দুলছে (কখনো কম, কখনো একটু বেশি) কিন্তু বিস্ফোরিত হচ্ছে না। এই দুই ধরনের আচরণ কি একই "স্থিতিশীলতা"?

হ্যাঁ — স্থিতিশীলতার সংজ্ঞা হলো এরর/পার্টার্বেশন সময়ের সাথে বাউন্ডেড থাকা (বাড়তে থাকা নয়), দোলন সম্পূর্ণ অনুপস্থিত থাকা নয়। স্পাইকের মতো একটি "রুক্ষ" (non-smooth) শুরুর শর্তে r=0.4 -তেও প্রাথমিক ধাপে কিছুটা দোলন দেখা স্বাভাবিক (কারণ স্পাইকে উচ্চ-ফ্রিকোয়েন্সি উপাদান আছে, যা কম দ্রুত ডিক্যে হয়), কিন্তু সেই দোলনের বিস্তার (amplitude) সময়ের সাথে কমছে, বাড়ছে না — এটিই স্থিতিশীল আচরণ। অস্থিতিশীল কেসে (r=0.6) দোলনের বিস্তার প্রতিটি ধাপে বাড়ছে — এই বৃদ্ধিই মূল পার্থক্য।

প্র ০৩ এই স্কিমে স্থিতিশীলতা শর্ত r ≤ 0.5 মানে Δx অর্ধেক করলে Δt-কে চার ভাগের এক ভাগ করতে হয়। এর ব্যবহারিক (প্র্যাক্টিক্যাল) পরিণতি কী?

একটি সূক্ষ্ম স্থানিক গ্রিড (বেশি নির্ভুলতার জন্য) ব্যবহার করলে সময়-ধাপ সংখ্যা অনেক বেশি বেড়ে যায় — Δx দশগুণ ছোট করলে (নির্ভুলতা বাড়াতে) Δt-কে ১০০ গুণ ছোট করতে হয়, অর্থাৎ একই সময়কাল কভার করতে ১০০ গুণ বেশি সময়-ধাপ লাগবে — কম্পিউটেশনাল খরচ দ্রুত বেড়ে যায়। এটিই বাস্তবে কেন ইমপ্লিসিট স্কিম (Crank-Nicolson, বা L34-এর মতো ট্রাইডায়াগোনাল সিস্টেম প্রতি ধাপে সমাধান করা) গুরুত্বপূর্ণ হয়ে ওঠে — সেগুলো এই বাউন্ড থেকে মুক্ত, যদিও প্রতি ধাপে একটু বেশি কম্পিউটেশন লাগে।

অনুশীলন

  1. চিন্তা করুন: স্থিতিশীল ডেমোতে steps=5-এর বদলে steps=10 চালালে (একই r=0.4), x=0.5-এ তাপমাত্রা মান আরও কমবে না বাড়বে বলে আপনার ধারণা, এবং কেন?

    আরও কমবে — হিট ইকুয়েশন সবসময় প্রোফাইলকে সমতল করার (ডিফিউজ করার) দিকে নিয়ে যায়, বাউন্ডারি শর্ত u(0,t)=u(1,t)=0-এর কারণে দীর্ঘমেয়াদে পুরো প্রোফাইল শূন্যের দিকে ডিক্যে করবে (এক্সপোনেনশিয়াল ফ্যাক্টর $e^{-\pi^2 t}$ সময়ের সাথে ক্রমাগত ছোট হয়)। কোড সেলে steps বাড়িয়ে চালালে এটি সরাসরি যাচাই করা যায়।

  2. পরীক্ষা করুন: স্পাইক ডেমোর কোড সেলে r-এর তালিকায় 0.5 (ঠিক সীমান্তে) যোগ করে Run চাপুন। কেন্দ্র বিন্দুর মান কেমন আচরণ করে — r=0.4-এর মতো (স্থিতিশীল) নাকি r=0.6-এর মতো (বিস্ফোরিত)?

    r=0.5 ঠিক তাত্ত্বিক সীমানায় — এই সীমান্ত-কেসে সর্বোচ্চ-ফ্রিকোয়েন্সি মোডের অ্যামপ্লিফিকেশন ফ্যাক্টর ঠিক -1 (বা কাছাকাছি) হয়, ফলে মান চিহ্ন পরিবর্তন করতে থাকে কিন্তু বিস্ফোরিত হয় না (না বাড়ে, না কমে) — একটি প্রান্তিক (marginally stable) আচরণ। এটি দেখায় r ≤ 0.5 শর্তের "≤" চিহ্নটি ঠিক কেন গুরুত্বপূর্ণ — r=0.5 এখনো (তাত্ত্বিকভাবে) স্থিতিশীল সীমার মধ্যে।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
PDE পরিচিতি — শ্রেণীবিভাগ