Path: blob/main/src/equations/hyperbolic_diffusion_1d.jl
2055 views
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).1# Since these FMAs can increase the performance of many numerical algorithms,2# we need to opt-in explicitly.3# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.4@muladd begin5#! format: noindent67@doc raw"""8HyperbolicDiffusionEquations1D910The linear hyperbolic diffusion equations in one space dimension.11A description of this system can be found in Sec. 2.5 of the book12- Masatsuka (2013)13I Do Like CFD, Too: Vol 1.14Freely available at [http://www.cfdbooks.com/](http://www.cfdbooks.com/)15Further analysis can be found in the paper16- Nishikawa (2007)17A first-order system approach for diffusion equation. I: Second-order residual-distribution18schemes19[DOI: 10.1016/j.jcp.2007.07.029](https://doi.org/10.1016/j.jcp.2007.07.029)20"""21struct HyperbolicDiffusionEquations1D{RealT <: Real} <:22AbstractHyperbolicDiffusionEquations{1, 2}23Lr::RealT # reference length scale24inv_Tr::RealT # inverse of the reference time scale25nu::RealT # diffusion constant26end2728function HyperbolicDiffusionEquations1D(; nu = 1.0, Lr = inv(2pi))29Tr = Lr^2 / nu30HyperbolicDiffusionEquations1D(promote(Lr, inv(Tr), nu)...)31end3233varnames(::typeof(cons2cons), ::HyperbolicDiffusionEquations1D) = ("phi", "q1")34varnames(::typeof(cons2prim), ::HyperbolicDiffusionEquations1D) = ("phi", "q1")35function default_analysis_errors(::HyperbolicDiffusionEquations1D)36(:l2_error, :linf_error, :residual)37end3839@inline function residual_steady_state(du, ::HyperbolicDiffusionEquations1D)40abs(du[1])41end4243"""44initial_condition_poisson_nonperiodic(x, t, equations::HyperbolicDiffusionEquations1D)4546A non-priodic smooth initial condition. Can be used for convergence tests in combination with47[`source_terms_poisson_nonperiodic`](@ref) and [`boundary_condition_poisson_nonperiodic`](@ref).48!!! note49The solution is periodic but the initial guess is not.50"""51function initial_condition_poisson_nonperiodic(x, t,52equations::HyperbolicDiffusionEquations1D)53# elliptic equation: -νΔϕ = f54# Taken from Section 6.1 of Nishikawa https://doi.org/10.1016/j.jcp.2007.07.02955RealT = eltype(x)56if t == 057# initial "guess" of the solution and its derivative58phi = x[1]^2 - x[1]59q1 = 2 * x[1] - 160else61phi = sinpi(x[1]) # ϕ62q1 = convert(RealT, pi) * cospi(x[1]) # ϕ_x63end64return SVector(phi, q1)65end6667"""68source_terms_poisson_nonperiodic(u, x, t,69equations::HyperbolicDiffusionEquations1D)7071Source terms that include the forcing function `f(x)` and right hand side for the hyperbolic72diffusion system that is used with [`initial_condition_poisson_nonperiodic`](@ref) and73[`boundary_condition_poisson_nonperiodic`](@ref).74"""75@inline function source_terms_poisson_nonperiodic(u, x, t,76equations::HyperbolicDiffusionEquations1D)77# elliptic equation: -νΔϕ = f78# analytical solution: ϕ = sin(πx) and f = π^2sin(πx)79RealT = eltype(u)80@unpack inv_Tr = equations8182dphi = convert(RealT, pi)^2 * sinpi(x[1])83dq1 = -inv_Tr * u[2]8485return SVector(dphi, dq1)86end8788"""89boundary_condition_poisson_nonperiodic(u_inner, orientation, direction, x, t,90surface_flux_function,91equations::HyperbolicDiffusionEquations1D)9293Boundary conditions used for convergence tests in combination with94[`initial_condition_poisson_nonperiodic`](@ref) and [`source_terms_poisson_nonperiodic`](@ref).95"""96function boundary_condition_poisson_nonperiodic(u_inner, orientation, direction, x, t,97surface_flux_function,98equations::HyperbolicDiffusionEquations1D)99# elliptic equation: -νΔϕ = f100RealT = eltype(u_inner)101phi = sinpi(x[1]) # ϕ102q1 = convert(RealT, pi) * cospi(x[1]) # ϕ_x103u_boundary = SVector(phi, q1)104105# Calculate boundary flux106if direction == 2 # u_inner is "left" of boundary, u_boundary is "right" of boundary107flux = surface_flux_function(u_inner, u_boundary, orientation, equations)108else # u_boundary is "left" of boundary, u_inner is "right" of boundary109flux = surface_flux_function(u_boundary, u_inner, orientation, equations)110end111112return flux113end114115"""116source_terms_harmonic(u, x, t, equations::HyperbolicDiffusionEquations1D)117118Source term that only includes the forcing from the hyperbolic diffusion system.119"""120@inline function source_terms_harmonic(u, x, t,121equations::HyperbolicDiffusionEquations1D)122# harmonic solution of the form ϕ = A + B * x, so f = 0123@unpack inv_Tr = equations124125dq1 = -inv_Tr * u[2]126127return SVector(0, dq1)128end129130"""131initial_condition_eoc_test_coupled_euler_gravity(x, t, equations::HyperbolicDiffusionEquations1D)132133Setup used for convergence tests of the Euler equations with self-gravity used in134- Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020)135A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics136[arXiv: 2008.10593](https://arxiv.org/abs/2008.10593)137in combination with [`source_terms_harmonic`](@ref).138"""139function initial_condition_eoc_test_coupled_euler_gravity(x, t,140equations::HyperbolicDiffusionEquations1D)141142# Determine phi_x143RealT = eltype(x)144G = 1 # gravitational constant145C = -4 * G / convert(RealT, pi) # -4 * G / ndims * pi146A = convert(RealT, 0.1) # perturbation coefficient must match Euler setup147rho1 = A * sinpi(x[1] - t)148# initialize with ansatz of gravity potential149phi = C * rho1150q1 = C * A * convert(RealT, pi) * cospi(x[1] - t) # = gravity acceleration in x-direction151152return SVector(phi, q1)153end154155# Calculate 1D flux for a single point156@inline function flux(u, orientation::Integer,157equations::HyperbolicDiffusionEquations1D)158phi, q1 = u159@unpack inv_Tr = equations160161# Ignore orientation since it is always "1" in 1D162f1 = -equations.nu * q1163f2 = -phi * inv_Tr164165return SVector(f1, f2)166end167168# Calculate maximum wave speed for local Lax-Friedrichs-type dissipation169@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer,170equations::HyperbolicDiffusionEquations1D)171return sqrt(equations.nu * equations.inv_Tr)172end173174@inline have_constant_speed(::HyperbolicDiffusionEquations1D) = True()175176@inline function max_abs_speeds(eq::HyperbolicDiffusionEquations1D)177return sqrt(eq.nu * eq.inv_Tr)178end179180# Convert conservative variables to primitive181@inline cons2prim(u, equations::HyperbolicDiffusionEquations1D) = u182183# Convert conservative variables to entropy found in I Do Like CFD, Too, Vol. 1184@inline function cons2entropy(u, equations::HyperbolicDiffusionEquations1D)185phi, q1 = u186187w1 = phi188w2 = equations.Lr^2 * q1189190return SVector(w1, w2)191end192193# Calculate entropy for a conservative state `u` (here: same as total energy)194@inline function entropy(u, equations::HyperbolicDiffusionEquations1D)195energy_total(u, equations)196end197198# Calculate total energy for a conservative state `u`199@inline function energy_total(u, equations::HyperbolicDiffusionEquations1D)200# energy function as found in equations (2.5.12) in the book "I Do Like CFD, Vol. 1"201phi, q1 = u202return 0.5f0 * (phi^2 + equations.Lr^2 * q1^2)203end204end # @muladd205206207