-
Notifications
You must be signed in to change notification settings - Fork 198
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
Modify stair-case approximation to the EB #5534
base: development
Are you sure you want to change the base?
Conversation
3a60ef0
to
3181d45
Compare
…to move_stair_case_approx
This reverts commit 4fd4dc7.
@@ -174,6 +174,14 @@ WarpX::RemakeLevel (int lev, Real /*time*/, const BoxArray& ba, const Distributi | |||
using ablastr::fields::Direction; | |||
using warpx::fields::FieldType; | |||
|
|||
const auto RemakeMultiFab = [&](auto& mf){ |
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.
This reintroduces a function that we removed when introducing the MultiFabRegister
(#5230).
It could be removed once we introduce an iMultiFabRegister
.
|
||
void | ||
WarpX::MarkCells () | ||
WarpX::MarkExtensionCells () |
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.
This function was renamed to avoid confusion with the other Mark...
function.
#endif | ||
|
||
// Skip field push in the embedded boundaries | ||
if (update_Ey_arr && update_Ey_arr(i, j, k) == 0) { return; } |
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.
The if
condition here is now more simple, since the logic that determines whether a cell should be updated has been moved to the function that initializes the update_E
flag.
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.
This looks good to me. I was wondering, though, did you by any chance try running the CI tests using the new m_eb_update_E
functionality but before moving the staircase approximation? That should be a really clean way to check that there are no hard to see bugs introduced in this PR, since all the CI tests should then pass with their original checksum values.
"Ez": 68412803445328.25 | ||
"Bx": 144495.08082507108, | ||
"By": 144495.08082507114, | ||
"Bz": 8481.958724628861, |
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.
This change is quite big (more than 2x). Do you understand why this component had such a dramatic change?
I guess the Bz value is small compared to the others so this is probably fine.
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.
Hm, yes, it is somewhat large. My guess is that this is because this PR changes the actual position of the EB for this test.
// Stair-case approximation: If neighboring cells are either partially | ||
// or fully covered: do not update field |
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.
If I'm understanding the logic here correctly, eb_flag
is defined on the cell centers and returns false
for isRegular()
if any part of the cell is touched by the EB. The reason you have to check the cell below the current one when dealing with a nodal MF is because for the same index, nodal MFs are offset by half a cell downward from the cell centered MF. I think it might be worth adding a bit more explanation in the comment to make it easier for future readers to understand why it is only necessary to check the index offset by -1 (but never +1).
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.
Yes, that's correct. I added more comments ; could you check if that's clearer now?
lev, PatchType::fine, | ||
warpx.GetEBUpdateEFlag()); |
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.
This is a slight problem in that there will be an inconsistency in the hybrid solver until the follow-up PR is merged that also updates the field update for the hybrid solver. I guess we should just be sure to have both PRs merge in quick succession.
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.
Sounds good.
I finalized the hybrid PR #5558 and the tests pass on that PR, so it is ready to be merged soon after this one.
@@ -1155,7 +1157,7 @@ WarpX::MacroscopicEvolveE (int lev, PatchType patch_type, amrex::Real a_dt, amre | |||
m_fields.get_alldirs(FieldType::Efield_fp, lev), | |||
m_fields.get_alldirs(FieldType::Bfield_fp, lev), | |||
m_fields.get_alldirs(FieldType::current_fp, lev), | |||
m_fields.get_alldirs(FieldType::edge_lengths, lev), | |||
m_eb_update_E[lev], |
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.
I'm assuming the plan is to replace these arguments once iMultiFabRegister
is introduced?
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.
Yes, I agree.
@@ -976,23 +976,21 @@ WarpX::InitLevelData (int lev, Real /*time*/) | |||
// The default maxlevel_extEMfield_init value is the total number of levels in the simulation | |||
if ((m_p_ext_field_params->B_ext_grid_type == ExternalFieldType::parse_ext_grid_function) | |||
&& (lev > 0) && (lev <= maxlevel_extEMfield_init)) { | |||
|
|||
// TODO: raise error when EB is activated |
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.
Why is this comment here? Why should an error be raised when EB is activated?
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.
This is because I realized that the code is probably incorrect when using MR with the EM solver (i.e. when we use the cp
version of the fields).
This is because we should also have cp
and fp
versions of the arrays eb_update_E
/ eb_update_B
.
That being said, the problem already existed before this PR. (i.e. we should have had cp
and fp
version of edge_length
and face_area
).
For now, I cleaned up this comment and will instead open an issue with more explanation.
#ifdef AMREX_USE_EB | ||
#ifdef WARPX_DIM_3D | ||
if(lx && ((topology=='e' and lx(i, j, k)<=0) or (topology=='f' and Sx(i, j, k)<=0))) { return; } | ||
#elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ) | ||
//In XZ and RZ Ex is associated with a x-edge, while Bx is associated with a z-edge | ||
if(lx && ((topology=='e' and lx(i, j, k)<=0) or (topology=='f' and lz(i, j, k)<=0))) { return; } | ||
#endif | ||
#endif |
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.
This is a great simplification! 🎉
bc10261
to
16ec9b2
Compare
That's a good point! I have done this in this PR: #5574
The checksum tests indeed pass for #5574. |
Overview
This PR changes the definition of the stair-case approximation of the EB (used in the Yee solver), so that the actual EB boundary (where e.g. particles are removed from the simulation) is inside the stair-case-approximated boundary - as opposed to the definition used in the current
development
branch, for which the actual EB is outside the stair-case-approximated boundary.This ensures that the algorithm remains charge conserving, when charged particles are absorbed or emitted by the embedded boundary, for particle shape of order 1. (Higher-order particle shapes will be addressed in #5209.) As illustrated in the figure below (and as discussed in this paper), this is fundamentally because the particle does not deposit any charge in the valid cells, at the time when it is removed/emitted.
(The black crosses show the locations where the electric field is not updated, and thus usually remains equal to 0. The red dots show the locations where the particle deposits charge, for particle shape of order 1.)
The better behavior with respect to charge-conservation can be observed in the following animations, which show two particles of opposing charge separating and going into the embedded boundary. (Note that a static error in
divE
remains at the position where the particle was absorbed, with thedevelopment
branch. The propagating errors indivE
are expected: they are due to electromagnetic waves reflecting on the EB.)development branch
this PR
Input script: inputs.txt
Analysis script: openPMD-visualization.ipynb.txt
(An automated tests using a similar configuration has been added in a separate, follow-up PR: #5562)
Note that, as part of this PR, the above new definition has been adopted for all the finite-difference solvers, except for the ECT solver (which uses a cut-cell representation instead of a stair-case representation).
Implementation
When updating
E
(and when initializing the field values forE
andB
with a parser), we used to check somewhat complicated conditions that relied on theMultiFabs
edge_lengths
andface_areas
.This PR now introduces separate arrays (
m_eb_update_E
andm_eb_update_B
, which areiMultiFab
instead ofMultiFab
and thus take up much less memory). These arrays contain flags that keep track of where to udpate the fields (i.e. the black crosses in the above figure). These arrays are initialized in separate function (MarkUpdateECellsECT
andMarkUpdateBCellsECT
for the ECT sover - which preserve the previous behavior of the embedded boundary for this solver ;MarkUpdateCellsStairCase
for the other FDTD solvers - which introduce the above-mentioned new stair-case definition). The code for the field pusher and field initialization uses these arrays (instead ofedge_lengths
andface_areas
). It is thus significantly simpler and avoids duplicating complicatedif
conditions.The above changes have not yet been implemented for the hybrid solver. This will instead be done in a separate PR: #5558. Once this is complete, the
MultiFab
edge_lengths
andface_areas
will not be needed anymore (except for the ECT solver), and we will thus only allocate them for the ECT solver. This should save a significant amount of memory.