From b33cbc2c0e779209dc998cc8b08b52bec86022b9 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 14 Aug 2023 08:44:39 +0200 Subject: [PATCH 001/138] Clean branch --- ...ixir_navierstokes_convergence_walls_amr.jl | 172 ++++++++++++++ src/callbacks_step/amr.jl | 172 ++++++++++++++ src/callbacks_step/amr_dg1d.jl | 222 ++++++++++++++++++ src/solvers/dgsem_tree/cache_viscous.jl | 33 +++ src/solvers/dgsem_tree/dg.jl | 3 + src/solvers/dgsem_tree/dg_1d_parabolic.jl | 11 +- test/test_parabolic_1d.jl | 19 ++ 7 files changed, 627 insertions(+), 5 deletions(-) create mode 100644 examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl create mode 100644 src/solvers/dgsem_tree/cache_viscous.jl diff --git a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl new file mode 100644 index 00000000000..1daeab04a71 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl @@ -0,0 +1,172 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +prandtl_number() = 0.72 +mu() = 0.01 + +equations = CompressibleEulerEquations1D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), Prandtl=prandtl_number(), + gradient_variables=GradientVariablesEntropy()) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, + volume_integral=VolumeIntegralWeakForm()) + +coordinates_min = -1.0 +coordinates_max = 1.0 + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=3, + periodicity=false, + n_cells_max=30_000) # set maximum capacity of tree data structure + +# Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion1D` +# since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion1D`) +# and by the initial condition (which passes in `CompressibleEulerEquations1D`). +# This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) +function initial_condition_navier_stokes_convergence_test(x, t, equations) + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t + + rho = c + A * cos(pi_x) * cos(pi_t) + v1 = log(x[1] + 2.0) * (1.0 - exp(-A * (x[1] - 1.0)) ) * cos(pi_t) + p = rho^2 + + return prim2cons(SVector(rho, v1, p), equations) +end + +@inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) + x = x[1] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * cos(pi_x) * cos(pi_t) + rho_t = -pi * A * cos(pi_x) * sin(pi_t) + rho_x = -pi * A * sin(pi_x) * cos(pi_t) + rho_xx = -pi * pi * A * cos(pi_x) * cos(pi_t) + + v1 = log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * cos(pi_t) + v1_t = -pi * log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * sin(pi_t) + v1_x = (A * log(x + 2.0) * exp(-A * (x - 1.0)) + (1.0 - exp(-A * (x - 1.0))) / (x + 2.0)) * cos(pi_t) + v1_xx = (( 2.0 * A * exp(-A * (x - 1.0)) / (x + 2.0) + - A * A * log(x + 2.0) * exp(-A * (x - 1.0)) + - (1.0 - exp(-A * (x - 1.0))) / ((x + 2.0) * (x + 2.0))) * cos(pi_t)) + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + + # y-momentum equation + du2 = ( rho_t * v1 + rho * v1_t + + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + # stress tensor from y-direction + - v1_xx * mu_) + + # total energy equation + du3 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) + # stress tensor and temperature gradient terms from x-direction + - v1_xx * v1 * mu_ + - v1_x * v1_x * mu_ + - T_const * inv_rho_cubed * ( p_xx * rho * rho + - 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x + - p * rho * rho_xx ) * mu_ ) + + return SVector(du1, du2, du3) +end + +initial_condition = initial_condition_navier_stokes_convergence_test + +# BC types +velocity_bc_left_right = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2]) + +heat_bc_left = Isothermal((x, t, equations) -> + Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), + equations_parabolic)) +heat_bc_right = Adiabatic((x, t, equations) -> 0.0) + +boundary_condition_left = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_left) +boundary_condition_right = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_right) + +# define inviscid boundary conditions +boundary_conditions = (; x_neg = boundary_condition_slip_wall, + x_pos = boundary_condition_slip_wall) + +# define viscous boundary conditions +boundary_conditions_parabolic = (; x_neg = boundary_condition_left, + x_pos = boundary_condition_right) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; + boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), + source_terms=source_terms_navier_stokes_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +amr_controller = ControllerThreeLevel(semi, + IndicatorLöhner(semi, variable=Trixi.density), + base_level=3, + med_level=4, med_threshold=0.005, + max_level=5, max_threshold=0.01) + +amr_callback = AMRCallback(semi, amr_controller, + interval=5, + adapt_initial_condition=true) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, + ode_default_options()..., callback=callbacks) +summary_callback() # print the timer summary \ No newline at end of file diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index 4d80e6e1139..d742b17d262 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -192,6 +192,16 @@ end amr_callback(u_ode, mesh_equations_solver_cache(semi)..., semi, t, iter; kwargs...) end +@inline function (amr_callback::AMRCallback)(u_ode::AbstractVector, + semi::SemidiscretizationHyperbolicParabolic, + t, iter; + kwargs...) + # Note that we don't `wrap_array` the vector `u_ode` to be able to `resize!` + # it when doing AMR while still dispatching on the `mesh` etc. + amr_callback(u_ode, mesh_equations_solver_cache(semi)..., semi.cache_parabolic, + semi, t, iter; kwargs...) +end + # `passive_args` is currently used for Euler with self-gravity to adapt the gravity solver # passively without querying its indicator, based on the assumption that both solvers use # the same mesh. That's a hack and should be improved in the future once we have more examples @@ -346,6 +356,168 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, return has_changed end +# `passive_args` is currently used for Euler with self-gravity to adapt the gravity solver +# passively without querying its indicator, based on the assumption that both solvers use +# the same mesh. That's a hack and should be improved in the future once we have more examples +# and a better understanding of such a coupling. +# `passive_args` is expected to be an iterable of `Tuple`s of the form +# `(p_u_ode, p_mesh, p_equations, p_dg, p_cache)`. +function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, + equations, dg::DG, + cache, cache_parabolic, + semi::SemidiscretizationHyperbolicParabolic, + t, iter; + only_refine = false, only_coarsen = false, + passive_args = ()) + @unpack controller, adaptor = amr_callback + + u = wrap_array(u_ode, mesh, equations, dg, cache) + # TODO: Keep indicator based on hyperbolic variables? + lambda = @trixi_timeit timer() "indicator" controller(u, mesh, equations, dg, cache, + t = t, iter = iter) + + if mpi_isparallel() + # Collect lambda for all elements + lambda_global = Vector{eltype(lambda)}(undef, nelementsglobal(dg, cache)) + # Use parent because n_elements_by_rank is an OffsetArray + recvbuf = MPI.VBuffer(lambda_global, parent(cache.mpi_cache.n_elements_by_rank)) + MPI.Allgatherv!(lambda, recvbuf, mpi_comm()) + lambda = lambda_global + end + + leaf_cell_ids = leaf_cells(mesh.tree) + @boundscheck begin + @assert axes(lambda)==axes(leaf_cell_ids) ("Indicator (axes = $(axes(lambda))) and leaf cell (axes = $(axes(leaf_cell_ids))) arrays have different axes") + end + + @unpack to_refine, to_coarsen = amr_callback.amr_cache + empty!(to_refine) + empty!(to_coarsen) + for element in 1:length(lambda) + controller_value = lambda[element] + if controller_value > 0 + push!(to_refine, leaf_cell_ids[element]) + elseif controller_value < 0 + push!(to_coarsen, leaf_cell_ids[element]) + end + end + + @trixi_timeit timer() "refine" if !only_coarsen && !isempty(to_refine) + # refine mesh + refined_original_cells = @trixi_timeit timer() "mesh" refine!(mesh.tree, + to_refine) + + # Find all indices of elements whose cell ids are in refined_original_cells + # NOTE: This assumes same indices for hyperbolic and parabolic part! + elements_to_refine = findall(in(refined_original_cells), + cache.elements.cell_ids) + + # refine solver + @trixi_timeit timer() "solver" refine!(u_ode, adaptor, mesh, equations, dg, + cache, cache_parabolic, + elements_to_refine) + for (p_u_ode, p_mesh, p_equations, p_dg, p_cache) in passive_args + @trixi_timeit timer() "passive solver" refine!(p_u_ode, adaptor, p_mesh, + p_equations, p_dg, p_cache, + elements_to_refine) + end + else + # If there is nothing to refine, create empty array for later use + refined_original_cells = Int[] + end + + @trixi_timeit timer() "coarsen" if !only_refine && !isempty(to_coarsen) + # Since the cells may have been shifted due to refinement, first we need to + # translate the old cell ids to the new cell ids + if !isempty(to_coarsen) + to_coarsen = original2refined(to_coarsen, refined_original_cells, mesh) + end + + # Next, determine the parent cells from which the fine cells are to be + # removed, since these are needed for the coarsen! function. However, since + # we only want to coarsen if *all* child cells are marked for coarsening, + # we count the coarsening indicators for each parent cell and only coarsen + # if all children are marked as such (i.e., where the count is 2^ndims). At + # the same time, check if a cell is marked for coarsening even though it is + # *not* a leaf cell -> this can only happen if it was refined due to 2:1 + # smoothing during the preceding refinement operation. + parents_to_coarsen = zeros(Int, length(mesh.tree)) + for cell_id in to_coarsen + # If cell has no parent, it cannot be coarsened + if !has_parent(mesh.tree, cell_id) + continue + end + + # If cell is not leaf (anymore), it cannot be coarsened + if !is_leaf(mesh.tree, cell_id) + continue + end + + # Increase count for parent cell + parent_id = mesh.tree.parent_ids[cell_id] + parents_to_coarsen[parent_id] += 1 + end + + # Extract only those parent cells for which all children should be coarsened + to_coarsen = collect(1:length(parents_to_coarsen))[parents_to_coarsen .== 2^ndims(mesh)] + + # Finally, coarsen mesh + coarsened_original_cells = @trixi_timeit timer() "mesh" coarsen!(mesh.tree, + to_coarsen) + + # Convert coarsened parent cell ids to the list of child cell ids that have + # been removed, since this is the information that is expected by the solver + removed_child_cells = zeros(Int, + n_children_per_cell(mesh.tree) * + length(coarsened_original_cells)) + for (index, coarse_cell_id) in enumerate(coarsened_original_cells) + for child in 1:n_children_per_cell(mesh.tree) + removed_child_cells[n_children_per_cell(mesh.tree) * (index - 1) + child] = coarse_cell_id + + child + end + end + + # Find all indices of elements whose cell ids are in removed_child_cells + # NOTE: This assumes same indices for hyperbolic and parabolic part! + elements_to_remove = findall(in(removed_child_cells), cache.elements.cell_ids) + + # coarsen solver + @trixi_timeit timer() "solver" coarsen!(u_ode, adaptor, mesh, equations, dg, + cache, cache_parabolic, + elements_to_remove) + + for (p_u_ode, p_mesh, p_equations, p_dg, p_cache) in passive_args + @trixi_timeit timer() "passive solver" coarsen!(p_u_ode, adaptor, p_mesh, + p_equations, p_dg, p_cache, + elements_to_remove) + end + else + # If there is nothing to coarsen, create empty array for later use + coarsened_original_cells = Int[] + end + + # Store whether there were any cells coarsened or refined + has_changed = !isempty(refined_original_cells) || !isempty(coarsened_original_cells) + if has_changed # TODO: Taal decide, where shall we set this? + # don't set it to has_changed since there can be changes from earlier calls + mesh.unsaved_changes = true + end + + # Dynamically balance computational load by first repartitioning the mesh and then redistributing the cells/elements + if has_changed && mpi_isparallel() && amr_callback.dynamic_load_balancing + @trixi_timeit timer() "dynamic load balancing" begin + old_mpi_ranks_per_cell = copy(mesh.tree.mpi_ranks) + + partition!(mesh) + + rebalance_solver!(u_ode, mesh, equations, dg, cache, old_mpi_ranks_per_cell) + end + end + + # Return true if there were any cells coarsened or refined, otherwise false + return has_changed +end + # Copy controller values to quad user data storage, will be called below function copy_to_quad_iter_volume(info, user_data) info_pw = PointerWrapper(info) diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index e31a74730ea..e729c8eccc8 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -76,6 +76,114 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, return nothing end +function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, + equations, dg::DGSEM, cache, cache_parabolic, + elements_to_refine) + # Return early if there is nothing to do + if isempty(elements_to_refine) + return + end + + # Determine for each existing element whether it needs to be refined + needs_refinement = falses(nelements(dg, cache)) + needs_refinement[elements_to_refine] .= true + + # Retain current solution data + old_n_elements = nelements(dg, cache) + old_u_ode = copy(u_ode) + GC.@preserve old_u_ode begin # OBS! If we don't GC.@preserve old_u_ode, it might be GC'ed + old_u = wrap_array(old_u_ode, mesh, equations, dg, cache) + + # Get new list of leaf cells + leaf_cell_ids = local_leaf_cells(mesh.tree) + + # re-initialize elements container + @unpack elements = cache + resize!(elements, length(leaf_cell_ids)) + init_elements!(elements, leaf_cell_ids, mesh, dg.basis) + @assert nelements(dg, cache) > old_n_elements + + @unpack elements, cache_viscous = cache_parabolic + resize!(elements, length(leaf_cell_ids)) + init_elements!(elements, leaf_cell_ids, mesh, dg.basis) + @assert nelements(dg, cache_parabolic) > old_n_elements + + resize!(u_ode, + nvariables(equations) * nnodes(dg)^ndims(mesh) * nelements(dg, cache)) + u = wrap_array(u_ode, mesh, equations, dg, cache) + + # Resize parabolic helper variables + resize!(cache_viscous, + nvariables(equations) * nnodes(dg)^ndims(mesh) * nelements(dg, cache)) + cache_parabolic.cache_viscous.u_transformed = unsafe_wrap(Array, + pointer(cache_parabolic.cache_viscous._u_transformed), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + cache_parabolic.cache_viscous.gradients = unsafe_wrap(Array, + pointer(cache_parabolic.cache_viscous._gradients), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + cache_parabolic.cache_viscous.flux_viscous = unsafe_wrap(Array, + pointer(cache_parabolic.cache_viscous._flux_viscous), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + # Loop over all elements in old container and either copy them or refine them + element_id = 1 + for old_element_id in 1:old_n_elements + if needs_refinement[old_element_id] + # Refine element and store solution directly in new data structure + refine_element!(u, element_id, old_u, old_element_id, + adaptor, equations, dg) + element_id += 2^ndims(mesh) + else + # Copy old element data to new element container + @views u[:, .., element_id] .= old_u[:, .., old_element_id] + element_id += 1 + end + end + # If everything is correct, we should have processed all elements. + # Depending on whether the last element processed above had to be refined or not, + # the counter `element_id` can have two different values at the end. + @assert element_id == + nelements(dg, cache) + + 1||element_id == nelements(dg, cache) + 2^ndims(mesh) "element_id = $element_id, nelements(dg, cache) = $(nelements(dg, cache))" + #= + @assert element_id == + nelements(dg, cache_parabolic) + + 1||element_id == nelements(dg, cache_parabolic) + 2^ndims(mesh) "element_id = $element_id, nelements(dg, cache_parabolic) = $(nelements(dg, cache_parabolic))" + =# + end # GC.@preserve old_u_ode + + # re-initialize interfaces container + @unpack interfaces = cache + resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) + init_interfaces!(interfaces, elements, mesh) + + @unpack interfaces = cache_parabolic + resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) + init_interfaces!(interfaces, elements, mesh) + + # re-initialize boundaries container + @unpack boundaries = cache + resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) + init_boundaries!(boundaries, elements, mesh) + + @unpack boundaries = cache_parabolic + resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) + init_boundaries!(boundaries, elements, mesh) + + # Sanity check + if isperiodic(mesh.tree) + @assert ninterfaces(interfaces)==1 * nelements(dg, cache) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") + #@assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") + end + + return nothing +end + # TODO: Taal compare performance of different implementations # Refine solution data u for an element, using L2 projection (interpolation) function refine_element!(u::AbstractArray{<:Any, 3}, element_id, @@ -201,6 +309,120 @@ function coarsen!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, return nothing end +function coarsen!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, + equations, dg::DGSEM, cache, cache_parabolic, + elements_to_remove) + # Return early if there is nothing to do + if isempty(elements_to_remove) + return + end + + # Determine for each old element whether it needs to be removed + to_be_removed = falses(nelements(dg, cache)) + to_be_removed[elements_to_remove] .= true + + # Retain current solution data + old_n_elements = nelements(dg, cache) + old_u_ode = copy(u_ode) + GC.@preserve old_u_ode begin # OBS! If we don't GC.@preserve old_u_ode, it might be GC'ed + old_u = wrap_array(old_u_ode, mesh, equations, dg, cache) + + # Get new list of leaf cells + leaf_cell_ids = local_leaf_cells(mesh.tree) + + # re-initialize elements container + @unpack elements = cache + resize!(elements, length(leaf_cell_ids)) + init_elements!(elements, leaf_cell_ids, mesh, dg.basis) + @assert nelements(dg, cache) < old_n_elements + + @unpack elements, cache_viscous = cache_parabolic + resize!(elements, length(leaf_cell_ids)) + init_elements!(elements, leaf_cell_ids, mesh, dg.basis) + @assert nelements(dg, cache_parabolic) < old_n_elements + + resize!(u_ode, + nvariables(equations) * nnodes(dg)^ndims(mesh) * nelements(dg, cache)) + u = wrap_array(u_ode, mesh, equations, dg, cache) + + # Resize parabolic helper variables + resize!(cache_viscous, + nvariables(equations) * nnodes(dg)^ndims(mesh) * nelements(dg, cache)) + cache_parabolic.cache_viscous.u_transformed = unsafe_wrap(Array, + pointer(cache_parabolic.cache_viscous._u_transformed), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + cache_parabolic.cache_viscous.gradients = unsafe_wrap(Array, + pointer(cache_parabolic.cache_viscous._gradients), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + cache_parabolic.cache_viscous.flux_viscous = unsafe_wrap(Array, + pointer(cache_parabolic.cache_viscous._flux_viscous), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + + # Loop over all elements in old container and either copy them or coarsen them + skip = 0 + element_id = 1 + for old_element_id in 1:old_n_elements + # If skip is non-zero, we just coarsened 2^ndims elements and need to omit the following elements + if skip > 0 + skip -= 1 + continue + end + + if to_be_removed[old_element_id] + # If an element is to be removed, sanity check if the following elements + # are also marked - otherwise there would be an error in the way the + # cells/elements are sorted + @assert all(to_be_removed[old_element_id:(old_element_id + 2^ndims(mesh) - 1)]) "bad cell/element order" + + # Coarsen elements and store solution directly in new data structure + coarsen_elements!(u, element_id, old_u, old_element_id, + adaptor, equations, dg) + element_id += 1 + skip = 2^ndims(mesh) - 1 + else + # Copy old element data to new element container + @views u[:, .., element_id] .= old_u[:, .., old_element_id] + element_id += 1 + end + end + # If everything is correct, we should have processed all elements. + @assert element_id==nelements(dg, cache) + 1 "element_id = $element_id, nelements(dg, cache) = $(nelements(dg, cache))" + @assert element_id==nelements(dg, cache_parabolic) + 1 "element_id = $element_id, nelements(dg, cache_parabolic) = $(nelements(dg, cache_parabolic))" + end # GC.@preserve old_u_ode + + # re-initialize interfaces container + @unpack interfaces = cache + resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) + init_interfaces!(interfaces, elements, mesh) + + @unpack interfaces = cache_parabolic + resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) + init_interfaces!(interfaces, elements, mesh) + + # re-initialize boundaries container + @unpack boundaries = cache + resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) + init_boundaries!(boundaries, elements, mesh) + + @unpack boundaries = cache_parabolic + resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) + init_boundaries!(boundaries, elements, mesh) + + # Sanity check + if isperiodic(mesh.tree) + @assert ninterfaces(interfaces)==1 * nelements(dg, cache) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") + @assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") + end + + return nothing +end + # TODO: Taal compare performance of different implementations # Coarsen solution data u for two elements, using L2 projection function coarsen_elements!(u::AbstractArray{<:Any, 3}, element_id, diff --git a/src/solvers/dgsem_tree/cache_viscous.jl b/src/solvers/dgsem_tree/cache_viscous.jl new file mode 100644 index 00000000000..17a2774db06 --- /dev/null +++ b/src/solvers/dgsem_tree/cache_viscous.jl @@ -0,0 +1,33 @@ +mutable struct CacheViscous1D{uEltype <: Real} + u_transformed::Array{uEltype, 3} + gradients::Array{uEltype, 3} + flux_viscous::Array{uEltype, 3} + + # internal `resize!`able storage + _u_transformed::Vector{uEltype} + _gradients::Vector{uEltype} + _flux_viscous::Vector{uEltype} + + function CacheViscous1D{uEltype}(n_vars::Integer, n_nodes::Integer, + n_elements::Integer) where {uEltype <: Real} + new(Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), + Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), + Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), + Vector{uEltype}(undef, n_vars * n_nodes * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes * n_elements)) + end +end + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(cache_viscous::CacheViscous1D, capacity) + resize!(cache_viscous._u_transformed, capacity) + resize!(cache_viscous._gradients, capacity) + resize!(cache_viscous._flux_viscous, capacity) + + return nothing +end diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index cb28dad968c..9b0874e5ae0 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -54,6 +54,9 @@ include("containers.jl") # Dimension-agnostic parallel setup include("dg_parallel.jl") +# Helper struct for parabolic AMR +include("cache_viscous.jl") + # 1D DG implementation include("dg_1d.jl") include("dg_1d_parabolic.jl") diff --git a/src/solvers/dgsem_tree/dg_1d_parabolic.jl b/src/solvers/dgsem_tree/dg_1d_parabolic.jl index c2aa75388c8..596a6a8acbf 100644 --- a/src/solvers/dgsem_tree/dg_1d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_1d_parabolic.jl @@ -17,7 +17,8 @@ function rhs_parabolic!(du, u, t, mesh::TreeMesh{1}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - @unpack u_transformed, gradients, flux_viscous = cache_parabolic + @unpack cache_viscous = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = cache_viscous # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin @@ -530,18 +531,18 @@ function create_cache_parabolic(mesh::TreeMesh{1}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) + # Additions for parabolic n_vars = nvariables(equations_hyperbolic) n_nodes = nnodes(elements) n_elements = nelements(elements) - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_elements) - gradients = similar(u_transformed) - flux_viscous = similar(u_transformed) + + cache_viscous = CacheViscous1D{uEltype}(n_vars, n_nodes, n_elements) interfaces = init_interfaces(leaf_cell_ids, mesh, elements) boundaries = init_boundaries(leaf_cell_ids, mesh, elements) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + cache = (; elements, interfaces, boundaries, cache_viscous) return cache end diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index 06a55100d62..ee8c9ea9d5e 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -53,6 +53,25 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [0.002754803146635787, 0.0028567714697580906, 0.012941794048176192] ) end + + @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_walls_amr.jl"), + equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), + Prandtl=prandtl_number()), + l2 = [2.527877257772131e-5, 2.5539911566937718e-5, 0.0001211860451244785], + linf = [0.00014663867588948776, 0.00019422448348348196, 0.0009556439394007299] + ) + end + + @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls_amr.jl: GradientVariablesEntropy" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_walls_amr.jl"), + equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), + Prandtl=prandtl_number(), + gradient_variables = GradientVariablesEntropy()), + l2 = [2.4593699163175966e-5, 2.392863645712634e-5, 0.00011252526651714956], + linf = [0.00011850555445525046, 0.0001898777490968537, 0.0009597561467877824] + ) + end end # Clean up afterwards: delete Trixi output directory From 7e32e24cedb655f7f13b126be28f10fa06d790e4 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 14 Aug 2023 08:58:32 +0200 Subject: [PATCH 002/138] Un-Comment --- src/callbacks_step/amr_dg1d.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index e729c8eccc8..a04eef031f9 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -150,11 +150,9 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, @assert element_id == nelements(dg, cache) + 1||element_id == nelements(dg, cache) + 2^ndims(mesh) "element_id = $element_id, nelements(dg, cache) = $(nelements(dg, cache))" - #= @assert element_id == nelements(dg, cache_parabolic) + 1||element_id == nelements(dg, cache_parabolic) + 2^ndims(mesh) "element_id = $element_id, nelements(dg, cache_parabolic) = $(nelements(dg, cache_parabolic))" - =# end # GC.@preserve old_u_ode # re-initialize interfaces container From 5e1997b5b252c207b5e34fd5cceb37c00203bfae Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 14 Aug 2023 09:00:59 +0200 Subject: [PATCH 003/138] un-comment --- src/callbacks_step/amr_dg1d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index a04eef031f9..ed1341ce3c3 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -176,7 +176,7 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, # Sanity check if isperiodic(mesh.tree) @assert ninterfaces(interfaces)==1 * nelements(dg, cache) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") - #@assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") + @assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") end return nothing From 54e328e378b301aa64db897f2cc2f2babdb1dd35 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 14 Aug 2023 09:20:27 +0200 Subject: [PATCH 004/138] test coarsen --- test/test_parabolic_1d.jl | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index ee8c9ea9d5e..45210c6795e 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -20,6 +20,29 @@ isdir(outdir) && rm(outdir, recursive=true) ) end + @trixi_testset "TreeMesh1D: elixir_advection_diffusion.jl (AMR)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_advection_diffusion.jl"), + tspan=(0.0, 0.0), initial_refinement_level = 6) + tspan=(0.0, 1.0) + ode = semidiscretize(semi, tspan) + initial_refinement_level = 6 + amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), + base_level=4, + med_level=5, med_threshold=0.1, + max_level=6, max_threshold=0.6) + amr_callback = AMRCallback(semi, amr_controller, + interval=5, + adapt_initial_condition=true) + + # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver + callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) + sol = solve(ode, KenCarp4(autodiff=false), abstol=time_abs_tol, reltol=time_int_tol, + save_everystep=false, callback=callbacks) + ac_sol = analysis_callback(sol) + @test ac_sol.l2[1] ≈ 5.888985009128617e-6 + @test ac_sol.linf[1] ≈ 2.885052015366707e-5 + end + @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl" begin @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_periodic.jl"), l2 = [0.0001133835907077494, 6.226282245610444e-5, 0.0002820171699999139], From a9e4cb796816509923efcbe42e9569251c2e14e3 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 14 Aug 2023 14:27:50 +0200 Subject: [PATCH 005/138] remove redundancy --- test/test_parabolic_1d.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index 45210c6795e..ccf7b0f5c7c 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -25,7 +25,6 @@ isdir(outdir) && rm(outdir, recursive=true) tspan=(0.0, 0.0), initial_refinement_level = 6) tspan=(0.0, 1.0) ode = semidiscretize(semi, tspan) - initial_refinement_level = 6 amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), base_level=4, med_level=5, med_threshold=0.1, From ebc9cc8be602140867202a32dbf5b09c86e37561 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Fri, 18 Aug 2023 09:51:55 +0200 Subject: [PATCH 006/138] Remove support for passive terms --- src/callbacks_step/amr.jl | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index d742b17d262..9ea76157ae1 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -356,19 +356,12 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, return has_changed end -# `passive_args` is currently used for Euler with self-gravity to adapt the gravity solver -# passively without querying its indicator, based on the assumption that both solvers use -# the same mesh. That's a hack and should be improved in the future once we have more examples -# and a better understanding of such a coupling. -# `passive_args` is expected to be an iterable of `Tuple`s of the form -# `(p_u_ode, p_mesh, p_equations, p_dg, p_cache)`. function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, equations, dg::DG, cache, cache_parabolic, semi::SemidiscretizationHyperbolicParabolic, t, iter; - only_refine = false, only_coarsen = false, - passive_args = ()) + only_refine = false, only_coarsen = false) @unpack controller, adaptor = amr_callback u = wrap_array(u_ode, mesh, equations, dg, cache) @@ -416,11 +409,6 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, @trixi_timeit timer() "solver" refine!(u_ode, adaptor, mesh, equations, dg, cache, cache_parabolic, elements_to_refine) - for (p_u_ode, p_mesh, p_equations, p_dg, p_cache) in passive_args - @trixi_timeit timer() "passive solver" refine!(p_u_ode, adaptor, p_mesh, - p_equations, p_dg, p_cache, - elements_to_refine) - end else # If there is nothing to refine, create empty array for later use refined_original_cells = Int[] @@ -485,12 +473,6 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, @trixi_timeit timer() "solver" coarsen!(u_ode, adaptor, mesh, equations, dg, cache, cache_parabolic, elements_to_remove) - - for (p_u_ode, p_mesh, p_equations, p_dg, p_cache) in passive_args - @trixi_timeit timer() "passive solver" coarsen!(p_u_ode, adaptor, p_mesh, - p_equations, p_dg, p_cache, - elements_to_remove) - end else # If there is nothing to coarsen, create empty array for later use coarsened_original_cells = Int[] From 9c766b93306680af3a31b4fc2866f7c93fa6d1b4 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Fri, 18 Aug 2023 10:28:52 +0200 Subject: [PATCH 007/138] expand resize --- src/callbacks_step/amr_dg1d.jl | 41 ++----------- src/solvers/dgsem_tree/cache_viscous.jl | 33 ----------- .../dgsem_tree/container_viscous_1d.jl | 58 +++++++++++++++++++ src/solvers/dgsem_tree/dg.jl | 2 +- src/solvers/dgsem_tree/dg_1d_parabolic.jl | 15 ++--- 5 files changed, 69 insertions(+), 80 deletions(-) delete mode 100644 src/solvers/dgsem_tree/cache_viscous.jl create mode 100644 src/solvers/dgsem_tree/container_viscous_1d.jl diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index ed1341ce3c3..dbbdf1ca397 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -103,7 +103,7 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, init_elements!(elements, leaf_cell_ids, mesh, dg.basis) @assert nelements(dg, cache) > old_n_elements - @unpack elements, cache_viscous = cache_parabolic + @unpack elements, viscous_container = cache_parabolic resize!(elements, length(leaf_cell_ids)) init_elements!(elements, leaf_cell_ids, mesh, dg.basis) @assert nelements(dg, cache_parabolic) > old_n_elements @@ -113,23 +113,8 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, u = wrap_array(u_ode, mesh, equations, dg, cache) # Resize parabolic helper variables - resize!(cache_viscous, - nvariables(equations) * nnodes(dg)^ndims(mesh) * nelements(dg, cache)) - cache_parabolic.cache_viscous.u_transformed = unsafe_wrap(Array, - pointer(cache_parabolic.cache_viscous._u_transformed), - (nvariables(equations), - nnodes(dg), - nelements(dg, cache))) - cache_parabolic.cache_viscous.gradients = unsafe_wrap(Array, - pointer(cache_parabolic.cache_viscous._gradients), - (nvariables(equations), - nnodes(dg), - nelements(dg, cache))) - cache_parabolic.cache_viscous.flux_viscous = unsafe_wrap(Array, - pointer(cache_parabolic.cache_viscous._flux_viscous), - (nvariables(equations), - nnodes(dg), - nelements(dg, cache))) + resize!(viscous_container, equations, dg, cache) + # Loop over all elements in old container and either copy them or refine them element_id = 1 for old_element_id in 1:old_n_elements @@ -334,7 +319,7 @@ function coarsen!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, init_elements!(elements, leaf_cell_ids, mesh, dg.basis) @assert nelements(dg, cache) < old_n_elements - @unpack elements, cache_viscous = cache_parabolic + @unpack elements, viscous_container = cache_parabolic resize!(elements, length(leaf_cell_ids)) init_elements!(elements, leaf_cell_ids, mesh, dg.basis) @assert nelements(dg, cache_parabolic) < old_n_elements @@ -344,23 +329,7 @@ function coarsen!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, u = wrap_array(u_ode, mesh, equations, dg, cache) # Resize parabolic helper variables - resize!(cache_viscous, - nvariables(equations) * nnodes(dg)^ndims(mesh) * nelements(dg, cache)) - cache_parabolic.cache_viscous.u_transformed = unsafe_wrap(Array, - pointer(cache_parabolic.cache_viscous._u_transformed), - (nvariables(equations), - nnodes(dg), - nelements(dg, cache))) - cache_parabolic.cache_viscous.gradients = unsafe_wrap(Array, - pointer(cache_parabolic.cache_viscous._gradients), - (nvariables(equations), - nnodes(dg), - nelements(dg, cache))) - cache_parabolic.cache_viscous.flux_viscous = unsafe_wrap(Array, - pointer(cache_parabolic.cache_viscous._flux_viscous), - (nvariables(equations), - nnodes(dg), - nelements(dg, cache))) + resize!(viscous_container, equations, dg, cache) # Loop over all elements in old container and either copy them or coarsen them skip = 0 diff --git a/src/solvers/dgsem_tree/cache_viscous.jl b/src/solvers/dgsem_tree/cache_viscous.jl deleted file mode 100644 index 17a2774db06..00000000000 --- a/src/solvers/dgsem_tree/cache_viscous.jl +++ /dev/null @@ -1,33 +0,0 @@ -mutable struct CacheViscous1D{uEltype <: Real} - u_transformed::Array{uEltype, 3} - gradients::Array{uEltype, 3} - flux_viscous::Array{uEltype, 3} - - # internal `resize!`able storage - _u_transformed::Vector{uEltype} - _gradients::Vector{uEltype} - _flux_viscous::Vector{uEltype} - - function CacheViscous1D{uEltype}(n_vars::Integer, n_nodes::Integer, - n_elements::Integer) where {uEltype <: Real} - new(Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), - Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), - Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), - Vector{uEltype}(undef, n_vars * n_nodes * n_elements), - Vector{uEltype}(undef, n_vars * n_nodes * n_elements), - Vector{uEltype}(undef, n_vars * n_nodes * n_elements)) - end -end - -# Only one-dimensional `Array`s are `resize!`able in Julia. -# Hence, we use `Vector`s as internal storage and `resize!` -# them whenever needed. Then, we reuse the same memory by -# `unsafe_wrap`ping multi-dimensional `Array`s around the -# internal storage. -function Base.resize!(cache_viscous::CacheViscous1D, capacity) - resize!(cache_viscous._u_transformed, capacity) - resize!(cache_viscous._gradients, capacity) - resize!(cache_viscous._flux_viscous, capacity) - - return nothing -end diff --git a/src/solvers/dgsem_tree/container_viscous_1d.jl b/src/solvers/dgsem_tree/container_viscous_1d.jl new file mode 100644 index 00000000000..47de34473a8 --- /dev/null +++ b/src/solvers/dgsem_tree/container_viscous_1d.jl @@ -0,0 +1,58 @@ +mutable struct ViscousContainer1D{uEltype <: Real} + u_transformed::Array{uEltype, 3} + gradients::Array{uEltype, 3} + flux_viscous::Array{uEltype, 3} + + # internal `resize!`able storage + _u_transformed::Vector{uEltype} + _gradients::Vector{uEltype} + _flux_viscous::Vector{uEltype} + + function ViscousContainer1D{uEltype}(n_vars::Integer, n_nodes::Integer, + n_elements::Integer) where {uEltype <: Real} + new(Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), + Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), + Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), + Vector{uEltype}(undef, n_vars * n_nodes * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes * n_elements)) + end +end + +function init_viscous_container(n_vars::Integer, n_nodes::Integer, + n_elements::Integer, ::Type{uEltype}) where {uEltype <: Real} + return ViscousContainer1D{uEltype}(n_vars, n_nodes, n_elements) +end + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(viscous_container::ViscousContainer1D, equations, dg, cache) + + capacity = nvariables(equations) * nnodes(dg) * nelements(dg, cache) + resize!(viscous_container._u_transformed, capacity) + resize!(viscous_container._gradients, capacity) + resize!(viscous_container._flux_viscous, capacity) + + viscous_container.u_transformed = unsafe_wrap(Array, + pointer(viscous_container._u_transformed), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + + viscous_container.gradients = unsafe_wrap(Array, + pointer(viscous_container._gradients), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + + viscous_container.flux_viscous = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + + return nothing +end diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 9b0874e5ae0..33132fee774 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -55,7 +55,7 @@ include("containers.jl") include("dg_parallel.jl") # Helper struct for parabolic AMR -include("cache_viscous.jl") +include("container_viscous_1d.jl") # 1D DG implementation include("dg_1d.jl") diff --git a/src/solvers/dgsem_tree/dg_1d_parabolic.jl b/src/solvers/dgsem_tree/dg_1d_parabolic.jl index 596a6a8acbf..64620edfb05 100644 --- a/src/solvers/dgsem_tree/dg_1d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_1d_parabolic.jl @@ -17,8 +17,8 @@ function rhs_parabolic!(du, u, t, mesh::TreeMesh{1}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - @unpack cache_viscous = cache_parabolic - @unpack u_transformed, gradients, flux_viscous = cache_viscous + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin @@ -530,19 +530,14 @@ function create_cache_parabolic(mesh::TreeMesh{1}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) - - # Additions for parabolic - n_vars = nvariables(equations_hyperbolic) - n_nodes = nnodes(elements) - n_elements = nelements(elements) - - cache_viscous = CacheViscous1D{uEltype}(n_vars, n_nodes, n_elements) + + viscous_container = init_viscous_container(nvariables(equations_hyperbolic), nnodes(elements), nelements(elements), uEltype) interfaces = init_interfaces(leaf_cell_ids, mesh, elements) boundaries = init_boundaries(leaf_cell_ids, mesh, elements) - cache = (; elements, interfaces, boundaries, cache_viscous) + cache = (; elements, interfaces, boundaries, viscous_container) return cache end From 82894d71086f98abd389166892d0fde3512b1a13 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Fri, 18 Aug 2023 10:35:43 +0200 Subject: [PATCH 008/138] comments --- src/callbacks_step/amr.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index 9ea76157ae1..0ea2500f6aa 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -370,6 +370,8 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, t = t, iter = iter) if mpi_isparallel() + error("MPI has not been verified yet for parabolic AMR") + # Collect lambda for all elements lambda_global = Vector{eltype(lambda)}(undef, nelementsglobal(dg, cache)) # Use parent because n_elements_by_rank is an OffsetArray @@ -401,7 +403,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, to_refine) # Find all indices of elements whose cell ids are in refined_original_cells - # NOTE: This assumes same indices for hyperbolic and parabolic part! + # Note: This assumes same indices for hyperbolic and parabolic part. elements_to_refine = findall(in(refined_original_cells), cache.elements.cell_ids) @@ -466,7 +468,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, end # Find all indices of elements whose cell ids are in removed_child_cells - # NOTE: This assumes same indices for hyperbolic and parabolic part! + # Note: This assumes same indices for hyperbolic and parabolic part. elements_to_remove = findall(in(removed_child_cells), cache.elements.cell_ids) # coarsen solver @@ -487,6 +489,8 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, # Dynamically balance computational load by first repartitioning the mesh and then redistributing the cells/elements if has_changed && mpi_isparallel() && amr_callback.dynamic_load_balancing + error("MPI has not been verified yet for parabolic AMR") + @trixi_timeit timer() "dynamic load balancing" begin old_mpi_ranks_per_cell = copy(mesh.tree.mpi_ranks) From 6ef88ca6343fb173f939660011ff1e1a896124ce Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Fri, 18 Aug 2023 10:37:38 +0200 Subject: [PATCH 009/138] format --- src/solvers/dgsem_tree/container_viscous_1d.jl | 4 ++-- src/solvers/dgsem_tree/dg_1d_parabolic.jl | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_tree/container_viscous_1d.jl b/src/solvers/dgsem_tree/container_viscous_1d.jl index 47de34473a8..a4919f75396 100644 --- a/src/solvers/dgsem_tree/container_viscous_1d.jl +++ b/src/solvers/dgsem_tree/container_viscous_1d.jl @@ -20,7 +20,8 @@ mutable struct ViscousContainer1D{uEltype <: Real} end function init_viscous_container(n_vars::Integer, n_nodes::Integer, - n_elements::Integer, ::Type{uEltype}) where {uEltype <: Real} + n_elements::Integer, + ::Type{uEltype}) where {uEltype <: Real} return ViscousContainer1D{uEltype}(n_vars, n_nodes, n_elements) end @@ -30,7 +31,6 @@ end # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. function Base.resize!(viscous_container::ViscousContainer1D, equations, dg, cache) - capacity = nvariables(equations) * nnodes(dg) * nelements(dg, cache) resize!(viscous_container._u_transformed, capacity) resize!(viscous_container._gradients, capacity) diff --git a/src/solvers/dgsem_tree/dg_1d_parabolic.jl b/src/solvers/dgsem_tree/dg_1d_parabolic.jl index 64620edfb05..561bd714032 100644 --- a/src/solvers/dgsem_tree/dg_1d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_1d_parabolic.jl @@ -530,8 +530,10 @@ function create_cache_parabolic(mesh::TreeMesh{1}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) - - viscous_container = init_viscous_container(nvariables(equations_hyperbolic), nnodes(elements), nelements(elements), uEltype) + + viscous_container = init_viscous_container(nvariables(equations_hyperbolic), + nnodes(elements), nelements(elements), + uEltype) interfaces = init_interfaces(leaf_cell_ids, mesh, elements) From 53f599145e001384c952843b0e540e1721f4a3b1 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Sun, 20 Aug 2023 14:45:48 +0200 Subject: [PATCH 010/138] Avoid code duplication --- src/callbacks_step/amr_dg1d.jl | 155 ++++----------------------------- 1 file changed, 16 insertions(+), 139 deletions(-) diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index dbbdf1ca397..d5f300ecb04 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -79,88 +79,30 @@ end function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, equations, dg::DGSEM, cache, cache_parabolic, elements_to_refine) - # Return early if there is nothing to do - if isempty(elements_to_refine) - return - end - - # Determine for each existing element whether it needs to be refined - needs_refinement = falses(nelements(dg, cache)) - needs_refinement[elements_to_refine] .= true - - # Retain current solution data - old_n_elements = nelements(dg, cache) - old_u_ode = copy(u_ode) - GC.@preserve old_u_ode begin # OBS! If we don't GC.@preserve old_u_ode, it might be GC'ed - old_u = wrap_array(old_u_ode, mesh, equations, dg, cache) - - # Get new list of leaf cells - leaf_cell_ids = local_leaf_cells(mesh.tree) - - # re-initialize elements container - @unpack elements = cache - resize!(elements, length(leaf_cell_ids)) - init_elements!(elements, leaf_cell_ids, mesh, dg.basis) - @assert nelements(dg, cache) > old_n_elements - - @unpack elements, viscous_container = cache_parabolic - resize!(elements, length(leaf_cell_ids)) - init_elements!(elements, leaf_cell_ids, mesh, dg.basis) - @assert nelements(dg, cache_parabolic) > old_n_elements + refine!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_refine) - resize!(u_ode, - nvariables(equations) * nnodes(dg)^ndims(mesh) * nelements(dg, cache)) - u = wrap_array(u_ode, mesh, equations, dg, cache) + # Get new list of leaf cells + leaf_cell_ids = local_leaf_cells(mesh.tree) - # Resize parabolic helper variables - resize!(viscous_container, equations, dg, cache) + @unpack elements, viscous_container = cache_parabolic + resize!(elements, length(leaf_cell_ids)) + init_elements!(elements, leaf_cell_ids, mesh, dg.basis) - # Loop over all elements in old container and either copy them or refine them - element_id = 1 - for old_element_id in 1:old_n_elements - if needs_refinement[old_element_id] - # Refine element and store solution directly in new data structure - refine_element!(u, element_id, old_u, old_element_id, - adaptor, equations, dg) - element_id += 2^ndims(mesh) - else - # Copy old element data to new element container - @views u[:, .., element_id] .= old_u[:, .., old_element_id] - element_id += 1 - end - end - # If everything is correct, we should have processed all elements. - # Depending on whether the last element processed above had to be refined or not, - # the counter `element_id` can have two different values at the end. - @assert element_id == - nelements(dg, cache) + - 1||element_id == nelements(dg, cache) + 2^ndims(mesh) "element_id = $element_id, nelements(dg, cache) = $(nelements(dg, cache))" - @assert element_id == - nelements(dg, cache_parabolic) + - 1||element_id == nelements(dg, cache_parabolic) + 2^ndims(mesh) "element_id = $element_id, nelements(dg, cache_parabolic) = $(nelements(dg, cache_parabolic))" - end # GC.@preserve old_u_ode + # Resize parabolic helper variables + resize!(viscous_container, equations, dg, cache) # re-initialize interfaces container - @unpack interfaces = cache - resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) - init_interfaces!(interfaces, elements, mesh) - @unpack interfaces = cache_parabolic resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) init_interfaces!(interfaces, elements, mesh) # re-initialize boundaries container - @unpack boundaries = cache - resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) - init_boundaries!(boundaries, elements, mesh) - @unpack boundaries = cache_parabolic resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) init_boundaries!(boundaries, elements, mesh) # Sanity check if isperiodic(mesh.tree) - @assert ninterfaces(interfaces)==1 * nelements(dg, cache) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") @assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") end @@ -295,95 +237,30 @@ end function coarsen!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, equations, dg::DGSEM, cache, cache_parabolic, elements_to_remove) - # Return early if there is nothing to do - if isempty(elements_to_remove) - return - end + coarsen!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_remove) - # Determine for each old element whether it needs to be removed - to_be_removed = falses(nelements(dg, cache)) - to_be_removed[elements_to_remove] .= true - - # Retain current solution data - old_n_elements = nelements(dg, cache) - old_u_ode = copy(u_ode) - GC.@preserve old_u_ode begin # OBS! If we don't GC.@preserve old_u_ode, it might be GC'ed - old_u = wrap_array(old_u_ode, mesh, equations, dg, cache) - - # Get new list of leaf cells - leaf_cell_ids = local_leaf_cells(mesh.tree) - - # re-initialize elements container - @unpack elements = cache - resize!(elements, length(leaf_cell_ids)) - init_elements!(elements, leaf_cell_ids, mesh, dg.basis) - @assert nelements(dg, cache) < old_n_elements - - @unpack elements, viscous_container = cache_parabolic - resize!(elements, length(leaf_cell_ids)) - init_elements!(elements, leaf_cell_ids, mesh, dg.basis) - @assert nelements(dg, cache_parabolic) < old_n_elements - - resize!(u_ode, - nvariables(equations) * nnodes(dg)^ndims(mesh) * nelements(dg, cache)) - u = wrap_array(u_ode, mesh, equations, dg, cache) - - # Resize parabolic helper variables - resize!(viscous_container, equations, dg, cache) - - # Loop over all elements in old container and either copy them or coarsen them - skip = 0 - element_id = 1 - for old_element_id in 1:old_n_elements - # If skip is non-zero, we just coarsened 2^ndims elements and need to omit the following elements - if skip > 0 - skip -= 1 - continue - end + # Get new list of leaf cells + leaf_cell_ids = local_leaf_cells(mesh.tree) - if to_be_removed[old_element_id] - # If an element is to be removed, sanity check if the following elements - # are also marked - otherwise there would be an error in the way the - # cells/elements are sorted - @assert all(to_be_removed[old_element_id:(old_element_id + 2^ndims(mesh) - 1)]) "bad cell/element order" + @unpack elements, viscous_container = cache_parabolic + resize!(elements, length(leaf_cell_ids)) + init_elements!(elements, leaf_cell_ids, mesh, dg.basis) - # Coarsen elements and store solution directly in new data structure - coarsen_elements!(u, element_id, old_u, old_element_id, - adaptor, equations, dg) - element_id += 1 - skip = 2^ndims(mesh) - 1 - else - # Copy old element data to new element container - @views u[:, .., element_id] .= old_u[:, .., old_element_id] - element_id += 1 - end - end - # If everything is correct, we should have processed all elements. - @assert element_id==nelements(dg, cache) + 1 "element_id = $element_id, nelements(dg, cache) = $(nelements(dg, cache))" - @assert element_id==nelements(dg, cache_parabolic) + 1 "element_id = $element_id, nelements(dg, cache_parabolic) = $(nelements(dg, cache_parabolic))" - end # GC.@preserve old_u_ode + # Resize parabolic helper variables + resize!(viscous_container, equations, dg, cache) # re-initialize interfaces container - @unpack interfaces = cache - resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) - init_interfaces!(interfaces, elements, mesh) - @unpack interfaces = cache_parabolic resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) init_interfaces!(interfaces, elements, mesh) # re-initialize boundaries container - @unpack boundaries = cache - resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) - init_boundaries!(boundaries, elements, mesh) - @unpack boundaries = cache_parabolic resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) init_boundaries!(boundaries, elements, mesh) # Sanity check if isperiodic(mesh.tree) - @assert ninterfaces(interfaces)==1 * nelements(dg, cache) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") @assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") end From cdfe93b092c28e363e9dc8bbaf5c64a938728f8f Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 22 Aug 2023 13:16:22 +0200 Subject: [PATCH 011/138] Update src/callbacks_step/amr_dg1d.jl Co-authored-by: Michael Schlottke-Lakemper --- src/callbacks_step/amr_dg1d.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index d5f300ecb04..1b273b05ef5 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -79,7 +79,12 @@ end function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, equations, dg::DGSEM, cache, cache_parabolic, elements_to_refine) + # Call `refine!` for the hyperbolic part, which does the heavy lifting of + # actually transferring the solution to the refined cells refine!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_refine) + + # The remaining function only handles the necessary adaptation of the data structures + # for the parabolic part of the semidiscretization # Get new list of leaf cells leaf_cell_ids = local_leaf_cells(mesh.tree) From 0f2b7790176c648cff5b3014b019b29f06ce644f Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 22 Aug 2023 13:22:52 +0200 Subject: [PATCH 012/138] comment --- src/callbacks_step/amr_dg1d.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index 1b273b05ef5..602d7645009 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -242,6 +242,8 @@ end function coarsen!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, equations, dg::DGSEM, cache, cache_parabolic, elements_to_remove) + # Call `coarsen!` for the hyperbolic part, which does the heavy lifting of + # actually transferring the solution to the coarsened cells coarsen!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_remove) # Get new list of leaf cells From 376f99e39e20670397a302a4bed09cc2b3c08aa6 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 22 Aug 2023 14:28:02 +0200 Subject: [PATCH 013/138] comment & format --- src/callbacks_step/amr.jl | 2 +- src/callbacks_step/amr_dg1d.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index 0ea2500f6aa..ba840ff9675 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -365,7 +365,7 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, @unpack controller, adaptor = amr_callback u = wrap_array(u_ode, mesh, equations, dg, cache) - # TODO: Keep indicator based on hyperbolic variables? + # Indicator kept based on hyperbolic variables lambda = @trixi_timeit timer() "indicator" controller(u, mesh, equations, dg, cache, t = t, iter = iter) diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index 602d7645009..e721ccc61cb 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -82,7 +82,7 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, # Call `refine!` for the hyperbolic part, which does the heavy lifting of # actually transferring the solution to the refined cells refine!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_refine) - + # The remaining function only handles the necessary adaptation of the data structures # for the parabolic part of the semidiscretization From 826553f118bb6843de913b6ec5c4e694f72614d3 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 28 Aug 2023 14:35:39 +0200 Subject: [PATCH 014/138] Try to increase coverage --- test/test_parabolic_1d.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index ccf7b0f5c7c..3c4b34d23cb 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -22,7 +22,7 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "TreeMesh1D: elixir_advection_diffusion.jl (AMR)" begin @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_advection_diffusion.jl"), - tspan=(0.0, 0.0), initial_refinement_level = 6) + tspan=(0.0, 0.0), initial_refinement_level = 5) tspan=(0.0, 1.0) ode = semidiscretize(semi, tspan) amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), @@ -38,8 +38,8 @@ isdir(outdir) && rm(outdir, recursive=true) sol = solve(ode, KenCarp4(autodiff=false), abstol=time_abs_tol, reltol=time_int_tol, save_everystep=false, callback=callbacks) ac_sol = analysis_callback(sol) - @test ac_sol.l2[1] ≈ 5.888985009128617e-6 - @test ac_sol.linf[1] ≈ 2.885052015366707e-5 + @test ac_sol.l2[1] ≈ 6.4878111416468355e-6 + @test ac_sol.linf[1] ≈ 3.258075790424364e-5 end @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl" begin From d20962904a0308c8e7085b7d2a1083ea62cdc228 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 29 Aug 2023 11:50:58 +0200 Subject: [PATCH 015/138] Slightly more expressive names --- test/test_parabolic_1d.jl | 6 +++--- test/test_parabolic_2d.jl | 12 ++++++------ test/test_parabolic_3d.jl | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index 3c4b34d23cb..7962151c1f3 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -37,9 +37,9 @@ isdir(outdir) && rm(outdir, recursive=true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) sol = solve(ode, KenCarp4(autodiff=false), abstol=time_abs_tol, reltol=time_int_tol, save_everystep=false, callback=callbacks) - ac_sol = analysis_callback(sol) - @test ac_sol.l2[1] ≈ 6.4878111416468355e-6 - @test ac_sol.linf[1] ≈ 3.258075790424364e-5 + analysis_callback_sol = analysis_callback(sol) + @test analysis_callback_sol.l2[1] ≈ 6.4878111416468355e-6 + @test analysis_callback_sol.linf[1] ≈ 3.258075790424364e-5 end @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl" begin diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index 1564a33dc41..ca0b8b198a2 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -143,9 +143,9 @@ isdir(outdir) && rm(outdir, recursive=true) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, ode_default_options()..., callback=callbacks) - ac_sol = analysis_callback(sol) - @test ac_sol.l2[1] ≈ 1.67452550744728e-6 - @test ac_sol.linf[1] ≈ 7.905059166368744e-6 + analysis_callback_sol = analysis_callback(sol) + @test analysis_callback_sol.l2[1] ≈ 1.67452550744728e-6 + @test analysis_callback_sol.linf[1] ≈ 7.905059166368744e-6 # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -229,9 +229,9 @@ isdir(outdir) && rm(outdir, recursive=true) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, ode_default_options()..., callback=callbacks) - ac_sol = analysis_callback(sol) - @test ac_sol.l2 ≈ [0.00024296959173852447; 0.0002093263158670915; 0.0005390572390977262; 0.00026753561392341537] - @test ac_sol.linf ≈ [0.0016210102053424436; 0.002593287648655501; 0.002953907343823712; 0.002077119120180271] + analysis_callback_sol = analysis_callback(sol) + @test analysis_callback_sol.l2 ≈ [0.00024296959173852447; 0.0002093263158670915; 0.0005390572390977262; 0.00026753561392341537] + @test analysis_callback_sol.linf ≈ [0.0016210102053424436; 0.002593287648655501; 0.002953907343823712; 0.002077119120180271] end @trixi_testset "TreeMesh2D: elixir_navierstokes_lid_driven_cavity.jl" begin diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index d607962afa0..14eb9471b41 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -94,9 +94,9 @@ isdir(outdir) && rm(outdir, recursive=true) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, ode_default_options()..., callback=callbacks) - ac_sol = analysis_callback(sol) - @test ac_sol.l2 ≈ [0.0003991794175622818; 0.0008853745163670504; 0.0010658655552066817; 0.0008785559918324284; 0.001403163458422815] - @test ac_sol.linf ≈ [0.0035306410538458177; 0.01505692306169911; 0.008862444161110705; 0.015065647972869856; 0.030402714743065218] + analysis_callback_sol = analysis_callback(sol) + @test analysis_callback_sol.l2 ≈ [0.0003991794175622818; 0.0008853745163670504; 0.0010658655552066817; 0.0008785559918324284; 0.001403163458422815] + @test analysis_callback_sol.linf ≈ [0.0035306410538458177; 0.01505692306169911; 0.008862444161110705; 0.015065647972869856; 0.030402714743065218] end @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin @@ -127,9 +127,9 @@ isdir(outdir) && rm(outdir, recursive=true) sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), dt=5e-3, save_everystep=false, callback=callbacks); - ac_sol = analysis_callback(sol) - @test ac_sol.l2 ≈ [0.0013666103707729502; 0.2313581629543744; 0.2308164306264533; 0.17460246787819503; 0.28121914446544005] - @test ac_sol.linf ≈ [0.006938093883741336; 1.028235074139312; 1.0345438209717241; 1.0821111605203542; 1.2669636522564645] + analysis_callback_sol = analysis_callback(sol) + @test analysis_callback_sol.l2 ≈ [0.0013666103707729502; 0.2313581629543744; 0.2308164306264533; 0.17460246787819503; 0.28121914446544005] + @test analysis_callback_sol.linf ≈ [0.006938093883741336; 1.028235074139312; 1.0345438209717241; 1.0821111605203542; 1.2669636522564645] # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From a7d56a1ae56a020420bd1bfb46207d215b7732f2 Mon Sep 17 00:00:00 2001 From: Michael Schlottke-Lakemper Date: Fri, 1 Sep 2023 21:55:38 +0200 Subject: [PATCH 016/138] Apply suggestions from code review --- test/test_parabolic_1d.jl | 6 +++--- test/test_parabolic_2d.jl | 12 ++++++------ test/test_parabolic_3d.jl | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index 7962151c1f3..3c2b8855ce8 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -37,9 +37,9 @@ isdir(outdir) && rm(outdir, recursive=true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) sol = solve(ode, KenCarp4(autodiff=false), abstol=time_abs_tol, reltol=time_int_tol, save_everystep=false, callback=callbacks) - analysis_callback_sol = analysis_callback(sol) - @test analysis_callback_sol.l2[1] ≈ 6.4878111416468355e-6 - @test analysis_callback_sol.linf[1] ≈ 3.258075790424364e-5 + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ [6.4878111416468355e-6] + @test linf_error ≈ [3.258075790424364e-5] end @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl" begin diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index ca0b8b198a2..3fff4382cd1 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -143,9 +143,9 @@ isdir(outdir) && rm(outdir, recursive=true) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, ode_default_options()..., callback=callbacks) - analysis_callback_sol = analysis_callback(sol) - @test analysis_callback_sol.l2[1] ≈ 1.67452550744728e-6 - @test analysis_callback_sol.linf[1] ≈ 7.905059166368744e-6 + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ [1.67452550744728e-6] + @test linf_error ≈ [7.905059166368744e-6] # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -229,9 +229,9 @@ isdir(outdir) && rm(outdir, recursive=true) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, ode_default_options()..., callback=callbacks) - analysis_callback_sol = analysis_callback(sol) - @test analysis_callback_sol.l2 ≈ [0.00024296959173852447; 0.0002093263158670915; 0.0005390572390977262; 0.00026753561392341537] - @test analysis_callback_sol.linf ≈ [0.0016210102053424436; 0.002593287648655501; 0.002953907343823712; 0.002077119120180271] + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ [0.00024296959173852447; 0.0002093263158670915; 0.0005390572390977262; 0.00026753561392341537] + @test linf_error ≈ [0.0016210102053424436; 0.002593287648655501; 0.002953907343823712; 0.002077119120180271] end @trixi_testset "TreeMesh2D: elixir_navierstokes_lid_driven_cavity.jl" begin diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 14eb9471b41..ded052fb9d3 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -94,9 +94,9 @@ isdir(outdir) && rm(outdir, recursive=true) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, ode_default_options()..., callback=callbacks) - analysis_callback_sol = analysis_callback(sol) - @test analysis_callback_sol.l2 ≈ [0.0003991794175622818; 0.0008853745163670504; 0.0010658655552066817; 0.0008785559918324284; 0.001403163458422815] - @test analysis_callback_sol.linf ≈ [0.0035306410538458177; 0.01505692306169911; 0.008862444161110705; 0.015065647972869856; 0.030402714743065218] + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ [0.0003991794175622818; 0.0008853745163670504; 0.0010658655552066817; 0.0008785559918324284; 0.001403163458422815] + @test linf_error ≈ [0.0035306410538458177; 0.01505692306169911; 0.008862444161110705; 0.015065647972869856; 0.030402714743065218] end @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin @@ -127,9 +127,9 @@ isdir(outdir) && rm(outdir, recursive=true) sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), dt=5e-3, save_everystep=false, callback=callbacks); - analysis_callback_sol = analysis_callback(sol) - @test analysis_callback_sol.l2 ≈ [0.0013666103707729502; 0.2313581629543744; 0.2308164306264533; 0.17460246787819503; 0.28121914446544005] - @test analysis_callback_sol.linf ≈ [0.006938093883741336; 1.028235074139312; 1.0345438209717241; 1.0821111605203542; 1.2669636522564645] + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ [0.0013666103707729502; 0.2313581629543744; 0.2308164306264533; 0.17460246787819503; 0.28121914446544005] + @test linf_error ≈ [0.006938093883741336; 1.028235074139312; 1.0345438209717241; 1.0821111605203542; 1.2669636522564645] # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From abb6dfb81392dc5d4a35cb09b6cb83a4a163c67f Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 09:55:25 +0200 Subject: [PATCH 017/138] add specifier for 1d --- src/solvers/dgsem_tree/container_viscous_1d.jl | 2 +- src/solvers/dgsem_tree/dg_1d_parabolic.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/container_viscous_1d.jl b/src/solvers/dgsem_tree/container_viscous_1d.jl index a4919f75396..3f9943aea1c 100644 --- a/src/solvers/dgsem_tree/container_viscous_1d.jl +++ b/src/solvers/dgsem_tree/container_viscous_1d.jl @@ -19,7 +19,7 @@ mutable struct ViscousContainer1D{uEltype <: Real} end end -function init_viscous_container(n_vars::Integer, n_nodes::Integer, +function init_viscous_container_1d(n_vars::Integer, n_nodes::Integer, n_elements::Integer, ::Type{uEltype}) where {uEltype <: Real} return ViscousContainer1D{uEltype}(n_vars, n_nodes, n_elements) diff --git a/src/solvers/dgsem_tree/dg_1d_parabolic.jl b/src/solvers/dgsem_tree/dg_1d_parabolic.jl index 561bd714032..20626471941 100644 --- a/src/solvers/dgsem_tree/dg_1d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_1d_parabolic.jl @@ -531,7 +531,7 @@ function create_cache_parabolic(mesh::TreeMesh{1}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) - viscous_container = init_viscous_container(nvariables(equations_hyperbolic), + viscous_container = init_viscous_container_1d(nvariables(equations_hyperbolic), nnodes(elements), nelements(elements), uEltype) From bfa3a2448e1c9045e478da7f2dc1cb3b08353576 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 09:56:22 +0200 Subject: [PATCH 018/138] Structs for resizing parabolic helpers --- .../dgsem_tree/container_viscous_2d.jl | 60 ++++++++++++++++++ .../dgsem_tree/container_viscous_3d.jl | 61 +++++++++++++++++++ src/solvers/dgsem_tree/containers_viscous.jl | 4 ++ src/solvers/dgsem_tree/dg.jl | 4 +- 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 src/solvers/dgsem_tree/container_viscous_2d.jl create mode 100644 src/solvers/dgsem_tree/container_viscous_3d.jl create mode 100644 src/solvers/dgsem_tree/containers_viscous.jl diff --git a/src/solvers/dgsem_tree/container_viscous_2d.jl b/src/solvers/dgsem_tree/container_viscous_2d.jl new file mode 100644 index 00000000000..151011e9757 --- /dev/null +++ b/src/solvers/dgsem_tree/container_viscous_2d.jl @@ -0,0 +1,60 @@ +mutable struct ViscousContainer2D{uEltype <: Real} + u_transformed::Array{uEltype, 4} + # IDEA: Use SVector for fixed sized vectors? + gradients::Vector{Array{uEltype, 4}} + flux_viscous::Vector{Array{uEltype, 4}} + + # internal `resize!`able storage + _u_transformed::Vector{uEltype} + _gradients::Vector{Vector{uEltype}} + _flux_viscous::Vector{Vector{uEltype}} + + function ViscousContainer2D{uEltype}(n_vars::Integer, n_nodes::Integer, n_elements::Integer) where {uEltype <: Real} + new(Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements), + [Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements) for _ in 1:2], + [Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements) for _ in 1:2], + Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements), + [Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements) for _ in 1:2], + [Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements) for _ in 1:2]) + end +end + +function init_viscous_container_2d(n_vars::Integer, n_nodes::Integer, + n_elements::Integer, + ::Type{uEltype}) where {uEltype <: Real} + return ViscousContainer2D{uEltype}(n_vars, n_nodes, n_elements) +end + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(viscous_container::ViscousContainer2D, equations, dg, cache) + capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nelements(dg, cache) + resize!(cache_viscous._u_transformed, capacity) + for dim in 1:2 + resize!(cache_viscous._gradients[dim], capacity) + resize!(cache_viscous._flux_viscous[dim], capacity) + end + + viscous_container.u_transformed = unsafe_wrap(Array, + pointer(viscous_container._u_transformed), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + viscous_container.gradients = unsafe_wrap(Array, + pointer(viscous_container._gradients), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + viscous_container.flux_viscous = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + return nothing +end \ No newline at end of file diff --git a/src/solvers/dgsem_tree/container_viscous_3d.jl b/src/solvers/dgsem_tree/container_viscous_3d.jl new file mode 100644 index 00000000000..9a7749d7a9b --- /dev/null +++ b/src/solvers/dgsem_tree/container_viscous_3d.jl @@ -0,0 +1,61 @@ +mutable struct ViscousContainer3D{uEltype <: Real} + u_transformed::Array{uEltype, 5} + # IDEA: Use SVector for fixed sized vectors? + gradients::Vector{Array{uEltype, 5}} + flux_viscous::Vector{Array{uEltype, 5}} + + # internal `resize!`able storage + _u_transformed::Vector{uEltype} + _gradients::Vector{Vector{uEltype}} + _flux_viscous::Vector{Vector{uEltype}} + + function ViscousContainer3D{uEltype}(n_vars::Integer, n_nodes::Integer, n_elements::Integer) where {uEltype <: Real} + new(Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements), + [Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) for _ in 1:3], + [Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) for _ in 1:3], + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + [Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements) for _ in 1:3], + [Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements) for _ in 1:3]) + end +end + + +function init_viscous_container_3d(n_vars::Integer, n_nodes::Integer, + n_elements::Integer, + ::Type{uEltype}) where {uEltype <: Real} + return ViscousContainer3D{uEltype}(n_vars, n_nodes, n_elements) +end + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(viscous_container::ViscousContainer3D, equations, dg, cache) + capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nnodes(dg) * nelements(dg, cache) + resize!(cache_viscous._u_transformed, capacity) + for dim in 1:3 + resize!(cache_viscous._gradients[dim], capacity) + resize!(cache_viscous._flux_viscous[dim], capacity) + end + + viscous_container.u_transformed = unsafe_wrap(Array, + pointer(viscous_container._u_transformed), + (nvariables(equations), + nnodes(dg), nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + viscous_container.gradients = unsafe_wrap(Array, + pointer(viscous_container._gradients), + (nvariables(equations), + nnodes(dg), nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + viscous_container.flux_viscous = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous), + (nvariables(equations), + nnodes(dg), nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + return nothing +end \ No newline at end of file diff --git a/src/solvers/dgsem_tree/containers_viscous.jl b/src/solvers/dgsem_tree/containers_viscous.jl new file mode 100644 index 00000000000..2a8989db55c --- /dev/null +++ b/src/solvers/dgsem_tree/containers_viscous.jl @@ -0,0 +1,4 @@ +# Dimension-specific implementations +include("container_viscous_1d.jl") +include("container_viscous_2d.jl") +include("container_viscous_3d.jl") \ No newline at end of file diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index ff37bad3b3a..ef9a42b4c1a 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -54,8 +54,8 @@ include("containers.jl") # Dimension-agnostic parallel setup include("dg_parallel.jl") -# Helper struct for parabolic AMR -include("container_viscous_1d.jl") +# Helper structs for parabolic AMR +include("containers_viscous.jl") # 1D DG implementation include("dg_1d.jl") From 40ad2668cfc6844cb8fbcbde71a3925390c006f6 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 09:57:18 +0200 Subject: [PATCH 019/138] check if mortars are present --- src/solvers/dgsem_tree/containers.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/solvers/dgsem_tree/containers.jl b/src/solvers/dgsem_tree/containers.jl index bba8b83b23a..3f05daf81d8 100644 --- a/src/solvers/dgsem_tree/containers.jl +++ b/src/solvers/dgsem_tree/containers.jl @@ -28,9 +28,11 @@ function reinitialize_containers!(mesh::TreeMesh, equations, dg::DGSEM, cache) init_boundaries!(boundaries, elements, mesh) # re-initialize mortars container - @unpack mortars = cache - resize!(mortars, count_required_mortars(mesh, leaf_cell_ids)) - init_mortars!(mortars, elements, mesh) + if hasproperty(cache, :mortars) # cache_parabolic does not carry mortars + @unpack mortars = cache + resize!(mortars, count_required_mortars(mesh, leaf_cell_ids)) + init_mortars!(mortars, elements, mesh) + end if mpi_isparallel() # re-initialize mpi_interfaces container From 4d1914bcb257d441eb2e963a68061f046cb60d7f Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 10:17:49 +0200 Subject: [PATCH 020/138] reuse `reinitialize_containers!` --- src/callbacks_step/amr_dg1d.jl | 43 +++++----------------------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index e721ccc61cb..b4cd6a00271 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -83,30 +83,13 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, # actually transferring the solution to the refined cells refine!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_refine) - # The remaining function only handles the necessary adaptation of the data structures - # for the parabolic part of the semidiscretization - - # Get new list of leaf cells - leaf_cell_ids = local_leaf_cells(mesh.tree) - - @unpack elements, viscous_container = cache_parabolic - resize!(elements, length(leaf_cell_ids)) - init_elements!(elements, leaf_cell_ids, mesh, dg.basis) - # Resize parabolic helper variables + @unpack viscous_container = cache_parabolic resize!(viscous_container, equations, dg, cache) - - # re-initialize interfaces container - @unpack interfaces = cache_parabolic - resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) - init_interfaces!(interfaces, elements, mesh) - - # re-initialize boundaries container - @unpack boundaries = cache_parabolic - resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) - init_boundaries!(boundaries, elements, mesh) + reinitialize_containers!(mesh, equations, dg, cache_parabolic) # Sanity check + @unpack interfaces = cache_parabolic if isperiodic(mesh.tree) @assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") end @@ -246,27 +229,13 @@ function coarsen!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, # actually transferring the solution to the coarsened cells coarsen!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_remove) - # Get new list of leaf cells - leaf_cell_ids = local_leaf_cells(mesh.tree) - - @unpack elements, viscous_container = cache_parabolic - resize!(elements, length(leaf_cell_ids)) - init_elements!(elements, leaf_cell_ids, mesh, dg.basis) - # Resize parabolic helper variables + @unpack viscous_container = cache_parabolic resize!(viscous_container, equations, dg, cache) - - # re-initialize interfaces container - @unpack interfaces = cache_parabolic - resize!(interfaces, count_required_interfaces(mesh, leaf_cell_ids)) - init_interfaces!(interfaces, elements, mesh) - - # re-initialize boundaries container - @unpack boundaries = cache_parabolic - resize!(boundaries, count_required_boundaries(mesh, leaf_cell_ids)) - init_boundaries!(boundaries, elements, mesh) + reinitialize_containers!(mesh, equations, dg, cache_parabolic) # Sanity check + @unpack interfaces = cache_parabolic if isperiodic(mesh.tree) @assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") end From 70c8e6641e078a55fefd0d01398ff63b7531893c Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 10:18:04 +0200 Subject: [PATCH 021/138] resize calls for parabolic helpers --- src/callbacks_step/amr_dg2d.jl | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/callbacks_step/amr_dg2d.jl b/src/callbacks_step/amr_dg2d.jl index 1d37dfce034..5b36f22c82e 100644 --- a/src/callbacks_step/amr_dg2d.jl +++ b/src/callbacks_step/amr_dg2d.jl @@ -136,6 +136,28 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, P4estM return nothing end +# AMR for hyperbolic-parabolic equations currently only supported on TreeMeshes +function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, TreeMesh{3}}, + equations, dg::DGSEM, cache, cache_parabolic, + elements_to_refine) + # Call `refine!` for the hyperbolic part, which does the heavy lifting of + # actually transferring the solution to the refined cells + refine!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_refine) + + # Resize parabolic helper variables + @unpack viscous_container = cache_parabolic + resize!(viscous_container, equations, dg, cache) + reinitialize_containers!(mesh, equations, dg, cache_parabolic) + + # Sanity check + if mesh isa TreeMesh && isperiodic(mesh.tree) && nmortars(cache.mortars) == 0 && + !mpi_isparallel() + @assert ninterfaces(cache_parabolic.interfaces)==ndims(mesh) * nelements(dg, cache_parabolic) ("For $(ndims(mesh))D and periodic domains and conforming elements, the number of interfaces must be $(ndims(mesh)) times the number of elements") + end + + return nothing +end + # TODO: Taal compare performance of different implementations # Refine solution data u for an element, using L2 projection (interpolation) function refine_element!(u::AbstractArray{<:Any, 4}, element_id, @@ -275,6 +297,28 @@ function coarsen!(u_ode::AbstractVector, adaptor, return nothing end +# AMR for hyperbolic-parabolic equations currently only supported on TreeMeshes +function coarsen!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, TreeMesh{3}}, + equations, dg::DGSEM, cache, cache_parabolic, + elements_to_remove) + # Call `coarsen!` for the hyperbolic part, which does the heavy lifting of + # actually transferring the solution to the coarsened cells + coarsen!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_remove) + + # Resize parabolic helper variables + @unpack viscous_container = cache_parabolic + resize!(viscous_container, equations, dg, cache) + reinitialize_containers!(mesh, equations, dg, cache_parabolic) + + # Sanity check + if mesh isa TreeMesh && isperiodic(mesh.tree) && nmortars(cache.mortars) == 0 && + !mpi_isparallel() + @assert ninterfaces(cache_parabolic.interfaces)==ndims(mesh) * nelements(dg, cache_parabolic) ("For $(ndims(mesh))D and periodic domains and conforming elements, the number of interfaces must be $(ndims(mesh)) times the number of elements") + end + + return nothing +end + # TODO: Taal compare performance of different implementations # Coarsen solution data u for four elements, using L2 projection function coarsen_elements!(u::AbstractArray{<:Any, 4}, element_id, From a5db7d0b7d28ea0bbbe1591ef7c78a9c45b55f87 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 10:20:31 +0200 Subject: [PATCH 022/138] update analysis callbacks --- src/callbacks_step/analysis_dg2d.jl | 2 +- src/callbacks_step/analysis_dg3d.jl | 2 +- src/callbacks_step/analysis_dgmulti.jl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/callbacks_step/analysis_dg2d.jl b/src/callbacks_step/analysis_dg2d.jl index aecabf0e4b7..a9e0cf87b0a 100644 --- a/src/callbacks_step/analysis_dg2d.jl +++ b/src/callbacks_step/analysis_dg2d.jl @@ -218,7 +218,7 @@ function integrate(func::Func, u, equations, equations_parabolic, dg::DGSEM, cache, cache_parabolic; normalize = true) where {Func} - gradients_x, gradients_y = cache_parabolic.gradients + gradients_x, gradients_y = cache_parabolic.viscous_container.gradients integrate_via_indices(u, mesh, equations, dg, cache; normalize = normalize) do u, i, j, element, equations, dg u_local = get_node_vars(u, equations, dg, i, j, element) diff --git a/src/callbacks_step/analysis_dg3d.jl b/src/callbacks_step/analysis_dg3d.jl index 3d9b38fd2a5..81d0795a159 100644 --- a/src/callbacks_step/analysis_dg3d.jl +++ b/src/callbacks_step/analysis_dg3d.jl @@ -232,7 +232,7 @@ function integrate(func::Func, u, equations, equations_parabolic, dg::DGSEM, cache, cache_parabolic; normalize = true) where {Func} - gradients_x, gradients_y, gradients_z = cache_parabolic.gradients + gradients_x, gradients_y, gradients_z = cache_parabolic.viscous_container.gradients integrate_via_indices(u, mesh, equations, dg, cache; normalize = normalize) do u, i, j, k, element, equations, dg u_local = get_node_vars(u, equations, dg, i, j, k, element) diff --git a/src/callbacks_step/analysis_dgmulti.jl b/src/callbacks_step/analysis_dgmulti.jl index dc294de9e7b..82a091250a8 100644 --- a/src/callbacks_step/analysis_dgmulti.jl +++ b/src/callbacks_step/analysis_dgmulti.jl @@ -140,7 +140,7 @@ function integrate(func::typeof(enstrophy), u, equations, equations_parabolic::CompressibleNavierStokesDiffusion3D, dg::DGMulti, cache, cache_parabolic; normalize = true) - gradients_x, gradients_y, gradients_z = cache_parabolic.gradients + gradients_x, gradients_y, gradients_z = cache_parabolic.viscous_container.gradients # allocate local storage for gradients. # TODO: can we avoid allocating here? From c9d98a21ca831ce93ffb896c3f3ebb4ca135e26f Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 10:24:43 +0200 Subject: [PATCH 023/138] Velocities for compr euler --- src/Trixi.jl | 2 +- src/equations/compressible_euler_1d.jl | 5 +++++ src/equations/compressible_euler_2d.jl | 10 ++++++++++ src/equations/compressible_euler_3d.jl | 15 +++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index ec4d20558e5..b95ede67163 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -205,7 +205,7 @@ export initial_condition_eoc_test_coupled_euler_gravity, export cons2cons, cons2prim, prim2cons, cons2macroscopic, cons2state, cons2mean, cons2entropy, entropy2cons -export density, pressure, density_pressure, velocity, global_mean_vars, +export density, pressure, density_pressure, velocity, v1, v2, v3, global_mean_vars, equilibrium_distribution, waterheight_pressure export entropy, energy_total, energy_kinetic, energy_internal, energy_magnetic, cross_helicity, diff --git a/src/equations/compressible_euler_1d.jl b/src/equations/compressible_euler_1d.jl index 9204989e8be..6d9ad996973 100644 --- a/src/equations/compressible_euler_1d.jl +++ b/src/equations/compressible_euler_1d.jl @@ -973,6 +973,11 @@ end return rho_times_p end +@inline function v1(u, equations::CompressibleEulerEquations1D) + rho, rho_v1, _ = u + return rho_v1/rho +end + # Calculate thermodynamic entropy for a conservative state `cons` @inline function entropy_thermodynamic(cons, equations::CompressibleEulerEquations1D) # Pressure diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 27b92f41953..ccc208d911d 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1428,6 +1428,16 @@ end return rho_times_p end +@inline function v1(u, equations::CompressibleEulerEquations2D) + rho, rho_v1, _, _ = u + return rho_v1/rho +end + +@inline function v2(u, equations::CompressibleEulerEquations2D) + rho, _, rho_v2, _ = u + return rho_v2/rho +end + # Calculates the entropy flux in direction "orientation" and the entropy variables for a state cons # NOTE: This method seems to work currently (b82534e) but is never used anywhere. Thus it is # commented here until someone uses it or writes a test for it. diff --git a/src/equations/compressible_euler_3d.jl b/src/equations/compressible_euler_3d.jl index 7f25bde31fd..357851a18d7 100644 --- a/src/equations/compressible_euler_3d.jl +++ b/src/equations/compressible_euler_3d.jl @@ -1514,6 +1514,21 @@ end return rho_times_p end +@inline function v1(u, equations::CompressibleEulerEquations3D) + rho, rho_v1, _, _, _ = u + return rho_v1/rho +end + +@inline function v2(u, equations::CompressibleEulerEquations3D) + rho, _, rho_v2, _, _ = u + return rho_v2/rho +end + +@inline function v3(u, equations::CompressibleEulerEquations3D) + rho, _, _, rho_v3, _ = u + return rho_v3/rho +end + # Calculate thermodynamic entropy for a conservative state `u` @inline function entropy_thermodynamic(u, equations::CompressibleEulerEquations3D) rho, _ = u From 694e6bc8a1379e4e76fe6cc400a5ba083770505d Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 10:39:50 +0200 Subject: [PATCH 024/138] Init container --- src/solvers/dgsem_tree/dg_1d_parabolic.jl | 8 ++++---- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 16 +++++++--------- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 16 +++++++--------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_1d_parabolic.jl b/src/solvers/dgsem_tree/dg_1d_parabolic.jl index 20626471941..1d0a7e247ee 100644 --- a/src/solvers/dgsem_tree/dg_1d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_1d_parabolic.jl @@ -531,14 +531,14 @@ function create_cache_parabolic(mesh::TreeMesh{1}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) - viscous_container = init_viscous_container_1d(nvariables(equations_hyperbolic), - nnodes(elements), nelements(elements), - uEltype) - interfaces = init_interfaces(leaf_cell_ids, mesh, elements) boundaries = init_boundaries(leaf_cell_ids, mesh, elements) + viscous_container = init_viscous_container_1d(nvariables(equations_hyperbolic), + nnodes(elements), nelements(elements), + uEltype) + cache = (; elements, interfaces, boundaries, viscous_container) return cache diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 0da25230380..3ac41c278ee 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -17,7 +17,8 @@ function rhs_parabolic!(du, u, t, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - (; u_transformed, gradients, flux_viscous) = cache_parabolic + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin @@ -906,21 +907,18 @@ function create_cache_parabolic(mesh::TreeMesh{2}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) - n_vars = nvariables(equations_hyperbolic) - n_nodes = nnodes(elements) - n_elements = nelements(elements) - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_nodes, n_elements) - gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) - flux_viscous = ntuple(_ -> similar(u_transformed), ndims(mesh)) - interfaces = init_interfaces(leaf_cell_ids, mesh, elements) boundaries = init_boundaries(leaf_cell_ids, mesh, elements) # mortars = init_mortars(leaf_cell_ids, mesh, elements, dg.mortar) + viscous_container = init_viscous_container_2d(nvariables(equations_hyperbolic), + nnodes(elements), nelements(elements), + uEltype) + # cache = (; elements, interfaces, boundaries, mortars) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + cache = (; elements, interfaces, boundaries, viscous_container) # Add specialized parts of the cache required to compute the mortars etc. # cache = (;cache..., create_cache(mesh, equations_parabolic, dg.mortar, uEltype)...) diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index 2745d312b37..b5719247fce 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -17,7 +17,8 @@ function rhs_parabolic!(du, u, t, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - @unpack u_transformed, gradients, flux_viscous = cache_parabolic + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin @@ -1096,21 +1097,18 @@ function create_cache_parabolic(mesh::TreeMesh{3}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) - n_vars = nvariables(equations_hyperbolic) - n_nodes = nnodes(elements) - n_elements = nelements(elements) - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) - gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) - flux_viscous = ntuple(_ -> similar(u_transformed), ndims(mesh)) - interfaces = init_interfaces(leaf_cell_ids, mesh, elements) boundaries = init_boundaries(leaf_cell_ids, mesh, elements) # mortars = init_mortars(leaf_cell_ids, mesh, elements, dg.mortar) + viscous_container = init_viscous_container_3d(nvariables(equations_hyperbolic), + nnodes(elements), nelements(elements), + uEltype) + # cache = (; elements, interfaces, boundaries, mortars) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + cache = (; elements, interfaces, boundaries, viscous_container) # Add specialized parts of the cache required to compute the mortars etc. # cache = (;cache..., create_cache(mesh, equations_parabolic, dg.mortar, uEltype)...) From 07655a47b43a4a3446ca3728be73a032371a9ce0 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 10:40:17 +0200 Subject: [PATCH 025/138] correct copy-paste error --- src/solvers/dgsem_tree/container_viscous_2d.jl | 6 +++--- src/solvers/dgsem_tree/container_viscous_3d.jl | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/solvers/dgsem_tree/container_viscous_2d.jl b/src/solvers/dgsem_tree/container_viscous_2d.jl index 151011e9757..2a44d8f44aa 100644 --- a/src/solvers/dgsem_tree/container_viscous_2d.jl +++ b/src/solvers/dgsem_tree/container_viscous_2d.jl @@ -32,10 +32,10 @@ end # internal storage. function Base.resize!(viscous_container::ViscousContainer2D, equations, dg, cache) capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nelements(dg, cache) - resize!(cache_viscous._u_transformed, capacity) + resize!(viscous_container._u_transformed, capacity) for dim in 1:2 - resize!(cache_viscous._gradients[dim], capacity) - resize!(cache_viscous._flux_viscous[dim], capacity) + resize!(viscous_container._gradients[dim], capacity) + resize!(viscous_container._flux_viscous[dim], capacity) end viscous_container.u_transformed = unsafe_wrap(Array, diff --git a/src/solvers/dgsem_tree/container_viscous_3d.jl b/src/solvers/dgsem_tree/container_viscous_3d.jl index 9a7749d7a9b..778a1df737a 100644 --- a/src/solvers/dgsem_tree/container_viscous_3d.jl +++ b/src/solvers/dgsem_tree/container_viscous_3d.jl @@ -33,10 +33,10 @@ end # internal storage. function Base.resize!(viscous_container::ViscousContainer3D, equations, dg, cache) capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nnodes(dg) * nelements(dg, cache) - resize!(cache_viscous._u_transformed, capacity) + resize!(viscous_container._u_transformed, capacity) for dim in 1:3 - resize!(cache_viscous._gradients[dim], capacity) - resize!(cache_viscous._flux_viscous[dim], capacity) + resize!(viscous_container._gradients[dim], capacity) + resize!(viscous_container._flux_viscous[dim], capacity) end viscous_container.u_transformed = unsafe_wrap(Array, From edd82ce95b02b5a59478710164d8df4fdd037898 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 11:37:00 +0200 Subject: [PATCH 026/138] resize each dim --- .../dgsem_tree/container_viscous_2d.jl | 25 ++++++++++--------- .../dgsem_tree/container_viscous_3d.jl | 25 ++++++++++--------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/solvers/dgsem_tree/container_viscous_2d.jl b/src/solvers/dgsem_tree/container_viscous_2d.jl index 2a44d8f44aa..80554365aa5 100644 --- a/src/solvers/dgsem_tree/container_viscous_2d.jl +++ b/src/solvers/dgsem_tree/container_viscous_2d.jl @@ -44,17 +44,18 @@ function Base.resize!(viscous_container::ViscousContainer2D, equations, dg, cach nnodes(dg), nnodes(dg), nelements(dg, cache))) - viscous_container.gradients = unsafe_wrap(Array, - pointer(viscous_container._gradients), - (nvariables(equations), - nnodes(dg), nnodes(dg), - nelements(dg, cache))) - - viscous_container.flux_viscous = unsafe_wrap(Array, - pointer(viscous_container._flux_viscous), - (nvariables(equations), - nnodes(dg), nnodes(dg), - nelements(dg, cache))) - + for dim in 1:2 + viscous_container.gradients[dim] = unsafe_wrap(Array, + pointer(viscous_container._gradients[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + viscous_container.flux_viscous[dim] = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) + end return nothing end \ No newline at end of file diff --git a/src/solvers/dgsem_tree/container_viscous_3d.jl b/src/solvers/dgsem_tree/container_viscous_3d.jl index 778a1df737a..30fa864825e 100644 --- a/src/solvers/dgsem_tree/container_viscous_3d.jl +++ b/src/solvers/dgsem_tree/container_viscous_3d.jl @@ -45,17 +45,18 @@ function Base.resize!(viscous_container::ViscousContainer3D, equations, dg, cach nnodes(dg), nnodes(dg), nnodes(dg), nelements(dg, cache))) - viscous_container.gradients = unsafe_wrap(Array, - pointer(viscous_container._gradients), - (nvariables(equations), - nnodes(dg), nnodes(dg), nnodes(dg), - nelements(dg, cache))) - - viscous_container.flux_viscous = unsafe_wrap(Array, - pointer(viscous_container._flux_viscous), - (nvariables(equations), - nnodes(dg), nnodes(dg), nnodes(dg), - nelements(dg, cache))) - + for dim in 1:3 + viscous_container.gradients[dim] = unsafe_wrap(Array, + pointer(viscous_container._gradients[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + viscous_container.flux_viscous[dim] = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), nnodes(dg), + nelements(dg, cache))) + end return nothing end \ No newline at end of file From ba1ef1bedeff57d340803bb72f947ab3813d7ae0 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 11:41:03 +0200 Subject: [PATCH 027/138] add dispatch --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 20 ++++++++++---------- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 21 ++++++++++----------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 3ac41c278ee..c4584a2cda5 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -132,10 +132,10 @@ function transform_variables!(u_transformed, u, mesh::Union{TreeMesh{2}, P4estMe end # This is the version used when calculating the divergence of the viscous fluxes -function calc_volume_integral!(du, flux_viscous, +function calc_volume_integral!(du, flux_viscous::Vector{Array{uEltype, 4}}, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, - dg::DGSEM, cache) + dg::DGSEM, cache) where {uEltype <: Real} @unpack derivative_dhat = dg.basis flux_viscous_x, flux_viscous_y = flux_viscous @@ -164,10 +164,10 @@ end # This is the version used when calculating the divergence of the viscous fluxes # We pass the `surface_integral` argument solely for dispatch -function prolong2interfaces!(cache_parabolic, flux_viscous, +function prolong2interfaces!(cache_parabolic, flux_viscous::Vector{Array{uEltype, 4}}, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) + surface_integral, dg::DG, cache) where {uEltype <: Real} @unpack interfaces = cache_parabolic @unpack orientations = interfaces @@ -240,10 +240,10 @@ function calc_interface_flux!(surface_flux_values, end # This is the version used when calculating the divergence of the viscous fluxes -function prolong2boundaries!(cache_parabolic, flux_viscous, +function prolong2boundaries!(cache_parabolic, flux_viscous::Vector{Array{uEltype, 4}}, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) + surface_integral, dg::DG, cache) where {uEltype <: Real} @unpack boundaries = cache_parabolic @unpack orientations, neighbor_sides = boundaries flux_viscous_x, flux_viscous_y = flux_viscous @@ -288,10 +288,10 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, return nothing end -function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, +function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 4}}, gradients, u_transformed, mesh::Union{TreeMesh{2}, P4estMesh{2}}, equations_parabolic::AbstractEquationsParabolic, - dg::DG, cache, cache_parabolic) + dg::DG, cache, cache_parabolic) where {uEltype <: Real} gradients_x, gradients_y = gradients flux_viscous_x, flux_viscous_y = flux_viscous # output arrays @@ -511,11 +511,11 @@ function calc_boundary_flux_by_direction_divergence!(surface_flux_values::Abstra return nothing end -function prolong2mortars!(cache, flux_viscous::Tuple{AbstractArray, AbstractArray}, +function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, mortar_l2::LobattoLegendreMortarL2, surface_integral, - dg::DGSEM) + dg::DGSEM) where {uEltype <: Real} flux_viscous_x, flux_viscous_y = flux_viscous @threaded for mortar in eachmortar(dg, cache) large_element = cache.mortars.neighbor_ids[3, mortar] diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index b5719247fce..efade560303 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -132,10 +132,10 @@ function transform_variables!(u_transformed, u, mesh::Union{TreeMesh{3}, P4estMe end # This is the version used when calculating the divergence of the viscous fluxes -function calc_volume_integral!(du, flux_viscous, +function calc_volume_integral!(du, flux_viscous::Vector{Array{uEltype, 5}}, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, - dg::DGSEM, cache) + dg::DGSEM, cache) where {uEltype <: Real} @unpack derivative_dhat = dg.basis flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous @@ -171,10 +171,10 @@ end # This is the version used when calculating the divergence of the viscous fluxes # We pass the `surface_integral` argument solely for dispatch -function prolong2interfaces!(cache_parabolic, flux_viscous, +function prolong2interfaces!(cache_parabolic, flux_viscous::Vector{Array{uEltype, 5}}, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) + surface_integral, dg::DG, cache) where {uEltype <: Real} @unpack interfaces = cache_parabolic @unpack orientations = interfaces @@ -261,10 +261,10 @@ function calc_interface_flux!(surface_flux_values, end # This is the version used when calculating the divergence of the viscous fluxes -function prolong2boundaries!(cache_parabolic, flux_viscous, +function prolong2boundaries!(cache_parabolic, flux_viscous::Vector{Array{uEltype, 5}}, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) + surface_integral, dg::DG, cache) where {uEltype <: Real} @unpack boundaries = cache_parabolic @unpack orientations, neighbor_sides = boundaries flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous @@ -336,10 +336,10 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, return nothing end -function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, +function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 5}}, gradients, u_transformed, mesh::Union{TreeMesh{3}, P4estMesh{3}}, equations_parabolic::AbstractEquationsParabolic, - dg::DG, cache, cache_parabolic) + dg::DG, cache, cache_parabolic) where {uEltype <: Real} gradients_x, gradients_y, gradients_z = gradients flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous # output arrays @@ -595,12 +595,11 @@ function calc_boundary_flux_by_direction_divergence!(surface_flux_values::Abstra end function prolong2mortars!(cache, - flux_viscous::Tuple{AbstractArray, AbstractArray, - AbstractArray}, + flux_viscous::Vector{Array{uEltype, 5}}, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, mortar_l2::LobattoLegendreMortarL2, - surface_integral, dg::DGSEM) + surface_integral, dg::DGSEM) where {uEltype <: Real} # temporary buffer for projections @unpack fstar_tmp1_threaded = cache From 7d351e512f967fdbea03733123f147f5dbf96adf Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 11:47:19 +0200 Subject: [PATCH 028/138] Add AMR for shear layer --- ...r.jl => elixir_navierstokes_shearlayer.jl} | 4 +- .../elixir_navierstokes_shearlayer_amr.jl | 85 +++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) rename examples/tree_2d_dgsem/{elixir_navierstokes_shear_layer.jl => elixir_navierstokes_shearlayer.jl} (94%) create mode 100644 examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shear_layer.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer.jl similarity index 94% rename from examples/tree_2d_dgsem/elixir_navierstokes_shear_layer.jl rename to examples/tree_2d_dgsem/elixir_navierstokes_shearlayer.jl index dd26fd8097b..6b111659273 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_shear_layer.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer.jl @@ -22,8 +22,8 @@ function initial_condition_shear_layer(x, t, equations::CompressibleEulerEquatio Ms = 0.1 # maximum Mach number rho = 1.0 - v1 = x[2] <= 0.5 ? u0 * tanh(k*(x[2]*0.5 - 0.25)) : u0 * tanh(k*(0.75 -x[2]*0.5)) - v2 = u0 * delta * sin(2*pi*(x[1]*0.5 + 0.25)) + v1 = x[2] <= 0.5 ? u0 * tanh(k*(x[2] - 0.25)) : u0 * tanh(k*(0.75 -x[2])) + v2 = u0 * delta * sin(2*pi*(x[1]+ 0.25)) p = (u0 / Ms)^2 * rho / equations.gamma # scaling to get Ms return prim2cons(SVector(rho, v1, v2, p), equations) diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl new file mode 100644 index 00000000000..10132f4ec1a --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl @@ -0,0 +1,85 @@ + +using OrdinaryDiffEq, Plots +using Trixi + +############################################################################### +# semidiscretization of the compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 1.0/3.0 * 10^(-5) + +equations = CompressibleEulerEquations2D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), + Prandtl=prandtl_number()) + +function initial_condition_shear_layer(x, t, equations::CompressibleEulerEquations2D) + # Shear layer parameters + k = 80 + delta = 0.05 + u0 = 1.0 + + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = x[2] <= 0.5 ? u0 * tanh(k*(x[2] - 0.25)) : u0 * tanh(k*(0.75 -x[2])) + v2 = u0 * delta * sin(2*pi*(x[1]+ 0.25)) + p = (u0 / Ms)^2 * rho / equations.gamma # scaling to get Ms + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_shear_layer + +volume_flux = flux_ranocha +solver = DGSEM(polydeg=3, surface_flux=flux_hllc, + volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = (0.0, 0.0) +coordinates_max = (1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=3, + n_cells_max=100_000) + + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.7) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 500 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +alive_callback = AliveCallback(analysis_interval=analysis_interval,) + +amr_indicator = IndicatorLöhner(semi, variable=v1) +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level = 3, + med_level = 5, med_threshold=0.2, + max_level = 7, max_threshold=0.5) +amr_callback = AMRCallback(semi, amr_controller, + interval=10, + adapt_initial_condition=true, + adapt_initial_condition_only_refine=true) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + amr_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) +summary_callback() # print the timer summary + +pd = PlotData2D(sol) +Plots.plot(pd["v1"]) +Plots.plot(getmesh(pd)) \ No newline at end of file From e60817454b7637133fa25ee2c5158a69d7090e74 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 12:01:28 +0200 Subject: [PATCH 029/138] USe only amr shear layer --- .../elixir_navierstokes_shearlayer.jl | 73 ------------------- .../elixir_navierstokes_shearlayer_amr.jl | 6 +- test/test_parabolic_2d.jl | 7 ++ 3 files changed, 10 insertions(+), 76 deletions(-) delete mode 100644 examples/tree_2d_dgsem/elixir_navierstokes_shearlayer.jl diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer.jl deleted file mode 100644 index 6b111659273..00000000000 --- a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer.jl +++ /dev/null @@ -1,73 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Navier-Stokes equations - -# TODO: parabolic; unify names of these accessor functions -prandtl_number() = 0.72 -mu() = 1.0/3.0 * 10^(-3) # equivalent to Re = 3000 - -equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) - -function initial_condition_shear_layer(x, t, equations::CompressibleEulerEquations2D) - # Shear layer parameters - k = 80 - delta = 0.05 - u0 = 1.0 - - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = x[2] <= 0.5 ? u0 * tanh(k*(x[2] - 0.25)) : u0 * tanh(k*(0.75 -x[2])) - v2 = u0 * delta * sin(2*pi*(x[1]+ 0.25)) - p = (u0 / Ms)^2 * rho / equations.gamma # scaling to get Ms - - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_shear_layer - -volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) - -coordinates_min = (0.0, 0.0) -coordinates_max = (1.0, 1.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000) - - -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 2.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval,) - -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback) - -############################################################################### -# run the simulation - -time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl index 10132f4ec1a..1da63588bcf 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl @@ -52,7 +52,7 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_interval = 500 +analysis_interval = 1000 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval,) @@ -63,7 +63,7 @@ amr_controller = ControllerThreeLevel(semi, amr_indicator, med_level = 5, med_threshold=0.2, max_level = 7, max_threshold=0.5) amr_callback = AMRCallback(semi, amr_controller, - interval=10, + interval=50, adapt_initial_condition=true, adapt_initial_condition_only_refine=true) @@ -75,7 +75,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -time_int_tol = 1e-8 +time_int_tol = 1e-7 sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, ode_default_options()..., callback=callbacks) summary_callback() # print the timer summary diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index 3fff4382cd1..a6cfd089c47 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -249,6 +249,13 @@ isdir(outdir) && rm(outdir, recursive=true) ) end + @trixi_testset "TreeMesh2D: elixir_navierstokes_shearlayer_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_shearlayer_amr.jl"), + l2 = [0.005352707453147317, 0.4077270907626271, 0.43758381263181434, 1.1758133763041454], + linf = [0.034784713829601244, 1.1650897299747531, 1.484016014155391, 8.71087741820071] + ) + end + @trixi_testset "P4estMesh2D: elixir_advection_diffusion_periodic.jl" begin @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_advection_diffusion_periodic.jl"), trees_per_dimension = (1, 1), initial_refinement_level = 2, tspan=(0.0, 0.5), From 6574bf59536e797b169137c8a9fbb24197c27473 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 13:26:19 +0200 Subject: [PATCH 030/138] first steps towards p4est parabolic amr --- src/callbacks_step/analysis_dgmulti.jl | 2 +- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 14 ++++---- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 14 ++++---- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 33 ++++++++++++++++- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 42 +++++++++++++++++++++- 5 files changed, 86 insertions(+), 19 deletions(-) diff --git a/src/callbacks_step/analysis_dgmulti.jl b/src/callbacks_step/analysis_dgmulti.jl index 82a091250a8..dc294de9e7b 100644 --- a/src/callbacks_step/analysis_dgmulti.jl +++ b/src/callbacks_step/analysis_dgmulti.jl @@ -140,7 +140,7 @@ function integrate(func::typeof(enstrophy), u, equations, equations_parabolic::CompressibleNavierStokesDiffusion3D, dg::DGMulti, cache, cache_parabolic; normalize = true) - gradients_x, gradients_y, gradients_z = cache_parabolic.viscous_container.gradients + gradients_x, gradients_y, gradients_z = cache_parabolic.gradients # allocate local storage for gradients. # TODO: can we avoid allocating here? diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index a04523d2fb4..cf07645b949 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -10,14 +10,11 @@ function create_cache_parabolic(mesh::P4estMesh{2}, equations_hyperbolic::Abstra interfaces = init_interfaces(mesh, equations_hyperbolic, dg.basis, elements) boundaries = init_boundaries(mesh, equations_hyperbolic, dg.basis, elements) - n_vars = nvariables(equations_hyperbolic) - n_elements = nelements(elements) - n_nodes = nnodes(dg.basis) # nodes in one direction - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_nodes, n_elements) - gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) - flux_viscous = ntuple(_ -> similar(u_transformed), ndims(mesh)) + viscous_container = init_viscous_container_2d(nvariables(equations_hyperbolic), + nnodes(dg.basis), nelements(elements), + uEltype) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + cache = (; elements, interfaces, boundaries, viscous_container) return cache end @@ -28,7 +25,8 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{2}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - (; u_transformed, gradients, flux_viscous) = cache_parabolic + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 2d26c1aff50..b06cdd42127 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -10,14 +10,11 @@ function create_cache_parabolic(mesh::P4estMesh{3}, equations_hyperbolic::Abstra interfaces = init_interfaces(mesh, equations_hyperbolic, dg.basis, elements) boundaries = init_boundaries(mesh, equations_hyperbolic, dg.basis, elements) - n_vars = nvariables(equations_hyperbolic) - n_elements = nelements(elements) - n_nodes = nnodes(dg.basis) # nodes in one direction - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) - gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) - flux_viscous = ntuple(_ -> similar(u_transformed), ndims(mesh)) + viscous_container = init_viscous_container_3d(nvariables(equations_hyperbolic), + nnodes(dg.basis), nelements(elements), + uEltype) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + cache = (; elements, interfaces, boundaries, viscous_container) return cache end @@ -36,7 +33,8 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - @unpack u_transformed, gradients, flux_viscous = cache_parabolic + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index c4584a2cda5..3d3e42d1a40 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -288,9 +288,40 @@ function prolong2boundaries!(cache_parabolic, flux_viscous::Vector{Array{uEltype return nothing end -function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 4}}, gradients, u_transformed, +function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, mesh::Union{TreeMesh{2}, P4estMesh{2}}, equations_parabolic::AbstractEquationsParabolic, + dg::DG, cache, cache_parabolic) + gradients_x, gradients_y = gradients + flux_viscous_x, flux_viscous_y = flux_viscous # output arrays + + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + # Get solution and gradients + u_node = get_node_vars(u_transformed, equations_parabolic, dg, i, j, + element) + gradients_1_node = get_node_vars(gradients_x, equations_parabolic, dg, i, j, + element) + gradients_2_node = get_node_vars(gradients_y, equations_parabolic, dg, i, j, + element) + + # Calculate viscous flux and store each component for later use + flux_viscous_node_x = flux(u_node, (gradients_1_node, gradients_2_node), 1, + equations_parabolic) + flux_viscous_node_y = flux(u_node, (gradients_1_node, gradients_2_node), 2, + equations_parabolic) + set_node_vars!(flux_viscous_x, flux_viscous_node_x, equations_parabolic, dg, + i, j, element) + set_node_vars!(flux_viscous_y, flux_viscous_node_y, equations_parabolic, dg, + i, j, element) + end + end +end + +function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 4}}, + gradients::Vector{Array{uEltype, 4}}, u_transformed, + mesh::TreeMesh{2}, + equations_parabolic::AbstractEquationsParabolic, dg::DG, cache, cache_parabolic) where {uEltype <: Real} gradients_x, gradients_y = gradients flux_viscous_x, flux_viscous_y = flux_viscous # output arrays diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index efade560303..1f625b74b3c 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -336,9 +336,49 @@ function prolong2boundaries!(cache_parabolic, flux_viscous::Vector{Array{uEltype return nothing end -function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 5}}, gradients, u_transformed, +function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, mesh::Union{TreeMesh{3}, P4estMesh{3}}, equations_parabolic::AbstractEquationsParabolic, + dg::DG, cache, cache_parabolic) + gradients_x, gradients_y, gradients_z = gradients + flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous # output arrays + + @threaded for element in eachelement(dg, cache) + for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) + # Get solution and gradients + u_node = get_node_vars(u_transformed, equations_parabolic, dg, i, j, k, + element) + gradients_1_node = get_node_vars(gradients_x, equations_parabolic, dg, i, j, + k, element) + gradients_2_node = get_node_vars(gradients_y, equations_parabolic, dg, i, j, + k, element) + gradients_3_node = get_node_vars(gradients_z, equations_parabolic, dg, i, j, + k, element) + + # Calculate viscous flux and store each component for later use + flux_viscous_node_x = flux(u_node, + (gradients_1_node, gradients_2_node, + gradients_3_node), 1, equations_parabolic) + flux_viscous_node_y = flux(u_node, + (gradients_1_node, gradients_2_node, + gradients_3_node), 2, equations_parabolic) + flux_viscous_node_z = flux(u_node, + (gradients_1_node, gradients_2_node, + gradients_3_node), 3, equations_parabolic) + set_node_vars!(flux_viscous_x, flux_viscous_node_x, equations_parabolic, dg, + i, j, k, element) + set_node_vars!(flux_viscous_y, flux_viscous_node_y, equations_parabolic, dg, + i, j, k, element) + set_node_vars!(flux_viscous_z, flux_viscous_node_z, equations_parabolic, dg, + i, j, k, element) + end + end +end + +function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 5}}, + gradients::Vector{Array{uEltype, 5}}, u_transformed, + mesh::TreeMesh{3}, + equations_parabolic::AbstractEquationsParabolic, dg::DG, cache, cache_parabolic) where {uEltype <: Real} gradients_x, gradients_y, gradients_z = gradients flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous # output arrays From 4c354301d6d6467f8fe1451c4b2a3f1bebd813b0 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 13:28:03 +0200 Subject: [PATCH 031/138] Add tests --- .../elixir_navierstokes_shearlayer_amr.jl | 10 +- .../elixir_advection_diffusion_amr.jl | 94 +++++++++++++++++++ test/test_parabolic_2d.jl | 4 +- test/test_parabolic_3d.jl | 7 ++ 4 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl index 1da63588bcf..86a278f2c60 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl @@ -13,6 +13,14 @@ equations = CompressibleEulerEquations2D(1.4) equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number()) +""" +A compressible version of the double shear layer initial condition. Adapted from +Brown and Minion (1995). + +- David L. Brown and Michael L. Minion (1995) + Performance of Under-resolved Two-Dimensional Incompressible Flow Simulations. + [DOI: 10.1006/jcph.1995.1205](https://doi.org/10.1006/jcph.1995.1205) +""" function initial_condition_shear_layer(x, t, equations::CompressibleEulerEquations2D) # Shear layer parameters k = 80 @@ -37,7 +45,7 @@ solver = DGSEM(polydeg=3, surface_flux=flux_hllc, coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, + initial_refinement_level=4, n_cells_max=100_000) diff --git a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl new file mode 100644 index 00000000000..08f678138ed --- /dev/null +++ b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl @@ -0,0 +1,94 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection equation + +advection_velocity = (0.2, -0.7, 0.5) +equations = LinearScalarAdvectionEquation3D(advection_velocity) + +diffusivity() = 5.0e-4 +equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) + +initial_condition = initial_condition_gauss +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) + +coordinates_min = (-1.0, -1.0, -1.0) +coordinates_max = ( 1.0, 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=4, + n_cells_max=80_000) + +# Define initial condition +function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation3D) + # Store translated coordinate for easy use of exact solution + x_trans = x - equation.advection_velocity * t + + nu = diffusivity() + c = 1.0 + A = 0.5 + L = 2 + f = 1/L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) + return SVector(scalar) +end +initial_condition = initial_condition_diffusive_convergence_test + +# define periodic boundary conditions everywhere +boundary_conditions = boundary_condition_periodic +boundary_conditions_parabolic = boundary_condition_periodic + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions=(boundary_conditions, + boundary_conditions_parabolic)) + + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.1) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, + extra_analysis_integrals=(entropy,)) + +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), + base_level=3, + med_level=4, med_threshold=1.2, + max_level=5, max_threshold=1.45) +amr_callback = AMRCallback(semi, amr_controller, + interval=5, + adapt_initial_condition=true, + adapt_initial_condition_only_refine=true) + +stepsize_callback = StepsizeCallback(cfl=1.0) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + amr_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); +summary_callback() # print the timer summary \ No newline at end of file diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index a6cfd089c47..24de7f13679 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -251,8 +251,8 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "TreeMesh2D: elixir_navierstokes_shearlayer_amr.jl" begin @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_shearlayer_amr.jl"), - l2 = [0.005352707453147317, 0.4077270907626271, 0.43758381263181434, 1.1758133763041454], - linf = [0.034784713829601244, 1.1650897299747531, 1.484016014155391, 8.71087741820071] + l2 = [0.005353306916161318, 0.4077336028873465, 0.43756829240941464, 1.1759497303478266], + linf = [0.034791663521213545, 1.1650592394066237, 1.4841924833734612, 8.713274087336629] ) end diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index ded052fb9d3..05a173ec5d2 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -157,6 +157,13 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [0.0006696415247340326, 0.03442565722527785, 0.03442565722577423, 0.06295407168705314, 0.032857472756916195] ) end + + @trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_amr.jl"), + l2 = [0.00017912610056132068], + linf = [0.0007821751390747478] + ) + end end # Clean up afterwards: delete Trixi.jl output directory From 21d29f84d5332a971ee8e4f616ae0883e43ff0b6 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 13:30:19 +0200 Subject: [PATCH 032/138] remove plots --- .../tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl index 86a278f2c60..7661cc5b44b 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl @@ -1,5 +1,5 @@ -using OrdinaryDiffEq, Plots +using OrdinaryDiffEq using Trixi ############################################################################### @@ -86,8 +86,4 @@ callbacks = CallbackSet(summary_callback, time_int_tol = 1e-7 sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary - -pd = PlotData2D(sol) -Plots.plot(pd["v1"]) -Plots.plot(getmesh(pd)) \ No newline at end of file +summary_callback() # print the timer summary \ No newline at end of file From 29bd2132c4b38e3208d9962893a80f65eb2dcb10 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 13:31:24 +0200 Subject: [PATCH 033/138] Format --- src/callbacks_step/amr_dg2d.jl | 10 ++- src/equations/compressible_euler_1d.jl | 2 +- src/equations/compressible_euler_2d.jl | 4 +- src/equations/compressible_euler_3d.jl | 6 +- .../dgsem_tree/container_viscous_1d.jl | 4 +- .../dgsem_tree/container_viscous_2d.jl | 55 ++++++------ .../dgsem_tree/container_viscous_3d.jl | 86 ++++++++++--------- src/solvers/dgsem_tree/containers_viscous.jl | 2 +- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 2 +- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 2 +- 10 files changed, 90 insertions(+), 83 deletions(-) diff --git a/src/callbacks_step/amr_dg2d.jl b/src/callbacks_step/amr_dg2d.jl index 5b36f22c82e..6395a9f348f 100644 --- a/src/callbacks_step/amr_dg2d.jl +++ b/src/callbacks_step/amr_dg2d.jl @@ -151,8 +151,9 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, TreeMe # Sanity check if mesh isa TreeMesh && isperiodic(mesh.tree) && nmortars(cache.mortars) == 0 && - !mpi_isparallel() - @assert ninterfaces(cache_parabolic.interfaces)==ndims(mesh) * nelements(dg, cache_parabolic) ("For $(ndims(mesh))D and periodic domains and conforming elements, the number of interfaces must be $(ndims(mesh)) times the number of elements") + !mpi_isparallel() + @assert ninterfaces(cache_parabolic.interfaces)==ndims(mesh) * + nelements(dg, cache_parabolic) ("For $(ndims(mesh))D and periodic domains and conforming elements, the number of interfaces must be $(ndims(mesh)) times the number of elements") end return nothing @@ -312,8 +313,9 @@ function coarsen!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, TreeM # Sanity check if mesh isa TreeMesh && isperiodic(mesh.tree) && nmortars(cache.mortars) == 0 && - !mpi_isparallel() - @assert ninterfaces(cache_parabolic.interfaces)==ndims(mesh) * nelements(dg, cache_parabolic) ("For $(ndims(mesh))D and periodic domains and conforming elements, the number of interfaces must be $(ndims(mesh)) times the number of elements") + !mpi_isparallel() + @assert ninterfaces(cache_parabolic.interfaces)==ndims(mesh) * + nelements(dg, cache_parabolic) ("For $(ndims(mesh))D and periodic domains and conforming elements, the number of interfaces must be $(ndims(mesh)) times the number of elements") end return nothing diff --git a/src/equations/compressible_euler_1d.jl b/src/equations/compressible_euler_1d.jl index 6d9ad996973..cef5a268c82 100644 --- a/src/equations/compressible_euler_1d.jl +++ b/src/equations/compressible_euler_1d.jl @@ -975,7 +975,7 @@ end @inline function v1(u, equations::CompressibleEulerEquations1D) rho, rho_v1, _ = u - return rho_v1/rho + return rho_v1 / rho end # Calculate thermodynamic entropy for a conservative state `cons` diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index ccc208d911d..d61bba8e6a6 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1430,12 +1430,12 @@ end @inline function v1(u, equations::CompressibleEulerEquations2D) rho, rho_v1, _, _ = u - return rho_v1/rho + return rho_v1 / rho end @inline function v2(u, equations::CompressibleEulerEquations2D) rho, _, rho_v2, _ = u - return rho_v2/rho + return rho_v2 / rho end # Calculates the entropy flux in direction "orientation" and the entropy variables for a state cons diff --git a/src/equations/compressible_euler_3d.jl b/src/equations/compressible_euler_3d.jl index 357851a18d7..af746c37025 100644 --- a/src/equations/compressible_euler_3d.jl +++ b/src/equations/compressible_euler_3d.jl @@ -1516,17 +1516,17 @@ end @inline function v1(u, equations::CompressibleEulerEquations3D) rho, rho_v1, _, _, _ = u - return rho_v1/rho + return rho_v1 / rho end @inline function v2(u, equations::CompressibleEulerEquations3D) rho, _, rho_v2, _, _ = u - return rho_v2/rho + return rho_v2 / rho end @inline function v3(u, equations::CompressibleEulerEquations3D) rho, _, _, rho_v3, _ = u - return rho_v3/rho + return rho_v3 / rho end # Calculate thermodynamic entropy for a conservative state `u` diff --git a/src/solvers/dgsem_tree/container_viscous_1d.jl b/src/solvers/dgsem_tree/container_viscous_1d.jl index 3f9943aea1c..71c68dfc6df 100644 --- a/src/solvers/dgsem_tree/container_viscous_1d.jl +++ b/src/solvers/dgsem_tree/container_viscous_1d.jl @@ -20,8 +20,8 @@ mutable struct ViscousContainer1D{uEltype <: Real} end function init_viscous_container_1d(n_vars::Integer, n_nodes::Integer, - n_elements::Integer, - ::Type{uEltype}) where {uEltype <: Real} + n_elements::Integer, + ::Type{uEltype}) where {uEltype <: Real} return ViscousContainer1D{uEltype}(n_vars, n_nodes, n_elements) end diff --git a/src/solvers/dgsem_tree/container_viscous_2d.jl b/src/solvers/dgsem_tree/container_viscous_2d.jl index 80554365aa5..eb62178b66d 100644 --- a/src/solvers/dgsem_tree/container_viscous_2d.jl +++ b/src/solvers/dgsem_tree/container_viscous_2d.jl @@ -9,14 +9,15 @@ mutable struct ViscousContainer2D{uEltype <: Real} _gradients::Vector{Vector{uEltype}} _flux_viscous::Vector{Vector{uEltype}} - function ViscousContainer2D{uEltype}(n_vars::Integer, n_nodes::Integer, n_elements::Integer) where {uEltype <: Real} + function ViscousContainer2D{uEltype}(n_vars::Integer, n_nodes::Integer, + n_elements::Integer) where {uEltype <: Real} new(Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements), [Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements) for _ in 1:2], [Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements) for _ in 1:2], Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements), [Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements) for _ in 1:2], [Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements) for _ in 1:2]) - end + end end function init_viscous_container_2d(n_vars::Integer, n_nodes::Integer, @@ -31,31 +32,31 @@ end # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. function Base.resize!(viscous_container::ViscousContainer2D, equations, dg, cache) - capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nelements(dg, cache) - resize!(viscous_container._u_transformed, capacity) - for dim in 1:2 - resize!(viscous_container._gradients[dim], capacity) - resize!(viscous_container._flux_viscous[dim], capacity) - end + capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nelements(dg, cache) + resize!(viscous_container._u_transformed, capacity) + for dim in 1:2 + resize!(viscous_container._gradients[dim], capacity) + resize!(viscous_container._flux_viscous[dim], capacity) + end - viscous_container.u_transformed = unsafe_wrap(Array, - pointer(viscous_container._u_transformed), - (nvariables(equations), - nnodes(dg), nnodes(dg), - nelements(dg, cache))) + viscous_container.u_transformed = unsafe_wrap(Array, + pointer(viscous_container._u_transformed), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) - for dim in 1:2 - viscous_container.gradients[dim] = unsafe_wrap(Array, - pointer(viscous_container._gradients[dim]), - (nvariables(equations), - nnodes(dg), nnodes(dg), - nelements(dg, cache))) + for dim in 1:2 + viscous_container.gradients[dim] = unsafe_wrap(Array, + pointer(viscous_container._gradients[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) - viscous_container.flux_viscous[dim] = unsafe_wrap(Array, - pointer(viscous_container._flux_viscous[dim]), - (nvariables(equations), - nnodes(dg), nnodes(dg), - nelements(dg, cache))) - end - return nothing -end \ No newline at end of file + viscous_container.flux_viscous[dim] = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) + end + return nothing +end diff --git a/src/solvers/dgsem_tree/container_viscous_3d.jl b/src/solvers/dgsem_tree/container_viscous_3d.jl index 30fa864825e..0b44cc6cc18 100644 --- a/src/solvers/dgsem_tree/container_viscous_3d.jl +++ b/src/solvers/dgsem_tree/container_viscous_3d.jl @@ -1,25 +1,27 @@ mutable struct ViscousContainer3D{uEltype <: Real} - u_transformed::Array{uEltype, 5} - # IDEA: Use SVector for fixed sized vectors? - gradients::Vector{Array{uEltype, 5}} - flux_viscous::Vector{Array{uEltype, 5}} + u_transformed::Array{uEltype, 5} + # IDEA: Use SVector for fixed sized vectors? + gradients::Vector{Array{uEltype, 5}} + flux_viscous::Vector{Array{uEltype, 5}} - # internal `resize!`able storage - _u_transformed::Vector{uEltype} - _gradients::Vector{Vector{uEltype}} - _flux_viscous::Vector{Vector{uEltype}} + # internal `resize!`able storage + _u_transformed::Vector{uEltype} + _gradients::Vector{Vector{uEltype}} + _flux_viscous::Vector{Vector{uEltype}} - function ViscousContainer3D{uEltype}(n_vars::Integer, n_nodes::Integer, n_elements::Integer) where {uEltype <: Real} - new(Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements), - [Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) for _ in 1:3], - [Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) for _ in 1:3], - Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), - [Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements) for _ in 1:3], - [Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements) for _ in 1:3]) - end + function ViscousContainer3D{uEltype}(n_vars::Integer, n_nodes::Integer, + n_elements::Integer) where {uEltype <: Real} + new(Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements), + [Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) + for _ in 1:3], + [Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) + for _ in 1:3], + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + [Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements) for _ in 1:3], + [Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements) for _ in 1:3]) + end end - function init_viscous_container_3d(n_vars::Integer, n_nodes::Integer, n_elements::Integer, ::Type{uEltype}) where {uEltype <: Real} @@ -32,31 +34,33 @@ end # `unsafe_wrap`ping multi-dimensional `Array`s around the # internal storage. function Base.resize!(viscous_container::ViscousContainer3D, equations, dg, cache) - capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nnodes(dg) * nelements(dg, cache) - resize!(viscous_container._u_transformed, capacity) - for dim in 1:3 - resize!(viscous_container._gradients[dim], capacity) - resize!(viscous_container._flux_viscous[dim], capacity) - end - - viscous_container.u_transformed = unsafe_wrap(Array, - pointer(viscous_container._u_transformed), - (nvariables(equations), - nnodes(dg), nnodes(dg), nnodes(dg), - nelements(dg, cache))) + capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nnodes(dg) * + nelements(dg, cache) + resize!(viscous_container._u_transformed, capacity) + for dim in 1:3 + resize!(viscous_container._gradients[dim], capacity) + resize!(viscous_container._flux_viscous[dim], capacity) + end - for dim in 1:3 - viscous_container.gradients[dim] = unsafe_wrap(Array, - pointer(viscous_container._gradients[dim]), - (nvariables(equations), - nnodes(dg), nnodes(dg), nnodes(dg), - nelements(dg, cache))) + viscous_container.u_transformed = unsafe_wrap(Array, + pointer(viscous_container._u_transformed), + (nvariables(equations), + nnodes(dg), nnodes(dg), nnodes(dg), + nelements(dg, cache))) - viscous_container.flux_viscous[dim] = unsafe_wrap(Array, - pointer(viscous_container._flux_viscous[dim]), - (nvariables(equations), + for dim in 1:3 + viscous_container.gradients[dim] = unsafe_wrap(Array, + pointer(viscous_container._gradients[dim]), + (nvariables(equations), nnodes(dg), nnodes(dg), nnodes(dg), nelements(dg, cache))) - end - return nothing -end \ No newline at end of file + + viscous_container.flux_viscous[dim] = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nnodes(dg), + nelements(dg, cache))) + end + return nothing +end diff --git a/src/solvers/dgsem_tree/containers_viscous.jl b/src/solvers/dgsem_tree/containers_viscous.jl index 2a8989db55c..444f2cb7303 100644 --- a/src/solvers/dgsem_tree/containers_viscous.jl +++ b/src/solvers/dgsem_tree/containers_viscous.jl @@ -1,4 +1,4 @@ # Dimension-specific implementations include("container_viscous_1d.jl") include("container_viscous_2d.jl") -include("container_viscous_3d.jl") \ No newline at end of file +include("container_viscous_3d.jl") diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 3d3e42d1a40..582b624a199 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -318,7 +318,7 @@ function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, end end -function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 4}}, +function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 4}}, gradients::Vector{Array{uEltype, 4}}, u_transformed, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index 1f625b74b3c..efed90d83aa 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -375,7 +375,7 @@ function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, end end -function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 5}}, +function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 5}}, gradients::Vector{Array{uEltype, 5}}, u_transformed, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, From cb3eac8e2c5371c345485265de7ab539af41c402 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 14:22:25 +0200 Subject: [PATCH 034/138] remove redundant line --- examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl index 08f678138ed..ded984bff2d 100644 --- a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl +++ b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl @@ -11,7 +11,6 @@ equations = LinearScalarAdvectionEquation3D(advection_velocity) diffusivity() = 5.0e-4 equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) -initial_condition = initial_condition_gauss solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) From 7e68d945c2ec64fa27cce7df2c85b408b988299b Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 11 Sep 2023 15:13:50 +0200 Subject: [PATCH 035/138] platform independent tests --- .../elixir_navierstokes_shearlayer_amr.jl | 13 ++++++++----- test/test_parabolic_2d.jl | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl index 7661cc5b44b..82c85aa16ba 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl @@ -60,7 +60,7 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_interval = 1000 +analysis_interval = 2000 analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval,) @@ -75,15 +75,18 @@ amr_callback = AMRCallback(semi, amr_controller, adapt_initial_condition=true, adapt_initial_condition_only_refine=true) +stepsize_callback = StepsizeCallback(cfl=1.3) + callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, - amr_callback) + amr_callback, + stepsize_callback) ############################################################################### # run the simulation -time_int_tol = 1e-7 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +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); summary_callback() # print the timer summary \ No newline at end of file diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index 24de7f13679..97447c0f438 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -251,8 +251,8 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "TreeMesh2D: elixir_navierstokes_shearlayer_amr.jl" begin @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_shearlayer_amr.jl"), - l2 = [0.005353306916161318, 0.4077336028873465, 0.43756829240941464, 1.1759497303478266], - linf = [0.034791663521213545, 1.1650592394066237, 1.4841924833734612, 8.713274087336629] + l2 = [0.00526017743452336, 0.4130430692895672, 0.4310996183791349, 1.1544344171604635], + linf = [0.03492185879198495, 1.392635891671335, 1.357551616406459, 8.713760873018146] ) end From 5c20c4fb0a7da37a4178ac08dad2243ee0f60eef Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 12 Sep 2023 15:44:41 +0200 Subject: [PATCH 036/138] No need for different flux_viscous comps after adding container_viscous to p4est --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 32 +----------------- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 41 +---------------------- 2 files changed, 2 insertions(+), 71 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 582b624a199..42d992ab52e 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -288,39 +288,9 @@ function prolong2boundaries!(cache_parabolic, flux_viscous::Vector{Array{uEltype return nothing end -function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, - mesh::Union{TreeMesh{2}, P4estMesh{2}}, - equations_parabolic::AbstractEquationsParabolic, - dg::DG, cache, cache_parabolic) - gradients_x, gradients_y = gradients - flux_viscous_x, flux_viscous_y = flux_viscous # output arrays - - @threaded for element in eachelement(dg, cache) - for j in eachnode(dg), i in eachnode(dg) - # Get solution and gradients - u_node = get_node_vars(u_transformed, equations_parabolic, dg, i, j, - element) - gradients_1_node = get_node_vars(gradients_x, equations_parabolic, dg, i, j, - element) - gradients_2_node = get_node_vars(gradients_y, equations_parabolic, dg, i, j, - element) - - # Calculate viscous flux and store each component for later use - flux_viscous_node_x = flux(u_node, (gradients_1_node, gradients_2_node), 1, - equations_parabolic) - flux_viscous_node_y = flux(u_node, (gradients_1_node, gradients_2_node), 2, - equations_parabolic) - set_node_vars!(flux_viscous_x, flux_viscous_node_x, equations_parabolic, dg, - i, j, element) - set_node_vars!(flux_viscous_y, flux_viscous_node_y, equations_parabolic, dg, - i, j, element) - end - end -end - function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 4}}, gradients::Vector{Array{uEltype, 4}}, u_transformed, - mesh::TreeMesh{2}, + mesh::Union{TreeMesh{2}, P4estMesh{2}}, equations_parabolic::AbstractEquationsParabolic, dg::DG, cache, cache_parabolic) where {uEltype <: Real} gradients_x, gradients_y = gradients diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index efed90d83aa..5cb2448a1bd 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -336,48 +336,9 @@ function prolong2boundaries!(cache_parabolic, flux_viscous::Vector{Array{uEltype return nothing end -function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, - mesh::Union{TreeMesh{3}, P4estMesh{3}}, - equations_parabolic::AbstractEquationsParabolic, - dg::DG, cache, cache_parabolic) - gradients_x, gradients_y, gradients_z = gradients - flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous # output arrays - - @threaded for element in eachelement(dg, cache) - for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - # Get solution and gradients - u_node = get_node_vars(u_transformed, equations_parabolic, dg, i, j, k, - element) - gradients_1_node = get_node_vars(gradients_x, equations_parabolic, dg, i, j, - k, element) - gradients_2_node = get_node_vars(gradients_y, equations_parabolic, dg, i, j, - k, element) - gradients_3_node = get_node_vars(gradients_z, equations_parabolic, dg, i, j, - k, element) - - # Calculate viscous flux and store each component for later use - flux_viscous_node_x = flux(u_node, - (gradients_1_node, gradients_2_node, - gradients_3_node), 1, equations_parabolic) - flux_viscous_node_y = flux(u_node, - (gradients_1_node, gradients_2_node, - gradients_3_node), 2, equations_parabolic) - flux_viscous_node_z = flux(u_node, - (gradients_1_node, gradients_2_node, - gradients_3_node), 3, equations_parabolic) - set_node_vars!(flux_viscous_x, flux_viscous_node_x, equations_parabolic, dg, - i, j, k, element) - set_node_vars!(flux_viscous_y, flux_viscous_node_y, equations_parabolic, dg, - i, j, k, element) - set_node_vars!(flux_viscous_z, flux_viscous_node_z, equations_parabolic, dg, - i, j, k, element) - end - end -end - function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 5}}, gradients::Vector{Array{uEltype, 5}}, u_transformed, - mesh::TreeMesh{3}, + mesh::Union{TreeMesh{3}, P4estMesh{3}}, equations_parabolic::AbstractEquationsParabolic, dg::DG, cache, cache_parabolic) where {uEltype <: Real} gradients_x, gradients_y, gradients_z = gradients From 21ccff481c8918f3732791ec4fddeb1e797ab660 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 12 Sep 2023 16:23:59 +0200 Subject: [PATCH 037/138] Laplace 3d --- .../elixir_advection_diffusion_amr.jl | 2 +- src/Trixi.jl | 2 +- src/equations/equations_parabolic.jl | 1 + src/equations/laplace_diffusion_3d.jl | 72 +++++++++++++++++++ test/test_parabolic_3d.jl | 4 +- 5 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/equations/laplace_diffusion_3d.jl diff --git a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl index ded984bff2d..4f498af5421 100644 --- a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl +++ b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl @@ -9,7 +9,7 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) diffusivity() = 5.0e-4 -equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) +equations_parabolic = LaplaceDiffusion3D(diffusivity(), equations) solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) diff --git a/src/Trixi.jl b/src/Trixi.jl index b95ede67163..57e756031c2 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -151,7 +151,7 @@ export AcousticPerturbationEquations2D, ShallowWaterTwoLayerEquations1D, ShallowWaterTwoLayerEquations2D, LinearizedEulerEquations2D -export LaplaceDiffusion1D, LaplaceDiffusion2D, +export LaplaceDiffusion1D, LaplaceDiffusion2D, LaplaceDiffusion3D, CompressibleNavierStokesDiffusion1D, CompressibleNavierStokesDiffusion2D, CompressibleNavierStokesDiffusion3D diff --git a/src/equations/equations_parabolic.jl b/src/equations/equations_parabolic.jl index 66214025044..47a76174cb1 100644 --- a/src/equations/equations_parabolic.jl +++ b/src/equations/equations_parabolic.jl @@ -7,6 +7,7 @@ abstract type AbstractLaplaceDiffusion{NDIMS, NVARS} <: AbstractEquationsParabolic{NDIMS, NVARS} end include("laplace_diffusion_1d.jl") include("laplace_diffusion_2d.jl") +include("laplace_diffusion_3d.jl") # Compressible Navier-Stokes equations abstract type AbstractCompressibleNavierStokesDiffusion{NDIMS, NVARS} <: diff --git a/src/equations/laplace_diffusion_3d.jl b/src/equations/laplace_diffusion_3d.jl new file mode 100644 index 00000000000..3988ce7144b --- /dev/null +++ b/src/equations/laplace_diffusion_3d.jl @@ -0,0 +1,72 @@ +@doc raw""" + LaplaceDiffusion3D(diffusivity, equations) + +`LaplaceDiffusion3D` represents a scalar diffusion term ``\nabla \cdot (\kappa\nabla u))`` +with diffusivity ``\kappa`` applied to each solution component defined by `equations`. +""" +struct LaplaceDiffusion3D{E, N, T} <: AbstractLaplaceDiffusion{3, N} + diffusivity::T + equations_hyperbolic::E +end + +function LaplaceDiffusion3D(diffusivity, equations_hyperbolic) + LaplaceDiffusion3D{typeof(equations_hyperbolic), nvariables(equations_hyperbolic), + typeof(diffusivity)}(diffusivity, equations_hyperbolic) +end + +function varnames(variable_mapping, equations_parabolic::LaplaceDiffusion3D) + varnames(variable_mapping, equations_parabolic.equations_hyperbolic) +end + +# no orientation specified since the flux is vector-valued +function flux(u, gradients, orientation::Integer, equations_parabolic::LaplaceDiffusion3D) + dudx, dudy, dudz = gradients + if orientation == 1 + return SVector(equations_parabolic.diffusivity * dudx) + elseif orientation == 2 + return SVector(equations_parabolic.diffusivity * dudy) + else # if orientation == 3 + return SVector(equations_parabolic.diffusivity * dudz) + end +end + +# TODO: parabolic; should this remain in the equations file, be moved to solvers, or live in the elixir? +# The penalization depends on the solver, but also depends explicitly on physical parameters, +# and would probably need to be specialized for every different equation. +function penalty(u_outer, u_inner, inv_h, equations_parabolic::LaplaceDiffusion3D, + dg::ViscousFormulationLocalDG) + return dg.penalty_parameter * (u_outer - u_inner) * equations_parabolic.diffusivity +end + +# Dirichlet-type boundary condition for use with a parabolic solver in weak form +@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, + normal::AbstractVector, + x, t, + operator_type::Gradient, + equations_parabolic::LaplaceDiffusion3D) + return boundary_condition.boundary_value_function(x, t, equations_parabolic) +end + +@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, + normal::AbstractVector, + x, t, + operator_type::Divergence, + equations_parabolic::LaplaceDiffusion3D) + return flux_inner +end + +@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, + normal::AbstractVector, + x, t, + operator_type::Divergence, + equations_parabolic::LaplaceDiffusion3D) + return boundary_condition.boundary_normal_flux_function(x, t, equations_parabolic) +end + +@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, + normal::AbstractVector, + x, t, + operator_type::Gradient, + equations_parabolic::LaplaceDiffusion3D) + return flux_inner +end diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 05a173ec5d2..95cb6052383 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -160,8 +160,8 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_amr.jl"), - l2 = [0.00017912610056132068], - linf = [0.0007821751390747478] + l2 = [0.0001791112986201992], + linf = [0.0007775704284449514] ) end end From 8df117b00be1a71c89ab9cdcd5c2493370f97ec0 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Wed, 20 Sep 2023 11:45:30 +0200 Subject: [PATCH 038/138] Longer times to allow converage to hit coarsen! --- examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl | 2 +- test/test_parabolic_3d.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl index 4f498af5421..0fab685b642 100644 --- a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl +++ b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl @@ -50,7 +50,7 @@ semi = SemidiscretizationHyperbolicParabolic(mesh, ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.1) +tspan = (0.0, 0.2) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 923511860a5..ef91550436d 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -160,8 +160,8 @@ isdir(outdir) && rm(outdir, recursive=true) @trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_amr.jl"), - l2 = [0.0001791112986201992], - linf = [0.0007775704284449514] + l2 = [0.000355780485397024], + linf = [0.0010810770271614256] ) end end From cdaa865da7ad10de528e53ce19956b6f95eb908e Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Wed, 20 Sep 2023 11:57:51 +0200 Subject: [PATCH 039/138] Increase testing of Laplace 3D --- .../elixir_advection_diffusion_nonperiodic.jl | 91 +++++++++++++++++++ test/test_parabolic_3d.jl | 7 ++ 2 files changed, 98 insertions(+) create mode 100644 examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl diff --git a/examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl b/examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl new file mode 100644 index 00000000000..5dc6e6338a7 --- /dev/null +++ b/examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl @@ -0,0 +1,91 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection-diffusion equation + +diffusivity() = 5.0e-2 +advection_velocity = (1.0, 0.0, 0.0) +equations = LinearScalarAdvectionEquation3D(advection_velocity) +equations_parabolic = LaplaceDiffusion3D(diffusivity(), equations) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) + +coordinates_min = (-1.0, -0.5, -0.25) # minimum coordinates (min(x), min(y), min(z)) +coordinates_max = ( 0.0, 0.5, 0.25) # maximum coordinates (max(x), max(y), max(z)) + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level=3, + periodicity=false, + n_cells_max=30_000) # set maximum capacity of tree data structure + +# Example setup taken from +# - Truman Ellis, Jesse Chan, and Leszek Demkowicz (2016). +# Robust DPG methods for transient convection-diffusion. +# In: Building bridges: connections and challenges in modern approaches +# to numerical partial differential equations. +# [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). +function initial_condition_eriksson_johnson(x, t, equations) + l = 4 + epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) +end +initial_condition = initial_condition_eriksson_johnson + +boundary_conditions = (; x_neg = BoundaryConditionDirichlet(initial_condition), + y_neg = BoundaryConditionDirichlet(initial_condition), + z_neg = boundary_condition_do_nothing, + y_pos = BoundaryConditionDirichlet(initial_condition), + x_pos = boundary_condition_do_nothing, + z_pos = boundary_condition_do_nothing) + +boundary_conditions_parabolic = BoundaryConditionDirichlet(initial_condition) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions=(boundary_conditions, + boundary_conditions_parabolic)) + + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 0.5) +ode = semidiscretize(semi, tspan); + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) + + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +time_int_tol = 1.0e-11 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) + +# Print the timer summary +summary_callback() diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index ef91550436d..3014ee9c6cf 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -164,6 +164,13 @@ isdir(outdir) && rm(outdir, recursive=true) linf = [0.0010810770271614256] ) end + + @trixi_testset "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_nonperiodic.jl"), + l2 = [0.0009808996243280868], + linf = [0.01732621559135459] + ) + end end # Clean up afterwards: delete Trixi.jl output directory From 4699a1003fcb40d6b756be38a0259c6951d8225d Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Wed, 20 Sep 2023 14:14:24 +0200 Subject: [PATCH 040/138] Add tests for velocities --- test/test_unit.jl | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/test_unit.jl b/test/test_unit.jl index 5c5291c2430..30bc9b6d97b 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -528,6 +528,28 @@ isdir(outdir) && rm(outdir, recursive=true) end end + @timed_testset "Euler test velocity functions" begin + rho, v1, v2, v3, p = 1.0, 0.1, 0.2, 0.3, 2.0 + + let equations = CompressibleEulerEquations1D(1.4) + cons_vars = prim2cons(SVector(rho,v1,p),equations) + @test v1 ≈ Trixi.v1(cons_vars, equations) + end + + let equations = CompressibleEulerEquations2D(1.4) + cons_vars = prim2cons(SVector(rho,v1,v2,p),equations) + @test v1 ≈ Trixi.v1(cons_vars, equations) + @test v2 ≈ Trixi.v2(cons_vars, equations) + end + + let equations = CompressibleEulerEquations3D(1.4) + cons_vars = prim2cons(SVector(rho,v1,v2,v3,p),equations) + @test v1 ≈ Trixi.v1(cons_vars, equations) + @test v2 ≈ Trixi.v2(cons_vars, equations) + @test v3 ≈ Trixi.v3(cons_vars, equations) + end + end + @timed_testset "Shallow water conversion between conservative/entropy variables" begin H, v1, v2, b = 3.5, 0.25, 0.1, 0.4 From 389d89c7ec3624c4a306dc26213c6e49c1d1d200 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Thu, 5 Oct 2023 08:55:37 +0200 Subject: [PATCH 041/138] remove comment --- src/solvers/dgsem_tree/container_viscous_2d.jl | 1 - src/solvers/dgsem_tree/container_viscous_3d.jl | 1 - 2 files changed, 2 deletions(-) diff --git a/src/solvers/dgsem_tree/container_viscous_2d.jl b/src/solvers/dgsem_tree/container_viscous_2d.jl index eb62178b66d..fd28e12a99a 100644 --- a/src/solvers/dgsem_tree/container_viscous_2d.jl +++ b/src/solvers/dgsem_tree/container_viscous_2d.jl @@ -1,6 +1,5 @@ mutable struct ViscousContainer2D{uEltype <: Real} u_transformed::Array{uEltype, 4} - # IDEA: Use SVector for fixed sized vectors? gradients::Vector{Array{uEltype, 4}} flux_viscous::Vector{Array{uEltype, 4}} diff --git a/src/solvers/dgsem_tree/container_viscous_3d.jl b/src/solvers/dgsem_tree/container_viscous_3d.jl index 0b44cc6cc18..6eec0c61279 100644 --- a/src/solvers/dgsem_tree/container_viscous_3d.jl +++ b/src/solvers/dgsem_tree/container_viscous_3d.jl @@ -1,6 +1,5 @@ mutable struct ViscousContainer3D{uEltype <: Real} u_transformed::Array{uEltype, 5} - # IDEA: Use SVector for fixed sized vectors? gradients::Vector{Array{uEltype, 5}} flux_viscous::Vector{Array{uEltype, 5}} From f86121fef03fe02aa46bc47a2713ee4a4274eeb1 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Fri, 6 Oct 2023 14:12:56 -0400 Subject: [PATCH 042/138] add elixir for amr testing --- ...elixir_advection_diffusion_periodic_amr.jl | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl new file mode 100644 index 00000000000..16ba3b45499 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl @@ -0,0 +1,94 @@ +using OrdinaryDiffEq, Plots +using Trixi + +############################################################################### +# semidiscretization of the linear advection-diffusion equation + +diffusivity() = 5.0e-2 +advection_velocity = (1.0, 1.0) +equations = LinearScalarAdvectionEquation2D(advection_velocity) +equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) + +function x_trans_periodic(x, domain_length=SVector(2 * pi), center=SVector(0.0)) + x_normalized = x .- center + x_shifted = x_normalized .% domain_length + x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* domain_length + return center + x_shifted + x_offset +end + +# Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") +function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) + # Store translated coordinate for easy use of exact solution + # Assumes that advection_velocity[2] = 0 (effectively that we are solving a 1D equation) + x_trans = x_trans_periodic(x[2] - equation.advection_velocity[2] * t) + + nu = diffusivity() + c = 0.0 + A = 1.0 + omega = 1.0 + scalar = c + A * sin(omega * sum(x_trans)) * exp(-nu * omega^2 * t) + return SVector(scalar) +end +initial_condition = initial_condition_diffusive_convergence_test + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) + +coordinates_min = (-pi, -pi) # minimum coordinates (min(x), min(y)) +coordinates_max = ( pi, pi) # maximum coordinates (max(x), max(y)) + +trees_per_dimension = (4, 4) +mesh = P4estMesh(trees_per_dimension, + polydeg=3, initial_refinement_level=2, + coordinates_min=coordinates_min, coordinates_max=coordinates_max, + periodicity=true) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver) + + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 1e-2) +ode = semidiscretize(semi, tspan); + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), + base_level=2, + med_level=3, med_threshold=0.5, + max_level=4, max_threshold=0.75) +amr_callback = AMRCallback(semi, amr_controller, + interval=5) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +#callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) + + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +time_int_tol = 1.0e-11 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) + +# Print the timer summary +summary_callback() +plot(sol) +pd = PlotData2D(sol) +plot!(getmesh(pd)) \ No newline at end of file From 27afc2d436c7d1dfb808c0980eded99d9e62e00f Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Fri, 6 Oct 2023 14:13:52 -0400 Subject: [PATCH 043/138] adding commented out mortar routines in 2D --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index cf07645b949..2a50ae0c5a2 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -97,6 +97,20 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{2}, # TODO: parabolic; extend to mortars @assert nmortars(dg, cache) == 0 + # # Prolong solution to mortars + # @trixi_timeit timer() "prolong2mortars" begin + # prolong2mortars!(cache, flux_viscous, mesh, equations_parabolic, + # dg.mortar, dg.surface_integral, dg) + # end + + # # Calculate mortar fluxes + # @trixi_timeit timer() "mortar flux" begin + # calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, mesh, + # equations_parabolic, + # dg.mortar, dg.surface_integral, dg, cache) + # end + + # Calculate surface integrals @trixi_timeit timer() "surface integral" begin calc_surface_integral!(du, u, mesh, equations_parabolic, @@ -205,6 +219,20 @@ function calc_gradient!(gradients, u_transformed, t, # TODO: parabolic; mortars @assert nmortars(dg, cache) == 0 + # # Prolong solution to mortars + # @trixi_timeit timer() "prolong2mortars" begin + # prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, + # dg.mortar, dg.surface_integral, dg) + # end + + # # Calculate mortar fluxes + # @trixi_timeit timer() "mortar flux" begin + # calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, + # mesh, + # equations_parabolic, + # dg.mortar, dg.surface_integral, dg, cache) + # end + # Calculate surface integrals @trixi_timeit timer() "surface integral" begin (; boundary_interpolation) = dg.basis From 794316789f5b478528db2340edf3d3a9866f03a6 Mon Sep 17 00:00:00 2001 From: Ahmad Peyvan Date: Fri, 6 Oct 2023 17:18:28 -0400 Subject: [PATCH 044/138] Adding Mortar to 2d dg parabolic term --- ...elixir_advection_diffusion_periodic_amr.jl | 43 ++- src/callbacks_step/amr.jl | 91 +++++++ src/callbacks_step/amr_dg2d.jl | 4 +- src/solvers/dgsem_p4est/containers.jl | 19 +- src/solvers/dgsem_p4est/dg_2d.jl | 1 - src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 254 +++++++++++++++++- 6 files changed, 386 insertions(+), 26 deletions(-) diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl index 16ba3b45499..519cc9b5f62 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl @@ -21,15 +21,24 @@ function initial_condition_diffusive_convergence_test(x, t, equation::LinearScal # Store translated coordinate for easy use of exact solution # Assumes that advection_velocity[2] = 0 (effectively that we are solving a 1D equation) x_trans = x_trans_periodic(x[2] - equation.advection_velocity[2] * t) + # y_trans = x_trans_periodic(x[1] - equation.advection_velocity[1] * t) nu = diffusivity() c = 0.0 A = 1.0 omega = 1.0 - scalar = c + A * sin(omega * sum(x_trans)) * exp(-nu * omega^2 * t) + scalar = c + A * sin(omega * (sum(x_trans))) * exp(-nu * omega^2 * t) return SVector(scalar) end -initial_condition = initial_condition_diffusive_convergence_test + +# Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") +function initial_condition_new_test(x, t, equation::LinearScalarAdvectionEquation2D) + # return SVector(x[1] + x[2] > 0) + #return SVector(sin(x[2])) + return SVector(sin(x[1])*sin(x[2])) +end +# initial_condition = initial_condition_diffusive_convergence_test +initial_condition = initial_condition_new_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) @@ -48,12 +57,11 @@ semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. # Create ODE problem with time span `tspan` -tspan = (0.0, 1e-2) +tspan = (0.0, 5e-3) ode = semidiscretize(semi, tspan); # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup @@ -67,28 +75,39 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) # The AliveCallback prints short status information in regular intervals alive_callback = AliveCallback(analysis_interval=analysis_interval) +# amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), +# base_level=2, +# med_level=3, med_threshold=0.5, +# max_level=4, max_threshold=0.75) + amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=2, - med_level=3, med_threshold=0.5, - max_level=4, max_threshold=0.75) + base_level=1, + med_level=2, med_threshold=0.5, + max_level=3, max_threshold=0.75) amr_callback = AMRCallback(semi, amr_controller, interval=5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -#callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) +# callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 +# function eigen_est() sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, ode_default_options()..., callback=callbacks) - +# sol = solve(ode, ROCK4(eigen_est=eigen_est); abstol=time_int_tol, reltol=time_int_tol, +# ode_default_options()..., callback=callbacks) # Print the timer summary summary_callback() plot(sol) pd = PlotData2D(sol) -plot!(getmesh(pd)) \ No newline at end of file +plot!(getmesh(pd)) + + +# u = sol.u[end] +# du = similar(u) +# Trixi.rhs_parabolic!(du, u, semi, 0.0) \ No newline at end of file diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index ba840ff9675..378f7f17bad 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -528,6 +528,97 @@ function copy_to_quad_iter_volume(info, user_data) return nothing end +function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::P4estMesh, + equations, dg::DG, cache, cache_parabolic, + semi, + t, iter; + only_refine = false, only_coarsen = false, + passive_args = ()) + @unpack controller, adaptor = amr_callback + + u = wrap_array(u_ode, mesh, equations, dg, cache) + lambda = @trixi_timeit timer() "indicator" controller(u, mesh, equations, dg, cache, + t = t, iter = iter) + + @boundscheck begin + @assert axes(lambda)==(Base.OneTo(ncells(mesh)),) ("Indicator array (axes = $(axes(lambda))) and mesh cells (axes = $(Base.OneTo(ncells(mesh)))) have different axes") + end + + # Copy controller value of each quad to the quad's user data storage + iter_volume_c = cfunction(copy_to_quad_iter_volume, Val(ndims(mesh))) + + # The pointer to lambda will be interpreted as Ptr{Int} above + @assert lambda isa Vector{Int} + iterate_p4est(mesh.p4est, lambda; iter_volume_c = iter_volume_c) + + @trixi_timeit timer() "refine" if !only_coarsen + # Refine mesh + refined_original_cells = @trixi_timeit timer() "mesh" refine!(mesh) + + # Refine solver + @trixi_timeit timer() "solver" refine!(u_ode, adaptor, mesh, equations, dg, + cache, cache_parabolic, + refined_original_cells) + for (p_u_ode, p_mesh, p_equations, p_dg, p_cache) in passive_args + @trixi_timeit timer() "passive solver" refine!(p_u_ode, adaptor, p_mesh, + p_equations, + p_dg, p_cache, + refined_original_cells) + end + else + # If there is nothing to refine, create empty array for later use + refined_original_cells = Int[] + end + + @trixi_timeit timer() "coarsen" if !only_refine + # Coarsen mesh + coarsened_original_cells = @trixi_timeit timer() "mesh" coarsen!(mesh) + + # coarsen solver + @trixi_timeit timer() "solver" coarsen!(u_ode, adaptor, mesh, equations, dg, + cache, cache_parabolic, + coarsened_original_cells) + for (p_u_ode, p_mesh, p_equations, p_dg, p_cache) in passive_args + @trixi_timeit timer() "passive solver" coarsen!(p_u_ode, adaptor, p_mesh, + p_equations, + p_dg, p_cache, + coarsened_original_cells) + end + else + # If there is nothing to coarsen, create empty array for later use + coarsened_original_cells = Int[] + end + + # Store whether there were any cells coarsened or refined and perform load balancing + has_changed = !isempty(refined_original_cells) || !isempty(coarsened_original_cells) + # Check if mesh changed on other processes + if mpi_isparallel() + has_changed = MPI.Allreduce!(Ref(has_changed), |, mpi_comm())[] + end + + if has_changed # TODO: Taal decide, where shall we set this? + # don't set it to has_changed since there can be changes from earlier calls + mesh.unsaved_changes = true + + if mpi_isparallel() && amr_callback.dynamic_load_balancing + @trixi_timeit timer() "dynamic load balancing" begin + global_first_quadrant = unsafe_wrap(Array, + unsafe_load(mesh.p4est).global_first_quadrant, + mpi_nranks() + 1) + old_global_first_quadrant = copy(global_first_quadrant) + partition!(mesh) + rebalance_solver!(u_ode, mesh, equations, dg, cache, + old_global_first_quadrant) + end + end + + reinitialize_boundaries!(semi.boundary_conditions, cache) + end + + # Return true if there were any cells coarsened or refined, otherwise false + return has_changed +end + # 2D function cfunction(::typeof(copy_to_quad_iter_volume), ::Val{2}) @cfunction(copy_to_quad_iter_volume, Cvoid, diff --git a/src/callbacks_step/amr_dg2d.jl b/src/callbacks_step/amr_dg2d.jl index 6395a9f348f..1c49df7fb01 100644 --- a/src/callbacks_step/amr_dg2d.jl +++ b/src/callbacks_step/amr_dg2d.jl @@ -137,7 +137,7 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, P4estM end # AMR for hyperbolic-parabolic equations currently only supported on TreeMeshes -function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, TreeMesh{3}}, +function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, P4estMesh{2}, TreeMesh{3}}, equations, dg::DGSEM, cache, cache_parabolic, elements_to_refine) # Call `refine!` for the hyperbolic part, which does the heavy lifting of @@ -299,7 +299,7 @@ function coarsen!(u_ode::AbstractVector, adaptor, end # AMR for hyperbolic-parabolic equations currently only supported on TreeMeshes -function coarsen!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, TreeMesh{3}}, +function coarsen!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2},P4estMesh{2}, TreeMesh{3}}, equations, dg::DGSEM, cache, cache_parabolic, elements_to_remove) # Call `coarsen!` for the hyperbolic part, which does the heavy lifting of diff --git a/src/solvers/dgsem_p4est/containers.jl b/src/solvers/dgsem_p4est/containers.jl index 0176f5c6346..e79dc97b554 100644 --- a/src/solvers/dgsem_p4est/containers.jl +++ b/src/solvers/dgsem_p4est/containers.jl @@ -429,13 +429,18 @@ function reinitialize_containers!(mesh::P4estMesh, equations, dg::DGSEM, cache) @unpack boundaries = cache resize!(boundaries, required.boundaries) - # resize mortars container - @unpack mortars = cache - resize!(mortars, required.mortars) - - # re-initialize containers together to reduce - # the number of iterations over the mesh in `p4est` - init_surfaces!(interfaces, mortars, boundaries, mesh) + # re-initialize mortars container + if hasproperty(cache, :mortars) # cache_parabolic does not carry mortars + @unpack mortars = cache + resize!(mortars, required.mortars) + + # re-initialize containers together to reduce + # the number of iterations over the mesh in `p4est` + init_surfaces!(interfaces, mortars, boundaries, mesh) + else + init_surfaces!(interfaces, nothing, boundaries, mesh) + end + end # A helper struct used in initialization methods below diff --git a/src/solvers/dgsem_p4est/dg_2d.jl b/src/solvers/dgsem_p4est/dg_2d.jl index 36624f2ce8a..6a04c19e8a2 100644 --- a/src/solvers/dgsem_p4est/dg_2d.jl +++ b/src/solvers/dgsem_p4est/dg_2d.jl @@ -569,7 +569,6 @@ end mortar_l2::LobattoLegendreMortarL2, dg::DGSEM, cache, mortar, fstar, u_buffer) @unpack neighbor_ids, node_indices = cache.mortars - # Copy solution small to small small_indices = node_indices[1, mortar] small_direction = indices2direction(small_indices) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 2a50ae0c5a2..6b1461363a2 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -94,8 +94,18 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{2}, dg.surface_integral, dg) end - # TODO: parabolic; extend to mortars - @assert nmortars(dg, cache) == 0 + # Prolong solution to mortars + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars!(cache, flux_viscous, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, mesh, + equations_parabolic, + dg.mortar, dg.surface_integral, dg, cache) + end # # Prolong solution to mortars # @trixi_timeit timer() "prolong2mortars" begin @@ -216,8 +226,19 @@ function calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, dg.surface_integral, dg) end - # TODO: parabolic; mortars - @assert nmortars(dg, cache) == 0 + # Prolong solution to mortars + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, + mesh, + equations_parabolic, + dg.mortar, dg.surface_integral, dg, cache) + end # # Prolong solution to mortars # @trixi_timeit timer() "prolong2mortars" begin @@ -548,6 +569,231 @@ function calc_interface_flux!(surface_flux_values, return nothing end +function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, equations, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DGSEM) where {uEltype <: Real} + @unpack neighbor_ids, node_indices = cache.mortars + @unpack contravariant_vectors = cache.elements + index_range = eachnode(dg) + + flux_viscous_x, flux_viscous_y = flux_viscous + + @threaded for mortar in eachmortar(dg, cache) + # Copy solution data from the small elements using "delayed indexing" with + # a start value and a step size to get the correct face and orientation. + small_indices = node_indices[1, mortar] + direction_index = indices2direction(small_indices) + + i_small_start, i_small_step = index_to_start_step_2d(small_indices[1], + index_range) + j_small_start, j_small_step = index_to_start_step_2d(small_indices[2], + index_range) + + for position in 1:2 + i_small = i_small_start + j_small = j_small_start + element = neighbor_ids[position, mortar] + for i in eachnode(dg) + normal_direction = get_normal_direction(direction_index, contravariant_vectors, + i_small, j_small, element) + # if mortar==1 && position == 1 && i == 1 + # println(" on small sides") + # @show normal_direction + # end + for v in eachvariable(equations) + flux_viscous = SVector(flux_viscous_x[v, i_small, j_small, element], + flux_viscous_y[v, i_small, j_small, element]) + + cache.mortars.u[1, v, position, i, mortar] = dot(flux_viscous, normal_direction) + end + i_small += i_small_step + j_small += j_small_step + end + end + + # Buffer to copy solution values of the large element in the correct orientation + # before interpolating + u_buffer = cache.u_threaded[Threads.threadid()] + + # Copy solution of large element face to buffer in the + # correct orientation + large_indices = node_indices[2, mortar] + direction_index = indices2direction(large_indices) + + i_large_start, i_large_step = index_to_start_step_2d(large_indices[1], + index_range) + j_large_start, j_large_step = index_to_start_step_2d(large_indices[2], + index_range) + + i_large = i_large_start + j_large = j_large_start + element = neighbor_ids[3, mortar] + for i in eachnode(dg) + normal_direction = get_normal_direction(direction_index, contravariant_vectors, + i_large, j_large, element) + # if mortar==1 && i == 1 + # println(" on large sides") + # @show -0.5 * normal_direction + # end + for v in eachvariable(equations) + flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, element], + flux_viscous_y[v, i_large, j_large, element]) + u_buffer[v, i] = 0.5 * dot(flux_viscous, normal_direction) + end + i_large += i_large_step + j_large += j_large_step + end + + # Interpolate large element face data from buffer to small face locations + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 1, :, mortar), + mortar_l2.forward_lower, + u_buffer) + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 2, :, mortar), + mortar_l2.forward_upper, + u_buffer) + end + + return nothing +end + +@inline function mortar_fluxes_to_elements!(surface_flux_values, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + dg::DGSEM, cache, mortar, fstar, u_buffer) + @unpack neighbor_ids, node_indices = cache.mortars + # Copy solution small to small + small_indices = node_indices[1, mortar] + small_direction = indices2direction(small_indices) + + for position in 1:2 + element = neighbor_ids[position, mortar] + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, i, small_direction, element] = fstar[position][v, + i] + end + end + end + + # Project small fluxes to large element. + multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_upper, fstar[2], + mortar_l2.reverse_lower, fstar[1]) + + # The flux is calculated in the outward direction of the small elements, + # so the sign must be switched to get the flux in outward direction + # of the large element. + # The contravariant vectors of the large element (and therefore the normal + # vectors of the large element as well) are twice as large as the + # contravariant vectors of the small elements. Therefore, the flux needs + # to be scaled by a factor of 2 to obtain the flux of the large element. + u_buffer .*= 2 + # u_buffer .*= -1 + + # Copy interpolated flux values from buffer to large element face in the + # correct orientation. + # Note that the index of the small sides will always run forward but + # the index of the large side might need to run backwards for flipped sides. + large_element = neighbor_ids[3, mortar] + large_indices = node_indices[2, mortar] + large_direction = indices2direction(large_indices) + + if :i_backward in large_indices + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, end + 1 - i, large_direction, large_element] = u_buffer[v, + i] + end + end + else + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, i, large_direction, large_element] = u_buffer[v, + i] + end + end + end + + return nothing +end + +# NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. +# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for +# hyperbolic terms with conserved terms only, i.e., no nonconservative terms. +function calc_mortar_flux!(surface_flux_values, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DG, cache) + @unpack neighbor_ids, node_indices = cache.mortars + @unpack contravariant_vectors = cache.elements + @unpack fstar_upper_threaded, fstar_lower_threaded = cache + index_range = eachnode(dg) + + @threaded for mortar in eachmortar(dg, cache) + # Choose thread-specific pre-allocated container + fstar = (fstar_lower_threaded[Threads.threadid()], + fstar_upper_threaded[Threads.threadid()]) + + # Get index information on the small elements + small_indices = node_indices[1, mortar] + small_direction = indices2direction(small_indices) + + i_small_start, i_small_step = index_to_start_step_2d(small_indices[1], + index_range) + j_small_start, j_small_step = index_to_start_step_2d(small_indices[2], + index_range) + + for position in 1:2 + i_small = i_small_start + j_small = j_small_start + for node in eachnode(dg) + calc_mortar_flux!(fstar, mesh, equations, + surface_integral, dg, cache, + mortar, position, + node, small_direction) + + i_small += i_small_step + j_small += j_small_step + end + end + + # Buffer to interpolate flux values of the large element to before + # copying in the correct orientation + u_buffer = cache.u_threaded[Threads.threadid()] + + mortar_fluxes_to_elements!(surface_flux_values, + mesh, equations, mortar_l2, dg, cache, + mortar, fstar, u_buffer) + end + + return nothing +end + +# NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. +# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for +# hyperbolic terms with conserved terms only, i.e., no nonconservative terms. +@inline function calc_mortar_flux!(fstar, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + equations::AbstractEquationsParabolic, + surface_integral, dg::DG, cache, + mortar_index, position_index, + node_index, small_direction) + @unpack u = cache.mortars + @unpack surface_flux = surface_integral + + u_ll, u_rr = get_surface_node_vars(u, equations, dg, position_index, node_index, + mortar_index) + + # TODO: parabolic; only BR1 at the moment + flux = 0.5 * (u_ll + u_rr) + + # Copy flux to buffer + set_node_vars!(fstar[position_index], flux, equations, dg, node_index) +end + # TODO: parabolic, finish implementing `calc_boundary_flux_gradients!` and `calc_boundary_flux_divergence!` function prolong2boundaries!(cache_parabolic, flux_viscous, mesh::P4estMesh{2}, From a8173c7fb7ae2098ede0b9053d84504a21ea93c3 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 14:20:42 -0400 Subject: [PATCH 045/138] remove testing snippet --- .../p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl index 519cc9b5f62..0b6302f807d 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl @@ -107,7 +107,3 @@ plot(sol) pd = PlotData2D(sol) plot!(getmesh(pd)) - -# u = sol.u[end] -# du = similar(u) -# Trixi.rhs_parabolic!(du, u, semi, 0.0) \ No newline at end of file From 5f4e8f3692128259b03b5ba1a201ab08ba068fad Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 14:21:34 -0400 Subject: [PATCH 046/138] fix comments --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 6b1461363a2..718f7e84387 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -200,7 +200,7 @@ function calc_gradient!(gradients, u_transformed, t, end end - # Prolong solution to interfaces + # Prolong solution to interfaces. This reuses P4est `prolong2interfaces`. @trixi_timeit timer() "prolong2interfaces" begin prolong2interfaces!(cache_parabolic, u_transformed, mesh, equations_parabolic, dg.surface_integral, dg) @@ -370,7 +370,7 @@ end flux_ = 0.5 * (u_ll + u_rr) # we assume that the gradient computations utilize a central flux - # Note that we don't flip the sign on the secondondary flux. This is because for parabolic terms, + # Note that we don't flip the sign on the secondary flux. This is because for parabolic terms, # the normals are not embedded in `flux_` for the parabolic gradient computations. for v in eachvariable(equations) surface_flux_values[v, primary_node_index, primary_direction_index, primary_element_index] = flux_[v] From 113bce53e94769e83c4b93f63bac21c7036a06d7 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 14:33:53 -0400 Subject: [PATCH 047/138] add more arguments for dispatch --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 718f7e84387..fcc22846d0e 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -235,25 +235,11 @@ function calc_gradient!(gradients, u_transformed, t, # Calculate mortar fluxes @trixi_timeit timer() "mortar flux" begin calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, - mesh, + mesh, False(), # False() = no nonconservative terms equations_parabolic, dg.mortar, dg.surface_integral, dg, cache) end - # # Prolong solution to mortars - # @trixi_timeit timer() "prolong2mortars" begin - # prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, - # dg.mortar, dg.surface_integral, dg) - # end - - # # Calculate mortar fluxes - # @trixi_timeit timer() "mortar flux" begin - # calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, - # mesh, - # equations_parabolic, - # dg.mortar, dg.surface_integral, dg, cache) - # end - # Calculate surface integrals @trixi_timeit timer() "surface integral" begin (; boundary_interpolation) = dg.basis @@ -777,10 +763,11 @@ end # hyperbolic terms with conserved terms only, i.e., no nonconservative terms. @inline function calc_mortar_flux!(fstar, mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + nonconservative_terms::False, equations::AbstractEquationsParabolic, surface_integral, dg::DG, cache, - mortar_index, position_index, - node_index, small_direction) + mortar_index, position_index, normal_direction, + node_index) @unpack u = cache.mortars @unpack surface_flux = surface_integral From 53c5c685b08bd6a6aae99639fc6cdfbb1adf30e4 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 14:36:48 -0400 Subject: [PATCH 048/138] add some temporary todo notes --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index fcc22846d0e..31ef812f277 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -705,9 +705,7 @@ end return nothing end -# NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. -# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for -# hyperbolic terms with conserved terms only, i.e., no nonconservative terms. +# THIS IS FOR THE DIVERGENCE???? function calc_mortar_flux!(surface_flux_values, mesh::Union{P4estMesh{2}, T8codeMesh{2}}, equations::AbstractEquationsParabolic, @@ -736,11 +734,18 @@ function calc_mortar_flux!(surface_flux_values, i_small = i_small_start j_small = j_small_start for node in eachnode(dg) - calc_mortar_flux!(fstar, mesh, equations, + calc_mortar_flux!(fstar, mesh, equations, surface_integral, dg, cache, mortar, position, node, small_direction) + # !!! TODO: replace this with manual calculation of {fstar} + # reason: when we specialize calc_mortar_flux / calc_interface_flux, we + # do so to reuse existing routines for hyperbolic problems for gradient + # computations. However, calc_interface_flux for divergence doesn't call a + # second specialization of calc_interface_flux, so calc_mortar_flux for div + # probably shouldn't either + i_small += i_small_step j_small += j_small_step end From 4c2ed6c3c11d8f590e3e36e5cf2bab158ed28b90 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 14:57:42 -0400 Subject: [PATCH 049/138] some updates for AP and KS --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 38 ++++++++-------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 31ef812f277..f0b60681583 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -107,19 +107,6 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{2}, dg.mortar, dg.surface_integral, dg, cache) end - # # Prolong solution to mortars - # @trixi_timeit timer() "prolong2mortars" begin - # prolong2mortars!(cache, flux_viscous, mesh, equations_parabolic, - # dg.mortar, dg.surface_integral, dg) - # end - - # # Calculate mortar fluxes - # @trixi_timeit timer() "mortar flux" begin - # calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, mesh, - # equations_parabolic, - # dg.mortar, dg.surface_integral, dg, cache) - # end - # Calculate surface integrals @trixi_timeit timer() "surface integral" begin @@ -226,13 +213,14 @@ function calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, dg.surface_integral, dg) end - # Prolong solution to mortars + # Prolong solution to mortars. These should reuse the hyperbolic version of `prolong2mortars` @trixi_timeit timer() "prolong2mortars" begin prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, dg.mortar, dg.surface_integral, dg) end - # Calculate mortar fluxes + # Calculate mortar fluxes. These should reuse the hyperbolic version of `calc_mortar_flux`, + # along with a specialization on `calc_mortar_flux` @trixi_timeit timer() "mortar flux" begin calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, mesh, False(), # False() = no nonconservative terms @@ -625,7 +613,7 @@ function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, for v in eachvariable(equations) flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, element], flux_viscous_y[v, i_large, j_large, element]) - u_buffer[v, i] = 0.5 * dot(flux_viscous, normal_direction) + u_buffer[v, i] = -0.5 * dot(flux_viscous, normal_direction) end i_large += i_large_step j_large += j_large_step @@ -675,8 +663,7 @@ end # vectors of the large element as well) are twice as large as the # contravariant vectors of the small elements. Therefore, the flux needs # to be scaled by a factor of 2 to obtain the flux of the large element. - u_buffer .*= 2 - # u_buffer .*= -1 + u_buffer .*= -2 # Copy interpolated flux values from buffer to large element face in the # correct orientation. @@ -734,12 +721,13 @@ function calc_mortar_flux!(surface_flux_values, i_small = i_small_start j_small = j_small_start for node in eachnode(dg) - calc_mortar_flux!(fstar, mesh, equations, - surface_integral, dg, cache, - mortar, position, - node, small_direction) + + # calc_mortar_flux!(fstar, mesh, equations, + # surface_integral, dg, cache, + # mortar, position, + # node, small_direction) - # !!! TODO: replace this with manual calculation of {fstar} + # !!! TODO: replace this with manual calculation of avg(fstar) # reason: when we specialize calc_mortar_flux / calc_interface_flux, we # do so to reuse existing routines for hyperbolic problems for gradient # computations. However, calc_interface_flux for divergence doesn't call a @@ -780,10 +768,10 @@ end mortar_index) # TODO: parabolic; only BR1 at the moment - flux = 0.5 * (u_ll + u_rr) + flux_ = 0.5 * (u_ll + u_rr) # Copy flux to buffer - set_node_vars!(fstar[position_index], flux, equations, dg, node_index) + set_node_vars!(fstar[position_index], flux_, equations, dg, node_index) end # TODO: parabolic, finish implementing `calc_boundary_flux_gradients!` and `calc_boundary_flux_divergence!` From 39cc7b84347ed4fcaa0ac7e140fc28303e4e4495 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 15:25:40 -0400 Subject: [PATCH 050/138] specialize mortar_fluxes_to_elements --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 128 +++++++++++---------- 1 file changed, 66 insertions(+), 62 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index f0b60681583..9f087a4b20c 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -220,7 +220,8 @@ function calc_gradient!(gradients, u_transformed, t, end # Calculate mortar fluxes. These should reuse the hyperbolic version of `calc_mortar_flux`, - # along with a specialization on `calc_mortar_flux` + # along with a specialization on `calc_mortar_flux!` and `mortar_fluxes_to_elements!` for + # AbstractEquationsParabolic. @trixi_timeit timer() "mortar flux" begin calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, mesh, False(), # False() = no nonconservative terms @@ -326,6 +327,70 @@ function calc_gradient!(gradients, u_transformed, t, return nothing end +# This version is called during `calc_gradients!` and must be specialized because the flux +# in the gradient is {u} which doesn't depend on normals. Thus, you don't need to scale by +# 2 and flip the sign when storing the mortar fluxes back into surface_flux_values +@inline function mortar_fluxes_to_elements!(surface_flux_values, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + dg::DGSEM, cache, mortar, fstar, u_buffer) + @unpack neighbor_ids, node_indices = cache.mortars + # Copy solution small to small + small_indices = node_indices[1, mortar] + small_direction = indices2direction(small_indices) + + for position in 1:2 + element = neighbor_ids[position, mortar] + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, i, small_direction, element] = fstar[position][v, + i] + end + end + end + + # Project small fluxes to large element. + multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_upper, fstar[2], + mortar_l2.reverse_lower, fstar[1]) + + # The flux is calculated in the outward direction of the small elements, + # so the sign must be switched to get the flux in outward direction + # of the large element. + # The contravariant vectors of the large element (and therefore the normal + # vectors of the large element as well) are twice as large as the + # contravariant vectors of the small elements. Therefore, the flux needs + # to be scaled by a factor of 2 to obtain the flux of the large element. + # u_buffer .*= 0.5 + + # Copy interpolated flux values from buffer to large element face in the + # correct orientation. + # Note that the index of the small sides will always run forward but + # the index of the large side might need to run backwards for flipped sides. + large_element = neighbor_ids[3, mortar] + large_indices = node_indices[2, mortar] + large_direction = indices2direction(large_indices) + + if :i_backward in large_indices + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, end + 1 - i, large_direction, large_element] = u_buffer[v, + i] + end + end + else + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, i, large_direction, large_element] = u_buffer[v, + i] + end + end + end + + return nothing +end + # This version is used for parabolic gradient computations @inline function calc_interface_flux!(surface_flux_values, mesh::P4estMesh{2}, nonconservative_terms::False, @@ -631,67 +696,6 @@ function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, return nothing end -@inline function mortar_fluxes_to_elements!(surface_flux_values, - mesh::Union{P4estMesh{2}, T8codeMesh{2}}, - equations::AbstractEquationsParabolic, - mortar_l2::LobattoLegendreMortarL2, - dg::DGSEM, cache, mortar, fstar, u_buffer) - @unpack neighbor_ids, node_indices = cache.mortars - # Copy solution small to small - small_indices = node_indices[1, mortar] - small_direction = indices2direction(small_indices) - - for position in 1:2 - element = neighbor_ids[position, mortar] - for i in eachnode(dg) - for v in eachvariable(equations) - surface_flux_values[v, i, small_direction, element] = fstar[position][v, - i] - end - end - end - - # Project small fluxes to large element. - multiply_dimensionwise!(u_buffer, - mortar_l2.reverse_upper, fstar[2], - mortar_l2.reverse_lower, fstar[1]) - - # The flux is calculated in the outward direction of the small elements, - # so the sign must be switched to get the flux in outward direction - # of the large element. - # The contravariant vectors of the large element (and therefore the normal - # vectors of the large element as well) are twice as large as the - # contravariant vectors of the small elements. Therefore, the flux needs - # to be scaled by a factor of 2 to obtain the flux of the large element. - u_buffer .*= -2 - - # Copy interpolated flux values from buffer to large element face in the - # correct orientation. - # Note that the index of the small sides will always run forward but - # the index of the large side might need to run backwards for flipped sides. - large_element = neighbor_ids[3, mortar] - large_indices = node_indices[2, mortar] - large_direction = indices2direction(large_indices) - - if :i_backward in large_indices - for i in eachnode(dg) - for v in eachvariable(equations) - surface_flux_values[v, end + 1 - i, large_direction, large_element] = u_buffer[v, - i] - end - end - else - for i in eachnode(dg) - for v in eachvariable(equations) - surface_flux_values[v, i, large_direction, large_element] = u_buffer[v, - i] - end - end - end - - return nothing -end - # THIS IS FOR THE DIVERGENCE???? function calc_mortar_flux!(surface_flux_values, mesh::Union{P4estMesh{2}, T8codeMesh{2}}, From e33bcfa9fccfffec422e41d29a89a93fc73ec289 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 17:57:54 -0400 Subject: [PATCH 051/138] BUGFIX: apply_jacobian_parabolic! was incorrect for P4estMesh --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 220ad75fbe6..10d536a8e2c 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -934,7 +934,7 @@ end # This is because the parabolic fluxes are assumed to be of the form # `du/dt + df/dx = dg/dx + source(x,t)`, # where f(u) is the inviscid flux and g(u) is the viscous flux. -function apply_jacobian_parabolic!(du, mesh::Union{TreeMesh{2}, P4estMesh{2}}, +function apply_jacobian_parabolic!(du, mesh::TreeMesh{2}, equations::AbstractEquationsParabolic, dg::DG, cache) @unpack inverse_jacobian = cache.elements @@ -950,4 +950,23 @@ function apply_jacobian_parabolic!(du, mesh::Union{TreeMesh{2}, P4estMesh{2}}, return nothing end + +function apply_jacobian_parabolic!(du, mesh::P4estMesh{2}, + equations::AbstractEquationsParabolic, + dg::DG, cache) + @unpack inverse_jacobian = cache.elements + + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + factor = inverse_jacobian[i, j, element] + + for v in eachvariable(equations) + du[v, i, j, element] *= factor + end + end + end + + return nothing +end + end # @muladd From 0ee3d3ee60c708e69c87fc2967e91ac9f6244f2f Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 19:05:26 -0400 Subject: [PATCH 052/138] fixed rhs_parabolic! for mortars --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 77 +++++++++++----------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 9f087a4b20c..08ff0c44806 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -9,12 +9,13 @@ function create_cache_parabolic(mesh::P4estMesh{2}, equations_hyperbolic::Abstra elements = init_elements(mesh, equations_hyperbolic, dg.basis, uEltype) interfaces = init_interfaces(mesh, equations_hyperbolic, dg.basis, elements) boundaries = init_boundaries(mesh, equations_hyperbolic, dg.basis, elements) + mortars = init_mortars(mesh, equations_hyperbolic, dg.basis, elements) viscous_container = init_viscous_container_2d(nvariables(equations_hyperbolic), nnodes(dg.basis), nelements(elements), uEltype) - cache = (; elements, interfaces, boundaries, viscous_container) + cache = (; elements, interfaces, boundaries, mortars, viscous_container) return cache end @@ -94,17 +95,19 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{2}, dg.surface_integral, dg) end - # Prolong solution to mortars + # Prolong solution to mortars (specialized for AbstractEquationsParabolic) + # !!! NOTE: we reuse the hyperbolic cache here since it contains "mortars" and "u_threaded" + # !!! Is this OK? @trixi_timeit timer() "prolong2mortars" begin - prolong2mortars!(cache, flux_viscous, mesh, equations_parabolic, - dg.mortar, dg.surface_integral, dg) + prolong2mortars_divergence!(cache, flux_viscous, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) end - # Calculate mortar fluxes + # Calculate mortar fluxes (specialized for AbstractEquationsParabolic) @trixi_timeit timer() "mortar flux" begin - calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, mesh, - equations_parabolic, - dg.mortar, dg.surface_integral, dg, cache) + calc_mortar_flux_divergence!(cache_parabolic.elements.surface_flux_values, + mesh, equations_parabolic, dg.mortar, + dg.surface_integral, dg, cache) end @@ -214,6 +217,8 @@ function calc_gradient!(gradients, u_transformed, t, end # Prolong solution to mortars. These should reuse the hyperbolic version of `prolong2mortars` + # !!! NOTE: we reuse the hyperbolic cache here, since it contains both `mortars` and `u_threaded`. + # !!! should we have a separate mortars/u_threaded in cache_parabolic? @trixi_timeit timer() "prolong2mortars" begin prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, dg.mortar, dg.surface_integral, dg) @@ -608,10 +613,10 @@ function calc_interface_flux!(surface_flux_values, return nothing end -function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, - mesh::Union{P4estMesh{2}, T8codeMesh{2}}, equations, - mortar_l2::LobattoLegendreMortarL2, - surface_integral, dg::DGSEM) where {uEltype <: Real} +function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, 4}}, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, equations, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DGSEM) where {uEltype <: Real} @unpack neighbor_ids, node_indices = cache.mortars @unpack contravariant_vectors = cache.elements index_range = eachnode(dg) @@ -636,10 +641,7 @@ function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, for i in eachnode(dg) normal_direction = get_normal_direction(direction_index, contravariant_vectors, i_small, j_small, element) - # if mortar==1 && position == 1 && i == 1 - # println(" on small sides") - # @show normal_direction - # end + for v in eachvariable(equations) flux_viscous = SVector(flux_viscous_x[v, i_small, j_small, element], flux_viscous_y[v, i_small, j_small, element]) @@ -671,13 +673,15 @@ function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, for i in eachnode(dg) normal_direction = get_normal_direction(direction_index, contravariant_vectors, i_large, j_large, element) - # if mortar==1 && i == 1 - # println(" on large sides") - # @show -0.5 * normal_direction - # end + for v in eachvariable(equations) flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, element], flux_viscous_y[v, i_large, j_large, element]) + + # We prolong the viscous flux dotted with respect the outward normal + # on the small element. We scale by -1/2 here because the normal + # direction on the large element is negative 2x that of the small + # element (these normal directions are "scaled" by the surface Jacobian) u_buffer[v, i] = -0.5 * dot(flux_viscous, normal_direction) end i_large += i_large_step @@ -696,12 +700,13 @@ function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, return nothing end -# THIS IS FOR THE DIVERGENCE???? -function calc_mortar_flux!(surface_flux_values, - mesh::Union{P4estMesh{2}, T8codeMesh{2}}, - equations::AbstractEquationsParabolic, - mortar_l2::LobattoLegendreMortarL2, - surface_integral, dg::DG, cache) +# We specialize `calc_mortar_flux!` for the divergence part of +# the parabolic terms. +function calc_mortar_flux_divergence!(surface_flux_values, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DG, cache) @unpack neighbor_ids, node_indices = cache.mortars @unpack contravariant_vectors = cache.elements @unpack fstar_upper_threaded, fstar_lower_threaded = cache @@ -725,18 +730,14 @@ function calc_mortar_flux!(surface_flux_values, i_small = i_small_start j_small = j_small_start for node in eachnode(dg) - - # calc_mortar_flux!(fstar, mesh, equations, - # surface_integral, dg, cache, - # mortar, position, - # node, small_direction) - - # !!! TODO: replace this with manual calculation of avg(fstar) - # reason: when we specialize calc_mortar_flux / calc_interface_flux, we - # do so to reuse existing routines for hyperbolic problems for gradient - # computations. However, calc_interface_flux for divergence doesn't call a - # second specialization of calc_interface_flux, so calc_mortar_flux for div - # probably shouldn't either + + for v in eachvariable(equations) + viscous_flux_normal_ll = cache.mortars.u[1, v, position, node, mortar] + viscous_flux_normal_rr = cache.mortars.u[1, v, position, node, mortar] + + # TODO: parabolic; only BR1 at the moment + fstar[position][v, node] = 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) + end i_small += i_small_step j_small += j_small_step From 2e23b36c054ab36e1e91d104a096a6400925ff4c Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 19:16:43 -0400 Subject: [PATCH 053/138] more changes to elixir --- ...elixir_advection_diffusion_periodic_amr.jl | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl index 0b6302f807d..de4189bd355 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the linear advection-diffusion equation -diffusivity() = 5.0e-2 +diffusivity() = 1.0e-2 advection_velocity = (1.0, 1.0) equations = LinearScalarAdvectionEquation2D(advection_velocity) equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) @@ -33,22 +33,20 @@ end # Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") function initial_condition_new_test(x, t, equation::LinearScalarAdvectionEquation2D) - # return SVector(x[1] + x[2] > 0) - #return SVector(sin(x[2])) - return SVector(sin(x[1])*sin(x[2])) + return SVector(2 * x[1] + x[2] > 0) end # initial_condition = initial_condition_diffusive_convergence_test initial_condition = initial_condition_new_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg=2, surface_flux=flux_lax_friedrichs) coordinates_min = (-pi, -pi) # minimum coordinates (min(x), min(y)) coordinates_max = ( pi, pi) # maximum coordinates (max(x), max(y)) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, + polydeg=2, initial_refinement_level=2, coordinates_min=coordinates_min, coordinates_max=coordinates_max, periodicity=true) @@ -61,7 +59,7 @@ semi = SemidiscretizationHyperbolicParabolic(mesh, # ODE solvers, callbacks etc. # Create ODE problem with time span `tspan` -tspan = (0.0, 5e-3) +tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan); # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup @@ -75,28 +73,22 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) # The AliveCallback prints short status information in regular intervals alive_callback = AliveCallback(analysis_interval=analysis_interval) -# amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), -# base_level=2, -# med_level=3, med_threshold=0.5, -# max_level=4, max_threshold=0.75) - amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=1, - med_level=2, med_threshold=0.5, - max_level=3, max_threshold=0.75) + base_level=2, + med_level=3, med_threshold=0.5, + max_level=4, max_threshold=0.75) + amr_callback = AMRCallback(semi, amr_controller, interval=5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) -# callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -# function eigen_est() sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, ode_default_options()..., callback=callbacks) # sol = solve(ode, ROCK4(eigen_est=eigen_est); abstol=time_int_tol, reltol=time_int_tol, From e0898033dbeaee3343873ae90733b72df44df30f Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 19:20:55 -0400 Subject: [PATCH 054/138] indexing bug --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 08ff0c44806..7d3b04ac072 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -733,7 +733,7 @@ function calc_mortar_flux_divergence!(surface_flux_values, for v in eachvariable(equations) viscous_flux_normal_ll = cache.mortars.u[1, v, position, node, mortar] - viscous_flux_normal_rr = cache.mortars.u[1, v, position, node, mortar] + viscous_flux_normal_rr = cache.mortars.u[2, v, position, node, mortar] # TODO: parabolic; only BR1 at the moment fstar[position][v, node] = 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) From 5b4c4da459136b10a629f9167fdc434b1fb48a03 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Sat, 7 Oct 2023 19:21:00 -0400 Subject: [PATCH 055/138] comments --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 7d3b04ac072..d8978fdb2f5 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -748,6 +748,7 @@ function calc_mortar_flux_divergence!(surface_flux_values, # copying in the correct orientation u_buffer = cache.u_threaded[Threads.threadid()] + # this reuses the hyperbolic version of `mortar_fluxes_to_elements!` mortar_fluxes_to_elements!(surface_flux_values, mesh, equations, mortar_l2, dg, cache, mortar, fstar, u_buffer) From 41770d7443ba7561792646d895033b41ed9e04f5 Mon Sep 17 00:00:00 2001 From: Ahmad Peyvan Date: Mon, 9 Oct 2023 13:34:30 -0400 Subject: [PATCH 056/138] Adding the example for nonperiodic BCs with amr --- ...xir_advection_diffusion_nonperiodic_amr.jl | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl new file mode 100644 index 00000000000..7ba64f36693 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl @@ -0,0 +1,110 @@ +using OrdinaryDiffEq, Plots +using Trixi + +############################################################################### +# semidiscretization of the linear advection-diffusion equation + +diffusivity() = 1.0e-2 +advection_velocity = (1.0, 0.0) +equations = LinearScalarAdvectionEquation2D(advection_velocity) +equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) + +function x_trans_periodic(x, domain_length=SVector(2 * pi), center=SVector(0.0)) + x_normalized = x .- center + x_shifted = x_normalized .% domain_length + x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* domain_length + return center + x_shifted + x_offset +end + +# Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") +function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) + # Store translated coordinate for easy use of exact solution + # Assumes that advection_velocity[2] = 0 (effectively that we are solving a 1D equation) + x_trans = x_trans_periodic(x[2] - equation.advection_velocity[2] * t) + # y_trans = x_trans_periodic(x[1] - equation.advection_velocity[1] * t) + + nu = diffusivity() + c = 0.0 + A = 1.0 + omega = 1.0 + scalar = c + A * sin(omega * (sum(x_trans))) * exp(-nu * omega^2 * t) + return SVector(scalar) +end + +# Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") +function initial_condition_new_test(x, t, equation) + return SVector((x[1]-pi)*(x[2]-pi)+(x[1]+pi)*(x[2]+pi)) +end +# initial_condition = initial_condition_diffusive_convergence_test +initial_condition = initial_condition_new_test + +boundary_conditions = Dict(:x_neg => BoundaryConditionDirichlet(initial_condition), + :y_neg => BoundaryConditionDirichlet(initial_condition), + :y_pos => BoundaryConditionDirichlet(initial_condition), + :x_pos => boundary_condition_do_nothing) + +boundary_conditions_parabolic = Dict(:x_neg => BoundaryConditionDirichlet(initial_condition), + :x_pos => BoundaryConditionDirichlet(initial_condition), + :y_neg => BoundaryConditionDirichlet(initial_condition), + :y_pos => BoundaryConditionDirichlet(initial_condition)) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=2, surface_flux=flux_lax_friedrichs) + +coordinates_min = (-pi, -pi) # minimum coordinates (min(x), min(y)) +coordinates_max = ( pi, pi) # maximum coordinates (max(x), max(y)) + +trees_per_dimension = (4, 4) +mesh = P4estMesh(trees_per_dimension, + polydeg=2, initial_refinement_level=2, + coordinates_min=coordinates_min, coordinates_max=coordinates_max, + periodicity=(false,false)) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver, + boundary_conditions = (boundary_conditions, boundary_conditions_parabolic)) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 0.1) +ode = semidiscretize(semi, tspan); + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval=analysis_interval) + +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), + base_level=2, + med_level=3, med_threshold=0.5, + max_level=4, max_threshold=0.75) + +amr_callback = AMRCallback(semi, amr_controller, + interval=5) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +time_int_tol = 1.0e-11 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) +# sol = solve(ode, ROCK4(eigen_est=eigen_est); abstol=time_int_tol, reltol=time_int_tol, +# ode_default_options()..., callback=callbacks) +# Print the timer summary +summary_callback() +plot(sol) +pd = PlotData2D(sol) +plot!(getmesh(pd)) + From 00a460af4f16be27be744e12d764e92866006595 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Mon, 9 Oct 2023 15:19:16 -0400 Subject: [PATCH 057/138] hopefully this fixes AMR boundaries for parabolic terms --- src/callbacks_step/amr.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index 378f7f17bad..2d823512659 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -613,6 +613,9 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::P4estMesh, end reinitialize_boundaries!(semi.boundary_conditions, cache) + if hasproperty(semi, :boundary_conditions_parabolic) + reinitialize_boundaries!(semi.boundary_conditions_parabolic, cache) + end end # Return true if there were any cells coarsened or refined, otherwise false From 6f465073b70c0a2895210be0f7f82d0e9f76aefa Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Mon, 9 Oct 2023 15:21:51 -0400 Subject: [PATCH 058/138] add elixir --- ...xir_advection_diffusion_nonperiodic_amr.jl | 88 +++++++++++-------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl index 7ba64f36693..688eb6fea5e 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl @@ -4,39 +4,17 @@ using Trixi ############################################################################### # semidiscretization of the linear advection-diffusion equation -diffusivity() = 1.0e-2 +diffusivity() = 1.0e-3 advection_velocity = (1.0, 0.0) equations = LinearScalarAdvectionEquation2D(advection_velocity) equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) -function x_trans_periodic(x, domain_length=SVector(2 * pi), center=SVector(0.0)) - x_normalized = x .- center - x_shifted = x_normalized .% domain_length - x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* domain_length - return center + x_shifted + x_offset -end - # Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) - # Store translated coordinate for easy use of exact solution - # Assumes that advection_velocity[2] = 0 (effectively that we are solving a 1D equation) - x_trans = x_trans_periodic(x[2] - equation.advection_velocity[2] * t) - # y_trans = x_trans_periodic(x[1] - equation.advection_velocity[1] * t) - - nu = diffusivity() - c = 0.0 - A = 1.0 - omega = 1.0 - scalar = c + A * sin(omega * (sum(x_trans))) * exp(-nu * omega^2 * t) - return SVector(scalar) +function initial_condition_bubble(x, t, equation) + return SVector((x[1]-pi) * (x[2]-pi) * (x[1]+pi) * (x[2]+pi)) end -# Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") -function initial_condition_new_test(x, t, equation) - return SVector((x[1]-pi)*(x[2]-pi)+(x[1]+pi)*(x[2]+pi)) -end -# initial_condition = initial_condition_diffusive_convergence_test -initial_condition = initial_condition_new_test +initial_condition = initial_condition_bubble boundary_conditions = Dict(:x_neg => BoundaryConditionDirichlet(initial_condition), :y_neg => BoundaryConditionDirichlet(initial_condition), @@ -58,18 +36,51 @@ trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, polydeg=2, initial_refinement_level=2, coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(false,false)) + periodicity=false) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver, - boundary_conditions = (boundary_conditions, boundary_conditions_parabolic)) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver, + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) + +# semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, +# boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. # Create ODE problem with time span `tspan` -tspan = (0.0, 0.1) -ode = semidiscretize(semi, tspan); +tspan = (0.0, .5) +ode = semidiscretize(semi, tspan) + +# u = sol.u[end] + +# du = similar(u) +# Trixi.rhs_parabolic!(du, u, semi, 0.0) + +# x, y = [semi.cache.elements.node_coordinates[i, :, :, :] for i in 1:2] +# for i in eachindex(x) +# u[i] = initial_condition_bubble((x[i], y[i]), 0.0, equations)[1] +# end +# u = Trixi.wrap_array(u, semi) +# fill!(cache_parabolic.elements.surface_flux_values, NaN); +# dg = solver +# parabolic_scheme = semi.solver_parabolic +# t = 0.0 +# (; cache, cache_parabolic, boundary_conditions_parabolic) = semi +# @unpack viscous_container = cache_parabolic +# @unpack u_transformed, gradients, flux_viscous = viscous_container + +# Trixi.transform_variables!(u_transformed, u, mesh, equations_parabolic, +# dg, parabolic_scheme, cache, cache_parabolic) + +# Trixi.calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, +# boundary_conditions_parabolic, dg, cache, cache_parabolic) + +# grad_x, grad_y = gradients +# @show any(isnan.(grad_x)) +# @show any(isnan.(grad_y)) # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup # and resets the timers @@ -83,9 +94,9 @@ analysis_callback = AnalysisCallback(semi, interval=analysis_interval) alive_callback = AliveCallback(analysis_interval=analysis_interval) amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=2, - med_level=3, med_threshold=0.5, - max_level=4, max_threshold=0.75) + base_level=1, + med_level=2, med_threshold=0.5, + max_level=3, max_threshold=0.75) amr_callback = AMRCallback(semi, amr_controller, interval=5) @@ -98,13 +109,12 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, +sol = solve(ode, dt = 1e-7, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, ode_default_options()..., callback=callbacks) -# sol = solve(ode, ROCK4(eigen_est=eigen_est); abstol=time_int_tol, reltol=time_int_tol, -# ode_default_options()..., callback=callbacks) + # Print the timer summary summary_callback() plot(sol) -pd = PlotData2D(sol) -plot!(getmesh(pd)) +# pd = PlotData2D(sol) +# plot!(getmesh(pd)) From 2c7fdd8fc63b78bd06088dae04fe13f2c96d7b7a Mon Sep 17 00:00:00 2001 From: Ahmad Peyvan Date: Mon, 9 Oct 2023 16:50:31 -0400 Subject: [PATCH 059/138] Example with non periodic bopundary conditions --- ...ixir_navierstokes_lid_driven_cavity_amr.jl | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity_amr.jl diff --git a/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity_amr.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity_amr.jl new file mode 100644 index 00000000000..e522acd4244 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity_amr.jl @@ -0,0 +1,102 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 0.001 + +equations = CompressibleEulerEquations2D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), + Prandtl=prandtl_number()) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) + +coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) + +# Create a uniformly refined mesh +trees_per_dimension = (6, 6) +mesh = P4estMesh(trees_per_dimension, + polydeg=3, initial_refinement_level=2, + coordinates_min=coordinates_min, coordinates_max=coordinates_max, + periodicity=(false, false)) + +function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) + Ma = 0.5 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) +end +initial_condition = initial_condition_cavity + +# BC types +velocity_bc_lid = NoSlip((x, t, equations) -> SVector(1.0, 0.0)) +velocity_bc_cavity = NoSlip((x, t, equations) -> SVector(0.0, 0.0)) +heat_bc = Adiabatic((x, t, equations) -> 0.0) +boundary_condition_lid = BoundaryConditionNavierStokesWall(velocity_bc_lid, heat_bc) +boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity, heat_bc) + +# define periodic boundary conditions everywhere +boundary_conditions = Dict( :x_neg => boundary_condition_slip_wall, + :y_neg => boundary_condition_slip_wall, + :y_pos => boundary_condition_slip_wall, + :x_pos => boundary_condition_slip_wall) + +boundary_conditions_parabolic = Dict( :x_neg => boundary_condition_cavity, + :y_neg => boundary_condition_cavity, + :y_pos => boundary_condition_lid, + :x_pos => boundary_condition_cavity) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions=(boundary_conditions, + boundary_conditions_parabolic)) + +# semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), +# initial_condition, solver;) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 25.0) +ode = semidiscretize(semi, tspan); + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval=100) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) + +amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) + +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level=0, + med_level=1, med_threshold=0.02, + max_level=3, max_threshold=0.05) + +amr_callback = AMRCallback(semi, amr_controller, + interval=5, + adapt_initial_condition=true, + adapt_initial_condition_only_refine=true) + +callbacks = CallbackSet(summary_callback, alive_callback,analysis_callback, amr_callback) +# callbacks = CallbackSet(summary_callback, alive_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) +summary_callback() # print the timer summary + + +pd = PlotData2D(sol) +plot(pd["rho"]) +plot!(getmesh(pd)) From d0afe4abc0466519b7193adcea7979a42f18d166 Mon Sep 17 00:00:00 2001 From: Jesse Chan Date: Mon, 9 Oct 2023 17:29:06 -0400 Subject: [PATCH 060/138] remove cruft --- .../elixir_advection_diffusion_nonperiodic_amr.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl index 688eb6fea5e..3cee18e3ff1 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl @@ -43,9 +43,6 @@ semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabol initial_condition, solver, boundary_conditions = (boundary_conditions, boundary_conditions_parabolic)) - -# semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, -# boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. From beff438e6307c0cb2b14037bd57bf51b36a87115 Mon Sep 17 00:00:00 2001 From: Ahmad Peyvan Date: Wed, 1 Nov 2023 20:17:29 -0400 Subject: [PATCH 061/138] 3D parabolic amr --- .../elixir_navierstokes_3d_blast_wave_amr.jl | 122 ++++++ .../elixir_navierstokes_convergence_amr.jl | 0 ...ir_navierstokes_taylor_green_vortex_amr.jl | 96 +++++ src/callbacks_step/amr_dg2d.jl | 4 +- src/callbacks_step/amr_dg3d.jl | 2 +- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 346 +++++++++++++++++- 6 files changed, 562 insertions(+), 8 deletions(-) create mode 100644 examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl create mode 100644 examples/p4est_3d_dgsem/elixir_navierstokes_convergence_amr.jl create mode 100644 examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl new file mode 100644 index 00000000000..d0b5919714c --- /dev/null +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -0,0 +1,122 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 6.25e-4 # equivalent to Re = 1600 + +equations = CompressibleEulerEquations3D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), + Prandtl=prandtl_number()) + +""" + initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) + +The classical inviscid Taylor-Green vortex. +""" +function initial_condition_3d_blast_wave(x, t, equations::CompressibleEulerEquations3D) + + rho_c = 1.0 + p_c = 1.0 + u_c = 0.0 + + rho_o = 0.125 + p_o = 0.1 + u_o = 0.0 + + rc = 0.5 + r = sqrt(x[1]^2+x[2]^2+x[3]^2) + if r < rc + rho = rho_c + v1 = u_c + v2 = u_c + v3 = u_c + p = p_c + else + rho = rho_o + v1 = u_o + v2 = u_o + v3 = u_o + p = p_o + end + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) +end +initial_condition = initial_condition_3d_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorHennemannGassner(equations, basis, + alpha_max=1.0, + alpha_min=0.001, + alpha_smooth=true, + variable=density_pressure) +volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) + +solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + +coordinates_min = (-1.0, -1.0, -1.0) .* pi +coordinates_max = ( 1.0, 1.0, 1.0) .* pi + +trees_per_dimension = (4, 4, 4) + +mesh = P4estMesh(trees_per_dimension, polydeg=3, + coordinates_min=coordinates_min, coordinates_max=coordinates_max, + periodicity=(true, true, true), initial_refinement_level=1) + + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.80) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 50 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +save_solution = SaveSolutionCallback(interval=20, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) + +# amr_controller = ControllerThreeLevel(semi, amr_indicator, +# base_level=0, +# med_level=2, med_threshold=0.05, +# max_level=5, max_threshold=0.1) +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level=0, + med_level=1, med_threshold=0.05, + max_level=4, max_threshold=0.1) +amr_callback = AMRCallback(semi, amr_controller, + interval=5, + adapt_initial_condition=true, + adapt_initial_condition_only_refine=true) + + +alive_callback = AliveCallback(analysis_interval=analysis_interval,) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback,amr_callback,save_solution) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) +summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_convergence_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_convergence_amr.jl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl new file mode 100644 index 00000000000..aa8570e7162 --- /dev/null +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -0,0 +1,96 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 6.25e-4 # equivalent to Re = 1600 + +equations = CompressibleEulerEquations3D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), + Prandtl=prandtl_number()) + +""" + initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) + +The classical inviscid Taylor-Green vortex. +""" +function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) +end +initial_condition = initial_condition_taylor_green_vortex + +volume_flux = flux_ranocha +solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, + volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = (-1.0, -1.0, -1.0) .* pi +coordinates_max = ( 1.0, 1.0, 1.0) .* pi + +trees_per_dimension = (2, 2, 2) + +mesh = P4estMesh(trees_per_dimension, polydeg=3, + coordinates_min=coordinates_min, coordinates_max=coordinates_max, + periodicity=(true, true, true), initial_refinement_level=2) + + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 50 +analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, + extra_analysis_integrals=(energy_kinetic, + energy_internal, + enstrophy)) +save_solution = SaveSolutionCallback(interval=100, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +amr_indicator = IndicatorLöhner(semi, variable=density_pressure) + +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level=0, + med_level=2, med_threshold=0.002, + max_level=4, max_threshold=0.004) + +amr_callback = AMRCallback(semi, amr_controller, + interval=1, + adapt_initial_condition=false, + adapt_initial_condition_only_refine=false) + + +alive_callback = AliveCallback(analysis_interval=analysis_interval,) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback,amr_callback,save_solution) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) +summary_callback() # print the timer summary \ No newline at end of file diff --git a/src/callbacks_step/amr_dg2d.jl b/src/callbacks_step/amr_dg2d.jl index 1c49df7fb01..c1a4f23d5ed 100644 --- a/src/callbacks_step/amr_dg2d.jl +++ b/src/callbacks_step/amr_dg2d.jl @@ -137,7 +137,7 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, P4estM end # AMR for hyperbolic-parabolic equations currently only supported on TreeMeshes -function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, P4estMesh{2}, TreeMesh{3}}, +function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, P4estMesh{2}, P4estMesh{3}, TreeMesh{3}}, equations, dg::DGSEM, cache, cache_parabolic, elements_to_refine) # Call `refine!` for the hyperbolic part, which does the heavy lifting of @@ -299,7 +299,7 @@ function coarsen!(u_ode::AbstractVector, adaptor, end # AMR for hyperbolic-parabolic equations currently only supported on TreeMeshes -function coarsen!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2},P4estMesh{2}, TreeMesh{3}}, +function coarsen!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2},P4estMesh{2},P4estMesh{3}, TreeMesh{3}}, equations, dg::DGSEM, cache, cache_parabolic, elements_to_remove) # Call `coarsen!` for the hyperbolic part, which does the heavy lifting of diff --git a/src/callbacks_step/amr_dg3d.jl b/src/callbacks_step/amr_dg3d.jl index c8abe6fdb05..d1596fb9a77 100644 --- a/src/callbacks_step/amr_dg3d.jl +++ b/src/callbacks_step/amr_dg3d.jl @@ -309,4 +309,4 @@ function create_cache(::Type{ControllerThreeLevel}, controller_value = Vector{Int}(undef, nelements(dg, cache)) return (; controller_value) end -end # @muladd +end # @muladd \ No newline at end of file diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index b06cdd42127..8436617ceed 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -102,8 +102,23 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, dg.surface_integral, dg) end - # TODO: parabolic; extend to mortars - @assert nmortars(dg, cache) == 0 + # # TODO: parabolic; extend to mortars + # @assert nmortars(dg, cache) == 0 + + # Prolong solution to mortars (specialized for AbstractEquationsParabolic) + # !!! NOTE: we reuse the hyperbolic cache here since it contains "mortars" and "u_threaded" + # !!! Is this OK? + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars_divergence!(cache, flux_viscous, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes (specialized for AbstractEquationsParabolic) + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux_divergence!(cache_parabolic.elements.surface_flux_values, + mesh, equations_parabolic, dg.mortar, + dg.surface_integral, dg, cache) + end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin @@ -230,8 +245,26 @@ function calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, dg.surface_integral, dg) end - # TODO: parabolic; mortars - @assert nmortars(dg, cache) == 0 + # # TODO: parabolic; mortars + # @assert nmortars(dg, cache) == 0 + + # Prolong solution to mortars. These should reuse the hyperbolic version of `prolong2mortars` + # !!! NOTE: we reuse the hyperbolic cache here, since it contains both `mortars` and `u_threaded`. + # !!! should we have a separate mortars/u_threaded in cache_parabolic? + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes. These should reuse the hyperbolic version of `calc_mortar_flux`, + # along with a specialization on `calc_mortar_flux!` and `mortar_fluxes_to_elements!` for + # AbstractEquationsParabolic. + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, + mesh, False(), # False() = no nonconservative terms + equations_parabolic, + dg.mortar, dg.surface_integral, dg, cache) + end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin @@ -324,6 +357,92 @@ function calc_gradient!(gradients, u_transformed, t, return nothing end +# This version is called during `calc_gradients!` and must be specialized because the flux +# in the gradient is {u} which doesn't depend on normals. Thus, you don't need to scale by +# 2 and flip the sign when storing the mortar fluxes back into surface_flux_values +@inline function mortar_fluxes_to_elements!(surface_flux_values, + mesh::P4estMesh{3}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + dg::DGSEM, cache, mortar, fstar, u_buffer,fstar_tmp) + @unpack neighbor_ids, node_indices = cache.mortars + index_range = eachnode(dg) + # Copy solution small to small + small_indices = node_indices[1, mortar] + small_direction = indices2direction(small_indices) + + for position in 1:4 + element = neighbor_ids[position, mortar] + for j in eachnode(dg), i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, i, j, small_direction, element] = fstar[v, i, j, + position] + end + end + end + + # Project small fluxes to large element. + multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_lower, mortar_l2.reverse_lower, + view(fstar, .., 1), + fstar_tmp) + add_multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_upper, mortar_l2.reverse_lower, + view(fstar, .., 2), + fstar_tmp) + add_multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_lower, mortar_l2.reverse_upper, + view(fstar, .., 3), + fstar_tmp) + add_multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_upper, mortar_l2.reverse_upper, + view(fstar, .., 4), + fstar_tmp) + + # The flux is calculated in the outward direction of the small elements, + # so the sign must be switched to get the flux in outward direction + # of the large element. + # The contravariant vectors of the large element (and therefore the normal + # vectors of the large element as well) are twice as large as the + # contravariant vectors of the small elements. Therefore, the flux needs + # to be scaled by a factor of 2 to obtain the flux of the large element. + # u_buffer .*= 0.5 + + # Copy interpolated flux values from buffer to large element face in the + # correct orientation. + # Note that the index of the small sides will always run forward but + # the index of the large side might need to run backwards for flipped sides. + large_element = neighbor_ids[5, mortar] + large_indices = node_indices[2, mortar] + large_direction = indices2direction(large_indices) + large_surface_indices = surface_indices(large_indices) + + i_large_start, i_large_step_i, i_large_step_j = index_to_start_step_3d(large_surface_indices[1], + index_range) + j_large_start, j_large_step_i, j_large_step_j = index_to_start_step_3d(large_surface_indices[2], + index_range) + + # Note that the indices of the small sides will always run forward but + # the large indices might need to run backwards for flipped sides. + i_large = i_large_start + j_large = j_large_start + for j in eachnode(dg) + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, i_large, j_large, large_direction, large_element] = u_buffer[v, + i, + j] + end + i_large += i_large_step_i + j_large += j_large_step_i + end + i_large += i_large_step_j + j_large += j_large_step_j + end + + return nothing +end + # This version is used for parabolic gradient computations @inline function calc_interface_flux!(surface_flux_values, mesh::P4estMesh{3}, nonconservative_terms::False, @@ -603,6 +722,223 @@ function calc_interface_flux!(surface_flux_values, return nothing end +function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, 5}}, + mesh::Union{P4estMesh{3}, T8codeMesh{3}}, equations, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DGSEM) where {uEltype <: Real} + @unpack neighbor_ids, node_indices = cache.mortars + @unpack fstar_tmp_threaded = cache + @unpack contravariant_vectors = cache.elements + index_range = eachnode(dg) + + flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous + + @threaded for mortar in eachmortar(dg, cache) + # Copy solution data from the small elements using "delayed indexing" with + # a start value and a step size to get the correct face and orientation. + small_indices = node_indices[1, mortar] + direction_index = indices2direction(small_indices) + + i_small_start, i_small_step_i, i_small_step_j = index_to_start_step_3d(small_indices[1], + index_range) + j_small_start, j_small_step_i, j_small_step_j = index_to_start_step_3d(small_indices[2], + index_range) + k_small_start, k_small_step_i, k_small_step_j = index_to_start_step_3d(small_indices[3], + index_range) + + for position in 1:4 + i_small = i_small_start + j_small = j_small_start + k_small = k_small_start + element = neighbor_ids[position, mortar] + for j in eachnode(dg) + for i in eachnode(dg) + normal_direction = get_normal_direction(direction_index, contravariant_vectors, + i_small, j_small, k_small, element) + + for v in eachvariable(equations) + flux_viscous = SVector(flux_viscous_x[v, i_small, j_small , k_small, element], + flux_viscous_y[v, i_small, j_small , k_small, element], + flux_viscous_z[v, i_small, j_small , k_small, element]) + + cache.mortars.u[1, v, position, i, j, mortar] = dot(flux_viscous, normal_direction) + end + i_small += i_small_step_i + j_small += j_small_step_i + k_small += k_small_step_i + end + i_small += i_small_step_j + j_small += j_small_step_j + k_small += k_small_step_j + end + end + + # Buffer to copy solution values of the large element in the correct orientation + # before interpolating + u_buffer = cache.u_threaded[Threads.threadid()] + + # temporary buffer for projections + fstar_tmp = fstar_tmp_threaded[Threads.threadid()] + + # Copy solution of large element face to buffer in the + # correct orientation + large_indices = node_indices[2, mortar] + + i_large_start, i_large_step_i, i_large_step_j = index_to_start_step_3d(large_indices[1], + index_range) + j_large_start, j_large_step_i, j_large_step_j = index_to_start_step_3d(large_indices[2], + index_range) + k_large_start, k_large_step_i, k_large_step_j = index_to_start_step_3d(large_indices[3], + index_range) + + i_large = i_large_start + j_large = j_large_start + k_large = k_large_start + element = neighbor_ids[5, mortar] + for j in eachnode(dg) + for i in eachnode(dg) + normal_direction = get_normal_direction(direction_index, contravariant_vectors, + i_large, j_large, k_large, element) + + for v in eachvariable(equations) + flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, k_large, element], + flux_viscous_y[v, i_large, j_large, k_large, element], + flux_viscous_z[v, i_large, j_large, k_large, element]) + + # We prolong the viscous flux dotted with respect the outward normal + # on the small element. We scale by -1/2 here because the normal + # direction on the large element is negative 2x that of the small + # element (these normal directions are "scaled" by the surface Jacobian) + u_buffer[v, i, j] = -0.5 * dot(flux_viscous, normal_direction) + end + i_large += i_large_step_i + j_large += j_large_step_i + k_large += k_large_step_i + end + i_large += i_large_step_j + j_large += j_large_step_j + k_large += k_large_step_j + end + + # Interpolate large element face data from buffer to small face locations + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 1, :, :, mortar), + mortar_l2.forward_lower, + mortar_l2.forward_lower, + u_buffer, + fstar_tmp) + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 2, :, :, mortar), + mortar_l2.forward_upper, + mortar_l2.forward_lower, + u_buffer, + fstar_tmp) + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 3, :, :, mortar), + mortar_l2.forward_lower, + mortar_l2.forward_upper, + u_buffer, + fstar_tmp) + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 4, :, :, mortar), + mortar_l2.forward_upper, + mortar_l2.forward_upper, + u_buffer, + fstar_tmp) + end + + return nothing +end + +# We specialize `calc_mortar_flux!` for the divergence part of +# the parabolic terms. +function calc_mortar_flux_divergence!(surface_flux_values, + mesh::Union{P4estMesh{3}, T8codeMesh{3}}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DG, cache) + @unpack neighbor_ids, node_indices = cache.mortars + @unpack contravariant_vectors = cache.elements + @unpack fstar_threaded, fstar_tmp_threaded = cache + index_range = eachnode(dg) + + @threaded for mortar in eachmortar(dg, cache) + # Choose thread-specific pre-allocated container + fstar = fstar_threaded[Threads.threadid()] + fstar_tmp = fstar_tmp_threaded[Threads.threadid()] + + # Get index information on the small elements + small_indices = node_indices[1, mortar] + small_direction = indices2direction(small_indices) + + i_small_start, i_small_step_i, i_small_step_j = index_to_start_step_3d(small_indices[1], + index_range) + j_small_start, j_small_step_i, j_small_step_j = index_to_start_step_3d(small_indices[2], + index_range) + k_small_start, k_small_step_i, k_small_step_j = index_to_start_step_3d(small_indices[3], + index_range) + + + for position in 1:4 + i_small = i_small_start + j_small = j_small_start + k_small = k_small_start + element = neighbor_ids[position, mortar] + for j in eachnode(dg) + for i in eachnode(dg) + + for v in eachvariable(equations) + viscous_flux_normal_ll = cache.mortars.u[1, v, position, i, j , mortar] + viscous_flux_normal_rr = cache.mortars.u[2, v, position, i, j , mortar] + + # TODO: parabolic; only BR1 at the moment + fstar[v, i, j, position] = 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) + end + + i_small += i_small_step_i + j_small += j_small_step_i + k_small += k_small_step_i + end + i_small += i_small_step_j + j_small += j_small_step_j + k_small += k_small_step_j + end + end + + # Buffer to interpolate flux values of the large element to before + # copying in the correct orientation + u_buffer = cache.u_threaded[Threads.threadid()] + + # this reuses the hyperbolic version of `mortar_fluxes_to_elements!` + mortar_fluxes_to_elements!(surface_flux_values, + mesh, equations, mortar_l2, dg, cache, + mortar, fstar, u_buffer, fstar_tmp) + end + + return nothing +end + +# NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. +# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for +# hyperbolic terms with conserved terms only, i.e., no nonconservative terms. +@inline function calc_mortar_flux!(fstar, + mesh::P4estMesh{3}, + nonconservative_terms::False, + equations::AbstractEquationsParabolic, + surface_integral, dg::DG, cache, + mortar_index, position_index, normal_direction, + i_node_index, j_node_index) + @unpack u = cache.mortars + @unpack surface_flux = surface_integral + + u_ll, u_rr = get_surface_node_vars(u, equations, dg, position_index, i_node_index, + j_node_index,mortar_index) + + # TODO: parabolic; only BR1 at the moment + flux_ = 0.5 * (u_ll + u_rr) +# # Copy flux to buffer +# set_node_vars!(fstar, flux, equations, dg, i_node_index, j_node_index, +# position_index) + # Copy flux to buffer + set_node_vars!(fstar, flux_, equations, dg, i_node_index, j_node_index, position_index) +end + # TODO: parabolic, finish implementing `calc_boundary_flux_gradients!` and `calc_boundary_flux_divergence!` function prolong2boundaries!(cache_parabolic, flux_viscous, mesh::P4estMesh{3}, @@ -731,4 +1067,4 @@ function calc_boundary_flux!(cache, t, k_node += k_node_step_j end end -end +end \ No newline at end of file From 223dcd72308e09e46ca1e31067cccc0da00ecfa1 Mon Sep 17 00:00:00 2001 From: Ahmad Peyvan Date: Wed, 1 Nov 2023 23:15:06 -0400 Subject: [PATCH 062/138] TGV elixir --- ...ir_navierstokes_taylor_green_vortex_amr.jl | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index aa8570e7162..1d8e8770430 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -33,6 +33,11 @@ function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEule end initial_condition = initial_condition_taylor_green_vortex +@inline function vel_mag(u, equations::CompressibleEulerEquations3D) + rho, rho_v1, rho_v2, rho_v3, _ = u + return sqrt(rho_v1^2+rho_v2^2+rho_v3^2)/rho +end + volume_flux = flux_ranocha solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) @@ -40,11 +45,11 @@ solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, coordinates_min = (-1.0, -1.0, -1.0) .* pi coordinates_max = ( 1.0, 1.0, 1.0) .* pi -trees_per_dimension = (2, 2, 2) +trees_per_dimension = (4, 4, 4) mesh = P4estMesh(trees_per_dimension, polydeg=3, coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, true, true), initial_refinement_level=2) + periodicity=(true, true, true), initial_refinement_level=0) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), @@ -53,7 +58,7 @@ semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabol ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 1.0) +tspan = (0.0, 10.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() @@ -68,15 +73,19 @@ save_solution = SaveSolutionCallback(interval=100, save_final_solution=true, solution_variables=cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=density_pressure) +amr_indicator = IndicatorLöhner(semi, variable=vel_mag) +# amr_controller = ControllerThreeLevel(semi, amr_indicator, +# base_level=0, +# med_level=2, med_threshold=0.002, +# max_level=4, max_threshold=0.004) amr_controller = ControllerThreeLevel(semi, amr_indicator, base_level=0, - med_level=2, med_threshold=0.002, - max_level=4, max_threshold=0.004) + med_level=1, med_threshold=0.1, + max_level=3, max_threshold=0.2) amr_callback = AMRCallback(semi, amr_controller, - interval=1, + interval=5, adapt_initial_condition=false, adapt_initial_condition_only_refine=false) From dc396d3a65fd7eeb3972e57b80eaad7a96869a9d Mon Sep 17 00:00:00 2001 From: Ahmad Peyvan Date: Sat, 2 Dec 2023 09:39:37 -0500 Subject: [PATCH 063/138] Creating test for AMR 3D parabolic --- .../p4est_3d_dgsem/elixir_navierstokes_convergence_amr.jl | 0 .../elixir_navierstokes_taylor_green_vortex_amr.jl | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 examples/p4est_3d_dgsem/elixir_navierstokes_convergence_amr.jl diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_convergence_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_convergence_amr.jl deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index 1d8e8770430..ee4c5523931 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -45,7 +45,7 @@ solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, coordinates_min = (-1.0, -1.0, -1.0) .* pi coordinates_max = ( 1.0, 1.0, 1.0) .* pi -trees_per_dimension = (4, 4, 4) +trees_per_dimension = (2, 2, 2) mesh = P4estMesh(trees_per_dimension, polydeg=3, coordinates_min=coordinates_min, coordinates_max=coordinates_max, @@ -58,7 +58,7 @@ semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabol ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 10.0) +tspan = (0.0, 0.50) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() From 868d2525b51feb420c5047f5de37c1625cc36944 Mon Sep 17 00:00:00 2001 From: Ahmad Peyvan Date: Sat, 2 Dec 2023 09:58:36 -0500 Subject: [PATCH 064/138] Formatting --- ...ir_navierstokes_taylor_green_vortex_amr.jl | 93 ++++++++++--------- src/callbacks_step/amr_dg3d.jl | 2 +- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 74 ++++++++------- 3 files changed, 92 insertions(+), 77 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index ee4c5523931..330d54da97e 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -10,47 +10,50 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex @inline function vel_mag(u, equations::CompressibleEulerEquations3D) - rho, rho_v1, rho_v2, rho_v3, _ = u - return sqrt(rho_v1^2+rho_v2^2+rho_v3^2)/rho + rho, rho_v1, rho_v2, rho_v3, _ = u + return sqrt(rho_v1^2 + rho_v2^2 + rho_v3^2) / rho end volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi trees_per_dimension = (2, 2, 2) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, true, true), initial_refinement_level=0) - +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, true, true), initial_refinement_level = 0) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -64,42 +67,42 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -amr_indicator = IndicatorLöhner(semi, variable=vel_mag) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +amr_indicator = IndicatorLöhner(semi, variable = vel_mag) # amr_controller = ControllerThreeLevel(semi, amr_indicator, # base_level=0, # med_level=2, med_threshold=0.002, # max_level=4, max_threshold=0.004) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=1, med_threshold=0.1, - max_level=3, max_threshold=0.2) + base_level = 0, + med_level = 1, med_threshold = 0.1, + max_level = 3, max_threshold = 0.2) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=false, - adapt_initial_condition_only_refine=false) - + interval = 5, + adapt_initial_condition = false, + adapt_initial_condition_only_refine = false) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, - alive_callback,amr_callback,save_solution) + alive_callback, amr_callback, save_solution) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/src/callbacks_step/amr_dg3d.jl b/src/callbacks_step/amr_dg3d.jl index d1596fb9a77..c8abe6fdb05 100644 --- a/src/callbacks_step/amr_dg3d.jl +++ b/src/callbacks_step/amr_dg3d.jl @@ -309,4 +309,4 @@ function create_cache(::Type{ControllerThreeLevel}, controller_value = Vector{Int}(undef, nelements(dg, cache)) return (; controller_value) end -end # @muladd \ No newline at end of file +end # @muladd diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 8436617ceed..1e1234216a8 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -115,8 +115,8 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, # Calculate mortar fluxes (specialized for AbstractEquationsParabolic) @trixi_timeit timer() "mortar flux" begin - calc_mortar_flux_divergence!(cache_parabolic.elements.surface_flux_values, - mesh, equations_parabolic, dg.mortar, + calc_mortar_flux_divergence!(cache_parabolic.elements.surface_flux_values, + mesh, equations_parabolic, dg.mortar, dg.surface_integral, dg, cache) end @@ -364,7 +364,8 @@ end mesh::P4estMesh{3}, equations::AbstractEquationsParabolic, mortar_l2::LobattoLegendreMortarL2, - dg::DGSEM, cache, mortar, fstar, u_buffer,fstar_tmp) + dg::DGSEM, cache, mortar, fstar, u_buffer, + fstar_tmp) @unpack neighbor_ids, node_indices = cache.mortars index_range = eachnode(dg) # Copy solution small to small @@ -753,23 +754,29 @@ function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, element = neighbor_ids[position, mortar] for j in eachnode(dg) for i in eachnode(dg) - normal_direction = get_normal_direction(direction_index, contravariant_vectors, - i_small, j_small, k_small, element) - - for v in eachvariable(equations) - flux_viscous = SVector(flux_viscous_x[v, i_small, j_small , k_small, element], - flux_viscous_y[v, i_small, j_small , k_small, element], - flux_viscous_z[v, i_small, j_small , k_small, element]) + normal_direction = get_normal_direction(direction_index, + contravariant_vectors, + i_small, j_small, k_small, + element) - cache.mortars.u[1, v, position, i, j, mortar] = dot(flux_viscous, normal_direction) + for v in eachvariable(equations) + flux_viscous = SVector(flux_viscous_x[v, i_small, j_small, k_small, + element], + flux_viscous_y[v, i_small, j_small, k_small, + element], + flux_viscous_z[v, i_small, j_small, k_small, + element]) + + cache.mortars.u[1, v, position, i, j, mortar] = dot(flux_viscous, + normal_direction) end i_small += i_small_step_i j_small += j_small_step_i k_small += k_small_step_i end - i_small += i_small_step_j - j_small += j_small_step_j - k_small += k_small_step_j + i_small += i_small_step_j + j_small += j_small_step_j + k_small += k_small_step_j end end @@ -797,13 +804,17 @@ function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, element = neighbor_ids[5, mortar] for j in eachnode(dg) for i in eachnode(dg) - normal_direction = get_normal_direction(direction_index, contravariant_vectors, + normal_direction = get_normal_direction(direction_index, + contravariant_vectors, i_large, j_large, k_large, element) for v in eachvariable(equations) - flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, k_large, element], - flux_viscous_y[v, i_large, j_large, k_large, element], - flux_viscous_z[v, i_large, j_large, k_large, element]) + flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, k_large, + element], + flux_viscous_y[v, i_large, j_large, k_large, + element], + flux_viscous_z[v, i_large, j_large, k_large, + element]) # We prolong the viscous flux dotted with respect the outward normal # on the small element. We scale by -1/2 here because the normal @@ -820,7 +831,7 @@ function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, k_large += k_large_step_j end - # Interpolate large element face data from buffer to small face locations + # Interpolate large element face data from buffer to small face locations multiply_dimensionwise!(view(cache.mortars.u, 2, :, 1, :, :, mortar), mortar_l2.forward_lower, mortar_l2.forward_lower, @@ -862,7 +873,7 @@ function calc_mortar_flux_divergence!(surface_flux_values, # Choose thread-specific pre-allocated container fstar = fstar_threaded[Threads.threadid()] fstar_tmp = fstar_tmp_threaded[Threads.threadid()] - + # Get index information on the small elements small_indices = node_indices[1, mortar] small_direction = indices2direction(small_indices) @@ -874,7 +885,6 @@ function calc_mortar_flux_divergence!(surface_flux_values, k_small_start, k_small_step_i, k_small_step_j = index_to_start_step_3d(small_indices[3], index_range) - for position in 1:4 i_small = i_small_start j_small = j_small_start @@ -882,13 +892,15 @@ function calc_mortar_flux_divergence!(surface_flux_values, element = neighbor_ids[position, mortar] for j in eachnode(dg) for i in eachnode(dg) - for v in eachvariable(equations) - viscous_flux_normal_ll = cache.mortars.u[1, v, position, i, j , mortar] - viscous_flux_normal_rr = cache.mortars.u[2, v, position, i, j , mortar] + viscous_flux_normal_ll = cache.mortars.u[1, v, position, i, j, + mortar] + viscous_flux_normal_rr = cache.mortars.u[2, v, position, i, j, + mortar] # TODO: parabolic; only BR1 at the moment - fstar[v, i, j, position] = 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) + fstar[v, i, j, position] = 0.5 * (viscous_flux_normal_ll + + viscous_flux_normal_rr) end i_small += i_small_step_i @@ -919,7 +931,7 @@ end # hyperbolic terms with conserved terms only, i.e., no nonconservative terms. @inline function calc_mortar_flux!(fstar, mesh::P4estMesh{3}, - nonconservative_terms::False, + nonconservative_terms::False, equations::AbstractEquationsParabolic, surface_integral, dg::DG, cache, mortar_index, position_index, normal_direction, @@ -928,13 +940,13 @@ end @unpack surface_flux = surface_integral u_ll, u_rr = get_surface_node_vars(u, equations, dg, position_index, i_node_index, - j_node_index,mortar_index) + j_node_index, mortar_index) # TODO: parabolic; only BR1 at the moment flux_ = 0.5 * (u_ll + u_rr) -# # Copy flux to buffer -# set_node_vars!(fstar, flux, equations, dg, i_node_index, j_node_index, -# position_index) + # # Copy flux to buffer + # set_node_vars!(fstar, flux, equations, dg, i_node_index, j_node_index, + # position_index) # Copy flux to buffer set_node_vars!(fstar, flux_, equations, dg, i_node_index, j_node_index, position_index) end @@ -1067,4 +1079,4 @@ function calc_boundary_flux!(cache, t, k_node += k_node_step_j end end -end \ No newline at end of file +end From 5cbbb40255b6a2223f053179716ba545b53c472d Mon Sep 17 00:00:00 2001 From: Ahmad Peyvan Date: Sat, 2 Dec 2023 09:59:54 -0500 Subject: [PATCH 065/138] test formatting --- test/test_parabolic_3d.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index df6a9ce9a24..78f8731c407 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -404,6 +404,14 @@ end ) end + @trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex_amr.jl"), + initial_refinement_level = 0, tspan=(0.0, 0.5), + l2 = [0.0016588740573444188, 0.03437058632045721, 0.03437058632045671, 0.041038898400430075, 0.30978593009044153], + linf = [0.004173569912012121, 0.09168674832979556, 0.09168674832975021, 0.12129218723807476, 0.8433893297612087] + ) + end + @trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_amr.jl"), l2 = [0.000355780485397024], From 9ca962ef8b1335a87826093af277ac20c7d7e812 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:36:17 +0100 Subject: [PATCH 066/138] Update src/Trixi.jl --- src/Trixi.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Trixi.jl b/src/Trixi.jl index e984c267c62..e18b2f6415c 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -212,7 +212,7 @@ export initial_condition_eoc_test_coupled_euler_gravity, export cons2cons, cons2prim, prim2cons, cons2macroscopic, cons2state, cons2mean, cons2entropy, entropy2cons -export density, pressure, density_pressure, velocity, v1, v2, v3, global_mean_vars, +export density, pressure, density_pressure, velocity, global_mean_vars, equilibrium_distribution, waterheight_pressure export entropy, energy_total, energy_kinetic, energy_internal, energy_magnetic, cross_helicity, From b039c2859d988189d5949aa716b02b0ad7abbabb Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:39:28 +0100 Subject: [PATCH 067/138] Update src/equations/compressible_euler_1d.jl --- src/equations/compressible_euler_1d.jl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/equations/compressible_euler_1d.jl b/src/equations/compressible_euler_1d.jl index a96ce6ba50b..05c38ce791d 100644 --- a/src/equations/compressible_euler_1d.jl +++ b/src/equations/compressible_euler_1d.jl @@ -945,11 +945,6 @@ end return rho_times_p end -@inline function v1(u, equations::CompressibleEulerEquations1D) - rho, rho_v1, _ = u - return rho_v1 / rho -end - # Calculate thermodynamic entropy for a conservative state `cons` @inline function entropy_thermodynamic(cons, equations::CompressibleEulerEquations1D) # Pressure From 491101f4a3c35f5ac6c2a91cc46aa21a5b1f1d25 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:39:50 +0100 Subject: [PATCH 068/138] Update src/equations/compressible_euler_2d.jl --- src/equations/compressible_euler_2d.jl | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 1944c45d597..a992f99eaf4 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1454,16 +1454,6 @@ end return rho_times_p end -@inline function v1(u, equations::CompressibleEulerEquations2D) - rho, rho_v1, _, _ = u - return rho_v1 / rho -end - -@inline function v2(u, equations::CompressibleEulerEquations2D) - rho, _, rho_v2, _ = u - return rho_v2 / rho -end - # Calculates the entropy flux in direction "orientation" and the entropy variables for a state cons # NOTE: This method seems to work currently (b82534e) but is never used anywhere. Thus it is # commented here until someone uses it or writes a test for it. From dc396a39ecb5ab9e6fd0fc328b1c275dd736fb37 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:40:08 +0100 Subject: [PATCH 069/138] Update src/equations/compressible_euler_3d.jl --- src/equations/compressible_euler_3d.jl | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/equations/compressible_euler_3d.jl b/src/equations/compressible_euler_3d.jl index 721a88ddc9b..fc56f58025b 100644 --- a/src/equations/compressible_euler_3d.jl +++ b/src/equations/compressible_euler_3d.jl @@ -1540,21 +1540,6 @@ end return rho_times_p end -@inline function v1(u, equations::CompressibleEulerEquations3D) - rho, rho_v1, _, _, _ = u - return rho_v1 / rho -end - -@inline function v2(u, equations::CompressibleEulerEquations3D) - rho, _, rho_v2, _, _ = u - return rho_v2 / rho -end - -@inline function v3(u, equations::CompressibleEulerEquations3D) - rho, _, _, rho_v3, _ = u - return rho_v3 / rho -end - # Calculate thermodynamic entropy for a conservative state `u` @inline function entropy_thermodynamic(u, equations::CompressibleEulerEquations3D) rho, _ = u From 6dee30849975ae25af81f4c1d91c7d0b73841673 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:42:04 +0100 Subject: [PATCH 070/138] Update src/solvers/dgsem_tree/container_viscous_2d.jl --- src/solvers/dgsem_tree/container_viscous_2d.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/solvers/dgsem_tree/container_viscous_2d.jl b/src/solvers/dgsem_tree/container_viscous_2d.jl index fd28e12a99a..db90b3e8821 100644 --- a/src/solvers/dgsem_tree/container_viscous_2d.jl +++ b/src/solvers/dgsem_tree/container_viscous_2d.jl @@ -1,5 +1,10 @@ mutable struct ViscousContainer2D{uEltype <: Real} u_transformed::Array{uEltype, 4} + # Using an outer fixed-size datastructure leads to nasty implementations, + # see https://github.com/trixi-framework/Trixi.jl/pull/1629#discussion_r1355293953. + # Also: This does not result in speed up compared to using tuples for the internal + # datastructures, see + # https://github.com/trixi-framework/Trixi.jl/pull/1629#discussion_r1363352188. gradients::Vector{Array{uEltype, 4}} flux_viscous::Vector{Array{uEltype, 4}} From 7789b9f936efbc159145e709c0e7059ef0b80c3e Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:42:30 +0100 Subject: [PATCH 071/138] Update src/solvers/dgsem_tree/container_viscous_2d.jl --- src/solvers/dgsem_tree/container_viscous_2d.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/container_viscous_2d.jl b/src/solvers/dgsem_tree/container_viscous_2d.jl index db90b3e8821..d706111fc87 100644 --- a/src/solvers/dgsem_tree/container_viscous_2d.jl +++ b/src/solvers/dgsem_tree/container_viscous_2d.jl @@ -10,8 +10,9 @@ mutable struct ViscousContainer2D{uEltype <: Real} # internal `resize!`able storage _u_transformed::Vector{uEltype} - _gradients::Vector{Vector{uEltype}} - _flux_viscous::Vector{Vector{uEltype}} + # Use Tuple for outer, fixed-size datastructure + _gradients::Tuple{Vector{uEltype}, Vector{uEltype}} + _flux_viscous::Tuple{Vector{uEltype}, Vector{uEltype}} function ViscousContainer2D{uEltype}(n_vars::Integer, n_nodes::Integer, n_elements::Integer) where {uEltype <: Real} From d77046d3e578c867295444dc564b7acf0b064a7b Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:42:52 +0100 Subject: [PATCH 072/138] Update src/solvers/dgsem_tree/container_viscous_2d.jl --- src/solvers/dgsem_tree/container_viscous_2d.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/container_viscous_2d.jl b/src/solvers/dgsem_tree/container_viscous_2d.jl index d706111fc87..bd7ff413af5 100644 --- a/src/solvers/dgsem_tree/container_viscous_2d.jl +++ b/src/solvers/dgsem_tree/container_viscous_2d.jl @@ -20,8 +20,10 @@ mutable struct ViscousContainer2D{uEltype <: Real} [Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements) for _ in 1:2], [Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements) for _ in 1:2], Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements), - [Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements) for _ in 1:2], - [Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements) for _ in 1:2]) + (Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements)), + (Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements))) end end From 3ca6542eb760f04aa4f538aabf933646ea023b23 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:43:18 +0100 Subject: [PATCH 073/138] Update src/solvers/dgsem_tree/container_viscous_3d.jl --- src/solvers/dgsem_tree/container_viscous_3d.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/solvers/dgsem_tree/container_viscous_3d.jl b/src/solvers/dgsem_tree/container_viscous_3d.jl index 6eec0c61279..20369bb17f2 100644 --- a/src/solvers/dgsem_tree/container_viscous_3d.jl +++ b/src/solvers/dgsem_tree/container_viscous_3d.jl @@ -1,5 +1,10 @@ mutable struct ViscousContainer3D{uEltype <: Real} u_transformed::Array{uEltype, 5} + # Using an outer fixed-size datastructure leads to nasty implementations, + # see https://github.com/trixi-framework/Trixi.jl/pull/1629#discussion_r1355293953. + # Also: This does not result in speed up compared to using tuples for the internal + # datastructures, see + # https://github.com/trixi-framework/Trixi.jl/pull/1629#discussion_r1363352188. gradients::Vector{Array{uEltype, 5}} flux_viscous::Vector{Array{uEltype, 5}} From 72c51311611079733dbfe88e14ac99b13211a8b9 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:43:41 +0100 Subject: [PATCH 074/138] Update src/solvers/dgsem_tree/container_viscous_3d.jl --- src/solvers/dgsem_tree/container_viscous_3d.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/container_viscous_3d.jl b/src/solvers/dgsem_tree/container_viscous_3d.jl index 20369bb17f2..ae726dbefc1 100644 --- a/src/solvers/dgsem_tree/container_viscous_3d.jl +++ b/src/solvers/dgsem_tree/container_viscous_3d.jl @@ -10,8 +10,9 @@ mutable struct ViscousContainer3D{uEltype <: Real} # internal `resize!`able storage _u_transformed::Vector{uEltype} - _gradients::Vector{Vector{uEltype}} - _flux_viscous::Vector{Vector{uEltype}} + # Use Tuple for outer, fixed-size datastructure + _gradients::Tuple{Vector{uEltype}, Vector{uEltype}, Vector{uEltype}} + _flux_viscous::Tuple{Vector{uEltype}, Vector{uEltype}, Vector{uEltype}} function ViscousContainer3D{uEltype}(n_vars::Integer, n_nodes::Integer, n_elements::Integer) where {uEltype <: Real} From 70f9f4c6252fff83625788f10b8c4b51c06fdbd1 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:44:20 +0100 Subject: [PATCH 075/138] Update src/solvers/dgsem_tree/container_viscous_3d.jl --- src/solvers/dgsem_tree/container_viscous_3d.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/container_viscous_3d.jl b/src/solvers/dgsem_tree/container_viscous_3d.jl index ae726dbefc1..64d283fe189 100644 --- a/src/solvers/dgsem_tree/container_viscous_3d.jl +++ b/src/solvers/dgsem_tree/container_viscous_3d.jl @@ -22,8 +22,12 @@ mutable struct ViscousContainer3D{uEltype <: Real} [Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) for _ in 1:3], Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), - [Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements) for _ in 1:3], - [Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements) for _ in 1:3]) + (Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements)), + (Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements))) end end From 1470879dd42ff556c5a76c188de252217bbd55ee Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:44:47 +0100 Subject: [PATCH 076/138] Update src/solvers/dgsem_p4est/dg_2d_parabolic.jl --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 0e4fd276849..f6ac5f1c5cc 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -9,7 +9,6 @@ function create_cache_parabolic(mesh::P4estMesh{2}, equations_hyperbolic::Abstra elements = init_elements(mesh, equations_hyperbolic, dg.basis, uEltype) interfaces = init_interfaces(mesh, equations_hyperbolic, dg.basis, elements) boundaries = init_boundaries(mesh, equations_hyperbolic, dg.basis, elements) - mortars = init_mortars(mesh, equations_hyperbolic, dg.basis, elements) viscous_container = init_viscous_container_2d(nvariables(equations_hyperbolic), nnodes(dg.basis), nelements(elements), From 030713b2054daaa102b93821610ca1ed4cb0e90e Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:45:02 +0100 Subject: [PATCH 077/138] Update src/solvers/dgsem_p4est/dg_2d_parabolic.jl --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index f6ac5f1c5cc..db5a1e9a40f 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -14,7 +14,7 @@ function create_cache_parabolic(mesh::P4estMesh{2}, equations_hyperbolic::Abstra nnodes(dg.basis), nelements(elements), uEltype) - cache = (; elements, interfaces, boundaries, mortars, viscous_container) + cache = (; elements, interfaces, boundaries, viscous_container) return cache end From d9c3f2f4174e8c5df7020215b64d37d4f25065c0 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:45:40 +0100 Subject: [PATCH 078/138] Update src/solvers/dgsem_tree/dg_2d_parabolic.jl --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 3ad165bb174..bec840b73ad 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -133,7 +133,7 @@ function transform_variables!(u_transformed, u, mesh::Union{TreeMesh{2}, P4estMe end # This is the version used when calculating the divergence of the viscous fluxes -function calc_volume_integral!(du, flux_viscous::Vector{Array{uEltype, 4}}, +function calc_volume_integral!(du, flux_viscous, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, dg::DGSEM, cache) where {uEltype <: Real} From f836e8e22658d57cf2a4c3689ac07064a837f314 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:45:59 +0100 Subject: [PATCH 079/138] Update src/solvers/dgsem_tree/dg_2d_parabolic.jl --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index bec840b73ad..ff017371c76 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -136,7 +136,7 @@ end function calc_volume_integral!(du, flux_viscous, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, - dg::DGSEM, cache) where {uEltype <: Real} + dg::DGSEM, cache) @unpack derivative_dhat = dg.basis flux_viscous_x, flux_viscous_y = flux_viscous From 97b546c123746e736ec36a7c0d5f1a0ebec249c7 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:46:14 +0100 Subject: [PATCH 080/138] Update src/solvers/dgsem_tree/dg_2d_parabolic.jl --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index ff017371c76..2a46dab0fde 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -165,7 +165,7 @@ end # This is the version used when calculating the divergence of the viscous fluxes # We pass the `surface_integral` argument solely for dispatch -function prolong2interfaces!(cache_parabolic, flux_viscous::Vector{Array{uEltype, 4}}, +function prolong2interfaces!(cache_parabolic, flux_viscous, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) where {uEltype <: Real} From 1a70b137a1f67c7a431d349ca4b6436df7c58f1a Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:46:28 +0100 Subject: [PATCH 081/138] Update src/solvers/dgsem_tree/dg_2d_parabolic.jl --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 2a46dab0fde..afa8e59aebe 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -168,7 +168,7 @@ end function prolong2interfaces!(cache_parabolic, flux_viscous, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) where {uEltype <: Real} + surface_integral, dg::DG, cache) @unpack interfaces = cache_parabolic @unpack orientations, neighbor_ids = interfaces interfaces_u = interfaces.u From b0438ab6ad0819f1c2f7e195130bd2b94135f0c6 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:46:42 +0100 Subject: [PATCH 082/138] Update src/solvers/dgsem_tree/dg_2d_parabolic.jl --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index afa8e59aebe..192e5c89cc5 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -242,7 +242,7 @@ function calc_interface_flux!(surface_flux_values, end # This is the version used when calculating the divergence of the viscous fluxes -function prolong2boundaries!(cache_parabolic, flux_viscous::Vector{Array{uEltype, 4}}, +function prolong2boundaries!(cache_parabolic, flux_viscous, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) where {uEltype <: Real} From b499d2cdb5d9c93e239ac09506d6ca819c158188 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:46:56 +0100 Subject: [PATCH 083/138] Update src/solvers/dgsem_tree/dg_2d_parabolic.jl --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 192e5c89cc5..e9c298ea123 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -245,7 +245,7 @@ end function prolong2boundaries!(cache_parabolic, flux_viscous, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) where {uEltype <: Real} + surface_integral, dg::DG, cache) @unpack boundaries = cache_parabolic @unpack orientations, neighbor_sides, neighbor_ids = boundaries boundaries_u = boundaries.u From 2d1e2035465ea257d5b0810eed1ef63c8f0cec5c Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:47:22 +0100 Subject: [PATCH 084/138] Update src/solvers/dgsem_tree/dg_2d_parabolic.jl --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index e9c298ea123..93c1891cdbf 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -291,8 +291,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, return nothing end -function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 4}}, - gradients::Vector{Array{uEltype, 4}}, u_transformed, +function calc_viscous_fluxes!(flux_viscous, + gradients, u_transformed, mesh::Union{TreeMesh{2}, P4estMesh{2}}, equations_parabolic::AbstractEquationsParabolic, dg::DG, cache, cache_parabolic) where {uEltype <: Real} From 5aa086a294e41d2b370e6b2e6ad2fe4cc6be5c4d Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:47:42 +0100 Subject: [PATCH 085/138] Update src/solvers/dgsem_tree/dg_2d_parabolic.jl --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 93c1891cdbf..252ed929b7a 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -295,7 +295,7 @@ function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, mesh::Union{TreeMesh{2}, P4estMesh{2}}, equations_parabolic::AbstractEquationsParabolic, - dg::DG, cache, cache_parabolic) where {uEltype <: Real} + dg::DG, cache, cache_parabolic) gradients_x, gradients_y = gradients flux_viscous_x, flux_viscous_y = flux_viscous # output arrays From c555239ccc38a82eba413d019c2f47fb2b3943ad Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:48:03 +0100 Subject: [PATCH 086/138] Update src/solvers/dgsem_tree/dg_2d_parabolic.jl --- src/solvers/dgsem_tree/dg_2d_parabolic.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 252ed929b7a..3083ae30680 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -511,6 +511,11 @@ function calc_boundary_flux_by_direction_divergence!(surface_flux_values::Abstra return nothing end +# `cache` is the hyperbolic cache, i.e., in particular not `cache_parabolic`. +# This is because mortar handling is done in the (hyperbolic) `cache`. +# Specialization `flux_viscous::Vector{Array{uEltype, 4}}` needed since +#`prolong2mortars!` in dg_2d.jl is used for both purely hyperbolic and +# hyperbolic-parabolic systems. function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, From da13ebbd0d82b4f3d74dcbf2b64291aad946b386 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:51:23 +0100 Subject: [PATCH 087/138] Update test/test_parabolic_3d.jl --- test/test_parabolic_3d.jl | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 78f8731c407..00cab252341 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -396,13 +396,33 @@ end end end - @trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.25), - l2 = [0.0001547509861140407, 0.015637861347119624, 0.015637861347119687, 0.022024699158522523, 0.009711013505930812], - linf = [0.0006696415247340326, 0.03442565722527785, 0.03442565722577423, 0.06295407168705314, 0.032857472756916195] - ) - end +@trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl"), + initial_refinement_level=2, tspan=(0.0, 0.25), + l2=[ + 0.0001547509861140407, + 0.015637861347119624, + 0.015637861347119687, + 0.022024699158522523, + 0.009711013505930812, + ], + linf=[ + 0.0006696415247340326, + 0.03442565722527785, + 0.03442565722577423, + 0.06295407168705314, + 0.032857472756916195, + ]) + # 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 "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex_amr.jl"), From 020c5a974af433cdf8bbf70061f4bb19ad09a98b Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:52:27 +0100 Subject: [PATCH 088/138] Update src/solvers/dgsem_tree/dg_3d_parabolic.jl --- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index d971410199d..1e795efca0b 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -133,7 +133,7 @@ function transform_variables!(u_transformed, u, mesh::Union{TreeMesh{3}, P4estMe end # This is the version used when calculating the divergence of the viscous fluxes -function calc_volume_integral!(du, flux_viscous::Vector{Array{uEltype, 5}}, +function calc_volume_integral!(du, flux_viscous, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, dg::DGSEM, cache) where {uEltype <: Real} From 33d8122bc3ee2f8196e402ae519b648ff4e62cc8 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:52:41 +0100 Subject: [PATCH 089/138] Update src/solvers/dgsem_tree/dg_3d_parabolic.jl --- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index 1e795efca0b..0eda6bfd6ce 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -136,7 +136,7 @@ end function calc_volume_integral!(du, flux_viscous, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, - dg::DGSEM, cache) where {uEltype <: Real} + dg::DGSEM, cache) @unpack derivative_dhat = dg.basis flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous From cfebbd3bc750cd6db252538588c09d8c7ced6832 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:53:00 +0100 Subject: [PATCH 090/138] Update src/solvers/dgsem_tree/dg_3d_parabolic.jl --- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index 0eda6bfd6ce..2270f0eb1c4 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -172,7 +172,7 @@ end # This is the version used when calculating the divergence of the viscous fluxes # We pass the `surface_integral` argument solely for dispatch -function prolong2interfaces!(cache_parabolic, flux_viscous::Vector{Array{uEltype, 5}}, +function prolong2interfaces!(cache_parabolic, flux_viscous, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) where {uEltype <: Real} From 1547c156889a1cb732078bb3599c5e6c102858bd Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:53:14 +0100 Subject: [PATCH 091/138] Update src/solvers/dgsem_tree/dg_3d_parabolic.jl --- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index 2270f0eb1c4..968b58fd3b7 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -175,7 +175,7 @@ end function prolong2interfaces!(cache_parabolic, flux_viscous, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) where {uEltype <: Real} + surface_integral, dg::DG, cache) @unpack interfaces = cache_parabolic @unpack orientations, neighbor_ids = interfaces interfaces_u = interfaces.u From 151905d5db732ba35dbefc9274b089f449483a10 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:53:33 +0100 Subject: [PATCH 092/138] Update src/solvers/dgsem_tree/dg_3d_parabolic.jl --- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index 968b58fd3b7..36ac11376db 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -263,7 +263,7 @@ function calc_interface_flux!(surface_flux_values, end # This is the version used when calculating the divergence of the viscous fluxes -function prolong2boundaries!(cache_parabolic, flux_viscous::Vector{Array{uEltype, 5}}, +function prolong2boundaries!(cache_parabolic, flux_viscous, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) where {uEltype <: Real} From 31fbcb64b37c4d434b8362a0ab93fb924ecbc906 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:53:45 +0100 Subject: [PATCH 093/138] Update src/solvers/dgsem_tree/dg_3d_parabolic.jl --- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index 36ac11376db..cb699142f8a 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -266,7 +266,7 @@ end function prolong2boundaries!(cache_parabolic, flux_viscous, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) where {uEltype <: Real} + surface_integral, dg::DG, cache) @unpack boundaries = cache_parabolic @unpack orientations, neighbor_sides, neighbor_ids = boundaries boundaries_u = boundaries.u From 6f8b0057c60e8fbe7283945b4a4d0d18ecd8546f Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:54:03 +0100 Subject: [PATCH 094/138] Update src/solvers/dgsem_tree/dg_3d_parabolic.jl --- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index cb699142f8a..dae24385d1c 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -339,8 +339,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, return nothing end -function calc_viscous_fluxes!(flux_viscous::Vector{Array{uEltype, 5}}, - gradients::Vector{Array{uEltype, 5}}, u_transformed, +function calc_viscous_fluxes!(flux_viscous, + gradients, u_transformed, mesh::Union{TreeMesh{3}, P4estMesh{3}}, equations_parabolic::AbstractEquationsParabolic, dg::DG, cache, cache_parabolic) where {uEltype <: Real} From 953d81bddf6878f315f5e530d81048e45abfe68b Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:54:19 +0100 Subject: [PATCH 095/138] Update src/solvers/dgsem_tree/dg_3d_parabolic.jl --- src/solvers/dgsem_tree/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index dae24385d1c..9ad28c6aa8e 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -343,7 +343,7 @@ function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, mesh::Union{TreeMesh{3}, P4estMesh{3}}, equations_parabolic::AbstractEquationsParabolic, - dg::DG, cache, cache_parabolic) where {uEltype <: Real} + dg::DG, cache, cache_parabolic) gradients_x, gradients_y, gradients_z = gradients flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous # output arrays From 0a5ef79fb1087e61d0b042b894a8e1804f997d4c Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:56:49 +0100 Subject: [PATCH 096/138] Update src/solvers/dgsem_p4est/dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 1e1234216a8..3e69cdca8d2 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -102,8 +102,6 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, dg.surface_integral, dg) end - # # TODO: parabolic; extend to mortars - # @assert nmortars(dg, cache) == 0 # Prolong solution to mortars (specialized for AbstractEquationsParabolic) # !!! NOTE: we reuse the hyperbolic cache here since it contains "mortars" and "u_threaded" From c7345f85b8b7cfcb4c37d1b10feb61897f845a07 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:57:19 +0100 Subject: [PATCH 097/138] Update src/solvers/dgsem_p4est/dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 3e69cdca8d2..863bb6734d1 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -243,8 +243,6 @@ function calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, dg.surface_integral, dg) end - # # TODO: parabolic; mortars - # @assert nmortars(dg, cache) == 0 # Prolong solution to mortars. These should reuse the hyperbolic version of `prolong2mortars` # !!! NOTE: we reuse the hyperbolic cache here, since it contains both `mortars` and `u_threaded`. From a38060b679d096a1882bc14fb763d64d1762acc5 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 09:59:28 +0100 Subject: [PATCH 098/138] Update src/solvers/dgsem_p4est/dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 863bb6734d1..b09cb2fd29c 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -719,10 +719,10 @@ function calc_interface_flux!(surface_flux_values, return nothing end -function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, 5}}, +function prolong2mortars_divergence!(cache, flux_viscous, mesh::Union{P4estMesh{3}, T8codeMesh{3}}, equations, mortar_l2::LobattoLegendreMortarL2, - surface_integral, dg::DGSEM) where {uEltype <: Real} + surface_integral, dg::DGSEM) @unpack neighbor_ids, node_indices = cache.mortars @unpack fstar_tmp_threaded = cache @unpack contravariant_vectors = cache.elements From 42b4b874447fb974093441a0c69924db852c9768 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:00:30 +0100 Subject: [PATCH 099/138] Update src/solvers/dgsem_p4est/dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index b09cb2fd29c..9243f635f9e 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -940,9 +940,6 @@ end # TODO: parabolic; only BR1 at the moment flux_ = 0.5 * (u_ll + u_rr) - # # Copy flux to buffer - # set_node_vars!(fstar, flux, equations, dg, i_node_index, j_node_index, - # position_index) # Copy flux to buffer set_node_vars!(fstar, flux_, equations, dg, i_node_index, j_node_index, position_index) end From 85340f78d45d64a638b18259055c9267bb771b65 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:01:59 +0100 Subject: [PATCH 100/138] Update src/solvers/dgsem_p4est/dg_2d_parabolic.jl --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index db5a1e9a40f..647c0e8bb1e 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -732,6 +732,7 @@ function calc_mortar_flux_divergence!(surface_flux_values, return nothing end + # We structure `calc_interface_flux!` similarly to "calc_mortar_flux!" for # hyperbolic equations with no nonconservative terms. # The reasoning is that parabolic fluxes are treated like conservative From 0dd0b69e033d39f6482bf91b24d123a5e25c3bf9 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:02:21 +0100 Subject: [PATCH 101/138] Update src/solvers/dgsem_p4est/dg_2d.jl --- src/solvers/dgsem_p4est/dg_2d.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solvers/dgsem_p4est/dg_2d.jl b/src/solvers/dgsem_p4est/dg_2d.jl index 6a04c19e8a2..36624f2ce8a 100644 --- a/src/solvers/dgsem_p4est/dg_2d.jl +++ b/src/solvers/dgsem_p4est/dg_2d.jl @@ -569,6 +569,7 @@ end mortar_l2::LobattoLegendreMortarL2, dg::DGSEM, cache, mortar, fstar, u_buffer) @unpack neighbor_ids, node_indices = cache.mortars + # Copy solution small to small small_indices = node_indices[1, mortar] small_direction = indices2direction(small_indices) From d3586135f74bd78adbc25239b6183e0983254949 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:02:36 +0100 Subject: [PATCH 102/138] Update src/solvers/dgsem_p4est/dg_2d_parabolic.jl --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 647c0e8bb1e..8040cae843e 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -632,6 +632,7 @@ function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, normal_direction = get_normal_direction(direction_index, contravariant_vectors, i_small, j_small, element) + for v in eachvariable(equations) flux_viscous = SVector(flux_viscous_x[v, i_small, j_small, element], flux_viscous_y[v, i_small, j_small, element]) From 8e90da6d1f2b4fa81eff7d56ecdf6fdf8f513e3b Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:02:49 +0100 Subject: [PATCH 103/138] Update src/solvers/dgsem_p4est/dg_2d_parabolic.jl --- src/solvers/dgsem_p4est/dg_2d_parabolic.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index 8040cae843e..a7f3345168f 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -708,6 +708,7 @@ function calc_mortar_flux_divergence!(surface_flux_values, # Choose thread-specific pre-allocated container fstar = (fstar_lower_threaded[Threads.threadid()], fstar_upper_threaded[Threads.threadid()]) + for position in 1:2 for node in eachnode(dg) for v in eachvariable(equations) From 42752a6246718249b328f7885ad7e6cb8981fb7c Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:05:33 +0100 Subject: [PATCH 104/138] Update test/test_parabolic_3d.jl --- test/test_parabolic_3d.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 00cab252341..79c5fc286d9 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -430,6 +430,14 @@ end l2 = [0.0016588740573444188, 0.03437058632045721, 0.03437058632045671, 0.041038898400430075, 0.30978593009044153], linf = [0.004173569912012121, 0.09168674832979556, 0.09168674832975021, 0.12129218723807476, 0.8433893297612087] ) + # 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 "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin From 1d654589f2fd12c59e68420afde67dd6888260c7 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:06:09 +0100 Subject: [PATCH 105/138] Update test/test_parabolic_3d.jl --- test/test_parabolic_3d.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 79c5fc286d9..23a0ed336a2 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -445,6 +445,14 @@ end l2 = [0.000355780485397024], linf = [0.0010810770271614256] ) + # 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 "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin From 85074bd7ba3b52d0889c7b2854989f11d3e2fdd4 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:06:25 +0100 Subject: [PATCH 106/138] Update test/test_parabolic_3d.jl --- test/test_parabolic_3d.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 23a0ed336a2..cf452732f9e 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -460,6 +460,14 @@ end l2 = [0.0009808996243280868], linf = [0.01732621559135459] ) + # 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 From b3db182639a1d46fd5fbc9b568993e38ba7cb289 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:07:15 +0100 Subject: [PATCH 107/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl --- .../p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl index d0b5919714c..f65557210ad 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -93,10 +93,6 @@ save_solution = SaveSolutionCallback(interval=20, amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) -# amr_controller = ControllerThreeLevel(semi, amr_indicator, -# base_level=0, -# med_level=2, med_threshold=0.05, -# max_level=5, max_threshold=0.1) amr_controller = ControllerThreeLevel(semi, amr_indicator, base_level=0, med_level=1, med_threshold=0.05, From d82685c0af9d66ac54097f3116548b4e80dd289d Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:07:41 +0100 Subject: [PATCH 108/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl --- .../elixir_navierstokes_taylor_green_vortex_amr.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index 330d54da97e..3b5cdbe12ed 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -79,10 +79,6 @@ save_solution = SaveSolutionCallback(interval = 100, amr_indicator = IndicatorLöhner(semi, variable = vel_mag) -# amr_controller = ControllerThreeLevel(semi, amr_indicator, -# base_level=0, -# med_level=2, med_threshold=0.002, -# max_level=4, max_threshold=0.004) amr_controller = ControllerThreeLevel(semi, amr_indicator, base_level = 0, med_level = 1, med_threshold = 0.1, From f0895648b8efbf2c2fdf47b124c047c1e860d2ef Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:10:00 +0100 Subject: [PATCH 109/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl --- .../p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl index f65557210ad..ea5e66934d6 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -16,7 +16,7 @@ equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) -The classical inviscid Taylor-Green vortex. +The classical Taylor-Green vortex. """ function initial_condition_3d_blast_wave(x, t, equations::CompressibleEulerEquations3D) From a559e4fd4a4e607a040e3f04b26961f8cc42c4db Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:10:24 +0100 Subject: [PATCH 110/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl --- .../elixir_navierstokes_taylor_green_vortex_amr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index 3b5cdbe12ed..a850dc35391 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -16,7 +16,7 @@ equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) -The classical inviscid Taylor-Green vortex. +The classical Taylor-Green vortex. """ function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) From c1085a402b429f98a1ca5b680706dd717f482877 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:10:58 +0100 Subject: [PATCH 111/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl --- .../p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl index ea5e66934d6..2b4f04ea842 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -13,11 +13,6 @@ equations = CompressibleEulerEquations3D(1.4) equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), Prandtl=prandtl_number()) -""" - initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - -The classical Taylor-Green vortex. -""" function initial_condition_3d_blast_wave(x, t, equations::CompressibleEulerEquations3D) rho_c = 1.0 From e8b38a7f81f21e18b834b881e3afc9e4026a2e62 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:11:27 +0100 Subject: [PATCH 112/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl --- .../p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl index 2b4f04ea842..60beef73b67 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -102,7 +102,9 @@ alive_callback = AliveCallback(analysis_interval=analysis_interval,) callbacks = CallbackSet(summary_callback, analysis_callback, - alive_callback,amr_callback,save_solution) + alive_callback, + amr_callback, + save_solution) ############################################################################### # run the simulation From 125521398b6be571c3c28a6be9e67bc764a82210 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:12:11 +0100 Subject: [PATCH 113/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl --- .../elixir_navierstokes_taylor_green_vortex_amr.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index a850dc35391..53503adef8e 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -93,7 +93,9 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, - alive_callback, amr_callback, save_solution) + alive_callback, + amr_callback, + save_solution) ############################################################################### # run the simulation From 1b0a530c732db00cc26844264dc35ac434ea829d Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:12:25 +0100 Subject: [PATCH 114/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl --- .../p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl index 60beef73b67..4ea3e003890 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -74,7 +74,7 @@ semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabol ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.80) +tspan = (0.0, 0.8) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() From 5bb3ddcb3b1e8c1b7ca0eb876150454d979aa0f4 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:12:51 +0100 Subject: [PATCH 115/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl --- .../elixir_navierstokes_taylor_green_vortex_amr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index 53503adef8e..454781b8895 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -61,7 +61,7 @@ semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabol ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.50) +tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() From 6f6ecc0a9b58496cf18270f2f7b3098fc9b501a1 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:20:51 +0100 Subject: [PATCH 116/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl --- .../elixir_navierstokes_3d_blast_wave_amr.jl | 178 +++++++++++------- 1 file changed, 105 insertions(+), 73 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl index 4ea3e003890..935ff8d59c5 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -1,4 +1,3 @@ - using OrdinaryDiffEq using Trixi @@ -10,36 +9,36 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = + CompressibleNavierStokesDiffusion3D(equations, mu = mu(), Prandtl = prandtl_number()) function initial_condition_3d_blast_wave(x, t, equations::CompressibleEulerEquations3D) - - rho_c = 1.0 - p_c = 1.0 - u_c = 0.0 - - rho_o = 0.125 - p_o = 0.1 - u_o = 0.0 - - rc = 0.5 - r = sqrt(x[1]^2+x[2]^2+x[3]^2) - if r < rc - rho = rho_c - v1 = u_c - v2 = u_c - v3 = u_c - p = p_c - else - rho = rho_o - v1 = u_o - v2 = u_o - v3 = u_o - p = p_o - end - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + + rho_c = 1.0 + p_c = 1.0 + u_c = 0.0 + + rho_o = 0.125 + p_o = 0.1 + u_o = 0.0 + + rc = 0.5 + r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) + if r < rc + rho = rho_c + v1 = u_c + v2 = u_c + v3 = u_c + p = p_c + else + rho = rho_o + v1 = u_o + v2 = u_o + v3 = u_o + p = p_o + end + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_3d_blast_wave @@ -47,29 +46,44 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) - -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +indicator_sc = IndicatorHennemannGassner( + equations, + basis, + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure, +) +volume_integral = VolumeIntegralShockCapturingHG( + indicator_sc; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux, +) + +solver = + DGSEM(polydeg = polydeg, surface_flux = surface_flux, volume_integral = volume_integral) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi trees_per_dimension = (4, 4, 4) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, true, true), initial_refinement_level=1) +mesh = P4estMesh( + trees_per_dimension, + polydeg = 3, + coordinates_min = coordinates_min, + coordinates_max = coordinates_max, + periodicity = (true, true, true), + initial_refinement_level = 1, +) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition, solver) +semi = SemidiscretizationHyperbolicParabolic( + mesh, + (equations, equations_parabolic), + initial_condition, + solver, +) ############################################################################### # ODE solvers, callbacks etc. @@ -80,36 +94,54 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=20, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) - -amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=1, med_threshold=0.05, - max_level=4, max_threshold=0.1) -amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) - - -alive_callback = AliveCallback(analysis_interval=analysis_interval,) - -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - amr_callback, - save_solution) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +save_solution = SaveSolutionCallback( + interval = 20, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim, +) + +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) + +amr_controller = ControllerThreeLevel( + semi, + amr_indicator, + base_level = 0, + med_level = 1, + med_threshold = 0.05, + max_level = 4, + max_threshold = 0.1, +) +amr_callback = AMRCallback( + semi, + amr_controller, + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true, +) + + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +callbacks = CallbackSet( + summary_callback, + analysis_callback, + alive_callback, + amr_callback, + save_solution, +) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file +sol = solve( + ode, + RDPK3SpFSAL49(); + abstol = time_int_tol, + reltol = time_int_tol, + ode_default_options()..., + callback = callbacks, +) +summary_callback() # print the timer summary From d25c639355edc89826d181f2bab3dc1d227a9660 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:22:09 +0100 Subject: [PATCH 117/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl --- ...ir_navierstokes_taylor_green_vortex_amr.jl | 126 ++++++++++++------ 1 file changed, 83 insertions(+), 43 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index 454781b8895..78cd480e2aa 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -1,4 +1,3 @@ - using OrdinaryDiffEq using Trixi @@ -10,16 +9,18 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), - Prandtl = prandtl_number()) +equations_parabolic = + CompressibleNavierStokesDiffusion3D(equations, mu = mu(), Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - The classical Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, - equations::CompressibleEulerEquations3D) +function initial_condition_taylor_green_vortex( + x, + t, + equations::CompressibleEulerEquations3D, +) A = 1.0 # magnitude of speed Ms = 0.1 # maximum Mach number @@ -28,10 +29,17 @@ function initial_condition_taylor_green_vortex(x, t, v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) v3 = 0.0 p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + - 1.0 / 16.0 * A^2 * rho * - (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + - cos(2 * x[2]) * cos(2 * x[3])) + p = + p + + 1.0 / 16.0 * + A^2 * + rho * + ( + cos(2 * x[1]) * cos(2 * x[3]) + + 2 * cos(2 * x[2]) + + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3]) + ) return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @@ -43,20 +51,32 @@ initial_condition = initial_condition_taylor_green_vortex end volume_flux = flux_ranocha -solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM( + polydeg = 3, + surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux), +) coordinates_min = (-1.0, -1.0, -1.0) .* pi coordinates_max = (1.0, 1.0, 1.0) .* pi trees_per_dimension = (2, 2, 2) -mesh = P4estMesh(trees_per_dimension, polydeg = 3, - coordinates_min = coordinates_min, coordinates_max = coordinates_max, - periodicity = (true, true, true), initial_refinement_level = 0) - -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition, solver) +mesh = P4estMesh( + trees_per_dimension, + polydeg = 3, + coordinates_min = coordinates_min, + coordinates_max = coordinates_max, + periodicity = (true, true, true), + initial_refinement_level = 0, +) + +semi = SemidiscretizationHyperbolicParabolic( + mesh, + (equations, equations_parabolic), + initial_condition, + solver, +) ############################################################################### # ODE solvers, callbacks etc. @@ -67,40 +87,60 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = true, - extra_analysis_integrals = (energy_kinetic, - energy_internal, - enstrophy)) -save_solution = SaveSolutionCallback(interval = 100, - save_initial_solution = true, - save_final_solution = true, - solution_variables = cons2prim) +analysis_callback = AnalysisCallback( + semi, + interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, energy_internal, enstrophy), +) +save_solution = SaveSolutionCallback( + interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim, +) amr_indicator = IndicatorLöhner(semi, variable = vel_mag) -amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level = 0, - med_level = 1, med_threshold = 0.1, - max_level = 3, max_threshold = 0.2) - -amr_callback = AMRCallback(semi, amr_controller, - interval = 5, - adapt_initial_condition = false, - adapt_initial_condition_only_refine = false) +amr_controller = ControllerThreeLevel( + semi, + amr_indicator, + base_level = 0, + med_level = 1, + med_threshold = 0.1, + max_level = 3, + max_threshold = 0.2, +) + +amr_callback = AMRCallback( + semi, + amr_controller, + interval = 5, + adapt_initial_condition = false, + adapt_initial_condition_only_refine = false, +) alive_callback = AliveCallback(analysis_interval = analysis_interval) -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - amr_callback, - save_solution) +callbacks = CallbackSet( + summary_callback, + analysis_callback, + alive_callback, + amr_callback, + save_solution, +) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, - ode_default_options()..., callback = callbacks) +sol = solve( + ode, + RDPK3SpFSAL49(); + abstol = time_int_tol, + reltol = time_int_tol, + ode_default_options()..., + callback = callbacks, +) summary_callback() # print the timer summary + From 84d973d6305ce75ec501605c399ec3d4f332fa73 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:24:03 +0100 Subject: [PATCH 118/138] Update dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 1255 +++++++++++++------- 1 file changed, 835 insertions(+), 420 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 9243f635f9e..0f8d8592a9c 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -1,18 +1,27 @@ # This method is called when a SemidiscretizationHyperbolicParabolic is constructed. # It constructs the basic `cache` used throughout the simulation to compute # the RHS etc. -function create_cache_parabolic(mesh::P4estMesh{3}, equations_hyperbolic::AbstractEquations, - equations_parabolic::AbstractEquationsParabolic, - dg::DG, parabolic_scheme, RealT, uEltype) +function create_cache_parabolic( + mesh::P4estMesh{3}, + equations_hyperbolic::AbstractEquations, + equations_parabolic::AbstractEquationsParabolic, + dg::DG, + parabolic_scheme, + RealT, + uEltype, +) balance!(mesh) elements = init_elements(mesh, equations_hyperbolic, dg.basis, uEltype) interfaces = init_interfaces(mesh, equations_hyperbolic, dg.basis, elements) boundaries = init_boundaries(mesh, equations_hyperbolic, dg.basis, elements) - viscous_container = init_viscous_container_3d(nvariables(equations_hyperbolic), - nnodes(dg.basis), nelements(elements), - uEltype) + viscous_container = init_viscous_container_3d( + nvariables(equations_hyperbolic), + nnodes(dg.basis), + nelements(elements), + uEltype, + ) cache = (; elements, interfaces, boundaries, viscous_container) @@ -27,31 +36,66 @@ end # 2. compute f(u, grad(u)) # 3. compute div(f(u, grad(u))) (i.e., the "regular" rhs! call) # boundary conditions will be applied to both grad(u) and div(f(u, grad(u))). -# TODO: Remove in favor of the implementation for the TreeMesh +# TODO: Remove in favor of the implementation for the TreeMesh # once the P4estMesh can handle mortars as well -function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - initial_condition, boundary_conditions_parabolic, source_terms, - dg::DG, parabolic_scheme, cache, cache_parabolic) +function rhs_parabolic!( + du, + u, + t, + mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + initial_condition, + boundary_conditions_parabolic, + source_terms, + dg::DG, + parabolic_scheme, + cache, + cache_parabolic, +) @unpack viscous_container = cache_parabolic @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin - transform_variables!(u_transformed, u, mesh, equations_parabolic, - dg, parabolic_scheme, cache, cache_parabolic) + transform_variables!( + u_transformed, + u, + mesh, + equations_parabolic, + dg, + parabolic_scheme, + cache, + cache_parabolic, + ) end # Compute the gradients of the transformed variables @trixi_timeit timer() "calculate gradient" begin - calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, - boundary_conditions_parabolic, dg, cache, cache_parabolic) + calc_gradient!( + gradients, + u_transformed, + t, + mesh, + equations_parabolic, + boundary_conditions_parabolic, + dg, + cache, + cache_parabolic, + ) end # Compute and store the viscous fluxes @trixi_timeit timer() "calculate viscous fluxes" begin - calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, mesh, - equations_parabolic, dg, cache, cache_parabolic) + calc_viscous_fluxes!( + flux_viscous, + gradients, + u_transformed, + mesh, + equations_parabolic, + dg, + cache, + cache_parabolic, + ) end # The remainder of this function is essentially a regular rhs! for parabolic @@ -78,28 +122,52 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, # Prolong solution to interfaces @trixi_timeit timer() "prolong2interfaces" begin - prolong2interfaces!(cache_parabolic, flux_viscous, mesh, equations_parabolic, - dg.surface_integral, dg, cache) + prolong2interfaces!( + cache_parabolic, + flux_viscous, + mesh, + equations_parabolic, + dg.surface_integral, + dg, + cache, + ) end # Calculate interface fluxes @trixi_timeit timer() "interface flux" begin - calc_interface_flux!(cache_parabolic.elements.surface_flux_values, mesh, - equations_parabolic, dg, cache_parabolic) + calc_interface_flux!( + cache_parabolic.elements.surface_flux_values, + mesh, + equations_parabolic, + dg, + cache_parabolic, + ) end # Prolong solution to boundaries @trixi_timeit timer() "prolong2boundaries" begin - prolong2boundaries!(cache_parabolic, flux_viscous, mesh, equations_parabolic, - dg.surface_integral, dg, cache) + prolong2boundaries!( + cache_parabolic, + flux_viscous, + mesh, + equations_parabolic, + dg.surface_integral, + dg, + cache, + ) end # Calculate boundary fluxes @trixi_timeit timer() "boundary flux" begin - calc_boundary_flux_divergence!(cache_parabolic, t, - boundary_conditions_parabolic, - mesh, equations_parabolic, - dg.surface_integral, dg) + calc_boundary_flux_divergence!( + cache_parabolic, + t, + boundary_conditions_parabolic, + mesh, + equations_parabolic, + dg.surface_integral, + dg, + ) end @@ -107,21 +175,41 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, # !!! NOTE: we reuse the hyperbolic cache here since it contains "mortars" and "u_threaded" # !!! Is this OK? @trixi_timeit timer() "prolong2mortars" begin - prolong2mortars_divergence!(cache, flux_viscous, mesh, equations_parabolic, - dg.mortar, dg.surface_integral, dg) + prolong2mortars_divergence!( + cache, + flux_viscous, + mesh, + equations_parabolic, + dg.mortar, + dg.surface_integral, + dg, + ) end # Calculate mortar fluxes (specialized for AbstractEquationsParabolic) @trixi_timeit timer() "mortar flux" begin - calc_mortar_flux_divergence!(cache_parabolic.elements.surface_flux_values, - mesh, equations_parabolic, dg.mortar, - dg.surface_integral, dg, cache) + calc_mortar_flux_divergence!( + cache_parabolic.elements.surface_flux_values, + mesh, + equations_parabolic, + dg.mortar, + dg.surface_integral, + dg, + cache, + ) end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin - calc_surface_integral!(du, u, mesh, equations_parabolic, - dg.surface_integral, dg, cache_parabolic) + calc_surface_integral!( + du, + u, + mesh, + equations_parabolic, + dg.surface_integral, + dg, + cache_parabolic, + ) end # Apply Jacobian from mapping to reference element @@ -132,10 +220,17 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, return nothing end -function calc_gradient!(gradients, u_transformed, t, - mesh::P4estMesh{3}, equations_parabolic, - boundary_conditions_parabolic, dg::DG, - cache, cache_parabolic) +function calc_gradient!( + gradients, + u_transformed, + t, + mesh::P4estMesh{3}, + equations_parabolic, + boundary_conditions_parabolic, + dg::DG, + cache, + cache_parabolic, +) gradients_x, gradients_y, gradients_z = gradients # Reset du @@ -154,112 +249,201 @@ function calc_gradient!(gradients, u_transformed, t, # Calculate gradients with respect to reference coordinates in one element for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - u_node = get_node_vars(u_transformed, equations_parabolic, dg, i, j, k, - element) + u_node = + get_node_vars(u_transformed, equations_parabolic, dg, i, j, k, element) for ii in eachnode(dg) - multiply_add_to_node_vars!(gradients_x, derivative_dhat[ii, i], - u_node, equations_parabolic, dg, ii, j, - k, element) + multiply_add_to_node_vars!( + gradients_x, + derivative_dhat[ii, i], + u_node, + equations_parabolic, + dg, + ii, + j, + k, + element, + ) end for jj in eachnode(dg) - multiply_add_to_node_vars!(gradients_y, derivative_dhat[jj, j], - u_node, equations_parabolic, dg, i, jj, - k, element) + multiply_add_to_node_vars!( + gradients_y, + derivative_dhat[jj, j], + u_node, + equations_parabolic, + dg, + i, + jj, + k, + element, + ) end for kk in eachnode(dg) - multiply_add_to_node_vars!(gradients_z, derivative_dhat[kk, k], - u_node, equations_parabolic, dg, i, j, - kk, element) + multiply_add_to_node_vars!( + gradients_z, + derivative_dhat[kk, k], + u_node, + equations_parabolic, + dg, + i, + j, + kk, + element, + ) end end # now that the reference coordinate gradients are computed, transform them node-by-node to physical gradients # using the contravariant vectors for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - Ja11, Ja12, Ja13 = get_contravariant_vector(1, contravariant_vectors, - i, j, k, element) - Ja21, Ja22, Ja23 = get_contravariant_vector(2, contravariant_vectors, - i, j, k, element) - Ja31, Ja32, Ja33 = get_contravariant_vector(3, contravariant_vectors, - i, j, k, element) - - gradients_reference_1 = get_node_vars(gradients_x, equations_parabolic, dg, - i, j, k, element) - gradients_reference_2 = get_node_vars(gradients_y, equations_parabolic, dg, - i, j, k, element) - gradients_reference_3 = get_node_vars(gradients_z, equations_parabolic, dg, - i, j, k, element) + Ja11, Ja12, Ja13 = + get_contravariant_vector(1, contravariant_vectors, i, j, k, element) + Ja21, Ja22, Ja23 = + get_contravariant_vector(2, contravariant_vectors, i, j, k, element) + Ja31, Ja32, Ja33 = + get_contravariant_vector(3, contravariant_vectors, i, j, k, element) + + gradients_reference_1 = + get_node_vars(gradients_x, equations_parabolic, dg, i, j, k, element) + gradients_reference_2 = + get_node_vars(gradients_y, equations_parabolic, dg, i, j, k, element) + gradients_reference_3 = + get_node_vars(gradients_z, equations_parabolic, dg, i, j, k, element) # note that the contravariant vectors are transposed compared with computations of flux # divergences in `calc_volume_integral!`. See # https://github.com/trixi-framework/Trixi.jl/pull/1490#discussion_r1213345190 # for a more detailed discussion. - gradient_x_node = Ja11 * gradients_reference_1 + - Ja21 * gradients_reference_2 + - Ja31 * gradients_reference_3 - gradient_y_node = Ja12 * gradients_reference_1 + - Ja22 * gradients_reference_2 + - Ja32 * gradients_reference_3 - gradient_z_node = Ja13 * gradients_reference_1 + - Ja23 * gradients_reference_2 + - Ja33 * gradients_reference_3 - - set_node_vars!(gradients_x, gradient_x_node, equations_parabolic, dg, - i, j, k, element) - set_node_vars!(gradients_y, gradient_y_node, equations_parabolic, dg, - i, j, k, element) - set_node_vars!(gradients_z, gradient_z_node, equations_parabolic, dg, - i, j, k, element) + gradient_x_node = + Ja11 * gradients_reference_1 + + Ja21 * gradients_reference_2 + + Ja31 * gradients_reference_3 + gradient_y_node = + Ja12 * gradients_reference_1 + + Ja22 * gradients_reference_2 + + Ja32 * gradients_reference_3 + gradient_z_node = + Ja13 * gradients_reference_1 + + Ja23 * gradients_reference_2 + + Ja33 * gradients_reference_3 + + set_node_vars!( + gradients_x, + gradient_x_node, + equations_parabolic, + dg, + i, + j, + k, + element, + ) + set_node_vars!( + gradients_y, + gradient_y_node, + equations_parabolic, + dg, + i, + j, + k, + element, + ) + set_node_vars!( + gradients_z, + gradient_z_node, + equations_parabolic, + dg, + i, + j, + k, + element, + ) end end end # Prolong solution to interfaces @trixi_timeit timer() "prolong2interfaces" begin - prolong2interfaces!(cache_parabolic, u_transformed, mesh, - equations_parabolic, dg.surface_integral, dg) + prolong2interfaces!( + cache_parabolic, + u_transformed, + mesh, + equations_parabolic, + dg.surface_integral, + dg, + ) end # Calculate interface fluxes for the gradient. This reuses P4est `calc_interface_flux!` along with a # specialization for AbstractEquationsParabolic. @trixi_timeit timer() "interface flux" begin - calc_interface_flux!(cache_parabolic.elements.surface_flux_values, - mesh, False(), # False() = no nonconservative terms - equations_parabolic, dg.surface_integral, dg, cache_parabolic) + calc_interface_flux!( + cache_parabolic.elements.surface_flux_values, + mesh, + False(), # False() = no nonconservative terms + equations_parabolic, + dg.surface_integral, + dg, + cache_parabolic, + ) end # Prolong solution to boundaries @trixi_timeit timer() "prolong2boundaries" begin - prolong2boundaries!(cache_parabolic, u_transformed, mesh, - equations_parabolic, dg.surface_integral, dg) + prolong2boundaries!( + cache_parabolic, + u_transformed, + mesh, + equations_parabolic, + dg.surface_integral, + dg, + ) end # Calculate boundary fluxes @trixi_timeit timer() "boundary flux" begin - calc_boundary_flux_gradients!(cache_parabolic, t, boundary_conditions_parabolic, - mesh, equations_parabolic, dg.surface_integral, dg) + calc_boundary_flux_gradients!( + cache_parabolic, + t, + boundary_conditions_parabolic, + mesh, + equations_parabolic, + dg.surface_integral, + dg, + ) end # Prolong solution to mortars. These should reuse the hyperbolic version of `prolong2mortars` - # !!! NOTE: we reuse the hyperbolic cache here, since it contains both `mortars` and `u_threaded`. + # !!! NOTE: we reuse the hyperbolic cache here, since it contains both `mortars` and `u_threaded`. # !!! should we have a separate mortars/u_threaded in cache_parabolic? @trixi_timeit timer() "prolong2mortars" begin - prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, - dg.mortar, dg.surface_integral, dg) + prolong2mortars!( + cache, + u_transformed, + mesh, + equations_parabolic, + dg.mortar, + dg.surface_integral, + dg, + ) end # Calculate mortar fluxes. These should reuse the hyperbolic version of `calc_mortar_flux`, - # along with a specialization on `calc_mortar_flux!` and `mortar_fluxes_to_elements!` for - # AbstractEquationsParabolic. + # along with a specialization on `calc_mortar_flux!` and `mortar_fluxes_to_elements!` for + # AbstractEquationsParabolic. @trixi_timeit timer() "mortar flux" begin - calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, - mesh, False(), # False() = no nonconservative terms - equations_parabolic, - dg.mortar, dg.surface_integral, dg, cache) + calc_mortar_flux!( + cache_parabolic.elements.surface_flux_values, + mesh, + False(), # False() = no nonconservative terms + equations_parabolic, + dg.mortar, + dg.surface_integral, + dg, + cache, + ) end # Calculate surface integrals @@ -276,64 +460,85 @@ function calc_gradient!(gradients, u_transformed, t, @threaded for element in eachelement(dg, cache) for l in eachnode(dg), m in eachnode(dg) for v in eachvariable(equations_parabolic) - for dim in 1:3 + for dim = 1:3 grad = gradients[dim] # surface at -x - normal_direction = get_normal_direction(1, contravariant_vectors, - 1, l, m, element) - grad[v, 1, l, m, element] = (grad[v, 1, l, m, element] + - surface_flux_values[v, l, m, 1, - element] * - factor_1 * normal_direction[dim]) + normal_direction = + get_normal_direction(1, contravariant_vectors, 1, l, m, element) + grad[v, 1, l, m, element] = ( + grad[v, 1, l, m, element] + + surface_flux_values[v, l, m, 1, element] * + factor_1 * + normal_direction[dim] + ) # surface at +x - normal_direction = get_normal_direction(2, contravariant_vectors, - nnodes(dg), l, m, element) - grad[v, nnodes(dg), l, m, element] = (grad[v, nnodes(dg), l, m, - element] + - surface_flux_values[v, l, m, - 2, - element] * - factor_2 * - normal_direction[dim]) + normal_direction = get_normal_direction( + 2, + contravariant_vectors, + nnodes(dg), + l, + m, + element, + ) + grad[v, nnodes(dg), l, m, element] = ( + grad[v, nnodes(dg), l, m, element] + + surface_flux_values[v, l, m, 2, element] * + factor_2 * + normal_direction[dim] + ) # surface at -y - normal_direction = get_normal_direction(3, contravariant_vectors, - l, m, 1, element) - grad[v, l, 1, m, element] = (grad[v, l, 1, m, element] + - surface_flux_values[v, l, m, 3, - element] * - factor_1 * normal_direction[dim]) + normal_direction = + get_normal_direction(3, contravariant_vectors, l, m, 1, element) + grad[v, l, 1, m, element] = ( + grad[v, l, 1, m, element] + + surface_flux_values[v, l, m, 3, element] * + factor_1 * + normal_direction[dim] + ) # surface at +y - normal_direction = get_normal_direction(4, contravariant_vectors, - l, nnodes(dg), m, element) - grad[v, l, nnodes(dg), m, element] = (grad[v, l, nnodes(dg), m, - element] + - surface_flux_values[v, l, m, - 4, - element] * - factor_2 * - normal_direction[dim]) + normal_direction = get_normal_direction( + 4, + contravariant_vectors, + l, + nnodes(dg), + m, + element, + ) + grad[v, l, nnodes(dg), m, element] = ( + grad[v, l, nnodes(dg), m, element] + + surface_flux_values[v, l, m, 4, element] * + factor_2 * + normal_direction[dim] + ) # surface at -z - normal_direction = get_normal_direction(5, contravariant_vectors, - l, m, 1, element) - grad[v, l, m, 1, element] = (grad[v, l, m, 1, element] + - surface_flux_values[v, l, m, 5, - element] * - factor_1 * normal_direction[dim]) + normal_direction = + get_normal_direction(5, contravariant_vectors, l, m, 1, element) + grad[v, l, m, 1, element] = ( + grad[v, l, m, 1, element] + + surface_flux_values[v, l, m, 5, element] * + factor_1 * + normal_direction[dim] + ) # surface at +z - normal_direction = get_normal_direction(6, contravariant_vectors, - l, m, nnodes(dg), element) - grad[v, l, m, nnodes(dg), element] = (grad[v, l, m, nnodes(dg), - element] + - surface_flux_values[v, l, m, - 6, - element] * - factor_2 * - normal_direction[dim]) + normal_direction = get_normal_direction( + 6, + contravariant_vectors, + l, + m, + nnodes(dg), + element, + ) + grad[v, l, m, nnodes(dg), element] = ( + grad[v, l, m, nnodes(dg), element] + + surface_flux_values[v, l, m, 6, element] * + factor_2 * + normal_direction[dim] + ) end end end @@ -342,59 +547,92 @@ function calc_gradient!(gradients, u_transformed, t, # Apply Jacobian from mapping to reference element @trixi_timeit timer() "Jacobian" begin - apply_jacobian_parabolic!(gradients_x, mesh, equations_parabolic, dg, - cache_parabolic) - apply_jacobian_parabolic!(gradients_y, mesh, equations_parabolic, dg, - cache_parabolic) - apply_jacobian_parabolic!(gradients_z, mesh, equations_parabolic, dg, - cache_parabolic) + apply_jacobian_parabolic!( + gradients_x, + mesh, + equations_parabolic, + dg, + cache_parabolic, + ) + apply_jacobian_parabolic!( + gradients_y, + mesh, + equations_parabolic, + dg, + cache_parabolic, + ) + apply_jacobian_parabolic!( + gradients_z, + mesh, + equations_parabolic, + dg, + cache_parabolic, + ) end return nothing end # This version is called during `calc_gradients!` and must be specialized because the flux -# in the gradient is {u} which doesn't depend on normals. Thus, you don't need to scale by +# in the gradient is {u} which doesn't depend on normals. Thus, you don't need to scale by # 2 and flip the sign when storing the mortar fluxes back into surface_flux_values -@inline function mortar_fluxes_to_elements!(surface_flux_values, - mesh::P4estMesh{3}, - equations::AbstractEquationsParabolic, - mortar_l2::LobattoLegendreMortarL2, - dg::DGSEM, cache, mortar, fstar, u_buffer, - fstar_tmp) +@inline function mortar_fluxes_to_elements!( + surface_flux_values, + mesh::P4estMesh{3}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + dg::DGSEM, + cache, + mortar, + fstar, + u_buffer, + fstar_tmp, +) @unpack neighbor_ids, node_indices = cache.mortars index_range = eachnode(dg) # Copy solution small to small small_indices = node_indices[1, mortar] small_direction = indices2direction(small_indices) - for position in 1:4 + for position = 1:4 element = neighbor_ids[position, mortar] for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) - surface_flux_values[v, i, j, small_direction, element] = fstar[v, i, j, - position] + surface_flux_values[v, i, j, small_direction, element] = + fstar[v, i, j, position] end end end # Project small fluxes to large element. - multiply_dimensionwise!(u_buffer, - mortar_l2.reverse_lower, mortar_l2.reverse_lower, - view(fstar, .., 1), - fstar_tmp) - add_multiply_dimensionwise!(u_buffer, - mortar_l2.reverse_upper, mortar_l2.reverse_lower, - view(fstar, .., 2), - fstar_tmp) - add_multiply_dimensionwise!(u_buffer, - mortar_l2.reverse_lower, mortar_l2.reverse_upper, - view(fstar, .., 3), - fstar_tmp) - add_multiply_dimensionwise!(u_buffer, - mortar_l2.reverse_upper, mortar_l2.reverse_upper, - view(fstar, .., 4), - fstar_tmp) + multiply_dimensionwise!( + u_buffer, + mortar_l2.reverse_lower, + mortar_l2.reverse_lower, + view(fstar, .., 1), + fstar_tmp, + ) + add_multiply_dimensionwise!( + u_buffer, + mortar_l2.reverse_upper, + mortar_l2.reverse_lower, + view(fstar, .., 2), + fstar_tmp, + ) + add_multiply_dimensionwise!( + u_buffer, + mortar_l2.reverse_lower, + mortar_l2.reverse_upper, + view(fstar, .., 3), + fstar_tmp, + ) + add_multiply_dimensionwise!( + u_buffer, + mortar_l2.reverse_upper, + mortar_l2.reverse_upper, + view(fstar, .., 4), + fstar_tmp, + ) # The flux is calculated in the outward direction of the small elements, # so the sign must be switched to get the flux in outward direction @@ -414,10 +652,10 @@ end large_direction = indices2direction(large_indices) large_surface_indices = surface_indices(large_indices) - i_large_start, i_large_step_i, i_large_step_j = index_to_start_step_3d(large_surface_indices[1], - index_range) - j_large_start, j_large_step_i, j_large_step_j = index_to_start_step_3d(large_surface_indices[2], - index_range) + i_large_start, i_large_step_i, i_large_step_j = + index_to_start_step_3d(large_surface_indices[1], index_range) + j_large_start, j_large_step_i, j_large_step_j = + index_to_start_step_3d(large_surface_indices[2], index_range) # Note that the indices of the small sides will always run forward but # the large indices might need to run backwards for flipped sides. @@ -426,9 +664,8 @@ end for j in eachnode(dg) for i in eachnode(dg) for v in eachvariable(equations) - surface_flux_values[v, i_large, j_large, large_direction, large_element] = u_buffer[v, - i, - j] + surface_flux_values[v, i_large, j_large, large_direction, large_element] = + u_buffer[v, i, j] end i_large += i_large_step_i j_large += j_large_step_i @@ -441,38 +678,68 @@ end end # This version is used for parabolic gradient computations -@inline function calc_interface_flux!(surface_flux_values, mesh::P4estMesh{3}, - nonconservative_terms::False, - equations::AbstractEquationsParabolic, - surface_integral, dg::DG, cache, - interface_index, normal_direction, - primary_i_node_index, primary_j_node_index, - primary_direction_index, primary_element_index, - secondary_i_node_index, secondary_j_node_index, - secondary_direction_index, - secondary_element_index) +@inline function calc_interface_flux!( + surface_flux_values, + mesh::P4estMesh{3}, + nonconservative_terms::False, + equations::AbstractEquationsParabolic, + surface_integral, + dg::DG, + cache, + interface_index, + normal_direction, + primary_i_node_index, + primary_j_node_index, + primary_direction_index, + primary_element_index, + secondary_i_node_index, + secondary_j_node_index, + secondary_direction_index, + secondary_element_index, +) @unpack u = cache.interfaces @unpack surface_flux = surface_integral - u_ll, u_rr = get_surface_node_vars(u, equations, dg, primary_i_node_index, - primary_j_node_index, - interface_index) + u_ll, u_rr = get_surface_node_vars( + u, + equations, + dg, + primary_i_node_index, + primary_j_node_index, + interface_index, + ) flux_ = 0.5 * (u_ll + u_rr) # we assume that the gradient computations utilize a central flux # Note that we don't flip the sign on the secondondary flux. This is because for parabolic terms, # the normals are not embedded in `flux_` for the parabolic gradient computations. for v in eachvariable(equations) - surface_flux_values[v, primary_i_node_index, primary_j_node_index, primary_direction_index, primary_element_index] = flux_[v] - surface_flux_values[v, secondary_i_node_index, secondary_j_node_index, secondary_direction_index, secondary_element_index] = flux_[v] + surface_flux_values[ + v, + primary_i_node_index, + primary_j_node_index, + primary_direction_index, + primary_element_index, + ] = flux_[v] + surface_flux_values[ + v, + secondary_i_node_index, + secondary_j_node_index, + secondary_direction_index, + secondary_element_index, + ] = flux_[v] end end # This is the version used when calculating the divergence of the viscous fluxes -function calc_volume_integral!(du, flux_viscous, - mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - dg::DGSEM, cache) +function calc_volume_integral!( + du, + flux_viscous, + mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + dg::DGSEM, + cache, +) (; derivative_dhat) = dg.basis (; contravariant_vectors) = cache.elements flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous @@ -486,32 +753,59 @@ function calc_volume_integral!(du, flux_viscous, # Compute the contravariant flux by taking the scalar product of the # first contravariant vector Ja^1 and the flux vector - Ja11, Ja12, Ja13 = get_contravariant_vector(1, contravariant_vectors, i, j, k, - element) + Ja11, Ja12, Ja13 = + get_contravariant_vector(1, contravariant_vectors, i, j, k, element) contravariant_flux1 = Ja11 * flux1 + Ja12 * flux2 + Ja13 * flux3 for ii in eachnode(dg) - multiply_add_to_node_vars!(du, derivative_dhat[ii, i], contravariant_flux1, - equations_parabolic, dg, ii, j, k, element) + multiply_add_to_node_vars!( + du, + derivative_dhat[ii, i], + contravariant_flux1, + equations_parabolic, + dg, + ii, + j, + k, + element, + ) end # Compute the contravariant flux by taking the scalar product of the # second contravariant vector Ja^2 and the flux vector - Ja21, Ja22, Ja23 = get_contravariant_vector(2, contravariant_vectors, i, j, k, - element) + Ja21, Ja22, Ja23 = + get_contravariant_vector(2, contravariant_vectors, i, j, k, element) contravariant_flux2 = Ja21 * flux1 + Ja22 * flux2 + Ja23 * flux3 for jj in eachnode(dg) - multiply_add_to_node_vars!(du, derivative_dhat[jj, j], contravariant_flux2, - equations_parabolic, dg, i, jj, k, element) + multiply_add_to_node_vars!( + du, + derivative_dhat[jj, j], + contravariant_flux2, + equations_parabolic, + dg, + i, + jj, + k, + element, + ) end # Compute the contravariant flux by taking the scalar product of the # second contravariant vector Ja^2 and the flux vector - Ja31, Ja32, Ja33 = get_contravariant_vector(3, contravariant_vectors, i, j, k, - element) + Ja31, Ja32, Ja33 = + get_contravariant_vector(3, contravariant_vectors, i, j, k, element) contravariant_flux3 = Ja31 * flux1 + Ja32 * flux2 + Ja33 * flux3 for kk in eachnode(dg) - multiply_add_to_node_vars!(du, derivative_dhat[kk, k], contravariant_flux3, - equations_parabolic, dg, i, j, kk, element) + multiply_add_to_node_vars!( + du, + derivative_dhat[kk, k], + contravariant_flux3, + equations_parabolic, + dg, + i, + j, + kk, + element, + ) end end end @@ -521,10 +815,15 @@ end # This is the version used when calculating the divergence of the viscous fluxes # We pass the `surface_integral` argument solely for dispatch -function prolong2interfaces!(cache_parabolic, flux_viscous, - mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) +function prolong2interfaces!( + cache_parabolic, + flux_viscous, + mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + surface_integral, + dg::DG, + cache, +) (; interfaces) = cache_parabolic (; contravariant_vectors) = cache_parabolic.elements index_range = eachnode(dg) @@ -540,12 +839,12 @@ function prolong2interfaces!(cache_parabolic, flux_viscous, primary_indices = interfaces.node_indices[1, interface] primary_direction = indices2direction(primary_indices) - i_primary_start, i_primary_step_i, i_primary_step_j = index_to_start_step_3d(primary_indices[1], - index_range) - j_primary_start, j_primary_step_i, j_primary_step_j = index_to_start_step_3d(primary_indices[2], - index_range) - k_primary_start, k_primary_step_i, k_primary_step_j = index_to_start_step_3d(primary_indices[3], - index_range) + i_primary_start, i_primary_step_i, i_primary_step_j = + index_to_start_step_3d(primary_indices[1], index_range) + j_primary_start, j_primary_step_i, j_primary_step_j = + index_to_start_step_3d(primary_indices[2], index_range) + k_primary_start, k_primary_step_i, k_primary_step_j = + index_to_start_step_3d(primary_indices[3], index_range) i_primary = i_primary_start j_primary = j_primary_start @@ -554,25 +853,25 @@ function prolong2interfaces!(cache_parabolic, flux_viscous, for j in eachnode(dg) for i in eachnode(dg) # this is the outward normal direction on the primary element - normal_direction = get_normal_direction(primary_direction, - contravariant_vectors, - i_primary, j_primary, k_primary, - primary_element) + normal_direction = get_normal_direction( + primary_direction, + contravariant_vectors, + i_primary, + j_primary, + k_primary, + primary_element, + ) for v in eachvariable(equations_parabolic) # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - flux_viscous = SVector(flux_viscous_x[v, i_primary, j_primary, - k_primary, - primary_element], - flux_viscous_y[v, i_primary, j_primary, - k_primary, - primary_element], - flux_viscous_z[v, i_primary, j_primary, - k_primary, - primary_element]) - - interfaces.u[1, v, i, j, interface] = dot(flux_viscous, - normal_direction) + flux_viscous = SVector( + flux_viscous_x[v, i_primary, j_primary, k_primary, primary_element], + flux_viscous_y[v, i_primary, j_primary, k_primary, primary_element], + flux_viscous_z[v, i_primary, j_primary, k_primary, primary_element], + ) + + interfaces.u[1, v, i, j, interface] = + dot(flux_viscous, normal_direction) end i_primary += i_primary_step_i j_primary += j_primary_step_i @@ -589,12 +888,12 @@ function prolong2interfaces!(cache_parabolic, flux_viscous, secondary_indices = interfaces.node_indices[2, interface] secondary_direction = indices2direction(secondary_indices) - i_secondary_start, i_secondary_step_i, i_secondary_step_j = index_to_start_step_3d(secondary_indices[1], - index_range) - j_secondary_start, j_secondary_step_i, j_secondary_step_j = index_to_start_step_3d(secondary_indices[2], - index_range) - k_secondary_start, k_secondary_step_i, k_secondary_step_j = index_to_start_step_3d(secondary_indices[3], - index_range) + i_secondary_start, i_secondary_step_i, i_secondary_step_j = + index_to_start_step_3d(secondary_indices[1], index_range) + j_secondary_start, j_secondary_step_i, j_secondary_step_j = + index_to_start_step_3d(secondary_indices[2], index_range) + k_secondary_start, k_secondary_step_i, k_secondary_step_j = + index_to_start_step_3d(secondary_indices[3], index_range) i_secondary = i_secondary_start j_secondary = j_secondary_start @@ -604,26 +903,43 @@ function prolong2interfaces!(cache_parabolic, flux_viscous, # This is the outward normal direction on the secondary element. # Here, we assume that normal_direction on the secondary element is # the negative of normal_direction on the primary element. - normal_direction = get_normal_direction(secondary_direction, - contravariant_vectors, - i_secondary, j_secondary, - k_secondary, - secondary_element) + normal_direction = get_normal_direction( + secondary_direction, + contravariant_vectors, + i_secondary, + j_secondary, + k_secondary, + secondary_element, + ) for v in eachvariable(equations_parabolic) # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - flux_viscous = SVector(flux_viscous_x[v, i_secondary, j_secondary, - k_secondary, - secondary_element], - flux_viscous_y[v, i_secondary, j_secondary, - k_secondary, - secondary_element], - flux_viscous_z[v, i_secondary, j_secondary, - k_secondary, - secondary_element]) + flux_viscous = SVector( + flux_viscous_x[ + v, + i_secondary, + j_secondary, + k_secondary, + secondary_element, + ], + flux_viscous_y[ + v, + i_secondary, + j_secondary, + k_secondary, + secondary_element, + ], + flux_viscous_z[ + v, + i_secondary, + j_secondary, + k_secondary, + secondary_element, + ], + ) # store the normal flux with respect to the primary normal direction - interfaces.u[2, v, i, j, interface] = -dot(flux_viscous, - normal_direction) + interfaces.u[2, v, i, j, interface] = + -dot(flux_viscous, normal_direction) end i_secondary += i_secondary_step_i j_secondary += j_secondary_step_i @@ -638,10 +954,14 @@ function prolong2interfaces!(cache_parabolic, flux_viscous, return nothing end -# This version is used for divergence flux computations -function calc_interface_flux!(surface_flux_values, - mesh::P4estMesh{3}, equations_parabolic, - dg::DG, cache_parabolic) +# This version is used for divergence flux computations +function calc_interface_flux!( + surface_flux_values, + mesh::P4estMesh{3}, + equations_parabolic, + dg::DG, + cache_parabolic, +) (; neighbor_ids, node_indices) = cache_parabolic.interfaces index_range = eachnode(dg) @@ -651,12 +971,12 @@ function calc_interface_flux!(surface_flux_values, primary_indices = node_indices[1, interface] primary_direction_index = indices2direction(primary_indices) - i_primary_start, i_primary_step_i, i_primary_step_j = index_to_start_step_3d(primary_indices[1], - index_range) - j_primary_start, j_primary_step_i, j_primary_step_j = index_to_start_step_3d(primary_indices[2], - index_range) - k_primary_start, k_primary_step_i, k_primary_step_j = index_to_start_step_3d(primary_indices[3], - index_range) + i_primary_start, i_primary_step_i, i_primary_step_j = + index_to_start_step_3d(primary_indices[1], index_range) + j_primary_start, j_primary_step_i, j_primary_step_j = + index_to_start_step_3d(primary_indices[2], index_range) + k_primary_start, k_primary_step_i, k_primary_step_j = + index_to_start_step_3d(primary_indices[3], index_range) i_primary = i_primary_start j_primary = j_primary_start @@ -674,28 +994,38 @@ function calc_interface_flux!(surface_flux_values, # Get the surface indexing on the secondary element. # Note that the indices of the primary side will always run forward but # the secondary indices might need to run backwards for flipped sides. - i_secondary_start, i_secondary_step_i, i_secondary_step_j = index_to_start_step_3d(secondary_surface_indices[1], - index_range) - j_secondary_start, j_secondary_step_i, j_secondary_step_j = index_to_start_step_3d(secondary_surface_indices[2], - index_range) + i_secondary_start, i_secondary_step_i, i_secondary_step_j = + index_to_start_step_3d(secondary_surface_indices[1], index_range) + j_secondary_start, j_secondary_step_i, j_secondary_step_j = + index_to_start_step_3d(secondary_surface_indices[2], index_range) i_secondary = i_secondary_start j_secondary = j_secondary_start for j in eachnode(dg) for i in eachnode(dg) - # We prolong the viscous flux dotted with respect the outward normal on the + # We prolong the viscous flux dotted with respect the outward normal on the # primary element. We assume a BR-1 type of flux. - viscous_flux_normal_ll, viscous_flux_normal_rr = get_surface_node_vars(cache_parabolic.interfaces.u, - equations_parabolic, - dg, - i, j, - interface) + viscous_flux_normal_ll, viscous_flux_normal_rr = get_surface_node_vars( + cache_parabolic.interfaces.u, + equations_parabolic, + dg, + i, + j, + interface, + ) flux = 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) for v in eachvariable(equations_parabolic) - surface_flux_values[v, i, j, primary_direction_index, primary_element] = flux[v] - surface_flux_values[v, i_secondary, j_secondary, secondary_direction_index, secondary_element] = -flux[v] + surface_flux_values[v, i, j, primary_direction_index, primary_element] = + flux[v] + surface_flux_values[ + v, + i_secondary, + j_secondary, + secondary_direction_index, + secondary_element, + ] = -flux[v] end # Increment the primary element indices @@ -719,10 +1049,15 @@ function calc_interface_flux!(surface_flux_values, return nothing end -function prolong2mortars_divergence!(cache, flux_viscous, - mesh::Union{P4estMesh{3}, T8codeMesh{3}}, equations, - mortar_l2::LobattoLegendreMortarL2, - surface_integral, dg::DGSEM) +function prolong2mortars_divergence!( + cache, + flux_viscous, + mesh::Union{P4estMesh{3},T8codeMesh{3}}, + equations, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, + dg::DGSEM, +) @unpack neighbor_ids, node_indices = cache.mortars @unpack fstar_tmp_threaded = cache @unpack contravariant_vectors = cache.elements @@ -736,35 +1071,38 @@ function prolong2mortars_divergence!(cache, flux_viscous, small_indices = node_indices[1, mortar] direction_index = indices2direction(small_indices) - i_small_start, i_small_step_i, i_small_step_j = index_to_start_step_3d(small_indices[1], - index_range) - j_small_start, j_small_step_i, j_small_step_j = index_to_start_step_3d(small_indices[2], - index_range) - k_small_start, k_small_step_i, k_small_step_j = index_to_start_step_3d(small_indices[3], - index_range) + i_small_start, i_small_step_i, i_small_step_j = + index_to_start_step_3d(small_indices[1], index_range) + j_small_start, j_small_step_i, j_small_step_j = + index_to_start_step_3d(small_indices[2], index_range) + k_small_start, k_small_step_i, k_small_step_j = + index_to_start_step_3d(small_indices[3], index_range) - for position in 1:4 + for position = 1:4 i_small = i_small_start j_small = j_small_start k_small = k_small_start element = neighbor_ids[position, mortar] for j in eachnode(dg) for i in eachnode(dg) - normal_direction = get_normal_direction(direction_index, - contravariant_vectors, - i_small, j_small, k_small, - element) + normal_direction = get_normal_direction( + direction_index, + contravariant_vectors, + i_small, + j_small, + k_small, + element, + ) for v in eachvariable(equations) - flux_viscous = SVector(flux_viscous_x[v, i_small, j_small, k_small, - element], - flux_viscous_y[v, i_small, j_small, k_small, - element], - flux_viscous_z[v, i_small, j_small, k_small, - element]) - - cache.mortars.u[1, v, position, i, j, mortar] = dot(flux_viscous, - normal_direction) + flux_viscous = SVector( + flux_viscous_x[v, i_small, j_small, k_small, element], + flux_viscous_y[v, i_small, j_small, k_small, element], + flux_viscous_z[v, i_small, j_small, k_small, element], + ) + + cache.mortars.u[1, v, position, i, j, mortar] = + dot(flux_viscous, normal_direction) end i_small += i_small_step_i j_small += j_small_step_i @@ -787,12 +1125,12 @@ function prolong2mortars_divergence!(cache, flux_viscous, # correct orientation large_indices = node_indices[2, mortar] - i_large_start, i_large_step_i, i_large_step_j = index_to_start_step_3d(large_indices[1], - index_range) - j_large_start, j_large_step_i, j_large_step_j = index_to_start_step_3d(large_indices[2], - index_range) - k_large_start, k_large_step_i, k_large_step_j = index_to_start_step_3d(large_indices[3], - index_range) + i_large_start, i_large_step_i, i_large_step_j = + index_to_start_step_3d(large_indices[1], index_range) + j_large_start, j_large_step_i, j_large_step_j = + index_to_start_step_3d(large_indices[2], index_range) + k_large_start, k_large_step_i, k_large_step_j = + index_to_start_step_3d(large_indices[3], index_range) i_large = i_large_start j_large = j_large_start @@ -800,21 +1138,25 @@ function prolong2mortars_divergence!(cache, flux_viscous, element = neighbor_ids[5, mortar] for j in eachnode(dg) for i in eachnode(dg) - normal_direction = get_normal_direction(direction_index, - contravariant_vectors, - i_large, j_large, k_large, element) + normal_direction = get_normal_direction( + direction_index, + contravariant_vectors, + i_large, + j_large, + k_large, + element, + ) for v in eachvariable(equations) - flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, k_large, - element], - flux_viscous_y[v, i_large, j_large, k_large, - element], - flux_viscous_z[v, i_large, j_large, k_large, - element]) - - # We prolong the viscous flux dotted with respect the outward normal - # on the small element. We scale by -1/2 here because the normal - # direction on the large element is negative 2x that of the small + flux_viscous = SVector( + flux_viscous_x[v, i_large, j_large, k_large, element], + flux_viscous_y[v, i_large, j_large, k_large, element], + flux_viscous_z[v, i_large, j_large, k_large, element], + ) + + # We prolong the viscous flux dotted with respect the outward normal + # on the small element. We scale by -1/2 here because the normal + # direction on the large element is negative 2x that of the small # element (these normal directions are "scaled" by the surface Jacobian) u_buffer[v, i, j] = -0.5 * dot(flux_viscous, normal_direction) end @@ -828,38 +1170,50 @@ function prolong2mortars_divergence!(cache, flux_viscous, end # Interpolate large element face data from buffer to small face locations - multiply_dimensionwise!(view(cache.mortars.u, 2, :, 1, :, :, mortar), - mortar_l2.forward_lower, - mortar_l2.forward_lower, - u_buffer, - fstar_tmp) - multiply_dimensionwise!(view(cache.mortars.u, 2, :, 2, :, :, mortar), - mortar_l2.forward_upper, - mortar_l2.forward_lower, - u_buffer, - fstar_tmp) - multiply_dimensionwise!(view(cache.mortars.u, 2, :, 3, :, :, mortar), - mortar_l2.forward_lower, - mortar_l2.forward_upper, - u_buffer, - fstar_tmp) - multiply_dimensionwise!(view(cache.mortars.u, 2, :, 4, :, :, mortar), - mortar_l2.forward_upper, - mortar_l2.forward_upper, - u_buffer, - fstar_tmp) + multiply_dimensionwise!( + view(cache.mortars.u, 2, :, 1, :, :, mortar), + mortar_l2.forward_lower, + mortar_l2.forward_lower, + u_buffer, + fstar_tmp, + ) + multiply_dimensionwise!( + view(cache.mortars.u, 2, :, 2, :, :, mortar), + mortar_l2.forward_upper, + mortar_l2.forward_lower, + u_buffer, + fstar_tmp, + ) + multiply_dimensionwise!( + view(cache.mortars.u, 2, :, 3, :, :, mortar), + mortar_l2.forward_lower, + mortar_l2.forward_upper, + u_buffer, + fstar_tmp, + ) + multiply_dimensionwise!( + view(cache.mortars.u, 2, :, 4, :, :, mortar), + mortar_l2.forward_upper, + mortar_l2.forward_upper, + u_buffer, + fstar_tmp, + ) end return nothing end -# We specialize `calc_mortar_flux!` for the divergence part of -# the parabolic terms. -function calc_mortar_flux_divergence!(surface_flux_values, - mesh::Union{P4estMesh{3}, T8codeMesh{3}}, - equations::AbstractEquationsParabolic, - mortar_l2::LobattoLegendreMortarL2, - surface_integral, dg::DG, cache) +# We specialize `calc_mortar_flux!` for the divergence part of +# the parabolic terms. +function calc_mortar_flux_divergence!( + surface_flux_values, + mesh::Union{P4estMesh{3},T8codeMesh{3}}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, + dg::DG, + cache, +) @unpack neighbor_ids, node_indices = cache.mortars @unpack contravariant_vectors = cache.elements @unpack fstar_threaded, fstar_tmp_threaded = cache @@ -874,14 +1228,14 @@ function calc_mortar_flux_divergence!(surface_flux_values, small_indices = node_indices[1, mortar] small_direction = indices2direction(small_indices) - i_small_start, i_small_step_i, i_small_step_j = index_to_start_step_3d(small_indices[1], - index_range) - j_small_start, j_small_step_i, j_small_step_j = index_to_start_step_3d(small_indices[2], - index_range) - k_small_start, k_small_step_i, k_small_step_j = index_to_start_step_3d(small_indices[3], - index_range) + i_small_start, i_small_step_i, i_small_step_j = + index_to_start_step_3d(small_indices[1], index_range) + j_small_start, j_small_step_i, j_small_step_j = + index_to_start_step_3d(small_indices[2], index_range) + k_small_start, k_small_step_i, k_small_step_j = + index_to_start_step_3d(small_indices[3], index_range) - for position in 1:4 + for position = 1:4 i_small = i_small_start j_small = j_small_start k_small = k_small_start @@ -889,14 +1243,14 @@ function calc_mortar_flux_divergence!(surface_flux_values, for j in eachnode(dg) for i in eachnode(dg) for v in eachvariable(equations) - viscous_flux_normal_ll = cache.mortars.u[1, v, position, i, j, - mortar] - viscous_flux_normal_rr = cache.mortars.u[2, v, position, i, j, - mortar] + viscous_flux_normal_ll = + cache.mortars.u[1, v, position, i, j, mortar] + viscous_flux_normal_rr = + cache.mortars.u[2, v, position, i, j, mortar] # TODO: parabolic; only BR1 at the moment - fstar[v, i, j, position] = 0.5 * (viscous_flux_normal_ll + - viscous_flux_normal_rr) + fstar[v, i, j, position] = + 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) end i_small += i_small_step_i @@ -914,29 +1268,52 @@ function calc_mortar_flux_divergence!(surface_flux_values, u_buffer = cache.u_threaded[Threads.threadid()] # this reuses the hyperbolic version of `mortar_fluxes_to_elements!` - mortar_fluxes_to_elements!(surface_flux_values, - mesh, equations, mortar_l2, dg, cache, - mortar, fstar, u_buffer, fstar_tmp) + mortar_fluxes_to_elements!( + surface_flux_values, + mesh, + equations, + mortar_l2, + dg, + cache, + mortar, + fstar, + u_buffer, + fstar_tmp, + ) end return nothing end # NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. -# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for +# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for # hyperbolic terms with conserved terms only, i.e., no nonconservative terms. -@inline function calc_mortar_flux!(fstar, - mesh::P4estMesh{3}, - nonconservative_terms::False, - equations::AbstractEquationsParabolic, - surface_integral, dg::DG, cache, - mortar_index, position_index, normal_direction, - i_node_index, j_node_index) +@inline function calc_mortar_flux!( + fstar, + mesh::P4estMesh{3}, + nonconservative_terms::False, + equations::AbstractEquationsParabolic, + surface_integral, + dg::DG, + cache, + mortar_index, + position_index, + normal_direction, + i_node_index, + j_node_index, +) @unpack u = cache.mortars @unpack surface_flux = surface_integral - u_ll, u_rr = get_surface_node_vars(u, equations, dg, position_index, i_node_index, - j_node_index, mortar_index) + u_ll, u_rr = get_surface_node_vars( + u, + equations, + dg, + position_index, + i_node_index, + j_node_index, + mortar_index, + ) # TODO: parabolic; only BR1 at the moment flux_ = 0.5 * (u_ll + u_rr) @@ -945,10 +1322,15 @@ end end # TODO: parabolic, finish implementing `calc_boundary_flux_gradients!` and `calc_boundary_flux_divergence!` -function prolong2boundaries!(cache_parabolic, flux_viscous, - mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG, cache) +function prolong2boundaries!( + cache_parabolic, + flux_viscous, + mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + surface_integral, + dg::DG, + cache, +) (; boundaries) = cache_parabolic (; contravariant_vectors) = cache_parabolic.elements index_range = eachnode(dg) @@ -962,12 +1344,12 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, node_indices = boundaries.node_indices[boundary] direction = indices2direction(node_indices) - i_node_start, i_node_step_i, i_node_step_j = index_to_start_step_3d(node_indices[1], - index_range) - j_node_start, j_node_step_i, j_node_step_j = index_to_start_step_3d(node_indices[2], - index_range) - k_node_start, k_node_step_i, k_node_step_j = index_to_start_step_3d(node_indices[3], - index_range) + i_node_start, i_node_step_i, i_node_step_j = + index_to_start_step_3d(node_indices[1], index_range) + j_node_start, j_node_step_i, j_node_step_j = + index_to_start_step_3d(node_indices[2], index_range) + k_node_start, k_node_step_i, k_node_step_j = + index_to_start_step_3d(node_indices[3], index_range) i_node = i_node_start j_node = j_node_start @@ -976,16 +1358,21 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, for j in eachnode(dg) for i in eachnode(dg) # this is the outward normal direction on the primary element - normal_direction = get_normal_direction(direction, contravariant_vectors, - i_node, j_node, k_node, element) + normal_direction = get_normal_direction( + direction, + contravariant_vectors, + i_node, + j_node, + k_node, + element, + ) for v in eachvariable(equations_parabolic) - flux_viscous = SVector(flux_viscous_x[v, i_node, j_node, k_node, - element], - flux_viscous_y[v, i_node, j_node, k_node, - element], - flux_viscous_z[v, i_node, j_node, k_node, - element]) + flux_viscous = SVector( + flux_viscous_x[v, i_node, j_node, k_node, element], + flux_viscous_y[v, i_node, j_node, k_node, element], + flux_viscous_z[v, i_node, j_node, k_node, element], + ) boundaries.u[v, i, j, boundary] = dot(flux_viscous, normal_direction) end @@ -1001,12 +1388,17 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, return nothing end -function calc_boundary_flux!(cache, t, - boundary_condition_parabolic, # works with Dict types - boundary_condition_indices, - operator_type, mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - surface_integral, dg::DG) +function calc_boundary_flux!( + cache, + t, + boundary_condition_parabolic, # works with Dict types + boundary_condition_indices, + operator_type, + mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + surface_integral, + dg::DG, +) (; boundaries) = cache (; node_coordinates, surface_flux_values) = cache.elements (; contravariant_vectors) = cache.elements @@ -1022,12 +1414,12 @@ function calc_boundary_flux!(cache, t, node_indices = boundaries.node_indices[boundary_index] direction_index = indices2direction(node_indices) - i_node_start, i_node_step_i, i_node_step_j = index_to_start_step_3d(node_indices[1], - index_range) - j_node_start, j_node_step_i, j_node_step_j = index_to_start_step_3d(node_indices[2], - index_range) - k_node_start, k_node_step_i, k_node_step_j = index_to_start_step_3d(node_indices[3], - index_range) + i_node_start, i_node_step_i, i_node_step_j = + index_to_start_step_3d(node_indices[1], index_range) + j_node_start, j_node_step_i, j_node_step_j = + index_to_start_step_3d(node_indices[2], index_range) + k_node_start, k_node_step_i, k_node_step_j = + index_to_start_step_3d(node_indices[3], index_range) i_node = i_node_start j_node = j_node_start @@ -1036,13 +1428,24 @@ function calc_boundary_flux!(cache, t, for j in eachnode(dg) for i in eachnode(dg) # Extract solution data from boundary container - u_inner = get_node_vars(boundaries.u, equations_parabolic, dg, i, j, - boundary_index) + u_inner = get_node_vars( + boundaries.u, + equations_parabolic, + dg, + i, + j, + boundary_index, + ) # Outward-pointing normal direction (not normalized) - normal_direction = get_normal_direction(direction_index, - contravariant_vectors, - i_node, j_node, k_node, element) + normal_direction = get_normal_direction( + direction_index, + contravariant_vectors, + i_node, + j_node, + k_node, + element, + ) # TODO: revisit if we want more general boundary treatments. # This assumes the gradient numerical flux at the boundary is the gradient variable, @@ -1050,13 +1453,25 @@ function calc_boundary_flux!(cache, t, flux_inner = u_inner # Coordinates at boundary node - x = get_node_coords(node_coordinates, equations_parabolic, dg, i_node, - j_node, k_node, - element) - - flux_ = boundary_condition_parabolic(flux_inner, u_inner, normal_direction, - x, t, operator_type, - equations_parabolic) + x = get_node_coords( + node_coordinates, + equations_parabolic, + dg, + i_node, + j_node, + k_node, + element, + ) + + flux_ = boundary_condition_parabolic( + flux_inner, + u_inner, + normal_direction, + x, + t, + operator_type, + equations_parabolic, + ) # Copy flux to element storage in the correct orientation for v in eachvariable(equations_parabolic) From b749f1098b7780d831ed797df6d2b445ed0d7ab7 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:24:50 +0100 Subject: [PATCH 119/138] Update test_parabolic_3d.jl --- test/test_parabolic_3d.jl | 582 ++++++++++++++++++++++---------------- 1 file changed, 338 insertions(+), 244 deletions(-) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index cf452732f9e..18019e99bc8 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -13,23 +13,25 @@ isdir(outdir) && rm(outdir, recursive = true) #! format: noindent @trixi_testset "DGMulti: elixir_navierstokes_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", - "elixir_navierstokes_convergence.jl"), - cells_per_dimension=(4, 4, 4), tspan=(0.0, 0.1), - l2=[ - 0.0005532847115849239, - 0.000659263490965341, - 0.0007776436127362806, - 0.0006592634909662951, - 0.0038073628897809185, - ], - linf=[ - 0.0017039861523615585, - 0.002628561703560073, - 0.003531057425112172, - 0.0026285617036090336, - 0.015587829540351095, - ]) + @test_trixi_include( + joinpath(examples_dir(), "dgmulti_3d", "elixir_navierstokes_convergence.jl"), + cells_per_dimension = (4, 4, 4), + tspan = (0.0, 0.1), + l2 = [ + 0.0005532847115849239, + 0.000659263490965341, + 0.0007776436127362806, + 0.0006592634909662951, + 0.0038073628897809185, + ], + linf = [ + 0.0017039861523615585, + 0.002628561703560073, + 0.003531057425112172, + 0.0026285617036090336, + 0.015587829540351095, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -41,23 +43,29 @@ isdir(outdir) && rm(outdir, recursive = true) end @trixi_testset "DGMulti: elixir_navierstokes_convergence_curved.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", - "elixir_navierstokes_convergence_curved.jl"), - cells_per_dimension=(4, 4, 4), tspan=(0.0, 0.1), - l2=[ - 0.0014027227251207474, - 0.0021322235533273513, - 0.0027873741447455194, - 0.0024587473070627423, - 0.00997836818019202, - ], - linf=[ - 0.006341750402837576, - 0.010306014252246865, - 0.01520740250924979, - 0.010968264045485565, - 0.047454389831591115, - ]) + @test_trixi_include( + joinpath( + examples_dir(), + "dgmulti_3d", + "elixir_navierstokes_convergence_curved.jl", + ), + cells_per_dimension = (4, 4, 4), + tspan = (0.0, 0.1), + l2 = [ + 0.0014027227251207474, + 0.0021322235533273513, + 0.0027873741447455194, + 0.0024587473070627423, + 0.00997836818019202, + ], + linf = [ + 0.006341750402837576, + 0.010306014252246865, + 0.01520740250924979, + 0.010968264045485565, + 0.047454389831591115, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -69,23 +77,29 @@ end end @trixi_testset "DGMulti: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", - "elixir_navierstokes_taylor_green_vortex.jl"), - cells_per_dimension=(4, 4, 4), tspan=(0.0, 0.25), - l2=[ - 0.0001825713444029892, - 0.015589736382772248, - 0.015589736382771884, - 0.021943924667273653, - 0.01927370280244222, - ], - linf=[ - 0.0006268463584697681, - 0.03218881662749007, - 0.03218881662697948, - 0.053872495395614256, - 0.05183822000984151, - ]) + @test_trixi_include( + joinpath( + examples_dir(), + "dgmulti_3d", + "elixir_navierstokes_taylor_green_vortex.jl", + ), + cells_per_dimension = (4, 4, 4), + tspan = (0.0, 0.25), + l2 = [ + 0.0001825713444029892, + 0.015589736382772248, + 0.015589736382771884, + 0.021943924667273653, + 0.01927370280244222, + ], + linf = [ + 0.0006268463584697681, + 0.03218881662749007, + 0.03218881662697948, + 0.053872495395614256, + 0.05183822000984151, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -97,23 +111,25 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), - l2=[ - 0.0019582188528512257, - 0.002653449504302844, - 0.002898264205184629, - 0.002653449504302853, - 0.009511572365085706, - ], - linf=[ - 0.013680656759085918, - 0.0356910450154318, - 0.023526343547736236, - 0.035691045015431855, - 0.11482570604041165, - ]) + @test_trixi_include( + joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level = 2, + tspan = (0.0, 0.1), + l2 = [ + 0.0019582188528512257, + 0.002653449504302844, + 0.002898264205184629, + 0.002653449504302853, + 0.009511572365085706, + ], + linf = [ + 0.013680656759085918, + 0.0356910450154318, + 0.023526343547736236, + 0.035691045015431855, + 0.11482570604041165, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -125,27 +141,31 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (isothermal walls)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), - heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, - t, - equations), - equations)), - l2=[ - 0.00195468651965362, - 0.0026554367897028506, - 0.002892730402724066, - 0.002655436789702817, - 0.009596351796609566, - ], - linf=[ - 0.013680508110645473, - 0.035673446359424356, - 0.024024936779729028, - 0.03567344635942474, - 0.11839497110809383, - ]) + @test_trixi_include( + joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level = 2, + tspan = (0.0, 0.1), + heat_bc_top_bottom = Isothermal( + (x, t, equations) -> Trixi.temperature( + initial_condition_navier_stokes_convergence_test(x, t, equations), + equations, + ), + ), + l2 = [ + 0.00195468651965362, + 0.0026554367897028506, + 0.002892730402724066, + 0.002655436789702817, + 0.009596351796609566, + ], + linf = [ + 0.013680508110645473, + 0.035673446359424356, + 0.024024936779729028, + 0.03567344635942474, + 0.11839497110809383, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -157,24 +177,26 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Entropy gradient variables)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), - gradient_variables=GradientVariablesEntropy(), - l2=[ - 0.0019770444875099307, - 0.0026524750946399327, - 0.00290860030832445, - 0.0026524750946399396, - 0.009509568981439294, - ], - linf=[ - 0.01387936112914212, - 0.03526260609304053, - 0.023554197097368997, - 0.035262606093040896, - 0.11719963716509518, - ]) + @test_trixi_include( + joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level = 2, + tspan = (0.0, 0.1), + gradient_variables = GradientVariablesEntropy(), + l2 = [ + 0.0019770444875099307, + 0.0026524750946399327, + 0.00290860030832445, + 0.0026524750946399396, + 0.009509568981439294, + ], + linf = [ + 0.01387936112914212, + 0.03526260609304053, + 0.023554197097368997, + 0.035262606093040896, + 0.11719963716509518, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -186,28 +208,32 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Entropy gradient variables, isothermal walls)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), - gradient_variables=GradientVariablesEntropy(), - heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, - t, - equations), - equations)), - l2=[ - 0.001974631423398113, - 0.002654768259143932, - 0.002907031063651286, - 0.002654768259143901, - 0.009587792882971452, - ], - linf=[ - 0.01387919380137137, - 0.035244084526358944, - 0.02398614622061363, - 0.03524408452635828, - 0.12005056512506407, - ]) + @test_trixi_include( + joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level = 2, + tspan = (0.0, 0.1), + gradient_variables = GradientVariablesEntropy(), + heat_bc_top_bottom = Isothermal( + (x, t, equations) -> Trixi.temperature( + initial_condition_navier_stokes_convergence_test(x, t, equations), + equations, + ), + ), + l2 = [ + 0.001974631423398113, + 0.002654768259143932, + 0.002907031063651286, + 0.002654768259143901, + 0.009587792882971452, + ], + linf = [ + 0.01387919380137137, + 0.035244084526358944, + 0.02398614622061363, + 0.03524408452635828, + 0.12005056512506407, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -219,24 +245,26 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (flux differencing)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), - volume_integral=VolumeIntegralFluxDifferencing(flux_central), - l2=[ - 0.0019582188528180213, - 0.002653449504301736, - 0.0028982642051960006, - 0.0026534495043017384, - 0.009511572364811033, - ], - linf=[ - 0.013680656758949583, - 0.035691045015224444, - 0.02352634354676752, - 0.035691045015223424, - 0.11482570603751441, - ]) + @test_trixi_include( + joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), + initial_refinement_level = 2, + tspan = (0.0, 0.1), + volume_integral = VolumeIntegralFluxDifferencing(flux_central), + l2 = [ + 0.0019582188528180213, + 0.002653449504301736, + 0.0028982642051960006, + 0.0026534495043017384, + 0.009511572364811033, + ], + linf = [ + 0.013680656758949583, + 0.035691045015224444, + 0.02352634354676752, + 0.035691045015223424, + 0.11482570603751441, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -248,25 +276,35 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Refined mesh)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_navierstokes_convergence.jl"), - tspan=(0.0, 0.0)) + @test_trixi_include( + joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), + tspan = (0.0, 0.0) + ) LLID = Trixi.local_leaf_cells(mesh.tree) num_leafs = length(LLID) @assert num_leafs % 16 == 0 Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 16)]) tspan = (0.0, 0.25) - semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition, solver; - boundary_conditions = (boundary_conditions, - boundary_conditions_parabolic), - source_terms = source_terms_navier_stokes_convergence_test) + semi = SemidiscretizationHyperbolicParabolic( + mesh, + (equations, equations_parabolic), + initial_condition, + solver; + boundary_conditions = (boundary_conditions, boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test, + ) ode = semidiscretize(semi, tspan) analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) - sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, - dt = 1e-5, - ode_default_options()..., callback = callbacks) + sol = solve( + ode, + RDPK3SpFSAL49(); + abstol = time_int_tol, + reltol = time_int_tol, + dt = 1e-5, + ode_default_options()..., + callback = callbacks, + ) l2_error, linf_error = analysis_callback(sol) @test l2_error ≈ [ 0.0003109336253407314, @@ -293,23 +331,29 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_navierstokes_taylor_green_vortex.jl"), - initial_refinement_level=2, tspan=(0.0, 0.25), - l2=[ - 0.00024173250389635442, - 0.015684268393762454, - 0.01568426839376248, - 0.021991909545192333, - 0.02825413672911425, - ], - linf=[ - 0.0008410587892853094, - 0.04740176181772552, - 0.04740176181772507, - 0.07483494924031157, - 0.150181591534448, - ]) + @test_trixi_include( + joinpath( + examples_dir(), + "tree_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl", + ), + initial_refinement_level = 2, + tspan = (0.0, 0.25), + l2 = [ + 0.00024173250389635442, + 0.015684268393762454, + 0.01568426839376248, + 0.021991909545192333, + 0.02825413672911425, + ], + linf = [ + 0.0008410587892853094, + 0.04740176181772552, + 0.04740176181772507, + 0.07483494924031157, + 0.150181591534448, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -321,27 +365,41 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl (Refined mesh)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_navierstokes_taylor_green_vortex.jl"), - tspan=(0.0, 0.0)) + @test_trixi_include( + joinpath( + examples_dir(), + "tree_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl", + ), + tspan = (0.0, 0.0) + ) LLID = Trixi.local_leaf_cells(mesh.tree) num_leafs = length(LLID) @assert num_leafs % 32 == 0 Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 32)]) tspan = (0.0, 0.1) - semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition, solver) + semi = SemidiscretizationHyperbolicParabolic( + mesh, + (equations, equations_parabolic), + initial_condition, + solver, + ) ode = semidiscretize(semi, tspan) - analysis_callback = AnalysisCallback(semi, interval = analysis_interval, - save_analysis = true, - extra_analysis_integrals = (energy_kinetic, - energy_internal, - enstrophy)) + analysis_callback = AnalysisCallback( + semi, + interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, energy_internal, enstrophy), + ) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) # Use CarpenterKennedy2N54 since `RDPK3SpFSAL49` gives slightly different results on different machines - sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), - dt = 5e-3, - save_everystep = false, callback = callbacks) + sol = solve( + ode, + CarpenterKennedy2N54(williamson_condition = false), + dt = 5e-3, + save_everystep = false, + callback = callbacks, + ) l2_error, linf_error = analysis_callback(sol) @test l2_error ≈ [ 7.314319856736271e-5, @@ -369,23 +427,29 @@ end end @trixi_testset "P4estMesh3D: elixir_navierstokes_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", - "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), - l2=[ - 0.00026599105554982194, - 0.000461877794472316, - 0.0005424899076052261, - 0.0004618777944723191, - 0.0015846392581126832, - ], - linf=[ - 0.0025241668929956163, - 0.006308461681816373, - 0.004334939663169113, - 0.006308461681804009, - 0.03176343480493493, - ]) + @test_trixi_include( + joinpath( + examples_dir(), + "p4est_3d_dgsem", + "elixir_navierstokes_convergence.jl", + ), + initial_refinement_level = 2, + tspan = (0.0, 0.1), + l2 = [ + 0.00026599105554982194, + 0.000461877794472316, + 0.0005424899076052261, + 0.0004618777944723191, + 0.0015846392581126832, + ], + linf = [ + 0.0025241668929956163, + 0.006308461681816373, + 0.004334939663169113, + 0.006308461681804009, + 0.03176343480493493, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -397,23 +461,29 @@ end end @trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", - "elixir_navierstokes_taylor_green_vortex.jl"), - initial_refinement_level=2, tspan=(0.0, 0.25), - l2=[ - 0.0001547509861140407, - 0.015637861347119624, - 0.015637861347119687, - 0.022024699158522523, - 0.009711013505930812, - ], - linf=[ - 0.0006696415247340326, - 0.03442565722527785, - 0.03442565722577423, - 0.06295407168705314, - 0.032857472756916195, - ]) + @test_trixi_include( + joinpath( + examples_dir(), + "p4est_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl", + ), + initial_refinement_level = 2, + tspan = (0.0, 0.25), + l2 = [ + 0.0001547509861140407, + 0.015637861347119624, + 0.015637861347119687, + 0.022024699158522523, + 0.009711013505930812, + ], + linf = [ + 0.0006696415247340326, + 0.03442565722527785, + 0.03442565722577423, + 0.06295407168705314, + 0.032857472756916195, + ] + ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -424,51 +494,75 @@ end end end - @trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex_amr.jl"), - initial_refinement_level = 0, tspan=(0.0, 0.5), - l2 = [0.0016588740573444188, 0.03437058632045721, 0.03437058632045671, 0.041038898400430075, 0.30978593009044153], - linf = [0.004173569912012121, 0.09168674832979556, 0.09168674832975021, 0.12129218723807476, 0.8433893297612087] +@trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin + @test_trixi_include( + joinpath( + examples_dir(), + "p4est_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex_amr.jl", + ), + initial_refinement_level = 0, + tspan = (0.0, 0.5), + l2 = [ + 0.0016588740573444188, + 0.03437058632045721, + 0.03437058632045671, + 0.041038898400430075, + 0.30978593009044153, + ], + linf = [ + 0.004173569912012121, + 0.09168674832979556, + 0.09168674832975021, + 0.12129218723807476, + 0.8433893297612087, + ] ) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # 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 - @trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_amr.jl"), - l2 = [0.000355780485397024], - linf = [0.0010810770271614256] +@trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin + @test_trixi_include( + joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_amr.jl"), + l2 = [0.000355780485397024], + linf = [0.0010810770271614256] ) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # 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 - @trixi_testset "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_nonperiodic.jl"), - l2 = [0.0009808996243280868], - linf = [0.01732621559135459] +@trixi_testset "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include( + joinpath( + examples_dir(), + "tree_3d_dgsem", + "elixir_advection_diffusion_nonperiodic.jl", + ), + l2 = [0.0009808996243280868], + linf = [0.01732621559135459] ) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # 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 # Clean up afterwards: delete Trixi.jl output directory From bff694dd718e594784510b7394c99d67f5e23cc8 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:29:40 +0100 Subject: [PATCH 120/138] Update elixir_navierstokes_3d_blast_wave_amr.jl --- .../elixir_navierstokes_3d_blast_wave_amr.jl | 176 +++++++----------- 1 file changed, 72 insertions(+), 104 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl index 935ff8d59c5..cb28987143c 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -1,3 +1,4 @@ + using OrdinaryDiffEq using Trixi @@ -9,36 +10,36 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = - CompressibleNavierStokesDiffusion3D(equations, mu = mu(), Prandtl = prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), + Prandtl=prandtl_number()) function initial_condition_3d_blast_wave(x, t, equations::CompressibleEulerEquations3D) - - rho_c = 1.0 - p_c = 1.0 - u_c = 0.0 - - rho_o = 0.125 - p_o = 0.1 - u_o = 0.0 - - rc = 0.5 - r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) - if r < rc - rho = rho_c - v1 = u_c - v2 = u_c - v3 = u_c - p = p_c - else - rho = rho_o - v1 = u_o - v2 = u_o - v3 = u_o - p = p_o - end - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + + rho_c = 1.0 + p_c = 1.0 + u_c = 0.0 + + rho_o = 0.125 + p_o = 0.1 + u_o = 0.0 + + rc = 0.5 + r = sqrt(x[1]^2+x[2]^2+x[3]^2) + if r < rc + rho = rho_c + v1 = u_c + v2 = u_c + v3 = u_c + p = p_c + else + rho = rho_o + v1 = u_o + v2 = u_o + v3 = u_o + p = p_o + end + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_3d_blast_wave @@ -46,44 +47,29 @@ surface_flux = flux_lax_friedrichs volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorHennemannGassner( - equations, - basis, - alpha_max = 1.0, - alpha_min = 0.001, - alpha_smooth = true, - variable = density_pressure, -) -volume_integral = VolumeIntegralShockCapturingHG( - indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux, -) - -solver = - DGSEM(polydeg = polydeg, surface_flux = surface_flux, volume_integral = volume_integral) +indicator_sc = IndicatorHennemannGassner(equations, basis, + alpha_max=1.0, + alpha_min=0.001, + alpha_smooth=true, + variable=density_pressure) +volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; + volume_flux_dg=volume_flux, + volume_flux_fv=surface_flux) + +solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = (1.0, 1.0, 1.0) .* pi +coordinates_max = ( 1.0, 1.0, 1.0) .* pi trees_per_dimension = (4, 4, 4) -mesh = P4estMesh( - trees_per_dimension, - polydeg = 3, - coordinates_min = coordinates_min, - coordinates_max = coordinates_max, - periodicity = (true, true, true), - initial_refinement_level = 1, -) +mesh = P4estMesh(trees_per_dimension, polydeg=3, + coordinates_min=coordinates_min, coordinates_max=coordinates_max, + periodicity=(true, true, true), initial_refinement_level=1) -semi = SemidiscretizationHyperbolicParabolic( - mesh, - (equations, equations_parabolic), - initial_condition, - solver, -) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. @@ -94,54 +80,36 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -save_solution = SaveSolutionCallback( - interval = 20, - save_initial_solution = true, - save_final_solution = true, - solution_variables = cons2prim, -) - -amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) - -amr_controller = ControllerThreeLevel( - semi, - amr_indicator, - base_level = 0, - med_level = 1, - med_threshold = 0.05, - max_level = 4, - max_threshold = 0.1, -) -amr_callback = AMRCallback( - semi, - amr_controller, - interval = 5, - adapt_initial_condition = true, - adapt_initial_condition_only_refine = true, -) - - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -callbacks = CallbackSet( - summary_callback, - analysis_callback, - alive_callback, - amr_callback, - save_solution, -) +analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +save_solution = SaveSolutionCallback(interval=20, + save_initial_solution=true, + save_final_solution=true, + solution_variables=cons2prim) + +amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) + +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level=0, + med_level=1, med_threshold=0.05, + max_level=4, max_threshold=0.1) +amr_callback = AMRCallback(semi, amr_controller, + interval=5, + adapt_initial_condition=true, + adapt_initial_condition_only_refine=true) + + +alive_callback = AliveCallback(analysis_interval=analysis_interval,) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + amr_callback, + save_solution) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve( - ode, - RDPK3SpFSAL49(); - abstol = time_int_tol, - reltol = time_int_tol, - ode_default_options()..., - callback = callbacks, -) +sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, + ode_default_options()..., callback=callbacks) summary_callback() # print the timer summary From 01dd0d223a9885577887a65aa81abe9bbb40073c Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:29:56 +0100 Subject: [PATCH 121/138] Update elixir_navierstokes_taylor_green_vortex_amr.jl --- ...ir_navierstokes_taylor_green_vortex_amr.jl | 126 ++++++------------ 1 file changed, 43 insertions(+), 83 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index 78cd480e2aa..454781b8895 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -1,3 +1,4 @@ + using OrdinaryDiffEq using Trixi @@ -9,18 +10,16 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = - CompressibleNavierStokesDiffusion3D(equations, mu = mu(), Prandtl = prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) + The classical Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex( - x, - t, - equations::CompressibleEulerEquations3D, -) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) A = 1.0 # magnitude of speed Ms = 0.1 # maximum Mach number @@ -29,17 +28,10 @@ function initial_condition_taylor_green_vortex( v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) v3 = 0.0 p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = - p + - 1.0 / 16.0 * - A^2 * - rho * - ( - cos(2 * x[1]) * cos(2 * x[3]) + - 2 * cos(2 * x[2]) + - 2 * cos(2 * x[1]) + - cos(2 * x[2]) * cos(2 * x[3]) - ) + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @@ -51,32 +43,20 @@ initial_condition = initial_condition_taylor_green_vortex end volume_flux = flux_ranocha -solver = DGSEM( - polydeg = 3, - surface_flux = flux_lax_friedrichs, - volume_integral = VolumeIntegralFluxDifferencing(volume_flux), -) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) .* pi coordinates_max = (1.0, 1.0, 1.0) .* pi trees_per_dimension = (2, 2, 2) -mesh = P4estMesh( - trees_per_dimension, - polydeg = 3, - coordinates_min = coordinates_min, - coordinates_max = coordinates_max, - periodicity = (true, true, true), - initial_refinement_level = 0, -) - -semi = SemidiscretizationHyperbolicParabolic( - mesh, - (equations, equations_parabolic), - initial_condition, - solver, -) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, true, true), initial_refinement_level = 0) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. @@ -87,60 +67,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback( - semi, - interval = analysis_interval, - save_analysis = true, - extra_analysis_integrals = (energy_kinetic, energy_internal, enstrophy), -) -save_solution = SaveSolutionCallback( - interval = 100, - save_initial_solution = true, - save_final_solution = true, - solution_variables = cons2prim, -) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorLöhner(semi, variable = vel_mag) -amr_controller = ControllerThreeLevel( - semi, - amr_indicator, - base_level = 0, - med_level = 1, - med_threshold = 0.1, - max_level = 3, - max_threshold = 0.2, -) - -amr_callback = AMRCallback( - semi, - amr_controller, - interval = 5, - adapt_initial_condition = false, - adapt_initial_condition_only_refine = false, -) +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level = 0, + med_level = 1, med_threshold = 0.1, + max_level = 3, max_threshold = 0.2) + +amr_callback = AMRCallback(semi, amr_controller, + interval = 5, + adapt_initial_condition = false, + adapt_initial_condition_only_refine = false) alive_callback = AliveCallback(analysis_interval = analysis_interval) -callbacks = CallbackSet( - summary_callback, - analysis_callback, - alive_callback, - amr_callback, - save_solution, -) +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + amr_callback, + save_solution) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve( - ode, - RDPK3SpFSAL49(); - abstol = time_int_tol, - reltol = time_int_tol, - ode_default_options()..., - callback = callbacks, -) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - From 7edce73256dfeae51780d9ffc2c48afd8f4807a5 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:30:26 +0100 Subject: [PATCH 122/138] Update dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 1255 +++++++------------- 1 file changed, 420 insertions(+), 835 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 0f8d8592a9c..9243f635f9e 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -1,27 +1,18 @@ # This method is called when a SemidiscretizationHyperbolicParabolic is constructed. # It constructs the basic `cache` used throughout the simulation to compute # the RHS etc. -function create_cache_parabolic( - mesh::P4estMesh{3}, - equations_hyperbolic::AbstractEquations, - equations_parabolic::AbstractEquationsParabolic, - dg::DG, - parabolic_scheme, - RealT, - uEltype, -) +function create_cache_parabolic(mesh::P4estMesh{3}, equations_hyperbolic::AbstractEquations, + equations_parabolic::AbstractEquationsParabolic, + dg::DG, parabolic_scheme, RealT, uEltype) balance!(mesh) elements = init_elements(mesh, equations_hyperbolic, dg.basis, uEltype) interfaces = init_interfaces(mesh, equations_hyperbolic, dg.basis, elements) boundaries = init_boundaries(mesh, equations_hyperbolic, dg.basis, elements) - viscous_container = init_viscous_container_3d( - nvariables(equations_hyperbolic), - nnodes(dg.basis), - nelements(elements), - uEltype, - ) + viscous_container = init_viscous_container_3d(nvariables(equations_hyperbolic), + nnodes(dg.basis), nelements(elements), + uEltype) cache = (; elements, interfaces, boundaries, viscous_container) @@ -36,66 +27,31 @@ end # 2. compute f(u, grad(u)) # 3. compute div(f(u, grad(u))) (i.e., the "regular" rhs! call) # boundary conditions will be applied to both grad(u) and div(f(u, grad(u))). -# TODO: Remove in favor of the implementation for the TreeMesh +# TODO: Remove in favor of the implementation for the TreeMesh # once the P4estMesh can handle mortars as well -function rhs_parabolic!( - du, - u, - t, - mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - initial_condition, - boundary_conditions_parabolic, - source_terms, - dg::DG, - parabolic_scheme, - cache, - cache_parabolic, -) +function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + initial_condition, boundary_conditions_parabolic, source_terms, + dg::DG, parabolic_scheme, cache, cache_parabolic) @unpack viscous_container = cache_parabolic @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin - transform_variables!( - u_transformed, - u, - mesh, - equations_parabolic, - dg, - parabolic_scheme, - cache, - cache_parabolic, - ) + transform_variables!(u_transformed, u, mesh, equations_parabolic, + dg, parabolic_scheme, cache, cache_parabolic) end # Compute the gradients of the transformed variables @trixi_timeit timer() "calculate gradient" begin - calc_gradient!( - gradients, - u_transformed, - t, - mesh, - equations_parabolic, - boundary_conditions_parabolic, - dg, - cache, - cache_parabolic, - ) + calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, + boundary_conditions_parabolic, dg, cache, cache_parabolic) end # Compute and store the viscous fluxes @trixi_timeit timer() "calculate viscous fluxes" begin - calc_viscous_fluxes!( - flux_viscous, - gradients, - u_transformed, - mesh, - equations_parabolic, - dg, - cache, - cache_parabolic, - ) + calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, mesh, + equations_parabolic, dg, cache, cache_parabolic) end # The remainder of this function is essentially a regular rhs! for parabolic @@ -122,52 +78,28 @@ function rhs_parabolic!( # Prolong solution to interfaces @trixi_timeit timer() "prolong2interfaces" begin - prolong2interfaces!( - cache_parabolic, - flux_viscous, - mesh, - equations_parabolic, - dg.surface_integral, - dg, - cache, - ) + prolong2interfaces!(cache_parabolic, flux_viscous, mesh, equations_parabolic, + dg.surface_integral, dg, cache) end # Calculate interface fluxes @trixi_timeit timer() "interface flux" begin - calc_interface_flux!( - cache_parabolic.elements.surface_flux_values, - mesh, - equations_parabolic, - dg, - cache_parabolic, - ) + calc_interface_flux!(cache_parabolic.elements.surface_flux_values, mesh, + equations_parabolic, dg, cache_parabolic) end # Prolong solution to boundaries @trixi_timeit timer() "prolong2boundaries" begin - prolong2boundaries!( - cache_parabolic, - flux_viscous, - mesh, - equations_parabolic, - dg.surface_integral, - dg, - cache, - ) + prolong2boundaries!(cache_parabolic, flux_viscous, mesh, equations_parabolic, + dg.surface_integral, dg, cache) end # Calculate boundary fluxes @trixi_timeit timer() "boundary flux" begin - calc_boundary_flux_divergence!( - cache_parabolic, - t, - boundary_conditions_parabolic, - mesh, - equations_parabolic, - dg.surface_integral, - dg, - ) + calc_boundary_flux_divergence!(cache_parabolic, t, + boundary_conditions_parabolic, + mesh, equations_parabolic, + dg.surface_integral, dg) end @@ -175,41 +107,21 @@ function rhs_parabolic!( # !!! NOTE: we reuse the hyperbolic cache here since it contains "mortars" and "u_threaded" # !!! Is this OK? @trixi_timeit timer() "prolong2mortars" begin - prolong2mortars_divergence!( - cache, - flux_viscous, - mesh, - equations_parabolic, - dg.mortar, - dg.surface_integral, - dg, - ) + prolong2mortars_divergence!(cache, flux_viscous, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) end # Calculate mortar fluxes (specialized for AbstractEquationsParabolic) @trixi_timeit timer() "mortar flux" begin - calc_mortar_flux_divergence!( - cache_parabolic.elements.surface_flux_values, - mesh, - equations_parabolic, - dg.mortar, - dg.surface_integral, - dg, - cache, - ) + calc_mortar_flux_divergence!(cache_parabolic.elements.surface_flux_values, + mesh, equations_parabolic, dg.mortar, + dg.surface_integral, dg, cache) end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin - calc_surface_integral!( - du, - u, - mesh, - equations_parabolic, - dg.surface_integral, - dg, - cache_parabolic, - ) + calc_surface_integral!(du, u, mesh, equations_parabolic, + dg.surface_integral, dg, cache_parabolic) end # Apply Jacobian from mapping to reference element @@ -220,17 +132,10 @@ function rhs_parabolic!( return nothing end -function calc_gradient!( - gradients, - u_transformed, - t, - mesh::P4estMesh{3}, - equations_parabolic, - boundary_conditions_parabolic, - dg::DG, - cache, - cache_parabolic, -) +function calc_gradient!(gradients, u_transformed, t, + mesh::P4estMesh{3}, equations_parabolic, + boundary_conditions_parabolic, dg::DG, + cache, cache_parabolic) gradients_x, gradients_y, gradients_z = gradients # Reset du @@ -249,201 +154,112 @@ function calc_gradient!( # Calculate gradients with respect to reference coordinates in one element for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - u_node = - get_node_vars(u_transformed, equations_parabolic, dg, i, j, k, element) + u_node = get_node_vars(u_transformed, equations_parabolic, dg, i, j, k, + element) for ii in eachnode(dg) - multiply_add_to_node_vars!( - gradients_x, - derivative_dhat[ii, i], - u_node, - equations_parabolic, - dg, - ii, - j, - k, - element, - ) + multiply_add_to_node_vars!(gradients_x, derivative_dhat[ii, i], + u_node, equations_parabolic, dg, ii, j, + k, element) end for jj in eachnode(dg) - multiply_add_to_node_vars!( - gradients_y, - derivative_dhat[jj, j], - u_node, - equations_parabolic, - dg, - i, - jj, - k, - element, - ) + multiply_add_to_node_vars!(gradients_y, derivative_dhat[jj, j], + u_node, equations_parabolic, dg, i, jj, + k, element) end for kk in eachnode(dg) - multiply_add_to_node_vars!( - gradients_z, - derivative_dhat[kk, k], - u_node, - equations_parabolic, - dg, - i, - j, - kk, - element, - ) + multiply_add_to_node_vars!(gradients_z, derivative_dhat[kk, k], + u_node, equations_parabolic, dg, i, j, + kk, element) end end # now that the reference coordinate gradients are computed, transform them node-by-node to physical gradients # using the contravariant vectors for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - Ja11, Ja12, Ja13 = - get_contravariant_vector(1, contravariant_vectors, i, j, k, element) - Ja21, Ja22, Ja23 = - get_contravariant_vector(2, contravariant_vectors, i, j, k, element) - Ja31, Ja32, Ja33 = - get_contravariant_vector(3, contravariant_vectors, i, j, k, element) - - gradients_reference_1 = - get_node_vars(gradients_x, equations_parabolic, dg, i, j, k, element) - gradients_reference_2 = - get_node_vars(gradients_y, equations_parabolic, dg, i, j, k, element) - gradients_reference_3 = - get_node_vars(gradients_z, equations_parabolic, dg, i, j, k, element) + Ja11, Ja12, Ja13 = get_contravariant_vector(1, contravariant_vectors, + i, j, k, element) + Ja21, Ja22, Ja23 = get_contravariant_vector(2, contravariant_vectors, + i, j, k, element) + Ja31, Ja32, Ja33 = get_contravariant_vector(3, contravariant_vectors, + i, j, k, element) + + gradients_reference_1 = get_node_vars(gradients_x, equations_parabolic, dg, + i, j, k, element) + gradients_reference_2 = get_node_vars(gradients_y, equations_parabolic, dg, + i, j, k, element) + gradients_reference_3 = get_node_vars(gradients_z, equations_parabolic, dg, + i, j, k, element) # note that the contravariant vectors are transposed compared with computations of flux # divergences in `calc_volume_integral!`. See # https://github.com/trixi-framework/Trixi.jl/pull/1490#discussion_r1213345190 # for a more detailed discussion. - gradient_x_node = - Ja11 * gradients_reference_1 + - Ja21 * gradients_reference_2 + - Ja31 * gradients_reference_3 - gradient_y_node = - Ja12 * gradients_reference_1 + - Ja22 * gradients_reference_2 + - Ja32 * gradients_reference_3 - gradient_z_node = - Ja13 * gradients_reference_1 + - Ja23 * gradients_reference_2 + - Ja33 * gradients_reference_3 - - set_node_vars!( - gradients_x, - gradient_x_node, - equations_parabolic, - dg, - i, - j, - k, - element, - ) - set_node_vars!( - gradients_y, - gradient_y_node, - equations_parabolic, - dg, - i, - j, - k, - element, - ) - set_node_vars!( - gradients_z, - gradient_z_node, - equations_parabolic, - dg, - i, - j, - k, - element, - ) + gradient_x_node = Ja11 * gradients_reference_1 + + Ja21 * gradients_reference_2 + + Ja31 * gradients_reference_3 + gradient_y_node = Ja12 * gradients_reference_1 + + Ja22 * gradients_reference_2 + + Ja32 * gradients_reference_3 + gradient_z_node = Ja13 * gradients_reference_1 + + Ja23 * gradients_reference_2 + + Ja33 * gradients_reference_3 + + set_node_vars!(gradients_x, gradient_x_node, equations_parabolic, dg, + i, j, k, element) + set_node_vars!(gradients_y, gradient_y_node, equations_parabolic, dg, + i, j, k, element) + set_node_vars!(gradients_z, gradient_z_node, equations_parabolic, dg, + i, j, k, element) end end end # Prolong solution to interfaces @trixi_timeit timer() "prolong2interfaces" begin - prolong2interfaces!( - cache_parabolic, - u_transformed, - mesh, - equations_parabolic, - dg.surface_integral, - dg, - ) + prolong2interfaces!(cache_parabolic, u_transformed, mesh, + equations_parabolic, dg.surface_integral, dg) end # Calculate interface fluxes for the gradient. This reuses P4est `calc_interface_flux!` along with a # specialization for AbstractEquationsParabolic. @trixi_timeit timer() "interface flux" begin - calc_interface_flux!( - cache_parabolic.elements.surface_flux_values, - mesh, - False(), # False() = no nonconservative terms - equations_parabolic, - dg.surface_integral, - dg, - cache_parabolic, - ) + calc_interface_flux!(cache_parabolic.elements.surface_flux_values, + mesh, False(), # False() = no nonconservative terms + equations_parabolic, dg.surface_integral, dg, cache_parabolic) end # Prolong solution to boundaries @trixi_timeit timer() "prolong2boundaries" begin - prolong2boundaries!( - cache_parabolic, - u_transformed, - mesh, - equations_parabolic, - dg.surface_integral, - dg, - ) + prolong2boundaries!(cache_parabolic, u_transformed, mesh, + equations_parabolic, dg.surface_integral, dg) end # Calculate boundary fluxes @trixi_timeit timer() "boundary flux" begin - calc_boundary_flux_gradients!( - cache_parabolic, - t, - boundary_conditions_parabolic, - mesh, - equations_parabolic, - dg.surface_integral, - dg, - ) + calc_boundary_flux_gradients!(cache_parabolic, t, boundary_conditions_parabolic, + mesh, equations_parabolic, dg.surface_integral, dg) end # Prolong solution to mortars. These should reuse the hyperbolic version of `prolong2mortars` - # !!! NOTE: we reuse the hyperbolic cache here, since it contains both `mortars` and `u_threaded`. + # !!! NOTE: we reuse the hyperbolic cache here, since it contains both `mortars` and `u_threaded`. # !!! should we have a separate mortars/u_threaded in cache_parabolic? @trixi_timeit timer() "prolong2mortars" begin - prolong2mortars!( - cache, - u_transformed, - mesh, - equations_parabolic, - dg.mortar, - dg.surface_integral, - dg, - ) + prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) end # Calculate mortar fluxes. These should reuse the hyperbolic version of `calc_mortar_flux`, - # along with a specialization on `calc_mortar_flux!` and `mortar_fluxes_to_elements!` for - # AbstractEquationsParabolic. + # along with a specialization on `calc_mortar_flux!` and `mortar_fluxes_to_elements!` for + # AbstractEquationsParabolic. @trixi_timeit timer() "mortar flux" begin - calc_mortar_flux!( - cache_parabolic.elements.surface_flux_values, - mesh, - False(), # False() = no nonconservative terms - equations_parabolic, - dg.mortar, - dg.surface_integral, - dg, - cache, - ) + calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, + mesh, False(), # False() = no nonconservative terms + equations_parabolic, + dg.mortar, dg.surface_integral, dg, cache) end # Calculate surface integrals @@ -460,85 +276,64 @@ function calc_gradient!( @threaded for element in eachelement(dg, cache) for l in eachnode(dg), m in eachnode(dg) for v in eachvariable(equations_parabolic) - for dim = 1:3 + for dim in 1:3 grad = gradients[dim] # surface at -x - normal_direction = - get_normal_direction(1, contravariant_vectors, 1, l, m, element) - grad[v, 1, l, m, element] = ( - grad[v, 1, l, m, element] + - surface_flux_values[v, l, m, 1, element] * - factor_1 * - normal_direction[dim] - ) + normal_direction = get_normal_direction(1, contravariant_vectors, + 1, l, m, element) + grad[v, 1, l, m, element] = (grad[v, 1, l, m, element] + + surface_flux_values[v, l, m, 1, + element] * + factor_1 * normal_direction[dim]) # surface at +x - normal_direction = get_normal_direction( - 2, - contravariant_vectors, - nnodes(dg), - l, - m, - element, - ) - grad[v, nnodes(dg), l, m, element] = ( - grad[v, nnodes(dg), l, m, element] + - surface_flux_values[v, l, m, 2, element] * - factor_2 * - normal_direction[dim] - ) + normal_direction = get_normal_direction(2, contravariant_vectors, + nnodes(dg), l, m, element) + grad[v, nnodes(dg), l, m, element] = (grad[v, nnodes(dg), l, m, + element] + + surface_flux_values[v, l, m, + 2, + element] * + factor_2 * + normal_direction[dim]) # surface at -y - normal_direction = - get_normal_direction(3, contravariant_vectors, l, m, 1, element) - grad[v, l, 1, m, element] = ( - grad[v, l, 1, m, element] + - surface_flux_values[v, l, m, 3, element] * - factor_1 * - normal_direction[dim] - ) + normal_direction = get_normal_direction(3, contravariant_vectors, + l, m, 1, element) + grad[v, l, 1, m, element] = (grad[v, l, 1, m, element] + + surface_flux_values[v, l, m, 3, + element] * + factor_1 * normal_direction[dim]) # surface at +y - normal_direction = get_normal_direction( - 4, - contravariant_vectors, - l, - nnodes(dg), - m, - element, - ) - grad[v, l, nnodes(dg), m, element] = ( - grad[v, l, nnodes(dg), m, element] + - surface_flux_values[v, l, m, 4, element] * - factor_2 * - normal_direction[dim] - ) + normal_direction = get_normal_direction(4, contravariant_vectors, + l, nnodes(dg), m, element) + grad[v, l, nnodes(dg), m, element] = (grad[v, l, nnodes(dg), m, + element] + + surface_flux_values[v, l, m, + 4, + element] * + factor_2 * + normal_direction[dim]) # surface at -z - normal_direction = - get_normal_direction(5, contravariant_vectors, l, m, 1, element) - grad[v, l, m, 1, element] = ( - grad[v, l, m, 1, element] + - surface_flux_values[v, l, m, 5, element] * - factor_1 * - normal_direction[dim] - ) + normal_direction = get_normal_direction(5, contravariant_vectors, + l, m, 1, element) + grad[v, l, m, 1, element] = (grad[v, l, m, 1, element] + + surface_flux_values[v, l, m, 5, + element] * + factor_1 * normal_direction[dim]) # surface at +z - normal_direction = get_normal_direction( - 6, - contravariant_vectors, - l, - m, - nnodes(dg), - element, - ) - grad[v, l, m, nnodes(dg), element] = ( - grad[v, l, m, nnodes(dg), element] + - surface_flux_values[v, l, m, 6, element] * - factor_2 * - normal_direction[dim] - ) + normal_direction = get_normal_direction(6, contravariant_vectors, + l, m, nnodes(dg), element) + grad[v, l, m, nnodes(dg), element] = (grad[v, l, m, nnodes(dg), + element] + + surface_flux_values[v, l, m, + 6, + element] * + factor_2 * + normal_direction[dim]) end end end @@ -547,92 +342,59 @@ function calc_gradient!( # Apply Jacobian from mapping to reference element @trixi_timeit timer() "Jacobian" begin - apply_jacobian_parabolic!( - gradients_x, - mesh, - equations_parabolic, - dg, - cache_parabolic, - ) - apply_jacobian_parabolic!( - gradients_y, - mesh, - equations_parabolic, - dg, - cache_parabolic, - ) - apply_jacobian_parabolic!( - gradients_z, - mesh, - equations_parabolic, - dg, - cache_parabolic, - ) + apply_jacobian_parabolic!(gradients_x, mesh, equations_parabolic, dg, + cache_parabolic) + apply_jacobian_parabolic!(gradients_y, mesh, equations_parabolic, dg, + cache_parabolic) + apply_jacobian_parabolic!(gradients_z, mesh, equations_parabolic, dg, + cache_parabolic) end return nothing end # This version is called during `calc_gradients!` and must be specialized because the flux -# in the gradient is {u} which doesn't depend on normals. Thus, you don't need to scale by +# in the gradient is {u} which doesn't depend on normals. Thus, you don't need to scale by # 2 and flip the sign when storing the mortar fluxes back into surface_flux_values -@inline function mortar_fluxes_to_elements!( - surface_flux_values, - mesh::P4estMesh{3}, - equations::AbstractEquationsParabolic, - mortar_l2::LobattoLegendreMortarL2, - dg::DGSEM, - cache, - mortar, - fstar, - u_buffer, - fstar_tmp, -) +@inline function mortar_fluxes_to_elements!(surface_flux_values, + mesh::P4estMesh{3}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + dg::DGSEM, cache, mortar, fstar, u_buffer, + fstar_tmp) @unpack neighbor_ids, node_indices = cache.mortars index_range = eachnode(dg) # Copy solution small to small small_indices = node_indices[1, mortar] small_direction = indices2direction(small_indices) - for position = 1:4 + for position in 1:4 element = neighbor_ids[position, mortar] for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) - surface_flux_values[v, i, j, small_direction, element] = - fstar[v, i, j, position] + surface_flux_values[v, i, j, small_direction, element] = fstar[v, i, j, + position] end end end # Project small fluxes to large element. - multiply_dimensionwise!( - u_buffer, - mortar_l2.reverse_lower, - mortar_l2.reverse_lower, - view(fstar, .., 1), - fstar_tmp, - ) - add_multiply_dimensionwise!( - u_buffer, - mortar_l2.reverse_upper, - mortar_l2.reverse_lower, - view(fstar, .., 2), - fstar_tmp, - ) - add_multiply_dimensionwise!( - u_buffer, - mortar_l2.reverse_lower, - mortar_l2.reverse_upper, - view(fstar, .., 3), - fstar_tmp, - ) - add_multiply_dimensionwise!( - u_buffer, - mortar_l2.reverse_upper, - mortar_l2.reverse_upper, - view(fstar, .., 4), - fstar_tmp, - ) + multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_lower, mortar_l2.reverse_lower, + view(fstar, .., 1), + fstar_tmp) + add_multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_upper, mortar_l2.reverse_lower, + view(fstar, .., 2), + fstar_tmp) + add_multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_lower, mortar_l2.reverse_upper, + view(fstar, .., 3), + fstar_tmp) + add_multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_upper, mortar_l2.reverse_upper, + view(fstar, .., 4), + fstar_tmp) # The flux is calculated in the outward direction of the small elements, # so the sign must be switched to get the flux in outward direction @@ -652,10 +414,10 @@ end large_direction = indices2direction(large_indices) large_surface_indices = surface_indices(large_indices) - i_large_start, i_large_step_i, i_large_step_j = - index_to_start_step_3d(large_surface_indices[1], index_range) - j_large_start, j_large_step_i, j_large_step_j = - index_to_start_step_3d(large_surface_indices[2], index_range) + i_large_start, i_large_step_i, i_large_step_j = index_to_start_step_3d(large_surface_indices[1], + index_range) + j_large_start, j_large_step_i, j_large_step_j = index_to_start_step_3d(large_surface_indices[2], + index_range) # Note that the indices of the small sides will always run forward but # the large indices might need to run backwards for flipped sides. @@ -664,8 +426,9 @@ end for j in eachnode(dg) for i in eachnode(dg) for v in eachvariable(equations) - surface_flux_values[v, i_large, j_large, large_direction, large_element] = - u_buffer[v, i, j] + surface_flux_values[v, i_large, j_large, large_direction, large_element] = u_buffer[v, + i, + j] end i_large += i_large_step_i j_large += j_large_step_i @@ -678,68 +441,38 @@ end end # This version is used for parabolic gradient computations -@inline function calc_interface_flux!( - surface_flux_values, - mesh::P4estMesh{3}, - nonconservative_terms::False, - equations::AbstractEquationsParabolic, - surface_integral, - dg::DG, - cache, - interface_index, - normal_direction, - primary_i_node_index, - primary_j_node_index, - primary_direction_index, - primary_element_index, - secondary_i_node_index, - secondary_j_node_index, - secondary_direction_index, - secondary_element_index, -) +@inline function calc_interface_flux!(surface_flux_values, mesh::P4estMesh{3}, + nonconservative_terms::False, + equations::AbstractEquationsParabolic, + surface_integral, dg::DG, cache, + interface_index, normal_direction, + primary_i_node_index, primary_j_node_index, + primary_direction_index, primary_element_index, + secondary_i_node_index, secondary_j_node_index, + secondary_direction_index, + secondary_element_index) @unpack u = cache.interfaces @unpack surface_flux = surface_integral - u_ll, u_rr = get_surface_node_vars( - u, - equations, - dg, - primary_i_node_index, - primary_j_node_index, - interface_index, - ) + u_ll, u_rr = get_surface_node_vars(u, equations, dg, primary_i_node_index, + primary_j_node_index, + interface_index) flux_ = 0.5 * (u_ll + u_rr) # we assume that the gradient computations utilize a central flux # Note that we don't flip the sign on the secondondary flux. This is because for parabolic terms, # the normals are not embedded in `flux_` for the parabolic gradient computations. for v in eachvariable(equations) - surface_flux_values[ - v, - primary_i_node_index, - primary_j_node_index, - primary_direction_index, - primary_element_index, - ] = flux_[v] - surface_flux_values[ - v, - secondary_i_node_index, - secondary_j_node_index, - secondary_direction_index, - secondary_element_index, - ] = flux_[v] + surface_flux_values[v, primary_i_node_index, primary_j_node_index, primary_direction_index, primary_element_index] = flux_[v] + surface_flux_values[v, secondary_i_node_index, secondary_j_node_index, secondary_direction_index, secondary_element_index] = flux_[v] end end # This is the version used when calculating the divergence of the viscous fluxes -function calc_volume_integral!( - du, - flux_viscous, - mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - dg::DGSEM, - cache, -) +function calc_volume_integral!(du, flux_viscous, + mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + dg::DGSEM, cache) (; derivative_dhat) = dg.basis (; contravariant_vectors) = cache.elements flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous @@ -753,59 +486,32 @@ function calc_volume_integral!( # Compute the contravariant flux by taking the scalar product of the # first contravariant vector Ja^1 and the flux vector - Ja11, Ja12, Ja13 = - get_contravariant_vector(1, contravariant_vectors, i, j, k, element) + Ja11, Ja12, Ja13 = get_contravariant_vector(1, contravariant_vectors, i, j, k, + element) contravariant_flux1 = Ja11 * flux1 + Ja12 * flux2 + Ja13 * flux3 for ii in eachnode(dg) - multiply_add_to_node_vars!( - du, - derivative_dhat[ii, i], - contravariant_flux1, - equations_parabolic, - dg, - ii, - j, - k, - element, - ) + multiply_add_to_node_vars!(du, derivative_dhat[ii, i], contravariant_flux1, + equations_parabolic, dg, ii, j, k, element) end # Compute the contravariant flux by taking the scalar product of the # second contravariant vector Ja^2 and the flux vector - Ja21, Ja22, Ja23 = - get_contravariant_vector(2, contravariant_vectors, i, j, k, element) + Ja21, Ja22, Ja23 = get_contravariant_vector(2, contravariant_vectors, i, j, k, + element) contravariant_flux2 = Ja21 * flux1 + Ja22 * flux2 + Ja23 * flux3 for jj in eachnode(dg) - multiply_add_to_node_vars!( - du, - derivative_dhat[jj, j], - contravariant_flux2, - equations_parabolic, - dg, - i, - jj, - k, - element, - ) + multiply_add_to_node_vars!(du, derivative_dhat[jj, j], contravariant_flux2, + equations_parabolic, dg, i, jj, k, element) end # Compute the contravariant flux by taking the scalar product of the # second contravariant vector Ja^2 and the flux vector - Ja31, Ja32, Ja33 = - get_contravariant_vector(3, contravariant_vectors, i, j, k, element) + Ja31, Ja32, Ja33 = get_contravariant_vector(3, contravariant_vectors, i, j, k, + element) contravariant_flux3 = Ja31 * flux1 + Ja32 * flux2 + Ja33 * flux3 for kk in eachnode(dg) - multiply_add_to_node_vars!( - du, - derivative_dhat[kk, k], - contravariant_flux3, - equations_parabolic, - dg, - i, - j, - kk, - element, - ) + multiply_add_to_node_vars!(du, derivative_dhat[kk, k], contravariant_flux3, + equations_parabolic, dg, i, j, kk, element) end end end @@ -815,15 +521,10 @@ end # This is the version used when calculating the divergence of the viscous fluxes # We pass the `surface_integral` argument solely for dispatch -function prolong2interfaces!( - cache_parabolic, - flux_viscous, - mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - surface_integral, - dg::DG, - cache, -) +function prolong2interfaces!(cache_parabolic, flux_viscous, + mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG, cache) (; interfaces) = cache_parabolic (; contravariant_vectors) = cache_parabolic.elements index_range = eachnode(dg) @@ -839,12 +540,12 @@ function prolong2interfaces!( primary_indices = interfaces.node_indices[1, interface] primary_direction = indices2direction(primary_indices) - i_primary_start, i_primary_step_i, i_primary_step_j = - index_to_start_step_3d(primary_indices[1], index_range) - j_primary_start, j_primary_step_i, j_primary_step_j = - index_to_start_step_3d(primary_indices[2], index_range) - k_primary_start, k_primary_step_i, k_primary_step_j = - index_to_start_step_3d(primary_indices[3], index_range) + i_primary_start, i_primary_step_i, i_primary_step_j = index_to_start_step_3d(primary_indices[1], + index_range) + j_primary_start, j_primary_step_i, j_primary_step_j = index_to_start_step_3d(primary_indices[2], + index_range) + k_primary_start, k_primary_step_i, k_primary_step_j = index_to_start_step_3d(primary_indices[3], + index_range) i_primary = i_primary_start j_primary = j_primary_start @@ -853,25 +554,25 @@ function prolong2interfaces!( for j in eachnode(dg) for i in eachnode(dg) # this is the outward normal direction on the primary element - normal_direction = get_normal_direction( - primary_direction, - contravariant_vectors, - i_primary, - j_primary, - k_primary, - primary_element, - ) + normal_direction = get_normal_direction(primary_direction, + contravariant_vectors, + i_primary, j_primary, k_primary, + primary_element) for v in eachvariable(equations_parabolic) # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - flux_viscous = SVector( - flux_viscous_x[v, i_primary, j_primary, k_primary, primary_element], - flux_viscous_y[v, i_primary, j_primary, k_primary, primary_element], - flux_viscous_z[v, i_primary, j_primary, k_primary, primary_element], - ) - - interfaces.u[1, v, i, j, interface] = - dot(flux_viscous, normal_direction) + flux_viscous = SVector(flux_viscous_x[v, i_primary, j_primary, + k_primary, + primary_element], + flux_viscous_y[v, i_primary, j_primary, + k_primary, + primary_element], + flux_viscous_z[v, i_primary, j_primary, + k_primary, + primary_element]) + + interfaces.u[1, v, i, j, interface] = dot(flux_viscous, + normal_direction) end i_primary += i_primary_step_i j_primary += j_primary_step_i @@ -888,12 +589,12 @@ function prolong2interfaces!( secondary_indices = interfaces.node_indices[2, interface] secondary_direction = indices2direction(secondary_indices) - i_secondary_start, i_secondary_step_i, i_secondary_step_j = - index_to_start_step_3d(secondary_indices[1], index_range) - j_secondary_start, j_secondary_step_i, j_secondary_step_j = - index_to_start_step_3d(secondary_indices[2], index_range) - k_secondary_start, k_secondary_step_i, k_secondary_step_j = - index_to_start_step_3d(secondary_indices[3], index_range) + i_secondary_start, i_secondary_step_i, i_secondary_step_j = index_to_start_step_3d(secondary_indices[1], + index_range) + j_secondary_start, j_secondary_step_i, j_secondary_step_j = index_to_start_step_3d(secondary_indices[2], + index_range) + k_secondary_start, k_secondary_step_i, k_secondary_step_j = index_to_start_step_3d(secondary_indices[3], + index_range) i_secondary = i_secondary_start j_secondary = j_secondary_start @@ -903,43 +604,26 @@ function prolong2interfaces!( # This is the outward normal direction on the secondary element. # Here, we assume that normal_direction on the secondary element is # the negative of normal_direction on the primary element. - normal_direction = get_normal_direction( - secondary_direction, - contravariant_vectors, - i_secondary, - j_secondary, - k_secondary, - secondary_element, - ) + normal_direction = get_normal_direction(secondary_direction, + contravariant_vectors, + i_secondary, j_secondary, + k_secondary, + secondary_element) for v in eachvariable(equations_parabolic) # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - flux_viscous = SVector( - flux_viscous_x[ - v, - i_secondary, - j_secondary, - k_secondary, - secondary_element, - ], - flux_viscous_y[ - v, - i_secondary, - j_secondary, - k_secondary, - secondary_element, - ], - flux_viscous_z[ - v, - i_secondary, - j_secondary, - k_secondary, - secondary_element, - ], - ) + flux_viscous = SVector(flux_viscous_x[v, i_secondary, j_secondary, + k_secondary, + secondary_element], + flux_viscous_y[v, i_secondary, j_secondary, + k_secondary, + secondary_element], + flux_viscous_z[v, i_secondary, j_secondary, + k_secondary, + secondary_element]) # store the normal flux with respect to the primary normal direction - interfaces.u[2, v, i, j, interface] = - -dot(flux_viscous, normal_direction) + interfaces.u[2, v, i, j, interface] = -dot(flux_viscous, + normal_direction) end i_secondary += i_secondary_step_i j_secondary += j_secondary_step_i @@ -954,14 +638,10 @@ function prolong2interfaces!( return nothing end -# This version is used for divergence flux computations -function calc_interface_flux!( - surface_flux_values, - mesh::P4estMesh{3}, - equations_parabolic, - dg::DG, - cache_parabolic, -) +# This version is used for divergence flux computations +function calc_interface_flux!(surface_flux_values, + mesh::P4estMesh{3}, equations_parabolic, + dg::DG, cache_parabolic) (; neighbor_ids, node_indices) = cache_parabolic.interfaces index_range = eachnode(dg) @@ -971,12 +651,12 @@ function calc_interface_flux!( primary_indices = node_indices[1, interface] primary_direction_index = indices2direction(primary_indices) - i_primary_start, i_primary_step_i, i_primary_step_j = - index_to_start_step_3d(primary_indices[1], index_range) - j_primary_start, j_primary_step_i, j_primary_step_j = - index_to_start_step_3d(primary_indices[2], index_range) - k_primary_start, k_primary_step_i, k_primary_step_j = - index_to_start_step_3d(primary_indices[3], index_range) + i_primary_start, i_primary_step_i, i_primary_step_j = index_to_start_step_3d(primary_indices[1], + index_range) + j_primary_start, j_primary_step_i, j_primary_step_j = index_to_start_step_3d(primary_indices[2], + index_range) + k_primary_start, k_primary_step_i, k_primary_step_j = index_to_start_step_3d(primary_indices[3], + index_range) i_primary = i_primary_start j_primary = j_primary_start @@ -994,38 +674,28 @@ function calc_interface_flux!( # Get the surface indexing on the secondary element. # Note that the indices of the primary side will always run forward but # the secondary indices might need to run backwards for flipped sides. - i_secondary_start, i_secondary_step_i, i_secondary_step_j = - index_to_start_step_3d(secondary_surface_indices[1], index_range) - j_secondary_start, j_secondary_step_i, j_secondary_step_j = - index_to_start_step_3d(secondary_surface_indices[2], index_range) + i_secondary_start, i_secondary_step_i, i_secondary_step_j = index_to_start_step_3d(secondary_surface_indices[1], + index_range) + j_secondary_start, j_secondary_step_i, j_secondary_step_j = index_to_start_step_3d(secondary_surface_indices[2], + index_range) i_secondary = i_secondary_start j_secondary = j_secondary_start for j in eachnode(dg) for i in eachnode(dg) - # We prolong the viscous flux dotted with respect the outward normal on the + # We prolong the viscous flux dotted with respect the outward normal on the # primary element. We assume a BR-1 type of flux. - viscous_flux_normal_ll, viscous_flux_normal_rr = get_surface_node_vars( - cache_parabolic.interfaces.u, - equations_parabolic, - dg, - i, - j, - interface, - ) + viscous_flux_normal_ll, viscous_flux_normal_rr = get_surface_node_vars(cache_parabolic.interfaces.u, + equations_parabolic, + dg, + i, j, + interface) flux = 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) for v in eachvariable(equations_parabolic) - surface_flux_values[v, i, j, primary_direction_index, primary_element] = - flux[v] - surface_flux_values[ - v, - i_secondary, - j_secondary, - secondary_direction_index, - secondary_element, - ] = -flux[v] + surface_flux_values[v, i, j, primary_direction_index, primary_element] = flux[v] + surface_flux_values[v, i_secondary, j_secondary, secondary_direction_index, secondary_element] = -flux[v] end # Increment the primary element indices @@ -1049,15 +719,10 @@ function calc_interface_flux!( return nothing end -function prolong2mortars_divergence!( - cache, - flux_viscous, - mesh::Union{P4estMesh{3},T8codeMesh{3}}, - equations, - mortar_l2::LobattoLegendreMortarL2, - surface_integral, - dg::DGSEM, -) +function prolong2mortars_divergence!(cache, flux_viscous, + mesh::Union{P4estMesh{3}, T8codeMesh{3}}, equations, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DGSEM) @unpack neighbor_ids, node_indices = cache.mortars @unpack fstar_tmp_threaded = cache @unpack contravariant_vectors = cache.elements @@ -1071,38 +736,35 @@ function prolong2mortars_divergence!( small_indices = node_indices[1, mortar] direction_index = indices2direction(small_indices) - i_small_start, i_small_step_i, i_small_step_j = - index_to_start_step_3d(small_indices[1], index_range) - j_small_start, j_small_step_i, j_small_step_j = - index_to_start_step_3d(small_indices[2], index_range) - k_small_start, k_small_step_i, k_small_step_j = - index_to_start_step_3d(small_indices[3], index_range) + i_small_start, i_small_step_i, i_small_step_j = index_to_start_step_3d(small_indices[1], + index_range) + j_small_start, j_small_step_i, j_small_step_j = index_to_start_step_3d(small_indices[2], + index_range) + k_small_start, k_small_step_i, k_small_step_j = index_to_start_step_3d(small_indices[3], + index_range) - for position = 1:4 + for position in 1:4 i_small = i_small_start j_small = j_small_start k_small = k_small_start element = neighbor_ids[position, mortar] for j in eachnode(dg) for i in eachnode(dg) - normal_direction = get_normal_direction( - direction_index, - contravariant_vectors, - i_small, - j_small, - k_small, - element, - ) + normal_direction = get_normal_direction(direction_index, + contravariant_vectors, + i_small, j_small, k_small, + element) for v in eachvariable(equations) - flux_viscous = SVector( - flux_viscous_x[v, i_small, j_small, k_small, element], - flux_viscous_y[v, i_small, j_small, k_small, element], - flux_viscous_z[v, i_small, j_small, k_small, element], - ) - - cache.mortars.u[1, v, position, i, j, mortar] = - dot(flux_viscous, normal_direction) + flux_viscous = SVector(flux_viscous_x[v, i_small, j_small, k_small, + element], + flux_viscous_y[v, i_small, j_small, k_small, + element], + flux_viscous_z[v, i_small, j_small, k_small, + element]) + + cache.mortars.u[1, v, position, i, j, mortar] = dot(flux_viscous, + normal_direction) end i_small += i_small_step_i j_small += j_small_step_i @@ -1125,12 +787,12 @@ function prolong2mortars_divergence!( # correct orientation large_indices = node_indices[2, mortar] - i_large_start, i_large_step_i, i_large_step_j = - index_to_start_step_3d(large_indices[1], index_range) - j_large_start, j_large_step_i, j_large_step_j = - index_to_start_step_3d(large_indices[2], index_range) - k_large_start, k_large_step_i, k_large_step_j = - index_to_start_step_3d(large_indices[3], index_range) + i_large_start, i_large_step_i, i_large_step_j = index_to_start_step_3d(large_indices[1], + index_range) + j_large_start, j_large_step_i, j_large_step_j = index_to_start_step_3d(large_indices[2], + index_range) + k_large_start, k_large_step_i, k_large_step_j = index_to_start_step_3d(large_indices[3], + index_range) i_large = i_large_start j_large = j_large_start @@ -1138,25 +800,21 @@ function prolong2mortars_divergence!( element = neighbor_ids[5, mortar] for j in eachnode(dg) for i in eachnode(dg) - normal_direction = get_normal_direction( - direction_index, - contravariant_vectors, - i_large, - j_large, - k_large, - element, - ) + normal_direction = get_normal_direction(direction_index, + contravariant_vectors, + i_large, j_large, k_large, element) for v in eachvariable(equations) - flux_viscous = SVector( - flux_viscous_x[v, i_large, j_large, k_large, element], - flux_viscous_y[v, i_large, j_large, k_large, element], - flux_viscous_z[v, i_large, j_large, k_large, element], - ) - - # We prolong the viscous flux dotted with respect the outward normal - # on the small element. We scale by -1/2 here because the normal - # direction on the large element is negative 2x that of the small + flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, k_large, + element], + flux_viscous_y[v, i_large, j_large, k_large, + element], + flux_viscous_z[v, i_large, j_large, k_large, + element]) + + # We prolong the viscous flux dotted with respect the outward normal + # on the small element. We scale by -1/2 here because the normal + # direction on the large element is negative 2x that of the small # element (these normal directions are "scaled" by the surface Jacobian) u_buffer[v, i, j] = -0.5 * dot(flux_viscous, normal_direction) end @@ -1170,50 +828,38 @@ function prolong2mortars_divergence!( end # Interpolate large element face data from buffer to small face locations - multiply_dimensionwise!( - view(cache.mortars.u, 2, :, 1, :, :, mortar), - mortar_l2.forward_lower, - mortar_l2.forward_lower, - u_buffer, - fstar_tmp, - ) - multiply_dimensionwise!( - view(cache.mortars.u, 2, :, 2, :, :, mortar), - mortar_l2.forward_upper, - mortar_l2.forward_lower, - u_buffer, - fstar_tmp, - ) - multiply_dimensionwise!( - view(cache.mortars.u, 2, :, 3, :, :, mortar), - mortar_l2.forward_lower, - mortar_l2.forward_upper, - u_buffer, - fstar_tmp, - ) - multiply_dimensionwise!( - view(cache.mortars.u, 2, :, 4, :, :, mortar), - mortar_l2.forward_upper, - mortar_l2.forward_upper, - u_buffer, - fstar_tmp, - ) + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 1, :, :, mortar), + mortar_l2.forward_lower, + mortar_l2.forward_lower, + u_buffer, + fstar_tmp) + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 2, :, :, mortar), + mortar_l2.forward_upper, + mortar_l2.forward_lower, + u_buffer, + fstar_tmp) + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 3, :, :, mortar), + mortar_l2.forward_lower, + mortar_l2.forward_upper, + u_buffer, + fstar_tmp) + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 4, :, :, mortar), + mortar_l2.forward_upper, + mortar_l2.forward_upper, + u_buffer, + fstar_tmp) end return nothing end -# We specialize `calc_mortar_flux!` for the divergence part of -# the parabolic terms. -function calc_mortar_flux_divergence!( - surface_flux_values, - mesh::Union{P4estMesh{3},T8codeMesh{3}}, - equations::AbstractEquationsParabolic, - mortar_l2::LobattoLegendreMortarL2, - surface_integral, - dg::DG, - cache, -) +# We specialize `calc_mortar_flux!` for the divergence part of +# the parabolic terms. +function calc_mortar_flux_divergence!(surface_flux_values, + mesh::Union{P4estMesh{3}, T8codeMesh{3}}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DG, cache) @unpack neighbor_ids, node_indices = cache.mortars @unpack contravariant_vectors = cache.elements @unpack fstar_threaded, fstar_tmp_threaded = cache @@ -1228,14 +874,14 @@ function calc_mortar_flux_divergence!( small_indices = node_indices[1, mortar] small_direction = indices2direction(small_indices) - i_small_start, i_small_step_i, i_small_step_j = - index_to_start_step_3d(small_indices[1], index_range) - j_small_start, j_small_step_i, j_small_step_j = - index_to_start_step_3d(small_indices[2], index_range) - k_small_start, k_small_step_i, k_small_step_j = - index_to_start_step_3d(small_indices[3], index_range) + i_small_start, i_small_step_i, i_small_step_j = index_to_start_step_3d(small_indices[1], + index_range) + j_small_start, j_small_step_i, j_small_step_j = index_to_start_step_3d(small_indices[2], + index_range) + k_small_start, k_small_step_i, k_small_step_j = index_to_start_step_3d(small_indices[3], + index_range) - for position = 1:4 + for position in 1:4 i_small = i_small_start j_small = j_small_start k_small = k_small_start @@ -1243,14 +889,14 @@ function calc_mortar_flux_divergence!( for j in eachnode(dg) for i in eachnode(dg) for v in eachvariable(equations) - viscous_flux_normal_ll = - cache.mortars.u[1, v, position, i, j, mortar] - viscous_flux_normal_rr = - cache.mortars.u[2, v, position, i, j, mortar] + viscous_flux_normal_ll = cache.mortars.u[1, v, position, i, j, + mortar] + viscous_flux_normal_rr = cache.mortars.u[2, v, position, i, j, + mortar] # TODO: parabolic; only BR1 at the moment - fstar[v, i, j, position] = - 0.5 * (viscous_flux_normal_ll + viscous_flux_normal_rr) + fstar[v, i, j, position] = 0.5 * (viscous_flux_normal_ll + + viscous_flux_normal_rr) end i_small += i_small_step_i @@ -1268,52 +914,29 @@ function calc_mortar_flux_divergence!( u_buffer = cache.u_threaded[Threads.threadid()] # this reuses the hyperbolic version of `mortar_fluxes_to_elements!` - mortar_fluxes_to_elements!( - surface_flux_values, - mesh, - equations, - mortar_l2, - dg, - cache, - mortar, - fstar, - u_buffer, - fstar_tmp, - ) + mortar_fluxes_to_elements!(surface_flux_values, + mesh, equations, mortar_l2, dg, cache, + mortar, fstar, u_buffer, fstar_tmp) end return nothing end # NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. -# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for +# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for # hyperbolic terms with conserved terms only, i.e., no nonconservative terms. -@inline function calc_mortar_flux!( - fstar, - mesh::P4estMesh{3}, - nonconservative_terms::False, - equations::AbstractEquationsParabolic, - surface_integral, - dg::DG, - cache, - mortar_index, - position_index, - normal_direction, - i_node_index, - j_node_index, -) +@inline function calc_mortar_flux!(fstar, + mesh::P4estMesh{3}, + nonconservative_terms::False, + equations::AbstractEquationsParabolic, + surface_integral, dg::DG, cache, + mortar_index, position_index, normal_direction, + i_node_index, j_node_index) @unpack u = cache.mortars @unpack surface_flux = surface_integral - u_ll, u_rr = get_surface_node_vars( - u, - equations, - dg, - position_index, - i_node_index, - j_node_index, - mortar_index, - ) + u_ll, u_rr = get_surface_node_vars(u, equations, dg, position_index, i_node_index, + j_node_index, mortar_index) # TODO: parabolic; only BR1 at the moment flux_ = 0.5 * (u_ll + u_rr) @@ -1322,15 +945,10 @@ end end # TODO: parabolic, finish implementing `calc_boundary_flux_gradients!` and `calc_boundary_flux_divergence!` -function prolong2boundaries!( - cache_parabolic, - flux_viscous, - mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - surface_integral, - dg::DG, - cache, -) +function prolong2boundaries!(cache_parabolic, flux_viscous, + mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG, cache) (; boundaries) = cache_parabolic (; contravariant_vectors) = cache_parabolic.elements index_range = eachnode(dg) @@ -1344,12 +962,12 @@ function prolong2boundaries!( node_indices = boundaries.node_indices[boundary] direction = indices2direction(node_indices) - i_node_start, i_node_step_i, i_node_step_j = - index_to_start_step_3d(node_indices[1], index_range) - j_node_start, j_node_step_i, j_node_step_j = - index_to_start_step_3d(node_indices[2], index_range) - k_node_start, k_node_step_i, k_node_step_j = - index_to_start_step_3d(node_indices[3], index_range) + i_node_start, i_node_step_i, i_node_step_j = index_to_start_step_3d(node_indices[1], + index_range) + j_node_start, j_node_step_i, j_node_step_j = index_to_start_step_3d(node_indices[2], + index_range) + k_node_start, k_node_step_i, k_node_step_j = index_to_start_step_3d(node_indices[3], + index_range) i_node = i_node_start j_node = j_node_start @@ -1358,21 +976,16 @@ function prolong2boundaries!( for j in eachnode(dg) for i in eachnode(dg) # this is the outward normal direction on the primary element - normal_direction = get_normal_direction( - direction, - contravariant_vectors, - i_node, - j_node, - k_node, - element, - ) + normal_direction = get_normal_direction(direction, contravariant_vectors, + i_node, j_node, k_node, element) for v in eachvariable(equations_parabolic) - flux_viscous = SVector( - flux_viscous_x[v, i_node, j_node, k_node, element], - flux_viscous_y[v, i_node, j_node, k_node, element], - flux_viscous_z[v, i_node, j_node, k_node, element], - ) + flux_viscous = SVector(flux_viscous_x[v, i_node, j_node, k_node, + element], + flux_viscous_y[v, i_node, j_node, k_node, + element], + flux_viscous_z[v, i_node, j_node, k_node, + element]) boundaries.u[v, i, j, boundary] = dot(flux_viscous, normal_direction) end @@ -1388,17 +1001,12 @@ function prolong2boundaries!( return nothing end -function calc_boundary_flux!( - cache, - t, - boundary_condition_parabolic, # works with Dict types - boundary_condition_indices, - operator_type, - mesh::P4estMesh{3}, - equations_parabolic::AbstractEquationsParabolic, - surface_integral, - dg::DG, -) +function calc_boundary_flux!(cache, t, + boundary_condition_parabolic, # works with Dict types + boundary_condition_indices, + operator_type, mesh::P4estMesh{3}, + equations_parabolic::AbstractEquationsParabolic, + surface_integral, dg::DG) (; boundaries) = cache (; node_coordinates, surface_flux_values) = cache.elements (; contravariant_vectors) = cache.elements @@ -1414,12 +1022,12 @@ function calc_boundary_flux!( node_indices = boundaries.node_indices[boundary_index] direction_index = indices2direction(node_indices) - i_node_start, i_node_step_i, i_node_step_j = - index_to_start_step_3d(node_indices[1], index_range) - j_node_start, j_node_step_i, j_node_step_j = - index_to_start_step_3d(node_indices[2], index_range) - k_node_start, k_node_step_i, k_node_step_j = - index_to_start_step_3d(node_indices[3], index_range) + i_node_start, i_node_step_i, i_node_step_j = index_to_start_step_3d(node_indices[1], + index_range) + j_node_start, j_node_step_i, j_node_step_j = index_to_start_step_3d(node_indices[2], + index_range) + k_node_start, k_node_step_i, k_node_step_j = index_to_start_step_3d(node_indices[3], + index_range) i_node = i_node_start j_node = j_node_start @@ -1428,24 +1036,13 @@ function calc_boundary_flux!( for j in eachnode(dg) for i in eachnode(dg) # Extract solution data from boundary container - u_inner = get_node_vars( - boundaries.u, - equations_parabolic, - dg, - i, - j, - boundary_index, - ) + u_inner = get_node_vars(boundaries.u, equations_parabolic, dg, i, j, + boundary_index) # Outward-pointing normal direction (not normalized) - normal_direction = get_normal_direction( - direction_index, - contravariant_vectors, - i_node, - j_node, - k_node, - element, - ) + normal_direction = get_normal_direction(direction_index, + contravariant_vectors, + i_node, j_node, k_node, element) # TODO: revisit if we want more general boundary treatments. # This assumes the gradient numerical flux at the boundary is the gradient variable, @@ -1453,25 +1050,13 @@ function calc_boundary_flux!( flux_inner = u_inner # Coordinates at boundary node - x = get_node_coords( - node_coordinates, - equations_parabolic, - dg, - i_node, - j_node, - k_node, - element, - ) - - flux_ = boundary_condition_parabolic( - flux_inner, - u_inner, - normal_direction, - x, - t, - operator_type, - equations_parabolic, - ) + x = get_node_coords(node_coordinates, equations_parabolic, dg, i_node, + j_node, k_node, + element) + + flux_ = boundary_condition_parabolic(flux_inner, u_inner, normal_direction, + x, t, operator_type, + equations_parabolic) # Copy flux to element storage in the correct orientation for v in eachvariable(equations_parabolic) From 3f1107fee6b940c3f56f2a07eae722061bdd5978 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:31:54 +0100 Subject: [PATCH 123/138] Update test_parabolic_3d.jl --- test/test_parabolic_3d.jl | 590 ++++++++++++++++---------------------- 1 file changed, 252 insertions(+), 338 deletions(-) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 18019e99bc8..6b0f6ddc4ac 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -13,25 +13,23 @@ isdir(outdir) && rm(outdir, recursive = true) #! format: noindent @trixi_testset "DGMulti: elixir_navierstokes_convergence.jl" begin - @test_trixi_include( - joinpath(examples_dir(), "dgmulti_3d", "elixir_navierstokes_convergence.jl"), - cells_per_dimension = (4, 4, 4), - tspan = (0.0, 0.1), - l2 = [ - 0.0005532847115849239, - 0.000659263490965341, - 0.0007776436127362806, - 0.0006592634909662951, - 0.0038073628897809185, - ], - linf = [ - 0.0017039861523615585, - 0.002628561703560073, - 0.003531057425112172, - 0.0026285617036090336, - 0.015587829540351095, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", + "elixir_navierstokes_convergence.jl"), + cells_per_dimension=(4, 4, 4), tspan=(0.0, 0.1), + l2=[ + 0.0005532847115849239, + 0.000659263490965341, + 0.0007776436127362806, + 0.0006592634909662951, + 0.0038073628897809185, + ], + linf=[ + 0.0017039861523615585, + 0.002628561703560073, + 0.003531057425112172, + 0.0026285617036090336, + 0.015587829540351095, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -43,29 +41,23 @@ isdir(outdir) && rm(outdir, recursive = true) end @trixi_testset "DGMulti: elixir_navierstokes_convergence_curved.jl" begin - @test_trixi_include( - joinpath( - examples_dir(), - "dgmulti_3d", - "elixir_navierstokes_convergence_curved.jl", - ), - cells_per_dimension = (4, 4, 4), - tspan = (0.0, 0.1), - l2 = [ - 0.0014027227251207474, - 0.0021322235533273513, - 0.0027873741447455194, - 0.0024587473070627423, - 0.00997836818019202, - ], - linf = [ - 0.006341750402837576, - 0.010306014252246865, - 0.01520740250924979, - 0.010968264045485565, - 0.047454389831591115, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", + "elixir_navierstokes_convergence_curved.jl"), + cells_per_dimension=(4, 4, 4), tspan=(0.0, 0.1), + l2=[ + 0.0014027227251207474, + 0.0021322235533273513, + 0.0027873741447455194, + 0.0024587473070627423, + 0.00997836818019202, + ], + linf=[ + 0.006341750402837576, + 0.010306014252246865, + 0.01520740250924979, + 0.010968264045485565, + 0.047454389831591115, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -77,29 +69,23 @@ end end @trixi_testset "DGMulti: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include( - joinpath( - examples_dir(), - "dgmulti_3d", - "elixir_navierstokes_taylor_green_vortex.jl", - ), - cells_per_dimension = (4, 4, 4), - tspan = (0.0, 0.25), - l2 = [ - 0.0001825713444029892, - 0.015589736382772248, - 0.015589736382771884, - 0.021943924667273653, - 0.01927370280244222, - ], - linf = [ - 0.0006268463584697681, - 0.03218881662749007, - 0.03218881662697948, - 0.053872495395614256, - 0.05183822000984151, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", + "elixir_navierstokes_taylor_green_vortex.jl"), + cells_per_dimension=(4, 4, 4), tspan=(0.0, 0.25), + l2=[ + 0.0001825713444029892, + 0.015589736382772248, + 0.015589736382771884, + 0.021943924667273653, + 0.01927370280244222, + ], + linf=[ + 0.0006268463584697681, + 0.03218881662749007, + 0.03218881662697948, + 0.053872495395614256, + 0.05183822000984151, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -111,25 +97,23 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl" begin - @test_trixi_include( - joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, - tspan = (0.0, 0.1), - l2 = [ - 0.0019582188528512257, - 0.002653449504302844, - 0.002898264205184629, - 0.002653449504302853, - 0.009511572365085706, - ], - linf = [ - 0.013680656759085918, - 0.0356910450154318, - 0.023526343547736236, - 0.035691045015431855, - 0.11482570604041165, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + l2=[ + 0.0019582188528512257, + 0.002653449504302844, + 0.002898264205184629, + 0.002653449504302853, + 0.009511572365085706, + ], + linf=[ + 0.013680656759085918, + 0.0356910450154318, + 0.023526343547736236, + 0.035691045015431855, + 0.11482570604041165, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -141,31 +125,27 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (isothermal walls)" begin - @test_trixi_include( - joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, - tspan = (0.0, 0.1), - heat_bc_top_bottom = Isothermal( - (x, t, equations) -> Trixi.temperature( - initial_condition_navier_stokes_convergence_test(x, t, equations), - equations, - ), - ), - l2 = [ - 0.00195468651965362, - 0.0026554367897028506, - 0.002892730402724066, - 0.002655436789702817, - 0.009596351796609566, - ], - linf = [ - 0.013680508110645473, - 0.035673446359424356, - 0.024024936779729028, - 0.03567344635942474, - 0.11839497110809383, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations)), + l2=[ + 0.00195468651965362, + 0.0026554367897028506, + 0.002892730402724066, + 0.002655436789702817, + 0.009596351796609566, + ], + linf=[ + 0.013680508110645473, + 0.035673446359424356, + 0.024024936779729028, + 0.03567344635942474, + 0.11839497110809383, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -177,26 +157,24 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Entropy gradient variables)" begin - @test_trixi_include( - joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, - tspan = (0.0, 0.1), - gradient_variables = GradientVariablesEntropy(), - l2 = [ - 0.0019770444875099307, - 0.0026524750946399327, - 0.00290860030832445, - 0.0026524750946399396, - 0.009509568981439294, - ], - linf = [ - 0.01387936112914212, - 0.03526260609304053, - 0.023554197097368997, - 0.035262606093040896, - 0.11719963716509518, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + gradient_variables=GradientVariablesEntropy(), + l2=[ + 0.0019770444875099307, + 0.0026524750946399327, + 0.00290860030832445, + 0.0026524750946399396, + 0.009509568981439294, + ], + linf=[ + 0.01387936112914212, + 0.03526260609304053, + 0.023554197097368997, + 0.035262606093040896, + 0.11719963716509518, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -208,32 +186,28 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Entropy gradient variables, isothermal walls)" begin - @test_trixi_include( - joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, - tspan = (0.0, 0.1), - gradient_variables = GradientVariablesEntropy(), - heat_bc_top_bottom = Isothermal( - (x, t, equations) -> Trixi.temperature( - initial_condition_navier_stokes_convergence_test(x, t, equations), - equations, - ), - ), - l2 = [ - 0.001974631423398113, - 0.002654768259143932, - 0.002907031063651286, - 0.002654768259143901, - 0.009587792882971452, - ], - linf = [ - 0.01387919380137137, - 0.035244084526358944, - 0.02398614622061363, - 0.03524408452635828, - 0.12005056512506407, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + gradient_variables=GradientVariablesEntropy(), + heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations)), + l2=[ + 0.001974631423398113, + 0.002654768259143932, + 0.002907031063651286, + 0.002654768259143901, + 0.009587792882971452, + ], + linf=[ + 0.01387919380137137, + 0.035244084526358944, + 0.02398614622061363, + 0.03524408452635828, + 0.12005056512506407, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -245,26 +219,24 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (flux differencing)" begin - @test_trixi_include( - joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, - tspan = (0.0, 0.1), - volume_integral = VolumeIntegralFluxDifferencing(flux_central), - l2 = [ - 0.0019582188528180213, - 0.002653449504301736, - 0.0028982642051960006, - 0.0026534495043017384, - 0.009511572364811033, - ], - linf = [ - 0.013680656758949583, - 0.035691045015224444, - 0.02352634354676752, - 0.035691045015223424, - 0.11482570603751441, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + volume_integral=VolumeIntegralFluxDifferencing(flux_central), + l2=[ + 0.0019582188528180213, + 0.002653449504301736, + 0.0028982642051960006, + 0.0026534495043017384, + 0.009511572364811033, + ], + linf=[ + 0.013680656758949583, + 0.035691045015224444, + 0.02352634354676752, + 0.035691045015223424, + 0.11482570603751441, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -276,35 +248,25 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Refined mesh)" begin - @test_trixi_include( - joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - tspan = (0.0, 0.0) - ) + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + tspan=(0.0, 0.0)) LLID = Trixi.local_leaf_cells(mesh.tree) num_leafs = length(LLID) @assert num_leafs % 16 == 0 Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 16)]) tspan = (0.0, 0.25) - semi = SemidiscretizationHyperbolicParabolic( - mesh, - (equations, equations_parabolic), - initial_condition, - solver; - boundary_conditions = (boundary_conditions, boundary_conditions_parabolic), - source_terms = source_terms_navier_stokes_convergence_test, - ) + semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ode = semidiscretize(semi, tspan) analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) - sol = solve( - ode, - RDPK3SpFSAL49(); - abstol = time_int_tol, - reltol = time_int_tol, - dt = 1e-5, - ode_default_options()..., - callback = callbacks, - ) + sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + dt = 1e-5, + ode_default_options()..., callback = callbacks) l2_error, linf_error = analysis_callback(sol) @test l2_error ≈ [ 0.0003109336253407314, @@ -331,29 +293,23 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include( - joinpath( - examples_dir(), - "tree_3d_dgsem", - "elixir_navierstokes_taylor_green_vortex.jl", - ), - initial_refinement_level = 2, - tspan = (0.0, 0.25), - l2 = [ - 0.00024173250389635442, - 0.015684268393762454, - 0.01568426839376248, - 0.021991909545192333, - 0.02825413672911425, - ], - linf = [ - 0.0008410587892853094, - 0.04740176181772552, - 0.04740176181772507, - 0.07483494924031157, - 0.150181591534448, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl"), + initial_refinement_level=2, tspan=(0.0, 0.25), + l2=[ + 0.00024173250389635442, + 0.015684268393762454, + 0.01568426839376248, + 0.021991909545192333, + 0.02825413672911425, + ], + linf=[ + 0.0008410587892853094, + 0.04740176181772552, + 0.04740176181772507, + 0.07483494924031157, + 0.150181591534448, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -365,41 +321,27 @@ end end @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl (Refined mesh)" begin - @test_trixi_include( - joinpath( - examples_dir(), - "tree_3d_dgsem", - "elixir_navierstokes_taylor_green_vortex.jl", - ), - tspan = (0.0, 0.0) - ) + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl"), + tspan=(0.0, 0.0)) LLID = Trixi.local_leaf_cells(mesh.tree) num_leafs = length(LLID) @assert num_leafs % 32 == 0 Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 32)]) tspan = (0.0, 0.1) - semi = SemidiscretizationHyperbolicParabolic( - mesh, - (equations, equations_parabolic), - initial_condition, - solver, - ) + semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) ode = semidiscretize(semi, tspan) - analysis_callback = AnalysisCallback( - semi, - interval = analysis_interval, - save_analysis = true, - extra_analysis_integrals = (energy_kinetic, energy_internal, enstrophy), - ) + analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) # Use CarpenterKennedy2N54 since `RDPK3SpFSAL49` gives slightly different results on different machines - sol = solve( - ode, - CarpenterKennedy2N54(williamson_condition = false), - dt = 5e-3, - save_everystep = false, - callback = callbacks, - ) + sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 5e-3, + save_everystep = false, callback = callbacks) l2_error, linf_error = analysis_callback(sol) @test l2_error ≈ [ 7.314319856736271e-5, @@ -427,29 +369,23 @@ end end @trixi_testset "P4estMesh3D: elixir_navierstokes_convergence.jl" begin - @test_trixi_include( - joinpath( - examples_dir(), - "p4est_3d_dgsem", - "elixir_navierstokes_convergence.jl", - ), - initial_refinement_level = 2, - tspan = (0.0, 0.1), - l2 = [ - 0.00026599105554982194, - 0.000461877794472316, - 0.0005424899076052261, - 0.0004618777944723191, - 0.0015846392581126832, - ], - linf = [ - 0.0025241668929956163, - 0.006308461681816373, - 0.004334939663169113, - 0.006308461681804009, - 0.03176343480493493, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + l2=[ + 0.00026599105554982194, + 0.000461877794472316, + 0.0005424899076052261, + 0.0004618777944723191, + 0.0015846392581126832, + ], + linf=[ + 0.0025241668929956163, + 0.006308461681816373, + 0.004334939663169113, + 0.006308461681804009, + 0.03176343480493493, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -461,29 +397,23 @@ end end @trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include( - joinpath( - examples_dir(), - "p4est_3d_dgsem", - "elixir_navierstokes_taylor_green_vortex.jl", - ), - initial_refinement_level = 2, - tspan = (0.0, 0.25), - l2 = [ - 0.0001547509861140407, - 0.015637861347119624, - 0.015637861347119687, - 0.022024699158522523, - 0.009711013505930812, - ], - linf = [ - 0.0006696415247340326, - 0.03442565722527785, - 0.03442565722577423, - 0.06295407168705314, - 0.032857472756916195, - ] - ) + @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl"), + initial_refinement_level=2, tspan=(0.0, 0.25), + l2=[ + 0.0001547509861140407, + 0.015637861347119624, + 0.015637861347119687, + 0.022024699158522523, + 0.009711013505930812, + ], + linf=[ + 0.0006696415247340326, + 0.03442565722527785, + 0.03442565722577423, + 0.06295407168705314, + 0.032857472756916195, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -494,75 +424,59 @@ end end end -@trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin - @test_trixi_include( - joinpath( - examples_dir(), - "p4est_3d_dgsem", - "elixir_navierstokes_taylor_green_vortex_amr.jl", - ), - initial_refinement_level = 0, - tspan = (0.0, 0.5), - l2 = [ - 0.0016588740573444188, - 0.03437058632045721, - 0.03437058632045671, - 0.041038898400430075, - 0.30978593009044153, - ], - linf = [ - 0.004173569912012121, - 0.09168674832979556, - 0.09168674832975021, - 0.12129218723807476, - 0.8433893297612087, - ] + @trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex_amr.jl"), + initial_refinement_level = 0, tspan=(0.0, 0.5), + l2 = [0.0016588740573444188, + 0.03437058632045721, + 0.03437058632045671, + 0.041038898400430075, + 0.30978593009044153], + linf = [0.004173569912012121, + 0.09168674832979556, + 0.09168674832975021, + 0.12129218723807476, + 0.8433893297612087] ) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # 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 -@trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin - @test_trixi_include( - joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_amr.jl"), - l2 = [0.000355780485397024], - linf = [0.0010810770271614256] + @trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_amr.jl"), + l2 = [0.000355780485397024], + linf = [0.0010810770271614256] ) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # 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 -@trixi_testset "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin - @test_trixi_include( - joinpath( - examples_dir(), - "tree_3d_dgsem", - "elixir_advection_diffusion_nonperiodic.jl", - ), - l2 = [0.0009808996243280868], - linf = [0.01732621559135459] + @trixi_testset "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_nonperiodic.jl"), + l2 = [0.0009808996243280868], + linf = [0.01732621559135459] ) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) + # 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 # Clean up afterwards: delete Trixi.jl output directory From b91684f8d35fc423716d1aa10c40c2be2460169b Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:32:50 +0100 Subject: [PATCH 124/138] Update test_parabolic_3d.jl --- test/test_parabolic_3d.jl | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index 6b0f6ddc4ac..cf452732f9e 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -427,16 +427,8 @@ end @trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex_amr.jl"), initial_refinement_level = 0, tspan=(0.0, 0.5), - l2 = [0.0016588740573444188, - 0.03437058632045721, - 0.03437058632045671, - 0.041038898400430075, - 0.30978593009044153], - linf = [0.004173569912012121, - 0.09168674832979556, - 0.09168674832975021, - 0.12129218723807476, - 0.8433893297612087] + l2 = [0.0016588740573444188, 0.03437058632045721, 0.03437058632045671, 0.041038898400430075, 0.30978593009044153], + linf = [0.004173569912012121, 0.09168674832979556, 0.09168674832975021, 0.12129218723807476, 0.8433893297612087] ) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From 4f00c9b44a18d093fd5ff5b4198ed7619218d287 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 10:35:21 +0100 Subject: [PATCH 125/138] Update examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl --- .../p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl index cb28987143c..2a401eff151 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -23,8 +23,8 @@ function initial_condition_3d_blast_wave(x, t, equations::CompressibleEulerEquat p_o = 0.1 u_o = 0.0 - rc = 0.5 - r = sqrt(x[1]^2+x[2]^2+x[3]^2) + rc = 0.5 + r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) if r < rc rho = rho_c v1 = u_c From 095e1173a65898a1a452beba9668a80b6a35b17b Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 16:23:04 +0100 Subject: [PATCH 126/138] Update elixir_navierstokes_3d_blast_wave_amr.jl --- .../elixir_navierstokes_3d_blast_wave_amr.jl | 110 +++++++++--------- 1 file changed, 54 insertions(+), 56 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl index 2a401eff151..5fc3639f9b2 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl @@ -10,36 +10,35 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) function initial_condition_3d_blast_wave(x, t, equations::CompressibleEulerEquations3D) - - rho_c = 1.0 - p_c = 1.0 - u_c = 0.0 - - rho_o = 0.125 - p_o = 0.1 - u_o = 0.0 - - rc = 0.5 - r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) - if r < rc - rho = rho_c - v1 = u_c - v2 = u_c - v3 = u_c - p = p_c - else - rho = rho_o - v1 = u_o - v2 = u_o - v3 = u_o - p = p_o - end - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + rho_c = 1.0 + p_c = 1.0 + u_c = 0.0 + + rho_o = 0.125 + p_o = 0.1 + u_o = 0.0 + + rc = 0.5 + r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) + if r < rc + rho = rho_c + v1 = u_c + v2 = u_c + v3 = u_c + p = p_c + else + rho = rho_o + v1 = u_o + v2 = u_o + v3 = u_o + p = p_o + end + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_3d_blast_wave @@ -48,25 +47,25 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi trees_per_dimension = (4, 4, 4) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, true, true), initial_refinement_level=1) - +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, true, true), initial_refinement_level = 1) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -80,25 +79,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -save_solution = SaveSolutionCallback(interval=20, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +save_solution = SaveSolutionCallback(interval = 20, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=1, med_threshold=0.05, - max_level=4, max_threshold=0.1) + base_level = 0, + med_level = 1, med_threshold = 0.05, + max_level = 4, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) - + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -110,6 +108,6 @@ callbacks = CallbackSet(summary_callback, # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary From d08c874b130e434a217e5e2436288979882bbc36 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 16:23:34 +0100 Subject: [PATCH 127/138] Update elixir_navierstokes_taylor_green_vortex_amr.jl --- .../elixir_navierstokes_taylor_green_vortex_amr.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl index 454781b8895..c15227a1c29 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex_amr.jl @@ -93,8 +93,8 @@ alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, - alive_callback, - amr_callback, + alive_callback, + amr_callback, save_solution) ############################################################################### From a73cb3a0c1cf8b4fafea86fc94251af97380c17d Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 16:25:50 +0100 Subject: [PATCH 128/138] Update dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 9243f635f9e..a90125b7509 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -102,7 +102,6 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, dg.surface_integral, dg) end - # Prolong solution to mortars (specialized for AbstractEquationsParabolic) # !!! NOTE: we reuse the hyperbolic cache here since it contains "mortars" and "u_threaded" # !!! Is this OK? @@ -243,7 +242,6 @@ function calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, dg.surface_integral, dg) end - # Prolong solution to mortars. These should reuse the hyperbolic version of `prolong2mortars` # !!! NOTE: we reuse the hyperbolic cache here, since it contains both `mortars` and `u_threaded`. # !!! should we have a separate mortars/u_threaded in cache_parabolic? From bb0cb0e0fc305384c248f4af273b9ea93c8902e9 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 19 Dec 2023 16:26:16 +0100 Subject: [PATCH 129/138] Update test_parabolic_3d.jl --- test/test_parabolic_3d.jl | 50 ++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index cf452732f9e..bc4c2e2729e 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -424,12 +424,24 @@ end end end - @trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex_amr.jl"), - initial_refinement_level = 0, tspan=(0.0, 0.5), - l2 = [0.0016588740573444188, 0.03437058632045721, 0.03437058632045671, 0.041038898400430075, 0.30978593009044153], - linf = [0.004173569912012121, 0.09168674832979556, 0.09168674832975021, 0.12129218723807476, 0.8433893297612087] - ) +@trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex_amr.jl"), + initial_refinement_level=0, tspan=(0.0, 0.5), + l2=[ + 0.0016588740573444188, + 0.03437058632045721, + 0.03437058632045671, + 0.041038898400430075, + 0.30978593009044153, + ], + linf=[ + 0.004173569912012121, + 0.09168674832979556, + 0.09168674832975021, + 0.12129218723807476, + 0.8433893297612087, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -438,13 +450,13 @@ end du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end - @trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_amr.jl"), - l2 = [0.000355780485397024], - linf = [0.0010810770271614256] - ) +@trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_advection_diffusion_amr.jl"), + l2=[0.000355780485397024], + linf=[0.0010810770271614256]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -453,13 +465,13 @@ end du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end - @trixi_testset "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_diffusion_nonperiodic.jl"), - l2 = [0.0009808996243280868], - linf = [0.01732621559135459] - ) +@trixi_testset "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_advection_diffusion_nonperiodic.jl"), + l2=[0.0009808996243280868], + linf=[0.01732621559135459]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -468,7 +480,7 @@ end du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end end # Clean up afterwards: delete Trixi.jl output directory From 3e35f9616ac235fe1e2d952353c274e56278f075 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Wed, 20 Dec 2023 11:05:28 +0100 Subject: [PATCH 130/138] Delete examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl --- .../elixir_navierstokes_3d_blast_wave_amr.jl | 113 ------------------ 1 file changed, 113 deletions(-) delete mode 100644 examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl deleted file mode 100644 index 5fc3639f9b2..00000000000 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_3d_blast_wave_amr.jl +++ /dev/null @@ -1,113 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Navier-Stokes equations - -# TODO: parabolic; unify names of these accessor functions -prandtl_number() = 0.72 -mu() = 6.25e-4 # equivalent to Re = 1600 - -equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), - Prandtl = prandtl_number()) - -function initial_condition_3d_blast_wave(x, t, equations::CompressibleEulerEquations3D) - rho_c = 1.0 - p_c = 1.0 - u_c = 0.0 - - rho_o = 0.125 - p_o = 0.1 - u_o = 0.0 - - rc = 0.5 - r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) - if r < rc - rho = rho_c - v1 = u_c - v2 = u_c - v3 = u_c - p = p_c - else - rho = rho_o - v1 = u_o - v2 = u_o - v3 = u_o - p = p_o - end - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) -end -initial_condition = initial_condition_3d_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -polydeg = 3 -basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max = 1.0, - alpha_min = 0.001, - alpha_smooth = true, - variable = density_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg = volume_flux, - volume_flux_fv = surface_flux) - -solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, - volume_integral = volume_integral) - -coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = (1.0, 1.0, 1.0) .* pi - -trees_per_dimension = (4, 4, 4) - -mesh = P4estMesh(trees_per_dimension, polydeg = 3, - coordinates_min = coordinates_min, coordinates_max = coordinates_max, - periodicity = (true, true, true), initial_refinement_level = 1) - -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 0.8) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -save_solution = SaveSolutionCallback(interval = 20, - save_initial_solution = true, - save_final_solution = true, - solution_variables = cons2prim) - -amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) - -amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level = 0, - med_level = 1, med_threshold = 0.05, - max_level = 4, max_threshold = 0.1) -amr_callback = AMRCallback(semi, amr_controller, - interval = 5, - adapt_initial_condition = true, - adapt_initial_condition_only_refine = true) - -alive_callback = AliveCallback(analysis_interval = analysis_interval) - -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - amr_callback, - save_solution) - -############################################################################### -# run the simulation - -time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, - ode_default_options()..., callback = callbacks) -summary_callback() # print the timer summary From 8cf401e08367f4a9470761a3a1cc9c2bd99c460d Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Wed, 20 Dec 2023 11:05:51 +0100 Subject: [PATCH 131/138] Create elixir_navierstokes_blast_wave_amr.jl --- .../elixir_navierstokes_blast_wave_amr.jl | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 examples/p4est_3d_dgsem/elixir_navierstokes_blast_wave_amr.jl diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_blast_wave_amr.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_blast_wave_amr.jl new file mode 100644 index 00000000000..5df89fbcdf2 --- /dev/null +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_blast_wave_amr.jl @@ -0,0 +1,113 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 6.25e-4 # equivalent to Re = 1600 + +equations = CompressibleEulerEquations3D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) + +function initial_condition_3d_blast_wave(x, t, equations::CompressibleEulerEquations3D) + rho_c = 1.0 + p_c = 1.0 + u_c = 0.0 + + rho_o = 0.125 + p_o = 0.1 + u_o = 0.0 + + rc = 0.5 + r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) + if r < rc + rho = rho_c + v1 = u_c + v2 = u_c + v3 = u_c + p = p_c + else + rho = rho_o + v1 = u_o + v2 = u_o + v3 = u_o + p = p_o + end + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) +end +initial_condition = initial_condition_3d_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +polydeg = 3 +basis = LobattoLegendreBasis(polydeg) +indicator_sc = IndicatorHennemannGassner(equations, basis, + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) +volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) + +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) + +coordinates_min = (-1.0, -1.0, -1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi + +trees_per_dimension = (4, 4, 4) + +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, true, true), initial_refinement_level = 1) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.8) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +save_solution = SaveSolutionCallback(interval = analysis_interval, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) + +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level = 0, + med_level = 1, med_threshold = 0.05, + max_level = 3, max_threshold = 0.1) +amr_callback = AMRCallback(semi, amr_controller, + interval = 10, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + amr_callback, + save_solution) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary From 3a51498ab778af014b6e0f4d9696f65e814abcde Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Wed, 20 Dec 2023 11:06:27 +0100 Subject: [PATCH 132/138] Update test_parabolic_3d.jl --- test/test_parabolic_3d.jl | 63 ++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index bc4c2e2729e..6fbfb8259d4 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -424,6 +424,36 @@ end end end +@trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_advection_diffusion_amr.jl"), + l2=[0.000355780485397024], + linf=[0.0010810770271614256]) + # 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 "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_advection_diffusion_nonperiodic.jl"), + l2=[0.0009808996243280868], + linf=[0.01732621559135459]) + # 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 "P4estMesh3D: elixir_navierstokes_taylor_green_vortex_amr.jl" begin @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex_amr.jl"), @@ -452,26 +482,19 @@ end end end -@trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_advection_diffusion_amr.jl"), - l2=[0.000355780485397024], - linf=[0.0010810770271614256]) - # 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 "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", - "elixir_advection_diffusion_nonperiodic.jl"), - l2=[0.0009808996243280868], - linf=[0.01732621559135459]) +@trixi_testset "P4estMesh3D: elixir_navierstokes_blast_wave_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", + "elixir_navierstokes_blast_wave_amr.jl"), + tspan=(0.0, 0.01), + l2=[ + 0.009472104410520866, 0.0017883742549557149, + 0.0017883742549557147, 0.0017883742549557196, + 0.024388540048562748, + ], + linf=[ + 0.6782397526873181, 0.17663702154066238, + 0.17663702154066266, 0.17663702154066238, 1.7327849844825238, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From ba9ea53ef42689d09a313c62370c1ea5486dd270 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Wed, 20 Dec 2023 11:10:48 +0100 Subject: [PATCH 133/138] Update NEWS.md --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index abd9fd27882..f29aad464d0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,11 @@ Trixi.jl follows the interpretation of [semantic versioning (semver)](https://ju used in the Julia ecosystem. Notable changes will be documented in this file for human readability. +## Changes in the v0.5 lifecycle + +#### Added +- AMR for hyperbolic-parabolic equations on 3D `P4estMesh` + ## Changes when updating to v0.6 from v0.5.x #### Added From e95cef4a8cf6a54824a18753797d3250c73e9336 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Wed, 20 Dec 2023 11:11:04 +0100 Subject: [PATCH 134/138] Update NEWS.md --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index f29aad464d0..e7bdd14eab2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,7 +4,7 @@ Trixi.jl follows the interpretation of [semantic versioning (semver)](https://ju used in the Julia ecosystem. Notable changes will be documented in this file for human readability. -## Changes in the v0.5 lifecycle +## Changes in the v0.6 lifecycle #### Added - AMR for hyperbolic-parabolic equations on 3D `P4estMesh` From e2bf5ce9f6d92579717019e3b11e4adb8b620962 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Wed, 20 Dec 2023 11:36:16 +0100 Subject: [PATCH 135/138] Update src/solvers/dgsem_p4est/dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index a90125b7509..00d62dd6af9 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -366,7 +366,7 @@ end small_indices = node_indices[1, mortar] small_direction = indices2direction(small_indices) - for position in 1:4 + for position in 1:4 # Loop over small elements element = neighbor_ids[position, mortar] for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) From f1dbdad79b5e39a0bd588116cbe30f7902befe15 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Wed, 20 Dec 2023 11:36:53 +0100 Subject: [PATCH 136/138] Update src/solvers/dgsem_p4est/dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 00d62dd6af9..2049afa190b 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -741,7 +741,7 @@ function prolong2mortars_divergence!(cache, flux_viscous, k_small_start, k_small_step_i, k_small_step_j = index_to_start_step_3d(small_indices[3], index_range) - for position in 1:4 + for position in 1:4 # Loop over small elements i_small = i_small_start j_small = j_small_start k_small = k_small_start From ebe69d4932652127217d427b7b90dd5284d09f60 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Wed, 20 Dec 2023 11:37:17 +0100 Subject: [PATCH 137/138] Update src/solvers/dgsem_p4est/dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 2049afa190b..99c542049e4 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -795,7 +795,7 @@ function prolong2mortars_divergence!(cache, flux_viscous, i_large = i_large_start j_large = j_large_start k_large = k_large_start - element = neighbor_ids[5, mortar] + element = neighbor_ids[5, mortar] # Large element for j in eachnode(dg) for i in eachnode(dg) normal_direction = get_normal_direction(direction_index, From 2a32c309a189ec66341e97e2b75fa3afe06f9847 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Wed, 20 Dec 2023 11:37:59 +0100 Subject: [PATCH 138/138] Update src/solvers/dgsem_p4est/dg_3d_parabolic.jl --- src/solvers/dgsem_p4est/dg_3d_parabolic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 99c542049e4..0bb97c7af02 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -879,7 +879,7 @@ function calc_mortar_flux_divergence!(surface_flux_values, k_small_start, k_small_step_i, k_small_step_j = index_to_start_step_3d(small_indices[3], index_range) - for position in 1:4 + for position in 1:4 # Loop over small elements i_small = i_small_start j_small = j_small_start k_small = k_small_start