diff --git a/src/glgl.jl b/src/glgl.jl index 47d47cd5e93664ea5c664d66877502772089ecc7..54207a060c001df34c369f22da71452ddc3f9b9e 100644 --- a/src/glgl.jl +++ b/src/glgl.jl @@ -1,22 +1,23 @@ module GLGL -using LinearAlgebra, Jacobi, ToggleableAsserts -import dg1d: purge_zeros!, lagrange_poly +using Jacobi, LinearAlgebra, ToggleableAsserts +import dg1d: purge_zeros!, lagrange_poly, first_derivative_matrix, second_derivative_matrix """ -Computes quadrature nodes, weights and derivative weights -for the Generalized-Gauss-Lobatto quadrature rule. -n_pts ... number of quadrature nodes -Return values -x ... quadrature nodes, vector -w ... quadrature weights, vector -v ... derivative weight, number + rule(Npts::Integer) + +Computes quadrature nodes and weights for the Generalized-Legendre-Gauss-Lobatto quadrature rule. """ -function rule(n_pts::Integer) +function rule(Npts::Integer) + x, w, v, D = inner_product_rule(Npts) + @. w += v * (D[1,:] - D[end,:]) + return x, w +end +function inner_product_rule(Npts::Integer) + N = Npts - 2 - N = n_pts - 2 gb_x, gb_w = [], [] if N > 0 # Integration nodes and weights for Gauss-Gegenbauer quadrature @@ -24,229 +25,127 @@ function rule(n_pts::Integer) gb_x = zgj(N, α, β) gb_w = wgj(gb_x, α, β) end - - x = zeros(n_pts) - w = zeros(n_pts) + x = zeros(Npts) + w = zeros(Npts) x[2:end-1] .= gb_x x[1] = -1.0 x[end] = 1.0 - w[2:end-1] .= @. gb_w / (1.0 - gb_x^2)^2 - w[1] = w[end] = 8.0 / 3.0 * (2.0 * N^2 + 10.0 * N + 9.0) / ((N+1.0) * (N+2.0) * (N+3.0) * (N+4.0)) v = 8.0 / ((N+1.0) * (N+2.0) * (N+3.0) * (N+4.0)) - return x, w, v -end # function - - - -""" - integrate(f, x, w, v, D) - -Integrate `f` sampled on GLGL quadrature nodes `x` with quadrature weights `w`, -boundary weight `v` and derivative matrix `D` based on `x`. -Use `rule` to obtain `x, w, v` and use `first_derivative_matrix` to obtain `D`. -""" -function integrate(f::AbstractVector, x::AbstractVector, w::AbstractVector, v::Real, D::AbstractVector) - - N = length(w) - @toggled_assert (N,N) == size(D) - @toggled_assert N == length(f) - - sum = dot(f, w) - sum += v * dot(view(D,1,:), f) - sum -= v * dot(view(D,N,:), f) + D = first_derivative_matrix(x) - return sum + return x, w, v, D end """ - integrate(f1, f2, w, v, D) + integrate(f, x, w) -Similar to `integrate(f, w)`, but computes the inner product of `f1*f2` where both -`f1, f2` must be sampled on the GLGL quadrature nodes `x` associated with the quadrature -weights `w`, boundary weight `v` and derivative matrix `D` based on `x`. -Use `rule` to obtain `x, w, v` and use `first_derivative_matrix` to obtain `D`. +Integrate `f` sampled on GLGL quadrature nodes `x` with quadrature weights `w`. +Use `rule` to obtain `x, w`. """ -function integrate(f1::AbstractVector, f2::AbstractVector, x::AbstractVector, w::AbstractVector, - v::Real, D::AbstractMatrix) - - N = length(w) - @toggled_assert (N,N) == size(D) - @toggled_assert N == length(f1) - @toggled_assert N == length(f2) - - sum = dot(f1.*f2, w) - vD1, vDN = view(D,1,:), view(D,N,:) - sum += v * (f1[1] * dot(vD1, f2) + f2[1] * dot(vD1, f1)) - sum -= v * (f1[end] * dot(vDN, f2) + f2[end] * dot(vDN, f1)) - - return sum +function integrate(f::AbstractVector, x::AbstractVector, w::AbstractVector) + @toggled_assert length(w) == length(f) == length(x) + return dot(w, f) end """ integrate(f::Function, idxs::AbstractVector{<:Integer}, x, w) -Integrate `f` sampled on GLGL quadrature nodes `x` with quadrature weights `w`, -boundary weight `v` and derivative matrix `D` based on `x`. +Integrate `f` sampled on GLGL quadrature nodes `x` with quadrature weights `w`. `f(idxs[i])` shall return the value of the integrand evaluated at `x[i]`. -Use `rule` to obtain `x, w, v` and use `first_derivative_matrix` to obtain `D`. +Use `rule` to obtain `x, w`. """ -function integrate(fn::Function, idxs::AbstractVector{<:Integer}, x::AbstractVector, w::AbstractVector, - v::Real, D::AbstractMatrix) - - N = length(w) - @toggled_assert (N,N) == size(D) - @toggled_assert N == length(idxs) - +function integrate(fn::Function, idxs::AbstractVector{<:Integer}, x::AbstractVector) + @toggled_assert length(w) == length(idxs) sum = 0.0 - for i in 1:N - fi = fn(idxs[i]) - sum += (w[i] + v * (D[1,i] - D[N,i])) * fi + for i in 1:length(w) + sum += w[i] * f(idxs[i]) end - return sum end """ - integrate(f::Function, x, w, v, D) + integrate(f::Function, x, w) -Integrate `f` sampled on GLGL quadrature nodes `x` with quadrature weights `w`, -boundary weight `v` and derivative matrix `D` based on `x`. +Integrate `f` sampled on GLGL quadrature nodes `x` with quadrature weights `w`. `f(x[i])` shall return the value of the integrand evaluated at `x[i]`. -Use `rule` to obtain `x, w, v` and use `first_derivative_matrix` to obtain `D`. +Use `rule` to obtain `x, w`. -This is similar to `integrate(f, idxs, x, w, v, D)`, but is better suited if the integrand is +This is similar to `integrate(f, idxs, x, w)`, but is better suited if the integrand is given in closed form. """ -function integrate(f::Function, x::AbstractVector, w::AbstractVector, v::Real, D::AbstractMatrix) - @toggled_assert length(w) == length(x) == size(D, 1) == size(D, 2) +function integrate(f::Function, x::AbstractVector, w::AbstractVector) + @toggled_assert length(w) == length(x) sum = 0.0 N = length(w) for i in 1:N fi = f(x[i]) - sum += (w[i] + v * (D[1,i] - D[N,i])) * fi + sum += w[i] * fi end return sum end """ -M_ij = (li, lj) -x ... GLGL nodes -w ... GLGL weights -v ... GLGL derivative weight -D ... Derivative matrix based on x. + inner_product(f1, f2, x, w) + +Computed the inner product between `f1` and `f2` sampled on GLGL quadrature nodes `x` +with quadrature weights `w`, boundary weights `v` and first derivative matrix `D` +Use `inner_product_rule` to obtain `x, w, v, D`. """ -function mass_matrix(x::AbstractVector, w::AbstractVector, v::Real, D::AbstractMatrix) +function inner_product(f1::AbstractVector, f2::AbstractVector, x::AbstractVector, w::AbstractVector, + v::Real, D::AbstractMatrix) + N = length(w) + @toggled_assert (N,N) == size(D) + @toggled_assert N == length(f1) + @toggled_assert N == length(f2) + sum = dot(f1.*f2, w) + vD1, vDN = view(D,1,:), view(D,N,:) + sum += v * (f1[1] * dot(vD1, f2) + f2[1] * dot(vD1, f1)) + sum -= v * (f1[end] * dot(vDN, f2) + f2[end] * dot(vDN, f1)) + return sum +end - N = length(x) - @assert N == length(w) - @assert (N,N) == size(D) +""" + mass_matrix(Npts::Integer) + +Mass matrix for Lagrange polynomials based on GLGL quadrature nodes. +M_ij = (li, lj) +""" +function mass_matrix(Npts::Integer) + x, w, v, D = inner_product_rule(Npts) M = diagm(w) M[1,:] += v * D[1,:] M[:,1] += v * D[1,:] M[end,:] -= v * D[end,:] M[:,end] -= v * D[end,:] - return M -end # function - +end """ + stiffness_matrix(Npts::Integer) + +Stiffness matrix for Lagrange polynomials based on GLGL quadrature nodes. S_ij = (li, dlj/dx) -Exactly representable, because product is of order 2N - 1 which can be integrated -exactly using LGL quadrature. -x ... GLGL nodes -w ... GLGL weights -v ... GLGL derivative weight -D ... First derivative matrix based on x. -D2 ... Second derivative matrix based on x. """ -function stiffness_matrix(x::AbstractVector, w::AbstractVector, v::Real, - D::AbstractMatrix, D2::AbstractMatrix) - - N = length(x) - @assert N == length(w) - @assert (N,N) == size(D) - @assert (N,N) == size(D2) - +function stiffness_matrix(Npts::Integer) + x, w, v, D = inner_product_rule(Npts) + D2 = second_derivative_matrix(x) S = w .* D S[1,:] += v * D2[1,:] S[end,:] -= v * D2[end,:] S .+= v * D[1,:] .* transpose(D[1,:]) S .-= v * D[end,:] .* transpose(D[end,:]) - return S end -# TODO Add versions of mass_matrix, stiffness_matrix that take -# a single argument n_pts. - - -""" -L_ij = (P_i, P_j) -Analogon to mass matrix of Lagrange polynomials, expresses the linear dependency -of the numerical representation of the Legendre basis. Ideally, it is a -diagonal matrix (which should be ensured by the GLGL quadrature). -x ... GLGL nodes -w ... GLGL weights -v ... GLGL derivative weight -D ... First derivative matrix based on x. -""" -function linear_dependency_matrix(x::AbstractVector, w::AbstractVector, v::Real, D::AbstractMatrix) - N = length(x) - L = zeros(N,N) - for i in 1:N - Pi = map(x->legendre(x, i-1), x) - for j in i:N - Pj = map(x->legendre(x, j-1), x) - lij = integrate(Pi, Pj, x, w, v, D) - L[i,j] = lij - if i != j - L[j,i] = L[i,j] - end - end - end - purge_zeros!(L) - - return L end - - -""" -E_ij = (l_i, P_j) -Commonly used to project either Lagrange polynomials onto Legendres or -reverse. -x ... GLGL nodes -w ... GLGL weights -v ... GLGL derivative weight -D ... First derivative matrix based on x. -""" -function expansion_matrix(x::AbstractVector, w::AbstractVector, v::Real, D::AbstractMatrix) - N = length(x) - T = zeros(N,N) - for i in 1:N - li = map(xi->lagrange_poly(i, xi, x), x) - for j in 1:N - Pj = map(x->legendre(x, j-1), x) - tij = integrate(li, Pj, x, w, v, D) - T[i,j] = tij - end - end - purge_zeros!(T) - - return T -end - - - -end # module diff --git a/src/lgl.jl b/src/lgl.jl index 31309a4173066a78e23a5f26f5b05577a94ab6ff..6a7c97e859347df251d63d181ce136bb110301eb 100644 --- a/src/lgl.jl +++ b/src/lgl.jl @@ -5,21 +5,19 @@ using Jacobi, LinearAlgebra, ToggleableAsserts import dg1d: lagrange_poly, first_derivative_matrix, purge_zeros! - """ -Quadrature nodes and weights for Gauss-Legendre rule. -n_pts ... number of quadrature points -Exact up to order 2*n_pts - 1. + rule(Npts::Integer) + +Computes quadrature nodes and weights for the Legendre-Gauss-Lobatto-Legendre quadrature rule. """ -function rule(n_pts::Integer) +function rule(Npts::Integer) α = 0.0; β = 0.0 - x = zglj(n_pts, α, β) + x = zglj(Npts, α, β) w = wglj(x, α, β) return x, w end - """ integrate(f, x, w) @@ -27,30 +25,11 @@ Integrate `f` sampled on LGL quadrature nodes `x` with quadrature weights `w`. Use `rule` to obtain `x, w`. """ function integrate(f::AbstractVector, x::AbstractVector, w::AbstractVector) - @toggled_assert length(w) == length(f) + @toggled_assert length(w) == length(f) == length(x) return dot(w, f) end -""" - integrate(f1, f2, x, w) - -Similar to `integrate(f, w)`, but computes the inner product of `f1*f2` where both -`f1, f2` must be sampled on the LGL quadrature nodes `x` associated with the quadrature -weights `w`. -Use `rule` to obtain `x, w`. -""" -function integrate(f1::AbstractVector, f2::AbstractVector, x::AbstractVector, w::AbstractVector) - @toggled_assert length(w) == length(f1) - @toggled_assert length(w) == length(f2) - I = 0.0 - for i = 1:length(w) - I += w[i] * f1[i] * f2[i] - end - return I -end - - """ integrate(f::Function, idxs::AbstractVector{<:Integer}, x, w) @@ -88,6 +67,23 @@ function integrate(f::Function, x::AbstractVector, w::AbstractVector) end +""" + inner_product(f1, f2, x, w) + +Computed the inner product between `f1` and `f2` sampled on LGL quadrature nodes `x` +with quadrature weights `w`. +Use `rule` to obtain `x, w`. +""" +function inner_product(f1::AbstractVector, f2::AbstractVector, x::AbstractVector, w::AbstractVector) + @toggled_assert length(w) == length(f1) == length(f2) == length(x) + sum = 0.0 + for i in 1:length(w) + sum += w[i] * f1[i] * f2[i] + end + return sum +end + + """ Inverse of exact full mass matrix, computed using Sherman-Morrison formula, cf. PhD thesis Marcus Bugner, Notes spectral elements Bernd Bruegmann, @@ -105,176 +101,64 @@ function inverse_mass_matrix_exact(n_pts::Integer) end - """ n_pts ... number of qudrature nodes = number of lagrange polynomials """ -function inverse_mass_matrix_lumped(n_pts::Integer) - _, w = rule(n_pts) +function inverse_mass_matrix_lumped(Npts::Integer) + _, w = rule(Npts) invM = diagm(1.0 ./ w) return invM end - """ M_ij = (li, lj) n_pts ... number of qudrature nodes = number of lagrange polynomials """ -function mass_matrix_exact(n_pts::Integer) - z, w = rule(n_pts) - M = zeros(n_pts, n_pts) - aux_z, aux_w = rule(n_pts+2) +function mass_matrix_exact(Npts::Integer) + z, w = rule(Npts) + M = zeros(Npts, Npts) + aux_z, aux_w = rule(Npts+2) L(i, x) = lagrange_poly(i, x, z) - M = zeros(n_pts, n_pts) - for i=1:n_pts, j=1:n_pts + M = zeros(Npts, Npts) + for i=1:Npts, j=i:Npts li = L.(i, aux_z) - for j = i:n_pts + for j = i:Npts lj = L.(j, aux_z) - M[i,j] = integrate(li, lj, aux_w) - if (i != j) + M[i,j] = inner_product(li, lj, aux_z, aux_w) + if j > i M[j,i] = M[i,j] end end end - return M end - """ M_ij = (li, lj) Approximated mass matrix due to under integration of LGL quadrature. n_pts ... number of qudrature nodes = number of lagrange polynomials """ -function mass_matrix_lumped(n_pts::Integer) - z, w = rule(n_pts) +function mass_matrix_lumped(Npts::Integer) + z, w = rule(Npts) M = diagm(w) return M end - """ S_ij = (li, dlj/dx) Exactly representable, because product is of order 2N - 1 which can be integrated exactly using LGL quadrature. n_pts ... number of quadrature nodes = number of lagrange polynomials """ -function stiffness_matrix(n_pts::Integer) - z, w = rule(n_pts) +function stiffness_matrix(Npts::Integer) + z, w = rule(Npts) D = first_derivative_matrix(z) S = w .* D return S end - -""" -L_ij = (P_i, P_j) -Analogon to mass matrix of Lagrange polynomials, expresses the linear dependency -of the numerical representation of the Legendre basis. -x ... GLGL nodes -w ... GLGL weights -""" -function linear_dependency_matrix_lumped(x::AbstractVector, w::AbstractVector) - N = length(x) - L = zeros(N,N) - for i in 1:N - Pi = map(x->legendre(x, i-1), x) - for j in i:N - Pj = map(x->legendre(x, j-1), x) - lij = integrate(Pi, Pj, x, w) - L[i,j] = lij - if i != j - L[j,i] = L[i,j] - end - end - end - purge_zeros!(L) - - return L -end - - -""" -E_ij = (l_i, P_j) -Commonly used to project either Lagrange polynomials onto Legendres or -reverse. -x ... GLGL nodes -w ... GLGL weights -""" -function expansion_matrix_lumped(x::AbstractVector, w::AbstractVector) - N = length(x) - T = zeros(N,N) - for i in 1:N - li = map(xi->lagrange_poly(i, xi, x), x) - for j in 1:N - Pj = map(x->legendre(x, j-1), x) - tij = integrate(li, Pj, x, w) - T[i,j] = tij - end - end - purge_zeros!(T) - - return T -end - - -""" -L_ij = (P_i, P_j) -Analogon to mass matrix of Lagrange polynomials, expresses the linear dependency -of the numerical representation of the Legendre basis. -x ... GLGL nodes -w ... GLGL weights -""" -function linear_dependency_matrix_exact(x::AbstractVector, w::AbstractVector) - N = length(x) - N2 = N+2 - x2, w2 = rule(N2) - L = zeros(N,N) - for i in 1:N - Pi = map(x->legendre(x, i-1), x2) - for j in i:N - Pj = map(x->legendre(x, j-1), x2) - lij = integrate(Pi, Pj, x2, w2) - L[i,j] = lij - if i != j - L[j,i] = L[i,j] - end - end - end - purge_zeros!(L) - - return L -end - - -""" -E_ij = (l_i, P_j) -Commonly used to project either Lagrange polynomials onto Legendres or -reverse. -x ... GLGL nodes -w ... GLGL weights -""" -function expansion_matrix_exact(x::AbstractVector, w::AbstractVector) - N = length(x) - N2 = N + 2 - x2, w2 = rule(N2) - T = zeros(N,N) - for i in 1:N - li = map(xi->lagrange_poly(i, xi, x), x2) - for j in 1:N - Pj = map(x->legendre(x, j-1), x2) - tij = integrate(li, Pj, x2, w2) - T[i,j] = tij - end - end - purge_zeros!(T) - - return T end - - -end # module LGL diff --git a/src/spectralelement.jl b/src/spectralelement.jl index dcf0b4186767f86b92bce7675df695bf51f1a907..81b56b75597663f8e3b9e77288cba8baa86d59b3 100644 --- a/src/spectralelement.jl +++ b/src/spectralelement.jl @@ -3,10 +3,9 @@ Base.@kwdef struct SpectralElement Npts::Int64 # number of quadrature points = N + 1 z::Vector{Float64} # quadrature points w::Vector{Float64} # quadrature weights - v::Float64 # derivative weight (only needed for GLGL quadrature rule) - bw::Vector{Float64} # barycentric weights D::Matrix{Float64} # derivative matrix S::Matrix{Float64} # stiffness matrix + M::Matrix{Float64} # mass matrix invM::Matrix{Float64} # inverse mass matrix MDM::Matrix{Float64} # = (M^-1 D^T M) = M^-1 S^T Ml_lhs::Vector{Float64} # = M^-1 l(-1) @@ -16,7 +15,7 @@ Base.@kwdef struct SpectralElement quadr::Symbol # :LGL, :LGL_mass_lumped, :GLGL F::Matrix{Float64} # spectral filtering matrix - function SpectralElement(N::Int, quadr::Symbol; + function SpectralElement(N::Integer, quadr::Symbol; # filter parameters ηc::Float64=0.5, sh::Float64=16.0, α::Float64=36.0) Npts = N + 1 @@ -25,35 +24,26 @@ Base.@kwdef struct SpectralElement z, w = LGL.rule(Npts) v = -1.0 # unused here purge_zeros!(z) # ensures that the centered node for even N basis sits exactly at x = 0. - bw = barycentric_weights(z) D = first_derivative_matrix(z) S = LGL.stiffness_matrix(Npts) + M = LGL.mass_matrix_exact(Npts) invM = LGL.inverse_mass_matrix_exact(Npts) - # TODO Figure out how much the aliasing error influences the accuracy of the inner product. - # Could be totally dealised using the Orszag 2/3rds rule. - L = LGL.linear_dependency_matrix_exact(z, w) - E = LGL.expansion_matrix_exact(z, w) elseif quadr === :LGL_lumped z, w = LGL.rule(Npts) v = -1.0 # unused here purge_zeros!(z) # ensures that the centered node for even N basis sits exactly at x = 0. - bw = barycentric_weights(z) D = first_derivative_matrix(z) S = LGL.stiffness_matrix(Npts) + M = LGL.mass_matrix_lumped(Npts) invM = LGL.inverse_mass_matrix_lumped(Npts) - L = LGL.linear_dependency_matrix_lumped(z, w) - E = LGL.expansion_matrix_lumped(z, w) elseif quadr === :GLGL - z, w, v = GLGL.rule(Npts) + z, w = GLGL.rule(Npts) purge_zeros!(z) # ensures that the centered node for even N basis sits exactly at x = 0. - bw = barycentric_weights(z) D = first_derivative_matrix(z) D2 = second_derivative_matrix(z) - M = GLGL.mass_matrix(z, w, v, D) - S = GLGL.stiffness_matrix(z, w, v, D, D2) + M = GLGL.mass_matrix(Npts) + S = GLGL.stiffness_matrix(Npts) invM = inv(M) - L = GLGL.linear_dependency_matrix(z, w, v, D) - E = GLGL.expansion_matrix(z, w, v, D) else error("Invalid quadrature rule specified! Use one of :LGL_lumped, :LGL, :GLGL.") end @@ -72,14 +62,14 @@ Base.@kwdef struct SpectralElement Ml_lhs = invM * l_lhs Ml_rhs = invM * l_rhs - return new(N, Npts, z, w, v, bw, D, S, invM, MDM, Ml_lhs, Ml_rhs, + return new(N, Npts, z, w, D, S, M, invM, MDM, Ml_lhs, Ml_rhs, V, invV, quadr, F) end end # (5.16) from Hesthaven, Warburton 2007 -function spectral_filter(η, prms) +function spectral_filter(η::Real, prms) ηc, sh, α = prms return if 0 ≤ η ≤ ηc 1 @@ -89,24 +79,23 @@ function spectral_filter(η, prms) end -@inline function inner_product(u1, u2, el::SpectralElement) - @unpack quadr = el - @toggled_assert quadr in (:LGL, :LGL_lumped, :GLGL) - if quadr === :LGL || quadr === :LGL_lumped - return LGL.integrate(u1, u2, el.z, el.w) - else # quadr === :GLGL - return GLGL.integrate(u1, u2, el.z, el.w, el.v, el.D) +@inline function inner_product(u1::AbstractVector, u2::AbstractVector, el::SpectralElement) + @unpack Npts, M = el + result = 0.0 + @turbo for i in 1:Npts, j in 1:Npts + result += u1[i] * M[i,j] * u2[j] end + return result end -@inline function integrate(u, el::SpectralElement) +@inline function integrate(u::AbstractVector, el::SpectralElement) @unpack quadr = el @toggled_assert quadr in (:LGL, :LGL_lumped, :GLGL) if quadr === :LGL || quadr === :LGL_lumped return LGL.integrate(u, el.z, el.w) else # quadr === :GLGL - return GLGL.integrate(u, el.z, el.w, el.v, el.D) + return GLGL.integrate(u, el.z, el.w) end end @@ -117,15 +106,16 @@ end if quadr === :LGL || quadr === :LGL_lumped return LGL.integrate(fn, idxs, el.z, el.w) else # quadr === :GLGL - return GLGL.integrate(fn, idxs, el.z, el.w, el.v, el.D) + return GLGL.integrate(fn, idxs, el.z, el.w) end end -@inline function differentiate(u, el::SpectralElement) +@inline function differentiate(u::AbstractArray, el::SpectralElement) return el.D * u end -@inline function differentiate!(du, u, el::SpectralElement) + +@inline function differentiate!(du::AbstractArray, u::AbstractArray, el::SpectralElement) mul!(du, el.D, u) end diff --git a/test/IntegrationTests/refs/burgers_sine_avmda/output1d.h5 b/test/IntegrationTests/refs/burgers_sine_avmda/output1d.h5 index d2e27152e4d1ac944e2d38cf87060dd1e7100f3f..1a041f434509447ed292d10e1db86b39f72d8094 100644 Binary files a/test/IntegrationTests/refs/burgers_sine_avmda/output1d.h5 and b/test/IntegrationTests/refs/burgers_sine_avmda/output1d.h5 differ diff --git a/test/IntegrationTests/refs/euler_sod_shock_tube_bernstein/output1d.h5 b/test/IntegrationTests/refs/euler_sod_shock_tube_bernstein/output1d.h5 index 7d2cb4eb0cb6a458e63086ae2c59b38af0b3f9e4..387eebaa35970d5fb6599bdae781512889b74e08 100644 Binary files a/test/IntegrationTests/refs/euler_sod_shock_tube_bernstein/output1d.h5 and b/test/IntegrationTests/refs/euler_sod_shock_tube_bernstein/output1d.h5 differ diff --git a/test/IntegrationTests/refs/grhd_bondi_accretion/output0d.h5 b/test/IntegrationTests/refs/grhd_bondi_accretion/output0d.h5 index 2c258cd6e73e717289c01b4a4a953373f070538d..add2a996056d73e37a32e3de6aa665dd59fc14b9 100644 Binary files a/test/IntegrationTests/refs/grhd_bondi_accretion/output0d.h5 and b/test/IntegrationTests/refs/grhd_bondi_accretion/output0d.h5 differ diff --git a/test/IntegrationTests/refs/grhd_bondi_accretion/output1d.h5 b/test/IntegrationTests/refs/grhd_bondi_accretion/output1d.h5 index 740e709f24c311ee88cb745632d6f3fb0f3db056..0bafcfb8acc690abf8d822611a6f20431289162b 100644 Binary files a/test/IntegrationTests/refs/grhd_bondi_accretion/output1d.h5 and b/test/IntegrationTests/refs/grhd_bondi_accretion/output1d.h5 differ diff --git a/test/IntegrationTests/refs/grhd_bondi_infall_avmda/output1d.h5 b/test/IntegrationTests/refs/grhd_bondi_infall_avmda/output1d.h5 index 6f9227a415288f4c49e200f88648973114f66f4f..220135c6a0abbf3b14330cca8d8708b86cf1097e 100644 Binary files a/test/IntegrationTests/refs/grhd_bondi_infall_avmda/output1d.h5 and b/test/IntegrationTests/refs/grhd_bondi_infall_avmda/output1d.h5 differ diff --git a/test/IntegrationTests/refs/srhd_simple_wave_avmda/output1d.h5 b/test/IntegrationTests/refs/srhd_simple_wave_avmda/output1d.h5 index 065bba8f1975121e930d94ae25151e5ccb47a7e3..8d7c701d82b877ec4bdcea885527db8d2f2716ea 100644 Binary files a/test/IntegrationTests/refs/srhd_simple_wave_avmda/output1d.h5 and b/test/IntegrationTests/refs/srhd_simple_wave_avmda/output1d.h5 differ diff --git a/test/UnitTests/src/test_spectral.jl b/test/UnitTests/src/test_spectral.jl index 3a2a38601b4d6e46d8767170b3bf5bf527f0c86d..cdb3f6f47d17015d4325fe53ed2179e7b4dcaa3a 100644 --- a/test/UnitTests/src/test_spectral.jl +++ b/test/UnitTests/src/test_spectral.jl @@ -37,18 +37,14 @@ end f(x) = x^3 - 5.0 * x^2 + 1.0 f2_ana = 118.0/21.0 # according to wolfram alpha - # use quadrature order N+1 = 3+1 = 4 here, because :LGL and :LGL_lumped are only exact up - # to and including 2N-1 + # LGL quadrature is only exact up to order 2*3-1=5, so use N=4 instead N = 4 L = 2.0 - quadrs = [ :LGL, :GLGL, :LGL_lumped ] - - for quadr in quadrs - el = SpectralElement(N, quadr) - fx = f.(el.z) - f2 = dg1d.inner_product(fx, fx, el) - @test isapprox(f2, f2_ana) - end + quadr = :LGL + el = SpectralElement(N, quadr) + fx = f.(el.z) + f2 = dg1d.inner_product(fx, fx, el) + @test isapprox(f2, f2_ana) # check that :GLGL quadrature is exact up to and including order 2N N = 3 @@ -64,8 +60,8 @@ end @testset "Barycentric interpolation" begin # setup - n_pts = 6 - x, _ = dg1d.LGL.rule(n_pts) + Npts = 6 + x, _ = dg1d.LGL.rule(Npts) bw = dg1d.barycentric_weights(x) # test function @@ -83,7 +79,7 @@ end fxintrp = [ dg1d.barycentric_interp(xi, x, bw, fx) for xi in xsmpl ] @test all(isapprox.(fxintrp, fxsmpl)) - # test interpolation using matrix multiplication + # test interpolation using matrix multiplication I = dg1d.barycentric_interp_matrix(xsmpl, x) fxintrp = I * fx @test all(isapprox.(fxintrp, fxsmpl)) @@ -101,62 +97,83 @@ end end -@testset "Operators GLGL" begin +@testset "Test orthogonality relation GLGL" begin - # set up quadrature rule - N = 5 - N_pts = N + 1 - x, w, v = dg1d.GLGL.rule(N_pts) - D = dg1d.first_derivative_matrix(x) + Npts = 6 + + x, w, v, D = dg1d.GLGL.inner_product_rule(Npts) + L = zeros(Npts,Npts) + for i in 1:Npts + Pi = map(x->dg1d.legendre(x, i-1), x) + for j in i:Npts + Pj = map(x->dg1d.legendre(x, j-1), x) + lij = dg1d.GLGL.inner_product(Pi, Pj, x, w, v, D) + L[i,j] = lij + if i != j + L[j,i] = L[i,j] + end + end + end + dg1d.purge_zeros!(L) # analytical result - L_ana = zeros(N_pts, N_pts) - for i in 1:N_pts + L_ana = zeros(Npts, Npts) + for i in 1:Npts L_ana[i,i] = 2.0 / (2.0 * i - 1.0) end - L = dg1d.GLGL.linear_dependency_matrix(x, w, v, D) - @test isapprox(L, L_ana) end -@testset "Operators LGL" begin - - # set up quadrature rule - n_pts = 6 - x, w = dg1d.LGL.rule(n_pts) - quad(f1, f2) = dg1d.LGL.inner_product(w, f1, f2) - - # analytical result - L_ana = zeros(n_pts, n_pts) - for i in 1:n_pts - L_ana[i,i] = 2.0 / (2.0 * i - 1.0) +function lgl_linear_dependency_matrix_exact(Npts::Integer) + Npts2 = Npts+2 + x2, w2 = dg1d.LGL.rule(Npts2) + L = zeros(N,N) + for i in 1:N + Pi = map(x->dg1d.legendre(x, i-1), x2) + for j in i:N + Pj = map(x->dg1d.legendre(x, j-1), x2) + lij = dg1d.LGL.integrate(Pi, Pj, x2, w2) + L[i,j] = lij + if i != j + L[j,i] = L[i,j] + end + end end + dg1d.purge_zeros!(L) - L = dg1d.LGL.linear_dependency_matrix_exact(x, w) - - @test isapprox(L, L_ana) - + return L end @testset "Test orthogonality relation" begin - # set up quadrature rule - n_pts = 6 - x, w = dg1d.LGL.rule(n_pts) - quad(f1, f2) = dg1d.LGL.inner_product(w, f1, f2) + Npts = 6 + + Npts2 = Npts+2 + x2, w2 = dg1d.LGL.rule(Npts2) + L = zeros(Npts,Npts) + for i in 1:Npts + Pi = map(x->dg1d.legendre(x, i-1), x2) + for j in i:Npts + Pj = map(x->dg1d.legendre(x, j-1), x2) + lij = dg1d.LGL.inner_product(Pi, Pj, x2, w2) + L[i,j] = lij + if i != j + L[j,i] = L[i,j] + end + end + end + dg1d.purge_zeros!(L) # analytical result - L_ana = zeros(n_pts, n_pts) - for i in 1:n_pts + L_ana = zeros(Npts, Npts) + for i in 1:Npts L_ana[i,i] = 2.0 / (2.0 * i - 1.0) end - L = dg1d.LGL.linear_dependency_matrix_exact(x, w) - @test isapprox(L, L_ana) end @@ -164,16 +181,15 @@ end @testset "More integrator tests" begin - n_pts = 6 + Npts = 6 p = x -> (x-4)^2 * (x+1)^3 - x, w = dg1d.LGL.rule(n_pts) + x, w = dg1d.LGL.rule(Npts) int = dg1d.LGL.integrate(p, x, w) @test int ≈ 140/3 - x, w, v = dg1d.GLGL.rule(n_pts) - D = dg1d.first_derivative_matrix(x) - int = dg1d.GLGL.integrate(p, x, w, v, D) + x, w = dg1d.GLGL.rule(Npts) + int = dg1d.GLGL.integrate(p, x, w) @test int ≈ 140/3 end