1D Heat Equation Solver 1.0
Computational Methods Assignment 2025
Loading...
Searching...
No Matches
laasonen.cpp
Go to the documentation of this file.
2
3#include <cstddef>
4#include <vector>
5
6void Laasonen::step(const Grid& g,
7 double D,
8 double dt,
9 const std::vector<double>& /*Tprev*/,
10 const std::vector<double>& Tcurr,
11 std::vector<double>& Tnext) const
12{
13 const std::size_t N = g.Nx;
14 const double dx = g.dx;
15 const double r = D * dt / (dx * dx);
16
17 // Safety check
18 if (N < 3)
19 return;
20
21 // Ensure output size
22 if (Tnext.size() != N)
23 Tnext.resize(N);
24
25 // Copy boundary conditions from current (or apply later, but solver handles BC usually)
26 // The solver (HeatSolver) applies BCs after step(), but we need them for the system if we solve
27 // for internal nodes. Actually, Tnext will be overwritten for internal nodes. We can just copy
28 // Tcurr to Tnext to initialize (and keep boundaries if they don't change in this step, though
29 // solver overrides them).
30 Tnext = Tcurr;
31
32 const std::size_t M = N - 2; // Number of internal nodes (excluding boundaries)
33
34 // Tridiagonal coefficients
35 // Equation: -r T_{i-1}^{n+1} + (1 + 2r) T_i^{n+1} - r T_{i+1}^{n+1} = T_i^n
36 std::vector<double> a(M, -r);
37 std::vector<double> b(M, 1.0 + 2.0 * r);
38 std::vector<double> c(M, -r);
39 std::vector<double> d(M, 0.0);
40
41 // RHS construction (Right-Hand Side) = T^n
42 for (std::size_t j = 0; j < M; ++j)
43 {
44 d[j] = Tcurr[j + 1];
45 }
46
47 // Adding boundary conditions to RHS
48 // T_{i-1}^{n+1} for i=1 is T_0^{n+1} (Boundary Left)
49 // T_{i+1}^{n+1} for i=M is T_{N-1}^{n+1} (Boundary Right)
50 // We assume Dirichlet BCs are fixed or handled by the solver.
51 // The solver calls apply_dirichlet(next_) AFTER step().
52 // But for the implicit solve, we need the boundary values at n+1.
53 // Since we don't have them passed explicitly as "next boundaries", we usually assume they are
54 // same as Tcurr or fixed. In this problem, Tsur is constant. So Tcurr[0] and Tcurr[N-1] are
55 // correct for T^{n+1} boundaries too.
56
57 d[0] += r * Tcurr[0]; // T_0^{n+1} assumed approx T_0^n or fixed
58 d[M - 1] += r * Tcurr[N - 1]; // T_{N-1}^{n+1}
59
60 // -----------------------
61 // Thomas Algorithm
62 // -----------------------
63
64 // Forward elimination
65 // c[0] /= b[0];
66 // d[0] /= b[0];
67 // for i = 1 to M-1
68 // temp = 1 / (b[i] - a[i] * c[i-1])
69 // c[i] *= temp
70 // d[i] = (d[i] - a[i] * d[i-1]) * temp
71
72 // Standard Thomas implementation
73 // Modify coefficients in place
74 c[0] /= b[0];
75 d[0] /= b[0];
76
77 for (std::size_t i = 1; i < M; ++i)
78 {
79 double temp = 1.0 / (b[i] - a[i] * c[i - 1]);
80 c[i] *= temp;
81 d[i] = (d[i] - a[i] * d[i - 1]) * temp;
82 }
83
84 // Backward substitution
85 // x[M-1] = d[M-1]
86 // for i = M-2 down to 0
87 // x[i] = d[i] - c[i] * x[i+1]
88
89 std::vector<double> x(M);
90 x[M - 1] = d[M - 1];
91
92 for (int i = static_cast<int>(M) - 2; i >= 0; --i)
93 {
94 x[i] = d[i] - c[i] * x[i + 1];
95 }
96
97 // Update T^{n+1} (internal nodes)
98 for (std::size_t j = 0; j < M; ++j)
99 {
100 Tnext[j + 1] = x[j];
101 }
102}
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
Computes the temperature field at the next time step (T^{n+1}).
Definition laasonen.cpp:6
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