Path: blob/main/src/callbacks_step/time_series_dg_tree.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# Find element ids containing coordinates given as a matrix [ndims, npoints]8function get_elements_by_coordinates!(element_ids, coordinates, mesh::TreeMesh, dg,9cache)10if length(element_ids) != size(coordinates, 2)11throw(DimensionMismatch("storage length for element ids does not match the number of coordinates"))12end1314@unpack cell_ids = cache.elements15@unpack tree = mesh1617# Reset element ids - 0 indicates "not (yet) found"18element_ids .= 019found_elements = 02021# Iterate over all elements22for element in eachelement(dg, cache)23# Get cell id24cell_id = cell_ids[element]2526# Iterate over coordinates27for index in eachindex(element_ids)28# Skip coordinates for which an element has already been found29if element_ids[index] > 030continue31end3233# Construct point34x = SVector(ntuple(i -> coordinates[i, index], ndims(mesh)))3536# Skip if point is not in cell37if !is_point_in_cell(tree, x, cell_id)38continue39end4041# Otherwise point is in cell and thus in element42element_ids[index] = element43found_elements += 144end4546# Exit loop if all elements have already been found47if found_elements == length(element_ids)48break49end50end5152return element_ids53end5455# Calculate the interpolating polynomials to extract data at the given coordinates56# The coordinates are known to be located in the respective element in `element_ids`57function calc_interpolating_polynomials!(interpolating_polynomials, coordinates,58element_ids,59mesh::TreeMesh, dg::DGSEM, cache)60@unpack tree = mesh61@unpack nodes = dg.basis6263wbary = barycentric_weights(nodes)6465for index in eachindex(element_ids)66# Construct point67x = SVector(ntuple(i -> coordinates[i, index], ndims(mesh)))6869# Convert to unit coordinates70cell_id = cache.elements.cell_ids[element_ids[index]]71cell_coordinates_ = cell_coordinates(tree, cell_id)72cell_length = length_at_cell(tree, cell_id)73unit_coordinates = (x .- cell_coordinates_) * 2 / cell_length7475# Calculate interpolating polynomial for each dimension, making use of tensor product structure76for d in 1:ndims(mesh)77interpolating_polynomials[:, d, index] .= lagrange_interpolating_polynomials(unit_coordinates[d],78nodes,79wbary)80end81end8283return interpolating_polynomials84end8586# Record the solution variables at each given point for the 1D case87function record_state_at_points!(point_data, u, solution_variables,88n_solution_variables,89mesh::TreeMesh{1}, equations, dg::DG,90time_series_cache)91@unpack element_ids, interpolating_polynomials = time_series_cache92old_length = length(first(point_data))93new_length = old_length + n_solution_variables9495# Loop over all points/elements that should be recorded96for index in eachindex(element_ids)97# Extract data array and element id98data = point_data[index]99element_id = element_ids[index]100101# Make room for new data to be recorded102resize!(data, new_length)103data[(old_length + 1):new_length] .= zero(eltype(data))104105# Loop over all nodes to compute their contribution to the interpolated values106for i in eachnode(dg)107u_node = solution_variables(get_node_vars(u, equations, dg, i,108element_id), equations)109110for v in eachindex(u_node)111data[old_length + v] += (u_node[v] *112interpolating_polynomials[i, 1, index])113end114end115end116117return nothing118end119120# Record the solution variables at each given point for the 2D case121function record_state_at_points!(point_data, u, solution_variables,122n_solution_variables,123mesh::TreeMesh{2},124equations, dg::DG, time_series_cache)125@unpack element_ids, interpolating_polynomials = time_series_cache126old_length = length(first(point_data))127new_length = old_length + n_solution_variables128129# Loop over all points/elements that should be recorded130for index in eachindex(element_ids)131# Extract data array and element id132data = point_data[index]133element_id = element_ids[index]134135# Make room for new data to be recorded136resize!(data, new_length)137data[(old_length + 1):new_length] .= zero(eltype(data))138139# Loop over all nodes to compute their contribution to the interpolated values140for j in eachnode(dg), i in eachnode(dg)141u_node = solution_variables(get_node_vars(u, equations, dg, i, j,142element_id), equations)143144for v in eachindex(u_node)145data[old_length + v] += (u_node[v]146* interpolating_polynomials[i, 1, index]147* interpolating_polynomials[j, 2, index])148end149end150end151152return nothing153end154155# Record the solution variables at each given point for the 3D case156function record_state_at_points!(point_data, u, solution_variables,157n_solution_variables,158mesh::TreeMesh{3}, equations, dg::DG,159time_series_cache)160@unpack element_ids, interpolating_polynomials = time_series_cache161old_length = length(first(point_data))162new_length = old_length + n_solution_variables163164# Loop over all points/elements that should be recorded165for index in eachindex(element_ids)166# Extract data array and element id167data = point_data[index]168element_id = element_ids[index]169170# Make room for new data to be recorded171resize!(data, new_length)172data[(old_length + 1):new_length] .= zero(eltype(data))173174# Loop over all nodes to compute their contribution to the interpolated values175for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)176u_node = solution_variables(get_node_vars(u, equations, dg, i, j, k,177element_id), equations)178179for v in eachindex(u_node)180data[old_length + v] += (u_node[v]181* interpolating_polynomials[i, 1, index]182* interpolating_polynomials[j, 2, index]183* interpolating_polynomials[k, 3, index])184end185end186end187188return nothing189end190end # @muladd191192193