1D Heat Equation Solver 1.0
Computational Methods Assignment 2025
Loading...
Searching...
No Matches
crank_nicolson.cpp
Go to the documentation of this file.
1/**
2 * @file crank_nicolson.cpp
3 * @brief Implementation of the Crank-Nicolson scheme using the Thomas Algorithm.
4 */
5
7
8#include <cstddef>
9#include <vector>
10
12 double D,
13 double dt,
14 const std::vector<double>& /*Tprev*/,
15 const std::vector<double>& Tcurr,
16 std::vector<double>& Tnext) const
17{
18 const std::size_t N = g.Nx;
19 const double dx = g.dx;
20
21 // Calculate the Fourier number r
22 const double r = D * dt / (dx * dx);
23 const double alpha = r / 2.0;
24
25 // Safety check for grid size
26 if (N < 3)
27 return;
28
29 // Resize Tnext if needed and copy current state (to preserve boundaries)
30 if (Tnext.size() != N)
31 Tnext.resize(N);
32 Tnext = Tcurr;
33
34 // Number of internal nodes (excluding boundaries 0 and N-1)
35 const std::size_t M = N - 2;
36
37 // --- 1. Set up the Tridiagonal Matrix Coefficients (LHS) ---
38 // The system is A * T^{n+1} = d
39 // A is constant: diag = (1+r), off-diag = -r/2
40 std::vector<double> a(M, -alpha); // Lower diagonal
41 std::vector<double> b(M, 1.0 + r); // Main diagonal
42 std::vector<double> c(M, -alpha); // Upper diagonal
43 std::vector<double> d(M, 0.0); // Right-hand side vector
44
45 // --- 2. Construct the Right-Hand Side (RHS) ---
46 // d_i = (r/2)*T_{i-1}^n + (1-r)*T_i^n + (r/2)*T_{i+1}^n
47 // Note: j indexes the internal nodes (0 to M-1), corresponding to grid indices 1 to N-2.
48 for (std::size_t j = 0; j < M; ++j)
49 {
50 std::size_t i = j + 1; // Actual grid index
51 d[j] = alpha * Tcurr[i - 1] + (1.0 - r) * Tcurr[i] + alpha * Tcurr[i + 1];
52 }
53
54 // --- 3. Apply Boundary Conditions to RHS ---
55 // The terms -alpha * T^{n+1}_boundary are moved to the RHS.
56 // T[0] and T[N-1] already contain the fixed boundary values (Tsur).
57 d[0] += alpha * Tcurr[0];
58 d[M - 1] += alpha * Tcurr[N - 1];
59
60 // --- 4. Solve using Thomas Algorithm (TDMA) ---
61
62 // Forward elimination phase
63 for (std::size_t i = 1; i < M; ++i)
64 {
65 double m = a[i] / b[i - 1];
66 b[i] -= m * c[i - 1];
67 d[i] -= m * d[i - 1];
68 }
69
70 // Backward substitution phase
71 std::vector<double> x(M);
72 x[M - 1] = d[M - 1] / b[M - 1];
73
74 for (std::size_t i = M - 1; i-- > 0;)
75 {
76 x[i] = (d[i] - c[i] * x[i + 1]) / b[i];
77 }
78
79 // --- 5. Update Solution Vector ---
80 // Map the internal solution back to the full grid vector
81 for (std::size_t j = 0; j < M; ++j)
82 {
83 Tnext[j + 1] = x[j];
84 }
85}
void step(const Grid &g, double D, double dt, const std::vector< double > &Tprev, const std::vector< double > &Tcurr, std::vector< double > &Tnext) const override
Advance one time step using Crank-Nicolson scheme.
Uniform 1D grid on x ∈ [0, L], including both boundary nodes.
Definition grid.hpp:15
std::size_t Nx
Number of nodes (including boundaries).
Definition grid.hpp:18
double dx
Spatial step [cm].
Definition grid.hpp:17