From 552654cc76f35902241812030b3e80c88739cf04 Mon Sep 17 00:00:00 2001 From: vavrines <21040679+vavrines@users.noreply.github.com> Date: Sun, 28 Jun 2026 04:03:42 +0000 Subject: [PATCH] Format .jl files --- docs/make.jl | 14 +- example/Riemann_problem/rp_1D.jl | 57 +- example/Riemann_problem/rp_2D.jl | 26 +- example/X38/X38_julia.jl | 63 +- example/X38/X38_text.jl | 21 +- example/X38/X38_udf.jl | 14 +- example/X38/model_transform.jl | 16 +- example/airfoil/airfoil.jl | 60 +- example/airfoil/airfoil_udf.jl | 4 +- example/blast_wave/bw_2D.jl | 25 +- example/blast_wave/bw_3D.jl | 29 +- example/cylinder/cylinder.jl | 50 +- example/cylinder/cylinder_udf.jl | 39 +- example/sphere/sphere.jl | 57 +- example/sphere/sphere_udf.jl | 42 +- lib/KitCore/2D.jl | 12 +- lib/KitCore/2D2F.jl | 131 +-- lib/KitCore/3D.jl | 9 +- lib/KitCore/3D1F.jl | 51 +- lib/KitCore/KitCore.jl | 36 +- src/Abstract/Types.jl | 109 ++- src/Boundary/AMR.jl | 177 +++-- src/Boundary/Boundary.jl | 10 +- src/Boundary/Circle.jl | 178 +++-- src/Boundary/Immersed_boundary.jl | 712 ++++++++++++----- src/Boundary/Parallel.jl | 97 ++- src/Boundary/Period.jl | 34 +- src/Boundary/Positivity.jl | 64 +- src/Boundary/Triangles.jl | 403 ++++++---- src/Boundary/Types.jl | 197 +++-- src/Boundary/Vertices.jl | 115 ++- src/Flux/CAIDVM.jl | 273 +++++-- src/Flux/DVM.jl | 216 +++-- src/Flux/Flux.jl | 390 +++++---- src/Flux/Slope.jl | 250 ++++-- src/Flux/UGKS.jl | 319 +++++--- src/Gas/Gas.jl | 2 +- src/Gas/Model.jl | 7 +- src/Gas/Types.jl | 62 +- src/IO/Check.jl | 67 +- src/IO/IO.jl | 7 +- src/IO/Input.jl | 4 +- src/IO/Output.jl | 1103 +++++++++++++++----------- src/IO/Restart.jl | 167 +++- src/IO/Types.jl | 58 +- src/KitAMR.jl | 7 +- src/Mesh/Connectivity.jl | 117 ++- src/Mesh/Mesh.jl | 2 +- src/Mesh/Neighbor.jl | 37 +- src/P4est/P4est.jl | 2 +- src/P4est/P4est_wrap.jl | 238 ++++-- src/Parallel/Ghost.jl | 552 ++++++++----- src/Parallel/Parallel.jl | 2 +- src/Parallel/Partition.jl | 275 ++++--- src/Physical_space/AMR.jl | 436 ++++++---- src/Physical_space/Criteria.jl | 96 ++- src/Physical_space/Physical_space.jl | 20 +- src/Physical_space/Types.jl | 219 +++-- src/Solver/AMR.jl | 49 +- src/Solver/Auxiliary.jl | 12 +- src/Solver/Finalize.jl | 17 +- src/Solver/Initialize.jl | 456 +++++++---- src/Solver/Solver.jl | 71 +- src/Solver/Types.jl | 699 ++++++++++------ src/Theory/I-projection.jl | 72 +- src/Theory/Iterate.jl | 51 +- src/Theory/Math.jl | 291 ++++--- src/Velocity_space/AMR.jl | 200 +++-- src/Velocity_space/Balance.jl | 59 +- src/Velocity_space/Criteria.jl | 343 ++++++-- src/Velocity_space/Cut_cell.jl | 232 +++--- src/Velocity_space/Initialize.jl | 77 +- src/Velocity_space/Neighbor.jl | 105 ++- src/Velocity_space/Rebuild.jl | 67 +- src/Velocity_space/Types.jl | 180 ++++- src/Velocity_space/Velocity_space.jl | 7 +- test/runtests.jl | 40 +- 77 files changed, 7083 insertions(+), 3725 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 92b9ea6..f1c956e 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -8,7 +8,7 @@ type_page = [ "Gas"=>"type_gas.md", "Physical space"=>"type_physical_space.md", "Velocity space"=>"type_velocity_space.md", - "Output"=>"type_output.md" + "Output"=>"type_output.md", ] methods_page = [ "Running a simulation"=>"methods_solve.md", @@ -20,7 +20,7 @@ methods_page = [ "Parallel"=>"methods_parallel.md", "Theory"=>"methods_theory.md", "Finalization"=>"methods_finalize.md", - "IO"=>"methods_io.md" + "IO"=>"methods_io.md", ] makedocs(; sitename = "KitAMR.jl", @@ -33,13 +33,11 @@ makedocs(; "Tutorial"=>"tutorial.md", "Cluster deployment"=>"cluster_deployment.md", "Index"=>"index_internal.md", - "Limitations"=>"limitations.md" - ], + "Limitations"=>"limitations.md", + ], # format = Documenter.HTML(; collapselevel=1), checkdocs = :none, - format = Documenter.HTML() + format = Documenter.HTML(), ) -deploydocs(;devbranch = "main", - repo = "github.com/CFDML/KitAMR.jl.git", -) \ No newline at end of file +deploydocs(; devbranch = "main", repo = "github.com/CFDML/KitAMR.jl.git") diff --git a/example/Riemann_problem/rp_1D.jl b/example/Riemann_problem/rp_1D.jl index f776f80..92dd564 100644 --- a/example/Riemann_problem/rp_1D.jl +++ b/example/Riemann_problem/rp_1D.jl @@ -1,16 +1,17 @@ -using KitAMR,MPI +using KitAMR, MPI MPI.Init() -function Sod_init(midpoint,kinfo) - if midpoint[1]<0. - return [1.,0.,0.,0.5] +function Sod_init(midpoint, kinfo) + if midpoint[1]<0.0 + return [1.0, 0.0, 0.0, 0.5] else - return [0.125,0.,0.,0.625] + return [0.125, 0.0, 0.0, 0.625] end end solver = Solver(; - DIM = 2, NDF = 2, + DIM = 2, + NDF = 2, CFL = 0.4, AMR_PS_MAXLEVEL = 3, AMR_VS_MAXLEVEL = 3, @@ -22,37 +23,31 @@ solver = Solver(; # time_marching = CIP_Marching, time_marching = Euler, # time_marching = CAIDVM_Marching, - max_sim_time = 20., + max_sim_time = 20.0, ) -gas = Gas(; - K = 1.0, - Kn = 0.001, - ω = 0.81, - ωᵣ = 0.81, -) -output = Output( +gas = Gas(; K = 1.0, Kn = 0.001, ω = 0.81, ωᵣ = 0.81) +output = Output(solver;) +udf = UDF(;) +config = Configure( solver; -) -udf = UDF(; -) -config = Configure(solver; - geometry = [-2.,2.,-0.5,0.5], - trees_num = [32,8], - quadrature = [-7.,7.,-7.,7.], - vs_trees_num = [8,8], + geometry = [-2.0, 2.0, -0.5, 0.5], + trees_num = [32, 8], + quadrature = [-7.0, 7.0, -7.0, 7.0], + vs_trees_num = [8, 8], IC = PCoordFn(Sod_init), domain = [ - Domain(UniformOutflow,1),Domain(UniformOutflow,2), - Domain(Period,3),Domain(Period,4) - ], + Domain(UniformOutflow, 1), + Domain(UniformOutflow, 2), + Domain(Period, 3), + Domain(Period, 4), + ], output = output, gas = gas, - user_defined = udf + user_defined = udf, ) -p4est,ka = initialize(config; prerefine_steps = 1, prerefine_recursive = true); -solve!(p4est, ka; - ps_interval = 20, vs_interval = 20, partition_interval = 20) -save_result(p4est,ka) -finalize!(p4est,ka) +p4est, ka = initialize(config; prerefine_steps = 1, prerefine_recursive = true); +solve!(p4est, ka; ps_interval = 20, vs_interval = 20, partition_interval = 20) +save_result(p4est, ka) +finalize!(p4est, ka) MPI.Finalize() diff --git a/example/Riemann_problem/rp_2D.jl b/example/Riemann_problem/rp_2D.jl index 9affba0..bdfb2a9 100644 --- a/example/Riemann_problem/rp_2D.jl +++ b/example/Riemann_problem/rp_2D.jl @@ -40,29 +40,24 @@ solver = Solver(; max_sim_time = 0.25, ) -gas = Gas(; - K = 1.0, - Kn = 0.001, - ω = 0.81, - ωᵣ = 0.81, -) +gas = Gas(; K = 1.0, Kn = 0.001, ω = 0.81, ωᵣ = 0.81) -output = Output( - solver; -) +output = Output(solver;) -udf = UDF(; -) +udf = UDF(;) -config = Configure(solver; +config = Configure( + solver; geometry = [-0.5, 0.5, -0.5, 0.5], trees_num = [16, 16], quadrature = [-5.0, 5.0, -5.0, 5.0], vs_trees_num = [8, 8], IC = PCoordFn(Riemann_2D_init), domain = [ - Domain(UniformOutflow, 1), Domain(UniformOutflow, 2), - Domain(UniformOutflow, 3), Domain(UniformOutflow, 4), + Domain(UniformOutflow, 1), + Domain(UniformOutflow, 2), + Domain(UniformOutflow, 3), + Domain(UniformOutflow, 4), ], output = output, gas = gas, @@ -71,8 +66,7 @@ config = Configure(solver; p4est, ka = initialize(config; prerefine_steps = 5, prerefine_reinit_ic = true) -solve!(p4est, ka; - ps_interval = 40, vs_interval = 40, partition_interval = 40) +solve!(p4est, ka; ps_interval = 40, vs_interval = 40, partition_interval = 40) save_result(p4est, ka) finalize!(p4est, ka) MPI.Finalize() diff --git a/example/X38/X38_julia.jl b/example/X38/X38_julia.jl index f7018c1..aff4787 100644 --- a/example/X38/X38_julia.jl +++ b/example/X38/X38_julia.jl @@ -1,4 +1,4 @@ -using KitAMR,MPI +using KitAMR, MPI include("./X38_udf.jl") MPI.Init() # MPI initialization. Mandatory for a paralleled program using MPI. @@ -10,7 +10,8 @@ MPI.Init() # MPI initialization. Mandatory for a paralleled program using MPI. Configuration by directly construct `Configure` struct. =# solver = Solver(; - DIM = 3, NDF = 1, + DIM = 3, + NDF = 1, AMR_PS_MAXLEVEL = 4, AMR_DYNAMIC_PS_MAXLEVEL = 4, AMR_VS_MAXLEVEL = 3, @@ -18,45 +19,47 @@ solver = Solver(; VS_DYNAMIC_AMR = true, flux = CAIDVM, time_marching = CAIDVM_Marching, - max_sim_time = 20., -) -gas = Gas(; - K = 0.0, - Kn = 0.275, - ω = 0.81, - ωᵣ = 0.81, - T_ref = 273/56, + max_sim_time = 20.0, ) +gas = Gas(; K = 0.0, Kn = 0.275, ω = 0.81, ωᵣ = 0.81, T_ref = 273/56) output = Output(solver) -udf = UDF(; - dynamic_ps_refine_flag = amr_region -) -config = Configure(solver; - geometry = [-4.0,5.0,-4.0,4.0,-4.0,4.0], - trees_num = [16,16,16], - quadrature = [-14.2,21.3,-17.75,17.75,-17.75,17.75], - vs_trees_num = [10,10,10], +udf = UDF(; dynamic_ps_refine_flag = amr_region) +config = Configure( + solver; + geometry = [-4.0, 5.0, -4.0, 4.0, -4.0, 4.0], + trees_num = [16, 16, 16], + quadrature = [-14.2, 21.3, -17.75, 17.75, -17.75, 17.75], + vs_trees_num = [10, 10, 10], IC = PCoordFn(X38_buffer_IC), domain = [ - Domain(SuperSonicInflow,1, - [1.,8.0*sqrt(5/6),0.,0.,1.0]),Domain(UniformOutflow,2),Domain(UniformOutflow,3), - Domain(UniformOutflow,4),Domain(UniformOutflow,5),Domain(UniformOutflow,6) - ], - IB = [Triangles(Maxwellian,"./example/X38/X38_normalized.stl",true,1.5,[1.,0.,0.,0.,56/300])], + Domain(SuperSonicInflow, 1, [1.0, 8.0*sqrt(5/6), 0.0, 0.0, 1.0]), + Domain(UniformOutflow, 2), + Domain(UniformOutflow, 3), + Domain(UniformOutflow, 4), + Domain(UniformOutflow, 5), + Domain(UniformOutflow, 6), + ], + IB = [ + Triangles( + Maxwellian, + "./example/X38/X38_normalized.stl", + true, + 1.5, + [1.0, 0.0, 0.0, 0.0, 56/300], + ), + ], output = output, gas = gas, - user_defined = udf + user_defined = udf, ) # ---------------------------------------------------------------------------------------------------- -p4est,ka = initialize(config; prerefine_steps = 0) # Initialization for `KitAMR_Data`. +p4est, ka = initialize(config; prerefine_steps = 0) # Initialization for `KitAMR_Data`. #= Run the time-stepping loop. `max_sim_time` is set in the `Solver` above; `solve!` terminates (and lands the last step) exactly on it via `reached_max_time` / `limit_Δt!`. =# -solve!(p4est, ka; - ps_interval = 40, vs_interval = 40, partition_interval = 40) -save_result(p4est,ka) # Save converging results. -finalize!(p4est,ka) # Finalize `p4est` things. Release the memory managed by `C`. +solve!(p4est, ka; ps_interval = 40, vs_interval = 40, partition_interval = 40) +save_result(p4est, ka) # Save converging results. +finalize!(p4est, ka) # Finalize `p4est` things. Release the memory managed by `C`. MPI.Finalize() # MPI finalization. Mandatory for a paralleled program using MPI. - diff --git a/example/X38/X38_text.jl b/example/X38/X38_text.jl index da95dd4..be0f01d 100644 --- a/example/X38/X38_text.jl +++ b/example/X38/X38_text.jl @@ -1,8 +1,8 @@ -using KitAMR,MPI +using KitAMR, MPI include("./X38_udf.jl") MPI.Init() config = KitAMR.read_config("./example/X38/configure_X38.txt") -p4est,ka = KitAMR.initialize(config); +p4est, ka = KitAMR.initialize(config); KitAMR.listen_for_save!() i = 0 while !KitAMR.reached_max_time(ka) # max_sim_time is read from the config file @@ -10,7 +10,13 @@ while !KitAMR.reached_max_time(ka) # max_sim_time is read from the config file if MPI.Comm_rank(MPI.COMM_WORLD)==0 @show i end - KitAMR.adaptive_mesh_refinement!(p4est,ka;ps_interval = 40, vs_interval=40,partition_interval=40) + KitAMR.adaptive_mesh_refinement!( + p4est, + ka; + ps_interval = 40, + vs_interval = 40, + partition_interval = 40, + ) KitAMR.limit_Δt!(ka) # shrink Δt to land exactly on the next animation frame / max_sim_time KitAMR.update_slope!(ka) KitAMR.slope_exchange!(p4est, ka) @@ -20,11 +26,10 @@ while !KitAMR.reached_max_time(ka) # max_sim_time is read from the config file KitAMR.flux!(ka) KitAMR.iterate!(ka) KitAMR.data_exchange!(p4est, ka) - check_for_animsave!(p4est,ka) # write a frame if this step landed on a frame time + check_for_animsave!(p4est, ka) # write a frame if this step landed on a frame time KitAMR.check_for_convergence(ka)&&break - KitAMR.check!(p4est,ka) + KitAMR.check!(p4est, ka) end -KitAMR.save_result(p4est,ka) -KitAMR.finalize!(p4est,ka) +KitAMR.save_result(p4est, ka) +KitAMR.finalize!(p4est, ka) MPI.Finalize() - diff --git a/example/X38/X38_udf.jl b/example/X38/X38_udf.jl index aaea160..69e3922 100644 --- a/example/X38/X38_udf.jl +++ b/example/X38/X38_udf.jl @@ -1,5 +1,5 @@ using LinearAlgebra -function amr_region(ps_data,level,ka) # dynamic +function amr_region(ps_data, level, ka) # dynamic midpoint = ps_data.midpoint ds = ps_data.ds L = 1.0 @@ -8,16 +8,16 @@ function amr_region(ps_data,level,ka) # dynamic end return false end -function X38_buffer_IC(midpoint::Vector{Float64},kinfo::KInfo) +function X38_buffer_IC(midpoint::Vector{Float64}, kinfo::KInfo) ib = kinfo.config.IB[1] - Ma = 8. + Ma = 8.0 T0 = 1.0 Tw = 300/56 - _,distance = KitAMR.nn(ib.tkdt.kdt,midpoint) + _, distance = KitAMR.nn(ib.tkdt.kdt, midpoint) R = 0.3 if distance > R - return [1.0,Ma*√(5/6),0.,0.,1/T0] + return [1.0, Ma*√(5/6), 0.0, 0.0, 1/T0] else - return [1.0,distance*Ma*√(5/6)/R,0.,0.,1.0/(T0+(R-distance)*(Tw-T0)/R)] + return [1.0, distance*Ma*√(5/6)/R, 0.0, 0.0, 1.0/(T0+(R-distance)*(Tw-T0)/R)] end -end \ No newline at end of file +end diff --git a/example/X38/model_transform.jl b/example/X38/model_transform.jl index 175df7e..3922849 100644 --- a/example/X38/model_transform.jl +++ b/example/X38/model_transform.jl @@ -1,12 +1,12 @@ using FileIO, MeshIO, GeometryBasics mesh = load("./example/X38/X38-surface-fine.stl") -points = [x[i] for i in 1:3, x in mesh.position] -mins = minimum(points,dims=2) -maxes = maximum(points,dims=2) +points = [x[i] for i = 1:3, x in mesh.position] +mins = minimum(points, dims = 2) +maxes = maximum(points, dims = 2) L = maximum(maxes-mins) α = -π/9# AOA 20 degrees -Rot = [cos(α) -sin(α) 0;sin(α) cos(α) 0;0 0 1.] -normalized_points = Rot*points./L -normalized_position = [Point(x[1],x[2],x[3]) for x in eachcol(normalized_points)] -new_mesh = Mesh(normalized_position,mesh.faces) -save("./example/X38/X38_normalized.stl",new_mesh) +Rot = [cos(α) -sin(α) 0; sin(α) cos(α) 0; 0 0 1.0] +normalized_points = Rot*points ./ L +normalized_position = [Point(x[1], x[2], x[3]) for x in eachcol(normalized_points)] +new_mesh = Mesh(normalized_position, mesh.faces) +save("./example/X38/X38_normalized.stl", new_mesh) diff --git a/example/airfoil/airfoil.jl b/example/airfoil/airfoil.jl index d227e46..0ac200a 100644 --- a/example/airfoil/airfoil.jl +++ b/example/airfoil/airfoil.jl @@ -1,48 +1,50 @@ -using KitAMR,MPI +using KitAMR, MPI include("./airfoil_udf.jl") MPI.Init() solver = Solver(; - DIM = 2, NDF = 2, + DIM = 2, + NDF = 2, AMR_PS_MAXLEVEL = 7, AMR_VS_MAXLEVEL = 0, PS_DYNAMIC_AMR = false, VS_DYNAMIC_AMR = false, flux = CAIDVM, time_marching = CAIDVM_Marching, - max_sim_time = 20., + max_sim_time = 20.0, ) -gas = Gas(; - K = 1.0, - Kn = 0.026, - ω = 0.81, - ωᵣ = 0.81, -) -output = Output( +gas = Gas(; K = 1.0, Kn = 0.026, ω = 0.81, ωᵣ = 0.81) +output = Output(solver;) +udf = UDF(; static_ps_refine_flag = shock_wave_region) +config = Configure( solver; -) -udf = UDF(; - static_ps_refine_flag = shock_wave_region -) -config = Configure(solver; - geometry = [-3.,7.,-7.,7.], - trees_num = [24,32], - quadrature = [-4.,8.,-6.,6.], - vs_trees_num = [60,60], - IC = Uniform([1.,2.0*sqrt(5/6),0.,1.]), + geometry = [-3.0, 7.0, -7.0, 7.0], + trees_num = [24, 32], + quadrature = [-4.0, 8.0, -6.0, 6.0], + vs_trees_num = [60, 60], + IC = Uniform([1.0, 2.0*sqrt(5/6), 0.0, 1.0]), domain = [ - Domain(SuperSonicInflow,1,[1.,2.0*sqrt(5/6),0.,1.]), - Domain(InterpolatedOutflow,2),Domain(InterpolatedOutflow,3),Domain(InterpolatedOutflow,4) - ], - IB = [Vertices(Maxwellian,"./example/airfoil/naca0012.csv",true,4.5,[1.,0.,0.,161/290])], + Domain(SuperSonicInflow, 1, [1.0, 2.0*sqrt(5/6), 0.0, 1.0]), + Domain(InterpolatedOutflow, 2), + Domain(InterpolatedOutflow, 3), + Domain(InterpolatedOutflow, 4), + ], + IB = [ + Vertices( + Maxwellian, + "./example/airfoil/naca0012.csv", + true, + 4.5, + [1.0, 0.0, 0.0, 161/290], + ), + ], output = output, gas = gas, - user_defined = udf + user_defined = udf, ) -p4est,ka = initialize(config; prerefine_steps = 0) +p4est, ka = initialize(config; prerefine_steps = 0) solve!(p4est, ka; partition_interval = 160) -save_result(p4est,ka) -finalize!(p4est,ka) +save_result(p4est, ka) +finalize!(p4est, ka) MPI.Finalize() - diff --git a/example/airfoil/airfoil_udf.jl b/example/airfoil/airfoil_udf.jl index 20a1404..4c1c396 100644 --- a/example/airfoil/airfoil_udf.jl +++ b/example/airfoil/airfoil_udf.jl @@ -1,4 +1,4 @@ -function shock_wave_region(midpoint,ds,kinfo,level) +function shock_wave_region(midpoint, ds, kinfo, level) if midpoint[1]>-1.0&&midpoint[1]<3.0&&midpoint[2]<1.0&&midpoint[2]>-1.0&&level<4 return true end @@ -9,4 +9,4 @@ end # return true # end # return false -# end \ No newline at end of file +# end diff --git a/example/blast_wave/bw_2D.jl b/example/blast_wave/bw_2D.jl index 630b4af..5c6bad3 100644 --- a/example/blast_wave/bw_2D.jl +++ b/example/blast_wave/bw_2D.jl @@ -42,38 +42,27 @@ solver = Solver(; max_sim_time = 0.25, ) -gas = Gas(; - K = 1.0, - Kn = 1e-3, - ω = 0.81, - ωᵣ = 0.81, -) +gas = Gas(; K = 1.0, Kn = 1e-3, ω = 0.81, ωᵣ = 0.81) -output = Output( - solver; -) +output = Output(solver;) -udf = UDF(; -) +udf = UDF(;) -config = Configure(solver; +config = Configure( + solver; geometry = [0.0, 1.0, 0.0, 1.0], trees_num = [16, 16], quadrature = [-30.0, 30.0, -30.0, 30.0], vs_trees_num = [8, 8], IC = PCoordFn(blast_wave_init), - domain = [ - Domain(Period, 1), Domain(Period, 2), - Domain(Period, 3), Domain(Period, 4), - ], + domain = [Domain(Period, 1), Domain(Period, 2), Domain(Period, 3), Domain(Period, 4)], output = output, gas = gas, user_defined = udf, ) p4est, ka = initialize(config) -solve!(p4est, ka; - ps_interval = 20, vs_interval = 40, partition_interval = 40) +solve!(p4est, ka; ps_interval = 20, vs_interval = 40, partition_interval = 40) save_result(p4est, ka) finalize!(p4est, ka) MPI.Finalize() diff --git a/example/blast_wave/bw_3D.jl b/example/blast_wave/bw_3D.jl index 1303cb4..c6655bc 100644 --- a/example/blast_wave/bw_3D.jl +++ b/example/blast_wave/bw_3D.jl @@ -47,30 +47,26 @@ solver = Solver(; max_sim_time = 0.25, ) -gas = Gas(; - K = 0., - Kn = 1e-3, - ω = 0.81, - ωᵣ = 0.81, -) +gas = Gas(; K = 0.0, Kn = 1e-3, ω = 0.81, ωᵣ = 0.81) -output = Output( - solver; -) +output = Output(solver;) -udf = UDF(; -) +udf = UDF(;) -config = Configure(solver; +config = Configure( + solver; geometry = [0.0, 1.0, 0.0, 1.0, 0.0, 1.0], trees_num = [16, 16, 16], quadrature = [-32.0, 32.0, -32.0, 32.0, -32.0, 32.0], vs_trees_num = [8, 8, 8], IC = PCoordFn(blast_wave_init), domain = [ - Domain(Period, 1), Domain(Period, 2), - Domain(Period, 3), Domain(Period, 4), - Domain(Period, 5), Domain(Period, 6), + Domain(Period, 1), + Domain(Period, 2), + Domain(Period, 3), + Domain(Period, 4), + Domain(Period, 5), + Domain(Period, 6), ], output = output, gas = gas, @@ -78,8 +74,7 @@ config = Configure(solver; ) p4est, ka = initialize(config; prerefine_steps = 3, prerefine_reinit_ic = true) -solve!(p4est, ka; - ps_interval = 40, vs_interval = 40, partition_interval = 40) +solve!(p4est, ka; ps_interval = 40, vs_interval = 40, partition_interval = 40) save_result(p4est, ka) finalize!(p4est, ka) MPI.Finalize() diff --git a/example/cylinder/cylinder.jl b/example/cylinder/cylinder.jl index 89e524d..ecffd1d 100644 --- a/example/cylinder/cylinder.jl +++ b/example/cylinder/cylinder.jl @@ -1,9 +1,10 @@ -using KitAMR,MPI +using KitAMR, MPI include("./cylinder_udf.jl") MPI.Init() solver = Solver(; - DIM = 2, NDF = 2, + DIM = 2, + NDF = 2, AMR_PS_MAXLEVEL = 7, AMR_DYNAMIC_PS_MAXLEVEL = 4, AMR_VS_MAXLEVEL = 3, @@ -11,41 +12,36 @@ solver = Solver(; VS_DYNAMIC_AMR = true, flux = CAIDVM, time_marching = CAIDVM_Marching, - max_sim_time = 20., -) -gas = Gas(; - K = 1.0, - Kn = 0.1, - ω = 0.81, - ωᵣ = 0.81, -) -output = Output( - solver; + max_sim_time = 20.0, ) +gas = Gas(; K = 1.0, Kn = 0.1, ω = 0.81, ωᵣ = 0.81) +output = Output(solver;) udf = UDF(; # static_ps_refine_flag = shock_wave_region - dynamic_ps_refine_flag = amr_region + dynamic_ps_refine_flag = amr_region, ) -config = Configure(solver; - geometry = [-16.,16.,-16.,16.], - trees_num = [25,25], - quadrature = [-10.,10.,-10.,10.], - vs_trees_num = [16,16], +config = Configure( + solver; + geometry = [-16.0, 16.0, -16.0, 16.0], + trees_num = [25, 25], + quadrature = [-10.0, 10.0, -10.0, 10.0], + vs_trees_num = [16, 16], IC = PCoordFn(cylinder_buffer_IC), domain = [ - Domain(SuperSonicInflow,1,[1.,5.0*sqrt(5/6),0.,1.]),Domain(UniformOutflow,2), - Domain(UniformOutflow,3),Domain(UniformOutflow,4) - ], - IB = [Circle(Maxwellian,[0.,0.],1.,true,4.0,[1.,0.,0.,1.])], + Domain(SuperSonicInflow, 1, [1.0, 5.0*sqrt(5/6), 0.0, 1.0]), + Domain(UniformOutflow, 2), + Domain(UniformOutflow, 3), + Domain(UniformOutflow, 4), + ], + IB = [Circle(Maxwellian, [0.0, 0.0], 1.0, true, 4.0, [1.0, 0.0, 0.0, 1.0])], output = output, gas = gas, - user_defined = udf + user_defined = udf, ) -p4est,ka = initialize(config; prerefine_steps = 0); +p4est, ka = initialize(config; prerefine_steps = 0); solve!(p4est, ka; ps_interval = 40, partition_interval = 40) -save_result(p4est,ka) -finalize!(p4est,ka) +save_result(p4est, ka) +finalize!(p4est, ka) MPI.Finalize() - diff --git a/example/cylinder/cylinder_udf.jl b/example/cylinder/cylinder_udf.jl index 46be916..b2d2052 100644 --- a/example/cylinder/cylinder_udf.jl +++ b/example/cylinder/cylinder_udf.jl @@ -1,39 +1,46 @@ using LinearAlgebra -function shock_wave_region(midpoint,ds,kinfo,level) - if midpoint[1]>-5.0&&midpoint[1]<5.0&&midpoint[2]<5.0&&midpoint[2]>-5.0&&√sum(midpoint.^2)>1.0&&level<4 +function shock_wave_region(midpoint, ds, kinfo, level) + if midpoint[1]>-5.0&&midpoint[1]<5.0&&midpoint[2]<5.0&&midpoint[2]>-5.0&&√sum( + midpoint .^ 2, + )>1.0&&level<4 return true end return false end -function amr_region(ps_data,level,ka) +function amr_region(ps_data, level, ka) midpoint = ps_data.midpoint - if midpoint[1]>-5.0&&midpoint[1]<5.0&&midpoint[2]<5.0&&midpoint[2]>-5.0&&√sum(midpoint.^2)>1.0 + if midpoint[1]>-5.0&&midpoint[1]<5.0&&midpoint[2]<5.0&&midpoint[2]>-5.0&&√sum( + midpoint .^ 2, + )>1.0 return true end return false end -function cylinder_buffer_IC(midpoint::Vector{Float64},::KInfo) +function cylinder_buffer_IC(midpoint::Vector{Float64}, ::KInfo) r = norm(midpoint) Ma = 5.0 Tw = 1.0 R = 1.0 l = 1.0 # buffer length if r>R+l - return [1.0,Ma*√(5/6),0.,1.0] + return [1.0, Ma*√(5/6), 0.0, 1.0] else - return [1.0,(r-R)*Ma*√(5/6),0.,Tw-(r-R)/l*(Tw-1.0)] + return [1.0, (r-R)*Ma*√(5/6), 0.0, Tw-(r-R)/l*(Tw-1.0)] end end -function vs_output_flag(;ps_data,kwargs...) - midpoint = ps_data.midpoint;ds = ps_data.ds - tps = Vector{Vector{Float64}}(undef,5) - tps[1] = [-1.4589554070669333,0.05709202822871219];tps[2] = [-1.3786385660534994,0.05709202822871219] - tps[3] = [1.7311,3.3467];tps[4] = [-0.9037743267386753,0.45412464859673063] - tps[5] = [0.9361902761835246,0.9787846953422692] +function vs_output_flag(; ps_data, kwargs...) + midpoint = ps_data.midpoint; + ds = ps_data.ds + tps = Vector{Vector{Float64}}(undef, 5) + tps[1] = [-1.4589554070669333, 0.05709202822871219]; + tps[2] = [-1.3786385660534994, 0.05709202822871219] + tps[3] = [1.7311, 3.3467]; + tps[4] = [-0.9037743267386753, 0.45412464859673063] + tps[5] = [0.9361902761835246, 0.9787846953422692] for i in eachindex(tps) if midpoint[1]-0.5ds[1]tps[i][1]&&midpoint[2]-0.5ds[2]tps[i][2] - return i,true + return i, true end end - return 0,false -end \ No newline at end of file + return 0, false +end diff --git a/example/sphere/sphere.jl b/example/sphere/sphere.jl index f91381b..1d69c3f 100644 --- a/example/sphere/sphere.jl +++ b/example/sphere/sphere.jl @@ -1,49 +1,56 @@ -using KitAMR,MPI +using KitAMR, MPI include("./sphere_udf.jl") MPI.Init() solver = Solver(; - DIM = 3, NDF = 1, + DIM = 3, + NDF = 1, AMR_PS_MAXLEVEL = 4, AMR_VS_MAXLEVEL = 2, PS_DYNAMIC_AMR = false, VS_DYNAMIC_AMR = false, flux = CAIDVM, time_marching = CAIDVM_Marching, - max_sim_time = 20., -) -gas = Gas(; - K = 0.0, - Kn = 0.03, - ω = 0.75, - ωᵣ = 0.75, - μᵣ = 5.0*√π/16.0*0.03 + max_sim_time = 20.0, ) +gas = Gas(; K = 0.0, Kn = 0.03, ω = 0.75, ωᵣ = 0.75, μᵣ = 5.0*√π/16.0*0.03) output = Output(solver) udf = UDF(; static_ps_refine_flag = shock_wave_region, - static_vs_refine_flag = vs_refine_region + static_vs_refine_flag = vs_refine_region, ) -config = Configure(solver; - geometry = [-4.,4.,-4.,4.,-4.,4.], - trees_num = [16,16,16], - quadrature = [-7.28,7.28,-7.28,7.28,-7.28,7.28], # 3σ: 3√Ts - vs_trees_num = [16,16,16], +config = Configure( + solver; + geometry = [-4.0, 4.0, -4.0, 4.0, -4.0, 4.0], + trees_num = [16, 16, 16], + quadrature = [-7.28, 7.28, -7.28, 7.28, -7.28, 7.28], # 3σ: 3√Ts + vs_trees_num = [16, 16, 16], IC = PCoordFn(sphere_buffer_IC), domain = [ - Domain(SuperSonicInflow,1,[1.,3.834*sqrt(5/6),0.,0.,1.]), - Domain(UniformOutflow,2),Domain(UniformOutflow,3),Domain(UniformOutflow,4), - Domain(UniformOutflow,5),Domain(UniformOutflow,6) + Domain(SuperSonicInflow, 1, [1.0, 3.834*sqrt(5/6), 0.0, 0.0, 1.0]), + Domain(UniformOutflow, 2), + Domain(UniformOutflow, 3), + Domain(UniformOutflow, 4), + Domain(UniformOutflow, 5), + Domain(UniformOutflow, 6), + ], + IB = [ + Sphere( + Maxwellian, + [0.0, 0.0, 0.0], + 0.5, + true, + 1.5, + [1.0, 0.0, 0.0, 0.0, 1.0/(1.0+(5/3-1)*0.5*3.834^2)], + ), ], - IB = [Sphere(Maxwellian,[0.,0.,0.],0.5,true,1.5,[1.,0.,0.,0., 1.0/(1.0+(5/3-1)*0.5*3.834^2)])], output = output, gas = gas, - user_defined = udf + user_defined = udf, ) -p4est,ka = initialize(config; prerefine_steps = 0); +p4est, ka = initialize(config; prerefine_steps = 0); solve!(p4est, ka; vs_interval = 10, partition_interval = 40) -save_result(p4est,ka) -finalize!(p4est,ka) +save_result(p4est, ka) +finalize!(p4est, ka) MPI.Finalize() - diff --git a/example/sphere/sphere_udf.jl b/example/sphere/sphere_udf.jl index 17db4b6..0c1d3cb 100644 --- a/example/sphere/sphere_udf.jl +++ b/example/sphere/sphere_udf.jl @@ -1,36 +1,48 @@ using LinearAlgebra -function shock_wave_region(midpoint,ds,kinfo,level) +function shock_wave_region(midpoint, ds, kinfo, level) refine_level = 4 - if midpoint[1]>-1.2&&midpoint[1]<1.2&&midpoint[2]<1.2&&midpoint[2]>-1.2&&√sum(midpoint.^2)>0.5&&midpoint[3]>-1.2&&midpoint[3]<1.2&&level-1.2&&midpoint[1]<1.2&&midpoint[2]<1.2&&midpoint[2]>-1.2&&√sum( + midpoint .^ 2, + )>0.5&&midpoint[3]>-1.2&&midpoint[3]<1.2&&level-0.8&&midpoint[1]<0.8&&midpoint[2]<0.8&&midpoint[2]>-0.8&&√sum(midpoint.^2)>0.5&&midpoint[3]>-0.8&&midpoint[3]<0.8&&level-0.8&&midpoint[1]<0.8&&midpoint[2]<0.8&&midpoint[2]>-0.8&&√sum( + midpoint .^ 2, + )>0.5&&midpoint[3]>-0.8&&midpoint[3]<0.8&&level1.0 - return [1.0,Ma*√(5/6),0.,0.,1.0] + return [1.0, Ma*√(5/6), 0.0, 0.0, 1.0] else - return [1.0,(r-0.5)/(1.0-0.5)*Ma*√(5/6),0.,0.,1.0/(Tw-(r-0.5)*(Tw-1.0))] + return [1.0, (r-0.5)/(1.0-0.5)*Ma*√(5/6), 0.0, 0.0, 1.0/(Tw-(r-0.5)*(Tw-1.0))] end end -function vs_refine_region(midpoint;kwargs...) +function vs_refine_region(midpoint; kwargs...) level = kwargs[:level] du = kwargs[:du] - refine_level = 2;DIM = 3 + refine_level = 2; + DIM = 3 Ma = 3.834 Ts = 1.0+(5/3-1)*0.5*Ma^2 - U_av = [0.5*Ma*√(5/6),0.,0.] + U_av = [0.5*Ma*√(5/6), 0.0, 0.0] sn = sign.(U_av-midpoint) - midpoint_new = midpoint+0.25*du.*sn - flag1 = levelU_av[i]-2.0*sqrt(Ts)&&midpoint_new[i]U_av[i]-1.0*sqrt(Ts)&&midpoint_new[i]U_av[i]-2.0*sqrt(Ts)&&midpoint_new[i]U_av[i]-1.0*sqrt(Ts)&&midpoint_new[i]=1 calculate _>0 _<0 <ξ^4> +function moment_u_2D2F(U::T, V::Real, λ::Real, n::Integer, m::Integer, K::Real) where {T} # n>=1 calculate _>0 _<0 <ξ^4> Mu_L = Vector{T}(undef, n + 1) Mu = Vector{T}(undef, n + 1) Mu_R = Vector{T}(undef, n + 1) @inbounds begin Mu_L[1] = 0.5 * erfc(-√(λ) * U) - Mu_L[2] = - U * Mu_L[1] + 0.5 * exp(-λ * U^2) / (√(π * λ)) - Mu_R[1] = 0.5 * erfc(√(λ) * U) - Mu_R[2] = - U * Mu_R[1] - 0.5 * exp(-λ * U^2) / (√(π * λ)) - for i = 1:n-1 - Mu_L[i+2] = U * Mu_L[i+1] + 0.5 * i / λ * Mu_L[i] - Mu_R[i+2] = U * Mu_R[i+1] + 0.5 * i / λ * Mu_R[i] - end - Mu = @. Mu_L + Mu_R - Mv = Vector{T}(undef, m + 1) - Mv[1] = one(T) - Mv[2] = V - for i = 1:m-1 - Mv[i+2] = V * Mv[i+1] + 0.5 * i * Mv[i] / λ - end - Mξ2 = 0.5 * K / (λ) - Mξ4 = (K^2 + 2.0 * K) / (4.0 * λ^2) - Mξ = [one(Mξ2), Mξ2, Mξ4] - end - return (Mu, Mv, Mξ, Mu_L, Mu_R) - end - - function moment_uv_2D2F(Mu::AbstractVector{T}, Mv, Mξ, α::Integer, β::Integer, δ::Integer) where{T} # calc - Muv = Vector{T}(undef, 4) - @inbounds begin - Muv[1] = Mu[α+1] * Mv[β+1] * Mξ[Int(δ / 2 + 1)] - Muv[2] = Mu[α+2] * Mv[β+1] * Mξ[Int(δ / 2 + 1)] - Muv[3] = Mu[α+1] * Mv[β+2] * Mξ[Int(δ / 2 + 1)] - Muv[4] = - 0.5 * ( - Mu[α+3] * Mv[β+1] * Mξ[Int(δ / 2 + 1)] + - Mu[α+1] * Mv[β+3] * Mξ[Int(δ / 2 + 1)] + - Mu[α+1] * Mv[β+1] * Mξ[Int(δ / 2 + 2)] - ) - end - return Muv - end - - function moment_au_2D2F(a, Mu, Mv, Mξ, α::Integer, β::Integer)# calc - @inbounds a[1] * moment_uv_2D2F(Mu, Mv, Mξ, α, β, 0) + - a[2] * moment_uv_2D2F(Mu, Mv, Mξ, α + 1, β, 0) + - a[3] * moment_uv_2D2F(Mu, Mv, Mξ, α, β + 1, 0) + - 0.5 * a[4] * moment_uv_2D2F(Mu, Mv, Mξ, α + 2, β, 0) + - 0.5 * a[4] * moment_uv_2D2F(Mu, Mv, Mξ, α, β + 2, 0) + - 0.5 * a[4] * moment_uv_2D2F(Mu, Mv, Mξ, α, β, 2) - end + Mu_L[2] = U * Mu_L[1] + 0.5 * exp(-λ * U^2) / (√(π * λ)) + Mu_R[1] = 0.5 * erfc(√(λ) * U) + Mu_R[2] = U * Mu_R[1] - 0.5 * exp(-λ * U^2) / (√(π * λ)) + for i = 1:(n-1) + Mu_L[i+2] = U * Mu_L[i+1] + 0.5 * i / λ * Mu_L[i] + Mu_R[i+2] = U * Mu_R[i+1] + 0.5 * i / λ * Mu_R[i] + end + Mu = @. Mu_L + Mu_R + Mv = Vector{T}(undef, m + 1) + Mv[1] = one(T) + Mv[2] = V + for i = 1:(m-1) + Mv[i+2] = V * Mv[i+1] + 0.5 * i * Mv[i] / λ + end + Mξ2 = 0.5 * K / (λ) + Mξ4 = (K^2 + 2.0 * K) / (4.0 * λ^2) + Mξ = [one(Mξ2), Mξ2, Mξ4] + end + return (Mu, Mv, Mξ, Mu_L, Mu_R) +end +function moment_uv_2D2F( + Mu::AbstractVector{T}, + Mv, + Mξ, + α::Integer, + β::Integer, + δ::Integer, +) where {T} # calc + Muv = Vector{T}(undef, 4) + @inbounds begin + Muv[1] = Mu[α+1] * Mv[β+1] * Mξ[Int(δ / 2 + 1)] + Muv[2] = Mu[α+2] * Mv[β+1] * Mξ[Int(δ / 2 + 1)] + Muv[3] = Mu[α+1] * Mv[β+2] * Mξ[Int(δ / 2 + 1)] + Muv[4] = + 0.5 * ( + Mu[α+3] * Mv[β+1] * Mξ[Int(δ / 2 + 1)] + + Mu[α+1] * Mv[β+3] * Mξ[Int(δ / 2 + 1)] + + Mu[α+1] * Mv[β+1] * Mξ[Int(δ / 2 + 2)] + ) + end + return Muv +end +function moment_au_2D2F(a, Mu, Mv, Mξ, α::Integer, β::Integer)# calc + @inbounds a[1] * moment_uv_2D2F(Mu, Mv, Mξ, α, β, 0) + + a[2] * moment_uv_2D2F(Mu, Mv, Mξ, α + 1, β, 0) + + a[3] * moment_uv_2D2F(Mu, Mv, Mξ, α, β + 1, 0) + + 0.5 * a[4] * moment_uv_2D2F(Mu, Mv, Mξ, α + 2, β, 0) + + 0.5 * a[4] * moment_uv_2D2F(Mu, Mv, Mξ, α, β + 2, 0) + + 0.5 * a[4] * moment_uv_2D2F(Mu, Mv, Mξ, α, β, 2) +end diff --git a/lib/KitCore/3D.jl b/lib/KitCore/3D.jl index c999206..e8ecdf9 100644 --- a/lib/KitCore/3D.jl +++ b/lib/KitCore/3D.jl @@ -15,7 +15,8 @@ function get_prim_3D(w::AbstractVector, γ::Real) @inbounds prim[2] = w[2] / w[1] @inbounds prim[3] = w[3] / w[1] @inbounds prim[4] = w[4] / w[1] - @inbounds prim[5] = 0.5 * w[1] / (γ - 1.0) / (w[5] - 0.5 * (w[2]^2 + w[3]^2 + w[4]^2) / w[1]) + @inbounds prim[5] = + 0.5 * w[1] / (γ - 1.0) / (w[5] - 0.5 * (w[2]^2 + w[3]^2 + w[4]^2) / w[1]) return prim end function micro_slope_3D(sw::AbstractVector{T}, prim::AbstractVector, K::Real) where {T} @@ -34,8 +35,8 @@ function micro_slope_3D(sw::AbstractVector{T}, prim::AbstractVector, K::Real) wh 0.5 * (prim[2]^2 + prim[3]^2 + prim[4]^2 + 0.5 * (K + 3.0) / prim[5]) * a[5] return a end -function pressure_3D(u::AbstractVector{T},v,w,h,weight) where{T} - p = Vector{T}(undef,6) +function pressure_3D(u::AbstractVector{T}, v, w, h, weight) where {T} + p = Vector{T}(undef, 6) p[1] = sum(@. u^2*h*weight) # p11 p[2] = sum(@. u*v*h*weight) # p12 p[3] = sum(@.u*w*h*weight) # p13 @@ -43,4 +44,4 @@ function pressure_3D(u::AbstractVector{T},v,w,h,weight) where{T} p[5] = sum(@. v*w*h*weight) # p23 p[6] = sum(@. w^2*h*weight) # p33 return p -end \ No newline at end of file +end diff --git a/lib/KitCore/3D1F.jl b/lib/KitCore/3D1F.jl index 8c3ba45..3de3d68 100644 --- a/lib/KitCore/3D1F.jl +++ b/lib/KitCore/3D1F.jl @@ -4,22 +4,17 @@ function discrete_maxwell_3D1F( w::AbstractVector, prim::AbstractVector, ) where {T} - M = Matrix{T}(undef, length(u),1) + M = Matrix{T}(undef, length(u), 1) @inbounds @. M = prim[1] * (prim[5] / π)^(3 / 2) * exp(-prim[5] * ((u - prim[2])^2 + (v - prim[3])^2 + (w - prim[4])^2)) return M end -function discrete_maxwell_3D1F( - u::Real, - v::Real, - w::Real, - prim::AbstractVector, -) - prim[1] * - (prim[5] / π)^(3 / 2) * - exp(-prim[5] * ((u - prim[2])^2 + (v - prim[3])^2 + (w - prim[4])^2)) +function discrete_maxwell_3D1F(u::Real, v::Real, w::Real, prim::AbstractVector) + prim[1] * + (prim[5] / π)^(3 / 2) * + exp(-prim[5] * ((u - prim[2])^2 + (v - prim[3])^2 + (w - prim[4])^2)) end function shakhov_part_3D1F( u::AbstractVector{T}, @@ -30,7 +25,7 @@ function shakhov_part_3D1F( qf::AbstractVector, Pr::Real, ) where {T} - M⁺ = Matrix{T}(undef, length(u),1) + M⁺ = Matrix{T}(undef, length(u), 1) @inbounds @. M⁺ = 0.8 * (1 - Pr) * prim[5]^2 / prim[1] * ((u - prim[2]) * qf[1] + (v - prim[3]) * qf[2] + (w - prim[4]) * qf[3]) * @@ -45,7 +40,7 @@ function heat_flux_3D1F( h::AbstractVector, prim::AbstractVector, weight::AbstractVector, -) where{T} +) where {T} q = Vector{T}(undef, 3) @inbounds q[1] = 0.5 * (sum( @@ -122,18 +117,24 @@ function micro_to_macro_3D1F( return W end -function moment_u_3D1F(U::T,V::Real,W::Real,λ::Real,n::Integer,m::Integer,δ::Integer) where{T} # n>=1 calculate _>0 _<0 +function moment_u_3D1F( + U::T, + V::Real, + W::Real, + λ::Real, + n::Integer, + m::Integer, + δ::Integer, +) where {T} # n>=1 calculate _>0 _<0 Mu_L = Vector{T}(undef, n + 1) Mu = Vector{T}(undef, n + 1) Mu_R = Vector{T}(undef, n + 1) @inbounds begin Mu_L[1] = 0.5 * erfc(-√(λ) * U) - Mu_L[2] = - U * Mu_L[1] + 0.5 * exp(-λ * U^2) / (√(π * λ)) + Mu_L[2] = U * Mu_L[1] + 0.5 * exp(-λ * U^2) / (√(π * λ)) Mu_R[1] = 0.5 * erfc(√(λ) * U) - Mu_R[2] = - U * Mu_R[1] - 0.5 * exp(-λ * U^2) / (√(π * λ)) - for i = 1:n-1 + Mu_R[2] = U * Mu_R[1] - 0.5 * exp(-λ * U^2) / (√(π * λ)) + for i = 1:(n-1) Mu_L[i+2] = U * Mu_L[i+1] + 0.5 * i / λ * Mu_L[i] Mu_R[i+2] = U * Mu_R[i+1] + 0.5 * i / λ * Mu_R[i] end @@ -141,20 +142,27 @@ function moment_u_3D1F(U::T,V::Real,W::Real,λ::Real,n::Integer,m::Integer,δ::I Mv = Vector{T}(undef, m + 1) Mv[1] = one(T) Mv[2] = V - for i = 1:m-1 + for i = 1:(m-1) Mv[i+2] = V * Mv[i+1] + 0.5 * i * Mv[i] / λ end Mw = Vector{T}(undef, δ + 1) Mw[1] = one(T) Mw[2] = W - for i = 1:δ-1 + for i = 1:(δ-1) Mw[i+2] = W * Mw[i+1] + 0.5 * i * Mw[i] / λ end end return (Mu, Mv, Mw, Mu_L, Mu_R) end -function moment_uv_3D1F(Mu::AbstractVector{T},Mv,Mw,α::Integer, β::Integer, δ::Integer) where{T}# calc +function moment_uv_3D1F( + Mu::AbstractVector{T}, + Mv, + Mw, + α::Integer, + β::Integer, + δ::Integer, +) where {T}# calc Muv = Vector{T}(undef, 5) @inbounds begin Muv[1] = Mu[α+1] * Mv[β+1] * Mw[δ+1] @@ -180,4 +188,3 @@ function moment_au_3D1F(a, Mu, Mv, Mw, α::Integer, β::Integer, δ::Integer)# c 0.5 * a[5] * moment_uv_3D1F(Mu, Mv, Mw, α, β + 2, δ) + 0.5 * a[5] * moment_uv_3D1F(Mu, Mv, Mw, α, β, δ + 2) end - diff --git a/lib/KitCore/KitCore.jl b/lib/KitCore/KitCore.jl index 4a48ee6..66ad314 100644 --- a/lib/KitCore/KitCore.jl +++ b/lib/KitCore/KitCore.jl @@ -1,21 +1,21 @@ module KitCore - using SpecialFunctions - using ExportAll - include("2D.jl") - include("2D2F.jl") - include("3D.jl") - include("3D1F.jl") - function time_int(τ::T, Δt)where{T} - Mt = Vector{T}(undef, 5) - @inbounds begin - Mt[4] = τ * (1.0 - exp(-Δt / τ)) - Mt[5] = -τ * Δt * exp(-Δt / τ) + τ * Mt[4] - Mt[1] = Δt - Mt[4] - Mt[2] = -τ * Mt[1] + Mt[5] - Mt[3] = 0.5 * Δt^2 - τ * Mt[1] - end - return Mt +using SpecialFunctions +using ExportAll +include("2D.jl") +include("2D2F.jl") +include("3D.jl") +include("3D1F.jl") +function time_int(τ::T, Δt) where {T} + Mt = Vector{T}(undef, 5) + @inbounds begin + Mt[4] = τ * (1.0 - exp(-Δt / τ)) + Mt[5] = -τ * Δt * exp(-Δt / τ) + τ * Mt[4] + Mt[1] = Δt - Mt[4] + Mt[2] = -τ * Mt[1] + Mt[5] + Mt[3] = 0.5 * Δt^2 - τ * Mt[1] end - - @exportAll() + return Mt +end + +@exportAll() end # module KitCore diff --git a/src/Abstract/Types.jl b/src/Abstract/Types.jl index 3e986ac..dffc28c 100644 --- a/src/Abstract/Types.jl +++ b/src/Abstract/Types.jl @@ -5,40 +5,88 @@ const SOLID_CELL_ID_NUM = 8 const BALANCE_FLAG = 127 const face_num_2d = 4 const face_num_3d = 6 -const WLST = [6,10] -const RFT = [[],[[2, 4], [1, 4], [3, 2], [1, 3]],[[-1,-1,-1],[1,-1,-1],[-1,1,-1],[1,1,-1],[-1,-1,1],[1,-1,1],[-1,1,1],[1,1,1]]] # refine face table -const RMT = [[],[[-1, -1], [1, -1], [-1, 1], [1, 1]],[[-1,-1,-1],[1,-1,-1],[-1,1,-1],[1,1,-1],[-1,-1,1],[1,-1,1],[-1,1,1],[1,1,1]]] # refine midpoint table -const ANTIVT = [[],[[-1, -1], [1, -1], [1, 1], [-1, 1]],[[-1,-1,-1],[1,-1,-1],[-1,1,-1],[1,1,-1],[-1,-1,1],[1,-1,1],[-1,1,1],[1,1,1]]] # anticlock vertices table -const NMT = [[],[[-1,0],[1,0],[0,-1],[0,1]],[[-1,0,0],[1,0,0],[0,-1,0],[0,1,0],[0,0,-1],[0,0,1]]] # neighbor midpoint table -const FAT = [[2,1],[[2,3],[1,3],[1,2]]]# face area table -const CLP = [1,3,5,7] # Vertices' indices in cut_rect -const CTN = [[],[[1,3],[2,3],[1,4],[2,4]],[]] # Corner target neighbor DIM{Corner_id{possible faces}} -const pxest_ts = [p4est_t,p8est_t] -const pxest_quadrant_ts = [p4est_quadrant_t,p8est_quadrant_t] -const pxest_ghost_ts = [p4est_ghost_t,p8est_ghost_t] -const pxest_mesh_ts = [p4est_mesh_t,p8est_mesh_t] -const pxest_iter_volume_info_ts = [p4est_iter_volume_info_t,p8est_iter_volume_info_t] -const pxest_iter_face_info_ts = [p4est_iter_face_info_t,p8est_iter_face_info_t] -const pxest_iter_face_side_ts = [p4est_iter_face_side_t,p8est_iter_face_side_t] +const WLST = [6, 10] +const RFT = [ + [], + [[2, 4], [1, 4], [3, 2], [1, 3]], + [ + [-1, -1, -1], + [1, -1, -1], + [-1, 1, -1], + [1, 1, -1], + [-1, -1, 1], + [1, -1, 1], + [-1, 1, 1], + [1, 1, 1], + ], +] # refine face table +const RMT = [ + [], + [[-1, -1], [1, -1], [-1, 1], [1, 1]], + [ + [-1, -1, -1], + [1, -1, -1], + [-1, 1, -1], + [1, 1, -1], + [-1, -1, 1], + [1, -1, 1], + [-1, 1, 1], + [1, 1, 1], + ], +] # refine midpoint table +const ANTIVT = [ + [], + [[-1, -1], [1, -1], [1, 1], [-1, 1]], + [ + [-1, -1, -1], + [1, -1, -1], + [-1, 1, -1], + [1, 1, -1], + [-1, -1, 1], + [1, -1, 1], + [-1, 1, 1], + [1, 1, 1], + ], +] # anticlock vertices table +const NMT = [ + [], + [[-1, 0], [1, 0], [0, -1], [0, 1]], + [[-1, 0, 0], [1, 0, 0], [0, -1, 0], [0, 1, 0], [0, 0, -1], [0, 0, 1]], +] # neighbor midpoint table +const FAT = [[2, 1], [[2, 3], [1, 3], [1, 2]]]# face area table +const CLP = [1, 3, 5, 7] # Vertices' indices in cut_rect +const CTN = [[], [[1, 3], [2, 3], [1, 4], [2, 4]], []] # Corner target neighbor DIM{Corner_id{possible faces}} +const pxest_ts = [p4est_t, p8est_t] +const pxest_quadrant_ts = [p4est_quadrant_t, p8est_quadrant_t] +const pxest_ghost_ts = [p4est_ghost_t, p8est_ghost_t] +const pxest_mesh_ts = [p4est_mesh_t, p8est_mesh_t] +const pxest_iter_volume_info_ts = [p4est_iter_volume_info_t, p8est_iter_volume_info_t] +const pxest_iter_face_info_ts = [p4est_iter_face_info_t, p8est_iter_face_info_t] +const pxest_iter_face_side_ts = [p4est_iter_face_side_t, p8est_iter_face_side_t] pxest_t = Union{p4est_t,p8est_t} pxest_ghost_t = Union{p4est_ghost_t,p8est_ghost_t} pxest_mesh_t = Union{p4est_mesh_t,p8est_mesh_t} -P_pxest_t = Union{Ptr{p4est_t}, Ptr{p8est_t}} -P_pxest_ghost_t = Union{Ptr{p4est_ghost_t}, Ptr{p8est_ghost_t}} -P_pxest_mesh_t = Union{Ptr{p4est_mesh_t}, Ptr{p8est_mesh_t}} -P_pxest_quadrant_t = Union{Ptr{p4est_quadrant_t}, Ptr{p8est_quadrant_t}} -P_pxest_iter_volume_info_t = Union{Ptr{p4est_iter_volume_info_t}, Ptr{p8est_iter_volume_info_t}} -P_pxest_iter_face_info_t = Union{Ptr{p4est_iter_face_info_t}, Ptr{p8est_iter_face_info_t}} +P_pxest_t = Union{Ptr{p4est_t},Ptr{p8est_t}} +P_pxest_ghost_t = Union{Ptr{p4est_ghost_t},Ptr{p8est_ghost_t}} +P_pxest_mesh_t = Union{Ptr{p4est_mesh_t},Ptr{p8est_mesh_t}} +P_pxest_quadrant_t = Union{Ptr{p4est_quadrant_t},Ptr{p8est_quadrant_t}} +P_pxest_iter_volume_info_t = + Union{Ptr{p4est_iter_volume_info_t},Ptr{p8est_iter_volume_info_t}} +P_pxest_iter_face_info_t = Union{Ptr{p4est_iter_face_info_t},Ptr{p8est_iter_face_info_t}} -PW_pxest_t = Union{PointerWrapper{p4est_t}, PointerWrapper{p8est_t}} -PW_pxest_ghost_t = Union{PointerWrapper{p4est_ghost_t}, PointerWrapper{p8est_ghost_t}} -PW_pxest_mesh_t = Union{PointerWrapper{p4est_mesh_t}, PointerWrapper{p8est_mesh_t}} -PW_pxest_quadrant_t = Union{PointerWrapper{p4est_quadrant_t}, PointerWrapper{p8est_quadrant_t}} -PW_pxest_iter_volume_info_t = Union{PointerWrapper{p4est_iter_volume_info_t}, PointerWrapper{p8est_iter_volume_info_t}} -PW_pxest_iter_face_info_t = Union{PointerWrapper{p4est_iter_face_info_t},PointerWrapper{p8est_iter_face_info_t}} -PW_pxest_iter_face_side_t = Union{PointerWrapper{p4est_iter_face_side_t},PointerWrapper{p8est_iter_face_side_t}} +PW_pxest_t = Union{PointerWrapper{p4est_t},PointerWrapper{p8est_t}} +PW_pxest_ghost_t = Union{PointerWrapper{p4est_ghost_t},PointerWrapper{p8est_ghost_t}} +PW_pxest_mesh_t = Union{PointerWrapper{p4est_mesh_t},PointerWrapper{p8est_mesh_t}} +PW_pxest_quadrant_t = + Union{PointerWrapper{p4est_quadrant_t},PointerWrapper{p8est_quadrant_t}} +PW_pxest_iter_volume_info_t = + Union{PointerWrapper{p4est_iter_volume_info_t},PointerWrapper{p8est_iter_volume_info_t}} +PW_pxest_iter_face_info_t = + Union{PointerWrapper{p4est_iter_face_info_t},PointerWrapper{p8est_iter_face_info_t}} +PW_pxest_iter_face_side_t = + Union{PointerWrapper{p4est_iter_face_side_t},PointerWrapper{p8est_iter_face_side_t}} """ $(TYPEDEF) @@ -93,7 +141,7 @@ const MicroFlux = Union{DVM} const HybridFlux = Union{UGKS,CAIDVM} # to add more... -abstract type Euler <:AbstractTimeMarchingType end +abstract type Euler <: AbstractTimeMarchingType end abstract type UGKS_Marching<:AbstractTimeMarchingType end abstract type CIP_Marching<:AbstractTimeMarchingType end """ @@ -167,7 +215,8 @@ include("../Boundary/Types.jl") include("../Solver/Types.jl") include("../IO/Types.jl") -export SuperSonicInflow, SuperSonicOutflow, UniformOutflow, InterpolatedOutflow, Period, Maxwellian +export SuperSonicInflow, + SuperSonicOutflow, UniformOutflow, InterpolatedOutflow, Period, Maxwellian export AbstractInitCond, AbstractBoundCond, AbstractBoundary export Pixel, Voxel, Triangle, Tetra export AbstractPsData, AbstractFace diff --git a/src/Boundary/AMR.jl b/src/Boundary/AMR.jl index 71229e8..839a137 100644 --- a/src/Boundary/AMR.jl +++ b/src/Boundary/AMR.jl @@ -2,7 +2,7 @@ AMR for boundaries, especially for immersed boundaries. =# -function solid_static_refine_flag(forest,which_tree,quadrant)::Cint +function solid_static_refine_flag(forest, which_tree, quadrant)::Cint GC.@preserve forest which_tree quadrant begin fp = PointerWrapper(forest) ka = unsafe_pointer_to_objref(pointer(fp.user_pointer)) @@ -13,7 +13,7 @@ function solid_static_refine_flag(forest,which_tree,quadrant)::Cint ps_data.bound_enc<0 && return Cint(1) for i in eachindex(ibs) ib = ibs[i] - if search_radius_flag(ib,ps_data.midpoint,ps_data.ds) + if search_radius_flag(ib, ps_data.midpoint, ps_data.ds) ps_data.bound_enc = i return Cint(1) end @@ -21,30 +21,49 @@ function solid_static_refine_flag(forest,which_tree,quadrant)::Cint return Cint(0) end end -function solid_static_coarsen_flag(forest::Ptr{p8est_t},which_tree,quadrants)::Cint +function solid_static_coarsen_flag(forest::Ptr{p8est_t}, which_tree, quadrants)::Cint GC.@preserve forest which_tree quadrants begin DIM = 3 quadrants_wrap = unsafe_wrap(Vector{Ptr{p8est_quadrant_t}}, quadrants, 2^DIM) - for i = 1:2^DIM + for i = 1:(2^DIM) qp = PointerWrapper(quadrants_wrap[i]) dp = PointerWrapper(P4estPsData, qp.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - !isa(ps_data,InsideSolidData)&&return Cint(0) + !isa(ps_data, InsideSolidData)&&return Cint(0) end return Cint(1) end end -function solid_static_replace!(forest,which_tree,num_out,out_quads::Ptr{T},num_in,in_quads)::Cvoid where{T} +function solid_static_replace!( + forest, + which_tree, + num_out, + out_quads::Ptr{T}, + num_in, + in_quads, +)::Cvoid where {T} GC.@preserve forest which_tree num_out out_quads num_in in_quads begin fp = PointerWrapper(forest) ka = unsafe_pointer_to_objref(pointer(fp.user_pointer)) out_quads_wrap = unsafe_wrap(Vector{T}, out_quads, num_out) in_quads_wrap = unsafe_wrap(Vector{T}, in_quads, num_in) - solid_static_replace!(Val(Int(num_out)),out_quads_wrap,in_quads_wrap,which_tree,ka) + solid_static_replace!( + Val(Int(num_out)), + out_quads_wrap, + in_quads_wrap, + which_tree, + ka, + ) return nothing end end -function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{DIM,NDF}) where{DIM,NDF}# refine replace +function solid_static_replace!( + ::Val{1}, + out_quad, + in_quads, + which_tree, + ka::KA{DIM,NDF}, +) where {DIM,NDF}# refine replace fp = PointerWrapper(ka.kinfo.forest.p4est) trees = ka.kdata.field.trees treeid = Int(which_tree) - trees.offset @@ -55,19 +74,19 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ ) index = findfirst(x -> x === Odata, datas) deleteat!(datas, index) - if isa(Odata,InsideSolidData) # + if isa(Odata, InsideSolidData) # ib = ka.kinfo.config.IB[-Odata.bound_enc] - for i = 1:2^DIM + for i = 1:(2^DIM) pw_in_quad = PointerWrapper(in_quads[i]) dp = PointerWrapper(P4estPsData, pw_in_quad.p.user_data[]) # ds = Odata.ds*0.5 # midpoint = Odata.midpoint+ 0.5 * ds .* RMT[DIM][i] - ds,midpoint = quad_to_cell(fp,which_tree,pw_in_quad) - if ghost_cell_flag(ib,midpoint,ds) # New born ghost cell - ps_data = PsData(DIM,NDF;bound_enc = Odata.bound_enc,midpoint,ds) - ps_data.vs_data = initialize_solid_vs_data(ib,ka.kinfo) + ds, midpoint = quad_to_cell(fp, which_tree, pw_in_quad) + if ghost_cell_flag(ib, midpoint, ds) # New born ghost cell + ps_data = PsData(DIM, NDF; bound_enc = Odata.bound_enc, midpoint, ds) + ps_data.vs_data = initialize_solid_vs_data(ib, ka.kinfo) else - ps_data = InsideSolidData{DIM,NDF}(Odata.bound_enc,midpoint,ds) + ps_data = InsideSolidData{DIM,NDF}(Odata.bound_enc, midpoint, ds) end insert!(datas, index - 1 + i, ps_data) dp[] = P4estPsData(pointer_from_objref(ps_data)) @@ -75,16 +94,16 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ elseif Odata.bound_enc<0 ib = ka.kinfo.config.IB[-Odata.bound_enc] flag = Odata.neighbor.state[1]==BALANCE_FLAG - for i = 1:2^DIM + for i = 1:(2^DIM) pw_in_quad = PointerWrapper(in_quads[i]) dp = PointerWrapper(P4estPsData, pw_in_quad.p.user_data[]) if flag # Balance flag ps_data = Odata.neighbor.data[1][i] else # Not-a-balance ds = Odata.ds*0.5 - midpoint = @. Odata.midpoint+ 0.5 * ds * RMT[DIM][i] - if solid_flag(ib,midpoint) # Inside solid - if ghost_cell_flag(ib,midpoint,ds) + midpoint = @. Odata.midpoint + 0.5 * ds * RMT[DIM][i] + if solid_flag(ib, midpoint) # Inside solid + if ghost_cell_flag(ib, midpoint, ds) ps_data = ps_copy(Odata) ps_data.bound_enc = Odata.bound_enc ps_data.ds .*= 0.5 @@ -95,7 +114,7 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ ps_data.neighbor.data[2] = [Odata] end else - ps_data = InsideSolidData{DIM,NDF}(Odata.bound_enc,midpoint,ds) + ps_data = InsideSolidData{DIM,NDF}(Odata.bound_enc, midpoint, ds) end else # fluid cell ps_data = ps_copy(Odata) @@ -103,13 +122,20 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ ps_data.ds .*= 0.5 vs_data = ps_data.vs_data @. ps_data.midpoint += 0.5 * ps_data.ds * RMT[DIM][i] - for k in axes(vs_data.df,2) - for j in axes(vs_data.df,1) - @views vs_data.df[j,k]+=min(abs(vs_data.df[j,k]/(0.5*dot(ps_data.ds,abs.(vs_data.sdf[j,k,:]))+EPS)),1.)*dot(vs_data.sdf[j,k,:],0.5 * ps_data.ds .* RMT[DIM][i]) + for k in axes(vs_data.df, 2) + for j in axes(vs_data.df, 1) + @views vs_data.df[j, k]+=min( + abs( + vs_data.df[j, k]/( + 0.5*dot(ps_data.ds, abs.(vs_data.sdf[j, k, :]))+EPS + ), + ), + 1.0, + )*dot(vs_data.sdf[j, k, :], 0.5 * ps_data.ds .* RMT[DIM][i]) end end ps_data.w = calc_w0(ps_data) - ps_data.prim = get_prim(ps_data.w,ka.kinfo) + ps_data.prim = get_prim(ps_data.w, ka.kinfo) if i==1 ps_data.neighbor.state[2] = BALANCE_FLAG ps_data.neighbor.data[2] = [Odata] @@ -121,7 +147,7 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ end elseif Odata.bound_enc==0 # Outside search radius flag = Odata.neighbor.state[1]==BALANCE_FLAG - for i = 1:2^DIM + for i = 1:(2^DIM) pw_in_quad = PointerWrapper(in_quads[i]) dp = PointerWrapper(P4estPsData, pw_in_quad.p.user_data[]) if flag @@ -131,13 +157,20 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ ps_data.ds .*= 0.5 vs_data = ps_data.vs_data @. ps_data.midpoint += 0.5 * ps_data.ds * RMT[DIM][i] - for k in axes(vs_data.df,2) - for j in axes(vs_data.df,1) - @views vs_data.df[j,k]+=min(abs(vs_data.df[j,k]/(0.5*dot(ps_data.ds,abs.(vs_data.sdf[j,k,:]))+EPS)),1.)*dot(vs_data.sdf[j,k,:],0.5 * ps_data.ds .* RMT[DIM][i]) + for k in axes(vs_data.df, 2) + for j in axes(vs_data.df, 1) + @views vs_data.df[j, k]+=min( + abs( + vs_data.df[j, k]/( + 0.5*dot(ps_data.ds, abs.(vs_data.sdf[j, k, :]))+EPS + ), + ), + 1.0, + )*dot(vs_data.sdf[j, k, :], 0.5 * ps_data.ds .* RMT[DIM][i]) end end ps_data.w = calc_w0(ps_data) - ps_data.prim = get_prim(ps_data.w,ka.kinfo) + ps_data.prim = get_prim(ps_data.w, ka.kinfo) if i==1 ps_data.neighbor.state[2] = BALANCE_FLAG ps_data.neighbor.data[2] = [Odata] @@ -149,16 +182,16 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ else # Inside search radius flag = Odata.neighbor.state[1]==BALANCE_FLAG ib = ka.kinfo.config.IB[Odata.bound_enc] - for i = 1:2^DIM + for i = 1:(2^DIM) pw_in_quad = PointerWrapper(in_quads[i]) dp = PointerWrapper(P4estPsData, pw_in_quad.p.user_data[]) if flag ps_data = Odata.neighbor.data[1][i] else ds = Odata.ds*0.5 - midpoint = @. Odata.midpoint+ 0.5 * ds * RMT[DIM][i] - if solid_flag(ib,midpoint) # Inside solid - if ghost_cell_flag(ib,midpoint,ds) + midpoint = @. Odata.midpoint + 0.5 * ds * RMT[DIM][i] + if solid_flag(ib, midpoint) # Inside solid + if ghost_cell_flag(ib, midpoint, ds) ps_data = ps_copy(Odata) ps_data.bound_enc = -Odata.bound_enc ps_data.ds .*= 0.5 @@ -169,7 +202,7 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ ps_data.neighbor.data[2] = [Odata] end else - ps_data = InsideSolidData{DIM,NDF}(-Odata.bound_enc,midpoint,ds) + ps_data = InsideSolidData{DIM,NDF}(-Odata.bound_enc, midpoint, ds) end else ps_data = ps_copy(Odata) @@ -177,13 +210,20 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ ps_data.ds .*= 0.5 vs_data = ps_data.vs_data @. ps_data.midpoint += 0.5 * ps_data.ds * RMT[DIM][i] - for k in axes(vs_data.df,2) - for j in axes(vs_data.df,1) - @views vs_data.df[j,k]+=min(abs(vs_data.df[j,k]/(0.5*dot(ps_data.ds,abs.(vs_data.sdf[j,k,:]))+EPS)),1.)*dot(vs_data.sdf[j,k,:],0.5 * ps_data.ds .* RMT[DIM][i]) + for k in axes(vs_data.df, 2) + for j in axes(vs_data.df, 1) + @views vs_data.df[j, k]+=min( + abs( + vs_data.df[j, k]/( + 0.5*dot(ps_data.ds, abs.(vs_data.sdf[j, k, :]))+EPS + ), + ), + 1.0, + )*dot(vs_data.sdf[j, k, :], 0.5 * ps_data.ds .* RMT[DIM][i]) end end ps_data.w = calc_w0(ps_data) - ps_data.prim = get_prim(ps_data.w,ka.kinfo) + ps_data.prim = get_prim(ps_data.w, ka.kinfo) if i==1 ps_data.neighbor.state[2] = BALANCE_FLAG ps_data.neighbor.data[2] = [Odata] @@ -197,54 +237,61 @@ function solid_static_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{ return nothing end -function solid_static_replace!(::ChildNum, out_quad, in_quads, which_tree, ka::KA{DIM,NDF}) where{DIM,NDF} # coarsen replace, average or interpolate? Currently interpolation strategy is adopted. If my memory serves me right, problems came out with average most likely due to the iterative balance process. +function solid_static_replace!( + ::ChildNum, + out_quad, + in_quads, + which_tree, + ka::KA{DIM,NDF}, +) where {DIM,NDF} # coarsen replace, average or interpolate? Currently interpolation strategy is adopted. If my memory serves me right, problems came out with average most likely due to the iterative balance process. trees = ka.kdata.field.trees treeid = Int(which_tree) - trees.offset datas = trees.data[treeid] pw_in_quad = PointerWrapper(in_quads[1]) dp = PointerWrapper(P4estPsData, pw_in_quad.p.user_data[]) Odatas = Vector{AbstractPsData{DIM,NDF}}(undef, 2^DIM) - for i = 1:2^DIM + for i = 1:(2^DIM) pw_out_quad = PointerWrapper(out_quad[i]) Odatas[i] = unsafe_pointer_to_objref( pointer(PointerWrapper(P4estPsData, pw_out_quad.p.user_data[]).ps_data), ) end ds = Odatas[1].ds*2.0 - midpoint = Odatas[1].midpoint-0.5*Odatas[1].ds.*RMT[DIM][1] - if all(x->isa(x,InsideSolidData),Odatas) - ps_data = InsideSolidData{DIM,NDF}(Odatas[1].bound_enc,midpoint,ds) + midpoint = Odatas[1].midpoint-0.5*Odatas[1].ds .* RMT[DIM][1] + if all(x->isa(x, InsideSolidData), Odatas) + ps_data = InsideSolidData{DIM,NDF}(Odatas[1].bound_enc, midpoint, ds) else if Odatas[1].neighbor.state[2]==BALANCE_FLAG ps_data = first(Odatas[1].neighbor.data[2]) else - _,index = findmin([x.vs_data.vs_num for x in Odatas]) - ps_data = ps_merge(Odatas,index,ka.kinfo) + _, index = findmin([x.vs_data.vs_num for x in Odatas]) + ps_data = ps_merge(Odatas, index, ka.kinfo) vs_data = ps_data.vs_data for i in eachindex(Odatas) vs_data_n = Odatas[i].vs_data - vs_merge!(vs_data.sdf,vs_data_n.sdf,vs_data.level,vs_data_n.level,ka) - vs_merge!(vs_data.df,vs_data_n.df,vs_data.level,vs_data_n.level,ka) + vs_merge!(vs_data.sdf, vs_data_n.sdf, vs_data.level, vs_data_n.level, ka) + vs_merge!(vs_data.df, vs_data_n.df, vs_data.level, vs_data_n.level, ka) end - vs_data.df./=2^DIM;vs_data.sdf./=2^DIM + vs_data.df./=2^DIM; + vs_data.sdf./=2^DIM ps_data.neighbor.state[1] = BALANCE_FLAG ps_data.neighbor.data[1] = Odatas end end index = findfirst(x -> x === Odatas[1], datas) - deleteat!(datas, index:index+2^DIM-1) + deleteat!(datas, index:(index+2^DIM-1)) insert!(datas, index, ps_data) dp[] = P4estPsData(pointer_from_objref(ps_data)) return nothing end -function initialize_solid_vs_data(ib::AbstractBoundary,kinfo::KInfo) +function initialize_solid_vs_data(ib::AbstractBoundary, kinfo::KInfo) prim = get_bc(ib.bc) - return initialize_vs_data(prim,kinfo) + return initialize_vs_data(prim, kinfo) end """ $(SIGNATURES) -Refine grids at original position of the immersed boundaries. The main purpose of the functionality is to obtain +Refine grids at original position of the immersed boundaries. The main purpose of the functionality is to obtain high-resolution field from a fast-obtained coarsener field. """ function solid_static_refine!(ka::KA{3}) @@ -253,9 +300,9 @@ function solid_static_refine!(ka::KA{3}) trees = ka.kdata.field.trees.data for tree in trees for ps_data in tree - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue if ps_data.bound_enc<0 - filter_solid_cell!(ps_data,ka) + filter_solid_cell!(ps_data, ka) end end end @@ -277,13 +324,13 @@ function solid_static_refine!(ka::KA{3}) ) ) GC.@preserve c_refine_flag_fn c_replace_fn p8est_refine_ext( - p4est, - 1, - kinfo.config.solver.AMR_PS_MAXLEVEL, - c_refine_flag_fn, - C_NULL, - c_replace_fn - ) + p4est, + 1, + kinfo.config.solver.AMR_PS_MAXLEVEL, + c_refine_flag_fn, + C_NULL, + c_replace_fn, + ) c_coarsen_flag_fn = @cfunction( $solid_static_coarsen_flag, @@ -296,22 +343,22 @@ function solid_static_refine!(ka::KA{3}) 0, c_coarsen_flag_fn, C_NULL, - c_replace_fn + c_replace_fn, ) GC.@preserve c_replace_fn p8est_balance_ext( p4est, P8EST_CONNECT_FULL, C_NULL, - c_replace_fn + c_replace_fn, ) for tree in trees for ps_data in tree - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue if ps_data.bound_enc>0 ps_data.bound_enc = 0 end end end return nothing -end \ No newline at end of file +end diff --git a/src/Boundary/Boundary.jl b/src/Boundary/Boundary.jl index cf618ca..777d263 100644 --- a/src/Boundary/Boundary.jl +++ b/src/Boundary/Boundary.jl @@ -14,14 +14,14 @@ export initialize_immersed_boundaries! export solid_exchange!, solid_exchange_begin!, solid_exchange_finish! -function overlap_test(lower,upper,hyper_rec::HyperRectangle{SVector{N,Float64}}) where N +function overlap_test(lower, upper, hyper_rec::HyperRectangle{SVector{N,Float64}}) where {N} for i = 1:N - (upper[i]hyper_rec.maxes[i])&& return false + (upper[i]hyper_rec.maxes[i]) && return false end return true end -get_bc(bc::AbstractVector;kwargs...) = copy(bc) -function get_bc(bc::Function;intersect_point,ib,kwargs...) - bc(;intersect_point,ib) +get_bc(bc::AbstractVector; kwargs...) = copy(bc) +function get_bc(bc::Function; intersect_point, ib, kwargs...) + bc(; intersect_point, ib) end diff --git a/src/Boundary/Circle.jl b/src/Boundary/Circle.jl index 16b8b70..045410e 100644 --- a/src/Boundary/Circle.jl +++ b/src/Boundary/Circle.jl @@ -1,69 +1,115 @@ -function boundary_flag(boundary::Circle,midpoint::AbstractVector,ds::AbstractVector,::KInfo) # Circle type IB boundary flag +function boundary_flag( + boundary::Circle, + midpoint::AbstractVector, + ds::AbstractVector, + ::KInfo, +) # Circle type IB boundary flag flag = 0 for i = 1:4 - flag += norm(midpoint.+ds.*NMT[2][i].-boundary.center)>boundary.radius ? 1 : -1 # any neighbor cross boundary? + flag += + norm(midpoint .+ ds .* NMT[2][i] .- boundary.center)>boundary.radius ? 1 : -1 # any neighbor cross boundary? end abs(flag)==4 && return false return true end -function boundary_flag(boundary::Sphere,midpoint::AbstractVector,ds::AbstractVector,::KInfo) # Circle type IB boundary flag +function boundary_flag( + boundary::Sphere, + midpoint::AbstractVector, + ds::AbstractVector, + ::KInfo, +) # Circle type IB boundary flag flag = 0 for i = 1:6 - flag += norm(midpoint.+ds.*NMT[3][i].-boundary.center)>boundary.radius ? 1 : -1 # any neighbor cross boundary? + flag += + norm(midpoint .+ ds .* NMT[3][i] .- boundary.center)>boundary.radius ? 1 : -1 # any neighbor cross boundary? end abs(flag)==6 && return false return true end -function solid_flag(boundary::AbstractCircle,midpoint::AbstractVector) # Does midpoint locate at solid? - return xor(norm(midpoint.-boundary.center)>boundary.radius,boundary.solid) -end -function solid_cell_flag(boundary::AbstractCircle,midpoint::AbstractVector,ds::AbstractVector,kinfo::KInfo,inside::Bool) # Ghost nodes, those are inside solid domain and immediately adjacent the boundary. - (boundary_flag(boundary,midpoint,ds,kinfo) && inside) && return true +function solid_flag(boundary::AbstractCircle, midpoint::AbstractVector) # Does midpoint locate at solid? + return xor(norm(midpoint .- boundary.center)>boundary.radius, boundary.solid) +end +function solid_cell_flag( + boundary::AbstractCircle, + midpoint::AbstractVector, + ds::AbstractVector, + kinfo::KInfo, + inside::Bool, +) # Ghost nodes, those are inside solid domain and immediately adjacent the boundary. + (boundary_flag(boundary, midpoint, ds, kinfo) && inside) && return true return false end -function calc_IB_ρw(aux_point::AbstractVector,bound::Circle,midpoint::AbstractMatrix,weight::AbstractVector,df::AbstractMatrix,vn::AbstractVector,Θ::AbstractVector) - calc_IB_ρw_2D(aux_point,bound.bc,midpoint,weight,df,vn,Θ) -end -function calc_IB_ρw(aux_point::AbstractVector,bound::Sphere,midpoint::AbstractMatrix,weight::AbstractVector,df::AbstractMatrix,vn::AbstractVector,Θ::AbstractVector) - calc_IB_ρw_3D(aux_point,bound.bc,midpoint,weight,df,vn,Θ) -end -function IB_prim(circle::AbstractCircle,aux_point::AbstractVector,ρw::Real) - IB_prim(circle.bc,aux_point,ρw) -end -function calc_intersect(f_midpoint,s_midpoint,::Vector,::Int,circle::Circle) - c = circle.center;r = circle.radius +function calc_IB_ρw( + aux_point::AbstractVector, + bound::Circle, + midpoint::AbstractMatrix, + weight::AbstractVector, + df::AbstractMatrix, + vn::AbstractVector, + Θ::AbstractVector, +) + calc_IB_ρw_2D(aux_point, bound.bc, midpoint, weight, df, vn, Θ) +end +function calc_IB_ρw( + aux_point::AbstractVector, + bound::Sphere, + midpoint::AbstractMatrix, + weight::AbstractVector, + df::AbstractMatrix, + vn::AbstractVector, + Θ::AbstractVector, +) + calc_IB_ρw_3D(aux_point, bound.bc, midpoint, weight, df, vn, Θ) +end +function IB_prim(circle::AbstractCircle, aux_point::AbstractVector, ρw::Real) + IB_prim(circle.bc, aux_point, ρw) +end +function calc_intersect(f_midpoint, s_midpoint, ::Vector, ::Int, circle::Circle) + c = circle.center; + r = circle.radius if abs(f_midpoint[1]-s_midpoint[1])c[2] - ap = [r*cos(t),r*sin(t)];n=ap./(circle.solid ? r : -r) + ap = [r*cos(t), r*sin(t)]; + n=ap ./ (circle.solid ? r : -r) else - ap = [r*cos(t),-r*sin(t)];n = ap./(circle.solid ? r : -r) + ap = [r*cos(t), -r*sin(t)]; + n = ap ./ (circle.solid ? r : -r) end else t = asin((f_midpoint[2]-c[2])/r) if f_midpoint[1]>c[1] - ap = [r*cos(t),r*sin(t)];n = ap./ (circle.solid ? r : -r) + ap = [r*cos(t), r*sin(t)]; + n = ap ./ (circle.solid ? r : -r) else - ap = [-r*cos(t),r*sin(t)];n = ap./ (circle.solid ? r : -r) + ap = [-r*cos(t), r*sin(t)]; + n = ap ./ (circle.solid ? r : -r) end end - return ap,n + return ap, n end -function calc_intersect(f_midpoint,s_midpoint,::Vector,::Int,circle::Sphere) - c = circle.center;r = circle.radius - dir = findfirst(x->x>EPS,abs.(f_midpoint-s_midpoint)) +function calc_intersect(f_midpoint, s_midpoint, ::Vector, ::Int, circle::Sphere) + c = circle.center; + r = circle.radius + dir = findfirst(x->x>EPS, abs.(f_midpoint-s_midpoint)) r_midpoint = f_midpoint-c - x = r_midpoint[dir%3+1]; y =r_midpoint[(dir+1)%3+1] - ap = copy(f_midpoint);n = copy(f_midpoint) + x = r_midpoint[dir%3+1]; + y = r_midpoint[(dir+1)%3+1] + ap = copy(f_midpoint); + n = copy(f_midpoint) rz = sqrt(r^2-x^2-y^2) - dz = abs((rz-r_midpoint[dir])/(s_midpoint[dir]-f_midpoint[dir])) < 1 ? rz-r_midpoint[dir] : -rz-r_midpoint[dir] - ap[dir] = dz+f_midpoint[dir];n[dir] = dz+r_midpoint[dir];n/=(circle.solid ? r : -r) - return ap,n + dz = + abs((rz-r_midpoint[dir])/(s_midpoint[dir]-f_midpoint[dir])) < 1 ? + rz-r_midpoint[dir] : -rz-r_midpoint[dir] + ap[dir] = dz+f_midpoint[dir]; + n[dir] = dz+r_midpoint[dir]; + n/=(circle.solid ? r : -r) + return ap, n end -function search_radius_flag!(i::Int,ib::Circle,midpoint,ds,mesh_data) - solid_box_flag(midpoint,ds,ib) || return false +function search_radius_flag!(i::Int, ib::Circle, midpoint, ds, mesh_data) + solid_box_flag(midpoint, ds, ib) || return false mesh_data.in_box = i r = ib.search_radius distance = abs(norm(midpoint .- ib.center) - ib.radius) @@ -74,39 +120,51 @@ function search_radius_flag!(i::Int,ib::Circle,midpoint,ds,mesh_data) return false end -function search_radius_flag(ib::Circle,midpoint,ds) - solid_box_flag(midpoint,ds,ib) || return false +function search_radius_flag(ib::Circle, midpoint, ds) + solid_box_flag(midpoint, ds, ib) || return false r = ib.search_radius distance = abs(norm(midpoint .- ib.center) - ib.radius) return distance < r + 0.5*norm(ds) end -function solid_box_flag(midpoint,ds,ib::Circle) +function solid_box_flag(midpoint, ds, ib::Circle) r = ib.search_radius - hyper_rec = HyperRectangle(SVector{2,Float64}(ib.center.-ib.radius.-r),SVector{2,Float64}(ib.center.+ib.radius.+r)) - lower = midpoint-0.5*ds;upper = midpoint+0.5*ds - if overlap_test(lower,upper,hyper_rec) + hyper_rec = HyperRectangle( + SVector{2,Float64}(ib.center .- ib.radius .- r), + SVector{2,Float64}(ib.center .+ ib.radius .+ r), + ) + lower = midpoint-0.5*ds; + upper = midpoint+0.5*ds + if overlap_test(lower, upper, hyper_rec) return true else return false end end -function solid_box_flag(midpoint,ds,ib::Sphere) +function solid_box_flag(midpoint, ds, ib::Sphere) r = ib.search_radius - hyper_rec = HyperRectangle(SVector{3,Float64}(ib.center.-ib.radius.-r),SVector{3,Float64}(ib.center.+ib.radius.+r)) - lower = midpoint-0.5*ds;upper = midpoint+0.5*ds - if overlap_test(lower,upper,hyper_rec) + hyper_rec = HyperRectangle( + SVector{3,Float64}(ib.center .- ib.radius .- r), + SVector{3,Float64}(ib.center .+ ib.radius .+ r), + ) + lower = midpoint-0.5*ds; + upper = midpoint+0.5*ds + if overlap_test(lower, upper, hyper_rec) return true else return false end end -function search_radius_flag!(i::Int,ib::Sphere,midpoint,ds,mesh_data) +function search_radius_flag!(i::Int, ib::Sphere, midpoint, ds, mesh_data) r = ib.search_radius - hyper_rec = HyperRectangle(SVector{3,Float64}(ib.center.-ib.radius.-r),SVector{3,Float64}(ib.center.+ib.radius.+r)) - lower = midpoint-0.5*ds;upper = midpoint+0.5*ds - if overlap_test(lower,upper,hyper_rec) + hyper_rec = HyperRectangle( + SVector{3,Float64}(ib.center .- ib.radius .- r), + SVector{3,Float64}(ib.center .+ ib.radius .+ r), + ) + lower = midpoint-0.5*ds; + upper = midpoint+0.5*ds + if overlap_test(lower, upper, hyper_rec) mesh_data.in_box = i distance = abs(norm(midpoint-ib.center)-ib.radius) if distanceib.radius ? 1 : -1 # any neighbor cross boundary? + flag += norm(midpoint .+ ds .* NMT[2][i] .- ib.center)>ib.radius ? 1 : -1 # any neighbor cross boundary? end abs(flag)==4 && return false return true @@ -133,23 +191,27 @@ end $(TYPEDSIGNATURES) Only accurate for grids that have been refined to the same level (inside the search radius). """ -function ghost_cell_flag(ib::Sphere,midpoint,ds) +function ghost_cell_flag(ib::Sphere, midpoint, ds) flag = 0 for i = 1:6 - flag += norm(midpoint.+ds.*NMT[3][i].-ib.center)>ib.radius ? 1 : -1 # any neighbor cross boundary? + flag += norm(midpoint .+ ds .* NMT[3][i] .- ib.center)>ib.radius ? 1 : -1 # any neighbor cross boundary? end abs(flag)==6 && return false return true end -function search_radius_flag(ib::AbstractCircle,midpoint,ds) +function search_radius_flag(ib::AbstractCircle, midpoint, ds) r = ib.search_radius - hyper_rec = HyperRectangle(SVector{3,Float64}(ib.center.-ib.radius.-r),SVector{3,Float64}(ib.center.+ib.radius.+r)) - lower = midpoint-0.5*ds;upper = midpoint+0.5*ds - if overlap_test(lower,upper,hyper_rec) + hyper_rec = HyperRectangle( + SVector{3,Float64}(ib.center .- ib.radius .- r), + SVector{3,Float64}(ib.center .+ ib.radius .+ r), + ) + lower = midpoint-0.5*ds; + upper = midpoint+0.5*ds + if overlap_test(lower, upper, hyper_rec) distance = abs(norm(midpoint-ib.center)-ib.radius) if distanceisa(x[1],SolidNeighbor),ps_data.neighbor.data) +function save_boundary_result!( + ib::AbstractBoundary, + ps_data::PsData{DIM,NDF}, + boundary_results::Vector{Boundary_Solution}, + ka::KA{DIM,NDF}; + dir_path = "", +) where {DIM,NDF} + solid_neighbors = findall(x->isa(x[1], SolidNeighbor), ps_data.neighbor.data) for i in solid_neighbors - save_boundary_result!(ib,ps_data,ps_data.neighbor.data[i][1],boundary_results,ka;dir_path) + save_boundary_result!( + ib, + ps_data, + ps_data.neighbor.data[i][1], + boundary_results, + ka; + dir_path, + ) end end -function solid_cell_index_encoder!(solid_cell_index::Vector{Int},now_index::Int) - id = findfirst(x->x==0,solid_cell_index) +function solid_cell_index_encoder!(solid_cell_index::Vector{Int}, now_index::Int) + id = findfirst(x->x==0, solid_cell_index) isnothing(id) && (@error `A larger SOLID_CELL_ID_NUM is needed!`) solid_cell_index[id]=now_index end function solid_cell_index_decoder(solid_cell_index::Vector{Int}) - ids = findall(x->x!=0,solid_cell_index) + ids = findall(x->x!=0, solid_cell_index) return solid_cell_index[ids] end -function solid_cell_index2ranks(indices::Vector,quadids::Vector,gfq::Vector) # give the 1-based ranks containing solid_cells in indices +function solid_cell_index2ranks(indices::Vector, quadids::Vector, gfq::Vector) # give the 1-based ranks containing solid_cells in indices qids = quadids[indices] lrank = MPI.Comm_rank(MPI.COMM_WORLD)+1 - ranks = Int[];lids = Int[] + ranks = Int[]; + lids = Int[] for i in eachindex(qids) - rank = findfirst(x->x>qids[i],gfq)-1 - !(rank==lrank||in(rank,ranks))&&push!(ranks,rank) - rank==lrank&&push!(lids,indices[i]) + rank = findfirst(x->x>qids[i], gfq)-1 + !(rank==lrank||in(rank, ranks))&&push!(ranks, rank) + rank==lrank&&push!(lids, indices[i]) end - return ranks,lids + return ranks, lids end -function solid_flag(::Domain,::AbstractVector) # Does midpoint locate at solid? +function solid_flag(::Domain, ::AbstractVector) # Does midpoint locate at solid? return false end -function solid_cell_flag(boundaries::Vector{AbstractBoundary},midpoint::AbstractVector,ds::AbstractVector,kinfo::KInfo) +function solid_cell_flag( + boundaries::Vector{AbstractBoundary}, + midpoint::AbstractVector, + ds::AbstractVector, + kinfo::KInfo, +) for boundary in boundaries - solid_cell_flag(boundary,midpoint,ds,kinfo,solid_flag(boundary,midpoint))&& return true + solid_cell_flag(boundary, midpoint, ds, kinfo, solid_flag(boundary, midpoint)) && + return true end return false end -function vs_extrapolate!(df::AbstractMatrix{Float64},sdf::AbstractArray{Float64},level::AbstractVector{Int8},dft::AbstractMatrix{Float64},levelt::Vector{Int8},dx::Vector{Float64},weight::AbstractVector{Float64},::KA{DIM,NDF}) where{DIM,NDF} - ddf = @views [dot(sdf[i,j,:],dx) for i in axes(sdf,1), j in axes(sdf,2)] - j = 1;flag = 0.0 - @inbounds for i in axes(dft,1) +function vs_extrapolate!( + df::AbstractMatrix{Float64}, + sdf::AbstractArray{Float64}, + level::AbstractVector{Int8}, + dft::AbstractMatrix{Float64}, + levelt::Vector{Int8}, + dx::Vector{Float64}, + weight::AbstractVector{Float64}, + ::KA{DIM,NDF}, +) where {DIM,NDF} + ddf = @views [dot(sdf[i, j, :], dx) for i in axes(sdf, 1), j in axes(sdf, 2)] + j = 1; + flag = 0.0 + @inbounds for i in axes(dft, 1) if levelt[i] == level[j] - @. dft[i, :] += @views (df[j, :]+ddf[j,:])*weight[i] + @. dft[i, :] += @views (df[j, :]+ddf[j, :])*weight[i] j += 1 elseif levelt[i] < level[j] while flag != 1.0 - @. dft[i, :] += @views (df[j, :]+ddf[j,:])/ 2^(DIM * (level[j] - levelt[i]))*weight[i] + @. dft[i, :] += + @views (df[j, :]+ddf[j, :]) / 2^(DIM * (level[j] - levelt[i]))*weight[i] flag += 1 / 2^(DIM * (level[j] - levelt[i])) j += 1 end flag = 0.0 else - @. dft[i, :] += @views (df[j,:]+ddf[j,:])*weight[i] + @. dft[i, :] += @views (df[j, :]+ddf[j, :])*weight[i] flag += 1 / 2^(DIM * (levelt[i] - level[j])) if flag == 1.0 j += 1 @@ -119,49 +221,79 @@ function vs_extrapolate!(df::AbstractMatrix{Float64},sdf::AbstractArray{Float64} end end end -function update_solid_cell!(::Type{T},ps_data::PsData{DIM,NDF},fluid_cells::Vector,ka::KA{DIM,NDF}) where{DIM,NDF,T<:Union{DVM,CAIDVM,UGKS}} - vs_data = ps_data.vs_data;vs_data.df.=0. - weights = Matrix{Float64}(undef,vs_data.vs_num,length(fluid_cells)) +function update_solid_cell!( + ::Type{T}, + ps_data::PsData{DIM,NDF}, + fluid_cells::Vector, + ka::KA{DIM,NDF}, +) where {DIM,NDF,T<:Union{DVM,CAIDVM,UGKS}} + vs_data = ps_data.vs_data; + vs_data.df.=0.0 + weights = Matrix{Float64}(undef, vs_data.vs_num, length(fluid_cells)) for i in eachindex(fluid_cells) - l = ps_data.midpoint-fluid_cells[i].midpoint;l/=norm(l) - weights[:,i] .= [max(0.,dot(u,l)/norm(u))^2 for u in eachrow(vs_data.midpoint)] + l = ps_data.midpoint-fluid_cells[i].midpoint; + l/=norm(l) + weights[:, i] .= [max(0.0, dot(u, l)/norm(u))^2 for u in eachrow(vs_data.midpoint)] end - weight_i = Vector{Float64}(undef,vs_data.vs_num) - weight_sum = sum(weights,dims=2) + weight_i = Vector{Float64}(undef, vs_data.vs_num) + weight_sum = sum(weights, dims = 2) for i in eachindex(fluid_cells) f_vs_data = fluid_cells[i].vs_data for j in eachindex(weight_i) - weight_i[j] = weight_sum[j]==0. ? 1.0/length(fluid_cells) : weights[j,i]/weight_sum[j] + weight_i[j] = + weight_sum[j]==0.0 ? 1.0/length(fluid_cells) : weights[j, i]/weight_sum[j] end - fdf = f_vs_data.df;fsdf = f_vs_data.sdf;dx = ps_data.midpoint-fluid_cells[i].midpoint - vs_extrapolate!(fdf,fsdf,f_vs_data.level,vs_data.df,vs_data.level,dx,weight_i,ka) + fdf = f_vs_data.df; + fsdf = f_vs_data.sdf; + dx = ps_data.midpoint-fluid_cells[i].midpoint + vs_extrapolate!( + fdf, + fsdf, + f_vs_data.level, + vs_data.df, + vs_data.level, + dx, + weight_i, + ka, + ) end ps_data.w = calc_w0(ps_data) - ps_data.prim = get_prim(ps_data,ka.kinfo) + ps_data.prim = get_prim(ps_data, ka.kinfo) end -function update_solid_cell!(ps_data::PsData{DIM,NDF},ka::KA{DIM,NDF}) where{DIM,NDF} - fluid_dirs = findall(x->!isnothing(x[1])&&!isa(x[1],AbstractInsideSolidData)&&x[1].bound_enc>=0,ps_data.neighbor.data) +function update_solid_cell!(ps_data::PsData{DIM,NDF}, ka::KA{DIM,NDF}) where {DIM,NDF} + fluid_dirs = findall( + x->!isnothing(x[1])&&!isa(x[1], AbstractInsideSolidData)&&x[1].bound_enc>=0, + ps_data.neighbor.data, + ) fluid_cells = [ps_data.neighbor.data[i][1] for i in fluid_dirs] - update_solid_cell!(ka.kinfo.config.solver.flux,ps_data,fluid_cells,ka) + update_solid_cell!(ka.kinfo.config.solver.flux, ps_data, fluid_cells, ka) end -function vs_translate!(df::AbstractMatrix{Float64},level::AbstractVector{Int8},dft::AbstractMatrix{Float64},levelt::Vector{Int8},weight::AbstractVector{Float64},::KA{DIM,NDF}) where{DIM,NDF} - j = 1;flag = 0.0 - @inbounds for i in axes(dft,1) +function vs_translate!( + df::AbstractMatrix{Float64}, + level::AbstractVector{Int8}, + dft::AbstractMatrix{Float64}, + levelt::Vector{Int8}, + weight::AbstractVector{Float64}, + ::KA{DIM,NDF}, +) where {DIM,NDF} + j = 1; + flag = 0.0 + @inbounds for i in axes(dft, 1) if levelt[i] == level[j] @. dft[i, :] += @views df[j, :]*weight[i] j += 1 elseif levelt[i] < level[j] while flag != 1.0 - @. dft[i, :] += @views df[j, :]/ 2^(DIM * (level[j] - levelt[i]))*weight[i] + @. dft[i, :] += @views df[j, :] / 2^(DIM * (level[j] - levelt[i]))*weight[i] flag += 1 / 2^(DIM * (level[j] - levelt[i])) j += 1 end flag = 0.0 else - @. dft[i, :] += @views df[j,:]*weight[i] + @. dft[i, :] += @views df[j, :]*weight[i] flag += 1 / 2^(DIM * (levelt[i] - level[j])) if flag == 1.0 j += 1 @@ -174,30 +306,41 @@ end $(SIGNATURES) Filter the solid cell by fluid cells to guarantee the positivity of density and temperature. """ -function filter_solid_cell!(ps_data::PsData{DIM,NDF},ka::KA{DIM,NDF}) where{DIM,NDF} - fluid_dirs = findall(x->!isnothing(x[1])&&!isa(x[1],AbstractInsideSolidData)&&x[1].bound_enc>=0,ps_data.neighbor.data) +function filter_solid_cell!(ps_data::PsData{DIM,NDF}, ka::KA{DIM,NDF}) where {DIM,NDF} + fluid_dirs = findall( + x->!isnothing(x[1])&&!isa(x[1], AbstractInsideSolidData)&&x[1].bound_enc>=0, + ps_data.neighbor.data, + ) fluid_cells = [ps_data.neighbor.data[i][1] for i in fluid_dirs] - filter_solid_cell!(ka.kinfo.config.solver.flux,ps_data,fluid_cells,ka) -end -function filter_solid_cell!(::Type{T},ps_data::PsData{DIM,NDF},fluid_cells::Vector,ka::KA{DIM,NDF}) where{DIM,NDF,T<:Union{DVM,CAIDVM,UGKS}} - vs_data = ps_data.vs_data;vs_data.df.=0. - weights = Matrix{Float64}(undef,vs_data.vs_num,length(fluid_cells)) + filter_solid_cell!(ka.kinfo.config.solver.flux, ps_data, fluid_cells, ka) +end +function filter_solid_cell!( + ::Type{T}, + ps_data::PsData{DIM,NDF}, + fluid_cells::Vector, + ka::KA{DIM,NDF}, +) where {DIM,NDF,T<:Union{DVM,CAIDVM,UGKS}} + vs_data = ps_data.vs_data; + vs_data.df.=0.0 + weights = Matrix{Float64}(undef, vs_data.vs_num, length(fluid_cells)) for i in eachindex(fluid_cells) - l = ps_data.midpoint-fluid_cells[i].midpoint;l/=norm(l) - weights[:,i] .= [max(0.,dot(u,l)/norm(u))^2 for u in eachrow(vs_data.midpoint)] + l = ps_data.midpoint-fluid_cells[i].midpoint; + l/=norm(l) + weights[:, i] .= [max(0.0, dot(u, l)/norm(u))^2 for u in eachrow(vs_data.midpoint)] end - weight_i = Vector{Float64}(undef,vs_data.vs_num) - weight_sum = sum(weights,dims=2) + weight_i = Vector{Float64}(undef, vs_data.vs_num) + weight_sum = sum(weights, dims = 2) for i in eachindex(fluid_cells) f_vs_data = fluid_cells[i].vs_data for j in eachindex(weight_i) - weight_i[j] = weight_sum[j]==0. ? 1.0/length(fluid_cells) : weights[j,i]/weight_sum[j] + weight_i[j] = + weight_sum[j]==0.0 ? 1.0/length(fluid_cells) : weights[j, i]/weight_sum[j] end fdf = f_vs_data.df - vs_translate!(fdf,f_vs_data.level,vs_data.df,vs_data.level,weight_i,ka) + vs_translate!(fdf, f_vs_data.level, vs_data.df, vs_data.level, weight_i, ka) end ps_data.w = calc_w0(ps_data) - ps_data.prim = get_prim(ps_data,ka.kinfo) + ps_data.prim = get_prim(ps_data, ka.kinfo) end """ @@ -207,7 +350,7 @@ Update `solid_cell` in [`SolidNeighbor`](@ref) with interpolation. function update_solid_cell!(ka::KA) for ib in ka.kdata.field.immersed_boundaries for ps_data in ib.solid_cells - update_solid_cell!(ps_data,ka) + update_solid_cell!(ps_data, ka) end end end @@ -218,109 +361,195 @@ $(TYPEDSIGNATURES) function initialize_solid_neighbor!(ka::KA) for tree in ka.kdata.field.trees.data for ps_data in tree - (isa(ps_data,InsideSolidData)||ps_data.bound_enc<0)&&continue - initialize_solid_neighbor!(ps_data,ka) + (isa(ps_data, InsideSolidData)||ps_data.bound_enc<0)&&continue + initialize_solid_neighbor!(ps_data, ka) end end end -function initialize_cutted_velocity_cell(n::Vector{Float64},vs_data::VsData{2},ka::KA{2,NDF}) where{NDF} - any(x->abs(x)<1e-6,n)&&(return CuttedVelocityCells(Int[],copy(vs_data.weight),Matrix{Float64}(undef,0,0),Matrix{Float64}(undef,0,0),Float64[],Float64[])) +function initialize_cutted_velocity_cell( + n::Vector{Float64}, + vs_data::VsData{2}, + ka::KA{2,NDF}, +) where {NDF} + any(x->abs(x)<1e-6, n)&&( + return CuttedVelocityCells( + Int[], + copy(vs_data.weight), + Matrix{Float64}(undef, 0, 0), + Matrix{Float64}(undef, 0, 0), + Float64[], + Float64[], + ) + ) kinfo = ka.kinfo - du = [(kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / - kinfo.config.vs_trees_num[i] for i in 1:2] - vertices = [zeros(2) for _ in 1:4] - index = Int[];solid_weights = Float64[];gas_weights = Float64[] - for i in 1:vs_data.vs_num - ddu = du./2^(vs_data.level[i]) - @views abs(dot(vs_data.midpoint[i,:],n))>0.5*norm(ddu)&&continue + du = [ + (kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / + kinfo.config.vs_trees_num[i] for i = 1:2 + ] + vertices = [zeros(2) for _ = 1:4] + index = Int[]; + solid_weights = Float64[]; + gas_weights = Float64[] + for i = 1:vs_data.vs_num + ddu = du ./ 2^(vs_data.level[i]) + @views abs(dot(vs_data.midpoint[i, :], n))>0.5*norm(ddu)&&continue for j in eachindex(vertices) - vertices[j] .= @views 0.5*ANTIVT[2][j].*ddu+vs_data.midpoint[i,:] + vertices[j] .= @views 0.5*ANTIVT[2][j] .* ddu+vs_data.midpoint[i, :] end - flag,gas_weight,solid_weight = cut_rect(n,vertices) + flag, gas_weight, solid_weight = cut_rect(n, vertices) if flag - push!(index,i);push!(solid_weights,solid_weight);push!(gas_weights,gas_weight) + push!(index, i); + push!(solid_weights, solid_weight); + push!(gas_weights, gas_weight) end end N = length(index) - gas_dfs = zeros(N,NDF);solid_dfs = zeros(N,NDF) + gas_dfs = zeros(N, NDF); + solid_dfs = zeros(N, NDF) weight = copy(vs_data.weight) - weight[index].=0. - return CuttedVelocityCells(index,weight,gas_dfs,solid_dfs,gas_weights,solid_weights) -end -function initialize_cutted_velocity_cell(n::AbstractVector,vs_data::VsData{3},ka::KA{3,NDF}) where{NDF} - l = findall(x->abs(x)<1e-6,n) - length(l)>1 && - (return CuttedVelocityCells(Int[],copy(vs_data.weight),Matrix{Float64}(undef,0,0),Matrix{Float64}(undef,0,0),Float64[],Float64[])) + weight[index].=0.0 + return CuttedVelocityCells( + index, + weight, + gas_dfs, + solid_dfs, + gas_weights, + solid_weights, + ) +end +function initialize_cutted_velocity_cell( + n::AbstractVector, + vs_data::VsData{3}, + ka::KA{3,NDF}, +) where {NDF} + l = findall(x->abs(x)<1e-6, n) + length(l)>1 && ( + return CuttedVelocityCells( + Int[], + copy(vs_data.weight), + Matrix{Float64}(undef, 0, 0), + Matrix{Float64}(undef, 0, 0), + Float64[], + Float64[], + ) + ) kinfo = ka.kinfo - du = [(kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / - kinfo.config.vs_trees_num[i] for i in 1:3] - vertices = zeros(3,8) - index = Int[];solid_weights = Float64[];gas_weights = Float64[] + du = [ + (kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / + kinfo.config.vs_trees_num[i] for i = 1:3 + ] + vertices = zeros(3, 8) + index = Int[]; + solid_weights = Float64[]; + gas_weights = Float64[] C = cut_cube_rotate(n) - for i in 1:vs_data.vs_num - ddu = du./2^(vs_data.level[i]) - midpoint = vs_data.midpoint[i,:] - abs(dot(midpoint,n))>0.5*norm(ddu)&&continue - for j in axes(vertices,2) - vertices[:,j] .= 0.5*ANTIVT[3][j].*ddu+midpoint + for i = 1:vs_data.vs_num + ddu = du ./ 2^(vs_data.level[i]) + midpoint = vs_data.midpoint[i, :] + abs(dot(midpoint, n))>0.5*norm(ddu)&&continue + for j in axes(vertices, 2) + vertices[:, j] .= 0.5*ANTIVT[3][j] .* ddu+midpoint end - flag,gas_weight,solid_weight = cut_cube(n,C,midpoint,ddu,vertices) + flag, gas_weight, solid_weight = cut_cube(n, C, midpoint, ddu, vertices) if flag - push!(index,i);push!(solid_weights,solid_weight);push!(gas_weights,gas_weight) + push!(index, i); + push!(solid_weights, solid_weight); + push!(gas_weights, gas_weight) end end N = length(index) - gas_dfs = zeros(N,NDF);solid_dfs = zeros(N,NDF) + gas_dfs = zeros(N, NDF); + solid_dfs = zeros(N, NDF) weight = copy(vs_data.weight) - weight[index].=0. - return CuttedVelocityCells(index,weight,gas_dfs,solid_dfs,gas_weights,solid_weights) + weight[index].=0.0 + return CuttedVelocityCells( + index, + weight, + gas_dfs, + solid_dfs, + gas_weights, + solid_weights, + ) end """ $(TYPEDSIGNATURES) """ -function initialize_solid_neighbor!(ps_data::PsData{DIM,NDF},ka::KA{DIM,NDF}) where{DIM,NDF} - solid_dirs = findall(x->!isnothing(x[1])&&x[1].bound_enc<0,ps_data.neighbor.data[1:2*DIM]) +function initialize_solid_neighbor!( + ps_data::PsData{DIM,NDF}, + ka::KA{DIM,NDF}, +) where {DIM,NDF} + solid_dirs = + findall(x->!isnothing(x[1])&&x[1].bound_enc<0, ps_data.neighbor.data[1:(2*DIM)]) vs_data = ps_data.vs_data for i in solid_dirs solid_cell = ps_data.neighbor.data[i][1] ps_data.bound_enc = -solid_cell.bound_enc ib = ka.kinfo.config.IB[-solid_cell.bound_enc] - aux_point,normal = calc_intersect(ps_data.midpoint,solid_cell.midpoint,ps_data.ds,get_dir(i),ib) + aux_point, normal = calc_intersect( + ps_data.midpoint, + solid_cell.midpoint, + ps_data.ds, + get_dir(i), + ib, + ) svsdata = VsData{DIM,NDF}( vs_data.vs_num, vs_data.level, vs_data.weight, vs_data.midpoint, copy(vs_data.df), - zeros(vs_data.vs_num,NDF,DIM), - zeros(vs_data.vs_num,NDF) + zeros(vs_data.vs_num, NDF, DIM), + zeros(vs_data.vs_num, NDF), ) - cvc = initialize_cutted_velocity_cell(normal,svsdata,ka) # heavy overhead + cvc = initialize_cutted_velocity_cell(normal, svsdata, ka) # heavy overhead ps_data.neighbor.data[i][1] = SolidNeighbor{DIM,NDF}( - solid_cell.bound_enc,i,0,aux_point,normal,solid_cell,solid_cell.midpoint,solid_cell.ds,zeros(DIM+2),zeros(DIM+2),zeros(DIM+2,DIM),cvc,svsdata + solid_cell.bound_enc, + i, + 0, + aux_point, + normal, + solid_cell, + solid_cell.midpoint, + solid_cell.ds, + zeros(DIM+2), + zeros(DIM+2), + zeros(DIM+2, DIM), + cvc, + svsdata, ) end return nothing end -function vs_interpolate!(f_df::AbstractMatrix,f_level::AbstractVector{Int8},fx,s_df,s_level,sx,b_df,bx,::KA{DIM,NDF}) where{DIM,NDF} - j = 1;flag = 0.0 - @inbounds for i in axes(f_df,1) +function vs_interpolate!( + f_df::AbstractMatrix, + f_level::AbstractVector{Int8}, + fx, + s_df, + s_level, + sx, + b_df, + bx, + ::KA{DIM,NDF}, +) where {DIM,NDF} + j = 1; + flag = 0.0 + @inbounds for i in axes(f_df, 1) if f_level[i] == s_level[j] - @. b_df[i, :] = @views f_df[i,:]+(s_df[j, :]-f_df[i,:])/(sx-fx)*(bx-fx) + @. b_df[i, :] = @views f_df[i, :]+(s_df[j, :]-f_df[i, :])/(sx-fx)*(bx-fx) j += 1 elseif f_level[i] < s_level[j] - @. b_df[i,:] = @views -f_df[i,:] + @. b_df[i, :] = @views -f_df[i, :] while flag != 1.0 - @. b_df[i, :] += @views s_df[j,:]/ 2^(DIM * (s_level[j] - f_level[i])) + @. b_df[i, :] += @views s_df[j, :] / 2^(DIM * (s_level[j] - f_level[i])) flag += 1 / 2^(DIM * (s_level[j] - f_level[i])) j += 1 end - @. b_df[i,:]*=(bx-fx)/(sx-fx) - @. b_df[i,:] += @views f_df[i,:] + @. b_df[i, :]*=(bx-fx)/(sx-fx) + @. b_df[i, :] += @views f_df[i, :] flag = 0.0 else - @. b_df[i, :] += @views f_df[i,:]+(s_df[j, :]-f_df[i,:])/(sx-fx)*(bx-fx) + @. b_df[i, :] += @views f_df[i, :]+(s_df[j, :]-f_df[i, :])/(sx-fx)*(bx-fx) flag += 1 / 2^(DIM * (f_level[i] - s_level[j])) if flag == 1.0 j += 1 @@ -329,24 +558,30 @@ function vs_interpolate!(f_df::AbstractMatrix,f_level::AbstractVector{Int8},fx,s end end end -function cvc_gas_correction!(aux_df,solid_neighbor::SolidNeighbor{DIM,NDF}) where{DIM,NDF} +function cvc_gas_correction!(aux_df, solid_neighbor::SolidNeighbor{DIM,NDF}) where {DIM,NDF} cvc = solid_neighbor.cvc for i in eachindex(cvc.indices) - cvc.gas_dfs[i,:] .= @views aux_df[cvc.indices[i],:] + cvc.gas_dfs[i, :] .= @views aux_df[cvc.indices[i], :] end end -function cvc_density(aux_df,vn::AbstractVector,Θ,solid_neighbor::SolidNeighbor,MuR::Real) +function cvc_density( + aux_df, + vn::AbstractVector, + Θ, + solid_neighbor::SolidNeighbor, + MuR::Real, +) cvc = solid_neighbor.cvc - @inbounds @views SF = sum(@. cvc.weight * vn * aux_df[:,1] * (1.0 - Θ)) + @inbounds @views SF = sum(@. cvc.weight * vn * aux_df[:, 1] * (1.0 - Θ)) for i in eachindex(cvc.indices) cvc_vn = vn[cvc.indices[i]] - SF += cvc.gas_weights[i]*cvc_vn*cvc.gas_dfs[i,1] + SF += cvc.gas_weights[i]*cvc_vn*cvc.gas_dfs[i, 1] end return -SF/MuR end -function cvc_Mu(M::AbstractVector,vn,Θ,solid_neighbor) +function cvc_Mu(M::AbstractVector, vn, Θ, solid_neighbor) cvc = solid_neighbor.cvc - Mu_cvc = @. @views cvc.weight * vn *M + Mu_cvc = @. @views cvc.weight * vn * M MuL = sum(@. Mu_cvc*(1.0-Θ)) MuR = sum(@. Mu_cvc * Θ) for i in eachindex(cvc.indices) @@ -354,52 +589,81 @@ function cvc_Mu(M::AbstractVector,vn,Θ,solid_neighbor) MuL += cvc.gas_weights[i]*cvc_vn*M[cvc.indices[i]] MuR += cvc.solid_weights[i]*cvc_vn*M[cvc.indices[i]] end - return MuL,MuR + return MuL, MuR end -function cvc_correction!(aux_df,F::AbstractMatrix,solid_neighbor,ka) +function cvc_correction!(aux_df, F::AbstractMatrix, solid_neighbor, ka) cvc = solid_neighbor.cvc for i in eachindex(cvc.indices) - cvc.solid_dfs[i,:] .= @views F[cvc.indices[i],:] - @views @. aux_df[cvc.indices[i],:] = (cvc.gas_weights[i]*cvc.gas_dfs[i,:]+cvc.solid_weights[i]*cvc.solid_dfs[i,:])/(cvc.gas_weights[i]+cvc.solid_weights[i]) - end -end -function image_df(ps_data,ip,ka::KA{DIM,NDF}) where{DIM,NDF} - fluid_dirs = findall(x->!isnothing(x[1])&&!isa(x[1],AbstractInsideSolidData)&&x[1].bound_enc>=0,ps_data.neighbor.data) - fluid_cells = Vector{AbstractPsData{DIM,NDF}}(undef,length(fluid_dirs)+1) + cvc.solid_dfs[i, :] .= @views F[cvc.indices[i], :] + @views @. aux_df[cvc.indices[i], :] = + (cvc.gas_weights[i]*cvc.gas_dfs[i, :]+cvc.solid_weights[i]*cvc.solid_dfs[i, :])/( + cvc.gas_weights[i]+cvc.solid_weights[i] + ) + end +end +function image_df(ps_data, ip, ka::KA{DIM,NDF}) where {DIM,NDF} + fluid_dirs = findall( + x->!isnothing(x[1])&&!isa(x[1], AbstractInsideSolidData)&&x[1].bound_enc>=0, + ps_data.neighbor.data, + ) + fluid_cells = Vector{AbstractPsData{DIM,NDF}}(undef, length(fluid_dirs)+1) for i in eachindex(fluid_dirs) fluid_cells[i] = ps_data.neighbor.data[fluid_dirs[i]][1] end fluid_cells[end]=ps_data - image_df(ps_data,fluid_cells,ip,ka) + image_df(ps_data, fluid_cells, ip, ka) end -function image_df(ps_data::PsData{DIM,NDF},fluid_cells,ip,ka) where{DIM,NDF} +function image_df(ps_data::PsData{DIM,NDF}, fluid_cells, ip, ka) where {DIM,NDF} vs_data = ps_data.vs_data - image_df = zeros(vs_data.vs_num,NDF) - weights = Matrix{Float64}(undef,vs_data.vs_num,length(fluid_cells)) + image_df = zeros(vs_data.vs_num, NDF) + weights = Matrix{Float64}(undef, vs_data.vs_num, length(fluid_cells)) for i in eachindex(fluid_cells) - l = ip-fluid_cells[i].midpoint;l/=norm(l) - weights[:,i] .= [max(0.,dot(u,l)/norm(u))^2 for u in eachrow(vs_data.midpoint)] + l = ip-fluid_cells[i].midpoint; + l/=norm(l) + weights[:, i] .= [max(0.0, dot(u, l)/norm(u))^2 for u in eachrow(vs_data.midpoint)] end - weight_i = Vector{Float64}(undef,vs_data.vs_num) - weight_sum = sum(weights,dims=2) + weight_i = Vector{Float64}(undef, vs_data.vs_num) + weight_sum = sum(weights, dims = 2) for i in eachindex(fluid_cells) f_vs_data = fluid_cells[i].vs_data for j in eachindex(weight_i) - weight_i[j] = weight_sum[j]==0. ? 1.0/length(fluid_cells) : weights[j,i]/weight_sum[j] + weight_i[j] = + weight_sum[j]==0.0 ? 1.0/length(fluid_cells) : weights[j, i]/weight_sum[j] end - fdf = f_vs_data.df;fsdf = f_vs_data.sdf;dx = ip-fluid_cells[i].midpoint - vs_extrapolate!(fdf,fsdf,f_vs_data.level,image_df,vs_data.level,dx,weight_i,ka) + fdf = f_vs_data.df; + fsdf = f_vs_data.sdf; + dx = ip-fluid_cells[i].midpoint + vs_extrapolate!( + fdf, + fsdf, + f_vs_data.level, + image_df, + vs_data.level, + dx, + weight_i, + ka, + ) end return image_df end -function boundary_slope!(sdf::AbstractMatrix,level,level_n,sp_df,dc_df,sc_df,dxf::Float64,dxs::Float64,::KA{DIM,NDF}) where{DIM,NDF} - sL = zeros(size(sdf,1),NDF) +function boundary_slope!( + sdf::AbstractMatrix, + level, + level_n, + sp_df, + dc_df, + sc_df, + dxf::Float64, + dxs::Float64, + ::KA{DIM,NDF}, +) where {DIM,NDF} + sL = zeros(size(sdf, 1), NDF) index = 1 flag = 0.0 df = dc_df dfn = sc_df - @inbounds for i in axes(sL,1) + @inbounds for i in axes(sL, 1) if level[i] == level_n[index] for j = 1:NDF sL[i, j] = (df[i, j] - dfn[index, j]) / dxs @@ -427,50 +691,69 @@ function boundary_slope!(sdf::AbstractMatrix,level,level_n,sp_df,dc_df,sc_df,dxf end end end - for j in axes(sdf,2) - for i in axes(sdf,1) - sdf[i,j] = minmod(sL[i,j],(sp_df[i,j]-dc_df[i,j])/dxf) + for j in axes(sdf, 2) + for i in axes(sdf, 1) + sdf[i, j] = minmod(sL[i, j], (sp_df[i, j]-dc_df[i, j])/dxf) end end end -function update_solid_neighbor!(::Type{T},ps_data::PsData{DIM,NDF},solid_neighbor::SolidNeighbor{DIM,NDF},ka::KA) where{DIM,NDF,T<:AbstractFluxType} - kinfo = ka.kinfo;ib = kinfo.config.IB[ps_data.bound_enc] +function update_solid_neighbor!( + ::Type{T}, + ps_data::PsData{DIM,NDF}, + solid_neighbor::SolidNeighbor{DIM,NDF}, + ka::KA, +) where {DIM,NDF,T<:AbstractFluxType} + kinfo = ka.kinfo; + ib = kinfo.config.IB[ps_data.bound_enc] vs_data = ps_data.vs_data - aux_point = solid_neighbor.aux_point;n = solid_neighbor.normal + aux_point = solid_neighbor.aux_point; + n = solid_neighbor.normal faceid = solid_neighbor.faceid dir = get_dir(faceid) - solid_cell = solid_neighbor.solid_cell;s_vs_data = solid_cell.vs_data - vn = @views [dot(v,n) for v in eachrow(ps_data.vs_data.midpoint)] - aux_df = zeros(vs_data.vs_num,NDF) + solid_cell = solid_neighbor.solid_cell; + s_vs_data = solid_cell.vs_data + vn = @views [dot(v, n) for v in eachrow(ps_data.vs_data.midpoint)] + aux_df = zeros(vs_data.vs_num, NDF) ib_point = aux_point+ps_data.midpoint-solid_cell.midpoint - ib_df = image_df(ps_data,ib_point,ka) + ib_df = image_df(ps_data, ib_point, ka) Θ = heaviside.(vn) - ssdf = @views solid_neighbor.vs_data.sdf[:,:,dir] - boundary_slope!(ssdf,vs_data.level,s_vs_data.level,ib_df,vs_data.df, - s_vs_data.df,ib_point[dir]-ps_data.midpoint[dir],ps_data.midpoint[dir]-solid_neighbor.midpoint[dir],ka) + ssdf = @views solid_neighbor.vs_data.sdf[:, :, dir] + boundary_slope!( + ssdf, + vs_data.level, + s_vs_data.level, + ib_df, + vs_data.df, + s_vs_data.df, + ib_point[dir]-ps_data.midpoint[dir], + ps_data.midpoint[dir]-solid_neighbor.midpoint[dir], + ka, + ) dxL = aux_point[dir]-ib_point[dir] - for j in axes(ssdf,2) - for i in axes(ssdf,1) + for j in axes(ssdf, 2) + for i in axes(ssdf, 1) # positivity-preserving - ssdf[i,j] = min(abs((ib_df[i,j]-eps())/(ssdf[i,j]*dxL+eps())),1.0)*ssdf[i,j] + ssdf[i, j] = + min(abs((ib_df[i, j]-eps())/(ssdf[i, j]*dxL+eps())), 1.0)*ssdf[i, j] end end @. aux_df = ib_df+ssdf*dxL - cvc_gas_correction!(aux_df,solid_neighbor) - aux_prim = get_bc(ib.bc;intersect_point=aux_point,ib);aux_prim[1] = 1. - M = discrete_maxwell(vs_data.midpoint,aux_prim,kinfo) - _,Mu_R = @views cvc_Mu(M[:,1],vn,Θ,solid_neighbor) - ρw = cvc_density(aux_df,vn,Θ,solid_neighbor,Mu_R) + cvc_gas_correction!(aux_df, solid_neighbor) + aux_prim = get_bc(ib.bc; intersect_point = aux_point, ib); + aux_prim[1] = 1.0 + M = discrete_maxwell(vs_data.midpoint, aux_prim, kinfo) + _, Mu_R = @views cvc_Mu(M[:, 1], vn, Θ, solid_neighbor) + ρw = cvc_density(aux_df, vn, Θ, solid_neighbor, Mu_R) aux_prim[1] = ρw M .*= aux_prim[1] - for i in 1:vs_data.vs_num - if Θ[i]==1. - for j in axes(aux_df,2) - aux_df[i,j] = M[i,j] + for i = 1:vs_data.vs_num + if Θ[i]==1.0 + for j in axes(aux_df, 2) + aux_df[i, j] = M[i, j] end end end - cvc_correction!(aux_df,M,solid_neighbor,ka) + cvc_correction!(aux_df, M, solid_neighbor, ka) @. solid_neighbor.vs_data.df = aux_df # Positive part @. solid_neighbor.vs_data.flux = ssdf*(solid_neighbor.midpoint[dir]-aux_point[dir]) # Reconstruction perturbance # for i in axes(ssdf,1) @@ -481,24 +764,29 @@ function update_solid_neighbor!(::Type{T},ps_data::PsData{DIM,NDF},solid_neighbo # solid_neighbor.w = calc_w0(vs_data.midpoint,solid_neighbor.vs_data.df,vs_data.weight,kinfo) # solid_neighbor.sw[:,dir] .= (solid_neighbor.w-ps_data.w)./(solid_neighbor.midpoint[dir]-ps_data.midpoint[dir]) end -function update_solid_neighbor!(ps_data::PsData{DIM,NDF},ka::KA{DIM,NDF}) where{DIM,NDF} - solid_neighbors = findall(x->isa(x[1],SolidNeighbor),ps_data.neighbor.data) +function update_solid_neighbor!(ps_data::PsData{DIM,NDF}, ka::KA{DIM,NDF}) where {DIM,NDF} + solid_neighbors = findall(x->isa(x[1], SolidNeighbor), ps_data.neighbor.data) for i in solid_neighbors - update_solid_neighbor!(ka.kinfo.config.solver.flux,ps_data,ps_data.neighbor.data[i][1],ka) + update_solid_neighbor!( + ka.kinfo.config.solver.flux, + ps_data, + ps_data.neighbor.data[i][1], + ka, + ) end end """ $(TYPEDSIGNATURES) Update [`VsData`](@ref) variables in [`SolidNeighbor`](@ref) with the immersed boundary method. """ -function update_solid_neighbor!(ka::KA{DIM,NDF}) where{DIM,NDF} +function update_solid_neighbor!(ka::KA{DIM,NDF}) where {DIM,NDF} for ib in ka.kdata.field.immersed_boundaries for ps_data in ib.donor_cells - update_solid_neighbor!(ps_data,ka) + update_solid_neighbor!(ps_data, ka) end end end -function update_solid!(ka::KA{DIM,NDF}) where{DIM,NDF} +function update_solid!(ka::KA{DIM,NDF}) where {DIM,NDF} initialize_solid_neighbor!(ka) end @@ -514,7 +802,7 @@ Collect donor cells, solid cells and IB-adjacent faces into Must be called after [`initialize_faces!`](@ref) and [`initialize_solid_neighbor!`](@ref). """ -function initialize_immersed_boundaries!(ka::KA{DIM,NDF}) where{DIM,NDF} +function initialize_immersed_boundaries!(ka::KA{DIM,NDF}) where {DIM,NDF} ibs = ImmersedBoundary{DIM,NDF}[] if isempty(ka.kinfo.config.IB) ka.kdata.field.immersed_boundaries = ibs @@ -539,4 +827,4 @@ function initialize_immersed_boundaries!(ka::KA{DIM,NDF}) where{DIM,NDF} push!(ibs, ImmersedBoundary{DIM,NDF}(donors, solids, ib_faces)) ka.kdata.field.immersed_boundaries = ibs return nothing -end \ No newline at end of file +end diff --git a/src/Boundary/Parallel.jl b/src/Boundary/Parallel.jl index 5f332fb..cb72409 100644 --- a/src/Boundary/Parallel.jl +++ b/src/Boundary/Parallel.jl @@ -16,23 +16,23 @@ function _mpi_solid_exchange_varsize!( mpisize, proc_offsets, mirror_proc_offsets, mirror_proc_mirrors = _ghost_comm_arrays(ghost) myrank = MPI.Comm_rank(MPI.COMM_WORLD) - comm = MPI.COMM_WORLD + comm = MPI.COMM_WORLD - reqs = Vector{MPI.Request}(undef, 0) + reqs = Vector{MPI.Request}(undef, 0) send_bufs = Vector{Vector{Float64}}(undef, 0) # Each entry: (recv_buf, solid_ghost_indices, solid_ghost_sizes) for one source rank. - recv_infos = Vector{Tuple{Vector{Float64}, Vector{Int}, Vector{Int}}}(undef, 0) + recv_infos = Vector{Tuple{Vector{Float64},Vector{Int},Vector{Int}}}(undef, 0) # --- Post receives grouped by source rank (only solid ghost cells) --- - for r in 0:mpisize-1 + for r = 0:(mpisize-1) r == myrank && continue g_start = Int(proc_offsets[r+1]) + 1 - g_end = Int(proc_offsets[r+2]) + g_end = Int(proc_offsets[r+2]) g_start > g_end && continue - solid_idx = Int[] - solid_szs = Int[] + solid_idx = Int[] + solid_szs = Int[] recv_elems = 0 - for i in g_start:g_end + for i = g_start:g_end sz = ghost_elem_sizes[i] sz == 0 && continue push!(solid_idx, i) @@ -46,19 +46,19 @@ function _mpi_solid_exchange_varsize!( end # --- Post sends grouped by destination rank (only solid mirror cells) --- - for r in 0:mpisize-1 + for r = 0:(mpisize-1) r == myrank && continue mp_start = Int(mirror_proc_offsets[r+1]) + 1 - mp_end = Int(mirror_proc_offsets[r+2]) + mp_end = Int(mirror_proc_offsets[r+2]) mp_start > mp_end && continue send_elems = 0 - for k in mp_start:mp_end - send_elems += mirror_elem_sizes[Int(mirror_proc_mirrors[k]) + 1] + for k = mp_start:mp_end + send_elems += mirror_elem_sizes[Int(mirror_proc_mirrors[k])+1] end send_elems == 0 && continue send_buf = Vector{Float64}(undef, send_elems) off = 0 - for k in mp_start:mp_end + for k = mp_start:mp_end m_idx = Int(mirror_proc_mirrors[k]) + 1 sz = mirror_elem_sizes[m_idx] sz == 0 && continue @@ -74,7 +74,7 @@ function _mpi_solid_exchange_varsize!( for (recv_buf, solid_idx, solid_szs) in recv_infos off = 0 for (i, sz) in zip(solid_idx, solid_szs) - dst = @view ghost_buffer[ghost_offsets[i]+1 : ghost_offsets[i]+sz] + dst = @view ghost_buffer[(ghost_offsets[i]+1):(ghost_offsets[i]+sz)] copyto!(dst, 1, recv_buf, off + 1, sz) off += sz end @@ -96,22 +96,24 @@ function solid_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} update_solid_mirror_data!(p4est, ka) - gb_buf = ka.kdata.ghost.ghost_buffer - gi = ka.kdata.ghost.ghost_info + gb_buf = ka.kdata.ghost.ghost_buffer + gi = ka.kdata.ghost.ghost_info ghost_wrap = ka.kdata.ghost.ghost_wrap # Ghost element sizes: non-zero only for solid-adjacent (bound_enc < 0) ghost cells. - ghost_szs = [(!isa(gw, GhostInsideSolidData) && gw.bound_enc < 0) ? - size_Ghost_Data(gi.ghost_vsnums[i], DIM, NDF) : 0 - for (i, gw) in enumerate(ghost_wrap)] + ghost_szs = [ + (!isa(gw, GhostInsideSolidData) && gw.bound_enc < 0) ? + size_Ghost_Data(gi.ghost_vsnums[i], DIM, NDF) : 0 for + (i, gw) in enumerate(ghost_wrap) + ] # Mirror element sizes: non-zero only for solid-adjacent mirror cells. - n_mirrors = length(gi.mirror_vsnums) + n_mirrors = length(gi.mirror_vsnums) mirror_szs = Vector{Int}(undef, n_mirrors) GC.@preserve p4est ka begin ghost_pw = PointerWrapper(ka.kinfo.forest.ghost) pp = PointerWrapper(p4est) - for i in 1:n_mirrors + for i = 1:n_mirrors pq = pw_mirror_quadrant(pp, ghost_pw, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) @@ -122,8 +124,13 @@ function solid_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} _mpi_solid_exchange_varsize!( ka.kinfo.forest.ghost, - gb_buf.ghost_datas, gi.ghost_data_offsets, - ghost_szs, gb_buf.mirror_data_bufs, mirror_szs, 51) + gb_buf.ghost_datas, + gi.ghost_data_offsets, + ghost_szs, + gb_buf.mirror_data_bufs, + mirror_szs, + 51, + ) return nothing end @@ -138,7 +145,7 @@ MPI request handles are stored in `ka.kinfo.status.mpi_reqs`. function solid_exchange_begin!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} reqs = ka.kinfo.status.mpi_reqs empty!(reqs) - recv_bufs = Tuple{Vector{Float64}, Vector{Int}, Vector{Int}}[] + recv_bufs = Tuple{Vector{Float64},Vector{Int},Vector{Int}}[] send_bufs = Vector{Vector{Float64}}(undef, 0) MPI.Comm_size(MPI.COMM_WORLD) == 1 && return (recv_bufs, send_bufs) @@ -146,20 +153,22 @@ function solid_exchange_begin!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF update_solid_mirror_data!(p4est, ka) - gb_buf = ka.kdata.ghost.ghost_buffer - gi = ka.kdata.ghost.ghost_info + gb_buf = ka.kdata.ghost.ghost_buffer + gi = ka.kdata.ghost.ghost_info ghost_wrap = ka.kdata.ghost.ghost_wrap - ghost_szs = [(!isa(gw, GhostInsideSolidData) && gw.bound_enc < 0) ? - size_Ghost_Data(gi.ghost_vsnums[i], DIM, NDF) : 0 - for (i, gw) in enumerate(ghost_wrap)] + ghost_szs = [ + (!isa(gw, GhostInsideSolidData) && gw.bound_enc < 0) ? + size_Ghost_Data(gi.ghost_vsnums[i], DIM, NDF) : 0 for + (i, gw) in enumerate(ghost_wrap) + ] - n_mirrors = length(gi.mirror_vsnums) + n_mirrors = length(gi.mirror_vsnums) mirror_szs = Vector{Int}(undef, n_mirrors) GC.@preserve p4est ka begin ghost_pw = PointerWrapper(ka.kinfo.forest.ghost) pp = PointerWrapper(p4est) - for i in 1:n_mirrors + for i = 1:n_mirrors pq = pw_mirror_quadrant(pp, ghost_pw, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) @@ -168,22 +177,22 @@ function solid_exchange_begin!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF end end - ghost = ka.kinfo.forest.ghost + ghost = ka.kinfo.forest.ghost mpisize, proc_offsets, mirror_proc_offsets, mirror_proc_mirrors = _ghost_comm_arrays(ghost) myrank = MPI.Comm_rank(MPI.COMM_WORLD) - comm = MPI.COMM_WORLD + comm = MPI.COMM_WORLD # Post receives into per-rank temporary buffers - for r in 0:mpisize-1 + for r = 0:(mpisize-1) r == myrank && continue g_start = Int(proc_offsets[r+1]) + 1 - g_end = Int(proc_offsets[r+2]) + g_end = Int(proc_offsets[r+2]) g_start > g_end && continue - solid_idx = Int[] - solid_szs = Int[] + solid_idx = Int[] + solid_szs = Int[] recv_elems = 0 - for i in g_start:g_end + for i = g_start:g_end sz = ghost_szs[i] sz == 0 && continue push!(solid_idx, i) @@ -197,19 +206,19 @@ function solid_exchange_begin!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF end # Post sends - for r in 0:mpisize-1 + for r = 0:(mpisize-1) r == myrank && continue mp_start = Int(mirror_proc_offsets[r+1]) + 1 - mp_end = Int(mirror_proc_offsets[r+2]) + mp_end = Int(mirror_proc_offsets[r+2]) mp_start > mp_end && continue send_elems = 0 - for k in mp_start:mp_end - send_elems += mirror_szs[Int(mirror_proc_mirrors[k]) + 1] + for k = mp_start:mp_end + send_elems += mirror_szs[Int(mirror_proc_mirrors[k])+1] end send_elems == 0 && continue send_buf = Vector{Float64}(undef, send_elems) off = 0 - for k in mp_start:mp_end + for k = mp_start:mp_end m_idx = Int(mirror_proc_mirrors[k]) + 1 sz = mirror_szs[m_idx] sz == 0 && continue @@ -250,7 +259,7 @@ function solid_exchange_finish!(ka::KA{DIM,NDF}, exchange_buffers) where {DIM,ND for (recv_buf, solid_idx, solid_szs) in recv_bufs off = 0 for (i, sz) in zip(solid_idx, solid_szs) - dst = @view ghost_buffer[ghost_offsets[i]+1 : ghost_offsets[i]+sz] + dst = @view ghost_buffer[(ghost_offsets[i]+1):(ghost_offsets[i]+sz)] copyto!(dst, 1, recv_buf, off + 1, sz) off += sz end diff --git a/src/Boundary/Period.jl b/src/Boundary/Period.jl index 2825076..6bac47f 100644 --- a/src/Boundary/Period.jl +++ b/src/Boundary/Period.jl @@ -1,19 +1,35 @@ -function periodic_ghost_cell(midpoint::Vector,ps_data::AbstractPsData{DIM,NDF}) where{DIM,NDF} +function periodic_ghost_cell( + midpoint::Vector, + ps_data::AbstractPsData{DIM,NDF}, +) where {DIM,NDF} # PsData{DIM,NDF}(ps_data.quadid,ps_data.bound_enc,ps_data.solid_cell_index, # ps_data.ds,midpoint,ps_data.qf,ps_data.w,ps_data.sw,ps_data.prim,ps_data.flux,ps_data.vs_data, # ps_data.neighbor # ) - PsData(ps_data;midpoint) + PsData(ps_data; midpoint) end -function periodic_ghost_cell(midpoint::Vector,ps_data::AbstractGhostPsData{DIM,NDF}) where{DIM,NDF} - GhostPsData{DIM,NDF}(ps_data.owner_rank,ps_data.quadid,ps_data.bound_enc, - ps_data.ds,midpoint,ps_data.w,ps_data.sw,ps_data.vs_data +function periodic_ghost_cell( + midpoint::Vector, + ps_data::AbstractGhostPsData{DIM,NDF}, +) where {DIM,NDF} + GhostPsData{DIM,NDF}( + ps_data.owner_rank, + ps_data.quadid, + ps_data.bound_enc, + ps_data.ds, + midpoint, + ps_data.w, + ps_data.sw, + ps_data.vs_data, ) end -function periodic_ghost_cell(midpoints::Vector{Vector{Float64}},ps_datas::Vector{NeighborQuad{DIM,NDF}}) where{DIM,NDF} - datas = Vector{AbstractPsData{DIM,NDF}}(undef,length(midpoints)) +function periodic_ghost_cell( + midpoints::Vector{Vector{Float64}}, + ps_datas::Vector{NeighborQuad{DIM,NDF}}, +) where {DIM,NDF} + datas = Vector{AbstractPsData{DIM,NDF}}(undef, length(midpoints)) for i in eachindex(midpoints) - datas[i] = periodic_ghost_cell(midpoints[i],ps_datas[i]) + datas[i] = periodic_ghost_cell(midpoints[i], ps_datas[i]) end return datas -end \ No newline at end of file +end diff --git a/src/Boundary/Positivity.jl b/src/Boundary/Positivity.jl index 0df6a1a..d9f76b5 100644 --- a/src/Boundary/Positivity.jl +++ b/src/Boundary/Positivity.jl @@ -1,44 +1,54 @@ -function positivity_preserving_ib!(ps_data::PsData{DIM,NDF},volume,Δt) where{DIM,NDF} +function positivity_preserving_ib!(ps_data::PsData{DIM,NDF}, volume, Δt) where {DIM,NDF} wb = ps_data.w # Positive part if ps_data.bound_enc==0 return nothing else vs_data = ps_data.vs_data - solid_dirs = findall(x->isa(x[1],SolidNeighbor),ps_data.neighbor.data) - micros = zeros(size(vs_data.df,1),size(vs_data.df,2),length(solid_dirs)) + solid_dirs = findall(x->isa(x[1], SolidNeighbor), ps_data.neighbor.data) + micros = zeros(size(vs_data.df, 1), size(vs_data.df, 2), length(solid_dirs)) we = zeros(DIM+2) - for (i,id) in enumerate(solid_dirs) + for (i, id) in enumerate(solid_dirs) solid_neighbor = ps_data.neighbor.data[id][1] - rot = get_rot(id);dir = get_dir(id) + rot = get_rot(id); + dir = get_dir(id) f_midpoint = copy(ps_data.midpoint) f_midpoint[dir] -= 0.5*rot*ps_data.ds[dir] - nheavi = [x>0. for x in rot*@views vs_data.midpoint[:,dir]] - ndf = @views solid_neighbor.vs_data.flux[nheavi,:] - there_mid = @views vs_data.midpoint[nheavi,:] - ndx = [f_midpoint[j]-there_mid[i,j]*Δt-solid_neighbor.midpoint[j] for i in axes(there_mid,1),j in axes(there_mid,2)] - vn = @views there_mid[:,dir] - area = rot*reduce(*,ps_data.ds[FAT[DIM-1][dir]]) - micro = @views micros[nheavi,:,i] - sdf = @views solid_neighbor.vs_data.sdf[nheavi,:,:] - for j in axes(micro,2) - for i in axes(micro,1) - micro[i,j] = @views (ndf[i,j]+dot(ndx[i,:],sdf[i,j,:]))*vn[i]*area + nheavi = [x>0.0 for x in rot*@views vs_data.midpoint[:, dir]] + ndf = @views solid_neighbor.vs_data.flux[nheavi, :] + there_mid = @views vs_data.midpoint[nheavi, :] + ndx = [ + f_midpoint[j]-there_mid[i, j]*Δt-solid_neighbor.midpoint[j] for + i in axes(there_mid, 1), j in axes(there_mid, 2) + ] + vn = @views there_mid[:, dir] + area = rot*reduce(*, ps_data.ds[FAT[DIM-1][dir]]) + micro = @views micros[nheavi, :, i] + sdf = @views solid_neighbor.vs_data.sdf[nheavi, :, :] + for j in axes(micro, 2) + for i in axes(micro, 1) + micro[i, j] = @views (ndf[i, j]+dot(ndx[i, :], sdf[i, j, :]))*vn[i]*area end end - we .+= @views micro_to_macro(micros[:,:,i],vs_data.midpoint,vs_data.weight,vs_data) + we .+= @views micro_to_macro( + micros[:, :, i], + vs_data.midpoint, + vs_data.weight, + vs_data, + ) end we .*= Δt/volume δ = 1e-3 - θρ = we[1] >0 ? 1. : min(1.,(1-δ)*wb[1]/(abs(we[1])+eps())) - rub = wb[2:end-1];rue = we[2:end-1] - eb = wb[end]-(sum(abs2,rub))/(2*wb[1]) - ee = we[end]-dot(rub,rue)/wb[1] - γ = sum(abs2,rue)/(2*wb[1]) - θe = min(1.,2*(1-δ)*eb/(√(ee^2+4*γ*(1-δ)*eb)-ee+eps())) - θ = min(θρ,θe) + θρ = we[1] > 0 ? 1.0 : min(1.0, (1-δ)*wb[1]/(abs(we[1])+eps())) + rub = wb[2:(end-1)]; + rue = we[2:(end-1)] + eb = wb[end]-(sum(abs2, rub))/(2*wb[1]) + ee = we[end]-dot(rub, rue)/wb[1] + γ = sum(abs2, rue)/(2*wb[1]) + θe = min(1.0, 2*(1-δ)*eb/(√(ee^2+4*γ*(1-δ)*eb)-ee+eps())) + θ = min(θρ, θe) wb .+= θ*we - for i in axes(micros,3) - vs_data.flux .+= @views θ*micros[:,:,i] + for i in axes(micros, 3) + vs_data.flux .+= @views θ*micros[:, :, i] end end -end \ No newline at end of file +end diff --git a/src/Boundary/Triangles.jl b/src/Boundary/Triangles.jl index 0a3e54d..1603841 100644 --- a/src/Boundary/Triangles.jl +++ b/src/Boundary/Triangles.jl @@ -1,80 +1,88 @@ -function triangle_box_table(kdt::KDTree,mesh::Mesh) +function triangle_box_table(kdt::KDTree, mesh::Mesh) tree_data = kdt.tree_data n_nodes = tree_data.n_internal_nodes n_leaves = tree_data.n_leafs - table = Vector{HyperRectangle{SVector{3,Float64}}}(undef,n_nodes+n_leaves) + table = Vector{HyperRectangle{SVector{3,Float64}}}(undef, n_nodes+n_leaves) lv = leaves(kdt) - lower = Inf*ones(3);upper = -Inf*ones(3) + lower = Inf*ones(3); + upper = -Inf*ones(3) for node in lv id = node.index ids = leaf_point_indices(node) for j in eachindex(ids) vertices = mesh.position[mesh.faces[ids[j]]] - for k in 1:3 - lower.=min.(lower,vertices[k]) - upper.=max.(upper,vertices[k]) + for k = 1:3 + lower.=min.(lower, vertices[k]) + upper.=max.(upper, vertices[k]) end end - table[id] = HyperRectangle(SVector{3,Float64}(lower),SVector{3,Float64}(upper)) - lower.=Inf;upper.=-Inf + table[id] = HyperRectangle(SVector{3,Float64}(lower), SVector{3,Float64}(upper)) + lower.=Inf; + upper.=-Inf end for node in PostOrderDFS(treeroot(kdt)) isempty(children(node))&&continue # is a leaf? - left_child,right_child = children(node) - lid = left_child.index;rid = right_child.index - lower.=min.(table[lid].mins,table[rid].mins) - upper.=max.(table[lid].maxes,table[rid].maxes) - table[node.index] = HyperRectangle(SVector{3,Float64}(lower),SVector{3,Float64}(upper)) - lower .= Inf;upper .= -Inf + left_child, right_child = children(node) + lid = left_child.index; + rid = right_child.index + lower.=min.(table[lid].mins, table[rid].mins) + upper.=max.(table[lid].maxes, table[rid].maxes) + table[node.index] = + HyperRectangle(SVector{3,Float64}(lower), SVector{3,Float64}(upper)) + lower .= Inf; + upper .= -Inf end return table end function triangle_recs(mesh::Mesh) - recs = Vector{HyperRectangle{SVector{3,Float64}}}(undef,length(mesh.faces)) - lower = Inf*ones(3);upper = -Inf*ones(3) + recs = Vector{HyperRectangle{SVector{3,Float64}}}(undef, length(mesh.faces)) + lower = Inf*ones(3); + upper = -Inf*ones(3) for i in eachindex(recs) vertices = mesh.position[mesh.faces[i]] - for j in 1:3 - lower .= min.(lower,vertices[j]) - upper .= max.(upper,vertices[j]) + for j = 1:3 + lower .= min.(lower, vertices[j]) + upper .= max.(upper, vertices[j]) end - recs[i] = HyperRectangle(SVector{3,Float64}(lower),SVector{3,Float64}(upper)) - lower .= Inf; upper .= -Inf + recs[i] = HyperRectangle(SVector{3,Float64}(lower), SVector{3,Float64}(upper)) + lower .= Inf; + upper .= -Inf end return recs end function triangle_edges(mesh::Mesh) - edges = Vector{Vector{SVector{3,Float64}}}(undef,length(mesh.faces)) + edges = Vector{Vector{SVector{3,Float64}}}(undef, length(mesh.faces)) for i in eachindex(mesh.faces) vertices = mesh.position[mesh.faces[i]] - edges[i] = Vector{SVector{3,Float64}}(undef,3) - for j in 1:3 + edges[i] = Vector{SVector{3,Float64}}(undef, 3) + for j = 1:3 edges[i][j] = SVector{3,Float64}(vertices[j%3+1]-vertices[j]) end end return edges end -function SAT_test_1(h,C,edge,V0) - n = cross(edge[1],edge[2]) - l = dot(h,abs.(n)) - s = abs(dot(n,V0-C)) +function SAT_test_1(h, C, edge, V0) + n = cross(edge[1], edge[2]) + l = dot(h, abs.(n)) + s = abs(dot(n, V0-C)) s>l && return false return true end -function SAT_test_2(a,edge,h,V) # note that V are vertices relative to the midpoint of the cell - dij = zeros(3);p = zeros(3) - for j in 1:3 - for i in 1:3 - dij .= cross(a[i],edge[j]) - for k in 1:3 - p[k] = dot(dij,V[k]) +function SAT_test_2(a, edge, h, V) # note that V are vertices relative to the midpoint of the cell + dij = zeros(3); + p = zeros(3) + for j = 1:3 + for i = 1:3 + dij .= cross(a[i], edge[j]) + for k = 1:3 + p[k] = dot(dij, V[k]) end - for k in 1:3 + for k = 1:3 dij[k] = abs(dij[k]) end - r = dot(dij,h) + r = dot(dij, h) if minimum(p) > r||maximum(p) < -r # TBD: replace with min/max return false end @@ -85,37 +93,42 @@ end -function any_intersect_test(midpoint,ds,tkdt::TriangleKDT) - lower = midpoint-0.5*ds;upper = midpoint+0.5*ds - any_recursion_test(treeroot(tkdt.kdt),midpoint,ds,lower,upper,tkdt) +function any_intersect_test(midpoint, ds, tkdt::TriangleKDT) + lower = midpoint-0.5*ds; + upper = midpoint+0.5*ds + any_recursion_test(treeroot(tkdt.kdt), midpoint, ds, lower, upper, tkdt) end -function any_recursion_test(node::TreeNode,midpoint,ds,lower,upper,tkdt) - table = tkdt.table;mesh = tkdt.mesh - recs = tkdt.triangle_recs;edges = tkdt.triangle_edges +function any_recursion_test(node::TreeNode, midpoint, ds, lower, upper, tkdt) + table = tkdt.table; + mesh = tkdt.mesh + recs = tkdt.triangle_recs; + edges = tkdt.triangle_edges id = node.index - if overlap_test(lower,upper,table[id]) # kernel intersect test + if overlap_test(lower, upper, table[id]) # kernel intersect test if isempty(children(node)) ids = leaf_point_indices(node) for i in ids - if overlap_test(lower,upper,recs[i]) - h = 0.5*ds;V = mesh.position[mesh.faces[i]] - if SAT_test_1(h,midpoint,edges[i],V[1]) + if overlap_test(lower, upper, recs[i]) + h = 0.5*ds; + V = mesh.position[mesh.faces[i]] + if SAT_test_1(h, midpoint, edges[i], V[1]) a = [ - SVector{3,Float64}([1,0,0]), - SVector{3,Float64}([0,1,0]), - SVector{3,Float64}([0,0,1]) + SVector{3,Float64}([1, 0, 0]), + SVector{3,Float64}([0, 1, 0]), + SVector{3,Float64}([0, 0, 1]), ] v = [x-midpoint for x in V] - if SAT_test_2(a,edges[i],h,v) + if SAT_test_2(a, edges[i], h, v) return true end end end end else - lc,rc = children(node) - any_intersect_recursion_test(lc,midpoint,ds,lower,upper,tkdt) && return true - return any_intersect_recursion_test(rc,midpoint,ds,lower,upper,tkdt) + lc, rc = children(node) + any_intersect_recursion_test(lc, midpoint, ds, lower, upper, tkdt) && + return true + return any_intersect_recursion_test(rc, midpoint, ds, lower, upper, tkdt) end else return false @@ -123,39 +136,75 @@ function any_recursion_test(node::TreeNode,midpoint,ds,lower,upper,tkdt) end -function all_intersect_test(midpoint,ds,tkdt::TriangleKDT) - lower = midpoint-0.5*ds;upper = midpoint+0.5*ds +function all_intersect_test(midpoint, ds, tkdt::TriangleKDT) + lower = midpoint-0.5*ds; + upper = midpoint+0.5*ds intersect_ids = Int[] - all_intersect_recursion_test!(treeroot(tkdt.kdt),midpoint,ds,lower,upper,tkdt,intersect_ids) + all_intersect_recursion_test!( + treeroot(tkdt.kdt), + midpoint, + ds, + lower, + upper, + tkdt, + intersect_ids, + ) return intersect_ids end -function all_intersect_recursion_test!(node::TreeNode,midpoint,ds,lower,upper,tkdt,intersect_ids::Vector{Int}) - table = tkdt.table;mesh = tkdt.mesh - recs = tkdt.triangle_recs;edges = tkdt.triangle_edges +function all_intersect_recursion_test!( + node::TreeNode, + midpoint, + ds, + lower, + upper, + tkdt, + intersect_ids::Vector{Int}, +) + table = tkdt.table; + mesh = tkdt.mesh + recs = tkdt.triangle_recs; + edges = tkdt.triangle_edges id = node.index - if overlap_test(lower,upper,table[id]) # kernel intersect test + if overlap_test(lower, upper, table[id]) # kernel intersect test if isempty(children(node)) ids = leaf_point_indices(node) for i in ids - if overlap_test(lower,upper,recs[i]) - h = 0.5*ds;V = mesh.position[mesh.faces[i]] - if SAT_test_1(h,midpoint,edges[i],V[1]) + if overlap_test(lower, upper, recs[i]) + h = 0.5*ds; + V = mesh.position[mesh.faces[i]] + if SAT_test_1(h, midpoint, edges[i], V[1]) a = [ - SVector{3,Float64}([1,0,0]), - SVector{3,Float64}([0,1,0]), - SVector{3,Float64}([0,0,1]) + SVector{3,Float64}([1, 0, 0]), + SVector{3,Float64}([0, 1, 0]), + SVector{3,Float64}([0, 0, 1]), ] v = [x-midpoint for x in V] - if SAT_test_2(a,edges[i],h,v) - push!(intersect_ids,i) + if SAT_test_2(a, edges[i], h, v) + push!(intersect_ids, i) end end end end else - lc,rc = children(node) - all_intersect_recursion_test!(lc,midpoint,ds,lower,upper,tkdt,intersect_ids) - all_intersect_recursion_test!(rc,midpoint,ds,lower,upper,tkdt,intersect_ids) + lc, rc = children(node) + all_intersect_recursion_test!( + lc, + midpoint, + ds, + lower, + upper, + tkdt, + intersect_ids, + ) + all_intersect_recursion_test!( + rc, + midpoint, + ds, + lower, + upper, + tkdt, + intersect_ids, + ) end end return nothing @@ -164,7 +213,7 @@ end function line_plane_intersection(midpoint::Vector{Float64}, V, edges, dir) - A,B,C = cross(edges[1],edges[2]) + A, B, C = cross(edges[1], edges[2]) D = -(A*V[1][1]+B*V[1][2]+C*V[1][3]) if dir == 1 y0 = midpoint[2] @@ -192,43 +241,51 @@ function line_plane_intersection(midpoint::Vector{Float64}, V, edges, dir) return [x0, y0, t] end end -function in_triangle_test(point::Vector{Float64},V,edges) - n = cross(edges[1],edges[2]) +function in_triangle_test(point::Vector{Float64}, V, edges) + n = cross(edges[1], edges[2]) p = [point-v for v in V] for i in eachindex(p) - dot(cross(edges[i],p[i]),n)<-eps()&&return false + dot(cross(edges[i], p[i]), n)<-eps()&&return false end return true end -function calc_intersect(f_midpoint,s_midpoint,ds,dir,ib::Triangles) - tkdt = ib.tkdt;mesh = tkdt.mesh - intersect_ids = all_intersect_test(f_midpoint,2.0*ds,tkdt) +function calc_intersect(f_midpoint, s_midpoint, ds, dir, ib::Triangles) + tkdt = ib.tkdt; + mesh = tkdt.mesh + intersect_ids = all_intersect_test(f_midpoint, 2.0*ds, tkdt) for id in intersect_ids V = mesh.position[mesh.faces[id]] edges = ib.tkdt.triangle_edges[id] - intersect_point = line_plane_intersection(f_midpoint,V,edges,dir) + intersect_point = line_plane_intersection(f_midpoint, V, edges, dir) isempty(intersect_point) && continue - (intersect_point[dir]-s_midpoint[dir])*(intersect_point[dir]-f_midpoint[dir])>0 && continue + (intersect_point[dir]-s_midpoint[dir])*(intersect_point[dir]-f_midpoint[dir])>0 && + continue abs((intersect_point[dir]-f_midpoint[dir])/ds[dir])>1.0+eps() && continue - if in_triangle_test(intersect_point,V,edges) - normal = collect(cross(edges[1],edges[2])) - normal = dot(normal,f_midpoint-s_midpoint)>0 ? normal/norm(normal) : -normal/norm(normal) - return intersect_point,normal + if in_triangle_test(intersect_point, V, edges) + normal = collect(cross(edges[1], edges[2])) + normal = + dot(normal, f_midpoint-s_midpoint)>0 ? normal/norm(normal) : + -normal/norm(normal) + return intersect_point, normal end end - return Float64[],Float64[] + return Float64[], Float64[] end """ $(TYPEDSIGNATURES) Whether a quadrant is overlap with the hyper_rec of the immersed boundary. """ -function solid_box_flag(midpoint,ds,ib::Triangles) +function solid_box_flag(midpoint, ds, ib::Triangles) r = ib.search_radius kdt = ib.tkdt.kdt triangle_rec = ib.tkdt.table[treeroot(kdt).index] - hyper_rec = HyperRectangle(SVector{3,Float64}(triangle_rec.mins.-r),SVector{3,Float64}(triangle_rec.maxes.+r)) - lower = midpoint-0.5*ds;upper = midpoint+0.5*ds - if overlap_test(lower,upper,hyper_rec) + hyper_rec = HyperRectangle( + SVector{3,Float64}(triangle_rec.mins .- r), + SVector{3,Float64}(triangle_rec.maxes .+ r), + ) + lower = midpoint-0.5*ds; + upper = midpoint+0.5*ds + if overlap_test(lower, upper, hyper_rec) return true else return false @@ -238,15 +295,19 @@ end $(TYPEDSIGNATURES) Whether a quadrant is inside the refine radius of the immersed boundary. """ -function search_radius_flag!(i::Int,ib::Triangles,midpoint,ds,mesh_data) +function search_radius_flag!(i::Int, ib::Triangles, midpoint, ds, mesh_data) r = ib.search_radius kdt = ib.tkdt.kdt triangle_rec = ib.tkdt.table[treeroot(kdt).index] - hyper_rec = HyperRectangle(SVector{3,Float64}(triangle_rec.mins.-r),SVector{3,Float64}(triangle_rec.maxes.+r)) - lower = midpoint-0.5*ds;upper = midpoint+0.5*ds - if overlap_test(lower,upper,hyper_rec) + hyper_rec = HyperRectangle( + SVector{3,Float64}(triangle_rec.mins .- r), + SVector{3,Float64}(triangle_rec.maxes .+ r), + ) + lower = midpoint-0.5*ds; + upper = midpoint+0.5*ds + if overlap_test(lower, upper, hyper_rec) mesh_data.in_box = i - _,distance = nn(kdt,midpoint) + _, distance = nn(kdt, midpoint) if distance1.0+eps() && continue - in_triangle_test(intersect_point,V,edges) && return true + in_triangle_test(intersect_point, V, edges) && return true end end return false end function cell_type_decision!(p4est::Ptr{p4est_t}) - AMR_volume_iterate(p4est) do ip,_,dp - kinfo,_ = unsafe_pointer_to_objref(pointer(ip.p4est.user_pointer)) + AMR_volume_iterate(p4est) do ip, _, dp + kinfo, _ = unsafe_pointer_to_objref(pointer(ip.p4est.user_pointer)) mesh_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - ds,midpoint = quad_to_cell(ip.p4est,ip.treeid[],ip.quad) + ds, midpoint = quad_to_cell(ip.p4est, ip.treeid[], ip.quad) if mesh_data.in_box!=0 ib = kinfo.config.IB[mesh_data.in_box] - mesh_data.in_solid = solid_flag(ib,midpoint) + mesh_data.in_solid = solid_flag(ib, midpoint) if mesh_data.in_search_radius!=0&&mesh_data.in_solid - mesh_data.is_ghost_cell = ghost_cell_flag(ib,midpoint,ds) + mesh_data.is_ghost_cell = ghost_cell_flag(ib, midpoint, ds) end else ibs = kinfo.config.IB @@ -317,15 +382,15 @@ function cell_type_decision!(p4est::Ptr{p4est_t}) end end function cell_type_decision!(p4est::Ptr{p8est_t}) - AMR_volume_iterate(p4est) do ip,_,dp - kinfo,_ = unsafe_pointer_to_objref(pointer(ip.p4est.user_pointer)) + AMR_volume_iterate(p4est) do ip, _, dp + kinfo, _ = unsafe_pointer_to_objref(pointer(ip.p4est.user_pointer)) mesh_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - ds,midpoint = quad_to_cell(ip.p4est,ip.treeid[],ip.quad) + ds, midpoint = quad_to_cell(ip.p4est, ip.treeid[], ip.quad) if mesh_data.in_box!=0 ib = kinfo.config.IB[mesh_data.in_box] - mesh_data.in_solid = solid_flag(ib,midpoint) + mesh_data.in_solid = solid_flag(ib, midpoint) if mesh_data.in_search_radius!=0&&mesh_data.in_solid - mesh_data.is_ghost_cell = ghost_cell_flag(ib,midpoint,ds) + mesh_data.is_ghost_cell = ghost_cell_flag(ib, midpoint, ds) end else ibs = kinfo.config.IB @@ -346,70 +411,89 @@ function ray_casting(ib::Triangles, midpoint) # Inside the closed surface? center = 0.5*(kdt.hyper_rec.mins[dir]+kdt.hyper_rec.maxes[dir]) is_pos = center=-eps()&&u>=-eps()&&v>=eps()&&(1.0-u-v>=-eps()) return true else return false end end -function Moller_Trumbore_line_test(midpoint,e,V) - e1 = V[2]-V[1];e2 = V[3]-V[1] - h = cross(e,e2) - a = dot(h,e1) +function Moller_Trumbore_line_test(midpoint, e, V) + e1 = V[2]-V[1]; + e2 = V[3]-V[1] + h = cross(e, e2) + a = dot(h, e1) if abs(a)=-eps()&&v>=eps()&&(1.0-u-v>=-eps()) return true @@ -417,9 +501,12 @@ function Moller_Trumbore_line_test(midpoint,e,V) return false end end -function ray_casting_rectangle_test(hyper_rec::HyperRectangle,midpoint,dir,is_pos) - dir2 = dir%3+1;dir3 = (dir+1)%3+1 - if (hyper_rec.mins[dir2]<=midpoint[dir2]<=hyper_rec.maxes[dir2])&&(hyper_rec.mins[dir3]<=midpoint[dir3]<=hyper_rec.maxes[dir3]) +function ray_casting_rectangle_test(hyper_rec::HyperRectangle, midpoint, dir, is_pos) + dir2 = dir%3+1; + dir3 = (dir+1)%3+1 + if (hyper_rec.mins[dir2]<=midpoint[dir2]<=hyper_rec.maxes[dir2])&&( + hyper_rec.mins[dir3]<=midpoint[dir3]<=hyper_rec.maxes[dir3] + ) if is_pos flag = hyper_rec.maxes[dir]>=midpoint[dir] else @@ -431,6 +518,14 @@ function ray_casting_rectangle_test(hyper_rec::HyperRectangle,midpoint,dir,is_po end end -function calc_IB_ρw(aux_point::AbstractVector,bound::Triangles,midpoint::AbstractMatrix,weight::AbstractVector,df::AbstractMatrix,vn::AbstractVector,Θ::AbstractVector) - calc_IB_ρw_3D(aux_point,bound.bc,midpoint,weight,df,vn,Θ) -end \ No newline at end of file +function calc_IB_ρw( + aux_point::AbstractVector, + bound::Triangles, + midpoint::AbstractMatrix, + weight::AbstractVector, + df::AbstractMatrix, + vn::AbstractVector, + Θ::AbstractVector, +) + calc_IB_ρw_3D(aux_point, bound.bc, midpoint, weight, df, vn, Θ) +end diff --git a/src/Boundary/Types.jl b/src/Boundary/Types.jl index 1c821ca..5a7d219 100644 --- a/src/Boundary/Types.jl +++ b/src/Boundary/Types.jl @@ -7,17 +7,22 @@ Structure of domain boundary. ## Fields $(TYPEDFIELDS) - """ struct Domain{T<:AbstractBoundCond} <: AbstractBoundary - "Index of the domain boundary. From 1 to 6, it represents the boundary of `xmin`, `xmax`, `ymin`, `ymax`, `zmin`, `zmax`." + """ + Index of the domain boundary. From 1 to 6, it represents the boundary of `xmin`, `xmax`, `ymin`, `ymax`, `zmin`, `zmax`. + """ id::Int - "Whether refine at the domain boundary. Default is `false`." + """ + Whether refine at the domain boundary. Default is `false`. + """ refine::Bool - "The boundary condition at the domain boundary." + """ + The boundary condition at the domain boundary. + """ bc::AbstractBCType - Domain(T,id;refine=false) = new{T}(id,refine) - Domain(T,id,bc;refine=false) = new{T}(id,refine,bc) + Domain(T, id; refine = false) = new{T}(id, refine) + Domain(T, id, bc; refine = false) = new{T}(id, refine, bc) end """ @@ -38,26 +43,40 @@ $(TYPEDEF) $(TYPEDFIELDS) """ struct Circle{T<:AbstractBoundCond} <: AbstractBoundary - "Center of the circle." + """ + Center of the circle. + """ center::Vector - "Radius of the circle." + """ + Radius of the circle. + """ radius::Real - "Is solid inside the circle?" + """ + Is solid inside the circle? # If is solid inside the circle, it should be true. Otherwise, it should be false. + """ solid::Bool # If is solid inside the circle, it should be true. Otherwise, it should be false. - "Refinement coefficient." + """ + Refinement coefficient. # The ratio of the search radius and the minimal mesh scale, which determines the maximal distance between IB nodes and aux_points. + """ search_coeffi::Real # The ratio of the search radius and the minimal mesh scale, which determines the maximal distance between IB nodes and aux_points. - "Primary macroscopic variables of the solid." + """ + Primary macroscopic variables of the solid. + """ bc::AbstractBCType - "Maximum distance of the refinement region from the boundary." + """ + Maximum distance of the refinement region from the boundary. + """ search_radius::Real - Circle(::Type{T},center::Vector,radius,solid,search_coeffi,bc) where{T<:AbstractBoundCond} = new{T}(center,radius,solid,search_coeffi,bc) - Circle(c::Circle{T},ds::Float64) where{T<:AbstractBoundCond} = new{T}(c.center, - c.radius, - c.solid, - c.search_coeffi, - c.bc, - c.search_coeffi*ds - ) + Circle( + ::Type{T}, + center::Vector, + radius, + solid, + search_coeffi, + bc, + ) where {T<:AbstractBoundCond} = new{T}(center, radius, solid, search_coeffi, bc) + Circle(c::Circle{T}, ds::Float64) where {T<:AbstractBoundCond} = + new{T}(c.center, c.radius, c.solid, c.search_coeffi, c.bc, c.search_coeffi*ds) end """ $(TYPEDEF) @@ -70,14 +89,16 @@ struct Sphere{T<:AbstractBoundCond} <: AbstractBoundary # 3D circle search_coeffi::Real bc::AbstractBCType search_radius::Real - Sphere(::Type{T},center::Vector,radius,solid,search_coeffi,bc) where{T<:AbstractBoundCond} = new{T}(center,radius,solid,search_coeffi,bc) - Sphere(c::Sphere{T},ds::Float64) where{T<:AbstractBoundCond} = new{T}(c.center, - c.radius, - c.solid, - c.search_coeffi, - c.bc, - c.search_coeffi*ds - ) + Sphere( + ::Type{T}, + center::Vector, + radius, + solid, + search_coeffi, + bc, + ) where {T<:AbstractBoundCond} = new{T}(center, radius, solid, search_coeffi, bc) + Sphere(c::Sphere{T}, ds::Float64) where {T<:AbstractBoundCond} = + new{T}(c.center, c.radius, c.solid, c.search_coeffi, c.bc, c.search_coeffi*ds) end const AbstractCircle = Union{Circle,Sphere} @@ -86,33 +107,58 @@ $(TYPEDEF) $(TYPEDFIELDS) """ struct Vertices{DIM,T<:AbstractBoundCond} <: AbstractBoundary - "Vertices of the boundary, sorted in clockwise or counterclockwise order. " + """ + Vertices of the boundary, sorted in clockwise or counterclockwise order. + """ vertices::Vector{Vector{Float64}} solid::Bool # Is solid inside the boundary? bc::AbstractBCType - "The outer box of the vertices as `[[xmin,ymin,zmin],[xmax,ymax,zmax]]`." + """ + The outer box of the vertices as `[[xmin,ymin,zmin],[xmax,ymax,zmax]]`. + """ box::Vector{Vector{Float64}} - "The number of cell layers refined from the boundary." + """ + The number of cell layers refined from the boundary. + """ search_radius::Real end """ $(TYPEDSIGNATURES) -- `file` is the path to the `.csv` file. + + - `file` is the path to the `.csv` file. """ -function Vertices(::Type{T},file::String,solid,refine_coeffi,bc) where{T<:AbstractBoundCond} - s = CSV.read(file,DataFrame;header=true) +function Vertices( + ::Type{T}, + file::String, + solid, + refine_coeffi, + bc, +) where {T<:AbstractBoundCond} + s = CSV.read(file, DataFrame; header = true) DIM = length(names(s)) - vertices = [[s.x[i],s.y[i]] for i in eachindex(s.x)] + vertices = [[s.x[i], s.y[i]] for i in eachindex(s.x)] if vertices[1]==vertices[end] - vertices = vertices[1:end-1] + vertices = vertices[1:(end-1)] end - box = [[minimum(s.x),minimum(s.y)],[maximum(s.x),maximum(s.y)]] - return Vertices{DIM,T}(vertices,solid,bc,box,refine_coeffi) + box = [[minimum(s.x), minimum(s.y)], [maximum(s.x), maximum(s.y)]] + return Vertices{DIM,T}(vertices, solid, bc, box, refine_coeffi) end -function Vertices(v::Vertices{DIM,T},config) where{DIM,T<:AbstractBoundCond} - ds_max = maximum([(config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i] for i in 1:config[:DIM]]) - ds = norm([(config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i]/2^config[:AMR_PS_MAXLEVEL] for i in 1:config[:DIM]]) - return Vertices{DIM,T}(v.vertices,v.solid,v.bc,[v.box[1].-ds_max,v.box[2].+ds_max],v.search_radius*ds) +function Vertices(v::Vertices{DIM,T}, config) where {DIM,T<:AbstractBoundCond} + ds_max = maximum([ + (config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i] for + i = 1:config[:DIM] + ]) + ds = norm([ + (config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i]/2^config[:AMR_PS_MAXLEVEL] + for i = 1:config[:DIM] + ]) + return Vertices{DIM,T}( + v.vertices, + v.solid, + v.bc, + [v.box[1] .- ds_max, v.box[2] .+ ds_max], + v.search_radius*ds, + ) end """ @@ -127,17 +173,23 @@ struct TriangleKDT triangle_edges::Vector{Vector{SVector{3,Float64}}} # Accessed by id of mesh.faces end function TriangleKDT(mesh::Mesh) - centers = zeros(3,length(mesh.faces)) + centers = zeros(3, length(mesh.faces)) for i in eachindex(mesh.faces) vertices = mesh.position[mesh.faces[i]] - for j in 1:3 - for k in 1:3 - centers[j,i] += vertices[k][j]/3.0 + for j = 1:3 + for k = 1:3 + centers[j, i] += vertices[k][j]/3.0 end end end - kdt = KDTree(centers;leafsize = 24) - return TriangleKDT(kdt,mesh,triangle_box_table(kdt,mesh),triangle_recs(mesh),triangle_edges(mesh)) + kdt = KDTree(centers; leafsize = 24) + return TriangleKDT( + kdt, + mesh, + triangle_box_table(kdt, mesh), + triangle_recs(mesh), + triangle_edges(mesh), + ) end """ @@ -152,19 +204,36 @@ struct Triangles{T<:AbstractBoundCond} <: AbstractBoundary end """ $(TYPEDSIGNATURES) -- `file` is the path to the `.stl` file. + + - `file` is the path to the `.stl` file. """ -function Triangles(::Type{T},file::String,solid,search_radius,bc) where{T<:AbstractBoundCond} +function Triangles( + ::Type{T}, + file::String, + solid, + search_radius, + bc, +) where {T<:AbstractBoundCond} mesh = load(file) tkdt = TriangleKDT(mesh) - return Triangles{T}(solid,bc,search_radius,tkdt) + return Triangles{T}(solid, bc, search_radius, tkdt) end -function Triangles(::Type{T},solid::Bool,search_radius,bc,tkdt::TriangleKDT,config) where{T<:AbstractBoundCond} - ds = norm([(config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i]/2^config[:AMR_PS_MAXLEVEL] for i in 1:config[:DIM]]) - return Triangles{T}(solid,bc,search_radius*ds,tkdt) +function Triangles( + ::Type{T}, + solid::Bool, + search_radius, + bc, + tkdt::TriangleKDT, + config, +) where {T<:AbstractBoundCond} + ds = norm([ + (config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i]/2^config[:AMR_PS_MAXLEVEL] + for i = 1:config[:DIM] + ]) + return Triangles{T}(solid, bc, search_radius*ds, tkdt) end -function Triangles(ib::Triangles{T},config) where{T} - return Triangles(T,ib.solid,ib.search_radius,ib.bc,ib.tkdt,config) +function Triangles(ib::Triangles{T}, config) where {T} + return Triangles(T, ib.solid, ib.search_radius, ib.bc, ib.tkdt, config) end @@ -176,9 +245,9 @@ mutable struct SolidCells{DIM,NDF} quadids provide the information of solidcells on other processors. Only after this, the exchange of IB nodes can be executeable. =# end -function SolidCells(ps_datas::Vector{PsData{DIM,NDF}}) where{DIM,NDF} +function SolidCells(ps_datas::Vector{PsData{DIM,NDF}}) where {DIM,NDF} quadids = [x.quadid for x in ps_datas] - return SolidCells{DIM,NDF}(ps_datas,quadids) + return SolidCells{DIM,NDF}(ps_datas, quadids) end """ @@ -190,10 +259,16 @@ scanning every cell in the tree. $(TYPEDFIELDS) """ mutable struct ImmersedBoundary{DIM,NDF} - "Donor cells (`bound_enc > 0`)." + """ + Donor cells (`bound_enc > 0`). + """ donor_cells::Vector{AbstractPsData{DIM,NDF}} - "Solid cells (`bound_enc < 0`, excluding `InsideSolidData`)." + """ + Solid cells (`bound_enc < 0`, excluding `InsideSolidData`). + """ solid_cells::Vector{AbstractPsData{DIM,NDF}} - "Faces that involve a `SolidNeighbor` on one side." + """ + Faces that involve a `SolidNeighbor` on one side. + """ faces::Vector{AbstractFace} end diff --git a/src/Boundary/Vertices.jl b/src/Boundary/Vertices.jl index c87401e..169e957 100644 --- a/src/Boundary/Vertices.jl +++ b/src/Boundary/Vertices.jl @@ -1,17 +1,28 @@ -function boundary_flag(boundary::Vertices,midpoint::AbstractVector,ds::AbstractVector,::Union{KInfo,Nothing}) # Circle type IB boundary flag +function boundary_flag( + boundary::Vertices, + midpoint::AbstractVector, + ds::AbstractVector, + ::Union{KInfo,Nothing}, +) # Circle type IB boundary flag # (boundary.box[1][1]>midpoint[1]||boundary.box[2][1]midpoint[2]||boundary.box[2][2] box_lower) end -function search_radius_flag!(i::Int,ib::Vertices,midpoint,ds,mesh_data) - solid_box_flag(midpoint,ds,ib) || return false +function search_radius_flag!(i::Int, ib::Vertices, midpoint, ds, mesh_data) + solid_box_flag(midpoint, ds, ib) || return false mesh_data.in_box = i r = ib.search_radius distance = minimum(norm(midpoint .- v) for v in ib.vertices) @@ -30,56 +41,74 @@ function search_radius_flag!(i::Int,ib::Vertices,midpoint,ds,mesh_data) end return false end -function search_radius_flag(ib::Vertices,midpoint,ds) - solid_box_flag(midpoint,ds,ib) || return false +function search_radius_flag(ib::Vertices, midpoint, ds) + solid_box_flag(midpoint, ds, ib) || return false r = ib.search_radius distance = minimum(norm(midpoint .- v) for v in ib.vertices) return distance < r + 0.5*norm(ds) end -function ghost_cell_flag(ib::Vertices{2},midpoint,ds) - return boundary_flag(ib,midpoint,ds,nothing) +function ghost_cell_flag(ib::Vertices{2}, midpoint, ds) + return boundary_flag(ib, midpoint, ds, nothing) end -function solid_flag(boundary::Vertices,midpoint::AbstractVector) # Does midpoint locate at solid? - inbox = (boundary.box[1][1]midpoint[1]&&boundary.box[1][2]midpoint[2]) - return xor(!(inbox&&ray_casting(midpoint,boundary.vertices)),boundary.solid) +function solid_flag(boundary::Vertices, midpoint::AbstractVector) # Does midpoint locate at solid? + inbox = ( + boundary.box[1][1]midpoint[1]&&boundary.box[1][2]midpoint[2] + ) + return xor(!(inbox&&ray_casting(midpoint, boundary.vertices)), boundary.solid) end -function IB_prim(circle::Vertices,aux_point::AbstractVector,ρw::Real) - IB_prim(circle.bc,aux_point,ρw) +function IB_prim(circle::Vertices, aux_point::AbstractVector, ρw::Real) + IB_prim(circle.bc, aux_point, ρw) end -function calc_IB_ρw(aux_point::AbstractVector,bound::Vertices{2},midpoint::AbstractMatrix,weight::AbstractVector,df::AbstractMatrix,vn::AbstractVector,Θ::AbstractVector) - calc_IB_ρw_2D(aux_point,bound.bc,midpoint,weight,df,vn,Θ) +function calc_IB_ρw( + aux_point::AbstractVector, + bound::Vertices{2}, + midpoint::AbstractMatrix, + weight::AbstractVector, + df::AbstractMatrix, + vn::AbstractVector, + Θ::AbstractVector, +) + calc_IB_ρw_2D(aux_point, bound.bc, midpoint, weight, df, vn, Θ) end -function calc_IB_ρw(aux_point::AbstractVector,bound::Vertices{3},midpoint::AbstractMatrix,weight::AbstractVector,df::AbstractMatrix,vn::AbstractVector,Θ::AbstractVector) - calc_IB_ρw_3D(aux_point,bound.bc,midpoint,weight,df,vn,Θ) +function calc_IB_ρw( + aux_point::AbstractVector, + bound::Vertices{3}, + midpoint::AbstractMatrix, + weight::AbstractVector, + df::AbstractMatrix, + vn::AbstractVector, + Θ::AbstractVector, +) + calc_IB_ρw_3D(aux_point, bound.bc, midpoint, weight, df, vn, Θ) end -function calc_intersect(f_midpoint,s_midpoint,::Vector,::Int,boundary::Vertices{2}) - find_intersections_2D(s_midpoint,f_midpoint,boundary.vertices) +function calc_intersect(f_midpoint, s_midpoint, ::Vector, ::Int, boundary::Vertices{2}) + find_intersections_2D(s_midpoint, f_midpoint, boundary.vertices) end -function ray_casting(point::Vector{Float64},vertices::Vector{Vector{Float64}}) # Inside the closed curve? +function ray_casting(point::Vector{Float64}, vertices::Vector{Vector{Float64}}) # Inside the closed curve? n = length(vertices) count = 0 - for i in 1:n + for i = 1:n j = (i % n) + 1 x_i, y_i = vertices[i] x_j, y_j = vertices[j] px, py = point if (py > min(y_i, y_j)) && (py <= max(y_i, y_j)) - if y_i == y_j + if y_i == y_j continue end x_intersect = (py-y_i) * (x_j - x_i) / (y_j - y_i) + x_i if x_intersect > px && (x_intersect <= max(x_i, x_j)) - count +=1 + count += 1 end end end return (count % 2) == 1 end -function calc_normal(p1,p2,s1,s2) # Calculate the unit normal vector of the vector (s2-s1), in the direction of (p2-p1). - n = [s2[2]-s1[2],s1[1]-s2[1]] +function calc_normal(p1, p2, s1, s2) # Calculate the unit normal vector of the vector (s2-s1), in the direction of (p2-p1). + n = [s2[2]-s1[2], s1[1]-s2[1]] n /= norm(n) - if dot(n,p2-p1)<0 + if dot(n, p2-p1)<0 n = -n end return n @@ -88,9 +117,9 @@ function find_horizontal_intersection(s_midpoint, f_midpoint, points) n = length(points) x_seg_min, x_seg_max = minmax(s_midpoint[1], f_midpoint[1]) y0 = s_midpoint[2] - for i in 1:n + for i = 1:n p1 = points[i] - p2 = points[i%n + 1] + p2 = points[i%n+1] x1, y1 = p1 x2, y2 = p2 if (y1 ≤ y0 ≤ y2) || (y2 ≤ y0 ≤ y1) @@ -98,7 +127,7 @@ function find_horizontal_intersection(s_midpoint, f_midpoint, points) if 0 < t < 1 x_intersect = x1 + t * (x2 - x1) if x_seg_min ≤ x_intersect ≤ x_seg_max - return [x_intersect, y0],calc_normal(s_midpoint, f_midpoint, p1, p2) + return [x_intersect, y0], calc_normal(s_midpoint, f_midpoint, p1, p2) end elseif t==1 x_intersect = x1 + t * (x2 - x1) @@ -106,23 +135,24 @@ function find_horizontal_intersection(s_midpoint, f_midpoint, points) p3 = points[i%n+2] n1 = calc_normal(s_midpoint, f_midpoint, p1, p2) n2 = calc_normal(s_midpoint, f_midpoint, p2, p3) - n0 = n1+n2;n0/=norm(n0) - return [x_intersect, y0],n0 + n0 = n1+n2; + n0/=norm(n0) + return [x_intersect, y0], n0 end end end end @show s_midpoint f_midpoint throw("Intersect error!") - return Float64[],Float64[] + return Float64[], Float64[] end function find_vertical_intersection(s_midpoint, f_midpoint, points) n = length(points) y_seg_min, y_seg_max = minmax(s_midpoint[2], f_midpoint[2]) x0 = s_midpoint[1] - for i in 1:n + for i = 1:n p1 = points[i] - p2 = points[i%n + 1] + p2 = points[i%n+1] x1, y1 = p1 x2, y2 = p2 if (x1 ≤ x0 ≤ x2) || (x2 ≤ x0 ≤ x1) @@ -130,7 +160,7 @@ function find_vertical_intersection(s_midpoint, f_midpoint, points) if 0 < t < 1 y_intersect = y1 + t * (y2 - y1) if y_seg_min ≤ y_intersect ≤ y_seg_max - return [x0, y_intersect],calc_normal(s_midpoint, f_midpoint, p1, p2) + return [x0, y_intersect], calc_normal(s_midpoint, f_midpoint, p1, p2) end elseif t==1 y_intersect = y1 + t * (y2 - y1) @@ -138,15 +168,16 @@ function find_vertical_intersection(s_midpoint, f_midpoint, points) p3 = points[i%n+2] n1 = calc_normal(s_midpoint, f_midpoint, p1, p2) n2 = calc_normal(s_midpoint, f_midpoint, p2, p3) - n0 = n1+n2;n0/=norm(n0) - return [x0, y_intersect],n0 + n0 = n1+n2; + n0/=norm(n0) + return [x0, y_intersect], n0 end end end end @show s_midpoint f_midpoint throw("Intersect error!") - return Float64[],Float64[] + return Float64[], Float64[] end function find_intersections_2D(s_midpoint, f_midpoint, closed_curve) x1, y1 = s_midpoint @@ -159,4 +190,4 @@ function find_intersections_2D(s_midpoint, f_midpoint, closed_curve) @show s_midpoint f_midpoint throw("Horizontal or vertical line segment is expected!") end -end \ No newline at end of file +end diff --git a/src/Flux/CAIDVM.jl b/src/Flux/CAIDVM.jl index 717ff15..cac114e 100644 --- a/src/Flux/CAIDVM.jl +++ b/src/Flux/CAIDVM.jl @@ -1,130 +1,247 @@ """ $(TYPEDSIGNATURES) """ -function calc_domain_flux(::Type{CAIDVM},here_vs::FaceVsData,face::DomainFace{DIM,NDF,Maxwellian},ka::KA) where{DIM,NDF} - _,direction,midpoint,_,ps_data = unpack(face) - heavi,here_weight,here_mid,here_vn,here_df,here_sdf = unpack(here_vs) +function calc_domain_flux( + ::Type{CAIDVM}, + here_vs::FaceVsData, + face::DomainFace{DIM,NDF,Maxwellian}, + ka::KA, +) where {DIM,NDF} + _, direction, midpoint, _, ps_data = unpack(face) + heavi, here_weight, here_mid, here_vn, here_df, here_sdf = unpack(here_vs) Δt = ka.kinfo.status.Δt vs_data = ps_data.vs_data nheavi = [!x for x in heavi] - there_mid = @views vs_data.midpoint[nheavi,:] + there_mid = @views vs_data.midpoint[nheavi, :] there_weight = @views vs_data.weight[nheavi] - there_vn = @views there_mid[:,direction] - @inbounds @views dx = [midpoint[j]-here_mid[i,j]*Δt-ps_data.midpoint[j] for i in axes(here_mid,1),j in axes(here_mid,2)] - @inbounds @views df = [here_df[i,j]+dot(dx[i,:],here_sdf[i,j,:]) for i in axes(here_df,1),j in axes(here_df,2)] + there_vn = @views there_mid[:, direction] + @inbounds @views dx = [ + midpoint[j]-here_mid[i, j]*Δt-ps_data.midpoint[j] for + i in axes(here_mid, 1), j in axes(here_mid, 2) + ] + @inbounds @views df = [ + here_df[i, j]+dot(dx[i, :], here_sdf[i, j, :]) for + i in axes(here_df, 1), j in axes(here_df, 2) + ] bc = get_bc(face.domain.bc) - bc[1] = calc_ρw(there_mid,df,bc,here_vn,there_vn,here_weight,there_weight,ka) - there_df = Matrix{Float64}(undef,size(there_mid,1),NDF) - for i in axes(there_df,1) - @views there_df[i,:] .= discrete_maxwell(there_mid[i,:],bc,ka.kinfo) + bc[1] = calc_ρw(there_mid, df, bc, here_vn, there_vn, here_weight, there_weight, ka) + there_df = Matrix{Float64}(undef, size(there_mid, 1), NDF) + for i in axes(there_df, 1) + @views there_df[i, :] .= discrete_maxwell(there_mid[i, :], bc, ka.kinfo) end - @inbounds here_micro = [df[i,j]*here_vn[i] for i in axes(df,1),j in axes(df,2)] - @inbounds there_micro = [there_df[i,j]*there_vn[i] for i in axes(there_df,1),j in axes(there_df,2)] - fw = micro_to_macro(here_micro,here_mid,here_weight,vs_data)+micro_to_macro(there_micro,there_mid,there_weight,vs_data) - return fw,[here_micro,there_micro] + @inbounds here_micro = [df[i, j]*here_vn[i] for i in axes(df, 1), j in axes(df, 2)] + @inbounds there_micro = + [there_df[i, j]*there_vn[i] for i in axes(there_df, 1), j in axes(there_df, 2)] + fw = + micro_to_macro(here_micro, here_mid, here_weight, vs_data)+micro_to_macro( + there_micro, + there_mid, + there_weight, + vs_data, + ) + return fw, [here_micro, there_micro] end """ $(TYPEDSIGNATURES) """ -function calc_domain_flux(::Type{CAIDVM},here_vs::FaceVsData,face::DomainFace{DIM,NDF,SuperSonicInflow},ka::KA) where{DIM,NDF} - _,direction,midpoint,_,ps_data = unpack(face) - heavi,here_weight,here_mid,here_vn,here_df,here_sdf = unpack(here_vs) +function calc_domain_flux( + ::Type{CAIDVM}, + here_vs::FaceVsData, + face::DomainFace{DIM,NDF,SuperSonicInflow}, + ka::KA, +) where {DIM,NDF} + _, direction, midpoint, _, ps_data = unpack(face) + heavi, here_weight, here_mid, here_vn, here_df, here_sdf = unpack(here_vs) Δt = ka.kinfo.status.Δt vs_data = ps_data.vs_data nheavi = [!x for x in heavi] - there_mid = @views vs_data.midpoint[nheavi,:] - there_vn = @views there_mid[:,direction] + there_mid = @views vs_data.midpoint[nheavi, :] + there_vn = @views there_mid[:, direction] there_weight = @views vs_data.weight[nheavi] - @inbounds @views dx = [midpoint[j]-here_mid[i,j]*Δt-ps_data.midpoint[j] for i in axes(here_mid,1),j in axes(here_mid,2)] - @inbounds @views df = [here_df[i,j]+dot(dx[i,:],here_sdf[i,j,:]) for i in axes(here_df,1),j in axes(here_df,2)] + @inbounds @views dx = [ + midpoint[j]-here_mid[i, j]*Δt-ps_data.midpoint[j] for + i in axes(here_mid, 1), j in axes(here_mid, 2) + ] + @inbounds @views df = [ + here_df[i, j]+dot(dx[i, :], here_sdf[i, j, :]) for + i in axes(here_df, 1), j in axes(here_df, 2) + ] bc = get_bc(face.domain.bc) - there_df = Matrix{Float64}(undef,size(there_mid,1),NDF) - for i in axes(there_df,1) - @views there_df[i,:] .= discrete_maxwell(there_mid[i,:],bc,ka.kinfo) + there_df = Matrix{Float64}(undef, size(there_mid, 1), NDF) + for i in axes(there_df, 1) + @views there_df[i, :] .= discrete_maxwell(there_mid[i, :], bc, ka.kinfo) end - @inbounds here_micro = [df[i,j]*here_vn[i] for i in axes(df,1),j in axes(df,2)] - @inbounds there_micro = [there_df[i,j]*there_vn[i] for i in axes(there_df,1),j in axes(there_df,2)] - fw = micro_to_macro(here_micro,here_mid,here_weight,vs_data)+micro_to_macro(there_micro,there_mid,there_weight,vs_data) - return fw,[here_micro,there_micro] + @inbounds here_micro = [df[i, j]*here_vn[i] for i in axes(df, 1), j in axes(df, 2)] + @inbounds there_micro = + [there_df[i, j]*there_vn[i] for i in axes(there_df, 1), j in axes(there_df, 2)] + fw = + micro_to_macro(here_micro, here_mid, here_weight, vs_data)+micro_to_macro( + there_micro, + there_mid, + there_weight, + vs_data, + ) + return fw, [here_micro, there_micro] end """ $(TYPEDSIGNATURES) """ -function calc_domain_flux(::Type{CAIDVM},here_vs::FaceVsData,face::DomainFace{DIM,NDF,UniformOutflow},ka::KA) where{DIM,NDF} - _,direction,_,_,ps_data = unpack(face) - heavi,here_weight,here_mid,here_vn,_,_ = unpack(here_vs) +function calc_domain_flux( + ::Type{CAIDVM}, + here_vs::FaceVsData, + face::DomainFace{DIM,NDF,UniformOutflow}, + ka::KA, +) where {DIM,NDF} + _, direction, _, _, ps_data = unpack(face) + heavi, here_weight, here_mid, here_vn, _, _ = unpack(here_vs) vs_data = ps_data.vs_data nheavi = [!x for x in heavi] - there_mid = @views vs_data.midpoint[nheavi,:] - ndf = @views vs_data.df[nheavi,:] - there_vn = @views there_mid[:,direction] + there_mid = @views vs_data.midpoint[nheavi, :] + ndf = @views vs_data.df[nheavi, :] + there_vn = @views there_mid[:, direction] there_weight = @views vs_data.weight[nheavi] - df = @views vs_data.df[heavi,:] - @inbounds here_micro = [df[i,j]*here_vn[i] for i in axes(df,1),j in axes(df,2)] - @inbounds there_micro = [ndf[i,j]*there_vn[i] for i in axes(ndf,1),j in axes(ndf,2)] - fw = micro_to_macro(here_micro,here_mid,here_weight,vs_data)+micro_to_macro(there_micro,there_mid,there_weight,vs_data) - return fw,[here_micro,there_micro] + df = @views vs_data.df[heavi, :] + @inbounds here_micro = [df[i, j]*here_vn[i] for i in axes(df, 1), j in axes(df, 2)] + @inbounds there_micro = [ndf[i, j]*there_vn[i] for i in axes(ndf, 1), j in axes(ndf, 2)] + fw = + micro_to_macro(here_micro, here_mid, here_weight, vs_data)+micro_to_macro( + there_micro, + there_mid, + there_weight, + vs_data, + ) + return fw, [here_micro, there_micro] end """ $(TYPEDSIGNATURES) """ -function calc_domain_flux(::Type{CAIDVM},here_vs::FaceVsData,face::DomainFace{2,NDF,InterpolatedOutflow},ka::KA) where{NDF} - _,direction,midpoint,_,ps_data = unpack(face) - heavi,here_weight,here_mid,here_vn,here_df,here_sdf = unpack(here_vs) +function calc_domain_flux( + ::Type{CAIDVM}, + here_vs::FaceVsData, + face::DomainFace{2,NDF,InterpolatedOutflow}, + ka::KA, +) where {NDF} + _, direction, midpoint, _, ps_data = unpack(face) + heavi, here_weight, here_mid, here_vn, here_df, here_sdf = unpack(here_vs) Δt = ka.kinfo.status.Δt here_ps_mid = ps_data.midpoint there_ps_mid = 2.0*midpoint-here_ps_mid vs_data = ps_data.vs_data nheavi = [!x for x in heavi] @inbounds @views begin - there_mid = vs_data.midpoint[nheavi,:] - there_sdf = vs_data.sdf[nheavi,:,:] - there_df = vs_data.df[nheavi,:]+(there_ps_mid[direction]-here_ps_mid[direction])*there_sdf[:,:,direction] - there_vn = there_mid[:,direction] + there_mid = vs_data.midpoint[nheavi, :] + there_sdf = vs_data.sdf[nheavi, :, :] + there_df = + vs_data.df[nheavi, :]+(there_ps_mid[direction]-here_ps_mid[direction])*there_sdf[ + :, + :, + direction, + ] + there_vn = there_mid[:, direction] there_weight = vs_data.weight[nheavi] - dx = [midpoint[j]-here_mid[i,j]*Δt-here_ps_mid[j] for i in axes(here_mid,1),j in axes(here_mid,2)] - ndx = [midpoint[j]-there_mid[i,j]*Δt-there_ps_mid[j] for i in axes(there_mid,1),j in axes(there_mid,2)] - df = [here_df[i,j]+dot(dx[i,:],here_sdf[i,j,:]) for i in axes(here_df,1),j in axes(here_df,2)] - ndf = [there_df[i,j]+dot(ndx[i,:],there_sdf[i,j,:]) for i in axes(there_df,1),j in axes(there_df,2)] - here_micro = [df[i,j]*here_vn[i] for i in axes(df,1),j in axes(df,2)] - there_micro = [ndf[i,j]*there_vn[i] for i in axes(ndf,1),j in axes(ndf,2)] + dx = [ + midpoint[j]-here_mid[i, j]*Δt-here_ps_mid[j] for + i in axes(here_mid, 1), j in axes(here_mid, 2) + ] + ndx = [ + midpoint[j]-there_mid[i, j]*Δt-there_ps_mid[j] for + i in axes(there_mid, 1), j in axes(there_mid, 2) + ] + df = [ + here_df[i, j]+dot(dx[i, :], here_sdf[i, j, :]) for + i in axes(here_df, 1), j in axes(here_df, 2) + ] + ndf = [ + there_df[i, j]+dot(ndx[i, :], there_sdf[i, j, :]) for + i in axes(there_df, 1), j in axes(there_df, 2) + ] + here_micro = [df[i, j]*here_vn[i] for i in axes(df, 1), j in axes(df, 2)] + there_micro = [ndf[i, j]*there_vn[i] for i in axes(ndf, 1), j in axes(ndf, 2)] end - fw = micro_to_macro(here_micro,here_mid,here_weight,vs_data)+micro_to_macro(there_micro,there_mid,there_weight,vs_data) - return fw,[here_micro,there_micro] + fw = + micro_to_macro(here_micro, here_mid, here_weight, vs_data)+micro_to_macro( + there_micro, + there_mid, + there_weight, + vs_data, + ) + return fw, [here_micro, there_micro] end """ $(TYPEDSIGNATURES) Compute the flux across a single inner face. For [`CAIDVM`](@ref), both macro and micro fluxes are computed. """ -function calc_flux(::Type{CAIDVM},here_vs,there_vs,flux_data::Union{FullFace,FluxData},ka::KA{DIM,NDF}) where{DIM,NDF} # without face area and Δt - _,_,midpoint,here_data,there_data = unpack(flux_data) +function calc_flux( + ::Type{CAIDVM}, + here_vs, + there_vs, + flux_data::Union{FullFace,FluxData}, + ka::KA{DIM,NDF}, +) where {DIM,NDF} # without face area and Δt + _, _, midpoint, here_data, there_data = unpack(flux_data) Δt = ka.kinfo.status.Δt - here_mid = here_vs.midpoint;there_mid = there_vs.midpoint - here_vn = here_vs.vn;there_vn = there_vs.vn - here_df = here_vs.df;there_df = there_vs.df - here_sdf = here_vs.sdf;there_sdf = there_vs.sdf - here_ps_mid = here_data.midpoint;there_ps_mid = there_data.midpoint + here_mid = here_vs.midpoint; + there_mid = there_vs.midpoint + here_vn = here_vs.vn; + there_vn = there_vs.vn + here_df = here_vs.df; + there_df = there_vs.df + here_sdf = here_vs.sdf; + there_sdf = there_vs.sdf + here_ps_mid = here_data.midpoint; + there_ps_mid = there_data.midpoint @inbounds @views begin - dx = [midpoint[j]-here_mid[i,j]*Δt-here_ps_mid[j] for i in axes(here_mid,1),j in axes(here_mid,2)] - ndx = [midpoint[j]-there_mid[i,j]*Δt-there_ps_mid[j] for i in axes(there_mid,1),j in axes(there_mid,2)] + dx = [ + midpoint[j]-here_mid[i, j]*Δt-here_ps_mid[j] for + i in axes(here_mid, 1), j in axes(here_mid, 2) + ] + ndx = [ + midpoint[j]-there_mid[i, j]*Δt-there_ps_mid[j] for + i in axes(there_mid, 1), j in axes(there_mid, 2) + ] if there_data.bound_enc<0 - here_micro = [(here_df[i,j]+dot(dx[i,:],here_sdf[i,j,:]))*here_vn[i] for i in axes(here_df,1),j in axes(here_df,2)] - there_micro = [there_df[i,j]*there_vn[i] for i in axes(there_df,1),j in axes(there_df,2)] + here_micro = [ + (here_df[i, j]+dot(dx[i, :], here_sdf[i, j, :]))*here_vn[i] for + i in axes(here_df, 1), j in axes(here_df, 2) + ] + there_micro = [ + there_df[i, j]*there_vn[i] for + i in axes(there_df, 1), j in axes(there_df, 2) + ] else - here_micro = positivity_preserving_reconstruct(here_df,here_sdf,here_data.ds,dx,here_vn) - there_micro = positivity_preserving_reconstruct(there_df,there_sdf,there_data.ds,ndx,there_vn) + here_micro = positivity_preserving_reconstruct( + here_df, + here_sdf, + here_data.ds, + dx, + here_vn, + ) + there_micro = positivity_preserving_reconstruct( + there_df, + there_sdf, + there_data.ds, + ndx, + there_vn, + ) end end - here_weight = here_vs.weight;there_weight = there_vs.weight - fw = micro_to_macro(here_micro,here_mid,here_weight,here_data.vs_data)+micro_to_macro(there_micro,there_mid,there_weight,there_data.vs_data) - return fw,[here_micro,there_micro] + here_weight = here_vs.weight; + there_weight = there_vs.weight + fw = + micro_to_macro(here_micro, here_mid, here_weight, here_data.vs_data)+micro_to_macro( + there_micro, + there_mid, + there_weight, + there_data.vs_data, + ) + return fw, [here_micro, there_micro] end """ $(TYPEDSIGNATURES) Positivity preserving reconstruction (10.1016/j.jcp.2009.12.030). """ -function positivity_preserving_reconstruct(here_df,here_sdf,here_ds,dx,vn) # positivity preserving reconstruct (10.1016/j.jcp.2009.12.030) +function positivity_preserving_reconstruct(here_df, here_sdf, here_ds, dx, vn) # positivity preserving reconstruct (10.1016/j.jcp.2009.12.030) # The inner contractions over the velocity-component axis are written as # explicit `sum(... for k)` generators instead of `dot(here_ds,abs.(here_sdf[i,j,:]))` # / `dot(dx[i,:],here_sdf[i,j,:])`. The previous form allocated a temporary @@ -132,11 +249,11 @@ function positivity_preserving_reconstruct(here_df,here_sdf,here_ds,dx,vn) # pos # allocation in the flux kernel. Generators allocate nothing and, with the # now-concrete `here_sdf` (RC-3), stay type-stable. Numerically identical. @inbounds micro = [ - let s_abs = sum(here_ds[k]*abs(here_sdf[i,j,k]) for k in axes(here_sdf,3)), - s_dx = sum(dx[i,k]*here_sdf[i,j,k] for k in axes(here_sdf,3)) - (here_df[i,j]+min(abs((here_df[i,j]-eps())/(0.5*s_abs+EPS)),1.)*s_dx)*vn[i] - end - for i in axes(here_df,1), j in axes(here_df,2) + let s_abs = sum(here_ds[k]*abs(here_sdf[i, j, k]) for k in axes(here_sdf, 3)), + s_dx = sum(dx[i, k]*here_sdf[i, j, k] for k in axes(here_sdf, 3)) + + (here_df[i, j]+min(abs((here_df[i, j]-eps())/(0.5*s_abs+EPS)), 1.0)*s_dx)*vn[i] + end for i in axes(here_df, 1), j in axes(here_df, 2) ] return micro -end \ No newline at end of file +end diff --git a/src/Flux/DVM.jl b/src/Flux/DVM.jl index 4219dd7..efe5ae7 100644 --- a/src/Flux/DVM.jl +++ b/src/Flux/DVM.jl @@ -1,99 +1,185 @@ -function calc_domain_flux(::Type{DVM},here_vs::FaceVsData,face::DomainFace{DIM,NDF,Maxwellian},ka::KA) where{DIM,NDF} - _,direction,midpoint,_,ps_data = unpack(face) - heavi,_,here_mid,here_vn,here_df,here_sdf = unpack(here_vs) +function calc_domain_flux( + ::Type{DVM}, + here_vs::FaceVsData, + face::DomainFace{DIM,NDF,Maxwellian}, + ka::KA, +) where {DIM,NDF} + _, direction, midpoint, _, ps_data = unpack(face) + heavi, _, here_mid, here_vn, here_df, here_sdf = unpack(here_vs) Δt = ka.kinfo.status.Δt vs_data = ps_data.vs_data nheavi = [!x for x in heavi] - there_mid = @views vs_data.midpoint[nheavi,:] - there_vn = @views there_mid[:,direction] - @inbounds @views dx = [midpoint[j]-here_mid[i,j]*Δt-ps_data.midpoint[j] for i in axes(here_mid,1),j in axes(here_mid,2)] - @inbounds @views df = [here_df[i,j]+dot(dx[i,:],here_sdf[i,j,:]) for i in axes(here_df,1),j in axes(here_df,2)] + there_mid = @views vs_data.midpoint[nheavi, :] + there_vn = @views there_mid[:, direction] + @inbounds @views dx = [ + midpoint[j]-here_mid[i, j]*Δt-ps_data.midpoint[j] for + i in axes(here_mid, 1), j in axes(here_mid, 2) + ] + @inbounds @views df = [ + here_df[i, j]+dot(dx[i, :], here_sdf[i, j, :]) for + i in axes(here_df, 1), j in axes(here_df, 2) + ] bc = get_bc(face.domain.bc) - bc[1] = calc_ρw(there_mid,df,bc,here_vn,there_vn,here_weight,there_weight,ka) - there_df = Matrix{Float64}(undef,size(there_mid,1),NDF) - for i in axes(there_df,1) - @views there_df[i,:] .= discrete_maxwell(there_mid[i,:],bc,ka.kinfo) + bc[1] = calc_ρw(there_mid, df, bc, here_vn, there_vn, here_weight, there_weight, ka) + there_df = Matrix{Float64}(undef, size(there_mid, 1), NDF) + for i in axes(there_df, 1) + @views there_df[i, :] .= discrete_maxwell(there_mid[i, :], bc, ka.kinfo) end - @inbounds here_micro = [df[i,j]*here_vn[i] for i in axes(df,1),j in axes(df,2)] - @inbounds there_micro = [there_df[i,j]*there_vn[i] for i in axes(there_df,1),j in axes(there_df,2)] - return nothing,[here_micro,there_micro] + @inbounds here_micro = [df[i, j]*here_vn[i] for i in axes(df, 1), j in axes(df, 2)] + @inbounds there_micro = + [there_df[i, j]*there_vn[i] for i in axes(there_df, 1), j in axes(there_df, 2)] + return nothing, [here_micro, there_micro] end -function calc_domain_flux(::Type{DVM},here_vs::FaceVsData,face::DomainFace{DIM,NDF,SuperSonicInflow},ka::KA) where{DIM,NDF} - _,direction,midpoint,_,ps_data = unpack(face) - heavi,_,here_mid,here_vn,here_df,here_sdf = unpack(here_vs) +function calc_domain_flux( + ::Type{DVM}, + here_vs::FaceVsData, + face::DomainFace{DIM,NDF,SuperSonicInflow}, + ka::KA, +) where {DIM,NDF} + _, direction, midpoint, _, ps_data = unpack(face) + heavi, _, here_mid, here_vn, here_df, here_sdf = unpack(here_vs) Δt = ka.kinfo.status.Δt vs_data = ps_data.vs_data nheavi = [!x for x in heavi] - there_mid = @views vs_data.midpoint[nheavi,:] - there_vn = @views there_mid[:,direction] - @inbounds @views dx = [midpoint[j]-here_mid[i,j]*Δt-ps_data.midpoint[j] for i in axes(here_mid,1),j in axes(here_mid,2)] - @inbounds @views df = [here_df[i,j]+dot(dx[i,:],here_sdf[i,j,:]) for i in axes(here_df,1),j in axes(here_df,2)] + there_mid = @views vs_data.midpoint[nheavi, :] + there_vn = @views there_mid[:, direction] + @inbounds @views dx = [ + midpoint[j]-here_mid[i, j]*Δt-ps_data.midpoint[j] for + i in axes(here_mid, 1), j in axes(here_mid, 2) + ] + @inbounds @views df = [ + here_df[i, j]+dot(dx[i, :], here_sdf[i, j, :]) for + i in axes(here_df, 1), j in axes(here_df, 2) + ] bc = get_bc(face.domain.bc) - there_df = Matrix{Float64}(undef,size(there_mid,1),NDF) - for i in axes(there_df,1) - @views there_df[i,:] .= discrete_maxwell(there_mid[i,:],bc,ka.kinfo) + there_df = Matrix{Float64}(undef, size(there_mid, 1), NDF) + for i in axes(there_df, 1) + @views there_df[i, :] .= discrete_maxwell(there_mid[i, :], bc, ka.kinfo) end - @inbounds here_micro = [df[i,j]*here_vn[i] for i in axes(df,1),j in axes(df,2)] - @inbounds there_micro = [there_df[i,j]*there_vn[i] for i in axes(there_df,1),j in axes(there_df,2)] - return nothing,[here_micro,there_micro] + @inbounds here_micro = [df[i, j]*here_vn[i] for i in axes(df, 1), j in axes(df, 2)] + @inbounds there_micro = + [there_df[i, j]*there_vn[i] for i in axes(there_df, 1), j in axes(there_df, 2)] + return nothing, [here_micro, there_micro] end -function calc_domain_flux(::Type{DVM},here_vs::FaceVsData,face::DomainFace{DIM,NDF,UniformOutflow},ka::KA) where{DIM,NDF} - _,direction,_,_,ps_data = unpack(face) - heavi,_,here_mid,here_vn,_,_ = unpack(here_vs) +function calc_domain_flux( + ::Type{DVM}, + here_vs::FaceVsData, + face::DomainFace{DIM,NDF,UniformOutflow}, + ka::KA, +) where {DIM,NDF} + _, direction, _, _, ps_data = unpack(face) + heavi, _, here_mid, here_vn, _, _ = unpack(here_vs) vs_data = ps_data.vs_data nheavi = [!x for x in heavi] - there_mid = @views vs_data.midpoint[nheavi,:] - ndf = @views vs_data.df[nheavi,:] - there_vn = @views there_mid[:,direction] - df = @views vs_data.df[heavi,:] - @inbounds here_micro = [df[i,j]*here_vn[i] for i in axes(df,1),j in axes(df,2)] - @inbounds there_micro = [ndf[i,j]*there_vn[i] for i in axes(ndf,1),j in axes(ndf,2)] - return nothing,[here_micro,there_micro] + there_mid = @views vs_data.midpoint[nheavi, :] + ndf = @views vs_data.df[nheavi, :] + there_vn = @views there_mid[:, direction] + df = @views vs_data.df[heavi, :] + @inbounds here_micro = [df[i, j]*here_vn[i] for i in axes(df, 1), j in axes(df, 2)] + @inbounds there_micro = [ndf[i, j]*there_vn[i] for i in axes(ndf, 1), j in axes(ndf, 2)] + return nothing, [here_micro, there_micro] end -function calc_domain_flux(::Type{DVM},here_vs::FaceVsData,face::DomainFace{2,NDF,InterpolatedOutflow},ka::KA) where{NDF} - _,direction,midpoint,_,ps_data = unpack(face) - heavi,_,here_mid,here_vn,here_df,here_sdf = unpack(here_vs) +function calc_domain_flux( + ::Type{DVM}, + here_vs::FaceVsData, + face::DomainFace{2,NDF,InterpolatedOutflow}, + ka::KA, +) where {NDF} + _, direction, midpoint, _, ps_data = unpack(face) + heavi, _, here_mid, here_vn, here_df, here_sdf = unpack(here_vs) Δt = ka.kinfo.status.Δt here_ps_mid = ps_data.midpoint there_ps_mid = 2.0*midpoint-here_ps_mid vs_data = ps_data.vs_data nheavi = [!x for x in heavi] @inbounds @views begin - there_mid = vs_data.midpoint[nheavi,:] - there_sdf = vs_data.sdf[nheavi,:,:] - there_df = vs_data.df[nheavi,:]+(there_ps_mid[direction]-here_ps_mid[direction])*there_sdf[:,:,direction] - there_vn = there_mid[:,direction] - dx = [midpoint[j]-here_mid[i,j]*Δt-here_ps_mid[j] for i in axes(here_mid,1),j in axes(here_mid,2)] - ndx = [midpoint[j]-there_mid[i,j]*Δt-there_ps_mid[j] for i in axes(there_mid,1),j in axes(there_mid,2)] - df = [here_df[i,j]+dot(dx[i,:],here_sdf[i,j,:]) for i in axes(here_df,1),j in axes(here_df,2)] - ndf = [there_df[i,j]+dot(ndx[i,:],there_sdf[i,j,:]) for i in axes(there_df,1),j in axes(there_df,2)] - here_micro = [df[i,j]*here_vn[i] for i in axes(df,1),j in axes(df,2)] - there_micro = [ndf[i,j]*there_vn[i] for i in axes(ndf,1),j in axes(ndf,2)] + there_mid = vs_data.midpoint[nheavi, :] + there_sdf = vs_data.sdf[nheavi, :, :] + there_df = + vs_data.df[nheavi, :]+(there_ps_mid[direction]-here_ps_mid[direction])*there_sdf[ + :, + :, + direction, + ] + there_vn = there_mid[:, direction] + dx = [ + midpoint[j]-here_mid[i, j]*Δt-here_ps_mid[j] for + i in axes(here_mid, 1), j in axes(here_mid, 2) + ] + ndx = [ + midpoint[j]-there_mid[i, j]*Δt-there_ps_mid[j] for + i in axes(there_mid, 1), j in axes(there_mid, 2) + ] + df = [ + here_df[i, j]+dot(dx[i, :], here_sdf[i, j, :]) for + i in axes(here_df, 1), j in axes(here_df, 2) + ] + ndf = [ + there_df[i, j]+dot(ndx[i, :], there_sdf[i, j, :]) for + i in axes(there_df, 1), j in axes(there_df, 2) + ] + here_micro = [df[i, j]*here_vn[i] for i in axes(df, 1), j in axes(df, 2)] + there_micro = [ndf[i, j]*there_vn[i] for i in axes(ndf, 1), j in axes(ndf, 2)] end - return nothing,[here_micro,there_micro] + return nothing, [here_micro, there_micro] end -function calc_flux(::Type{DVM},here_vs,there_vs,flux_data::Union{FullFace,FluxData},ka::KA{DIM,NDF}) where{DIM,NDF} # without face area and Δt - _,_,midpoint,here_data,there_data = unpack(flux_data) +function calc_flux( + ::Type{DVM}, + here_vs, + there_vs, + flux_data::Union{FullFace,FluxData}, + ka::KA{DIM,NDF}, +) where {DIM,NDF} # without face area and Δt + _, _, midpoint, here_data, there_data = unpack(flux_data) Δt = ka.kinfo.status.Δt - here_mid = here_vs.midpoint;there_mid = there_vs.midpoint - here_vn = here_vs.vn;there_vn = there_vs.vn - here_df = here_vs.df;there_df = there_vs.df - here_sdf = here_vs.sdf;there_sdf = there_vs.sdf - here_ps_mid = here_data.midpoint;there_ps_mid = there_data.midpoint + here_mid = here_vs.midpoint; + there_mid = there_vs.midpoint + here_vn = here_vs.vn; + there_vn = there_vs.vn + here_df = here_vs.df; + there_df = there_vs.df + here_sdf = here_vs.sdf; + there_sdf = there_vs.sdf + here_ps_mid = here_data.midpoint; + there_ps_mid = there_data.midpoint @inbounds @views begin - dx = [midpoint[j]-here_mid[i,j]*Δt-here_ps_mid[j] for i in axes(here_mid,1),j in axes(here_mid,2)] - ndx = [midpoint[j]-there_mid[i,j]*Δt-there_ps_mid[j] for i in axes(there_mid,1),j in axes(there_mid,2)] + dx = [ + midpoint[j]-here_mid[i, j]*Δt-here_ps_mid[j] for + i in axes(here_mid, 1), j in axes(here_mid, 2) + ] + ndx = [ + midpoint[j]-there_mid[i, j]*Δt-there_ps_mid[j] for + i in axes(there_mid, 1), j in axes(there_mid, 2) + ] if there_data.bound_enc<0 - here_micro = [(here_df[i,j]+dot(dx[i,:],here_sdf[i,j,:]))*here_vn[i] for i in axes(here_df,1),j in axes(here_df,2)] - there_micro = [(there_df[i,j]+dot(ndx[i,:],there_sdf[i,j,:]))*there_vn[i] for i in axes(there_df,1),j in axes(there_df,2)] + here_micro = [ + (here_df[i, j]+dot(dx[i, :], here_sdf[i, j, :]))*here_vn[i] for + i in axes(here_df, 1), j in axes(here_df, 2) + ] + there_micro = [ + (there_df[i, j]+dot(ndx[i, :], there_sdf[i, j, :]))*there_vn[i] for + i in axes(there_df, 1), j in axes(there_df, 2) + ] else - here_micro = positivity_preserving_reconstruct(here_df,here_sdf,here_data.ds,dx,here_vn) - there_micro = positivity_preserving_reconstruct(there_df,there_sdf,there_data.ds,ndx,there_vn) + here_micro = positivity_preserving_reconstruct( + here_df, + here_sdf, + here_data.ds, + dx, + here_vn, + ) + there_micro = positivity_preserving_reconstruct( + there_df, + there_sdf, + there_data.ds, + ndx, + there_vn, + ) end end - return nothing,[here_micro,there_micro] + return nothing, [here_micro, there_micro] end diff --git a/src/Flux/Flux.jl b/src/Flux/Flux.jl index 0f4dfa7..ff8c5d8 100644 --- a/src/Flux/Flux.jl +++ b/src/Flux/Flux.jl @@ -2,9 +2,15 @@ include("CAIDVM.jl") include("DVM.jl") include("UGKS.jl") include("Slope.jl") -export slope!, update_slope!, update_slope_inner_vs!, update_slope_bound_vs!, update_slope_inner_ps!, update_slope_bound_ps! +export slope!, + update_slope!, + update_slope_inner_vs!, + update_slope_bound_vs!, + update_slope_inner_ps!, + update_slope_bound_ps! export vanleer, minmod, diff_vs! -export flux!, update_flux!, update_domain_flux!, update_micro_flux!, update_macro_flux!, make_face_vs +export flux!, + update_flux!, update_domain_flux!, update_micro_flux!, update_macro_flux!, make_face_vs export calc_flux, calc_domain_flux, positivity_preserving_reconstruct function face_area(ps_data::AbstractPsData{2}, DIR::Integer) @@ -16,44 +22,64 @@ end """ $(TYPEDSIGNATURES) """ -function flux!(::Type{F},face::DomainFace,ka::KA) where {F<:AbstractFluxType} +function flux!(::Type{F}, face::DomainFace, ka::KA) where {F<:AbstractFluxType} here_vs = make_face_vs(face) - flux,micro_flux = calc_domain_flux(F,here_vs,face,ka) - update_domain_flux!(flux,micro_flux,face,here_vs.heavi) + flux, micro_flux = calc_domain_flux(F, here_vs, face, ka) + update_domain_flux!(flux, micro_flux, face, here_vs.heavi) return nothing end """ $(TYPEDSIGNATURES) """ -function flux!(::Type{F},face::FullFace,ka::KA) where {F<:AbstractFluxType} - here_vs,there_vs = make_face_vs(face) - flux,micro_flux = calc_flux(F,here_vs,there_vs,face,ka) - update_flux!(flux,micro_flux,face,here_vs.heavi) +function flux!(::Type{F}, face::FullFace, ka::KA) where {F<:AbstractFluxType} + here_vs, there_vs = make_face_vs(face) + flux, micro_flux = calc_flux(F, here_vs, there_vs, face, ka) + update_flux!(flux, micro_flux, face, here_vs.heavi) return nothing end """ $(TYPEDSIGNATURES) """ -function flux!(::Type{F},face::HangingFace{DIM,NDF},ka::KA) where {DIM,NDF,F<:AbstractFluxType} - rot,direction,midpoint,here_data,there_data = unpack(face) - here_vs,there_vs = make_face_vs(face) +function flux!( + ::Type{F}, + face::HangingFace{DIM,NDF}, + ka::KA, +) where {DIM,NDF,F<:AbstractFluxType} + rot, direction, midpoint, here_data, there_data = unpack(face) + here_vs, there_vs = make_face_vs(face) for i in eachindex(there_vs) - flux_data = FluxData{HangingFace{DIM,NDF}}(rot,direction,midpoint[i],here_data,there_data[i]) - flux,micro_flux = calc_flux(F,here_vs,there_vs[i],flux_data,ka) - update_flux!(flux,micro_flux,flux_data,here_vs.heavi) + flux_data = FluxData{HangingFace{DIM,NDF}}( + rot, + direction, + midpoint[i], + here_data, + there_data[i], + ) + flux, micro_flux = calc_flux(F, here_vs, there_vs[i], flux_data, ka) + update_flux!(flux, micro_flux, flux_data, here_vs.heavi) end return nothing end """ $(TYPEDSIGNATURES) """ -function flux!(::Type{F},face::BackHangingFace{DIM,NDF},ka::KA) where {DIM,NDF,F<:AbstractFluxType} - rot,direction,midpoint,here_data,there_data = unpack(face) - here_vs,there_vs = make_face_vs(face) +function flux!( + ::Type{F}, + face::BackHangingFace{DIM,NDF}, + ka::KA, +) where {DIM,NDF,F<:AbstractFluxType} + rot, direction, midpoint, here_data, there_data = unpack(face) + here_vs, there_vs = make_face_vs(face) for i in eachindex(here_vs) - flux_data = FluxData{BackHangingFace{DIM,NDF}}(rot,direction,midpoint[i],here_data[i],there_data) - flux,micro_flux = calc_flux(F,here_vs[i],there_vs,flux_data,ka) - update_flux!(flux,micro_flux,flux_data,here_vs[i].heavi) + flux_data = FluxData{BackHangingFace{DIM,NDF}}( + rot, + direction, + midpoint[i], + here_data[i], + there_data, + ) + flux, micro_flux = calc_flux(F, here_vs[i], there_vs, flux_data, ka) + update_flux!(flux, micro_flux, flux_data, here_vs[i].heavi) end return nothing end @@ -61,59 +87,89 @@ end """ $(TYPEDSIGNATURES) """ -function update_domain_flux!(flux::AbstractVector,micro_flux::Vector{Matrix{Float64}},face::DomainFace,heavi::Vector{Bool}) - rot,direction,_,_,ps_data = unpack(face) - area = rot*face_area(ps_data,direction) - here_micro,there_micro = micro_flux +function update_domain_flux!( + flux::AbstractVector, + micro_flux::Vector{Matrix{Float64}}, + face::DomainFace, + heavi::Vector{Bool}, +) + rot, direction, _, _, ps_data = unpack(face) + area = rot*face_area(ps_data, direction) + here_micro, there_micro = micro_flux ps_data.flux .+= area*flux - ps_data.vs_data.flux[heavi,:] .+= area*here_micro - ps_data.vs_data.flux[.!heavi,:] .+= area*there_micro + ps_data.vs_data.flux[heavi, :] .+= area*here_micro + ps_data.vs_data.flux[.!heavi, :] .+= area*there_micro return nothing end """ $(TYPEDSIGNATURES) """ -function update_domain_flux!(::Nothing,micro_flux::Vector{Matrix{Float64}},face::DomainFace,heavi::Vector{Bool}) - rot,direction,_,_,ps_data = unpack(face) - area = rot*face_area(ps_data,direction) - here_micro,there_micro = micro_flux - ps_data.vs_data.flux[heavi,:] .+= area*here_micro - ps_data.vs_data.flux[.!heavi,:] .+= area*there_micro +function update_domain_flux!( + ::Nothing, + micro_flux::Vector{Matrix{Float64}}, + face::DomainFace, + heavi::Vector{Bool}, +) + rot, direction, _, _, ps_data = unpack(face) + area = rot*face_area(ps_data, direction) + here_micro, there_micro = micro_flux + ps_data.vs_data.flux[heavi, :] .+= area*here_micro + ps_data.vs_data.flux[.!heavi, :] .+= area*there_micro return nothing end -function face_area(::FluxData{HangingFace{DIM,NDF}},here_data::AbstractPsData{DIM},direction,rot) where{DIM,NDF} - face_area(here_data,direction)/2^(DIM-1)*rot +function face_area( + ::FluxData{HangingFace{DIM,NDF}}, + here_data::AbstractPsData{DIM}, + direction, + rot, +) where {DIM,NDF} + face_area(here_data, direction)/2^(DIM-1)*rot end -function face_area(::T,here_data,direction,rot) where{T<:Union{FluxData{BackHangingFace{DIM,NDF}},FullFace{DIM,NDF}} where{DIM,NDF}} - face_area(here_data,direction)*rot +function face_area( + ::T, + here_data, + direction, + rot, +) where {T<:Union{FluxData{BackHangingFace{DIM,NDF}},FullFace{DIM,NDF}} where {DIM,NDF}} + face_area(here_data, direction)*rot end """ $(TYPEDSIGNATURES) """ -function update_flux!(flux::AbstractVector,micro_flux::Vector{Matrix{Float64}},face::Union{FullFace,FluxData},heavi::Vector{Bool}) - rot,direction,_,here_data,there_data = unpack(face) - area = face_area(face,here_data,direction,rot) - here_micro,there_micro = micro_flux - update_macro_flux!(flux*area,here_data,there_data) - update_micro_flux!(here_micro*area,there_micro*area,here_data,there_data,heavi) +function update_flux!( + flux::AbstractVector, + micro_flux::Vector{Matrix{Float64}}, + face::Union{FullFace,FluxData}, + heavi::Vector{Bool}, +) + rot, direction, _, here_data, there_data = unpack(face) + area = face_area(face, here_data, direction, rot) + here_micro, there_micro = micro_flux + update_macro_flux!(flux*area, here_data, there_data) + update_micro_flux!(here_micro*area, there_micro*area, here_data, there_data, heavi) return nothing end """ $(TYPEDSIGNATURES) """ -function update_flux!(::Nothing,micro_flux::Vector{Matrix{Float64}},face::Union{FullFace,FluxData},heavi::Vector{Bool}) - rot,direction,_,here_data,there_data = unpack(face) - area = face_area(face,here_data,direction,rot) - here_micro,there_micro = micro_flux - update_micro_flux!(here_micro*area,there_micro*area,here_data,there_data,heavi) +function update_flux!( + ::Nothing, + micro_flux::Vector{Matrix{Float64}}, + face::Union{FullFace,FluxData}, + heavi::Vector{Bool}, +) + rot, direction, _, here_data, there_data = unpack(face) + area = face_area(face, here_data, direction, rot) + here_micro, there_micro = micro_flux + update_micro_flux!(here_micro*area, there_micro*area, here_data, there_data, heavi) return nothing end """ $(TYPEDSIGNATURES) """ -function update_macro_flux!(flux::Vector,here_data::PsData,there_data::PsData) +function update_macro_flux!(flux::Vector, here_data::PsData, there_data::PsData) here_data.flux .+= flux if there_data.bound_enc>=0 there_data.flux .-= flux @@ -123,41 +179,58 @@ end """ $(TYPEDSIGNATURES) """ -function update_macro_flux!(flux::Vector,here_data::PsData,::AbstractGhostPsData) +function update_macro_flux!(flux::Vector, here_data::PsData, ::AbstractGhostPsData) here_data.flux .+= flux return nothing end """ $(TYPEDSIGNATURES) """ -function update_macro_flux!(flux::Vector,here_data::PsData,::SolidNeighbor) +function update_macro_flux!(flux::Vector, here_data::PsData, ::SolidNeighbor) here_data.flux .+= flux return nothing end """ $(TYPEDSIGNATURES) """ -function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM},::SolidNeighbor{DIM},heavi::Vector{Bool}) where{DIM} - vs_data = here_data.vs_data;flux = vs_data.flux - @. flux[heavi,:]+= here_micro +function update_micro_flux!( + here_micro, + there_micro, + here_data::PsData{DIM}, + ::SolidNeighbor{DIM}, + heavi::Vector{Bool}, +) where {DIM} + vs_data = here_data.vs_data; + flux = vs_data.flux + @. flux[heavi, :] += here_micro nheavi = [!x for x in heavi] - @. flux[nheavi,:]+= there_micro + @. flux[nheavi, :] += there_micro return nothing end """ $(TYPEDSIGNATURES) """ -function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},there_data::PsData,heavi::Vector{Bool}) where{DIM,NDF} - vs_data = here_data.vs_data;nvs_data = there_data.vs_data - level = vs_data.level;level_n = nvs_data.level - flux = vs_data.flux;flux_n = nvs_data.flux - index = j = index_n = 1;flag = 0. +function update_micro_flux!( + here_micro, + there_micro, + here_data::PsData{DIM,NDF}, + there_data::PsData, + heavi::Vector{Bool}, +) where {DIM,NDF} + vs_data = here_data.vs_data; + nvs_data = there_data.vs_data + level = vs_data.level; + level_n = nvs_data.level + flux = vs_data.flux; + flux_n = nvs_data.flux + index = j = index_n = 1; + flag = 0.0 if there_data.bound_enc<0 @inbounds for i = 1:vs_data.vs_num if heavi[i] - @simd for ii in 1:NDF - flux[i, ii] +=here_micro[index, ii] + @simd for ii = 1:NDF + flux[i, ii] += here_micro[index, ii] end if level[i] == level_n[j] j += 1 @@ -177,14 +250,14 @@ function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},th index += 1 else if level[i] == level_n[j] - @simd for ii in 1:NDF + @simd for ii = 1:NDF flux[i, ii] += there_micro[index_n, ii] end j += 1 index_n += 1 elseif level[i] < level_n[j] while flag != 1.0 - for ii in 1:NDF + for ii = 1:NDF flux[i, ii] += (there_micro[index_n, ii]) / 2^(DIM * (level_n[j] - level[i])) @@ -195,7 +268,7 @@ function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},th end flag = 0.0 else - for ii in 1:NDF + for ii = 1:NDF flux[i, ii] += there_micro[index_n, ii] end flag += 1 / 2^(DIM * (level[i] - level_n[j])) @@ -210,17 +283,17 @@ function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},th else @inbounds for i = 1:vs_data.vs_num if heavi[i] - @simd for ii in 1:NDF - flux[i, ii] +=here_micro[index, ii] + @simd for ii = 1:NDF + flux[i, ii] += here_micro[index, ii] end if level[i] == level_n[j] - @simd for ii in 1:NDF + @simd for ii = 1:NDF flux_n[j, ii] -= here_micro[index, ii] end j += 1 elseif level[i] < level_n[j] while flag != 1.0 - @simd for ii in 1:NDF + @simd for ii = 1:NDF flux_n[j, ii] -= here_micro[index, ii] end flag += 1 / 2^(DIM * (level_n[j] - level[i])) @@ -228,7 +301,7 @@ function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},th end flag = 0.0 else - @simd for ii in 1:NDF + @simd for ii = 1:NDF flux_n[j, ii] -= (here_micro[index, ii]) / 2^(DIM * (level[i] - level_n[j])) end @@ -241,7 +314,7 @@ function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},th index += 1 else if level[i] == level_n[j] - @simd for ii in 1:NDF + @simd for ii = 1:NDF flux_n[j, ii] -= there_micro[index_n, ii] flux[i, ii] += there_micro[index_n, ii] end @@ -249,7 +322,7 @@ function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},th index_n += 1 elseif level[i] < level_n[j] while flag != 1.0 - @simd for ii in 1:NDF + @simd for ii = 1:NDF flux_n[j, ii] -= there_micro[index_n, ii] flux[i, ii] += (there_micro[index_n, ii]) / @@ -261,12 +334,12 @@ function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},th end flag = 0.0 else - @simd for ii in 1:NDF - flux[i, ii] += there_micro[index_n, ii] + @simd for ii = 1:NDF + flux[i, ii] += there_micro[index_n, ii] end flag += 1 / 2^(DIM * (level[i] - level_n[j])) if flag == 1.0 - @simd for ii in 1:NDF + @simd for ii = 1:NDF flux_n[j, ii] -= there_micro[index_n, ii] end j += 1 @@ -282,15 +355,24 @@ end """ $(TYPEDSIGNATURES) """ -function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},there_data::AbstractGhostPsData,heavi::Vector{Bool}) where{DIM,NDF} - vs_data = here_data.vs_data;nvs_data = there_data.vs_data - level = vs_data.level;level_n = nvs_data.level +function update_micro_flux!( + here_micro, + there_micro, + here_data::PsData{DIM,NDF}, + there_data::AbstractGhostPsData, + heavi::Vector{Bool}, +) where {DIM,NDF} + vs_data = here_data.vs_data; + nvs_data = there_data.vs_data + level = vs_data.level; + level_n = nvs_data.level flux = vs_data.flux - index = j = index_n = 1;flag = 0. + index = j = index_n = 1; + flag = 0.0 @inbounds for i = 1:vs_data.vs_num if heavi[i] - @simd for ii in 1:NDF - flux[i, ii] +=here_micro[index, ii] + @simd for ii = 1:NDF + flux[i, ii] += here_micro[index, ii] end if level[i] == level_n[j] j += 1 @@ -310,17 +392,16 @@ function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},th index += 1 else if level[i] == level_n[j] - @simd for ii in 1:NDF + @simd for ii = 1:NDF flux[i, ii] += there_micro[index_n, ii] end j += 1 index_n += 1 elseif level[i] < level_n[j] while flag != 1.0 - for ii in 1:NDF + for ii = 1:NDF flux[i, ii] += - (there_micro[index_n, ii]) / - 2^(DIM * (level_n[j] - level[i])) + (there_micro[index_n, ii]) / 2^(DIM * (level_n[j] - level[i])) end flag += 1 / 2^(DIM * (level_n[j] - level[i])) j += 1 @@ -328,7 +409,7 @@ function update_micro_flux!(here_micro,there_micro,here_data::PsData{DIM,NDF},th end flag = 0.0 else - for ii in 1:NDF + for ii = 1:NDF flux[i, ii] += there_micro[index_n, ii] end flag += 1 / 2^(DIM * (level[i] - level_n[j])) @@ -346,81 +427,112 @@ end """ $(TYPEDSIGNATURES) """ -function make_face_vs(face::DomainFace{DIM,NDF})where{DIM,NDF} - rot,direction,_,_,ps_data = unpack(face) - vs_data = ps_data.vs_data;here_mid = vs_data.midpoint - heavi = [x<=0. for x in rot.*@views here_mid[:,direction]] +function make_face_vs(face::DomainFace{DIM,NDF}) where {DIM,NDF} + rot, direction, _, _, ps_data = unpack(face) + vs_data = ps_data.vs_data; + here_mid = vs_data.midpoint + heavi = [x<=0.0 for x in rot .* @views here_mid[:, direction]] @views here_vs = FaceVsData{DIM,NDF}( - heavi,vs_data.weight[heavi],here_mid[heavi,:],here_mid[heavi,direction], - vs_data.df[heavi,:],vs_data.sdf[heavi,:,:] + heavi, + vs_data.weight[heavi], + here_mid[heavi, :], + here_mid[heavi, direction], + vs_data.df[heavi, :], + vs_data.sdf[heavi, :, :], ) return here_vs end """ $(TYPEDSIGNATURES) """ -function make_face_vs(face::FullFace{DIM,NDF}) where{DIM,NDF} - rot,direction,_,here_data,there_data = unpack(face) - vs_data = here_data.vs_data;nvs_data = there_data.vs_data - here_mid = vs_data.midpoint;there_mid = nvs_data.midpoint - heavi = [x<=0. for x in rot.*@views here_mid[:,direction]] - nheavi = [x>0. for x in rot.*@views there_mid[:,direction]] +function make_face_vs(face::FullFace{DIM,NDF}) where {DIM,NDF} + rot, direction, _, here_data, there_data = unpack(face) + vs_data = here_data.vs_data; + nvs_data = there_data.vs_data + here_mid = vs_data.midpoint; + there_mid = nvs_data.midpoint + heavi = [x<=0.0 for x in rot .* @views here_mid[:, direction]] + nheavi = [x>0.0 for x in rot .* @views there_mid[:, direction]] @views here_vs = FaceVsData{DIM,NDF}( - heavi,vs_data.weight[heavi],here_mid[heavi,:],here_mid[heavi,direction], - vs_data.df[heavi,:],vs_data.sdf[heavi,:,:] + heavi, + vs_data.weight[heavi], + here_mid[heavi, :], + here_mid[heavi, direction], + vs_data.df[heavi, :], + vs_data.sdf[heavi, :, :], ) @views there_vs = FaceVsData{DIM,NDF}( - nheavi,nvs_data.weight[nheavi],there_mid[nheavi,:],there_mid[nheavi,direction], - nvs_data.df[nheavi,:],nvs_data.sdf[nheavi,:,:] + nheavi, + nvs_data.weight[nheavi], + there_mid[nheavi, :], + there_mid[nheavi, direction], + nvs_data.df[nheavi, :], + nvs_data.sdf[nheavi, :, :], ) - return here_vs,there_vs + return here_vs, there_vs end """ $(TYPEDSIGNATURES) """ -function make_face_vs(face::HangingFace{DIM,NDF}) where{DIM,NDF} - rot,direction,_,here_data,there_data = unpack(face) +function make_face_vs(face::HangingFace{DIM,NDF}) where {DIM,NDF} + rot, direction, _, here_data, there_data = unpack(face) vs_data = here_data.vs_data here_mid = vs_data.midpoint - heavi = [x<=0. for x in rot.*@views here_mid[:,direction]] + heavi = [x<=0.0 for x in rot .* @views here_mid[:, direction]] @views here_vs = FaceVsData{DIM,NDF}( - heavi,vs_data.weight[heavi],here_mid[heavi,:],here_mid[heavi,direction],vs_data.df[heavi,:], - vs_data.sdf[heavi,:,:] + heavi, + vs_data.weight[heavi], + here_mid[heavi, :], + here_mid[heavi, direction], + vs_data.df[heavi, :], + vs_data.sdf[heavi, :, :], ) - there_vs = Vector{FaceVsData{DIM,NDF}}(undef,length(there_data)) + there_vs = Vector{FaceVsData{DIM,NDF}}(undef, length(there_data)) for i in eachindex(there_data) nvs_data = there_data[i].vs_data there_mid = nvs_data.midpoint - nheavi = [x>0. for x in rot.*@views there_mid[:,direction]] + nheavi = [x>0.0 for x in rot .* @views there_mid[:, direction]] @views there_vs[i] = FaceVsData{DIM,NDF}( - nheavi,nvs_data.weight[nheavi],there_mid[nheavi,:],there_mid[nheavi,direction], - nvs_data.df[nheavi,:],nvs_data.sdf[nheavi,:,:] + nheavi, + nvs_data.weight[nheavi], + there_mid[nheavi, :], + there_mid[nheavi, direction], + nvs_data.df[nheavi, :], + nvs_data.sdf[nheavi, :, :], ) end - return here_vs,there_vs + return here_vs, there_vs end """ $(TYPEDSIGNATURES) """ -function make_face_vs(face::BackHangingFace{DIM,NDF}) where{DIM,NDF} - rot,direction,_,here_data,there_data = unpack(face) +function make_face_vs(face::BackHangingFace{DIM,NDF}) where {DIM,NDF} + rot, direction, _, here_data, there_data = unpack(face) nvs_data = there_data.vs_data - nheavi = [x>0. for x in rot.*@views nvs_data.midpoint[:,direction]] + nheavi = [x>0.0 for x in rot .* @views nvs_data.midpoint[:, direction]] @views there_vs = FaceVsData{DIM,NDF}( - nheavi,nvs_data.weight[nheavi],nvs_data.midpoint[nheavi,:],nvs_data.midpoint[nheavi,direction], - nvs_data.df[nheavi,:],nvs_data.sdf[nheavi,:,:] - ) - here_vs = Vector{FaceVsData{DIM,NDF}}(undef,length(here_data)) + nheavi, + nvs_data.weight[nheavi], + nvs_data.midpoint[nheavi, :], + nvs_data.midpoint[nheavi, direction], + nvs_data.df[nheavi, :], + nvs_data.sdf[nheavi, :, :], + ) + here_vs = Vector{FaceVsData{DIM,NDF}}(undef, length(here_data)) for i in eachindex(here_data) vs_data = here_data[i].vs_data here_mid = vs_data.midpoint - heavi = [x<=0. for x in rot.*@views here_mid[:,direction]] + heavi = [x<=0.0 for x in rot .* @views here_mid[:, direction]] @views here_vs[i] = FaceVsData{DIM,NDF}( - heavi,vs_data.weight[heavi],here_mid[heavi,:],here_mid[heavi,direction],vs_data.df[heavi,:], - vs_data.sdf[heavi,:,:] - ) + heavi, + vs_data.weight[heavi], + here_mid[heavi, :], + here_mid[heavi, direction], + vs_data.df[heavi, :], + vs_data.sdf[heavi, :, :], + ) end - return here_vs,there_vs + return here_vs, there_vs end """ @@ -447,13 +559,13 @@ end $(TYPEDSIGNATURES) Asynchronous flux computation with overlapped `solid_exchange!`. -1. `update_solid_cell!` — interpolate solid-cell df from fluid neighbors. -2. `solid_exchange_begin!` — post non-blocking MPI sends/recvs. -3. Compute flux for all non-IB faces (overlapped with communication). -4. `solid_exchange_finish!` — `MPI_Waitall` + scatter. -5. `update_solid_neighbor!` — reconstruct `SolidNeighbor` df/w/sw from the - now-synchronised ghost data. -6. Compute flux for IB faces. + 1. `update_solid_cell!` — interpolate solid-cell df from fluid neighbors. + 2. `solid_exchange_begin!` — post non-blocking MPI sends/recvs. + 3. Compute flux for all non-IB faces (overlapped with communication). + 4. `solid_exchange_finish!` — `MPI_Waitall` + scatter. + 5. `update_solid_neighbor!` — reconstruct `SolidNeighbor` df/w/sw from the + now-synchronised ghost data. + 6. Compute flux for IB faces. """ function flux!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} ibs = ka.kdata.field.immersed_boundaries @@ -471,7 +583,10 @@ function flux!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} # 3. compute non-IB face fluxes (overlapped with MPI communication) ib_face_set = Set{UInt}() for ib in ibs - for f in ib.faces; push!(ib_face_set, objectid(f)); end + for f in ib.faces + ; + push!(ib_face_set, objectid(f)); + end end _flux_nonib_faces!(F, ka.kdata.field.faces, ib_face_set, ka) @@ -486,7 +601,12 @@ function flux!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} return nothing end -function _flux_nonib_faces!(::Type{F}, faces, ib_face_set, ka::KA) where {F<:AbstractFluxType} +function _flux_nonib_faces!( + ::Type{F}, + faces, + ib_face_set, + ka::KA, +) where {F<:AbstractFluxType} for face in faces objectid(face) in ib_face_set && continue flux!(F, face, ka) @@ -500,4 +620,4 @@ function _flux_ib_faces!(::Type{F}, ibs, ka::KA) where {F<:AbstractFluxType} end end return nothing -end \ No newline at end of file +end diff --git a/src/Flux/Slope.jl b/src/Flux/Slope.jl index fdc5bc7..f0079e8 100644 --- a/src/Flux/Slope.jl +++ b/src/Flux/Slope.jl @@ -17,16 +17,21 @@ end """ $(TYPEDSIGNATURES) """ -function minmod(sL::Real,sR::Real) +function minmod(sL::Real, sR::Real) SL = abs(sL) SR = abs(sR) - 0.5(sign(sL)+sign(sR))*min(SL,SR) + 0.5(sign(sL)+sign(sR))*min(SL, SR) end """ $(TYPEDSIGNATURES) Difference through all velocity cells in two neighboring physical cells. """ -function diff_vs!(vs_data::AbstractVsData{DIM,NDF}, vs_data_n::AbstractVsData{DIM,NDF}, dsL::Float64, sL::AbstractMatrix) where{DIM,NDF} +function diff_vs!( + vs_data::AbstractVsData{DIM,NDF}, + vs_data_n::AbstractVsData{DIM,NDF}, + dsL::Float64, + sL::AbstractMatrix, +) where {DIM,NDF} index = 1 flag = 0.0 level = vs_data.level @@ -71,7 +76,7 @@ function update_slope_bound_vs!( ds::Float64, dir::Int, ws_sdf::Matrix{Float64}, -) where{DIM,NDF} +) where {DIM,NDF} vsn = vs_data.vs_num sdf = @view ws_sdf[1:vsn, :] fill!(sdf, 0.0) @@ -96,21 +101,24 @@ function update_slope_inner_vs!( dir::Int, ws_sL::Matrix{Float64}, ws_sR::Matrix{Float64}, -) where{DIM,NDF} +) where {DIM,NDF} vsn = vs_data.vs_num sL = @view ws_sL[1:vsn, :] sR = @view ws_sR[1:vsn, :] - fill!(sL, 0.0); fill!(sR, 0.0) - nL = length(Ldata); nR = length(Rdata) - for j in 1:nL + fill!(sL, 0.0); + fill!(sR, 0.0) + nL = length(Ldata); + nR = length(Rdata) + for j = 1:nL L_data = Ldata[j].vs_data diff_vs!(vs_data, L_data, dsL, sL) end - for j in 1:nR + for j = 1:nR R_data = Rdata[j].vs_data diff_vs!(vs_data, R_data, dsR, sR) end - sL ./= nL; sR ./= nR + sL ./= nL; + sR ./= nR @. vs_data.sdf[:, :, dir] = minmod(sL, sR) return nothing end @@ -126,16 +134,19 @@ function update_slope_inner_ps!( dir::Int, ws_swL::Vector{Float64}, ws_swR::Vector{Float64}, -) where{DIM,NDF} - fill!(ws_swL, 0.0); fill!(ws_swR, 0.0) - nL = length(Ldata); nR = length(Rdata) - for j in 1:nL +) where {DIM,NDF} + fill!(ws_swL, 0.0); + fill!(ws_swR, 0.0) + nL = length(Ldata); + nR = length(Rdata) + for j = 1:nL @. ws_swL += (ps_data.w - Ldata[j].w) / dsL end - for j in 1:nR + for j = 1:nR @. ws_swR += (ps_data.w - Rdata[j].w) / dsR end - ws_swL ./= nL; ws_swR ./= nR + ws_swL ./= nL; + ws_swR ./= nR for j in eachindex(ws_swL) ps_data.sw[j, dir] = minmod(ws_swL[j], ws_swR[j]) end @@ -151,10 +162,10 @@ function update_slope_bound_ps!( dsL::Float64, dir::Int, ws_swL::Vector{Float64}, -) where{DIM,NDF} +) where {DIM,NDF} fill!(ws_swL, 0.0) nL = length(Ldata) - for j in 1:nL + for j = 1:nL @. ws_swL += (ps_data.w - Ldata[j].w) / dsL end ws_swL ./= nL @@ -174,7 +185,11 @@ end # `slope!` updates levels coarsest-to-finest). # --------------------------------------------------------------------------- -@inline function _ps_has_transverse_offset(ps_data::PsData{DIM}, neighbours::AbstractVector, dir::Int) where{DIM} +@inline function _ps_has_transverse_offset( + ps_data::PsData{DIM}, + neighbours::AbstractVector, + dir::Int, +) where {DIM} DIM == 1 && return false n_count = length(neighbours) n_count == 0 && return false @@ -186,10 +201,10 @@ end # direction(s), so the average matches `ps_data` and no projection is # needed (and would otherwise rely on the fine neighbours' own sw, # which has not yet been computed in the coarsest-to-finest sweep). - @inbounds for t in 1:DIM + @inbounds for t = 1:DIM t == dir && continue avg_t = 0.0 - for j in 1:n_count + for j = 1:n_count avg_t += neighbours[j].midpoint[t] end avg_t /= n_count @@ -204,9 +219,14 @@ Returns `true` if any neighbour in `Ldata` or `Rdata` has a transverse-midpoint offset relative to `ps_data` in `dir`. Used to decide whether the transverse projection is needed at all on a given face (1-D fine cells skip the work). """ -@inline function needs_transverse_correction(ps_data::PsData, Ldata::AbstractVector, Rdata::AbstractVector, dir::Int) +@inline function needs_transverse_correction( + ps_data::PsData, + Ldata::AbstractVector, + Rdata::AbstractVector, + dir::Int, +) _ps_has_transverse_offset(ps_data, Ldata, dir) || - _ps_has_transverse_offset(ps_data, Rdata, dir) + _ps_has_transverse_offset(ps_data, Rdata, dir) end """ @@ -228,17 +248,19 @@ function update_slope_inner_ps_transverse!( dir::Int, ws_swL::Vector{Float64}, ws_swR::Vector{Float64}, -) where{DIM,NDF} - fill!(ws_swL, 0.0); fill!(ws_swR, 0.0) - nL = length(Ldata); nR = length(Rdata) +) where {DIM,NDF} + fill!(ws_swL, 0.0); + fill!(ws_swR, 0.0) + nL = length(Ldata); + nR = length(Rdata) projL = _ps_has_transverse_offset(ps_data, Ldata, dir) projR = _ps_has_transverse_offset(ps_data, Rdata, dir) - @inbounds for j in 1:nL + @inbounds for j = 1:nL n = Ldata[j] for i in eachindex(ws_swL) w_proj = n.w[i] if projL - for t in 1:DIM + for t = 1:DIM t == dir && continue w_proj += (ps_data.midpoint[t] - n.midpoint[t]) * n.sw[i, t] end @@ -246,12 +268,12 @@ function update_slope_inner_ps_transverse!( ws_swL[i] += (ps_data.w[i] - w_proj) / dsL end end - @inbounds for j in 1:nR + @inbounds for j = 1:nR n = Rdata[j] for i in eachindex(ws_swR) w_proj = n.w[i] if projR - for t in 1:DIM + for t = 1:DIM t == dir && continue w_proj += (ps_data.midpoint[t] - n.midpoint[t]) * n.sw[i, t] end @@ -259,7 +281,8 @@ function update_slope_inner_ps_transverse!( ws_swR[i] += (ps_data.w[i] - w_proj) / dsR end end - ws_swL ./= nL; ws_swR ./= nR + ws_swL ./= nL; + ws_swR ./= nR @inbounds for j in eachindex(ws_swL) ps_data.sw[j, dir] = minmod(ws_swL[j], ws_swR[j]) end @@ -281,7 +304,7 @@ function diff_vs_transverse!( dsL::Float64, dm_t::AbstractVector{Float64}, sL::AbstractMatrix, -) where{DIM,NDF} +) where {DIM,NDF} index = 1 flag = 0.0 level = vs_data.level @@ -293,7 +316,7 @@ function diff_vs_transverse!( if level[i] == level_n[index] for j = 1:NDF proj = dfn[index, j] - for t in 1:DIM + for t = 1:DIM proj += dm_t[t] * sdfn[index, j, t] end sL[i, j] += (df[i, j] - proj) / dsL @@ -303,12 +326,11 @@ function diff_vs_transverse!( while flag != 1.0 for j = 1:NDF proj = dfn[index, j] - for t in 1:DIM + for t = 1:DIM proj += dm_t[t] * sdfn[index, j, t] end sL[i, j] += - (df[i, j] - proj) / 2^(DIM * (level_n[index] - level[i])) / - dsL + (df[i, j] - proj) / 2^(DIM * (level_n[index] - level[i])) / dsL end flag += 1 / 2^(DIM * (level_n[index] - level[i])) index += 1 @@ -317,7 +339,7 @@ function diff_vs_transverse!( else for j = 1:NDF proj = dfn[index, j] - for t in 1:DIM + for t = 1:DIM proj += dm_t[t] * sdfn[index, j, t] end sL[i, j] += (df[i, j] - proj) / dsL @@ -345,20 +367,22 @@ function update_slope_inner_vs_transverse!( dir::Int, ws_sL::Matrix{Float64}, ws_sR::Matrix{Float64}, -) where{DIM,NDF} +) where {DIM,NDF} vs_data = ps_data.vs_data vsn = vs_data.vs_num sL = @view ws_sL[1:vsn, :] sR = @view ws_sR[1:vsn, :] - fill!(sL, 0.0); fill!(sR, 0.0) - nL = length(Ldata); nR = length(Rdata) + fill!(sL, 0.0); + fill!(sR, 0.0) + nL = length(Ldata); + nR = length(Rdata) projL = _ps_has_transverse_offset(ps_data, Ldata, dir) projR = _ps_has_transverse_offset(ps_data, Rdata, dir) dm = zeros(Float64, DIM) - @inbounds for j in 1:nL + @inbounds for j = 1:nL n = Ldata[j] if projL - for t in 1:DIM + for t = 1:DIM dm[t] = (t == dir) ? 0.0 : (ps_data.midpoint[t] - n.midpoint[t]) end diff_vs_transverse!(vs_data, n.vs_data, dsL, dm, sL) @@ -366,10 +390,10 @@ function update_slope_inner_vs_transverse!( diff_vs!(vs_data, n.vs_data, dsL, sL) end end - @inbounds for j in 1:nR + @inbounds for j = 1:nR n = Rdata[j] if projR - for t in 1:DIM + for t = 1:DIM dm[t] = (t == dir) ? 0.0 : (ps_data.midpoint[t] - n.midpoint[t]) end diff_vs_transverse!(vs_data, n.vs_data, dsR, dm, sR) @@ -377,7 +401,8 @@ function update_slope_inner_vs_transverse!( diff_vs!(vs_data, n.vs_data, dsR, sR) end end - sL ./= nL; sR ./= nR + sL ./= nL; + sR ./= nR @. vs_data.sdf[:, :, dir] = minmod(sL, sR) return nothing end @@ -401,14 +426,14 @@ function update_slope_bound_ps_transverse!( dsL::Float64, dir::Int, ws_swL::Vector{Float64}, -) where{DIM,NDF} +) where {DIM,NDF} fill!(ws_swL, 0.0) nL = length(Ldata) - @inbounds for j in 1:nL + @inbounds for j = 1:nL n = Ldata[j] for i in eachindex(ws_swL) w_proj = n.w[i] - for t in 1:DIM + for t = 1:DIM t == dir && continue w_proj += (ps_data.midpoint[t] - n.midpoint[t]) * n.sw[i, t] end @@ -431,16 +456,16 @@ function update_slope_bound_vs_transverse!( dsL::Float64, dir::Int, ws_sL::Matrix{Float64}, -) where{DIM,NDF} +) where {DIM,NDF} vs_data = ps_data.vs_data vsn = vs_data.vs_num sL = @view ws_sL[1:vsn, :] fill!(sL, 0.0) nL = length(Ldata) dm = zeros(Float64, DIM) - @inbounds for j in 1:nL + @inbounds for j = 1:nL n = Ldata[j] - for t in 1:DIM + for t = 1:DIM dm[t] = (t == dir) ? 0.0 : (ps_data.midpoint[t] - n.midpoint[t]) end diff_vs_transverse!(vs_data, n.vs_data, dsL, dm, sL) @@ -469,7 +494,7 @@ function update_slope!( ws_swR::Vector{Float64}, ) where {DIM,NDF} if Ldata[1].bound_enc<0&&Rdata[1].bound_enc<0 - ps_data.vs_data.sdf[:,:,dir] .= 0. + ps_data.vs_data.sdf[:, :, dir] .= 0.0 elseif Ldata[1].bound_enc<0 ds = ps_data.midpoint[dir]-Rdata[1].midpoint[dir] update_slope_bound_vs!(ps_data.vs_data, Rdata, ds, dir, ws_sL) @@ -542,7 +567,16 @@ function update_slope!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_slope_inner_vs!(ps_data.vs_data, Ldata, Rdata, 0.75 * ds, -0.75 * ds, dir, ws_sL, ws_sR) + update_slope_inner_vs!( + ps_data.vs_data, + Ldata, + Rdata, + 0.75 * ds, + -0.75 * ds, + dir, + ws_sL, + ws_sR, + ) # update_slope_inner_ps!(ps_data, Ldata, Rdata, 0.75 * ds, -0.75 * ds, dir, ws_swL, ws_swR) end """ @@ -562,7 +596,16 @@ function update_slope!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_slope_inner_vs!(ps_data.vs_data, Ldata, Rdata, 1.5 * ds, -1.5 * ds, dir, ws_sL, ws_sR) + update_slope_inner_vs!( + ps_data.vs_data, + Ldata, + Rdata, + 1.5 * ds, + -1.5 * ds, + dir, + ws_sL, + ws_sR, + ) # update_slope_inner_ps!(ps_data, Ldata, Rdata, 1.5 * ds, -1.5 * ds, dir, ws_swL, ws_swR) end """ @@ -622,7 +665,16 @@ function update_slope!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_slope_inner_vs!(ps_data.vs_data, Ldata, Rdata, 0.75 * ds, -1.5 * ds, dir, ws_sL, ws_sR) + update_slope_inner_vs!( + ps_data.vs_data, + Ldata, + Rdata, + 0.75 * ds, + -1.5 * ds, + dir, + ws_sL, + ws_sR, + ) # update_slope_inner_ps!(ps_data, Ldata, Rdata, 0.75 * ds, -1.5 * ds, dir, ws_swL, ws_swR) end """ @@ -642,7 +694,16 @@ function update_slope!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_slope_inner_vs!(ps_data.vs_data, Ldata, Rdata, 1.5 * ds, -0.75 * ds, dir, ws_sL, ws_sR) + update_slope_inner_vs!( + ps_data.vs_data, + Ldata, + Rdata, + 1.5 * ds, + -0.75 * ds, + dir, + ws_sL, + ws_sR, + ) # update_slope_inner_ps!(ps_data, Ldata, Rdata, 1.5 * ds, -0.75 * ds, dir, ws_swL, ws_swR) end @@ -773,7 +834,7 @@ end """ $(TYPEDSIGNATURES) """ -function update_slope!(ka::KA{DIM,NDF}) where{DIM,NDF} +function update_slope!(ka::KA{DIM,NDF}) where {DIM,NDF} trees = ka.kdata.field.trees kinfo = ka.kinfo @@ -787,15 +848,15 @@ function update_slope!(ka::KA{DIM,NDF}) where{DIM,NDF} end end - ws_sL = zeros(Float64, max_vsn, NDF) - ws_sR = zeros(Float64, max_vsn, NDF) + ws_sL = zeros(Float64, max_vsn, NDF) + ws_sR = zeros(Float64, max_vsn, NDF) ws_swL = zeros(Float64, DIM + 2) ws_swR = zeros(Float64, DIM + 2) @inbounds for i in eachindex(trees.data) @inbounds for j in eachindex(trees.data[i]) ps_data = trees.data[i][j] - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue ps_data.bound_enc<0 && continue # solid_cells neighbor = ps_data.neighbor for dir = 1:DIM @@ -809,7 +870,10 @@ function update_slope!(ka::KA{DIM,NDF}) where{DIM,NDF} neighbor.data[iL], neighbor.data[iR], dir, - ws_sL, ws_sR, ws_swL, ws_swR, + ws_sL, + ws_sR, + ws_swL, + ws_swR, ) end end @@ -833,20 +897,20 @@ $(TYPEDSIGNATURES) Per-level slope pass with transverse correction. For every local cell whose level equals `L`: - 1. Compute `sw`/`sdf` in **every** direction with the original dispatcher - (same kernels as [`update_slope!`](@ref)) — this initialises the - non-Val{-1} faces (same-level or hanging-fine sides) which the - transverse pass alone does not touch. - 2. Re-compute, with the transverse-projection variants, only the faces - that actually have a coarse (`Val{-1}`) neighbour, where the spurious - transverse contribution lives. + 1. Compute `sw`/`sdf` in **every** direction with the original dispatcher + (same kernels as [`update_slope!`](@ref)) — this initialises the + non-Val{-1} faces (same-level or hanging-fine sides) which the + transverse pass alone does not touch. + 2. Re-compute, with the transverse-projection variants, only the faces + that actually have a coarse (`Val{-1}`) neighbour, where the spurious + transverse contribution lives. This must be invoked from the coarsest level upward, with [`slope_exchange_level!`](@ref) called after every level so the corrected coarse-side `sw`/`sdf` are visible across ranks before the next level reads them. """ -function update_slope_transverse_level!(ka::KA{DIM,NDF}, L::Integer) where{DIM,NDF} +function update_slope_transverse_level!(ka::KA{DIM,NDF}, L::Integer) where {DIM,NDF} trees = ka.kdata.field.trees kinfo = ka.kinfo @@ -859,8 +923,8 @@ function update_slope_transverse_level!(ka::KA{DIM,NDF}, L::Integer) where{DIM,N max_vsn = max(max_vsn, ps_data.vs_data.vs_num) end end - ws_sL = zeros(Float64, max_vsn, NDF) - ws_sR = zeros(Float64, max_vsn, NDF) + ws_sL = zeros(Float64, max_vsn, NDF) + ws_sR = zeros(Float64, max_vsn, NDF) ws_swL = zeros(Float64, DIM + 2) ws_swR = zeros(Float64, DIM + 2) @@ -887,7 +951,10 @@ function update_slope_transverse_level!(ka::KA{DIM,NDF}, L::Integer) where{DIM,N neighbor.data[iL], neighbor.data[iR], dir, - ws_sL, ws_sR, ws_swL, ws_swR, + ws_sL, + ws_sR, + ws_swL, + ws_swR, ) end @@ -918,11 +985,20 @@ function update_slope_transverse_level!(ka::KA{DIM,NDF}, L::Integer) where{DIM,N # (Ldata[1].bound_enc < 0 || Rdata[1].bound_enc < 0) && continue dsL = ps_data.midpoint[dir] - Ldata[1].midpoint[dir] dsR = ps_data.midpoint[dir] - Rdata[1].midpoint[dir] - update_slope_inner_vs_transverse!(ps_data, Ldata, Rdata, dsL, dsR, dir, ws_sL, ws_sR) + update_slope_inner_vs_transverse!( + ps_data, + Ldata, + Rdata, + dsL, + dsR, + dir, + ws_sL, + ws_sR, + ) if Ldata[1].bound_enc<0 - update_slope_bound_vs_transverse!(ps_data,Rdata,dsR,dir,ws_sL) + update_slope_bound_vs_transverse!(ps_data, Rdata, dsR, dir, ws_sL) elseif Rdata[1].bound_enc<0 - update_slope_bound_vs_transverse!(ps_data,Ldata,dsL,dir,ws_sL) + update_slope_bound_vs_transverse!(ps_data, Ldata, dsL, dir, ws_sL) end # update_slope_inner_ps_transverse!(ps_data, Ldata, Rdata, dsL, dsR, dir, ws_swL, ws_swR) elseif sR_state == 0 && sL_state == -1 @@ -974,7 +1050,7 @@ every local cell whose physical-space level equals `L`, using the original the sweep at `L_min` — those cells have no coarser neighbour and therefore their first-pass slopes are already final. """ -function update_slope_level!(ka::KA{DIM,NDF}, L::Integer) where{DIM,NDF} +function update_slope_level!(ka::KA{DIM,NDF}, L::Integer) where {DIM,NDF} trees = ka.kdata.field.trees kinfo = ka.kinfo @@ -987,8 +1063,8 @@ function update_slope_level!(ka::KA{DIM,NDF}, L::Integer) where{DIM,NDF} max_vsn = max(max_vsn, ps_data.vs_data.vs_num) end end - ws_sL = zeros(Float64, max_vsn, NDF) - ws_sR = zeros(Float64, max_vsn, NDF) + ws_sL = zeros(Float64, max_vsn, NDF) + ws_sR = zeros(Float64, max_vsn, NDF) ws_swL = zeros(Float64, DIM + 2) ws_swR = zeros(Float64, DIM + 2) @@ -1010,7 +1086,10 @@ function update_slope_level!(ka::KA{DIM,NDF}, L::Integer) where{DIM,NDF} neighbor.data[iL], neighbor.data[iR], dir, - ws_sL, ws_sR, ws_swL, ws_swR, + ws_sL, + ws_sR, + ws_swL, + ws_swR, ) end end @@ -1019,7 +1098,7 @@ function update_slope_level!(ka::KA{DIM,NDF}, L::Integer) where{DIM,NDF} end -function update_macro_slope!(ka::KA{DIM}) where{DIM} +function update_macro_slope!(ka::KA{DIM}) where {DIM} trees = ka.kdata.field.trees kinfo = ka.kinfo @inbounds for i in eachindex(trees.data) @@ -1029,7 +1108,12 @@ function update_macro_slope!(ka::KA{DIM}) where{DIM} ps_data.bound_enc < 0 && continue vs_data = ps_data.vs_data for dir = 1:DIM - ps_data.sw[:,dir] .= @views calc_w0(vs_data.midpoint,vs_data.sdf[:,:,dir],vs_data.weight,kinfo) + ps_data.sw[:, dir] .= @views calc_w0( + vs_data.midpoint, + vs_data.sdf[:, :, dir], + vs_data.weight, + kinfo, + ) end end end @@ -1044,7 +1128,7 @@ corrected mirror/ghost data is exchanged over MPI between levels. Call once per step **after** [`adaptive_mesh_refinement!`](@ref) / [`limit_Δt!`](@ref) and **before** [`flux!`](@ref), which consumes these slopes. (The [`solve!`](@ref) driver does this.) """ -function slope!(p4est::P_pxest_t,ka::KA{DIM}) where{DIM} +function slope!(p4est::P_pxest_t, ka::KA{DIM}) where {DIM} L_min = min_cell_level(ka) L_max = ka.kinfo.config.solver.AMR_PS_MAXLEVEL @@ -1060,7 +1144,7 @@ function slope!(p4est::P_pxest_t,ka::KA{DIM}) where{DIM} # next level reads the freshly-corrected coarse data. Each exchange is # filtered to mirrors/ghosts whose level equals `L`, so the per-level # communication cost scales with the size of that level alone. - for L in (L_min + 1):L_max + for L = (L_min+1):L_max update_slope_transverse_level!(ka, L) slope_exchange_level!(p4est, ka, L) end diff --git a/src/Flux/UGKS.jl b/src/Flux/UGKS.jl index cb8f52b..4bd87bc 100644 --- a/src/Flux/UGKS.jl +++ b/src/Flux/UGKS.jl @@ -1,31 +1,46 @@ -function calc_domain_flux(::Type{UGKS},here_vs::FaceVsData,face::DomainFace{2,2,SuperSonicInflow},ka::KA) - rot,direction,midpoint,_,here_data = unpack(face) - heavi,_,_,_,here_df,here_sdf = unpack(here_vs) +function calc_domain_flux( + ::Type{UGKS}, + here_vs::FaceVsData, + face::DomainFace{2,2,SuperSonicInflow}, + ka::KA, +) + rot, direction, midpoint, _, here_data = unpack(face) + heavi, _, _, _, here_df, here_sdf = unpack(here_vs) kinfo = ka.kinfo gas = kinfo.config.gas Δt = kinfo.status.Δt vs_data = here_data.vs_data nheavi = .!heavi - there_mid = @views vs_data.midpoint[nheavi,:] + there_mid = @views vs_data.midpoint[nheavi, :] there_weight = @views vs_data.weight[nheavi] - there_vn = @views there_mid[:,direction] - there_sdf = @views vs_data.sdf[nheavi,:,:] + there_vn = @views there_mid[:, direction] + there_sdf = @views vs_data.sdf[nheavi, :, :] dx = midpoint-here_data.midpoint bc = get_bc(face.domain.bc) - domain_w = get_conserved(bc,kinfo) + domain_w = get_conserved(bc, kinfo) df = copy(here_df) for k in axes(here_sdf, 3) @views @. df += dx[k] * here_sdf[:, :, k] end - ndf = Matrix{Float64}(undef,size(there_mid,1),2) - @inbounds for i in axes(ndf,1) - @views ndf[i,:] .= discrete_maxwell(there_mid[i,:],bc,kinfo) + ndf = Matrix{Float64}(undef, size(there_mid, 1), 2) + @inbounds for i in axes(ndf, 1) + @views ndf[i, :] .= discrete_maxwell(there_mid[i, :], bc, kinfo) end - Here_vs = FaceVsData(here_vs,df);There_vs = FaceVsData{2,2}(nheavi,there_weight,there_mid,there_vn,ndf,there_sdf) - w0 = calc_w0(Here_vs,There_vs) + Here_vs = FaceVsData(here_vs, df); + There_vs = FaceVsData{2,2}(nheavi, there_weight, there_mid, there_vn, ndf, there_sdf) + w0 = calc_w0(Here_vs, There_vs) prim0 = get_prim(w0, kinfo) - qf0 = calc_qf(Here_vs,There_vs,prim0) - aL, aR = calc_a(w0, prim0, here_data.w, domain_w, here_data.ds[direction], here_data.ds[direction], kinfo, rot) + qf0 = calc_qf(Here_vs, There_vs, prim0) + aL, aR = calc_a( + w0, + prim0, + here_data.w, + domain_w, + here_data.ds[direction], + here_data.ds[direction], + kinfo, + rot, + ) Mu, Mv, Mξ, Mu_L, Mu_R = moment_u(prim0, kinfo, rot, direction) A = calc_A(prim0, aL, aR, Mu, Mv, Mξ, Mu_L, Mu_R, kinfo, direction) τ0 = get_τ(prim0, gas.μᵣ, gas.ω) @@ -38,29 +53,51 @@ function calc_domain_flux(::Type{UGKS},here_vs::FaceVsData,face::DomainFace{2,2, fw += calc_flux_f0(Here_vs, There_vs, here_F⁺, there_F⁺, Mt, direction) here_micro = calc_micro_flux(Here_vs, here_F, here_F⁺, aL, A, Mξ, Mt, direction) there_micro = calc_micro_flux(There_vs, there_F, there_F⁺, aR, A, Mξ, Mt, direction) - return fw,[here_micro,there_micro] + return fw, [here_micro, there_micro] end -function calc_domain_flux(::Type{UGKS},here_vs::FaceVsData,face::DomainFace{2,2,UniformOutflow},ka::KA) - rot,direction,midpoint,_,here_data = unpack(face) - heavi,here_weight,here_mid,here_vn,here_df,here_sdf = unpack(here_vs) +function calc_domain_flux( + ::Type{UGKS}, + here_vs::FaceVsData, + face::DomainFace{2,2,UniformOutflow}, + ka::KA, +) + rot, direction, midpoint, _, here_data = unpack(face) + heavi, here_weight, here_mid, here_vn, here_df, here_sdf = unpack(here_vs) kinfo = ka.kinfo gas = kinfo.config.gas Δt = kinfo.status.Δt vs_data = here_data.vs_data nheavi = [!x for x in heavi] - there_mid = @views vs_data.midpoint[nheavi,:] + there_mid = @views vs_data.midpoint[nheavi, :] there_weight = @views vs_data.weight[nheavi] - there_vn = @views there_mid[:,direction] - there_df = @views vs_data.df[nheavi,:] - there_sdf = @views vs_data.sdf[nheavi,:,:] + there_vn = @views there_mid[:, direction] + there_df = @views vs_data.df[nheavi, :] + there_sdf = @views vs_data.sdf[nheavi, :, :] df = here_df ndf = there_df - Here_vs = FaceVsData{2,2}(heavi,here_weight,here_mid,here_vn,df,zeros(size(here_sdf))) - There_vs = FaceVsData{2,2}(nheavi,there_weight,there_mid,there_vn,ndf,zeros(size(there_sdf))) - w0 = calc_w0(Here_vs,There_vs) + Here_vs = + FaceVsData{2,2}(heavi, here_weight, here_mid, here_vn, df, zeros(size(here_sdf))) + There_vs = FaceVsData{2,2}( + nheavi, + there_weight, + there_mid, + there_vn, + ndf, + zeros(size(there_sdf)), + ) + w0 = calc_w0(Here_vs, There_vs) prim0 = get_prim(w0, kinfo) - qf0 = calc_qf(Here_vs,There_vs,prim0) - aL, aR = calc_a(w0, prim0, here_data.w, w0, here_data.ds[direction], here_data.ds[direction], kinfo, rot) + qf0 = calc_qf(Here_vs, There_vs, prim0) + aL, aR = calc_a( + w0, + prim0, + here_data.w, + w0, + here_data.ds[direction], + here_data.ds[direction], + kinfo, + rot, + ) Mu, Mv, Mξ, Mu_L, Mu_R = moment_u(prim0, kinfo, rot, direction) A = calc_A(prim0, aL, aR, Mu, Mv, Mξ, Mu_L, Mu_R, kinfo, direction) τ0 = get_τ(prim0, gas.μᵣ, gas.ω) @@ -73,34 +110,56 @@ function calc_domain_flux(::Type{UGKS},here_vs::FaceVsData,face::DomainFace{2,2, fw += calc_flux_f0(Here_vs, There_vs, here_F⁺, there_F⁺, Mt, direction) here_micro = calc_micro_flux(Here_vs, here_F, here_F⁺, aL, A, Mξ, Mt, direction) there_micro = calc_micro_flux(There_vs, there_F, there_F⁺, aR, A, Mξ, Mt, direction) - return fw,[here_micro,there_micro] + return fw, [here_micro, there_micro] end -function calc_domain_flux(::Type{UGKS},here_vs::FaceVsData,face::DomainFace{2,2,InterpolatedOutflow},ka::KA) - rot,direction,midpoint,_,here_data = unpack(face) - heavi,here_weight,here_mid,here_vn,here_df,here_sdf = unpack(here_vs) +function calc_domain_flux( + ::Type{UGKS}, + here_vs::FaceVsData, + face::DomainFace{2,2,InterpolatedOutflow}, + ka::KA, +) + rot, direction, midpoint, _, here_data = unpack(face) + heavi, here_weight, here_mid, here_vn, here_df, here_sdf = unpack(here_vs) kinfo = ka.kinfo gas = kinfo.config.gas Δt = kinfo.status.Δt vs_data = here_data.vs_data here_ps_mid = here_data.midpoint nheavi = [!x for x in heavi] - there_mid = @views vs_data.midpoint[nheavi,:] + there_mid = @views vs_data.midpoint[nheavi, :] there_weight = @views vs_data.weight[nheavi] - there_vn = @views there_mid[:,direction] - there_df = @views vs_data.df[nheavi,:]+2.0*vs_data.sdf[nheavi,:,direction]*(midpoint[direction]-here_ps_mid[direction]) - there_sdf = @views vs_data.sdf[nheavi,:,:] + there_vn = @views there_mid[:, direction] + there_df = @views vs_data.df[nheavi, :]+2.0*vs_data.sdf[nheavi, :, direction]*( + midpoint[direction]-here_ps_mid[direction] + ) + there_sdf = @views vs_data.sdf[nheavi, :, :] dx = midpoint-here_ps_mid ndx = -dx @inbounds @views begin - df = [here_df[i,j]+dot(dx,here_sdf[i,j,:]) for i in axes(here_df,1),j in axes(here_df,2)] - ndf = [there_df[i,j]+dot(ndx,there_sdf[i,j,:]) for i in axes(there_df,1),j in axes(there_df,2)] + df = [ + here_df[i, j]+dot(dx, here_sdf[i, j, :]) for + i in axes(here_df, 1), j in axes(here_df, 2) + ] + ndf = [ + there_df[i, j]+dot(ndx, there_sdf[i, j, :]) for + i in axes(there_df, 1), j in axes(there_df, 2) + ] end - Here_vs = FaceVsData{2,2}(heavi,here_weight,here_mid,here_vn,df,here_sdf) - There_vs = FaceVsData{2,2}(nheavi,there_weight,there_mid,there_vn,ndf,there_sdf) - w0 = calc_w0(Here_vs,There_vs) + Here_vs = FaceVsData{2,2}(heavi, here_weight, here_mid, here_vn, df, here_sdf) + There_vs = FaceVsData{2,2}(nheavi, there_weight, there_mid, there_vn, ndf, there_sdf) + w0 = calc_w0(Here_vs, There_vs) prim0 = get_prim(w0, kinfo) - qf0 = calc_qf(Here_vs,There_vs,prim0) - aL, aR = calc_a(w0, prim0, here_data.w, 2.0*w0-here_data.w, here_data.ds[direction], here_data.ds[direction], kinfo, rot) + qf0 = calc_qf(Here_vs, There_vs, prim0) + aL, aR = calc_a( + w0, + prim0, + here_data.w, + 2.0*w0-here_data.w, + here_data.ds[direction], + here_data.ds[direction], + kinfo, + rot, + ) Mu, Mv, Mξ, Mu_L, Mu_R = moment_u(prim0, kinfo, rot, direction) A = calc_A(prim0, aL, aR, Mu, Mv, Mξ, Mu_L, Mu_R, kinfo, direction) τ0 = get_τ(prim0, gas.μᵣ, gas.ω) @@ -113,52 +172,87 @@ function calc_domain_flux(::Type{UGKS},here_vs::FaceVsData,face::DomainFace{2,2, fw += calc_flux_f0(Here_vs, There_vs, here_F⁺, there_F⁺, Mt, direction) here_micro = calc_micro_flux(Here_vs, here_F, here_F⁺, aL, A, Mξ, Mt, direction) there_micro = calc_micro_flux(There_vs, there_F, there_F⁺, aR, A, Mξ, Mt, direction) - return fw,[here_micro,there_micro] + return fw, [here_micro, there_micro] end -function calc_w0(here_vs::FaceVsData{2,2},there_vs::FaceVsData) +function calc_w0(here_vs::FaceVsData{2,2}, there_vs::FaceVsData) @inbounds @views micro_to_macro_2D2F( - here_vs.midpoint[:,1],here_vs.midpoint[:,2], - here_vs.df[:,1],here_vs.df[:,2],here_vs.weight - ) + - micro_to_macro_2D2F( - there_vs.midpoint[:,1],there_vs.midpoint[:,2], - there_vs.df[:,1],there_vs.df[:,2],there_vs.weight + here_vs.midpoint[:, 1], + here_vs.midpoint[:, 2], + here_vs.df[:, 1], + here_vs.df[:, 2], + here_vs.weight, + ) + micro_to_macro_2D2F( + there_vs.midpoint[:, 1], + there_vs.midpoint[:, 2], + there_vs.df[:, 1], + there_vs.df[:, 2], + there_vs.weight, ) end -function calc_w0(here_vs::FaceVsData{3,1},there_vs::FaceVsData) +function calc_w0(here_vs::FaceVsData{3,1}, there_vs::FaceVsData) @inbounds @views micro_to_macro_3D1F( - here_vs.midpoint[:,1],here_vs.midpoint[:,2], - here_vs.df[:,1],here_vs.df[:,2],here_vs.weight - ) + - micro_to_macro_3D1F( - there_vs.midpoint[:,1],there_vs.midpoint[:,2], - there_vs.df[:,1],there_vs.df[:,2],there_vs.weight + here_vs.midpoint[:, 1], + here_vs.midpoint[:, 2], + here_vs.df[:, 1], + here_vs.df[:, 2], + here_vs.weight, + ) + micro_to_macro_3D1F( + there_vs.midpoint[:, 1], + there_vs.midpoint[:, 2], + there_vs.df[:, 1], + there_vs.df[:, 2], + there_vs.weight, ) end -function calc_qf(here_vs::FaceVsData{2,2},there_vs::FaceVsData,prim::AbstractVector) +function calc_qf(here_vs::FaceVsData{2,2}, there_vs::FaceVsData, prim::AbstractVector) @inbounds @views heat_flux_2D2F( - here_vs.midpoint[:,1],here_vs.midpoint[:,2], - here_vs.df[:,1],here_vs.df[:,2], - prim,here_vs.weight, - ) + - heat_flux_2D2F( - there_vs.midpoint[:,1],there_vs.midpoint[:,2], - there_vs.df[:,1],there_vs.df[:,2], - prim,there_vs.weight, + here_vs.midpoint[:, 1], + here_vs.midpoint[:, 2], + here_vs.df[:, 1], + here_vs.df[:, 2], + prim, + here_vs.weight, + ) + heat_flux_2D2F( + there_vs.midpoint[:, 1], + there_vs.midpoint[:, 2], + there_vs.df[:, 1], + there_vs.df[:, 2], + prim, + there_vs.weight, ) end -function calc_flux_f0(hvd::FaceVsData{2,2},tvd,here_F::AbstractMatrix,there_F,Mt,direction::Int) +function calc_flux_f0( + hvd::FaceVsData{2,2}, + tvd, + here_F::AbstractMatrix, + there_F, + Mt, + direction::Int, +) @inbounds @views calc_flux_f0_2D2F( - hvd.midpoint[:,1],hvd.midpoint[:,2], - hvd.df[:,1],hvd.df[:,2], - hvd.sdf[:,1,direction],hvd.sdf[:,2,direction], - hvd.weight,here_F[:,1],here_F[:,2],hvd.vn,Mt - ) + - calc_flux_f0_2D2F( - tvd.midpoint[:,1],tvd.midpoint[:,2], - tvd.df[:,1],tvd.df[:,2], - tvd.sdf[:,1,direction],tvd.sdf[:,2,direction], - tvd.weight,there_F[:,1],there_F[:,2],tvd.vn,Mt + hvd.midpoint[:, 1], + hvd.midpoint[:, 2], + hvd.df[:, 1], + hvd.df[:, 2], + hvd.sdf[:, 1, direction], + hvd.sdf[:, 2, direction], + hvd.weight, + here_F[:, 1], + here_F[:, 2], + hvd.vn, + Mt, + ) + calc_flux_f0_2D2F( + tvd.midpoint[:, 1], + tvd.midpoint[:, 2], + tvd.df[:, 1], + tvd.df[:, 2], + tvd.sdf[:, 1, direction], + tvd.sdf[:, 2, direction], + tvd.weight, + there_F[:, 1], + there_F[:, 2], + tvd.vn, + Mt, ) end @@ -190,7 +284,7 @@ function calc_micro_flux_2D2F( ax[2] * u * H0 + ax[3] * v * H0 + 0.5 * ax[4] * ((u^2 + v^2) * H0 + B0) - )+ + ) + Mt[3] * vn * ( @@ -238,8 +332,8 @@ function calc_micro_flux( f_vs_data.midpoint[:, 2], f_vs_data.df[:, 1], f_vs_data.df[:, 2], - f_vs_data.sdf[:, 1,direction], - f_vs_data.sdf[:, 2,direction], + f_vs_data.sdf[:, 1, direction], + f_vs_data.sdf[:, 2, direction], F0[:, 1], F0[:, 2], F⁺[:, 1], @@ -252,27 +346,53 @@ function calc_micro_flux( ) end end -function calc_flux(::Type{UGKS},here_vs,there_vs,flux_data::Union{FullFace,FluxData},ka::KA{2,2}) # without face area - rot,direction,midpoint,here_data,there_data = unpack(flux_data) +function calc_flux( + ::Type{UGKS}, + here_vs, + there_vs, + flux_data::Union{FullFace,FluxData}, + ka::KA{2,2}, +) # without face area + rot, direction, midpoint, here_data, there_data = unpack(flux_data) kinfo = ka.kinfo - gas = kinfo.config.gas;Δt = kinfo.status.Δt - here_df = here_vs.df;there_df = there_vs.df - here_sdf = here_vs.sdf;there_sdf = there_vs.sdf - here_ps_mid = here_data.midpoint;there_ps_mid = there_data.midpoint + gas = kinfo.config.gas; + Δt = kinfo.status.Δt + here_df = here_vs.df; + there_df = there_vs.df + here_sdf = here_vs.sdf; + there_sdf = there_vs.sdf + here_ps_mid = here_data.midpoint; + there_ps_mid = there_data.midpoint dx = midpoint-here_ps_mid ndx = midpoint-there_ps_mid @inbounds @views begin - df = [here_df[i,j]+dot(dx,here_sdf[i,j,:]) for i in axes(here_df,1),j in axes(here_df,2)] - ndf = [there_df[i,j]+dot(ndx,there_sdf[i,j,:]) for i in axes(there_df,1),j in axes(there_df,2)] + df = [ + here_df[i, j]+dot(dx, here_sdf[i, j, :]) for + i in axes(here_df, 1), j in axes(here_df, 2) + ] + ndf = [ + there_df[i, j]+dot(ndx, there_sdf[i, j, :]) for + i in axes(there_df, 1), j in axes(there_df, 2) + ] end - Here_vs = FaceVsData(here_vs,df);There_vs = FaceVsData(there_vs,ndf) - w0 = calc_w0(Here_vs,There_vs) + Here_vs = FaceVsData(here_vs, df); + There_vs = FaceVsData(there_vs, ndf) + w0 = calc_w0(Here_vs, There_vs) prim0 = get_prim(w0, kinfo) if 1/prim0[end]>1e-6 - qf0 = calc_qf(Here_vs,There_vs,prim0) - wL = @. here_data.w+dx[FAT[1][direction]]*here_data.sw[:,FAT[1][direction]] - wR = @. there_data.w+ndx[FAT[1][direction]]*there_data.sw[:,FAT[1][direction]] - aL, aR = calc_a(w0, prim0, wL, wR, here_data.ds[direction], there_data.ds[direction], kinfo, rot) + qf0 = calc_qf(Here_vs, There_vs, prim0) + wL = @. here_data.w+dx[FAT[1][direction]]*here_data.sw[:, FAT[1][direction]] + wR = @. there_data.w+ndx[FAT[1][direction]]*there_data.sw[:, FAT[1][direction]] + aL, aR = calc_a( + w0, + prim0, + wL, + wR, + here_data.ds[direction], + there_data.ds[direction], + kinfo, + rot, + ) Mu, Mv, Mξ, Mu_L, Mu_R = moment_u(prim0, kinfo, rot, direction) A = calc_A(prim0, aL, aR, Mu, Mv, Mξ, Mu_L, Mu_R, kinfo, direction) τ0 = get_τ(prim0, gas.μᵣ, gas.ω) @@ -286,10 +406,11 @@ function calc_flux(::Type{UGKS},here_vs,there_vs,flux_data::Union{FullFace,FluxD here_micro = calc_micro_flux(Here_vs, here_F, here_F⁺, aL, A, Mξ, Mt, direction) there_micro = calc_micro_flux(There_vs, there_F, there_F⁺, aR, A, Mξ, Mt, direction) else - fw, microflux = calc_flux(CAIDVM,here_vs,there_vs,flux_data,ka) - here_micro,there_micro = microflux - here_micro *= kinfo.status.Δt;there_micro *= kinfo.status.Δt + fw, microflux = calc_flux(CAIDVM, here_vs, there_vs, flux_data, ka) + here_micro, there_micro = microflux + here_micro *= kinfo.status.Δt; + there_micro *= kinfo.status.Δt fw *= kinfo.status.Δt end - return fw,[here_micro,there_micro] -end \ No newline at end of file + return fw, [here_micro, there_micro] +end diff --git a/src/Gas/Gas.jl b/src/Gas/Gas.jl index 1ea62a7..4718fec 100644 --- a/src/Gas/Gas.jl +++ b/src/Gas/Gas.jl @@ -1,3 +1,3 @@ include("Model.jl") -export Gas, ref_vhs_vis, get_τ \ No newline at end of file +export Gas, ref_vhs_vis, get_τ diff --git a/src/Gas/Model.jl b/src/Gas/Model.jl index d886faf..8a5e170 100644 --- a/src/Gas/Model.jl +++ b/src/Gas/Model.jl @@ -2,8 +2,9 @@ $(TYPEDSIGNATURES) Reference viscousity obtained by VHS molecules model. """ -function ref_vhs_vis(Kn, omega, alpha = 1., T_ref = 1.) - μ_0 = 5.0 * (alpha + 1.0) * (alpha + 2.0) * √π / +function ref_vhs_vis(Kn, omega, alpha = 1.0, T_ref = 1.0) + μ_0 = + 5.0 * (alpha + 1.0) * (alpha + 2.0) * √π / (4.0 * alpha * (5.0 - 2.0 * omega) * (7.0 - 2.0 * omega)) * Kn return μ_0*(T_ref)^(0.5-omega) end @@ -11,4 +12,4 @@ end $(TYPEDSIGNATURES) Calculate collisional time. """ -get_τ(prim::AbstractVector, μ::Real, ω::Real) = μ * 2.0 * prim[end]^(1 - ω) / prim[1] \ No newline at end of file +get_τ(prim::AbstractVector, μ::Real, ω::Real) = μ * 2.0 * prim[end]^(1 - ω) / prim[1] diff --git a/src/Gas/Types.jl b/src/Gas/Types.jl index f193068..ae22c4a 100644 --- a/src/Gas/Types.jl +++ b/src/Gas/Types.jl @@ -3,36 +3,52 @@ $(TYPEDEF) $(TYPEDFIELDS) """ mutable struct Gas <: AbstractGas - "Default is `0.05`." + """ + Default is `0.05`. + """ Kn::Float64 - "Default is `2/3`." + """ + Default is `2/3`. + """ Pr::Float64 - "The translational internal DOF.Default is `1.0`." + """ + The translational internal DOF.Default is `1.0`. # for 1-D, K = N+2; for 2-D, K = N+1; for 3-D, K = N; where, N denotes the degree of internal freedom (containing rotational and viberational, etc., but not translational.) + """ K::Float64 # for 1-D, K = N+2; for 2-D, K = N+1; for 3-D, K = N; where, N denotes the degree of internal freedom (containing rotational and viberational, etc., but not translational.) - "Default is `5/3`." + """ + Default is `5/3`. # γ=Cₚ/Cᵥ=((N+3)+2)/(N+3). For monotomic gas, N=0 and γ=5/3. + """ γ::Float64 # γ=Cₚ/Cᵥ=((N+3)+2)/(N+3). For monotomic gas, N=0 and γ=5/3. - "Default is `0.5`." + """ + Default is `0.5`. + """ ω::Float64 - "Default is `1.0`." + """ + Default is `1.0`. + """ αᵣ::Float64 - "Default is `0.81`." + """ + Default is `0.81`. + """ ωᵣ::Float64 - "The reference viscosity. Default is computed by [`ref_vhs_vis`](@ref)." + """ + The reference viscosity. Default is computed by [`ref_vhs_vis`](@ref). + """ μᵣ::Float64 - "The reference temperature of the molecular model. Default is `1.0`." + """ + The reference temperature of the molecular model. Default is `1.0`. # The reference temperature of the molecular model + """ T_ref::Float64 # The reference temperature of the molecular model end -function Gas(;kwargs...) - Kn = haskey(kwargs,:Kn) ? kwargs[:Kn] : 0.05 - Pr = haskey(kwargs,:Pr) ? kwargs[:Pr] : 2/3 - K = haskey(kwargs,:K) ? kwargs[:K] : 1.0 - γ = haskey(kwargs,:γ) ? kwargs[:γ] : 5/3 - ω = haskey(kwargs,:ω) ? kwargs[:ω] : 0.5 - αᵣ = haskey(kwargs,:αᵣ) ? kwargs[:αᵣ] : 1.0 - ωᵣ = haskey(kwargs,:ωᵣ) ? kwargs[:ωᵣ] : 0.81 - μᵣ = haskey(kwargs,:μᵣ) ? kwargs[:μᵣ] : ref_vhs_vis(Kn,αᵣ,ωᵣ) - T_ref = haskey(kwargs,:T_ref) ? kwargs[:T_ref] : 1.0 - return Gas( - Kn,Pr,K,γ,ω,αᵣ,ωᵣ,μᵣ,T_ref - ) -end \ No newline at end of file +function Gas(; kwargs...) + Kn = haskey(kwargs, :Kn) ? kwargs[:Kn] : 0.05 + Pr = haskey(kwargs, :Pr) ? kwargs[:Pr] : 2/3 + K = haskey(kwargs, :K) ? kwargs[:K] : 1.0 + γ = haskey(kwargs, :γ) ? kwargs[:γ] : 5/3 + ω = haskey(kwargs, :ω) ? kwargs[:ω] : 0.5 + αᵣ = haskey(kwargs, :αᵣ) ? kwargs[:αᵣ] : 1.0 + ωᵣ = haskey(kwargs, :ωᵣ) ? kwargs[:ωᵣ] : 0.81 + μᵣ = haskey(kwargs, :μᵣ) ? kwargs[:μᵣ] : ref_vhs_vis(Kn, αᵣ, ωᵣ) + T_ref = haskey(kwargs, :T_ref) ? kwargs[:T_ref] : 1.0 + return Gas(Kn, Pr, K, γ, ω, αᵣ, ωᵣ, μᵣ, T_ref) +end diff --git a/src/IO/Check.jl b/src/IO/Check.jl index 772bb5a..02d1445 100644 --- a/src/IO/Check.jl +++ b/src/IO/Check.jl @@ -2,16 +2,17 @@ $(SIGNATURES) Perform a check procedure. Simulation status will be output every `ST_CHECK_INTERVAL` steps. """ -function check!(p4est,ka) +function check!(p4est, ka) if ka.kinfo.status.step%ka.kinfo.config.solver.ST_CHECK_INTERVAL==0 - execute_check!(p4est,ka) - check_for_save!(p4est,ka) + execute_check!(p4est, ka) + check_for_save!(p4est, ka) end end -function execute_check!(p4est,ka) +function execute_check!(p4est, ka) status = ka.kinfo.status - max_vs_num,total_phase_num = check_vs_num(ka) - status.max_vs_num = max_vs_num;status.total_phase_num = total_phase_num + max_vs_num, total_phase_num = check_vs_num(ka) + status.max_vs_num = max_vs_num; + status.total_phase_num = total_phase_num if MPI.Comm_rank(MPI.COMM_WORLD) == 0 println("Iteration: $(ka.kinfo.status.step)") sim_time = ka.kinfo.status.sim_time @@ -37,7 +38,7 @@ Start listening for the input from command line. Must be called before calling [ No-op when `stdin` does not support async reading — e.g. an `IOStream` under `Pkg.test` or redirected input — in which case the runtime `save` command is unavailable for that run. """ -function listen_for_save!(;rank=0) +function listen_for_save!(; rank = 0) if MPI.Comm_rank(MPI.COMM_WORLD)==rank && _stdin_listenable() Base.start_reading(stdin) end @@ -47,7 +48,7 @@ end $(SIGNATURES) Check whether `save` is input during the iteration. If the result is true, a saving process will be executed. """ -function check_for_save!(p4est::P_pxest_t,ka;rank=0) +function check_for_save!(p4est::P_pxest_t, ka; rank = 0) save_flag = ka.kinfo.status.save_flag if MPI.Comm_rank(MPI.COMM_WORLD)==rank && _stdin_listenable() if bytesavailable(stdin)!=0 @@ -57,10 +58,10 @@ function check_for_save!(p4est::P_pxest_t,ka;rank=0) end end end - MPI.Bcast!(save_flag,rank,MPI.COMM_WORLD) + MPI.Bcast!(save_flag, rank, MPI.COMM_WORLD) if save_flag[] == true MPI.Comm_rank(MPI.COMM_WORLD)==rank&&println("saving...") - save_result(p4est,ka) + save_result(p4est, ka) MPI.Comm_rank(MPI.COMM_WORLD)==rank&&println("done.") save_flag[] = false end @@ -75,55 +76,43 @@ is disabled (`output.anim_dt <= 0`, the default). Which cells write their veloci controlled by `output.vs_output_criterion` (see [`Output`](@ref)). Intended to be called once per step after [`iterate!`](@ref); [`solve!`](@ref) does this when `animation = true`. """ -function check_for_animsave!(p4est::P_pxest_t,ka;path="./animation") +function check_for_animsave!(p4est::P_pxest_t, ka; path = "./animation") output = ka.kinfo.config.output - output.anim_dt <= 0. && return nothing # animation disabled; safe no-op + output.anim_dt <= 0.0 && return nothing # animation disabled; safe no-op sim_time = ka.kinfo.status.sim_time - if sim_time==0. + if sim_time==0.0 step = output.anim_index - for (celltype,suffix) in celltype_outputs(output.vtk_celltype) - save_anim_field(path,p4est,ka,celltype,step,sim_time,0,suffix) + for (celltype, suffix) in celltype_outputs(output.vtk_celltype) + save_anim_field(path, p4est, ka, celltype, step, sim_time, 0, suffix) end - save_anim_vs(path,ka,step,sim_time,0) + save_anim_vs(path, ka, step, sim_time, 0) elseif sim_time >= (output.anim_index+1)*output.anim_dt - 1e-10*output.anim_dt step = output.anim_index+1 - for (celltype,suffix) in celltype_outputs(output.vtk_celltype) - save_anim_field(path,p4est,ka,celltype,step,sim_time,1,suffix) + for (celltype, suffix) in celltype_outputs(output.vtk_celltype) + save_anim_field(path, p4est, ka, celltype, step, sim_time, 1, suffix) end - save_anim_vs(path,ka,step,sim_time,1) + save_anim_vs(path, ka, step, sim_time, 1) output.anim_index += 1 end end function check_vs_num(ka::KA) trees = ka.kdata.field.trees.data - buffer = zeros(Int,2) # [max,total] + buffer = zeros(Int, 2) # [max,total] for tree in trees for ps_data in tree - isa(ps_data,InsideSolidData)&&continue + isa(ps_data, InsideSolidData)&&continue vs_num = ps_data.vs_data.vs_num - buffer[1] = max(buffer[1],vs_num) + buffer[1] = max(buffer[1], vs_num) buffer[2] += vs_num end end if MPI.Comm_rank(MPI.COMM_WORLD)==0 - buffer[1] = MPI.Reduce(buffer[1], - MPI.MAX, - MPI.COMM_WORLD - ) - buffer[2] = MPI.Reduce(buffer[1], - +, - MPI.COMM_WORLD - ) + buffer[1] = MPI.Reduce(buffer[1], MPI.MAX, MPI.COMM_WORLD) + buffer[2] = MPI.Reduce(buffer[1], +, MPI.COMM_WORLD) else - MPI.Reduce(buffer[1], - MPI.MAX, - MPI.COMM_WORLD - ) - MPI.Reduce(buffer[2], - +, - MPI.COMM_WORLD - ) + MPI.Reduce(buffer[1], MPI.MAX, MPI.COMM_WORLD) + MPI.Reduce(buffer[2], +, MPI.COMM_WORLD) end return buffer -end \ No newline at end of file +end diff --git a/src/IO/IO.jl b/src/IO/IO.jl index c8acc83..a46a371 100644 --- a/src/IO/IO.jl +++ b/src/IO/IO.jl @@ -3,14 +3,15 @@ include("Input.jl") include("Output.jl") include("Restart.jl") -export read_config, save_result, listen_for_save!, check_for_save!, check!, check_for_animsave! +export read_config, + save_result, listen_for_save!, check_for_save!, check!, check_for_animsave! export save_for_restart, restart function string_to_Cstring(s::String) t = codeunits(s) p = Ptr{Cstring}(malloc(sizeof(UInt8)*(length(t)+1))) - ap = Base.unsafe_wrap(Vector{UInt8},Ptr{UInt8}(p),length(t)+1) - ap[1:end-1] .= t + ap = Base.unsafe_wrap(Vector{UInt8}, Ptr{UInt8}(p), length(t)+1) + ap[1:(end-1)] .= t ap[end] = 0 return p end diff --git a/src/IO/Input.jl b/src/IO/Input.jl index 17477f3..bbc1bc8 100644 --- a/src/IO/Input.jl +++ b/src/IO/Input.jl @@ -7,7 +7,7 @@ function read_config(filename::AbstractString) @info "reading config from $filename" println("--------------------------------------------------------------") end - f = open(filename,"r";lock = false) + f = open(filename, "r"; lock = false) config_dict = Dict{Symbol,Any}() for line in eachline(f) if length(line) == 0 || line[1] == '#' @@ -27,4 +27,4 @@ function read_config(filename::AbstractString) end close(f) return config_dict -end \ No newline at end of file +end diff --git a/src/IO/Output.jl b/src/IO/Output.jl index dab626d..be92ea1 100644 --- a/src/IO/Output.jl +++ b/src/IO/Output.jl @@ -1,49 +1,51 @@ -function vtk_data(vs_data::VsData{2,NDF},ka,::Type{T}) where{NDF,T<:Pixel} +function vtk_data(vs_data::VsData{2,NDF}, ka, ::Type{T}) where {NDF,T<:Pixel} kinfo = ka.kinfo - xmin,xmax,ymin,ymax = kinfo.config.quadrature - Nx,Ny = kinfo.config.vs_trees_num + xmin, xmax, ymin, ymax = kinfo.config.quadrature + Nx, Ny = kinfo.config.vs_trees_num AMR_VS_MAXLEVEL = kinfo.config.solver.AMR_VS_MAXLEVEL dx = (xmax - xmin) / Nx/2^AMR_VS_MAXLEVEL dy = (ymax - ymin) / Ny/2^AMR_VS_MAXLEVEL - D = [dx,dy] - vertices = Matrix{Float64}(undef,2,4*length(vs_data.level)) + D = [dx, dy] + vertices = Matrix{Float64}(undef, 2, 4*length(vs_data.level)) midpoint = vs_data.midpoint level = vs_data.level dlevel = -(vs_data.level .- AMR_VS_MAXLEVEL) - cells = Vector{MeshCell}(undef,length(level)) - solutions = vs_data.df;point_solutions = Matrix{Float64}(undef,4*vs_data.vs_num,NDF) + cells = Vector{MeshCell}(undef, length(level)) + solutions = vs_data.df; + point_solutions = Matrix{Float64}(undef, 4*vs_data.vs_num, NDF) for i in eachindex(level) - for j in 1:4 - @. vertices[:,(i-1)*4+j] = midpoint[i,:]+RMT[2][j]*2^dlevel[i]*D/2 - @views @. point_solutions[4*(i-1)+j,:] = vs_data.df[i,:] + for j = 1:4 + @. vertices[:, (i-1)*4+j] = midpoint[i, :]+RMT[2][j]*2^dlevel[i]*D/2 + @views @. point_solutions[4*(i-1)+j, :] = vs_data.df[i, :] end - cells[i] = MeshCell(VTKCellTypes.VTK_PIXEL,(1:4).+4*(i-1)) + cells[i] = MeshCell(VTKCellTypes.VTK_PIXEL, (1:4) .+ 4*(i-1)) end - return vertices,cells,point_solutions,solutions + return vertices, cells, point_solutions, solutions end -function vtk_data(vs_data::VsData{3,NDF},ka,::Type{T}) where{NDF,T<:Voxel} +function vtk_data(vs_data::VsData{3,NDF}, ka, ::Type{T}) where {NDF,T<:Voxel} kinfo = ka.kinfo - xmin,xmax,ymin,ymax,zmin,zmax = kinfo.config.quadrature - Nx,Ny,Nz = kinfo.config.vs_trees_num + xmin, xmax, ymin, ymax, zmin, zmax = kinfo.config.quadrature + Nx, Ny, Nz = kinfo.config.vs_trees_num AMR_VS_MAXLEVEL = kinfo.config.solver.AMR_VS_MAXLEVEL dx = (xmax - xmin) / Nx/2^AMR_VS_MAXLEVEL dy = (ymax - ymin) / Ny/2^AMR_VS_MAXLEVEL dz = (zmax - zmin) / Nz/2^AMR_VS_MAXLEVEL - D = [dx,dy,dz] - vertices = Matrix{Float64}(undef,3,8*length(vs_data.level)) + D = [dx, dy, dz] + vertices = Matrix{Float64}(undef, 3, 8*length(vs_data.level)) midpoint = vs_data.midpoint level = vs_data.level dlevel = -(vs_data.level .- AMR_VS_MAXLEVEL) - cells = Vector{MeshCell}(undef,length(level)) - solutions = vs_data.df;point_solutions = Matrix{Float64}(undef,8*vs_data.vs_num,NDF) + cells = Vector{MeshCell}(undef, length(level)) + solutions = vs_data.df; + point_solutions = Matrix{Float64}(undef, 8*vs_data.vs_num, NDF) for i in eachindex(level) - for j in 1:8 - @. vertices[:,(i-1)*8+j] = midpoint[i,:]+RMT[3][j]*2^dlevel[i]*D/2 - @views @. point_solutions[8*(i-1)+j,:] = vs_data.df[i,:] + for j = 1:8 + @. vertices[:, (i-1)*8+j] = midpoint[i, :]+RMT[3][j]*2^dlevel[i]*D/2 + @views @. point_solutions[8*(i-1)+j, :] = vs_data.df[i, :] end - cells[i] = MeshCell(VTKCellTypes.VTK_VOXEL,(1:8).+8*(i-1)) + cells[i] = MeshCell(VTKCellTypes.VTK_VOXEL, (1:8) .+ 8*(i-1)) end - return vertices,cells,point_solutions,solutions + return vertices, cells, point_solutions, solutions end #= example: @@ -51,100 +53,139 @@ function fieldvalues_fn(vs_data::VsData{3}) return [vs_data.df[:,1],vs_data.level] end =# -function write_vs_VTK(vs_data::AbstractVsData{2,2},ka::KA{2,2},filename::String,fieldnames::Vector{String},fieldvalues_fn) +function write_vs_VTK( + vs_data::AbstractVsData{2,2}, + ka::KA{2,2}, + filename::String, + fieldnames::Vector{String}, + fieldvalues_fn, +) kinfo = ka.kinfo - xmin,xmax,ymin,ymax = kinfo.config.quadrature - Nx,Ny = kinfo.config.vs_trees_num + xmin, xmax, ymin, ymax = kinfo.config.quadrature + Nx, Ny = kinfo.config.vs_trees_num AMR_VS_MAXLEVEL = kinfo.config.solver.AMR_VS_MAXLEVEL dx = (xmax - xmin) / Nx/2^AMR_VS_MAXLEVEL dy = (ymax - ymin) / Ny/2^AMR_VS_MAXLEVEL - D = [dx,dy] - vertices = Matrix{Float64}(undef,2,4*length(vs_data.level)) + D = [dx, dy] + vertices = Matrix{Float64}(undef, 2, 4*length(vs_data.level)) midpoint = vs_data.midpoint level = vs_data.level dlevel = -(vs_data.level .- AMR_VS_MAXLEVEL) - cells = Vector{MeshCell}(undef,length(level)) + cells = Vector{MeshCell}(undef, length(level)) for i in eachindex(level) - for j in 1:4 - @. vertices[:,(i-1)*4+j] = midpoint[i,:]+RMT[2][j]*2^dlevel[i]*D/2 + for j = 1:4 + @. vertices[:, (i-1)*4+j] = midpoint[i, :]+RMT[2][j]*2^dlevel[i]*D/2 end - cells[i] = MeshCell(VTKCellTypes.VTK_PIXEL,(1:4).+4*(i-1)) + cells[i] = MeshCell(VTKCellTypes.VTK_PIXEL, (1:4) .+ 4*(i-1)) end - vtk_grid(filename,vertices,cells;append=false) do vtk + vtk_grid(filename, vertices, cells; append = false) do vtk cell_datas = fieldvalues_fn(vs_data) for i in eachindex(fieldnames) - vtk[fieldnames[i],VTKCellData()] = cell_datas[i] + vtk[fieldnames[i], VTKCellData()] = cell_datas[i] end end end -function write_vs_VTK(df::AbstractMatrix,vs_data::AbstractVsData{2,2},ka::KA{2,2},filename::String,fieldnames::Vector{String},fieldvalues_fn) +function write_vs_VTK( + df::AbstractMatrix, + vs_data::AbstractVsData{2,2}, + ka::KA{2,2}, + filename::String, + fieldnames::Vector{String}, + fieldvalues_fn, +) config = ka.kinfo.config - write_vs_VTK(df,vs_data,config,filename,fieldnames,fieldvalues_fn) + write_vs_VTK(df, vs_data, config, filename, fieldnames, fieldvalues_fn) end -function write_vs_VTK(df::AbstractMatrix,vs_data::AbstractVsData{2,2},config::AbstractConfig{2,2},filename::String,fieldnames::Vector{String},fieldvalues_fn) - xmin,xmax,ymin,ymax = config.quadrature - Nx,Ny = config.vs_trees_num +function write_vs_VTK( + df::AbstractMatrix, + vs_data::AbstractVsData{2,2}, + config::AbstractConfig{2,2}, + filename::String, + fieldnames::Vector{String}, + fieldvalues_fn, +) + xmin, xmax, ymin, ymax = config.quadrature + Nx, Ny = config.vs_trees_num AMR_VS_MAXLEVEL = config.solver.AMR_VS_MAXLEVEL dx = (xmax - xmin) / Nx/2^AMR_VS_MAXLEVEL dy = (ymax - ymin) / Ny/2^AMR_VS_MAXLEVEL - D = [dx,dy] - vertices = Matrix{Float64}(undef,2,4*length(vs_data.level)) + D = [dx, dy] + vertices = Matrix{Float64}(undef, 2, 4*length(vs_data.level)) midpoint = vs_data.midpoint level = vs_data.level dlevel = -(vs_data.level .- AMR_VS_MAXLEVEL) - cells = Vector{MeshCell}(undef,length(level)) + cells = Vector{MeshCell}(undef, length(level)) for i in eachindex(level) - for j in 1:4 - @. vertices[:,(i-1)*4+j] = midpoint[i,:]+RMT[2][j]*2^dlevel[i]*D/2 + for j = 1:4 + @. vertices[:, (i-1)*4+j] = midpoint[i, :]+RMT[2][j]*2^dlevel[i]*D/2 end - cells[i] = MeshCell(VTKCellTypes.VTK_PIXEL,(1:4).+4*(i-1)) + cells[i] = MeshCell(VTKCellTypes.VTK_PIXEL, (1:4) .+ 4*(i-1)) end - vtk_grid(filename,vertices,cells;append=false) do vtk - cell_datas = fieldvalues_fn(vs_data,df) + vtk_grid(filename, vertices, cells; append = false) do vtk + cell_datas = fieldvalues_fn(vs_data, df) for i in eachindex(fieldnames) - vtk[fieldnames[i],VTKCellData()] = cell_datas[i] + vtk[fieldnames[i], VTKCellData()] = cell_datas[i] end end end -function write_vs_VTK(df::AbstractMatrix,vs_data::AbstractVsData{3,1},ka::KA{3,1},filename::String,fieldnames::Vector{String},fieldvalues_fn) +function write_vs_VTK( + df::AbstractMatrix, + vs_data::AbstractVsData{3,1}, + ka::KA{3,1}, + filename::String, + fieldnames::Vector{String}, + fieldvalues_fn, +) config = ka.kinfo.config - write_vs_VTK(df,vs_data,config,filename,fieldnames,fieldvalues_fn) + write_vs_VTK(df, vs_data, config, filename, fieldnames, fieldvalues_fn) end -function write_vs_VTK(df::AbstractMatrix,vs_data::AbstractVsData{3,1},config::AbstractConfig{3,1},filename::String,fieldnames::Vector{String},fieldvalues_fn) - xmin,xmax,ymin,ymax,zmin,zmax = config.quadrature - Nx,Ny,Nz = config.vs_trees_num +function write_vs_VTK( + df::AbstractMatrix, + vs_data::AbstractVsData{3,1}, + config::AbstractConfig{3,1}, + filename::String, + fieldnames::Vector{String}, + fieldvalues_fn, +) + xmin, xmax, ymin, ymax, zmin, zmax = config.quadrature + Nx, Ny, Nz = config.vs_trees_num AMR_VS_MAXLEVEL = config.solver.AMR_VS_MAXLEVEL dx = (xmax - xmin) / Nx/2^AMR_VS_MAXLEVEL dy = (ymax - ymin) / Ny/2^AMR_VS_MAXLEVEL dz = (zmax - zmin) / Nz/2^AMR_VS_MAXLEVEL - D = [dx,dy,dz] - vertices = Matrix{Float64}(undef,3,8*length(vs_data.level)) + D = [dx, dy, dz] + vertices = Matrix{Float64}(undef, 3, 8*length(vs_data.level)) midpoint = vs_data.midpoint level = vs_data.level dlevel = -(vs_data.level .- AMR_VS_MAXLEVEL) - cells = Vector{MeshCell}(undef,length(level)) + cells = Vector{MeshCell}(undef, length(level)) for i in eachindex(level) - for j in 1:8 - @. vertices[:,(i-1)*8+j] = midpoint[i,:]+RMT[3][j]*2^dlevel[i]*D/2 + for j = 1:8 + @. vertices[:, (i-1)*8+j] = midpoint[i, :]+RMT[3][j]*2^dlevel[i]*D/2 end - cells[i] = MeshCell(VTKCellTypes.VTK_VOXEL,(1:8).+8*(i-1)) + cells[i] = MeshCell(VTKCellTypes.VTK_VOXEL, (1:8) .+ 8*(i-1)) end - vtk_grid(filename,vertices,cells;append=false) do vtk - cell_datas = fieldvalues_fn(vs_data,df) + vtk_grid(filename, vertices, cells; append = false) do vtk + cell_datas = fieldvalues_fn(vs_data, df) for i in eachindex(fieldnames) - vtk[fieldnames[i],VTKCellData()] = cell_datas[i] + vtk[fieldnames[i], VTKCellData()] = cell_datas[i] end end end -function neighbor_num(ps_data::PsData,::P_pxest_t,::KA,::Integer) +function neighbor_num(ps_data::PsData, ::P_pxest_t, ::KA, ::Integer) return abs.(ps_data.neighbor.state) end -function neighbor_num(::InsideSolidData,p4est::P_pxest_t,ka::KA{DIM},quadid::Integer) where {DIM} - neighbor_num = Vector{Int}(undef,2*DIM) +function neighbor_num( + ::InsideSolidData, + p4est::P_pxest_t, + ka::KA{DIM}, + quadid::Integer, +) where {DIM} + neighbor_num = Vector{Int}(undef, 2*DIM) kinfo = ka.kinfo ghost = kinfo.forest.ghost mesh = kinfo.forest.mesh - for dir = 1:2*DIM + for dir = 1:(2*DIM) neighbor_quads = sc_array_new(sizeof(P_pxest_quadrant_t)) neighbor_encs = sc_array_new(sizeof(Cint)) neighbor_qid = sc_array_new(sizeof(Cint)) @@ -165,28 +206,39 @@ function neighbor_num(::InsideSolidData,p4est::P_pxest_t,ka::KA{DIM},quadid::Int end return neighbor_num end -function save_vs_result(ka::KA{DIM,NDF};dir_path) where{DIM,NDF} +function save_vs_result(ka::KA{DIM,NDF}; dir_path) where {DIM,NDF} vs_solutions = VS_Solution[] vs_path = dir_path*"vs_result_"*string(MPI.Comm_rank(MPI.COMM_WORLD))*".jld2" op = ka.kinfo.config.output for tree in ka.kdata.field.trees.data for ps_data in tree - (isa(ps_data,InsideSolidData)||ps_data.bound_enc<0)&&continue + (isa(ps_data, InsideSolidData)||ps_data.bound_enc<0)&&continue vs_data = ps_data.vs_data - flag = op.vs_output_criterion==null_udf ? true : op.vs_output_criterion(ps_data,ka) + flag = + op.vs_output_criterion==null_udf ? true : + op.vs_output_criterion(ps_data, ka) if flag - push!(vs_solutions,VS_Solution(ps_data.quadid,ps_data.midpoint,vs_data.midpoint,vs_data.level,vs_data.df)) + push!( + vs_solutions, + VS_Solution( + ps_data.quadid, + ps_data.midpoint, + vs_data.midpoint, + vs_data.level, + vs_data.df, + ), + ) end end end - save_object(vs_path,vs_solutions) + save_object(vs_path, vs_solutions) end function load_vs_result(path) solverset = load_object(path*"/solverset.jld2") vs_result = VS_Solution[] for i = 1:solverset.mpi_size vr = load_object(path*"/vs_result_"*string(i-1)*".jld2") - append!(vs_result,vr) + append!(vs_result, vr) end return vs_result end @@ -195,14 +247,14 @@ end $(TYPEDSIGNATURES) Save all results to `dir_path`. If `isempty(dir_path)` is `true`, a folder named `result` will be made in current path. """ -function save_result(p4est::Ptr{p4est_t},ka::KA{DIM,NDF};dir_path="") where{DIM,NDF} +function save_result(p4est::Ptr{p4est_t}, ka::KA{DIM,NDF}; dir_path = "") where {DIM,NDF} update_slope!(ka) - slope_exchange!(p4est,ka) + slope_exchange!(p4est, ka) update_solid_cell!(ka) - data_exchange!(p4est,ka) + data_exchange!(p4est, ka) fp = PointerWrapper(p4est) - ps_solution = Vector{PS_Solution}(undef,fp.local_num_quadrants[]) - neighbor_nums = Vector{Vector{Int}}(undef,fp.local_num_quadrants[]) + ps_solution = Vector{PS_Solution}(undef, fp.local_num_quadrants[]) + neighbor_nums = Vector{Vector{Int}}(undef, fp.local_num_quadrants[]) trees = ka.kdata.field.trees.data config = ka.kinfo.config index = 1 @@ -210,25 +262,25 @@ function save_result(p4est::Ptr{p4est_t},ka::KA{DIM,NDF};dir_path="") where{DIM, for j in eachindex(trees[i]) ps_data = trees[i][j] ps_solution[index] = PS_Solution(ps_data) - neighbor_nums[index] = neighbor_num(ps_data,p4est,ka,index-1) + neighbor_nums[index] = neighbor_num(ps_data, p4est, ka, index-1) index+=1 end end solution = Solution(ps_solution) rank = MPI.Comm_rank(MPI.COMM_WORLD) - result = Result(solution,MeshInfo(neighbor_nums)) + result = Result(solution, MeshInfo(neighbor_nums)) if isempty(dir_path) if MPI.Comm_rank(MPI.COMM_WORLD)==0 dir_path = "./result"*Dates.format(now(), "yyyy-mm-dd_HH-MM")*"/" path_v = collect(dir_path) pl = length(path_v) - MPI.Bcast!([pl],0,MPI.COMM_WORLD) - MPI.Bcast!(path_v,0,MPI.COMM_WORLD) + MPI.Bcast!([pl], 0, MPI.COMM_WORLD) + MPI.Bcast!(path_v, 0, MPI.COMM_WORLD) else pl = [0] - MPI.Bcast!(pl,0,MPI.COMM_WORLD) - path_v = Vector{Char}(undef,first(pl)) - MPI.Bcast!(path_v,0,MPI.COMM_WORLD) + MPI.Bcast!(pl, 0, MPI.COMM_WORLD) + path_v = Vector{Char}(undef, first(pl)) + MPI.Bcast!(path_v, 0, MPI.COMM_WORLD) dir_path = String(path_v) end else @@ -241,26 +293,26 @@ function save_result(p4est::Ptr{p4est_t},ka::KA{DIM,NDF};dir_path="") where{DIM, MPI.Barrier(MPI.COMM_WORLD) pro_path = pwd() cd(dir_path) - p4est_save_ext("p",p4est,Cint(0),Cint(0)) + p4est_save_ext("p", p4est, Cint(0), Cint(0)) cd(pro_path) if rank==0 size = MPI.Comm_size(MPI.COMM_WORLD) - solverset = SolverSet(ConfigureForSave(config),size) + solverset = SolverSet(ConfigureForSave(config), size) save_object(dir_path * "solverset.jld2", solverset) end - save_object(dir_path * "result_"*string(rank)*".jld2", result) - save_pvtu(dir_path*"vtk/field",p4est,ka,ka.kinfo.config.output.vtk_celltype) - save_vs_result(ka;dir_path) - save_boundary_result(dir_path,ka) + save_object(dir_path * "result_" * string(rank) * ".jld2", result) + save_pvtu(dir_path*"vtk/field", p4est, ka, ka.kinfo.config.output.vtk_celltype) + save_vs_result(ka; dir_path) + save_boundary_result(dir_path, ka) end -function save_result(p4est::Ptr{p8est_t},ka::KA{DIM,NDF};dir_path="") where{DIM,NDF} +function save_result(p4est::Ptr{p8est_t}, ka::KA{DIM,NDF}; dir_path = "") where {DIM,NDF} update_slope!(ka) - slope_exchange!(p4est,ka) + slope_exchange!(p4est, ka) update_solid_cell!(ka) - data_exchange!(p4est,ka) + data_exchange!(p4est, ka) fp = PointerWrapper(p4est) - ps_solution = Vector{PS_Solution}(undef,fp.local_num_quadrants[]) - neighbor_nums = Vector{Vector{Int}}(undef,fp.local_num_quadrants[]) + ps_solution = Vector{PS_Solution}(undef, fp.local_num_quadrants[]) + neighbor_nums = Vector{Vector{Int}}(undef, fp.local_num_quadrants[]) trees = ka.kdata.field.trees.data config = ka.kinfo.config index = 1 @@ -273,19 +325,19 @@ function save_result(p4est::Ptr{p8est_t},ka::KA{DIM,NDF};dir_path="") where{DIM, end solution = Solution(ps_solution) rank = MPI.Comm_rank(MPI.COMM_WORLD) - result = Result(solution,MeshInfo(Vector{Int}[])) + result = Result(solution, MeshInfo(Vector{Int}[])) if isempty(dir_path) if MPI.Comm_rank(MPI.COMM_WORLD)==0 dir_path = "./result"*Dates.format(now(), "yyyy-mm-dd_HH-MM")*"/" path_v = collect(dir_path) pl = length(path_v) - MPI.Bcast!([pl],0,MPI.COMM_WORLD) - MPI.Bcast!(path_v,0,MPI.COMM_WORLD) + MPI.Bcast!([pl], 0, MPI.COMM_WORLD) + MPI.Bcast!(path_v, 0, MPI.COMM_WORLD) else pl = [0] - MPI.Bcast!(pl,0,MPI.COMM_WORLD) - path_v = Vector{Char}(undef,first(pl)) - MPI.Bcast!(path_v,0,MPI.COMM_WORLD) + MPI.Bcast!(pl, 0, MPI.COMM_WORLD) + path_v = Vector{Char}(undef, first(pl)) + MPI.Bcast!(path_v, 0, MPI.COMM_WORLD) dir_path = String(path_v) end else @@ -298,17 +350,17 @@ function save_result(p4est::Ptr{p8est_t},ka::KA{DIM,NDF};dir_path="") where{DIM, MPI.Barrier(MPI.COMM_WORLD) pro_path = pwd() cd(dir_path) - p4est_save_ext("p",p4est,Cint(0),Cint(0)) + p4est_save_ext("p", p4est, Cint(0), Cint(0)) cd(pro_path) if rank==0 size = MPI.Comm_size(MPI.COMM_WORLD) - solverset = SolverSet(ConfigureForSave(config),size) + solverset = SolverSet(ConfigureForSave(config), size) save_object(dir_path * "solverset.jld2", solverset) end - save_pvtu(dir_path*"vtk/field",p4est,ka,ka.kinfo.config.output.vtk_celltype) - save_vs_result(ka;dir_path) - save_object(dir_path * "result_"*string(rank)*".jld2", result) - save_boundary_result(dir_path,ka) + save_pvtu(dir_path*"vtk/field", p4est, ka, ka.kinfo.config.output.vtk_celltype) + save_vs_result(ka; dir_path) + save_object(dir_path * "result_" * string(rank) * ".jld2", result) + save_boundary_result(dir_path, ka) end """ $(SIGNATURES) @@ -322,358 +374,453 @@ A single cell type yields one pair with an empty suffix (backward compatible); a of cell types yields one pair per type, each with a `_` suffix so the per-type files are written side by side without overwriting each other. """ -celltype_outputs(celltype) = celltype isa AbstractVector ? - [(ct, celltype_suffix(ct)) for ct in celltype] : [(celltype, "")] +celltype_outputs(celltype) = + celltype isa AbstractVector ? [(ct, celltype_suffix(ct)) for ct in celltype] : + [(celltype, "")] -function save_pvtu(dir_path::String,p4est::P_pxest_t,ka,celltypes::AbstractVector) +function save_pvtu(dir_path::String, p4est::P_pxest_t, ka, celltypes::AbstractVector) for ct in celltypes - save_pvtu(dir_path*celltype_suffix(ct),p4est,ka,ct) + save_pvtu(dir_path*celltype_suffix(ct), p4est, ka, ct) end return nothing end -function save_pvtu(dir_path::String,p4est::Ptr{p4est_t},ka,celltype::Type) +function save_pvtu(dir_path::String, p4est::Ptr{p4est_t}, ka, celltype::Type) pp = PointerWrapper(p4est) gfq = Base.unsafe_wrap( Vector{Int}, pointer(pp.global_first_quadrant), MPI.Comm_size(MPI.COMM_WORLD) + 1, ) - nums = [gfq[i]-gfq[i-1] for i in 2:MPI.Comm_size(MPI.COMM_WORLD)+1] - nparts = length(findall(x->x>0,nums));part = length(findall(x->x>0,nums[1:MPI.Comm_rank(MPI.COMM_WORLD)+1])) - vertices,cells,point_solutions,solutions = pvtu_data(p4est,ka,celltype) - ranks = ones(Int,size(solutions,1))*MPI.Comm_rank(MPI.COMM_WORLD) + nums = [gfq[i]-gfq[i-1] for i = 2:(MPI.Comm_size(MPI.COMM_WORLD)+1)] + nparts = length(findall(x->x>0, nums)); + part = length(findall(x->x>0, nums[1:(MPI.Comm_rank(MPI.COMM_WORLD)+1)])) + vertices, cells, point_solutions, solutions = pvtu_data(p4est, ka, celltype) + ranks = ones(Int, size(solutions, 1))*MPI.Comm_rank(MPI.COMM_WORLD) if length(ranks)>0 - pvtk_grid(dir_path,vertices,cells;part = part,nparts = nparts) do pvtk - pvtk["rho"] = @views solutions[:,1] - pvtk["velocity"] = @views (solutions[:,2],solutions[:,3]) - pvtk["T"] = @views solutions[:,4] - pvtk["qf"] = (solutions[:,5],solutions[:,6]) + pvtk_grid(dir_path, vertices, cells; part = part, nparts = nparts) do pvtk + pvtk["rho"] = @views solutions[:, 1] + pvtk["velocity"] = @views (solutions[:, 2], solutions[:, 3]) + pvtk["T"] = @views solutions[:, 4] + pvtk["qf"] = (solutions[:, 5], solutions[:, 6]) pvtk["mpi_rank"] = ranks - pvtk["rho",VTKPointData()] = @views point_solutions[:,1] - pvtk["velocity",VTKPointData()] = @views (point_solutions[:,2],point_solutions[:,3]) - pvtk["T",VTKPointData()] = @views point_solutions[:,4] - pvtk["qf",VTKPointData()] = (point_solutions[:,5],point_solutions[:,6]) + pvtk["rho", VTKPointData()] = @views point_solutions[:, 1] + pvtk["velocity", VTKPointData()] = + @views (point_solutions[:, 2], point_solutions[:, 3]) + pvtk["T", VTKPointData()] = @views point_solutions[:, 4] + pvtk["qf", VTKPointData()] = (point_solutions[:, 5], point_solutions[:, 6]) end end end -function save_pvtu(dir_path::String,p4est::Ptr{p8est_t},ka,celltype::Type) +function save_pvtu(dir_path::String, p4est::Ptr{p8est_t}, ka, celltype::Type) pp = PointerWrapper(p4est) gfq = Base.unsafe_wrap( Vector{Int}, pointer(pp.global_first_quadrant), MPI.Comm_size(MPI.COMM_WORLD) + 1, ) - nums = [gfq[i]-gfq[i-1] for i in 2:MPI.Comm_size(MPI.COMM_WORLD)+1] - nparts = length(findall(x->x>0,nums));part = length(findall(x->x>0,nums[1:MPI.Comm_rank(MPI.COMM_WORLD)+1])) - vertices,cells,point_solutions,solutions = pvtu_data(p4est,ka,celltype) - ranks = ones(Int,size(solutions,1))*MPI.Comm_rank(MPI.COMM_WORLD) - if size(solutions,1)>0 - pvtk_grid(dir_path,vertices,cells;part = part,nparts = nparts) do pvtk - pvtk["rho"] = @views solutions[:,1] - pvtk["velocity"] = @views (solutions[:,2],solutions[:,3],solutions[:,4]) - pvtk["T"] = @views solutions[:,5] - pvtk["qf"] = (solutions[:,6],solutions[:,7],solutions[:,8]) + nums = [gfq[i]-gfq[i-1] for i = 2:(MPI.Comm_size(MPI.COMM_WORLD)+1)] + nparts = length(findall(x->x>0, nums)); + part = length(findall(x->x>0, nums[1:(MPI.Comm_rank(MPI.COMM_WORLD)+1)])) + vertices, cells, point_solutions, solutions = pvtu_data(p4est, ka, celltype) + ranks = ones(Int, size(solutions, 1))*MPI.Comm_rank(MPI.COMM_WORLD) + if size(solutions, 1)>0 + pvtk_grid(dir_path, vertices, cells; part = part, nparts = nparts) do pvtk + pvtk["rho"] = @views solutions[:, 1] + pvtk["velocity"] = @views (solutions[:, 2], solutions[:, 3], solutions[:, 4]) + pvtk["T"] = @views solutions[:, 5] + pvtk["qf"] = (solutions[:, 6], solutions[:, 7], solutions[:, 8]) pvtk["mpi_rank"] = ranks - pvtk["rho",VTKPointData()] = @views point_solutions[:,1] - pvtk["velocity",VTKPointData()] = @views (point_solutions[:,2],point_solutions[:,3],point_solutions[:,4]) - pvtk["T",VTKPointData()] = @views point_solutions[:,5] - pvtk["qf",VTKPointData()] = (point_solutions[:,6],point_solutions[:,7],point_solutions[:,8]) + pvtk["rho", VTKPointData()] = @views point_solutions[:, 1] + pvtk["velocity", VTKPointData()] = + @views (point_solutions[:, 2], point_solutions[:, 3], point_solutions[:, 4]) + pvtk["T", VTKPointData()] = @views point_solutions[:, 5] + pvtk["qf", VTKPointData()] = + (point_solutions[:, 6], point_solutions[:, 7], point_solutions[:, 8]) end end end -function pvtu_data(p4est,ka,::Type{T}) where{T<:Triangle} +function pvtu_data(p4est, ka, ::Type{T}) where {T<:Triangle} N = PointerWrapper(p4est).local_num_quadrants[] - tb = Vector{SVector{2,Float64}}(undef,4) - tb[1] = @SVector [-1.,-1.];tb[2] = @SVector [1.,-1.];tb[3] = @SVector [1.,1.];tb[4] = @SVector [-1.,1.] - ptb = Vector{SVector{3,Int}}(undef,4)# pixel-triangle vertices table - ptb[1] = @SVector [1,2,5];ptb[2] = @SVector [2,3,5];ptb[3] = @SVector [3,4,5];ptb[4] = @SVector [1,4,5] - vertices = Matrix{Float64}(undef,2,5*N) - cells = Vector{MeshCell}(undef,4*N) - levels = Vector{Int8}(undef,N) + tb = Vector{SVector{2,Float64}}(undef, 4) + tb[1] = @SVector [-1.0, -1.0]; + tb[2] = @SVector [1.0, -1.0]; + tb[3] = @SVector [1.0, 1.0]; + tb[4] = @SVector [-1.0, 1.0] + ptb = Vector{SVector{3,Int}}(undef, 4)# pixel-triangle vertices table + ptb[1] = @SVector [1, 2, 5]; + ptb[2] = @SVector [2, 3, 5]; + ptb[3] = @SVector [3, 4, 5]; + ptb[4] = @SVector [1, 4, 5] + vertices = Matrix{Float64}(undef, 2, 5*N) + cells = Vector{MeshCell}(undef, 4*N) + levels = Vector{Int8}(undef, N) index = 1 - data = [index,vertices,cells,levels] + data = [index, vertices, cells, levels] p_data = pointer_from_objref(data) - GC.@preserve data AMR_volume_iterate(p4est;user_data = p_data) do ip,data,dp - d = unsafe_pointer_to_objref(data);index,vertices,cells = d + GC.@preserve data AMR_volume_iterate(p4est; user_data = p_data) do ip, data, dp + d = unsafe_pointer_to_objref(data); + index, vertices, cells = d ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - if isa(ps_data,InsideSolidData) - ds, midpoint = quad_to_cell(ip.p4est,ip.treeid[],ip.quad) + if isa(ps_data, InsideSolidData) + ds, midpoint = quad_to_cell(ip.p4est, ip.treeid[], ip.quad) else ds = ps_data.ds midpoint = ps_data.midpoint end - for i in 1:4 - @. vertices[:,(index-1)*5+i] = midpoint+tb[i]/2*ds + for i = 1:4 + @. vertices[:, (index-1)*5+i] = midpoint+tb[i]/2*ds end - vertices[:,5*index] .= midpoint + vertices[:, 5*index] .= midpoint for i in eachindex(ptb) - cells[4*(index-1)+i] = MeshCell(VTKCellTypes.VTK_TRIANGLE,ptb[i].+5*(index-1)) + cells[4*(index-1)+i] = + MeshCell(VTKCellTypes.VTK_TRIANGLE, ptb[i] .+ 5*(index-1)) end levels[index] = ip.quad.level[] d[1]+=1 end - solutions = Matrix{Float64}(undef,4*N,6) - point_solutions = Matrix{Float64}(undef,5*N,6) + solutions = Matrix{Float64}(undef, 4*N, 6) + point_solutions = Matrix{Float64}(undef, 5*N, 6) # bound_encs = Vector{Float64}(undef,N) index = 1 for tree in ka.kdata.field.trees.data for ps_data in tree - if isa(ps_data,InsideSolidData)||ps_data.bound_enc<0 - solutions[4*(index-1)+1:4*index,:].=NaN - point_solutions[5*(index-1)+1:5*index,:] .= NaN + if isa(ps_data, InsideSolidData)||ps_data.bound_enc<0 + solutions[(4*(index-1)+1):(4*index), :].=NaN + point_solutions[(5*(index-1)+1):(5*index), :] .= NaN else - for i in 1:4 - solutions[4*(index-1)+i,1] = ps_data.prim[1] - @views solutions[4*(index-1)+i,2:3] .= ps_data.prim[2:3] - solutions[4*(index-1)+i,4] = 1.0/ps_data.prim[end] - @views solutions[4*(index-1)+i,5:6] .= ps_data.qf + for i = 1:4 + solutions[4*(index-1)+i, 1] = ps_data.prim[1] + @views solutions[4*(index-1)+i, 2:3] .= ps_data.prim[2:3] + solutions[4*(index-1)+i, 4] = 1.0/ps_data.prim[end] + @views solutions[4*(index-1)+i, 5:6] .= ps_data.qf end - + vs_data = ps_data.vs_data - β = @views [min(abs(vs_data.df[i,j]/(0.5*dot(ps_data.ds,abs.(vs_data.sdf[i,j,:]))+EPS)),1.) for i in axes(vs_data.df,1), j in axes(vs_data.df,2)] + β = @views [ + min( + abs( + vs_data.df[i, j]/( + 0.5*dot(ps_data.ds, abs.(vs_data.sdf[i, j, :]))+EPS + ), + ), + 1.0, + ) for i in axes(vs_data.df, 1), j in axes(vs_data.df, 2) + ] point_df = similar(vs_data.df) - for i in 1:4 + for i = 1:4 df = vs_data.df sdf = vs_data.sdf - dx = 0.5*ps_data.ds.*tb[i] - point_df .= @views df+[β[i,j]*dot(sdf[i,j,:],dx) for i in axes(df,1), j in axes(df,2)] - w = calc_w0(vs_data.midpoint,point_df,vs_data.weight,ka.kinfo) - prim = get_prim(w,ka.kinfo) - qf = calc_qf(vs_data.midpoint,point_df,vs_data.weight,prim,ka.kinfo) - point_solutions[5*(index-1)+i,1] = prim[1] - @views point_solutions[5*(index-1)+i,2:3] .= prim[2:3] - point_solutions[5*(index-1)+i,4] = 1.0/prim[end] - @views point_solutions[5*(index-1)+i,5:6] .= qf + dx = 0.5*ps_data.ds .* tb[i] + point_df .= @views df+[ + β[i, j]*dot(sdf[i, j, :], dx) for i in axes(df, 1), j in axes(df, 2) + ] + w = calc_w0(vs_data.midpoint, point_df, vs_data.weight, ka.kinfo) + prim = get_prim(w, ka.kinfo) + qf = calc_qf(vs_data.midpoint, point_df, vs_data.weight, prim, ka.kinfo) + point_solutions[5*(index-1)+i, 1] = prim[1] + @views point_solutions[5*(index-1)+i, 2:3] .= prim[2:3] + point_solutions[5*(index-1)+i, 4] = 1.0/prim[end] + @views point_solutions[5*(index-1)+i, 5:6] .= qf end - point_solutions[5*index,1] = ps_data.prim[1] - @views point_solutions[5*index,2:3] .= ps_data.prim[2:3] - point_solutions[5*index,4] = 1.0/ps_data.prim[end] - @views point_solutions[5*index,5:6] .= ps_data.qf + point_solutions[5*index, 1] = ps_data.prim[1] + @views point_solutions[5*index, 2:3] .= ps_data.prim[2:3] + point_solutions[5*index, 4] = 1.0/ps_data.prim[end] + @views point_solutions[5*index, 5:6] .= ps_data.qf end index += 1 end end - return vertices,cells,point_solutions,solutions + return vertices, cells, point_solutions, solutions end -function pvtu_data(p4est,ka,::Type{T}) where{T<:Pixel} +function pvtu_data(p4est, ka, ::Type{T}) where {T<:Pixel} N = PointerWrapper(p4est).local_num_quadrants[] - tb = Vector{SVector{2,Float64}}(undef,4) - tb[1] = @SVector [-1.,-1.];tb[2] = @SVector [1.,-1.];tb[3] = @SVector [-1.,1.];tb[4] = @SVector [1.,1.] - vertices = Matrix{Float64}(undef,2,4*N) - cells = Vector{MeshCell}(undef,N) - levels = Vector{Int8}(undef,N) + tb = Vector{SVector{2,Float64}}(undef, 4) + tb[1] = @SVector [-1.0, -1.0]; + tb[2] = @SVector [1.0, -1.0]; + tb[3] = @SVector [-1.0, 1.0]; + tb[4] = @SVector [1.0, 1.0] + vertices = Matrix{Float64}(undef, 2, 4*N) + cells = Vector{MeshCell}(undef, N) + levels = Vector{Int8}(undef, N) index = 1 - data = [index,vertices,cells,levels] + data = [index, vertices, cells, levels] p_data = pointer_from_objref(data) - GC.@preserve data AMR_volume_iterate(p4est;user_data = p_data) do ip,data,dp - d = unsafe_pointer_to_objref(data);index,vertices,cells = d + GC.@preserve data AMR_volume_iterate(p4est; user_data = p_data) do ip, data, dp + d = unsafe_pointer_to_objref(data); + index, vertices, cells = d ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - if isa(ps_data,InsideSolidData) - ds, midpoint = quad_to_cell(ip.p4est,ip.treeid[],ip.quad) + if isa(ps_data, InsideSolidData) + ds, midpoint = quad_to_cell(ip.p4est, ip.treeid[], ip.quad) else ds = ps_data.ds midpoint = ps_data.midpoint end - for i in 1:4 - @. vertices[:,(index-1)*4+i] = midpoint+tb[i]/2*ds + for i = 1:4 + @. vertices[:, (index-1)*4+i] = midpoint+tb[i]/2*ds end - cells[index] = MeshCell(VTKCellTypes.VTK_PIXEL,(1:4).+4*(index-1)) + cells[index] = MeshCell(VTKCellTypes.VTK_PIXEL, (1:4) .+ 4*(index-1)) levels[index] = ip.quad.level[] d[1]+=1 end - solutions = Matrix{Float64}(undef,N,6) - point_solutions = Matrix{Float64}(undef,4*N,6) + solutions = Matrix{Float64}(undef, N, 6) + point_solutions = Matrix{Float64}(undef, 4*N, 6) index = 1 for tree in ka.kdata.field.trees.data for ps_data in tree - if isa(ps_data,InsideSolidData)||ps_data.bound_enc<0 - solutions[index,:].=NaN - point_solutions[4*(index-1)+1:4*index,:] .= NaN + if isa(ps_data, InsideSolidData)||ps_data.bound_enc<0 + solutions[index, :].=NaN + point_solutions[(4*(index-1)+1):(4*index), :] .= NaN else - solutions[index,1] = ps_data.prim[1] - @views solutions[index,2:3] .= ps_data.prim[2:3] - solutions[index,4] = 1.0/ps_data.prim[end] - @views solutions[index,5:6] .= ps_data.qf - for i in 1:4 - point_solutions[4*(index-1)+i,1] = ps_data.prim[1] - @views point_solutions[4*(index-1)+i,2:3] .= ps_data.prim[2:3] - point_solutions[4*(index-1)+i,4] = 1.0/ps_data.prim[end] - @views point_solutions[4*(index-1)+i,5:6] .= ps_data.qf + solutions[index, 1] = ps_data.prim[1] + @views solutions[index, 2:3] .= ps_data.prim[2:3] + solutions[index, 4] = 1.0/ps_data.prim[end] + @views solutions[index, 5:6] .= ps_data.qf + for i = 1:4 + point_solutions[4*(index-1)+i, 1] = ps_data.prim[1] + @views point_solutions[4*(index-1)+i, 2:3] .= ps_data.prim[2:3] + point_solutions[4*(index-1)+i, 4] = 1.0/ps_data.prim[end] + @views point_solutions[4*(index-1)+i, 5:6] .= ps_data.qf end end index += 1 end end - return vertices,cells,point_solutions,solutions + return vertices, cells, point_solutions, solutions end -function pvtu_data(p4est,ka,::Type{T}) where{T<:Tetra} +function pvtu_data(p4est, ka, ::Type{T}) where {T<:Tetra} N = PointerWrapper(p4est).local_num_quadrants[] - tb = Vector{SVector{3,Float64}}(undef,14) - tb[1] = @SVector [-1.,-1.,-1.];tb[2] = @SVector [1.,-1.,-1.];tb[3] = @SVector [1.,1.,-1.];tb[4] = @SVector [-1.,1.,-1.] - tb[5] = @SVector [-1.,-1.,1.];tb[6] = @SVector [1.,-1.,1.];tb[7] = @SVector [1.,1.,1.];tb[8] = @SVector [-1.,1.,1.] - tb[9] = @SVector [-1.,0.,0.];tb[10] = @SVector [1.,0.,0.]; tb[11] = @SVector [0.,-1.,0.];tb[12] = @SVector [0.,1.,0.] - tb[13] = @SVector [0.,0.,-1.];tb[14] = @SVector [0.,0.,1.] - ptb = Vector{SVector{4,Int}}(undef,24)# voxel-tetra vertices table - ptb[1] = @SVector [1,2,13,15];ptb[2] = @SVector [2,3,13,15];ptb[3] = @SVector [3,4,13,15];ptb[4] = @SVector [4,1,13,15] - ptb[5] = @SVector [5,6,14,15];ptb[6] = @SVector [6,7,14,15];ptb[7] = @SVector [7,8,14,15];ptb[8] = @SVector [8,5,14,15]; - ptb[9] = @SVector [1,4,9,15];ptb[10] = @SVector [4,8,9,15];ptb[11] = @SVector [8,5,9,15];ptb[12] = @SVector [5,1,9,15]; - ptb[13] = @SVector [2,6,10,15];ptb[14] = @SVector [6,7,10,15];ptb[15] = @SVector [7,3,10,15];ptb[16] = @SVector [3,2,10,15]; - ptb[17] = @SVector [1,2,11,15];ptb[18] = @SVector [2,6,11,15];ptb[19] = @SVector [6,5,11,15];ptb[20] = @SVector [5,1,11,15]; - ptb[21] = @SVector [3,4,12,15];ptb[22] = @SVector [4,8,12,15];ptb[23] = @SVector [8,7,12,15];ptb[24] = @SVector [7,3,12,15]; + tb = Vector{SVector{3,Float64}}(undef, 14) + tb[1] = @SVector [-1.0, -1.0, -1.0]; + tb[2] = @SVector [1.0, -1.0, -1.0]; + tb[3] = @SVector [1.0, 1.0, -1.0]; + tb[4] = @SVector [-1.0, 1.0, -1.0] + tb[5] = @SVector [-1.0, -1.0, 1.0]; + tb[6] = @SVector [1.0, -1.0, 1.0]; + tb[7] = @SVector [1.0, 1.0, 1.0]; + tb[8] = @SVector [-1.0, 1.0, 1.0] + tb[9] = @SVector [-1.0, 0.0, 0.0]; + tb[10] = @SVector [1.0, 0.0, 0.0]; + tb[11] = @SVector [0.0, -1.0, 0.0]; + tb[12] = @SVector [0.0, 1.0, 0.0] + tb[13] = @SVector [0.0, 0.0, -1.0]; + tb[14] = @SVector [0.0, 0.0, 1.0] + ptb = Vector{SVector{4,Int}}(undef, 24)# voxel-tetra vertices table + ptb[1] = @SVector [1, 2, 13, 15]; + ptb[2] = @SVector [2, 3, 13, 15]; + ptb[3] = @SVector [3, 4, 13, 15]; + ptb[4] = @SVector [4, 1, 13, 15] + ptb[5] = @SVector [5, 6, 14, 15]; + ptb[6] = @SVector [6, 7, 14, 15]; + ptb[7] = @SVector [7, 8, 14, 15]; + ptb[8] = @SVector [8, 5, 14, 15]; + ptb[9] = @SVector [1, 4, 9, 15]; + ptb[10] = @SVector [4, 8, 9, 15]; + ptb[11] = @SVector [8, 5, 9, 15]; + ptb[12] = @SVector [5, 1, 9, 15]; + ptb[13] = @SVector [2, 6, 10, 15]; + ptb[14] = @SVector [6, 7, 10, 15]; + ptb[15] = @SVector [7, 3, 10, 15]; + ptb[16] = @SVector [3, 2, 10, 15]; + ptb[17] = @SVector [1, 2, 11, 15]; + ptb[18] = @SVector [2, 6, 11, 15]; + ptb[19] = @SVector [6, 5, 11, 15]; + ptb[20] = @SVector [5, 1, 11, 15]; + ptb[21] = @SVector [3, 4, 12, 15]; + ptb[22] = @SVector [4, 8, 12, 15]; + ptb[23] = @SVector [8, 7, 12, 15]; + ptb[24] = @SVector [7, 3, 12, 15]; nv = length(tb)+1 # The 15th one represents the midpoint of the voxel. nc = length(ptb) - vertices = Matrix{Float64}(undef,3,nv*N) - cells = Vector{MeshCell}(undef,nc*N) - levels = Vector{Int8}(undef,N) + vertices = Matrix{Float64}(undef, 3, nv*N) + cells = Vector{MeshCell}(undef, nc*N) + levels = Vector{Int8}(undef, N) index = 1 - data = [index,vertices,cells,levels] + data = [index, vertices, cells, levels] p_data = pointer_from_objref(data) - GC.@preserve data AMR_volume_iterate(p4est;user_data = p_data) do ip,data,dp - d = unsafe_pointer_to_objref(data);index,vertices,cells = d + GC.@preserve data AMR_volume_iterate(p4est; user_data = p_data) do ip, data, dp + d = unsafe_pointer_to_objref(data); + index, vertices, cells = d ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - if isa(ps_data,InsideSolidData) - ds, midpoint = quad_to_cell(ip.p4est,ip.treeid[],ip.quad) + if isa(ps_data, InsideSolidData) + ds, midpoint = quad_to_cell(ip.p4est, ip.treeid[], ip.quad) else ds = ps_data.ds midpoint = ps_data.midpoint end - for i in 1:nv-1 - vertices[:,(index-1)*nv+i] .= midpoint+0.5*tb[i].*ds + for i = 1:(nv-1) + vertices[:, (index-1)*nv+i] .= midpoint+0.5*tb[i] .* ds end - vertices[:,nv*index] .= midpoint + vertices[:, nv*index] .= midpoint for i in eachindex(ptb) - cells[nc*(index-1)+i] = MeshCell(VTKCellTypes.VTK_TETRA,ptb[i].+nv*(index-1)) + cells[nc*(index-1)+i] = MeshCell(VTKCellTypes.VTK_TETRA, ptb[i] .+ nv*(index-1)) end levels[index] = ip.quad.level[] d[1]+=1 end - solutions = Matrix{Float64}(undef,nc*N,8) - point_solutions = Matrix{Float64}(undef,nv*N,8) + solutions = Matrix{Float64}(undef, nc*N, 8) + point_solutions = Matrix{Float64}(undef, nv*N, 8) index = 1 for tree in ka.kdata.field.trees.data for ps_data in tree - if isa(ps_data,InsideSolidData)||ps_data.bound_enc<0 - solutions[nc*(index-1)+1:nc*index,:].=NaN - point_solutions[nv*(index-1)+1:nv*index,:] .= NaN + if isa(ps_data, InsideSolidData)||ps_data.bound_enc<0 + solutions[(nc*(index-1)+1):(nc*index), :].=NaN + point_solutions[(nv*(index-1)+1):(nv*index), :] .= NaN else - for i in 1:nc - solutions[nc*(index-1)+i,1] = ps_data.prim[1] - @views solutions[nc*(index-1)+i,2:4] .= ps_data.prim[2:4] - solutions[nc*(index-1)+i,5] = 1.0/ps_data.prim[end] - @views solutions[nc*(index-1)+i,6:8] .= ps_data.qf + for i = 1:nc + solutions[nc*(index-1)+i, 1] = ps_data.prim[1] + @views solutions[nc*(index-1)+i, 2:4] .= ps_data.prim[2:4] + solutions[nc*(index-1)+i, 5] = 1.0/ps_data.prim[end] + @views solutions[nc*(index-1)+i, 6:8] .= ps_data.qf end - + vs_data = ps_data.vs_data - β = @views [min(abs(vs_data.df[i,j]/(0.5*dot(ps_data.ds,abs.(vs_data.sdf[i,j,:]))+EPS)),1.) for i in axes(vs_data.df,1), j in axes(vs_data.df,2)] # positivity preserving coefficient + β = @views [ + min( + abs( + vs_data.df[i, j]/( + 0.5*dot(ps_data.ds, abs.(vs_data.sdf[i, j, :]))+EPS + ), + ), + 1.0, + ) for i in axes(vs_data.df, 1), j in axes(vs_data.df, 2) + ] # positivity preserving coefficient point_df = similar(vs_data.df) - for i in 1:nv-1 + for i = 1:(nv-1) df = vs_data.df sdf = vs_data.sdf - dx = 0.5*ps_data.ds.*tb[i] - point_df .= @views df+[β[i,j]*dot(sdf[i,j,:],dx) for i in axes(df,1), j in axes(df,2)] - w = calc_w0(vs_data.midpoint,point_df,vs_data.weight,ka.kinfo) - prim = get_prim(w,ka.kinfo) - qf = calc_qf(vs_data.midpoint,point_df,vs_data.weight,prim,ka.kinfo) - point_solutions[nv*(index-1)+i,1] = prim[1] - @views point_solutions[nv*(index-1)+i,2:4] .= prim[2:4] - point_solutions[nv*(index-1)+i,5] = 1.0/prim[end] - @views point_solutions[nv*(index-1)+i,6:8] .= qf + dx = 0.5*ps_data.ds .* tb[i] + point_df .= @views df+[ + β[i, j]*dot(sdf[i, j, :], dx) for i in axes(df, 1), j in axes(df, 2) + ] + w = calc_w0(vs_data.midpoint, point_df, vs_data.weight, ka.kinfo) + prim = get_prim(w, ka.kinfo) + qf = calc_qf(vs_data.midpoint, point_df, vs_data.weight, prim, ka.kinfo) + point_solutions[nv*(index-1)+i, 1] = prim[1] + @views point_solutions[nv*(index-1)+i, 2:4] .= prim[2:4] + point_solutions[nv*(index-1)+i, 5] = 1.0/prim[end] + @views point_solutions[nv*(index-1)+i, 6:8] .= qf end - point_solutions[nv*index,1] = ps_data.prim[1] - @views point_solutions[nv*index,2:4] .= ps_data.prim[2:4] - point_solutions[nv*index,5] = 1.0/ps_data.prim[end] - @views point_solutions[nv*index,6:8] .= ps_data.qf + point_solutions[nv*index, 1] = ps_data.prim[1] + @views point_solutions[nv*index, 2:4] .= ps_data.prim[2:4] + point_solutions[nv*index, 5] = 1.0/ps_data.prim[end] + @views point_solutions[nv*index, 6:8] .= ps_data.qf end index += 1 end end - return vertices,cells,point_solutions,solutions + return vertices, cells, point_solutions, solutions end -function pvtu_data(p4est,ka,::Type{T}) where{T<:Voxel} +function pvtu_data(p4est, ka, ::Type{T}) where {T<:Voxel} N = PointerWrapper(p4est).local_num_quadrants[] - tb = Vector{SVector{3,Float64}}(undef,8) - tb[1] = @SVector [-1.,-1.,-1.];tb[2] = @SVector [1.,-1.,-1.];tb[3] = @SVector [-1.,1.,-1.];tb[4] = @SVector [1.,1.,-1.] - tb[5] = @SVector [-1.,-1.,1.];tb[6] = @SVector [1.,-1.,1.];tb[7] = @SVector [-1.,1.,1.];tb[8] = @SVector [1.,1.,1.] - vertices = Matrix{Float64}(undef,3,8*N) - cells = Vector{MeshCell}(undef,N) - levels = Vector{Int8}(undef,N) + tb = Vector{SVector{3,Float64}}(undef, 8) + tb[1] = @SVector [-1.0, -1.0, -1.0]; + tb[2] = @SVector [1.0, -1.0, -1.0]; + tb[3] = @SVector [-1.0, 1.0, -1.0]; + tb[4] = @SVector [1.0, 1.0, -1.0] + tb[5] = @SVector [-1.0, -1.0, 1.0]; + tb[6] = @SVector [1.0, -1.0, 1.0]; + tb[7] = @SVector [-1.0, 1.0, 1.0]; + tb[8] = @SVector [1.0, 1.0, 1.0] + vertices = Matrix{Float64}(undef, 3, 8*N) + cells = Vector{MeshCell}(undef, N) + levels = Vector{Int8}(undef, N) index = 1 - data = [index,vertices,cells,levels] + data = [index, vertices, cells, levels] p_data = pointer_from_objref(data) - GC.@preserve data AMR_volume_iterate(p4est;user_data = p_data) do ip,data,dp - d = unsafe_pointer_to_objref(data);index,vertices,cells = d + GC.@preserve data AMR_volume_iterate(p4est; user_data = p_data) do ip, data, dp + d = unsafe_pointer_to_objref(data); + index, vertices, cells = d ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - if isa(ps_data,InsideSolidData) - ds, midpoint = quad_to_cell(ip.p4est,ip.treeid[],ip.quad) + if isa(ps_data, InsideSolidData) + ds, midpoint = quad_to_cell(ip.p4est, ip.treeid[], ip.quad) else ds = ps_data.ds midpoint = ps_data.midpoint end - for i in 1:8 - @. vertices[:,(index-1)*8+i] = midpoint+tb[i]/2*ds + for i = 1:8 + @. vertices[:, (index-1)*8+i] = midpoint+tb[i]/2*ds end - cells[index] = MeshCell(VTKCellTypes.VTK_VOXEL,(1:8).+8*(index-1)) + cells[index] = MeshCell(VTKCellTypes.VTK_VOXEL, (1:8) .+ 8*(index-1)) levels[index] = ip.quad.level[] d[1]+=1 end - solutions = Matrix{Float64}(undef,N,8) - point_solutions = Matrix{Float64}(undef,8*N,8) + solutions = Matrix{Float64}(undef, N, 8) + point_solutions = Matrix{Float64}(undef, 8*N, 8) index = 1 for tree in ka.kdata.field.trees.data for ps_data in tree - if isa(ps_data,InsideSolidData)||ps_data.bound_enc<0 - solutions[index,:].=NaN - point_solutions[8*(index-1)+1:8*index,:] .= NaN + if isa(ps_data, InsideSolidData)||ps_data.bound_enc<0 + solutions[index, :].=NaN + point_solutions[(8*(index-1)+1):(8*index), :] .= NaN else - solutions[index,1] = ps_data.prim[1] - @views solutions[index,2:4] .= ps_data.prim[2:4] - solutions[index,5] = 1.0/ps_data.prim[end] - @views solutions[index,6:8] .= ps_data.qf - for i in 1:8 - point_solutions[8*(index-1)+i,1] = ps_data.prim[1] - @views point_solutions[8*(index-1)+i,2:4] .= ps_data.prim[2:4] - point_solutions[8*(index-1)+i,5] = 1.0/ps_data.prim[end] - @views point_solutions[8*(index-1)+i,6:8] .= ps_data.qf + solutions[index, 1] = ps_data.prim[1] + @views solutions[index, 2:4] .= ps_data.prim[2:4] + solutions[index, 5] = 1.0/ps_data.prim[end] + @views solutions[index, 6:8] .= ps_data.qf + for i = 1:8 + point_solutions[8*(index-1)+i, 1] = ps_data.prim[1] + @views point_solutions[8*(index-1)+i, 2:4] .= ps_data.prim[2:4] + point_solutions[8*(index-1)+i, 5] = 1.0/ps_data.prim[end] + @views point_solutions[8*(index-1)+i, 6:8] .= ps_data.qf end end index += 1 end end - return vertices,cells,point_solutions,solutions + return vertices, cells, point_solutions, solutions end -function save_surfaces_pvtu(::String,::Vector{Boundary_Solution},ka::KA{2}) +function save_surfaces_pvtu(::String, ::Vector{Boundary_Solution}, ka::KA{2}) return nothing end -function save_surfaces_pvtu(dir_path::String,boundary_results::Vector{Boundary_Solution},ka::KA{3}) +function save_surfaces_pvtu( + dir_path::String, + boundary_results::Vector{Boundary_Solution}, + ka::KA{3}, +) np = MPI.Comm_size(MPI.COMM_WORLD) - rflags = [Ref(false) for _ in 1:np] + rflags = [Ref(false) for _ = 1:np] rank = MPI.Comm_rank(MPI.COMM_WORLD) surface_path = dir_path*"/vtk" for i in eachindex(boundary_results) boundary_solutions = boundary_results[i] rflags[rank+1][] = !isempty(boundary_solutions.ps_solutions) - reqs = Vector{MPI.Request}(undef,0) - for i in 1:np + reqs = Vector{MPI.Request}(undef, 0) + for i = 1:np i-1==rank&&continue - sreq = MPI.Isend(rflags[rank+1],MPI.COMM_WORLD;dest = i-1,tag = COMM_DATA_TAG+rank) - push!(reqs,sreq) - end - for i in 1:np - i-1==rank&&continue - rreq = MPI.Irecv!( - rflags[i], + sreq = MPI.Isend( + rflags[rank+1], MPI.COMM_WORLD; - source = i-1, - tag = COMM_DATA_TAG+i-1 + dest = i-1, + tag = COMM_DATA_TAG+rank, ) - push!(reqs,rreq) + push!(reqs, sreq) + end + for i = 1:np + i-1==rank&&continue + rreq = + MPI.Irecv!(rflags[i], MPI.COMM_WORLD; source = i-1, tag = COMM_DATA_TAG+i-1) + push!(reqs, rreq) end MPI.Waitall(reqs) if rflags[rank+1][] - nparts = length(findall(x->x[],rflags));part = length(findall(x->x[],rflags[1:rank+1])) - points = [boundary_solutions.midpoints[i][j] for i in eachindex(boundary_solutions.midpoints), j in 1:3] |> permutedims - cells = [MeshCell(VTKCellTypes.VTK_VERTEX,[i]) for i in eachindex(boundary_solutions.midpoints)] - pvtk_grid(surface_path*"/surface_"*string(i),points,cells;part = part,nparts = nparts) do pvtk + nparts = length(findall(x->x[], rflags)); + part = length(findall(x->x[], rflags[1:(rank+1)])) + points = + [ + boundary_solutions.midpoints[i][j] for + i in eachindex(boundary_solutions.midpoints), j = 1:3 + ] |> permutedims + cells = [ + MeshCell(VTKCellTypes.VTK_VERTEX, [i]) for + i in eachindex(boundary_solutions.midpoints) + ] + pvtk_grid( + surface_path*"/surface_"*string(i), + points, + cells; + part = part, + nparts = nparts, + ) do pvtk pvtk["rho"] = [x.prim[1] for x in boundary_solutions.ps_solutions] pvtk["U"] = [x.prim[2] for x in boundary_solutions.ps_solutions] pvtk["V"] = [x.prim[3] for x in boundary_solutions.ps_solutions] @@ -684,17 +831,23 @@ function save_surfaces_pvtu(dir_path::String,boundary_results::Vector{Boundary_S pvtk["p13"] = [x.p[3] for x in boundary_solutions.ps_solutions] pvtk["p22"] = [x.p[4] for x in boundary_solutions.ps_solutions] pvtk["p23"] = [x.p[5] for x in boundary_solutions.ps_solutions] - pvtk["p33"] = [x.p[6] for x in boundary_solutions.ps_solutions ] - pvtk["normal"] = ([x[1] for x in boundary_solutions.normal],[x[2] for x in boundary_solutions.normal], - [x[3] for x in boundary_solutions.normal]) + pvtk["p33"] = [x.p[6] for x in boundary_solutions.ps_solutions] + pvtk["normal"] = ( + [x[1] for x in boundary_solutions.normal], + [x[2] for x in boundary_solutions.normal], + [x[3] for x in boundary_solutions.normal], + ) end end end return nothing end -function save_boundary_result(dir_path::String,ka::KA{DIM,NDF}) where{DIM,NDF} +function save_boundary_result(dir_path::String, ka::KA{DIM,NDF}) where {DIM,NDF} ibs = ka.kinfo.config.IB - boundary_results = [Boundary_Solution(Vector{Float64}[],Vector{Float64}[],Boundary_PS_Solution[]) for _ in eachindex(ibs)] + boundary_results = [ + Boundary_Solution(Vector{Float64}[], Vector{Float64}[], Boundary_PS_Solution[]) + for _ in eachindex(ibs) + ] for i in eachindex(ibs) if MPI.Comm_rank(MPI.COMM_WORLD)==0 vs_dir_path = dir_path*"/boundary_vs_"*string(i) @@ -704,53 +857,69 @@ function save_boundary_result(dir_path::String,ka::KA{DIM,NDF}) where{DIM,NDF} MPI.Barrier(MPI.COMM_WORLD) for tree in ka.kdata.field.trees.data for ps_data in tree - (isa(ps_data,InsideSolidData)||ps_data.bound_enc<=0)&&continue + (isa(ps_data, InsideSolidData)||ps_data.bound_enc<=0)&&continue ib = ibs[ps_data.bound_enc] - save_boundary_result!(ib,ps_data,boundary_results,ka;dir_path = dir_path*"/boundary_vs_"*string(ps_data.bound_enc)) + save_boundary_result!( + ib, + ps_data, + boundary_results, + ka; + dir_path = dir_path*"/boundary_vs_"*string(ps_data.bound_enc), + ) end end rank = MPI.Comm_rank(MPI.COMM_WORLD) - save_object(dir_path*"boundary_result_"*string(rank)*".jld2",boundary_results) - save_surfaces_pvtu(dir_path,boundary_results,ka) + save_object(dir_path*"boundary_result_"*string(rank)*".jld2", boundary_results) + save_surfaces_pvtu(dir_path, boundary_results, ka) end -function boundary_write_csv(csvname,results,config::ConfigureForSave{2}) +function boundary_write_csv(csvname, results, config::ConfigureForSave{2}) for i in eachindex(config.IB) df = DataFrame() - df.x=[x[1] for x in results[i].midpoints];df.y=[x[2] for x in results[i].midpoints] - df.nx = [x[1] for x in results[i].normal];df.ny = [x[2] for x in results[i].normal] + df.x=[x[1] for x in results[i].midpoints]; + df.y=[x[2] for x in results[i].midpoints] + df.nx = [x[1] for x in results[i].normal]; + df.ny = [x[2] for x in results[i].normal] df.rho=[x.prim[1] for x in results[i].ps_solutions] df.u=[x.prim[2] for x in results[i].ps_solutions] df.v=[x.prim[3] for x in results[i].ps_solutions] df.T=[1/x.prim[4] for x in results[i].ps_solutions] - df.qfx=[x.qf[1] for x in results[i].ps_solutions];df.qfy=[x.qf[2] for x in results[i].ps_solutions] - df.p11 = [x.p[1] for x in results[i].ps_solutions];df.p12 = [x.p[2] for x in results[i].ps_solutions] + df.qfx=[x.qf[1] for x in results[i].ps_solutions]; + df.qfy=[x.qf[2] for x in results[i].ps_solutions] + df.p11 = [x.p[1] for x in results[i].ps_solutions]; + df.p12 = [x.p[2] for x in results[i].ps_solutions] df.p22 = [x.p[3] for x in results[i].ps_solutions] - CSV.write(csvname*"_"*string(i)*".csv",df) + CSV.write(csvname*"_"*string(i)*".csv", df) end end -function boundary_write_csv(csvname,results,config::ConfigureForSave{3}) +function boundary_write_csv(csvname, results, config::ConfigureForSave{3}) for i in eachindex(config.IB) df = DataFrame() - df.x=[x[1] for x in results[i].midpoints];df.y=[x[2] for x in results[i].midpoints] - df.nx = [x[1] for x in results[i].normal];df.ny = [x[2] for x in results[i].normal] + df.x=[x[1] for x in results[i].midpoints]; + df.y=[x[2] for x in results[i].midpoints] + df.nx = [x[1] for x in results[i].normal]; + df.ny = [x[2] for x in results[i].normal] df.rho=[x.prim[1] for x in results[i].ps_solutions] df.u=[x.prim[2] for x in results[i].ps_solutions] df.v=[x.prim[3] for x in results[i].ps_solutions] df.w=[x.prim[4] for x in results[i].ps_solutions] df.T=[1/x.prim[4] for x in results[i].ps_solutions] - df.qfx=[x.qf[1] for x in results[i].ps_solutions];df.qfy=[x.qf[2] for x in results[i].ps_solutions] + df.qfx=[x.qf[1] for x in results[i].ps_solutions]; + df.qfy=[x.qf[2] for x in results[i].ps_solutions] df.qfz=[x.qf[3] for x in results[i].ps_solutions] - df.p11 = [x.p[1] for x in results[i].ps_solutions];df.p12 = [x.p[2] for x in results[i].ps_solutions] - df.p13 = [x.p[3] for x in results[i].ps_solutions];df.p22 = [x.p[4] for x in results[i].ps_solutions]; - df.p23 = [x.p[5] for x in results[i].ps_solutions];df.p33 = [x.p[6] for x in results[i].ps_solutions]; - CSV.write(csvname*"_"*string(i)*".csv",df) + df.p11 = [x.p[1] for x in results[i].ps_solutions]; + df.p12 = [x.p[2] for x in results[i].ps_solutions] + df.p13 = [x.p[3] for x in results[i].ps_solutions]; + df.p22 = [x.p[4] for x in results[i].ps_solutions]; + df.p23 = [x.p[5] for x in results[i].ps_solutions]; + df.p33 = [x.p[6] for x in results[i].ps_solutions]; + CSV.write(csvname*"_"*string(i)*".csv", df) end end -function boundary_result2csv(dirname::String,csvname::String) +function boundary_result2csv(dirname::String, csvname::String) path = "./"*dirname solverset = load_object(path*"/solverset.jld2") results = nothing - for i in 1:solverset.mpi_size + for i = 1:solverset.mpi_size if i==1 results = load_object(path*"/boundary_result_"*string(i-1)*".jld2") else @@ -758,40 +927,51 @@ function boundary_result2csv(dirname::String,csvname::String) for j in eachindex(rs) r = rs[j] result = results[j] - append!(result.ps_solutions,r.ps_solutions) - append!(result.midpoints,r.midpoints) - append!(result.normal,r.normal) + append!(result.ps_solutions, r.ps_solutions) + append!(result.midpoints, r.midpoints) + append!(result.normal, r.normal) end end end - boundary_write_csv(csvname,results,solverset.config) + boundary_write_csv(csvname, results, solverset.config) end -function result2vtk(dirname::String,vtkname::String) +function result2vtk(dirname::String, vtkname::String) !MPI.Initialized() && MPI.Init() path = "./"*dirname solverset = load_object(path*"/solverset.jld2") if typeof(solverset.config).parameters[1]==2 DIM=2 - cnn = Ptr{Ptr{p4est_connectivity_t}}(Libc.malloc(sizeof(Ptr{Ptr{p4est_connectivity_t}}))) + cnn = Ptr{Ptr{p4est_connectivity_t}}( + Libc.malloc(sizeof(Ptr{Ptr{p4est_connectivity_t}})), + ) pro_path = pwd() cd(dirname) - p4est = p4est_load_ext("p",MPI.COMM_WORLD,Cint(0),Cint(0),Cint(1),Cint(0),C_NULL,cnn) + p4est = p4est_load_ext( + "p", + MPI.COMM_WORLD, + Cint(0), + Cint(0), + Cint(1), + Cint(0), + C_NULL, + cnn, + ) cd(pro_path) result = nothing ranks = nothing for i = 1:solverset.mpi_size if i==1 result = load_object(path*"/result_"*string(i-1)*".jld2") - ranks = zeros(Int,length(result.solution.ps_solutions)) + ranks = zeros(Int, length(result.solution.ps_solutions)) else r = load_object(path*"/result_"*string(i-1)*".jld2") - append!(result.solution.ps_solutions,r.solution.ps_solutions) - append!(result.solution.vs_solutions,r.solution.vs_solutions) - append!(result.mesh_info.neighbor_nums,r.mesh_info.neighbor_nums) - append!(ranks,ones(Int,length(r.solution.ps_solutions))*(i-1)) + append!(result.solution.ps_solutions, r.solution.ps_solutions) + append!(result.solution.vs_solutions, r.solution.vs_solutions) + append!(result.mesh_info.neighbor_nums, r.mesh_info.neighbor_nums) + append!(ranks, ones(Int, length(r.solution.ps_solutions))*(i-1)) end end - vtk_cnn = Vector{Vector{Int}}(undef,length(result.solution.ps_solutions)) + vtk_cnn = Vector{Vector{Int}}(undef, length(result.solution.ps_solutions)) neighbor_nums = result.mesh_info.neighbor_nums for i in eachindex(neighbor_nums) for j in eachindex(neighbor_nums[i]) @@ -801,29 +981,29 @@ function result2vtk(dirname::String,vtkname::String) for i in eachindex(vtk_cnn) addi_points_num = 0 for j in eachindex(neighbor_nums[i]) - addi_points_num+= neighbor_nums[i][j]==2^(DIM-1) ? 1 : 0 + addi_points_num += neighbor_nums[i][j]==2^(DIM-1) ? 1 : 0 end - vtk_cnn[i] = Vector{Int}(undef,2^DIM+addi_points_num) + vtk_cnn[i] = Vector{Int}(undef, 2^DIM+addi_points_num) end points = Vector{Float64}[] data = Vector{Any}() - for el in (points,vtk_cnn,neighbor_nums) - push!(data,el) + for el in (points, vtk_cnn, neighbor_nums) + push!(data, el) end p_data = pointer_from_objref(data) - GC.@preserve data AMR_corner_iterate(p4est;user_data = p_data) do ip,data - points,vtk_cnn,neighbor_nums = unsafe_pointer_to_objref(data) - DIM=isa(ip,PointerWrapper{p4est_iter_corner_info_t}) ? 2 : 3 - for i in 1:ip.sides.elem_count[] - side = iPointerWrapper(ip.sides,p4est_iter_corner_side_t,i-1) + GC.@preserve data AMR_corner_iterate(p4est; user_data = p_data) do ip, data + points, vtk_cnn, neighbor_nums = unsafe_pointer_to_objref(data) + DIM=isa(ip, PointerWrapper{p4est_iter_corner_info_t}) ? 2 : 3 + for i = 1:ip.sides.elem_count[] + side = iPointerWrapper(ip.sides, p4est_iter_corner_side_t, i-1) cornerid = side.corner[]+1 # z-order if i==1 - ds,midpoint = quad_to_cell(ip.p4est,side.treeid[],side.quad) + ds, midpoint = quad_to_cell(ip.p4est, side.treeid[], side.quad) point = @. midpoint+0.5*ds*RMT[DIM][cornerid] - push!(points,point) + push!(points, point) end id = length(points) - quadid = local_quadid(ip,side) + quadid = local_quadid(ip, side) neighbor_num = neighbor_nums[quadid+1] cornerid==1&&(vtk_cnn[quadid+1][1]=id) cornerid==2&&(vtk_cnn[quadid+1][neighbor_num[3]+1]=id) @@ -832,62 +1012,80 @@ function result2vtk(dirname::String,vtkname::String) end return nothing end - GC.@preserve data AMR_face_iterate(p4est;user_data = p_data) do ip,data - points,vtk_cnn,neighbor_nums = unsafe_pointer_to_objref(data) - DIM=isa(ip,PointerWrapper{p4est_iter_face_info_t}) ? 2 : 3 + GC.@preserve data AMR_face_iterate(p4est; user_data = p_data) do ip, data + points, vtk_cnn, neighbor_nums = unsafe_pointer_to_objref(data) + DIM=isa(ip, PointerWrapper{p4est_iter_face_info_t}) ? 2 : 3 ip.sides.elem_count[]==1&&return nothing - side1 = iPointerWrapper(ip.sides,p4est_iter_face_side_t,0) - side2 = iPointerWrapper(ip.sides,p4est_iter_face_side_t,1) + side1 = iPointerWrapper(ip.sides, p4est_iter_face_side_t, 0) + side2 = iPointerWrapper(ip.sides, p4est_iter_face_side_t, 1) (side1.is_hanging[]==0&&side2.is_hanging[]==0)&&return nothing - for side in (side1,side2) - if side.is_hanging[]==0 - ds,midpoint = quad_to_cell(ip.p4est,side.treeid[],side.is.full.quad) - faceid = side.face[]+1 - point = @. midpoint+0.5*ds*NMT[DIM][faceid] - push!(points,point) - id = length(points) - quadid = local_quadid(ip.p4est,side.treeid[],side.is.full.quadid[]) - neighbor_num = neighbor_nums[quadid+1] - faceid==1&&(@inbounds vtk_cnn[quadid+1][end]=id) - faceid==2&&(@inbounds vtk_cnn[quadid+1][neighbor_num[3]+2]=id) - faceid==3&&(@inbounds vtk_cnn[quadid+1][2]=id) - faceid==4&&(@inbounds vtk_cnn[quadid+1][sum(neighbor_num[2:3])+2]=id) - end + for side in (side1, side2) + if side.is_hanging[]==0 + ds, midpoint = quad_to_cell(ip.p4est, side.treeid[], side.is.full.quad) + faceid = side.face[]+1 + point = @. midpoint+0.5*ds*NMT[DIM][faceid] + push!(points, point) + id = length(points) + quadid = local_quadid(ip.p4est, side.treeid[], side.is.full.quadid[]) + neighbor_num = neighbor_nums[quadid+1] + faceid==1&&(@inbounds vtk_cnn[quadid+1][end]=id) + faceid==2&&(@inbounds vtk_cnn[quadid+1][neighbor_num[3]+2]=id) + faceid==3&&(@inbounds vtk_cnn[quadid+1][2]=id) + faceid==4&&(@inbounds vtk_cnn[quadid+1][sum(neighbor_num[2:3])+2]=id) + end end - for side in (side1,side2) - if side.is_hanging[]==1 - faceid = side.face[]+1 - id = length(points) - quadids = side.is.hanging.quadid[] - quadid1 = local_quadid(ip.p4est,side.treeid[],quadids[1]) - quadid2 = local_quadid(ip.p4est,side.treeid[],quadids[2]) - neighbor_num1 = neighbor_nums[quadid1+1] - neighbor_num2 = neighbor_nums[quadid2+1] - faceid==1&&(@inbounds vtk_cnn[quadid1+1][end]=id;vtk_cnn[quadid2+1][1]=id) - faceid==2&&(@inbounds vtk_cnn[quadid1+1][sum(neighbor_num1[2:3])+1]=id;vtk_cnn[quadid2+1][neighbor_num2[3]+1]=id) - faceid==3&&(@inbounds vtk_cnn[quadid1+1][2]=id;vtk_cnn[quadid2+1][1]=id) - faceid==4&&(@inbounds vtk_cnn[quadid1+1][sum(neighbor_num1[2:3])+1]=id;vtk_cnn[quadid2+1][end]=id) - end + for side in (side1, side2) + if side.is_hanging[]==1 + faceid = side.face[]+1 + id = length(points) + quadids = side.is.hanging.quadid[] + quadid1 = local_quadid(ip.p4est, side.treeid[], quadids[1]) + quadid2 = local_quadid(ip.p4est, side.treeid[], quadids[2]) + neighbor_num1 = neighbor_nums[quadid1+1] + neighbor_num2 = neighbor_nums[quadid2+1] + faceid==1&&( + @inbounds vtk_cnn[quadid1+1][end]=id; + vtk_cnn[quadid2+1][1] = id + ) + faceid==2&&( + @inbounds vtk_cnn[quadid1+1][sum(neighbor_num1[2:3])+1]=id; + vtk_cnn[quadid2+1][neighbor_num2[3]+1] = id + ) + faceid==3&&( + @inbounds vtk_cnn[quadid1+1][2]=id; + vtk_cnn[quadid2+1][1] = id + ) + faceid==4&&( + @inbounds vtk_cnn[quadid1+1][sum(neighbor_num1[2:3])+1]=id; + vtk_cnn[quadid2+1][end] = id + ) + end end return nothing end - cells = [MeshCell(PolyData.Polys(),cnn) for cnn in vtk_cnn] - vertices = Matrix{Float64}(undef,2,length(points)) + cells = [MeshCell(PolyData.Polys(), cnn) for cnn in vtk_cnn] + vertices = Matrix{Float64}(undef, 2, length(points)) for i in eachindex(points) - @inbounds vertices[:,i] .= points[i] + @inbounds vertices[:, i] .= points[i] end - vtk_grid(vtkname,vertices,cells) do vtk - vtk["rho"] = [ps_solution.prim[1] for ps_solution in result.solution.ps_solutions] - vtk["velocity"] = ([ps_solution.prim[2] for ps_solution in result.solution.ps_solutions], + vtk_grid(vtkname, vertices, cells) do vtk + vtk["rho"] = + [ps_solution.prim[1] for ps_solution in result.solution.ps_solutions] + vtk["velocity"] = ( + [ps_solution.prim[2] for ps_solution in result.solution.ps_solutions], [ps_solution.prim[3] for ps_solution in result.solution.ps_solutions], - [0. for _ in result.solution.ps_solutions]) - vtk["T"] = [1/ps_solution.prim[end] for ps_solution in result.solution.ps_solutions] - vtk["qf"] = ([ps_solution.qf[1] for ps_solution in result.solution.ps_solutions], + [0.0 for _ in result.solution.ps_solutions], + ) + vtk["T"] = + [1/ps_solution.prim[end] for ps_solution in result.solution.ps_solutions] + vtk["qf"] = ( + [ps_solution.qf[1] for ps_solution in result.solution.ps_solutions], [ps_solution.qf[2] for ps_solution in result.solution.ps_solutions], - [0. for _ in result.solution.ps_solutions]) + [0.0 for _ in result.solution.ps_solutions], + ) vtk["mpi_rank"] = ranks end - fp = PointerWrapper(p4est) + fp = PointerWrapper(p4est) p4est_connectivity_destroy(pointer(fp.connectivity)) p4est_destroy(p4est) else @@ -900,32 +1098,34 @@ end $(SIGNATURES) Write the physical-space field arrays into an open `pvtk` handle for a 2D animation frame. """ -function write_anim_field_data!(pvtk,solutions,point_solutions,ranks,::KA{2}) - pvtk["rho"] = @views solutions[:,1] - pvtk["velocity"] = @views (solutions[:,2],solutions[:,3]) - pvtk["T"] = @views solutions[:,4] - pvtk["qf"] = (solutions[:,5],solutions[:,6]) +function write_anim_field_data!(pvtk, solutions, point_solutions, ranks, ::KA{2}) + pvtk["rho"] = @views solutions[:, 1] + pvtk["velocity"] = @views (solutions[:, 2], solutions[:, 3]) + pvtk["T"] = @views solutions[:, 4] + pvtk["qf"] = (solutions[:, 5], solutions[:, 6]) pvtk["mpi_rank"] = ranks - pvtk["rho",VTKPointData()] = @views point_solutions[:,1] - pvtk["velocity",VTKPointData()] = @views (point_solutions[:,2],point_solutions[:,3]) - pvtk["T",VTKPointData()] = @views point_solutions[:,4] - pvtk["qf",VTKPointData()] = (point_solutions[:,5],point_solutions[:,6]) + pvtk["rho", VTKPointData()] = @views point_solutions[:, 1] + pvtk["velocity", VTKPointData()] = @views (point_solutions[:, 2], point_solutions[:, 3]) + pvtk["T", VTKPointData()] = @views point_solutions[:, 4] + pvtk["qf", VTKPointData()] = (point_solutions[:, 5], point_solutions[:, 6]) return nothing end """ $(SIGNATURES) Write the physical-space field arrays into an open `pvtk` handle for a 3D animation frame. """ -function write_anim_field_data!(pvtk,solutions,point_solutions,ranks,::KA{3}) - pvtk["rho"] = @views solutions[:,1] - pvtk["velocity"] = @views (solutions[:,2],solutions[:,3],solutions[:,4]) - pvtk["T"] = @views solutions[:,5] - pvtk["qf"] = (solutions[:,6],solutions[:,7],solutions[:,8]) +function write_anim_field_data!(pvtk, solutions, point_solutions, ranks, ::KA{3}) + pvtk["rho"] = @views solutions[:, 1] + pvtk["velocity"] = @views (solutions[:, 2], solutions[:, 3], solutions[:, 4]) + pvtk["T"] = @views solutions[:, 5] + pvtk["qf"] = (solutions[:, 6], solutions[:, 7], solutions[:, 8]) pvtk["mpi_rank"] = ranks - pvtk["rho",VTKPointData()] = @views point_solutions[:,1] - pvtk["velocity",VTKPointData()] = @views (point_solutions[:,2],point_solutions[:,3],point_solutions[:,4]) - pvtk["T",VTKPointData()] = @views point_solutions[:,5] - pvtk["qf",VTKPointData()] = (point_solutions[:,6],point_solutions[:,7],point_solutions[:,8]) + pvtk["rho", VTKPointData()] = @views point_solutions[:, 1] + pvtk["velocity", VTKPointData()] = + @views (point_solutions[:, 2], point_solutions[:, 3], point_solutions[:, 4]) + pvtk["T", VTKPointData()] = @views point_solutions[:, 5] + pvtk["qf", VTKPointData()] = + (point_solutions[:, 6], point_solutions[:, 7], point_solutions[:, 8]) return nothing end """ @@ -936,20 +1136,35 @@ requested, each one gets its own `full_simulation.pvd` / `step= 1024 && i < length(units) - x /= 1024; i += 1 + x /= 1024; + i += 1 end return string(round(x; digits = 2), " ", units[i]) end @@ -70,7 +72,12 @@ configuration (`solverset.jld2` incl. the initial-condition / user-defined funct Call after a time step (e.g. inside or after [`solve!`](@ref)); the saved distribution `df` is taken as-is, so no slope/macro update is performed. """ -function save_for_restart(p4est::P_pxest_t, ka::KA{DIM,NDF}; dir_path::String = "restart", confirm::Bool = true) where{DIM,NDF} +function save_for_restart( + p4est::P_pxest_t, + ka::KA{DIM,NDF}; + dir_path::String = "restart", + confirm::Bool = true, +) where {DIM,NDF} comm = MPI.COMM_WORLD rank = MPI.Comm_rank(comm) mpi_size = MPI.Comm_size(comm) @@ -108,7 +115,7 @@ function save_for_restart(p4est::P_pxest_t, ka::KA{DIM,NDF}; dir_path::String = isa(ps_data, InsideSolidData) && continue vs_data = ps_data.vs_data vn = vs_data.vs_num - rng = offset+1:offset+vn + rng = (offset+1):(offset+vn) vs_levels[rng] .= vs_data.level vs_midpoints[rng, :] .= vs_data.midpoint vs_df[rng, :] .= vs_data.df @@ -117,13 +124,20 @@ function save_for_restart(p4est::P_pxest_t, ka::KA{DIM,NDF}; dir_path::String = end # Size estimate (raw, uncompressed) and optional confirmation. - local_bytes = sizeof(vs_nums) + sizeof(bound_encs) + sizeof(ws) + - sizeof(vs_levels) + sizeof(vs_midpoints) + sizeof(vs_df) + local_bytes = + sizeof(vs_nums) + + sizeof(bound_encs) + + sizeof(ws) + + sizeof(vs_levels) + + sizeof(vs_midpoints) + + sizeof(vs_df) total_bytes = MPI.Reduce(local_bytes, +, 0, comm) proceed = true if rank == 0 - println("Restart checkpoint: ≈ $(_human_bytes(total_bytes)) of phase-space data " * - "($(mpi_size) rank file(s)) → $(dir_path)/") + println( + "Restart checkpoint: ≈ $(_human_bytes(total_bytes)) of phase-space data " * + "($(mpi_size) rank file(s)) → $(dir_path)/", + ) if confirm && isa(stdin, Base.TTY) print("Continue saving? [y/N]: ") ans = strip(readline()) @@ -218,12 +232,34 @@ function _restart_load_forest(dir::String, DIM::Integer) # balance the load across the (possibly different) current number of ranks. dsz = Csize_t(sizeof(P4estPsData)) if DIM == 2 - cnn = Ptr{Ptr{p4est_connectivity_t}}(Libc.malloc(sizeof(Ptr{Ptr{p4est_connectivity_t}}))) - p4est = GC.@preserve cnn p4est_load_ext("p", MPI.COMM_WORLD, Cint(0), Cint(0), Cint(1), Cint(0), C_NULL, cnn) + cnn = Ptr{Ptr{p4est_connectivity_t}}( + Libc.malloc(sizeof(Ptr{Ptr{p4est_connectivity_t}})), + ) + p4est = GC.@preserve cnn p4est_load_ext( + "p", + MPI.COMM_WORLD, + Cint(0), + Cint(0), + Cint(1), + Cint(0), + C_NULL, + cnn, + ) GC.@preserve p4est p4est_reset_data(p4est, dsz, C_NULL, C_NULL) else - cnn = Ptr{Ptr{p8est_connectivity_t}}(Libc.malloc(sizeof(Ptr{Ptr{p8est_connectivity_t}}))) - p4est = GC.@preserve cnn p8est_load_ext("p", MPI.COMM_WORLD, Cint(0), Cint(0), Cint(1), Cint(0), C_NULL, cnn) + cnn = Ptr{Ptr{p8est_connectivity_t}}( + Libc.malloc(sizeof(Ptr{Ptr{p8est_connectivity_t}})), + ) + p4est = GC.@preserve cnn p8est_load_ext( + "p", + MPI.COMM_WORLD, + Cint(0), + Cint(0), + Cint(1), + Cint(0), + C_NULL, + cnn, + ) GC.@preserve p4est p8est_reset_data(p4est, dsz, C_NULL, C_NULL) end cd(pro_path) @@ -234,15 +270,18 @@ end function _restart_integrity_message(dir::String, manifest) problems = String[] old_size = manifest["mpi_size"] - manifest["format_version"] == RESTART_FORMAT_VERSION || - push!(problems, "manifest format_version $(manifest["format_version"]) ≠ expected $(RESTART_FORMAT_VERSION)") + manifest["format_version"] == RESTART_FORMAT_VERSION || push!( + problems, + "manifest format_version $(manifest["format_version"]) ≠ expected $(RESTART_FORMAT_VERSION)", + ) for f in ("solverset.jld2", "output.jld2", "status.jld2") isfile(dir * f) || push!(problems, "missing metadata file: $(dir*f)") end isempty(filter(f -> startswith(f, "p"), readdir(dir))) && push!(problems, "missing p4est forest files (prefix 'p') in $(dir)") - lqn = manifest["local_quad_nums"]; vst = manifest["vs_totals"] - for r in 0:old_size-1 + lqn = manifest["local_quad_nums"]; + vst = manifest["vs_totals"] + for r = 0:(old_size-1) f = dir * "restart_" * string(r) * ".jld2" if !isfile(f) push!(problems, "missing per-rank data file: $f") @@ -252,25 +291,35 @@ function _restart_integrity_message(dir::String, manifest) vsn = jldopen(io -> io["vs_nums"], f) # cheap per-cell array length(vsn) == lqn[r+1] || push!(problems, "$f: cell count $(length(vsn)) ≠ manifest $(lqn[r+1])") - sum(vsn) == vst[r+1] || - push!(problems, "$f: velocity-cell total $(sum(vsn)) ≠ manifest $(vst[r+1])") + sum(vsn) == vst[r+1] || push!( + problems, + "$f: velocity-cell total $(sum(vsn)) ≠ manifest $(vst[r+1])", + ) catch e push!(problems, "$f: failed to read ($e)") end end - return isempty(problems) ? "" : "Restart integrity check failed:\n - " * join(problems, "\n - ") + return isempty(problems) ? "" : + "Restart integrity check failed:\n - " * join(problems, "\n - ") end # Reconstruct this rank's ordered ps_data list from the saved per-cell arrays, mapping the saved # partition (gfq_old, old_size files) onto this rank's global quadrant range under the *current* # communicator. p4est save/load preserves the global Morton ordering, so concatenating the # overlapping old-rank files in order and slicing out [G0, G1) is exact. -function _restart_build_ps_list(dir::String, kinfo::KInfo{DIM,NDF}, gfq_old::Vector{Int}, p4est::P_pxest_t) where{DIM,NDF} +function _restart_build_ps_list( + dir::String, + kinfo::KInfo{DIM,NDF}, + gfq_old::Vector{Int}, + p4est::P_pxest_t, +) where {DIM,NDF} comm = MPI.COMM_WORLD rank = MPI.Comm_rank(comm) fp = PointerWrapper(p4est) - gfq_new = unsafe_wrap(Vector{Int}, pointer(fp.global_first_quadrant), MPI.Comm_size(comm) + 1) - G0 = gfq_new[rank+1]; G1 = gfq_new[rank+2] + gfq_new = + unsafe_wrap(Vector{Int}, pointer(fp.global_first_quadrant), MPI.Comm_size(comm) + 1) + G0 = gfq_new[rank+1]; + G1 = gfq_new[rank+2] count = G1 - G0 ps_list = Vector{AbstractPsData{DIM,NDF}}(undef, count) count == 0 && return ps_list @@ -278,14 +327,16 @@ function _restart_build_ps_list(dir::String, kinfo::KInfo{DIM,NDF}, gfq_old::Vec first_old = searchsortedlast(gfq_old, G0) - 1 # old rank owning global cell G0 last_old = searchsortedlast(gfq_old, G1 - 1) - 1 # old rank owning global cell G1-1 - vs_nums = Int[]; bound_encs = Int[] + vs_nums = Int[]; + bound_encs = Int[] ws = Matrix{Float64}(undef, 0, DIM + 2) vs_levels = Int8[] vs_midpoints = Matrix{Float64}(undef, 0, DIM) vs_df = Matrix{Float64}(undef, 0, NDF) - for r in first_old:last_old + for r = first_old:last_old d = load(dir * "restart_" * string(r) * ".jld2") - append!(vs_nums, d["vs_nums"]); append!(bound_encs, d["bound_encs"]) + append!(vs_nums, d["vs_nums"]); + append!(bound_encs, d["bound_encs"]) ws = vcat(ws, d["ws"]) append!(vs_levels, d["vs_levels"]) vs_midpoints = vcat(vs_midpoints, d["vs_midpoints"]) @@ -306,19 +357,34 @@ function _restart_build_ps_list(dir::String, kinfo::KInfo{DIM,NDF}, gfq_old::Vec tree_weight = vs_space / reduce(*, kinfo.config.vs_trees_num) voff = vs_start - for i in 1:count + for i = 1:count ci = sa + i - 1 vn = vs_nums[ci] if vn == 0 ps_list[i] = InsideSolidData(DIM, NDF; bound_enc = bound_encs[ci]) else w = ws[ci, :] - levels = vs_levels[voff+1:voff+vn] - mids = vs_midpoints[voff+1:voff+vn, :] - df = vs_df[voff+1:voff+vn, :] + levels = vs_levels[(voff+1):(voff+vn)] + mids = vs_midpoints[(voff+1):(voff+vn), :] + df = vs_df[(voff+1):(voff+vn), :] weight = @. tree_weight / 2.0^(DIM * levels) - vs_data = VsData{DIM,NDF}(vn, levels, weight, mids, df, zeros(vn, NDF, DIM), zeros(vn, NDF)) - ps_list[i] = PsData(DIM, NDF; bound_enc = bound_encs[ci], w = w, prim = get_prim(w, kinfo), vs_data = vs_data) + vs_data = VsData{DIM,NDF}( + vn, + levels, + weight, + mids, + df, + zeros(vn, NDF, DIM), + zeros(vn, NDF), + ) + ps_list[i] = PsData( + DIM, + NDF; + bound_enc = bound_encs[ci], + w = w, + prim = get_prim(w, kinfo), + vs_data = vs_data, + ) end voff += vn end @@ -326,9 +392,14 @@ function _restart_build_ps_list(dir::String, kinfo::KInfo{DIM,NDF}, gfq_old::Vec end # Attach the reconstructed ps_data to the loaded quadrants (in local order) and build the trees. -function _restart_attach!(p4est::P_pxest_t, kinfo::KInfo{DIM,NDF}, ps_list::Vector{AbstractPsData{DIM,NDF}}) where{DIM,NDF} +function _restart_attach!( + p4est::P_pxest_t, + kinfo::KInfo{DIM,NDF}, + ps_list::Vector{AbstractPsData{DIM,NDF}}, +) where {DIM,NDF} fp = PointerWrapper(p4est) - trees_data = [AbstractPsData{DIM,NDF}[] for _ in 1:fp.last_local_tree[]-fp.first_local_tree[]+1] + trees_data = + [AbstractPsData{DIM,NDF}[] for _ = 1:(fp.last_local_tree[]-fp.first_local_tree[]+1)] trees = PsTrees{DIM,NDF}(trees_data, fp.first_local_tree[] - 1) ctx = Any[trees, ps_list, Ref(0)] p_data = pointer_from_objref(ctx) @@ -372,7 +443,8 @@ function restart(dir_path::String; config = nothing, check_integrity::Bool = tru dir = endswith(dir_path, "/") ? dir_path : dir_path * "/" manifest = load(dir * "manifest.jld2") - DIM = manifest["DIM"]; NDF = manifest["NDF"] + DIM = manifest["DIM"]; + NDF = manifest["NDF"] if check_integrity msg = MPI.Comm_rank(comm) == 0 ? _restart_integrity_message(dir, manifest) : "" @@ -384,12 +456,27 @@ function restart(dir_path::String; config = nothing, check_integrity::Bool = tru if config === nothing solverset = load(dir * "solverset.jld2")["solverset"] cfs = solverset.config - output = isfile(dir * "output.jld2") ? load(dir * "output.jld2")["output"] : Output(cfs.solver) - config = Configure{DIM,NDF}(cfs.geometry, cfs.trees_num, cfs.quadrature, cfs.vs_trees_num, - cfs.IC, cfs.domain, cfs.IB, cfs.gas, cfs.solver, output, cfs.user_defined) + output = + isfile(dir * "output.jld2") ? load(dir * "output.jld2")["output"] : + Output(cfs.solver) + config = Configure{DIM,NDF}( + cfs.geometry, + cfs.trees_num, + cfs.quadrature, + cfs.vs_trees_num, + cfs.IC, + cfs.domain, + cfs.IB, + cfs.gas, + cfs.solver, + output, + cfs.user_defined, + ) else (typeof(config).parameters[1] == DIM && typeof(config).parameters[2] == NDF) || - error("supplied `config` is $(typeof(config).parameters[1])D/NDF=$(typeof(config).parameters[2]); checkpoint is $(DIM)D/NDF=$NDF.") + error( + "supplied `config` is $(typeof(config).parameters[1])D/NDF=$(typeof(config).parameters[2]); checkpoint is $(DIM)D/NDF=$NDF.", + ) end kinfo = KInfo(config) @@ -425,7 +512,9 @@ function restart(dir_path::String; config = nothing, check_integrity::Bool = tru status.vs_adapt_step = st["vs_adapt_step"] status.partition_step = st["partition_step"] - MPI.Comm_rank(comm) == 0 && println("Restarted from $(dir) at step $(status.step), sim_time $(status.sim_time).") + MPI.Comm_rank(comm) == 0 && println( + "Restarted from $(dir) at step $(status.step), sim_time $(status.sim_time).", + ) execute_check!(p4est, ka) return p4est, ka end diff --git a/src/IO/Types.jl b/src/IO/Types.jl index 130c899..8d77603 100644 --- a/src/IO/Types.jl +++ b/src/IO/Types.jl @@ -19,26 +19,44 @@ struct StatusForSave vs_adapt_step::Int partition_step::Int end -function ConfigureForSave(config::Configure{DIM,NDF}) where{DIM,NDF} +function ConfigureForSave(config::Configure{DIM,NDF}) where {DIM,NDF} return ConfigureForSave{DIM,NDF}( - config.geometry,config.trees_num,config.quadrature, - config.vs_trees_num,config.IC,config.domain, - config.IB,config.gas, + config.geometry, + config.trees_num, + config.quadrature, + config.vs_trees_num, + config.IC, + config.domain, + config.IB, + config.gas, config.solver, - config.user_defined + config.user_defined, ) end function StatusForSave(status::Status) return StatusForSave( - status.gradmax,status.Δt, - status.Δt_ξ,status.sim_time,status.ps_adapt_step, - status.vs_adapt_step,status.partition_step + status.gradmax, + status.Δt, + status.Δt_ξ, + status.sim_time, + status.ps_adapt_step, + status.vs_adapt_step, + status.partition_step, ) end function Status(status::StatusForSave, DIM::Int) - return Status(status.gradmax,status.Δt, - status.Δt_ξ,status.sim_time,status.ps_adapt_step, - status.vs_adapt_step,status.partition_step,Residual(DIM),Ref(false),false) + return Status( + status.gradmax, + status.Δt, + status.Δt_ξ, + status.sim_time, + status.ps_adapt_step, + status.vs_adapt_step, + status.partition_step, + Residual(DIM), + Ref(false), + false, + ) end struct SolverSet config::ConfigureForSave @@ -53,17 +71,21 @@ struct Boundary_PS_Solution qf::Vector{Float64} p::Vector{Float64} end -function PS_Solution(ps_data::PsData{DIM}) where{DIM} +function PS_Solution(ps_data::PsData{DIM}) where {DIM} if ps_data.bound_enc<0 - prim = Vector{Float64}(undef,DIM+2);prim.=NaN - qf = Vector{Float64}(undef,DIM);qf.=NaN + prim = Vector{Float64}(undef, DIM+2); + prim.=NaN + qf = Vector{Float64}(undef, DIM); + qf.=NaN return PS_Solution(prim, qf) end return PS_Solution(ps_data.prim, ps_data.qf) end -function PS_Solution(::InsideSolidData{DIM,NDF}) where{DIM,NDF} - prim = Vector{Float64}(undef,DIM+2);prim.=NaN - qf = Vector{Float64}(undef,DIM);qf.=NaN +function PS_Solution(::InsideSolidData{DIM,NDF}) where {DIM,NDF} + prim = Vector{Float64}(undef, DIM+2); + prim.=NaN + qf = Vector{Float64}(undef, DIM); + qf.=NaN return PS_Solution(prim, qf) end struct VS_Solution @@ -91,4 +113,4 @@ struct Boundary_Solution midpoints::Vector{Vector{Float64}} normal::Vector{Vector{Float64}} ps_solutions::Vector{Boundary_PS_Solution} -end \ No newline at end of file +end diff --git a/src/KitAMR.jl b/src/KitAMR.jl index 8d12121..4ef0f85 100644 --- a/src/KitAMR.jl +++ b/src/KitAMR.jl @@ -13,8 +13,8 @@ using Reexport using CSV using DataFrames using Statistics -using FileIO,NearestNeighbors,AbstractTrees -using GeometryBasics:Mesh +using FileIO, NearestNeighbors, AbstractTrees +using GeometryBasics: Mesh using StructArrays using P4est using ProgressMeter @@ -49,7 +49,8 @@ function __init__() # variable, set to an `SC_LP_*` integer threshold — e.g. `6` (SC_LP_PRODUCTION) to restore # the per-operation chatter, `8` (SC_LP_ERROR, the default here), `9` (SC_LP_SILENT) to mute # everything including errors. - threshold = something(tryparse(Cint, get(ENV, "KITAMR_P4EST_LOG", "")), Cint(SC_LP_ERROR)) + threshold = + something(tryparse(Cint, get(ENV, "KITAMR_P4EST_LOG", "")), Cint(SC_LP_ERROR)) p4est_init(C_NULL, threshold) end diff --git a/src/Mesh/Connectivity.jl b/src/Mesh/Connectivity.jl index 96db70d..1c770a2 100644 --- a/src/Mesh/Connectivity.jl +++ b/src/Mesh/Connectivity.jl @@ -27,24 +27,44 @@ as `NTuple{3,Cdouble}`. Writing through it mutates the underlying C memory. """ function unsafe_vertices(c::Connectivity) cs = PointerWrapper(c.pointer) - v = unsafe_wrap(Matrix{Cdouble}, pointer(cs.vertices), (3, Int(cs.num_vertices[])), own = false) + v = unsafe_wrap( + Matrix{Cdouble}, + pointer(cs.vertices), + (3, Int(cs.num_vertices[])), + own = false, + ) return reinterpret(reshape, NTuple{3,Cdouble}, v) end function unsafe_trees(c::Connectivity{X}) where {X} cs = PointerWrapper(c.pointer) - ttv = unsafe_wrap(Matrix{p4est_topidx_t}, pointer(cs.tree_to_vertex), (X, Int(cs.num_trees[])), own = false) + ttv = unsafe_wrap( + Matrix{p4est_topidx_t}, + pointer(cs.tree_to_vertex), + (X, Int(cs.num_trees[])), + own = false, + ) return reinterpret(reshape, NTuple{X,p4est_topidx_t}, ttv) end function unsafe_tree_to_tree(c::Connectivity{X}) where {X} cs = PointerWrapper(c.pointer) sides = X == 4 ? 4 : 6 - ttt = unsafe_wrap(Matrix{p4est_topidx_t}, pointer(cs.tree_to_tree), (sides, Int(cs.num_trees[])), own = false) + ttt = unsafe_wrap( + Matrix{p4est_topidx_t}, + pointer(cs.tree_to_tree), + (sides, Int(cs.num_trees[])), + own = false, + ) return reinterpret(reshape, NTuple{sides,p4est_topidx_t}, ttt) end function unsafe_tree_to_face(c::Connectivity{X}) where {X} cs = PointerWrapper(c.pointer) sides = X == 4 ? 4 : 6 - ttf = unsafe_wrap(Matrix{Int8}, pointer(cs.tree_to_face), (sides, Int(cs.num_trees[])), own = false) + ttf = unsafe_wrap( + Matrix{Int8}, + pointer(cs.tree_to_face), + (sides, Int(cs.num_trees[])), + own = false, + ) return reinterpret(reshape, NTuple{sides,Int8}, ttf) end @@ -61,10 +81,12 @@ for 3D hexes. Self-connecting faces are filled in and `complete!` resolves the t function Connectivity{X}(vertices::AbstractVector, cells::AbstractVector) where {X} if X == 4 conn = GC.@preserve vertices cells Connectivity{X}( - p4est_connectivity_new(length(vertices), length(cells), 0, 0)) + p4est_connectivity_new(length(vertices), length(cells), 0, 0), + ) elseif X == 8 conn = GC.@preserve vertices cells Connectivity{X}( - p8est_connectivity_new(length(vertices), length(cells), 0, 0, 0, 0)) + p8est_connectivity_new(length(vertices), length(cells), 0, 0, 0, 0), + ) else throw(error("Unsupported cells.")) end @@ -79,7 +101,8 @@ function Connectivity{X}(vertices::AbstractVector, cells::AbstractVector) where tree_to_face[i] = ntuple(j -> (j - 1), NUM_FACES) end for i in eachindex(cvertices, vertices) - cvertices[i] = ntuple(j -> (j ≤ length(vertices[i]) ? Float64(vertices[i][j]) : 0.0), Val(3)) + cvertices[i] = + ntuple(j -> (j ≤ length(vertices[i]) ? Float64(vertices[i][j]) : 0.0), Val(3)) end complete!(conn) return conn @@ -105,8 +128,8 @@ function Cartesian_connectivity(Nx, Ny, xmin, xmax, ymin, ymax) vertices_C = Array{NTuple{2,Float64}}(undef, Nx + 1, Ny + 1) dx = (xmax - xmin) / Nx dy = (ymax - ymin) / Ny - for j = 1:Ny+1 - for i = 1:Nx+1 + for j = 1:(Ny+1) + for i = 1:(Nx+1) vertices_C[i, j] = (xmin + (i - 1) * dx, ymin + (j - 1) * dy) end end @@ -121,15 +144,16 @@ function Cartesian_connectivity(Nx, Ny, xmin, xmax, ymin, ymax) cells = reshape(cell2ver, :) connectivity = GC.@preserve vertices cells Connectivity{4}(vertices, cells) end -function Cartesian_connectivity(Nx,Ny,Nz,xmin,xmax,ymin,ymax,zmin,zmax) +function Cartesian_connectivity(Nx, Ny, Nz, xmin, xmax, ymin, ymax, zmin, zmax) vertices_C = Array{NTuple{3,Float64}}(undef, Nx + 1, Ny + 1, Nz + 1) dx = (xmax - xmin) / Nx dy = (ymax - ymin) / Ny dz = (zmax - zmin) / Nz - for k = 1:Nz+1 - for j = 1:Ny+1 - for i = 1:Nx+1 - vertices_C[i, j, k] = (xmin + (i - 1) * dx, ymin + (j - 1) * dy, zmin + (k - 1) * dz) + for k = 1:(Nz+1) + for j = 1:(Ny+1) + for i = 1:(Nx+1) + vertices_C[i, j, k] = + (xmin + (i - 1) * dx, ymin + (j - 1) * dy, zmin + (k - 1) * dz) end end end @@ -139,33 +163,45 @@ function Cartesian_connectivity(Nx,Ny,Nz,xmin,xmax,ymin,ymax,zmin,zmax) for k in axes(cell2ver, 3) for j in axes(cell2ver, 2) for i in axes(cell2ver, 1) - cell2ver[i, j, k] = (vL[i, j, k], vL[i+1, j, k], vL[i, j+1, k], vL[i+1, j+1, k], - vL[i, j, k+1], vL[i+1, j, k+1], vL[i, j+1, k+1], vL[i+1, j+1, k+1]) + cell2ver[i, j, k] = ( + vL[i, j, k], + vL[i+1, j, k], + vL[i, j+1, k], + vL[i+1, j+1, k], + vL[i, j, k+1], + vL[i+1, j, k+1], + vL[i, j+1, k+1], + vL[i+1, j+1, k+1], + ) end end end cells = reshape(cell2ver, :) connectivity = GC.@preserve vertices cells Connectivity{8}(vertices, cells) end -function set_connectivity(kinfo::KInfo{DIM}) where{DIM} +function set_connectivity(kinfo::KInfo{DIM}) where {DIM} domain = kinfo.config.domain - periodic_dirs = ntuple(i -> begin - first_boundary = (i-1)*2 + 1 # 1, 3, 5 for i = 1, 2, 3 - second_boundary = first_boundary + 1 # 3, 5, 7 for i = 1, 2, 3 - nameof(typeof(domain[first_boundary]).parameters[1]) == :Period && - nameof(typeof(domain[second_boundary]).parameters[1]) == :Period - end, DIM) - + periodic_dirs = ntuple( + i -> begin + first_boundary = (i-1)*2 + 1 # 1, 3, 5 for i = 1, 2, 3 + second_boundary = first_boundary + 1 # 3, 5, 7 for i = 1, 2, 3 + nameof(typeof(domain[first_boundary]).parameters[1]) == :Period && + nameof(typeof(domain[second_boundary]).parameters[1]) == :Period + end, + DIM, + ) + if periodic_dirs != ntuple(_ -> false, DIM) connectivity_ps = set_periodic_connectivity(kinfo, periodic_dirs) else - connectivity_ps = Cartesian_connectivity(kinfo.config.trees_num..., kinfo.config.geometry...) + connectivity_ps = + Cartesian_connectivity(kinfo.config.trees_num..., kinfo.config.geometry...) end return connectivity_ps end -function set_periodic_connectivity(kinfo::KInfo{DIM}, periodic_dirs) where{DIM} +function set_periodic_connectivity(kinfo::KInfo{DIM}, periodic_dirs) where {DIM} geometry = kinfo.config.geometry bounds = if DIM == 2 ntuple(i -> begin @@ -184,22 +220,23 @@ function set_periodic_connectivity(kinfo::KInfo{DIM}, periodic_dirs) where{DIM} (geometry[min_idx], geometry[max_idx]) # (xmin,xmax), (ymin,ymax), (zmin,zmax) end, 3) end - - connectivity_ps = brick( - Tuple(kinfo.config.trees_num), - periodic_dirs - ) + + connectivity_ps = brick(Tuple(kinfo.config.trees_num), periodic_dirs) vertices = unsafe_vertices(connectivity_ps) for i in eachindex(vertices) normalized_coords = vertices[i] - - vertices[i] = ntuple(j -> begin - if j <= DIM - normalized_coords[j] * (bounds[j][2] - bounds[j][1])/kinfo.config.trees_num[j] + bounds[j][1] - else - 0.0 - end - end, 3) + + vertices[i] = ntuple( + j -> begin + if j <= DIM + normalized_coords[j] * (bounds[j][2] - bounds[j][1])/kinfo.config.trees_num[j] + + bounds[j][1] + else + 0.0 + end + end, + 3, + ) end return connectivity_ps -end \ No newline at end of file +end diff --git a/src/Mesh/Mesh.jl b/src/Mesh/Mesh.jl index b3a1ffd..677af98 100644 --- a/src/Mesh/Mesh.jl +++ b/src/Mesh/Mesh.jl @@ -1,3 +1,3 @@ include("Connectivity.jl") include("Neighbor.jl") -export initialize_neighbor_data! \ No newline at end of file +export initialize_neighbor_data! diff --git a/src/Mesh/Neighbor.jl b/src/Mesh/Neighbor.jl index b2f7d96..85b7526 100644 --- a/src/Mesh/Neighbor.jl +++ b/src/Mesh/Neighbor.jl @@ -6,7 +6,7 @@ function access_neighbor( kinfo::KInfo{DIM,NDF}, ghost_wrap::Array{AbstractGhostPsData}, dir::Integer, -) where{DIM,NDF} +) where {DIM,NDF} neighbor_quads = sc_array_new(sizeof(Ptr{p4est_quadrant_t})) neighbor_encs = sc_array_new(sizeof(Cint)) neighbor_qid = sc_array_new(sizeof(Cint)) @@ -73,7 +73,7 @@ function access_neighbor( kinfo::KInfo{DIM,NDF}, ghost_wrap::Array{AbstractGhostPsData}, dir::Integer, -) where{DIM,NDF} +) where {DIM,NDF} neighbor_quads = sc_array_new(sizeof(Ptr{p8est_quadrant_t})) neighbor_encs = sc_array_new(sizeof(Cint)) neighbor_qid = sc_array_new(sizeof(Cint)) @@ -140,11 +140,16 @@ $(TYPEDSIGNATURES) """ function initialize_neighbor_data!(p4est::P_pxest_t, ka::KA) p_ka = pointer_from_objref(ka) - GC.@preserve ka AMR_volume_iterate(p4est;ghost = ka.kinfo.forest.ghost,user_data = p_ka) do ip,data,dp + GC.@preserve ka AMR_volume_iterate( + p4est; + ghost = ka.kinfo.forest.ghost, + user_data = p_ka, + ) do ip, data, dp ka = unsafe_pointer_to_objref(data) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - isa(ps_data,InsideSolidData) && return nothing - face_num = ip isa PointerWrapper{p4est_iter_volume_info_t} ? face_num_2d : face_num_3d + isa(ps_data, InsideSolidData) && return nothing + face_num = + ip isa PointerWrapper{p4est_iter_volume_info_t} ? face_num_2d : face_num_3d for i = 1:face_num ps_data.neighbor.data[i], ps_data.neighbor.state[i] = access_neighbor( pointer(ip.p4est), @@ -157,14 +162,15 @@ function initialize_neighbor_data!(p4est::P_pxest_t, ka::KA) corner_range = ip isa PointerWrapper{p4est_iter_volume_info_t} ? (4:7) : (6:25) if ps_data.bound_enc<0 for i in corner_range - nb,state = access_neighbor( + nb, state = access_neighbor( pointer(ip.p4est), local_quadid(ip), ka.kinfo, ka.kdata.ghost.ghost_wrap, i, ) - push!(ps_data.neighbor.data,nb);push!(ps_data.neighbor.state,state) + push!(ps_data.neighbor.data, nb); + push!(ps_data.neighbor.state, state) end end return nothing @@ -177,10 +183,14 @@ face_micro_nums: 1->4时记1,只需在state=-1时+0.25即可 function update_neighbor_kernel!(p4est::P_pxest_t, ka::KA) p_ka = pointer_from_objref(ka) MPI.Barrier(MPI.COMM_WORLD) - GC.@preserve ka AMR_volume_iterate(p4est;ghost = ka.kinfo.forest.ghost,user_data = p_ka) do ip,data,dp + GC.@preserve ka AMR_volume_iterate( + p4est; + ghost = ka.kinfo.forest.ghost, + user_data = p_ka, + ) do ip, data, dp ka = unsafe_pointer_to_objref(data) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - isa(ps_data,InsideSolidData) && return nothing + isa(ps_data, InsideSolidData) && return nothing is2d = ip isa PointerWrapper{p4est_iter_volume_info_t} face_num = is2d ? face_num_2d : face_num_3d extra_range = is2d ? (4:7) : (6:25) @@ -196,7 +206,7 @@ function update_neighbor_kernel!(p4est::P_pxest_t, ka::KA) end if length(ps_data.neighbor.data) > extra_thresh for i in extra_range - ps_data.neighbor.data[i+1],ps_data.neighbor.state[i+1] = access_neighbor( + ps_data.neighbor.data[i+1], ps_data.neighbor.state[i+1] = access_neighbor( pointer(ip.p4est), local_quadid(ip), ka.kinfo, @@ -206,14 +216,15 @@ function update_neighbor_kernel!(p4est::P_pxest_t, ka::KA) end elseif ps_data.bound_enc<0 for i in extra_range - nb,state = access_neighbor( + nb, state = access_neighbor( pointer(ip.p4est), local_quadid(ip), ka.kinfo, ka.kdata.ghost.ghost_wrap, i, ) - push!(ps_data.neighbor.data,nb);push!(ps_data.neighbor.state,state) + push!(ps_data.neighbor.data, nb); + push!(ps_data.neighbor.state, state) end end return nothing @@ -225,7 +236,7 @@ function update_neighbor!(p4est::Ptr{p4est_t}, ka::KA) p4est_mesh_destroy(kinfo.forest.mesh) end kinfo.forest.mesh = - p4est_mesh_new_ext(p4est, kinfo.forest.ghost, 1, 1, P4EST_CONNECT_FULL) + p4est_mesh_new_ext(p4est, kinfo.forest.ghost, 1, 1, P4EST_CONNECT_FULL) update_neighbor_kernel!(p4est, ka) end function update_neighbor!(p4est::Ptr{p8est_t}, ka::KA) diff --git a/src/P4est/P4est.jl b/src/P4est/P4est.jl index 3446f97..02d0a32 100644 --- a/src/P4est/P4est.jl +++ b/src/P4est/P4est.jl @@ -1,2 +1,2 @@ include("P4est_wrap.jl") -export AMR_ghost_new, AMR_mesh_new \ No newline at end of file +export AMR_ghost_new, AMR_mesh_new diff --git a/src/P4est/P4est_wrap.jl b/src/P4est/P4est_wrap.jl index 3598362..87979f5 100644 --- a/src/P4est/P4est_wrap.jl +++ b/src/P4est/P4est_wrap.jl @@ -44,7 +44,11 @@ mutable struct AMR_weight_context user_pointer::Ptr{Cvoid} end -function _amr_weight_cb_p4est(p4est::Ptr{p4est_t}, which_tree::p4est_topidx_t, quadrant::Ptr{p4est_quadrant_t})::Cint +function _amr_weight_cb_p4est( + p4est::Ptr{p4est_t}, + which_tree::p4est_topidx_t, + quadrant::Ptr{p4est_quadrant_t}, +)::Cint fp = PointerWrapper(p4est) ctx = unsafe_pointer_to_objref(pointer(fp.user_pointer))::AMR_weight_context GC.@preserve ctx begin @@ -54,7 +58,11 @@ function _amr_weight_cb_p4est(p4est::Ptr{p4est_t}, which_tree::p4est_topidx_t, q end return w end -function _amr_weight_cb_p8est(p4est::Ptr{p8est_t}, which_tree::p4est_topidx_t, quadrant::Ptr{p8est_quadrant_t})::Cint +function _amr_weight_cb_p8est( + p4est::Ptr{p8est_t}, + which_tree::p4est_topidx_t, + quadrant::Ptr{p8est_quadrant_t}, +)::Cint fp = PointerWrapper(p4est) ctx = unsafe_pointer_to_objref(pointer(fp.user_pointer))::AMR_weight_context GC.@preserve ctx begin @@ -64,7 +72,11 @@ function _amr_weight_cb_p8est(p4est::Ptr{p8est_t}, which_tree::p4est_topidx_t, q end return w end -function _amr_init_cb_p4est(p4est::Ptr{p4est_t}, which_tree::p4est_topidx_t, quadrant::Ptr{p4est_quadrant_t})::Cvoid +function _amr_init_cb_p4est( + p4est::Ptr{p4est_t}, + which_tree::p4est_topidx_t, + quadrant::Ptr{p4est_quadrant_t}, +)::Cvoid fp = PointerWrapper(p4est) ctx = unsafe_pointer_to_objref(pointer(fp.user_pointer))::AMR_init_context GC.@preserve ctx begin @@ -74,7 +86,11 @@ function _amr_init_cb_p4est(p4est::Ptr{p4est_t}, which_tree::p4est_topidx_t, qua end return nothing end -function _amr_init_cb_p8est(p4est::Ptr{p8est_t}, which_tree::p4est_topidx_t, quadrant::Ptr{p8est_quadrant_t})::Cvoid +function _amr_init_cb_p8est( + p4est::Ptr{p8est_t}, + which_tree::p4est_topidx_t, + quadrant::Ptr{p8est_quadrant_t}, +)::Cvoid fp = PointerWrapper(p4est) ctx = unsafe_pointer_to_objref(pointer(fp.user_pointer))::AMR_init_context GC.@preserve ctx begin @@ -96,7 +112,10 @@ mutable struct AMR_iterate_context user_data::Ptr{Cvoid} end -function _amr_volume_iter_cb_p4est(info::Ptr{p4est_iter_volume_info}, data::Ptr{Nothing})::Cvoid +function _amr_volume_iter_cb_p4est( + info::Ptr{p4est_iter_volume_info}, + data::Ptr{Nothing}, +)::Cvoid GC.@preserve info begin ctx = unsafe_pointer_to_objref(data)::AMR_iterate_context ip = PointerWrapper(info) @@ -105,7 +124,10 @@ function _amr_volume_iter_cb_p4est(info::Ptr{p4est_iter_volume_info}, data::Ptr{ end return nothing end -function _amr_volume_iter_cb_p8est(info::Ptr{p8est_iter_volume_info}, data::Ptr{Nothing})::Cvoid +function _amr_volume_iter_cb_p8est( + info::Ptr{p8est_iter_volume_info}, + data::Ptr{Nothing}, +)::Cvoid GC.@preserve info begin ctx = unsafe_pointer_to_objref(data)::AMR_iterate_context ip = PointerWrapper(info) @@ -114,7 +136,10 @@ function _amr_volume_iter_cb_p8est(info::Ptr{p8est_iter_volume_info}, data::Ptr{ end return nothing end -function _amr_corner_iter_cb_p4est(info::Ptr{p4est_iter_corner_info}, data::Ptr{Nothing})::Cvoid +function _amr_corner_iter_cb_p4est( + info::Ptr{p4est_iter_corner_info}, + data::Ptr{Nothing}, +)::Cvoid GC.@preserve info begin ctx = unsafe_pointer_to_objref(data)::AMR_iterate_context ip = PointerWrapper(info) @@ -185,37 +210,45 @@ function quad_to_cell( qp.z[] + halflength, mid, ) - ds = 2. * (mid - quad) + ds = 2.0 * (mid - quad) end (ds, mid) end -function iPointerWrapper(p::Ptr{T},i::Integer) where{T} +function iPointerWrapper(p::Ptr{T}, i::Integer) where {T} return PointerWrapper(p + sizeof(T) * i) end -function iPointerWrapper(pw::PointerWrapper{T},i::Integer) where{T} +function iPointerWrapper(pw::PointerWrapper{T}, i::Integer) where {T} return PointerWrapper(pointer(pw)+i*sizeof(T)) end -function iPointerWrapper(p::Ptr{sc_array_t},::Type{T},i::Integer) where{T} - return PointerWrapper(T,pointer(PointerWrapper(p).array)+i*sizeof(T)) +function iPointerWrapper(p::Ptr{sc_array_t}, ::Type{T}, i::Integer) where {T} + return PointerWrapper(T, pointer(PointerWrapper(p).array)+i*sizeof(T)) end -function iPointerWrapper(p::Ptr{sc_array_t},::Type{Ptr{T}},i::Integer) where{T} # to avoid the dereference of the Pointer-type +function iPointerWrapper(p::Ptr{sc_array_t}, ::Type{Ptr{T}}, i::Integer) where {T} # to avoid the dereference of the Pointer-type return PointerWrapper(Ptr{Ptr{T}}(pointer(PointerWrapper(p).array)+i*sizeof(Ptr{T}))) end -function iPointerWrapper(pw::PointerWrapper{sc_array_t},::Type{T},i::Integer) where{T} - return PointerWrapper(T,pointer(pw.array)+i*sizeof(T)) +function iPointerWrapper(pw::PointerWrapper{sc_array_t}, ::Type{T}, i::Integer) where {T} + return PointerWrapper(T, pointer(pw.array)+i*sizeof(T)) end -function iPointerWrapper(pw::PointerWrapper{sc_array_t},::Type{Ptr{T}},i::Integer) where{T} +function iPointerWrapper( + pw::PointerWrapper{sc_array_t}, + ::Type{Ptr{T}}, + i::Integer, +) where {T} return PointerWrapper(Ptr{Ptr{T}}(pointer(pw.array)+i*sizeof(Ptr{T}))) end -function iPointerWrapper(pw::PointerWrapper{NTuple{N,T}},::Type{T},i::Integer) where{N,T} - return PointerWrapper(T,pointer(pw)+i*sizeof(T)) +function iPointerWrapper(pw::PointerWrapper{NTuple{N,T}}, ::Type{T}, i::Integer) where {N,T} + return PointerWrapper(T, pointer(pw)+i*sizeof(T)) end -function iPointerWrapper(pw::PointerWrapper{NTuple{N,Ptr{T}}},::Type{Ptr{T}},i::Integer) where{N,T} +function iPointerWrapper( + pw::PointerWrapper{NTuple{N,Ptr{T}}}, + ::Type{Ptr{T}}, + i::Integer, +) where {N,T} return PointerWrapper(Ptr{Ptr{T}}(pointer(pw)+i*sizeof(Ptr{T}))) end -function local_quadid(p4est::PointerWrapper{p4est_t},treeid::Integer,quadid::Integer) +function local_quadid(p4est::PointerWrapper{p4est_t}, treeid::Integer, quadid::Integer) tp = iPointerWrapper(p4est.trees, p4est_tree_t, treeid) return tp.quadrants_offset[] + quadid end @@ -223,7 +256,10 @@ function local_quadid(ip::PointerWrapper{p4est_iter_volume_info_t}) tp = iPointerWrapper(ip.p4est.trees, p4est_tree_t, ip.treeid[]) return tp.quadrants_offset[] + ip.quadid[] end -function local_quadid(ip::PointerWrapper{p4est_iter_corner_info_t},side::PointerWrapper{p4est_iter_corner_side_t}) +function local_quadid( + ip::PointerWrapper{p4est_iter_corner_info_t}, + side::PointerWrapper{p4est_iter_corner_side_t}, +) tp = iPointerWrapper(ip.p4est.trees, p4est_tree_t, side.treeid[]) return tp.quadrants_offset[] + side.quadid[] end @@ -231,16 +267,19 @@ function local_quadid(ip::PointerWrapper{p8est_iter_volume_info_t}) tp = iPointerWrapper(ip.p4est.trees, p8est_tree_t, ip.treeid[]) return tp.quadrants_offset[] + ip.quadid[] end -function local_quadid(ip::PointerWrapper{p8est_iter_corner_info_t},side::PointerWrapper{p8est_iter_corner_side_t}) +function local_quadid( + ip::PointerWrapper{p8est_iter_corner_info_t}, + side::PointerWrapper{p8est_iter_corner_side_t}, +) tp = iPointerWrapper(ip.p4est.trees, p4est_tree_t, side.treeid[]) return tp.quadrants_offset[] + side.quadid[] end function global_quadid(ip::PW_pxest_iter_volume_info_t) gfq = unsafe_wrap( - Vector{Int}, - pointer(ip.p4est.global_first_quadrant), - MPI.Comm_size(MPI.COMM_WORLD) + 1, - ) + Vector{Int}, + pointer(ip.p4est.global_first_quadrant), + MPI.Comm_size(MPI.COMM_WORLD) + 1, + ) return local_quadid(ip) + gfq[MPI.Comm_rank(MPI.COMM_WORLD)+1] end @@ -265,7 +304,11 @@ function AMR_4est_new( min_level, uniform, sizeof(T), - @cfunction(_amr_init_cb_p4est, Cvoid, (Ptr{p4est_t}, p4est_topidx_t, Ptr{p4est_quadrant_t})), + @cfunction( + _amr_init_cb_p4est, + Cvoid, + (Ptr{p4est_t}, p4est_topidx_t, Ptr{p4est_quadrant_t}) + ), pointer_from_objref(ctx), ) PointerWrapper(p4est).user_pointer = orig # restore original user_pointer @@ -292,7 +335,11 @@ function AMR_4est_new( min_level, uniform, sizeof(T), - @cfunction(_amr_init_cb_p8est, Cvoid, (Ptr{p8est_t}, p4est_topidx_t, Ptr{p8est_quadrant_t})), + @cfunction( + _amr_init_cb_p8est, + Cvoid, + (Ptr{p8est_t}, p4est_topidx_t, Ptr{p8est_quadrant_t}) + ), pointer_from_objref(ctx), ) PointerWrapper(p8est).user_pointer = orig # restore original user_pointer @@ -324,7 +371,11 @@ function AMR_4est_new( 0, 1, sizeof(T), - @cfunction(_amr_init_cb_p4est, Cvoid, (Ptr{p4est_t}, p4est_topidx_t, Ptr{p4est_quadrant_t})), + @cfunction( + _amr_init_cb_p4est, + Cvoid, + (Ptr{p4est_t}, p4est_topidx_t, Ptr{p4est_quadrant_t}) + ), pointer_from_objref(ctx), ) PointerWrapper(p4est).user_pointer = orig # restore original user_pointer @@ -348,7 +399,11 @@ function AMR_4est_new( 0, 1, sizeof(T), - @cfunction(_amr_init_cb_p8est, Cvoid, (Ptr{p8est_t}, p4est_topidx_t, Ptr{p8est_quadrant_t})), + @cfunction( + _amr_init_cb_p8est, + Cvoid, + (Ptr{p8est_t}, p4est_topidx_t, Ptr{p8est_quadrant_t}) + ), pointer_from_objref(ctx), ) PointerWrapper(p8est).user_pointer = orig # restore original user_pointer @@ -407,7 +462,11 @@ function AMR_4est_new( 0, 1, sizeof(T), - @cfunction(_amr_init_cb_p4est, Cvoid, (Ptr{p4est_t}, p4est_topidx_t, Ptr{p4est_quadrant_t})), + @cfunction( + _amr_init_cb_p4est, + Cvoid, + (Ptr{p4est_t}, p4est_topidx_t, Ptr{p4est_quadrant_t}) + ), pointer_from_objref(ctx), ) PointerWrapper(p4est).user_pointer = orig # restore original user_pointer (C_NULL) @@ -430,7 +489,11 @@ function AMR_4est_new( 0, 1, sizeof(T), - @cfunction(_amr_init_cb_p8est, Cvoid, (Ptr{p8est_t}, p4est_topidx_t, Ptr{p8est_quadrant_t})), + @cfunction( + _amr_init_cb_p8est, + Cvoid, + (Ptr{p8est_t}, p4est_topidx_t, Ptr{p8est_quadrant_t}) + ), pointer_from_objref(ctx), ) PointerWrapper(p8est).user_pointer = orig # restore original user_pointer (C_NULL) @@ -463,35 +526,53 @@ function AMR_ghost_new(p4est::Ptr{p8est_t}) GC.@preserve p4est p8est_ghost_new(p4est, P8EST_CONNECT_FULL) end -function AMR_partition(p4est::Ptr{p4est_t},weight_fn::T=C_NULL) where{T<:Union{Ptr{Nothing},Base.CFunction}} +function AMR_partition( + p4est::Ptr{p4est_t}, + weight_fn::T = C_NULL, +) where {T<:Union{Ptr{Nothing},Base.CFunction}} p4est_partition(p4est, 0, weight_fn) end -function AMR_partition(weight_fn::Function,p4est::Ptr{p4est_t}) +function AMR_partition(weight_fn::Function, p4est::Ptr{p4est_t}) fp = PointerWrapper(p4est) orig = Ptr{Cvoid}(pointer(fp.user_pointer)) # original user_pointer (e.g. kinfo/ka) ctx = AMR_weight_context(weight_fn, orig) GC.@preserve weight_fn ctx begin fp.user_pointer = pointer_from_objref(ctx) try - AMR_partition(p4est, - @cfunction(_amr_weight_cb_p4est,Cint,(Ptr{p4est_t},p4est_topidx_t,Ptr{p4est_quadrant_t}))) + AMR_partition( + p4est, + @cfunction( + _amr_weight_cb_p4est, + Cint, + (Ptr{p4est_t}, p4est_topidx_t, Ptr{p4est_quadrant_t}) + ) + ) finally fp.user_pointer = orig # restore original user_pointer end end end -function AMR_partition(p4est::Ptr{p8est_t},weight_fn::T=C_NULL) where{T<:Union{Ptr{Nothing},Base.CFunction}} +function AMR_partition( + p4est::Ptr{p8est_t}, + weight_fn::T = C_NULL, +) where {T<:Union{Ptr{Nothing},Base.CFunction}} p8est_partition(p4est, 0, weight_fn) end -function AMR_partition(weight_fn::Function,p4est::Ptr{p8est_t}) +function AMR_partition(weight_fn::Function, p4est::Ptr{p8est_t}) fp = PointerWrapper(p4est) orig = Ptr{Cvoid}(pointer(fp.user_pointer)) # original user_pointer (e.g. kinfo/ka) ctx = AMR_weight_context(weight_fn, orig) GC.@preserve weight_fn ctx begin fp.user_pointer = pointer_from_objref(ctx) try - AMR_partition(p4est, - @cfunction(_amr_weight_cb_p8est,Cint,(Ptr{p8est_t},p4est_topidx_t,Ptr{p8est_quadrant_t}))) + AMR_partition( + p4est, + @cfunction( + _amr_weight_cb_p8est, + Cint, + (Ptr{p8est_t}, p4est_topidx_t, Ptr{p8est_quadrant_t}) + ) + ) finally fp.user_pointer = orig # restore original user_pointer end @@ -501,14 +582,14 @@ end """ $(TYPEDSIGNATURES) """ -function AMR_mesh_new(p4est::Ptr{p4est_t},ghost::Ptr{p4est_ghost_t}) - GC.@preserve p4est ghost p4est_mesh_new_ext(p4est,ghost,1,1,P4EST_CONNECT_FULL) +function AMR_mesh_new(p4est::Ptr{p4est_t}, ghost::Ptr{p4est_ghost_t}) + GC.@preserve p4est ghost p4est_mesh_new_ext(p4est, ghost, 1, 1, P4EST_CONNECT_FULL) end """ $(TYPEDSIGNATURES) """ -function AMR_mesh_new(p4est::Ptr{p8est_t},ghost::Ptr{p8est_ghost_t}) - GC.@preserve p4est ghost p8est_mesh_new_ext(p4est,ghost,1,1,P8EST_CONNECT_FULL) +function AMR_mesh_new(p4est::Ptr{p8est_t}, ghost::Ptr{p8est_ghost_t}) + GC.@preserve p4est ghost p8est_mesh_new_ext(p4est, ghost, 1, 1, P8EST_CONNECT_FULL) end @@ -528,30 +609,55 @@ function unsafe_wrap_sc(::Type{T}, sc_array_pw::PointerWrapper{sc_array}) where return unsafe_wrap(Vector{T}, Ptr{T}(pointer(array)), elem_count) end -function AMR_volume_iterate(f::Function,forest::Ptr{p4est_t};ghost=C_NULL,user_data=C_NULL,data_type = P4estPsData) +function AMR_volume_iterate( + f::Function, + forest::Ptr{p4est_t}; + ghost = C_NULL, + user_data = C_NULL, + data_type = P4estPsData, +) ctx = AMR_iterate_context(f, data_type, Ptr{Cvoid}(user_data)) GC.@preserve f ctx forest ghost p4est_iterate( forest, ghost, pointer_from_objref(ctx), - @cfunction(_amr_volume_iter_cb_p4est,Cvoid, (Ptr{p4est_iter_volume_info}, Ptr{Nothing})), + @cfunction( + _amr_volume_iter_cb_p4est, + Cvoid, + (Ptr{p4est_iter_volume_info}, Ptr{Nothing}) + ), C_NULL, C_NULL, ) end -function AMR_volume_iterate(f::Function,forest::Ptr{p8est_t};ghost=C_NULL,user_data=C_NULL,data_type = P4estPsData) +function AMR_volume_iterate( + f::Function, + forest::Ptr{p8est_t}; + ghost = C_NULL, + user_data = C_NULL, + data_type = P4estPsData, +) ctx = AMR_iterate_context(f, data_type, Ptr{Cvoid}(user_data)) GC.@preserve f ctx forest ghost p8est_iterate( forest, ghost, pointer_from_objref(ctx), - @cfunction(_amr_volume_iter_cb_p8est,Cvoid, (Ptr{p8est_iter_volume_info}, Ptr{Nothing})), + @cfunction( + _amr_volume_iter_cb_p8est, + Cvoid, + (Ptr{p8est_iter_volume_info}, Ptr{Nothing}) + ), C_NULL, C_NULL, C_NULL, ) end -function AMR_corner_iterate(f::Function,forest::Ptr{p4est_t};ghost=C_NULL,user_data=C_NULL) +function AMR_corner_iterate( + f::Function, + forest::Ptr{p4est_t}; + ghost = C_NULL, + user_data = C_NULL, +) ctx = AMR_iterate_context(f, Nothing, Ptr{Cvoid}(user_data)) GC.@preserve f ctx forest ghost p4est_iterate( forest, @@ -559,29 +665,51 @@ function AMR_corner_iterate(f::Function,forest::Ptr{p4est_t};ghost=C_NULL,user_d pointer_from_objref(ctx), C_NULL, C_NULL, - @cfunction(_amr_corner_iter_cb_p4est,Cvoid, (Ptr{p4est_iter_corner_info}, Ptr{Nothing})), + @cfunction( + _amr_corner_iter_cb_p4est, + Cvoid, + (Ptr{p4est_iter_corner_info}, Ptr{Nothing}) + ), ) end -function AMR_face_iterate(f::Function,forest::Ptr{p4est_t};ghost=C_NULL,user_data=C_NULL) +function AMR_face_iterate( + f::Function, + forest::Ptr{p4est_t}; + ghost = C_NULL, + user_data = C_NULL, +) ctx = AMR_iterate_context(f, Nothing, Ptr{Cvoid}(user_data)) GC.@preserve f ctx forest ghost p4est_iterate( forest, ghost, pointer_from_objref(ctx), C_NULL, - @cfunction(_amr_face_iter_cb_p4est,Cvoid, (Ptr{p4est_iter_face_info}, Ptr{Nothing})), + @cfunction( + _amr_face_iter_cb_p4est, + Cvoid, + (Ptr{p4est_iter_face_info}, Ptr{Nothing}) + ), C_NULL, ) end -function AMR_face_iterate(f::Function,forest::Ptr{p8est_t};ghost=C_NULL,user_data=C_NULL) +function AMR_face_iterate( + f::Function, + forest::Ptr{p8est_t}; + ghost = C_NULL, + user_data = C_NULL, +) ctx = AMR_iterate_context(f, Nothing, Ptr{Cvoid}(user_data)) GC.@preserve f ctx forest ghost p8est_iterate( # volume, face, edge, corner forest, ghost, pointer_from_objref(ctx), C_NULL, - @cfunction(_amr_face_iter_cb_p8est,Cvoid, (Ptr{p8est_iter_face_info}, Ptr{Nothing})), + @cfunction( + _amr_face_iter_cb_p8est, + Cvoid, + (Ptr{p8est_iter_face_info}, Ptr{Nothing}) + ), C_NULL, C_NULL, ) -end \ No newline at end of file +end diff --git a/src/Parallel/Ghost.jl b/src/Parallel/Ghost.jl index 658759a..70294f0 100644 --- a/src/Parallel/Ghost.jl +++ b/src/Parallel/Ghost.jl @@ -1,7 +1,7 @@ -size_Ghost_Data(vs_num,DIM,NDF) = 3 * DIM + 4 + NDF * vs_num -size_Ghost_Slope(vs_num,DIM,NDF) = vs_num * DIM * NDF + DIM*(DIM+2) +size_Ghost_Data(vs_num, DIM, NDF) = 3 * DIM + 4 + NDF * vs_num +size_Ghost_Slope(vs_num, DIM, NDF) = vs_num * DIM * NDF + DIM*(DIM+2) size_Ghost_SW(DIM) = DIM * (DIM + 2) -size_Ghost_VS_Structure(vs_num,DIM) = vs_num * (DIM + 2) +size_Ghost_VS_Structure(vs_num, DIM) = vs_num * (DIM + 2) """ $(TYPEDSIGNATURES) @@ -10,16 +10,24 @@ Get the globally largest number of the velocity cells among all local and ghost function get_vs_num(forest::P_pxest_t, ghost::P_pxest_ghost_t) get_vs_num(PointerWrapper(forest), PointerWrapper(ghost)) end -function pw_mirror_quadrant(pp::PointerWrapper{p4est_t},gp::PointerWrapper{p4est_ghost_t},i::Integer) - pm = iPointerWrapper(gp.mirrors, p4est_quadrant_t, i - 1) - pt = iPointerWrapper(pp.trees, p4est_tree_t, pm.p.piggy3.which_tree[]) - pq = iPointerWrapper( - pt.quadrants, - p4est_quadrant_t, - pm.p.piggy3.local_num[] - pt.quadrants_offset[], - ) +function pw_mirror_quadrant( + pp::PointerWrapper{p4est_t}, + gp::PointerWrapper{p4est_ghost_t}, + i::Integer, +) + pm = iPointerWrapper(gp.mirrors, p4est_quadrant_t, i - 1) + pt = iPointerWrapper(pp.trees, p4est_tree_t, pm.p.piggy3.which_tree[]) + pq = iPointerWrapper( + pt.quadrants, + p4est_quadrant_t, + pm.p.piggy3.local_num[] - pt.quadrants_offset[], + ) end -function pw_mirror_quadrant(pp::PointerWrapper{p8est_t},gp::PointerWrapper{p8est_ghost_t},i::Integer) +function pw_mirror_quadrant( + pp::PointerWrapper{p8est_t}, + gp::PointerWrapper{p8est_ghost_t}, + i::Integer, +) pm = iPointerWrapper(gp.mirrors, p8est_quadrant_t, i - 1) pt = iPointerWrapper(pp.trees, p8est_tree_t, pm.p.piggy3.which_tree[]) pq = iPointerWrapper( @@ -31,29 +39,41 @@ end function get_vs_num(pp::PW_pxest_t, gp::PW_pxest_ghost_t) vs_num = 0 for i = 1:gp.mirrors.elem_count[] - pq = pw_mirror_quadrant(pp,gp,i) + pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - isa(ps_data,InsideSolidData)&&continue + isa(ps_data, InsideSolidData)&&continue vs_num = max(vs_num, ps_data.vs_data.vs_num) end vs_num = MPI.Allreduce(vs_num, MPI.MAX, MPI.COMM_WORLD) end -function get_mirror_data_inner!(ps_data::PsData{DIM,NDF}, vs_temp::AbstractVector) where{DIM,NDF} +function get_mirror_data_inner!( + ps_data::PsData{DIM,NDF}, + vs_temp::AbstractVector, +) where {DIM,NDF} vs_data = ps_data.vs_data vs_num = vs_data.vs_num - vs_temp[1:NDF*vs_num] .= reshape(vs_data.df, vs_num * NDF) + vs_temp[1:(NDF*vs_num)] .= reshape(vs_data.df, vs_num * NDF) end -function get_mirror_slope_inner!(ps_data::PsData{DIM,NDF}, vs_temp::AbstractVector) where{DIM,NDF} +function get_mirror_slope_inner!( + ps_data::PsData{DIM,NDF}, + vs_temp::AbstractVector, +) where {DIM,NDF} vs_data = ps_data.vs_data vs_num = size(vs_data.weight, 1) vs_temp[1:(vs_num*NDF*DIM)] .= reshape(vs_data.sdf, vs_num * NDF * DIM) - vs_temp[vs_num*NDF*DIM+1:vs_num*NDF*DIM+DIM*(DIM+2)] .= reshape(ps_data.sw, DIM*(DIM+2)) + vs_temp[(vs_num*NDF*DIM+1):(vs_num*NDF*DIM+DIM*(DIM+2))] .= + reshape(ps_data.sw, DIM*(DIM+2)) end function get_mirror_slope_inner!(::InsideSolidData, vs_temp::AbstractVector) vs_temp[1] = EPS end -function get_mirror_structure_inner!(ps_data::PsData{DIM}, weight_temp, level_temp, midpoint_temp) where{DIM} +function get_mirror_structure_inner!( + ps_data::PsData{DIM}, + weight_temp, + level_temp, + midpoint_temp, +) where {DIM} vs_data = ps_data.vs_data vs_num = vs_data.vs_num weight_temp[1:vs_num] .= vs_data.weight @@ -62,7 +82,12 @@ function get_mirror_structure_inner!(ps_data::PsData{DIM}, weight_temp, level_te end function ghost_data_alloc(N::Int, ghost::P_pxest_ghost_t) - Ptr{Float64}(sc_malloc(P4est.package_id(), sizeof(Float64) * N * PointerWrapper(ghost).ghosts.elem_count[])) + Ptr{Float64}( + sc_malloc( + P4est.package_id(), + sizeof(Float64) * N * PointerWrapper(ghost).ghosts.elem_count[], + ), + ) end # Julia-managed flat ghost receive buffer (replaces sc_malloc'd Ptr version). @@ -125,22 +150,32 @@ Extract the p4est ghost communication topology arrays from the ghost pointer. Returns `(mpisize, proc_offsets, mirror_proc_offsets, mirror_proc_mirrors)`. Julia indexing convention (1-based): -- Ghosts from rank `r` occupy ghost indices `proc_offsets[r+1]+1 : proc_offsets[r+2]`. -- Mirrors going to rank `r` are at mirror_proc_mirrors indices - `mirror_proc_offsets[r+1]+1 : mirror_proc_offsets[r+2]`, where each entry is a - 0-based mirror index (add 1 for Julia indexing). + + - Ghosts from rank `r` occupy ghost indices `proc_offsets[r+1]+1 : proc_offsets[r+2]`. + - Mirrors going to rank `r` are at mirror_proc_mirrors indices + `mirror_proc_offsets[r+1]+1 : mirror_proc_offsets[r+2]`, where each entry is a + 0-based mirror index (add 1 for Julia indexing). """ function _ghost_comm_arrays(ghost::P_pxest_ghost_t) gp = PointerWrapper(ghost) mpisize = Int(gp.mpisize[]) - proc_offsets = Base.unsafe_wrap( - Vector{Int32}, pointer(gp.proc_offsets), mpisize + 1, own = false) + proc_offsets = + Base.unsafe_wrap(Vector{Int32}, pointer(gp.proc_offsets), mpisize + 1, own = false) mpo = Base.unsafe_wrap( - Vector{Int32}, pointer(gp.mirror_proc_offsets), mpisize + 1, own = false) + Vector{Int32}, + pointer(gp.mirror_proc_offsets), + mpisize + 1, + own = false, + ) n_mpm = Int(mpo[end]) - mpm = n_mpm > 0 ? - Base.unsafe_wrap(Vector{Int32}, pointer(gp.mirror_proc_mirrors), n_mpm, own = false) : - Int32[] + mpm = + n_mpm > 0 ? + Base.unsafe_wrap( + Vector{Int32}, + pointer(gp.mirror_proc_mirrors), + n_mpm, + own = false, + ) : Int32[] return mpisize, proc_offsets, mpo, mpm end @@ -151,19 +186,20 @@ fixed-size (`N = 1`) call to `p4est_ghost_exchange_custom`. Also updates `kinfo.status.max_vs_num` via `MPI.Allreduce`. Returns `(ghost_vsnums, mirror_vsnums)`: -- `ghost_vsnums[i]` — `vs_num` of ghost quadrant `i` (0 for `InsideSolidData`). -- `mirror_vsnums[i]` — `vs_num` of mirror quadrant `i` (computed locally). + + - `ghost_vsnums[i]` — `vs_num` of ghost quadrant `i` (0 for `InsideSolidData`). + - `mirror_vsnums[i]` — `vs_num` of mirror quadrant `i` (computed locally). """ function exchange_ghost_vsnums(p4est, kinfo::KInfo{DIM,NDF}) where {DIM,NDF} GC.@preserve p4est kinfo begin gp = PointerWrapper(kinfo.forest.ghost) pp = PointerWrapper(p4est) n_mirrors = Int(gp.mirrors.elem_count[]) - n_ghosts = Int(gp.ghosts.elem_count[]) + n_ghosts = Int(gp.ghosts.elem_count[]) mirror_vsnums = Vector{Int}(undef, n_mirrors) size_ptrs = Array{Ptr{Float64}}(undef, n_mirrors) - for i in 1:n_mirrors + for i = 1:n_mirrors pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) @@ -177,7 +213,7 @@ function exchange_ghost_vsnums(p4est, kinfo::KInfo{DIM,NDF}) where {DIM,NDF} ghost_raw = amr_exchange(p4est, kinfo.forest.ghost, size_ptrs, 1) ghost_vsnums = Vector{Int}(undef, n_ghosts) - for i in 1:n_ghosts + for i = 1:n_ghosts p = ghost_data_ptr(1, ghost_raw, i - 1) ghost_vsnums[i] = Int(round(Base.unsafe_load(p))) end @@ -187,7 +223,10 @@ function exchange_ghost_vsnums(p4est, kinfo::KInfo{DIM,NDF}) where {DIM,NDF} # kinfo.status.max_vs_num = Int(MPI.Allreduce(max(local_max, ghost_max), max, MPI.COMM_WORLD)) id = P4est.package_id() - for p in size_ptrs; sc_free(id, p); end + for p in size_ptrs + ; + sc_free(id, p); + end sc_free(id, ghost_raw) end return ghost_vsnums, mirror_vsnums @@ -214,11 +253,11 @@ function _mpi_exchange_varsize!( myrank = MPI.Comm_rank(MPI.COMM_WORLD) comm = MPI.COMM_WORLD - reqs = Vector{MPI.Request}(undef, 0) - send_bufs = Vector{Vector{Float64}}(undef, 0) - recv_infos = Vector{Tuple{Any, Vector{Int}, Bool}}(undef, 0) + reqs = Vector{MPI.Request}(undef, 0) + send_bufs = Vector{Vector{Float64}}(undef, 0) + recv_infos = Vector{Tuple{Any,Vector{Int},Bool}}(undef, 0) - for r in 0:mpisize-1 + for r = 0:(mpisize-1) r == myrank && continue ghost_ids = _active_ghost_ids_native(ghost_elem_sizes, proc_offsets, r) isempty(ghost_ids) && continue @@ -229,7 +268,7 @@ function _mpi_exchange_varsize!( recv_elems == 0 && continue if _is_compact_recv_layout(ghost_ids, ghost_offsets, ghost_elem_sizes) first_offset = ghost_offsets[first(ghost_ids)] - recv_buf = @view ghost_buffer[first_offset+1:first_offset+recv_elems] + recv_buf = @view ghost_buffer[(first_offset+1):(first_offset+recv_elems)] push!(recv_infos, (recv_buf, Int[], false)) else recv_buf = Vector{Float64}(undef, recv_elems) @@ -239,20 +278,20 @@ function _mpi_exchange_varsize!( end n_recvs = length(recv_infos) - for r in 0:mpisize-1 + for r = 0:(mpisize-1) r == myrank && continue mp_start = Int(mirror_proc_offsets[r+1]) + 1 - mp_end = Int(mirror_proc_offsets[r+2]) + mp_end = Int(mirror_proc_offsets[r+2]) mp_start > mp_end && continue send_elems = 0 - for k in mp_start:mp_end + for k = mp_start:mp_end m_idx = Int(mirror_proc_mirrors[k]) + 1 send_elems += mirror_elem_sizes[m_idx] end send_elems == 0 && continue send_buf = Vector{Float64}(undef, send_elems) off = 0 - for k in mp_start:mp_end + for k = mp_start:mp_end m_idx = Int(mirror_proc_mirrors[k]) + 1 sz = mirror_elem_sizes[m_idx] sz == 0 && continue @@ -266,12 +305,17 @@ function _mpi_exchange_varsize!( isempty(reqs) && return nothing statuses = GC.@preserve send_bufs recv_infos MPI.Waitall(reqs, MPI.Status) - @inbounds for recv_id in 1:n_recvs + @inbounds for recv_id = 1:n_recvs recv_buf, ghost_ids, needs_scatter = recv_infos[recv_id] recv_count = MPI.Get_count(statuses[recv_id], Float64) recv_count == length(recv_buf) || error( - "Direct MPI ghost exchange size mismatch on rank ", myrank, - ": expected ", length(recv_buf), " Float64 values, received ", recv_count) + "Direct MPI ghost exchange size mismatch on rank ", + myrank, + ": expected ", + length(recv_buf), + " Float64 values, received ", + recv_count, + ) needs_scatter || continue off = 0 for i in ghost_ids @@ -298,24 +342,34 @@ function _mpi_exchange_varsize_sparse!( mirror_elem_sizes::Vector{Int}, tag::Int, ) - _mpi_exchange_varsize!(ghost, ghost_buffer, ghost_offsets, ghost_elem_sizes, - mirror_data_bufs, mirror_elem_sizes, tag) + _mpi_exchange_varsize!( + ghost, + ghost_buffer, + ghost_offsets, + ghost_elem_sizes, + mirror_data_bufs, + mirror_elem_sizes, + tag, + ) end function _active_ghost_ids_native(ghost_elem_sizes::Vector{Int}, proc_offsets, r::Integer) g_start = Int(proc_offsets[r+1]) + 1 - g_end = Int(proc_offsets[r+2]) + g_end = Int(proc_offsets[r+2]) ids = Int[] g_start > g_end && return ids - @inbounds for i in g_start:g_end + @inbounds for i = g_start:g_end ghost_elem_sizes[i] == 0 && continue push!(ids, i) end return ids end -function _is_compact_recv_layout(ids::Vector{Int}, ghost_offsets::Vector{Int}, - ghost_elem_sizes::Vector{Int}) +function _is_compact_recv_layout( + ids::Vector{Int}, + ghost_offsets::Vector{Int}, + ghost_elem_sizes::Vector{Int}, +) isempty(ids) && return true expected = ghost_offsets[first(ids)] @inbounds for i in ids @@ -350,12 +404,12 @@ function _native_exchange_varsize( n_ghosts = length(ghost_elem_sizes) ghost_offsets = Vector{Int}(undef, n_ghosts) total_elems = 0 - @inbounds for i in 1:n_ghosts + @inbounds for i = 1:n_ghosts ghost_offsets[i] = total_elems total_elems += ghost_elem_sizes[i] end ghost_buffer = ghost_vec_alloc(total_elems) - @inbounds for i in 1:n_ghosts + @inbounds for i = 1:n_ghosts sz = ghost_elem_sizes[i] sz == 0 && continue src = ghost_data_ptr(N, ghost_raw, i - 1) @@ -405,8 +459,8 @@ $(TYPEDSIGNATURES) Allocate a variable-size ghost receive buffer, perform the MPI exchange, and return `(ghost_buffer, ghost_offsets)`. -- `ghost_buffer`: Julia-managed `Vector{Float64}` holding all ghost data concatenated. -- `ghost_offsets[i]`: Float64-element offset of ghost `i`'s data within `ghost_buffer`. + - `ghost_buffer`: Julia-managed `Vector{Float64}` holding all ghost data concatenated. + - `ghost_offsets[i]`: Float64-element offset of ghost `i`'s data within `ghost_buffer`. """ function amr_exchange_varsize( p4est::P_pxest_t, @@ -416,8 +470,13 @@ function amr_exchange_varsize( ghost_elem_sizes::Vector{Int}, tag::Int, ) - ghost_buffer, ghost_offsets = - amr_exchange_varsize(ghost, mirror_data_bufs, mirror_elem_sizes, ghost_elem_sizes, tag) + ghost_buffer, ghost_offsets = amr_exchange_varsize( + ghost, + mirror_data_bufs, + mirror_elem_sizes, + ghost_elem_sizes, + tag, + ) return ghost_buffer, ghost_offsets end @@ -431,14 +490,21 @@ function amr_exchange_varsize( n_ghosts = length(ghost_elem_sizes) ghost_offsets = Vector{Int}(undef, n_ghosts) total_elems = 0 - for i in 1:n_ghosts + for i = 1:n_ghosts ghost_offsets[i] = total_elems total_elems += ghost_elem_sizes[i] end ghost_buffer = ghost_vec_alloc(total_elems) if MPI.Comm_size(MPI.COMM_WORLD) > 1 - _mpi_exchange_varsize!(ghost, ghost_buffer, ghost_offsets, ghost_elem_sizes, - mirror_data_bufs, mirror_elem_sizes, tag) + _mpi_exchange_varsize!( + ghost, + ghost_buffer, + ghost_offsets, + ghost_elem_sizes, + mirror_data_bufs, + mirror_elem_sizes, + tag, + ) end return ghost_buffer, ghost_offsets end @@ -460,8 +526,14 @@ function amr_exchange_varsize!( tag::Int, ) amr_exchange_varsize!( - ghost, ghost_buffer, ghost_offsets, ghost_elem_sizes, - mirror_data_bufs, mirror_elem_sizes, tag) + ghost, + ghost_buffer, + ghost_offsets, + ghost_elem_sizes, + mirror_data_bufs, + mirror_elem_sizes, + tag, + ) return nothing end @@ -475,8 +547,15 @@ function amr_exchange_varsize!( tag::Int, ) MPI.Comm_size(MPI.COMM_WORLD) == 1 && return nothing - _mpi_exchange_varsize!(ghost, ghost_buffer, ghost_offsets, ghost_elem_sizes, - mirror_data_bufs, mirror_elem_sizes, tag) + _mpi_exchange_varsize!( + ghost, + ghost_buffer, + ghost_offsets, + ghost_elem_sizes, + mirror_data_bufs, + mirror_elem_sizes, + tag, + ) return nothing end @@ -498,8 +577,14 @@ function amr_exchange_varsize_sparse!( tag::Int, ) amr_exchange_varsize_sparse!( - ghost, ghost_buffer, ghost_offsets, ghost_elem_sizes, - mirror_data_bufs, mirror_elem_sizes, tag) + ghost, + ghost_buffer, + ghost_offsets, + ghost_elem_sizes, + mirror_data_bufs, + mirror_elem_sizes, + tag, + ) return nothing end @@ -513,8 +598,15 @@ function amr_exchange_varsize_sparse!( tag::Int, ) MPI.Comm_size(MPI.COMM_WORLD) == 1 && return nothing - _mpi_exchange_varsize_sparse!(ghost, ghost_buffer, ghost_offsets, ghost_elem_sizes, - mirror_data_bufs, mirror_elem_sizes, tag) + _mpi_exchange_varsize_sparse!( + ghost, + ghost_buffer, + ghost_offsets, + ghost_elem_sizes, + mirror_data_bufs, + mirror_elem_sizes, + tag, + ) return nothing end @@ -522,33 +614,37 @@ end # Mirror buffer packing (exact-size allocation per quadrant) # --------------------------------------------------------------------------- -function get_mirror_data(p4est, kinfo::KInfo{DIM,NDF}, mirror_vsnums::Vector{Int}) where{DIM,NDF} +function get_mirror_data( + p4est, + kinfo::KInfo{DIM,NDF}, + mirror_vsnums::Vector{Int}, +) where {DIM,NDF} GC.@preserve p4est kinfo begin gp = PointerWrapper(kinfo.forest.ghost) pp = PointerWrapper(p4est) n_mirrors = Int(gp.mirrors.elem_count[]) mirror_data_bufs = Vector{Vector{Float64}}(undef, n_mirrors) for i = 1:n_mirrors - pq = pw_mirror_quadrant(pp,gp,i) + pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) vs_num = mirror_vsnums[i] sz = size_Ghost_Data(vs_num, DIM, NDF) ap = Vector{Float64}(undef, sz) offset = 0 - if isa(ps_data,InsideSolidData) + if isa(ps_data, InsideSolidData) ap[1:(offset+=DIM)] .= ps_data.ds - ap[offset+1:(offset+=DIM)] .= ps_data.midpoint - ap[offset+1:(offset+=DIM+2)] .= Inf + ap[(offset+1):(offset+=DIM)] .= ps_data.midpoint + ap[(offset+1):(offset+=DIM+2)] .= Inf ap[offset+=1] = 0 ap[offset+=1] = ps_data.bound_enc else ap[1:(offset+=DIM)] .= ps_data.ds - ap[offset+1:(offset+=DIM)] .= ps_data.midpoint - ap[offset+1:(offset+=DIM+2)] .= ps_data.w + ap[(offset+1):(offset+=DIM)] .= ps_data.midpoint + ap[(offset+1):(offset+=DIM+2)] .= ps_data.w ap[offset+=1] = ps_data.vs_data.vs_num ap[offset+=1] = ps_data.bound_enc - vs_temp = @view(ap[offset+1:(offset+=NDF*vs_num)]) + vs_temp = @view(ap[(offset+1):(offset+=NDF*vs_num)]) get_mirror_data_inner!(ps_data, vs_temp) end mirror_data_bufs[i] = ap @@ -557,14 +653,18 @@ function get_mirror_data(p4est, kinfo::KInfo{DIM,NDF}, mirror_vsnums::Vector{Int return mirror_data_bufs end -function get_mirror_slope(p4est, kinfo::KInfo{DIM,NDF}, mirror_vsnums::Vector{Int}) where{DIM,NDF} +function get_mirror_slope( + p4est, + kinfo::KInfo{DIM,NDF}, + mirror_vsnums::Vector{Int}, +) where {DIM,NDF} GC.@preserve p4est kinfo begin gp = PointerWrapper(kinfo.forest.ghost) pp = PointerWrapper(p4est) n_mirrors = Int(gp.mirrors.elem_count[]) mirror_slope_bufs = Vector{Vector{Float64}}(undef, n_mirrors) for i = 1:n_mirrors - pq = pw_mirror_quadrant(pp,gp,i) + pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) vs_num = mirror_vsnums[i] @@ -578,14 +678,18 @@ function get_mirror_slope(p4est, kinfo::KInfo{DIM,NDF}, mirror_vsnums::Vector{In return mirror_slope_bufs end -function get_mirror_structure(p4est, kinfo::KInfo{DIM,NDF}, mirror_vsnums::Vector{Int}) where{DIM,NDF} +function get_mirror_structure( + p4est, + kinfo::KInfo{DIM,NDF}, + mirror_vsnums::Vector{Int}, +) where {DIM,NDF} GC.@preserve p4est kinfo begin gp = PointerWrapper(kinfo.forest.ghost) pp = PointerWrapper(p4est) n_mirrors = Int(gp.mirrors.elem_count[]) mirror_structure_bufs = Vector{Vector{Float64}}(undef, n_mirrors) for i = 1:n_mirrors - pq = pw_mirror_quadrant(pp,gp,i) + pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) if isa(ps_data, InsideSolidData) @@ -597,9 +701,9 @@ function get_mirror_structure(p4est, kinfo::KInfo{DIM,NDF}, mirror_vsnums::Vecto vs_num = mirror_vsnums[i] sz = size_Ghost_VS_Structure(vs_num, DIM) ap = Vector{Float64}(undef, max(sz, 1)) - weight_temp = @view(ap[1:vs_num]) - level_temp = @view(ap[vs_num+1:2*vs_num]) - midpoint_temp = @view(ap[2*vs_num+1:vs_num*(DIM+2)]) + weight_temp = @view(ap[1:vs_num]) + level_temp = @view(ap[(vs_num+1):(2*vs_num)]) + midpoint_temp = @view(ap[(2*vs_num+1):(vs_num*(DIM+2))]) get_mirror_structure_inner!(ps_data, weight_temp, level_temp, midpoint_temp) mirror_structure_bufs[i] = ap end @@ -611,37 +715,66 @@ end # Ghost pointer and wrap initialisation # --------------------------------------------------------------------------- -function initialize_ghost_pool(p4est, kinfo::KInfo{DIM,NDF}) where{DIM,NDF} +function initialize_ghost_pool(p4est, kinfo::KInfo{DIM,NDF}) where {DIM,NDF} ghost_vsnums, mirror_vsnums = exchange_ghost_vsnums(p4est, kinfo) ghost_levels, mirror_levels = exchange_ghost_levels(p4est, kinfo) - mirror_data_szs = [size_Ghost_Data(v, DIM, NDF) for v in mirror_vsnums] - ghost_data_szs = [size_Ghost_Data(v, DIM, NDF) for v in ghost_vsnums] + mirror_data_szs = [size_Ghost_Data(v, DIM, NDF) for v in mirror_vsnums] + ghost_data_szs = [size_Ghost_Data(v, DIM, NDF) for v in ghost_vsnums] mirror_data_bufs = get_mirror_data(p4est, kinfo, mirror_vsnums) ghost_datas, ghost_data_offsets = amr_exchange_varsize( - p4est, kinfo.forest.ghost, mirror_data_bufs, mirror_data_szs, ghost_data_szs, 51) + p4est, + kinfo.forest.ghost, + mirror_data_bufs, + mirror_data_szs, + ghost_data_szs, + 51, + ) - mirror_slope_szs = [size_Ghost_Slope(v, DIM, NDF) for v in mirror_vsnums] - ghost_slope_szs = [size_Ghost_Slope(v, DIM, NDF) for v in ghost_vsnums] + mirror_slope_szs = [size_Ghost_Slope(v, DIM, NDF) for v in mirror_vsnums] + ghost_slope_szs = [size_Ghost_Slope(v, DIM, NDF) for v in ghost_vsnums] mirror_slope_bufs = get_mirror_slope(p4est, kinfo, mirror_vsnums) ghost_slopes, ghost_slope_offsets = amr_exchange_varsize( - p4est, kinfo.forest.ghost, mirror_slope_bufs, mirror_slope_szs, ghost_slope_szs, 52) + p4est, + kinfo.forest.ghost, + mirror_slope_bufs, + mirror_slope_szs, + ghost_slope_szs, + 52, + ) mirror_structure_bufs = get_mirror_structure(p4est, kinfo, mirror_vsnums) mirror_struct_szs = [size_Ghost_VS_Structure(v, DIM) for v in mirror_vsnums] - ghost_struct_szs = [size_Ghost_VS_Structure(v, DIM) for v in ghost_vsnums] + ghost_struct_szs = [size_Ghost_VS_Structure(v, DIM) for v in ghost_vsnums] ghost_structures, ghost_structure_offsets = amr_exchange_varsize( - p4est, kinfo.forest.ghost, mirror_structure_bufs, mirror_struct_szs, ghost_struct_szs, 53) + p4est, + kinfo.forest.ghost, + mirror_structure_bufs, + mirror_struct_szs, + ghost_struct_szs, + 53, + ) gb = GhostBuffer( - ghost_datas, ghost_slopes, ghost_structures, - mirror_data_bufs, mirror_slope_bufs, mirror_structure_bufs, + ghost_datas, + ghost_slopes, + ghost_structures, + mirror_data_bufs, + mirror_slope_bufs, + mirror_structure_bufs, ) gi = GhostInfo( - ghost_vsnums, mirror_vsnums, - ghost_data_offsets, ghost_slope_offsets, ghost_structure_offsets, - ghost_data_szs, ghost_slope_szs, mirror_data_szs, mirror_slope_szs, - ghost_levels, mirror_levels, + ghost_vsnums, + mirror_vsnums, + ghost_data_offsets, + ghost_slope_offsets, + ghost_structure_offsets, + ghost_data_szs, + ghost_slope_szs, + mirror_data_szs, + mirror_slope_szs, + ghost_levels, + mirror_levels, ) return gb, gi end @@ -657,11 +790,11 @@ function exchange_ghost_levels(p4est, kinfo::KInfo) gp = PointerWrapper(kinfo.forest.ghost) pp = PointerWrapper(p4est) n_mirrors = Int(gp.mirrors.elem_count[]) - n_ghosts = Int(gp.ghosts.elem_count[]) + n_ghosts = Int(gp.ghosts.elem_count[]) mirror_levels = Vector{Int8}(undef, n_mirrors) lvl_ptrs = Array{Ptr{Float64}}(undef, n_mirrors) - for i in 1:n_mirrors + for i = 1:n_mirrors pq = pw_mirror_quadrant(pp, gp, i) lvl = Int8(pq.level[]) mirror_levels[i] = lvl @@ -673,41 +806,46 @@ function exchange_ghost_levels(p4est, kinfo::KInfo) ghost_raw = amr_exchange(p4est, kinfo.forest.ghost, lvl_ptrs, 1) ghost_levels = Vector{Int8}(undef, n_ghosts) - for i in 1:n_ghosts + for i = 1:n_ghosts p = ghost_data_ptr(1, ghost_raw, i - 1) ghost_levels[i] = Int8(round(Base.unsafe_load(p))) end id = P4est.package_id() - for p in lvl_ptrs; sc_free(id, p); end + for p in lvl_ptrs + ; + sc_free(id, p); + end sc_free(id, ghost_raw) end return ghost_levels, mirror_levels end -function initialize_ghost_wrap(kinfo::KInfo{DIM,NDF}, - ghost_buffer::GhostBuffer, - ghost_info::GhostInfo) where{DIM,NDF} +function initialize_ghost_wrap( + kinfo::KInfo{DIM,NDF}, + ghost_buffer::GhostBuffer, + ghost_info::GhostInfo, +) where {DIM,NDF} gp = PointerWrapper(kinfo.forest.ghost) n_ghosts = Int(gp.ghosts.elem_count[]) ghost_wrap = Array{AbstractGhostPsData}(undef, n_ghosts) - ghost_vsnums = ghost_info.ghost_vsnums - ghost_data_offsets = ghost_info.ghost_data_offsets - ghost_slope_offsets = ghost_info.ghost_slope_offsets + ghost_vsnums = ghost_info.ghost_vsnums + ghost_data_offsets = ghost_info.ghost_data_offsets + ghost_slope_offsets = ghost_info.ghost_slope_offsets ghost_structure_offsets = ghost_info.ghost_structure_offsets # Raw pointers into Julia-managed buffers. The buffers live in ghost_buffer # (held by Ghost → ka.kdata.ghost) so they outlive all the wrapped arrays. - p_datas = pointer(ghost_buffer.ghost_datas) - p_slopes = pointer(ghost_buffer.ghost_slopes) + p_datas = pointer(ghost_buffer.ghost_datas) + p_slopes = pointer(ghost_buffer.ghost_slopes) p_structs = pointer(ghost_buffer.ghost_structures) for i in eachindex(ghost_wrap) pq = iPointerWrapper(gp.ghosts, p4est_quadrant_t, i - 1) owner_rank = pq.p.piggy1.owner_rank[] which_tree = pq.p.piggy3.which_tree[] - local_num = pq.p.piggy3.local_num[] + local_num = pq.p.piggy3.local_num[] quadid = which_tree * 2^(DIM * kinfo.config.solver.AMR_PS_MAXLEVEL) + local_num vs_num = ghost_vsnums[i] @@ -715,12 +853,12 @@ function initialize_ghost_wrap(kinfo::KInfo{DIM,NDF}, # --- data buffer (ds, midpoint, w, vs_num, bound_enc, df) --- p_data = p_datas + ghost_data_offsets[i] * sizeof(Float64) offset = 0 - ds = Base.unsafe_wrap(Vector{Float64}, p_data + offset * sizeof(Float64), DIM) - offset += DIM + ds = Base.unsafe_wrap(Vector{Float64}, p_data + offset * sizeof(Float64), DIM) + offset += DIM midpoint = Base.unsafe_wrap(Vector{Float64}, p_data + offset * sizeof(Float64), DIM) - offset += DIM - w = Base.unsafe_wrap(Vector{Float64}, p_data + offset * sizeof(Float64), DIM + 2) - offset += DIM + 2 + offset += DIM + w = Base.unsafe_wrap(Vector{Float64}, p_data + offset * sizeof(Float64), DIM + 2) + offset += DIM + 2 bound_enc = Int(Base.unsafe_load(p_data + (offset + 1) * sizeof(Float64))) if w[1] == Inf @@ -729,23 +867,44 @@ function initialize_ghost_wrap(kinfo::KInfo{DIM,NDF}, end offset += 2 - df = Base.unsafe_wrap(Matrix{Float64}, p_data + offset * sizeof(Float64), (vs_num, NDF)) + df = Base.unsafe_wrap( + Matrix{Float64}, + p_data + offset * sizeof(Float64), + (vs_num, NDF), + ) # --- slope buffer (sdf, sw) --- p_slope = p_slopes + ghost_slope_offsets[i] * sizeof(Float64) - sdf = Base.unsafe_wrap(Array{Float64}, p_slope, (vs_num, NDF, DIM)) - sw = Base.unsafe_wrap(Matrix{Float64}, p_slope + vs_num * NDF * DIM * sizeof(Float64), - (DIM + 2, DIM)) + sdf = Base.unsafe_wrap(Array{Float64}, p_slope, (vs_num, NDF, DIM)) + sw = Base.unsafe_wrap( + Matrix{Float64}, + p_slope + vs_num * NDF * DIM * sizeof(Float64), + (DIM + 2, DIM), + ) # --- structure buffer (weight, level, midpoint_vs) --- - p_struct = p_structs + ghost_structure_offsets[i] * sizeof(Float64) - weight = Base.unsafe_wrap(Vector{Float64}, p_struct, vs_num) - level = Base.unsafe_wrap(Vector{Float64}, p_struct + vs_num * sizeof(Float64), vs_num) - midpoint_vs = Base.unsafe_wrap(Matrix{Float64}, - p_struct + 2 * vs_num * sizeof(Float64), (vs_num, DIM)) + p_struct = p_structs + ghost_structure_offsets[i] * sizeof(Float64) + weight = Base.unsafe_wrap(Vector{Float64}, p_struct, vs_num) + level = + Base.unsafe_wrap(Vector{Float64}, p_struct + vs_num * sizeof(Float64), vs_num) + midpoint_vs = Base.unsafe_wrap( + Matrix{Float64}, + p_struct + 2 * vs_num * sizeof(Float64), + (vs_num, DIM), + ) - vs_data = GhostVsData{DIM,NDF}(vs_num, Int8.(round.(level)), weight, midpoint_vs, df, sdf) - ghost_wrap[i] = GhostPsData{DIM,NDF}(owner_rank, quadid, bound_enc, ds, midpoint, w, sw, vs_data) + vs_data = + GhostVsData{DIM,NDF}(vs_num, Int8.(round.(level)), weight, midpoint_vs, df, sdf) + ghost_wrap[i] = GhostPsData{DIM,NDF}( + owner_rank, + quadid, + bound_enc, + ds, + midpoint, + w, + sw, + vs_data, + ) end return ghost_wrap end @@ -754,67 +913,67 @@ end # Mirror buffer update (in-place, called each time-step before exchange) # --------------------------------------------------------------------------- -function update_mirror_data!(p4est, ka::KA{DIM,NDF}) where{DIM,NDF} +function update_mirror_data!(p4est, ka::KA{DIM,NDF}) where {DIM,NDF} GC.@preserve p4est ka begin mirror_data_bufs = ka.kdata.ghost.ghost_buffer.mirror_data_bufs - mirror_vsnums = ka.kdata.ghost.ghost_info.mirror_vsnums + mirror_vsnums = ka.kdata.ghost.ghost_info.mirror_vsnums gp = PointerWrapper(ka.kinfo.forest.ghost) pp = PointerWrapper(p4est) for i in eachindex(mirror_data_bufs) - pq = pw_mirror_quadrant(pp,gp,i) + pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue ap = mirror_data_bufs[i] - ap[DIM*2+1:DIM*3+2] .= ps_data.w - vs_temp = @view(ap[3*DIM+4+1:end]) + ap[(DIM*2+1):(DIM*3+2)] .= ps_data.w + vs_temp = @view(ap[(3*DIM+4+1):end]) get_mirror_data_inner!(ps_data, vs_temp) end end end -function update_solid_mirror_data!(p4est, ka::KA{DIM,NDF}) where{DIM,NDF} +function update_solid_mirror_data!(p4est, ka::KA{DIM,NDF}) where {DIM,NDF} GC.@preserve p4est ka begin mirror_data_bufs = ka.kdata.ghost.ghost_buffer.mirror_data_bufs - mirror_vsnums = ka.kdata.ghost.ghost_info.mirror_vsnums + mirror_vsnums = ka.kdata.ghost.ghost_info.mirror_vsnums gp = PointerWrapper(ka.kinfo.forest.ghost) pp = PointerWrapper(p4est) for i in eachindex(mirror_data_bufs) - pq = pw_mirror_quadrant(pp,gp,i) + pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - (isa(ps_data,InsideSolidData) || ps_data.bound_enc >= 0) && continue + (isa(ps_data, InsideSolidData) || ps_data.bound_enc >= 0) && continue ap = mirror_data_bufs[i] - ap[DIM*2+1:DIM*3+2] .= ps_data.w - vs_temp = @view(ap[3*DIM+4+1:end]) + ap[(DIM*2+1):(DIM*3+2)] .= ps_data.w + vs_temp = @view(ap[(3*DIM+4+1):end]) get_mirror_data_inner!(ps_data, vs_temp) end end end -function update_mirror_slope!(p4est, ka::KA{DIM,NDF}) where{DIM,NDF} +function update_mirror_slope!(p4est, ka::KA{DIM,NDF}) where {DIM,NDF} GC.@preserve p4est ka begin mirror_slope_bufs = ka.kdata.ghost.ghost_buffer.mirror_slope_bufs gp = PointerWrapper(ka.kinfo.forest.ghost) pp = PointerWrapper(p4est) for i in eachindex(mirror_slope_bufs) - pq = pw_mirror_quadrant(pp,gp,i) + pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue get_mirror_slope_inner!(ps_data, mirror_slope_bufs[i]) end end end -function get_mirror_sw(p4est, ka::KA{DIM,NDF}) where{DIM,NDF} +function get_mirror_sw(p4est, ka::KA{DIM,NDF}) where {DIM,NDF} sw_sz = size_Ghost_SW(DIM) GC.@preserve p4est ka begin gp = PointerWrapper(ka.kinfo.forest.ghost) pp = PointerWrapper(p4est) n_mirrors = Int(gp.mirrors.elem_count[]) mirror_sw_bufs = Vector{Vector{Float64}}(undef, n_mirrors) - for i in 1:n_mirrors + for i = 1:n_mirrors pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) @@ -838,36 +997,47 @@ end $(TYPEDSIGNATURES) Update `df` in [`GhostVsData`](@ref). """ -function data_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where{DIM,NDF} +function data_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} MPI.Comm_size(MPI.COMM_WORLD) == 1 && return nothing update_mirror_data!(p4est, ka) gb_buf = ka.kdata.ghost.ghost_buffer - gi = ka.kdata.ghost.ghost_info + gi = ka.kdata.ghost.ghost_info amr_exchange_varsize!( - p4est, ka.kinfo.forest.ghost, - gb_buf.ghost_datas, gi.ghost_data_offsets, gi.ghost_data_szs, - gb_buf.mirror_data_bufs, gi.mirror_data_szs, 51) + p4est, + ka.kinfo.forest.ghost, + gb_buf.ghost_datas, + gi.ghost_data_offsets, + gi.ghost_data_szs, + gb_buf.mirror_data_bufs, + gi.mirror_data_szs, + 51, + ) end """ $(TYPEDSIGNATURES) Update `sdf` in [`GhostVsData`](@ref). """ -function slope_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where{DIM,NDF} +function slope_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} MPI.Comm_size(MPI.COMM_WORLD) == 1 && return nothing update_mirror_slope!(p4est, ka) gb_buf = ka.kdata.ghost.ghost_buffer - gi = ka.kdata.ghost.ghost_info + gi = ka.kdata.ghost.ghost_info _native_exchange_varsize!( - p4est, ka.kinfo.forest.ghost, - gb_buf.ghost_slopes, gi.ghost_slope_offsets, gi.ghost_slope_szs, - gb_buf.mirror_slope_bufs, gi.mirror_slope_szs) + p4est, + ka.kinfo.forest.ghost, + gb_buf.ghost_slopes, + gi.ghost_slope_offsets, + gi.ghost_slope_szs, + gb_buf.mirror_slope_bufs, + gi.mirror_slope_szs, + ) end -function sw_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where{DIM,NDF} +function sw_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} MPI.Comm_size(MPI.COMM_WORLD) == 1 && return nothing gb_buf = ka.kdata.ghost.ghost_buffer - gi = ka.kdata.ghost.ghost_info + gi = ka.kdata.ghost.ghost_info sw_sz = size_Ghost_SW(DIM) mirror_sw_bufs = get_mirror_sw(p4est, ka) mirror_sw_szs = fill(sw_sz, length(gi.mirror_slope_szs)) @@ -877,9 +1047,15 @@ function sw_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where{DIM,NDF} ghost_sw_offsets[i] = gi.ghost_slope_offsets[i] + gi.ghost_vsnums[i] * NDF * DIM end amr_exchange_varsize!( - p4est, ka.kinfo.forest.ghost, - gb_buf.ghost_slopes, ghost_sw_offsets, ghost_sw_szs, - mirror_sw_bufs, mirror_sw_szs, 56) + p4est, + ka.kinfo.forest.ghost, + gb_buf.ghost_slopes, + ghost_sw_offsets, + ghost_sw_szs, + mirror_sw_bufs, + mirror_sw_szs, + 56, + ) return nothing end @@ -893,10 +1069,14 @@ contents at those slots are left untouched. Used by [`slope!`](@ref) to push the freshly transverse-corrected sw/sdf of one refinement level to ranks where that level appears as a coarse neighbour of a finer cell. """ -function slope_exchange_level!(p4est::P_pxest_t, ka::KA{DIM,NDF}, L::Integer) where{DIM,NDF} +function slope_exchange_level!( + p4est::P_pxest_t, + ka::KA{DIM,NDF}, + L::Integer, +) where {DIM,NDF} MPI.Comm_size(MPI.COMM_WORLD) == 1 && return nothing gb_buf = ka.kdata.ghost.ghost_buffer - gi = ka.kdata.ghost.ghost_info + gi = ka.kdata.ghost.ghost_info GC.@preserve p4est ka begin mirror_slope_bufs = gb_buf.mirror_slope_bufs @@ -913,19 +1093,25 @@ function slope_exchange_level!(p4est::P_pxest_t, ka::KA{DIM,NDF}, L::Integer) wh end n_mirrors = length(gi.mirror_slope_szs) - n_ghosts = length(gi.ghost_slope_szs) + n_ghosts = length(gi.ghost_slope_szs) mirror_szs = Vector{Int}(undef, n_mirrors) - ghost_szs = Vector{Int}(undef, n_ghosts) - @inbounds for i in 1:n_mirrors + ghost_szs = Vector{Int}(undef, n_ghosts) + @inbounds for i = 1:n_mirrors mirror_szs[i] = (gi.mirror_levels[i] == L) ? gi.mirror_slope_szs[i] : 0 end - @inbounds for i in 1:n_ghosts + @inbounds for i = 1:n_ghosts ghost_szs[i] = (gi.ghost_levels[i] == L) ? gi.ghost_slope_szs[i] : 0 end amr_exchange_varsize_sparse!( - p4est, ka.kinfo.forest.ghost, - gb_buf.ghost_slopes, gi.ghost_slope_offsets, ghost_szs, - gb_buf.mirror_slope_bufs, mirror_szs, 55) + p4est, + ka.kinfo.forest.ghost, + gb_buf.ghost_slopes, + gi.ghost_slope_offsets, + ghost_szs, + gb_buf.mirror_slope_bufs, + mirror_szs, + 55, + ) end """ @@ -936,20 +1122,20 @@ identity, with `true` for ghosts whose owner-side cell is above threshold. Caller must have already filled `ps_data.lohner` on all local cells. `GhostInsideSolidData` ghosts are left out of the map. """ -function lohner_flag_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where{DIM,NDF} - ghost_flags = Dict{UInt64, Bool}() +function lohner_flag_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} + ghost_flags = Dict{UInt64,Bool}() MPI.Comm_size(MPI.COMM_WORLD) == 1 && return ghost_flags - ghost = ka.kinfo.forest.ghost + ghost = ka.kinfo.forest.ghost threshold = ka.kinfo.config.solver.ADAPT_COEFFI_PS gp = PointerWrapper(ghost) pp = PointerWrapper(p4est) n_mirrors = Int(gp.mirrors.elem_count[]) - n_ghosts = Int(gp.ghosts.elem_count[]) + n_ghosts = Int(gp.ghosts.elem_count[]) mirror_bufs = Vector{Vector{Float64}}(undef, n_mirrors) GC.@preserve p4est ka begin - for i in 1:n_mirrors + for i = 1:n_mirrors pq = pw_mirror_quadrant(pp, gp, i) dp = PointerWrapper(P4estPsData, pq.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) @@ -963,16 +1149,16 @@ function lohner_flag_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where{DIM,NDF} end mirror_szs = fill(1, n_mirrors) - ghost_szs = fill(1, n_ghosts) + ghost_szs = fill(1, n_ghosts) recv_buf, recv_offsets = amr_exchange_varsize(p4est, ghost, mirror_bufs, mirror_szs, ghost_szs, 54) ghost_wrap = ka.kdata.ghost.ghost_wrap - for i in 1:n_ghosts + for i = 1:n_ghosts gw = ghost_wrap[i] isa(gw, GhostInsideSolidData) && continue gw.vs_data.vs_num == 0 && continue - ghost_flags[objectid(gw)] = recv_buf[recv_offsets[i] + 1] > 0.5 + ghost_flags[objectid(gw)] = recv_buf[recv_offsets[i]+1] > 0.5 end return ghost_flags end @@ -993,8 +1179,8 @@ function update_ghost!(p4est::Ptr{p4est_t}, ka::KA) kinfo.forest.ghost = p4est_ghost_new(p4est, P4EST_CONNECT_FULL) gb, gi = initialize_ghost_pool(p4est, kinfo) ka.kdata.ghost.ghost_buffer = gb - ka.kdata.ghost.ghost_info = gi - ka.kdata.ghost.ghost_wrap = initialize_ghost_wrap(kinfo, gb, gi) + ka.kdata.ghost.ghost_info = gi + ka.kdata.ghost.ghost_wrap = initialize_ghost_wrap(kinfo, gb, gi) end function update_ghost!(p4est::Ptr{p8est_t}, ka::KA) kinfo = ka.kinfo @@ -1008,6 +1194,6 @@ function update_ghost!(p4est::Ptr{p8est_t}, ka::KA) kinfo.forest.ghost = p8est_ghost_new(p4est, P8EST_CONNECT_FULL) gb, gi = initialize_ghost_pool(p4est, kinfo) ka.kdata.ghost.ghost_buffer = gb - ka.kdata.ghost.ghost_info = gi - ka.kdata.ghost.ghost_wrap = initialize_ghost_wrap(kinfo, gb, gi) + ka.kdata.ghost.ghost_info = gi + ka.kdata.ghost.ghost_wrap = initialize_ghost_wrap(kinfo, gb, gi) end diff --git a/src/Parallel/Parallel.jl b/src/Parallel/Parallel.jl index 646a126..f241bec 100644 --- a/src/Parallel/Parallel.jl +++ b/src/Parallel/Parallel.jl @@ -2,4 +2,4 @@ include("Ghost.jl") include("Partition.jl") export data_exchange!, slope_exchange!, sw_exchange!, get_vs_num -export ps_partition!, partition_weight, partition! \ No newline at end of file +export ps_partition!, partition_weight, partition! diff --git a/src/Parallel/Partition.jl b/src/Parallel/Partition.jl index 2f000d8..160beb9 100644 --- a/src/Parallel/Partition.jl +++ b/src/Parallel/Partition.jl @@ -1,24 +1,24 @@ -function pre_partition_box_weight(p4est::P_pxest_t,which_tree,quadrant) +function pre_partition_box_weight(p4est::P_pxest_t, which_tree, quadrant) fp = PointerWrapper(p4est) kinfo = unsafe_pointer_to_objref(pointer(fp.user_pointer)) ibs = kinfo.config.IB qp = PointerWrapper(quadrant) - ds,midpoint = quad_to_cell(p4est,which_tree,qp) + ds, midpoint = quad_to_cell(p4est, which_tree, qp) for ib in ibs - if solid_box_flag(midpoint,ds,ib) + if solid_box_flag(midpoint, ds, ib) return Cint(1) end end return Cint(0) end -function meshed_partition!(p4est::P_pxest_t,trees_data) - src_gfq, dest_gfq, src_flt, src_llt = partition!(p4est,C_NULL) +function meshed_partition!(p4est::P_pxest_t, trees_data) + src_gfq, dest_gfq, src_flt, src_llt = partition!(p4est, C_NULL) receives, sends, receive_nums, send_nums = get_receive_send(src_gfq, dest_gfq) - s_datas = static_data_transfer_wrap(sends,send_nums,trees_data) + s_datas = static_data_transfer_wrap(sends, send_nums, trees_data) transfer_pop!(sends, send_nums, trees_data) up_datas, down_datas = static_data_partition_transfer(sends, s_datas, receives, receive_nums) - up_ps_datas,down_ps_datas = static_data_unpack_data(up_datas,down_datas) + up_ps_datas, down_ps_datas = static_data_unpack_data(up_datas, down_datas) ti_data = TransferInit( length(up_ps_datas), length(down_ps_datas), @@ -32,40 +32,40 @@ function meshed_partition!(p4est::P_pxest_t,trees_data) ) static_data_init_transferred_data!(p4est, ti_data, trees_data) end -function static_data_init_transferred_data!(p4est,ti_data,trees_data) - static_data_insert_trees!(p4est,ti_data,trees_data) - static_data_init_transferred_quadrant!(p4est,ti_data,trees_data) +function static_data_init_transferred_data!(p4est, ti_data, trees_data) + static_data_insert_trees!(p4est, ti_data, trees_data) + static_data_init_transferred_quadrant!(p4est, ti_data, trees_data) end -function static_data_insert_trees!(p4est,ti_data,trees::Vector{Vector{T}}) where{T} +function static_data_insert_trees!(p4est, ti_data, trees::Vector{Vector{T}}) where {T} pp = PointerWrapper(p4est) if !isempty(trees) if pp.first_local_tree[] < ti_data.old_flt - for _ = 1:ti_data.old_flt-pp.first_local_tree[] + for _ = 1:(ti_data.old_flt-pp.first_local_tree[]) pushfirst!(trees, Vector{T}(undef, 0)) end end if pp.last_local_tree[] > ti_data.old_llt - for _ = 1:pp.last_local_tree[]-ti_data.old_llt + for _ = 1:(pp.last_local_tree[]-ti_data.old_llt) push!(trees, Vector{T}(undef, 0)) end end else - for _ = 1:pp.last_local_tree[]-pp.first_local_tree[]+1 + for _ = 1:(pp.last_local_tree[]-pp.first_local_tree[]+1) push!(trees, Vector{T}(undef, 0)) end end end -function static_data_init_transferred_quadrant!(p4est, ti_data,trees) - data = [ti_data,trees] +function static_data_init_transferred_quadrant!(p4est, ti_data, trees) + data = [ti_data, trees] p_data = pointer_from_objref(data) - GC.@preserve data AMR_volume_iterate(p4est;user_data = p_data) do ip,data,dp - ti_data,trees = unsafe_pointer_to_objref(data) + GC.@preserve data AMR_volume_iterate(p4est; user_data = p_data) do ip, data, dp + ti_data, trees = unsafe_pointer_to_objref(data) treeid = ip.treeid[]-ip.p4est.first_local_tree[]+1 - static_data_init_up_quadrants!(ip,dp,ti_data,trees[treeid]) - static_data_init_down_quadrants!(ip,dp,ti_data,trees[treeid]) + static_data_init_up_quadrants!(ip, dp, ti_data, trees[treeid]) + static_data_init_down_quadrants!(ip, dp, ti_data, trees[treeid]) end end -function static_data_init_up_quadrants!(ip,dp,ti_data,tree_datas) +function static_data_init_up_quadrants!(ip, dp, ti_data, tree_datas) ti_data.up_index > ti_data.up_num && return nothing ps_data = ti_data.up_data[ti_data.up_index] dp[] = P4estPsData(pointer_from_objref(ps_data)) @@ -78,9 +78,8 @@ function static_data_init_up_quadrants!(ip,dp,ti_data,tree_datas) ti_data.up_index += 1 return nothing end -function static_data_init_down_quadrants!(ip,dp,ti_data,tree_datas) - local_quadid(ip) < (ip.p4est.local_num_quadrants[] - ti_data.down_num) && - return nothing +function static_data_init_down_quadrants!(ip, dp, ti_data, tree_datas) + local_quadid(ip) < (ip.p4est.local_num_quadrants[] - ti_data.down_num) && return nothing ps_data = ti_data.down_data[ti_data.down_index] dp[] = P4estPsData(pointer_from_objref(ps_data)) push!(tree_datas, ps_data) @@ -88,31 +87,35 @@ function static_data_init_down_quadrants!(ip,dp,ti_data,tree_datas) return nothing end -function static_data_unpack_data(up_datas,down_datas::Vector{StructArray{T}}) where{T} - up_ps_datas = Vector{T}(undef,0) - down_ps_datas = Vector{T}(undef,0) +function static_data_unpack_data(up_datas, down_datas::Vector{StructArray{T}}) where {T} + up_ps_datas = Vector{T}(undef, 0) + down_ps_datas = Vector{T}(undef, 0) for data in up_datas for i in eachindex(data) - push!(up_ps_datas,data[i]) + push!(up_ps_datas, data[i]) end end for data in down_datas for i in eachindex(data) - push!(down_ps_datas,data[i]) + push!(down_ps_datas, data[i]) end end - return up_ps_datas,down_ps_datas + return up_ps_datas, down_ps_datas end -function static_data_transfer_wrap(sends,send_nums,trees_data::Vector{Vector{T}}) where{T} +function static_data_transfer_wrap( + sends, + send_nums, + trees_data::Vector{Vector{T}}, +) where {T} isempty(sends) && return Vector{Vector{T}}(undef, 0) - up_datas = static_data_up_transfer_wrap(sends,send_nums,trees_data) - down_datas = static_data_down_transfer_wrap(sends,send_nums,trees_data) - append!(up_datas,down_datas) + up_datas = static_data_up_transfer_wrap(sends, send_nums, trees_data) + down_datas = static_data_down_transfer_wrap(sends, send_nums, trees_data) + append!(up_datas, down_datas) return up_datas end -function static_data_up_transfer_wrap(sends,send_nums,trees::Vector{Vector{T}}) where{T} - s_datas = Vector{Vector{T}}(undef,0) +function static_data_up_transfer_wrap(sends, send_nums, trees::Vector{Vector{T}}) where {T} + s_datas = Vector{Vector{T}}(undef, 0) send_index = 1 index = 1 up_num = length(sends) @@ -120,7 +123,7 @@ function static_data_up_transfer_wrap(sends,send_nums,trees::Vector{Vector{T}}) for i in eachindex(trees) for j in eachindex(trees[i]) sends[send_index] > MPI.Comm_rank(MPI.COMM_WORLD) + 1 && break - push!(inner_datas,trees[i][j]) + push!(inner_datas, trees[i][j]) index += 1 if index > send_nums[send_index] push!(s_datas, inner_datas) @@ -135,8 +138,12 @@ function static_data_up_transfer_wrap(sends,send_nums,trees::Vector{Vector{T}}) end return s_datas end -function static_data_down_transfer_wrap(sends, send_nums, trees::Vector{Vector{T}}) where{T} - s_datas = Vector{Vector{T}}(undef,0) +function static_data_down_transfer_wrap( + sends, + send_nums, + trees::Vector{Vector{T}}, +) where {T} + s_datas = Vector{Vector{T}}(undef, 0) send_index = length(sends) index = send_nums[send_index] inner_datas = T[] @@ -158,36 +165,41 @@ function static_data_down_transfer_wrap(sends, send_nums, trees::Vector{Vector{T end return s_datas end -function static_data_partition_transfer(sends::Vector{Int}, s_datas::Vector{Vector{T}}, receives::Vector{Int}, receive_nums::Vector{Int}) where{T} +function static_data_partition_transfer( + sends::Vector{Int}, + s_datas::Vector{Vector{T}}, + receives::Vector{Int}, + receive_nums::Vector{Int}, +) where {T} struct_arrays = [StructArray(data) for data in s_datas] - reqs = Vector{MPI.Request}(undef,0) + reqs = Vector{MPI.Request}(undef, 0) for i in eachindex(sends) data = struct_arrays[i] properties = propertynames(data) for p in properties sreq = MPI.Isend( - getproperty(data,p), + getproperty(data, p), MPI.COMM_WORLD; dest = sends[i]-1, tag = COMM_DATA_TAG + MPI.Comm_rank(MPI.COMM_WORLD), ) - push!(reqs,sreq) + push!(reqs, sreq) end end - r_datas = Vector{StructArray{T}}(undef,0) + r_datas = Vector{StructArray{T}}(undef, 0) for i in eachindex(receives) - r_data = StructArray([T() for _ in 1:receive_nums[i]]) + r_data = StructArray([T() for _ = 1:receive_nums[i]]) properties = propertynames(r_data) for p in properties rreq = MPI.Irecv!( - getproperty(r_data,p), + getproperty(r_data, p), MPI.COMM_WORLD; source = receives[i]-1, - tag = COMM_DATA_TAG+receives[i]-1 + tag = COMM_DATA_TAG+receives[i]-1, ) - push!(reqs,rreq) + push!(reqs, rreq) end - push!(r_datas,r_data) + push!(r_datas, r_data) end MPI.Waitall(reqs) up_index = [x < MPI.Comm_rank(MPI.COMM_WORLD) + 1 for x in receives] @@ -203,21 +215,21 @@ function partition_check(p4est::P_pxest_t) pointer(pp.global_first_quadrant), MPI.Comm_size(MPI.COMM_WORLD) + 1, ) - nums = [gfq[i]-gfq[i-1] for i in 2:MPI.Comm_size(MPI.COMM_WORLD)+1] + nums = [gfq[i]-gfq[i-1] for i = 2:(MPI.Comm_size(MPI.COMM_WORLD)+1)] return (maximum(nums)-minimum(nums))/minimum(nums)>0.1 end """ $(TYPEDSIGNATURES) """ -function partition_weight(p4est::P_pxest_t,which_tree,quadrant::P_pxest_quadrant_t) +function partition_weight(p4est::P_pxest_t, which_tree, quadrant::P_pxest_quadrant_t) qp = PointerWrapper(quadrant) - dp = PointerWrapper(P4estPsData,qp.p.user_data[]) + dp = PointerWrapper(P4estPsData, qp.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - isa(ps_data,InsideSolidData)&&return Cint(0) + isa(ps_data, InsideSolidData)&&return Cint(0) ps_data.bound_enc<0&&return Cint(2*ps_data.vs_data.vs_num) if ps_data.bound_enc>0 - sn = findall(x->isa(x[1],SolidNeighbor),ps_data.neighbor.data) + sn = findall(x->isa(x[1], SolidNeighbor), ps_data.neighbor.data) return Cint((1+length(sn))*ps_data.vs_data.vs_num) end return Cint(ps_data.vs_data.vs_num) @@ -225,21 +237,27 @@ end """ $(TYPEDSIGNATURES) """ -function partition!(p4est::Ptr{p4est_t},weight::Function = partition_weight) +function partition!(p4est::Ptr{p4est_t}, weight::Function = partition_weight) fp = PointerWrapper(p4est) orig = Ptr{Cvoid}(pointer(fp.user_pointer)) # original user_pointer (e.g. kinfo/ka) ctx = AMR_weight_context(weight, orig) GC.@preserve weight ctx begin fp.user_pointer = pointer_from_objref(ctx) try - return partition!(p4est, - @cfunction(_amr_weight_cb_p4est,Cint,(Ptr{p4est_t},p4est_topidx_t,Ptr{p4est_quadrant_t}))) + return partition!( + p4est, + @cfunction( + _amr_weight_cb_p4est, + Cint, + (Ptr{p4est_t}, p4est_topidx_t, Ptr{p4est_quadrant_t}) + ) + ) finally fp.user_pointer = orig # restore original user_pointer end end end -function partition!(p4est::Ptr{p4est_t},weight::Union{Ptr{Nothing},Base.CFunction}) +function partition!(p4est::Ptr{p4est_t}, weight::Union{Ptr{Nothing},Base.CFunction}) pp = PointerWrapper(p4est) gfq = Base.unsafe_wrap( Vector{Int}, @@ -252,21 +270,27 @@ function partition!(p4est::Ptr{p4est_t},weight::Union{Ptr{Nothing},Base.CFunctio p4est_partition(p4est, 1, weight) return src_gfq, gfq, src_flt, src_llt end -function partition!(p4est::Ptr{p8est_t},weight::Function = partition_weight) +function partition!(p4est::Ptr{p8est_t}, weight::Function = partition_weight) fp = PointerWrapper(p4est) orig = Ptr{Cvoid}(pointer(fp.user_pointer)) # original user_pointer (e.g. kinfo/ka) ctx = AMR_weight_context(weight, orig) GC.@preserve weight ctx begin fp.user_pointer = pointer_from_objref(ctx) try - return partition!(p4est, - @cfunction(_amr_weight_cb_p8est,Cint,(Ptr{p8est_t},p4est_topidx_t,Ptr{p8est_quadrant_t}))) + return partition!( + p4est, + @cfunction( + _amr_weight_cb_p8est, + Cint, + (Ptr{p8est_t}, p4est_topidx_t, Ptr{p8est_quadrant_t}) + ) + ) finally fp.user_pointer = orig # restore original user_pointer end end end -function partition!(p4est::Ptr{p8est_t},weight::Union{Ptr{Nothing},Base.CFunction}) +function partition!(p4est::Ptr{p8est_t}, weight::Union{Ptr{Nothing},Base.CFunction}) pp = PointerWrapper(p4est) gfq = Base.unsafe_wrap( Vector{Int}, @@ -292,7 +316,7 @@ function get_receive_send(src_gfq::Vector, dest_gfq::Vector) r2 = MPI.Comm_rank(MPI.COMM_WORLD) == MPI.Comm_size(MPI.COMM_WORLD) - 1 ? MPI.Comm_size(MPI.COMM_WORLD) - 1 : findfirst(x -> x > llq, src_gfq) - 2 - is_receives[r1+1:r2+1] .= true + is_receives[(r1+1):(r2+1)] .= true is_receives[MPI.Comm_rank(MPI.COMM_WORLD)+1] = false if r1 == r2 receive_nums[r1+1] = llq - lfq + 1 @@ -312,7 +336,7 @@ function get_receive_send(src_gfq::Vector, dest_gfq::Vector) s2 = MPI.Comm_rank(MPI.COMM_WORLD) == MPI.Comm_size(MPI.COMM_WORLD) - 1 ? MPI.Comm_size(MPI.COMM_WORLD) - 1 : findfirst(x -> x > llq, dest_gfq) - 2 - is_sends[s1+1:s2+1] .= true + is_sends[(s1+1):(s2+1)] .= true is_sends[MPI.Comm_rank(MPI.COMM_WORLD)+1] = false if s1 == s2 send_nums[s1+1] = llq - lfq + 1 @@ -326,17 +350,17 @@ function get_receive_send(src_gfq::Vector, dest_gfq::Vector) end end end - singular = findall(x->x==0,receive_nums) + singular = findall(x->x==0, receive_nums) is_receives[singular] .= false receives = findall(is_receives) - singular = findall(x->x==0,send_nums) + singular = findall(x->x==0, send_nums) is_sends[singular] .= false sends = findall(is_sends) receive_nums = receive_nums[is_receives] send_nums = send_nums[is_sends] return receives, sends, receive_nums, send_nums end -function up_transfer_wrap(DIM::Integer,NDF::Integer,sends, send_nums, trees::Vector) +function up_transfer_wrap(DIM::Integer, NDF::Integer, sends, send_nums, trees::Vector) s_datas = Vector{TransferData{DIM,NDF}}(undef, 0) s_vs_numss = Vector{Vector{Int}}(undef, 0) send_index = 1 @@ -352,14 +376,14 @@ function up_transfer_wrap(DIM::Integer,NDF::Integer,sends, send_nums, trees::Vec for j in eachindex(trees[i]) sends[send_index] > MPI.Comm_rank(MPI.COMM_WORLD) + 1 && break ps_data = trees[i][j] - if isa(ps_data,InsideSolidData) - push!(encs,ps_data.bound_enc) - append!(encs,zeros(Int,SOLID_CELL_ID_NUM)) - append!(ws,zeros(DIM+2)) + if isa(ps_data, InsideSolidData) + push!(encs, ps_data.bound_enc) + append!(encs, zeros(Int, SOLID_CELL_ID_NUM)) + append!(ws, zeros(DIM+2)) s_vs_nums[index] = 0 else - push!(encs,ps_data.bound_enc) - append!(encs,ps_data.solid_cell_index) + push!(encs, ps_data.bound_enc) + append!(encs, ps_data.solid_cell_index) append!(ws, ps_data.w) append!(vs_levels, ps_data.vs_data.level) append!(vs_midpoints, reshape(ps_data.vs_data.midpoint, :)) @@ -368,7 +392,10 @@ function up_transfer_wrap(DIM::Integer,NDF::Integer,sends, send_nums, trees::Vec end index += 1 if index > send_nums[send_index] - push!(s_datas, TransferData{DIM,NDF}(encs, ws, vs_levels, vs_midpoints, vs_df)) + push!( + s_datas, + TransferData{DIM,NDF}(encs, ws, vs_levels, vs_midpoints, vs_df), + ) push!(s_vs_numss, s_vs_nums) index = 1 send_index += 1 @@ -386,7 +413,7 @@ function up_transfer_wrap(DIM::Integer,NDF::Integer,sends, send_nums, trees::Vec end return s_vs_numss, s_datas end -function down_transfer_wrap(DIM::Integer,NDF::Integer,sends, send_nums, trees::Vector) +function down_transfer_wrap(DIM::Integer, NDF::Integer, sends, send_nums, trees::Vector) s_datas = Vector{TransferData{DIM,NDF}}(undef, 0) s_vs_numss = Vector{Vector{Int}}(undef, 0) send_index = length(sends) @@ -401,13 +428,13 @@ function down_transfer_wrap(DIM::Integer,NDF::Integer,sends, send_nums, trees::V for j in reverse(eachindex(trees[i])) sends[send_index] < MPI.Comm_rank(MPI.COMM_WORLD) + 1 && break ps_data = trees[i][j] - if isa(ps_data,InsideSolidData) - prepend!(encs,zeros(SOLID_CELL_ID_NUM)) - pushfirst!(encs,ps_data.bound_enc) - prepend!(ws,zeros(DIM+2)) + if isa(ps_data, InsideSolidData) + prepend!(encs, zeros(SOLID_CELL_ID_NUM)) + pushfirst!(encs, ps_data.bound_enc) + prepend!(ws, zeros(DIM+2)) s_vs_nums[index] = 0 else - prepend!(encs,ps_data.solid_cell_index) + prepend!(encs, ps_data.solid_cell_index) pushfirst!(encs, ps_data.bound_enc) prepend!(ws, ps_data.w) prepend!(vs_levels, ps_data.vs_data.level) @@ -417,7 +444,10 @@ function down_transfer_wrap(DIM::Integer,NDF::Integer,sends, send_nums, trees::V end index -= 1 if index < 1 - pushfirst!(s_datas, TransferData{DIM,NDF}(encs, ws, vs_levels, vs_midpoints, vs_df)) + pushfirst!( + s_datas, + TransferData{DIM,NDF}(encs, ws, vs_levels, vs_midpoints, vs_df), + ) pushfirst!(s_vs_numss, s_vs_nums) send_index -= 1 send_index < 1 && break @@ -435,11 +465,12 @@ function down_transfer_wrap(DIM::Integer,NDF::Integer,sends, send_nums, trees::V end return s_vs_numss, s_datas end -function transfer_wrap(sends::Vector, send_nums::Vector, ka::KA{DIM,NDF}) where{DIM,NDF} - isempty(sends) && return Vector{Vector{Int}}(undef, 0), Vector{TransferData{DIM,NDF}}(undef, 0) +function transfer_wrap(sends::Vector, send_nums::Vector, ka::KA{DIM,NDF}) where {DIM,NDF} + isempty(sends) && + return Vector{Vector{Int}}(undef, 0), Vector{TransferData{DIM,NDF}}(undef, 0) trees = ka.kdata.field.trees.data - up_vs_numss, up_datas = up_transfer_wrap(DIM,NDF,sends, send_nums, trees) - down_vs_numss, down_datas = down_transfer_wrap(DIM,NDF,sends, send_nums, trees) + up_vs_numss, up_datas = up_transfer_wrap(DIM, NDF, sends, send_nums, trees) + down_vs_numss, down_datas = down_transfer_wrap(DIM, NDF, sends, send_nums, trees) append!(up_vs_numss, down_vs_numss) append!(up_datas, down_datas) return up_vs_numss, up_datas @@ -497,7 +528,7 @@ function pre_transfer( dest = sends[i] - 1, tag = COMM_NUMS_TAG + MPI.Comm_rank(MPI.COMM_WORLD), ) - push!(reqs,sreq) + push!(reqs, sreq) end r_vs_numss = Vector{Vector{Int}}(undef, length(receives)) for i in eachindex(receives) @@ -508,7 +539,7 @@ function pre_transfer( source = receives[i] - 1, tag = COMM_NUMS_TAG + receives[i] - 1, ) - push!(reqs,rreq) + push!(reqs, rreq) r_vs_numss[i] = r_vs_nums end MPI.Waitall(reqs) @@ -520,7 +551,7 @@ function transfer( receives::Vector{Int}, receive_nums::Vector{Int}, r_vs_numss::Vector, -) where{DIM,NDF} +) where {DIM,NDF} reqs = Vector{MPI.Request}(undef, 0) for i in eachindex(sends) sreq = MPI.Isend( @@ -562,7 +593,7 @@ function transfer( r_datas = Vector{TransferData{DIM,NDF}}(undef, 0) for i in eachindex(receives) total_vs_num = sum(r_vs_numss[i]) - r_data = TransferData(DIM,NDF,receive_nums[i], total_vs_num) + r_data = TransferData(DIM, NDF, receive_nums[i], total_vs_num) rreq = MPI.Irecv!( r_data.encs, MPI.COMM_WORLD; @@ -615,11 +646,11 @@ function partition_transfer( s_datas::Vector{TransferData{DIM,NDF}}, receives::Vector{Int}, receive_nums::Vector{Int}, -)where{DIM,NDF} +) where {DIM,NDF} r_vs_numss = pre_transfer(sends, s_vs_numss, receives, receive_nums) transfer(sends, s_datas, receives, receive_nums, r_vs_numss) end -function unpack_data(vs_nums, data, ka::KA{DIM,NDF}) where{DIM,NDF} +function unpack_data(vs_nums, data, ka::KA{DIM,NDF}) where {DIM,NDF} transfer_ps_datas = Vector{AbstractPsData{DIM,NDF}}(undef, length(vs_nums)) quadrature = ka.kinfo.config.quadrature vs_trees_num = reduce(*, ka.kinfo.config.vs_trees_num) @@ -632,15 +663,22 @@ function unpack_data(vs_nums, data, ka::KA{DIM,NDF}) where{DIM,NDF} for i in eachindex(vs_nums) vs_num = vs_nums[i] if vs_num==0 - transfer_ps_datas[i] = InsideSolidData(DIM,NDF;bound_enc = data.encs[(SOLID_CELL_ID_NUM+1)*(i-1)+1]) + transfer_ps_datas[i] = InsideSolidData( + DIM, + NDF; + bound_enc = data.encs[(SOLID_CELL_ID_NUM+1)*(i-1)+1], + ) else - encs = data.encs[(SOLID_CELL_ID_NUM+1)*(i-1)+1:(SOLID_CELL_ID_NUM+1)*i] - w = data.w[(DIM+2)*(i-1)+1:(DIM+2)*i] - prim = get_prim(w,ka.kinfo) - vs_levels = data.vs_levels[offset+1:offset+vs_num] - vs_midpoints = - reshape(data.vs_midpoints[DIM*offset+1:DIM*(offset+vs_num)], vs_num, DIM) - vs_df = reshape(data.vs_df[NDF*offset+1:NDF*(offset+vs_num)], vs_num, NDF) + encs = data.encs[((SOLID_CELL_ID_NUM+1)*(i-1)+1):((SOLID_CELL_ID_NUM+1)*i)] + w = data.w[((DIM+2)*(i-1)+1):((DIM+2)*i)] + prim = get_prim(w, ka.kinfo) + vs_levels = data.vs_levels[(offset+1):(offset+vs_num)] + vs_midpoints = reshape( + data.vs_midpoints[(DIM*offset+1):(DIM*(offset+vs_num))], + vs_num, + DIM, + ) + vs_df = reshape(data.vs_df[(NDF*offset+1):(NDF*(offset+vs_num))], vs_num, NDF) vs_weight = @. tree_weight / 2.0^(DIM * vs_levels) vs_data = VsData{DIM,NDF}( vs_num, @@ -651,13 +689,27 @@ function unpack_data(vs_nums, data, ka::KA{DIM,NDF}) where{DIM,NDF} zeros(vs_num, NDF, DIM), zeros(vs_num, NDF), ) - transfer_ps_datas[i] = PsData(DIM,NDF;bound_enc=encs[1],solid_cell_index=encs[2:SOLID_CELL_ID_NUM+1],w, prim, vs_data) + transfer_ps_datas[i] = PsData( + DIM, + NDF; + bound_enc = encs[1], + solid_cell_index = encs[2:(SOLID_CELL_ID_NUM+1)], + w, + prim, + vs_data, + ) end offset += vs_num end return transfer_ps_datas end -function unpack_data(up_vs_numss, down_vs_numss, up_datas, down_datas, ka::KA{DIM,NDF}) where{DIM,NDF} +function unpack_data( + up_vs_numss, + down_vs_numss, + up_datas, + down_datas, + ka::KA{DIM,NDF}, +) where {DIM,NDF} up_ps_datas = Vector{AbstractPsData{DIM,NDF}}(undef, 0) down_ps_datas = Vector{AbstractPsData{DIM,NDF}}(undef, 0) for i in eachindex(up_vs_numss) @@ -683,8 +735,7 @@ function init_up_quadrants!(ip, dp, ti_data::TransferInit, treeid::Integer, tree return nothing end function init_down_quadrants!(ip, dp, ti_data::TransferInit, treeid::Integer, tree_datas) - local_quadid(ip) < (ip.p4est.local_num_quadrants[] - ti_data.down_num) && - return nothing + local_quadid(ip) < (ip.p4est.local_num_quadrants[] - ti_data.down_num) && return nothing ps_data = ti_data.down_data[ti_data.down_index] ps_data.ds, ps_data.midpoint = quad_to_cell(ip.p4est, treeid, ip.quad) dp[] = P4estPsData(pointer_from_objref(ps_data)) @@ -695,7 +746,11 @@ end function init_transferred_quadrant!(p4est::P_pxest_t, ti_data::TransferInit, ka) ghost = ka.kinfo.forest.ghost p_data = pointer_from_objref(ti_data) - GC.@preserve ti_data AMR_volume_iterate(p4est;ghost = ghost,user_data = p_data) do ip,data,dp + GC.@preserve ti_data AMR_volume_iterate( + p4est; + ghost = ghost, + user_data = p_data, + ) do ip, data, dp ti_data = unsafe_pointer_to_objref(data) ka = unsafe_pointer_to_objref(pointer(ip.p4est.user_pointer)) trees = ka.kdata.field.trees @@ -709,22 +764,26 @@ function init_transferred_ps!(p4est::P_pxest_t, ti_data::TransferInit, ka::KA) insert_trees!(p4est, ti_data, ka) init_transferred_quadrant!(p4est, ti_data, ka) end -function insert_trees!(p4est::P_pxest_t, ti_data::TransferInit, ka::KA{DIM,NDF}) where{DIM,NDF} +function insert_trees!( + p4est::P_pxest_t, + ti_data::TransferInit, + ka::KA{DIM,NDF}, +) where {DIM,NDF} trees = ka.kdata.field.trees.data pp = PointerWrapper(p4est) if !isempty(trees) if pp.first_local_tree[] < ti_data.old_flt - for i = 1:ti_data.old_flt-pp.first_local_tree[] + for i = 1:(ti_data.old_flt-pp.first_local_tree[]) pushfirst!(trees, Vector{AbstractPsData{DIM,NDF}}(undef, 0)) end end if pp.last_local_tree[] > ti_data.old_llt - for i = 1:pp.last_local_tree[]-ti_data.old_llt + for i = 1:(pp.last_local_tree[]-ti_data.old_llt) push!(trees, Vector{AbstractPsData{DIM,NDF}}(undef, 0)) end end else - for _ = 1:pp.last_local_tree[]-pp.first_local_tree[]+1 + for _ = 1:(pp.last_local_tree[]-pp.first_local_tree[]+1) push!(trees, Vector{AbstractPsData{DIM,NDF}}(undef, 0)) end end diff --git a/src/Physical_space/AMR.jl b/src/Physical_space/AMR.jl index 0667834..9a217b5 100644 --- a/src/Physical_space/AMR.jl +++ b/src/Physical_space/AMR.jl @@ -14,7 +14,7 @@ function update_criterion!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_Lohner_inner_ps!(ps_data, Ldata, Rdata, ds, ds, dir, ws_swL, ws_swR,kinfo) + update_Lohner_inner_ps!(ps_data, Ldata, Rdata, ds, ds, dir, ws_swL, ws_swR, kinfo) return nothing end """ @@ -32,7 +32,17 @@ function update_criterion!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_Lohner_inner_ps!(ps_data, Ldata, Rdata, ds, 0.75 * ds, dir, ws_swL, ws_swR,kinfo) + update_Lohner_inner_ps!( + ps_data, + Ldata, + Rdata, + ds, + 0.75 * ds, + dir, + ws_swL, + ws_swR, + kinfo, + ) end """ $(TYPEDSIGNATURES) @@ -49,7 +59,17 @@ function update_criterion!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_Lohner_inner_ps!(ps_data, Ldata, Rdata, 0.75 * ds, ds, dir, ws_swL, ws_swR,kinfo) + update_Lohner_inner_ps!( + ps_data, + Ldata, + Rdata, + 0.75 * ds, + ds, + dir, + ws_swL, + ws_swR, + kinfo, + ) end """ $(TYPEDSIGNATURES) @@ -66,7 +86,17 @@ function update_criterion!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_Lohner_inner_ps!(ps_data, Ldata, Rdata, 0.75 * ds, 0.75 * ds, dir, ws_swL, ws_swR,kinfo) + update_Lohner_inner_ps!( + ps_data, + Ldata, + Rdata, + 0.75 * ds, + 0.75 * ds, + dir, + ws_swL, + ws_swR, + kinfo, + ) end """ $(TYPEDSIGNATURES) @@ -85,7 +115,17 @@ function update_criterion!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_Lohner_inner_ps!(ps_data, Ldata, Rdata, 1.5 * ds, 1.5 * ds, dir, ws_swL, ws_swR,kinfo) + update_Lohner_inner_ps!( + ps_data, + Ldata, + Rdata, + 1.5 * ds, + 1.5 * ds, + dir, + ws_swL, + ws_swR, + kinfo, + ) end """ $(TYPEDSIGNATURES) @@ -102,7 +142,7 @@ function update_criterion!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_Lohner_inner_ps!(ps_data, Ldata, Rdata, ds, 1.5 * ds, dir, ws_swL, ws_swR,kinfo) + update_Lohner_inner_ps!(ps_data, Ldata, Rdata, ds, 1.5 * ds, dir, ws_swL, ws_swR, kinfo) end """ $(TYPEDSIGNATURES) @@ -119,7 +159,7 @@ function update_criterion!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_Lohner_inner_ps!(ps_data, Ldata, Rdata, 1.5 * ds, ds, dir, ws_swL, ws_swR,kinfo) + update_Lohner_inner_ps!(ps_data, Ldata, Rdata, 1.5 * ds, ds, dir, ws_swL, ws_swR, kinfo) end """ $(TYPEDSIGNATURES) @@ -136,7 +176,17 @@ function update_criterion!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_Lohner_inner_ps!(ps_data, Ldata, Rdata, 0.75 * ds, 1.5 * ds, dir, ws_swL, ws_swR,kinfo) + update_Lohner_inner_ps!( + ps_data, + Ldata, + Rdata, + 0.75 * ds, + 1.5 * ds, + dir, + ws_swL, + ws_swR, + kinfo, + ) end """ $(TYPEDSIGNATURES) @@ -153,7 +203,17 @@ function update_criterion!( ws_swR::Vector{Float64}, ) where {DIM,NDF} ds = ps_data.ds[dir] - update_Lohner_inner_ps!(ps_data, Ldata, Rdata, 1.5 * ds, 0.75 * ds, dir, ws_swL, ws_swR,kinfo) + update_Lohner_inner_ps!( + ps_data, + Ldata, + Rdata, + 1.5 * ds, + 0.75 * ds, + dir, + ws_swL, + ws_swR, + kinfo, + ) end # Boundary @@ -171,7 +231,7 @@ function update_criterion!( ws_swL::Vector{Float64}, ws_swR::Vector{Float64}, ) where {DIM,NDF} - ps_data.lohner[:,dir] .= 0. + ps_data.lohner[:, dir] .= 0.0 end """ $(TYPEDSIGNATURES) @@ -187,7 +247,7 @@ function update_criterion!( ws_swL::Vector{Float64}, ws_swR::Vector{Float64}, ) where {DIM,NDF} - ps_data.lohner[:,dir] .= 0. + ps_data.lohner[:, dir] .= 0.0 end """ $(TYPEDSIGNATURES) @@ -203,7 +263,7 @@ function update_criterion!( ws_swL::Vector{Float64}, ws_swR::Vector{Float64}, ) where {DIM,NDF} - ps_data.lohner[:,dir] .= 0. + ps_data.lohner[:, dir] .= 0.0 end """ $(TYPEDSIGNATURES) @@ -219,7 +279,7 @@ function update_criterion!( ws_swL::Vector{Float64}, ws_swR::Vector{Float64}, ) where {DIM,NDF} - ps_data.lohner[:,dir] .= 0. + ps_data.lohner[:, dir] .= 0.0 end """ $(TYPEDSIGNATURES) @@ -235,7 +295,7 @@ function update_criterion!( ws_swL::Vector{Float64}, ws_swR::Vector{Float64}, ) where {DIM,NDF} - ps_data.lohner[:,dir] .= 0. + ps_data.lohner[:, dir] .= 0.0 end """ $(TYPEDSIGNATURES) @@ -251,9 +311,9 @@ function update_criterion!( ws_swL::Vector{Float64}, ws_swR::Vector{Float64}, ) where {DIM,NDF} - ps_data.lohner[:,dir] .= 0. + ps_data.lohner[:, dir] .= 0.0 end -function update_criterion!(ka::KA{DIM,NDF}) where{DIM,NDF} +function update_criterion!(ka::KA{DIM,NDF}) where {DIM,NDF} trees = ka.kdata.field.trees kinfo = ka.kinfo ws_swL = zeros(Float64, DIM + 2) @@ -262,7 +322,7 @@ function update_criterion!(ka::KA{DIM,NDF}) where{DIM,NDF} @inbounds for i in eachindex(trees.data) @inbounds for j in eachindex(trees.data[i]) ps_data = trees.data[i][j] - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue ps_data.bound_enc<0 && continue # solid_cells neighbor = ps_data.neighbor for dir = 1:DIM @@ -276,7 +336,8 @@ function update_criterion!(ka::KA{DIM,NDF}) where{DIM,NDF} neighbor.data[iL], neighbor.data[iR], dir, - ws_swL, ws_swR, + ws_swL, + ws_swR, ) end end @@ -293,7 +354,7 @@ will also be flagged for refinement. Decide-then-apply keeps the buffer strictly one layer thick. Ghost neighbours' flags are synced via [`lohner_flag_exchange!`](@ref). """ -function apply_amr_buffer!(ka::KA{DIM,NDF}) where{DIM,NDF} +function apply_amr_buffer!(ka::KA{DIM,NDF}) where {DIM,NDF} trees = ka.kdata.field.trees threshold = ka.kinfo.config.solver.ADAPT_COEFFI_PS inflate = 2.0 * threshold @@ -340,22 +401,28 @@ function apply_amr_buffer!(ka::KA{DIM,NDF}) where{DIM,NDF} return nothing end -function vs_merge!(sdf::AbstractArray,sdf_n::AbstractArray,level::Vector,level_n::Vector,::KA{DIM}) where{DIM} +function vs_merge!( + sdf::AbstractArray, + sdf_n::AbstractArray, + level::Vector, + level_n::Vector, + ::KA{DIM}, +) where {DIM} j = 1 flag = 0.0 - for i in axes(sdf,1) + for i in axes(sdf, 1) if level[i] == level_n[j] - @. sdf[i,:,:] += @views sdf_n[j, :, :] + @. sdf[i, :, :] += @views sdf_n[j, :, :] j += 1 elseif level[i] < level_n[j] while flag != 1.0 - @. sdf[i, :, :] += @views sdf_n[j, :, :]/ 2^(DIM * (level_n[j] - level[i])) + @. sdf[i, :, :] += @views sdf_n[j, :, :] / 2^(DIM * (level_n[j] - level[i])) flag += 1 / 2^(DIM * (level_n[j] - level[i])) j += 1 end flag = 0.0 else - @. sdf[i, :, :] += @views sdf_n[j,:,:] + @. sdf[i, :, :] += @views sdf_n[j, :, :] flag += 1 / 2^(DIM * (level[i] - level_n[j])) if flag == 1.0 j += 1 @@ -364,22 +431,28 @@ function vs_merge!(sdf::AbstractArray,sdf_n::AbstractArray,level::Vector,level_n end end end -function vs_merge!(sdf::AbstractMatrix,sdf_n::AbstractMatrix,level::Vector,level_n::Vector,::KA{DIM}) where{DIM} +function vs_merge!( + sdf::AbstractMatrix, + sdf_n::AbstractMatrix, + level::Vector, + level_n::Vector, + ::KA{DIM}, +) where {DIM} j = 1 flag = 0.0 - for i in axes(sdf,1) + for i in axes(sdf, 1) if level[i] == level_n[j] - @. sdf[i,:] += @views sdf_n[j, :] + @. sdf[i, :] += @views sdf_n[j, :] j += 1 elseif level[i] < level_n[j] while flag != 1.0 - @. sdf[i, :] += @views sdf_n[j, :]/ 2^(DIM * (level_n[j] - level[i])) + @. sdf[i, :] += @views sdf_n[j, :] / 2^(DIM * (level_n[j] - level[i])) flag += 1 / 2^(DIM * (level_n[j] - level[i])) j += 1 end flag = 0.0 else - @. sdf[i, :] += @views sdf_n[j,:] + @. sdf[i, :] += @views sdf_n[j, :] flag += 1 / 2^(DIM * (level[i] - level_n[j])) if flag == 1.0 j += 1 @@ -390,7 +463,7 @@ function vs_merge!(sdf::AbstractMatrix,sdf_n::AbstractMatrix,level::Vector,level end -function user_defined_ps_refine_flag(forest::P_pxest_t,which_tree,quadrant) +function user_defined_ps_refine_flag(forest::P_pxest_t, which_tree, quadrant) GC.@preserve forest which_tree quadrant begin fp = PointerWrapper(forest) qp = PointerWrapper(quadrant) @@ -404,7 +477,7 @@ function user_defined_ps_refine_flag(forest::P_pxest_t,which_tree,quadrant) end end end -function user_defined_ps_refine!(p4est::Ptr{p4est_t},kinfo::KInfo) +function user_defined_ps_refine!(p4est::Ptr{p4est_t}, kinfo::KInfo) p4est_refine_ext( p4est, 1, @@ -418,7 +491,7 @@ function user_defined_ps_refine!(p4est::Ptr{p4est_t},kinfo::KInfo) C_NULL, ) end -function user_defined_ps_refine!(p4est::Ptr{p8est_t},kinfo::KInfo) +function user_defined_ps_refine!(p4est::Ptr{p8est_t}, kinfo::KInfo) p8est_refine_ext( p4est, 1, @@ -433,46 +506,60 @@ function user_defined_ps_refine!(p4est::Ptr{p8est_t},kinfo::KInfo) ) end -function initialize_MeshData!(p4est::P_pxest_t,kinfo::KInfo) +function initialize_MeshData!(p4est::P_pxest_t, kinfo::KInfo) fp = PointerWrapper(p4est) - trees = [MeshData[] for _ in 1:fp.last_local_tree[]-fp.first_local_tree[]+1] + trees = [MeshData[] for _ = 1:(fp.last_local_tree[]-fp.first_local_tree[]+1)] p_data = pointer_from_objref(trees) - GC.@preserve trees AMR_volume_iterate(p4est;user_data = p_data) do ip,data,dp + GC.@preserve trees AMR_volume_iterate(p4est; user_data = p_data) do ip, data, dp treeid = ip.treeid[]-ip.p4est.first_local_tree[]+1 mesh_data = MeshData() dp[] = P4estPsData(pointer_from_objref(mesh_data)) trees = unsafe_pointer_to_objref(data) - push!(trees[treeid],mesh_data) - end + push!(trees[treeid], mesh_data) + end return trees end -function search_radius_flag!(forest::P_pxest_t,which_tree,quadrant) +function search_radius_flag!(forest::P_pxest_t, which_tree, quadrant) GC.@preserve forest which_tree quadrant begin fp = PointerWrapper(forest) - kinfo,_ = unsafe_pointer_to_objref(pointer(fp.user_pointer)) + kinfo, _ = unsafe_pointer_to_objref(pointer(fp.user_pointer)) qp = PointerWrapper(quadrant) - dp = PointerWrapper(P4estPsData,qp.p.user_data[]) + dp = PointerWrapper(P4estPsData, qp.p.user_data[]) mesh_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) ibs = kinfo.config.IB ds, midpoint = quad_to_cell(fp, which_tree, qp) for i in eachindex(ibs) - search_radius_flag!(i,ibs[i],midpoint,ds,mesh_data) && return Cint(1) + search_radius_flag!(i, ibs[i], midpoint, ds, mesh_data) && return Cint(1) end return Cint(0) end end -function search_radius_refine_replace(forest::P_pxest_t,which_tree,num_out,out_quads::Ptr{T},num_in,in_quads) where{T} +function search_radius_refine_replace( + forest::P_pxest_t, + which_tree, + num_out, + out_quads::Ptr{T}, + num_in, + in_quads, +) where {T} GC.@preserve forest which_tree num_out out_quads num_in in_quads begin fp = PointerWrapper(forest) - kinfo,trees = unsafe_pointer_to_objref(pointer(fp.user_pointer)) + kinfo, trees = unsafe_pointer_to_objref(pointer(fp.user_pointer)) out_quads_wrap = unsafe_wrap(Vector{T}, out_quads, num_out) in_quads_wrap = unsafe_wrap(Vector{T}, in_quads, num_in) - search_radius_refine_replace(forest, out_quads_wrap, in_quads_wrap, which_tree, trees, kinfo) + search_radius_refine_replace( + forest, + out_quads_wrap, + in_quads_wrap, + which_tree, + trees, + kinfo, + ) return nothing end end -function search_radius_refine!(p4est::Ptr{p4est_t},kinfo::KInfo) +function search_radius_refine!(p4est::Ptr{p4est_t}, kinfo::KInfo) p4est_refine_ext( p4est, 1, @@ -497,7 +584,7 @@ function search_radius_refine!(p4est::Ptr{p4est_t},kinfo::KInfo) ) ) end -function search_radius_refine!(p4est::Ptr{p8est_t},kinfo::KInfo) +function search_radius_refine!(p4est::Ptr{p8est_t}, kinfo::KInfo) p8est_refine_ext( p4est, 1, @@ -523,20 +610,20 @@ function search_radius_refine!(p4est::Ptr{p8est_t},kinfo::KInfo) ) end -function search_radius_refine_replace(p4est, out_quads,in_quads,which_tree,trees,kinfo) +function search_radius_refine_replace(p4est, out_quads, in_quads, which_tree, trees, kinfo) fp = PointerWrapper(p4est) out_qp = PointerWrapper(out_quads[1]) - dp = PointerWrapper(P4estPsData,out_qp.p.user_data[]) + dp = PointerWrapper(P4estPsData, out_qp.p.user_data[]) mesh_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) ib = kinfo.config.IB[mesh_data.in_search_radius] treeid = which_tree - fp.first_local_tree[]+1 datas = trees[treeid] - index = findfirst(x->x===mesh_data,datas) + index = findfirst(x->x===mesh_data, datas) deleteat!(datas, index) if out_qp.level[]==kinfo.config.solver.AMR_PS_MAXLEVEL-1 for i in eachindex(in_quads) qp = PointerWrapper(in_quads[i]) - dp = PointerWrapper(P4estPsData,qp.p.user_data[]) + dp = PointerWrapper(P4estPsData, qp.p.user_data[]) mesh_data_i = deepcopy(mesh_data) dp[] = P4estPsData(pointer_from_objref(mesh_data_i)) insert!(datas, index - 1 + i, mesh_data_i) @@ -544,7 +631,7 @@ function search_radius_refine_replace(p4est, out_quads,in_quads,which_tree,trees else for i in eachindex(in_quads) qp = PointerWrapper(in_quads[i]) - dp = PointerWrapper(P4estPsData,qp.p.user_data[]) + dp = PointerWrapper(P4estPsData, qp.p.user_data[]) mesh_data_i = MeshData() dp[] = P4estPsData(pointer_from_objref(mesh_data_i)) insert!(datas, index - 1 + i, mesh_data_i) @@ -554,34 +641,41 @@ end # function boundary_flag(::Domain,::AbstractVector,::AbstractVector,::KInfo) # Domain boundary flag # return false # end -function boundary_flag(boundary::Domain,midpoint::AbstractVector,ds::AbstractVector,kinfo::KInfo) # Domain boundary flag +function boundary_flag( + boundary::Domain, + midpoint::AbstractVector, + ds::AbstractVector, + kinfo::KInfo, +) # Domain boundary flag !boundary.refine && return false index = Int(floor((boundary.id-1)/2))+1 abs(midpoint[index] - kinfo.config.geometry[boundary.id]) < ds[index] && return true end -function domain_flag(kinfo::KInfo,midpoint::AbstractVector,ds::AbstractVector) # domain flag for physical space dynamic adaptive +function domain_flag(kinfo::KInfo, midpoint::AbstractVector, ds::AbstractVector) # domain flag for physical space dynamic adaptive domains = kinfo.config.domain for domain in domains - boundary_flag(domain,midpoint,ds,kinfo) && return true + boundary_flag(domain, midpoint, ds, kinfo) && return true end return false end -function boundary_flag(midpoint::AbstractVector,ds::AbstractVector,kinfo::KInfo) # Is the cell at midpoint +function boundary_flag(midpoint::AbstractVector, ds::AbstractVector, kinfo::KInfo) # Is the cell at midpoint domain = kinfo.config.domain boundary = kinfo.config.IB for i in eachindex(domain) - boundary_flag(domain[i],midpoint,ds,kinfo) && return true + boundary_flag(domain[i], midpoint, ds, kinfo) && return true end - return solid_cell_flag(boundary,midpoint,ds,kinfo) + return solid_cell_flag(boundary, midpoint, ds, kinfo) end -function ps_copy(data::PsData{DIM,NDF}) where{DIM,NDF} - p = PsData(DIM,NDF; - ds=copy(data.ds), - midpoint=copy(data.midpoint), - w=copy(data.w), - sw=copy(data.sw), - lohner=copy(data.lohner), - vs_data=deepcopy(data.vs_data), +function ps_copy(data::PsData{DIM,NDF}) where {DIM,NDF} + p = PsData( + DIM, + NDF; + ds = copy(data.ds), + midpoint = copy(data.midpoint), + w = copy(data.w), + sw = copy(data.sw), + lohner = copy(data.lohner), + vs_data = deepcopy(data.vs_data), prim = copy(data.prim), flux = copy(data.flux), # neighbor = data.neighbor @@ -589,29 +683,35 @@ function ps_copy(data::PsData{DIM,NDF}) where{DIM,NDF} return p end -function ps_merge(Odatas::Vector,index::Int,kinfo::KInfo{DIM,NDF}) where{DIM,NDF} +function ps_merge(Odatas::Vector, index::Int, kinfo::KInfo{DIM,NDF}) where {DIM,NDF} data = Odatas[index] - vs_data = data.vs_data;vs_num = vs_data.vs_num - w_new = [sum([x.w[i] for x in Odatas]) for i in 1:DIM+2]./2^DIM - p = PsData(DIM,NDF; - ds = data.ds *2.0, - midpoint = data.midpoint - 0.5 * data.ds .* RMT[DIM][index], - w = w_new, - prim = get_prim(w_new,kinfo), - sw = [sum([x.sw[i,j] for x in Odatas]) for i in 1:DIM+2,j in 1:DIM]./2^DIM, - flux = [sum([x.flux[i] for x in Odatas]) for i in 1:DIM+2]./2^DIM, - vs_data = VsData{DIM,NDF}(vs_num,copy(vs_data.level),copy(vs_data.weight),copy(vs_data.midpoint), - zeros(vs_num,NDF),zeros(vs_num,NDF,DIM),zeros(vs_num,NDF)) - ) + vs_data = data.vs_data; + vs_num = vs_data.vs_num + w_new = [sum([x.w[i] for x in Odatas]) for i = 1:(DIM+2)] ./ 2^DIM + p = PsData( + DIM, + NDF; + ds = data.ds * 2.0, + midpoint = data.midpoint - 0.5 * data.ds .* RMT[DIM][index], + w = w_new, + prim = get_prim(w_new, kinfo), + sw = [sum([x.sw[i, j] for x in Odatas]) for i = 1:(DIM+2), j = 1:DIM] ./ 2^DIM, + flux = [sum([x.flux[i] for x in Odatas]) for i = 1:(DIM+2)] ./ 2^DIM, + vs_data = VsData{DIM,NDF}( + vs_num, + copy(vs_data.level), + copy(vs_data.weight), + copy(vs_data.midpoint), + zeros(vs_num, NDF), + zeros(vs_num, NDF, DIM), + zeros(vs_num, NDF), + ), + ) p.neighbor.state[1] = BALANCE_FLAG p.neighbor.data[1] = Odatas return p end -function ps_refine_flag( - ::InsideSolidData, - ::Int8, - ::KA, -) +function ps_refine_flag(::InsideSolidData, ::Int8, ::KA) Cint(0) end function ps_refine_flag(forest::P_pxest_t, which_tree, quadrant) @@ -630,7 +730,7 @@ end $(TYPEDSIGNATURES) Replacement function in a refinement process. """ -function ps_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{DIM}) where{DIM}# refine replace +function ps_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{DIM}) where {DIM}# refine replace trees = ka.kdata.field.trees treeid = Int(which_tree) - trees.offset datas = trees.data[treeid] @@ -641,7 +741,7 @@ function ps_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{DIM}) wher index = findfirst(x -> x === Odata, datas) deleteat!(datas, index) flag = Odata.neighbor.state[1]==BALANCE_FLAG - for i = 1:2^DIM + for i = 1:(2^DIM) pw_in_quad = PointerWrapper(in_quads[i]) dp = PointerWrapper(P4estPsData, pw_in_quad.p.user_data[]) if flag @@ -651,13 +751,20 @@ function ps_replace!(::Val{1}, out_quad, in_quads, which_tree, ka::KA{DIM}) wher ps_data.ds .*= 0.5 vs_data = ps_data.vs_data @. ps_data.midpoint += 0.5 * ps_data.ds * RMT[DIM][i] - for k in axes(vs_data.df,2) - for j in axes(vs_data.df,1) - @views vs_data.df[j,k]+=min(abs(vs_data.df[j,k]/(dot(ps_data.ds,abs.(vs_data.sdf[j,k,:]))+EPS)),1.)*dot(vs_data.sdf[j,k,:],0.5 * ps_data.ds .* RMT[DIM][i]) + for k in axes(vs_data.df, 2) + for j in axes(vs_data.df, 1) + @views vs_data.df[j, k]+=min( + abs( + vs_data.df[j, k]/( + dot(ps_data.ds, abs.(vs_data.sdf[j, k, :]))+EPS + ), + ), + 1.0, + )*dot(vs_data.sdf[j, k, :], 0.5 * ps_data.ds .* RMT[DIM][i]) end end ps_data.w = calc_w0(ps_data) - ps_data.prim = get_prim(ps_data.w,ka.kinfo) + ps_data.prim = get_prim(ps_data.w, ka.kinfo) end insert!(datas, index - 1 + i, ps_data) dp[] = P4estPsData(pointer_from_objref(ps_data)) @@ -668,40 +775,54 @@ end $(TYPEDSIGNATURES) Replacement function in a coarsening process. """ -function ps_replace!(::ChildNum, out_quad, in_quads, which_tree, ka::KA{DIM,NDF}) where{DIM,NDF} # coarsen replace, average or interpolate? Currently interpolation strategy is adopted. If my memory serves me right, problems came out with average most likely due to the iterative balance process. +function ps_replace!( + ::ChildNum, + out_quad, + in_quads, + which_tree, + ka::KA{DIM,NDF}, +) where {DIM,NDF} # coarsen replace, average or interpolate? Currently interpolation strategy is adopted. If my memory serves me right, problems came out with average most likely due to the iterative balance process. trees = ka.kdata.field.trees treeid = Int(which_tree) - trees.offset datas = trees.data[treeid] pw_in_quad = PointerWrapper(in_quads[1]) dp = PointerWrapper(P4estPsData, pw_in_quad.p.user_data[]) Odatas = Vector{AbstractPsData{DIM,NDF}}(undef, 2^DIM) - for i = 1:2^DIM + for i = 1:(2^DIM) pw_out_quad = PointerWrapper(out_quad[i]) Odatas[i] = unsafe_pointer_to_objref( pointer(PointerWrapper(P4estPsData, pw_out_quad.p.user_data[]).ps_data), ) end - if any(x->x<0,[x.bound_enc for x in Odatas]) + if any(x->x<0, [x.bound_enc for x in Odatas]) @error `solid_cells coarsen!` end - _,index = findmin([x.vs_data.vs_num for x in Odatas]) - ps_data = ps_merge(Odatas,index,ka.kinfo) + _, index = findmin([x.vs_data.vs_num for x in Odatas]) + ps_data = ps_merge(Odatas, index, ka.kinfo) vs_data = ps_data.vs_data for i in eachindex(Odatas) vs_data_n = Odatas[i].vs_data - vs_merge!(vs_data.sdf,vs_data_n.sdf,vs_data.level,vs_data_n.level,ka) - vs_merge!(vs_data.df,vs_data_n.df,vs_data.level,vs_data_n.level,ka) + vs_merge!(vs_data.sdf, vs_data_n.sdf, vs_data.level, vs_data_n.level, ka) + vs_merge!(vs_data.df, vs_data_n.df, vs_data.level, vs_data_n.level, ka) end - vs_data.df./=2^DIM;vs_data.sdf./=2^DIM + vs_data.df./=2^DIM; + vs_data.sdf./=2^DIM ps_data.neighbor.state[1] = BALANCE_FLAG ps_data.neighbor.data[1] = Odatas index = findfirst(x -> x === Odatas[1], datas) - deleteat!(datas, index:index+2^DIM-1) + deleteat!(datas, index:(index+2^DIM-1)) insert!(datas, index, ps_data) dp[] = P4estPsData(pointer_from_objref(ps_data)) return nothing end -function p4est_replace(forest::T1, which_tree, num_out, out_quads::Ptr{T2}, num_in, in_quads) where{T1<:P_pxest_t,T2<:P_pxest_quadrant_t} +function p4est_replace( + forest::T1, + which_tree, + num_out, + out_quads::Ptr{T2}, + num_in, + in_quads, +) where {T1<:P_pxest_t,T2<:P_pxest_quadrant_t} GC.@preserve forest which_tree num_out out_quads num_in in_quads begin fp = PointerWrapper(forest) ka = unsafe_pointer_to_objref(pointer(fp.user_pointer)) @@ -711,13 +832,27 @@ function p4est_replace(forest::T1, which_tree, num_out, out_quads::Ptr{T2}, num_ return nothing end end -function pre_ps_replace(forest::T1, which_tree, num_out, out_quads::Ptr{T2}, num_in, in_quads) where{T1<:P_pxest_t,T2<:P_pxest_quadrant_t} +function pre_ps_replace( + forest::T1, + which_tree, + num_out, + out_quads::Ptr{T2}, + num_in, + in_quads, +) where {T1<:P_pxest_t,T2<:P_pxest_quadrant_t} GC.@preserve forest which_tree num_out out_quads num_in in_quads begin fp = PointerWrapper(forest) - _,trees = unsafe_pointer_to_objref(pointer(fp.user_pointer)) + _, trees = unsafe_pointer_to_objref(pointer(fp.user_pointer)) out_quads_wrap = unsafe_wrap(Vector{T2}, out_quads, num_out) in_quads_wrap = unsafe_wrap(Vector{T2}, in_quads, num_in) - pre_ps_replace(Val(Int(num_out)), forest, out_quads_wrap, in_quads_wrap, which_tree, trees) + pre_ps_replace( + Val(Int(num_out)), + forest, + out_quads_wrap, + in_quads_wrap, + which_tree, + trees, + ) return nothing end end @@ -739,7 +874,14 @@ function pre_ps_replace(::Val{1}, p4est, out_quad, in_quads, which_tree, trees)# dp[] = P4estPsData(pointer_from_objref(mesh_data)) end end -function pre_ps_replace(::ChildNum, p4est, out_quad, in_quads, which_tree, trees::Vector{Vector{T}}) where{T} # coarsen replace, average or interpolate? Currently interpolation strategy is adopted. If my memory serves me right, problems came out with average most likely due to the iterative balance process. +function pre_ps_replace( + ::ChildNum, + p4est, + out_quad, + in_quads, + which_tree, + trees::Vector{Vector{T}}, +) where {T} # coarsen replace, average or interpolate? Currently interpolation strategy is adopted. If my memory serves me right, problems came out with average most likely due to the iterative balance process. fp = PointerWrapper(p4est) treeid = Int(which_tree) - fp.first_local_tree[]+1 datas = trees[treeid] @@ -754,7 +896,7 @@ function pre_ps_replace(::ChildNum, p4est, out_quad, in_quads, which_tree, trees end mesh_data = deepcopy(Odatas[1]) index = findfirst(x -> x === Odatas[1], datas) - deleteat!(datas, index:index+length(out_quad)-1) + deleteat!(datas, index:(index+length(out_quad)-1)) insert!(datas, index, mesh_data) dp[] = P4estPsData(pointer_from_objref(mesh_data)) end @@ -762,7 +904,7 @@ end """ $(TYPEDSIGNATURES) """ -function ps_refine!(p4est::Ptr{p4est_t},ka::KA; recursive = 0) +function ps_refine!(p4est::Ptr{p4est_t}, ka::KA; recursive = 0) p4est_refine_ext( p4est, recursive, @@ -790,7 +932,7 @@ end """ $(TYPEDSIGNATURES) """ -function ps_refine!(p4est::Ptr{p8est_t},ka::KA; recursive = 0) +function ps_refine!(p4est::Ptr{p8est_t}, ka::KA; recursive = 0) p8est_refine_ext( p4est, recursive, @@ -817,37 +959,55 @@ function ps_refine!(p4est::Ptr{p8est_t},ka::KA; recursive = 0) end -function pre_ps_coarsen_flag(forest::Ptr{p4est_t},which_tree,quadrants) +function pre_ps_coarsen_flag(forest::Ptr{p4est_t}, which_tree, quadrants) GC.@preserve forest which_tree quadrants begin DIM = 2 fp = PointerWrapper(forest) quadrants_wrap = unsafe_wrap(Vector{Ptr{p4est_quadrant_t}}, quadrants, 2^DIM) - kinfo,_ = unsafe_pointer_to_objref(pointer(fp.user_pointer)) - for i = 1:2^DIM + kinfo, _ = unsafe_pointer_to_objref(pointer(fp.user_pointer)) + for i = 1:(2^DIM) quadrants_wrap[i]==C_NULL&&break qp = PointerWrapper(quadrants_wrap[i]) - dp = PointerWrapper(P4estPsData,qp.p.user_data[]) + dp = PointerWrapper(P4estPsData, qp.p.user_data[]) mesh_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - ds,midpoint = quad_to_cell(fp,which_tree,qp) - (kinfo.config.user_defined.static_ps_refine_flag(midpoint,ds,kinfo,qp.level[]-1)&&!mesh_data.in_solid - ||mesh_data.is_ghost_cell||(mesh_data.in_search_radius!=0&&!mesh_data.in_solid))&&return Cint(0) + ds, midpoint = quad_to_cell(fp, which_tree, qp) + ( + kinfo.config.user_defined.static_ps_refine_flag( + midpoint, + ds, + kinfo, + qp.level[]-1, + )&&!mesh_data.in_solid || + mesh_data.is_ghost_cell||( + mesh_data.in_search_radius!=0&&!mesh_data.in_solid + ) + )&&return Cint(0) end return Cint(1) end end -function pre_ps_coarsen_flag(forest::Ptr{p8est_t},which_tree,quadrants) +function pre_ps_coarsen_flag(forest::Ptr{p8est_t}, which_tree, quadrants) GC.@preserve forest which_tree quadrants begin DIM = 3 fp = PointerWrapper(forest) quadrants_wrap = unsafe_wrap(Vector{Ptr{p8est_quadrant_t}}, quadrants, 2^DIM) - kinfo,_ = unsafe_pointer_to_objref(pointer(fp.user_pointer)) - for i = 1:2^DIM + kinfo, _ = unsafe_pointer_to_objref(pointer(fp.user_pointer)) + for i = 1:(2^DIM) qp = PointerWrapper(quadrants_wrap[i]) - dp = PointerWrapper(P4estPsData,qp.p.user_data[]) + dp = PointerWrapper(P4estPsData, qp.p.user_data[]) mesh_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - ds,midpoint = quad_to_cell(fp,which_tree,qp) - (kinfo.config.user_defined.static_ps_refine_flag(midpoint,ds,kinfo,qp.level[]-1)&&!mesh_data.in_solid - ||mesh_data.is_ghost_cell||(mesh_data.in_search_radius!=0&&!mesh_data.in_solid))&&return Cint(0) + ds, midpoint = quad_to_cell(fp, which_tree, qp) + ( + kinfo.config.user_defined.static_ps_refine_flag( + midpoint, + ds, + kinfo, + qp.level[]-1, + )&&!mesh_data.in_solid || + mesh_data.is_ghost_cell||( + mesh_data.in_search_radius!=0&&!mesh_data.in_solid + ) + )&&return Cint(0) end return Cint(1) end @@ -910,11 +1070,11 @@ function ps_coarsen_flag(forest::Ptr{p4est_t}, which_tree, quadrants) quadrants_wrap = unsafe_wrap(Vector{Ptr{p4est_quadrant_t}}, quadrants, 2^DIM) levels = Vector{Int}(undef, 2^DIM) ps_datas = Vector{PsData}(undef, 2^DIM) - for i = 1:2^DIM + for i = 1:(2^DIM) qp = PointerWrapper(quadrants_wrap[i]) dp = PointerWrapper(P4estPsData, qp.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - isa(ps_data,InsideSolidData)&&return Cint(0) + isa(ps_data, InsideSolidData)&&return Cint(0) levels[i] = qp.level[] ps_datas[i] = ps_data end @@ -929,11 +1089,11 @@ function ps_coarsen_flag(forest::Ptr{p8est_t}, which_tree, quadrants) quadrants_wrap = unsafe_wrap(Vector{Ptr{p8est_quadrant_t}}, quadrants, 2^DIM) levels = Vector{Int}(undef, 2^DIM) ps_datas = Vector{PsData}(undef, 2^DIM) - for i = 1:2^DIM + for i = 1:(2^DIM) qp = PointerWrapper(quadrants_wrap[i]) dp = PointerWrapper(P4estPsData, qp.p.user_data[]) ps_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) - isa(ps_data,InsideSolidData)&&return Cint(0) + isa(ps_data, InsideSolidData)&&return Cint(0) levels[i] = qp.level[] ps_datas[i] = ps_data end @@ -1039,7 +1199,10 @@ function ps_balance!(p4est::Ptr{p8est_t}) ) end function pre_ps_balance!(p4est::Ptr{p4est_t}) - p4est_balance_ext(p4est, P4EST_CONNECT_FULL, C_NULL, + p4est_balance_ext( + p4est, + P4EST_CONNECT_FULL, + C_NULL, @cfunction( pre_ps_replace, Cvoid, @@ -1055,7 +1218,10 @@ function pre_ps_balance!(p4est::Ptr{p4est_t}) ) end function pre_ps_balance!(p4est::Ptr{p8est_t}) - p8est_balance_ext(p4est, P8EST_CONNECT_FULL, C_NULL, + p8est_balance_ext( + p4est, + P8EST_CONNECT_FULL, + C_NULL, @cfunction( pre_ps_replace, Cvoid, @@ -1075,17 +1241,17 @@ end $(TYPEDSIGNATURES) Update the globally maximum gradients of conserved variables as a referrence of the AMR in physical space. """ -function update_gradmax!(ka::KA{DIM}) where{DIM} - gradmax = ka.kinfo.status.gradmax - gradmax .= 0. +function update_gradmax!(ka::KA{DIM}) where {DIM} + gradmax = ka.kinfo.status.gradmax + gradmax .= 0.0 trees = ka.kdata.field.trees.data for tree in trees for ps_data in tree - isa(ps_data,InsideSolidData)&&continue + isa(ps_data, InsideSolidData)&&continue ps_data.bound_enc<0&&continue - for i in 1:DIM + for i = 1:DIM for j in eachindex(gradmax) - gradmax[j] = max(gradmax[j],abs(ps_data.sw[j,i])) + gradmax[j] = max(gradmax[j], abs(ps_data.sw[j, i])) end end end @@ -1105,11 +1271,11 @@ This low-level pass does **not** rebuild the ghost/neighbor/face data structures [`adaptive_mesh_refinement!`](@ref) (interval-driven, recovers automatically) or simply [`solve!`](@ref), which also uses it for the optional initial pre-refinement. """ -function ps_adaptive_mesh_refinement!(p4est::P_pxest_t,ka::KA;recursive = false) +function ps_adaptive_mesh_refinement!(p4est::P_pxest_t, ka::KA; recursive = false) # update_gradmax!(ka) - slope!(p4est,ka) + slope!(p4est, ka) update_criterion!(ka) - ps_refine!(p4est,ka;recursive = recursive ? 1 : 0) + ps_refine!(p4est, ka; recursive = recursive ? 1 : 0) ps_coarsen!(p4est; recursive = recursive ? 1 : 0) ps_balance!(p4est) return nothing diff --git a/src/Physical_space/Criteria.jl b/src/Physical_space/Criteria.jl index e33a9dc..d816c08 100644 --- a/src/Physical_space/Criteria.jl +++ b/src/Physical_space/Criteria.jl @@ -15,15 +15,22 @@ end max( lohner_rowmax(ps_data.lohner, 1), # max( - # lohner_rowmax(ps_data.lohner, 2), - lohner_rowmax(ps_data.lohner, size(ps_data.lohner, 1)) + # lohner_rowmax(ps_data.lohner, 2), + lohner_rowmax(ps_data.lohner, size(ps_data.lohner, 1)), # ), ) end -@inline function lohner_value(left::Real, center::Real, right::Real, dsL::Real, dsR::Real, eps::Real) +@inline function lohner_value( + left::Real, + center::Real, + right::Real, + dsL::Real, + dsR::Real, + eps::Real, +) scale = dsR * abs(left) + (dsL + dsR) * abs(center) + dsL * abs(right) - scale < PS_LOHNER_ABS_FLOOR*min(dsL,dsR) && return 0.0 + scale < PS_LOHNER_ABS_FLOOR*min(dsL, dsR) && return 0.0 denom = dsR * abs(left - center) + dsL * abs(right - center) + eps * scale denom <= 0.0 && return 0.0 abs(dsR * left - (dsL + dsR) * center + dsL * right) / denom @@ -35,7 +42,12 @@ end jump >= PS_PRIMITIVE_REL_JUMP_FLOOR * scale end -@inline function velocity_slope(sw::AbstractMatrix, prim::AbstractVector, component::Integer, dir::Integer) +@inline function velocity_slope( + sw::AbstractMatrix, + prim::AbstractVector, + component::Integer, + dir::Integer, +) row = component + 1 @inbounds (sw[row, dir] - prim[row] * sw[1, dir]) / prim[1] end @@ -53,14 +65,20 @@ end @inline function velocity_scale(prim::AbstractVector) speed2 = 0.0 - @inbounds for i in 2:(length(prim) - 1) + @inbounds for i = 2:(length(prim)-1) speed2 += prim[i] * prim[i] end lambda = max(abs(prim[end]), eps(Float64)) max(sqrt(speed2), inv(sqrt(lambda))) end -@inline function vorticity_amplitude_ok(left::Real, center::Real, right::Real, prim::AbstractVector, h::Real) +@inline function vorticity_amplitude_ok( + left::Real, + center::Real, + right::Real, + prim::AbstractVector, + h::Real, +) omega = max(abs(left), max(abs(center), abs(right))) omega * h >= PS_VORTICITY_JUMP_FLOOR * velocity_scale(prim) end @@ -68,18 +86,21 @@ end """ $(TYPEDSIGNATURES) """ -function ps_refine_flag( - ps_data::PsData{DIM}, - level::Int8, - ka::KA{DIM} -) where{DIM} +function ps_refine_flag(ps_data::PsData{DIM}, level::Int8, ka::KA{DIM}) where {DIM} kinfo = ka.kinfo - if ps_data.bound_enc!=0||domain_flag(kinfo,ps_data.midpoint,ps_data.ds) + if ps_data.bound_enc!=0||domain_flag(kinfo, ps_data.midpoint, ps_data.ds) return Cint(1) end level>kinfo.config.solver.AMR_DYNAMIC_PS_MAXLEVEL-1&&return Cint(0) - kinfo.config.user_defined.static_ps_refine_flag(ps_data.midpoint,ps_data.ds,kinfo,level) && return Cint(1) - dflag = kinfo.config.user_defined.dynamic_ps_refine_flag==null_udf ? true : kinfo.config.user_defined.dynamic_ps_refine_flag(ps_data,level,ka) + kinfo.config.user_defined.static_ps_refine_flag( + ps_data.midpoint, + ps_data.ds, + kinfo, + level, + ) && return Cint(1) + dflag = + kinfo.config.user_defined.dynamic_ps_refine_flag==null_udf ? true : + kinfo.config.user_defined.dynamic_ps_refine_flag(ps_data, level, ka) !dflag&&return Cint(0) return Cint(ps_sensor(ps_data)>kinfo.config.solver.ADAPT_COEFFI_PS) end @@ -87,14 +108,24 @@ end """ $(TYPEDSIGNATURES) """ -function ps_coarsen_flag(ps_datas::Vector{PsData}, levels::Vector{Int}, ka::KA{DIM,NDF}) where{DIM,NDF} +function ps_coarsen_flag( + ps_datas::Vector{PsData}, + levels::Vector{Int}, + ka::KA{DIM,NDF}, +) where {DIM,NDF} kinfo = ka.kinfo levels[1]>kinfo.config.solver.AMR_DYNAMIC_PS_MAXLEVEL&&return Cint(0) threshold = PS_COARSEN_SENSOR_RATIO * kinfo.config.solver.ADAPT_COEFFI_PS - for i = 1:2^DIM + for i = 1:(2^DIM) ps_data = ps_datas[i] - (ps_data.bound_enc!=0||domain_flag(kinfo,ps_data.midpoint,ps_data.ds)) && return Cint(0) - kinfo.config.user_defined.static_ps_refine_flag(ps_data.midpoint,ps_data.ds,kinfo,levels[i]-1) && return Cint(0) + (ps_data.bound_enc!=0||domain_flag(kinfo, ps_data.midpoint, ps_data.ds)) && + return Cint(0) + kinfo.config.user_defined.static_ps_refine_flag( + ps_data.midpoint, + ps_data.ds, + kinfo, + levels[i]-1, + ) && return Cint(0) ps_sensor(ps_data)>threshold && return Cint(0) end return Cint(1) @@ -109,20 +140,20 @@ function update_Lohner_inner_ps!( dir::Int, ws_swL::Vector{Float64}, ws_swR::Vector{Float64}, - kinfo::KInfo -) where{DIM,NDF} + kinfo::KInfo, +) where {DIM,NDF} fill!(ws_swL, 0.0) fill!(ws_swR, 0.0) - swL = zeros(DIM+2,DIM) - swR = zeros(DIM+2,DIM) + swL = zeros(DIM+2, DIM) + swR = zeros(DIM+2, DIM) nL = length(Ldata) nR = length(Rdata) - @inbounds for j in 1:nL + @inbounds for j = 1:nL @. ws_swL += Ldata[j].w @. swL += Ldata[j].sw end - @inbounds for j in 1:nR + @inbounds for j = 1:nR @. ws_swR += Rdata[j].w @. swR += Rdata[j].sw end @@ -130,13 +161,13 @@ function update_Lohner_inner_ps!( if dsL>ps_data.ds[dir] dx = (ps_data.midpoint-Ldata[1].midpoint)[FAT[DIM-1][dir]] @inbounds for j in eachindex(ws_swL) - @views ws_swL[j] += dot(dx, Ldata[1].sw[j,FAT[DIM-1][dir]]) + @views ws_swL[j] += dot(dx, Ldata[1].sw[j, FAT[DIM-1][dir]]) end end if dsR>ps_data.ds[dir] dx = (ps_data.midpoint-Rdata[1].midpoint)[FAT[DIM-1][dir]] @inbounds for j in eachindex(ws_swR) - @views ws_swR[j] += dot(dx, Rdata[1].sw[j,FAT[DIM-1][dir]]) + @views ws_swR[j] += dot(dx, Rdata[1].sw[j, FAT[DIM-1][dir]]) end end @@ -145,19 +176,20 @@ function update_Lohner_inner_ps!( swL ./= nL swR ./= nR - ws_swL .= get_prim(ws_swL,kinfo) - ws_swR .= get_prim(ws_swR,kinfo) + ws_swL .= get_prim(ws_swL, kinfo) + ws_swR .= get_prim(ws_swR, kinfo) omegaL = vorticity(swL, ws_swL, Val(DIM)) omegaR = vorticity(swR, ws_swR, Val(DIM)) omega = vorticity(ps_data.sw, ps_data.prim, Val(DIM)) - use_vorticity = vorticity_amplitude_ok(omegaL, omega, omegaR, ps_data.prim, max(dsL, dsR)) + use_vorticity = + vorticity_amplitude_ok(omegaL, omega, omegaR, ps_data.prim, max(dsL, dsR)) eps_l = 0.2*ps_data.ds[dir] @inbounds for j in eachindex(ws_swL) if j == 2 - ps_data.lohner[j, dir] = use_vorticity ? - lohner_value(omegaL, omega, omegaR, dsL, dsR, eps_l) : 0.0 + ps_data.lohner[j, dir] = + use_vorticity ? lohner_value(omegaL, omega, omegaR, dsL, dsR, eps_l) : 0.0 else ps_data.lohner[j, dir] = primitive_amplitude_ok(ws_swL[j], ps_data.prim[j], ws_swR[j]) ? diff --git a/src/Physical_space/Physical_space.jl b/src/Physical_space/Physical_space.jl index 7992052..e310d8a 100644 --- a/src/Physical_space/Physical_space.jl +++ b/src/Physical_space/Physical_space.jl @@ -1,4 +1,20 @@ include("AMR.jl") include("Criteria.jl") -export PsData, GhostPsData, InsideSolidData, GhostInsideSolidData, Neighbor, SolidNeighbor, FullFace, HangingFace, BackHangingFace, FluxData -export ps_adaptive_mesh_refinement!, ps_refine!, ps_coarsen!, ps_balance!, ps_replace!, ps_refine_flag, ps_coarsen_flag, update_gradmax! \ No newline at end of file +export PsData, + GhostPsData, + InsideSolidData, + GhostInsideSolidData, + Neighbor, + SolidNeighbor, + FullFace, + HangingFace, + BackHangingFace, + FluxData +export ps_adaptive_mesh_refinement!, + ps_refine!, + ps_coarsen!, + ps_balance!, + ps_replace!, + ps_refine_flag, + ps_coarsen_flag, + update_gradmax! diff --git a/src/Physical_space/Types.jl b/src/Physical_space/Types.jl index 6484f69..61f5ed9 100644 --- a/src/Physical_space/Types.jl +++ b/src/Physical_space/Types.jl @@ -1,4 +1,4 @@ -NeighborQuad{DIM,NDF} = Union{AbstractPsData{DIM,NDF}, Nothing} +NeighborQuad{DIM,NDF} = Union{AbstractPsData{DIM,NDF},Nothing} ChildNum = Union{Val{4},Val{8}} NeighborNum = Union{Val{2},Val{4}} @@ -15,34 +15,48 @@ $(TYPEDFIELDS) mutable struct Neighbor{DIM,NDF} data::Vector{Vector{NeighborQuad{DIM,NDF}}} state::Vector{Int} - Neighbor(DIM,NDF) = (n = new{DIM,NDF}(); - n.data = Vector{Vector{NeighborQuad{DIM,NDF}}}(undef, 2*DIM); - n.state = zeros(Int8, 2*DIM); - n) + Neighbor(DIM, NDF) = ( + n = new{DIM,NDF}(); + n.data = Vector{Vector{NeighborQuad{DIM,NDF}}}(undef, 2*DIM); + n.state = zeros(Int8, 2*DIM); + n + ) end """ $(TYPEDEF) $(TYPEDFIELDS) """ -mutable struct SolidNeighbor{DIM,NDF} <:AbstractPsData{DIM,NDF} +mutable struct SolidNeighbor{DIM,NDF} <: AbstractPsData{DIM,NDF} bound_enc::Int - "Index of the face of the donor cell corresponding to this SolidNeighbor." + """ + Index of the face of the donor cell corresponding to this SolidNeighbor. # The faceid through which the neighbor is the solidneighbor. + """ faceid::Int # The faceid through which the neighbor is the solidneighbor. - "Deprecated." + """ + Deprecated. # corner neighbor id for corner ghost cells' average. + """ av_id::Int # corner neighbor id for corner ghost cells' average. - "Intersect point at the boundary corresponding to this SolidNeighbor." + """ + Intersect point at the boundary corresponding to this SolidNeighbor. + """ aux_point::Vector{Float64} - "Normal vector of the boundary at `aux_point`." + """ + Normal vector of the boundary at `aux_point`. + """ normal::Vector{Float64} - "Solid_cell corresponding to this SolidNeighbor." + """ + Solid_cell corresponding to this SolidNeighbor. + """ solid_cell::AbstractPsData{DIM,NDF} midpoint::Vector{Float64} ds::Vector{Float64} w::Vector{Float64} flux::Vector{Float64} sw::Matrix{Float64} - "Struct containing information of cut cell in velocity space." + """ + Struct containing information of cut cell in velocity space. + """ cvc::CuttedVelocityCells vs_data::VsData{DIM,NDF} end @@ -51,53 +65,86 @@ $(TYPEDEF) $(TYPEDFIELDS) """ mutable struct PsData{DIM,NDF} <: AbstractPsData{DIM,NDF} - "Index of the quadrant corresponding to `PsData`." + """ + Index of the quadrant corresponding to `PsData`. # The unique identification of the ps_data, is currently used for SolidCells and IB nodes' partition. Only need to be updated before partition. Can be negative for SolidCells/IB nodes for the convenience of boundary_flag + """ quadid::Cint # The unique identification of the ps_data, is currently used for SolidCells and IB nodes' partition. Only need to be updated before partition. Can be negative for SolidCells/IB nodes for the convenience of boundary_flag - "Encoding of the cell type. `0`:fluid cell;`>0`: donor cell of `bound_enc` th immersed boundary;`<0`: solid cell (or solid neighbor) of `bound_enc` th boundary." + """ + Encoding of the cell type. `0`:fluid cell;`>0`: donor cell of `bound_enc` th immersed boundary;`<0`: solid cell (or solid neighbor) of `bound_enc` th boundary. # 0:fluid_cell;>0:bound_enc th boundary's IB_cell;<0: bound_enc th boundary's solid_cell; + """ bound_enc::Int # 0:fluid_cell;>0:bound_enc th boundary's IB_cell;<0: bound_enc th boundary's solid_cell; - "Deprecated." + """ + Deprecated. + """ solid_cell_index::Vector{Int} - "Faces area (length)." + """ + Faces area (length). # DIM + """ ds::Vector{Float64} # DIM - "Coordinates of the cell center." + """ + Coordinates of the cell center. + """ midpoint::Vector{Float64} - "Heat flux." + """ + Heat flux. + """ qf::Vector{Float64} - "Conserved variables." + """ + Conserved variables. + """ w::Vector{Float64} - "Gradients of conserved variables." + """ + Gradients of conserved variables. # DIM + 2 x DIM + """ sw::Matrix{Float64} # DIM + 2 x DIM - "Loner criterion for each direction." + """ + Loner criterion for each direction. # DIM + 2 x DIM + """ lohner::Matrix{Float64} # DIM + 2 x DIM - "Primary variables." + """ + Primary variables. + """ prim::Vector{Float64} - "Conserved flux." + """ + Conserved flux. + """ flux::Vector{Float64} - "Data of the velocity space." + """ + Data of the velocity space. + """ vs_data::VsData{DIM,NDF} - "Neighbor of the cell." + """ + Neighbor of the cell. + """ neighbor::Neighbor{DIM,NDF} - PsData(DIM,NDF;kwargs...)=(n = new{DIM,NDF}(); - n.quadid = haskey(kwargs,:quadid) ? kwargs[:quadid] : 0; - n.bound_enc = haskey(kwargs,:bound_enc) ? kwargs[:bound_enc] : 0; - n.solid_cell_index = haskey(kwargs,:solid_cell_index) ? kwargs[:solid_cell_index] : zeros(SOLID_CELL_ID_NUM); - n.ds = haskey(kwargs,:ds) ? kwargs[:ds] : zeros(DIM); - n.midpoint = haskey(kwargs,:midpoint) ? kwargs[:midpoint] : zeros(DIM); - n.qf = haskey(kwargs,:qf) ? kwargs[:qf] : zeros(DIM); - n.w = haskey(kwargs,:w) ? kwargs[:w] : zeros(DIM+2); - n.sw = haskey(kwargs,:sw) ? kwargs[:sw] : zeros(DIM+2, DIM); - n.lohner = haskey(kwargs,:lohner) ? kwargs[:lohner] : zeros(DIM+2, DIM); - n.prim = haskey(kwargs,:prim) ? kwargs[:prim] : zeros(DIM+2); - n.flux = haskey(kwargs,:flux) ? kwargs[:flux] : zeros(DIM+2); - if haskey(kwargs,:vs_data) - n.vs_data = kwargs[:vs_data] + PsData(DIM, NDF; kwargs...) = ( + n = new{DIM,NDF}(); + n.quadid = haskey(kwargs, :quadid) ? kwargs[:quadid] : 0; + n.bound_enc = haskey(kwargs, :bound_enc) ? kwargs[:bound_enc] : 0; + n.solid_cell_index = haskey(kwargs, :solid_cell_index) ? + kwargs[:solid_cell_index] : zeros(SOLID_CELL_ID_NUM); + n.ds = haskey(kwargs, :ds) ? kwargs[:ds] : zeros(DIM); + n.midpoint = haskey(kwargs, :midpoint) ? kwargs[:midpoint] : zeros(DIM); + n.qf = haskey(kwargs, :qf) ? kwargs[:qf] : zeros(DIM); + n.w = haskey(kwargs, :w) ? kwargs[:w] : zeros(DIM+2); + n.sw = haskey(kwargs, :sw) ? kwargs[:sw] : zeros(DIM+2, DIM); + n.lohner = haskey(kwargs, :lohner) ? kwargs[:lohner] : zeros(DIM+2, DIM); + n.prim = haskey(kwargs, :prim) ? kwargs[:prim] : zeros(DIM+2); + n.flux = haskey(kwargs, :flux) ? kwargs[:flux] : zeros(DIM+2); + if haskey(kwargs, :vs_data) + n.vs_data = kwargs[:vs_data] end; - n.neighbor = haskey(kwargs,:neighbor) ? kwargs[:neighbor] : Neighbor(DIM,NDF); + n.neighbor = haskey(kwargs, :neighbor) ? kwargs[:neighbor] : Neighbor(DIM, NDF); n ) - PsData(ps_data::PsData{DIM,NDF};kwargs...) where{DIM,NDF}=(n = new{DIM,NDF}(); + PsData(ps_data::PsData{DIM,NDF}; kwargs...) where {DIM,NDF} = ( + n = new{DIM,NDF}(); for field in fieldnames(PsData{DIM,NDF}) - setfield!(n,field,haskey(kwargs,field) ? kwargs[field] : getfield(ps_data,field)) + setfield!( + n, + field, + haskey(kwargs, field) ? kwargs[field] : getfield(ps_data, field), + ) end; n ) @@ -121,7 +168,7 @@ end """ $(TYPEDEF) """ -mutable struct GhostInsideSolidData{DIM,NDF} <: AbstractGhostPsData{DIM,NDF} +mutable struct GhostInsideSolidData{DIM,NDF} <: AbstractGhostPsData{DIM,NDF} bound_enc::Int midpoint::Vector{Float64} ds::Vector{Float64} @@ -130,16 +177,16 @@ end """ $(TYPEDEF) """ -mutable struct InsideSolidData{DIM,NDF} <: AbstractPsData{DIM,NDF} +mutable struct InsideSolidData{DIM,NDF} <: AbstractPsData{DIM,NDF} bound_enc::Int midpoint::Vector{Float64} ds::Vector{Float64} end -function InsideSolidData(DIM,NDF;kwargs...) +function InsideSolidData(DIM, NDF; kwargs...) return InsideSolidData{DIM,NDF}( - (haskey(kwargs,:bound_enc) ? kwargs[:bound_enc] : 0), - (haskey(kwargs,:midpoint) ? kwargs[:midpoint] : zeros(DIM)), - (haskey(kwargs,:ds) ? kwargs[:ds] : zeros(DIM)), + (haskey(kwargs, :bound_enc) ? kwargs[:bound_enc] : 0), + (haskey(kwargs, :midpoint) ? kwargs[:midpoint] : zeros(DIM)), + (haskey(kwargs, :ds) ? kwargs[:ds] : zeros(DIM)), ) end AbstractInsideSolidData = Union{InsideSolidData,GhostInsideSolidData} @@ -155,21 +202,43 @@ Face shared by cells with the same refinement level. $(TYPEDFIELDS) """ struct FullFace{DIM,NDF,TD<:AbstractPsData{DIM,NDF}}<:InnerFace - "Rotational coefficient of the face. `-1` if `here_data` locates at the negative direction relative to the face." + """ + Rotational coefficient of the face. `-1` if `here_data` locates at the negative direction relative to the face. + """ rot::Float64 - "Direction of the face's normal. 1, 2, 3 correspond to x, y, z respectively." + """ + Direction of the face's normal. 1, 2, 3 correspond to x, y, z respectively. + """ direction::Int - "Coordinates of the face's center." + """ + Coordinates of the face's center. + """ midpoint::Vector{Float64} - "`PsData` on one side of the face. It is guaranteed to be local." + """ + `PsData` on one side of the face. It is guaranteed to be local. + """ here_data::PsData{DIM,NDF} - "`AbstractPsData` on the other side of the face. It can be a ghost one." + """ + `AbstractPsData` on the other side of the face. It can be a ghost one. + """ there_data::TD end # Outer constructor: existing `FullFace{DIM,NDF}(...)` call sites keep working; # `TD` is taken from the concrete runtime type of `there_data`. -function FullFace{DIM,NDF}(rot,direction,midpoint,here_data::PsData{DIM,NDF},there_data::AbstractPsData{DIM,NDF}) where {DIM,NDF} - return FullFace{DIM,NDF,typeof(there_data)}(rot,direction,midpoint,here_data,there_data) +function FullFace{DIM,NDF}( + rot, + direction, + midpoint, + here_data::PsData{DIM,NDF}, + there_data::AbstractPsData{DIM,NDF}, +) where {DIM,NDF} + return FullFace{DIM,NDF,typeof(there_data)}( + rot, + direction, + midpoint, + here_data, + there_data, + ) end """ @@ -182,7 +251,9 @@ struct HangingFace{DIM,NDF}<:InnerFace direction::Int midpoint::Vector{Vector{Float64}} here_data::PsData{DIM,NDF} - "`AbstractPsData`s with higher refinement level." + """ + `AbstractPsData`s with higher refinement level. + """ there_data::Vector{AbstractPsData{DIM,NDF}} end @@ -198,8 +269,20 @@ struct BackHangingFace{DIM,NDF,TD<:AbstractPsData{DIM,NDF}}<:InnerFace here_data::Vector{PsData{DIM,NDF}} there_data::TD end -function BackHangingFace{DIM,NDF}(rot,direction,midpoint,here_data::Vector{PsData{DIM,NDF}},there_data::AbstractPsData{DIM,NDF}) where {DIM,NDF} - return BackHangingFace{DIM,NDF,typeof(there_data)}(rot,direction,midpoint,here_data,there_data) +function BackHangingFace{DIM,NDF}( + rot, + direction, + midpoint, + here_data::Vector{PsData{DIM,NDF}}, + there_data::AbstractPsData{DIM,NDF}, +) where {DIM,NDF} + return BackHangingFace{DIM,NDF,typeof(there_data)}( + rot, + direction, + midpoint, + here_data, + there_data, + ) end """ @@ -214,8 +297,20 @@ struct FluxData{T<:InnerFace,HD<:AbstractPsData,TD<:AbstractPsData} here_data::HD there_data::TD end -function FluxData{T}(rot,direction,midpoint,here_data::AbstractPsData,there_data::AbstractPsData) where {T<:InnerFace} - return FluxData{T,typeof(here_data),typeof(there_data)}(rot,direction,midpoint,here_data,there_data) +function FluxData{T}( + rot, + direction, + midpoint, + here_data::AbstractPsData, + there_data::AbstractPsData, +) where {T<:InnerFace} + return FluxData{T,typeof(here_data),typeof(there_data)}( + rot, + direction, + midpoint, + here_data, + there_data, + ) end mutable struct MeshData @@ -225,5 +320,5 @@ mutable struct MeshData is_ghost_cell::Bool end function MeshData() - return MeshData(0,false,0,false) -end \ No newline at end of file + return MeshData(0, false, 0, false) +end diff --git a/src/Solver/AMR.jl b/src/Solver/AMR.jl index a2f77ae..026bb70 100644 --- a/src/Solver/AMR.jl +++ b/src/Solver/AMR.jl @@ -1,33 +1,49 @@ """ $(TYPEDSIGNATURES) """ -function adaptive_mesh_refinement!(p4est::P_pxest_t,ka::KA;ps_interval=40,vs_interval=80,partition_interval=40,ps_recursive = false, vs_balance=false) +function adaptive_mesh_refinement!( + p4est::P_pxest_t, + ka::KA; + ps_interval = 40, + vs_interval = 80, + partition_interval = 40, + ps_recursive = false, + vs_balance = false, +) ka.kinfo.status.residual.redundant_step>0&&(return nothing) res = maximum(ka.kinfo.status.residual.residual) - converge_ratio = res/ka.kinfo.config.solver.TOLERANCE>100 ? 1 : Int(floor(100*ka.kinfo.config.solver.TOLERANCE/res)) + converge_ratio = + res/ka.kinfo.config.solver.TOLERANCE>100 ? 1 : + Int(floor(100*ka.kinfo.config.solver.TOLERANCE/res)) ps_changed = false vs_changed = false partition_changed = false - if ka.kinfo.config.solver.PS_DYNAMIC_AMR&&ka.kinfo.status.ps_adapt_step > ps_interval*converge_ratio - ps_adaptive_mesh_refinement!(p4est,ka;recursive = ps_recursive) - ps_changed = true;ka.kinfo.status.ps_adapt_step = 1 + if ka.kinfo.config.solver.PS_DYNAMIC_AMR&&ka.kinfo.status.ps_adapt_step > + ps_interval*converge_ratio + ps_adaptive_mesh_refinement!(p4est, ka; recursive = ps_recursive) + ps_changed = true; + ka.kinfo.status.ps_adapt_step = 1 end - if ka.kinfo.config.solver.VS_DYNAMIC_AMR&&ka.kinfo.status.vs_adapt_step > vs_interval*converge_ratio + if ka.kinfo.config.solver.VS_DYNAMIC_AMR&&ka.kinfo.status.vs_adapt_step > + vs_interval*converge_ratio if vs_balance && ps_changed - update_ghost!(p4est,ka) - update_neighbor!(p4est,ka) + update_ghost!(p4est, ka) + update_neighbor!(p4est, ka) end - vs_changed = vs_adaptive_mesh_refinement!(ka;vs_balance = vs_balance) + vs_changed = vs_adaptive_mesh_refinement!(ka; vs_balance = vs_balance) ka.kinfo.status.vs_adapt_step=1 end - if (ka.kinfo.config.solver.PS_DYNAMIC_AMR||ka.kinfo.config.solver.VS_DYNAMIC_AMR)&&ka.kinfo.status.partition_step>partition_interval*converge_ratio&&(ps_changed||vs_changed) + if (ka.kinfo.config.solver.PS_DYNAMIC_AMR||ka.kinfo.config.solver.VS_DYNAMIC_AMR)&&ka.kinfo.status.partition_step>partition_interval*converge_ratio&&( + ps_changed||vs_changed + ) ps_partition!(p4est, ka) - partition_changed = true;ka.kinfo.status.partition_step = 1 + partition_changed = true; + ka.kinfo.status.partition_step = 1 end if ps_changed || partition_changed - amr_recover!(p4est,ka;topology_changed = true, velocity_changed = vs_changed) + amr_recover!(p4est, ka; topology_changed = true, velocity_changed = vs_changed) elseif vs_changed - amr_recover!(p4est,ka;topology_changed = false, velocity_changed = true) + amr_recover!(p4est, ka; topology_changed = false, velocity_changed = true) end return nothing end @@ -51,7 +67,12 @@ end $(TYPEDSIGNATURES) Recover the ghost layers, neighbor relations, immersed boundaries, and faces after an AMR or partition process. """ -function amr_recover!(p4est::P_pxest_t,ka::KA;topology_changed::Bool = true, velocity_changed::Bool = true) +function amr_recover!( + p4est::P_pxest_t, + ka::KA; + topology_changed::Bool = true, + velocity_changed::Bool = true, +) if topology_changed update_ghost!(p4est, ka) update_neighbor!(p4est, ka) diff --git a/src/Solver/Auxiliary.jl b/src/Solver/Auxiliary.jl index 96cb9c8..28ad6b6 100644 --- a/src/Solver/Auxiliary.jl +++ b/src/Solver/Auxiliary.jl @@ -1,9 +1,9 @@ function unpack(t) - return (getfield(t,i) for i in 1:nfields(t)) + return (getfield(t, i) for i = 1:nfields(t)) end -function MPI_tune(f::Function,args...) - for i in 1:MPI.Comm_size(MPI.COMM_WORLD) +function MPI_tune(f::Function, args...) + for i = 1:MPI.Comm_size(MPI.COMM_WORLD) if MPI.Comm_rank(MPI.COMM_WORLD)==i-1 f(args...) end @@ -12,11 +12,11 @@ function MPI_tune(f::Function,args...) end -function fieldvalues_fn(vs_data,aux_df) +function fieldvalues_fn(vs_data, aux_df) NDF = typeof(vs_data).parameters[2] - return [aux_df[:,i] for i in 1:NDF] + return [aux_df[:, i] for i = 1:NDF] end function fieldvalues_fn(vs_data) NDF = typeof(vs_data).parameters[2] - return [vs_data.df[:,i] for i in 1:NDF] + return [vs_data.df[:, i] for i = 1:NDF] end diff --git a/src/Solver/Finalize.jl b/src/Solver/Finalize.jl index d5e6d81..76d2331 100644 --- a/src/Solver/Finalize.jl +++ b/src/Solver/Finalize.jl @@ -2,10 +2,10 @@ $(TYPEDSIGNATURES) Update residuals. """ -function residual_check!(ps_data::PsData,prim::Vector{Float64},kinfo::KInfo) +function residual_check!(ps_data::PsData, prim::Vector{Float64}, kinfo::KInfo) Res = kinfo.status.residual kinfo.status.step%kinfo.config.solver.ST_CHECK_INTERVAL!=0&&(return nothing) - @. Res.sumRes+=(prim-ps_data.prim).^2 + @. Res.sumRes+=(prim-ps_data.prim) .^ 2 @. Res.sumAvg+=abs(prim) return nothing end @@ -14,20 +14,23 @@ function residual_comm!(kinfo::KInfo) fp = PointerWrapper(kinfo.forest.p4est) N = fp.global_num_quadrants[] kinfo.status.step%kinfo.config.solver.ST_CHECK_INTERVAL!=0&&(return nothing) - MPI.Reduce!(Res.sumRes,+,0,MPI.COMM_WORLD) - MPI.Reduce!(Res.sumAvg,+,0,MPI.COMM_WORLD) + MPI.Reduce!(Res.sumRes, +, 0, MPI.COMM_WORLD) + MPI.Reduce!(Res.sumAvg, +, 0, MPI.COMM_WORLD) if MPI.Comm_rank(MPI.COMM_WORLD)==0 @. Res.residual=sqrt(Res.sumRes*N)/(Res.sumAvg+EPS) end - MPI.Bcast!(Res.residual,0,MPI.COMM_WORLD) - Res.sumRes.=0.;Res.sumAvg.=0. + MPI.Bcast!(Res.residual, 0, MPI.COMM_WORLD) + Res.sumRes.=0.0; + Res.sumAvg.=0.0 end """ $(SIGNATURES) Check whether the `residual` and `redundant_step` in [`Status`](@ref) satisfies the convergence criterion. """ function check_for_convergence(ka::KA) - maximum(ka.kinfo.status.residual.residual)ka.kinfo.config.solver.REDUNDANT_STEPS_NUM end diff --git a/src/Solver/Initialize.jl b/src/Solver/Initialize.jl index 344c33d..1b45dbb 100644 --- a/src/Solver/Initialize.jl +++ b/src/Solver/Initialize.jl @@ -2,96 +2,141 @@ """ $(TYPEDSIGNATURES) """ -function initialize_faces!(p4est::Ptr{p4est_t},ka::KA) +function initialize_faces!(p4est::Ptr{p4est_t}, ka::KA) kinfo = ka.kinfo p_data = pointer_from_objref(ka) - GC.@preserve ka AMR_face_iterate(p4est;user_data = p_data,ghost = kinfo.forest.ghost) do ip,data + GC.@preserve ka AMR_face_iterate( + p4est; + user_data = p_data, + ghost = kinfo.forest.ghost, + ) do ip, data ka = unsafe_pointer_to_objref(data) if ip.sides.elem_count[]==1 - initialize_domain_face!(iPointerWrapper(ip.sides,p4est_iter_face_side_t,0),ka) + initialize_domain_face!( + iPointerWrapper(ip.sides, p4est_iter_face_side_t, 0), + ka, + ) else - Aside = iPointerWrapper(ip.sides,p4est_iter_face_side_t,0) - Bside = iPointerWrapper(ip.sides,p4est_iter_face_side_t,1) + Aside = iPointerWrapper(ip.sides, p4est_iter_face_side_t, 0) + Bside = iPointerWrapper(ip.sides, p4est_iter_face_side_t, 1) if Aside.is_hanging[]==0 if Aside.is.full.is_ghost[]==0 if Bside.is_hanging[]==0 - initialize_full_face!(Aside,ka) + initialize_full_face!(Aside, ka) else - initialize_hanging_face!(Aside,ka) + initialize_hanging_face!(Aside, ka) end elseif Bside.is_hanging[]==0 - initialize_full_face!(Bside,ka) + initialize_full_face!(Bside, ka) else - initialize_back_hanging_face!(Bside,ka) + initialize_back_hanging_face!(Bside, ka) end elseif Bside.is.full.is_ghost[]==0 - initialize_hanging_face!(Bside,ka) + initialize_hanging_face!(Bside, ka) else - initialize_back_hanging_face!(Aside,ka) + initialize_back_hanging_face!(Aside, ka) end end end end -function solid_full_face_check(base_quad,faceid) +function solid_full_face_check(base_quad, faceid) neighbor = base_quad.neighbor.data[faceid][1] - (!isa(neighbor,PsData)||neighbor.bound_enc<0) && return true + (!isa(neighbor, PsData)||neighbor.bound_enc<0) && return true return false end -function solid_hanging_face_check(base_quad,faceid) - ids = findall(x->(isa(x,PsData)&&x.bound_enc>=0),base_quad.neighbor.data[faceid]) +function solid_hanging_face_check(base_quad, faceid) + ids = findall(x->(isa(x, PsData)&&x.bound_enc>=0), base_quad.neighbor.data[faceid]) return ids end -function initialize_domain_face!(side::PW_pxest_iter_face_side_t,ka::KA{DIM,NDF}) where{DIM,NDF} +function initialize_domain_face!( + side::PW_pxest_iter_face_side_t, + ka::KA{DIM,NDF}, +) where {DIM,NDF} faces = ka.kdata.field.faces - base_quad = - unsafe_pointer_to_objref(pointer(PointerWrapper(P4estPsData, - side.is.full.quad.p.user_data[]).ps_data)) - isa(base_quad,InsideSolidData) && return nothing + base_quad = unsafe_pointer_to_objref( + pointer(PointerWrapper(P4estPsData, side.is.full.quad.p.user_data[]).ps_data), + ) + isa(base_quad, InsideSolidData) && return nothing faceid = side.face[]+1 direction = get_dir(faceid) rot = get_rot(faceid) midpoint = copy(base_quad.midpoint) midpoint[direction] -= 0.5*rot*base_quad.ds[direction] domain = ka.kinfo.config.domain[faceid] - push!(faces,DomainFace{DIM,NDF,typeof(domain).parameters[1]}(rot,direction,midpoint,domain,base_quad)) + push!( + faces, + DomainFace{DIM,NDF,typeof(domain).parameters[1]}( + rot, + direction, + midpoint, + domain, + base_quad, + ), + ) return nothing end -function initialize_full_face!(side::PW_pxest_iter_face_side_t,ka::KA{DIM,NDF}) where{DIM,NDF} +function initialize_full_face!( + side::PW_pxest_iter_face_side_t, + ka::KA{DIM,NDF}, +) where {DIM,NDF} faces = ka.kdata.field.faces - base_quad = - unsafe_pointer_to_objref(pointer(PointerWrapper(P4estPsData, - side.is.full.quad.p.user_data[]).ps_data)) - isa(base_quad,InsideSolidData) && return nothing + base_quad = unsafe_pointer_to_objref( + pointer(PointerWrapper(P4estPsData, side.is.full.quad.p.user_data[]).ps_data), + ) + isa(base_quad, InsideSolidData) && return nothing faceid = side.face[] + 1 if base_quad.bound_enc<0 - solid_full_face_check(base_quad,faceid) && return nothing + solid_full_face_check(base_quad, faceid) && return nothing base_quad = base_quad.neighbor.data[faceid][1] - faceid += faceid%2==0 ? -1 : 1 + faceid += faceid%2==0 ? -1 : 1 end direction = get_dir(faceid) rot = get_rot(faceid) midpoint = copy(base_quad.midpoint) midpoint[direction] -= 0.5*rot*base_quad.ds[direction] kinfo = ka.kinfo - if midpoint[direction] == kinfo.config.geometry[2*direction-1]||midpoint[direction] == kinfo.config.geometry[2*direction] - there_midpoint = copy(midpoint);there_midpoint[direction] -= 0.5*rot*base_quad.ds[direction] - push!(faces,FullFace{DIM,NDF}(rot,direction,midpoint,base_quad,periodic_ghost_cell(there_midpoint,base_quad.neighbor.data[faceid][1]))) + if midpoint[direction] == kinfo.config.geometry[2*direction-1]||midpoint[direction] == + kinfo.config.geometry[2*direction] + there_midpoint = copy(midpoint); + there_midpoint[direction] -= 0.5*rot*base_quad.ds[direction] + push!( + faces, + FullFace{DIM,NDF}( + rot, + direction, + midpoint, + base_quad, + periodic_ghost_cell(there_midpoint, base_quad.neighbor.data[faceid][1]), + ), + ) else - push!(faces,FullFace{DIM,NDF}(rot,direction,midpoint,base_quad,base_quad.neighbor.data[faceid][1])) + push!( + faces, + FullFace{DIM,NDF}( + rot, + direction, + midpoint, + base_quad, + base_quad.neighbor.data[faceid][1], + ), + ) end return nothing end -function initialize_hanging_face!(side::PW_pxest_iter_face_side_t,ka::KA{DIM,NDF}) where{DIM,NDF} +function initialize_hanging_face!( + side::PW_pxest_iter_face_side_t, + ka::KA{DIM,NDF}, +) where {DIM,NDF} faces = ka.kdata.field.faces - base_quad = - unsafe_pointer_to_objref(pointer(PointerWrapper(P4estPsData, - side.is.full.quad.p.user_data[]).ps_data)) - isa(base_quad,InsideSolidData) && return nothing + base_quad = unsafe_pointer_to_objref( + pointer(PointerWrapper(P4estPsData, side.is.full.quad.p.user_data[]).ps_data), + ) + isa(base_quad, InsideSolidData) && return nothing faceid = side.face[] + 1 if base_quad.bound_enc<0 - ids = solid_hanging_face_check(base_quad,faceid) - isempty(ids) && return nothing + ids = solid_hanging_face_check(base_quad, faceid) + isempty(ids) && return nothing here_data = base_quad.neighbor.data[faceid][ids] faceid += faceid%2==0 ? -1 : 1 direction = get_dir(faceid) @@ -100,7 +145,10 @@ function initialize_hanging_face!(side::PW_pxest_iter_face_side_t,ka::KA{DIM,NDF for i in eachindex(midpoint) midpoint[i][direction] -= 0.5*rot*here_data[i].ds[direction] end - push!(faces,BackHangingFace{DIM,NDF}(rot,direction,midpoint,here_data,base_quad)) + push!( + faces, + BackHangingFace{DIM,NDF}(rot, direction, midpoint, here_data, base_quad), + ) return nothing end direction = get_dir(faceid) @@ -108,36 +156,53 @@ function initialize_hanging_face!(side::PW_pxest_iter_face_side_t,ka::KA{DIM,NDF neighbor = base_quad.neighbor.data[faceid] midpoint = [copy(x.midpoint) for x in neighbor] for i in eachindex(neighbor) - midpoint[i][direction] = base_quad.midpoint[direction] - 0.5 * rot * base_quad.ds[direction] + midpoint[i][direction] = + base_quad.midpoint[direction] - 0.5 * rot * base_quad.ds[direction] end kinfo = ka.kinfo - if midpoint[1][direction] == kinfo.config.geometry[2*direction-1]||midpoint[1][direction] == kinfo.config.geometry[2*direction] + if midpoint[1][direction] == kinfo.config.geometry[2*direction-1]||midpoint[1][direction] == + kinfo.config.geometry[2*direction] periodic_midpoints = [copy(x) for x in midpoint] for i in eachindex(periodic_midpoints) periodic_midpoints[i][direction] -= 0.5*rot*neighbor[i].ds[direction] end - push!(faces,HangingFace{DIM,NDF}(rot,direction,midpoint,base_quad,periodic_ghost_cell(periodic_midpoints,neighbor))) + push!( + faces, + HangingFace{DIM,NDF}( + rot, + direction, + midpoint, + base_quad, + periodic_ghost_cell(periodic_midpoints, neighbor), + ), + ) else - push!(faces,HangingFace{DIM,NDF}(rot,direction,midpoint,base_quad,neighbor)) + push!(faces, HangingFace{DIM,NDF}(rot, direction, midpoint, base_quad, neighbor)) end return nothing end -function initialize_back_hanging_face!(side::PointerWrapper{p4est_iter_face_side_t},ka::KA{DIM,NDF}) where{DIM,NDF} +function initialize_back_hanging_face!( + side::PointerWrapper{p4est_iter_face_side_t}, + ka::KA{DIM,NDF}, +) where {DIM,NDF} faces = ka.kdata.field.faces is_ghost = Base.unsafe_wrap( Vector{Int8}, Ptr{Int8}(pointer(side.is.hanging.is_ghost)), 2^(DIM - 1), ) - ids = findall(x->x==0,is_ghost).-1 + ids = findall(x->x==0, is_ghost) .- 1 faceid = side.face[]+1 here_data = Vector{PsData{DIM,NDF}}() for i in ids - qp = PointerWrapper(iPointerWrapper(side.is.hanging.quad, Ptr{p4est_quadrant_t}, i)[]) - base_quad = - unsafe_pointer_to_objref(pointer(PointerWrapper(P4estPsData, qp.p.user_data[]).ps_data)) - (!isa(base_quad,PsData)||base_quad.bound_enc<0) && continue - push!(here_data,base_quad) + qp = PointerWrapper( + iPointerWrapper(side.is.hanging.quad, Ptr{p4est_quadrant_t}, i)[], + ) + base_quad = unsafe_pointer_to_objref( + pointer(PointerWrapper(P4estPsData, qp.p.user_data[]).ps_data), + ) + (!isa(base_quad, PsData)||base_quad.bound_enc<0) && continue + push!(here_data, base_quad) end isempty(here_data)&&return nothing direction = get_dir(faceid) @@ -147,12 +212,35 @@ function initialize_back_hanging_face!(side::PointerWrapper{p4est_iter_face_side midpoint[i][direction] -= 0.5*rot*here_data[i].ds[direction] end kinfo = ka.kinfo - if midpoint[1][direction] == kinfo.config.geometry[2*direction-1]||midpoint[1][direction] == kinfo.config.geometry[2*direction] + if midpoint[1][direction] == kinfo.config.geometry[2*direction-1]||midpoint[1][direction] == + kinfo.config.geometry[2*direction] there_midpoint = copy(first(here_data).neighbor.data[faceid][1].midpoint) - there_midpoint[direction] = midpoint[1][direction] - rot*first(here_data).ds[direction] - push!(faces,BackHangingFace{DIM,NDF}(rot,direction,midpoint,here_data,periodic_ghost_cell(there_midpoint,first(here_data).neighbor.data[faceid][1]))) + there_midpoint[direction] = + midpoint[1][direction] - rot*first(here_data).ds[direction] + push!( + faces, + BackHangingFace{DIM,NDF}( + rot, + direction, + midpoint, + here_data, + periodic_ghost_cell( + there_midpoint, + first(here_data).neighbor.data[faceid][1], + ), + ), + ) else - push!(faces,BackHangingFace{DIM,NDF}(rot,direction,midpoint,here_data,first(here_data).neighbor.data[faceid][1])) + push!( + faces, + BackHangingFace{DIM,NDF}( + rot, + direction, + midpoint, + here_data, + first(here_data).neighbor.data[faceid][1], + ), + ) end return nothing end @@ -161,88 +249,123 @@ end """ $(TYPEDSIGNATURES) """ -function initialize_faces!(p4est::Ptr{p8est_t},ka::KA) +function initialize_faces!(p4est::Ptr{p8est_t}, ka::KA) kinfo = ka.kinfo p_data = pointer_from_objref(ka) - GC.@preserve ka AMR_face_iterate(p4est;user_data = p_data,ghost = kinfo.forest.ghost) do ip,data + GC.@preserve ka AMR_face_iterate( + p4est; + user_data = p_data, + ghost = kinfo.forest.ghost, + ) do ip, data ka = unsafe_pointer_to_objref(data) if ip.sides.elem_count[]==1 - initialize_domain_face!(iPointerWrapper(ip.sides,p8est_iter_face_side_t,0),ka) + initialize_domain_face!( + iPointerWrapper(ip.sides, p8est_iter_face_side_t, 0), + ka, + ) else - Aside = iPointerWrapper(ip.sides,p8est_iter_face_side_t,0) - Bside = iPointerWrapper(ip.sides,p8est_iter_face_side_t,1) + Aside = iPointerWrapper(ip.sides, p8est_iter_face_side_t, 0) + Bside = iPointerWrapper(ip.sides, p8est_iter_face_side_t, 1) if Aside.is_hanging[]==0 if Aside.is.full.is_ghost[]==0 if Bside.is_hanging[]==0 - initialize_full_face!(Aside,ka) + initialize_full_face!(Aside, ka) else - initialize_hanging_face!(Aside,ka) + initialize_hanging_face!(Aside, ka) end elseif Bside.is_hanging[]==0 - initialize_full_face!(Bside,ka) + initialize_full_face!(Bside, ka) else - initialize_back_hanging_face!(Bside,ka) + initialize_back_hanging_face!(Bside, ka) end elseif Bside.is.full.is_ghost[]==0 - initialize_hanging_face!(Bside,ka) + initialize_hanging_face!(Bside, ka) else - initialize_back_hanging_face!(Aside,ka) + initialize_back_hanging_face!(Aside, ka) end end end end -function initialize_back_hanging_face!(side::PointerWrapper{p8est_iter_face_side_t},ka::KA{DIM,NDF}) where{DIM,NDF} +function initialize_back_hanging_face!( + side::PointerWrapper{p8est_iter_face_side_t}, + ka::KA{DIM,NDF}, +) where {DIM,NDF} faces = ka.kdata.field.faces is_ghost = Base.unsafe_wrap( Vector{Int8}, Ptr{Int8}(pointer(side.is.hanging.is_ghost)), 2^(DIM - 1), ) - ids = findall(x->x==0,is_ghost).-1 + ids = findall(x->x==0, is_ghost) .- 1 faceid = side.face[]+1 here_data = Vector{PsData{DIM,NDF}}() for i in ids - qp = PointerWrapper(iPointerWrapper(side.is.hanging.quad, Ptr{p8est_quadrant_t}, i)[]) - base_quad = - unsafe_pointer_to_objref(pointer(PointerWrapper(P4estPsData, qp.p.user_data[]).ps_data)) - (!isa(base_quad,PsData)||base_quad.bound_enc<0) && continue - push!(here_data,base_quad) + qp = PointerWrapper( + iPointerWrapper(side.is.hanging.quad, Ptr{p8est_quadrant_t}, i)[], + ) + base_quad = unsafe_pointer_to_objref( + pointer(PointerWrapper(P4estPsData, qp.p.user_data[]).ps_data), + ) + (!isa(base_quad, PsData)||base_quad.bound_enc<0) && continue + push!(here_data, base_quad) end isempty(here_data)&&return nothing direction = get_dir(faceid) rot = get_rot(faceid) midpoint = [copy(x.midpoint) for x in here_data] - for i in eachindex(midpoint) - midpoint[i][direction] -= 0.5*rot*here_data[i].ds[direction] - end + for i in eachindex(midpoint) + midpoint[i][direction] -= 0.5*rot*here_data[i].ds[direction] + end # push!(faces,BackHangingFace(rot,direction,midpoint,here_data,first(here_data).neighbor.data[faceid][1])) kinfo = ka.kinfo - if midpoint[1][direction] == kinfo.config.geometry[2*direction-1]||midpoint[1][direction] == kinfo.config.geometry[2*direction] + if midpoint[1][direction] == kinfo.config.geometry[2*direction-1]||midpoint[1][direction] == + kinfo.config.geometry[2*direction] there_midpoint = copy(first(here_data).neighbor.data[faceid][1].midpoint) - there_midpoint[direction] = midpoint[1][direction] - rot*first(here_data).ds[direction] - push!(faces,BackHangingFace{DIM,NDF}(rot,direction,midpoint,here_data,periodic_ghost_cell(there_midpoint,first(here_data).neighbor.data[faceid][1]))) + there_midpoint[direction] = + midpoint[1][direction] - rot*first(here_data).ds[direction] + push!( + faces, + BackHangingFace{DIM,NDF}( + rot, + direction, + midpoint, + here_data, + periodic_ghost_cell( + there_midpoint, + first(here_data).neighbor.data[faceid][1], + ), + ), + ) else - push!(faces,BackHangingFace{DIM,NDF}(rot,direction,midpoint,here_data,first(here_data).neighbor.data[faceid][1])) + push!( + faces, + BackHangingFace{DIM,NDF}( + rot, + direction, + midpoint, + here_data, + first(here_data).neighbor.data[faceid][1], + ), + ) end return nothing end -function initial_prim(ic::Uniform;kwargs...) +function initial_prim(ic::Uniform; kwargs...) return ic.ic end -function initial_prim(ic::PCoordFn;midpoint::AbstractVector{Float64},kinfo::KInfo) - return ic.PCIC_fn(midpoint,kinfo) +function initial_prim(ic::PCoordFn; midpoint::AbstractVector{Float64}, kinfo::KInfo) + return ic.PCIC_fn(midpoint, kinfo) end function re_init_vs4est!(trees, kinfo) for i in eachindex(trees.data) for j in eachindex(trees.data[i]) ps_data = trees.data[i][j] - isa(ps_data,InsideSolidData)&&continue + isa(ps_data, InsideSolidData)&&continue # ps_data.bound_enc<0 && continue - ps_data.vs_data.df .= - discrete_maxwell(ps_data, kinfo) + ps_data.vs_data.df .= discrete_maxwell(ps_data, kinfo) end end end @@ -255,7 +378,7 @@ This is intended for initial physical-space AMR: after refinement creates children from interpolated parent data, call this before rebuilding ghosts so new fine cells receive the exact initial state at their own cell centers. """ -function reinitialize_initial_condition!(ka::KA{DIM,NDF}) where{DIM,NDF} +function reinitialize_initial_condition!(ka::KA{DIM,NDF}) where {DIM,NDF} kinfo = ka.kinfo ic = kinfo.config.IC for tree in ka.kdata.field.trees.data @@ -277,30 +400,30 @@ end """ $(TYPEDSIGNATURES) """ -function pre_refine!(p4est::Ptr{p4est_t},kinfo::KInfo) - user_defined_ps_refine!(p4est,kinfo) - AMR_partition(p4est) do p4est,which_tree,quadrant +function pre_refine!(p4est::Ptr{p4est_t}, kinfo::KInfo) + user_defined_ps_refine!(p4est, kinfo) + AMR_partition(p4est) do p4est, which_tree, quadrant fp = PointerWrapper(p4est) kinfo = unsafe_pointer_to_objref(pointer(fp.user_pointer)) ibs = kinfo.config.IB qp = PointerWrapper(quadrant) - ds,midpoint = quad_to_cell(fp,which_tree,qp) + ds, midpoint = quad_to_cell(fp, which_tree, qp) for ib in ibs - if solid_box_flag(midpoint,ds,ib) + if solid_box_flag(midpoint, ds, ib) return Cint(1) end end return Cint(0) end - trees = initialize_MeshData!(p4est,kinfo) - data = [kinfo,trees] + trees = initialize_MeshData!(p4est, kinfo) + data = [kinfo, trees] PointerWrapper(p4est).user_pointer = pointer_from_objref(data) GC.@preserve data begin - search_radius_refine!(p4est,kinfo) + search_radius_refine!(p4est, kinfo) cell_type_decision!(p4est) pre_ps_coarsen!(p4est) pre_ps_balance!(p4est) - meshed_partition!(p4est,trees) + meshed_partition!(p4est, trees) end PointerWrapper(p4est).user_pointer = pointer_from_objref(kinfo) return trees @@ -308,30 +431,30 @@ end """ $(TYPEDSIGNATURES) """ -function pre_refine!(p4est::Ptr{p8est_t},kinfo::KInfo) - user_defined_ps_refine!(p4est,kinfo) - AMR_partition(p4est) do p4est,which_tree,quadrant +function pre_refine!(p4est::Ptr{p8est_t}, kinfo::KInfo) + user_defined_ps_refine!(p4est, kinfo) + AMR_partition(p4est) do p4est, which_tree, quadrant fp = PointerWrapper(p4est) kinfo = unsafe_pointer_to_objref(pointer(fp.user_pointer)) ibs = kinfo.config.IB qp = PointerWrapper(quadrant) - ds,midpoint = quad_to_cell(fp,which_tree,qp) + ds, midpoint = quad_to_cell(fp, which_tree, qp) for ib in ibs - if solid_box_flag(midpoint,ds,ib) + if solid_box_flag(midpoint, ds, ib) return Cint(1) end end return Cint(0) end - trees = initialize_MeshData!(p4est,kinfo) - data = [kinfo,trees] + trees = initialize_MeshData!(p4est, kinfo) + data = [kinfo, trees] PointerWrapper(p4est).user_pointer = pointer_from_objref(data) GC.@preserve data begin - search_radius_refine!(p4est,kinfo) + search_radius_refine!(p4est, kinfo) cell_type_decision!(p4est) pre_ps_coarsen!(p4est) pre_ps_balance!(p4est) - meshed_partition!(p4est,trees) + meshed_partition!(p4est, trees) end PointerWrapper(p4est).user_pointer = pointer_from_objref(kinfo) return trees @@ -340,17 +463,19 @@ end """ $(TYPEDSIGNATURES) """ -function initialize_ps!(p4est::Ptr{p4est_t},kinfo::KInfo{DIM,NDF}) where{DIM,NDF} +function initialize_ps!(p4est::Ptr{p4est_t}, kinfo::KInfo{DIM,NDF}) where {DIM,NDF} fp = PointerWrapper(p4est) - trees_data = - Vector{Vector{AbstractPsData{DIM,NDF}}}(undef, fp.last_local_tree[] - fp.first_local_tree[] + 1) + trees_data = Vector{Vector{AbstractPsData{DIM,NDF}}}( + undef, + fp.last_local_tree[] - fp.first_local_tree[] + 1, + ) for i in eachindex(trees_data) trees_data[i] = AbstractPsData{DIM,NDF}[] end trees = PsTrees{DIM,NDF}(trees_data, fp.first_local_tree[] - 1) - data = [kinfo,trees] + data = [kinfo, trees] p_data = pointer_from_objref(data) - GC.@preserve data AMR_volume_iterate(p4est;user_data = p_data) do ip,data,dp + GC.@preserve data AMR_volume_iterate(p4est; user_data = p_data) do ip, data, dp kinfo, trees = unsafe_pointer_to_objref(data) ds, midpoint = quad_to_cell(ip.p4est, ip.treeid[], ip.quad) mesh_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) @@ -363,16 +488,20 @@ function initialize_ps!(p4est::Ptr{p4est_t},kinfo::KInfo{DIM,NDF}) where{DIM,NDF ps_data.quadid = global_quadid(ip) ps_data.ds .= ds ps_data.midpoint .= midpoint - ps_data.prim .= initial_prim(ic;midpoint = ps_data.midpoint,kinfo = kinfo) + ps_data.prim .= initial_prim(ic; midpoint = ps_data.midpoint, kinfo = kinfo) ps_data.w .= get_conserved(ps_data, kinfo) ps_data.vs_data = initialize_vs_data(ps_data.prim, kinfo) if mesh_data.is_ghost_cell ps_data.bound_enc = -mesh_data.in_search_radius end else - inside_quad = InsideSolidData{typeof(kinfo).parameters...}(-mesh_data.in_box,midpoint,ds) + inside_quad = InsideSolidData{typeof(kinfo).parameters...}( + -mesh_data.in_box, + midpoint, + ds, + ) dp[] = P4estPsData(pointer_from_objref(inside_quad)) - push!(trees.data[treeid],inside_quad) + push!(trees.data[treeid], inside_quad) end end # re_init_vs4est!(trees, kinfo) @@ -382,13 +511,14 @@ end """ $(TYPEDSIGNATURES) """ -function initialize_ps!(p4est::Ptr{p8est_t},kinfo::KInfo{DIM,NDF}) where{DIM,NDF} +function initialize_ps!(p4est::Ptr{p8est_t}, kinfo::KInfo{DIM,NDF}) where {DIM,NDF} fp = PointerWrapper(p4est) - trees_data = [AbstractPsData{DIM,NDF}[] for _ in 1:fp.last_local_tree[] - fp.first_local_tree[] + 1] + trees_data = + [AbstractPsData{DIM,NDF}[] for _ = 1:(fp.last_local_tree[]-fp.first_local_tree[]+1)] trees = PsTrees{DIM,NDF}(trees_data, fp.first_local_tree[] - 1) - data = [kinfo,trees] + data = [kinfo, trees] p_data = pointer_from_objref(data) - GC.@preserve data AMR_volume_iterate(p4est;user_data = p_data) do ip,data,dp + GC.@preserve data AMR_volume_iterate(p4est; user_data = p_data) do ip, data, dp kinfo, trees = unsafe_pointer_to_objref(data) ds, midpoint = quad_to_cell(ip.p4est, ip.treeid[], ip.quad) mesh_data = unsafe_pointer_to_objref(pointer(dp.ps_data)) @@ -401,16 +531,20 @@ function initialize_ps!(p4est::Ptr{p8est_t},kinfo::KInfo{DIM,NDF}) where{DIM,NDF ps_data.quadid = global_quadid(ip) ps_data.ds .= ds ps_data.midpoint .= midpoint - ps_data.prim .= initial_prim(ic;midpoint = ps_data.midpoint,kinfo) + ps_data.prim .= initial_prim(ic; midpoint = ps_data.midpoint, kinfo) ps_data.w .= get_conserved(ps_data, kinfo) ps_data.vs_data = initialize_vs_data(ps_data.prim, kinfo) if mesh_data.is_ghost_cell ps_data.bound_enc = -mesh_data.in_search_radius end else - inside_quad = InsideSolidData{typeof(kinfo).parameters...}(-mesh_data.in_box,midpoint,ds) + inside_quad = InsideSolidData{typeof(kinfo).parameters...}( + -mesh_data.in_box, + midpoint, + ds, + ) dp[] = P4estPsData(pointer_from_objref(inside_quad)) - push!(trees.data[treeid],inside_quad) + push!(trees.data[treeid], inside_quad) end end # re_init_vs4est!(trees, kinfo) @@ -421,7 +555,7 @@ end $(TYPEDSIGNATURES) Initialize field for 2D case. """ -function initialize_trees!(kinfo::KInfo{DIM,NDF}) where{DIM,NDF} +function initialize_trees!(kinfo::KInfo{DIM,NDF}) where {DIM,NDF} GC.@preserve kinfo begin connectivity_ps = set_connectivity(kinfo) p4est = AMR_4est_new( @@ -431,9 +565,9 @@ function initialize_trees!(kinfo::KInfo{DIM,NDF}) where{DIM,NDF} pointer_from_objref(kinfo), ) kinfo.forest.p4est = p4est - mesh_tree = pre_refine!(p4est,kinfo) + mesh_tree = pre_refine!(p4est, kinfo) GC.@preserve mesh_tree begin - trees = initialize_ps!(p4est,kinfo) + trees = initialize_ps!(p4est, kinfo) end return p4est, trees end @@ -443,7 +577,7 @@ end $(TYPEDSIGNATURES) Initialize field for 3D case. """ -function initialize_trees!(kinfo::KInfo{3,NDF}) where{NDF} +function initialize_trees!(kinfo::KInfo{3,NDF}) where {NDF} GC.@preserve kinfo begin connectivity_ps = set_connectivity(kinfo) p4est = AMR_4est_new( @@ -453,9 +587,9 @@ function initialize_trees!(kinfo::KInfo{3,NDF}) where{NDF} pointer_from_objref(kinfo), ) kinfo.forest.p4est = p4est - mesh_tree = pre_refine!(p4est,kinfo) + mesh_tree = pre_refine!(p4est, kinfo) GC.@preserve mesh_tree begin - trees = initialize_ps!(p4est,kinfo) + trees = initialize_ps!(p4est, kinfo) end return p4est, trees end @@ -465,13 +599,13 @@ end $(TYPEDSIGNATURES) Initialize [`Ghost`](@ref) structure. """ -function initialize_ghost(p4est::P_pxest_t,kinfo::KInfo) - ghost_buffer, ghost_info = initialize_ghost_pool(p4est,kinfo) +function initialize_ghost(p4est::P_pxest_t, kinfo::KInfo) + ghost_buffer, ghost_info = initialize_ghost_pool(p4est, kinfo) ghost_wrap = initialize_ghost_wrap(kinfo, ghost_buffer, ghost_info) return Ghost(ghost_buffer, ghost_wrap, ghost_info) end -function initialize_forest!(p4est,kinfo::KInfo) +function initialize_forest!(p4est, kinfo::KInfo) kinfo.forest.p4est = p4est ghost_ps = AMR_ghost_new(p4est) mesh_ps = AMR_mesh_new(p4est, ghost_ps) @@ -485,9 +619,9 @@ Initial vs_balance. Before calling the function, ghost and neighbor should be in """ function initialize_balanced_vs!(ka::KA) vs_balance!(ka) - re_init_vs4est!(ka.kdata.field.trees,ka.kinfo) + re_init_vs4est!(ka.kdata.field.trees, ka.kinfo) vs_ghost_exchange!(ka.kinfo.forest.p4est, ka) - update_neighbor!(ka.kinfo.forest.p4est,ka) + update_neighbor!(ka.kinfo.forest.p4est, ka) end """ @@ -497,24 +631,33 @@ Initialize everthing according to `config` dictionary. # Initial mesh pre-refinement, run at the end of `initialize`: apply `ps_adaptive_mesh_refinement!` # `steps` times (each followed by `amr_recover!` to rebuild ghost/neighbor/face data), optionally # re-applying the initial condition after each pass so newly refined cells get the exact IC. -function _prerefine!(p4est::P_pxest_t, ka::KA, steps::Integer, recursive::Bool, reinit_ic::Bool) - for _ in 1:steps +function _prerefine!( + p4est::P_pxest_t, + ka::KA, + steps::Integer, + recursive::Bool, + reinit_ic::Bool, +) + for _ = 1:steps ps_adaptive_mesh_refinement!(p4est, ka; recursive = recursive) reinit_ic && reinitialize_initial_condition!(ka) amr_recover!(p4est, ka) end return nothing end -function initialize(config::Dict; - prerefine_steps::Integer = Solver(config).AMR_DYNAMIC_PS_MAXLEVEL, - prerefine_recursive::Bool = false, prerefine_reinit_ic::Bool = true) +function initialize( + config::Dict; + prerefine_steps::Integer = Solver(config).AMR_DYNAMIC_PS_MAXLEVEL, + prerefine_recursive::Bool = false, + prerefine_reinit_ic::Bool = true, +) kinfo = KInfo(config) p4est, trees = initialize_trees!(kinfo) kdata = KData(trees) - ka = KA(kinfo,kdata) + ka = KA(kinfo, kdata) PointerWrapper(p4est).user_pointer = pointer_from_objref(ka) ps_partition!(p4est, ka) - initialize_forest!(p4est,kinfo) + initialize_forest!(p4est, kinfo) kdata.ghost = initialize_ghost(p4est, kinfo) initialize_neighbor_data!(p4est, ka) initialize_solid_neighbor!(ka) @@ -522,7 +665,7 @@ function initialize(config::Dict; initialize_immersed_boundaries!(ka) _prerefine!(p4est, ka, prerefine_steps, prerefine_recursive, prerefine_reinit_ic) execute_check!(p4est, ka) # report the status once initialization (incl. pre-refinement) is complete - return p4est,ka + return p4est, ka end """ $(TYPEDSIGNATURES) @@ -536,31 +679,36 @@ first load-balancing partition, runs the solution-driven initial mesh pre-refine keyword arguments below), and finally reports the initial status. Returns `(p4est, ka)`: -- `p4est` — opaque pointer to the p4est forest (the parallel mesh topology); -- `ka` — the [`KA`](@ref) object holding all solver data, configuration and status. + + - `p4est` — opaque pointer to the p4est forest (the parallel mesh topology); + - `ka` — the [`KA`](@ref) object holding all solver data, configuration and status. Pass both to [`solve!`](@ref) (or to the individual per-step driver functions), then to [`save_result`](@ref) and [`finalize!`](@ref). # Keyword arguments — initial mesh pre-refinement -- `prerefine_steps::Integer = solver.AMR_DYNAMIC_PS_MAXLEVEL` — number of - [`ps_adaptive_mesh_refinement!`](@ref) passes applied after the base setup; the default builds - the mesh up to the dynamic physical-space max level. Pass `0` to skip. -- `prerefine_recursive::Bool = false` — `recursive` flag for those passes. -- `prerefine_reinit_ic::Bool = true` — re-apply the initial condition - ([`reinitialize_initial_condition!`](@ref)) after each pass, so newly refined cells get the - exact IC (recommended for sharp initial conditions, e.g. Riemann / blast waves). + + - `prerefine_steps::Integer = solver.AMR_DYNAMIC_PS_MAXLEVEL` — number of + [`ps_adaptive_mesh_refinement!`](@ref) passes applied after the base setup; the default builds + the mesh up to the dynamic physical-space max level. Pass `0` to skip. + - `prerefine_recursive::Bool = false` — `recursive` flag for those passes. + - `prerefine_reinit_ic::Bool = true` — re-apply the initial condition + ([`reinitialize_initial_condition!`](@ref)) after each pass, so newly refined cells get the + exact IC (recommended for sharp initial conditions, e.g. Riemann / blast waves). """ -function initialize(config::Configure{DIM,NDF}; - prerefine_steps::Integer = config.solver.AMR_DYNAMIC_PS_MAXLEVEL, - prerefine_recursive::Bool = false, prerefine_reinit_ic::Bool = true) where{DIM,NDF} +function initialize( + config::Configure{DIM,NDF}; + prerefine_steps::Integer = config.solver.AMR_DYNAMIC_PS_MAXLEVEL, + prerefine_recursive::Bool = false, + prerefine_reinit_ic::Bool = true, +) where {DIM,NDF} kinfo = KInfo(config) p4est, trees = initialize_trees!(kinfo) kdata = KData(trees) - ka = KA(kinfo,kdata) + ka = KA(kinfo, kdata) PointerWrapper(p4est).user_pointer = pointer_from_objref(ka) ps_partition!(p4est, ka) - initialize_forest!(p4est,kinfo) + initialize_forest!(p4est, kinfo) kdata.ghost = initialize_ghost(p4est, kinfo) initialize_neighbor_data!(p4est, ka) initialize_balanced_vs!(ka) @@ -569,5 +717,5 @@ function initialize(config::Configure{DIM,NDF}; initialize_immersed_boundaries!(ka) _prerefine!(p4est, ka, prerefine_steps, prerefine_recursive, prerefine_reinit_ic) execute_check!(p4est, ka) # report the status once initialization (incl. pre-refinement) is complete - return p4est,ka + return p4est, ka end diff --git a/src/Solver/Solver.jl b/src/Solver/Solver.jl index e2e6abe..68dd2c7 100644 --- a/src/Solver/Solver.jl +++ b/src/Solver/Solver.jl @@ -3,9 +3,16 @@ include("Auxiliary.jl") include("Finalize.jl") include("Initialize.jl") export Configure, Uniform, PCoordFn, Solver, Output, UDF, check_vs_setting -export KA, KInfo, KData, Forest, Status, Residual, Ghost, GhostBuffer, GhostInfo, PsTrees, Field +export KA, + KInfo, KData, Forest, Status, Residual, Ghost, GhostBuffer, GhostInfo, PsTrees, Field export residual_check!, finalize!, check_for_convergence -export initialize, initialize_ps!, initialize_ghost, initialize_trees!, pre_refine!, initialize_faces!, reinitialize_initial_condition! +export initialize, + initialize_ps!, + initialize_ghost, + initialize_trees!, + pre_refine!, + initialize_faces!, + reinitialize_initial_condition! export adaptive_mesh_refinement!, amr_recover! export solve! @@ -26,41 +33,57 @@ Returns `ka`. arguments, not here.) AMR / load balancing (forwarded to [`adaptive_mesh_refinement!`](@ref) each step): -- `ps_interval=40`, `vs_interval=80`, `partition_interval=40` -- `ps_recursive::Bool=false`, `vs_balance::Bool=false` + + - `ps_interval=40`, `vs_interval=80`, `partition_interval=40` + - `ps_recursive::Bool=false`, `vs_balance::Bool=false` Loop control: -- `max_steps=typemax(Int)` — hard cap on the number of steps. -- `break_on_convergence::Bool=true` — stop when [`check_for_convergence`](@ref) holds. + + - `max_steps=typemax(Int)` — hard cap on the number of steps. + - `break_on_convergence::Bool=true` — stop when [`check_for_convergence`](@ref) holds. Lifecycle / IO (toggle `false` to manage these yourself): -- `listen_for_save::Bool=true` — [`listen_for_save!`](@ref) before the loop. -- `animation::Bool=true`, `anim_path::String="./animation"` — per-step [`check_for_animsave!`](@ref). -- `status_check::Bool=true` — per-step [`check!`](@ref) (periodic status print + save hook). -- `progress::Bool=true` — show a `ProgressMeter` bar (rank 0 only) whose length is one - `ST_CHECK_INTERVAL` window, i.e. how far the current step is from the next [`check!`](@ref); it - completes and restarts at each check. + + - `listen_for_save::Bool=true` — [`listen_for_save!`](@ref) before the loop. + - `animation::Bool=true`, `anim_path::String="./animation"` — per-step [`check_for_animsave!`](@ref). + - `status_check::Bool=true` — per-step [`check!`](@ref) (periodic status print + save hook). + - `progress::Bool=true` — show a `ProgressMeter` bar (rank 0 only) whose length is one + `ST_CHECK_INTERVAL` window, i.e. how far the current step is from the next [`check!`](@ref); it + completes and restarts at each check. """ function solve!( - p4est::P_pxest_t, ka::KA; - ps_interval = 40, vs_interval = 80, partition_interval = 40, - ps_recursive::Bool = false, vs_balance::Bool = false, - max_steps = typemax(Int), break_on_convergence::Bool = true, - listen_for_save::Bool = true, - animation::Bool = true, anim_path::String = "./animation", - status_check::Bool = true, progress::Bool = true, - ) + p4est::P_pxest_t, + ka::KA; + ps_interval = 40, + vs_interval = 80, + partition_interval = 40, + ps_recursive::Bool = false, + vs_balance::Bool = false, + max_steps = typemax(Int), + break_on_convergence::Bool = true, + listen_for_save::Bool = true, + animation::Bool = true, + anim_path::String = "./animation", + status_check::Bool = true, + progress::Bool = true, +) listen_for_save && listen_for_save!() # Progress bar (rank 0 only): one bar spans a single `ST_CHECK_INTERVAL` window, i.e. it shows # how far the current step is from the next `check!`; it completes and restarts at each check. interval = ka.kinfo.config.solver.ST_CHECK_INTERVAL - bar = (progress && MPI.Comm_rank(MPI.COMM_WORLD) == 0) ? + bar = + (progress && MPI.Comm_rank(MPI.COMM_WORLD) == 0) ? Progress(interval; desc = "Solving → next check!: ", color = :cyan) : nothing while !reached_max_time(ka) - adaptive_mesh_refinement!(p4est, ka; - ps_interval = ps_interval, vs_interval = vs_interval, + adaptive_mesh_refinement!( + p4est, + ka; + ps_interval = ps_interval, + vs_interval = vs_interval, partition_interval = partition_interval, - ps_recursive = ps_recursive, vs_balance = vs_balance) + ps_recursive = ps_recursive, + vs_balance = vs_balance, + ) limit_Δt!(ka) slope!(p4est, ka) flux!(p4est, ka) diff --git a/src/Solver/Types.jl b/src/Solver/Types.jl index 8d69861..34c121a 100644 --- a/src/Solver/Types.jl +++ b/src/Solver/Types.jl @@ -12,10 +12,11 @@ boundary states. ## Fields $(TYPEDFIELDS) - """ struct Uniform<:AbstractInitCond - "Primitive macroscopic variables `[ρ, U₁, …, U_DIM, λ]` applied uniformly to every cell." + """ + Primitive macroscopic variables `[ρ, U₁, …, U_DIM, λ]` applied uniformly to every cell. + """ ic::AbstractVector end """ @@ -37,10 +38,11 @@ primitive vector `[ρ, U₁, …, U_DIM, λ]` (length `DIM+2`, `λ = ρ/(2p)`). ## Fields $(TYPEDFIELDS) - """ struct PCoordFn<:AbstractInitCond # A function that accepts physical coordinates and returns initial primary variable at the position. - "Function `(midpoint, kinfo) -> prim` returning the primitive vector at a physical coordinate." + """ + Function `(midpoint, kinfo) -> prim` returning the primitive vector at a physical coordinate. + """ PCIC_fn::Function end @@ -54,59 +56,103 @@ Structure of solver configuration. ## Fields $(TYPEDFIELDS) - """ struct Solver{DIM,NDF} - "Courant-Friedrichs-Lewy number. Default is `0.4`." + """ + Courant-Friedrichs-Lewy number. Default is `0.4`. + """ CFL::Float64 - "Maximum level of the (static) AMR in physical space. **Mandatory**." + """ + Maximum level of the (static) AMR in physical space. **Mandatory**. + """ AMR_PS_MAXLEVEL::Int - "Maximum level of the dynamic AMR in physical space. In most cases, it should be smaller than the static one. Default is equal to `AMR_PS_MAXLEVEL`." + """ + Maximum level of the dynamic AMR in physical space. In most cases, it should be smaller than the static one. Default is equal to `AMR_PS_MAXLEVEL`. + """ AMR_DYNAMIC_PS_MAXLEVEL::Int - "Maximum level of the AMR in velocity space. **Mandatory**." + """ + Maximum level of the AMR in velocity space. **Mandatory**. + """ AMR_VS_MAXLEVEL::Int - "Numerical flux type. **Mandatory**." + """ + Numerical flux type. **Mandatory**. + """ flux::Type{Tf} where {Tf<:AbstractFluxType} - "Time-marching scheme. **Mandatory**." + """ + Time-marching scheme. **Mandatory**. + """ time_marching::Type{Tt} where {Tt<:AbstractTimeMarchingType} - "Dynamic AMR in physical space is open or not. Default is `true`." + """ + Dynamic AMR in physical space is open or not. Default is `true`. + """ PS_DYNAMIC_AMR::Bool - "Dynamic AMR in velocity space is open or not. Default is `true`." + """ + Dynamic AMR in velocity space is open or not. Default is `true`. + """ VS_DYNAMIC_AMR::Bool - "Criterion of AMR in L\"ohner criterion of physical space. Default is `0.2`." + """ + Criterion of AMR in L\"ohner criterion of physical space. Default is `0.2`. + """ ADAPT_COEFFI_PS::Float64 - "Redundancy coefficient of AMR in velocity space. Default is `0.125`." + """ + Redundancy coefficient of AMR in velocity space. Default is `0.125`. + """ ADAPT_COEFFI_VS_GLOBAL::Float64 - "Proportion that a refinement-required velocity cell contributes to the macroscopic quantities in a local physical cell. Default is `0.01`." + """ + Proportion that a refinement-required velocity cell contributes to the macroscopic quantities in a local physical cell. Default is `0.01`. + """ ADAPT_COEFFI_VS_LOCAL::Float64 - "Velocity-space refinement criterion. `:lohner` (default) uses the moment-weighted Löhner indicator with `local_contribution_*` as a relative mass/energy floor; `:contribution` uses the legacy magnitude/contribution flags." + """ + Velocity-space refinement criterion. `:lohner` (default) uses the moment-weighted Löhner indicator with `local_contribution_*` as a relative mass/energy floor; `:contribution` uses the legacy magnitude/contribution flags. + """ ADAPT_VS_MODE::Symbol - "Threshold of the moment-weighted Löhner indicator (in `[0,1]`) for velocity-space refinement when `ADAPT_VS_MODE == :lohner`. Default is `0.6`." + """ + Threshold of the moment-weighted Löhner indicator (in `[0,1]`) for velocity-space refinement when `ADAPT_VS_MODE == :lohner`. Default is `0.6`. + """ ADAPT_COEFFI_VS_LOHNER::Float64 - "Tolerance for convergence judgement. Default is `1e-6`." + """ + Tolerance for convergence judgement. Default is `1e-6`. + """ TOLERANCE::Float64 - "Number of steps between two checks of status. Default is `100`." + """ + Number of steps between two checks of status. Default is `100`. + """ ST_CHECK_INTERVAL::Int - "Number of redundant steps after convergence criterion has been satisfied. Default is `100`." + """ + Number of redundant steps after convergence criterion has been satisfied. Default is `100`. + """ REDUNDANT_STEPS_NUM::Int - "Simulation termination time (dimensionless). The main loop runs until `sim_time` reaches this value, and the last time step is shrunk to land exactly on it (see [`limit_Δt!`](@ref) / [`reached_max_time`](@ref)). Default is `Inf` (no time limit; terminate by convergence)." + """ + Simulation termination time (dimensionless). The main loop runs until `sim_time` reaches this value, and the last time step is shrunk to land exactly on it (see [`limit_Δt!`](@ref) / [`reached_max_time`](@ref)). Default is `Inf` (no time limit; terminate by convergence). + """ max_sim_time::Float64 end function Solver(config::Dict) - ADAPT_COEFFI_PS = haskey(config,:ADAPT_COEFFI_PS) ? config[:ADAPT_COEFFI_PS] : 0.25 - ADAPT_COEFFI_VS_GLOBAL = haskey(config,:ADAPT_COEFFI_VS_GLOBAL) ? config[:ADAPT_COEFFI_VS_GLOBAL] : 0.125 - ADAPT_COEFFI_VS_LOCAL = haskey(config,:ADAPT_COEFFI_VS_LOCAL) ? config[:ADAPT_COEFFI_VS_LOCAL] : 1e-2 - ADAPT_VS_MODE = haskey(config,:ADAPT_VS_MODE) ? Symbol(config[:ADAPT_VS_MODE]) : :lohner - ADAPT_COEFFI_VS_LOHNER = haskey(config,:ADAPT_COEFFI_VS_LOHNER) ? config[:ADAPT_COEFFI_VS_LOHNER] : 0.6 - TOLERANCE = haskey(config,:TOLERANCE) ? config[:TOLERANCE] : 1e-6 - ST_CHECK_INTERVAL = haskey(config,:ST_CHECK_INTERVAL) ? config[:ST_CHECK_INTERVAL] : 100 - REDUNDANT_STEPS_NUM = haskey(config,:REDUNDANT_STEPS_NUM) ? config[:REDUNDANT_STEPS_NUM] : 100 - max_sim_time = haskey(config,:max_sim_time) ? config[:max_sim_time] : Inf - return Solver{config[:DIM],config[:NDF]}(config[:CFL],config[:AMR_PS_MAXLEVEL], - haskey(config,:AMR_DYNAMIC_PS_MAXLEVEL) ? config[:AMR_DYNAMIC_PS_MAXLEVEL] : config[:AMR_PS_MAXLEVEL], - config[:AMR_VS_MAXLEVEL],config[:flux],config[:time_marching], - (haskey(config,:PS_DYNAMIC_AMR) ? config[:PS_DYNAMIC_AMR] : true), - (haskey(config,:VS_DYNAMIC_AMR) ? config[:VS_DYNAMIC_AMR] : true), + ADAPT_COEFFI_PS = haskey(config, :ADAPT_COEFFI_PS) ? config[:ADAPT_COEFFI_PS] : 0.25 + ADAPT_COEFFI_VS_GLOBAL = + haskey(config, :ADAPT_COEFFI_VS_GLOBAL) ? config[:ADAPT_COEFFI_VS_GLOBAL] : 0.125 + ADAPT_COEFFI_VS_LOCAL = + haskey(config, :ADAPT_COEFFI_VS_LOCAL) ? config[:ADAPT_COEFFI_VS_LOCAL] : 1e-2 + ADAPT_VS_MODE = + haskey(config, :ADAPT_VS_MODE) ? Symbol(config[:ADAPT_VS_MODE]) : :lohner + ADAPT_COEFFI_VS_LOHNER = + haskey(config, :ADAPT_COEFFI_VS_LOHNER) ? config[:ADAPT_COEFFI_VS_LOHNER] : 0.6 + TOLERANCE = haskey(config, :TOLERANCE) ? config[:TOLERANCE] : 1e-6 + ST_CHECK_INTERVAL = + haskey(config, :ST_CHECK_INTERVAL) ? config[:ST_CHECK_INTERVAL] : 100 + REDUNDANT_STEPS_NUM = + haskey(config, :REDUNDANT_STEPS_NUM) ? config[:REDUNDANT_STEPS_NUM] : 100 + max_sim_time = haskey(config, :max_sim_time) ? config[:max_sim_time] : Inf + return Solver{config[:DIM],config[:NDF]}( + config[:CFL], + config[:AMR_PS_MAXLEVEL], + haskey(config, :AMR_DYNAMIC_PS_MAXLEVEL) ? config[:AMR_DYNAMIC_PS_MAXLEVEL] : + config[:AMR_PS_MAXLEVEL], + config[:AMR_VS_MAXLEVEL], + config[:flux], + config[:time_marching], + (haskey(config, :PS_DYNAMIC_AMR) ? config[:PS_DYNAMIC_AMR] : true), + (haskey(config, :VS_DYNAMIC_AMR) ? config[:VS_DYNAMIC_AMR] : true), ADAPT_COEFFI_PS, ADAPT_COEFFI_VS_GLOBAL, ADAPT_COEFFI_VS_LOCAL, @@ -115,27 +161,40 @@ function Solver(config::Dict) TOLERANCE, ST_CHECK_INTERVAL, REDUNDANT_STEPS_NUM, - max_sim_time - ) + max_sim_time, + ) end -function Solver(;kwargs...) - CFL = haskey(kwargs,:CFL) ? kwargs[:CFL] : 0.4 - AMR_DYNAMIC_PS_MAXLEVEL = haskey(kwargs,:AMR_DYNAMIC_PS_MAXLEVEL) ? kwargs[:AMR_DYNAMIC_PS_MAXLEVEL] : kwargs[:AMR_PS_MAXLEVEL] - PS_DYNAMIC_AMR = haskey(kwargs,:PS_DYNAMIC_AMR) ? kwargs[:PS_DYNAMIC_AMR] : true - VS_DYNAMIC_AMR = haskey(kwargs,:VS_DYNAMIC_AMR) ? kwargs[:VS_DYNAMIC_AMR] : true - ADAPT_COEFFI_PS = haskey(kwargs,:ADAPT_COEFFI_PS) ? kwargs[:ADAPT_COEFFI_PS] : 0.25 - ADAPT_COEFFI_VS_GLOBAL = haskey(kwargs,:ADAPT_COEFFI_VS_GLOBAL) ? kwargs[:ADAPT_COEFFI_VS_GLOBAL] : 0.125 - ADAPT_COEFFI_VS_LOCAL = haskey(kwargs,:ADAPT_COEFFI_VS_LOCAL) ? kwargs[:ADAPT_COEFFI_VS_LOCAL] : 1e-2 - ADAPT_VS_MODE = haskey(kwargs,:ADAPT_VS_MODE) ? Symbol(kwargs[:ADAPT_VS_MODE]) : :lohner - ADAPT_COEFFI_VS_LOHNER = haskey(kwargs,:ADAPT_COEFFI_VS_LOHNER) ? kwargs[:ADAPT_COEFFI_VS_LOHNER] : 0.6 - TOLERANCE = haskey(kwargs,:TOLERANCE) ? kwargs[:TOLERANCE] : 1e-6 - ST_CHECK_INTERVAL = haskey(kwargs,:ST_CHECK_INTERVAL) ? kwargs[:ST_CHECK_INTERVAL] : 100 - REDUNDANT_STEPS_NUM = haskey(kwargs,:REDUNDANT_STEPS_NUM) ? kwargs[:REDUNDANT_STEPS_NUM] : 100 - max_sim_time = haskey(kwargs,:max_sim_time) ? kwargs[:max_sim_time] : Inf +function Solver(; kwargs...) + CFL = haskey(kwargs, :CFL) ? kwargs[:CFL] : 0.4 + AMR_DYNAMIC_PS_MAXLEVEL = + haskey(kwargs, :AMR_DYNAMIC_PS_MAXLEVEL) ? kwargs[:AMR_DYNAMIC_PS_MAXLEVEL] : + kwargs[:AMR_PS_MAXLEVEL] + PS_DYNAMIC_AMR = haskey(kwargs, :PS_DYNAMIC_AMR) ? kwargs[:PS_DYNAMIC_AMR] : true + VS_DYNAMIC_AMR = haskey(kwargs, :VS_DYNAMIC_AMR) ? kwargs[:VS_DYNAMIC_AMR] : true + ADAPT_COEFFI_PS = haskey(kwargs, :ADAPT_COEFFI_PS) ? kwargs[:ADAPT_COEFFI_PS] : 0.25 + ADAPT_COEFFI_VS_GLOBAL = + haskey(kwargs, :ADAPT_COEFFI_VS_GLOBAL) ? kwargs[:ADAPT_COEFFI_VS_GLOBAL] : 0.125 + ADAPT_COEFFI_VS_LOCAL = + haskey(kwargs, :ADAPT_COEFFI_VS_LOCAL) ? kwargs[:ADAPT_COEFFI_VS_LOCAL] : 1e-2 + ADAPT_VS_MODE = + haskey(kwargs, :ADAPT_VS_MODE) ? Symbol(kwargs[:ADAPT_VS_MODE]) : :lohner + ADAPT_COEFFI_VS_LOHNER = + haskey(kwargs, :ADAPT_COEFFI_VS_LOHNER) ? kwargs[:ADAPT_COEFFI_VS_LOHNER] : 0.6 + TOLERANCE = haskey(kwargs, :TOLERANCE) ? kwargs[:TOLERANCE] : 1e-6 + ST_CHECK_INTERVAL = + haskey(kwargs, :ST_CHECK_INTERVAL) ? kwargs[:ST_CHECK_INTERVAL] : 100 + REDUNDANT_STEPS_NUM = + haskey(kwargs, :REDUNDANT_STEPS_NUM) ? kwargs[:REDUNDANT_STEPS_NUM] : 100 + max_sim_time = haskey(kwargs, :max_sim_time) ? kwargs[:max_sim_time] : Inf return Solver{kwargs[:DIM],kwargs[:NDF]}( - CFL,kwargs[:AMR_PS_MAXLEVEL],AMR_DYNAMIC_PS_MAXLEVEL, - kwargs[:AMR_VS_MAXLEVEL],kwargs[:flux],kwargs[:time_marching], - PS_DYNAMIC_AMR,VS_DYNAMIC_AMR, + CFL, + kwargs[:AMR_PS_MAXLEVEL], + AMR_DYNAMIC_PS_MAXLEVEL, + kwargs[:AMR_VS_MAXLEVEL], + kwargs[:flux], + kwargs[:time_marching], + PS_DYNAMIC_AMR, + VS_DYNAMIC_AMR, ADAPT_COEFFI_PS, ADAPT_COEFFI_VS_GLOBAL, ADAPT_COEFFI_VS_LOCAL, @@ -144,11 +203,11 @@ function Solver(;kwargs...) TOLERANCE, ST_CHECK_INTERVAL, REDUNDANT_STEPS_NUM, - max_sim_time - ) + max_sim_time, + ) end -function Solver(solver::Solver{DIM,NDF};kwargs...) where{DIM,NDF} - new_args = [get(kwargs,f,getfield(solver,f)) for f in fieldnames(Solver)] +function Solver(solver::Solver{DIM,NDF}; kwargs...) where {DIM,NDF} + new_args = [get(kwargs, f, getfield(solver, f)) for f in fieldnames(Solver)] return Solver{DIM,NDF}(new_args...) end @@ -163,7 +222,6 @@ and worked examples. ## Fields $(TYPEDFIELDS) - """ mutable struct UDF """ @@ -188,19 +246,20 @@ mutable struct UDF region of interest); `true` lets the sensor decide. Default (unset): always allow. """ dynamic_ps_refine_flag::Function - "Reserved for a static velocity-space refinement flag. **Currently unused** — the field is stored but never invoked." + """ + Reserved for a static velocity-space refinement flag. **Currently unused** — the field is stored but never invoked. + """ static_vs_refine_flag::Function end -null_udf(args...;kwargs...) = false -function UDF(;kwargs...) - static_ps_refine_flag = haskey(kwargs,:static_ps_refine_flag) ? kwargs[:static_ps_refine_flag] : null_udf - dynamic_ps_refine_flag = haskey(kwargs,:dynamic_ps_refine_flag) ? kwargs[:dynamic_ps_refine_flag] : null_udf - static_vs_refine_flag = haskey(kwargs,:static_vs_refine_flag) ? kwargs[:static_vs_refine_flag] : null_udf - return UDF( - static_ps_refine_flag, - dynamic_ps_refine_flag, - static_vs_refine_flag - ) +null_udf(args...; kwargs...) = false +function UDF(; kwargs...) + static_ps_refine_flag = + haskey(kwargs, :static_ps_refine_flag) ? kwargs[:static_ps_refine_flag] : null_udf + dynamic_ps_refine_flag = + haskey(kwargs, :dynamic_ps_refine_flag) ? kwargs[:dynamic_ps_refine_flag] : null_udf + static_vs_refine_flag = + haskey(kwargs, :static_vs_refine_flag) ? kwargs[:static_vs_refine_flag] : null_udf + return UDF(static_ps_refine_flag, dynamic_ps_refine_flag, static_vs_refine_flag) end """ $(TYPEDEF) @@ -210,51 +269,56 @@ Structure of output information. ## Fields $(TYPEDFIELDS) - """ mutable struct Output - "VTK cell type in physical space. Available options: `Pixel` and `Triangle` for 2D; `Voxel` and `Tetra` for 3D. Default is [`Triangle`](@ref) for 2D and [`Tetra`](@ref) for 3D. A `Vector` of cell types (e.g. `[Triangle, Pixel]`) may also be given; in that case a separate output (pvtu for the flow field, and its own animation collection) is written for every cell type, with the cell-type name appended to the corresponding file name." + """ + VTK cell type in physical space. Available options: `Pixel` and `Triangle` for 2D; `Voxel` and `Tetra` for 3D. Default is [`Triangle`](@ref) for 2D and [`Tetra`](@ref) for 3D. A `Vector` of cell types (e.g. `[Triangle, Pixel]`) may also be given; in that case a separate output (pvtu for the flow field, and its own animation collection) is written for every cell type, with the cell-type name appended to the corresponding file name. + """ vtk_celltype::Union{Type{<:AbstractVTKCellType},Vector} - "VTK cell type in velocity space. Available options: `Pixel` for 2D." - vs_vtk_celltype::Type{Tv} where{Tv<:AbstractVTKCellType} - "Time interval between animation frames. `0` (default) disables animation output, making [`check_for_animsave!`](@ref) a no-op." + """ + VTK cell type in velocity space. Available options: `Pixel` for 2D. + """ + vs_vtk_celltype::Type{Tv} where {Tv<:AbstractVTKCellType} + """ + Time interval between animation frames. `0` (default) disables animation output, making [`check_for_animsave!`](@ref) a no-op. + """ anim_dt::Float64 """ Optional callback selecting which physical cells write their (per-cell) velocity-space distribution. Two call conventions, one per output path: - - Final result ([`save_result`](@ref)): `vs_output_criterion(ps_data, ka) -> Bool` — - return `true` to include this cell's velocity space. Default (unset): include every cell. - - Animation frames ([`check_for_animsave!`](@ref)): `vs_output_criterion(; ps_data, ka) - -> (id::Int, flag::Bool)` — `flag` selects the cell and `id` names its output file. - Default (unset): write no per-cell velocity space. - See the [User-defined functions](@ref) page. + + - Final result ([`save_result`](@ref)): `vs_output_criterion(ps_data, ka) -> Bool` — + return `true` to include this cell's velocity space. Default (unset): include every cell. + - Animation frames ([`check_for_animsave!`](@ref)): `vs_output_criterion(; ps_data, ka) -> (id::Int, flag::Bool)` — `flag` selects the cell and `id` names its output file. + Default (unset): write no per-cell velocity space. + See the [User-defined functions](@ref) page. """ vs_output_criterion::Function - "Index of the last saved animation frame." + """ + Index of the last saved animation frame. + """ anim_index::Int end function Output(config::Dict) output = Output( config[:DIM]==2 ? Triangle : Tetra, config[:DIM]==2 ? Pixel : Voxel, - 0.,null_udf,0 + 0.0, + null_udf, + 0, ) for i in fieldnames(Output) - if haskey(config,i) - setfield!(output,i,config[i]) + if haskey(config, i) + setfield!(output, i, config[i]) end end return output end -function Output(solver::Solver{DIM,NDF};kwargs...) where{DIM,NDF} - output = Output( - DIM==2 ? Triangle : Tetra, - DIM==2 ? Pixel : Voxel, - 0.,null_udf,0 - ) +function Output(solver::Solver{DIM,NDF}; kwargs...) where {DIM,NDF} + output = Output(DIM==2 ? Triangle : Tetra, DIM==2 ? Pixel : Voxel, 0.0, null_udf, 0) for i in fieldnames(Output) - if haskey(kwargs,i) - setfield!(output,i,kwargs[i]) + if haskey(kwargs, i) + setfield!(output, i, kwargs[i]) end end return output @@ -269,12 +333,15 @@ This struct plays an key role in the solution process. ## Fields $(TYPEDFIELDS) - """ struct Configure{DIM,NDF}<:AbstractConfig{DIM,NDF} - "Range of the simulated domain. As an example, for 2D case, it should be aligned as [xmin,xmax,ymin,ymax]." + """ + Range of the simulated domain. As an example, for 2D case, it should be aligned as [xmin,xmax,ymin,ymax]. + """ geometry::Vector{Float64} - "Number of tree roots for each dimension. For 2D case, it should be aligned as [x_num,y_num]" + """ + Number of tree roots for each dimension. For 2D case, it should be aligned as [x_num,y_num] + """ trees_num::Vector{Int64} """ For `Vector` type, it represents the range of the velocity space. For 2D case, it should be @@ -286,36 +353,58 @@ struct Configure{DIM,NDF}<:AbstractConfig{DIM,NDF} like Gauss-Hermite. """ quadrature::Union{AbstractQuadrature,Vector{Float64}} - "Number of tree roots for each dimension in velocity space. Together with `quadrature` it must place the origin `v = 0` on a root-grid corner (see `quadrature`; checked by [`check_vs_setting`](@ref))." + """ + Number of tree roots for each dimension in velocity space. Together with `quadrature` it must place the origin `v = 0` on a root-grid corner (see `quadrature`; checked by [`check_vs_setting`](@ref)). + """ vs_trees_num::Vector{Int64} - "Initial condition defined by [`AbstractInitCond`](@ref)." + """ + Initial condition defined by [`AbstractInitCond`](@ref). + """ IC::AbstractInitCond - "Types of the domain boundary. For 2D case, the vector should catain 4 elements corresponding to the 4 domain boundaries. The element type is defined by [`Domain`](@ref)." + """ + Types of the domain boundary. For 2D case, the vector should catain 4 elements corresponding to the 4 domain boundaries. The element type is defined by [`Domain`](@ref). + """ domain::Vector{Domain} - "Immersed boundary. Multiple boundaries are supported. The element type is defined by [`AbstractBoundary`](@ref)" + """ + Immersed boundary. Multiple boundaries are supported. The element type is defined by [`AbstractBoundary`](@ref) + """ IB::Vector{AbstractBoundary} - "Properties of the simulated gas defined by [`Gas`](@ref)." + """ + Properties of the simulated gas defined by [`Gas`](@ref). + """ gas::Gas - "Setup of the solver defined by [`Solver`](@ref)." + """ + Setup of the solver defined by [`Solver`](@ref). + """ solver::Solver{DIM,NDF} - "Setup of the output form defined by [`Output`](@ref)." + """ + Setup of the output form defined by [`Output`](@ref). + """ output::Output - "Functions defined by users, including some criteria." + """ + Functions defined by users, including some criteria. + """ user_defined::UDF end -function config_IB(ib::Circle,config::Dict) - ds = minimum([(config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i]/2^config[:AMR_PS_MAXLEVEL] for i in 1:config[:DIM]]) - Circle(ib,ds) +function config_IB(ib::Circle, config::Dict) + ds = minimum([ + (config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i]/2^config[:AMR_PS_MAXLEVEL] + for i = 1:config[:DIM] + ]) + Circle(ib, ds) end -function config_IB(ib::Sphere,config::Dict) - ds = minimum([(config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i]/2^config[:AMR_PS_MAXLEVEL] for i in 1:config[:DIM]]) - Sphere(ib,ds) +function config_IB(ib::Sphere, config::Dict) + ds = minimum([ + (config[:geometry][2i]-config[:geometry][2i-1])/config[:trees_num][i]/2^config[:AMR_PS_MAXLEVEL] + for i = 1:config[:DIM] + ]) + Sphere(ib, ds) end -function config_IB(ib::Vertices,config::Dict) - Vertices(ib,config) +function config_IB(ib::Vertices, config::Dict) + Vertices(ib, config) end -function config_IB(ib::Triangles,config::Dict) - Triangles(ib,config) +function config_IB(ib::Triangles, config::Dict) + Triangles(ib, config) end """ $(TYPEDSIGNATURES) @@ -334,11 +423,18 @@ no-op for a non-Cartesian `AbstractQuadrature`. """ function check_vs_setting(quadrature, vs_trees_num, DIM::Integer) quadrature isa AbstractVector || return nothing # non-Cartesian quadrature: requirement N/A - length(quadrature) == 2DIM || error("`quadrature` must have length 2*DIM = $(2DIM) (got $(length(quadrature))): an increasing [min,max] pair per velocity dimension.") - length(vs_trees_num) == DIM || error("`vs_trees_num` must have length DIM = $DIM (got $(length(vs_trees_num))).") - for d in 1:DIM - lo = quadrature[2d-1]; hi = quadrature[2d]; n = vs_trees_num[d] - hi > lo || error("velocity-space dimension $d: `quadrature` range [$lo, $hi] must be increasing.") + length(quadrature) == 2DIM || error( + "`quadrature` must have length 2*DIM = $(2DIM) (got $(length(quadrature))): an increasing [min,max] pair per velocity dimension.", + ) + length(vs_trees_num) == DIM || + error("`vs_trees_num` must have length DIM = $DIM (got $(length(vs_trees_num))).") + for d = 1:DIM + lo = quadrature[2d-1]; + hi = quadrature[2d]; + n = vs_trees_num[d] + hi > lo || error( + "velocity-space dimension $d: `quadrature` range [$lo, $hi] must be increasing.", + ) n >= 1 || error("velocity-space dimension $d: `vs_trees_num[$d]` = $n must be ≥ 1.") k = -lo * n / (hi - lo) # fractional root-grid index of the v = 0 vertex i = round(k) @@ -347,42 +443,53 @@ function check_vs_setting(quadrature, vs_trees_num, DIM::Integer) "root-grid corner. With range [$lo, $hi] and `vs_trees_num[$d]` = $n, 0 falls at " * "fractional cell index $k (it must be an integer in 0:$n). Adjust the `quadrature` " * "range and/or `vs_trees_num` so that (0 - min)/(max - min)*vs_trees_num is an integer " * - "— e.g. a symmetric range [-a, a] with an even `vs_trees_num`.") + "— e.g. a symmetric range [-a, a] with an even `vs_trees_num`.", + ) end return nothing end function Configure(config::Dict) gas = Gas() for i in fieldnames(Gas) - if haskey(config,i) - setfield!(gas,i,config[i]) + if haskey(config, i) + setfield!(gas, i, config[i]) end end - if !haskey(config,:μᵣ) - gas.μᵣ = ref_vhs_vis(gas.Kn,gas.αᵣ,gas.ωᵣ) + if !haskey(config, :μᵣ) + gas.μᵣ = ref_vhs_vis(gas.Kn, gas.αᵣ, gas.ωᵣ) end - IB = haskey(config,:IB) ? config[:IB] : [] + IB = haskey(config, :IB) ? config[:IB] : [] for i in eachindex(IB) - IB[i] = config_IB(IB[i],config) + IB[i] = config_IB(IB[i], config) end user_defined = UDF() for i in fieldnames(UDF) - if haskey(config,i) - setfield!(user_defined,i,config[i]) + if haskey(config, i) + setfield!(user_defined, i, config[i]) else - setfield!(user_defined,i,null_udf) + setfield!(user_defined, i, null_udf) end end check_vs_setting(config[:quadrature], config[:vs_trees_num], config[:DIM]) - return Configure{config[:DIM],config[:NDF]}(config[:geometry],config[:trees_num], - config[:quadrature],config[:vs_trees_num],config[:IC],config[:domain],IB, - gas,Solver(config),Output(config),user_defined) + return Configure{config[:DIM],config[:NDF]}( + config[:geometry], + config[:trees_num], + config[:quadrature], + config[:vs_trees_num], + config[:IC], + config[:domain], + IB, + gas, + Solver(config), + Output(config), + user_defined, + ) end -function Configure(solver::Solver{DIM,NDF};kwargs...) where{DIM,NDF} +function Configure(solver::Solver{DIM,NDF}; kwargs...) where {DIM,NDF} geometry = kwargs[:geometry] trees_num = kwargs[:trees_num] AMR_PS_MAXLEVEL = solver.AMR_PS_MAXLEVEL - IB = haskey(kwargs,:IB) ? kwargs[:IB] : [] + IB = haskey(kwargs, :IB) ? kwargs[:IB] : [] config_dict = Dict( :DIM=>DIM, :geometry=>geometry, @@ -390,7 +497,7 @@ function Configure(solver::Solver{DIM,NDF};kwargs...) where{DIM,NDF} :AMR_PS_MAXLEVEL=>AMR_PS_MAXLEVEL, ) for i in eachindex(IB) - IB[i] = config_IB(IB[i],config_dict) + IB[i] = config_IB(IB[i], config_dict) end check_vs_setting(kwargs[:quadrature], kwargs[:vs_trees_num], DIM) return Configure{DIM,NDF}( @@ -404,22 +511,24 @@ function Configure(solver::Solver{DIM,NDF};kwargs...) where{DIM,NDF} kwargs[:gas], solver, kwargs[:output], - kwargs[:user_defined] + kwargs[:user_defined], ) end -function Configure(solver::Solver,config::Configure{DIM,NDF};kwargs...)where{DIM,NDF} +function Configure(solver::Solver, config::Configure{DIM,NDF}; kwargs...) where {DIM,NDF} return Configure( solver; - geometry = haskey(kwargs,:geometry) ? kwargs[:geometry] : config.geometry, - trees_num = haskey(kwargs,:trees_num) ? kwargs[:trees_num] : config.trees_num, - quadrature = haskey(kwargs,:quadrature) ? kwargs[:quadrature] : config.quadrature, - vs_trees_num = haskey(kwargs,:vs_trees_num) ? kwargs[:vs_trees_num] : config.vs_trees_num, - IC = haskey(kwargs,:IC) ? kwargs[:IC] : config.IC, - domain = haskey(kwargs,:domain) ? kwargs[:domain] : config.domain, - IB = haskey(kwargs,:IB) ? kwargs[:IB] : config.IB, - gas = haskey(kwargs,:gas) ? kwargs[:gas] : config.gas, - output = haskey(kwargs,:output) ? kwargs[:output] : config.output, - user_defined = haskey(kwargs,:user_defined) ? kwargs[:user_defined] : config.user_defined + geometry = haskey(kwargs, :geometry) ? kwargs[:geometry] : config.geometry, + trees_num = haskey(kwargs, :trees_num) ? kwargs[:trees_num] : config.trees_num, + quadrature = haskey(kwargs, :quadrature) ? kwargs[:quadrature] : config.quadrature, + vs_trees_num = haskey(kwargs, :vs_trees_num) ? kwargs[:vs_trees_num] : + config.vs_trees_num, + IC = haskey(kwargs, :IC) ? kwargs[:IC] : config.IC, + domain = haskey(kwargs, :domain) ? kwargs[:domain] : config.domain, + IB = haskey(kwargs, :IB) ? kwargs[:IB] : config.IB, + gas = haskey(kwargs, :gas) ? kwargs[:gas] : config.gas, + output = haskey(kwargs, :output) ? kwargs[:output] : config.output, + user_defined = haskey(kwargs, :user_defined) ? kwargs[:user_defined] : + config.user_defined, ) end """ @@ -431,11 +540,12 @@ mutable struct Forest{DIM} p4est::P_pxest_t ghost::P_pxest_ghost_t mesh::P_pxest_mesh_t - Forest(DIM) = (n = new{DIM}(); - n.p4est = Ptr{pxest_ts[DIM-1]}(C_NULL); - n.ghost = Ptr{pxest_ghost_ts[DIM-1]}(C_NULL); - n.mesh = Ptr{pxest_mesh_ts[DIM-1]}(C_NULL); - n + Forest(DIM) = ( + n = new{DIM}(); + n.p4est = Ptr{pxest_ts[DIM-1]}(C_NULL); + n.ghost = Ptr{pxest_ghost_ts[DIM-1]}(C_NULL); + n.mesh = Ptr{pxest_mesh_ts[DIM-1]}(C_NULL); + n ) end """ @@ -443,17 +553,25 @@ $(TYPEDEF) $(TYPEDFIELDS) """ mutable struct Residual - "Residual of primary variables, is updated by [`residual_check!`](@ref)." + """ + Residual of primary variables, is updated by [`residual_check!`](@ref). + """ residual::Vector{Float64} - "Summation of residuals." + """ + Summation of residuals. + """ sumRes::Vector{Float64} - "Summation of primary variables to average `sumRes`." + """ + Summation of primary variables to average `sumRes`. + """ sumAvg::Vector{Float64} - "Count of redundant step to insure the convergence." + """ + Count of redundant step to insure the convergence. + """ redundant_step::Int end function Residual(DIM::Int) - return Residual(ones(DIM+2),zeros(DIM+2),zeros(DIM+2),0) + return Residual(ones(DIM+2), zeros(DIM+2), zeros(DIM+2), 0) end """ @@ -466,31 +584,57 @@ Structure of simulation status. It contains the real time information, and is up $(TYPEDFIELDS) """ mutable struct Status - "Maximum absolute value of the gradients of conserved variables." + """ + Maximum absolute value of the gradients of conserved variables. + """ gradmax::Vector{Float64} - "Maximum number of velocity cells in a physical cell." + """ + Maximum number of velocity cells in a physical cell. + """ max_vs_num::Int - "Total number of phase grids." + """ + Total number of phase grids. + """ total_phase_num::Int - "Time step size used in [`iterate!`](@ref)." + """ + Time step size used in [`iterate!`](@ref). + """ Δt::Float64 - "Time step size constraint by grid size." + """ + Time step size constraint by grid size. + """ Δt_ξ::Float64 - "Dimensionless simulation time." + """ + Dimensionless simulation time. + """ sim_time::Float64 - "Number of steps that have been marched." + """ + Number of steps that have been marched. + """ step::Int - "Number of steps after last AMR in physical space." + """ + Number of steps after last AMR in physical space. + """ ps_adapt_step::Int - "Number of steps after last AMR in velocity space." + """ + Number of steps after last AMR in velocity space. + """ vs_adapt_step::Int - "Number of steps after last partition." + """ + Number of steps after last partition. + """ partition_step::Int - "Residual of conserved variables defined by [`Residual`](@ref)." + """ + Residual of conserved variables defined by [`Residual`](@ref). + """ residual::Residual - "Flag indicating whether to save." + """ + Flag indicating whether to save. + """ save_flag::Base.RefValue{Bool} - "Reusable vector of MPI requests for asynchronous communication." + """ + Reusable vector of MPI requests for asynchronous communication. + """ mpi_reqs::Vector{MPI.Request} end function Status(config::Dict) @@ -499,24 +643,66 @@ function Status(config::Dict) geometry = config[:geometry] vs_trees_num = config[:vs_trees_num] quadrature = config[:quadrature] - ds = [(geometry[2*i]-geometry[2*i-1])/trees_num[i]/2^config[:AMR_PS_MAXLEVEL] for i in 1:DIM] - U = isa(quadrature,Vector) ? [max(quadrature[2*i],abs(quadrature[2*i-1])) - - (quadrature[2*i] - quadrature[2*i-1]) / vs_trees_num[i]/ - 2^config[:AMR_VS_MAXLEVEL] / 2 for i in 1:DIM] : [maximum(abs.(quadrature.vcoords)) for _ in 1:DIM] + ds = [ + (geometry[2*i]-geometry[2*i-1])/trees_num[i]/2^config[:AMR_PS_MAXLEVEL] for + i = 1:DIM + ] + U = + isa(quadrature, Vector) ? + [ + max(quadrature[2*i], abs(quadrature[2*i-1])) - + (quadrature[2*i] - quadrature[2*i-1]) / vs_trees_num[i] / + 2^config[:AMR_VS_MAXLEVEL] / 2 for i = 1:DIM + ] : [maximum(abs.(quadrature.vcoords)) for _ = 1:DIM] Δt_ξ = config[:CFL]*minimum(ds ./ U) - return Status(zeros(DIM+2), 0,0,Δt_ξ,Δt_ξ,0.,0,1,1,1,Residual(DIM),Ref(false),MPI.Request[]) + return Status( + zeros(DIM+2), + 0, + 0, + Δt_ξ, + Δt_ξ, + 0.0, + 0, + 1, + 1, + 1, + Residual(DIM), + Ref(false), + MPI.Request[], + ) end -function Status(config::Configure{DIM,NDF}) where{DIM,NDF} +function Status(config::Configure{DIM,NDF}) where {DIM,NDF} trees_num = config.trees_num geometry = config.geometry vs_trees_num = config.vs_trees_num quadrature = config.quadrature - ds = [(geometry[2*i]-geometry[2*i-1])/trees_num[i]/2^config.solver.AMR_PS_MAXLEVEL for i in 1:DIM] - U = isa(quadrature,Vector) ? [max(quadrature[2*i],abs(quadrature[2*i-1])) - - (quadrature[2*i] - quadrature[2*i-1]) / vs_trees_num[i]/ - 2^config.solver.AMR_VS_MAXLEVEL / 2 for i in 1:DIM] : [maximum(abs.(quadrature.vcoords)) for _ in 1:DIM] + ds = [ + (geometry[2*i]-geometry[2*i-1])/trees_num[i]/2^config.solver.AMR_PS_MAXLEVEL for + i = 1:DIM + ] + U = + isa(quadrature, Vector) ? + [ + max(quadrature[2*i], abs(quadrature[2*i-1])) - + (quadrature[2*i] - quadrature[2*i-1]) / vs_trees_num[i] / + 2^config.solver.AMR_VS_MAXLEVEL / 2 for i = 1:DIM + ] : [maximum(abs.(quadrature.vcoords)) for _ = 1:DIM] Δt_ξ = config.solver.CFL*minimum(ds ./ U) - return Status(zeros(DIM+2), 0,0,Δt_ξ,Δt_ξ,0.,0,1,1,1,Residual(DIM),Ref(false),MPI.Request[]) + return Status( + zeros(DIM+2), + 0, + 0, + Δt_ξ, + Δt_ξ, + 0.0, + 0, + 1, + 1, + 1, + Residual(DIM), + Ref(false), + MPI.Request[], + ) end """ @@ -525,50 +711,60 @@ Structure of required information during a simulation. $(TYPEDFIELDS) """ mutable struct KInfo{DIM,NDF} - "Defined by [`Configure`](@ref)." + """ + Defined by [`Configure`](@ref). + """ config::Configure{DIM,NDF} - "Defined by [`Forest`](@ref)." + """ + Defined by [`Forest`](@ref). + """ forest::Forest{DIM} - "Defined by [`Status`](@ref)." + """ + Defined by [`Status`](@ref). + """ status::Status end function KInfo(config::Dict) return KInfo{config[:DIM],config[:NDF]}( Configure(config), Forest(config[:DIM]), - Status(config) + Status(config), ) end -function KInfo(config::Configure{DIM,NDF}) where{DIM,NDF} - return KInfo{DIM,NDF}( - config, - Forest(DIM), - Status(config) - ) +function KInfo(config::Configure{DIM,NDF}) where {DIM,NDF} + return KInfo{DIM,NDF}(config, Forest(DIM), Status(config)) end """ $(TYPEDSIGNATURES) Update information in [`KInfo`](@ref) to maintain self consistency. """ -function KInfo!(kinfo::KInfo{DIM,NDF};kwargs...) where{DIM,NDF} - if haskey(kwargs,:solver) +function KInfo!(kinfo::KInfo{DIM,NDF}; kwargs...) where {DIM,NDF} + if haskey(kwargs, :solver) solver = kwargs[:solver] - config = Configure(solver,kinfo.config) + config = Configure(solver, kinfo.config) else - config = haskey(kwargs,:config) ? kwargs[:config] : kinfo.config + config = haskey(kwargs, :config) ? kwargs[:config] : kinfo.config end trees_num = config.trees_num geometry = config.geometry vs_trees_num = config.vs_trees_num quadrature = config.quadrature - ds = [(geometry[2*i]-geometry[2*i-1])/trees_num[i]/2^config.solver.AMR_PS_MAXLEVEL for i in 1:DIM] - U = isa(quadrature,Vector) ? [max(quadrature[2*i],abs(quadrature[2*i-1])) - - (quadrature[2*i] - quadrature[2*i-1]) / vs_trees_num[i]/ - 2^config.solver.AMR_VS_MAXLEVEL / 2 for i in 1:DIM] : [maximum(abs.(quadrature.vcoords)) for _ in 1:DIM] + ds = [ + (geometry[2*i]-geometry[2*i-1])/trees_num[i]/2^config.solver.AMR_PS_MAXLEVEL for + i = 1:DIM + ] + U = + isa(quadrature, Vector) ? + [ + max(quadrature[2*i], abs(quadrature[2*i-1])) - + (quadrature[2*i] - quadrature[2*i-1]) / vs_trees_num[i] / + 2^config.solver.AMR_VS_MAXLEVEL / 2 for i = 1:DIM + ] : [maximum(abs.(quadrature.vcoords)) for _ = 1:DIM] Δt_ξ = config.solver.CFL*minimum(ds ./ U) - kinfo.status.Δt = Δt_ξ;kinfo.status.Δt_ξ = Δt_ξ + kinfo.status.Δt = Δt_ξ; + kinfo.status.Δt_ξ = Δt_ξ kinfo.status.residual.redundant_step = 0 - kinfo.status.residual.residual = Inf.*ones(DIM+2) + kinfo.status.residual.residual = Inf .* ones(DIM+2) kinfo.config = config end @@ -583,17 +779,29 @@ GC; no manual `sc_free` is required. $(TYPEDFIELDS) """ mutable struct GhostBuffer - "Flat receive buffer for ghost cell data (df, w, …)." + """ + Flat receive buffer for ghost cell data (df, w, …). + """ ghost_datas::Vector{Float64} - "Flat receive buffer for ghost cell slopes (sdf, sw)." + """ + Flat receive buffer for ghost cell slopes (sdf, sw). + """ ghost_slopes::Vector{Float64} - "Flat receive buffer for ghost VS structure (weight, level, midpoint)." + """ + Flat receive buffer for ghost VS structure (weight, level, midpoint). + """ ghost_structures::Vector{Float64} - "Per-mirror send buffer for data, one entry per mirror quadrant." + """ + Per-mirror send buffer for data, one entry per mirror quadrant. + """ mirror_data_bufs::Vector{Vector{Float64}} - "Per-mirror send buffer for slopes, one entry per mirror quadrant." + """ + Per-mirror send buffer for slopes, one entry per mirror quadrant. + """ mirror_slope_bufs::Vector{Vector{Float64}} - "Per-mirror send buffer for VS structure, one entry per mirror quadrant." + """ + Per-mirror send buffer for VS structure, one entry per mirror quadrant. + """ mirror_structure_bufs::Vector{Vector{Float64}} end @@ -604,27 +812,49 @@ pre-computed element-count arrays that are reused every time-step without reallo $(TYPEDFIELDS) """ struct GhostInfo - "vs_num of each ghost quadrant (length = n_ghosts)." + """ + vs_num of each ghost quadrant (length = n_ghosts). + """ ghost_vsnums::Vector{Int} - "vs_num of each mirror quadrant (length = n_mirrors)." + """ + vs_num of each mirror quadrant (length = n_mirrors). + """ mirror_vsnums::Vector{Int} - "Float64-element offset into ghost_datas for each ghost quadrant." + """ + Float64-element offset into ghost_datas for each ghost quadrant. + """ ghost_data_offsets::Vector{Int} - "Float64-element offset into ghost_slopes for each ghost quadrant." + """ + Float64-element offset into ghost_slopes for each ghost quadrant. + """ ghost_slope_offsets::Vector{Int} - "Float64-element offset into ghost_structures for each ghost quadrant." + """ + Float64-element offset into ghost_structures for each ghost quadrant. + """ ghost_structure_offsets::Vector{Int} - "Cached Float64-element count of ghost data buffer per ghost quadrant." + """ + Cached Float64-element count of ghost data buffer per ghost quadrant. + """ ghost_data_szs::Vector{Int} - "Cached Float64-element count of ghost slope buffer per ghost quadrant." + """ + Cached Float64-element count of ghost slope buffer per ghost quadrant. + """ ghost_slope_szs::Vector{Int} - "Cached Float64-element count of ghost data buffer per mirror quadrant." + """ + Cached Float64-element count of ghost data buffer per mirror quadrant. + """ mirror_data_szs::Vector{Int} - "Cached Float64-element count of ghost slope buffer per mirror quadrant." + """ + Cached Float64-element count of ghost slope buffer per mirror quadrant. + """ mirror_slope_szs::Vector{Int} - "Physical-space refinement level of each ghost quadrant." + """ + Physical-space refinement level of each ghost quadrant. + """ ghost_levels::Vector{Int8} - "Physical-space refinement level of each mirror quadrant." + """ + Physical-space refinement level of each mirror quadrant. + """ mirror_levels::Vector{Int8} end @@ -633,9 +863,11 @@ $(TYPEDEF) Structure of cells data managed by `Julia`. $(TYPEDFIELDS) """ -mutable struct PsTrees{DIM,NDF} +mutable struct PsTrees{DIM,NDF} data::Vector{Vector{AbstractPsData{DIM,NDF}}} - "Offset of treeid used in partition." + """ + Offset of treeid used in partition. + """ offset::Int end @@ -656,11 +888,17 @@ Structure of fields data. $(TYPEDFIELDS) """ mutable struct Field{DIM,NDF} - "Cells data defined by [`PsTrees`](@ref)." + """ + Cells data defined by [`PsTrees`](@ref). + """ trees::PsTrees{DIM,NDF} - "Mapping between faces and cells. The element type is defined by [`AbstractFace`](@ref)." + """ + Mapping between faces and cells. The element type is defined by [`AbstractFace`](@ref). + """ faces::Vector{AbstractFace} - "Pre-collected immersed-boundary data (donor cells, solid cells, IB faces)." + """ + Pre-collected immersed-boundary data (donor cells, solid cells, IB faces). + """ immersed_boundaries::Vector{ImmersedBoundary{DIM,NDF}} end @@ -672,8 +910,13 @@ $(TYPEDFIELDS) mutable struct KData{DIM,NDF} field::Field{DIM,NDF} ghost::Ghost - KData(trees::PsTrees{DIM,NDF}) where{DIM,NDF} = (n = new{DIM,NDF}(); - n.field = Field{DIM,NDF}(trees,Vector{AbstractFace}(undef,0),ImmersedBoundary{DIM,NDF}[]); + KData(trees::PsTrees{DIM,NDF}) where {DIM,NDF} = ( + n = new{DIM,NDF}(); + n.field = Field{DIM,NDF}( + trees, + Vector{AbstractFace}(undef, 0), + ImmersedBoundary{DIM,NDF}[], + ); n ) end @@ -698,13 +941,13 @@ struct TransferData{DIM,NDF} vs_midpoints::Vector{Float64} vs_df::Vector{Float64} end -function TransferData(DIM::Integer,NDF::Integer,ps_num::Integer,total_vs_num::Integer) +function TransferData(DIM::Integer, NDF::Integer, ps_num::Integer, total_vs_num::Integer) return TransferData{DIM,NDF}( Vector{Int}(undef, (SOLID_CELL_ID_NUM+1)*ps_num), Vector{Float64}(undef, (DIM+2) * ps_num), Vector{Int8}(undef, total_vs_num), Vector{Float64}(undef, DIM * total_vs_num), - Vector{Float64}(undef, NDF * total_vs_num) + Vector{Float64}(undef, NDF * total_vs_num), ) end diff --git a/src/Theory/I-projection.jl b/src/Theory/I-projection.jl index 29f094f..3eccdb4 100644 --- a/src/Theory/I-projection.jl +++ b/src/Theory/I-projection.jl @@ -6,10 +6,10 @@ function build_psi_matrix(midpoint::AbstractMatrix{T}) where {T<:Real} N, D = size(midpoint) Psi = Matrix{T}(undef, N, D + 2) - @inbounds for k in 1:N + @inbounds for k = 1:N Psi[k, 1] = one(T) s = zero(T) - for d in 1:D + for d = 1:D x = midpoint[k, d] Psi[k, 1+d] = x s += x * x @@ -23,7 +23,7 @@ end dual_objective(Psi, f, W, weight, lambda) I-投影的对偶目标 - Φ(λ) = ⟨f* exp(λ·ψ)⟩ - λ·W = Σ_k ω_k f_k exp(λ·ψ_k) - λ·W. +Φ(λ) = ⟨f* exp(λ·ψ)⟩ - λ·W = Σ_k ω_k f_k exp(λ·ψ_k) - λ·W. 满足 ∇Φ = G, ∇²Φ = J. 严格凸, Newton 方向是 Φ 的下降方向, 可用于 Armijo. """ @@ -36,9 +36,9 @@ function dual_objective( ) where {T<:Real} N, M = size(Psi) acc = zero(T) - @inbounds for k in 1:N + @inbounds for k = 1:N dot_lp = zero(T) - for i in 1:M + for i = 1:M dot_lp += lambda[i] * Psi[k, i] end acc += weight[k] * f[k] * exp(dot_lp) @@ -57,8 +57,8 @@ function solve_I_projection( f::AbstractVector{T}, W::AbstractVector{T}, weight::AbstractVector{T}; - tol::Real=1e-10, - maxiter::Integer=10, + tol::Real = 1e-10, + maxiter::Integer = 10, ) where {T<:Real} N, D = size(midpoint) M = D + 2 @@ -83,22 +83,22 @@ function solve_I_projection( end - for _ in 1:maxiter + for _ = 1:maxiter fill!(G, zero(T)) fill!(J, zero(T)) - @inbounds for k in 1:N + @inbounds for k = 1:N dot_lp = zero(T) - for i in 1:M + for i = 1:M dot_lp += lambda[i] * Psi[k, i] end c = weight[k] * f[k] * exp(dot_lp) - for i in 1:M + for i = 1:M psi_ki = Psi[k, i] ci = c * psi_ki G[i] += ci - for j in i:M + for j = i:M J[i, j] += ci * Psi[k, j] end end @@ -106,11 +106,11 @@ function solve_I_projection( G .-= W G_norm = norm(G) - + if G_norm < tol_eff return lambda, Psi end - + # 检测停滞: 残差不再显著下降 if G_norm > 0.9 * G_prev_norm stall_count += 1 @@ -126,7 +126,7 @@ function solve_I_projection( Φ0 = dual_objective(Psi, f, W, weight, lambda) slope = dot(G, Δλ) # = ∇Φ·Δλ < 0 α = one(T) - for _ in 1:maxiter + for _ = 1:maxiter if dual_objective(Psi, f, W, weight, lambda + α*Δλ) ≤ Φ0 + 1e-4*α*slope break end @@ -141,24 +141,30 @@ function solve_I_projection( end -function conserved_I_porjection!(vs_data::VsData{2,2},w::AbstractVector) - e_int = @views dot(vs_data.weight,vs_data.df[:,2])/2 - w_trans = copy(w);w_trans[end]-=e_int - λ,Ψ = @views solve_I_projection(vs_data.midpoint,vs_data.df[:,1],w_trans,vs_data.weight) - for i in axes(vs_data.df,1) - vs_data.df[i,1]*= @views exp(dot(λ,Ψ[i,:])) +function conserved_I_porjection!(vs_data::VsData{2,2}, w::AbstractVector) + e_int = @views dot(vs_data.weight, vs_data.df[:, 2])/2 + w_trans = copy(w); + w_trans[end]-=e_int + λ, Ψ = @views solve_I_projection( + vs_data.midpoint, + vs_data.df[:, 1], + w_trans, + vs_data.weight, + ) + for i in axes(vs_data.df, 1) + vs_data.df[i, 1] *= @views exp(dot(λ, Ψ[i, :])) end end -function conserved_I_porjection!(vs_data::VsData{3,1},w::AbstractVector) - λ,Ψ = @views solve_I_projection(vs_data.midpoint,vs_data.df[:,1],w,vs_data.weight) - for i in axes(vs_data.df,1) - vs_data.df[i,1]*= @views exp(dot(λ,Ψ[i,:])) +function conserved_I_porjection!(vs_data::VsData{3,1}, w::AbstractVector) + λ, Ψ = @views solve_I_projection(vs_data.midpoint, vs_data.df[:, 1], w, vs_data.weight) + for i in axes(vs_data.df, 1) + vs_data.df[i, 1] *= @views exp(dot(λ, Ψ[i, :])) end end -function iterate!(::Type{CIP_Marching},ka::KA) +function iterate!(::Type{CIP_Marching}, ka::KA) kinfo = ka.kinfo gas = kinfo.config.gas trees = ka.kdata.field.trees @@ -166,28 +172,28 @@ function iterate!(::Type{CIP_Marching},ka::KA) for i in eachindex(trees.data) @inbounds for j in eachindex(trees.data[i]) ps_data = trees.data[i][j] - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue ps_data.bound_enc<0 && continue vs_data = ps_data.vs_data area = reduce(*, ps_data.ds) - ps_data.w .+= ps_data.flux .*Δt / area # Macroscopic update - positivity_preserving_ib!(ps_data,area,Δt) + ps_data.w .+= ps_data.flux .* Δt / area # Macroscopic update + positivity_preserving_ib!(ps_data, area, Δt) prim_c = get_prim(ps_data, kinfo) # Conserved macroscopic variables f = vs_data.df - f.+= Δt/area*vs_data.flux # Convection first + f .+= Δt/area*vs_data.flux # Convection first F_c = discrete_maxwell(vs_data.midpoint, prim_c, kinfo) ps_data.qf .= qf = calc_qf(vs_data, prim_c) # Heatflux after convection F_c .+= shakhov_part(vs_data.midpoint, F_c, prim_c, qf, kinfo) # g^{S,n+1} - conserved_I_porjection!(vs_data,ps_data.w) + conserved_I_porjection!(vs_data, ps_data.w) # Collision process τ = get_τ(prim_c, gas.μᵣ, gas.ω) # τ^{n+1} f .*= τ/(τ+Δt) @. f += Δt/(τ+Δt)*F_c - residual_check!(ps_data,prim_c,kinfo) + residual_check!(ps_data, prim_c, kinfo) ps_data.prim .= prim_c ps_data.flux .= 0.0 vs_data.flux .= 0.0 end end return nothing -end \ No newline at end of file +end diff --git a/src/Theory/Iterate.jl b/src/Theory/Iterate.jl index f74896e..bf8def6 100644 --- a/src/Theory/Iterate.jl +++ b/src/Theory/Iterate.jl @@ -2,9 +2,9 @@ $(TYPEDSIGNATURES) Outer function of collision and time marching. """ -function iterate!(p4est::P_pxest_t,ka::KA) +function iterate!(p4est::P_pxest_t, ka::KA) time_marching = ka.kinfo.config.solver.time_marching - iterate!(time_marching,ka) + iterate!(time_marching, ka) residual_comm!(ka.kinfo) data_exchange!(p4est, ka) ka.kinfo.status.step += 1 @@ -28,12 +28,12 @@ function limit_Δt!(ka::KA) status = ka.kinfo.status output = ka.kinfo.config.output Δt = status.Δt_ξ - if output.anim_dt > 0. + if output.anim_dt > 0.0 Δt_anim = (output.anim_index+1)*output.anim_dt - status.sim_time - Δt_anim > 0. && (Δt = min(Δt, Δt_anim)) + Δt_anim > 0.0 && (Δt = min(Δt, Δt_anim)) end Δt_end = ka.kinfo.config.solver.max_sim_time - status.sim_time - Δt_end > 0. && (Δt = min(Δt, Δt_end)) + Δt_end > 0.0 && (Δt = min(Δt, Δt_end)) status.Δt = Δt return nothing end @@ -46,7 +46,7 @@ tolerance). Use as the main-loop termination condition. Always `false` for the d function reached_max_time(ka::KA) return ka.kinfo.status.sim_time >= ka.kinfo.config.solver.max_sim_time*(1-1e-12) end -function iterate!(::Type{UGKS_Marching},ka::KA) +function iterate!(::Type{UGKS_Marching}, ka::KA) kinfo = ka.kinfo gas = kinfo.config.gas trees = ka.kdata.field.trees @@ -55,7 +55,7 @@ function iterate!(::Type{UGKS_Marching},ka::KA) @inbounds for i in eachindex(trees.data) @inbounds for j in eachindex(trees.data[i]) ps_data = trees.data[i][j] - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue ps_data.bound_enc<0 && continue vs_data = ps_data.vs_data prim_ = get_prim(ps_data, kinfo) @@ -66,14 +66,14 @@ function iterate!(::Type{UGKS_Marching},ka::KA) ps_data.prim .= prim = get_prim(ps_data, kinfo) f = vs_data.df if 1/prim[end]<1e-6 - @. f = max(f,0.) + @. f = max(f, 0.0) ps_data.w = calc_w0(ps_data) - prim = get_prim(ps_data,kinfo) + prim = get_prim(ps_data, kinfo) τ = kinfo.config.gas.Kn else τ = get_τ(prim, gas.μᵣ, gas.ω) end - residual_check!(ps_data,prim_,kinfo) + residual_check!(ps_data, prim_, kinfo) ps_data.qf .= qf = calc_qf(vs_data, prim_) F_ = discrete_maxwell(vs_data.midpoint, prim_, kinfo) F = discrete_maxwell(vs_data.midpoint, prim, kinfo) @@ -82,7 +82,10 @@ function iterate!(::Type{UGKS_Marching},ka::KA) F⁺ = shakhov_part(vs_data.midpoint, F, prim, qf, kinfo) F .+= F⁺ f = vs_data.df - @inbounds @. f = abs((f + 0.5 * Δt * (F / τ + (F_ - f) / τ_)) / (1.0 + 0.5 * Δt / τ) + vs_data.flux / area / (1.0 + 0.5 * Δt / τ)) + @inbounds @. f = abs( + (f + 0.5 * Δt * (F / τ + (F_ - f) / τ_)) / (1.0 + 0.5 * Δt / τ) + + vs_data.flux / area / (1.0 + 0.5 * Δt / τ), + ) vs_data.flux .= 0.0 end end @@ -93,7 +96,7 @@ end $(TYPEDSIGNATURES) Iteration for Conserved Adaptive Implicit DVM (CAIDVM). """ -function iterate!(::Type{CAIDVM_Marching},ka::KA) +function iterate!(::Type{CAIDVM_Marching}, ka::KA) kinfo = ka.kinfo gas = kinfo.config.gas trees = ka.kdata.field.trees @@ -101,16 +104,16 @@ function iterate!(::Type{CAIDVM_Marching},ka::KA) for i in eachindex(trees.data) @inbounds for j in eachindex(trees.data[i]) ps_data = trees.data[i][j] - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue ps_data.bound_enc<0 && continue vs_data = ps_data.vs_data area = reduce(*, ps_data.ds) - ps_data.w .+= ps_data.flux .*Δt / area # Macroscopic update + ps_data.w .+= ps_data.flux .* Δt / area # Macroscopic update prim_c = get_prim(ps_data, kinfo) # Conserved macroscopic variables f = vs_data.df - f.+= Δt/area*vs_data.flux # Convection first - w = calc_w0(vs_data.midpoint,f,vs_data.weight,kinfo) - prim = get_prim(w,kinfo) + f .+= Δt/area*vs_data.flux # Convection first + w = calc_w0(vs_data.midpoint, f, vs_data.weight, kinfo) + prim = get_prim(w, kinfo) τ = get_τ(prim_c, gas.μᵣ, gas.ω) # τ^{n+1} F_c = discrete_maxwell(vs_data.midpoint, prim_c, kinfo) F = discrete_maxwell(vs_data.midpoint, prim, kinfo) @@ -120,7 +123,7 @@ function iterate!(::Type{CAIDVM_Marching},ka::KA) # Collision process f .*= τ/(τ+Δt) @. f += Δt/(τ+Δt)*F_c - residual_check!(ps_data,prim_c,kinfo) + residual_check!(ps_data, prim_c, kinfo) ps_data.prim .= prim_c ps_data.flux .= 0.0 vs_data.flux .= 0.0 @@ -128,7 +131,7 @@ function iterate!(::Type{CAIDVM_Marching},ka::KA) end return nothing end -function iterate!(::Type{Euler},ka::KA{DIM}) where{DIM} +function iterate!(::Type{Euler}, ka::KA{DIM}) where {DIM} kinfo = ka.kinfo gas = kinfo.config.gas trees = ka.kdata.field.trees @@ -137,14 +140,14 @@ function iterate!(::Type{Euler},ka::KA{DIM}) where{DIM} @inbounds for i in eachindex(trees.data) @inbounds for j in eachindex(trees.data[i]) ps_data = trees.data[i][j] - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue ps_data.bound_enc<0 && continue vs_data = ps_data.vs_data area = reduce(*, ps_data.ds) - if isa(ka.kinfo.config.solver.flux,MicroFlux) + if isa(ka.kinfo.config.solver.flux, MicroFlux) ps_data.w = calc_w0(ps_data) else - ps_data.w .+= ps_data.flux .*Δt / area + ps_data.w .+= ps_data.flux .* Δt / area ps_data.flux .= 0.0 end prim = get_prim(ps_data, kinfo) @@ -154,9 +157,9 @@ function iterate!(::Type{Euler},ka::KA{DIM}) where{DIM} F = discrete_maxwell(vs_data.midpoint, prim, kinfo) F .+= shakhov_part(vs_data.midpoint, F, prim, qf, kinfo) f .= (f+Δt/area*vs_data.flux)*τ/(τ+Δt)+Δt/(τ+Δt)*F - residual_check!(ps_data,prim,kinfo) + residual_check!(ps_data, prim, kinfo) ps_data.prim .= prim vs_data.flux .= 0.0 end end -end \ No newline at end of file +end diff --git a/src/Theory/Math.jl b/src/Theory/Math.jl index 52d76af..aa0cf1b 100644 --- a/src/Theory/Math.jl +++ b/src/Theory/Math.jl @@ -58,7 +58,12 @@ function get_sprim(sw::AbstractMatrix, prim::AbstractVector, gamma::Real) sprim = similar(sw) get_sprim!(sprim, sw, prim, gamma) end -function get_sprim!(sprim::AbstractVector, sw::AbstractVector, prim::AbstractVector, gamma::Real) +function get_sprim!( + sprim::AbstractVector, + sw::AbstractVector, + prim::AbstractVector, + gamma::Real, +) DIM = length(prim) - 2 @inbounds begin rho = prim[1] @@ -67,21 +72,26 @@ function get_sprim!(sprim::AbstractVector, sw::AbstractVector, prim::AbstractVec velocity2 = zero(lambda * sw[1] / rho) momentum_slope = zero(lambda * sw[1] / rho) - for i in 1:DIM - velocity = prim[i + 1] - sw_momentum = sw[i + 1] - sprim[i + 1] = (sw_momentum - velocity * sw[1]) / rho + for i = 1:DIM + velocity = prim[i+1] + sw_momentum = sw[i+1] + sprim[i+1] = (sw_momentum - velocity * sw[1]) / rho velocity2 += velocity^2 momentum_slope += velocity * sw_momentum end internal_energy = 0.5 * rho / lambda / (gamma - 1.0) - internal_slope = sw[DIM + 2] - momentum_slope + 0.5 * velocity2 * sw[1] - sprim[DIM + 2] = lambda * (sw[1] / rho - internal_slope / internal_energy) + internal_slope = sw[DIM+2] - momentum_slope + 0.5 * velocity2 * sw[1] + sprim[DIM+2] = lambda * (sw[1] / rho - internal_slope / internal_energy) end return sprim end -function get_sprim!(sprim::AbstractMatrix, sw::AbstractMatrix, prim::AbstractVector, gamma::Real) +function get_sprim!( + sprim::AbstractMatrix, + sw::AbstractMatrix, + prim::AbstractVector, + gamma::Real, +) @inbounds for dir in axes(sw, 2) get_sprim!(view(sprim, :, dir), view(sw, :, dir), prim, gamma) end @@ -96,11 +106,7 @@ Caculate the discretized Maxwellian distribution according to the primary macros function discrete_maxwell(ps_data::PsData, kinfo::KInfo) discrete_maxwell(ps_data.vs_data.midpoint, ps_data.prim, kinfo) end -function discrete_maxwell( - midpoint::AbstractMatrix, - prim::AbstractVector, - ::KInfo{3,1}, -) +function discrete_maxwell(midpoint::AbstractMatrix, prim::AbstractVector, ::KInfo{3,1}) discrete_maxwell_3D1F( @view(midpoint[:, 1]), @view(midpoint[:, 2]), @@ -109,11 +115,7 @@ function discrete_maxwell( ) end -function discrete_maxwell( - midpoint::AbstractMatrix, - prim::AbstractVector, - kinfo::KInfo{2,2}, -) +function discrete_maxwell(midpoint::AbstractMatrix, prim::AbstractVector, kinfo::KInfo{2,2}) discrete_maxwell_2D2F( @view(midpoint[:, 1]), @view(midpoint[:, 2]), @@ -121,25 +123,11 @@ function discrete_maxwell( kinfo.config.gas.K, ) end -function discrete_maxwell( - midpoint::AbstractVector, - prim::AbstractVector, - ::KInfo{3,1}, -) - discrete_maxwell_3D1F( - midpoint[1], - midpoint[2], - midpoint[3], - prim, - ) +function discrete_maxwell(midpoint::AbstractVector, prim::AbstractVector, ::KInfo{3,1}) + discrete_maxwell_3D1F(midpoint[1], midpoint[2], midpoint[3], prim) end -function discrete_maxwell(midpoint::AbstractVector,prim::AbstractVector,kinfo::KInfo{2,2}) - discrete_maxwell_2D2F( - midpoint[1], - midpoint[2], - prim, - kinfo.config.gas.K, - ) +function discrete_maxwell(midpoint::AbstractVector, prim::AbstractVector, kinfo::KInfo{2,2}) + discrete_maxwell_2D2F(midpoint[1], midpoint[2], prim, kinfo.config.gas.K) end """ @@ -170,7 +158,7 @@ function shakhov_part( prim::AbstractVector, qf::AbstractVector, kinfo::KInfo{2,2}, -) where{T<:Union{Tuple,AbstractVector}} +) where {T<:Union{Tuple,AbstractVector}} shakhov_part_2D2F( midpoint[1], midpoint[2], @@ -194,7 +182,7 @@ function shakhov_part( midpoint[:, 1], midpoint[:, 2], midpoint[:, 3], - F[:,1], + F[:, 1], prim, qf, kinfo.config.gas.Pr, @@ -230,23 +218,68 @@ end $(TYPEDSIGNATURES) Calculate the conserved macroscopic variables according to the microscopic distribution. """ -function calc_w0(midpoint::AbstractMatrix,df::AbstractMatrix,weight::AbstractVector,::KInfo{2,2}) - @views micro_to_macro_2D2F(midpoint[:,1],midpoint[:,2],df[:,1],df[:,2],weight) +function calc_w0( + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + ::KInfo{2,2}, +) + @views micro_to_macro_2D2F(midpoint[:, 1], midpoint[:, 2], df[:, 1], df[:, 2], weight) end -function calc_w0(midpoint::AbstractMatrix,df::AbstractMatrix,weight::AbstractVector,::KInfo{3,1}) - @views micro_to_macro_3D1F(midpoint[:,1],midpoint[:,2],midpoint[:,3],df[:,1],weight) +function calc_w0( + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + ::KInfo{3,1}, +) + @views micro_to_macro_3D1F( + midpoint[:, 1], + midpoint[:, 2], + midpoint[:, 3], + df[:, 1], + weight, + ) end -function calc_qf(midpoint::AbstractMatrix,df::AbstractMatrix,weight::AbstractVector,prim::AbstractVector,::KInfo{2,2}) - @views heat_flux_2D2F(midpoint[:,1],midpoint[:,2],df[:,1],df[:,2],prim,weight) +function calc_qf( + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + prim::AbstractVector, + ::KInfo{2,2}, +) + @views heat_flux_2D2F(midpoint[:, 1], midpoint[:, 2], df[:, 1], df[:, 2], prim, weight) end -function calc_qf(midpoint::AbstractMatrix,df::AbstractMatrix,weight::AbstractVector,prim::AbstractVector,::KInfo{3,1}) - @views heat_flux_3D1F(midpoint[:,1],midpoint[:,2],midpoint[:,3],df[:,1],prim,weight) +function calc_qf( + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + prim::AbstractVector, + ::KInfo{3,1}, +) + @views heat_flux_3D1F( + midpoint[:, 1], + midpoint[:, 2], + midpoint[:, 3], + df[:, 1], + prim, + weight, + ) end -function calc_pressure(midpoint::AbstractMatrix,df::AbstractMatrix,weight::AbstractVector,::KInfo{2}) - @views pressure_2D(midpoint[:,1],midpoint[:,2],df[:,1],weight) +function calc_pressure( + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + ::KInfo{2}, +) + @views pressure_2D(midpoint[:, 1], midpoint[:, 2], df[:, 1], weight) end -function calc_pressure(midpoint::AbstractMatrix,df::AbstractMatrix,weight::AbstractVector,::KInfo{3}) - @views pressure_3D(midpoint[:,1],midpoint[:,2],midpoint[:,3],df[:,1],weight) +function calc_pressure( + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + ::KInfo{3}, +) + @views pressure_3D(midpoint[:, 1], midpoint[:, 2], midpoint[:, 3], df[:, 1], weight) end function calc_ρw( there_midpoint::AbstractMatrix, @@ -256,12 +289,20 @@ function calc_ρw( there_vn::AbstractVector, here_weight, there_weight, - ::KA{2,2} + ::KA{2,2}, ) - @inbounds @views SF = sum(@. here_weight * here_vn * here_df[:,1]) + @inbounds @views SF = sum(@. here_weight * here_vn * here_df[:, 1]) @inbounds @views SG = - prim[4] / π * - sum(@. there_weight * there_vn * exp(-prim[4] * ((there_midpoint[:,1] - prim[2])^2 + (there_midpoint[:,2] - prim[3])^2))) + prim[4] / π * sum( + @. there_weight * + there_vn * + exp( + -prim[4] * ( + (there_midpoint[:, 1] - prim[2])^2 + + (there_midpoint[:, 2] - prim[3])^2 + ), + ) + ) return -SF / SG end function calc_ρw( @@ -272,12 +313,21 @@ function calc_ρw( there_vn::AbstractVector, here_weight, there_weight, - ::KA{3,1} + ::KA{3,1}, ) - @inbounds @views SF = sum(@. here_weight * here_vn * here_df[:,1]) + @inbounds @views SF = sum(@. here_weight * here_vn * here_df[:, 1]) @inbounds @views SG = - (prim[5] / π)^(3/2) * - sum(@. there_weight * there_vn * exp(-prim[5] * ((there_midpoint[:,1] - prim[2])^2 + (there_midpoint[:,2] - prim[3])^2+(there_midpoint[:,3] - prim[4])^2))) + (prim[5] / π)^(3/2) * sum( + @. there_weight * + there_vn * + exp( + -prim[5] * ( + (there_midpoint[:, 1] - prim[2])^2 + + (there_midpoint[:, 2] - prim[3])^2 + + (there_midpoint[:, 3] - prim[4])^2 + ), + ) + ) return -SF / SG end function calc_ρw( @@ -338,24 +388,24 @@ function calc_fwb(vs_data::VsData{3,1}, F::AbstractMatrix, vn::AbstractVector) end function calc_w0(ps_data::AbstractPsData{2,2}) - vs_data = ps_data.vs_data - @inbounds micro_to_macro_2D2F( - @view(vs_data.midpoint[:,1]), - @view(vs_data.midpoint[:,2]), - @view(vs_data.df[:,1]), - @view(vs_data.df[:,2]), - vs_data.weight - ) + vs_data = ps_data.vs_data + @inbounds micro_to_macro_2D2F( + @view(vs_data.midpoint[:, 1]), + @view(vs_data.midpoint[:, 2]), + @view(vs_data.df[:, 1]), + @view(vs_data.df[:, 2]), + vs_data.weight, + ) end function calc_w0(ps_data::AbstractPsData{3,1}) - vs_data = ps_data.vs_data - @inbounds @views micro_to_macro_3D1F( - vs_data.midpoint[:,1], - vs_data.midpoint[:,2], - vs_data.midpoint[:,3], - vs_data.df[:,1], - vs_data.weight - ) + vs_data = ps_data.vs_data + @inbounds @views micro_to_macro_3D1F( + vs_data.midpoint[:, 1], + vs_data.midpoint[:, 2], + vs_data.midpoint[:, 3], + vs_data.df[:, 1], + vs_data.weight, + ) end function calc_a( @@ -383,12 +433,7 @@ function micro_slope(sw::AbstractVector, prim::AbstractVector, kinfo::KInfo{3}) micro_slope_3D(sw, prim, kinfo.config.gas.K) end -function moment_u( - prim0::AbstractVector, - kinfo::KInfo{2,2}, - ROT::Real, - DIR::Integer, -) +function moment_u(prim0::AbstractVector, kinfo::KInfo{2,2}, ROT::Real, DIR::Integer) @inbounds U = prim0[DIR+1] V = prim0[FAT[1][DIR]+1] λ = prim0[4] @@ -475,7 +520,7 @@ function calc_A( micro_slope(sw, prim, kinfo) end -function calc_flux_f0_2D2F(prim,Mt,Mu,Mv,Mξ,a,A) +function calc_flux_f0_2D2F(prim, Mt, Mu, Mv, Mξ, a, A) Mau_0 = moment_uv_2D2F(Mu, Mv, Mξ, 1, 0, 0) Mau2 = moment_au_2D2F(a, Mu, Mv, Mξ, 2, 0) Mau_T = moment_au_2D2F(A, Mu, Mv, Mξ, 1, 0) @@ -517,7 +562,19 @@ function calc_flux_g0_3D1F(prim, Mt, Mu, Mv, Mw, Mu_L, Mu_R, aL, aR, A, dir) end -function calc_flux_f0_2D2F(u::AbstractVector{T}, v, h, b, sh, sb, weight, H⁺, B⁺, vn, Mt) where {T} +function calc_flux_f0_2D2F( + u::AbstractVector{T}, + v, + h, + b, + sh, + sb, + weight, + H⁺, + B⁺, + vn, + Mt, +) where {T} F = Vector{T}(undef, 4) @inbounds begin F[1] = @@ -570,11 +627,31 @@ function calc_flux_f0_3D1F(u::AbstractVector{T}, v, w, f, sf, weight, F⁺, vn, end -function calc_unified_ft(midpoint::AbstractMatrix,df::AbstractMatrix,sdf::AbstractMatrix,F::AbstractMatrix,F⁺::AbstractMatrix,ax,at,Mξ,Mt,dir,::KInfo{2,2}) - f = similar(df);vn = @views midpoint[:,dir] - u = @views midpoint[:,1];v = @views midpoint[:,2];h = @views df[:,1];b = @views df[:,2] - sh = @views sdf[:,1]; sb = @views sdf[:,2] - H0 = @views F[:,1]; B0 = @views F[:,2]; H⁺ = @views F⁺[:,1]; B⁺ = @views F⁺[:,2] +function calc_unified_ft( + midpoint::AbstractMatrix, + df::AbstractMatrix, + sdf::AbstractMatrix, + F::AbstractMatrix, + F⁺::AbstractMatrix, + ax, + at, + Mξ, + Mt, + dir, + ::KInfo{2,2}, +) + f = similar(df); + vn = @views midpoint[:, dir] + u = @views midpoint[:, 1]; + v = @views midpoint[:, 2]; + h = @views df[:, 1]; + b = @views df[:, 2] + sh = @views sdf[:, 1]; + sb = @views sdf[:, 2] + H0 = @views F[:, 1]; + B0 = @views F[:, 2]; + H⁺ = @views F⁺[:, 1]; + B⁺ = @views F⁺[:, 2] @inbounds begin @. f[:, 1] = Mt[1] * (H0 + H⁺) + @@ -585,9 +662,8 @@ function calc_unified_ft(midpoint::AbstractMatrix,df::AbstractMatrix,sdf::Abstra ax[2] * u * H0 + ax[3] * v * H0 + 0.5 * ax[4] * ((u^2 + v^2) * H0 + B0) - )+ - Mt[3] * - ( + ) + + Mt[3] * ( at[1] * H0 + at[2] * u * H0 + at[3] * v * H0 + @@ -595,7 +671,7 @@ function calc_unified_ft(midpoint::AbstractMatrix,df::AbstractMatrix,sdf::Abstra ) + Mt[4] * h - Mt[5] * vn * sh @. f[:, 2] = - Mt[1] * (B0 + B⁺) + + Mt[1] * (B0 + B⁺) + Mt[2] * vn * ( @@ -604,8 +680,7 @@ function calc_unified_ft(midpoint::AbstractMatrix,df::AbstractMatrix,sdf::Abstra ax[3] * v * B0 + 0.5 * ax[4] * ((u^2 + v^2) * B0 + Mξ[3] * H0) ) + - Mt[3] * - ( + Mt[3] * ( at[1] * B0 + at[2] * u * B0 + at[3] * v * B0 + @@ -754,9 +829,31 @@ function calc_micro_flux_3D1F( return micro_flux .* ds end -function micro_to_macro(df::AbstractMatrix,midpoint::AbstractMatrix,weight::AbstractVector,::AbstractVsData{2,2}) - @inbounds @views micro_to_macro_2D2F(midpoint[:,1],midpoint[:,2],df[:,1],df[:,2],weight) +function micro_to_macro( + df::AbstractMatrix, + midpoint::AbstractMatrix, + weight::AbstractVector, + ::AbstractVsData{2,2}, +) + @inbounds @views micro_to_macro_2D2F( + midpoint[:, 1], + midpoint[:, 2], + df[:, 1], + df[:, 2], + weight, + ) end -function micro_to_macro(df::AbstractMatrix,midpoint::AbstractMatrix,weight::AbstractVector,::AbstractVsData{3,1}) - @inbounds @views micro_to_macro_3D1F(midpoint[:,1],midpoint[:,2],midpoint[:,3],df[:,1],weight) +function micro_to_macro( + df::AbstractMatrix, + midpoint::AbstractMatrix, + weight::AbstractVector, + ::AbstractVsData{3,1}, +) + @inbounds @views micro_to_macro_3D1F( + midpoint[:, 1], + midpoint[:, 2], + midpoint[:, 3], + df[:, 1], + weight, + ) end diff --git a/src/Velocity_space/AMR.jl b/src/Velocity_space/AMR.jl index 6d6cd5c..5801498 100644 --- a/src/Velocity_space/AMR.jl +++ b/src/Velocity_space/AMR.jl @@ -6,15 +6,23 @@ criterion distribution `df + max_d|sdf*ds|` and the midpoint of velocity cell `c refine/coarsen decision can evaluate the contribution criteria per cell without allocating a full criterion matrix. `ds` is the *physical* cell size `ps_data.ds`. """ -@inline function _criterion_cell!(cdf_i, mid_i, vs_data::AbstractVsData{DIM,NDF}, ds, c::Int) where {DIM,NDF} - df = vs_data.df; sdf = vs_data.sdf - @inbounds for d in 1:DIM +@inline function _criterion_cell!( + cdf_i, + mid_i, + vs_data::AbstractVsData{DIM,NDF}, + ds, + c::Int, +) where {DIM,NDF} + df = vs_data.df; + sdf = vs_data.sdf + @inbounds for d = 1:DIM mid_i[d] = vs_data.midpoint[c, d] end - @inbounds for k in 1:NDF + @inbounds for k = 1:NDF m = 0.0 - for d in 1:DIM - a = abs(sdf[c, k, d] * ds[d]); a > m && (m = a) + for d = 1:DIM + a = abs(sdf[c, k, d] * ds[d]); + a > m && (m = a) end cdf_i[k] = df[c, k] + m end @@ -23,11 +31,14 @@ end """ $(TYPEDSIGNATURES) """ -function vs_refine!(va_data::Velocity_Adaptive_Data, ka::KA{DIM,NDF}) where{DIM,NDF} - trees = ka.kdata.field.trees;kinfo = ka.kinfo - !isa(kinfo.config.quadrature,Vector)&&return nothing - ds = [(kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / - kinfo.config.vs_trees_num[i] for i in 1:DIM] +function vs_refine!(va_data::Velocity_Adaptive_Data, ka::KA{DIM,NDF}) where {DIM,NDF} + trees = ka.kdata.field.trees; + kinfo = ka.kinfo + !isa(kinfo.config.quadrature, Vector)&&return nothing + ds = [ + (kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / + kinfo.config.vs_trees_num[i] for i = 1:DIM + ] va_flags = va_data.va_flags id = 0 lohner = kinfo.config.solver.ADAPT_VS_MODE === :lohner @@ -44,22 +55,41 @@ function vs_refine!(va_data::Velocity_Adaptive_Data, ka::KA{DIM,NDF}) where{DIM, for j in eachindex(trees.data[i]) id += 1 ps_data = trees.data[i][j] - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue vs_data = ps_data.vs_data - U = @view(ps_data.prim[2:1+DIM]) + U = @view(ps_data.prim[2:(1+DIM)]) n = vs_data.vs_num - s1 = 0.0; s2 = 0.0 + s1 = 0.0; + s2 = 0.0 if lohner build_vs_index!(vsidx, vs_data, vmin, ds0, vstn, maxlevel) s1, s2 = vs_lohner_scales(vs_data) end resize!(refine_flags, n) - @inbounds for c in 1:n + @inbounds for c = 1:n _criterion_cell!(cdf_i, mid_i, vs_data, ps_data.ds, c) - base = lohner ? - (vs_lohner_indicator(vs_data, vsidx, c, s1, s2) > τL || - local_contribution_refine_flag(ps_data.w, U, mid_i, cdf_i, vs_data.weight[c], kinfo)) : - contribution_refine_flag(ps_data.w, U, mid_i, cdf_i, vs_data.weight[c], va_data.vr, kinfo) + base = + lohner ? + ( + vs_lohner_indicator(vs_data, vsidx, c, s1, s2) > τL || + local_contribution_refine_flag( + ps_data.w, + U, + mid_i, + cdf_i, + vs_data.weight[c], + kinfo, + ) + ) : + contribution_refine_flag( + ps_data.w, + U, + mid_i, + cdf_i, + vs_data.weight[c], + va_data.vr, + kinfo, + ) refine_flags[c] = vs_data.level[c] < maxlevel && base end refine_grid_stream!(vs_data, refine_flags, ds) && (va_flags[id] = true) @@ -70,10 +100,13 @@ end """ $(TYPEDSIGNATURES) """ -function vs_coarsen!(va_data::Velocity_Adaptive_Data,ka::KA{DIM,NDF})where{DIM,NDF} - trees = ka.kdata.field.trees;kinfo = ka.kinfo - ds = [(kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / - kinfo.config.vs_trees_num[i] for i in 1:DIM] +function vs_coarsen!(va_data::Velocity_Adaptive_Data, ka::KA{DIM,NDF}) where {DIM,NDF} + trees = ka.kdata.field.trees; + kinfo = ka.kinfo + ds = [ + (kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / + kinfo.config.vs_trees_num[i] for i = 1:DIM + ] va_flags = va_data.va_flags id = 0 lohner = kinfo.config.solver.ADAPT_VS_MODE === :lohner @@ -90,23 +123,49 @@ function vs_coarsen!(va_data::Velocity_Adaptive_Data,ka::KA{DIM,NDF})where{DIM,N for j in eachindex(trees.data[i]) id += 1 ps_data = trees.data[i][j] - isa(ps_data,InsideSolidData) && continue + isa(ps_data, InsideSolidData) && continue vs_data = ps_data.vs_data - U = @view(ps_data.prim[2:1+DIM]) + U = @view(ps_data.prim[2:(1+DIM)]) n = vs_data.vs_num - s1 = 0.0; s2 = 0.0 + s1 = 0.0; + s2 = 0.0 if lohner build_vs_index!(vsidx, vs_data, vmin, ds0, vstn, maxlevel) s1, s2 = vs_lohner_scales(vs_data) end resize!(coarsen_ok, n) - @inbounds for c in 1:n + @inbounds for c = 1:n _criterion_cell!(cdf_i, mid_i, vs_data, ps_data.ds, c) - coarsen_ok[c] = lohner ? - (vs_lohner_indicator(vs_data, vsidx, c, s1, s2) < τc && - local_contribution_coarsen_flag(ps_data.w, U, mid_i, cdf_i, vs_data.weight[c], kinfo)) : - (local_contribution_coarsen_flag(ps_data.w, U, mid_i, cdf_i, vs_data.weight[c], kinfo) && - global_contribution_coarsen_flag(U, mid_i, cdf_i, vs_data.weight[c], va_data.vr, kinfo)) + coarsen_ok[c] = + lohner ? + ( + vs_lohner_indicator(vs_data, vsidx, c, s1, s2) < τc && + local_contribution_coarsen_flag( + ps_data.w, + U, + mid_i, + cdf_i, + vs_data.weight[c], + kinfo, + ) + ) : + ( + local_contribution_coarsen_flag( + ps_data.w, + U, + mid_i, + cdf_i, + vs_data.weight[c], + kinfo, + ) && global_contribution_coarsen_flag( + U, + mid_i, + cdf_i, + vs_data.weight[c], + va_data.vr, + kinfo, + ) + ) end coarsen_grid_stream!(vs_data, coarsen_ok, ds, maxlevel) && (va_flags[id] = true) end @@ -117,86 +176,97 @@ end """ $(TYPEDSIGNATURES) """ -function vs_conserved_correction!(va_data::Velocity_Adaptive_Data,ka) +function vs_conserved_correction!(va_data::Velocity_Adaptive_Data, ka) trees = ka.kdata.field.trees va_flags = va_data.va_flags id = 0 @inbounds for i in eachindex(trees.data) for j in eachindex(trees.data[i]) - id+=1;!va_flags[id]&&continue + id+=1; + !va_flags[id]&&continue ps_data = trees.data[i][j] - (isa(ps_data,InsideSolidData)||ps_data.bound_enc<0)&&continue + (isa(ps_data, InsideSolidData)||ps_data.bound_enc<0)&&continue vs_data = ps_data.vs_data - conserved_I_porjection!(vs_data,ps_data.w) + conserved_I_porjection!(vs_data, ps_data.w) end end end function vs_resolution(ka) trees = ka.kdata.field.trees - vs_resolution(trees,ka.kinfo) + vs_resolution(trees, ka.kinfo) end -function vs_resolution(trees::PsTrees,kinfo) - density_res = 0.;energy_res = 0. +function vs_resolution(trees::PsTrees, kinfo) + density_res = 0.0; + energy_res = 0.0 @inbounds for tree in trees.data for ps_data in tree - (isa(ps_data,InsideSolidData)||ps_data.bound_enc<0)&&continue - density_res_i,energy_res_i = vs_resolution(ps_data,kinfo) - density_res = max(density_res_i,density_res) - energy_res = max(energy_res_i,energy_res) + (isa(ps_data, InsideSolidData)||ps_data.bound_enc<0)&&continue + density_res_i, energy_res_i = vs_resolution(ps_data, kinfo) + density_res = max(density_res_i, density_res) + energy_res = max(energy_res_i, energy_res) end end density_res = MPI.Allreduce(density_res, MPI.MAX, MPI.COMM_WORLD) energy_res = MPI.Allreduce(energy_res, MPI.MAX, MPI.COMM_WORLD) - return Velocity_Resolution(density_res,energy_res) + return Velocity_Resolution(density_res, energy_res) end -function vs_resolution(ps_data::PsData{DIM,NDF},kinfo) where{DIM,NDF} +function vs_resolution(ps_data::PsData{DIM,NDF}, kinfo) where {DIM,NDF} vs_data = ps_data.vs_data - U = ps_data.prim[2:DIM+1] + U = ps_data.prim[2:(DIM+1)] density_max = maximum(vs_data.df) - c2 = @views [sum((U-u).^2) for u in eachrow(vs_data.midpoint)] - energy_max = NDF==1 ? 0.5*maximum(vs_data.df.*c2) : 0.5*maximum(@view(vs_data.df[:,1]).*c2+@view(vs_data.df[:,2])) + c2 = @views [sum((U-u) .^ 2) for u in eachrow(vs_data.midpoint)] + energy_max = + NDF==1 ? 0.5*maximum(vs_data.df .* c2) : + 0.5*maximum(@view(vs_data.df[:, 1]) .* c2+@view(vs_data.df[:, 2])) vs_trees_num = kinfo.config.vs_trees_num quadrature = kinfo.config.quadrature - du = [quadrature[2*i]-quadrature[2*i-1] for i in 1:DIM] - weight = reduce(*,du)/reduce(*,vs_trees_num)/2^(DIM*(kinfo.config.solver.AMR_VS_MAXLEVEL)) - return density_max*weight,energy_max*weight + du = [quadrature[2*i]-quadrature[2*i-1] for i = 1:DIM] + weight = + reduce(*, du)/reduce(*, vs_trees_num)/2^(DIM*(kinfo.config.solver.AMR_VS_MAXLEVEL)) + return density_max*weight, energy_max*weight end """ $(TYPEDSIGNATURES) """ -function vs_adaptive_mesh_refinement!(ka;vs_balance = false) +function vs_adaptive_mesh_refinement!(ka; vs_balance = false) vr = vs_resolution(ka) fp = PointerWrapper(ka.kinfo.forest.p4est) - va_flags = zeros(Bool,fp.local_num_quadrants[]) - va_data = Velocity_Adaptive_Data(vr,va_flags) - vs_refine!(va_data,ka) - vs_coarsen!(va_data,ka) + va_flags = zeros(Bool, fp.local_num_quadrants[]) + va_data = Velocity_Adaptive_Data(vr, va_flags) + vs_refine!(va_data, ka) + vs_coarsen!(va_data, ka) changed = any(va_flags) if vs_balance changed |= vs_balance!(ka) end - vs_conserved_correction!(va_data,ka) + vs_conserved_correction!(va_data, ka) return Bool(MPI.Allreduce(Int(changed), +, MPI.COMM_WORLD) > 0) end -function initial_vs_adaptive_mesh_refinement!(prim,vs_data,kinfo::KInfo{DIM,NDF}) where{DIM,NDF} - ds = [(kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / - kinfo.config.vs_trees_num[i] for i in 1:DIM] +function initial_vs_adaptive_mesh_refinement!( + prim, + vs_data, + kinfo::KInfo{DIM,NDF}, +) where {DIM,NDF} + ds = [ + (kinfo.config.quadrature[2*i] - kinfo.config.quadrature[2*i-1]) / + kinfo.config.vs_trees_num[i] for i = 1:DIM + ] maxlevel = kinfo.config.solver.AMR_VS_MAXLEVEL - ddus = [ds ./ 2.0^i for i in 0:maxlevel] # cell size per level - U = @view(prim[2:1+DIM]) + ddus = [ds ./ 2.0^i for i = 0:maxlevel] # cell size per level + U = @view(prim[2:(1+DIM)]) n = vs_data.vs_num refine_flags = Vector{Bool}(undef, n) I0buf = Vector{Float64}(undef, DIM) I2buf = Vector{Float64}(undef, DIM) - @inbounds for c in 1:n + @inbounds for c = 1:n L = vs_data.level[c] mid = @view(vs_data.midpoint[c, :]) - refine_flags[c] = L < maxlevel && + refine_flags[c] = + L < maxlevel && maxwellian_refine_flag(mid, ddus[L+1], U, prim, kinfo, I0buf, I2buf) end refine_grid_stream!(vs_data, refine_flags, ds) return nothing end - diff --git a/src/Velocity_space/Balance.jl b/src/Velocity_space/Balance.jl index fbc7ef7..8d6a9d6 100644 --- a/src/Velocity_space/Balance.jl +++ b/src/Velocity_space/Balance.jl @@ -22,18 +22,24 @@ function vs_balance_pair!( # balances this pair (a cell may need several levels), each level costing O(N) instead of the # O(N) positional insert! per refined cell. while true - nL = vs_local.vs_num; nN = vs_neighbor.vs_num - resize!(refine_flags, nL); fill!(refine_flags, false) - i = 1; j = 1 + nL = vs_local.vs_num; + nN = vs_neighbor.vs_num + resize!(refine_flags, nL); + fill!(refine_flags, false) + i = 1; + j = 1 flag = 0.0 # fraction of the current (coarser) neighbor cell already covered @inbounds while i <= nL && j <= nN - l = vs_local.level[i]; ln = vs_neighbor.level[j] + l = vs_local.level[i]; + ln = vs_neighbor.level[j] if l == ln - i += 1; j += 1 + i += 1; + j += 1 elseif l < ln # Local cell i is coarser: accumulate the neighbor cells covering it, tracking # their maximum level, then decide. - maxlev = 0; f = 0.0 + maxlev = 0; + f = 0.0 while f < 1.0 - 1e-10 && j <= nN lv = vs_neighbor.level[j] lv > maxlev && (maxlev = Int(lv)) @@ -46,7 +52,8 @@ function vs_balance_pair!( # Local cell i is finer: one neighbor cell covers it (and more); no violation. flag += 1.0 / 2^(DIM * (l - ln)) if flag >= 1.0 - 1e-10 - j += 1; flag = 0.0 + j += 1; + flag = 0.0 end i += 1 end @@ -75,8 +82,7 @@ function vs_balance_local!(ka::KA{DIM,NDF}) where {DIM,NDF} trees = ka.kdata.field.trees ds = [ (ka.kinfo.config.quadrature[2*i] - ka.kinfo.config.quadrature[2*i-1]) / - ka.kinfo.config.vs_trees_num[i] - for i in 1:DIM + ka.kinfo.config.vs_trees_num[i] for i = 1:DIM ] any_changed = false @@ -88,7 +94,7 @@ function vs_balance_local!(ka::KA{DIM,NDF}) where {DIM,NDF} isa(ps_data, InsideSolidData) && continue ps_data.bound_enc < 0 && continue - for face_idx in 1:2*DIM + for face_idx = 1:(2*DIM) for neighbor in ps_data.neighbor.data[face_idx] neighbor === nothing && continue isa(neighbor, AbstractInsideSolidData) && continue @@ -122,7 +128,7 @@ function _patch_neighbor_ghost_refs!( new_ghost_wrap::AbstractVector, ) where {DIM,NDF} # Map Julia object identity (old ghost) → new ghost object. - ghost_patch = Dict{UInt64, AbstractGhostPsData{DIM,NDF}}() + ghost_patch = Dict{UInt64,AbstractGhostPsData{DIM,NDF}}() sizehint!(ghost_patch, length(old_ghost_wrap)) for i in eachindex(old_ghost_wrap) ghost_patch[objectid(old_ghost_wrap[i])] = new_ghost_wrap[i] @@ -153,8 +159,7 @@ Re-communicate the velocity-space structure (levels, midpoints, weights, and distribution-function values) of ghost cells after local velocity-space refinement, without rebuilding the physical-mesh ghost topology. -Compared to `update_ghost!`, this function skips the `p4est_ghost_destroy / -p4est_ghost_new` calls because the physical quadrant adjacency is unchanged. Ghost-cell +Compared to `update_ghost!`, this function skips the `p4est_ghost_destroy / p4est_ghost_new` calls because the physical quadrant adjacency is unchanged. Ghost-cell pointers cached in every local cell's `neighbor.data` are patched in-place so that they refer to the freshly allocated ghost objects. @@ -170,8 +175,8 @@ function vs_ghost_exchange!(p4est::P_pxest_t, ka::KA{DIM,NDF}) where {DIM,NDF} # Re-exchange velocity-space structure; Julia GC handles old buffer cleanup. new_gb, new_gi = initialize_ghost_pool(p4est, kinfo) ka.kdata.ghost.ghost_buffer = new_gb - ka.kdata.ghost.ghost_info = new_gi - ka.kdata.ghost.ghost_wrap = initialize_ghost_wrap(kinfo, new_gb, new_gi) + ka.kdata.ghost.ghost_info = new_gi + ka.kdata.ghost.ghost_wrap = initialize_ghost_wrap(kinfo, new_gb, new_gi) # Replace stale ghost references in neighbor.data with the new objects. _patch_neighbor_ghost_refs!(ka, old_ghost_wrap, ka.kdata.ghost.ghost_wrap) return nothing @@ -185,12 +190,13 @@ physical cells, including pairs that span different MPI ranks. **Algorithm** Each iteration: -1. Runs a local balance pass ([`vs_balance!`](@ref)) that refines local velocity cells - which are more than 1 level coarser than any neighbor (local or ghost). -2. Performs an `MPI_Allreduce` to check whether *any* rank made changes. -3. If changes occurred on at least one rank, calls [`vs_ghost_exchange!`](@ref) so that - every rank learns the updated velocity-space levels of its neighbors before the next - pass. + + 1. Runs a local balance pass ([`vs_balance!`](@ref)) that refines local velocity cells + which are more than 1 level coarser than any neighbor (local or ghost). + 2. Performs an `MPI_Allreduce` to check whether *any* rank made changes. + 3. If changes occurred on at least one rank, calls [`vs_ghost_exchange!`](@ref) so that + every rank learns the updated velocity-space levels of its neighbors before the next + pass. The loop terminates when no rank reports a change, guaranteeing that the 2:1 constraint is satisfied globally. @@ -198,10 +204,11 @@ is satisfied globally. For single-rank runs the MPI steps are skipped. **Note** After this function returns: -- `ghost_wrap` and `neighbor.data` contain up-to-date velocity-space level data. -- The p4est mesh and the face list are **not** rebuilt. Call `update_neighbor!(p4est, ka)` - and `update_faces!(p4est, ka)` (or `amr_recover!(p4est, ka)`) afterwards if those - structures are needed for flux or slope calculations. + + - `ghost_wrap` and `neighbor.data` contain up-to-date velocity-space level data. + - The p4est mesh and the face list are **not** rebuilt. Call `update_neighbor!(p4est, ka)` + and `update_faces!(p4est, ka)` (or `amr_recover!(p4est, ka)`) afterwards if those + structures are needed for flux or slope calculations. """ function vs_balance!(ka::KA{DIM,NDF}) where {DIM,NDF} p4est = ka.kinfo.forest.p4est @@ -214,7 +221,7 @@ function vs_balance!(ka::KA{DIM,NDF}) where {DIM,NDF} any_changed = false changed_global = true while changed_global - changed_local = vs_balance_local!(ka) + changed_local = vs_balance_local!(ka) # Reduce across all ranks: any change on any rank keeps the loop going. changed_global = Bool(MPI.Allreduce(Int(changed_local), +, MPI.COMM_WORLD) > 0) any_changed |= changed_global diff --git a/src/Velocity_space/Criteria.jl b/src/Velocity_space/Criteria.jl index 5765e14..5b4c390 100644 --- a/src/Velocity_space/Criteria.jl +++ b/src/Velocity_space/Criteria.jl @@ -1,84 +1,238 @@ """ $(TYPEDSIGNATURES) """ -function contribution_refine_flag(w::AbstractVector, U::AbstractVector, midpoint::AbstractVector, df::AbstractVector, weight::Float64, vr::Velocity_Resolution, kinfo::KInfo) - return local_contribution_refine_flag(w,U,midpoint,df,weight,kinfo)||global_contribution_refine_flag(U,midpoint,df,weight,vr,kinfo) +function contribution_refine_flag( + w::AbstractVector, + U::AbstractVector, + midpoint::AbstractVector, + df::AbstractVector, + weight::Float64, + vr::Velocity_Resolution, + kinfo::KInfo, +) + return local_contribution_refine_flag(w, U, midpoint, df, weight, kinfo)||global_contribution_refine_flag( + U, + midpoint, + df, + weight, + vr, + kinfo, + ) end """ $(TYPEDSIGNATURES) """ -function contribution_coarsen_flag(w::AbstractVector, U::AbstractVector, midpoint::AbstractMatrix, df::AbstractMatrix, weight::AbstractVector, vr::Velocity_Resolution, kinfo::KInfo) - return local_contribution_coarsen_flag(w,U,midpoint,df,weight,kinfo)&&global_contribution_coarsen_flag(U,midpoint,df,weight,vr,kinfo) +function contribution_coarsen_flag( + w::AbstractVector, + U::AbstractVector, + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + vr::Velocity_Resolution, + kinfo::KInfo, +) + return local_contribution_coarsen_flag(w, U, midpoint, df, weight, kinfo)&&global_contribution_coarsen_flag( + U, + midpoint, + df, + weight, + vr, + kinfo, + ) end -function local_contribution_refine_flag(w::AbstractVector, U::AbstractVector, midpoint::AbstractVector, df::AbstractVector, weight::Float64, kinfo::KInfo{DIM,2}) where{DIM} - max(abs(0.5 * (sum((U - midpoint) .^ 2) * df[1] + df[2])* weight) / - (w[end] - 0.5 * w[1] * sum((U) .^ 2)),df[1]*weight/w[1]) > kinfo.config.solver.ADAPT_COEFFI_VS_LOCAL ? true : false +function local_contribution_refine_flag( + w::AbstractVector, + U::AbstractVector, + midpoint::AbstractVector, + df::AbstractVector, + weight::Float64, + kinfo::KInfo{DIM,2}, +) where {DIM} + max( + abs(0.5 * (sum((U - midpoint) .^ 2) * df[1] + df[2]) * weight) / + (w[end] - 0.5 * w[1] * sum((U) .^ 2)), + df[1]*weight/w[1], + ) > kinfo.config.solver.ADAPT_COEFFI_VS_LOCAL ? true : false end -function local_contribution_refine_flag(w::AbstractVector, U::AbstractVector, midpoint::AbstractVector, df::AbstractVector, weight::Float64, kinfo::KInfo{DIM,1}) where{DIM} - max(abs(0.5 * sum((U - midpoint) .^ 2) * df[1]* weight) / - (w[end] - 0.5 * w[1] * sum((U) .^ 2)),df[1]*weight/w[1]) > kinfo.config.solver.ADAPT_COEFFI_VS_LOCAL ? true : false +function local_contribution_refine_flag( + w::AbstractVector, + U::AbstractVector, + midpoint::AbstractVector, + df::AbstractVector, + weight::Float64, + kinfo::KInfo{DIM,1}, +) where {DIM} + max( + abs(0.5 * sum((U - midpoint) .^ 2) * df[1] * weight) / + (w[end] - 0.5 * w[1] * sum((U) .^ 2)), + df[1]*weight/w[1], + ) > kinfo.config.solver.ADAPT_COEFFI_VS_LOCAL ? true : false end -function local_contribution_coarsen_flag(w::AbstractVector, U::AbstractVector, midpoint::AbstractMatrix, df::AbstractMatrix, weight::AbstractVector, kinfo::KInfo{DIM,2}) where{DIM} - for i = 1:2^DIM - !local_contribution_coarsen_flag(w, U, @view(midpoint[i, :]), @view(df[i, :]), weight[i], kinfo) && - return false +function local_contribution_coarsen_flag( + w::AbstractVector, + U::AbstractVector, + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + kinfo::KInfo{DIM,2}, +) where {DIM} + for i = 1:(2^DIM) + !local_contribution_coarsen_flag( + w, + U, + @view(midpoint[i, :]), + @view(df[i, :]), + weight[i], + kinfo, + ) && return false end return true end -function local_contribution_coarsen_flag(w::AbstractVector, U::AbstractVector, midpoint::AbstractMatrix, df::AbstractMatrix, weight::AbstractVector, kinfo::KInfo{DIM,1}) where{DIM} - for i = 1:2^DIM - !local_contribution_coarsen_flag(w, U, @view(midpoint[i, :]), @view(df[i, :]), weight[i], kinfo) && - return false +function local_contribution_coarsen_flag( + w::AbstractVector, + U::AbstractVector, + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + kinfo::KInfo{DIM,1}, +) where {DIM} + for i = 1:(2^DIM) + !local_contribution_coarsen_flag( + w, + U, + @view(midpoint[i, :]), + @view(df[i, :]), + weight[i], + kinfo, + ) && return false end return true end -function local_contribution_coarsen_flag(w::AbstractVector, U::AbstractVector, midpoint::AbstractVector, df::AbstractVector, weight::Float64, kinfo::KInfo{DIM,2}) where{DIM} - max(0.5 * (sum((U - midpoint) .^ 2) * df[1] + df[2])* weight / - (w[end] - 0.5 * w[1] * sum((U) .^ 2)),df[1]*weight/w[1]) < kinfo.config.solver.ADAPT_COEFFI_VS_LOCAL/ 2^DIM +function local_contribution_coarsen_flag( + w::AbstractVector, + U::AbstractVector, + midpoint::AbstractVector, + df::AbstractVector, + weight::Float64, + kinfo::KInfo{DIM,2}, +) where {DIM} + max( + 0.5 * (sum((U - midpoint) .^ 2) * df[1] + df[2]) * weight / + (w[end] - 0.5 * w[1] * sum((U) .^ 2)), + df[1]*weight/w[1], + ) < kinfo.config.solver.ADAPT_COEFFI_VS_LOCAL / 2^DIM end -function local_contribution_coarsen_flag(w::AbstractVector, U::AbstractVector, midpoint::AbstractVector, df::AbstractVector, weight::Float64, kinfo::KInfo{DIM,1}) where{DIM} - max(0.5 * (sum((U - midpoint) .^ 2) * df[1])* weight / - (w[end] - 0.5 * w[1] * sum((U) .^ 2)),df[1]*weight/w[1]) < kinfo.config.solver.ADAPT_COEFFI_VS_LOCAL/ 2^DIM +function local_contribution_coarsen_flag( + w::AbstractVector, + U::AbstractVector, + midpoint::AbstractVector, + df::AbstractVector, + weight::Float64, + kinfo::KInfo{DIM,1}, +) where {DIM} + max( + 0.5 * (sum((U - midpoint) .^ 2) * df[1]) * weight / + (w[end] - 0.5 * w[1] * sum((U) .^ 2)), + df[1]*weight/w[1], + ) < kinfo.config.solver.ADAPT_COEFFI_VS_LOCAL / 2^DIM end -function global_contribution_refine_flag(U::AbstractVector, midpoint::AbstractVector, df::AbstractVector, weight::Float64, vr::Velocity_Resolution, kinfo::KInfo{DIM,2}) where{DIM} - df[1]*weight > kinfo.config.solver.ADAPT_COEFFI_VS_GLOBAL*vr.density || 0.5 * (sum((U - midpoint) .^ 2) * df[1] + df[2])* weight>vr.energy*kinfo.config.solver.ADAPT_COEFFI_VS_GLOBAL +function global_contribution_refine_flag( + U::AbstractVector, + midpoint::AbstractVector, + df::AbstractVector, + weight::Float64, + vr::Velocity_Resolution, + kinfo::KInfo{DIM,2}, +) where {DIM} + df[1]*weight > kinfo.config.solver.ADAPT_COEFFI_VS_GLOBAL*vr.density || + 0.5 * (sum((U - midpoint) .^ 2) * df[1] + df[2]) * weight>vr.energy*kinfo.config.solver.ADAPT_COEFFI_VS_GLOBAL end -function global_contribution_refine_flag(U::AbstractVector, midpoint::AbstractVector, df::AbstractVector, weight::Float64, vr::Velocity_Resolution, kinfo::KInfo{DIM,1}) where{DIM} - df[1]*weight > vr.density*kinfo.config.solver.ADAPT_COEFFI_VS_GLOBAL || 0.5 * (sum((U - midpoint) .^ 2) * df[1])* weight>vr.energy*kinfo.config.solver.ADAPT_COEFFI_VS_GLOBAL +function global_contribution_refine_flag( + U::AbstractVector, + midpoint::AbstractVector, + df::AbstractVector, + weight::Float64, + vr::Velocity_Resolution, + kinfo::KInfo{DIM,1}, +) where {DIM} + df[1]*weight > vr.density*kinfo.config.solver.ADAPT_COEFFI_VS_GLOBAL || + 0.5 * (sum((U - midpoint) .^ 2) * df[1]) * weight>vr.energy*kinfo.config.solver.ADAPT_COEFFI_VS_GLOBAL end -function global_contribution_coarsen_flag(U::AbstractVector, midpoint::AbstractMatrix, df::AbstractMatrix, weight::AbstractVector, vr::Velocity_Resolution, kinfo::KInfo{DIM,2}) where{DIM} - for i = 1:2^DIM - !global_contribution_coarsen_flag(U, @view(midpoint[i, :]), @view(df[i, :]), weight[i], vr, kinfo) && - return false +function global_contribution_coarsen_flag( + U::AbstractVector, + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + vr::Velocity_Resolution, + kinfo::KInfo{DIM,2}, +) where {DIM} + for i = 1:(2^DIM) + !global_contribution_coarsen_flag( + U, + @view(midpoint[i, :]), + @view(df[i, :]), + weight[i], + vr, + kinfo, + ) && return false end return true end -function global_contribution_coarsen_flag(U::AbstractVector, midpoint::AbstractMatrix, df::AbstractMatrix, weight::AbstractVector, vr::Velocity_Resolution, kinfo::KInfo{DIM,1}) where{DIM} - for i = 1:2^DIM - !global_contribution_coarsen_flag(U, @view(midpoint[i, :]), @view(df[i, :]), weight[i], vr, kinfo) && - return false +function global_contribution_coarsen_flag( + U::AbstractVector, + midpoint::AbstractMatrix, + df::AbstractMatrix, + weight::AbstractVector, + vr::Velocity_Resolution, + kinfo::KInfo{DIM,1}, +) where {DIM} + for i = 1:(2^DIM) + !global_contribution_coarsen_flag( + U, + @view(midpoint[i, :]), + @view(df[i, :]), + weight[i], + vr, + kinfo, + ) && return false end return true end -function global_contribution_coarsen_flag(U::AbstractVector, midpoint::AbstractVector, df::AbstractVector, weight::Float64, vr::Velocity_Resolution, kinfo::KInfo{DIM,2}) where{DIM} - df[1]*weight < kinfo.config.solver.ADAPT_COEFFI_VS_GLOBAL*vr.density/2^DIM && 0.5 * (sum((U - midpoint) .^ 2) * df[1] + df[2])* weight MAXWELLIAN_INIT_FLOOR && return true if kinfo.config.solver.ADAPT_VS_MODE === :lohner - return maxwellian_quad_error(dρ, midpoint, du, U, prim, Val(DIM)) > kinfo.config.solver.ADAPT_COEFFI_VS_LOHNER + return maxwellian_quad_error(dρ, midpoint, du, U, prim, Val(DIM)) > + kinfo.config.solver.ADAPT_COEFFI_VS_LOHNER end return false end @@ -208,21 +382,38 @@ end # `local_contribution_*` retained as a relative mass/energy floor. # ------------------------------------------------------------------------------------------ -"Löhner ripple-filter coefficient (relative noise floor)." +""" +Löhner ripple-filter coefficient (relative noise floor). +""" const VS_LOHNER_EPS_FLT = 1e-2 -"Löhner absolute floor coefficient: structure below `EPS_ABS * scale` is ignored." +""" +Löhner absolute floor coefficient: structure below `EPS_ABS * scale` is ignored. +""" const VS_LOHNER_EPS_ABS = 1e-3 -"Coarsen-eligibility fraction of the refine threshold (hysteresis)." +""" +Coarsen-eligibility fraction of the refine threshold (hysteresis). +""" const VS_LOHNER_COARSEN_RATIO = 0.3 # Normalized non-uniform Löhner ratio from left/center/right values at center-to-neighbor # distances `dsL`/`dsR`. Same weighting as the physical-space `lohner_value`, so the second # difference is correct across velocity cells of differing size (coarse/fine interfaces). -@inline function _lohner_ratio(L::Real, C::Real, R::Real, dsL::Real, dsR::Real, εflt::Real, εabs::Real, scale::Real) +@inline function _lohner_ratio( + L::Real, + C::Real, + R::Real, + dsL::Real, + dsR::Real, + εflt::Real, + εabs::Real, + scale::Real, +) num = abs(dsR * L - (dsL + dsR) * C + dsL * R) - den = dsR * abs(L - C) + dsL * abs(R - C) + - εflt * (dsR * abs(L) + (dsL + dsR) * abs(C) + dsL * abs(R)) + - εabs * scale * (dsL + dsR) + den = + dsR * abs(L - C) + + dsL * abs(R - C) + + εflt * (dsR * abs(L) + (dsL + dsR) * abs(C) + dsL * abs(R)) + + εabs * scale * (dsL + dsR) return den > 0 ? num / den : 0.0 end @@ -237,11 +428,14 @@ Per-physical-cell reference magnitudes (peaks of the mass distribution `h` and, Löhner ratio. """ function vs_lohner_scales(vs::AbstractVsData{DIM,NDF}) where {DIM,NDF} - s1 = 0.0; s2 = 0.0 - @inbounds for j in 1:vs.vs_num - a1 = abs(vs.df[j, 1]); a1 > s1 && (s1 = a1) + s1 = 0.0; + s2 = 0.0 + @inbounds for j = 1:vs.vs_num + a1 = abs(vs.df[j, 1]); + a1 > s1 && (s1 = a1) if NDF == 2 - a2 = abs(vs.df[j, 2]); a2 > s2 && (s2 = a2) + a2 = abs(vs.df[j, 2]); + a2 > s2 && (s2 = a2) end end return s1, s2 @@ -256,13 +450,20 @@ the independent internal-energy distribution `b = df[:,2]`. The second differen on the raw distributions (no `c^2` weight, which would inject the spurious curvature of the velocity weight itself). `s1`/`s2` are the scales from [`vs_lohner_scales`](@ref). """ -function vs_lohner_indicator(vs::AbstractVsData{DIM,NDF}, idx::VsNeighborIndex{DIM}, i::Integer, s1::Real, s2::Real) where {DIM,NDF} - εflt = VS_LOHNER_EPS_FLT; εabs = VS_LOHNER_EPS_ABS +function vs_lohner_indicator( + vs::AbstractVsData{DIM,NDF}, + idx::VsNeighborIndex{DIM}, + i::Integer, + s1::Real, + s2::Real, +) where {DIM,NDF} + εflt = VS_LOHNER_EPS_FLT; + εabs = VS_LOHNER_EPS_ABS @inbounds begin h0 = vs.df[i, 1] b0 = NDF == 2 ? vs.df[i, 2] : 0.0 η = 0.0 - for d in 1:DIM + for d = 1:DIM hi = _vs_cell_size(idx, vs, i, d) Ln = vs_face_neighbor(idx, vs, i, d, -1) Rn = vs_face_neighbor(idx, vs, i, d, +1) diff --git a/src/Velocity_space/Cut_cell.jl b/src/Velocity_space/Cut_cell.jl index d72eec1..dd1d7a4 100644 --- a/src/Velocity_space/Cut_cell.jl +++ b/src/Velocity_space/Cut_cell.jl @@ -1,8 +1,8 @@ function gaussian_area(A::AbstractMatrix) # DIMxN area = 0 - for i in axes(A,2) - j = i%size(A,2)+1 - area+=@views det(A[:,[i,j]]) + for i in axes(A, 2) + j = i%size(A, 2)+1 + area+=@views det(A[:, [i, j]]) end return 0.5*abs(area) end @@ -10,7 +10,7 @@ end """ 2D cut cell. """ -function cut_rect(n::Vector{Float64},vertices::Vector{Vector{Float64}}) # The splitting line at the boundary with normal direction n. Return the areas of the two part. The former one locates at the direction n. +function cut_rect(n::Vector{Float64}, vertices::Vector{Vector{Float64}}) # The splitting line at the boundary with normal direction n. Return the areas of the two part. The former one locates at the direction n. # The cases where n is oriented to along the axes are excluded in advance. #= y @@ -20,58 +20,61 @@ function cut_rect(n::Vector{Float64},vertices::Vector{Vector{Float64}}) # The sp # | | | # 1(2)|-----2-----|3(4) x =# - points = Vector{Float64}[];indices = Int[];i = 0 - xmin,xmax,ymin,ymax = vertices[1][1],vertices[2][1],vertices[1][2],vertices[3][2] + points = Vector{Float64}[]; + indices = Int[]; + i = 0 + xmin, xmax, ymin, ymax = vertices[1][1], vertices[2][1], vertices[1][2], vertices[3][2] y = -n[1]/n[2]*xmin if yymin - push!(points,[xmin,y]) - push!(indices,8) + push!(points, [xmin, y]) + push!(indices, 8) i+=1 end y = -n[1]/n[2]*xmax if yymin - push!(points,[xmax,y]) - push!(indices,4) + push!(points, [xmax, y]) + push!(indices, 4) i+=1 end x = -n[2]/n[1]*ymin if xxmin - push!(points,[x,ymin]) - push!(indices,2) + push!(points, [x, ymin]) + push!(indices, 2) i+=1 end x = -n[2]/n[1]*ymax if xxmin - push!(points,[x,ymax]) - push!(indices,6) + push!(points, [x, ymax]) + push!(indices, 6) i+=1 end - clp = findall(x->dot(x,n)==0.,vertices) # Number of vertices lying on the discontinuity + clp = findall(x->dot(x, n)==0.0, vertices) # Number of vertices lying on the discontinuity if length(clp)+i<2 - return false,0.,0. + return false, 0.0, 0.0 else - append!(points,vertices) - append!(indices,CLP) # CLP is defined in dim.jl + append!(points, vertices) + append!(indices, CLP) # CLP is defined in dim.jl sid = sortperm(indices) indices = indices[sid] points = points[sid] - aid = findfirst(x->iseven(x)||in(x,CLP[clp]),indices) - bid = findlast(x->iseven(x)||in(x,CLP[clp]),indices) - A = Matrix{Float64}(undef,2,bid-aid+1);B = Matrix{Float64}(undef,2,length(indices)-(bid-aid)+1) - for i in aid:bid - A[:,i-aid+1] .= points[i] + aid = findfirst(x->iseven(x)||in(x, CLP[clp]), indices) + bid = findlast(x->iseven(x)||in(x, CLP[clp]), indices) + A = Matrix{Float64}(undef, 2, bid-aid+1); + B = Matrix{Float64}(undef, 2, length(indices)-(bid-aid)+1) + for i = aid:bid + A[:, i-aid+1] .= points[i] end - for i in 0:length(indices)-(bid-aid) + for i = 0:(length(indices)-(bid-aid)) index = bid+i>length(indices) ? (bid+i)%length(indices) : bid+i - B[:,i+1] .= points[index] + B[:, i+1] .= points[index] end l = points[bid]-points[aid] if n[1]*l[2]-n[2]*l[1]<0 gas_weight = gaussian_area(A) - return true,gas_weight,((xmax-xmin)*(ymax-ymin))-gas_weight # solid first + return true, gas_weight, ((xmax-xmin)*(ymax-ymin))-gas_weight # solid first else solid_weight = gaussian_area(A) - return true,((xmax-xmin)*(ymax-ymin))-solid_weight,solid_weight + return true, ((xmax-xmin)*(ymax-ymin))-solid_weight, solid_weight end end end @@ -80,14 +83,18 @@ end 3D cut cell. """ function cut_cube_rotate(n::Vector{Float64}) - C = zeros(2,3) - e1 = [1.,0.,0.] - e1 = cross(n,e1);e1./=norm(e1) - e2 = cross(n,e1);e2./=norm(e2) - if dot(cross(e1,e2),n)>0 - C[1,:].=e1;C[2,:].=e2 + C = zeros(2, 3) + e1 = [1.0, 0.0, 0.0] + e1 = cross(n, e1); + e1./=norm(e1) + e2 = cross(n, e1); + e2./=norm(e2) + if dot(cross(e1, e2), n)>0 + C[1, :].=e1; + C[2, :].=e2 else - C[2,:].=e1;C[1,:].=e2 + C[2, :].=e1; + C[1, :].=e2 end return C end @@ -96,106 +103,147 @@ end Calculate the flux of the vector (x,y,z)/3 through the vertical faces composed by intersecting points and vertices. Normally, the cases where the connecting line of the two neighboring intersecting pionts are parallel to grid lines should have been got rid of before the function is called. """ -function Vertical_Volume_Flux(points::AbstractVector{Vector{Float64}},midpoint::Vector{Float64},vertices::AbstractMatrix{Float64}) - H = 0.;N = length(points) +function Vertical_Volume_Flux( + points::AbstractVector{Vector{Float64}}, + midpoint::Vector{Float64}, + vertices::AbstractMatrix{Float64}, +) + H = 0.0; + N = length(points) for i in eachindex(points) - p1 = points[i%N+1];p2 = points[i] - dx= abs.(p1-p2) - _,dir = findmin(dx) + p1 = points[i%N+1]; + p2 = points[i] + dx = abs.(p1-p2) + _, dir = findmin(dx) if dx[dir]>1e-6 throw(`Cut-cube Error!`) end - vid = findall(x->abs(x[dir]-points[i][dir])abs(x[dir]-points[i][dir])abs(midpoint[i])≈0.5*ddu[i],1:length(midpoint)) +function vertices_sweep!(midpoint, ddu, vertices) # Clean the eps in vertices. + if any(i->abs(midpoint[i])≈0.5*ddu[i], 1:length(midpoint)) for i in eachindex(vertices) - abs(vertices[i]) < EPS && (vertices[i] = 0.) + abs(vertices[i]) < EPS && (vertices[i] = 0.0) end end return nothing end -function cut_cube(n::Vector{Float64},C::Matrix{Float64},midpoint::Vector{Float64},ddu::Vector{Float64},vertices::Matrix{Float64}) # 3.627 μs (215 allocations: 8.45 KiB). Acceptable? - vertices_sweep!(midpoint,ddu,vertices) - vltable = [[1,2],[3,4],[7,8],[5,6],[1,3],[2,4],[6,8],[5,7],[1,5],[2,6],[4,8],[3,7]] # vertices-edges table - points = Vector{Vector{Float64}}(undef,6);index = 1 +function cut_cube( + n::Vector{Float64}, + C::Matrix{Float64}, + midpoint::Vector{Float64}, + ddu::Vector{Float64}, + vertices::Matrix{Float64}, +) # 3.627 μs (215 allocations: 8.45 KiB). Acceptable? + vertices_sweep!(midpoint, ddu, vertices) + vltable = [ + [1, 2], + [3, 4], + [7, 8], + [5, 6], + [1, 3], + [2, 4], + [6, 8], + [5, 7], + [1, 5], + [2, 6], + [4, 8], + [3, 7], + ] # vertices-edges table + points = Vector{Vector{Float64}}(undef, 6); + index = 1 dirs = permutedims(vertices)*n # what if vertices[i]=0.? for i in eachindex(vltable) - d1 = dirs[vltable[i][1]]; d2 = dirs[vltable[i][2]] + d1 = dirs[vltable[i][1]]; + d2 = dirs[vltable[i][2]] flag = d1*d2 # flag==0: cut any end of the edge; flag<0: cut the edge; flag>0: not cut the edge - if min(abs(d1),abs(d2))<3.0*eps() - if cld(i,4)==1 # avoid redundancy + if min(abs(d1), abs(d2))<3.0*eps() + if cld(i, 4)==1 # avoid redundancy if abs(dirs[vltable[i][1]])<3.0*eps() # end A intersects - points[index] = vertices[:,vltable[i][1]];index+=1 + points[index] = vertices[:, vltable[i][1]]; + index+=1 else # end B intersects - points[index] = vertices[:,vltable[i][2]];index+=1 + points[index] = vertices[:, vltable[i][2]]; + index+=1 end end elseif flag<0 # intersects between the two ends - point = vertices[:,vltable[i][1]] - dir = cld(i,4);point[dir]=0. - point[dir] = -dot(point,n)/(n[dir]) - points[index] = point;index+=1 + point = vertices[:, vltable[i][1]] + dir = cld(i, 4); + point[dir]=0.0 + point[dir] = -dot(point, n)/(n[dir]) + points[index] = point; + index+=1 end end - index<4&&return false,0.,0. - points = points[1:index-1] - posid = findall(x->x>3.0*eps(),dirs) + index<4&&return false, 0.0, 0.0 + points = points[1:(index-1)] + posid = findall(x->x>3.0*eps(), dirs) pos = length(posid)<4 ? true : false # H represents solid? - if any(x->abs(x)abs(x)abs(x[dir]-vertices[dir])abs(x)abs(x)abs(x[dir]-vertices[dir])abs(x[dir]-vertices[dir])EPS,eachcol(vertices)) # all vertices share the same face with the first one, but not cut by the boundary face + vid = + findall(x->abs(x[dir]-vertices[dir])EPS, eachcol(vertices)) # all vertices share the same face with the first one, but not cut by the boundary face else - vid = findall(x->abs(x[dir]-vertices[dir])abs(x[dir]-vertices[dir])abs(centers[i]-midpoint[i])≈0.5*ddu[i],1:3) + centers = @views sum(vertices[:, posid], dims = 2) ./ 4.0 + dir = findfirst(i->abs(centers[i]-midpoint[i])≈0.5*ddu[i], 1:3) if isnothing(dir) - H = 0. + H = 0.0 else - id1 = dir%3+1;id2 = (dir+1)%3+1 - H = pos ? sign(centers[dir]-midpoint[dir])*centers[dir]*ddu[id1]*ddu[id2]/3.0 : -sign(centers[dir]-midpoint[dir])*(2.0*midpoint[dir]-centers[dir])*ddu[id1]*ddu[id2]/3.0 + id1 = dir%3+1; + id2 = (dir+1)%3+1 + H = + pos ? + sign(centers[dir]-midpoint[dir])*centers[dir]*ddu[id1]*ddu[id2]/3.0 : + -sign(centers[dir]-midpoint[dir])*(2.0*midpoint[dir]-centers[dir])*ddu[id1]*ddu[id2]/3.0 end else - H = 0. + H = 0.0 end if pos - @views H+=Vertical_Volume_Flux(points[id],midpoint,vertices[:,posid]) - return true,8*prod(midpoint-@view(vertices[:,1]))-H,H # gas first + @views H+=Vertical_Volume_Flux(points[id], midpoint, vertices[:, posid]) + return true, 8*prod(midpoint-@view(vertices[:, 1]))-H, H # gas first else - negid = findall(x->x<-3.0*eps(),dirs) - @views H+=Vertical_Volume_Flux(points[id],midpoint,vertices[:,negid]) - return true,H,8*prod(midpoint-@view(vertices[:,1]))-H + negid = findall(x->x<-3.0*eps(), dirs) + @views H+=Vertical_Volume_Flux(points[id], midpoint, vertices[:, negid]) + return true, H, 8*prod(midpoint-@view(vertices[:, 1]))-H end end -end \ No newline at end of file +end diff --git a/src/Velocity_space/Initialize.jl b/src/Velocity_space/Initialize.jl index 1c9b821..1bfca05 100644 --- a/src/Velocity_space/Initialize.jl +++ b/src/Velocity_space/Initialize.jl @@ -1,12 +1,16 @@ -function initialize_vs_data(prim::AbstractVector,kinfo::KInfo) +function initialize_vs_data(prim::AbstractVector, kinfo::KInfo) quadrature = kinfo.config.quadrature - initialize_vs_data(prim,kinfo,quadrature) + initialize_vs_data(prim, kinfo, quadrature) end function initialize_vs_data(vs_data::VsData) return deepcopy(vs_data) end -function initialize_vs_data(prim::AbstractVector,kinfo::KInfo{DIM,NDF},quadrature::Vector{Float64}) where{DIM,NDF} +function initialize_vs_data( + prim::AbstractVector, + kinfo::KInfo{DIM,NDF}, + quadrature::Vector{Float64}, +) where {DIM,NDF} trees_num = kinfo.config.vs_trees_num vs_num = reduce(*, trees_num) midpoint = zeros(vs_num, DIM) @@ -22,56 +26,79 @@ function initialize_vs_data(prim::AbstractVector,kinfo::KInfo{DIM,NDF},quadratur midpoints = Base.Iterators.product(ranges...) index = 1 for point in midpoints - midpoint[index,:] .= point + midpoint[index, :] .= point index += 1 end df = discrete_maxwell(midpoint, prim, kinfo) sdf = zeros(vs_num, NDF, DIM) flux = zeros(vs_num, NDF) vs_data = VsData{DIM,NDF}(vs_num, zeros(Int, vs_num), weight, midpoint, df, sdf, flux) - for _ in 1:kinfo.config.solver.AMR_VS_MAXLEVEL - initial_vs_adaptive_mesh_refinement!(prim,vs_data,kinfo) + for _ = 1:kinfo.config.solver.AMR_VS_MAXLEVEL + initial_vs_adaptive_mesh_refinement!(prim, vs_data, kinfo) end vs_data.df = discrete_maxwell(vs_data.midpoint, prim, kinfo) return vs_data end -function initialize_vs_data(prim::AbstractVector,kinfo::KInfo{2,NDF},quadrature::Gauss_Hermite{NP};kwargs...) where{NDF,NP} +function initialize_vs_data( + prim::AbstractVector, + kinfo::KInfo{2,NDF}, + quadrature::Gauss_Hermite{NP}; + kwargs..., +) where {NDF,NP} DIM = 2 trees_num = kinfo.config.vs_trees_num vs_num = reduce(*, trees_num) - index = 1;midpoint = Matrix{Float64}(undef,vs_num,DIM);weight = Vector{Float64}(undef,vs_num) - vcoords = quadrature.vcoords;weights = quadrature.weights - for i in 1:NP - for j in 1:NP - midpoint[index,1] = vcoords[i];midpoint[index,2] = vcoords[j] - weight[index] = weights[i]*exp(midpoint[index,1]^2)*weights[j]*exp(midpoint[index,2]^2) + index = 1; + midpoint = Matrix{Float64}(undef, vs_num, DIM); + weight = Vector{Float64}(undef, vs_num) + vcoords = quadrature.vcoords; + weights = quadrature.weights + for i = 1:NP + for j = 1:NP + midpoint[index, 1] = vcoords[i]; + midpoint[index, 2] = vcoords[j] + weight[index] = + weights[i]*exp(midpoint[index, 1]^2)*weights[j]*exp(midpoint[index, 2]^2) index += 1 end - end - df = haskey(kwargs,:df) ? kwargs[:df] : discrete_maxwell(midpoint, prim, kinfo) + end + df = haskey(kwargs, :df) ? kwargs[:df] : discrete_maxwell(midpoint, prim, kinfo) sdf = zeros(vs_num, NDF, DIM) flux = zeros(vs_num, NDF) return VsData{DIM,NDF}(vs_num, zeros(Int, vs_num), weight, midpoint, df, sdf, flux) end -function initialize_vs_data(prim::AbstractVector,kinfo::KInfo{3,NDF},quadrature::Gauss_Hermite{NP};kwargs...) where{NDF,NP} +function initialize_vs_data( + prim::AbstractVector, + kinfo::KInfo{3,NDF}, + quadrature::Gauss_Hermite{NP}; + kwargs..., +) where {NDF,NP} DIM = 3 trees_num = kinfo.config.vs_trees_num vs_num = reduce(*, trees_num) - index = 1;midpoint = Matrix{Float64}(undef,vs_num,DIM);weight = Vector{Float64}(undef,vs_num) - vcoords = quadrature.vcoords;weights = quadrature.weights - for i in 1:NP - for j in 1:NP - for k in 1:NP - midpoint[index,1] = vcoords[i];midpoint[index,2] = vcoords[j];midpoint[index,3] = vcoords[k] - weight[index] = weights[i]*exp(midpoint[index,1]^2)*weights[j]*exp(midpoint[index,2]^2)*weights[k]*exp(midpoint[index,3]^2) + index = 1; + midpoint = Matrix{Float64}(undef, vs_num, DIM); + weight = Vector{Float64}(undef, vs_num) + vcoords = quadrature.vcoords; + weights = quadrature.weights + for i = 1:NP + for j = 1:NP + for k = 1:NP + midpoint[index, 1] = vcoords[i]; + midpoint[index, 2] = vcoords[j]; + midpoint[index, 3] = vcoords[k] + weight[index] = + weights[i]*exp(midpoint[index, 1]^2)*weights[j]*exp( + midpoint[index, 2]^2, + )*weights[k]*exp(midpoint[index, 3]^2) index += 1 end end end - df = haskey(kwargs,:df) ? kwargs[:df] : discrete_maxwell(midpoint, prim, kinfo) + df = haskey(kwargs, :df) ? kwargs[:df] : discrete_maxwell(midpoint, prim, kinfo) sdf = zeros(vs_num, NDF, DIM) flux = zeros(vs_num, NDF) return VsData{DIM,NDF}(vs_num, zeros(Int, vs_num), weight, midpoint, df, sdf, flux) -end \ No newline at end of file +end diff --git a/src/Velocity_space/Neighbor.jl b/src/Velocity_space/Neighbor.jl index 575a651..10358e0 100644 --- a/src/Velocity_space/Neighbor.jl +++ b/src/Velocity_space/Neighbor.jl @@ -31,35 +31,67 @@ Reusable point-location / face-neighbor index over a single velocity grid. $(TYPEDFIELDS) """ mutable struct VsNeighborIndex{DIM} - "Lower corner of the velocity domain per dimension." + """ + Lower corner of the velocity domain per dimension. + """ vmin::NTuple{DIM,Float64} - "Finest-level cell size per dimension." + """ + Finest-level cell size per dimension. + """ h_fine::NTuple{DIM,Float64} - "Number of root cells per dimension (any positive integers)." + """ + Number of root cells per dimension (any positive integers). + """ vs_trees_num::NTuple{DIM,Int} - "Row-major strides over the root grid (`rootstride[1] = 1`)." + """ + Row-major strides over the root grid (`rootstride[1] = 1`). + """ rootstride::NTuple{DIM,Int} - "Maximum velocity-space refinement level." + """ + Maximum velocity-space refinement level. + """ maxlevel::Int - "Bits of the intra-root Morton code, `DIM * maxlevel`." + """ + Bits of the intra-root Morton code, `DIM * maxlevel`. + """ mortonbits::Int - "Sorted packed keys `(cellkey << INDEX_BITS) | leaf`; only the first `n` are valid." + """ + Sorted packed keys `(cellkey << INDEX_BITS) | leaf`; only the first `n` are valid. + """ keys::Vector{UInt64} - "Reusable scratch buffer for the in-place sort (avoids per-build radix allocation)." + """ + Reusable scratch buffer for the in-place sort (avoids per-build radix allocation). + """ scratch::Vector{UInt64} - "Number of valid entries in `keys`." + """ + Number of valid entries in `keys`. + """ n::Int end function VsNeighborIndex{DIM}() where {DIM} z = ntuple(_ -> 0, DIM) return VsNeighborIndex{DIM}( - ntuple(_ -> 0.0, DIM), ntuple(_ -> 0.0, DIM), z, z, 0, 0, UInt64[], UInt64[], 0, + ntuple(_ -> 0.0, DIM), + ntuple(_ -> 0.0, DIM), + z, + z, + 0, + 0, + UInt64[], + UInt64[], + 0, ) end # Finest-level global integer coordinate of a leaf's lower corner from its center and level. -@inline function _corner_index(mid::Float64, level, vmin_d::Float64, h_fine_d::Float64, maxlevel::Int) +@inline function _corner_index( + mid::Float64, + level, + vmin_d::Float64, + h_fine_d::Float64, + maxlevel::Int, +) cell = h_fine_d * (1 << (maxlevel - level)) # cell size along this dim return round(Int, (mid - 0.5 * cell - vmin_d) / h_fine_d) end @@ -84,7 +116,7 @@ function build_vs_index!( vstn = ntuple(d -> Int(vs_trees_num[d]), Val(DIM)) rootstride = ntuple(Val(DIM)) do d s = 1 - for e in 1:d-1 + for e = 1:(d-1) s *= vstn[e] end s @@ -93,12 +125,13 @@ function build_vs_index!( # Bit budget: cellkey (root_lin << mortonbits | morton) plus the leaf id must fit in 64 bits. prod_roots = 1 - @inbounds for d in 1:DIM + @inbounds for d = 1:DIM prod_roots *= vstn[d] end rootbits = prod_roots <= 1 ? 0 : (sizeof(Int) * 8 - leading_zeros(prod_roots - 1)) - rootbits + mortonbits + _VS_INDEX_BITS > 64 && - error("VsNeighborIndex: cellkey ($(rootbits + mortonbits)) + index ($_VS_INDEX_BITS) bits exceed 64.") + rootbits + mortonbits + _VS_INDEX_BITS > 64 && error( + "VsNeighborIndex: cellkey ($(rootbits + mortonbits)) + index ($_VS_INDEX_BITS) bits exceed 64.", + ) N = vs.vs_num N > (1 << _VS_INDEX_BITS) - 1 && error("VsNeighborIndex: $N leaves exceed the $_VS_INDEX_BITS-bit index field.") @@ -107,23 +140,27 @@ function build_vs_index!( resize!(idx.keys, N) length(idx.scratch) < N && resize!(idx.scratch, N) keys = idx.keys - @inbounds for i in 1:N + @inbounds for i = 1:N L = vs.level[i] root_lin = 0 morton = UInt64(0) - for d in 1:DIM # inline; no tuple, no closure + for d = 1:DIM # inline; no tuple, no closure g = _corner_index(vs.midpoint[i, d], L, vmin[d], h_fine[d], maxlevel) root_lin += (g >> maxlevel) * rootstride[d] q = g & mask - for b in 0:maxlevel-1 + for b = 0:(maxlevel-1) morton |= (UInt64((q >> b) & 1)) << (b * DIM + (d - 1)) end end cellkey = (UInt64(root_lin) << mortonbits) | morton keys[i] = (cellkey << _VS_INDEX_BITS) | UInt64(i) end - sort!(keys; alg = Base.Sort.DEFAULT_UNSTABLE, order = Base.Order.Forward, - scratch = idx.scratch) + sort!( + keys; + alg = Base.Sort.DEFAULT_UNSTABLE, + order = Base.Order.Forward, + scratch = idx.scratch, + ) idx.vmin = vmin idx.h_fine = h_fine @@ -136,7 +173,11 @@ function build_vs_index!( end # Locate the leaf owning `cellkey` (predecessor + interval containment check). No allocation. -@inline function _vs_locate_code(idx::VsNeighborIndex{DIM}, vs::AbstractVsData{DIM}, code::UInt64) where {DIM} +@inline function _vs_locate_code( + idx::VsNeighborIndex{DIM}, + vs::AbstractVsData{DIM}, + code::UInt64, +) where {DIM} packed = (code << _VS_INDEX_BITS) | _VS_INDEX_MASK k = searchsortedlast(idx.keys, packed, 1, idx.n, Base.Order.Forward) k == 0 && return 0 @@ -155,16 +196,20 @@ $(TYPEDSIGNATURES) Return the leaf containing velocity-space `point`, or `0` if `point` lies outside the velocity domain. `vs` is the grid the index was built over (used to verify containment). """ -function vs_locate(idx::VsNeighborIndex{DIM}, vs::AbstractVsData{DIM}, point::NTuple{DIM,Float64}) where {DIM} +function vs_locate( + idx::VsNeighborIndex{DIM}, + vs::AbstractVsData{DIM}, + point::NTuple{DIM,Float64}, +) where {DIM} mask = (1 << idx.maxlevel) - 1 root_lin = 0 morton = UInt64(0) - @inbounds for d in 1:DIM + @inbounds for d = 1:DIM g = floor(Int, (point[d] - idx.vmin[d]) / idx.h_fine[d]) (g < 0 || g >= idx.vs_trees_num[d] << idx.maxlevel) && return 0 root_lin += (g >> idx.maxlevel) * idx.rootstride[d] q = g & mask - for b in 0:idx.maxlevel-1 + for b = 0:(idx.maxlevel-1) morton |= (UInt64((q >> b) & 1)) << (b * DIM + (d - 1)) end end @@ -178,7 +223,13 @@ and direction `dir` (`+1` / `-1`). Returns `0` when the face is on the velocity boundary (treat as vacuum, `f = 0`). Reusable primitive for Löhner indicators and finite-difference velocity derivatives. """ -function vs_face_neighbor(idx::VsNeighborIndex{DIM}, vs::AbstractVsData{DIM}, i::Integer, dim::Integer, dir::Integer) where {DIM} +function vs_face_neighbor( + idx::VsNeighborIndex{DIM}, + vs::AbstractVsData{DIM}, + i::Integer, + dim::Integer, + dir::Integer, +) where {DIM} mask = (1 << idx.maxlevel) - 1 root_lin = 0 morton = UInt64(0) @@ -186,14 +237,14 @@ function vs_face_neighbor(idx::VsNeighborIndex{DIM}, vs::AbstractVsData{DIM}, i: L = vs.level[i] cell = idx.h_fine[dim] * (1 << (idx.maxlevel - L)) # Probe just across the face, at the face-centre line in the other dimensions. - for d in 1:DIM + for d = 1:DIM coord = vs.midpoint[i, d] d == dim && (coord += dir * (0.5 * cell + 0.5 * idx.h_fine[d])) g = floor(Int, (coord - idx.vmin[d]) / idx.h_fine[d]) (g < 0 || g >= idx.vs_trees_num[d] << idx.maxlevel) && return 0 root_lin += (g >> idx.maxlevel) * idx.rootstride[d] q = g & mask - for b in 0:idx.maxlevel-1 + for b = 0:(idx.maxlevel-1) morton |= (UInt64((q >> b) & 1)) << (b * DIM + (d - 1)) end end diff --git a/src/Velocity_space/Rebuild.jl b/src/Velocity_space/Rebuild.jl index a3a0188..c809b2f 100644 --- a/src/Velocity_space/Rebuild.jl +++ b/src/Velocity_space/Rebuild.jl @@ -13,21 +13,29 @@ # original positional-surgery refine/coarsen was verified bit-for-bit before that code was # retired. -@inline function _copy_cell!(dlevel, dweight, dmid, ddf, w::Int, vs_data::AbstractVsData{DIM,NDF}, src::Int) where {DIM,NDF} +@inline function _copy_cell!( + dlevel, + dweight, + dmid, + ddf, + w::Int, + vs_data::AbstractVsData{DIM,NDF}, + src::Int, +) where {DIM,NDF} @inbounds begin dlevel[w] = vs_data.level[src] dweight[w] = vs_data.weight[src] - for d in 1:DIM + for d = 1:DIM dmid[w, d] = vs_data.midpoint[src, d] end - for k in 1:NDF + for k = 1:NDF ddf[w, k] = vs_data.df[src, k] end end end @inline function _all_same_level(vs_data::AbstractVsData, index::Int, fl, nc::Int) - @inbounds for g in 1:nc-1 + @inbounds for g = 1:(nc-1) vs_data.level[index+g] != fl && return false end return true @@ -41,11 +49,15 @@ Streaming refinement: single O(N) pass into fresh arrays. `refine_flags[i]` dec cell `i`. Children are emitted in `RMT` order with the parent's `df` injected, parent weight split by `2^DIM`, and `sdf`/`flux` reset to zero. """ -function refine_grid_stream!(vs_data::VsData{DIM,NDF}, refine_flags::AbstractVector{Bool}, ds) where {DIM,NDF} +function refine_grid_stream!( + vs_data::VsData{DIM,NDF}, + refine_flags::AbstractVector{Bool}, + ds, +) where {DIM,NDF} n = vs_data.vs_num nc = 2^DIM nnew = n - @inbounds for i in 1:n + @inbounds for i = 1:n refine_flags[i] && (nnew += nc - 1) end nnew == n && return false @@ -54,18 +66,19 @@ function refine_grid_stream!(vs_data::VsData{DIM,NDF}, refine_flags::AbstractVec dmid = Matrix{Float64}(undef, nnew, DIM) ddf = Matrix{Float64}(undef, nnew, NDF) w = 0 - @inbounds for i in 1:n + @inbounds for i = 1:n if refine_flags[i] L = vs_data.level[i] wi = vs_data.weight[i] / nc - for c in 1:nc + for c = 1:nc w += 1 dlevel[w] = L + 1 dweight[w] = wi - for d in 1:DIM - dmid[w, d] = vs_data.midpoint[i, d] + 0.5 * (ds[d] / 2^(L + 1)) * RMT[DIM][c][d] + for d = 1:DIM + dmid[w, d] = + vs_data.midpoint[i, d] + 0.5 * (ds[d] / 2^(L + 1)) * RMT[DIM][c][d] end - for k in 1:NDF + for k = 1:NDF ddf[w, k] = vs_data.df[i, k] end end @@ -93,7 +106,12 @@ emitting merged/kept cells into fresh arrays. `coarsen_ok[i]` is the per-cell w coarsen; a `2^DIM`-aligned same-level sibling group is merged iff every member is willing. `maxlevel` sizes the alignment bookkeeping `flag`. """ -function coarsen_grid_stream!(vs_data::VsData{DIM,NDF}, coarsen_ok::AbstractVector{Bool}, ds, maxlevel::Integer) where {DIM,NDF} +function coarsen_grid_stream!( + vs_data::VsData{DIM,NDF}, + coarsen_ok::AbstractVector{Bool}, + ds, + maxlevel::Integer, +) where {DIM,NDF} n = vs_data.vs_num nc = 2^DIM dlevel = Vector{Int8}(undef, n) @@ -102,46 +120,51 @@ function coarsen_grid_stream!(vs_data::VsData{DIM,NDF}, coarsen_ok::AbstractVect ddf = Matrix{Float64}(undef, n, NDF) flag = zeros(maxlevel) changed = false - w = 0; index = 1 + w = 0; + index = 1 @inbounds while index <= n fl = vs_data.level[index] if fl > 0 - if flag[fl] % 1 == 0.0 && index + nc - 1 <= n && _all_same_level(vs_data, index, fl, nc) + if flag[fl] % 1 == 0.0 && + index + nc - 1 <= n && + _all_same_level(vs_data, index, fl, nc) grp = true - for g in 0:nc-1 + for g = 0:(nc-1) coarsen_ok[index+g] || (grp = false; break) end if grp w += 1 dlevel[w] = fl - 1 dweight[w] = vs_data.weight[index] * nc - for d in 1:DIM - dmid[w, d] = vs_data.midpoint[index, d] - 0.5 * (ds[d] / 2^fl) * RMT[DIM][1][d] + for d = 1:DIM + dmid[w, d] = + vs_data.midpoint[index, d] - + 0.5 * (ds[d] / 2^fl) * RMT[DIM][1][d] end - for k in 1:NDF + for k = 1:NDF s = 0.0 - for g in 0:nc-1 + for g = 0:(nc-1) s += vs_data.df[index+g, k] end ddf[w, k] = s / nc end changed = true else - for g in 0:nc-1 + for g = 0:(nc-1) w += 1 _copy_cell!(dlevel, dweight, dmid, ddf, w, vs_data, index + g) end end index += nc if fl > 1 - for i in 1:fl-1 + for i = 1:(fl-1) flag[i] += 1 / 2^(DIM * (fl - i)) end end else w += 1 _copy_cell!(dlevel, dweight, dmid, ddf, w, vs_data, index) - for i in 1:fl + for i = 1:fl flag[i] += 1 / 2^(DIM * (fl - i + 1)) end index += 1 diff --git a/src/Velocity_space/Types.jl b/src/Velocity_space/Types.jl index ea221a4..fc3238a 100644 --- a/src/Velocity_space/Types.jl +++ b/src/Velocity_space/Types.jl @@ -3,19 +3,33 @@ $(TYPEDEF) $(TYPEDFIELDS) """ mutable struct VsData{DIM,NDF} <: AbstractVsData{DIM,NDF} - "Number of velocity cells." + """ + Number of velocity cells. + """ vs_num::Int - "Refinement level of velocity cells." + """ + Refinement level of velocity cells. # vs_num + """ level::Vector{Int8} # vs_num - "Quadrature weight of velocity cells." + """ + Quadrature weight of velocity cells. # vs_num + """ weight::Vector{Float64} # vs_num - "Coordinates of centers of velocity cells in velocity space." + """ + Coordinates of centers of velocity cells in velocity space. # vs_num x DIM + """ midpoint::Matrix{Float64} # vs_num x DIM - "Discretized distribution function." + """ + Discretized distribution function. # vs_num x NDF + """ df::Matrix{Float64} # vs_num x NDF - "Spatial gradients (df/dx) of distribution function." + """ + Spatial gradients (df/dx) of distribution function. # vs_num x NDF x DIM + """ sdf::Array{Float64,3} # vs_num x NDF x DIM - "Numerical flux of distribution function." + """ + Numerical flux of distribution function. # vs_num x NDF + """ flux::Matrix{Float64} # vs_num x NDF end @@ -43,30 +57,50 @@ $(TYPEDEF) Information of the velocity space corresponding to the face during the calculation of numerical flux. $(TYPEDFIELDS) """ -struct FaceVsData{DIM,NDF, - W<:AbstractVector{Float64}, - M<:AbstractMatrix{Float64}, - V<:AbstractVector{Float64}, - D<:AbstractMatrix{Float64}, - S<:AbstractArray{Float64}} # different sides of the face combining the face-velocity-space - "Upwinding flags. Upwinding velocities are set to `true`." +struct FaceVsData{ + DIM, + NDF, + W<:AbstractVector{Float64}, + M<:AbstractMatrix{Float64}, + V<:AbstractVector{Float64}, + D<:AbstractMatrix{Float64}, + S<:AbstractArray{Float64}, +} # different sides of the face combining the face-velocity-space + """ + Upwinding flags. Upwinding velocities are set to `true`. + """ heavi::Vector{Bool} weight::W midpoint::M - "Normal component of velocities across the face." + """ + Normal component of velocities across the face. + """ vn::V df::D sdf::S end # Outer constructor: lets existing `FaceVsData{DIM,NDF}(...)` call sites keep # working while the remaining (array-type) parameters are inferred from the args. -function FaceVsData{DIM,NDF}(heavi::Vector{Bool},weight::W,midpoint::M,vn::V,df::D,sdf::S) where {DIM,NDF, - W<:AbstractVector{Float64},M<:AbstractMatrix{Float64},V<:AbstractVector{Float64}, - D<:AbstractMatrix{Float64},S<:AbstractArray{Float64}} - return FaceVsData{DIM,NDF,W,M,V,D,S}(heavi,weight,midpoint,vn,df,sdf) +function FaceVsData{DIM,NDF}( + heavi::Vector{Bool}, + weight::W, + midpoint::M, + vn::V, + df::D, + sdf::S, +) where { + DIM, + NDF, + W<:AbstractVector{Float64}, + M<:AbstractMatrix{Float64}, + V<:AbstractVector{Float64}, + D<:AbstractMatrix{Float64}, + S<:AbstractArray{Float64}, +} + return FaceVsData{DIM,NDF,W,M,V,D,S}(heavi, weight, midpoint, vn, df, sdf) end -function FaceVsData(fvd::FaceVsData{DIM,NDF},df::AbstractMatrix) where{DIM,NDF} - return FaceVsData{DIM,NDF}(fvd.heavi,fvd.weight,fvd.midpoint,fvd.vn,df,fvd.sdf) +function FaceVsData(fvd::FaceVsData{DIM,NDF}, df::AbstractMatrix) where {DIM,NDF} + return FaceVsData{DIM,NDF}(fvd.heavi, fvd.weight, fvd.midpoint, fvd.vn, df, fvd.sdf) end struct VelocityTemplates indices::Vector{Int} # Indices of the templates @@ -79,17 +113,29 @@ Structure for cut cell in velocity space used in immersed boundaries. $(TYPEDFIELDS) """ mutable struct CuttedVelocityCells - "Indices of cut cells in [`SolidNeighbor`](@ref)'s [`VsData`](@ref)." + """ + Indices of cut cells in [`SolidNeighbor`](@ref)'s [`VsData`](@ref). + """ indices::Vector{Int} - "Quadrature weight of velocity cells. Specially, the weight of cut cells is set to 0." + """ + Quadrature weight of velocity cells. Specially, the weight of cut cells is set to 0. + """ weight::Vector{Float64} - "Distribution function of gas part corresponding to velocity at the center of cut cells." + """ + Distribution function of gas part corresponding to velocity at the center of cut cells. + """ gas_dfs::Matrix{Float64} - "Distribution function of solid part corresponding to velocity at the center of cut cells." + """ + Distribution function of solid part corresponding to velocity at the center of cut cells. + """ solid_dfs::Matrix{Float64} - "Areas of gas part in cut cells." + """ + Areas of gas part in cut cells. + """ gas_weights::Vector{Float64} - "Areas of solid part in cut cells." + """ + Areas of solid part in cut cells. + """ solid_weights::Vector{Float64} end mutable struct VS_Projection{DIM} @@ -103,23 +149,69 @@ struct Gauss_Hermite{NUM} <: AbstractQuadrature vcoords::AbstractVector weights::AbstractVector end -function Gauss_Hermite(;NP=28) +function Gauss_Hermite(; NP = 28) if NP==28 - vcoords = [ -0.5392407922630E+01, -0.4628038787602E+01, -0.3997895360339E+01, -0.3438309154336E+01, - -0.2926155234545E+01, -0.2450765117455E+01, -0.2007226518418E+01, -0.1594180474269E+01, - -0.1213086106429E+01, -0.8681075880846E+00, -0.5662379126244E+00, -0.3172834649517E+00, - -0.1331473976273E+00, -0.2574593750171E-01, +0.2574593750171E-01, +0.1331473976273E+00, - +0.3172834649517E+00, +0.5662379126244E+00, +0.8681075880846E+00, +0.1213086106429E+01, - +0.1594180474269E+01, +0.2007226518418E+01, +0.2450765117455E+01, +0.2926155234545E+01, - +0.3438309154336E+01, +0.3997895360339E+01, +0.4628038787602E+01, +0.5392407922630E+01 ] - weights = [ +0.2070921821819E-12, +0.3391774320172E-09, +0.6744233894962E-07, +0.3916031412192E-05, - +0.9416408715712E-04, +0.1130613659204E-02, +0.7620883072174E-02, +0.3130804321888E-01, - +0.8355201801999E-01, +0.1528864568113E+00, +0.2012086859914E+00, +0.1976903952423E+00, - +0.1450007948865E+00, +0.6573088665062E-01, +0.6573088665062E-01, +0.1450007948865E+00, - +0.1976903952423E+00, +0.2012086859914E+00, +0.1528864568113E+00, +0.8355201801999E-01, - +0.3130804321888E-01, +0.7620883072174E-02, +0.1130613659204E-02, +0.9416408715712E-04, - +0.3916031412192E-05, +0.6744233894962E-07, +0.3391774320172E-09, +0.2070921821819E-12 ] - return Gauss_Hermite{NP}(vcoords,weights) + vcoords = [ + -0.5392407922630E+01, + -0.4628038787602E+01, + -0.3997895360339E+01, + -0.3438309154336E+01, + -0.2926155234545E+01, + -0.2450765117455E+01, + -0.2007226518418E+01, + -0.1594180474269E+01, + -0.1213086106429E+01, + -0.8681075880846E+00, + -0.5662379126244E+00, + -0.3172834649517E+00, + -0.1331473976273E+00, + -0.2574593750171E-01, + +0.2574593750171E-01, + +0.1331473976273E+00, + +0.3172834649517E+00, + +0.5662379126244E+00, + +0.8681075880846E+00, + +0.1213086106429E+01, + +0.1594180474269E+01, + +0.2007226518418E+01, + +0.2450765117455E+01, + +0.2926155234545E+01, + +0.3438309154336E+01, + +0.3997895360339E+01, + +0.4628038787602E+01, + +0.5392407922630E+01, + ] + weights = [ + +0.2070921821819E-12, + +0.3391774320172E-09, + +0.6744233894962E-07, + +0.3916031412192E-05, + +0.9416408715712E-04, + +0.1130613659204E-02, + +0.7620883072174E-02, + +0.3130804321888E-01, + +0.8355201801999E-01, + +0.1528864568113E+00, + +0.2012086859914E+00, + +0.1976903952423E+00, + +0.1450007948865E+00, + +0.6573088665062E-01, + +0.6573088665062E-01, + +0.1450007948865E+00, + +0.1976903952423E+00, + +0.2012086859914E+00, + +0.1528864568113E+00, + +0.8355201801999E-01, + +0.3130804321888E-01, + +0.7620883072174E-02, + +0.1130613659204E-02, + +0.9416408715712E-04, + +0.3916031412192E-05, + +0.6744233894962E-07, + +0.3391774320172E-09, + +0.2070921821819E-12, + ] + return Gauss_Hermite{NP}(vcoords, weights) else throw(`Gauss_Hermite not defined yet.`) end @@ -133,4 +225,4 @@ end struct Velocity_Adaptive_Data vr::Velocity_Resolution va_flags::Vector{Bool} -end \ No newline at end of file +end diff --git a/src/Velocity_space/Velocity_space.jl b/src/Velocity_space/Velocity_space.jl index ec843c9..fe1892c 100644 --- a/src/Velocity_space/Velocity_space.jl +++ b/src/Velocity_space/Velocity_space.jl @@ -6,5 +6,10 @@ include("Rebuild.jl") include("Cut_cell.jl") include("Initialize.jl") export VsData, GhostVsData, FaceVsData, CuttedVelocityCells -export vs_adaptive_mesh_refinement!, vs_refine!, vs_coarsen!, vs_conserved_correction!, contribution_refine_flag, contribution_coarsen_flag +export vs_adaptive_mesh_refinement!, + vs_refine!, + vs_coarsen!, + vs_conserved_correction!, + contribution_refine_flag, + contribution_coarsen_flag export VsNeighborIndex, build_vs_index!, vs_locate, vs_face_neighbor diff --git a/test/runtests.jl b/test/runtests.jl index 9783323..379e306 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,7 +2,8 @@ using KitAMR, MPI MPI.Init() solver = Solver(; - DIM = 2, NDF = 2, + DIM = 2, + NDF = 2, AMR_PS_MAXLEVEL = 0, AMR_VS_MAXLEVEL = 0, PS_DYNAMIC_AMR = false, @@ -11,32 +12,29 @@ solver = Solver(; time_marching = CAIDVM_Marching, max_sim_time = 0.25, ) -gas = Gas(; - K = 0.0, - Kn = 0.075, - ω = 0.81, - ωᵣ = 0.81, -) +gas = Gas(; K = 0.0, Kn = 0.075, ω = 0.81, ωᵣ = 0.81) output = Output(solver) udf = UDF() -config = Configure(solver; - geometry = [-0.5,0.5,-0.5,0.5], - trees_num = [16,16], - quadrature = [-5.0,5.0,-5.0,5.0], - vs_trees_num = [16,16], - IC = Uniform([1.,0.,0.,1.]), +config = Configure( + solver; + geometry = [-0.5, 0.5, -0.5, 0.5], + trees_num = [16, 16], + quadrature = [-5.0, 5.0, -5.0, 5.0], + vs_trees_num = [16, 16], + IC = Uniform([1.0, 0.0, 0.0, 1.0]), domain = [ - Domain(Maxwellian,1,[1.,0.,0.,1.]), - Domain(Maxwellian,2,[1.,1.0*sqrt(5/6),0.,1.0]),Domain(Period,3), - Domain(Period,4) - ], + Domain(Maxwellian, 1, [1.0, 0.0, 0.0, 1.0]), + Domain(Maxwellian, 2, [1.0, 1.0*sqrt(5/6), 0.0, 1.0]), + Domain(Period, 3), + Domain(Period, 4), + ], output = output, gas = gas, - user_defined = udf + user_defined = udf, ) -p4est,ka = initialize(config); -solve!(p4est,ka) +p4est, ka = initialize(config); +solve!(p4est, ka) # save_result(p4est,ka) -finalize!(p4est,ka) +finalize!(p4est, ka) MPI.Finalize()