MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d) { int i, oldne; PointIndex pi; int meshed; int cntsteps; ARRAY<INDEX_2> connectednodes; mesh3d.Compress(); // mesh3d.PrintMemInfo (cout); if (mp.checkoverlappingboundary) if (mesh3d.CheckOverlappingBoundary()) throw NgException ("Stop meshing since boundary mesh is overlapping"); int nonconsist = 0; for (int k = 1; k <= mesh3d.GetNDomains(); k++) { PrintMessage (3, "Check subdomain ", k, " / ", mesh3d.GetNDomains()); mesh3d.FindOpenElements(k); /* bool res = mesh3d.CheckOverlappingBoundary(); if (res) { PrintError ("Surface is overlapping !!"); nonconsist = 1; } */ bool res = (mesh3d.CheckConsistentBoundary() != 0); if (res) { PrintError ("Surface mesh not consistent"); nonconsist = 1; } } if (nonconsist) { PrintError ("Stop meshing since surface mesh not consistent"); throw NgException ("Stop meshing since surface mesh not consistent"); } double globmaxh = mp.maxh; for (int k = 1; k <= mesh3d.GetNDomains(); k++) { if (multithread.terminate) break; PrintMessage (2, ""); PrintMessage (1, "Meshing subdomain ", k, " of ", mesh3d.GetNDomains()); (*testout) << "Meshing subdomain " << k << endl; mp.maxh = min2 (globmaxh, mesh3d.MaxHDomain(k)); mesh3d.CalcSurfacesOfNode(); mesh3d.FindOpenElements(k); if (!mesh3d.GetNOpenElements()) continue; Box<3> domain_bbox( Box<3>::EMPTY_BOX ); /* Point<3> (1e10, 1e10, 1e10), Point<3> (-1e10, -1e10, -1e10)); */ for (SurfaceElementIndex sei = 0; sei < mesh3d.GetNSE(); sei++) { const Element2d & el = mesh3d[sei]; if (el.IsDeleted() ) continue; if (mesh3d.GetFaceDescriptor(el.GetIndex()).DomainIn() == k || mesh3d.GetFaceDescriptor(el.GetIndex()).DomainOut() == k) for (int j = 0; j < el.GetNP(); j++) domain_bbox.Add (mesh3d[el[j]]); } domain_bbox.Increase (0.01 * domain_bbox.Diam()); for (int qstep = 1; qstep <= 3; qstep++) { if (mesh3d.HasOpenQuads()) { string rulefile = ngdir; const char ** rulep = NULL; switch (qstep) { case 1: rulefile += "/rules/prisms2.rls"; rulep = prismrules2; break; case 2: // connect pyramid to triangle rulefile += "/rules/pyramids2.rls"; rulep = pyramidrules2; break; case 3: // connect to vis-a-vis point rulefile += "/rules/pyramids.rls"; rulep = pyramidrules; break; } // Meshing3 meshing(rulefile); Meshing3 meshing(rulep); MeshingParameters mpquad = mp; mpquad.giveuptol = 15; mpquad.baseelnp = 4; mpquad.starshapeclass = 1000; mpquad.check_impossible = qstep == 1; // for prisms only (air domain in trafo) for (pi = PointIndex::BASE; pi < mesh3d.GetNP()+PointIndex::BASE; pi++) meshing.AddPoint (mesh3d[pi], pi); mesh3d.GetIdentifications().GetPairs (0, connectednodes); for (i = 1; i <= connectednodes.Size(); i++) meshing.AddConnectedPair (connectednodes.Get(i)); for (i = 1; i <= mesh3d.GetNOpenElements(); i++) { Element2d hel = mesh3d.OpenElement(i); meshing.AddBoundaryElement (hel); } oldne = mesh3d.GetNE(); meshing.GenerateMesh (mesh3d, mpquad); for (i = oldne + 1; i <= mesh3d.GetNE(); i++) mesh3d.VolumeElement(i).SetIndex (k); (*testout) << "mesh has " << mesh3d.GetNE() << " prism/pyramid�elements" << endl; mesh3d.FindOpenElements(k); } } if (mesh3d.HasOpenQuads()) { PrintSysError ("mesh has still open quads"); throw NgException ("Stop meshing since too many attempts"); // return MESHING3_GIVEUP; } if (mp.delaunay && mesh3d.GetNOpenElements()) { Meshing3 meshing((const char**)NULL); mesh3d.FindOpenElements(k); for (pi = PointIndex::BASE; pi < mesh3d.GetNP()+PointIndex::BASE; pi++) meshing.AddPoint (mesh3d[pi], pi); for (i = 1; i <= mesh3d.GetNOpenElements(); i++) meshing.AddBoundaryElement (mesh3d.OpenElement(i)); oldne = mesh3d.GetNE(); meshing.Delaunay (mesh3d, k, mp); for (i = oldne + 1; i <= mesh3d.GetNE(); i++) mesh3d.VolumeElement(i).SetIndex (k); PrintMessage (3, mesh3d.GetNP(), " points, ", mesh3d.GetNE(), " elements"); } cntsteps = 0; if (mesh3d.GetNOpenElements()) do { if (multithread.terminate) break; mesh3d.FindOpenElements(k); PrintMessage (5, mesh3d.GetNOpenElements(), " open faces"); cntsteps++; if (cntsteps > mp.maxoutersteps) throw NgException ("Stop meshing since too many attempts"); string rulefile = ngdir + "/tetra.rls"; PrintMessage (1, "start tetmeshing"); // Meshing3 meshing(rulefile); Meshing3 meshing(tetrules); ARRAY<int, PointIndex::BASE> glob2loc(mesh3d.GetNP()); glob2loc = -1; for (pi = PointIndex::BASE; pi < mesh3d.GetNP()+PointIndex::BASE; pi++) if (domain_bbox.IsIn (mesh3d[pi])) glob2loc[pi] = meshing.AddPoint (mesh3d[pi], pi); for (i = 1; i <= mesh3d.GetNOpenElements(); i++) { Element2d hel = mesh3d.OpenElement(i); for (int j = 0; j < hel.GetNP(); j++) hel[j] = glob2loc[hel[j]]; meshing.AddBoundaryElement (hel); // meshing.AddBoundaryElement (mesh3d.OpenElement(i)); } oldne = mesh3d.GetNE(); mp.giveuptol = 15 + 10 * cntsteps; mp.sloppy = 5; meshing.GenerateMesh (mesh3d, mp); for (ElementIndex ei = oldne; ei < mesh3d.GetNE(); ei++) mesh3d[ei].SetIndex (k); mesh3d.CalcSurfacesOfNode(); mesh3d.FindOpenElements(k); teterrpow = 2; if (mesh3d.GetNOpenElements() != 0) { meshed = 0; PrintMessage (5, mesh3d.GetNOpenElements(), " open faces found"); // mesh3d.Save ("tmp.vol"); MeshOptimize3d optmesh; const char * optstr = "mcmstmcmstmcmstmcm"; size_t j; for (j = 1; j <= strlen(optstr); j++) { mesh3d.CalcSurfacesOfNode(); mesh3d.FreeOpenElementsEnvironment(2); mesh3d.CalcSurfacesOfNode(); switch (optstr[j-1]) { case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break; case 'd': optmesh.SplitImprove(mesh3d, OPT_REST); break; case 's': optmesh.SwapImprove(mesh3d, OPT_REST); break; case 't': optmesh.SwapImprove2(mesh3d, OPT_REST); break; case 'm': mesh3d.ImproveMesh(OPT_REST); break; } } mesh3d.FindOpenElements(k); PrintMessage (3, "Call remove problem"); RemoveProblem (mesh3d, k); mesh3d.FindOpenElements(k); } else { meshed = 1; PrintMessage (1, "Success !"); } } while (!meshed); PrintMessage (1, mesh3d.GetNP(), " points, ", mesh3d.GetNE(), " elements"); } mp.maxh = globmaxh; MeshQuality3d (mesh3d); return MESHING3_OK; }
void LocalH :: FindInnerBoxesRec2 (GradingBox * box, class AdFront3 * adfront, ARRAY<Box3d> & faceboxes, ARRAY<int> & faceinds, int nfinbox) { if (!box) return; int i, j; GradingBox * father = box -> father; Point3d c(box->xmid[0], box->xmid[1], box->xmid[2]); Vec3d v(box->h2, box->h2, box->h2); Box3d boxc(c-v, c+v); Point3d fc(father->xmid[0], father->xmid[1], father->xmid[2]); Vec3d fv(father->h2, father->h2, father->h2); Box3d fboxc(fc-fv, fc+fv); Box3d boxcfc(c,fc); static ARRAY<int> faceused; static ARRAY<int> faceused2; static ARRAY<int> facenotused; faceused.SetSize(0); facenotused.SetSize(0); faceused2.SetSize(0); for (j = 1; j <= nfinbox; j++) { // adfront->GetFaceBoundingBox (faceinds.Get(j), facebox); const Box3d & facebox = faceboxes.Get(faceinds.Get(j)); if (boxc.Intersect (facebox)) faceused.Append(faceinds.Get(j)); else facenotused.Append(faceinds.Get(j)); if (boxcfc.Intersect (facebox)) faceused2.Append (faceinds.Get(j)); } for (j = 1; j <= faceused.Size(); j++) faceinds.Elem(j) = faceused.Get(j); for (j = 1; j <= facenotused.Size(); j++) faceinds.Elem(j+faceused.Size()) = facenotused.Get(j); if (!father->flags.cutboundary) { box->flags.isinner = father->flags.isinner; box->flags.pinner = father->flags.pinner; } else { Point3d cf(father->xmid[0], father->xmid[1], father->xmid[2]); if (father->flags.isinner) box->flags.pinner = 1; else { if (adfront->SameSide (c, cf, &faceused2)) box->flags.pinner = father->flags.pinner; else box->flags.pinner = 1 - father->flags.pinner; } if (box->flags.cutboundary) box->flags.isinner = 0; else box->flags.isinner = box->flags.pinner; } int nf = faceused.Size(); for (i = 0; i < 8; i++) FindInnerBoxesRec2 (box->childs[i], adfront, faceboxes, faceinds, nf); }
twoint GetOLimit(int i) const {return olimit->Get(i);}
twoint GetILimit(int i) const {return ilimit->Get(i);}
//get all trigs: int GetTrig(int i) const { if (i <= charttrigs->Size()) {return charttrigs->Get(i);} else {return outertrigs->Get(i-charttrigs->Size());} }
int GetOuterTrig(int i) const {return outertrigs->Get(i);}
int GetChartTrig(int i) const {return charttrigs->Get(i);}
const STLBoundarySeg & GetSegment(int i) {return boundary.Get(i);}
void MeshOptimize2d :: GenericImprove (Mesh & mesh) { if (!faceindex) { if (writestatus) PrintMessage (3, "Generic Improve"); for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) GenericImprove (mesh); faceindex = 0; } // int j, k, l, ri; int np = mesh.GetNP(); int ne = mesh.GetNSE(); // SurfaceElementIndex sei; // for (SurfaceElementIndex sei = 0; sei < ne; sei++) // { // const Element2d & el = mesh[sei]; // (*testout) << "element " << sei << ": " <<flush; // for(int j=0; j<el.GetNP(); j++) // (*testout) << el[j] << " " << flush; // (*testout) << "IsDeleted() " << el.IsDeleted()<< endl; // } bool ok; int olddef, newdef; ARRAY<ImprovementRule*> rules; ARRAY<SurfaceElementIndex> elmap; ARRAY<int> elrot; ARRAY<PointIndex> pmap; ARRAY<PointGeomInfo> pgi; int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr(); ImprovementRule * r1; // 2 triangles to quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3)); r1->oldels.Append (Element2d (3, 2, 4)); r1->newels.Append (Element2d (1, 2, 4, 3)); r1->deledges.Append (INDEX_2 (2,3)); r1->onp = 4; r1->bonus = 2; rules.Append (r1); // 2 quad to 1 quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (4, 3, 2, 5)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // swap quads r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (3, 2, 5, 6)); r1->newels.Append (Element2d (1, 6, 3, 4)); r1->newels.Append (Element2d (1, 2, 5, 6)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); // three quads to 2 r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 6, 3)); r1->oldels.Append (Element2d (3, 6, 7, 4)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->newels.Append (Element2d (4, 5, 6, 7)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 6)); r1->onp = 7; r1->bonus = -1; rules.Append (r1); // quad + 2 connected trigs to quad r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->oldels.Append (Element2d (3, 5, 4)); r1->newels.Append (Element2d (1, 2, 5, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 5)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // quad + 2 non-connected trigs to quad (a and b) r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 6, 3)); r1->oldels.Append (Element2d (1, 4, 5)); r1->newels.Append (Element2d (1, 3, 4, 5)); r1->newels.Append (Element2d (1, 2, 6, 3)); r1->deledges.Append (INDEX_2 (1, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 6, 3)); r1->oldels.Append (Element2d (1, 4, 5)); r1->newels.Append (Element2d (1, 2, 4, 5)); r1->newels.Append (Element2d (4, 2, 6, 3)); r1->deledges.Append (INDEX_2 (1, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; rules.Append (r1); // two quad + trig -> one quad + trig r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 6, 3)); r1->oldels.Append (Element2d (4, 3, 6)); r1->newels.Append (Element2d (1, 2, 6, 4)); r1->newels.Append (Element2d (2, 5, 6)); r1->deledges.Append (INDEX_2 (2, 3)); r1->deledges.Append (INDEX_2 (3, 4)); r1->deledges.Append (INDEX_2 (3, 6)); r1->onp = 6; r1->bonus = -1; rules.Append (r1); // swap quad + trig (a and b) r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->newels.Append (Element2d (2, 5, 3, 4)); r1->newels.Append (Element2d (1, 2, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (2, 5, 3)); r1->newels.Append (Element2d (1, 2, 5, 3)); r1->newels.Append (Element2d (1, 3, 4)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 5; r1->bonus = 0; rules.Append (r1); // 2 quads to quad + 2 trigs r1 = new ImprovementRule; r1->oldels.Append (Element2d (1, 2, 3, 4)); r1->oldels.Append (Element2d (3, 2, 5, 6)); r1->newels.Append (Element2d (1, 5, 6, 4)); r1->newels.Append (Element2d (1, 2, 5)); r1->newels.Append (Element2d (4, 6, 3)); r1->deledges.Append (INDEX_2 (2, 3)); r1->onp = 6; r1->bonus = 0; // rules.Append (r1); ARRAY<int> mapped(rules.Size()); ARRAY<int> used(rules.Size()); used = 0; mapped = 0; for (int ri = 0; ri < rules.Size(); ri++) { ImprovementRule & rule = *rules[ri]; rule.incelsonnode.SetSize (rule.onp); rule.reused.SetSize (rule.onp); for (int j = 1; j <= rule.onp; j++) { rule.incelsonnode.Elem(j) = 0; rule.reused.Elem(j) = 0; } for (int j = 1; j <= rule.oldels.Size(); j++) { const Element2d & el = rule.oldels.Elem(j); for (int k = 1; k <= el.GetNP(); k++) rule.incelsonnode.Elem(el.PNum(k))--; } for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & el = rule.newels.Elem(j); for (int k = 1; k <= el.GetNP(); k++) { rule.incelsonnode.Elem(el.PNum(k))++; rule.reused.Elem(el.PNum(k)) = 1; } } } TABLE<int,PointIndex::BASE> elonnode(np); ARRAY<int,PointIndex::BASE> nelonnode(np); TABLE<SurfaceElementIndex> nbels(ne); nelonnode = -4; for (SurfaceElementIndex sei = 0; sei < ne; sei++) { const Element2d & el = mesh[sei]; if (el.GetIndex() == faceindex && !el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) elonnode.Add (el[j], sei); } if(!el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) nelonnode[el[j]]++; } } for (SurfaceElementIndex sei = 0; sei < ne; sei++) { const Element2d & el = mesh[sei]; if (el.GetIndex() == faceindex && !el.IsDeleted()) { for (int j = 0; j < el.GetNP(); j++) { for (int k = 0; k < elonnode[el[j]].Size(); k++) { int nbel = elonnode[el[j]] [k]; bool inuse = false; for (int l = 0; l < nbels[sei].Size(); l++) if (nbels[sei][l] == nbel) inuse = true; if (!inuse) nbels.Add (sei, nbel); } } } } for (int ri = 0; ri < rules.Size(); ri++) { const ImprovementRule & rule = *rules[ri]; elmap.SetSize (rule.oldels.Size()); elrot.SetSize (rule.oldels.Size()); pmap.SetSize (rule.onp); pgi.SetSize (rule.onp); for (SurfaceElementIndex sei = 0; sei < ne; sei++) { if (multithread.terminate) break; if (mesh[sei].IsDeleted()) continue; elmap[0] = sei; FlatArray<SurfaceElementIndex> neighbours = nbels[sei]; for (elrot[0] = 0; elrot[0] < mesh[sei].GetNP(); elrot[0]++) { const Element2d & el0 = mesh[sei]; const Element2d & rel0 = rule.oldels[0]; if (el0.GetIndex() != faceindex) continue; if (el0.IsDeleted()) continue; if (el0.GetNP() != rel0.GetNP()) continue; pmap = -1; for (int k = 0; k < el0.GetNP(); k++) { pmap.Elem(rel0[k]) = el0.PNumMod(k+elrot[0]+1); pgi.Elem(rel0[k]) = el0.GeomInfoPiMod(k+elrot[0]+1); } ok = 1; for (int i = 1; i < elmap.Size(); i++) { // try to find a mapping for reference-element i const Element2d & rel = rule.oldels[i]; bool possible = 0; for (elmap[i] = 0; elmap[i] < neighbours.Size(); elmap[i]++) { const Element2d & el = mesh[neighbours[elmap[i]]]; if (el.IsDeleted()) continue; if (el.GetNP() != rel.GetNP()) continue; for (elrot[i] = 0; elrot[i] < rel.GetNP(); elrot[i]++) { possible = 1; for (int k = 0; k < rel.GetNP(); k++) if (pmap.Elem(rel[k]) != -1 && pmap.Elem(rel[k]) != el.PNumMod (k+elrot[i]+1)) possible = 0; if (possible) { for (int k = 0; k < el.GetNP(); k++) { pmap.Elem(rel[k]) = el.PNumMod(k+elrot[i]+1); pgi.Elem(rel[k]) = el.GeomInfoPiMod(k+elrot[i]+1); } break; } } if (possible) break; } if (!possible) { ok = 0; break; } elmap[i] = neighbours[elmap[i]]; } for(int i=0; ok && i<rule.deledges.Size(); i++) { ok = !mesh.IsSegment(pmap.Elem(rule.deledges[i].I1()), pmap.Elem(rule.deledges[i].I2())); } if (!ok) continue; mapped[ri]++; olddef = 0; for (int j = 1; j <= pmap.Size(); j++) olddef += sqr (nelonnode[pmap.Get(j)]); olddef += rule.bonus; newdef = 0; for (int j = 1; j <= pmap.Size(); j++) if (rule.reused.Get(j)) newdef += sqr (nelonnode[pmap.Get(j)] + rule.incelsonnode.Get(j)); if (newdef > olddef) continue; // calc metric badness double bad1 = 0, bad2 = 0; Vec<3> n; SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1)); GetNormalVector (surfnr, mesh.Point(pmap.Get(1)), pgi.Elem(1), n); for (int j = 1; j <= rule.oldels.Size(); j++) bad1 += mesh.SurfaceElement(elmap.Get(j)).CalcJacobianBadness (mesh.Points(), n); // check new element: for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & rnel = rule.newels.Get(j); Element2d nel(rnel.GetNP()); for (int k = 1; k <= rnel.GetNP(); k++) nel.PNum(k) = pmap.Get(rnel.PNum(k)); bad2 += nel.CalcJacobianBadness (mesh.Points(), n); } if (bad2 > 1e3) continue; if (newdef == olddef && bad2 > bad1) continue; // generate new element: for (int j = 1; j <= rule.newels.Size(); j++) { const Element2d & rnel = rule.newels.Get(j); Element2d nel(rnel.GetNP()); nel.SetIndex (faceindex); for (int k = 1; k <= rnel.GetNP(); k++) { nel.PNum(k) = pmap.Get(rnel.PNum(k)); nel.GeomInfoPi(k) = pgi.Get(rnel.PNum(k)); } mesh.AddSurfaceElement(nel); } for (int j = 0; j < rule.oldels.Size(); j++) mesh.DeleteSurfaceElement ( elmap[j] ); for (int j = 1; j <= pmap.Size(); j++) nelonnode[pmap.Get(j)] += rule.incelsonnode.Get(j); used[ri]++; } } } mesh.Compress(); for (int ri = 0; ri < rules.Size(); ri++) { PrintMessage (5, "rule ", ri+1, " ", mapped[ri], "/", used[ri], " mapped/used"); } }