From: David A. <Dav...@in...> - 2010-09-29 20:27:54
Attachments:
m.C
|
Hi! I have a question regarding BoundaryInfo on inner edges. My situation is the following: 1) I generate a mesh: a 2x2 square (element numbers are 0..3, boundary ids are 0..3) 2) I refine the mesh once, so I get 16 more elements If I look at the original mesh, the element 0 (bottom left one) has a boundary id 0 on local edge 0 and boundary id 3 on local edge 3. Local edges 1 and 2 have -1234 (=invalid id). That is perfectly fine. However, there is something strange on the refined mesh. The element 4 (the very bottom left one - child of element 0) has the same info as its parent - that is still ok. But, if I look at the elements 5, 6, 7 which are the three remaining child elements of element 0, they do have the same boundary info like element 0, i.e. local edges 0 and 3 have the same boundary ids. I would expect that element 5 would have only boundary info associated with local edge 0, element 6 only with edge 3 and element 7 would not have this info at all since it is an interior element. In other words, the child elements inherit the boundary info from the parent element. Attached is simple code that shows this behavior. Maybe, I'm supposed to call something in order to get the proper boundary infos? Thank you, -- David Andrs |
From: Roy S. <roy...@ic...> - 2010-09-29 20:43:06
|
On Wed, 29 Sep 2010, David Andrs wrote: > However, there is something strange on the refined mesh. The element 4 > (the very bottom left one - child of element 0) has the same info as its > parent - that is still ok. But, if I look at the elements 5, 6, 7 which > are the three remaining child elements of element 0, they do have the same > boundary info like element 0, i.e. local edges 0 and 3 have the same > boundary ids. I would expect that element 5 would have only boundary info > associated with local edge 0, element 6 only with edge 3 and element 7 > would not have this info at all since it is an interior element. In other > words, the child elements inherit the boundary info from the parent > element. Not just inherits - specifically references. Check boundary_info.C, line 466. By using the top_parent() boundary info we never even have to duplicate the ids, which is nice. And it works for most apps, since we don't bother to check boundary ids until after checking that a neighbor is NULL (i.e. that we're actually on the domain boundary). A workaround for some types of internal boundaries is to use subdomain ids: i.e. if you're in subdomain 1 and your neighbor is in subdomain 3 then you apply whatever interface condition is associated with std::pair<>(1,3). If that workaround isn't sufficient for your case then we should talk about changing the API behavior. If internal boundary ids are all defined on the coarse mesh, then additional cases to handle that would be quick and easy. If you need to change boundary ids as you refine then life gets harder. --- Roy |
From: David A. <Dav...@in...> - 2010-09-29 21:31:52
|
Roy Stogner <roy...@ic...> wrote on 09/29/2010 02:42:58 PM: > > On Wed, 29 Sep 2010, David Andrs wrote: > > > However, there is something strange on the refined mesh. The element 4 > > (the very bottom left one - child of element 0) has the same info as its > > parent - that is still ok. But, if I look at the elements 5, 6, 7 which > > are the three remaining child elements of element 0, they do have the same > > boundary info like element 0, i.e. local edges 0 and 3 have the same > > boundary ids. I would expect that element 5 would have only boundary info > > associated with local edge 0, element 6 only with edge 3 and element 7 > > would not have this info at all since it is an interior element. In other > > words, the child elements inherit the boundary info from the parent > > element. > > Not just inherits - specifically references. Check boundary_info.C, > line 466. By using the top_parent() boundary info we never even have > to duplicate the ids, which is nice. > > And it works for most apps, since we don't bother to check boundary > ids until after checking that a neighbor is NULL (i.e. that we're > actually on the domain boundary). > I was not sure if this was an expected behavior or it was just me doing something wrong. However, I need that for internal boundaries as you mentioned below. > A workaround for some types of internal boundaries is to use subdomain > ids: i.e. if you're in subdomain 1 and your neighbor is in subdomain 3 > then you apply whatever interface condition is associated with > std::pair<>(1,3). Our boundary ids come as a sideset ids from exodus file. So as long I'm able to iterate over the sideset and figure out the neighboring subdomain id, this would be a way to go. > > If that workaround isn't sufficient for your case then we should talk > about changing the API behavior. If internal boundary ids are all > defined on the coarse mesh, then additional cases to handle that would > be quick and easy. If you need to change boundary ids as you refine > then life gets harder. So far, we do not need to change the boundary ids as we refine the mesh. One more thought: I'm not really familiar with libMesh internals, but as long as the local edge/face ids are preserved (I suspect they are, from what I saw so far), it should be possible to not copy the references for new internal edges that were created by the refinement and copy only the "outer" ones. Or not? Thank you, -- David Andrs > --- > Roy > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > Libmesh-users mailing list > Lib...@li... > https://lists.sourceforge.net/lists/listinfo/libmesh-users |
From: Roy S. <roy...@ic...> - 2010-09-29 21:51:38
|
On Wed, 29 Sep 2010, David Andrs wrote: > Roy Stogner <roy...@ic...> wrote on 09/29/2010 02:42:58 PM: > > > A workaround for some types of internal boundaries is to use subdomain > > ids: i.e. if you're in subdomain 1 and your neighbor is in subdomain 3 > > then you apply whatever interface condition is associated with > > std::pair<>(1,3). > > Our boundary ids come as a sideset ids from exodus file. So as long I'm able to iterate over the sideset and figure out the neighboring > subdomain id, this would be a way to go. Good to hear. But sounds like supporting internal boundary IDs would be more natural for your problem, though, no? > > If that workaround isn't sufficient for your case then we should talk > > about changing the API behavior. If internal boundary ids are all > > defined on the coarse mesh, then additional cases to handle that would > > be quick and easy. If you need to change boundary ids as you refine > > then life gets harder. > > So far, we do not need to change the boundary ids as we refine the mesh. In that case the solution's pretty easy: instead of calling top_parent(), we'd iterate ourselves until parent() is NULL, but give up and return invalid_id if is_child_on_side(which_child_am_i(..),..) is false first. Maybe optimize for the common case by just calling top_parent() if elem->side() is NULL. Looks like there'd be 4 functions which need changing in boundary_info.C. I'll look over the patch if you want to take a crack at it, otherwise I'll probably be able to code it up myself a few weeks from now, after our upcoming big deadline passes and after my stuff-to-postpone-until-after-deadline queue clears up. > One more thought: I'm not really familiar with libMesh internals, > but as long as the local edge/face ids are preserved (I suspect they > are, from what I saw so far) They are where possible; things get a little tricky for pyramids and tets. > it should be possible to not copy the references for new internal > edges that were created by the refinement and copy only the "outer" > ones. Or not? No copies at all necessary, not if we're still happy with boundary ids that don't change with refinement. Even in that latter case we could get away with just storing the changed ids and falling back on parent values when no changed id exists. On a somewhat-related note: if you're using internal boundary ids it's possible that you've got a somewhat larger ID set (and are querying it much more often) than most people. You might want to check and see if std::unordered_multimap gives you any better performance than std::multimap in the two containers in boundary_info.h. I suspect the differences will be trivial, but it couldn't hurt to have someone test and confirm that. --- Roy |
From: David A. <Dav...@in...> - 2010-09-30 15:53:53
|
Roy Stogner <roy...@ic...> wrote on 09/29/2010 03:51:25 PM: > > On Wed, 29 Sep 2010, David Andrs wrote: > > > Roy Stogner <roy...@ic...> wrote on 09/29/2010 02:42:58 PM: > > > > > A workaround for some types of internal boundaries is to use subdomain > > > ids: i.e. if you're in subdomain 1 and your neighbor is in subdomain 3 > > > then you apply whatever interface condition is associated with > > > std::pair<>(1,3). > > > > Our boundary ids come as a sideset ids from exodus file. So as > long I'm able to iterate over the sideset and figure out the neighboring > > subdomain id, this would be a way to go. > > Good to hear. But sounds like supporting internal boundary IDs would > be more natural for your problem, though, no? > > > > If that workaround isn't sufficient for your case then we should talk > > > about changing the API behavior. If internal boundary ids are all > > > defined on the coarse mesh, then additional cases to handle that would > > > be quick and easy. If you need to change boundary ids as you refine > > > then life gets harder. > > > > So far, we do not need to change the boundary ids as we refine the mesh. > > In that case the solution's pretty easy: instead of calling > top_parent(), we'd iterate ourselves until parent() is NULL, but give > up and return invalid_id if is_child_on_side(which_child_am_i(..),..) > is false first. Maybe optimize for the common case by just calling > top_parent() if elem->side() is NULL. > > Looks like there'd be 4 functions which need changing in > boundary_info.C. I'll look over the patch if you want to take a crack > at it, otherwise I'll probably be able to code it up myself a few > weeks from now, after our upcoming big deadline passes and after my > stuff-to-postpone-until-after-deadline queue clears up. > Attached is the patch that does it for boundary_id() and boundary_ids(). If you could check that I understood you correctly... I also tried that with my little test code that I sent earlier and it seems to work (I tried 1 and 2 levels of refinements) What are the other 2 functions that need this fix? > > One more thought: I'm not really familiar with libMesh internals, > > but as long as the local edge/face ids are preserved (I suspect they > > are, from what I saw so far) > > They are where possible; things get a little tricky for pyramids and > tets. > > > it should be possible to not copy the references for new internal > > edges that were created by the refinement and copy only the "outer" > > ones. Or not? > > No copies at all necessary, not if we're still happy with boundary ids > that don't change with refinement. Even in that latter case we could > get away with just storing the changed ids and falling back on parent > values when no changed id exists. > > On a somewhat-related note: if you're using internal boundary ids it's > possible that you've got a somewhat larger ID set (and are querying it > much more often) than most people. You might want to check and see if Right now we have only one inner boundary, so the ID set is not that much bigger. Maybe later we get to something bigger. > std::unordered_multimap gives you any better performance than > std::multimap in the two containers in boundary_info.h. I suspect the > differences will be trivial, but it couldn't hurt to have someone test > and confirm that. > --- > Roy -- David Andrs |
From: David A. <Dav...@in...> - 2010-09-30 16:03:54
|
Sorry, I forgot the attachment. -- David David Andrs <Dav...@in...> wrote on 09/30/2010 09:53:33 AM: > Roy Stogner <roy...@ic...> wrote on 09/29/2010 03:51:25 PM: > > > > > On Wed, 29 Sep 2010, David Andrs wrote: > > > > > Roy Stogner <roy...@ic...> wrote on 09/29/2010 02:42:58 > PM: > > > > > > > A workaround for some types of internal boundaries is to use > subdomain > > > > ids: i.e. if you're in subdomain 1 and your neighbor is in subdomain > 3 > > > > then you apply whatever interface condition is associated with > > > > std::pair<>(1,3). > > > > > > Our boundary ids come as a sideset ids from exodus file. So as > > long I'm able to iterate over the sideset and figure out the neighboring > > > subdomain id, this would be a way to go. > > > > Good to hear. But sounds like supporting internal boundary IDs would > > be more natural for your problem, though, no? > > > > > > If that workaround isn't sufficient for your case then we should > talk > > > > about changing the API behavior. If internal boundary ids are all > > > > defined on the coarse mesh, then additional cases to handle that > would > > > > be quick and easy. If you need to change boundary ids as you refine > > > > then life gets harder. > > > > > > So far, we do not need to change the boundary ids as we refine the > mesh. > > > > In that case the solution's pretty easy: instead of calling > > top_parent(), we'd iterate ourselves until parent() is NULL, but give > > up and return invalid_id if is_child_on_side(which_child_am_i(..),..) > > is false first. Maybe optimize for the common case by just calling > > top_parent() if elem->side() is NULL. > > > > Looks like there'd be 4 functions which need changing in > > boundary_info.C. I'll look over the patch if you want to take a crack > > at it, otherwise I'll probably be able to code it up myself a few > > weeks from now, after our upcoming big deadline passes and after my > > stuff-to-postpone-until-after-deadline queue clears up. > > > > Attached is the patch that does it for boundary_id() and boundary_ids(). > If you could check that I understood you correctly... > I also tried that with my little test code that I sent earlier and it > seems to work (I tried 1 and 2 levels of refinements) > > What are the other 2 functions that need this fix? > > > > One more thought: I'm not really familiar with libMesh internals, > > > but as long as the local edge/face ids are preserved (I suspect they > > > are, from what I saw so far) > > > > They are where possible; things get a little tricky for pyramids and > > tets. > > > > > it should be possible to not copy the references for new internal > > > edges that were created by the refinement and copy only the "outer" > > > ones. Or not? > > > > No copies at all necessary, not if we're still happy with boundary ids > > that don't change with refinement. Even in that latter case we could > > get away with just storing the changed ids and falling back on parent > > values when no changed id exists. > > > > On a somewhat-related note: if you're using internal boundary ids it's > > possible that you've got a somewhat larger ID set (and are querying it > > much more often) than most people. You might want to check and see if > > Right now we have only one inner boundary, so the ID set is not that much > bigger. Maybe later we get to something bigger. > > > std::unordered_multimap gives you any better performance than > > std::multimap in the two containers in boundary_info.h. I suspect the > > differences will be trivial, but it couldn't hurt to have someone test > > and confirm that. > > > --- > > Roy > > -- > David Andrs > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > Libmesh-users mailing list > Lib...@li... > https://lists.sourceforge.net/lists/listinfo/libmesh-users |
From: Roy S. <roy...@ic...> - 2010-09-30 17:29:50
|
On Thu, 30 Sep 2010, David Andrs wrote: > Attached is the patch that does it for boundary_id() and > boundary_ids(). If you could check that I understood you > correctly... Exactly, thanks. > I also tried that with my little test code that I sent earlier and > it seems to work (I tried 1 and 2 levels of refinements) Okay; I'll test it on my own codes, but it should be safe to commit. > What are the other 2 functions that need this fix? My mistake - only one other function needs it, BoundaryInfo::side_with_boundary_id() --- Roy |
From: David A. <Dav...@in...> - 2010-09-30 21:45:19
|
Roy Stogner <roy...@ic...> wrote on 09/30/2010 11:29:39 AM: > > On Thu, 30 Sep 2010, David Andrs wrote: > > > Attached is the patch that does it for boundary_id() and > > boundary_ids(). If you could check that I understood you > > correctly... > > Exactly, thanks. > > > I also tried that with my little test code that I sent earlier and > > it seems to work (I tried 1 and 2 levels of refinements) > > Okay; I'll test it on my own codes, but it should be safe to commit. > > > What are the other 2 functions that need this fix? > > My mistake - only one other function needs it, > BoundaryInfo::side_with_boundary_id() I looked at this function, but I cannot use the same approach as for boundary_id(). This one is using _boundary_side_id mapping of elem -> (side, bnd_id). However, when I refine the mesh, there are no additional entries for newly created elements like for nodal ones in _boudary_node_id (unless I'm supposed to call something in order to get it, but I doubt that, since add_side has an assert for elem->level() == 0). With these new entries, side_with_boundary_id() should work with one little modification. Thus, the fix would have to change adding and removing sides, where I could use the above-mentioned approach. Or is there another way how to achieve this? -- David Andrs > --- > Roy > > ------------------------------------------------------------------------------ > Start uncovering the many advantages of virtual appliances > and start using them to simplify application deployment and > accelerate your shift to cloud computing. > http://p.sf.net/sfu/novell-sfdev2dev > _______________________________________________ > Libmesh-users mailing list > Lib...@li... > https://lists.sourceforge.net/lists/listinfo/libmesh-users |
From: Roy S. <roy...@ic...> - 2010-09-30 22:42:08
|
On Thu, 30 Sep 2010, David Andrs wrote: > Roy Stogner <roy...@ic...> wrote on 09/30/2010 11:29:39 AM: > > > My mistake - only one other function needs it, > > BoundaryInfo::side_with_boundary_id() > > I looked at this function, but I cannot use the same approach as for > boundary_id(). This one is using _boundary_side_id mapping of elem > -> (side, bnd_id). However, when I refine the mesh, there are no > additional entries for newly created elements like for nodal ones in > _boudary_node_id (unless I'm supposed to call something in order to > get it, but I doubt that, since add_side has an assert for > elem->level() == 0). With these new entries, side_with_boundary_id() > should work with one little modification. Thus, the fix would have > to change adding and removing sides, where I could use the > above-mentioned approach. > > Or is there another way how to achieve this? This is trickier, yes, but I think the most efficient way to handle it would be to leave boundary ids defined on top level elements, and just add some checks before "return e.first->second.first;" (who says C++ isn't intuitive!) Something like the attached (untested!) patch. --- Roy |
From: David A. <Dav...@in...> - 2010-10-01 14:30:44
|
Roy Stogner <roy...@ic...> wrote on 09/30/2010 04:42:01 PM: > > On Thu, 30 Sep 2010, David Andrs wrote: > > > Roy Stogner <roy...@ic...> wrote on 09/30/2010 11:29:39 AM: > > > > > My mistake - only one other function needs it, > > > BoundaryInfo::side_with_boundary_id() > > > > I looked at this function, but I cannot use the same approach as for > > boundary_id(). This one is using _boundary_side_id mapping of elem > > -> (side, bnd_id). However, when I refine the mesh, there are no > > additional entries for newly created elements like for nodal ones in > > _boudary_node_id (unless I'm supposed to call something in order to > > get it, but I doubt that, since add_side has an assert for > > elem->level() == 0). With these new entries, side_with_boundary_id() > > should work with one little modification. Thus, the fix would have > > to change adding and removing sides, where I could use the > > above-mentioned approach. > > > > Or is there another way how to achieve this? > > This is trickier, yes, but I think the most efficient way to handle it > would be to leave boundary ids defined on top level elements, and just > add some checks before "return e.first->second.first;" (who says C++ > isn't intuitive!) > > Something like the attached (untested!) patch. I tested that on my simple test case (mesh with 1 and 2 levels of refinements) and it works. So if it is ok, I'd commit the whole thing. > --- > Roy[attachment "bdy_side.diff" deleted by David Andrs/ANDRSD/FN/INEEL/US] Thanks for all your help, -- David Andrs |
From: Roy S. <roy...@ic...> - 2010-10-01 15:55:06
|
On Fri, 1 Oct 2010, David Andrs wrote: > I tested that on my simple test case (mesh with 1 and 2 levels of > refinements) and it works. So if it is ok, I'd commit the whole > thing. Sounds good; thanks! --- Roy |