32 throw std::runtime_error(
"meshPolygon2DGeoFromVertices: need at least 3 vertices.");
34 std::vector<int> pids;
35 pids.reserve(verts.size());
36 for (
const auto &v : verts)
37 pids.push_back(gmsh::model::geo::addPoint(v.d_x, v.d_y, v.d_z, h));
39 std::vector<int> lines;
40 const size_t n = verts.size();
42 for (
size_t i = 0; i < n; ++i)
43 lines.push_back(gmsh::model::geo::addLine(pids[i], pids[(i + 1) % n]));
45 int cl = gmsh::model::geo::addCurveLoop(lines);
46 gmsh::model::geo::addPlaneSurface({cl});
47 gmsh::model::geo::synchronize();
74 const double t = g.
d_t;
75 const double hx = 0.5 * t, hy = 0.5 * t, hz = 0.5 * t;
78 return {x0 + hx, y0 + hy, z0 + hz};
80 return {x1 - hx, y0 + hy, z0 + hz};
82 return {x0 + hx, y0 + hy, z0 + hz};
84 return {x0 + hx, y1 - hy, z0 + hz};
86 return {x0 + hx, y0 + hy, z0 + hz};
88 return {x0 + hx, y0 + hy, z1 - hz};
90 throw std::runtime_error(
"embedPointOpenCuboidChannel3DForMesh: open_face must be 0..5.");
98 const double Lx = x1 - x0, Ly = y1 - y0, Lz = z1 - z0;
99 const double t = g.
d_t;
102 const int out_vol = gmsh::model::occ::addBox(x0, y0, z0, Lx, Ly, Lz);
103 gmsh::model::occ::synchronize();
104 const int in_vol = gmsh::model::occ::addBox(x0 + t, y0 + t, z0 + t, Lx - 2. * t, Ly - 2. * t,
106 gmsh::model::occ::synchronize();
107 std::vector<std::pair<int, int>> ov;
108 std::vector<std::vector<std::pair<int, int>>> ovv;
109 gmsh::model::occ::cut({{3, out_vol}}, {{3, in_vol}}, ov, ovv, -1,
true,
true);
110 gmsh::model::occ::synchronize();
111 gmsh::model::occ::removeAllDuplicates();
112 gmsh::model::occ::synchronize();
116 std::vector<std::pair<int, int>> ents;
117 gmsh::model::getEntities(ents, 3);
119 shell = ents.back().second;
122 throw std::runtime_error(
"buildOpenCuboidChannel3DGeo: no volume after outer−inner cut.");
127 slab = gmsh::model::occ::addBox(x1 - t, y0, z0, t, Ly, Lz);
130 slab = gmsh::model::occ::addBox(x0, y0, z0, t, Ly, Lz);
133 slab = gmsh::model::occ::addBox(x0, y1 - t, z0, Lx, t, Lz);
136 slab = gmsh::model::occ::addBox(x0, y0, z0, Lx, t, Lz);
139 slab = gmsh::model::occ::addBox(x0, y0, z1 - t, Lx, Ly, t);
142 slab = gmsh::model::occ::addBox(x0, y0, z0, Lx, Ly, t);
145 throw std::runtime_error(
"buildOpenCuboidChannel3DGeo: open_face must be 0..5.");
147 gmsh::model::occ::synchronize();
149 std::vector<std::pair<int, int>> ov2;
150 gmsh::model::occ::cut({{3, shell}}, {{3, slab}}, ov2, ovv, -1,
true,
true);
151 gmsh::model::occ::synchronize();
152 gmsh::model::occ::removeAllDuplicates();
153 gmsh::model::occ::synchronize();
157 std::vector<std::pair<int, int>> ents;
158 gmsh::model::getEntities(ents, 3);
160 vol = ents.back().second;
163 throw std::runtime_error(
"buildOpenCuboidChannel3DGeo: no volume after removing opening slab.");
166 const int p = gmsh::model::occ::addPoint(c.
d_x, c.
d_y, c.
d_z, h);
167 gmsh::model::occ::synchronize();
168 gmsh::model::mesh::embed(0, {p}, 3, vol);
169 gmsh::model::occ::synchronize();
171 const double tol = std::max(1.0e-9, 1.0e-6 * std::max({Lx, Ly, Lz}));
213 throw std::runtime_error(
"buildComplexRectangles2DOcc: empty or mismatched flags.");
215 throw std::runtime_error(
"buildComplexRectangles2DOcc: first object must be plus.");
218 if (o.d_name ==
"rectangle") {
221 const auto &hi = r.d_vertices[2];
222 return gmsh::model::occ::addRectangle(lo.d_x, lo.d_y, lo.d_z, hi.d_x - lo.d_x,
225 if (o.d_name ==
"triangle") {
227 std::vector<int> pts(3), lines(3);
228 for (
int i = 0; i < 3; ++i)
229 pts[i] = gmsh::model::occ::addPoint(t.d_vertices[i].d_x, t.d_vertices[i].d_y,
230 t.d_vertices[i].d_z);
231 for (
int i = 0; i < 3; ++i)
232 lines[i] = gmsh::model::occ::addLine(pts[i], pts[(i + 1) % 3]);
233 const int cl = gmsh::model::occ::addCurveLoop(lines);
234 return gmsh::model::occ::addPlaneSurface({cl});
236 throw std::runtime_error(
237 "buildComplexRectangles2DOcc: only rectangle/triangle parts supported (got " +
241 if (c.
d_obj[0]->d_name !=
"rectangle")
242 throw std::runtime_error(
"buildComplexRectangles2DOcc: outer object must be a rectangle.");
244 int base = surfaceTag(*c.
d_obj[0]);
245 gmsh::model::occ::synchronize();
246 std::vector<std::pair<int, int>> tools;
247 for (
size_t i = 1; i < c.
d_obj.size(); ++i) {
249 throw std::runtime_error(
"buildComplexRectangles2DOcc: only plus then minus cuts supported.");
250 tools.push_back({2, surfaceTag(*c.
d_obj[i])});
252 gmsh::model::occ::synchronize();
254 std::vector<std::pair<int, int>> ov;
255 std::vector<std::vector<std::pair<int, int>>> ovv;
256 if (!tools.empty()) {
257 gmsh::model::occ::cut({{2, base}}, tools, ov, ovv, -1,
true,
true);
258 gmsh::model::occ::synchronize();
259 gmsh::model::occ::removeAllDuplicates();
260 gmsh::model::occ::synchronize();
265 int surface_tag = -1;
266 for (
const auto &pr : ov)
268 surface_tag = pr.second;
271 if (surface_tag < 0) {
272 std::vector<std::pair<int, int>> ents;
273 gmsh::model::getEntities(ents, 2);
275 surface_tag = ents.back().second;
278 throw std::runtime_error(
"buildComplexRectangles2DOcc: no surface after cut.");
281 const auto bx = c.
d_obj[0]->box();
282 const double cx = 0.5 * (bx.first.d_x + bx.second.d_x);
283 const double cy = 0.5 * (bx.first.d_y + bx.second.d_y);
284 const double cz = bx.first.d_z;
285 const int p = gmsh::model::occ::addPoint(cx, cy, cz, h);
286 gmsh::model::occ::synchronize();
287 gmsh::model::mesh::embed(0, {p}, 2, surface_tag);
288 gmsh::model::occ::synchronize();