Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maxwell 1D (Wave Equation) #1949

Merged
merged 26 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8a3fb07
Maxwell 1D
DanielDoehring Apr 11, 2024
b24b178
test
DanielDoehring May 16, 2024
a0baf93
another maxwell example
DanielDoehring May 17, 2024
900df0d
non-trivial example
DanielDoehring May 22, 2024
2eef36c
fmt
DanielDoehring May 22, 2024
3612e52
remove comment
DanielDoehring May 22, 2024
d867148
Merge branch 'main' into Maxwell1D
DanielDoehring May 22, 2024
246fece
Merge branch 'main' into Maxwell1D
DanielDoehring May 26, 2024
8e3d844
test for coverage
DanielDoehring May 27, 2024
10813fc
Merge branch 'Maxwell1D' of github.com:DanielDoehring/Trixi.jl into M…
DanielDoehring May 27, 2024
770c420
Merge branch 'main' into Maxwell1D
SimonCan Jun 11, 2024
5a293f9
Update src/equations/maxwell_1d.jl
DanielDoehring Jun 12, 2024
6647154
Update src/equations/maxwell_1d.jl
DanielDoehring Jun 14, 2024
ca45d85
Merge branch 'main' into Maxwell1D
DanielDoehring Jun 14, 2024
c5ea779
Merge branch 'main' into Maxwell1D
SimonCan Jun 14, 2024
9bdbd14
Apply suggestions from code review
DanielDoehring Jun 27, 2024
6345c6f
Merge branch 'main' into Maxwell1D
SimonCan Jul 2, 2024
a2f972b
Apply suggestions from code review
DanielDoehring Jul 3, 2024
5edb7ca
c is scalar
DanielDoehring Jul 3, 2024
9614c13
Merge branch 'main' into Maxwell1D
DanielDoehring Jul 3, 2024
b0b6fa9
try return
DanielDoehring Jul 4, 2024
9c2a0bc
Merge branch 'Maxwell1D' of github.com:DanielDoehring/Trixi.jl into M…
DanielDoehring Jul 4, 2024
0539ffa
Abstract Maxwell
DanielDoehring Jul 4, 2024
fe71bd9
similar constructor as lin euler 1d
DanielDoehring Jul 4, 2024
5d67121
try another constructor
DanielDoehring Jul 4, 2024
7d3fc24
Update src/equations/maxwell_1d.jl
DanielDoehring Jul 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions examples/tree_1d_dgsem/elixir_maxwell_E_excitation.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

using OrdinaryDiffEq
using Trixi

###############################################################################
# semidiscretization of the linear advection equation

equations = MaxwellEquations1D()

solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs)

coordinates_min = 0.0
coordinates_max = 1.0

# Create a uniformly refined mesh with periodic boundaries
mesh = TreeMesh(coordinates_min, coordinates_max,
initial_refinement_level = 4,
n_cells_max = 30_000) # set maximum capacity of tree data structure

# Excite the electric field which causes a standing wave.
# The solution is an undamped exchange between electric and magnetic energy.
function initial_condition_E_excitation(x, t, equations::MaxwellEquations1D)
c = equations.speed_of_light
E = -c * sin(2 * pi * x[1])
B = 0.0

return SVector(E, B)
end

initial_condition = initial_condition_E_excitation
semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)

###############################################################################
# ODE solvers, callbacks etc.

# As the wave speed is equal to the speed of light which is on the order of 3 * 10^8
# we consider only a small time horizon.
ode = semidiscretize(semi, (0.0, 1e-7));
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
summary_callback = SummaryCallback()

# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results
analysis_callback = AnalysisCallback(semi, interval = 100)

# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step
stepsize_callback = StepsizeCallback(cfl = 1.6)

# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver
callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback)

###############################################################################
# run the simulation

sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false),
dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep = false, callback = callbacks);

# Print the timer summary
summary_callback()
49 changes: 49 additions & 0 deletions examples/tree_1d_dgsem/elixir_maxwell_convergence.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

