Get neighbor elements from a physical group
Hello everyone,
For the sake of a simulation, I want to isolate the N layers of a given physical group so those elements can later on have a different property at the solver level. I first thought about building the CAD for that secondary region but that would be quite complex here. To play with the different aspects, I built that simple example below of a small_box in a large_box and how I use ShowNeighborElements.
However, I'm not quite sure how to deal with those now visible entities (I first thought about doing the ShowNeighborElements work manually by finding my nodes, finding my elements outside my small_box and iterate on that - that's still an option if I can't find a way to manage to take that visibility filter to the next step) + not quite sure how to remove those elements from the large_box physical group and add them to a new skin physical group.
Looking at it over and over again, I can't find a way to manage physical groups for the mesh and it seems to be only at the geometry level, the mesh itself being a children of the geometry? Meaning that in this case finding those neighbor elements won't get me far anyway? Very very last resort, once I have my list of elements, I could write out an ASCII .msh and have a script come and change the physical group of those elements but I'd like to really avoid something like that...
Thanks for your insights!
import gmsh
gmsh.initialize()
# We create here two boxes, a small one and a large one that encompasses the small one.
# I've found boolean operations sometimes unpredictable so I'm collecting faces and essentially reconstructing
# the second box based on those faces. This also guarantees the fact that the two boxes share the same faces for the
# solid meshing to come.
small_box = gmsh.model.occ.addBox(-1/2, -1/2, -1/2, 1, 1, 1)
gmsh.model.occ.synchronize()
small_box_faces = gmsh.model.getEntities(2)
large_box = gmsh.model.occ.addBox(-1, -1, -1, 2, 2, 2)
gmsh.model.occ.synchronize()
large_box_faces = [ent for ent in gmsh.model.getEntities(2) if ent not in small_box_faces]
gmsh.model.occ.remove([(3, large_box)], recursive=False)
gmsh.model.occ.synchronize()
large_box = gmsh.model.occ.addVolume([gmsh.model.occ.addSurfaceLoop([ent[1] for ent in large_box_faces]), gmsh.model.occ.addSurfaceLoop([ent[1] for ent in small_box_faces])])
gmsh.model.occ.synchronize()
# We create the 2 physical groups
gmsh.model.addPhysicalGroup(3, [small_box], name="small_box")
gmsh.model.addPhysicalGroup(3, [large_box], name="large_box")
gmsh.model.mesh.setSize(gmsh.model.occ.getEntities(0), 0.2)
gmsh.model.mesh.generate(3)
# We use the plugin ShowNeighborElements to collect elements at the boundary of small_box
num_layer = 2
gmsh.plugin.setNumber("ShowNeighborElements", "NumLayers", num_layer)
for group_info in gmsh.model.getEntitiesForPhysicalName("small_box"):
for tag_entity in gmsh.model.getEntitiesForPhysicalGroup(group_info[0], group_info[1]):
for element_type in gmsh.model.mesh.getElementTypes(group_info[0], tag_entity):
elements, _ = gmsh.model.mesh.getElementsByType(element_type, tag_entity)
for element in elements:
gmsh.plugin.setNumber("ShowNeighborElements", "Element1", element)
gmsh.plugin.run("ShowNeighborElements")
gmsh.model.mesh.setVisibility(elements, 0)
# Need to figure out how to:
# - collect the visible elements (trial with ExtractElements below or potentially NewView based on ElementData?)
gmsh.plugin.setNumber("ExtractElements", "Visible", 1)
gmsh.plugin.setNumber("ExtractElements", "View", -1)
#gmsh.plugin.run("ExtractElements") - it doesn't seem to find the plugin for some reason?
# - how to use that collection of elements to remove them from "large_box" physical group and add them to a new physical group that
# will later on have a special treatment by the solver?
gmsh.fltk.run()
gmsh.finalize()