@muladd begin
"""
P4estMeshView{NDIMS, NDIMS_AMBIENT, RealT <: Real, Parent} <: AbstractMesh{NDIMS}
A view on a [`P4estMesh`](@ref).
"""
mutable struct P4estMeshView{NDIMS, NDIMS_AMBIENT, RealT <: Real, Parent} <:
AbstractMesh{NDIMS}
parent::Parent
cell_ids::Vector{Int}
unsaved_changes::Bool
current_filename::String
end
"""
P4estMeshView(parent; cell_ids)
Create a `P4estMeshView` on a [`P4estMesh`](@ref) parent.
# Arguments
- `parent`: the parent `P4estMesh`.
- `cell_ids`: array of cell ids that are part of this view.
"""
function P4estMeshView(parent::P4estMesh{NDIMS, NDIMS_AMBIENT, RealT},
cell_ids::Vector) where {NDIMS, NDIMS_AMBIENT, RealT}
return P4estMeshView{NDIMS, NDIMS_AMBIENT, RealT, typeof(parent)}(parent, cell_ids,
parent.unsaved_changes,
parent.current_filename)
end
@inline Base.ndims(::P4estMeshView{NDIMS}) where {NDIMS} = NDIMS
@inline Base.real(::P4estMeshView{NDIMS, NDIMS_AMBIENT, RealT}) where {NDIMS, NDIMS_AMBIENT, RealT} = RealT
function extract_p4est_mesh_view(elements_parent,
interfaces_parent,
boundaries_parent,
mortars_parent,
mesh,
equations,
dg,
::Type{uEltype}) where {uEltype <: Real}
elements = deepcopy(elements_parent)
resize!(elements, length(mesh.cell_ids))
@views elements.inverse_jacobian .= elements_parent.inverse_jacobian[..,
mesh.cell_ids]
@views elements.jacobian_matrix .= elements_parent.jacobian_matrix[..,
mesh.cell_ids]
@views elements.node_coordinates .= elements_parent.node_coordinates[..,
mesh.cell_ids]
@views elements.contravariant_vectors .= elements_parent.contravariant_vectors[..,
mesh.cell_ids]
@views elements.surface_flux_values .= elements_parent.surface_flux_values[..,
mesh.cell_ids]
interfaces = extract_interfaces(mesh, interfaces_parent)
return elements, interfaces, boundaries_parent, mortars_parent
end
function extract_interfaces(mesh::P4estMeshView, interfaces_parent)
mask = BitArray(undef, ninterfaces(interfaces_parent))
for interface in 1:size(interfaces_parent.neighbor_ids)[2]
mask[interface] = (interfaces_parent.neighbor_ids[1, interface] in mesh.cell_ids) &&
(interfaces_parent.neighbor_ids[2, interface] in mesh.cell_ids)
end
interfaces = deepcopy(interfaces_parent)
resize!(interfaces, sum(mask))
@views interfaces.u .= interfaces_parent.u[.., mask]
@views interfaces.node_indices .= interfaces_parent.node_indices[.., mask]
@views neighbor_ids = interfaces_parent.neighbor_ids[.., mask]
interfaces.neighbor_ids = zeros(Int, size(neighbor_ids))
for interface in 1:size(neighbor_ids)[2]
interfaces.neighbor_ids[1, interface] = findall(id -> id ==
neighbor_ids[1, interface],
mesh.cell_ids)[1]
interfaces.neighbor_ids[2, interface] = findall(id -> id ==
neighbor_ids[2, interface],
mesh.cell_ids)[1]
end
return interfaces
end
function save_mesh_file(mesh::P4estMeshView, output_directory, timestep,
mpi_parallel::False)
mkpath(output_directory)
if timestep > 0
filename = joinpath(output_directory, @sprintf("mesh_%09d.h5", timestep))
p4est_filename = @sprintf("p4est_data_%09d", timestep)
else
filename = joinpath(output_directory, "mesh.h5")
p4est_filename = "p4est_data"
end
p4est_file = joinpath(output_directory, p4est_filename)
save_p4est!(p4est_file, mesh.parent.p4est)
h5open(filename, "w") do file
attributes(file)["mesh_type"] = get_name(mesh)
attributes(file)["ndims"] = ndims(mesh)
attributes(file)["p4est_file"] = p4est_filename
attributes(file)["cell_ids"] = mesh.cell_ids
file["tree_node_coordinates"] = mesh.parent.tree_node_coordinates
file["nodes"] = Vector(mesh.parent.nodes)
file["boundary_names"] = mesh.parent.boundary_names .|> String
end
return filename
end
function calc_node_coordinates!(node_coordinates,
mesh::P4estMeshView{2, NDIMS_AMBIENT},
nodes::AbstractVector) where {NDIMS_AMBIENT}
tmp1 = StrideArray(undef, real(mesh),
StaticInt(NDIMS_AMBIENT), static_length(nodes),
static_length(mesh.parent.nodes))
matrix1 = StrideArray(undef, real(mesh),
static_length(nodes), static_length(mesh.parent.nodes))
matrix2 = similar(matrix1)
baryweights_in = barycentric_weights(mesh.parent.nodes)
p4est_root_len = 1 << P4EST_MAXLEVEL
p4est_quadrant_len(l) = 1 << (P4EST_MAXLEVEL - l)
trees = unsafe_wrap_sc(p4est_tree_t, mesh.parent.p4est.trees)
mesh_view_cell_id = 0
for tree_id in eachindex(trees)
tree_offset = trees[tree_id].quadrants_offset
quadrants = unsafe_wrap_sc(p4est_quadrant_t, trees[tree_id].quadrants)
for i in eachindex(quadrants)
parent_mesh_cell_id = tree_offset + i
if !(parent_mesh_cell_id in mesh.cell_ids)
continue
end
mesh_view_cell_id += 1
quad = quadrants[i]
quad_length = p4est_quadrant_len(quad.level) / p4est_root_len
nodes_out_x = 2 * (quad_length * 1 / 2 * (nodes .+ 1) .+
quad.x / p4est_root_len) .- 1
nodes_out_y = 2 * (quad_length * 1 / 2 * (nodes .+ 1) .+
quad.y / p4est_root_len) .- 1
polynomial_interpolation_matrix!(matrix1, mesh.parent.nodes, nodes_out_x,
baryweights_in)
polynomial_interpolation_matrix!(matrix2, mesh.parent.nodes, nodes_out_y,
baryweights_in)
multiply_dimensionwise!(view(node_coordinates, :, :, :, mesh_view_cell_id),
matrix1, matrix2,
view(mesh.parent.tree_node_coordinates, :, :, :,
tree_id),
tmp1)
end
end
return node_coordinates
end
@inline mpi_parallel(mesh::P4estMeshView) = False()
end