using OrdinaryDiffEq
using Trixi

###############################################################################
# semidiscretization of the linear advection equation

equations = MaxwellEquations1D()

solver = DGSEM(polydeg = 3, surface_flux = flux_hll)

coordinates_min = 0.0
coordinates_max = 1.0

# Create a uniformly refined mesh with periodic boundaries
mesh = TreeMesh(coordinates_min, coordinates_max,
initial_refinement_level = 4,
n_cells_max = 30_000) # set maximum capacity of tree data structure

semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test,
solver)

###############################################################################
# ODE solvers, callbacks etc.

# As the wave speed is equal to the speed of light which is on the order of 3 * 10^8
# we consider only a small time horizon.
ode = semidiscretize(semi, (0.0, 1e-8));
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

summary_callback = SummaryCallback()

# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results
analysis_callback = AnalysisCallback(semi, interval = 100)

# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step
stepsize_callback = StepsizeCallback(cfl = 1.6)

# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver
callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback)

###############################################################################
# run the simulation

sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false),
dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback
save_everystep = false, callback = callbacks);

# Print the timer summary
summary_callback()
3 changes: 2 additions & 1 deletion src/Trixi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ export AcousticPerturbationEquations2D,
ShallowWaterEquationsQuasi1D,
LinearizedEulerEquations1D, LinearizedEulerEquations2D, LinearizedEulerEquations3D,
PolytropicEulerEquations2D,
TrafficFlowLWREquations1D
TrafficFlowLWREquations1D,
MaxwellEquations1D

export LaplaceDiffusion1D, LaplaceDiffusion2D, LaplaceDiffusion3D,
CompressibleNavierStokesDiffusion1D, CompressibleNavierStokesDiffusion2D,
Expand Down
4 changes: 4 additions & 0 deletions src/equations/equations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -512,4 +512,8 @@ abstract type AbstractEquationsParabolic{NDIMS, NVARS, GradientVariables} <:
abstract type AbstractTrafficFlowLWREquations{NDIMS, NVARS} <:
AbstractEquations{NDIMS, NVARS} end
include("traffic_flow_lwr_1d.jl")

abstract type AbstractMaxwellEquations{NDIMS, NVARS} <:
AbstractEquations{NDIMS, NVARS} end
include("maxwell_1d.jl")
end # @muladd
104 changes: 104 additions & 0 deletions src/equations/maxwell_1d.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
# Since these FMAs can increase the performance of many numerical algorithms,
# we need to opt-in explicitly.
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
@muladd begin
#! format: noindent

@doc raw"""
MaxwellEquations1D(c = 299_792_458.0)

The Maxwell equations of electro dynamics
```math
\frac{\partial}{\partial t}
\begin{pmatrix}
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
E \\ B
\end{pmatrix}
+
\frac{\partial}{\partial x}
\begin{pmatrix}
c^2 B \\ E
\end{pmatrix}
=
\begin{pmatrix}
0 \\ 0
\end{pmatrix}
```
in one dimension with speed of light `c = 299792458 m/s` (in vacuum).
In one dimension the Maxwell equations reduce to a wave equation.
The orthogonal magnetic (e.g.`B_y`) and electric field (`E_z`) propagate as waves
through the domain in `x`-direction.
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
For reference, see
- e.g. p.15 of Numerical Methods for Conservation Laws: From Analysis to Algorithms
https://doi.org/10.1137/1.9781611975109

- or equation (1) in https://inria.hal.science/hal-01720293/document
"""
struct MaxwellEquations1D{RealT <: Real} <: AbstractMaxwellEquations{1, 2}
speed_of_light::RealT # c

function MaxwellEquations1D(c::Real = 299_792_458.0)
new{typeof(c)}(c)
end
end

function varnames(::typeof(cons2cons), ::MaxwellEquations1D)
("E", "B")
end
function varnames(::typeof(cons2prim), ::MaxwellEquations1D)
("E", "B")
end

