-
Notifications
You must be signed in to change notification settings - Fork 707
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
Added GridTools::get_subdomain_association(Tria, CellId). #11366
Conversation
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 would like to create a map of cells which live on different triangulations that may be partitioned differently. This function will be used to determine sending and receiving processes for data transfer between those cells. To be more specific, between cells on a volume and a surface mesh. |
In this case, I add a |
The p4est case is actually quite cheap. You're creating the The point of the function (which should probably be mentioned in its documentation) is that with the function one can also ask for the owner of cells identified by |
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, but it needs to be re-based once #11364 is merged.
@peterrum We need this kind of functionality and it's cheap to query for p::d::T
without communication. At some point we probably want this to also work with p::f::T
. Are you ok with merging this (once rebased)? Do you have an idea how at some point one would implement this also for p::f::T
?
I had a look at the implementation of the p4est function (https://github.com/cburstedde/p4est/blob/ea25d0221dce486dc40ea224a394b06c9f016a6b/src/p4est_communication.c#L675-L742). Apparently, they save the global start point of each process on each process. Via binary search they can find the rank of a cell. This only works because they exploit the structure of a space-filling curve. This is not something we can do in the case other partitioning approaches like done in Furthermore, I am not happy with As a consequence, I would rather suggest to have a function with the following interface: namespace GridTools
{
template<int dim, int spacedim>
std::vector<unsigned int>
get_owning_subdomain_for_cells(const Triangulation<dim, spacedim>& tria,
const std::vector<CellId> &cell_id);
} where one could batch the query. For p:d:T, the function would use the implementation as suggested in this PR. For p:f:T, there would be no implementation for now. For p:s:T, the artificial cells would be removed as a preparation. Furthermore, the documentation could say that it is highly recommended not to call this function for a single cell.
As stated above, I am not happy with this PR in the current state. But I won't block. |
@marcfehling originally had the function externally, but it clearly requires internal knowledge of the triangulation in question to work -- so he moved it into the triangulation class, which I believe is the right place for it to be. I'd be ok with changing the interface so that it take a whole vector of |
That would be better. But, I am still not convinced that the serial |
I would second this point - this is a very specific use case that seems to break with our previous tradition of keeping features genuine to a parallel/distributed triangulation out of the base class. To give an example, the much more widely used function |
I am happy to accept a PR that adds this. |
Let's not hold this PR up because we've made design mistakes in other contexts :-) I'm not quite sure what the alternative to the function here would be, though. Would you want to introduce it as a virtual function Maybe it's worthwhile explaining where we want to use this function: We'd like to write something of the sort
The returned object of type The point is that it would be quite nice if we could set all of this up in some sort of generic way. Being able to query the owner of a cell identified by |
a4a9333
to
cdd238e
Compare
Thanks for sharing the application background, this makes the discussion easier, even though I have to admit I could probably have extracted that from #11366 (comment) already. What I think @peterrum is concerned about is the generality of this approach, and alternatives on a higher level, not on where to place this function. Given dealii/include/deal.II/grid/tria_accessor.h Lines 3485 to 3486 in 97bbe3d
ConsensusAlgorithm , one can identify this information for any kind of triangulation. One merely needs an intermediate step with bounding boxes to do it in a fully unstructured way for cases where p4est cannot help in terms of a complicated coarse grid. As a matter of fact, we have done something very similar to the coupling between a volume and surface mesh for a fluid-structure-interaction application with non-matching grids along the fluid-structure interface already, coded mostly by @peterrum regarding the communication aspect, as a result of many discussions with me and @nfehn. So I would really like to join the efforts here and aim to insert the most general approach in the library. Or a small set of different variants, in case it turns out the flexible setup were not as suited in terms of HPC for example (I am not suggesting the two are in conflict at this stage, just a random example). For this, we would need to define what exactly the surface mesh and volume mesh set as requirements and how we would like the communication pattern to look like. I could not find that specification in #10037 so I suggest we take that effort now to save a lot of work down the road.
|
I do not have a general opinion on where to add this function. @bangerth's point to make it a class member is that we need access to internal data structures. While this is true, we can also get access to those via getter functions that are already implemented (most probably). His other argument to make it a member of the There are enough arguments for and against it. As far as I can tell, we allow the I do however have an opinion on the generality of this approach. For every different Triangulation type in the However, the interface for all functions should look the same. @peterrum suggested to supply a container of Since the What do you think? |
@kronbichler We continue to not make progress and are holding up @marcfehling :-( I understand that if you have non-matching grids, that one needs a more general algorithm that will involve bounding boxes. But we're not interested in this, and in fact have much more information available than just a general cell's location: The What is your objection to having a function
in the interface of |
I have gone through all the comments of this PR, but I have to admit that it is really difficult to extract the problem description. @bangerth, you argued that you prefer simpler algorithms than some generic routines: What I did not understand so far is where you get the relevant information from to construct the maps if the routines are not "fully generic"? How does the part of your algorithm look like that cares about geometry, location, neighborhood? @bangerth You have also motivated this PR from the point of view of complexities. For me, complexity is only part of the problem, because identifying and removing bottlenecks (talking about absolute runtimes) is more important. It would be helpful to get insights why you have concerns that a generic algorithm will not satisfy your needs. In my opinion one should first argue or give evidence that the generic routines suggested by @kronbichler form a bottleneck relative to other grid/triangulation functions that one has to do anyway, because two different functions (which are again specialized for all the dealii::triangulations if I understood the discussion correctly) is something that one would like to avoid from a code design, maintenance, documentation, usability perspective. I wonder a bit why the opinions are so divided regarding this question. Isn't the discussion also stuck because the topic is so difficult that one always has to think about the different Triangulation types, that p4est is part of this discussion, etc.? In my opinion, this should be a clear hint to rethink the design. |
Sorry for the delay. The main problem I see with this algorithm is that it only realistically works with two types of triangulations, the serial one (where you do not need it) and for the As always, I do not feel that strongly that I would straight out oppose to this PR and the last thing I would want to do is block your progress, but I wanted to raise a flag that a different interface might be preferable in terms of later extensions. That said, we would still need to discuss the different requirements on coupling algorithms and as things look like we won't find a one-way-fits-all solution at least in the short run, so a |
I think one of the problems related to this discussion is that we do not have the entire solution for coupling bulk and surface processes in front of us, and still work towards the final picture. I would thus suggest to place this function in the If we decide that we do not need this function, we could simply scrap it later on. If we have a plan how to acquire this information on many or all types of Triangulation classes, we can still turn it into a member function and deprecate the free function. I will adjust this PR accordingly. |
e570eb3
to
75253db
Compare
/rebuild |
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.
Looks good. Just a few minor points.
// the most general type of triangulation is the serial one. here, all | ||
// subdomain information is directly available | ||
for (const auto &cell_id : cell_ids) | ||
{ | ||
subdomain_ids.push_back( | ||
triangulation.create_cell_iterator(cell_id)->subdomain_id()); | ||
} |
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 most general type of triangulation is the serial one. here, all | |
// subdomain information is directly available | |
for (const auto &cell_id : cell_ids) | |
{ | |
subdomain_ids.push_back( | |
triangulation.create_cell_iterator(cell_id)->subdomain_id()); | |
} | |
return std::vector<types::subdomain_id>(cell_ids.size(), 0); |
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 would leave this as is.
If, at some point, we decide to handle the subdomain_id
for serial triangulations differently (e.g., choose invalid_subdomain_id
instead of 0
), we need to remember to also change it here.
If there are no further objections, I will squash all commits and release this PR from its draft state. |
Sounds good! Thanks! |
b764b4e
to
b90f1a9
Compare
I've squashed all commits. Two comments on the current state:
|
ping |
As far as I can see, all comments have been addressed. I'll merge. :) |
Blocked by #11364 and #11365.
The function returns the subdomain of a cell represented by a
CellId
on aparallel::distributed::Triangulation
. We ask thep4est
oracle for the corresponding owner.For all other triangulation types, we simply request the subdomain id of a cell iterator object created on the local object from a
CellId
. @peterrum -- This works for fullydistributed too, right?I still need to come up with a meaningful test for the new functionality, which is why I open this as a draft. But I would already welcome your thoughts and opinions!