diff --git a/Examples/Tests/embedded_boundary_em_particle_absorption/CMakeLists.txt b/Examples/Tests/embedded_boundary_em_particle_absorption/CMakeLists.txt index fb5d54c0dbe..0aa5b48b2b7 100644 --- a/Examples/Tests/embedded_boundary_em_particle_absorption/CMakeLists.txt +++ b/Examples/Tests/embedded_boundary_em_particle_absorption/CMakeLists.txt @@ -13,6 +13,29 @@ if(WarpX_EB) ) endif() +if(WarpX_EB) + add_warpx_test( + test_3d_embedded_boundary_em_particle_absorption_sh_factor_2 # name + 3 # dims + 1 # nprocs + inputs_test_3d_embedded_boundary_em_particle_absorption_sh_factor_2 # inputs + "analysis.py" # analysis + "analysis_default_regression.py --path diags/diag1" # checksum + OFF # dependency + ) +endif() + +if(WarpX_EB) + add_warpx_test( + test_3d_embedded_boundary_em_particle_absorption_sh_factor_3 # name + 3 # dims + 1 # nprocs + inputs_test_3d_embedded_boundary_em_particle_absorption_sh_factor_3 # inputs + "analysis.py" # analysis + "analysis_default_regression.py --path diags/diag1" # checksum + OFF # dependency + ) +endif() if(WarpX_EB) add_warpx_test( @@ -26,6 +49,30 @@ if(WarpX_EB) ) endif() +if(WarpX_EB) + add_warpx_test( + test_2d_embedded_boundary_em_particle_absorption_sh_factor_2 # name + 2 # dims + 1 # nprocs + inputs_test_2d_embedded_boundary_em_particle_absorption_sh_factor_2 # inputs + "analysis.py" # analysis + "analysis_default_regression.py --path diags/diag1" # checksum + OFF # dependency + ) +endif() + +if(WarpX_EB) + add_warpx_test( + test_2d_embedded_boundary_em_particle_absorption_sh_factor_3 # name + 2 # dims + 1 # nprocs + inputs_test_2d_embedded_boundary_em_particle_absorption_sh_factor_3 # inputs + "analysis.py" # analysis + "analysis_default_regression.py --path diags/diag1" # checksum + OFF # dependency + ) +endif() + if(WarpX_EB) add_warpx_test( test_rz_embedded_boundary_em_particle_absorption_sh_factor_1 # name @@ -37,3 +84,27 @@ if(WarpX_EB) OFF # dependency ) endif() + +if(WarpX_EB) + add_warpx_test( + test_rz_embedded_boundary_em_particle_absorption_sh_factor_2 # name + RZ # dims + 1 # nprocs + inputs_test_rz_embedded_boundary_em_particle_absorption_sh_factor_2 # inputs + "analysis.py" # analysis + "analysis_default_regression.py --path diags/diag1" # checksum + OFF # dependency + ) +endif() + +if(WarpX_EB) + add_warpx_test( + test_rz_embedded_boundary_em_particle_absorption_sh_factor_3 # name + RZ # dims + 1 # nprocs + inputs_test_rz_embedded_boundary_em_particle_absorption_sh_factor_3 # inputs + "analysis.py" # analysis + "analysis_default_regression.py --path diags/diag1" # checksum + OFF # dependency + ) +endif() diff --git a/Examples/Tests/embedded_boundary_em_particle_absorption/analysis.py b/Examples/Tests/embedded_boundary_em_particle_absorption/analysis.py index 7647c23d846..3ba44a8ac1b 100755 --- a/Examples/Tests/embedded_boundary_em_particle_absorption/analysis.py +++ b/Examples/Tests/embedded_boundary_em_particle_absorption/analysis.py @@ -39,7 +39,7 @@ elif dim == "thetaMode": # In RZ: there are issues with divE on axis # Set the few cells around the axis to 0 for this test - divE_avg[13:19] = 0 + divE_avg[:, 13:19] = 0 tolerance = 4e-12 diff --git a/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_2d_embedded_boundary_em_particle_absorption_sh_factor_2 b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_2d_embedded_boundary_em_particle_absorption_sh_factor_2 new file mode 100644 index 00000000000..4cdbfc5dd5e --- /dev/null +++ b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_2d_embedded_boundary_em_particle_absorption_sh_factor_2 @@ -0,0 +1,11 @@ +# base input parameters +FILE = inputs_base + +geometry.dims = 2 +amr.n_cell = 32 32 +geometry.prob_lo = -10 -10 +geometry.prob_hi = 10 10 +boundary.field_lo = pec absorbing_silver_mueller +boundary.field_hi = pec absorbing_silver_mueller + +algo.particle_shape = 2 diff --git a/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_2d_embedded_boundary_em_particle_absorption_sh_factor_3 b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_2d_embedded_boundary_em_particle_absorption_sh_factor_3 new file mode 100644 index 00000000000..6113f0668fe --- /dev/null +++ b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_2d_embedded_boundary_em_particle_absorption_sh_factor_3 @@ -0,0 +1,11 @@ +# base input parameters +FILE = inputs_base + +geometry.dims = 2 +amr.n_cell = 32 32 +geometry.prob_lo = -10 -10 +geometry.prob_hi = 10 10 +boundary.field_lo = pec absorbing_silver_mueller +boundary.field_hi = pec absorbing_silver_mueller + +algo.particle_shape = 3 diff --git a/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_3d_embedded_boundary_em_particle_absorption_sh_factor_2 b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_3d_embedded_boundary_em_particle_absorption_sh_factor_2 new file mode 100644 index 00000000000..ea977877a2d --- /dev/null +++ b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_3d_embedded_boundary_em_particle_absorption_sh_factor_2 @@ -0,0 +1,11 @@ +# base input parameters +FILE = inputs_base + +geometry.dims = 3 +amr.n_cell = 32 32 32 +geometry.prob_lo = -10 -10 -10 +geometry.prob_hi = 10 10 10 +boundary.field_lo = pec pec absorbing_silver_mueller +boundary.field_hi = pec pec absorbing_silver_mueller + +algo.particle_shape = 1 diff --git a/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_3d_embedded_boundary_em_particle_absorption_sh_factor_3 b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_3d_embedded_boundary_em_particle_absorption_sh_factor_3 new file mode 100644 index 00000000000..553e5e058e7 --- /dev/null +++ b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_3d_embedded_boundary_em_particle_absorption_sh_factor_3 @@ -0,0 +1,11 @@ +# base input parameters +FILE = inputs_base + +geometry.dims = 3 +amr.n_cell = 32 32 32 +geometry.prob_lo = -10 -10 -10 +geometry.prob_hi = 10 10 10 +boundary.field_lo = pec pec absorbing_silver_mueller +boundary.field_hi = pec pec absorbing_silver_mueller + +algo.particle_shape = 3 diff --git a/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_rz_embedded_boundary_em_particle_absorption_sh_factor_2 b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_rz_embedded_boundary_em_particle_absorption_sh_factor_2 new file mode 100644 index 00000000000..7faf7fd8934 --- /dev/null +++ b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_rz_embedded_boundary_em_particle_absorption_sh_factor_2 @@ -0,0 +1,11 @@ +# base input parameters +FILE = inputs_base + +geometry.dims = RZ +amr.n_cell = 16 32 +geometry.prob_lo = 0 -10 +geometry.prob_hi = 10 10 +boundary.field_lo = none absorbing_silver_mueller +boundary.field_hi = pec absorbing_silver_mueller + +algo.particle_shape = 1 diff --git a/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_rz_embedded_boundary_em_particle_absorption_sh_factor_3 b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_rz_embedded_boundary_em_particle_absorption_sh_factor_3 new file mode 100644 index 00000000000..aad65594c96 --- /dev/null +++ b/Examples/Tests/embedded_boundary_em_particle_absorption/inputs_test_rz_embedded_boundary_em_particle_absorption_sh_factor_3 @@ -0,0 +1,11 @@ +# base input parameters +FILE = inputs_base + +geometry.dims = RZ +amr.n_cell = 16 32 +geometry.prob_lo = 0 -10 +geometry.prob_hi = 10 10 +boundary.field_lo = none absorbing_silver_mueller +boundary.field_hi = pec absorbing_silver_mueller + +algo.particle_shape = 3 diff --git a/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_em_particle_absorption_sh_factor_2.json b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_em_particle_absorption_sh_factor_2.json new file mode 100644 index 00000000000..481aba1f36b --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_em_particle_absorption_sh_factor_2.json @@ -0,0 +1,24 @@ +{ + "lev=0": { + "divE": 2.4521053721245334e-08, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} \ No newline at end of file diff --git a/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_em_particle_absorption_sh_factor_3.json b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_em_particle_absorption_sh_factor_3.json new file mode 100644 index 00000000000..82b6c6849ac --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_em_particle_absorption_sh_factor_3.json @@ -0,0 +1,24 @@ +{ + "lev=0": { + "divE": 2.2059346534892452e-08, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} \ No newline at end of file diff --git a/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_removal_depth_sh_factor_1.json b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_removal_depth_sh_factor_1.json new file mode 100644 index 00000000000..632c48df963 --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_removal_depth_sh_factor_1.json @@ -0,0 +1,30 @@ +{ + "lev=0": { + "Bx": 0.0, + "By": 2.3792992316172512e-15, + "Bz": 0.0 , + "Ex": 6.177046470842443e-07, + "Ey": 0.0, + "Ez": 7.259396011803518e-07, + "divE": 2.809306467366024e-07, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} \ No newline at end of file diff --git a/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_removal_depth_sh_factor_2.json b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_removal_depth_sh_factor_2.json new file mode 100644 index 00000000000..9112c931b55 --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_removal_depth_sh_factor_2.json @@ -0,0 +1,30 @@ +{ + "lev=0": { + "Bx": 0.0, + "By": 2.3948084603369097e-15, + "Bz": 0.0, + "Ex": 6.747158562891953e-07, + "Ey": 0.0, + "Ez": 5.541309886315263e-07, + "divE": 2.091715826275267e-07, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} diff --git a/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_removal_depth_sh_factor_3.json b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_removal_depth_sh_factor_3.json new file mode 100644 index 00000000000..8d6ddf169af --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_2d_embedded_boundary_removal_depth_sh_factor_3.json @@ -0,0 +1,31 @@ +{ + "lev=0": { + "Bx": 0.0, + "By": 2.379299231617251e-15, + "Bz": 0.0, + "Ex": 6.177046470842443e-07, + "Ey": 0.0, + "Ez": 7.259396011803522e-07, + "divE": 2.8093064673660275e-07, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } + } + diff --git a/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_em_particle_absorption_sh_factor_2.json b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_em_particle_absorption_sh_factor_2.json new file mode 100644 index 00000000000..d3e08d9723e --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_em_particle_absorption_sh_factor_2.json @@ -0,0 +1,24 @@ +{ + "lev=0": { + "divE": 4.928354322096152e-07, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} \ No newline at end of file diff --git a/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_em_particle_absorption_sh_factor_3.json b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_em_particle_absorption_sh_factor_3.json new file mode 100644 index 00000000000..23c03c7e7bc --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_em_particle_absorption_sh_factor_3.json @@ -0,0 +1,24 @@ +{ + "lev=0": { + "divE": 4.3355127342920327e-07, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} \ No newline at end of file diff --git a/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_removal_depth_sh_factor_1.json b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_removal_depth_sh_factor_1.json new file mode 100644 index 00000000000..109f5fb4d35 --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_removal_depth_sh_factor_1.json @@ -0,0 +1,30 @@ +{ + "lev=0": { + "Bx": 3.835377401535272e-15, + "By": 7.634560527952392e-15, + "Bz": 7.670097149513554e-15, + "Ex": 1.837433604148419e-06, + "Ey": 1.4507850267928362e-06, + "Ez": 1.4325637523931794e-06, + "divE": 7.330866223540695e-07, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} \ No newline at end of file diff --git a/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_removal_depth_sh_factor_2.json b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_removal_depth_sh_factor_2.json new file mode 100644 index 00000000000..9ff91af6550 --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_removal_depth_sh_factor_2.json @@ -0,0 +1,30 @@ +{ + "lev=0": { + "Bx": 2.3948084603369097e-15, + "By": 0.0, + "Bz": 6.747158562891953e-07, + "Ex": 0.0, + "Ey": 5.541309886315263e-07, + "Ez": 0.0, + "divE": 2.091715826275267e-07, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} \ No newline at end of file diff --git a/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_removal_depth_sh_factor_3.json b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_removal_depth_sh_factor_3.json new file mode 100644 index 00000000000..0e0cdf5eb0f --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_3d_embedded_boundary_removal_depth_sh_factor_3.json @@ -0,0 +1,31 @@ +{ + "lev=0": { + "Bx": 2.9100687916345874e-15, + "By": 6.121275580503632e-15, + "Bz": 5.9043095451081354e-15, + "Ex": 1.4574231057224582e-06, + "Ey": 1.1648744803916206e-06, + "Ez": 1.16164257835401e-06, + "divE": 6.781029990295743e-07, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } + } + diff --git a/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_em_particle_absorption_sh_factor_2.json b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_em_particle_absorption_sh_factor_2.json new file mode 100644 index 00000000000..30d7d0ba081 --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_em_particle_absorption_sh_factor_2.json @@ -0,0 +1,24 @@ +{ + "lev=0": { + "divE": 1.4599714697029335e-08, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} \ No newline at end of file diff --git a/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_em_particle_absorption_sh_factor_3.json b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_em_particle_absorption_sh_factor_3.json new file mode 100644 index 00000000000..76baf73cc3a --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_em_particle_absorption_sh_factor_3.json @@ -0,0 +1,24 @@ +{ + "lev=0": { + "divE": 1.3292471881599093e-08, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} \ No newline at end of file diff --git a/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_removal_depth_sh_factor_1.json b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_removal_depth_sh_factor_1.json new file mode 100644 index 00000000000..0376427a4f0 --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_removal_depth_sh_factor_1.json @@ -0,0 +1,28 @@ +{ + "lev=0": { + "Br": 0.0, + "Bz": 0.0, + "Er": 1.6208621785146114e-07, + "Ez": 2.805848027148827e-07, + "divE": 5.118824286040605e-08, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} diff --git a/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_removal_depth_sh_factor_2.json b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_removal_depth_sh_factor_2.json new file mode 100644 index 00000000000..0376427a4f0 --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_removal_depth_sh_factor_2.json @@ -0,0 +1,28 @@ +{ + "lev=0": { + "Br": 0.0, + "Bz": 0.0, + "Er": 1.6208621785146114e-07, + "Ez": 2.805848027148827e-07, + "divE": 5.118824286040605e-08, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} diff --git a/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_removal_depth_sh_factor_3.json b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_removal_depth_sh_factor_3.json new file mode 100644 index 00000000000..0376427a4f0 --- /dev/null +++ b/Regression/Checksum/benchmarks_json/test_rz_embedded_boundary_removal_depth_sh_factor_3.json @@ -0,0 +1,28 @@ +{ + "lev=0": { + "Br": 0.0, + "Bz": 0.0, + "Er": 1.6208621785146114e-07, + "Ez": 2.805848027148827e-07, + "divE": 5.118824286040605e-08, + "rho": 0.0 + }, + "electron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + }, + "positron": { + "particle_position_x": 0.0, + "particle_position_y": 0.0, + "particle_position_z": 0.0, + "particle_momentum_x": 0.0, + "particle_momentum_y": 0.0, + "particle_momentum_z": 0.0, + "particle_weight": 0.0 + } +} diff --git a/Source/EmbeddedBoundary/WarpXInitEB.cpp b/Source/EmbeddedBoundary/WarpXInitEB.cpp index 6a6f594b380..271f12231b0 100644 --- a/Source/EmbeddedBoundary/WarpXInitEB.cpp +++ b/Source/EmbeddedBoundary/WarpXInitEB.cpp @@ -291,6 +291,97 @@ WarpX::ScaleAreas (ablastr::fields::VectorField& face_areas, } } +void +WarpX::MarkReducedShapeCells ( + std::unique_ptr & eb_reduce_particle_shape, + amrex::EBFArrayBoxFactory const & eb_fact, + int const particle_shape_order ) +{ + // Pre-fill array with 0, including in the ghost cells outside of the domain. + // (The guard cells in the domain will be updated by `FillBoundary` at the end of this function.) + eb_reduce_particle_shape->setVal(0, eb_reduce_particle_shape->nGrow()); + + // Extract structures for embedded boundaries + amrex::FabArray const& eb_flag = eb_fact.getMultiEBCellFlagFab(); + +#ifdef AMREX_USE_OMP +#pragma omp parallel if (amrex::Gpu::notInLaunchRegion()) +#endif + for (amrex::MFIter mfi(*eb_reduce_particle_shape); mfi.isValid(); ++mfi) { + + const amrex::Box& box = mfi.tilebox(); + amrex::Array4 const & eb_reduce_particle_shape_arr = eb_reduce_particle_shape->array(mfi); + + // Check if the box (including one layer of guard cells) contains a mix of covered and regular cells + const amrex::Box& eb_info_box = mfi.tilebox(amrex::IntVect::TheCellVector()).grow(1); + amrex::FabType const fab_type = eb_flag[mfi].getType( eb_info_box ); + + if (fab_type == amrex::FabType::regular) { // All cells in the box are regular + + // Every cell in box is regular: do not reduce particle shape in any cell + amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE (int i, int j, int k) { + eb_reduce_particle_shape_arr(i, j, k) = 0; + }); + + } else if (fab_type == amrex::FabType::covered) { // All cells in the box are covered + + // Every cell in box is fully covered: reduce particle shape + amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE (int i, int j, int k) { + eb_reduce_particle_shape_arr(i, j, k) = 1; + }); + + } else { // The box contains a mix of covered and regular cells + + auto const & flag = eb_flag[mfi].array(); + + amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE (int i, int j, int k) { + + // Check if any of the neighboring cells over which the particle shape might extend + // are either partially or fully covered. In this case, set eb_reduce_particle_shape_arr + // to one for this cell, to indicate that the particle should use an order 1 shape + // (This ensures that the particle never deposits any charge in a partially or + // fully covered cell, even with higher-order shapes) + // Note: in the code below `particle_shape_order/2` corresponds to the number of neighboring cells + // over which the shape factor could extend, in each direction. + int const i_start = i-particle_shape_order/2; + int const i_end = i+particle_shape_order/2; +#if AMREX_SPACEDIM > 1 + int const j_start = j-particle_shape_order/2; + int const j_end = j+particle_shape_order/2; +#else + int const j_start = j; + int const j_end = j; +#endif +#if AMREX_SPACEDIM > 2 + int const k_start = k-particle_shape_order/2; + int const k_end = k+particle_shape_order/2; +#else + int const k_start = k; + int const k_end = k; +#endif + int reduce_shape = 0; + for (int i_cell = i_start; i_cell <= i_end; ++i_cell) { + for (int j_cell = j_start; j_cell <= j_end; ++j_cell) { + for (int k_cell = k_start; k_cell <= k_end; ++k_cell) { + // `isRegular` returns `false` if the cell is either partially or fully covered. + if ( !flag(i_cell, j_cell, k_cell).isRegular() ) { + reduce_shape = 1; + } + } + } + } + eb_reduce_particle_shape_arr(i, j, k) = reduce_shape; + }); + + } + + } + + // FillBoundary to set the values in the guard cells + eb_reduce_particle_shape->FillBoundary(Geom(0).periodicity()); + +} + void WarpX::MarkUpdateCellsStairCase ( std::array< std::unique_ptr,3> & eb_update, diff --git a/Source/Initialization/WarpXInitData.cpp b/Source/Initialization/WarpXInitData.cpp index 69e87ba7b7e..f9f70e5a9e0 100644 --- a/Source/Initialization/WarpXInitData.cpp +++ b/Source/Initialization/WarpXInitData.cpp @@ -1227,20 +1227,12 @@ void WarpX::InitializeEBGridData (int lev) #ifdef AMREX_USE_EB if (lev == maxLevel()) { - // Throw a warning if EB is on and particle_shape > 1 - if ((nox > 1 or noy > 1 or noz > 1) and EB::enabled()) - { - ablastr::warn_manager::WMRecordWarning("Particles", - "when algo.particle_shape > 1, numerical artifacts will be present when\n" - "particles are close to embedded boundaries"); - } + auto const eb_fact = fieldEBFactory(lev); if (WarpX::electromagnetic_solver_id != ElectromagneticSolverAlgo::PSATD ) { using warpx::fields::FieldType; - auto const eb_fact = fieldEBFactory(lev); - if (WarpX::electromagnetic_solver_id == ElectromagneticSolverAlgo::ECT) { auto edge_lengths_lev = m_fields.get_alldirs(FieldType::edge_lengths, lev); @@ -1261,7 +1253,6 @@ void WarpX::InitializeEBGridData (int lev) MarkUpdateBCellsECT( m_eb_update_B[lev], face_areas_lev, edge_lengths_lev); } else { - // Mark on which grid points E should be updated (stair-case approximation) MarkUpdateCellsStairCase( m_eb_update_E[lev], @@ -1272,12 +1263,12 @@ void WarpX::InitializeEBGridData (int lev) m_eb_update_B[lev], m_fields.get_alldirs(FieldType::Bfield_fp, lev), eb_fact ); - } } ComputeDistanceToEB(); + MarkReducedShapeCells( m_eb_reduce_particle_shape[lev], eb_fact, WarpX::nox ); } #else diff --git a/Source/Parallelization/WarpXRegrid.cpp b/Source/Parallelization/WarpXRegrid.cpp index 79975397196..4c7668aa0e2 100644 --- a/Source/Parallelization/WarpXRegrid.cpp +++ b/Source/Parallelization/WarpXRegrid.cpp @@ -194,6 +194,7 @@ WarpX::RemakeLevel (int lev, Real /*time*/, const BoxArray& ba, const Distributi for (int idim=0; idim < 3; ++idim) { if (eb_enabled) { + RemakeMultiFab( m_eb_reduce_particle_shape[lev] ); if (WarpX::electromagnetic_solver_id != ElectromagneticSolverAlgo::PSATD) { RemakeMultiFab( m_eb_update_E[lev][idim] ); RemakeMultiFab( m_eb_update_B[lev][idim] ); diff --git a/Source/Particles/Deposition/CurrentDeposition.H b/Source/Particles/Deposition/CurrentDeposition.H index cb56c559bc0..bc870257d8f 100644 --- a/Source/Particles/Deposition/CurrentDeposition.H +++ b/Source/Particles/Deposition/CurrentDeposition.H @@ -638,6 +638,9 @@ void doDepositionSharedShapeN (const GetParticlePosition& GetPosition, * \param lo Index lower bounds of domain. * \param q species charge. * \param n_rz_azimuthal_modes Number of azimuthal modes when using RZ geometry. + * \param reduced_particle_shape_mask Array4 of int, Mask that indicates whether a particle + * should use its regular shape factor or a reduced, order-1 shape factor instead in a given cell. + * \param enable_reduced_shape Flag to indicate whether to use the reduced shape factor */ template void doEsirkepovDepositionShapeN (const GetParticlePosition& GetPosition, @@ -656,7 +659,10 @@ void doEsirkepovDepositionShapeN (const GetParticlePosition& GetPosition, const amrex::XDim3 & xyzmin, amrex::Dim3 lo, amrex::Real q, - [[maybe_unused]]int n_rz_azimuthal_modes) + [[maybe_unused]] int n_rz_azimuthal_modes, + const amrex::Array4& reduced_particle_shape_mask, + bool enable_reduced_shape + ) { using namespace amrex; using namespace amrex::literals; @@ -680,9 +686,14 @@ void doEsirkepovDepositionShapeN (const GetParticlePosition& GetPosition, #endif // Loop over particles and deposit into Jx_arr, Jy_arr and Jz_arr - amrex::ParallelFor( - np_to_deposit, - [=] AMREX_GPU_DEVICE (long const ip) { + + // (Compile 2 versions of the kernel: with and without reduced shape) + enum eb_flags : int { has_reduced_shape, no_reduced_shape }; + const int reduce_shape_runtime_flag = (enable_reduced_shape && (depos_order>1))? has_reduced_shape : no_reduced_shape; + + amrex::ParallelFor( TypeList>{}, + {reduce_shape_runtime_flag}, + np_to_deposit, [=] AMREX_GPU_DEVICE (long ip, auto reduce_shape_control) { // --- Get particle quantities Real const gaminv = 1.0_rt/std::sqrt(1.0_rt + uxp[ip]*uxp[ip]*clightsq + uyp[ip]*uyp[ip]*clightsq @@ -735,6 +746,43 @@ void doEsirkepovDepositionShapeN (const GetParticlePosition& GetPosition, double const z_new = (zp - xyzmin.z + (relative_time + 0.5_rt*dt)*uzp[ip]*gaminv)*dinv.z; double const z_old = z_new - dt*dinv.z*uzp[ip]*gaminv; + // Check whether the particle is close to the EB at the old and new position + bool reduce_shape_old, reduce_shape_new; +#ifdef AMREX_USE_CUDA + amrex::ignore_unused(reduced_particle_shape_mask, lo); // Needed to avoid compilation error with nvcc +#endif + if constexpr (reduce_shape_control == has_reduced_shape) { +#if defined(WARPX_DIM_3D) + reduce_shape_old = reduced_particle_shape_mask( + lo.x + int(amrex::Math::floor(x_old)), + lo.y + int(amrex::Math::floor(y_old)), + lo.z + int(amrex::Math::floor(z_old))); + reduce_shape_new = reduced_particle_shape_mask( + lo.x + int(amrex::Math::floor(x_new)), + lo.y + int(amrex::Math::floor(y_new)), + lo.z + int(amrex::Math::floor(z_new))); +#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ) + reduce_shape_old = reduced_particle_shape_mask( + lo.x + int(amrex::Math::floor(x_old)), + lo.y + int(amrex::Math::floor(z_old)), + 0); + reduce_shape_new = reduced_particle_shape_mask( + lo.x + int(amrex::Math::floor(x_new)), + lo.y + int(amrex::Math::floor(z_new)), + 0); +#elif defined(WARPX_DIM_1D_Z) + reduce_shape_old = reduced_particle_shape_mask( + lo.x + int(amrex::Math::floor(z_old)), + 0, 0); + reduce_shape_new = reduced_particle_shape_mask( + lo.x + int(amrex::Math::floor(z_new)), + 0, 0); +#endif + } else { + reduce_shape_old = false; + reduce_shape_new = false; + } + #if defined(WARPX_DIM_RZ) Real const vy = (-uxp[ip]*sintheta_mid + uyp[ip]*costheta_mid)*gaminv; #elif defined(WARPX_DIM_XZ) @@ -749,6 +797,9 @@ void doEsirkepovDepositionShapeN (const GetParticlePosition& GetPosition, // [ijk]_new: leftmost grid point that the particle touches const Compute_shape_factor< depos_order > compute_shape_factor; const Compute_shifted_shape_factor< depos_order > compute_shifted_shape_factor; + // In cells marked by reduced_particle_shape_mask, we need order 1 deposition + const Compute_shifted_shape_factor< 1 > compute_shifted_shape_factor_order1; + amrex::ignore_unused(compute_shifted_shape_factor_order1); // unused for `no_reduced_shape` // Shape factor arrays // Note that there are extra values above and below @@ -758,19 +809,58 @@ void doEsirkepovDepositionShapeN (const GetParticlePosition& GetPosition, #if !defined(WARPX_DIM_1D_Z) double sx_new[depos_order + 3] = {0.}; double sx_old[depos_order + 3] = {0.}; - const int i_new = compute_shape_factor(sx_new+1, x_new); + const int i_new = compute_shape_factor(sx_new+1, x_new ); const int i_old = compute_shifted_shape_factor(sx_old, x_old, i_new); + // If particle is close to the embedded boundary, recompute deposition with order 1 shape + if constexpr (reduce_shape_control == has_reduced_shape) { + if (reduce_shape_new) { + for (int i=0; i eb_reduce_particle_shape; + if (EB::enabled()) { + eb_reduce_particle_shape = (*warpx.GetEBReduceParticleShapeFlag()[lev])[pti].array(); + } + + if (WarpX::nox == 1){ doEsirkepovDepositionShapeN<1>( - GetPosition, wp.dataPtr() + offset, uxp.dataPtr() + offset, - uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev, - jx_arr, jy_arr, jz_arr, np_to_deposit, dt, relative_time, dinv, xyzmin, lo, q, - WarpX::n_rz_azimuthal_modes); + GetPosition, wp.dataPtr() + offset, uxp.dataPtr() + offset, + uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev, + jx_arr, jy_arr, jz_arr, + np_to_deposit, dt, relative_time, dinv, xyzmin, lo, q, + WarpX::n_rz_azimuthal_modes, + eb_reduce_particle_shape, EB::enabled() ); } else if (WarpX::nox == 2){ doEsirkepovDepositionShapeN<2>( GetPosition, wp.dataPtr() + offset, uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev, - jx_arr, jy_arr, jz_arr, np_to_deposit, dt, relative_time, dinv, xyzmin, lo, q, - WarpX::n_rz_azimuthal_modes); + jx_arr, jy_arr, jz_arr, + np_to_deposit, dt, relative_time, dinv, xyzmin, lo, q, + WarpX::n_rz_azimuthal_modes, + eb_reduce_particle_shape, EB::enabled() ); } else if (WarpX::nox == 3){ doEsirkepovDepositionShapeN<3>( GetPosition, wp.dataPtr() + offset, uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev, - jx_arr, jy_arr, jz_arr, np_to_deposit, dt, relative_time, dinv, xyzmin, lo, q, - WarpX::n_rz_azimuthal_modes); + jx_arr, jy_arr, jz_arr, + np_to_deposit, dt, relative_time, dinv, xyzmin, lo, q, + WarpX::n_rz_azimuthal_modes, + eb_reduce_particle_shape, EB::enabled() ); } else if (WarpX::nox == 4){ doEsirkepovDepositionShapeN<4>( GetPosition, wp.dataPtr() + offset, uxp.dataPtr() + offset, uyp.dataPtr() + offset, uzp.dataPtr() + offset, ion_lev, - jx_arr, jy_arr, jz_arr, np_to_deposit, dt, relative_time, dinv, xyzmin, lo, q, - WarpX::n_rz_azimuthal_modes); + jx_arr, jy_arr, jz_arr, + np_to_deposit, dt, relative_time, dinv, xyzmin, lo, q, + WarpX::n_rz_azimuthal_modes, + eb_reduce_particle_shape, EB::enabled() ); } + } else if (push_type == PushType::Implicit) { #if (AMREX_SPACEDIM >= 2) auto& xp_n = pti.GetAttribs(particle_comps["x_n"]); diff --git a/Source/WarpX.H b/Source/WarpX.H index c5a58febe69..a5a8ea81438 100644 --- a/Source/WarpX.H +++ b/Source/WarpX.H @@ -162,9 +162,9 @@ public: HybridPICModel& GetHybridPICModel () { return *m_hybrid_pic_model; } [[nodiscard]] HybridPICModel * get_pointer_HybridPICModel () const { return m_hybrid_pic_model.get(); } MultiDiagnostics& GetMultiDiags () {return *multi_diags;} - ParticleBoundaryBuffer& GetParticleBoundaryBuffer () { return *m_particle_boundary_buffer; } amrex::Vector,3 > >& GetEBUpdateEFlag() { return m_eb_update_E; } + amrex::Vector< std::unique_ptr > const & GetEBReduceParticleShapeFlag() const { return m_eb_reduce_particle_shape; } static void shiftMF (amrex::MultiFab& mf, const amrex::Geometry& geom, int num_shift, int dir, int lev, bool update_cost_flag, @@ -1007,6 +1007,26 @@ public: void InitEB (); #ifdef AMREX_USE_EB + + /** \brief Set a flag to indicate in which cells a particle should deposit charge/current + * with a reduced, order 1 shape. + * + * More specifically, the flag is set to 1 if any of the neighboring cells over which the + * particle shape might extend are either partially or fully covered by an embedded boundary. + * This ensures that a particle in this cell deposits with an order 1 shape, which in turn + * makes sure that the particle never deposits any charge in a partially or fully covered cell. + * + * \param[in] eb_reduce_particle_shape multifab to be filled with 1s and 0s + * \param[in] eb_fact EB factory + * \param[in] particle_shape_order order of the particle shape function + */ + + + void MarkReducedShapeCells ( + std::unique_ptr & eb_reduce_particle_shape, + amrex::EBFArrayBoxFactory const & eb_fact, + int particle_shape_order ); + /** \brief Set a flag to indicate on which grid points the field `field` * should be updated, depending on their position relative to the embedded boundary. * @@ -1428,6 +1448,13 @@ private: amrex::Vector,3 > > m_eb_update_E; amrex::Vector,3 > > m_eb_update_B; + /** EB: Mask that indicates whether a particle should use its regular shape factor (mask set to 0) + * or a reduced, order-1 shape factor instead (mask set to 1) in a given cell, when depositing charge/current. + * The flag is typically set to 1 in cells that are close to the embedded boundary, in order to avoid + * errors in charge conservation when a particle is too close to the embedded boundary. + */ + amrex::Vector< std::unique_ptr > m_eb_reduce_particle_shape; + /** EB: for every mesh face flag_info_face contains a: * * 0 if the face needs to be extended * * 1 if the face is large enough to lend area to other faces diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp index c08906cf289..50a7fb4ea8f 100644 --- a/Source/WarpX.cpp +++ b/Source/WarpX.cpp @@ -342,6 +342,8 @@ WarpX::WarpX () m_eb_update_E.resize(nlevs_max); m_eb_update_B.resize(nlevs_max); + m_eb_reduce_particle_shape.resize(nlevs_max); + m_flag_info_face.resize(nlevs_max); m_flag_ext_face.resize(nlevs_max); m_borrowing.resize(nlevs_max); @@ -2329,9 +2331,13 @@ WarpX::AllocLevelMFs (int lev, const BoxArray& ba, const DistributionMapping& dm amrex::IntVect const ng_ls(2); //EB level set m_fields.alloc_init(FieldType::distance_to_eb, lev, amrex::convert(ba, IntVect::TheNodeVector()), dm, nc_ls, ng_ls, 0.0_rt); + // Whether to reduce the particle shape to order 1 when close to the EB + AllocInitMultiFab(m_eb_reduce_particle_shape[lev], amrex::convert(ba, IntVect::TheCellVector()), dm, ncomps, + ngRho, lev, "m_eb_reduce_particle_shape"); // EB info are needed only at the finest level if (lev == maxLevel()) { + if (WarpX::electromagnetic_solver_id != ElectromagneticSolverAlgo::PSATD) { AllocInitMultiFab(m_eb_update_E[lev][0], amrex::convert(ba, Ex_nodal_flag), dm, ncomps,