"""
initial_condition_convergence_test(x, t, equations::MaxwellEquations1D)

A smooth initial condition used for convergence tests.
"""
function initial_condition_convergence_test(x, t, equations::MaxwellEquations1D)
c = equations.speed_of_light
char_pos = c * t + x[1]

sin_char_pos = sin(2 * pi * char_pos)

E = -c * sin_char_pos
B = sin_char_pos

return SVector(E, B)
end

# Calculate 1D flux for a single point
@inline function flux(u, orientation::Integer,
equations::MaxwellEquations1D)
E, B = u
return SVector(equations.speed_of_light^2 * B, E)
end

# Calculate maximum wave speed for local Lax-Friedrichs-type dissipation
@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Int,
equations::MaxwellEquations1D)
λ_max = equations.speed_of_light
end

@inline have_constant_speed(::MaxwellEquations1D) = True()

@inline function max_abs_speeds(equations::MaxwellEquations1D)
return equations.speed_of_light
end

@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer,
equations::MaxwellEquations1D)
min_max_speed_davis(u_ll, u_rr, orientation, equations)
end

@inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer,
equations::MaxwellEquations1D)
λ_min = -equations.speed_of_light
λ_max = equations.speed_of_light

return λ_min, λ_max
end

# Convert conservative variables to primitive
@inline cons2prim(u, ::MaxwellEquations1D) = u
@inline cons2entropy(u, ::MaxwellEquations1D) = u
end # @muladd
3 changes: 3 additions & 0 deletions test/test_tree_1d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ isdir(outdir) && rm(outdir, recursive = true)

# Linearized Euler
include("test_tree_1d_linearizedeuler.jl")

# Maxwell
include("test_tree_1d_maxwell.jl")
end

# Coverage test for all initial conditions
Expand Down
44 changes: 44 additions & 0 deletions test/test_tree_1d_maxwell.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module TestExamples1DMaxwell

using Test
using Trixi

include("test_trixi.jl")

EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem")

@testset "Maxwell" begin
#! format: noindent

@trixi_testset "elixir_maxwell_convergence.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR,
"elixir_maxwell_convergence.jl"),
l2=[8933.196486422636, 2.979793603210305e-5],
linf=[21136.527033627033, 7.050386515528029e-5])
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
t = sol.t[end]
u_ode = sol.u[end]
du_ode = similar(u_ode)
@test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000
end
end

@trixi_testset "elixir_maxwell_E_excitation.jl" begin
@test_trixi_include(joinpath(EXAMPLES_DIR,
"elixir_maxwell_E_excitation.jl"),
l2=[1.8181768208894413e6, 0.09221738723979069],
linf=[2.5804473693440557e6, 0.1304024464192847])
# Ensure that we do not have excessive memory allocations
# (e.g., from type instabilities)
let
t = sol.t[end]
u_ode = sol.u[end]
du_ode = similar(u_ode)
@test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000
end
end
end

end # module
19 changes: 19 additions & 0 deletions test/test_unit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,25 @@ end
min_max_speed_davis(u_ll, u_rr, normal_z,
equations)))
end

@timed_testset "Maxwell 1D" begin
equations = MaxwellEquations1D()

u_values_left = [SVector(1.0, 0.0),
SVector(0.0, 1.0),
SVector(0.5, -0.5),
SVector(-1.2, 0.3)]

u_values_right = [SVector(1.0, 0.0),
SVector(0.0, 1.0),
SVector(0.5, -0.5),
SVector(-1.2, 0.3)]
for u_ll in u_values_left, u_rr in u_values_right
@test all(isapprox(x, y)
for (x, y) in zip(min_max_speed_naive(u_ll, u_rr, 1, equations),
min_max_speed_davis(u_ll, u_rr, 1, equations)))
end
end
end

@testset "SimpleKronecker" begin
Expand Down
Loading