Path: blob/main/src/solvers/dgsem_tree/containers.jl
5591 views
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).1# Since these FMAs can increase the performance of many numerical algorithms,2# we need to opt-in explicitly.3# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.4@muladd begin5#! format: noindent67# Dimension independent code related to containers of the DG solver8# with the mesh type TreeMesh910abstract type AbstractTreeElementContainer <: AbstractElementContainer end1112# Return number of elements13@inline nelements(elements::AbstractTreeElementContainer) = length(elements.cell_ids)14# Return number of element nodes15@inline nnodes(elements::AbstractTreeElementContainer) = size(elements.node_coordinates,162)17@inline nvariables(elements::AbstractTreeElementContainer) = size(elements.surface_flux_values,181)19# TODO: Taal performance, 1:nelements(elements) vs. Base.OneTo(nelements(elements))20"""21eachelement(elements::AbstractTreeElementContainer)2223Return an iterator over the indices that specify the location in relevant data structures24for the elements in `elements`.25In particular, not the elements themselves are returned.26"""27@inline eachelement(elements::AbstractTreeElementContainer) = Base.OneTo(nelements(elements))2829@inline Base.real(elements::AbstractTreeElementContainer) = eltype(elements.node_coordinates)30@inline Base.eltype(elements::AbstractTreeElementContainer) = eltype(elements.surface_flux_values)3132abstract type AbstractTreeInterfaceContainer <: AbstractInterfaceContainer end3334# Return number of interfaces35@inline ninterfaces(interfaces::AbstractTreeInterfaceContainer) = length(interfaces.orientations)36# Return number of interface nodes for 2D and 3D. For 1D hard-coded to 1 interface node.37@inline nnodes(interfaces::AbstractTreeInterfaceContainer) = size(interfaces.u, 3)38# Return number of equation variables39@inline nvariables(interfaces::AbstractTreeInterfaceContainer) = size(interfaces.u, 2)4041abstract type AbstractTreeMPIInterfaceContainer <: AbstractMPIInterfaceContainer end4243# Return number of interfaces44@inline function nmpiinterfaces(mpi_interfaces::AbstractTreeMPIInterfaceContainer)45return length(mpi_interfaces.orientations)46end47# Return number of interface nodes for 2D and 3D. For 1D hard-coded to 1 interface node.48@inline nnodes(interfaces::AbstractTreeMPIInterfaceContainer) = size(interfaces.u, 3)49# Return number of equation variables50@inline nvariables(interfaces::AbstractTreeMPIInterfaceContainer) = size(interfaces.u,512)5253abstract type AbstractTreeBoundaryContainer <: AbstractBoundaryContainer end5455# Return number of boundaries56@inline nboundaries(boundaries::AbstractTreeBoundaryContainer) = length(boundaries.orientations)57# Return number of boundary nodes for 2D and 3D. For 1D hard-coded to 1 boundary node.58@inline nnodes(boundaries::AbstractTreeBoundaryContainer) = size(boundaries.u, 3)59# Return number of equation variables60@inline nvariables(boundaries::AbstractTreeBoundaryContainer) = size(boundaries.u, 2)6162abstract type AbstractTreeL2MortarContainer <: AbstractMortarContainer end6364# Return number of L2 mortars65@inline nmortars(l2mortars::AbstractTreeL2MortarContainer) = length(l2mortars.orientations)6667abstract type AbstractTreeL2MPIMortarContainer <: AbstractMPIMortarContainer end6869# Return number of L2 mortars70@inline function nmpimortars(mpi_l2mortars::AbstractTreeL2MPIMortarContainer)71return length(mpi_l2mortars.orientations)72end7374# Container data structure (structure-of-arrays style) for variables used for IDP limiting75mutable struct ContainerSubcellLimiterIDP{NDIMS, uEltype <: Real, NDIMSP1} <:76AbstractContainer77alpha::Array{uEltype, NDIMSP1} # [i, j, k, element]78variable_bounds::Dict{Symbol, Array{uEltype, NDIMSP1}}79# internal `resize!`able storage80_alpha::Vector{uEltype}81_variable_bounds::Dict{Symbol, Vector{uEltype}}82end8384function ContainerSubcellLimiterIDP{NDIMS, uEltype}(capacity::Integer, n_nodes,85bound_keys) where {NDIMS,86uEltype <: Real}87nan_uEltype = convert(uEltype, NaN)8889# Initialize fields with defaults90_alpha = fill(nan_uEltype, prod(ntuple(_ -> n_nodes, NDIMS)) * capacity)91alpha = unsafe_wrap(Array, pointer(_alpha),92(ntuple(_ -> n_nodes, NDIMS)..., capacity))9394_variable_bounds = Dict{Symbol, Vector{uEltype}}()95variable_bounds = Dict{Symbol, Array{uEltype, NDIMS + 1}}()96for key in bound_keys97_variable_bounds[key] = fill(nan_uEltype,98prod(ntuple(_ -> n_nodes, NDIMS)) * capacity)99variable_bounds[key] = unsafe_wrap(Array, pointer(_variable_bounds[key]),100(ntuple(_ -> n_nodes, NDIMS)..., capacity))101end102103return ContainerSubcellLimiterIDP{NDIMS, uEltype, NDIMS + 1}(alpha,104variable_bounds,105_alpha,106_variable_bounds)107end108109@inline nnodes(container::ContainerSubcellLimiterIDP) = size(container.alpha, 1)110@inline Base.ndims(::ContainerSubcellLimiterIDP{NDIMS}) where {NDIMS} = NDIMS111112# Only one-dimensional `Array`s are `resize!`able in Julia.113# Hence, we use `Vector`s as internal storage and `resize!`114# them whenever needed. Then, we reuse the same memory by115# `unsafe_wrap`ping multi-dimensional `Array`s around the116# internal storage.117function Base.resize!(container::ContainerSubcellLimiterIDP, capacity)118n_nodes = nnodes(container)119n_dims = ndims(container)120121(; _alpha) = container122resize!(_alpha, prod(ntuple(_ -> n_nodes, n_dims)) * capacity)123container.alpha = unsafe_wrap(Array, pointer(_alpha),124(ntuple(_ -> n_nodes, n_dims)..., capacity))125container.alpha .= convert(eltype(container.alpha), NaN)126127(; _variable_bounds) = container128for (key, _) in _variable_bounds129resize!(_variable_bounds[key], prod(ntuple(_ -> n_nodes, n_dims)) * capacity)130container.variable_bounds[key] = unsafe_wrap(Array,131pointer(_variable_bounds[key]),132(ntuple(_ -> n_nodes, n_dims)...,133capacity))134end135136return nothing137end138139abstract type AbstractContainerAntidiffusiveFlux <: AbstractContainer end140nvariables(fluxes::AbstractContainerAntidiffusiveFlux) = size(fluxes.antidiffusive_flux1_L,1411)142nnodes(fluxes::AbstractContainerAntidiffusiveFlux) = size(fluxes.antidiffusive_flux1_L,1433)144145# Dimension-specific implementations146include("containers_1d.jl")147include("containers_2d.jl")148include("containers_3d.jl")149end # @muladd150151152