Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/meshes/structured_mesh_view.jl
2055 views
1
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
2
# Since these FMAs can increase the performance of many numerical algorithms,
3
# we need to opt-in explicitly.
4
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
5
@muladd begin
6
#! format: noindent
7
8
"""
9
StructuredMeshView{NDIMS, RealT <: Real} <: AbstractMesh{NDIMS}
10
11
A view on a structured curved mesh.
12
"""
13
mutable struct StructuredMeshView{NDIMS, RealT <: Real} <: AbstractMesh{NDIMS}
14
parent::StructuredMesh{NDIMS, RealT}
15
cells_per_dimension::NTuple{NDIMS, Int}
16
mapping::Any # Not relevant for performance
17
mapping_as_string::String
18
current_filename::String
19
indices_min::NTuple{NDIMS, Int}
20
indices_max::NTuple{NDIMS, Int}
21
unsaved_changes::Bool
22
end
23
24
"""
25
StructuredMeshView(parent; indices_min, indices_max)
26
27
Create a StructuredMeshView on a StructuredMesh parent.
28
29
# Arguments
30
- `parent`: the parent StructuredMesh.
31
- `indices_min`: starting indices of the parent mesh.
32
- `indices_max`: ending indices of the parent mesh.
33
"""
34
function StructuredMeshView(parent::StructuredMesh{NDIMS, RealT};
35
indices_min = ntuple(_ -> 1, Val(NDIMS)),
36
indices_max = size(parent)) where {NDIMS, RealT}
37
@assert indices_min <= indices_max
38
@assert all(indices_min .> 0)
39
@assert indices_max <= size(parent)
40
41
cells_per_dimension = indices_max .- indices_min .+ 1
42
43
# Compute cell sizes `deltas`
44
deltas = (parent.mapping.coordinates_max .- parent.mapping.coordinates_min) ./
45
parent.cells_per_dimension
46
# Calculate the domain boundaries.
47
coordinates_min = parent.mapping.coordinates_min .+ deltas .* (indices_min .- 1)
48
coordinates_max = parent.mapping.coordinates_min .+ deltas .* indices_max
49
mapping = coordinates2mapping(coordinates_min, coordinates_max)
50
mapping_as_string = """
51
coordinates_min = $coordinates_min
52
coordinates_max = $coordinates_max
53
mapping = coordinates2mapping(coordinates_min, coordinates_max)
54
"""
55
56
return StructuredMeshView{NDIMS, RealT}(parent, cells_per_dimension, mapping,
57
mapping_as_string,
58
parent.current_filename,
59
indices_min, indices_max,
60
parent.unsaved_changes)
61
end
62
63
# Check if mesh is periodic
64
function isperiodic(mesh::StructuredMeshView)
65
@unpack parent = mesh
66
return isperiodic(parent) && size(parent) == size(mesh)
67
end
68
69
function isperiodic(mesh::StructuredMeshView, dimension)
70
@unpack parent, indices_min, indices_max = mesh
71
return (isperiodic(parent, dimension) &&
72
indices_min[dimension] == 1 &&
73
indices_max[dimension] == size(parent, dimension))
74
end
75
76
@inline Base.ndims(::StructuredMeshView{NDIMS}) where {NDIMS} = NDIMS
77
@inline Base.real(::StructuredMeshView{NDIMS, RealT}) where {NDIMS, RealT} = RealT
78
function Base.size(mesh::StructuredMeshView)
79
@unpack indices_min, indices_max = mesh
80
return indices_max .- indices_min .+ 1
81
end
82
function Base.size(mesh::StructuredMeshView, i)
83
@unpack indices_min, indices_max = mesh
84
return indices_max[i] - indices_min[i] + 1
85
end
86
Base.axes(mesh::StructuredMeshView) = map(Base.OneTo, size(mesh))
87
Base.axes(mesh::StructuredMeshView, i) = Base.OneTo(size(mesh, i))
88
89
function calc_node_coordinates!(node_coordinates, element,
90
cell_x, cell_y, mapping,
91
mesh::StructuredMeshView{2},
92
basis)
93
@unpack nodes = basis
94
95
# Get cell length in reference mesh
96
dx = 2 / size(mesh, 1)
97
dy = 2 / size(mesh, 2)
98
99
# Calculate node coordinates of reference mesh
100
cell_x_offset = -1 + (cell_x - 1) * dx + dx / 2
101
cell_y_offset = -1 + (cell_y - 1) * dy + dy / 2
102
103
for j in eachnode(basis), i in eachnode(basis)
104
# node_coordinates are the mapped reference node_coordinates
105
node_coordinates[:, i, j, element] .= mapping(cell_x_offset + dx / 2 * nodes[i],
106
cell_y_offset + dy / 2 * nodes[j])
107
end
108
109
return nothing
110
end
111
112
# Does not save the mesh itself to an HDF5 file. Instead saves important attributes
113
# of the mesh, like its size and the type of boundary mapping function.
114
# Then, within Trixi2Vtk, the StructuredMesh and its node coordinates are reconstructured from
115
# these attributes for plotting purposes.
116
function save_mesh_file(mesh::StructuredMeshView, output_directory; system = "",
117
timestep = 0)
118
# Create output directory (if it does not exist)
119
mkpath(output_directory)
120
121
filename = joinpath(output_directory, @sprintf("mesh_%s_%09d.h5", system, timestep))
122
123
# Open file (clobber existing content)
124
h5open(filename, "w") do file
125
# Add context information as attributes
126
attributes(file)["mesh_type"] = get_name(mesh)
127
attributes(file)["ndims"] = ndims(mesh)
128
attributes(file)["size"] = collect(size(mesh))
129
attributes(file)["mapping"] = mesh.mapping_as_string
130
end
131
132
return filename
133
end
134
end # @muladd
135
136