idaholab / moose

Multiphysics Object Oriented Simulation Environment
https://www.mooseframework.org
GNU Lesser General Public License v2.1
1.77k stars 1.05k forks source link

BoundaryMarker #11643

Closed friedmud closed 3 weeks ago

friedmud commented 6 years ago

Rationale

We really need the ability to mark along boundaries for refinement/coarsening.

Description

See above

Impact

None - new capability

shoheiogawa commented 6 years ago

The implementation at first was not right. I fixed it so I edit the comments below.

This issue is related to this thread in the mailing list.

I implemented something that works.

moose/framework/include/markers/BoundaryMarker.h

moose/framework/src/markers/BoundaryMarker.C

moose/test/tests/markers/boundary_marker/boundary_marker_test.i

In this input file, the marker is working only on the right block. moose/test/tests/markers/boundary_marker/refine_center.i

The program finds elements near selected boundaries within a certain number of elements from the boundaries. The range of the refinement is specified with a parameter range.

To detect one element is close to the boundary, I find if one of the nodes of the element is on the boundaries. If range is more than 1, this algorithm is recursively applied starting from each element in the block. I think the order of computation amount is 4^range for tetrahedron element case, so it could be very slow if you set range high.

Also, the algorithm didn't work if I override the markerSetup function to get latest boundary information when the marker works. In this case, I didn't find any elements refined.

void
BoundaryMarker::markerSetup()
{
  // updating the boundary info everytime this marker works.
  Marker::markerSetup(); 
  _boundary_info = _mesh.getMesh().get_boundary_info();
}

Initial marker computation: init

Refinement 1: refine1

Refinement 2: refine2

permcody commented 6 years ago

This is a good start. However, there are a few improvements that could be made to improve the current implementation. First, MooseMesh contains methods that will just give you the elements/nodes along boundaries so you don't have to figure that out yourself.

I'm really puzzled about the boundary_info problem in MarkerSetup. That really shouldn't matter at all. We'll need to get to the bottom of that.

On Thu, Jun 28, 2018 at 3:05 PM Shohei Ogawa notifications@github.com wrote:

This issue is related to this thread https://groups.google.com/forum/#!searchin/moose-users/refinement%7Csort:date/moose-users/-dBXgfO0zxI/ADGtmekGAgAJ in the mailing list.

I implemented something that works. BoundaryMarker.h https://github.com/shoheiogawa/moose/blob/ff0d98d9800cb588a48487cea6ae136550b5ea05/framework/include/markers/BoundaryMarker.h BoundaryMarker.C https://github.com/shoheiogawa/moose/blob/ff0d98d9800cb588a48487cea6ae136550b5ea05/framework/src/markers/BoundaryMarker.C boundary_marker_test.i https://github.com/shoheiogawa/moose/blob/ff0d98d9800cb588a48487cea6ae136550b5ea05/test/tests/markers/boundary_marker/boundary_marker_test.i

The program finds elements near selected boundaries within a certain number of elements from the boundaries. The range of the refinement is specified with a parameter range.

To detect one element is close to the boundary, I find if one of the nodes of the element is on the boundaries. If range is more than 1, this algorithm is recursively applied starting from each element in the block. I think the order of computation amount is 4^range for tetrahedron element case, so it could be very slow if you set range high.

Also, the algorithm didn't work if I overriede the markerSetup function to get latest boundary information when the marker works. In this case, I didn't find any elements refined.

