-
Notifications
You must be signed in to change notification settings - Fork 35
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
[Breaking Change] Make Mesh-Level Boundary Conditions Usable without "User" flag (now without bitrot) #1177
Conversation
Ping @pgrete, @brryan , @bprather and @adamdempsey90 you guys asked for this. Please review when you get the chance. :) |
@@ -1,4 +1,4 @@ | |||
.. _sphinx-doc: | |||
.. _boundary-conds: |
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 think this was an error. The hyperlink never should have been _sphinx_doc
A per-variable reflecting boundary condition is available, but you | ||
must register it manually. To do so, simply call | ||
``app_in->RegisterDefaultReflectingBoundaryConditions()`` and it | ||
will be available as a mesh boundary with the name ``reflecting``. | ||
The reason manual registration is required is to support custom | ||
reflecting boundary conditions in the case where a single variable | ||
is used as the state vector. |
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.
As requested by @pgrete in the prior MR.
forest_def.AddBC(edge_t({n[0], n[1]}), parthenon::BoundaryFlag::outflow); | ||
forest_def.AddBC(edge_t({n[0], n[3]}), parthenon::BoundaryFlag::outflow); | ||
forest_def.AddBC(edge_t({n[0], n[1]})); | ||
forest_def.AddBC(edge_t({n[0], n[3]})); |
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 default flag is now user which then uses the boundary function pointer selected in the input deck. Explicitly specifying the boundary flag is thus unnecessary.
pman.app_input->RegisterBoundaryCondition(BoundaryFace::inner_x1, | ||
parthenon::BoundaryFunction::OutflowInnerX1); | ||
pman.app_input->RegisterBoundaryCondition(BoundaryFace::outer_x1, | ||
parthenon::BoundaryFunction::OutflowOuterX1); | ||
pman.app_input->RegisterSwarmBoundaryCondition(BoundaryFace::inner_x1, | ||
SwarmUserInnerX1); | ||
pman.app_input->RegisterSwarmBoundaryCondition(BoundaryFace::outer_x1, | ||
SwarmUserOuterX1); |
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.
Because I don't specify a name, these get added as "user"
struct ApplicationInput { | ||
class ApplicationInput { |
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.
There's more private scope now, so this seemed like an appropriate change.
src/mesh/mesh.cpp
Outdated
mesh_bc_names = {pin->GetOrAddString("parthenon/mesh", "ix1_bc", "outflow"), | ||
pin->GetOrAddString("parthenon/mesh", "ox1_bc", "outflow"), | ||
pin->GetOrAddString("parthenon/mesh", "ix2_bc", "outflow"), | ||
pin->GetOrAddString("parthenon/mesh", "ox2_bc", "outflow"), | ||
pin->GetOrAddString("parthenon/mesh", "ix3_bc", "outflow"), | ||
pin->GetOrAddString("parthenon/mesh", "ox3_bc", "outflow")}; | ||
mesh_swarm_bc_names = { | ||
pin->GetOrAddString("parthenon/swarm", "ix1_bc", mesh_bc_names[0]), | ||
pin->GetOrAddString("parthenon/swarm", "ox1_bc", mesh_bc_names[1]), | ||
pin->GetOrAddString("parthenon/swarm", "ix2_bc", mesh_bc_names[2]), | ||
pin->GetOrAddString("parthenon/swarm", "ox2_bc", mesh_bc_names[3]), | ||
pin->GetOrAddString("parthenon/swarm", "ix3_bc", mesh_bc_names[4]), | ||
pin->GetOrAddString("parthenon/swarm", "ox3_bc", mesh_bc_names[5])}; |
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.
@brryan does this seem reasonable to you?
mesh_bcs = { | ||
GetBoundaryFlag(pin->GetOrAddString("parthenon/mesh", "ix1_bc", "reflecting")), | ||
GetBoundaryFlag(pin->GetOrAddString("parthenon/mesh", "ox1_bc", "reflecting")), | ||
GetBoundaryFlag(pin->GetOrAddString("parthenon/mesh", "ix2_bc", "reflecting")), | ||
GetBoundaryFlag(pin->GetOrAddString("parthenon/mesh", "ox2_bc", "reflecting")), | ||
GetBoundaryFlag(pin->GetOrAddString("parthenon/mesh", "ix3_bc", "reflecting")), | ||
GetBoundaryFlag(pin->GetOrAddString("parthenon/mesh", "ox3_bc", "reflecting"))}; | ||
SetBCNames_(pin); | ||
mesh_bcs = GetBCsFromNames_(mesh_bc_names); |
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 mesh_bcs
logic is repeated in the initializer list for each constructor. This is silly. I moved it to a standalone function.
and key != "BoundaryConditions" | ||
and key != "SwarmBoundaryConditions" |
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 safe to exclude from metadata checks becuase it was always unused by the infrastructure and this MR (dramatically) changes what this output looks like.
…pecify swarm BCs if you're not using swarms
auto maybe = [](const std::string &s) { | ||
return ((s == "outflow") || (s == "periodic")) ? s : "outflow"; | ||
}; | ||
mesh_swarm_bc_names = { |
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.
Cool. I think this API is more flexible when needing to specify different boundary conditions for fields vs swarms.
Just for my understanding, can you help me work through the scenario that I want to specify user defined boundary conditions that are unique for swarms and fields. I would do
parthenon/mesh/ix1_bc=custom_mesh_ix1
parthenon/swarm/ix1_bc=custom_swarm_ix1
with
pman.app_input->RegisterBoundaryCondition(parthenon::BoundaryFace::inner_x1, "custom_mesh_ix1", MyMeshBoundaryInnerX1);
pman.app_input->RegisterSwarmBoundaryCondition(parthenon::BoundaryFace::inner_x1, "custom_swarm_ix1", MySwarmBoundaryInnerX1);
or equivalently
parthenon/mesh/ix1_bc=user
with
pman.app_input->RegisterBoundaryCondition(parthenon::BoundaryFace::inner_x1, MyMeshBoundaryInnerX1);
pman.app_input->RegisterSwarmBoundaryCondition(parthenon::BoundaryFace::inner_x1, MySwarmBoundaryInnerX1);
is that right?
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.
Yep that's right!
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.
LGTM
NOTICE
This is my second attempt at #989 . The code has changed so much since my original implementation that it was easier to start from scratch rather than trying to merge with develop. Some notes:
API Breaking change
When registering user boundary functions, the mechanism changes from assigning the function pointer to an array. You now must call
ApplicationInput::RegisterBoundaryCondition
and give the custom boundary condition a name. This also eliminates the need for theuser
boundary flag in the input file, although that flag is implicitly still supported.PR Summary
A discussion on the new downstream code headed by @brryan @pdmullen indicated a desire to set mesh-level boundary conditions without using the
user
flag. Here I implement this feature. The changes I made are:ApplicationInput
now has a registration function where you register either a grid or particle boundary condition, with a function pointer (or a class in the case of swarm bounds) and a name.ApplicationInput
with the"reflecting"
name.BoundaryFlag
s are dramatically simplified, indicating (essentially) only whether or not boundaries are periodic.ApplicationInput
.The advantage of this is that you can now call (in your main function)
pman->app_input.RegisterBoundaryCondition(parthenon::BoundaryFace::inner_x1, "my_bc", &my_bc_func);
and then in the input file just use
I think the refactored code is also significantly cleaner and easier to read. Also I put a link to the parthenon paper in the readme.
PR Checklist