8 #include "GmshConfig.h"
20 #if defined(HAVE_NETGEN)
23 #include "nglib_gmsh.h"
25 using namespace nglib;
27 static void getAllBoundingVertices(
28 GRegion *gr, std::set<MVertex *, MVertexPtrLessThan> &allBoundingVertices)
31 auto it =
faces.begin();
33 while(it !=
faces.end()) {
35 for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
37 for(
int k = 0; k < 3; k++)
38 if(allBoundingVertices.find(t->
getVertex(k)) ==
39 allBoundingVertices.end())
40 allBoundingVertices.insert(t->
getVertex(k));
46 static Ng_Mesh *buildNetgenStructure(
GRegion *gr,
bool importVolumeMesh,
47 std::vector<MVertex *> &numberedV)
50 Ng_Mesh *ngmesh = Ng_NewMesh();
52 std::set<MVertex *, MVertexPtrLessThan> allBoundingVertices;
53 getAllBoundingVertices(gr, allBoundingVertices);
55 auto itv = allBoundingVertices.begin();
57 while(itv != allBoundingVertices.end()) {
62 (*itv)->setIndex(I++);
63 numberedV.push_back(*itv);
64 Ng_AddPoint(ngmesh, tmp);
68 if(importVolumeMesh) {
75 Ng_AddPoint(ngmesh, tmp);
79 auto it =
faces.begin();
80 while(it !=
faces.end()) {
82 for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
88 Ng_AddSurfaceElement(ngmesh, NG_TRIG, tmp);
93 if(importVolumeMesh) {
94 for(std::size_t i = 0; i < gr->
tetrahedra.size(); i++) {
103 Ng_AddVolumeElement(ngmesh, NG_TET, tmp);
110 static void TransferVolumeMesh(
GRegion *gr, Ng_Mesh *ngmesh,
111 std::vector<MVertex *> &numberedV)
114 int nbv = Ng_GetNP(ngmesh);
115 int nbe = Ng_GetNE(ngmesh);
116 if(!nbv || !nbe)
return;
118 int nbpts = numberedV.size();
123 for(
int i = 0; i < nbe; i++) {
125 Ng_GetVolumeElement(ngmesh, i + 1, tmp);
126 for(
int j = 0; j < 4; j++) {
127 if(tmp[j] > nbpts) used.insert(tmp[j]);
132 for(
int i = nbpts; i < nbv; i++) {
134 Ng_GetPoint(ngmesh, i + 1, tmp);
135 if(used.count(i + 1)) {
137 numberedV.push_back(v);
141 numberedV.push_back(
nullptr);
146 for(
int i = 0; i < nbe; i++) {
148 Ng_GetVolumeElement(ngmesh, i + 1, tmp);
150 for(
int j = 0; j < 4; j++)
151 v[j] = numberedV[tmp[j] - 1];
152 if(v[0] && v[1] && v[2] && v[3])
155 Msg::Error(
"Tetrahedron with unknown node - should never be here!");
164 double P[3],
double N[3],
165 const double eps_prec)
167 double mat[3][3], det;
170 mat[0][0] = X[1] - X[0];
171 mat[0][1] = X[2] - X[0];
174 mat[1][0] = Y[1] - Y[0];
175 mat[1][1] = Y[2] - Y[0];
178 mat[2][0] = Z[1] - Z[0];
179 mat[2][1] = Z[2] - Z[0];
188 if(res[0] >= eps_prec && res[0] <= 1.0 - eps_prec && res[1] >= eps_prec &&
189 res[1] <= 1.0 - eps_prec && 1 - res[0] - res[1] >= eps_prec &&
190 1 - res[0] - res[1] <= 1.0 - eps_prec) {
192 return (res[2] > 0) ? 1 : 0;
194 else if(res[0] < -eps_prec || res[0] > 1.0 + eps_prec || res[1] < -eps_prec ||
195 res[1] > 1.0 + eps_prec || 1 - res[0] - res[1] < -eps_prec ||
196 1 - res[0] - res[1] > 1.0 + eps_prec) {
207 static void setRand(
double r[6])
209 for(
int i = 0; i < 6; i++)
210 r[i] = 0.0001 * ((
double)rand() / (
double)RAND_MAX);
213 static void meshNormalsPointOutOfTheRegion(
GRegion *gr)
216 auto it =
faces.begin();
222 Msg::Warning(
"Bad scaling in meshNormalsPointOutOfTheRegion");
229 while(it !=
faces.end()) {
231 int nb_intersect = 0;
232 for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
240 for(
int j = 0; j < 3; j++) {
246 double P[3] = {(X[0] + X[1] + X[2]) / 3., (Y[0] + Y[1] + Y[2]) / 3.,
247 (Z[0] + Z[1] + Z[2]) / 3.};
248 double v1[3] = {X[0] - X[1], Y[0] - Y[1], Z[0] - Z[1]};
249 double v2[3] = {X[2] - X[1], Y[2] - Y[1], Z[2] - Z[1]};
255 N[0] += rrr[0] * v1[0] + rrr[1] * v2[0];
256 N[1] += rrr[2] * v1[1] + rrr[3] * v2[1];
257 N[2] += rrr[4] * v1[2] + rrr[5] * v2[2];
259 auto it_b =
faces.begin();
260 while(it_b !=
faces.end()) {
261 GFace *gf_b = (*it_b);
262 for(std::size_t i_b = 0; i_b < gf_b->
triangles.size(); i_b++) {
271 for(
int j = 0; j < 3; j++) {
277 nb_intersect += inters;
284 if(nb_intersect >= 0)
288 if(nb_intersect < 0) {
setRand(rrr); }
290 if(nb_intersect % 2 == 1) {
292 for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
315 #if !defined(HAVE_NETGEN)
316 Msg::Error(
"Frontal algorithm requires Netgen");
320 for(
auto it =
faces.begin(); it !=
faces.end(); it++) {
321 if((*it)->quadrangles.size()) {
323 "Cannot use frontal 3D algorithm with quadrangles on boundary");
330 meshNormalsPointOutOfTheRegion(gr);
331 std::vector<MVertex *> numberedV;
332 Ng_Mesh *ngmesh = buildNetgenStructure(gr,
false, numberedV);
335 Ng_GenerateVolumeMesh(ngmesh, lc);
336 TransferVolumeMesh(gr, ngmesh, numberedV);
337 Ng_DeleteMesh(ngmesh);
354 Msg::Info(
"Skipping Netgen optimizer for hybrid mesh");
358 #if !defined(HAVE_NETGEN)
359 Msg::Error(
"Netgen optimizer is not compiled in this version of Gmsh");
363 std::vector<MVertex *> numberedV;
364 Ng_Mesh *ngmesh = buildNetgenStructure(gr,
true, numberedV);
371 Ng_OptimizeVolumeMesh(ngmesh, lc);
372 TransferVolumeMesh(gr, ngmesh, numberedV);
373 Ng_DeleteMesh(ngmesh);