voidBoundaryMarker::markerSetup() { // updating the boundary info everytime this marker works. Marker::markerSetup(); _boundary_info = _mesh.getMesh().get_boundary_info(); }

Initial marker computation: [image: init] https://user-images.githubusercontent.com/15840886/42059885-e8aeb39e-7af2-11e8-990c-f585abdf29b6.png

Refinement 1: [image: refine1] https://user-images.githubusercontent.com/15840886/42059890-ec378568-7af2-11e8-919e-f80b06b359b3.png

Refinement 2: [image: refine2] https://user-images.githubusercontent.com/15840886/42059894-eed88d9e-7af2-11e8-9451-77f9a3253d34.png

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/idaholab/moose/issues/11643#issuecomment-401173177, or mute the thread https://github.com/notifications/unsubscribe-auth/AC5XICM25RezX1Cj93cRS1E-fIRPdI-6ks5uBUUhgaJpZM4Uc4Z5 .

permcody commented 6 years ago

I wouldn't be too concerned about the recursive growth. Normally you could solve that problem by building up each layer so that you don't need to recurse, however since you don't have control over the loop and worse, these loops are executed in a threaded manner, it's pretty difficult to get a thread-safe data structure built up so your implementation is fine unless somebody does something really crazy. My only comment is that I prefer the parameter: depth over range but I'm fine with either.

shoheiogawa commented 6 years ago

I am trying to use

isBoundaryElem (dof_id_type elem_id, BoundaryID bnd_id) const

in MooseMesh. However, I am not sure how to get the element ID from the pointer to the element. After I searched for documents, it seems that there is not a getter function to get _id in libMesh::Elem.

How could I get element IDs?

friedmud commented 6 years ago

elem->id()

Derek

On Fri, Jun 29, 2018 at 1:00 PM Shohei Ogawa notifications@github.com wrote:

I am trying to use

isBoundaryElem (dof_id_type elem_id, BoundaryID bnd_id) const

in MooseMesh. However, I am not sure how to get the element ID from the pointer to the element. After I searched for documents, it seems that there is not a getter function to get _id in libMesh::Elem.

How could I get element IDs?

— You are receiving this because you authored the thread.

Reply to this email directly, view it on GitHub https://github.com/idaholab/moose/issues/11643#issuecomment-401444639, or mute the thread https://github.com/notifications/unsubscribe-auth/AA1JMfqzXU3uXMLjI3ziM056nWw6Eoafks5uBnlfgaJpZM4Uc4Z5 .

shoheiogawa commented 6 years ago

I was able to use the function. I have a question. Does

isBoundaryElem (dof_id_type elem_id, BoundaryID bnd_id) const

returns true only if elements supplied are on a master block of a sideset?

I have a site set between two blocks created SideSetsBetweenSubdomains.

BoundaryMarker with isBoundaryElem works in only one of the two blocks.

shoheiogawa commented 6 years ago

Also, if isBoundaryElem returns true only when one of the faces is shared by the element and a boundary, it would be better to check if nodes are on the boundary instead. I am not sure about this. The document of the function says,

Returns true if the requested element is in the list of boundary elements for the specified boundary, false otherwise.

The node search is better when we have a triangle or tetrahedral mesh in particular.

In that case, I can do something like below.

if (_mesh.isBoundaryNode(elem->get_node(node)->id(), boundary_id))
permcody commented 6 years ago

Let's make sure we get our terminology straight. "Boundary" really does mean an "edge" in your domain where there is no more mesh connected to elements. "Internal side" would be the complement to boundary. "Side" can mean either "boundary" or "internal side". With that in mind, you may want to name the marker you are creating appropriately.

I can see your point about sides versus nodes when dealing with tets versus something like quads when marking elements near a boundary. These are all design decisions. In MOOSE we like to try to support multiple algorithms that can be selected via a parameter. I'd say either is fine as long as it's documented and clear about what happens.

shoheiogawa commented 6 years ago

So you mean something like "SideSetNeighborMarker" is better naming?

My priority is "node search" rather than "face search" but I can implement the two methods at the same time and add a parameter so that users can choose one of them.

permcody commented 6 years ago

Maybe just SideNeighborMarker

You don't necessarily have to implement face search if you aren't going to use it. Just start with what you need for now and if somebody wants the other version, we can easily implement it. I'd rather not have unused features floating around in the framework.

friedmud commented 6 years ago

This shouldn't work off of nodes - it should work off of sidesets. Nodesets and adaptivity don't go together perfectly (how do new nodes know they should be in the nodeset or not? There are several corner cases).

SideSetMarker would be my suggestion.

shoheiogawa commented 6 years ago

@friedmud Using isBoundaryNode function, I can find if nodes are on a certain boundary, i.e sideset. I think that I am not using a nodeset here. Don't Moose or Libmesh add new nodes of refined elements to the node list of the boundaries?

There are pro and cons using isBoundaryNode and isBoundaryElem When I use isBoundaryNode, the refinement is not perfect, but it works for most of the elements, e.g. some elements are not refined when I refine several times near the boundary.

When I use isBoundaryElem, it seems that element refinement is done only one of the blocks next to each other. As the elements in the one block are refined iteratively, elements on the other side are refined as well. This could be a problem if you specify the slave block to refine. In this case, no refinement happens at all.

Maybe the work around here is using both, or implement both so that users can choose either one.

permcody commented 6 years ago

Don't Moose or Libmesh add new nodes of refined elements to the node list of the boundaries?

No, How would libMesh know which nodes to add? Nodesets can be arbitrary nodes (in the volume, on the surface, etc). They are very flexible. Sidesets however are much easier to deal with when refining. If a node is placed on a given surface it's automatically part of that sideset.

I'm not sure what's going on with the rest of your comment there. It's possible that the implementation isn't correct. MOOSE existed for a long time with only boundaries and sidesets appearing on the edge of the domain. Later, we started supporting interior sidesets and nodesets. Some of the older APIs require updates to make them work on the exterior and interior. I'm not sure if that's what's going on here or not, but in any case, we should design the new code correctly instead of using a hack. If you don't have time to look at it, or need help, let us know and one of us can take the work you have here and see if we can finish it up.

Thanks for your patience.

shoheiogawa commented 6 years ago

Sorry, I don't have much time now for more development. It would be nice if one of you could help with this. I pushed what I have done to my forked repository.

The current implementation is we find elements are on a boundary or not. I kept the node implementation too. Please see framework/src/markers/SideNeighborMarker.C.

I have some tests too. refine_center_left.i and refine_center_right.i are for the refinement around an internal sideset. As I mentioned earlier, with refine_center_right.i, no refinement happens.

Let me know if you have any question or need anything.

permcody commented 6 years ago

Thanks for your time on this.

permcody commented 6 years ago

Tag @idaholab/moose-team if anybody wants to finish this off.

shoheiogawa commented 6 years ago

OK

shoheiogawa commented 6 years ago

Sorry, but where should I add the tag? To my branch on the GitHub?

permcody commented 6 years ago

Yes to the branch where you committed.

shoheiogawa commented 6 years ago

I added the tag to my branch and pushed it.

shoheiogawa commented 5 years ago

I worked on the side neighbor marker (boundary marker). The algorithm runs on a distributed mesh with a relationship manager. If I create a pull request, do I have to add a test description and gold files? Is there any instruction page on creating a pull request?

https://github.com/shoheiogawa/moose/tree/side_neighbor_marker_11643

lindsayad commented 5 years ago

We should have some info here: https://mooseframework.inl.gov/framework_development/contributing.html

On Mon, Sep 9, 2019 at 6:18 AM Shohei Ogawa notifications@github.com wrote:

I worked on the side neighbor marker (boundary marker). The algorithm runs on a distributed mesh with a relationship manager. If I create a pull request, do I have to add a test description and gold files? Is there any instruction page on creating a pull request?

https://github.com/shoheiogawa/moose/tree/side_neighbor_marker_11643

— You are receiving this because you are on a team that was mentioned. Reply to this email directly, view it on GitHub https://github.com/idaholab/moose/issues/11643?email_source=notifications&email_token=ACOGA4HJ2DWEDECW5ZXAGK3QIZEK5A5CNFSM4FDTQZ42YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6HRDXY#issuecomment-529469919, or mute the thread https://github.com/notifications/unsubscribe-auth/ACOGA4BCHNSHSM7FZND7DPLQIZEK5ANCNFSM4FDTQZ4Q .

shoheiogawa commented 5 years ago

@lindsayad Thank you. What I got for this marker have about 10 commits. Should I just extract the files added and commit to the development branch once?

lindsayad commented 5 years ago

Multiple commits that show a clean progression of ideas are just fine. If you have commits that are like "fix bug in previous commit", then that should be squashed.

development branch

As you've indicated here, we generally recommend that your commits be rebased on top of the devel branch, but importantly as our doc says:

The main thing to remember when issuing a PR for MOOSE is that all PRs should be specified to go to the next branch.

So when you submit your pull request on github, make sure that your base branch is next as shown below:

next-branch
jmeziere commented 4 years ago

@permcody I'm not 100% sure how far shoheiogawa got on this. Could you explain a little on what more needs to be done?

permcody commented 4 years ago

It looks like the code is complete. It just never got merged. Alex attempted to show him the error here. I would suggest cherry-picking his commits onto a new branch and submit a new PR. If you do this correctly, he retains authorship. You get committer status and everyone is happy! If changes are necessary due to changes in the code you can just add new commits on top.

GiudGiud commented 3 weeks ago

@dschwen contributed a BoundaryMarker in 2021 https://github.com/idaholab/moose/pull/17682 Closing as the capability has been added