public void Update(TaskManager tm = DummyTaskManager, Tracer tracer = DummyTracer) { //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer = NgProfiler::CreateTimer("clusters"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer1 = NgProfiler::CreateTimer("clusters1"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer2 = NgProfiler::CreateTimer("clusters2"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer3 = NgProfiler::CreateTimer("clusters3"); NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(Update_timer); MeshTopology top = mesh.GetTopology(); var id = this.mesh.GetCommunicator().Rank(); var ntasks = this.mesh.GetCommunicator().Size(); bool hasedges = top.HasEdges(); bool hasfaces = top.HasFaces(); if (!hasedges || !hasfaces) { return; } if (id == 0) { PrintMessage(3, "Update clusters"); } nv = mesh.GetNV(); ned = top.GetNEdges(); nfa = top.GetNFaces(); ne = mesh.GetNE(); int nse = mesh.GetNSE(); cluster_reps.SetSize(nv + ned + nfa + ne); cluster_reps = -1; Array <int> llist = new Array <int>(nv + ned + nfa + ne); llist = 0; Array <int> nnums = new Array <int>(); Array <int> ednums = new Array <int>(); Array <int> fanums = new Array <int>(); int changed; NgProfiler.StartTimer(Update_timer1); /* * for (int i = 1; i <= ne; i++) * { * const Element & el = mesh.VolumeElement(i); * ELEMENT_TYPE typ = el.GetType(); * * top.GetElementEdges (i, ednums); * top.GetElementFaces (i, fanums); * * int elnv = top.GetNVertices (typ); * int elned = ednums.Size(); * int elnfa = fanums.Size(); * * nnums.SetSize(elnv+elned+elnfa+1); * for (int j = 1; j <= elnv; j++) * nnums.Elem(j) = el.PNum(j); * for (int j = 1; j <= elned; j++) * nnums.Elem(elnv+j) = nv+ednums.Elem(j); * for (int j = 1; j <= elnfa; j++) * nnums.Elem(elnv+elned+j) = nv+ned+fanums.Elem(j); * nnums.Elem(elnv+elned+elnfa+1) = nv+ned+nfa+i; * * for (int j = 0; j < nnums.Size(); j++) * cluster_reps.Elem(nnums[j]) = nnums[j]; * } */ netgen.GlobalMembers.ParallelForRange(new TaskManager(tm), ne, (uint begin, uint end) => { Array <int> nnums = new Array <int>(); Array <int> ednums = new Array <int>(); Array <int> fanums = new Array <int>(); for (int i = (int)(begin + 1); i <= end; i++) { Element el = mesh.VolumeElement(i); ELEMENT_TYPE typ = el.GetType(); top.GetElementEdges(i, ednums); top.GetElementFaces(i, fanums); int elnv = top.GetNVertices(typ); int elned = ednums.Size(); int elnfa = fanums.Size(); nnums.SetSize(elnv + elned + elnfa + 1); for (int j = 1; j <= elnv; j++) { nnums.Elem(j) = el.PNum(j) + 1 - PointIndex.BASE; } for (int j = 1; j <= elned; j++) { nnums.Elem(elnv + j) = nv + ednums.Elem(j); } for (int j = 1; j <= elnfa; j++) { nnums.Elem(elnv + elned + j) = nv + ned + fanums.Elem(j); } nnums.Elem(elnv + elned + elnfa + 1) = nv + ned + nfa + i; for (int j = 0; j < nnums.Size(); j++) { cluster_reps.Elem(nnums[j]) = nnums[j]; } } }); NgProfiler.StopTimer(Update_timer1); NgProfiler.StartTimer(Update_timer2); /* * for (int i = 1; i <= nse; i++) * { * const Element2d & el = mesh.SurfaceElement(i); * ELEMENT_TYPE typ = el.GetType(); * * top.GetSurfaceElementEdges (i, ednums); * int fanum = top.GetSurfaceElementFace (i); * * int elnv = top.GetNVertices (typ); * int elned = ednums.Size(); * * nnums.SetSize(elnv+elned+1); * for (int j = 1; j <= elnv; j++) * nnums.Elem(j) = el.PNum(j)+1-PointIndex::BASE; * for (int j = 1; j <= elned; j++) * nnums.Elem(elnv+j) = nv+ednums.Elem(j); * nnums.Elem(elnv+elned+1) = fanum; * * for (int j = 0; j < nnums.Size(); j++) * cluster_reps.Elem(nnums[j]) = nnums[j]; * } */ netgen.GlobalMembers.ParallelForRange(new TaskManager(tm), (uint)nse, (uint begin, uint end) => { ArrayMem <int, 9> nnums = new ArrayMem <int, 9>(); ArrayMem <int, 9> ednums = new ArrayMem <int, 9>(); for (int i = (int)(begin + 1); i <= end; i++) { Element2d el = mesh.SurfaceElement(i); ELEMENT_TYPE typ = el.GetType(); top.GetSurfaceElementEdges(i, ednums); int fanum = top.GetSurfaceElementFace(i); int elnv = top.GetNVertices(typ); int elned = ednums.Size(); nnums.SetSize(elnv + elned + 1); for (int j = 1; j <= elnv; j++) { nnums.Elem(j) = el.PNum(j) + 1 - PointIndex.BASE; } for (int j = 1; j <= elned; j++) { nnums.Elem(elnv + j) = nv + ednums.Elem(j); } nnums.Elem(elnv + elned + 1) = fanum; for (int j = 0; j < nnums.Size(); j++) { cluster_reps.Elem(nnums[j]) = nnums[j]; } } }); NgProfiler.StopTimer(Update_timer2); NgProfiler.StartTimer(Update_timer3); int[] hex_cluster = { 1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 7, 8, 5, 6, 7, 8, 1, 2, 3, 4, 9, 9, 5, 8, 6, 7, 9 }; int[] prism_cluster = { 1, 2, 3, 1, 2, 3, 4, 5, 6, 4, 5, 6, 3, 1, 2, 7, 7, 4, 5, 6, 7 }; int[] pyramid_cluster = { 1, 2, 2, 1, 3, 4, 2, 1, 4, 6, 5, 5, 6, 7, 5, 7, 6, 4, 7 }; int[] tet_cluster14 = { 1, 2, 3, 1, 1, 4, 5, 4, 5, 6, 7, 5, 4, 7, 7 }; int[] tet_cluster12 = { 1, 1, 2, 3, 4, 4, 5, 1, 6, 6, 7, 7, 4, 6, 7 }; int[] tet_cluster13 = { 1, 2, 1, 3, 4, 6, 4, 5, 1, 5, 7, 4, 7, 5, 7 }; int[] tet_cluster23 = { 2, 1, 1, 3, 6, 5, 5, 4, 4, 1, 5, 7, 7, 4, 7 }; int[] tet_cluster24 = { 2, 1, 3, 1, 4, 1, 5, 4, 6, 5, 5, 7, 4, 7, 7 }; int[] tet_cluster34 = { 2, 3, 1, 1, 4, 5, 1, 6, 4, 5, 5, 4, 7, 7, 7 }; int cnt = 0; do { tracer("update cluster, identify", false); cnt++; changed = 0; for (int i = 1; i <= ne; i++) { Element el = mesh.VolumeElement(i); ELEMENT_TYPE typ = el.GetType(); //C++ TO C# CONVERTER TODO TASK: C# does not have an equivalent to pointers to value types: //ORIGINAL LINE: const int * clustertab = null; int clustertab = null; switch (typ) { case PRISM: case PRISM12: clustertab = prism_cluster; break; case HEX: clustertab = hex_cluster; break; case PYRAMID: clustertab = pyramid_cluster; break; case TET: case TET10: if (cluster_reps.Get(el.PNum(1) + 1 - PointIndex.BASE) == cluster_reps.Get(el.PNum(2) + 1 - PointIndex.BASE)) { clustertab = tet_cluster12; } else if (cluster_reps.Get(el.PNum(1) + 1 - PointIndex.BASE) == cluster_reps.Get(el.PNum(3) + 1 - PointIndex.BASE)) { clustertab = tet_cluster13; } else if (cluster_reps.Get(el.PNum(1) + 1 - PointIndex.BASE) == cluster_reps.Get(el.PNum(4) + 1 - PointIndex.BASE)) { clustertab = tet_cluster14; } else if (cluster_reps.Get(el.PNum(2) + 1 - PointIndex.BASE) == cluster_reps.Get(el.PNum(3) + 1 - PointIndex.BASE)) { clustertab = tet_cluster23; } else if (cluster_reps.Get(el.PNum(2) + 1 - PointIndex.BASE) == cluster_reps.Get(el.PNum(4) + 1 - PointIndex.BASE)) { clustertab = tet_cluster24; } else if (cluster_reps.Get(el.PNum(3) + 1 - PointIndex.BASE) == cluster_reps.Get(el.PNum(4) + 1 - PointIndex.BASE)) { clustertab = tet_cluster34; } else { clustertab = null; } break; default: clustertab = null; break; } if (clustertab != 0) { top.GetElementEdges(i, ednums); top.GetElementFaces(i, fanums); int elnv = top.GetNVertices(typ); int elned = ednums.Size(); int elnfa = fanums.Size(); nnums.SetSize(elnv + elned + elnfa + 1); for (int j = 1; j <= elnv; j++) { nnums.Elem(j) = el.PNum(j) + 1 - PointIndex.BASE; } for (int j = 1; j <= elned; j++) { nnums.Elem(elnv + j) = nv + ednums.Elem(j); } for (int j = 1; j <= elnfa; j++) { nnums.Elem(elnv + elned + j) = nv + ned + fanums.Elem(j); } nnums.Elem(elnv + elned + elnfa + 1) = nv + ned + nfa + i; for (int j = 0; j < nnums.Size(); j++) { for (int k = 0; k < j; k++) { if (clustertab[j] == clustertab[k]) { int jj = nnums[j]; int kk = nnums[k]; if (cluster_reps.Get(kk) < cluster_reps.Get(jj)) { swap(jj, kk); } if (cluster_reps.Get(jj) < cluster_reps.Get(kk)) { /* * cluster_reps.Elem(kk) = cluster_reps.Get(jj); * changed = 1; */ int rep = cluster_reps.Get(jj); int next = cluster_reps.Get(kk); do { int cur = next; next = llist.Elem(next); cluster_reps.Elem(cur) = rep; llist.Elem(cur) = llist.Elem(rep); llist.Elem(rep) = cur; } while (next != 0); changed = 1; } } } } } /* * if (clustertab) * { * if (typ == PYRAMID) * (*testout) << "pyramid"; * else if (typ == PRISM || typ == PRISM12) * (*testout) << "prism"; * else if (typ == TET || typ == TET10) * (*testout) << "tet"; * else * (*testout) << "unknown type" << endl; * * (*testout) << ", nnums = "; * for (j = 0; j < nnums.Size(); j++) * (*testout) << "node " << j << " = " << nnums[j] << ", rep = " * << cluster_reps.Get(nnums[j]) << endl; * } */ } tracer("update cluster, identify", true); } while (changed != 0); NgProfiler.StopTimer(Update_timer3); /* * (*testout) << "cluster reps:" << endl; * for (i = 1; i <= cluster_reps.Size(); i++) * { * (*testout) << i << ": "; * if (i <= nv) * (*testout) << "v" << i << " "; * else if (i <= nv+ned) * (*testout) << "e" << i-nv << " "; * else if (i <= nv+ned+nfa) * (*testout) << "f" << i-nv-ned << " "; * else * (*testout) << "c" << i-nv-ned-nfa << " "; * (*testout) << cluster_reps.Get(i) << endl; * } */ }
//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found: public void BlockFillLocalH(Mesh mesh, MeshingParameters mp) { //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer = NgProfiler::CreateTimer("Meshing2::BlockFill"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer1 = NgProfiler::CreateTimer("Meshing2::BlockFill 1"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer2 = NgProfiler::CreateTimer("Meshing2::BlockFill 2"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer3 = NgProfiler::CreateTimer("Meshing2::BlockFill 3"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer4 = NgProfiler::CreateTimer("Meshing2::BlockFill 4"); NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(BlockFillLocalH_timer); NgProfiler.StartTimer(BlockFillLocalH_timer1); double filldist = mp.filldist; Console.Write("blockfill local h"); Console.Write("\n"); Console.Write("rel filldist = "); Console.Write(filldist); Console.Write("\n"); PrintMessage(3, "blockfill local h"); Array <Point <3> > npoints = new Array <Point <3> >(); // adfront -> CreateTrees(); Box <3> bbox(Box <3> .EMPTY_BOX); double maxh = 0; for (int i = 0; i < adfront.GetNFL(); i++) { FrontLine line = adfront.GetLine(i); const Point <3>& p1 = adfront.GetPoint(line.L().I1()); const Point <3>& p2 = adfront.GetPoint(line.L().I2()); maxh = Math.Max(maxh, Dist(p1, p2)); bbox.Add(p1); bbox.Add(p2); } Console.Write("bbox = "); Console.Write(bbox); Console.Write("\n"); // Point<3> mpc = bbox.Center(); bbox.Increase(bbox.Diam() / 2); Box <3> meshbox = bbox; NgProfiler.StopTimer(BlockFillLocalH_timer1); NgProfiler.StartTimer(BlockFillLocalH_timer2); LocalH loch2 = new LocalH(bbox, 1, 2); if (mp.maxh < maxh) { maxh = mp.maxh; } bool changed; do { mesh.LocalHFunction().ClearFlags(); for (int i = 0; i < adfront.GetNFL(); i++) { FrontLine line = adfront.GetLine(i); Box <3> bbox(adfront.GetPoint(line.L().I1())); bbox.Add(adfront.GetPoint(line.L().I2())); double filld = filldist * bbox.Diam(); bbox.Increase(filld); mesh.LocalHFunction().CutBoundary(bbox); } mesh.LocalHFunction().FindInnerBoxes(adfront, null); npoints.SetSize(0); mesh.LocalHFunction().GetInnerPoints(npoints); changed = false; for (int i = 0; i < npoints.Size(); i++) { if (mesh.LocalHFunction().GetH(npoints[i]) > 1.2 * maxh) { mesh.LocalHFunction().SetH(npoints[i], maxh); changed = true; } } } while (changed); NgProfiler.StopTimer(BlockFillLocalH_timer2); NgProfiler.StartTimer(BlockFillLocalH_timer3); if (debugparam.slowchecks) { (*testout) << "Blockfill with points: " << "\n"; } *testout << "loch = " << mesh.LocalHFunction() << "\n"; *testout << "npoints = " << "\n" << npoints << "\n"; for (int i = 1; i <= npoints.Size(); i++) { if (meshbox.IsIn(npoints.Get(i))) { PointIndex gpnum = mesh.AddPoint(npoints.Get(i)); adfront.AddPoint(npoints.Get(i), gpnum); if (debugparam.slowchecks) { (*testout) << npoints.Get(i) << "\n"; Point <2> p2d(npoints.Get(i)(0), npoints.Get(i)(1)); if (!adfront.Inside(p2d)) { Console.Write("add outside point"); Console.Write("\n"); (*testout) << "outside" << "\n"; } } } } NgProfiler.StopTimer(BlockFillLocalH_timer3); NgProfiler.StartTimer(BlockFillLocalH_timer4); // find outer points loch2.ClearFlags(); for (int i = 0; i < adfront.GetNFL(); i++) { FrontLine line = adfront.GetLine(i); Box <3> bbox(adfront.GetPoint(line.L().I1())); bbox.Add(adfront.GetPoint(line.L().I2())); loch2.SetH(bbox.Center(), bbox.Diam()); } for (int i = 0; i < adfront.GetNFL(); i++) { FrontLine line = adfront.GetLine(i); Box <3> bbox(adfront.GetPoint(line.L().I1())); bbox.Add(adfront.GetPoint(line.L().I2())); bbox.Increase(filldist * bbox.Diam()); loch2.CutBoundary(bbox); } loch2.FindInnerBoxes(adfront, null); // outer points : smooth mesh-grading npoints.SetSize(0); loch2.GetOuterPoints(npoints); for (int i = 1; i <= npoints.Size(); i++) { if (meshbox.IsIn(npoints.Get(i))) { PointIndex gpnum = mesh.AddPoint(npoints.Get(i)); adfront.AddPoint(npoints.Get(i), gpnum); } } NgProfiler.StopTimer(BlockFillLocalH_timer4); }
//C++ TO C# CONVERTER WARNING: The original C++ declaration of the following method implementation was not found: public void Delaunay(Mesh mesh, int domainnr, MeshingParameters mp) { //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer = NgProfiler::CreateTimer("Meshing2::Delaunay - total"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timerstart = NgProfiler::CreateTimer("Meshing2::Delaunay - start"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timerfinish = NgProfiler::CreateTimer("Meshing2::Delaunay - finish"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer1 = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer1a = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental a"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer1b = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental b"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer1c = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental c"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer1d = NgProfiler::CreateTimer("Meshing2::Delaunay - incremental d"); NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(Delaunay_timer); Console.Write("2D Delaunay meshing (in progress)"); Console.Write("\n"); BlockFillLocalH(mesh, mp); NgProfiler.StartTimer(Delaunay_timerstart); // do the delaunay // face bounding box: Box <3> bbox(Box <3> .EMPTY_BOX); for (int i = 0; i < adfront.GetNFL(); i++) { FrontLine line = adfront.GetLine(i); bbox.Add(Point <3> (adfront.GetPoint(line.L [0]))); bbox.Add(Point <3> (adfront.GetPoint(line.L [1]))); } for (int i = 0; i < mesh.LockedPoints().Size(); i++) { bbox.Add(new mesh.Point(mesh.LockedPoints [i])); } Console.Write("bbox = "); Console.Write(bbox); Console.Write("\n"); // external point Vec <3> vdiag = bbox.PMax() - bbox.PMin(); var old_points = mesh.Points().Range(); DelaunayTrig startel = new DelaunayTrig(); startel[0] = mesh.AddPoint(bbox.PMin() + Vec <3> (-8 * vdiag(0), -8 * vdiag(1), 0)); startel[1] = mesh.AddPoint(bbox.PMin() + Vec <3> (+8 * vdiag(0), -8 * vdiag(1), 0)); startel[2] = mesh.AddPoint(bbox.PMin() + Vec <3> (0, 8 * vdiag(1), 0)); Box <3> hbox; hbox.Set(mesh[startel[0]]); hbox.Add(mesh[startel[1]]); hbox.Add(mesh[startel[2]]); Point <3> hp = mesh[startel[0]]; hp(2) = 1; hbox.Add(hp); hp(2) = -1; hbox.Add(hp); BoxTree <3> searchtree(hbox); Array <DelaunayTrig> tempels = new Array <DelaunayTrig>(); startel.CalcCenter(mesh); tempels.Append(startel); searchtree.Insert(startel.BoundingBox(), 0); Array <int> closeels = new Array <int>(); Array <int> intersecting = new Array <int>(); Array <INDEX_2> edges = new Array <INDEX_2>(); // reorder points Array <PointIndex, PointIndex.BASE, PointIndex> mixed = new Array <PointIndex, PointIndex.BASE, PointIndex>(old_points.Size()); int[] prims = { 11, 13, 17, 19, 23, 29, 31, 37 }; int prim; { int i = 0; while (old_points.Size() % prims[i] == 0) { i++; } prim = prims[i]; } foreach (PointIndex pi in old_points) { mixed[pi] = new PointIndex((prim * pi) % old_points.Size() + PointIndex.BASE); } NgProfiler.StopTimer(Delaunay_timerstart); NgProfiler.StartTimer(Delaunay_timer1); foreach (PointIndex i1 in old_points) { PointIndex i = mixed[i1]; NgProfiler.StartTimer(Delaunay_timer1a); Point <3> newp = mesh[i]; intersecting.SetSize(0); edges.SetSize(0); searchtree.GetIntersecting(newp, newp, closeels); // for (int jj = 0; jj < closeels.Size(); jj++) // for (int j = 0; j < tempels.Size(); j++) foreach (int j in closeels) { if (tempels[j][0] < 0) { continue; } Point <3> c = tempels[j].Center(); double r2 = tempels[j].Radius2(); bool inside = Dist2(mesh[i], c) < r2; if (inside) { intersecting.Append(j); } } NgProfiler.StopTimer(Delaunay_timer1a); NgProfiler.StartTimer(Delaunay_timer1b); // find outer edges foreach (var j in intersecting) { DelaunayTrig trig = tempels[j]; for (int k = 0; k < 3; k++) { int p1 = trig[k]; int p2 = trig[(k + 1) % 3]; INDEX_2 edge = new INDEX_2(p1, p2); edge.Sort(); bool found = false; for (int l = 0; l < edges.Size(); l++) { if (edges[l] == edge) { edges.Delete(l); found = true; break; } } if (!found) { edges.Append(edge); } } } NgProfiler.StopTimer(Delaunay_timer1b); NgProfiler.StartTimer(Delaunay_timer1c); /* * for (int j = intersecting.Size()-1; j >= 0; j--) * tempels.Delete (intersecting[j]); */ foreach (int j in intersecting) { searchtree.DeleteElement(j); tempels[j][0] = -1; tempels[j][1] = -1; tempels[j][2] = -1; } NgProfiler.StopTimer(Delaunay_timer1c); NgProfiler.StartTimer(Delaunay_timer1d); foreach (var edge in edges) { DelaunayTrig trig = new DelaunayTrig(edge[0], edge[1], i); trig.CalcCenter(mesh); tempels.Append(trig); searchtree.Insert(trig.BoundingBox(), tempels.Size() - 1); } NgProfiler.StopTimer(Delaunay_timer1d); } NgProfiler.StopTimer(Delaunay_timer1); NgProfiler.StartTimer(Delaunay_timerfinish); foreach (DelaunayTrig trig in tempels) { if (trig[0] < 0) { continue; } Point <3> c = Center(mesh[trig[0]], mesh[trig[1]], mesh[trig[2]]); if (!adfront.Inside(Point <2> (c(0), c(1)))) { continue; } Vec <3> n = Cross(mesh[trig[1]] - mesh[trig[0]], mesh[trig[2]] - mesh[trig[0]]); if (n(2) < 0) { Swap(ref trig[1], ref trig[2]); } Element2d el = new Element2d(trig[0], trig[1], trig[2]); el.SetIndex(domainnr); mesh.AddSurfaceElement(el); } foreach (PointIndex pi in mesh.Points().Range()) { *testout << pi << ": " << mesh[pi].Type() << "\n"; } NgProfiler.StopTimer(Delaunay_timerfinish); }
public void UpdateCoarseGrid() { // cout << "UpdateCoarseGrid" << endl; // if (is_updated) return; NgMPI_Comm comm = mesh.GetCommunicator(); int id = comm.Rank(); int ntasks = comm.Size(); if (ntasks == 1) { return; } Reset(); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer = NgProfiler::CreateTimer("UpdateCoarseGrid"); NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(UpdateCoarseGrid_timer); (*testout) << "UPDATE COARSE GRID PARALLEL TOPOLOGY " << "\n"; if (id == 0) { PrintMessage(1, "update parallel topology"); } // UpdateCoarseGridGlobal(); // MPI_Barrier (MPI_COMM_WORLD); MPI_Group MPI_GROUP_comm = new MPI_Group(); MPI_Group MPI_LocalGroup = new MPI_Group(); MPI_Comm MPI_LocalComm = new MPI_Comm(); int[] process_ranks = { 0 }; MPI_Comm_group(comm, MPI_GROUP_comm); MPI_Group_excl(MPI_GROUP_comm, 1, process_ranks, MPI_LocalGroup); MPI_Comm_create(comm, MPI_LocalGroup, MPI_LocalComm); if (id == 0) { return; } MeshTopology topology = mesh.GetTopology(); Array <int> cnt_send = new Array <int>(ntasks - 1); // update new vertices after mesh-refinement if (mesh.mlbetweennodes.Size() > 0) { // cout << "UpdateCoarseGrid - vertices" << endl; int newnv = mesh.mlbetweennodes.Size(); loc2distvert.ChangeSize(mesh.mlbetweennodes.Size()); /* * for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++) * { * PointIndex v1 = mesh.mlbetweennodes[pi][0]; * PointIndex v2 = mesh.mlbetweennodes[pi][1]; * if (mesh.mlbetweennodes[pi][0] != PointIndex::BASE-1) * for (int dest = 1; dest < ntasks; dest++) * if (IsExchangeVert (dest, v1) && IsExchangeVert (dest, v2)) * SetDistantPNum(dest, pi); * } */ bool changed = true; while (changed) { changed = false; // build exchange vertices cnt_send = 0; foreach (PointIndex pi in mesh.Points().Range()) { foreach (int dist in GetDistantPNums(pi - PointIndex.BASE)) { cnt_send[dist - 1]++; } } TABLE <int> dest2vert = new TABLE <int>(cnt_send); foreach (PointIndex pi in mesh.Points().Range()) { foreach (int dist in GetDistantPNums(pi - PointIndex.BASE)) { dest2vert.Add(dist - 1, pi); } } for (PointIndex pi = PointIndex.BASE; pi < newnv + PointIndex.BASE; pi++) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1) { // for (int dest = 1; dest < ntasks; dest++) foreach (int dest in GetDistantPNums(v1 - PointIndex.BASE)) { if (IsExchangeVert(dest, new netgen.PointIndex(v1)) && IsExchangeVert(dest, new netgen.PointIndex(v2))) { cnt_send[dest - 1]++; } } } } TABLE <int> dest2pair = new TABLE <int>(cnt_send); // for (int dest = 1; dest < ntasks; dest++) for (PointIndex pi = PointIndex.BASE; pi < newnv + PointIndex.BASE; pi++) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1) { foreach (int dest in GetDistantPNums(v1 - PointIndex.BASE)) { if (IsExchangeVert(dest, new netgen.PointIndex(v1)) && IsExchangeVert(dest, new netgen.PointIndex(v2))) { dest2pair.Add(dest - 1, pi); } } } } cnt_send = 0; int v1; int v2; for (PointIndex pi = PointIndex.BASE; pi < newnv + PointIndex.BASE; pi++) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1) { foreach (int dest in GetDistantPNums(v1 - PointIndex.BASE)) { if (IsExchangeVert(dest, new netgen.PointIndex(v2))) { cnt_send[dest - 1] += 2; } } } } TABLE <int> send_verts = new TABLE <int>(cnt_send); Array <int, PointIndex.BASE> loc2exchange = new Array <int, PointIndex.BASE>(mesh.GetNV()); for (int dest = 1; dest < ntasks; dest++) { if (dest != id) { loc2exchange = -1; int cnt = 0; /* * for (PointIndex pi : mesh.Points().Range()) * if (IsExchangeVert(dest, pi)) * loc2exchange[pi] = cnt++; */ foreach (PointIndex pi in dest2vert[dest - 1]) { loc2exchange[pi] = cnt++; } // for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++) foreach (PointIndex pi in dest2pair[dest - 1]) { PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1) { if (IsExchangeVert(dest, new netgen.PointIndex(v1)) && IsExchangeVert(dest, new netgen.PointIndex(v2))) { send_verts.Add(dest - 1, loc2exchange[v1]); send_verts.Add(dest - 1, loc2exchange[v2]); } } } } } TABLE <int> recv_verts = new TABLE <int>(ntasks - 1); netgen.GlobalMembers.MyMPI_ExchangeTable(send_verts, recv_verts, MPI_TAG_MESH + 9, MPI_LocalComm); for (int dest = 1; dest < ntasks; dest++) { if (dest != id) { loc2exchange = -1; int cnt = 0; /* * for (PointIndex pi : mesh.Points().Range()) * if (IsExchangeVert(dest, pi)) * loc2exchange[pi] = cnt++; */ foreach (PointIndex pi in dest2vert[dest - 1]) { loc2exchange[pi] = cnt++; } FlatArray <int> recvarray = recv_verts[dest - 1]; for (int ii = 0; ii < recvarray.Size(); ii += 2) { foreach (PointIndex pi in dest2pair[dest - 1]) { // for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++) PointIndex v1 = mesh.mlbetweennodes[pi][0]; PointIndex v2 = mesh.mlbetweennodes[pi][1]; if (mesh.mlbetweennodes[pi][0] != PointIndex.BASE - 1) { INDEX_2 re = new INDEX_2(recvarray[ii], recvarray[ii + 1]); INDEX_2 es = new INDEX_2(loc2exchange[v1], loc2exchange[v2]); if (es == re && !IsExchangeVert(dest, new netgen.PointIndex(pi))) { SetDistantPNum(dest, new netgen.PointIndex(pi)); changed = true; } } } } } } } } Array <int> sendarray = new Array <int>(); Array <int> recvarray = new Array <int>(); // cout << "UpdateCoarseGrid - edges" << endl; // static int timerv = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex vertices"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timere = NgProfiler::CreateTimer("UpdateCoarseGrid - ex edges"); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timerf = NgProfiler::CreateTimer("UpdateCoarseGrid - ex faces"); NgProfiler.StartTimer(UpdateCoarseGrid_timere); int nfa = topology.GetNFaces(); int ned = topology.GetNEdges(); // build exchange vertices cnt_send = 0; foreach (PointIndex pi in mesh.Points().Range()) { foreach (int dist in GetDistantPNums(pi - PointIndex.BASE)) { cnt_send[dist - 1]++; } } TABLE <int> dest2vert = new TABLE <int>(cnt_send); foreach (PointIndex pi in mesh.Points().Range()) { foreach (int dist in GetDistantPNums(pi - PointIndex.BASE)) { dest2vert.Add(dist - 1, pi); } } // exchange edges cnt_send = 0; int v1; int v2; for (int edge = 1; edge <= ned; edge++) { topology.GetEdgeVertices(edge, ref v1, ref v2); for (int dest = 1; dest < ntasks; dest++) { if (IsExchangeVert(dest, v1) && IsExchangeVert(dest, v2)) { cnt_send[dest - 1] += 1; } } } TABLE <int> dest2edge = new TABLE <int>(cnt_send); foreach (int v in cnt_send) { v *= 2; } TABLE <int> send_edges = new TABLE <int>(cnt_send); for (int edge = 1; edge <= ned; edge++) { topology.GetEdgeVertices(edge, ref v1, ref v2); for (int dest = 1; dest < ntasks; dest++) { if (IsExchangeVert(dest, v1) && IsExchangeVert(dest, v2)) { dest2edge.Add(dest - 1, edge); } } } Array <int, PointIndex.BASE> loc2exchange = new Array <int, PointIndex.BASE>(mesh.GetNV()); for (int dest = 1; dest < ntasks; dest++) { loc2exchange = -1; int cnt = 0; foreach (PointIndex pi in dest2vert[dest - 1]) { loc2exchange[pi] = cnt++; } foreach (int edge in dest2edge[dest - 1]) { topology.GetEdgeVertices(edge, ref v1, ref v2); if (IsExchangeVert(dest, v1) && IsExchangeVert(dest, v2)) { send_edges.Add(dest - 1, loc2exchange[v1]); send_edges.Add(dest - 1, loc2exchange[v2]); } } } // cout << "UpdateCoarseGrid - edges mpi-exchange" << endl; TABLE <int> recv_edges = new TABLE <int>(ntasks - 1); netgen.GlobalMembers.MyMPI_ExchangeTable(send_edges, recv_edges, MPI_TAG_MESH + 9, MPI_LocalComm); // cout << "UpdateCoarseGrid - edges mpi-exchange done" << endl; /* * for (int dest = 1; dest < ntasks; dest++) * { * auto ex2loc = dest2vert[dest-1]; * FlatArray<int> recvarray = recv_edges[dest-1]; * for (int ii = 0; ii < recvarray.Size(); ii+=2) * for (int edge : dest2edge[dest-1]) * { * topology.GetEdgeVertices (edge, v1, v2); * INDEX_2 re(ex2loc[recvarray[ii]], * ex2loc[recvarray[ii+1]]); * INDEX_2 es(v1, v2); * if (es == re) * SetDistantEdgeNum(dest, edge); * } * } */ for (int dest = 1; dest < ntasks; dest++) { var ex2loc = dest2vert[dest - 1]; if (ex2loc.Size() == 0) { continue; } INDEX_2_CLOSED_HASHTABLE <int> vert2edge = new INDEX_2_CLOSED_HASHTABLE <int>((uint)(2 * dest2edge[dest - 1].Size() + 10)); foreach (int edge in dest2edge[dest - 1]) { topology.GetEdgeVertices(edge, ref v1, ref v2); vert2edge.Set(new INDEX_2(v1, v2), edge); } FlatArray <int> recvarray = recv_edges[dest - 1]; for (int ii = 0; ii < recvarray.Size(); ii += 2) { INDEX_2 re = new INDEX_2(ex2loc[recvarray[ii]], ex2loc[recvarray[ii + 1]]); if (vert2edge.Used(re)) { SetDistantEdgeNum(dest, vert2edge.Get(re)); } } } NgProfiler.StopTimer(UpdateCoarseGrid_timere); // MPI_Barrier (MPI_LocalComm); // cout << "UpdateCoarseGrid - faces" << endl; if (mesh.GetDimension() == 3) { NgProfiler.StartTimer(UpdateCoarseGrid_timerf); Array <int> verts = new Array <int>(); // exchange faces cnt_send = 0; for (int face = 1; face <= nfa; face++) { topology.GetFaceVertices(face, verts); for (int dest = 1; dest < ntasks; dest++) { if (dest != id) { if (IsExchangeVert(dest, verts[0]) && IsExchangeVert(dest, verts[1]) && IsExchangeVert(dest, verts[2])) { cnt_send[dest - 1]++; } } } } TABLE <int> dest2face = new TABLE <int>(cnt_send); for (int face = 1; face <= nfa; face++) { topology.GetFaceVertices(face, verts); for (int dest = 1; dest < ntasks; dest++) { if (dest != id) { if (IsExchangeVert(dest, verts[0]) && IsExchangeVert(dest, verts[1]) && IsExchangeVert(dest, verts[2])) { dest2face.Add(dest - 1, face); } } } } foreach (int c in cnt_send) { c *= 3; } TABLE <int> send_faces = new TABLE <int>(cnt_send); Array <int, PointIndex.BASE> loc2exchange = new Array <int, PointIndex.BASE>(mesh.GetNV()); for (int dest = 1; dest < ntasks; dest++) { if (dest != id) { /* * loc2exchange = -1; * int cnt = 0; * for (PointIndex pi : mesh.Points().Range()) * if (IsExchangeVert(dest, pi)) * loc2exchange[pi] = cnt++; */ if (dest2vert[dest - 1].Size() == 0) { continue; } loc2exchange = -1; int cnt = 0; foreach (PointIndex pi in dest2vert[dest - 1]) { loc2exchange[pi] = cnt++; } foreach (int face in dest2face[dest - 1]) { topology.GetFaceVertices(face, verts); if (IsExchangeVert(dest, verts[0]) && IsExchangeVert(dest, verts[1]) && IsExchangeVert(dest, verts[2])) { send_faces.Add(dest - 1, loc2exchange[verts[0]]); send_faces.Add(dest - 1, loc2exchange[verts[1]]); send_faces.Add(dest - 1, loc2exchange[verts[2]]); } } } } // cout << "UpdateCoarseGrid - faces mpi-exchange" << endl; TABLE <int> recv_faces = new TABLE <int>(ntasks - 1); netgen.GlobalMembers.MyMPI_ExchangeTable(send_faces, recv_faces, MPI_TAG_MESH + 9, MPI_LocalComm); // cout << "UpdateCoarseGrid - faces mpi-exchange done" << endl; /* * for (int dest = 1; dest < ntasks; dest++) * if (dest != id) * { * loc2exchange = -1; * int cnt = 0; * for (PointIndex pi : dest2vert[dest-1]) * loc2exchange[pi] = cnt++; * * FlatArray<int> recvarray = recv_faces[dest-1]; * for (int ii = 0; ii < recvarray.Size(); ii+=3) * for (int face : dest2face[dest-1]) * { * topology.GetFaceVertices (face, verts); * INDEX_3 re(recvarray[ii], recvarray[ii+1], recvarray[ii+2]); * INDEX_3 es(loc2exchange[verts[0]], loc2exchange[verts[1]], loc2exchange[verts[2]]); * if (es == re) * SetDistantFaceNum(dest, face); * } * } */ for (int dest = 1; dest < ntasks; dest++) { var ex2loc = dest2vert[dest - 1]; if (ex2loc.Size() == 0) { continue; } INDEX_3_CLOSED_HASHTABLE <int> vert2face = new INDEX_3_CLOSED_HASHTABLE <int>(2 * dest2face[dest - 1].Size() + 10); foreach (int face in dest2face[dest - 1]) { topology.GetFaceVertices(face, verts); vert2face.Set(new INDEX_3(verts[0], verts[1], verts[2]), face); } FlatArray <int> recvarray = recv_faces[dest - 1]; for (int ii = 0; ii < recvarray.Size(); ii += 3) { INDEX_3 re = new INDEX_3(ex2loc[recvarray[ii]], ex2loc[recvarray[ii + 1]], ex2loc[recvarray[ii + 2]]); if (vert2face.Used(re)) { SetDistantFaceNum(dest, vert2face.Get(re)); } } } /* * Array<int,1> glob2loc; * * int maxface = 0; * for (int face = 1; face <= nfa; face++) * maxface = max (maxface, GetGlobalFaceNum (face)); * * // glob2loc.SetSize (nfaglob); * glob2loc.SetSize (maxface); * glob2loc = -1; * * for (int loc = 1; loc <= nfa; loc++) * glob2loc[GetGlobalFaceNum(loc)] = loc; * * cnt_send = 0; * Array<int> verts; * for (int face = 1; face <= nfa; face++) * { * topology.GetFaceVertices (face, verts); * for (int dest = 1; dest < ntasks; dest++) * if (IsExchangeVert (dest, verts[0]) && * IsExchangeVert (dest, verts[1]) && * IsExchangeVert (dest, verts[2])) * { * cnt_send[dest-1]+=2; * } * } * * TABLE<int> send_faces(cnt_send); * for (int face = 1; face <= nfa; face++) * { * topology.GetFaceVertices (face, verts); * for (int dest = 1; dest < ntasks; dest++) * { * if (IsExchangeVert (dest, verts[0]) && * IsExchangeVert (dest, verts[1]) && * IsExchangeVert (dest, verts[2])) * { * send_faces.Add (dest-1, GetGlobalFaceNum(face)); * send_faces.Add (dest-1, face); * } * } * } * TABLE<int> recv_faces(ntasks-1); * MyMPI_ExchangeTable (send_faces, recv_faces, MPI_TAG_MESH+8, MPI_LocalComm); * * for (int sender = 1; sender < ntasks; sender ++) * if (id != sender) * { * FlatArray<int> recvarray = recv_faces[sender-1]; * * for (int ii = 0; ii < recvarray.Size(); ) * { * int globf = recvarray[ii++]; * int distf = recvarray[ii++]; * * if (globf <= maxface) * { * int locf = glob2loc[globf]; * if (locf != -1) * SetDistantFaceNum (sender, locf); * } * } * } */ NgProfiler.StopTimer(UpdateCoarseGrid_timerf); } // cout << "UpdateCoarseGrid - done" << endl; is_updated = true; }
public void EdgeSwapping(Mesh mesh, int usemetric) { if (!faceindex) { if (usemetric != 0) { PrintMessage(3, "Edgeswapping, metric"); } else { PrintMessage(3, "Edgeswapping, topological"); } for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) { EdgeSwapping(mesh, usemetric); if (multithread.terminate) { throw new Exception("Meshing stopped"); } } faceindex = 0; mesh.CalcSurfacesOfNode(); return; } //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer = NgProfiler::CreateTimer("EdgeSwapping 2D"); NgProfiler.RegionTimer reg1 = new NgProfiler.RegionTimer(EdgeSwapping_timer); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timerstart = NgProfiler::CreateTimer("EdgeSwapping 2D start"); NgProfiler.StartTimer(EdgeSwapping_timerstart); Array <SurfaceElementIndex> seia = new Array <SurfaceElementIndex>(); mesh.GetSurfaceElementsOfFace(faceindex, seia); for (int i = 0; i < seia.Size(); i++) { if (mesh[seia[i]].GetNP() != 3) { GenericImprove(mesh); return; } } int surfnr = mesh.GetFaceDescriptor(faceindex).SurfNr(); Array <Neighbour> neighbors = new Array <Neighbour>(mesh.GetNSE()); INDEX_2_HASHTABLE <trionedge> other = new INDEX_2_HASHTABLE <trionedge>(seia.Size() + 2); Array <char> swapped = new Array <char>(mesh.GetNSE()); Array <int, PointIndex.BASE> pdef = new Array <int, PointIndex.BASE>(mesh.GetNP()); Array <double, PointIndex.BASE> pangle = new Array <double, PointIndex.BASE>(mesh.GetNP()); // int e; // double d; // Vec3d nv1, nv2; // double loch(-1); double[] minangle = { 0, 1.481, 2.565, 3.627, 4.683, 5.736, 7, 9 }; for (int i = 0; i < seia.Size(); i++) { Element2d sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) { pangle[sel[j]] = 0.0; } } // pangle = 0; for (int i = 0; i < seia.Size(); i++) { Element2d sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) { POINTTYPE typ = mesh[sel[j]].Type(); if (typ == FIXEDPOINT || typ == EDGEPOINT) { pangle[sel[j]] += Angle(mesh[sel[(j + 1) % 3]] - mesh[sel[j]], mesh[sel[(j + 2) % 3]] - mesh[sel[j]]); } } } // for (PointIndex pi = PointIndex::BASE; // pi < mesh.GetNP()+PointIndex::BASE; pi++) // pdef = 0; for (int i = 0; i < seia.Size(); i++) { Element2d sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) { PointIndex pi = sel[j]; if (mesh[pi].Type() == INNERPOINT || mesh[pi].Type() == SURFACEPOINT) { pdef[pi] = -6; } else { for (int j = 0; j < 8; j++) { if (pangle[pi] >= minangle[j]) { pdef[pi] = -1 - j; } } } } } for (int i = 0; i < seia.Size(); i++) { Element2d sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) { pdef[sel[j]]++; } } for (int i = 0; i < seia.Size(); i++) { for (int j = 0; j < 3; j++) { neighbors[seia[i]].SetNr(j, -1); neighbors[seia[i]].SetOrientation(j, 0); } } /* * Array<Vec3d> normals(mesh.GetNP()); * for (i = 1; i <= mesh.GetNSE(); i++) * { * Element2d & hel = mesh.SurfaceElement(i); * if (hel.GetIndex() == faceindex) * for (k = 1; k <= 3; k++) * { * int pi = hel.PNum(k); * SelectSurfaceOfPoint (mesh.Point(pi), hel.GeomInfoPi(k)); * int surfi = mesh.GetFaceDescriptor(faceindex).SurfNr(); * GetNormalVector (surfi, mesh.Point(pi), normals.Elem(pi)); * normals.Elem(pi) /= normals.Elem(pi).Length(); * } * } */ for (int i = 0; i < seia.Size(); i++) { Element2d sel = mesh[seia[i]]; for (int j = 0; j < 3; j++) { PointIndex pi1 = sel.PNumMod(j + 2); PointIndex pi2 = sel.PNumMod(j + 3); // double loch = mesh.GetH(mesh[pi1]); INDEX_2 edge = new INDEX_2(pi1, pi2); edge.Sort(); if (mesh.IsSegment(pi1, pi2)) { continue; } /* * if (segments.Used (edge)) * continue; */ INDEX_2 ii2 = new INDEX_2(pi1, pi2); if (other.Used(ii2)) { // INDEX_2 i2s(ii2); // i2s.Sort(); int i2 = other.Get(ii2).tnr; int j2 = other.Get(ii2).sidenr; neighbors[seia[i]].SetNr(j, i2); neighbors[seia[i]].SetOrientation(j, j2); neighbors[i2].SetNr(j2, seia[i]); neighbors[i2].SetOrientation(j2, j); } else { other.Set(new INDEX_2(pi2, pi1), new trionedge(seia[i], j)); } } } for (int i = 0; i < seia.Size(); i++) { swapped[seia[i]] = 0; } NgProfiler.StopTimer(EdgeSwapping_timerstart); int t = 4; int done = 0; while (done == 0 && t >= 2) { for (int i = 0; i < seia.Size(); i++) { SurfaceElementIndex t1 = seia[i]; if (mesh[t1].IsDeleted()) { continue; } if (mesh[t1].GetIndex() != faceindex) { continue; } if (multithread.terminate) { throw new Exception("Meshing stopped"); } for (int o1 = 0; o1 < 3; o1++) { bool should; SurfaceElementIndex t2 = neighbors[t1].GetNr(o1); int o2 = neighbors[t1].GetOrientation(o1); if (t2 == -1) { continue; } if (swapped[t1] || swapped[t2]) { continue; } PointIndex pi1 = mesh[t1].PNumMod(o1 + 1 + 1); PointIndex pi2 = mesh[t1].PNumMod(o1 + 1 + 2); PointIndex pi3 = mesh[t1].PNumMod(o1 + 1); PointIndex pi4 = mesh[t2].PNumMod(o2 + 1); PointGeomInfo gi1 = mesh[t1].GeomInfoPiMod(o1 + 1 + 1); PointGeomInfo gi2 = mesh[t1].GeomInfoPiMod(o1 + 1 + 2); PointGeomInfo gi3 = mesh[t1].GeomInfoPiMod(o1 + 1); PointGeomInfo gi4 = mesh[t2].GeomInfoPiMod(o2 + 1); bool allowswap = true; Vec <3> auxvec1 = mesh[pi3] - mesh[pi4]; Vec <3> auxvec2 = mesh[pi1] - mesh[pi4]; allowswap = allowswap && ngsimd.GlobalMembers.fabs(1.0 - (auxvec1 * auxvec2) / (auxvec1.Length() * auxvec2.Length())) > 1e-4; if (!allowswap) { continue; } // normal of new Vec <3> nv1 = netgen.GlobalMembers.Cross(auxvec1, auxvec2); auxvec1 = new mesh.Point(pi4) - new mesh.Point(pi3); auxvec2 = new mesh.Point(pi2) - new mesh.Point(pi3); allowswap = allowswap && ngsimd.GlobalMembers.fabs(1.0 - (auxvec1 * auxvec2) / (auxvec1.Length() * auxvec2.Length())) > 1e-4; if (!allowswap) { continue; } Vec <3> nv2 = netgen.GlobalMembers.Cross(auxvec1, auxvec2); // normals of original Vec <3> nv3 = netgen.GlobalMembers.Cross(mesh[pi1] - mesh[pi4], mesh[pi2] - mesh[pi4]); Vec <3> nv4 = netgen.GlobalMembers.Cross(mesh[pi2] - mesh[pi3], mesh[pi1] - mesh[pi3]); nv3 *= -1; nv4 *= -1; nv3.Normalize(); nv4.Normalize(); nv1.Normalize(); nv2.Normalize(); Vec <3> nvp3, nvp4; SelectSurfaceOfPoint(new mesh.Point(pi3), gi3); GetNormalVector(surfnr, new mesh.Point(pi3), gi3, nvp3); nvp3.Normalize(); SelectSurfaceOfPoint(new mesh.Point(pi4), gi4); GetNormalVector(surfnr, new mesh.Point(pi4), gi4, nvp4); nvp4.Normalize(); double critval = ngsimd.GlobalMembers.cos(DefineConstants.M_PI / 6); // 30 degree allowswap = allowswap && (nv1 * nvp3 > critval) && (nv1 * nvp4 > critval) && (nv2 * nvp3 > critval) && (nv2 * nvp4 > critval) && (nvp3 * nv3 > critval) && (nvp4 * nv4 > critval); double horder = netgen.GlobalMembers.Dist(new mesh.Point(pi1), new mesh.Point(pi2)); if (nv1.Length() > 1e-3 * horder * horder && nv2.Length() > 1e-3 * horder * horder && allowswap) { if (usemetric == 0) { int e = pdef[pi1] + pdef[pi2] - pdef[pi3] - pdef[pi4]; double d = netgen.GlobalMembers.Dist2(new mesh.Point(pi1), new mesh.Point(pi2)) - netgen.GlobalMembers.Dist2(new mesh.Point(pi3), new mesh.Point(pi4)); should = e >= t && (e > 2 || d > 0); } else { double loch = mesh.GetH(mesh[pi1]); should = CalcTriangleBadness(new mesh.Point(pi4), new mesh.Point(pi3), new mesh.Point(pi1), metricweight, loch) + CalcTriangleBadness(new mesh.Point(pi3), new mesh.Point(pi4), new mesh.Point(pi2), metricweight, loch) < CalcTriangleBadness(new mesh.Point(pi1), new mesh.Point(pi2), new mesh.Point(pi3), metricweight, loch) + CalcTriangleBadness(new mesh.Point(pi2), new mesh.Point(pi1), new mesh.Point(pi4), metricweight, loch); } if (allowswap) { Element2d sw1 = new Element2d(pi4, pi3, pi1); Element2d sw2 = new Element2d(pi3, pi4, pi2); int legal1 = mesh.LegalTrig(mesh.SurfaceElement(t1)) + mesh.LegalTrig(mesh.SurfaceElement(t2)); int legal2 = mesh.LegalTrig(sw1) + mesh.LegalTrig(sw2); if (legal1 < legal2) { should = true; } if (legal2 < legal1) { should = false; } } if (should) { // do swapping ! done = 1; mesh[t1].PNum(1) = pi1; mesh[t1].PNum(2) = pi4; mesh[t1].PNum(3) = pi3; mesh[t2].PNum(1) = pi2; mesh[t2].PNum(2) = pi3; mesh[t2].PNum(3) = pi4; mesh[t1].GeomInfoPi(1) = gi1; mesh[t1].GeomInfoPi(2) = gi4; mesh[t1].GeomInfoPi(3) = gi3; mesh[t2].GeomInfoPi(1) = gi2; mesh[t2].GeomInfoPi(2) = gi3; mesh[t2].GeomInfoPi(3) = gi4; pdef[pi1]--; pdef[pi2]--; pdef[pi3]++; pdef[pi4]++; swapped[t1] = 1; swapped[t2] = 1; } } } } t--; } mesh.SetNextTimeStamp(); }
public void CombineImprove(Mesh mesh) { if (!faceindex) { PrintMessage(3, "Combine improve"); for (faceindex = 1; faceindex <= mesh.GetNFD(); faceindex++) { CombineImprove(mesh); if (multithread.terminate) { throw new Exception("Meshing stopped"); } } faceindex = 0; return; } //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timer = NgProfiler::CreateTimer("Combineimprove 2D"); NgProfiler.RegionTimer reg = new NgProfiler.RegionTimer(CombineImprove_timer); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timerstart = NgProfiler::CreateTimer("Combineimprove 2D start"); NgProfiler.StartTimer(CombineImprove_timerstart); //C++ TO C# CONVERTER NOTE: This static local variable declaration (not allowed in C#) has been moved just prior to the method: // static int timerstart1 = NgProfiler::CreateTimer("Combineimprove 2D start1"); NgProfiler.StartTimer(CombineImprove_timerstart1); // int i, j, k, l; // PointIndex pi; // SurfaceElementIndex sei; Array <SurfaceElementIndex> seia = new Array <SurfaceElementIndex>(); mesh.GetSurfaceElementsOfFace(faceindex, seia); for (int i = 0; i < seia.Size(); i++) { if (mesh[seia[i]].GetNP() != 3) { return; } } int surfnr = 0; if (faceindex) { surfnr = mesh.GetFaceDescriptor(faceindex).SurfNr(); } // PointIndex pi1, pi2; // MeshPoint p1, p2, pnew; double bad1; double bad2; Vec <3> nv; int np = mesh.GetNP(); //int nse = mesh.GetNSE(); TABLE <SurfaceElementIndex, PointIndex.BASE> elementsonnode = new TABLE <SurfaceElementIndex, PointIndex.BASE>(np); Array <SurfaceElementIndex> hasonepi = new Array <SurfaceElementIndex>(); Array <SurfaceElementIndex> hasbothpi = new Array <SurfaceElementIndex>(); for (int i = 0; i < seia.Size(); i++) { Element2d el = mesh[seia[i]]; for (int j = 0; j < el.GetNP(); j++) { elementsonnode.Add(el[j], seia[i]); } } Array <bool, PointIndex.BASE> @fixed = new Array <bool, PointIndex.BASE>(np); @fixed = false; NgProfiler.StopTimer(CombineImprove_timerstart1); /* * for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++) * { * INDEX_2 i2(mesh[si][0], mesh[si][1]); * fixed[i2.I1()] = true; * fixed[i2.I2()] = true; * } */ for (int i = 0; i < seia.Size(); i++) { Element2d sel = mesh[seia[i]]; for (int j = 0; j < sel.GetNP(); j++) { PointIndex pi1 = sel.PNumMod(j + 2); PointIndex pi2 = sel.PNumMod(j + 3); if (mesh.IsSegment(pi1, pi2)) { @fixed[pi1] = true; @fixed[pi2] = true; } } } for (int i = 0; i < mesh.LockedPoints().Size(); i++) { @fixed[mesh.LockedPoints()[i]] = true; } Array <Vec <3>, PointIndex.BASE> normals = new Array <Vec <3>, PointIndex.BASE>(np); for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) { if (elementsonnode[pi].Size()) { Element2d hel = mesh[elementsonnode[pi][0]]; for (int k = 0; k < 3; k++) { if (hel[k] == pi) { SelectSurfaceOfPoint(mesh[pi], hel.GeomInfoPi(k + 1)); GetNormalVector(surfnr, mesh[pi], hel.GeomInfoPi(k + 1), normals[pi]); break; } } } } NgProfiler.StopTimer(CombineImprove_timerstart); for (int i = 0; i < seia.Size(); i++) { SurfaceElementIndex sei = seia[i]; Element2d elem = mesh[sei]; if (elem.IsDeleted()) { continue; } for (int j = 0; j < 3; j++) { PointIndex pi1 = elem[j]; PointIndex pi2 = elem[(j + 1) % 3]; if (pi1 < PointIndex.BASE || pi2 < PointIndex.BASE) { continue; } /* * INDEX_2 i2(pi1, pi2); * i2.Sort(); * if (segmentht.Used(i2)) * continue; */ bool debugflag = false; if (debugflag) { (*testout) << "Combineimprove, face = " << faceindex << "pi1 = " << pi1 << " pi2 = " << pi2 << "\n"; } /* * // save version: * if (fixed.Get(pi1) || fixed.Get(pi2)) * continue; * if (pi2 < pi1) swap (pi1, pi2); */ // more general if (@fixed[pi2]) { netgen.GlobalMembers.Swap(ref pi1, ref pi2); } if (@fixed[pi2]) { continue; } double loch = mesh.GetH(mesh[pi1]); INDEX_2 si2 = new INDEX_2(pi1, pi2); si2.Sort(); /* * if (edgetested.Used (si2)) * continue; * edgetested.Set (si2, 1); */ hasonepi.SetSize(0); hasbothpi.SetSize(0); for (int k = 0; k < elementsonnode[pi1].Size(); k++) { Element2d el2 = mesh[elementsonnode[pi1][k]]; if (el2.IsDeleted()) { continue; } if (el2[0] == pi2 || el2[1] == pi2 || el2[2] == pi2) { hasbothpi.Append(elementsonnode[pi1][k]); nv = netgen.GlobalMembers.Cross(new Vec3d(mesh[el2[0]], mesh[el2[1]]), new Vec3d(mesh[el2[0]], mesh[el2[2]])); } else { hasonepi.Append(elementsonnode[pi1][k]); } } Element2d hel = mesh[hasbothpi[0]]; for (int k = 0; k < 3; k++) { if (hel[k] == pi1) { SelectSurfaceOfPoint(mesh[pi1], hel.GeomInfoPi(k + 1)); GetNormalVector(surfnr, mesh[pi1], hel.GeomInfoPi(k + 1), nv); break; } } // nv = normals.Get(pi1); for (int k = 0; k < elementsonnode[pi2].Size(); k++) { Element2d el2 = mesh[elementsonnode[pi2][k]]; if (el2.IsDeleted()) { continue; } if (el2[0] == pi1 || el2[1] == pi1 || el2[2] == pi1) { ; } else { hasonepi.Append(elementsonnode[pi2][k]); } } bad1 = 0; int illegal1 = 0; int illegal2 = 0; for (int k = 0; k < hasonepi.Size(); k++) { Element2d el = mesh[hasonepi[k]]; bad1 += CalcTriangleBadness(mesh[el[0]], mesh[el[1]], mesh[el[2]], nv, -1, loch); illegal1 += 1 - mesh.LegalTrig(el); } for (int k = 0; k < hasbothpi.Size(); k++) { Element2d el = mesh[hasbothpi[k]]; bad1 += CalcTriangleBadness(mesh[el[0]], mesh[el[1]], mesh[el[2]], nv, -1, loch); illegal1 += 1 - mesh.LegalTrig(el); } bad1 /= (hasonepi.Size() + hasbothpi.Size()); MeshPoint p1 = mesh[pi1]; MeshPoint p2 = mesh[pi2]; MeshPoint pnew = new MeshPoint(p1); mesh[pi1] = pnew; mesh[pi2] = pnew; bad2 = 0; for (int k = 0; k < hasonepi.Size(); k++) { Element2d el = mesh[hasonepi[k]]; double err = CalcTriangleBadness(mesh[el[0]], mesh[el[1]], mesh[el[2]], nv, -1, loch); bad2 += err; Vec <3> hnv = netgen.GlobalMembers.Cross(new Vec3d(mesh[el[0]], mesh[el[1]]), new Vec3d(mesh[el[0]], mesh[el[2]])); if (hnv * nv < 0) { bad2 += 1e10; } for (int l = 0; l < 3; l++) { if ((normals[el[l]] * nv) < 0.5) { bad2 += 1e10; } } illegal2 += 1 - mesh.LegalTrig(el); } bad2 /= hasonepi.Size(); mesh[pi1] = p1; mesh[pi2] = p2; if (debugflag) { (*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << "\n"; } bool should = (bad2 < bad1 && bad2 < 1e4); if (bad2 < 1e4) { if (illegal1 > illegal2) { should = true; } if (illegal2 > illegal1) { should = false; } } if (should) { /* * (*testout) << "combine !" << endl; * (*testout) << "bad1 = " << bad1 << ", bad2 = " << bad2 << endl; * (*testout) << "illegal1 = " << illegal1 << ", illegal2 = " << illegal2 << endl; * (*testout) << "loch = " << loch << endl; */ mesh[pi1] = pnew; PointGeomInfo gi = new PointGeomInfo(); // bool gi_set(false); Element2d el1p = new Element2d(null); int l = 0; while (mesh[elementsonnode[pi1][l]].IsDeleted() && l < elementsonnode.EntrySize(pi1)) { l++; } if (l < elementsonnode.EntrySize(pi1)) { el1p = mesh[elementsonnode[pi1][l]]; } else { cerr << "OOPS!" << "\n"; } for (l = 0; l < el1p.GetNP(); l++) { if (el1p[l] == pi1) { gi = el1p.GeomInfoPi(l + 1); // gi_set = true; } } // (*testout) << "Connect point " << pi2 << " to " << pi1 << "\n"; for (int k = 0; k < elementsonnode[pi2].Size(); k++) { Element2d el = mesh[elementsonnode[pi2][k]]; if (el.IsDeleted()) { continue; } elementsonnode.Add(pi1, elementsonnode[pi2][k]); bool haspi1 = false; for (l = 0; l < el.GetNP(); l++) { if (el[l] == pi1) { haspi1 = true; } } if (haspi1) { continue; } for (int l = 0; l < el.GetNP(); l++) { if (el[l] == pi2) { el[l] = pi1; el.GeomInfoPi(l + 1) = gi; } @fixed[el[l]] = true; } } /* * for (k = 0; k < hasbothpi.Size(); k++) * { * cout << mesh[hasbothpi[k]] << endl; * for (l = 0; l < 3; l++) * cout << mesh[mesh[hasbothpi[k]][l]] << " "; * cout << endl; * } */ for (int k = 0; k < hasbothpi.Size(); k++) { mesh[hasbothpi[k]].Delete(); /* * for (l = 0; l < 4; l++) * mesh[hasbothpi[k]][l] = PointIndex::BASE-1; */ } } } } // mesh.Compress(); mesh.SetNextTimeStamp(); }