MATLAB lessons N.7 and N.8¶
An implementation of ADER2 numerical flux: File ADER2Flux.m
:open:
1%
2% Compute Ader Flux
3%
4function [F,S] = ADER2Flux( Q, ...
5 Xnodes, ...
6 DT, ...
7 Flux, ...
8 SlopeLimiter, ...
9 Leading0, ...
10 Leading1, ...
11 Source )
12
13 nr = size(Q,1) ;
14 DX = Xnodes(2)-Xnodes(1) ;
15
16 % Reconstruct phase
17 % construct limited slopes (given N+2 averages return N slopes)
18 DQ = feval( SlopeLimiter, Q ) ;
19
20 % extrapolate from the left
21 QL = Q(:,2:end-2) + DQ(:,1:end-1)./2 ;
22
23 % extrapolate from the right
24 QR = Q(:,3:end-1) - DQ(:,2:end)./2 ;
25
26 % compute slopes
27 DELTA = DQ ./ DX ;
28
29 % left slopes
30 DELTAL = DELTA(:,1:end-1) ;
31
32 % right slopes
33 DELTAR = DELTA(:,2:end) ;
34
35 % End of Reconstruct phase
36
37 % Compute leading term
38 D0 = Leading0( QL, QR ) ;
39 D1 = Leading1( DELTAL, DELTAR, D0 ) ;
40 % End Compute leading term
41
42 % Evaluate ADER2 state
43 D0L = D0 - D1 ./2 ;
44 D0R = D0 + D1 ./2 ;
45 %
46 % In order to eliminate the loop
47 %
48 %Qader = D0 ;
49 %for k=1:size(Qader,2)
50 % A0 = feval( JFlux, D0(:,k) ) ;
51 % Qader(:,k) = Qader(:,k) + (DT/2) * (feval(Source, D0(:,k)) - A0 * D1(:,k)) ;
52 %end
53 %
54 % The second order approxination A0 * D1 ~ Flux( D0+D1/2 ) - Flux(D0-D1/2)
55 %
56 Qader = D0 + (DT/2) * ( feval( Source, D0 ) - feval( Flux, D0R ) + feval( Flux, D0L ) ) ;
57 F = feval( Flux, Qader) ;
58 % End Evaluate numerical flux
59
60 % Evaluate source
61 Qs = Q(:,3:end-2) ; % consider only "true" cells
62 DD = DELTA(:,2:end-1) ./2 ; % consider only half of the slope of "true" cells
63 %
64 % In order to eliminate the loop
65 %
66 % for k=1:size(Qs,2)
67 % Qs(:,k) = Qs(:,k) + (DT/2) * ( feval( Source, Qs(:,k) ) - feval( JFlux, Qs(:,k) )*DELTA(:,k+1) ) ;
68 % end
69 %
70 % The second order approxination JFlux(Qs) DELTA = Flux( Qs+DELTA/2 ) - Flux(Qs-DELTA/2)
71 %
72 DL = Qs - DD ;
73 DR = Qs + DD ;
74
75 Qs = Qs + (DT/2) * ( feval( Source, Qs ) - feval( Flux, DR ) + feval( Flux, DL ) ) ;
76 S = feval( Source, Qs ) ;
77 % End Evaluate source
78
79end
A generic advancing algorithm for hyperbolic problem: File Advancing.m
:open:
1% General Advancing procedure used to test numerical solver for hyperbolic equations
2%
3% Name of program: Advancing
4%
5% Developed by: Enrico Bertolazzi
6% Department of Mechanical and Structural Engineering
7% enrico.bertolazzi@ing.unitn.it
8% http://www.ing.unitn.it/~bertolaz/
9%
10% Last revision: 2 June 2009
11%
12% INPUTS:
13%
14% Qinit = initial cell average values
15% Xnodes = boundary of the cells
16% InitialTime = starting simulation time
17% FinalTime = end of simulation time
18% StepTime = the time difference at which the solution is saved
19% CFLratio = the Courant–Friedrichs–Lewy ratio at which the solver can advance
20%
21% maxSpeed = function with one vector argument which compute maximum speed signal for each cell.
22% Usage: feval( maxSpeed, Q ).
23%
24% doStep = function which perform step of the numerical scheme
25% Usage: feval( doStep, Time, DT, DX, XC, Q ).
26% Time = Actual time
27% DT = advancing time step
28% DX = cells size
29% XC = cells center
30% Q = cells actual state
31%
32% OUTPUTS:
33%
34% Tframes = vector with the time values of saved frame
35% Qframes = cell array with the solution frames computed
36% Qframes{1} = contains the solution at time Tframes(1)
37% Qframes{2} = contains the solution at time Tframes(2)
38%
39% ...
40%
41% Qframes{end} = contains the solution at time Tframes(end)
42%
43function [ Qframes, Tframes ] = Advancing( Qinit, ...
44 Xnodes, ...
45 InitialTime, ...
46 FinalTime, ...
47 StepTime, ...
48 CFLratio, ...
49 maxSpeed, ...
50 doStep )
51
52 % Initial conditions are copied in the vector Q
53 Q = Qinit ;
54
55 % Compute cell size DX, the size of the cells are assumed all equals.
56 DX = Xnodes(2) - Xnodes(1) ;
57
58 % save initial frame
59 Qframes{1} = Q ;
60 Tframes(1) = InitialTime ;
61
62 kframe = 1 ; % number of saved framed
63 Time = InitialTime ; % initial time
64 NextTime = InitialTime + StepTime ; % Time to save next frame
65
66 % Time marching procedure, a maximum of 10000 steps are allowed
67 for NITER=1:10000
68
69 % Courant-Friedrichs-Lewy (CFL) condition imposed
70 DT = CFLratio * DX / max( feval( maxSpeed, Q ) ) ;
71
72 % reduce DT if necessary for the last step
73 if Time+DT >= FinalTime
74 DT = FinalTime - Time ;
75 % perform last step
76 Q = feval( doStep, Time, DT, Xnodes, Q ) ;
77 % save last frame
78 kframe = kframe+1 ;
79 Qframes{kframe} = Q ;
80 Tframes(kframe) = FinalTime ;
81 % exit loop
82 break ;
83 end
84
85 % adjust time step if necessary to match the time grid
86 DT1 = NextTime - Time ;
87 while DT >= DT1 % if DT contains a grid step perform smaller step
88
89 % perform step
90 Qnew = feval( doStep, Time, DT1, Xnodes, Q ) ;
91
92 % Solution frame is saved
93 kframe = kframe+1 ;
94 Qframes{kframe} = Qnew ;
95 Tframes(kframe) = NextTime ;
96
97 % check if we have reached the final mesh point
98 if FinalTime < NextTime
99 break ;
100 end ;
101
102 % update next time frame
103 NextTime = NextTime + StepTime ;
104 DT1 = NextTime - Time ;
105 end
106
107 % perform step
108 Q = feval( doStep, Time, DT, Xnodes, Q ) ;
109
110 % update time
111 Time = Time + DT ;
112 end
113
114end
Utility routine for good plotting of average values: File buildXYForPlot.m
:open:
1% Name of program: buildXYForPlot
2%
3% Developed by: Enrico Bertolazzi
4% Department of Mechanical and Structural Engineering
5% enrico.bertolazzi@ing.unitn.it
6% http://www.ing.unitn.it/~bertolaz/
7%
8% Last revision: 2 June 2009
9%
10% Given a vector CB of cells boundary edges and a vector Q of cell average values
11% build the vectos x and y which can be used to plot the piecewise constant function
12% which represents the solution
13%
14% INPUT
15% Xnodes: cells boundary (row vector)
16% Q: cell average value
17%
18% OUTPUT
19% X: x-coordinate
20% Y:
21%
22% +------+------+
23% | | | +------+
24% +------+ | | | |
25% | | | +------+ |
26% | Q(1) | Q(2) | Q(3) | Q(4) | |
27% | | | | | |
28% CB(1) CB(2) CB(3)
29%
30% Last revision: 2 June 2009
31%
32function [X,Y] = buildXYForPlot( Xnodes, Q )
33
34 % allocate memory
35 N = size(Q,2) ;
36 X = zeros( 1, 2*N ) ;
37 Y = zeros( size(Q,1), 2*N ) ;
38
39 X(1:2:2*N-1) = Xnodes(1:end-1) ;
40 X(2:2:2*N) = Xnodes(2:end) ;
41
42 Y(:,1:2:2*N-1) = Q ;
43 Y(:,2:2:2*N) = Q ;
44
45end
An implementation of minmid slope limiter: File WENOSlopeLimiter.m
:open:
1% Given average states compute WENO limited slopes
2%
3% Name of program: WENOSlopeLimiter.m
4%
5% Developed by: Enrico Bertolazzi
6% Department of Mechanical and Structural Engineering
7% enrico.bertolazzi@ing.unitn.it
8% http://www.ing.unitn.it/~bertolaz/
9%
10% This code is inspired on the library
11% NUMERICA
12% A Library of Source Codes for Teaching,
13% Research and Applications,
14% by E. F. Toro
15% Published by NUMERITEK LTD,
16% Website: www.numeritek.coM
17%
18% The algorithm are described in the book:
19%
20% E. F. Toro, "Riemann Solvers and Numerical Methods for Fluid Dynamics"
21% Springer-Verlag, 1997, Second Edition, 1999
22%
23% Last revision: 27 May 2009
24%
25% The scheme can be visualized in the following way
26%
27% +===+ The cell where the average value Qi is "stored".
28%
29% +...+ Ghost cell. These cells are used to extrapolate values for the
30% construction of the bounary conditions. Two ghost cell for boundary
31% are enough for all the considered fluxes.
32%
33% +xxx+ Uncomputed values. These cells do not cotains valid values.
34% Are used to avoid shifting of indices or complex indicization.
35%
36% Averages states
37%
38% +...+...+===+===+===+===+=== ===+===+...+...+
39% Q1 Q2 Q3 QN+4
40%
41% Limited slopes, the slopes S1 and SN+4 are not computed (indeed it is not possible)
42%
43% +xxx+===+===+===+===+===+=== ===+===+===+xxx+
44% S1 S2 S3 SN+1
45%
46% INPUTS:
47%
48% Q = average values
49%
50% OUTPUTS:
51%
52% SLOPE = limited slopes
53%
54% The slopes are built by finite difference of sucessive averages.
55% In this way slopes associated to interfaces are used to copute cell slopes.
56% The slopes associated to a cell is the minimum slope between the two interface slopes.
57%
58function DELTA = WENOSlopeLimiter( Q )
59
60 % compute interface slopes, SLOPE(k) is the slopes of interface between cell k and k+1
61 SLOPE = Q(:,2:end) - Q(:,1:end-1) ;
62
63 % left slopes
64 LSLOPE = SLOPE(:,1:end-1);
65
66 % right slopes
67 RSLOPE = SLOPE(:,2:end);
68
69 % find minimum slopes
70 DELTA = minmod( LSLOPE, RSLOPE ) ;
71
72 % is equivalent to the loop
73 %
74 % for k=1:lenght(SLOPE)
75 % if abs(LSLOPE(k)) < abs(RSLOPE(k))
76 % SLOPE(k) = LSLOPE(k);
77 % else
78 % SLOPE(k) = RSLOPE(k);
79 % end
80 % end
81
82end
83
84%
85% given the vector (matrix) a and b return
86% res(k) = sign(a)*min(abs(a(k)),abs(b(k))) if a(k)*b(k)>0
87% res(k) = 0 otherwise
88%
89function res = minmod( a, b )
90 res = zeros( size(a) ) ;
91 I1 = find( a > 0 & b > 0 ) ;
92 I2 = find( a < 0 & b < 0 ) ;
93 I3 = find( a.*b <= 0 ) ;
94 res(I1) = min(a(I1),b(I1)) ;
95 res(I2) = max(a(I2),b(I2)) ;
96 res(I3) = 0 ;
97end
Test Ader2 for linear transport equation: File TestAder2LinearTransport.m
:open:
1% Test Advancing routine by solving the problem
2%
3% Q(x,t) + Q(x,t) = 0 -1 <= x <= 1
4% t x
5%
6% /
7% | 0 if x < -1/2
8% Q(x,0) = | 1 if x > -1/2 and x < 1/2
9% | 0 if x > 1/2
10% \
11% +---+
12% | |
13% ---------+ +----------
14%
15% Cyclic boundary conditions
16%
17% Last revision: 28 May 2009
18%
19function TestAder2LinearTransport
20
21 N = 100 ; % number of cells
22 N4 = N/4 ;
23
24 % setup intial conditions
25 Qinit = [ zeros(1,N4) ones(1,N-2*N4) zeros(1,N4) ] ;
26
27 % setup the boundary of the cells
28 Xnodes = -1:2/N:1 ;
29
30 % initial time and time step
31 InitialTime = 0 ;
32 FinalTime = 20 ;
33 StepTime = 0.1 ;
34 CFLratio = 0.95 ;
35
36 [ Qframes, Tframes ] = Advancing( Qinit, ...
37 Xnodes, ...
38 InitialTime, ...
39 FinalTime, ...
40 StepTime, ...
41 CFLratio, ...
42 @maxSpeed, ...
43 @doStepADER2 ) ;
44
45 [ Qframes1, Tframes1 ] = Advancing( Qinit, ...
46 Xnodes, ...
47 InitialTime, ...
48 FinalTime, ...
49 StepTime, ...
50 CFLratio, ...
51 @maxSpeed, ...
52 @doStepGodunov ) ;
53
54 % plot the solution at final time step
55 [XX,YY] = buildXYForPlot( Xnodes, Qframes{end} ) ;
56 [X1,Y1] = buildXYForPlot( Xnodes, Qframes1{end} ) ;
57 plot( XX, YY, X1, Y1 ) ;
58
59end
60%
61% Return a vector with the maximum speed of each cell
62%
63function SPEED = maxSpeed( Q )
64 SPEED = ones(size(Q)) ;
65end
66
67%
68% Flux for linear transport
69%
70function F = Flux( Q )
71 F = Q ;
72end
73
74%
75% Jacobians of the flux (vectorial form)
76%
77function A = JFlux( Q )
78 A = ones(size(Q)) ;
79end
80%
81% Solve the Riemann problem for the linear transport equation exactly.
82%
83function USTAR = Riemann(UL, UR)
84 USTAR = UL ;
85end
86
87function S = Source( Q )
88 S = zeros(size(Q)) ;
89end
90
91function D0 = Leading0( QL, QR )
92 D0 = Riemann(QL,QR) ;
93end
94
95function D1 = Leading1( DL, DR, D0 )
96 D1 = Riemann(DL, DR) ;
97end
98%
99% Advancing with ADER2 numerical scheme
100%
101function Qnew = doStepADER2( Time, DT, Xnodes, Q )
102
103 % extrapolation
104 Qe = [ Q(:,end-1) Q(:,end) Q Q(:,1) Q(:,2) ] ;
105
106 [F,S] = ADER2Flux( Qe, Xnodes, DT, @Flux, @WENOSlopeLimiter, @Leading0, @Leading1, @Source ) ;
107
108 DX = Xnodes(2)-Xnodes(1) ;
109 Qnew = Q - (DT/DX) .* ( F(:,2:end) - F(:,1:end-1) ) + DT * S ;
110
111end
112
113%
114% Advancing with simple Godunov numerical scheme
115%
116function Qnew = doStepGodunov( Time, DT, Xnodes, Q )
117 % extrapolation (with only one ghost cell by side)
118 Qe = [ Q(:,end) Q Q(:,1) ] ;
119 % reconstruction no needed
120
121 % compute numerical flux
122 QL = Qe(:,1:end-1) ; % cell on the left
123 QR = Qe(:,2:end) ; % cell on the right
124 QSTAR = Riemann(QL, QR) ;
125 F = Flux(QSTAR) ;
126 S = Source(Q) ;
127
128 DX = Xnodes(2) - Xnodes(1) ; % cells are assumed all of equal size
129 Qnew = Q - (DT/DX) .* ( F(2:end) - F(1:end-1) ) + DT * S ;
130
131end
Test Ader2 for Burger equation: File TestAder2Burger.m
:open:
1% Test Advancing routine by solving the problem
2%
3% Q (x,t) + Q(x,t) Q (x,t) = 0 -pi <= x <= pi
4% t x
5%
6% Q(x,0) = 1+sin(x)
7%
8% Cyclic boundary conditions
9%
10% Last revision: 28 May 2009
11%
12function TestAder2Burger
13
14 N = 100 ; % number of cells
15
16 % setup the boundary of the cells
17 DX = 2*pi/N ;
18 Xnodes = [-pi:DX:pi] ;
19
20 % setup intial conditions
21 Xc = (Xnodes(1:end-1)+Xnodes(2:end))/2 ; % center of the cells
22 Qinit = 1+sin(Xc) ;
23
24 % initial time and time step
25 InitialTime = 0 ;
26 FinalTime = 10 ;
27 StepTime = 0.1 ;
28 CFLratio = 0.9 ;
29
30 [ Qframes, Tframes ] = Advancing( Qinit, ...
31 Xnodes, ...
32 InitialTime, ...
33 FinalTime, ...
34 StepTime, ...
35 CFLratio, ...
36 @maxSpeed, ...
37 @doStepADER2 ) ;
38
39 [ Qframes1, Tframes1 ] = Advancing( Qinit, ...
40 Xnodes, ...
41 InitialTime, ...
42 FinalTime, ...
43 StepTime, ...
44 CFLratio, ...
45 @maxSpeed, ...
46 @doStepGodunov ) ;
47
48 % plot the solution at final time step
49 [XX,YY] = buildXYForPlot( Xnodes, Qframes{end} ) ;
50 [X1,Y1] = buildXYForPlot( Xnodes, Qframes1{end} ) ;
51 plot( XX, YY, X1, Y1 ) ;
52
53end
54%
55% Return a vector with the maximum speed of each cell
56%
57function SPEED = maxSpeed( Q )
58 SPEED = abs(Q) ;
59end
60
61function A = JFlux( Q )
62 A = Q ;
63end
64
65function F = Flux( Q )
66 F = (Q .* Q) ./ 2 ;
67end
68%
69% Solve the Riemann problem for the inviscid Burgers equation exactly.
70%
71function USTAR = Riemann(UL, UR)
72 % UL Left data state
73 % UR Right data state
74 % S Shock speed
75 % USTAR Sampled state
76 ISW = find ( UL < UR ) ;
77 IRW = find ( UL >= UR ) ;
78 % Solution is a shock wave
79 % Compute shock speed S
80 S(ISW) = 0.5*(UL(ISW) + UR(ISW)) ;
81 % Sample the state along the t-axis
82 IGE = find( S(ISW) >= 0 ) ;
83 ILT = find( S(ISW) < 0 ) ;
84 USTAR(IGE) = UL(IGE) ;
85 USTAR(ILT) = UR(ILT) ;
86 % Solution is a rarefaction wave.
87 % There are 3 cases:
88 I1 = find( UL >= 0 ) ;
89 I2 = find( UR <= 0 ) ;
90 I3 = find( UL < 0 & UR > 0 ) ;
91 USTAR(I1) = UL(I1) ; % Right supersonic rarefaction
92 USTAR(I2) = UR(I2) ; % Left supersonic rarefaction
93 USTAR(I3) = 0 ; % Transonic rarefaction
94end
95
96function S = Source( Q )
97 S = zeros(size(Q)) ;
98end
99
100function D0 = Leading0( QL, QR )
101 D0 = Riemann(QL,QR) ;
102end
103
104function D1 = Leading1( QL, QR, D0 )
105 D1 = zeros(size(QL)) ;
106 I1 = find( D0 > 0 ) ;
107 I2 = find( D0 <= 0 ) ;
108 D1(I1) = QL(I1) ;
109 D1(I2) = QR(I2) ;
110 %for k=1:size(QL,2)
111 % D1(k) = LinearRiemannProblem( QL(k), QR(k), A(k) ) ;
112 %end
113end
114%
115% Advancing with simple Godunov numerical scheme
116%
117function Qnew = doStepADER2( Time, DT, Xnodes, Q )
118
119 % extrapolation
120 Qe = [ Q(:,end-1) Q(:,end) Q Q(:,1) Q(:,2) ] ;
121
122 [F,S] = ADER2Flux( Qe, Xnodes, DT, @Flux, @WENOSlopeLimiter, @Leading0, @Leading1, @Source ) ;
123
124 DX = Xnodes(2)-Xnodes(1) ;
125 Qnew = Q - (DT/DX) .* ( F(:,2:end) - F(:,1:end-1) ) + DT * S ;
126
127end
128
129%
130% Advancing with simple Godunov numerical scheme
131%
132function Qnew = doStepGodunov( Time, DT, Xnodes, Q )
133 % extrapolation (with only one ghost cell by side)
134 Qe = [ Q(end) Q Q(1) ] ;
135 % reconstruction no needed
136
137 % compute numerical flux
138 QL = Qe(1:end-1) ; % cell on the left
139 QR = Qe(2:end) ; % cell on the right
140 QSTAR = Riemann(QL, QR) ;
141 F = Flux( QSTAR ) ;
142
143 DX = Xnodes(2) - Xnodes(1) ; % cells are assumed all of equal size
144 Qnew = Q - (DT/DX) .* ( F(2:end) - F(1:end-1) ) ;
145
146end
Test Ader2 for a 2D linear hyperbolic equation: File TestAder2.m
:open:
1% Test Advancing routine by solving the problem
2%
3% Q (x,t) + A Q (x,t) = 0 -1 <= x <= 1
4% t x
5%
6% /
7% | [0;0] if x < -1/2
8% Q(x,0) = | [1;2] if x > -1/2 and x < 1/2
9% | [0;0] if x > 1/2
10% \
11% +---+
12% | |
13% ---------+ +----------
14%
15% Cyclic boundary conditions
16%
17% Last revision: 28 May 2009
18%
19function TestAder2
20
21 global A_jacobian ;
22
23 A_jacobian = [ 0 1 ; 1 0 ] ;
24
25 N = 100 ; % number of cells
26 N4 = N/4 ;
27
28 % setup intial conditions
29 Qinit = [ zeros(2,N4) [1;2]*ones(1,N-2*N4) zeros(2,N4) ] ;
30
31 % setup the boundary of the cells
32 Xnodes = -1:2/N:1 ;
33
34 % initial time and time step
35 InitialTime = 0 ;
36 FinalTime = 6.3 ;
37 StepTime = 0.1 ;
38 CFLratio = 0.9 ;
39
40 [ Qframes, Tframes ] = Advancing( Qinit, ...
41 Xnodes, ...
42 InitialTime, ...
43 FinalTime, ...
44 StepTime, ...
45 CFLratio, ...
46 @maxSpeed, ...
47 @doStepADER2 ) ;
48
49 [ Qframes1, Tframes1 ] = Advancing( Qinit, ...
50 Xnodes, ...
51 InitialTime, ...
52 FinalTime, ...
53 StepTime, ...
54 CFLratio, ...
55 @maxSpeed, ...
56 @doStepGodunov ) ;
57
58 % plot the solution at final time step
59 [XX,YY] = buildXYForPlot( Xnodes, Qframes{end} ) ;
60 [X1,Y1] = buildXYForPlot( Xnodes, Qframes1{end} ) ;
61 plot( XX, YY, X1, Y1 ) ;
62
63end
64
65%
66% Return a vector with the maximum speed of each cell
67%
68function SPEED = maxSpeed( Q )
69 SPEED = ones(1,size(Q,2)) ;
70end
71
72function F = Flux( Q )
73 F = JFlux( Q ) * Q ;
74end
75
76function A = JFlux( Q )
77 global A_jacobian ;
78 A = A_jacobian ;
79end
80
81function S = Source( Q )
82 S = zeros(size(Q)) ;
83end
84
85function D0 = Leading0( QL, QR )
86 global A_jacobian ;
87 D0 = LinearRiemannProblem( QL, QR, A_jacobian ) ;
88end
89
90function D1 = Leading1( QL, QR, D0 )
91 global A_jacobian ;
92 D1 = LinearRiemannProblem( QL, QR, A_jacobian ) ;
93end
94%
95% Advancing with simple Godunov numerical scheme
96%
97function Qnew = doStepADER2( Time, DT, Xnodes, Q )
98
99 % extrapolation
100 Qe = [ Q(:,end-1) Q(:,end) Q Q(:,1) Q(:,2) ] ;
101
102 [F,S] = ADER2Flux( Qe, Xnodes, DT, @Flux, @WENOSlopeLimiter, @Leading0, @Leading1, @Source ) ;
103
104 DX = Xnodes(2)-Xnodes(1) ;
105 Qnew = Q - (DT/DX) .* ( F(:,2:end) - F(:,1:end-1) ) + DT * S ;
106
107end
108
109%
110% Advancing with simple Godunov numerical scheme
111%
112function Qnew = doStepGodunov( Time, DT, Xnodes, Q )
113 % extrapolation (with only one ghost cell by side)
114 Qe = [ Q(:,end) Q Q(:,1) ] ;
115 % reconstruction no needed
116
117 % compute numerical flux
118 QL = Qe(:,1:end-1) ; % cell on the left
119 QR = Qe(:,2:end) ; % cell on the right
120 QSTAR = Leading0(QL, QR) ;
121 F = Flux( QSTAR ) ;
122
123 DX = Xnodes(2) - Xnodes(1) ; % cells are assumed all of equal size
124 Qnew = Q - (DT/DX) .* ( F(:,2:end) - F(:,1:end-1) ) ;
125
126end
Check the second order of Ader2 numerical flux: File TestAder2Order.m
:open:
1% Test ADER2 by solving the problem
2%
3% Q(x,t) + Q(x,t) = 0 -1 <= x <= 1
4% t x
5%
6% Q(x,0) = 1+sin(x)
7%
8% With Cyclic boundary conditions
9%
10% Last revision: 28 May 2009
11%
12function TestAder2Order
13
14 NN = [ 50 100 200 400 800 ] ;
15
16 for k=1:4
17
18 N = NN(k) ;% number of cells
19
20 % setup the boundary of the cells
21 DX = 2*pi/N ;
22 Xnodes = [-pi:DX:pi] ;
23
24 % setup intial conditions
25 Xc = (Xnodes(1:end-1)+Xnodes(2:end))/2 ; % center of the cells
26 Qinit = Q0(Xc) ;
27
28 % initial time and time step
29 InitialTime = 0 ;
30 FinalTime = 20 ;
31 StepTime = 1 ;
32 CFLratio = 0.95 ;
33
34 Qesatta = Q0(Xc - 20) ;
35
36 [ Qframes, Tframes ] = Advancing( Qinit, ...
37 Xnodes, ...
38 InitialTime, ...
39 FinalTime, ...
40 StepTime, ...
41 CFLratio, ...
42 @maxSpeed, ...
43 @doStepADER2 ) ;
44
45 % plot the solution at final time step
46 [XX,YY] = buildXYForPlot( Xnodes, Qframes{end} ) ;
47 [X1,Y1] = buildXYForPlot( Xnodes, Qesatta ) ;
48 plot( XX, YY, X1, Y1) ;
49
50 err(k) = max(abs(YY-Y1)) ;
51 disp( sprintf( 'Errore %g', err(k) ) ) ;
52 end
53
54 disp( sprintf( 'Order %g', log(err(1)/err(2))/log(2) ) ) ;
55 disp( sprintf( 'Order %g', log(err(2)/err(3))/log(2) ) ) ;
56 disp( sprintf( 'Order %g', log(err(3)/err(4))/log(2) ) ) ;
57
58end
59
60%
61%
62%
63function Q = Q0( Xc )
64 Q = 1+sin(Xc) ;
65end
66
67
68%
69% Return a vector with the maximum speed of each cell
70%
71function SPEED = maxSpeed( Q )
72 SPEED = ones(size(Q)) ;
73end
74
75%
76% Flux for linear transport
77%
78function F = Flux( Q )
79 F = Q ;
80end
81
82%
83% Jacobians of the flux (vectorial form)
84%
85function A = JFlux( Q )
86 A = ones(size(Q)) ;
87end
88%
89% Solve the Riemann problem for the linear transport equation exactly.
90%
91function USTAR = Riemann(UL, UR)
92 USTAR = UL ;
93end
94
95function S = Source( Q )
96 S = zeros(size(Q)) ;
97end
98
99function D0 = Leading0( QL, QR )
100 D0 = Riemann(QL,QR) ;
101end
102
103function D1 = Leading1( DL, DR, D0 )
104 D1 = Riemann(DL, DR) ;
105end
106%
107% Given average states compute unlimited slopes
108%
109% INPUTS:
110%
111% Q = average values
112%
113% OUTPUTS:
114%
115% DELTA = slopes
116%
117% The slopes are built by finite difference of sucessive averages.
118% In this way slopes associated to interfaces are used to copute cell slopes.
119% The slopes associated to a cell is the minimum slope between the two interface slopes.
120%
121function DELTA = SlopeNoLimiter( Q )
122 % compute interface slopes, SLOPE(k) is the slopes of interface between cell k and k+1
123 DELTA = (Q(:,3:end) - Q(:,1:end-2))./2 ;
124end
125
126%
127% given the vector (matrix) a and b return
128% res(k) = sign(a)*min(abs(a(k)),abs(b(k))) if a(k)*b(k)>0
129% res(k) = 0 otherwise
130%
131function res = minmod( a, b )
132 res = zeros( size(a) ) ;
133 I1 = find( a > 0 & b > 0 ) ;
134 I2 = find( a < 0 & b < 0 ) ;
135 I3 = find( a.*b <= 0 ) ;
136 res(I1) = min(a(I1),b(I1)) ;
137 res(I2) = max(a(I2),b(I2)) ;
138 res(I3) = 0 ;
139end
140
141%
142% Advancing with ADER2 numerical scheme
143%
144function Qnew = doStepADER2( Time, DT, Xnodes, Q )
145
146 % extrapolation
147 Qe = [ Q(:,end-1) Q(:,end) Q Q(:,1) Q(:,2) ] ;
148
149 [F,S] = ADER2Flux( Qe, Xnodes, DT, @Flux, @SlopeNoLimiter, @Leading0, @Leading1, @Source ) ;
150
151 DX = Xnodes(2)-Xnodes(1) ;
152 Qnew = Q - (DT/DX) .* ( F(:,2:end) - F(:,1:end-1) ) + DT * S ;
153
154end