Path: blob/main/src/meshes/structured_mesh_view.jl
2055 views
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).1# Since these FMAs can increase the performance of many numerical algorithms,2# we need to opt-in explicitly.3# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.4@muladd begin5#! format: noindent67"""8StructuredMeshView{NDIMS, RealT <: Real} <: AbstractMesh{NDIMS}910A view on a structured curved mesh.11"""12mutable struct StructuredMeshView{NDIMS, RealT <: Real} <: AbstractMesh{NDIMS}13parent::StructuredMesh{NDIMS, RealT}14cells_per_dimension::NTuple{NDIMS, Int}15mapping::Any # Not relevant for performance16mapping_as_string::String17current_filename::String18indices_min::NTuple{NDIMS, Int}19indices_max::NTuple{NDIMS, Int}20unsaved_changes::Bool21end2223"""24StructuredMeshView(parent; indices_min, indices_max)2526Create a StructuredMeshView on a StructuredMesh parent.2728# Arguments29- `parent`: the parent StructuredMesh.30- `indices_min`: starting indices of the parent mesh.31- `indices_max`: ending indices of the parent mesh.32"""33function StructuredMeshView(parent::StructuredMesh{NDIMS, RealT};34indices_min = ntuple(_ -> 1, Val(NDIMS)),35indices_max = size(parent)) where {NDIMS, RealT}36@assert indices_min <= indices_max37@assert all(indices_min .> 0)38@assert indices_max <= size(parent)3940cells_per_dimension = indices_max .- indices_min .+ 14142# Compute cell sizes `deltas`43deltas = (parent.mapping.coordinates_max .- parent.mapping.coordinates_min) ./44parent.cells_per_dimension45# Calculate the domain boundaries.46coordinates_min = parent.mapping.coordinates_min .+ deltas .* (indices_min .- 1)47coordinates_max = parent.mapping.coordinates_min .+ deltas .* indices_max48mapping = coordinates2mapping(coordinates_min, coordinates_max)49mapping_as_string = """50coordinates_min = $coordinates_min51coordinates_max = $coordinates_max52mapping = coordinates2mapping(coordinates_min, coordinates_max)53"""5455return StructuredMeshView{NDIMS, RealT}(parent, cells_per_dimension, mapping,56mapping_as_string,57parent.current_filename,58indices_min, indices_max,59parent.unsaved_changes)60end6162# Check if mesh is periodic63function isperiodic(mesh::StructuredMeshView)64@unpack parent = mesh65return isperiodic(parent) && size(parent) == size(mesh)66end6768function isperiodic(mesh::StructuredMeshView, dimension)69@unpack parent, indices_min, indices_max = mesh70return (isperiodic(parent, dimension) &&71indices_min[dimension] == 1 &&72indices_max[dimension] == size(parent, dimension))73end7475@inline Base.ndims(::StructuredMeshView{NDIMS}) where {NDIMS} = NDIMS76@inline Base.real(::StructuredMeshView{NDIMS, RealT}) where {NDIMS, RealT} = RealT77function Base.size(mesh::StructuredMeshView)78@unpack indices_min, indices_max = mesh79return indices_max .- indices_min .+ 180end81function Base.size(mesh::StructuredMeshView, i)82@unpack indices_min, indices_max = mesh83return indices_max[i] - indices_min[i] + 184end85Base.axes(mesh::StructuredMeshView) = map(Base.OneTo, size(mesh))86Base.axes(mesh::StructuredMeshView, i) = Base.OneTo(size(mesh, i))8788function calc_node_coordinates!(node_coordinates, element,89cell_x, cell_y, mapping,90mesh::StructuredMeshView{2},91basis)92@unpack nodes = basis9394# Get cell length in reference mesh95dx = 2 / size(mesh, 1)96dy = 2 / size(mesh, 2)9798# Calculate node coordinates of reference mesh99cell_x_offset = -1 + (cell_x - 1) * dx + dx / 2100cell_y_offset = -1 + (cell_y - 1) * dy + dy / 2101102for j in eachnode(basis), i in eachnode(basis)103# node_coordinates are the mapped reference node_coordinates104node_coordinates[:, i, j, element] .= mapping(cell_x_offset + dx / 2 * nodes[i],105cell_y_offset + dy / 2 * nodes[j])106end107108return nothing109end110111# Does not save the mesh itself to an HDF5 file. Instead saves important attributes112# of the mesh, like its size and the type of boundary mapping function.113# Then, within Trixi2Vtk, the StructuredMesh and its node coordinates are reconstructured from114# these attributes for plotting purposes.115function save_mesh_file(mesh::StructuredMeshView, output_directory; system = "",116timestep = 0)117# Create output directory (if it does not exist)118mkpath(output_directory)119120filename = joinpath(output_directory, @sprintf("mesh_%s_%09d.h5", system, timestep))121122# Open file (clobber existing content)123h5open(filename, "w") do file124# Add context information as attributes125attributes(file)["mesh_type"] = get_name(mesh)126attributes(file)["ndims"] = ndims(mesh)127attributes(file)["size"] = collect(size(mesh))128attributes(file)["mapping"] = mesh.mapping_as_string129end130131return filename132end133end # @muladd134135136