PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
annulusMesh3D.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2026 Prashant K. Jha
4 * -------------------------------------------
5 * PeriDEM https://github.com/prashjha/PeriDEM
6 *
7 * Distributed under the Boost Software License, Version 1.0.
8 */
9
10#include "annulusMesh3D.h"
12#include "geom/geomObjects.h"
13#include <cmath>
14#include <gmsh.h>
15#include <sstream>
16#include <stdexcept>
17#include <vector>
18
19namespace mesh_gen {
20namespace {
21
22void assertCuboidAnnulusValid(const geom::Cuboid &outer, const geom::Cuboid &inner) {
23 const auto &blo = outer.d_vertices[0];
24 const auto &bhi = outer.d_vertices[6];
25 const auto &bli = inner.d_vertices[0];
26 const auto &bhi_i = inner.d_vertices[6];
27
28 constexpr double eps = 1.0e-12;
29 if (!(bli.d_x > blo.d_x + eps && bhi_i.d_x < bhi.d_x - eps && bli.d_y > blo.d_y + eps &&
30 bhi_i.d_y < bhi.d_y - eps && bli.d_z > blo.d_z + eps && bhi_i.d_z < bhi.d_z - eps))
31 throw std::runtime_error(
32 "buildAnnulus3DInCurrentModel: inner cuboid must be strictly inside the outer cuboid.");
33}
34
35void assertSphereAnnulusValid(const geom::Sphere &outer, const geom::Sphere &inner) {
36 constexpr double eps = 1.0e-10;
37 if ((outer.d_x - inner.d_x).lengthSq() > eps)
38 throw std::runtime_error(
39 "buildAnnulus3DInCurrentModel: sphere annulus requires coincident centers (concentric spheres).");
40 if (inner.d_r <= 0. || outer.d_r <= inner.d_r)
41 throw std::runtime_error(
42 "buildAnnulus3DInCurrentModel: require 0 < r_inner < r_outer for sphere − sphere.");
43}
44
45static int firstTagOfDim(const std::vector<std::pair<int, int>> &ov, int dim) {
46 for (const auto &pr : ov)
47 if (pr.first == dim)
48 return pr.second;
49 return -1;
50}
51
54 if (a.d_inObj_p->d_name == "sphere" && a.d_outObj_p->d_name == "sphere") {
55 const auto &outer = *static_cast<const geom::Sphere *>(a.d_outObj_p);
56 const auto &inner = *static_cast<const geom::Sphere *>(a.d_inObj_p);
57 const double r_mid = 0.5 * (outer.d_r + inner.d_r);
58 return {outer.d_x.d_x + r_mid, outer.d_x.d_y, outer.d_x.d_z};
59 }
60 if (a.d_inObj_p->d_name == "cuboid" && a.d_outObj_p->d_name == "cuboid") {
61 const auto &outer = *static_cast<const geom::Cuboid *>(a.d_outObj_p);
62 const auto &inner = *static_cast<const geom::Cuboid *>(a.d_inObj_p);
63 const auto &blo = outer.d_vertices[0];
64 const auto &bli = inner.d_vertices[0];
65 return {0.5 * (blo.d_x + bli.d_x), 0.5 * (blo.d_y + bli.d_y), 0.5 * (blo.d_z + bli.d_z)};
66 }
67 return a.center();
68}
69
70void finish3DCutEmbedVolume(const std::vector<std::pair<int, int>> &ov, const geom::AnnulusGeomObject &a,
71 double h) {
72
73 int vol_tag = firstTagOfDim(ov, 3);
74 if (vol_tag < 0) {
75 std::vector<std::pair<int, int>> ents;
76 gmsh::model::getEntities(ents, 3);
77 if (!ents.empty())
78 vol_tag = ents.back().second;
79 }
80 if (vol_tag < 0) {
81 std::ostringstream oss;
82 oss << "buildAnnulus3DInCurrentModel: boolean cut did not produce a volume (ov size = "
83 << ov.size() << ").";
84 throw std::runtime_error(oss.str());
85 }
86
88 const int p = gmsh::model::occ::addPoint(c.d_x, c.d_y, c.d_z, h);
89 gmsh::model::occ::synchronize();
90 gmsh::model::mesh::embed(0, {p}, 3, vol_tag);
91 gmsh::model::occ::synchronize();
92}
93
95 const auto &outer = *static_cast<const geom::Cuboid *>(a.d_outObj_p);
96 const auto &inner = *static_cast<const geom::Cuboid *>(a.d_inObj_p);
97 assertCuboidAnnulusValid(outer, inner);
98
99 const auto &lo = outer.d_vertices[0];
100 const int out_vol =
101 gmsh::model::occ::addBox(lo.d_x, lo.d_y, lo.d_z, outer.d_Lx, outer.d_Ly, outer.d_Lz);
102 gmsh::model::occ::synchronize();
103
104 const auto &li = inner.d_vertices[0];
105 const int in_vol =
106 gmsh::model::occ::addBox(li.d_x, li.d_y, li.d_z, inner.d_Lx, inner.d_Ly, inner.d_Lz);
107 gmsh::model::occ::synchronize();
108
109 std::vector<std::pair<int, int>> ov;
110 std::vector<std::vector<std::pair<int, int>>> ovv;
111 gmsh::model::occ::cut({{3, out_vol}}, {{3, in_vol}}, ov, ovv, -1, true, true);
112 gmsh::model::occ::synchronize();
113 gmsh::model::occ::removeAllDuplicates();
114 gmsh::model::occ::synchronize();
115
116 finish3DCutEmbedVolume(ov, a, h);
117}
118
120 const auto &outer = *static_cast<const geom::Sphere *>(a.d_outObj_p);
121 const auto &inner = *static_cast<const geom::Sphere *>(a.d_inObj_p);
122 assertSphereAnnulusValid(outer, inner);
123
124 const int out_vol =
125 gmsh::model::occ::addSphere(outer.d_x.d_x, outer.d_x.d_y, outer.d_x.d_z, outer.d_r);
126 gmsh::model::occ::synchronize();
127 const int in_vol =
128 gmsh::model::occ::addSphere(inner.d_x.d_x, inner.d_x.d_y, inner.d_x.d_z, inner.d_r);
129 gmsh::model::occ::synchronize();
130
131 std::vector<std::pair<int, int>> ov;
132 std::vector<std::vector<std::pair<int, int>>> ovv;
133 gmsh::model::occ::cut({{3, out_vol}}, {{3, in_vol}}, ov, ovv, -1, true, true);
134 gmsh::model::occ::synchronize();
135 gmsh::model::occ::removeAllDuplicates();
136 gmsh::model::occ::synchronize();
137
138 finish3DCutEmbedVolume(ov, a, h);
139}
140
141} // namespace
142
144
145 if (a.d_dim != 3)
146 throw std::runtime_error("buildAnnulus3DInCurrentModel: expected d_dim == 3.");
147 if (!a.d_inObj_p || !a.d_outObj_p)
148 throw std::runtime_error("buildAnnulus3DInCurrentModel: null inner or outer geometry.");
149
150 if (a.d_inObj_p->d_name == "cuboid" && a.d_outObj_p->d_name == "cuboid") {
151 buildCuboidAnnulus3D(a, h);
152 return;
153 }
154 if (a.d_inObj_p->d_name == "sphere" && a.d_outObj_p->d_name == "sphere") {
155 buildSphereAnnulus3D(a, h);
156 return;
157 }
158
159 throw std::runtime_error(
160 "buildAnnulus3DInCurrentModel: unsupported 3D pair (supported: cuboid−cuboid, sphere−sphere).");
161}
162
163} // namespace mesh_gen
Defines annulus rectangle.
GeomObject * d_outObj_p
Outer object.
util::Point center() const override
Computes the center of object.
size_t d_dim
Dimension objects live in.
GeomObject * d_inObj_p
Inner object.
Defines cuboid.
std::vector< util::Point > d_vertices
Vertices.
const std::string d_name
name of object
Defines sphere.
double d_r
Radius.
util::Point d_x
Center.
void buildCuboidAnnulus3D(const geom::AnnulusGeomObject &a, double h)
util::Point embedPointInAnnulus3D(const geom::AnnulusGeomObject &a)
void assertSphereAnnulusValid(const geom::Sphere &outer, const geom::Sphere &inner)
void finish3DCutEmbedVolume(const std::vector< std::pair< int, int > > &ov, const geom::AnnulusGeomObject &a, double h)
void assertCuboidAnnulusValid(const geom::Cuboid &outer, const geom::Cuboid &inner)
void buildSphereAnnulus3D(const geom::AnnulusGeomObject &a, double h)
static int firstTagOfDim(const std::vector< std::pair< int, int > > &ov, int dim)
void buildAnnulus3DInCurrentModel(const geom::AnnulusGeomObject &a, double h)
A structure to represent 3d vectors.
Definition point.h:30
double d_y
the y coordinate
Definition point.h:36
double d_z
the z coordinate
Definition point.h:39
double d_x
the x coordinate
Definition point.h:33