From e4ac391e8054ffdc4b5c953ad783594f58c81d0a Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 27 May 2024 10:09:49 +0200 Subject: [PATCH 01/11] AMR-Compat SurfaceIntegrals --- .../elixir_euler_NACA0012airfoil_mach085.jl | 2 +- .../elixir_euler_subsonic_cylinder.jl | 4 +- ...xir_navierstokes_NACA0012airfoil_mach08.jl | 2 +- src/callbacks_step/analysis.jl | 8 +++- .../analysis_surface_integral_2d.jl | 44 ++++++++++--------- test/test_p4est_2d.jl | 8 ++-- test/test_parabolic_2d.jl | 8 ++-- 7 files changed, 43 insertions(+), 33 deletions(-) diff --git a/examples/p4est_2d_dgsem/elixir_euler_NACA0012airfoil_mach085.jl b/examples/p4est_2d_dgsem/elixir_euler_NACA0012airfoil_mach085.jl index fb5f29bd038..8806f9cc2af 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_NACA0012airfoil_mach085.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_NACA0012airfoil_mach085.jl @@ -84,7 +84,7 @@ analysis_interval = 2000 l_inf = 1.0 # Length of airfoil -force_boundary_names = [:AirfoilBottom, :AirfoilTop] +force_boundary_names = (:AirfoilBottom, :AirfoilTop) drag_coefficient = AnalysisSurfaceIntegral(semi, force_boundary_names, DragCoefficientPressure(aoa(), rho_inf(), u_inf(equations), l_inf)) diff --git a/examples/p4est_2d_dgsem/elixir_euler_subsonic_cylinder.jl b/examples/p4est_2d_dgsem/elixir_euler_subsonic_cylinder.jl index dc23e192de8..e522a0dcfd3 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_subsonic_cylinder.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_subsonic_cylinder.jl @@ -89,11 +89,11 @@ rho_inf = 1.4 u_inf = 0.38 l_inf = 1.0 # Diameter of circle -drag_coefficient = AnalysisSurfaceIntegral(semi, :x_neg, +drag_coefficient = AnalysisSurfaceIntegral(semi, (:x_neg,), DragCoefficientPressure(aoa, rho_inf, u_inf, l_inf)) -lift_coefficient = AnalysisSurfaceIntegral(semi, :x_neg, +lift_coefficient = AnalysisSurfaceIntegral(semi, (:x_neg,), LiftCoefficientPressure(aoa, rho_inf, u_inf, l_inf)) diff --git a/examples/p4est_2d_dgsem/elixir_navierstokes_NACA0012airfoil_mach08.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_NACA0012airfoil_mach08.jl index 1b485913ab2..3e4679f5afe 100644 --- a/examples/p4est_2d_dgsem/elixir_navierstokes_NACA0012airfoil_mach08.jl +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_NACA0012airfoil_mach08.jl @@ -119,7 +119,7 @@ summary_callback = SummaryCallback() analysis_interval = 2000 -force_boundary_names = [:AirfoilBottom, :AirfoilTop] +force_boundary_names = (:AirfoilBottom, :AirfoilTop) drag_coefficient = AnalysisSurfaceIntegral(semi, force_boundary_names, DragCoefficientPressure(aoa(), rho_inf(), u_inf(equations), diff --git a/src/callbacks_step/analysis.jl b/src/callbacks_step/analysis.jl index 8f89af755a2..bd4db4d0e60 100644 --- a/src/callbacks_step/analysis.jl +++ b/src/callbacks_step/analysis.jl @@ -694,6 +694,12 @@ include("analysis_dg2d_parallel.jl") include("analysis_dg3d.jl") include("analysis_dg3d_parallel.jl") +function analyze(quantity::AnalysisSurfaceIntegral, du, u, t, + semi::AbstractSemidiscretization) + mesh, equations, solver, cache = mesh_equations_solver_cache(semi) + analyze(quantity, du, u, t, mesh, equations, solver, cache, semi) +end + # Special analyze for `SemidiscretizationHyperbolicParabolic` such that # precomputed gradients are available. Required for `enstrophy` (see above) and viscous forces. # Note that this needs to be included after `analysis_surface_integral_2d.jl` to @@ -706,6 +712,6 @@ function analyze(quantity::AnalysisSurfaceIntegral{Variable}, mesh, equations, solver, cache = mesh_equations_solver_cache(semi) equations_parabolic = semi.equations_parabolic cache_parabolic = semi.cache_parabolic - analyze(quantity, du, u, t, mesh, equations, equations_parabolic, solver, cache, + analyze(quantity, du, u, t, mesh, equations, equations_parabolic, solver, cache, semi, cache_parabolic) end diff --git a/src/callbacks_step/analysis_surface_integral_2d.jl b/src/callbacks_step/analysis_surface_integral_2d.jl index 7ae259e5285..a266527c108 100644 --- a/src/callbacks_step/analysis_surface_integral_2d.jl +++ b/src/callbacks_step/analysis_surface_integral_2d.jl @@ -21,30 +21,18 @@ drag coefficient [`DragCoefficientPressure`](@ref) of e.g. an airfoil with the b name `:Airfoil` in 2D. - `semi::Semidiscretization`: Passed in to retrieve boundary condition information -- `boundary_symbol_or_boundary_symbols::Symbol|Vector{Symbol}`: Name(s) of the boundary/boundaries +- `boundary_symbols::Tuple{Vararg{Symbol}}`: Name(s) of the boundary/boundaries where the quantity of interest is computed - `variable::Variable`: Quantity of interest, like lift or drag """ struct AnalysisSurfaceIntegral{Variable} - indices::Vector{Int} # Indices in `boundary_condition_indices` where quantity of interest is computed variable::Variable # Quantity of interest, like lift or drag + boundary_symbols::Tuple{Vararg{Symbol}} # Name(s) of the boundary/boundaries - function AnalysisSurfaceIntegral(semi, boundary_symbol, variable) + function AnalysisSurfaceIntegral(semi, boundary_symbols, variable) @unpack boundary_symbol_indices = semi.boundary_conditions - indices = boundary_symbol_indices[boundary_symbol] - return new{typeof(variable)}(indices, variable) - end - - function AnalysisSurfaceIntegral(semi, boundary_symbols::Vector{Symbol}, variable) - @unpack boundary_symbol_indices = semi.boundary_conditions - indices = Vector{Int}() - for name in boundary_symbols - append!(indices, boundary_symbol_indices[name]) - end - sort!(indices) - - return new{typeof(variable)}(indices, variable) + return new{typeof(variable)}(variable, boundary_symbols) end end @@ -255,14 +243,27 @@ function (drag_coefficient::DragCoefficientShearStress)(u, normal_direction, x, (0.5 * rhoinf * uinf^2 * linf) end +function get_boundary_indices(boundary_symbols, boundary_symbol_indices) + indices = Vector{Int}() + for name in boundary_symbols + append!(indices, boundary_symbol_indices[name]) + end + sort!(indices) + + return indices +end + function analyze(surface_variable::AnalysisSurfaceIntegral, du, u, t, mesh::P4estMesh{2}, - equations, dg::DGSEM, cache) + equations, dg::DGSEM, cache, semi) @unpack boundaries = cache @unpack surface_flux_values, node_coordinates, contravariant_vectors = cache.elements @unpack weights = dg.basis - @unpack indices, variable = surface_variable + @unpack variable, boundary_symbols = surface_variable + + @unpack boundary_symbol_indices = semi.boundary_conditions + indices = get_boundary_indices(boundary_symbols, boundary_symbol_indices) surface_integral = zero(eltype(u)) index_range = eachnode(dg) @@ -308,13 +309,16 @@ end function analyze(surface_variable::AnalysisSurfaceIntegral{Variable}, du, u, t, mesh::P4estMesh{2}, equations, equations_parabolic, - dg::DGSEM, cache, + dg::DGSEM, cache, semi, cache_parabolic) where {Variable <: VariableViscous} @unpack boundaries = cache @unpack surface_flux_values, node_coordinates, contravariant_vectors = cache.elements @unpack weights = dg.basis - @unpack indices, variable = surface_variable + @unpack variable, boundary_symbols = surface_variable + + @unpack boundary_symbol_indices = semi.boundary_conditions + indices = get_boundary_indices(boundary_symbols, boundary_symbol_indices) # Additions for parabolic @unpack viscous_container = cache_parabolic diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index fbc94fdfd6d..43eea13914a 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -587,9 +587,9 @@ end u = Trixi.wrap_array(u_ode, semi) du = Trixi.wrap_array(du_ode, semi) drag = Trixi.analyze(drag_coefficient, du, u, tspan[2], mesh, equations, solver, - semi.cache) + semi.cache, semi) lift = Trixi.analyze(lift_coefficient, du, u, tspan[2], mesh, equations, solver, - semi.cache) + semi.cache, semi) @test isapprox(lift, -6.501138753497174e-15, atol = 1e-13) @test isapprox(drag, 2.588589856781827, atol = 1e-13) @@ -630,9 +630,9 @@ end u = Trixi.wrap_array(u_ode, semi) du = Trixi.wrap_array(du_ode, semi) drag = Trixi.analyze(drag_coefficient, du, u, tspan[2], mesh, equations, solver, - semi.cache) + semi.cache, semi) lift = Trixi.analyze(lift_coefficient, du, u, tspan[2], mesh, equations, solver, - semi.cache) + semi.cache, semi) @test isapprox(lift, 0.0262382560809345, atol = 1e-13) @test isapprox(drag, 0.10898248971932244, atol = 1e-13) diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index 7749a0c4780..d038354f88a 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -739,16 +739,16 @@ end du = Trixi.wrap_array(du_ode, semi) drag_p = Trixi.analyze(drag_coefficient, du, u, tspan[2], mesh, equations, solver, - semi.cache) + semi.cache, semi) lift_p = Trixi.analyze(lift_coefficient, du, u, tspan[2], mesh, equations, solver, - semi.cache) + semi.cache, semi) drag_f = Trixi.analyze(drag_coefficient_shear_force, du, u, tspan[2], mesh, equations, equations_parabolic, solver, - semi.cache, semi.cache_parabolic) + semi.cache, semi, semi.cache_parabolic) lift_f = Trixi.analyze(lift_coefficient_shear_force, du, u, tspan[2], mesh, equations, equations_parabolic, solver, - semi.cache, semi.cache_parabolic) + semi.cache, semi, semi.cache_parabolic) @test isapprox(drag_p, 0.17963843913309516, atol = 1e-13) @test isapprox(lift_p, 0.26462588007949367, atol = 1e-13) From 22bc80d07a4d124f4a21974f40c3a1d14fb8abca Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Mon, 27 May 2024 10:33:38 +0200 Subject: [PATCH 02/11] Apply suggestions from code review --- src/callbacks_step/analysis_surface_integral_2d.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/callbacks_step/analysis_surface_integral_2d.jl b/src/callbacks_step/analysis_surface_integral_2d.jl index a266527c108..f727963147f 100644 --- a/src/callbacks_step/analysis_surface_integral_2d.jl +++ b/src/callbacks_step/analysis_surface_integral_2d.jl @@ -261,7 +261,6 @@ function analyze(surface_variable::AnalysisSurfaceIntegral, du, u, t, @unpack weights = dg.basis @unpack variable, boundary_symbols = surface_variable - @unpack boundary_symbol_indices = semi.boundary_conditions indices = get_boundary_indices(boundary_symbols, boundary_symbol_indices) @@ -316,7 +315,6 @@ function analyze(surface_variable::AnalysisSurfaceIntegral{Variable}, @unpack weights = dg.basis @unpack variable, boundary_symbols = surface_variable - @unpack boundary_symbol_indices = semi.boundary_conditions indices = get_boundary_indices(boundary_symbols, boundary_symbol_indices) From e187ae0af1f44237f14798ca7d08e68eaf33383f Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Mon, 27 May 2024 10:45:11 +0200 Subject: [PATCH 03/11] shorten --- src/callbacks_step/analysis_surface_integral_2d.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/callbacks_step/analysis_surface_integral_2d.jl b/src/callbacks_step/analysis_surface_integral_2d.jl index a266527c108..1ecd8e981e0 100644 --- a/src/callbacks_step/analysis_surface_integral_2d.jl +++ b/src/callbacks_step/analysis_surface_integral_2d.jl @@ -30,8 +30,6 @@ struct AnalysisSurfaceIntegral{Variable} boundary_symbols::Tuple{Vararg{Symbol}} # Name(s) of the boundary/boundaries function AnalysisSurfaceIntegral(semi, boundary_symbols, variable) - @unpack boundary_symbol_indices = semi.boundary_conditions - return new{typeof(variable)}(variable, boundary_symbols) end end From 3eb91b9aa9f550b9e7f52fd5466796f1f418d0ca Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 28 May 2024 10:35:52 +0200 Subject: [PATCH 04/11] test with amr being called --- test/test_p4est_2d.jl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index 43eea13914a..a691ad60570 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -600,13 +600,14 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_NACA0012airfoil_mach085.jl"), l2=[ - 5.371568111383228e-7, 6.4158131303956445e-6, - 1.0324346542348325e-5, 0.0006348064933187732, + 5.634402680811982e-7, 6.748066107517321e-6, + 1.091879472416885e-5, 0.0006686372064029146, ], linf=[ - 0.0016263400091978443, 0.028471072159724428, - 0.02986133204785877, 1.9481060511014872, + 0.0021456247890772823, 0.03957142889488085, + 0.03832024233032798, 2.6628739573358495, ], + amr_interval=1, base_level=0, med_level=1, max_level=1, tspan=(0.0, 0.0001), adapt_initial_condition=false, @@ -634,8 +635,8 @@ end lift = Trixi.analyze(lift_coefficient, du, u, tspan[2], mesh, equations, solver, semi.cache, semi) - @test isapprox(lift, 0.0262382560809345, atol = 1e-13) - @test isapprox(drag, 0.10898248971932244, atol = 1e-13) + @test isapprox(lift, 0.029076443678087403, atol = 1e-13) + @test isapprox(drag, 0.13564720009197903, atol = 1e-13) end end From 56f2dc84d7f21c8d6803a42b6e6a7661b2f994f8 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 28 May 2024 10:38:56 +0200 Subject: [PATCH 05/11] Add comment --- src/callbacks_step/analysis.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/callbacks_step/analysis.jl b/src/callbacks_step/analysis.jl index bd4db4d0e60..d01319832a6 100644 --- a/src/callbacks_step/analysis.jl +++ b/src/callbacks_step/analysis.jl @@ -694,6 +694,9 @@ include("analysis_dg2d_parallel.jl") include("analysis_dg3d.jl") include("analysis_dg3d_parallel.jl") +# This version of `analyze` is used for [`AnalysisSurfaceIntegral`](@ref) which requires +# `semi` to be passed along to retrieve the current boundary indices, which are non-static +# in the case of AMR. function analyze(quantity::AnalysisSurfaceIntegral, du, u, t, semi::AbstractSemidiscretization) mesh, equations, solver, cache = mesh_equations_solver_cache(semi) From 8770d38f8bd1322da972ebe356f110b75ba4cf63 Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 28 May 2024 10:40:53 +0200 Subject: [PATCH 06/11] Update src/callbacks_step/analysis_surface_integral_2d.jl --- src/callbacks_step/analysis_surface_integral_2d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/callbacks_step/analysis_surface_integral_2d.jl b/src/callbacks_step/analysis_surface_integral_2d.jl index 5191700a583..dd20de28766 100644 --- a/src/callbacks_step/analysis_surface_integral_2d.jl +++ b/src/callbacks_step/analysis_surface_integral_2d.jl @@ -246,7 +246,7 @@ function get_boundary_indices(boundary_symbols, boundary_symbol_indices) for name in boundary_symbols append!(indices, boundary_symbol_indices[name]) end - sort!(indices) + sort!(indices) # Try to achieve some data locality by sorting return indices end From 7e73c5a57ed83d95d2bdf7f2e015d25a1103d6ca Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 28 May 2024 15:15:21 +0200 Subject: [PATCH 07/11] ntuple --- src/callbacks_step/analysis_surface_integral_2d.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/callbacks_step/analysis_surface_integral_2d.jl b/src/callbacks_step/analysis_surface_integral_2d.jl index dd20de28766..f76034e1d16 100644 --- a/src/callbacks_step/analysis_surface_integral_2d.jl +++ b/src/callbacks_step/analysis_surface_integral_2d.jl @@ -21,16 +21,16 @@ drag coefficient [`DragCoefficientPressure`](@ref) of e.g. an airfoil with the b name `:Airfoil` in 2D. - `semi::Semidiscretization`: Passed in to retrieve boundary condition information -- `boundary_symbols::Tuple{Vararg{Symbol}}`: Name(s) of the boundary/boundaries +- `boundary_symbols::NTuple{NBoundaries, Symbol}`: Name(s) of the boundary/boundaries where the quantity of interest is computed - `variable::Variable`: Quantity of interest, like lift or drag """ -struct AnalysisSurfaceIntegral{Variable} +struct AnalysisSurfaceIntegral{Variable, NBoundaries} variable::Variable # Quantity of interest, like lift or drag - boundary_symbols::Tuple{Vararg{Symbol}} # Name(s) of the boundary/boundaries + boundary_symbols::NTuple{NBoundaries, Symbol} # Name(s) of the boundary/boundaries - function AnalysisSurfaceIntegral(semi, boundary_symbols, variable) - return new{typeof(variable)}(variable, boundary_symbols) + function AnalysisSurfaceIntegral(semi, boundary_symbols::NTuple{NBoundaries, Symbol}, variable) where NBoundaries + return new{typeof(variable), NBoundaries}(variable, boundary_symbols) end end From 7118d6ae7931049297054744c062b1f0430ce90d Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 28 May 2024 15:20:12 +0200 Subject: [PATCH 08/11] fmt --- src/callbacks_step/analysis_surface_integral_2d.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/callbacks_step/analysis_surface_integral_2d.jl b/src/callbacks_step/analysis_surface_integral_2d.jl index f76034e1d16..1247eba114a 100644 --- a/src/callbacks_step/analysis_surface_integral_2d.jl +++ b/src/callbacks_step/analysis_surface_integral_2d.jl @@ -29,7 +29,9 @@ struct AnalysisSurfaceIntegral{Variable, NBoundaries} variable::Variable # Quantity of interest, like lift or drag boundary_symbols::NTuple{NBoundaries, Symbol} # Name(s) of the boundary/boundaries - function AnalysisSurfaceIntegral(semi, boundary_symbols::NTuple{NBoundaries, Symbol}, variable) where NBoundaries + function AnalysisSurfaceIntegral(semi, + boundary_symbols::NTuple{NBoundaries, Symbol}, + variable) where {NBoundaries} return new{typeof(variable), NBoundaries}(variable, boundary_symbols) end end From 268fc38543a842505471ff841a2d3c665342e50b Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 25 Jun 2024 16:28:41 +0200 Subject: [PATCH 09/11] mention changes --- NEWS.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS.md b/NEWS.md index ecbd70ce472..4e2937b112d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,15 @@ Trixi.jl follows the interpretation of [semantic versioning (semver)](https://ju used in the Julia ecosystem. Notable changes will be documented in this file for human readability. +## Changes when updating to v0.8 from v0.7.x + +#### Added + +#### Changed + +- The specification of boundary names on which `AnalysisSurfaceIntegral`s are computed (such as drag and lift coefficients) has changed from `Symbol` and `Vector{Symbol}` to `NTuple{Symbol}`. +Thus, for one boundary the syntax changes from `:boundary` to `(:boundary,)` and for `Vector`s `[:boundary1, :boundary2]` to `(:boundary1, boundary2)`. + ## Changes in the v0.7 lifecycle #### Added From 89f6c8c263e490774aa93f78d81891ff72f5f81c Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 25 Jun 2024 16:29:34 +0200 Subject: [PATCH 10/11] news --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index 4e2937b112d..8b3668518de 100644 --- a/NEWS.md +++ b/NEWS.md @@ -13,6 +13,10 @@ for human readability. - The specification of boundary names on which `AnalysisSurfaceIntegral`s are computed (such as drag and lift coefficients) has changed from `Symbol` and `Vector{Symbol}` to `NTuple{Symbol}`. Thus, for one boundary the syntax changes from `:boundary` to `(:boundary,)` and for `Vector`s `[:boundary1, :boundary2]` to `(:boundary1, boundary2)`. +#### Deprecated + +#### Removed + ## Changes in the v0.7 lifecycle #### Added From cdd1bc77926da3e7dff3f8f53cdbf95f7604e63b Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Fri, 28 Jun 2024 17:46:56 +0200 Subject: [PATCH 11/11] Apply suggestions from code review Co-authored-by: Michael Schlottke-Lakemper --- NEWS.md | 2 +- src/callbacks_step/analysis_surface_integral_2d.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8b3668518de..b2cef287edd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,7 +11,7 @@ for human readability. #### Changed - The specification of boundary names on which `AnalysisSurfaceIntegral`s are computed (such as drag and lift coefficients) has changed from `Symbol` and `Vector{Symbol}` to `NTuple{Symbol}`. -Thus, for one boundary the syntax changes from `:boundary` to `(:boundary,)` and for `Vector`s `[:boundary1, :boundary2]` to `(:boundary1, boundary2)`. +Thus, for one boundary the syntax changes from `:boundary` to `(:boundary,)` and for `Vector`s `[:boundary1, :boundary2]` to `(:boundary1, :boundary2)` ([1959]). #### Deprecated diff --git a/src/callbacks_step/analysis_surface_integral_2d.jl b/src/callbacks_step/analysis_surface_integral_2d.jl index 1247eba114a..d92ac5a2076 100644 --- a/src/callbacks_step/analysis_surface_integral_2d.jl +++ b/src/callbacks_step/analysis_surface_integral_2d.jl @@ -244,7 +244,7 @@ function (drag_coefficient::DragCoefficientShearStress)(u, normal_direction, x, end function get_boundary_indices(boundary_symbols, boundary_symbol_indices) - indices = Vector{Int}() + indices = Int[] for name in boundary_symbols append!(indices, boundary_symbol_indices[name]) end