I am trying to implement the DG method for the solution of non-linear hyperbolic problems. The aim is mainly educational. I want to make sure I understand exactly what is happening and not just using some ready-made toolbox and think that I know what is happening when in fact I do not. Therefore, I am writing the complete code from scratch.
I started with the linear advection equation and I managed to get a working solution for the nodal approximation for both Gauss-Legendre and Gauss-Lobatto nodes with Lagrange polynomials as the basis function. A naive transition to the non-linear Burgers' equation, where numerical quadratures were used for the stiffness matrix, was unsuccessful so I did the numerical quadrature version for the linear advection as well. It is not at all stable either. I would like to understand the reason for that and find out the solution for a stable numerical method.
I do understand that the Gauss-Lobato is only accurate for polynomials of order $2n-3$ and I do understand that the diagonal mass matrix resulting from such quadrature is not exact. The polynomial order is $k=2$, the number of GL points is $n=3$. The integrands in the mass matrix are of order $4$ and in the stiffness matrix of order $3$.
From that I would assume that the stiffness matrix should be evaluated exactly in case of the linear advection, but I am getting a different form.
The scheme is: $$ M \frac{\partial y}{\partial t} = K y - (f_r - f_l) / dx $$
together with the RK SSP43 solver in time. Numerical fluxes use the upwind flux scheme.
When using these matrices, derived in Mathematica by analytical integration, the scheme works well:
$$ M = \begin{pmatrix} 4 & 2 & -1\\ 2 & 16 & 2 \\ -1 & 2 & 4 \end{pmatrix}/15\\ K = \begin{pmatrix} -3 & -4 & 1\\ 4 & 0 & -4 \\ -1 & 4 & 3 \end{pmatrix} / 6\\ $$
With the numerically-derived stiffness matrix it produces very oscillatory solutions after a very short time, no matter which mass-matrix is used:
$$ M = \begin{pmatrix} 1 & 0 & 0\\ 0 & 3 & 0 \\ 0 & 0 & 1 \end{pmatrix}/4\\ K = \begin{pmatrix} -3 & -3 & 1\\ 4 & 0 & -4 \\ -1 & 3 & 3 \end{pmatrix} / 8\\ $$
My Mathematica code for the derivations is probably not very elegant, but I can share it too
In[4]:= Clear["Global`*"]
In[5]:= a = ({
{a1},
{a2},
{a3}
})
Out[5]= {{a1}, {a2}, {a3}}
In[7]:= nodes = {-1, 0, 1}
Out[7]= {-1, 0, 1}
In[8]:= \[Phi][\[Xi]_] = ({
{InterpolatingPolynomial[{{nodes[[1]], 1}, {nodes[[2]],
0}, {nodes[[3]], 0}}, \[Xi]]},
{InterpolatingPolynomial[{{nodes[[1]], 0}, {nodes[[2]],
1}, {nodes[[3]], 0}}, \[Xi]]},
{InterpolatingPolynomial[{{nodes[[1]], 0}, {nodes[[2]],
0}, {nodes[[3]], 1}}, \[Xi]]}
}) // FullSimplify
Out[8]= {{1/2 (-1 + \[Xi]) \[Xi]}, {1 - \[Xi]^2}, {1/
2 \[Xi] (1 + \[Xi])}}
In[9]:= \[Phi][\[Xi]_] = {InterpolatingPolynomial[{{nodes[[1]],
1}, {nodes[[2]], 0}, {nodes[[3]], 0}}, \[Xi]],
InterpolatingPolynomial[{{nodes[[1]], 0}, {nodes[[2]],
1}, {nodes[[3]], 0}}, \[Xi]],
InterpolatingPolynomial[{{nodes[[1]], 0}, {nodes[[2]],
0}, {nodes[[3]], 1}}, \[Xi]]} // FullSimplify
Out[9]= {1/2 (-1 + \[Xi]) \[Xi], 1 - \[Xi]^2, 1/2 \[Xi] (1 + \[Xi])}
In[10]:= D\[Phi][\[Xi]_] = D[\[Phi][\[Xi]], \[Xi]] // FullSimplify
Out[10]= {-(1/2) + \[Xi], -2 \[Xi], 1/2 + \[Xi]}
In[11]:= M = Integrate[TensorProduct[\[Phi][x], \[Phi][x]], {x, -1, 1}]
Out[11]= {{4/15, 2/15, -(1/15)}, {2/15, 16/15, 2/15}, {-(1/15), 2/15,
4/15}}
In[12]:= S =
Integrate[TensorProduct[\[Phi][x], D\[Phi][x]], {x, -1, 1}] //
FullSimplify
Out[12]= {{-(1/2), 2/3, -(1/6)}, {-(2/3), 0, 2/3}, {1/6, -(2/3), 1/2}}
In[13]:= S2 = S * 6
Out[13]= {{-3, 4, -1}, {-4, 0, 4}, {1, -4, 3}}
In[14]:= K2 = Transpose[S2]
Out[14]= {{-3, -4, 1}, {4, 0, -4}, {-1, 4, 3}}
In[15]:= {{-3, -4, 1}, {4, 0, -4}, {-1, 4, 3}}
Out[15]= {{-3, -4, 1}, {4, 0, -4}, {-1, 4, 3}}
In[16]:= TPM = TensorProduct[\[Phi][x], \[Phi][x]]
Out[16]= {{1/4 (-1 + x)^2 x^2, 1/2 (-1 + x) x (1 - x^2),
1/4 (-1 + x) x^2 (1 + x)}, {1/2 (-1 + x) x (1 - x^2), (1 - x^2)^2,
1/2 x (1 + x) (1 - x^2)}, {1/4 (-1 + x) x^2 (1 + x),
1/2 x (1 + x) (1 - x^2), 1/4 x^2 (1 + x)^2}}
In[17]:= Mnum =
1/4 * (TPM /. x -> -1) + 3/4*(TPM /. x -> 0) + 1/4*(TPM /. x -> 1)
Out[17]= {{1/4, 0, 0}, {0, 3/4, 0}, {0, 0, 1/4}}
In[19]:= TP = TensorProduct[\[Phi][x], D\[Phi][x]]
Out[19]= {{1/2 (-1 + x) (-(1/2) + x) x, -((-1 + x) x^2),
1/2 (-1 + x) x (1/2 + x)}, {(-(1/2) + x) (1 - x^2), -2 x (1 -
x^2), (1/2 + x) (1 - x^2)}, {1/
2 (-(1/2) + x) x (1 + x), -x^2 (1 + x), 1/2 x (1/2 + x) (1 + x)}}
In[20]:= Snum =
1/4 * (TP /. x -> -1) + 3/4*(TP /. x -> 0) + 1/4*(TP /. x -> 1)
Out[20]= {{-(3/8), 1/2, -(1/8)}, {-(3/8), 0, 3/8}, {1/8, -(1/2), 3/8}}
In[21]:= Snum2 = Snum*8
Out[21]= {{-3, 4, -1}, {-3, 0, 3}, {1, -4, 3}}
In[22]:= Knum = Transpose[Snum2]
Out[22]= {{-3, -3, 1}, {4, 0, -4}, {-1, 3, 3}}
```