Boolean fragments of Extruded Entities of distinct hights in OpenCASCADE backend
Hi,
First of all, I would like to thank the dev team of Gmsh for this fantastic software! Our team makes heavy use of Gmsh in our daily work for simulation tasks such as CFD.
I have a question on some strange interactions between BooleanFragments
and Extrude
d entities.
Suppose I want to mesh a cylinder region with four fans inside it, like this:
The left is a slice at the center of the cylinder body and the right is a vertical slice. Actual mesh is a cylinder region of radius 1.0 and height 2.0, with four vacuum (no-mesh, empty) area corresponding to fans in the middle of cylinder with height 1.0. With OpenCASCADE backend, it is just easy to satisfy this requirement alone:
SetFactory("OpenCASCADE");
circ = newl;
circ_cl = newcl;
circ_surf = news;
Circle(circ) = {0.0,0.0,-1.0, 1.0};
Curve Loop(circ_cl) = {circ};
Surface(circ_surf) = {circ_cl};
cyl_exts[] = Extrude {0,0, 2.0} {
Surface{circ_surf}; Layers{10}; Recombine;
};
cyl_vol = cyl_exts[1];
peg_surfs[] = {};
peg_curvs[] = {};
pegl = newl;
pegcl = newcl;
pegs = news;
peg_curvs[] += {pegl};
peg_surfs[] += {pegs};
Ellipse(pegl) = {0.25,0.0,-0.5, 0.1, 0.025};
Curve Loop(pegcl) = {pegl};
Surface(pegs) = {pegcl};
pegl = newl;
pegcl = newcl;
pegs = news;
peg_curvs[] += {pegl};
peg_surfs[] += {pegs};
Ellipse(pegl) = {0.25,0.0,-0.5, 0.1, 0.025};
Curve Loop(pegcl) = {pegl};
Surface(pegs) = {pegcl};
Rotate { {0,0,1}, {0,0,-1}, Pi/2 } {
Surface{pegs};
}
pegl = newl;
pegcl = newcl;
pegs = news;
peg_curvs[] += {pegl};
peg_surfs[] += {pegs};
Ellipse(pegl) = {-0.25,0.0,-0.5, 0.1, 0.025};
Curve Loop(pegcl) = {pegl};
Surface(pegs) = {pegcl};
pegl = newl;
pegcl = newcl;
pegs = news;
peg_curvs[] += {pegl};
peg_surfs[] += {pegs};
Ellipse(pegl) = {-0.25,0.0,-0.5, 0.1, 0.025};
Curve Loop(pegcl) = {pegl};
Surface(pegs) = {pegcl};
Rotate { {0,0,1}, {0,0,-1}, Pi/2 } {
Surface{pegs};
}
core_exts[] = Extrude {0,0,1.0} {
Surface{peg_surfs[]};
};
peg_vols[] = {core_exts[1],core_exts[4],core_exts[7],core_exts[10]};
frags[] = BooleanFragments {
Volume{cyl_vol}; Delete;
} {
Volume{peg_vols[]}; Delete;
};
cyl_vol = frags[4];
peg_frags[] = {frags[0],frags[1],frags[2],frags[3]};
Recursive Delete {Volume{peg_frags[]};}
Physical Volume("outer") = {cyl_vol};
// Mesh.SaveAll = 1;
Mesh.MshFileVersion = 2.2;
Mesh 3;
Save "extrude-pegs.msh";
Save "extrude-pegs.vtk";
The above gives a mesh as desired:
But the situation changes if we want to impose more requirements on it. For example, we have to satisfy the following additional constraints:
- We need to mesh volumes adjacent to side surface as a structured mesh (hexahedron).
- Outermost layers in bottom and top surfaces must be divided into quads, whereas rest of the parts must be meshed by triangles.
- We need boundary layers of quads around each fans
(1) is already met; actually, this is the reason we used Extrude
instead of Cylinder
command. (2) can be easily done when we use four or more revolved circle arcs with Layers
specifier.
The constraint (3) poses us some problem: it must be specified to planer curves, and hence we need some plane including original fan curves. One straightforward (non-)solution which first came in my mind was as follows:
- create small circle containing all four fan curves
- take a
BooleanFragments
of circles with fan curves, deleting original ones - extrude fragments into a smaller cylinder
- takes boolean fragments of larger, smaller cylinder and four fan volumes.
- Recursively Deletes fan volumes.
Unfortunately, this didn't work - it seems that the resulted mesh still has meshes in fan regions.
Indeed, just taking BooleanFragments
of two extruded cylinders just didn't work as expected.
For example, consider the following:
SetFactory("OpenCASCADE");
circ = newl;
circ_cl = newcl;
circ_surf = news;
Circle(circ) = {0.0,0.0,-1.0, 1.0};
Curve Loop(circ_cl) = {circ};
Surface(circ_surf) = {circ_cl};
cyl_exts[] = Extrude {0,0, 2.0} {
Surface{circ_surf}; Layers{10}; Recombine;
};
cyl_vol = cyl_exts[1];
mid_circ = newl;
mid_circ_cl = newcl;
mid_circ_surf = news;
Circle(mid_circ) = {0.0, 0.0, -0.5, 0.5};
Curve Loop(mid_circ_cl) = {mid_circ};
Surface(mid_circ_surf) = {mid_circ_cl};
core_exts[] = Extrude {0,0,1.0} {
Surface{mid_circ_surf};
};
core_vol = core_exts[1];
frags[] = BooleanFragments {
Volume{cyl_vol}; Delete;
} {
Volume{core_vol}; Delete;
};
core_vol = frags[0];
cyl_vol = frags[1];
Recursive Delete {Volume{core_vol};}
Physical Volume("outer") = {cyl_vol};
// Mesh.SaveAll = 1;
Mesh.MshFileVersion = 2.2;
Mesh 3;
Save "extrude-pegs.msh";
Save "extrude-pegs.vtk";
This seems just taking BooleanFragments of two nested cylinders made with Extrude
directive and then delete the inner one.
So the result is expected to have an empty region in the core of bigger cylinder.
Contrary to this, this generates the dense mesh:
Changing the radius and/or the center of the inner circle won't change the situation. This seems rather strange as it did work for extruded ellipses.
Environment
I am using Gmsh 4.11.1 on macOS Ventura (13.4(22F66)).