-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding support for pml in domain for multiple patches #4632
Changes from all commits
d6c8909
96cc7fa
af19b69
00c136e
4dbfaf0
3cdacfe
528fc6f
82225d6
d72fd6e
be9fe48
3762427
1a6b723
9dcf20a
ea0babc
3afca6d
74ce961
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# Copyright 2019-2020 Luca Fedeli, Maxence Thevenet, Remi Lehe | ||
# | ||
# | ||
# This file is part of WarpX. | ||
# | ||
# License: BSD-3-Clause-LBNL | ||
|
||
""" | ||
This script tests the absorption of particles in the PML. | ||
|
||
The input file inputs_2d/inputs is used: it features a positive and a | ||
negative particle, going in opposite direction and eventually | ||
leaving the box. This script tests that the field in the box | ||
is close to 0 once the particles have left. With regular | ||
PML, this test fails, since the particles leave a spurious | ||
charge, with associated fields, behind them. | ||
""" | ||
import os | ||
import sys | ||
|
||
import yt | ||
|
||
yt.funcs.mylog.setLevel(0) | ||
sys.path.insert(1, '../../../../warpx/Regression/Checksum/') | ||
import checksumAPI | ||
|
||
# Open plotfile specified in command line | ||
filename = sys.argv[1] | ||
ds = yt.load( filename ) | ||
|
||
# Check that the field is low enough | ||
ad0 = ds.covering_grid(level=0, left_edge=ds.domain_left_edge, dims=ds.domain_dimensions) | ||
Ex_array_lev0 = ad0[('mesh','Ex')].to_ndarray() | ||
Ey_array_lev0 = ad0[('mesh','Ey')].to_ndarray() | ||
Ez_array_lev0 = ad0[('mesh','Ez')].to_ndarray() | ||
max_Efield_lev0 = max(Ex_array_lev0.max(), Ey_array_lev0.max(), Ez_array_lev0.max()) | ||
print( "max_Efield level0 = %s" %max_Efield_lev0 ) | ||
|
||
ad1 = ds.covering_grid(level=1, left_edge=ds.domain_left_edge, dims=ds.domain_dimensions) | ||
Ex_array_lev1 = ad1[('mesh','Ex')].to_ndarray() | ||
Ey_array_lev1 = ad1[('mesh','Ey')].to_ndarray() | ||
Ez_array_lev1 = ad1[('mesh','Ez')].to_ndarray() | ||
max_Efield_lev1 = max(Ex_array_lev1.max(), Ey_array_lev1.max(), Ez_array_lev1.max()) | ||
print( "max_Efield level1 = %s" %max_Efield_lev1 ) | ||
|
||
# The field associated with the particle does not have | ||
# the same amplitude in 2d and 3d | ||
if ds.dimensionality == 2: | ||
if ds.max_level == 0: | ||
tolerance_abs = 0.0003 | ||
elif ds.max_level == 1: | ||
tolerance_abs = 0.0006 | ||
elif ds.dimensionality == 3: | ||
if ds.max_level == 0: | ||
tolerance_abs = 10 | ||
elif ds.max_level == 1: | ||
tolerance_abs = 110 | ||
else: | ||
raise ValueError("Unknown dimensionality") | ||
|
||
print("tolerance_abs: " + str(tolerance_abs)) | ||
assert max_Efield_lev0 < tolerance_abs | ||
assert max_Efield_lev1 < tolerance_abs | ||
|
||
test_name = os.path.split(os.getcwd())[1] | ||
checksumAPI.evaluate_checksum(test_name, filename) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -560,40 +560,56 @@ PML::PML (const int lev, const BoxArray& grid_ba, const DistributionMapping& gri | |
m_geom(geom), | ||
m_cgeom(cgeom) | ||
{ | ||
// When `do_pml_in_domain` is true, the PML overlap with the last `ncell` of the physical domain | ||
// (instead of extending `ncell` outside of the physical domain) | ||
// In order to implement this, a reduced domain is created here (decreased by ncells in all direction) | ||
// and passed to `MakeBoxArray`, which surrounds it by PML boxes | ||
// (thus creating the PML boxes at the right position, where they overlap with the original domain) | ||
// minimalBox provides the bounding box around grid_ba for level, lev. | ||
// Note that this is okay to build pml inside domain for a single patch, or joint patches | ||
// with same [min,max]. But it does not support multiple disjoint refinement patches. | ||
Box domain0 = grid_ba.minimalBox(); | ||
// When `do_pml_in_domain` is true, the PML overlap with the last `ncell` of the physical domain or fine patch(es) | ||
// (instead of extending `ncell` outside of the physical domain or fine patch(es)) | ||
// In order to implement this, we define a new reduced Box Array ensuring that it does not | ||
// include ncells from the edges of the physical domain or fine patch. | ||
// (thus creating the PML boxes at the right position, where they overlap with the original domain or fine patch(es)) | ||
|
||
BoxArray grid_ba_reduced = grid_ba; | ||
if (do_pml_in_domain) { | ||
for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) { | ||
if (do_pml_Lo[idim]){ | ||
domain0.growLo(idim, -ncell); | ||
} | ||
if (do_pml_Hi[idim]){ | ||
domain0.growHi(idim, -ncell); | ||
BoxList bl = grid_ba.boxList(); | ||
// Here we loop over all the boxes in the original grid_ba BoxArray | ||
// For each box, we find if its in the edge (or boundary), and the size of those boxes are decreased by ncell | ||
for (auto& b : bl) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a comment to explain what this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added comments to clarify |
||
for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) { | ||
if (do_pml_Lo[idim]) { | ||
// Get neighboring box on lower side in direction idim and check if it intersects with any of the boxes | ||
// in grid_ba. If no intersection, then the box, b, in the boxlist, is in the edge and we decrase | ||
// the size by ncells using growLo(idim,-ncell) | ||
Box const& bb = amrex::adjCellLo(b, idim); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a comment to explains what this code (the call to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added comments to clarify |
||
if ( ! grid_ba.intersects(bb) ) { | ||
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(b.length(idim) > ncell, " box length must be greater that pml size"); | ||
b.growLo(idim, -ncell); | ||
} | ||
} | ||
if (do_pml_Hi[idim]) { | ||
// Get neighboring box on higher side in direction idim and check if it intersects with any of the boxes | ||
// in grid_ba. If no intersection, then the box, b, in the boxlist, is in the edge and we decrase | ||
// the size by ncells using growHi(idim,-ncell) | ||
Box const& bb = amrex::adjCellHi(b, idim); | ||
if ( ! grid_ba.intersects(bb) ) { | ||
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(b.length(idim) > ncell, " box length must be greater that pml size"); | ||
b.growHi(idim, -ncell); | ||
} | ||
} | ||
} | ||
} | ||
grid_ba_reduced = BoxArray(std::move(bl)); | ||
} | ||
const BoxArray grid_ba_reduced = (do_pml_in_domain) ? | ||
BoxArray(grid_ba.boxList().intersect(domain0)) : grid_ba; | ||
|
||
Box const domain0 = grid_ba_reduced.minimalBox(); | ||
const bool is_single_box_domain = domain0.numPts() == grid_ba_reduced.numPts(); | ||
const BoxArray& ba = MakeBoxArray(is_single_box_domain, domain0, *geom, grid_ba_reduced, | ||
IntVect(ncell), do_pml_in_domain, do_pml_Lo, do_pml_Hi); | ||
|
||
|
||
if (ba.empty()) { | ||
m_ok = false; | ||
return; | ||
} else { | ||
m_ok = true; | ||
} | ||
|
||
// Define the number of guard cells in each direction, for E, B, and F | ||
// Define the number of guard cells in each di;rection, for E, B, and F | ||
auto nge = IntVect(AMREX_D_DECL(2, 2, 2)); | ||
auto ngb = IntVect(AMREX_D_DECL(2, 2, 2)); | ||
int ngf_int = 0; | ||
|
@@ -760,24 +776,28 @@ PML::PML (const int lev, const BoxArray& grid_ba, const DistributionMapping& gri | |
BoxArray grid_cba = grid_ba; | ||
grid_cba.coarsen(ref_ratio); | ||
|
||
// assuming that the bounding box around grid_cba is a single patch, and not disjoint patches, similar to fine patch. | ||
amrex::Box cdomain = grid_cba.minimalBox(); | ||
BoxArray grid_cba_reduced = grid_cba; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code below duplicates the above code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes. I ll do this in a separate PR |
||
if (do_pml_in_domain) { | ||
for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) { | ||
if (do_pml_Lo[idim]){ | ||
// ncell is divided by refinement ratio to ensure that the | ||
// physical width of the PML region is equal in fine and coarse patch | ||
cdomain.growLo(idim, -ncell/ref_ratio[idim]); | ||
} | ||
if (do_pml_Hi[idim]){ | ||
// ncell is divided by refinement ratio to ensure that the | ||
// physical width of the PML region is equal in fine and coarse patch | ||
cdomain.growHi(idim, -ncell/ref_ratio[idim]); | ||
BoxList bl = grid_cba.boxList(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we can use simplified_list as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. discussed offline, switched back to boxList due to failing CI |
||
for (auto& b : bl) { | ||
for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) { | ||
if (do_pml_Lo[idim]) { | ||
Box const& bb = amrex::adjCellLo(b, idim); | ||
if ( ! grid_cba.intersects(bb) ) { | ||
b.growLo(idim, -ncell/ref_ratio[idim]); | ||
} | ||
} | ||
if (do_pml_Hi[idim]) { | ||
Box const& bb = amrex::adjCellHi(b, idim); | ||
if ( ! grid_cba.intersects(bb) ) { | ||
b.growHi(idim, -ncell/ref_ratio[idim]); | ||
} | ||
} | ||
} | ||
} | ||
grid_cba_reduced = BoxArray(std::move(bl)); | ||
} | ||
const BoxArray grid_cba_reduced = (do_pml_in_domain) ? | ||
BoxArray(grid_cba.boxList().intersect(cdomain)) : grid_cba; | ||
Box const cdomain = grid_cba_reduced.minimalBox(); | ||
|
||
const IntVect cncells = IntVect(ncell)/ref_ratio; | ||
const IntVect cdelta = IntVect(delta)/ref_ratio; | ||
|
@@ -792,7 +812,6 @@ PML::PML (const int lev, const BoxArray& grid_ba, const DistributionMapping& gri | |
} else { | ||
cdm.define(cba); | ||
} | ||
|
||
const amrex::BoxArray cba_Ex = amrex::convert(cba, WarpX::GetInstance().getEfield_cp(1,0).ixType().toIntVect()); | ||
const amrex::BoxArray cba_Ey = amrex::convert(cba, WarpX::GetInstance().getEfield_cp(1,1).ixType().toIntVect()); | ||
const amrex::BoxArray cba_Ez = amrex::convert(cba, WarpX::GetInstance().getEfield_cp(1,2).ixType().toIntVect()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also use
simplified_list()
instead ofboxList
here. That way, it's less likely to hit the assert failure below.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you Weiqun for the suggestions!
Done