Solving Advection Equation PDE with 2nd order Accuracy

21 ビュー (過去 30 日間)
Nick
Nick 2025 年 2 月 5 日 20:02
コメント済み: Nick 2025 年 2 月 5 日 20:26
I am solving the advection equation ∂t/∂u = -c * ∂t/∂x and imposing a small pulse of material in the beginning of the simulation, imposed in the boundary. I'm using ODE15s as a solver and am discretizing the equation spatially with a backward fininte difference scheme. I have a code that can implement a first order or second order backward discretization scheme. For the first order implementation, I can simulate and do not get osciallations. For the 2nd order scheme, I get oscillations, regardless of how fine my mesh is. Is there a way to implement this with 2nd order accuracy and not get oscillations?
clear
% Parameters
Nx = 1000; % Number of spatial points
Lx = 10; % Length of domain
dx = Lx / Nx; % Spatial step
c = 1.0; % Advection speed
tspan = [0, 20]; % Time span for simulation
% Switch between 'first' and 'second' order backward difference
order = 'second'; % Options: 'first' or 'second'
% Spatial grid
x = linspace(0, Lx, Nx);
% Initial Condition: All zeros
u0 = zeros(Nx, 1);
% Solve ODE system using ODE15s
[t, U] = ode15s(@(t, u) advection_ode(t, u, dx, c, Nx, order), tspan, u0);
% Choose a fixed observation point in space (e.g., midpoint of domain)
obs_index = round(Nx / 2);
concentration_over_time = U(:, obs_index); % Track concentration at obs_index
% Plot Concentration vs. Time
figure;
plot(t, concentration_over_time, 'b', 'LineWidth', 2);
xlabel('Time (s)');
ylabel('Concentration at x = Lx/2');
title(['Advection Equation: ', order, ' Order Backward Difference with Pulse Injection']);
grid on;
% -----------------------
% Function for ODE System
% -----------------------
function dudt = advection_ode(t, u, dx, c, Nx, order)
dudt = zeros(Nx, 1);
% Inject a small pulse at x = 0 for a short time (0 <= t <= 0.5)
if t >= 0 && t <= 0.5
u(1) = 1; % Set a pulse at the inlet
else
u(1) = 0; % No pulse after injection time
end
if strcmp(order, 'first')
% First-order backward difference
for i = 2:Nx
dudt(i) = -c * (u(i) - u(i-1)) / dx;
end
elseif strcmp(order, 'second')
% Second-order backward difference
for i = 3:Nx
dudt(i) = -c * (3*u(i) - 4*u(i-1) + u(i-2)) / (2*dx);
end
% Approximate first-order difference for the second point (i=2)
dudt(2) = -c * (u(2) - u(1)) / dx;
end
% Apply the boundary condition at x = 0 (Pulse Injection)
dudt(1) = 0; % Fix inlet value
end

採用された回答

Torsten
Torsten 2025 年 2 月 5 日 20:19
編集済み: Torsten 2025 年 2 月 5 日 20:24
Usual second-order schemes for the advection equation will always produce oscillations. Section 3.1.3 of the enclosed article suggests a scheme that adds "artificial viscosity" near the discontinuity to avoid oscillations and is second-order accurate elsewhere. But it costs quite a bit of effort to implement it.
I suggest you use a fine grid together with the first-order scheme - this will be almost as exact as a second-order scheme. Or - if the equation doesn't become more complicated - you can solve it analytically.
At least you should integrate in two steps (with a restart from the solution of the first step) avoiding the if-statement on time
if t >= 0 && t <= 0.5
u(1) = 1; % Set a pulse at the inlet
else
u(1) = 0; % No pulse after injection time
end
  1 件のコメント
Nick
Nick 2025 年 2 月 5 日 20:26
That makes sense, thanks!

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeEigenvalue Problems についてさらに検索

製品


リリース

R2024a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by