|
1 | | -% Numerical solution of Terzaghi's 1D consolidation equation using MOLE |
| 1 | +% Terzaghi 1D: using MOLE operators |
2 | 2 | clc; |
3 | 3 | close all; |
4 | 4 |
|
5 | | -addpath('../../src/matlab'); % Update this path to your MOLE operators |
| 5 | +addpath('../../src/matlab'); % MOLE operator path |
6 | 6 |
|
7 | | -% Parameters |
| 7 | +%% Parameters |
8 | 8 | P0 = 10e6; % Face load in Pascals |
9 | | -cf = 1e-4; % Consolidation (diffusion) constant |
10 | | -L = 25; % Domain length in meters |
11 | | -k = 2; % Order of accuracy |
| 9 | +cf = 1e-4; % Diffusion constant |
| 10 | +l = 25; % Domain length in meters |
| 11 | +k = 2; % MOLE operator order |
12 | 12 | m = 50; % Number of cells |
13 | | -a = 0; b = L; |
| 13 | + |
| 14 | +% Spatial discretization |
| 15 | +a = 0; |
| 16 | +b = l; |
14 | 17 | dx = (b - a)/m; |
15 | 18 | xgrid = [a a+dx/2 : dx : b-dx/2 b]; % Staggered grid |
16 | 19 |
|
17 | 20 | % Times to evaluate (in hours) |
18 | 21 | times_hr = [1, 10, 40, 70]; |
19 | 22 | times_sec = times_hr * 3600; |
20 | 23 |
|
21 | | -% Fluid and medium properties |
22 | | -K = 1e-12; % Permeability [m^2] |
23 | | -mu = 1e-3; % Dynamic viscosity [Pa·s] |
24 | | -rho = 1000; % Fluid density [kg/m^3] |
25 | | -g = 9.81; % Gravity [m/s^2] |
26 | | - |
27 | | -% MOLE operators |
28 | | -L = lap(k, m, dx); % Laplacian |
29 | | -G = grad(k, m, dx); % Gradient |
| 24 | +% Fluid properties |
| 25 | +K = 1e-12; % Permeability [m^2] |
| 26 | +mu = 1e-3; % Dynamic viscosity [Pa·s] |
| 27 | +rho = 1000; % Fluid density [kg/m^3] |
| 28 | +g = 9.81; % Gravity [m/s^2] |
30 | 29 |
|
31 | | -% Enforce zero rows for boundary (to avoid Laplacian affecting boundary values) |
32 | | -L(1,:) = 0; |
33 | | -L(end,:) = 0; |
| 30 | +%% Numerical (MOLE) Solution |
| 31 | +L = lap(k, m, dx); |
| 32 | +G = grad(k, m, dx); |
| 33 | +L(1,:) = 0; L(end,:) = 0; |
34 | 34 |
|
35 | | -% Store results |
36 | | -p_all = zeros(length(xgrid), length(times_sec)); |
37 | | -q_all = zeros(length(xgrid), length(times_sec)); |
38 | | - |
39 | | -% Plot pressure |
40 | | -figure(1); hold on; |
| 35 | +p_numerical = zeros(length(xgrid), length(times_sec)); |
41 | 36 | for i = 1:length(times_sec) |
42 | 37 | t_final = times_sec(i); |
43 | 38 | dt = 0.03; |
44 | 39 | nsteps = round(t_final / dt); |
45 | | - |
46 | | - %Uniform Initial Condition |
| 40 | + |
| 41 | + % Uniform Initial Condition |
47 | 42 | p = P0 * ones(size(xgrid))'; |
48 | 43 |
|
49 | | - % Time stepping loop |
50 | 44 | for step = 1:nsteps |
51 | 45 | p = p + dt * cf * (L * p); |
52 | | - % Boundary Conditions |
53 | | - p(1) = 0; % Dirichlet at x = 0 |
54 | | - p(end) = p(end-1); % Neumann at x = L (zero gradient) |
| 46 | + p(1) = 0; % Dirichlet BC |
| 47 | + p(end) = p(end-1); % Neumann BC |
55 | 48 | end |
56 | | - |
57 | | - % Store final pressure |
58 | | - p_all(:,i) = p; |
59 | 49 |
|
60 | | - % Compute gradient and Darcy flux |
61 | | - dpdx = G * p; |
62 | | - q = - (K / mu) * (dpdx - rho * g); |
63 | | - q_all(1:m+1,i) = q(1:m+1); % Exclude ghost point |
| 50 | + p_numerical(:,i) = p; |
| 51 | +end |
64 | 52 |
|
65 | | - % Plot pressure profile |
66 | | - semilogy(xgrid, p/1e6, '-o', 'DisplayName', ['t = ' num2str(times_hr(i)) ' hr']); |
| 53 | +%% Analytical Solution |
| 54 | +N_max = 100; |
| 55 | +p_analytical = zeros(length(xgrid), length(times_sec)); |
| 56 | +for i = 1:length(times_sec) |
| 57 | + t = times_sec(i); |
| 58 | + p = zeros(size(xgrid)); |
| 59 | + for N = 0:N_max |
| 60 | + n = 2*N + 1; |
| 61 | + term = (1/n) * sin(n*pi*xgrid/(2*l)) .* exp(-(n^2)*(pi^2)*cf*t/(4*l^2)); |
| 62 | + p = p + term; |
| 63 | + end |
| 64 | + p_analytical(:,i) = (4/pi) * P0 * p; |
67 | 65 | end |
68 | | -title('Pressure p(x,t) at various times'); |
69 | | -xlabel('x (m)'); |
| 66 | + |
| 67 | +%% Combined Plot |
| 68 | +figure('Name','Terzaghi one-dimensional consolidation'); |
| 69 | +set(gcf,'Color','white'); |
| 70 | +% Top subplot: MOLE numerical |
| 71 | +subplot(2,1,1); |
| 72 | +hold on; |
| 73 | +for i = 1:length(times_sec) |
| 74 | + semilogy(xgrid, p_numerical(:,i)/1e6, '-o', 'DisplayName', [num2str(times_hr(i)) ' hr']); |
| 75 | +end |
| 76 | +title('MOLE Numerical Solution'); |
70 | 77 | ylabel('Excess Pore Pressure p(x,t) [MPa]'); |
| 78 | +axis([0 l 1e-3 10]); |
71 | 79 | legend('Location', 'southeast'); |
72 | 80 | grid on; |
73 | 81 |
|
74 | | -% Plot Darcy flux |
75 | | -figure(2); hold on; |
76 | | -x_flux = linspace(a + dx/2, b - dx/2, m+1); |
| 82 | +% Bottom subplot: Analytical |
| 83 | +subplot(2,1,2); |
| 84 | +hold on; |
77 | 85 | for i = 1:length(times_sec) |
78 | | - q = q_all(1:m+1,i); |
79 | | - semilogy(x_flux, q, '-s', 'DisplayName', ['t = ' num2str(times_hr(i)) ' hr']); |
| 86 | + semilogy(xgrid, p_analytical(:,i)/1e6, '--s', 'DisplayName', [num2str(times_hr(i)) ' hr']); |
80 | 87 | end |
81 | | -title('Darcy Flux q(x,t) at various times'); |
| 88 | +title('Analytical Benchmark Solution'); |
82 | 89 | xlabel('x (m)'); |
83 | | -ylabel('q(x,t) [m/s]'); |
| 90 | +ylabel('Excess Pore Pressure p(x,t) [MPa]'); |
| 91 | +axis([0 l 1e-3 10]); |
84 | 92 | legend('Location', 'southeast'); |
85 | 93 | grid on; |
86 | 94 |
|
87 | | -% Print final values |
| 95 | +%% Print relative L2 errors |
| 96 | +fprintf('\nRelative L2 Errors (Numerical vs Analytical):\n'); |
88 | 97 | for i = 1:length(times_hr) |
89 | | - fprintf('\nFinal pressure p(x,t = %.2f hr):\n', times_hr(i)); |
90 | | - disp(p_all(:,i)'); |
91 | | - fprintf('Final Darcy flux q(x,t = %.2f hr):\n', times_hr(i)); |
92 | | - disp(q_all(1:m+1,i)'); |
| 98 | + rel_err = norm(p_numerical(:,i) - p_analytical(:,i)) / norm(p_analytical(:,i)); |
| 99 | + fprintf('t = %.2f hr: %.6e\n', times_hr(i), rel_err); |
93 | 100 | end |
94 | | - |
95 | | -% Save pressure for comparison |
96 | | -p_numerical = p_all; |
|
0 commit comments