Richardson extrapolation for time scheme

조회 수: 12 (최근 30일)
Karl Zero
Karl Zero 2022년 5월 27일
편집: Torsten 2022년 5월 30일
I am solving an equation by using finite volume method :
I am writing a linear system in order to solve it by using a forward euler scheme in time. The scheme is written as :
It is a semi-implicit scheme as the derivative of the Q term is writing in the time (n+1). We end up with a linear system to solve as :
My question is now : how to write the code that is related to this scheme in order to use a Richardson extrapolation ?
I have read some papers in order to understand the method but I have some misunderstandings... For instance, if we evaluate the value of the function u at time step h and the value of this same function in the time step 2h we can write the exact value of that one is trying to compute as :
(k is the order of approximation of the method)
I don't know how I can implement it in my code since I am basically computing a time loop solving the linear system at each time step. Moreover : the exact solution of my problem is unknown...
Nx = 100; % Number of grid points
L = 10; % Length of interval
x = linspace(0, L, Nx+1); % Grid points
dx = x(2) - x(1); % Spatial step
t = 0; % Initial time
dt = 0.1; % Time step
t_final = 30; % Final time
Nt = t_final/dt;
h_new = zeros(1,Nx+1); % h at new time
h_old = zeros(1,Nx+1); % h at old time
c = dt/(dx^2); % Constant
epsilon = 1e-7; % condition
% Initialization of the linear system
A = zeros(Nx+1, Nx+1);
b = zeros(Nx+1,1);
solution = zeros(Nt,Nx+1);
% Stationnary condition
for i=1:Nx+1
h_old(i)= (1-((x(i)/L)).^2).^2;
end
%% Solving AU=b
% Time loop
while t<=t_final
% Matrix elements
for i=2:Nx
A(i,i-1) = -c*((h_old(i)+h_old(i-1))/2)^3;
A(i,i+1) = -c*((h_old(i)+h_old(i+1))/2)^3;
A(i,i) = 1 +c*((h_old(i)+h_old(i+1))/2)^3+c*((h_old(i)+h_old(i-1))/2)^3;
end
A(1,1) = (1+2*c*((h_old(1)+h_old(2))/2)^3);
A(1,2) = -2*c*((h_old(1)+h_old(2))/2)^3;
A(Nx+1,Nx+1) = 1;
% b vector elements
for i=1:Nx
b(i) = h_old(i);
end
b(Nx+1) = epsilon;
h_new(:) = linsolve(A, b);
% Update of h_old.
h_old(:) = h_new;
% Time iteration.
t = t+dt;
end
Could someone help me to do so please ? And understand the implementation of the method.
  댓글 수: 14
Karl Zero
Karl Zero 2022년 5월 30일
@Torsten it may seem dumb but in fact the result plotted by the main code is a matrix nammed solution which is :
solution = zeros(Nt,Nx+1 );
because there is a solution calcuted on Nx+1 points for each time step (in the while loop )
So for instance the line :
M(:,1, 1) = Euler_implicit(t, t_final, dt );
returns an error of size (which is legit ) :
Unable to perform assignment because the size of the left side is 101-by-1 and the size of the right side is 300-by-101.
However, i don't understand how to avoid it ....
Torsten
Torsten 2022년 5월 30일
편집: Torsten 2022년 5월 30일
You only need h for t = t_final in the Richardson function. Thus "solution" should be initialized as zeros(Nx+1,1) in Euler_implicit.
Maybe of interest for you:
format long
tStart = 0; % Starting time
tEnd = 5; % Ending time
f = @(t,y) -y^2; % The derivative of y, so y' = f(t, y(t)) = -y^2
% The solution to this ODE is y = 1/(1 + t)
y0 = 1; % The initial position (i.e. y0 = y(tStart) = y(0) = 1)
tolerance = 10^-11; % 10 digit accuracy is desired
maxRows = 20; % Don't allow the iteration to continue indefinitely
initialH = tEnd - tStart; % Pick an initial step size
haveWeFoundSolution = false; % Were we able to find the solution to within the desired tolerance? not yet.
h = initialH;
% Create a 2D matrix of size maxRows by maxRows to hold the Richardson extrapolates
% Note that this will be a lower triangular matrix and that at most two rows are actually
% needed at any time in the computation.
A = zeros(maxRows, maxRows);
%Compute the top left element of the matrix. The first row of this (lower triangular) matrix has now been filled.
A(1, 1) = Trapezoidal(f, tStart, tEnd, h, y0)
% Each row of the matrix requires one call to Trapezoidal
% This loops starts by filling the second row of the matrix, since the first row was computed above
for i = 1 : maxRows - 1 % Starting at i = 1, iterate at most maxRows - 1 times
h = h/2; % Halve the previous value of h since this is the start of a new row.
% Starting filling row i+1 from the left by calling the Trapezoidal function with this new smaller step size
A(i + 1, 1) = Trapezoidal(f, tStart, tEnd, h, y0);
for j = 1 : i % Go across this current (i+1)-th row until the diagonal is reached
% To compute A(i + 1, j + 1), which is the next Richardson extrapolate,
% use the most recently computed value (i.e. A(i + 1, j)) and the value from the
% row above it (i.e. A(i, j)).
A(i + 1, j + 1) = ((4^j).*A(i + 1, j) - A(i, j))/(4^j - 1);
end
% After leaving the above inner loop, the diagonal element of row i + 1 has been computed
% This diagonal element is the latest Richardson extrapolate to be computed.
% The difference between this extrapolate and the last extrapolate of row i is a good
% indication of the error.
if (abs(A(i + 1, i + 1) - A(i, i)) < tolerance) % If the result is within tolerance
%print('y = ', A(i + 1, i + 1)) % Display the result of the Richardson extrapolation
A(i+1,i+1)
haveWeFoundSolution = true;
break % Done, so leave the loop
end
end
if (haveWeFoundSolution == false) % If we were not able to find a solution to within the desired tolerance
print("Warning: Not able to find solution to within the desired tolerance of ", tolerance);
print("The last computed extrapolate was ", A(maxRows, maxRows))
end
function y = Trapezoidal (f,tStart,tEnd,h,y0)
t = tStart:h:tEnd;
n = numel(t)
y = y0;
yold = y;
for i = 2:n
fun = @(y)y - yold - 0.5*h*(f(t(i-1),yold)+f(t(i),y));
y = fsolve(fun,yold);
yold = y;
end
end

댓글을 달려면 로그인하십시오.

답변 (0개)

카테고리

Help CenterFile Exchange에서 Boundary Conditions에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by