Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/auxiliary/t8code.jl
2055 views
1
"""
2
init_t8code()
3
4
Initialize `t8code` by calling `sc_init`, `p4est_init`, and `t8_init` while
5
setting the log level to `SC_LP_ERROR`. This function will check if `t8code`
6
is already initialized and if yes, do nothing, thus it is safe to call it
7
multiple times.
8
"""
9
function init_t8code()
10
# Only initialize t8code if T8code.jl can be used
11
if T8code.preferences_set_correctly()
12
t8code_package_id = t8_get_package_id()
13
if t8code_package_id >= 0
14
return nothing
15
end
16
17
# Initialize `libsc`, `p4est`, and `t8code` with log level
18
# `SC_LP_ERROR` to prevent a lot of output in AMR simulations
19
# For development, log level `SC_LP_DEBUG` is recommended.
20
LOG_LEVEL = T8code.Libt8.SC_LP_ERROR
21
22
if T8code.Libt8.sc_is_initialized() == 0
23
# Initialize the sc library, has to happen before we initialize t8code.
24
let catch_signals = 0, print_backtrace = 0, log_handler = C_NULL
25
T8code.Libt8.sc_init(mpi_comm(), catch_signals, print_backtrace,
26
log_handler,
27
LOG_LEVEL)
28
end
29
end
30
31
if T8code.Libt8.p4est_is_initialized() == 0
32
T8code.Libt8.p4est_init(C_NULL, LOG_LEVEL)
33
end
34
35
# Clean up t8code before MPI shuts down.
36
MPI.add_finalize_hook!() do
37
T8code.clean_up()
38
status = T8code.Libt8.sc_finalize_noabort()
39
if status != 0
40
@warn("Inconsistent state detected after finalizing t8code.")
41
end
42
end
43
44
# Initialize t8code.
45
t8_init(LOG_LEVEL)
46
else
47
@warn "Preferences for T8code.jl are not set correctly. Until fixed, using `T8codeMesh` will result in a crash. " *
48
"See also https://trixi-framework.github.io/TrixiDocumentation/stable/parallelization/#parallel_system_MPI"
49
end
50
51
return nothing
52
end
53
54
function trixi_t8_get_local_element_levels(forest)
55
# Check that forest is a committed, that is valid and usable, forest.
56
@assert t8_forest_is_committed(forest) != 0
57
58
levels = Vector{UInt8}(undef, t8_forest_get_local_num_elements(forest))
59
60
# Get the number of trees that have elements of this process.
61
num_local_trees = t8_forest_get_num_local_trees(forest)
62
63
current_index = 0
64
65
for itree in 0:(num_local_trees - 1)
66
tree_class = t8_forest_get_tree_class(forest, itree)
67
eclass_scheme = t8_forest_get_eclass_scheme(forest, tree_class)
68
69
# Get the number of elements of this tree.
70
num_elements_in_tree = t8_forest_get_tree_num_elements(forest, itree)
71
72
for ielement in 0:(num_elements_in_tree - 1)
73
element = t8_forest_get_element_in_tree(forest, itree, ielement)
74
current_index += 1
75
levels[current_index] = UInt8(t8_element_level(eclass_scheme, element))
76
end # for
77
end # for
78
79
return levels
80
end
81
82
# Callback function prototype to decide for refining and coarsening.
83
# If `is_family` equals 1, the first `num_elements` in elements
84
# form a family and we decide whether this family should be coarsened
85
# or only the first element should be refined.
86
# Otherwise `is_family` must equal zero and we consider the first entry
87
# of the element array for refinement.
88
# Entries of the element array beyond the first `num_elements` are undefined.
89
# \param [in] forest the forest to which the new elements belong
90
# \param [in] forest_from the forest that is adapted.
91
# \param [in] which_tree the local tree containing `elements`
92
# \param [in] lelement_id the local element id in `forest_old` in the tree of the current element
93
# \param [in] ts the eclass scheme of the tree
94
# \param [in] is_family if 1, the first `num_elements` entries in `elements` form a family. If 0, they do not.
95
# \param [in] num_elements the number of entries in `elements` that are defined
96
# \param [in] elements Pointers to a family or, if `is_family` is zero,
97
# pointer to one element.
98
# \return greater zero if the first entry in `elements` should be refined,
99
# smaller zero if the family `elements` shall be coarsened,
100
# zero else.
101
function adapt_callback(forest::Ptr{t8_forest},
102
forest_from::Ptr{t8_forest},
103
which_tree,
104
lelement_id,
105
ts,
106
is_family,
107
num_elements,
108
elements)::Cint
109
num_levels = t8_forest_get_local_num_elements(forest_from)
110
111
indicator_ptr = Ptr{Int}(t8_forest_get_user_data(forest))
112
indicators = unsafe_wrap(Array, indicator_ptr, num_levels)
113
114
offset = t8_forest_get_tree_element_offset(forest_from, which_tree)
115
116
# Only allow coarsening for complete families.
117
if indicators[offset + lelement_id + 1] < 0 && is_family == 0
118
return Cint(0)
119
end
120
121
return Cint(indicators[offset + lelement_id + 1])
122
end
123
124
function trixi_t8_adapt_new(old_forest, indicators)
125
new_forest_ref = Ref{t8_forest_t}()
126
t8_forest_init(new_forest_ref)
127
new_forest = new_forest_ref[]
128
129
let set_from = C_NULL, recursive = 0, no_repartition = 1, do_ghost = 1
130
t8_forest_set_user_data(new_forest, pointer(indicators))
131
t8_forest_set_adapt(new_forest, old_forest, @t8_adapt_callback(adapt_callback),
132
recursive)
133
t8_forest_set_balance(new_forest, set_from, no_repartition)
134
t8_forest_set_ghost(new_forest, do_ghost, T8_GHOST_FACES)
135
t8_forest_commit(new_forest)
136
end
137
138
return new_forest
139
end
140
141
function trixi_t8_get_difference(old_levels, new_levels, num_children)
142
old_nelems = length(old_levels)
143
new_nelems = length(new_levels)
144
145
changes = Vector{Int}(undef, old_nelems)
146
147
# Local element indices.
148
old_index = 1
149
new_index = 1
150
151
while old_index <= old_nelems && new_index <= new_nelems
152
if old_levels[old_index] < new_levels[new_index]
153
# Refined.
154
155
changes[old_index] = 1
156
157
old_index += 1
158
new_index += num_children
159
160
elseif old_levels[old_index] > new_levels[new_index]
161
# Coarsend.
162
163
for child_index in old_index:(old_index + num_children - 1)
164
changes[child_index] = -1
165
end
166
167
old_index += num_children
168
new_index += 1
169
170
else
171
# No changes.
172
173
changes[old_index] = 0
174
175
old_index += 1
176
new_index += 1
177
end
178
end
179
180
return changes
181
end
182
183
# Coarsen or refine marked cells and rebalance forest. Return a difference between
184
# old and new mesh.
185
function trixi_t8_adapt!(mesh, indicators)
186
old_levels = trixi_t8_get_local_element_levels(mesh.forest)
187
188
forest_cached = trixi_t8_adapt_new(mesh.forest, indicators)
189
190
new_levels = trixi_t8_get_local_element_levels(forest_cached)
191
192
differences = trixi_t8_get_difference(old_levels, new_levels, 2^ndims(mesh))
193
194
update_forest!(mesh, forest_cached)
195
196
return differences
197
end
198
199