mirror of
https://github.com/NGSolve/netgen.git
synced 2024-11-15 10:28:34 +05:00
Merge remote-tracking branch 'origin/master' into boundarylayer_fixes
This commit is contained in:
commit
4a95414ec8
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,3 +1,11 @@
|
||||
*.whl
|
||||
dist
|
||||
build
|
||||
*.vol.gz
|
||||
*.vol
|
||||
*.ini
|
||||
__pycache__
|
||||
*.json
|
||||
*.zip
|
||||
.cache
|
||||
*.patch
|
||||
|
@ -1271,9 +1271,6 @@ namespace netgen
|
||||
if (res != MESHING3_OK) return 1;
|
||||
if (multithread.terminate) return 0;
|
||||
|
||||
RemoveIllegalElements (*mesh);
|
||||
if (multithread.terminate) return 0;
|
||||
|
||||
MeshQuality3d (*mesh);
|
||||
}
|
||||
|
||||
|
@ -1625,7 +1625,8 @@ namespace netgen
|
||||
// tempmesh.Save ("tempmesh.vol");
|
||||
|
||||
{
|
||||
MeshOptimize3d meshopt(mp);
|
||||
MeshOptimize3d meshopt(tempmesh, mp);
|
||||
meshopt.SetGoal(OPT_CONFORM);
|
||||
tempmesh.Compress();
|
||||
tempmesh.FindOpenElements ();
|
||||
#ifndef EMSCRIPTEN
|
||||
@ -1638,7 +1639,7 @@ namespace netgen
|
||||
if(i%5==0)
|
||||
tempmesh.FreeOpenElementsEnvironment (1);
|
||||
|
||||
meshopt.SwapImprove(tempmesh, OPT_CONFORM);
|
||||
meshopt.SwapImprove();
|
||||
}
|
||||
tempmesh.Compress();
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ static ArrayMem<Element, 3> SplitElement (Element old, PointIndex pi0, PointInde
|
||||
ArrayMem<Element, 3> new_elements;
|
||||
// split element by cutting edge pi0,pi1 at pinew
|
||||
auto np = old.GetNP();
|
||||
old.Flags().illegal_valid = 0;
|
||||
old.Touch();
|
||||
if(np == 4)
|
||||
{
|
||||
// Split tet into two tets
|
||||
@ -89,7 +89,7 @@ static ArrayMem<Element, 3> SplitElement (Element old, PointIndex pi0, PointInde
|
||||
}
|
||||
|
||||
return new_elements;
|
||||
};
|
||||
}
|
||||
|
||||
static double SplitElementBadness (const Mesh::T_POINTS & points, const MeshingParameters & mp, Element old, PointIndex pi0, PointIndex pi1, MeshPoint & pnew)
|
||||
{
|
||||
@ -133,7 +133,63 @@ static double SplitElementBadness (const Mesh::T_POINTS & points, const MeshingP
|
||||
}
|
||||
|
||||
return badness;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
tuple<double, double, int> MeshOptimize3d :: UpdateBadness()
|
||||
{
|
||||
static Timer tbad("UpdateBadness");
|
||||
RegionTimer reg(tbad);
|
||||
|
||||
double totalbad = 0.0;
|
||||
double maxbad = 0.0;
|
||||
atomic<int> bad_elements = 0;
|
||||
|
||||
ParallelForRange(Range(mesh.GetNE()), [&] (auto myrange) {
|
||||
double totalbad_local = 0.0;
|
||||
double maxbad_local = 0.0;
|
||||
int bad_elements_local = 0;
|
||||
for (ElementIndex ei : myrange)
|
||||
{
|
||||
auto & el = mesh[ei];
|
||||
if(mp.only3D_domain_nr && mp.only3D_domain_nr != el.GetIndex()) continue;
|
||||
if(!el.BadnessValid())
|
||||
el.SetBadness(CalcBad(mesh.Points(), el, 0));
|
||||
double bad = el.GetBadness();
|
||||
totalbad_local += bad;
|
||||
maxbad_local = max(maxbad_local, bad);
|
||||
if(bad > min_badness)
|
||||
bad_elements_local++;
|
||||
}
|
||||
AtomicAdd(totalbad, totalbad_local);
|
||||
AtomicMax(maxbad, maxbad_local);
|
||||
bad_elements += bad_elements_local;
|
||||
});
|
||||
return {totalbad, maxbad, bad_elements};
|
||||
}
|
||||
|
||||
bool MeshOptimize3d :: HasBadElement(FlatArray<ElementIndex> els)
|
||||
{
|
||||
for(auto ei : els)
|
||||
if(mesh[ei].GetBadness()>min_badness)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MeshOptimize3d :: HasIllegalElement(FlatArray<ElementIndex> els)
|
||||
{
|
||||
for(auto ei : els)
|
||||
if(!mesh.LegalTet(mesh[ei]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MeshOptimize3d :: NeedsOptimization(FlatArray<ElementIndex> els)
|
||||
{
|
||||
if(goal == OPT_LEGAL) return HasIllegalElement(els);
|
||||
if(goal == OPT_QUALITY) return HasBadElement(els);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -143,10 +199,8 @@ static double SplitElementBadness (const Mesh::T_POINTS & points, const MeshingP
|
||||
Connect inner point to boundary point, if one
|
||||
point is inner point.
|
||||
*/
|
||||
double MeshOptimize3d :: CombineImproveEdge (Mesh & mesh,
|
||||
const MeshingParameters & mp,
|
||||
double MeshOptimize3d :: CombineImproveEdge (
|
||||
Table<ElementIndex, PointIndex> & elements_of_point,
|
||||
Array<double> & elerrs,
|
||||
PointIndex pi0, PointIndex pi1,
|
||||
FlatArray<bool, PointIndex> is_point_removed,
|
||||
bool check_only)
|
||||
@ -199,9 +253,9 @@ double MeshOptimize3d :: CombineImproveEdge (Mesh & mesh,
|
||||
|
||||
double badness_old = 0.0;
|
||||
for (auto ei : has_one_point)
|
||||
badness_old += elerrs[ei];
|
||||
badness_old += mesh[ei].GetBadness();
|
||||
for (auto ei : has_both_points)
|
||||
badness_old += elerrs[ei];
|
||||
badness_old += mesh[ei].GetBadness();
|
||||
|
||||
MeshPoint pnew = p0;
|
||||
if (p0.Type() == INNERPOINT)
|
||||
@ -232,7 +286,7 @@ double MeshOptimize3d :: CombineImproveEdge (Mesh & mesh,
|
||||
break;
|
||||
}
|
||||
|
||||
elem.Flags().illegal_valid = 0;
|
||||
elem.Touch();
|
||||
if (!mesh.LegalTet(elem))
|
||||
badness_new += 1e4;
|
||||
}
|
||||
@ -255,17 +309,17 @@ double MeshOptimize3d :: CombineImproveEdge (Mesh & mesh,
|
||||
if (elem[l] == pi1)
|
||||
elem[l] = pi0;
|
||||
|
||||
elem.Flags().illegal_valid = 0;
|
||||
elem.Touch();
|
||||
if (!mesh.LegalTet (elem))
|
||||
(*testout) << "illegal tet " << ei << endl;
|
||||
}
|
||||
|
||||
for (auto i : Range(has_one_point))
|
||||
elerrs[has_one_point[i]] = one_point_badness[i];
|
||||
mesh[has_one_point[i]].SetBadness(one_point_badness[i]);
|
||||
|
||||
for (auto ei : has_both_points)
|
||||
{
|
||||
mesh[ei].Flags().illegal_valid = 0;
|
||||
mesh[ei].Touch();
|
||||
mesh[ei].Delete();
|
||||
}
|
||||
}
|
||||
@ -273,14 +327,12 @@ double MeshOptimize3d :: CombineImproveEdge (Mesh & mesh,
|
||||
return d_badness;
|
||||
}
|
||||
|
||||
void MeshOptimize3d :: CombineImprove (Mesh & mesh,
|
||||
OPTIMIZEGOAL goal)
|
||||
void MeshOptimize3d :: CombineImprove ()
|
||||
{
|
||||
static Timer t("MeshOptimize3d::CombineImprove"); RegionTimer reg(t);
|
||||
static Timer topt("Optimize");
|
||||
static Timer tsearch("Search");
|
||||
static Timer tbuild_elements_table("Build elements table");
|
||||
static Timer tbad("CalcBad");
|
||||
|
||||
mesh.BuildBoundaryEdges(false);
|
||||
|
||||
@ -288,7 +340,6 @@ void MeshOptimize3d :: CombineImprove (Mesh & mesh,
|
||||
int ne = mesh.GetNE();
|
||||
int ntasks = 4*ngcore::TaskManager::GetNumThreads();
|
||||
|
||||
Array<double> elerrs (ne);
|
||||
Array<bool, PointIndex> is_point_removed (np);
|
||||
is_point_removed = false;
|
||||
|
||||
@ -300,26 +351,11 @@ void MeshOptimize3d :: CombineImprove (Mesh & mesh,
|
||||
multithread.task = "Optimize Volume: Combine Improve";
|
||||
|
||||
|
||||
tbad.Start();
|
||||
double totalbad = 0.0;
|
||||
ParallelForRange(Range(ne), [&] (auto myrange)
|
||||
{
|
||||
double totalbad_local = 0.0;
|
||||
for (ElementIndex ei : myrange)
|
||||
{
|
||||
if(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh[ei].GetIndex())
|
||||
continue;
|
||||
double elerr = CalcBad (mesh.Points(), mesh[ei], 0);
|
||||
totalbad_local += elerr;
|
||||
elerrs[ei] = elerr;
|
||||
}
|
||||
AtomicAdd(totalbad, totalbad_local);
|
||||
}, ntasks);
|
||||
tbad.Stop();
|
||||
UpdateBadness();
|
||||
|
||||
if (goal == OPT_QUALITY)
|
||||
if (goal == OPT_QUALITY && testout->good())
|
||||
{
|
||||
totalbad = mesh.CalcTotalBad (mp);
|
||||
double totalbad = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << totalbad << endl;
|
||||
}
|
||||
|
||||
@ -338,7 +374,7 @@ void MeshOptimize3d :: CombineImprove (Mesh & mesh,
|
||||
for(auto i : myrange)
|
||||
{
|
||||
auto [p0,p1] = edges[i];
|
||||
double d_badness = CombineImproveEdge (mesh, mp, elementsonnode, elerrs, p0, p1, is_point_removed, true);
|
||||
double d_badness = CombineImproveEdge (elementsonnode, p0, p1, is_point_removed, true);
|
||||
if(d_badness<0.0)
|
||||
{
|
||||
int index = improvement_counter++;
|
||||
@ -360,7 +396,7 @@ void MeshOptimize3d :: CombineImprove (Mesh & mesh,
|
||||
for(auto [d_badness, ei] : edges_with_improvement)
|
||||
{
|
||||
auto [p0,p1] = edges[ei];
|
||||
if (CombineImproveEdge (mesh, mp, elementsonnode, elerrs, p0, p1, is_point_removed, false) < 0.0)
|
||||
if (CombineImproveEdge (elementsonnode, p0, p1, is_point_removed, false) < 0.0)
|
||||
cnt++;
|
||||
}
|
||||
topt.Stop();
|
||||
@ -371,9 +407,9 @@ void MeshOptimize3d :: CombineImprove (Mesh & mesh,
|
||||
PrintMessage (5, cnt, " elements combined");
|
||||
(*testout) << "CombineImprove done" << "\n";
|
||||
|
||||
if (goal == OPT_QUALITY)
|
||||
if (goal == OPT_QUALITY && testout->good())
|
||||
{
|
||||
totalbad = mesh.CalcTotalBad (mp);
|
||||
double totalbad = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << totalbad << endl;
|
||||
|
||||
int cntill = 0;
|
||||
@ -389,7 +425,7 @@ void MeshOptimize3d :: CombineImprove (Mesh & mesh,
|
||||
|
||||
|
||||
|
||||
double MeshOptimize3d :: SplitImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal, Table<ElementIndex,PointIndex> & elementsonnode, Array<double> &elerrs, NgArray<INDEX_3> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only)
|
||||
double MeshOptimize3d :: SplitImproveEdge (Table<ElementIndex,PointIndex> & elementsonnode, NgArray<INDEX_3> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only)
|
||||
{
|
||||
double d_badness = 0.0;
|
||||
// int cnt = 0;
|
||||
@ -418,21 +454,14 @@ double MeshOptimize3d :: SplitImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal, Table
|
||||
if(mp.only3D_domain_nr != mesh[ei].GetIndex())
|
||||
return 0.0;
|
||||
|
||||
if (goal == OPT_LEGAL)
|
||||
{
|
||||
bool all_tets_legal = true;
|
||||
for(auto ei : hasbothpoints)
|
||||
if( !mesh.LegalTet (mesh[ei]) || elerrs[ei] > 1e3)
|
||||
all_tets_legal = false;
|
||||
if(all_tets_legal)
|
||||
return 0.0;
|
||||
}
|
||||
if (!NeedsOptimization(hasbothpoints))
|
||||
return 0.0;
|
||||
|
||||
double bad1 = 0.0;
|
||||
double bad1_max = 0.0;
|
||||
for (ElementIndex ei : hasbothpoints)
|
||||
{
|
||||
double bad = elerrs[ei];
|
||||
double bad = mesh[ei].GetBadness();
|
||||
bad1 += bad;
|
||||
bad1_max = max(bad1_max, bad);
|
||||
}
|
||||
@ -505,9 +534,8 @@ double MeshOptimize3d :: SplitImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal, Table
|
||||
Element newel1 = oldel;
|
||||
Element newel2 = oldel;
|
||||
|
||||
oldel.Flags().illegal_valid = 0;
|
||||
newel1.Flags().illegal_valid = 0;
|
||||
newel2.Flags().illegal_valid = 0;
|
||||
newel1.Touch();
|
||||
newel2.Touch();
|
||||
|
||||
for (int l = 0; l < 4; l++)
|
||||
{
|
||||
@ -536,11 +564,11 @@ double MeshOptimize3d :: SplitImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal, Table
|
||||
Element newel1 = oldel;
|
||||
Element newel2 = oldel;
|
||||
|
||||
oldel.Flags().illegal_valid = 0;
|
||||
oldel.Touch();
|
||||
oldel.Delete();
|
||||
|
||||
newel1.Flags().illegal_valid = 0;
|
||||
newel2.Flags().illegal_valid = 0;
|
||||
newel1.Touch();
|
||||
newel2.Touch();
|
||||
|
||||
for (int l = 0; l < 4; l++)
|
||||
{
|
||||
@ -555,8 +583,7 @@ double MeshOptimize3d :: SplitImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal, Table
|
||||
return d_badness;
|
||||
}
|
||||
|
||||
void MeshOptimize3d :: SplitImprove (Mesh & mesh,
|
||||
OPTIMIZEGOAL goal)
|
||||
void MeshOptimize3d :: SplitImprove ()
|
||||
{
|
||||
static Timer t("MeshOptimize3d::SplitImprove"); RegionTimer reg(t);
|
||||
static Timer topt("Optimize");
|
||||
@ -569,8 +596,6 @@ void MeshOptimize3d :: SplitImprove (Mesh & mesh,
|
||||
|
||||
auto elementsonnode = mesh.CreatePoint2ElementTable(nullopt, mp.only3D_domain_nr);
|
||||
|
||||
Array<double> elerrs(ne);
|
||||
|
||||
const char * savetask = multithread.task;
|
||||
multithread.task = "Optimize Volume: Split Improve";
|
||||
|
||||
@ -578,17 +603,9 @@ void MeshOptimize3d :: SplitImprove (Mesh & mesh,
|
||||
(*testout) << "start SplitImprove" << "\n";
|
||||
mesh.BuildBoundaryEdges(false);
|
||||
|
||||
ParallelFor( mesh.VolumeElements().Range(), [&] (ElementIndex ei) NETGEN_LAMBDA_INLINE
|
||||
{
|
||||
if(mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex())
|
||||
return;
|
||||
UpdateBadness();
|
||||
|
||||
elerrs[ei] = CalcBad (mesh.Points(), mesh[ei], 0);
|
||||
bad += elerrs[ei];
|
||||
AtomicMax(badmax, elerrs[ei]);
|
||||
});
|
||||
|
||||
if (goal == OPT_QUALITY)
|
||||
if (goal == OPT_QUALITY && testout->good())
|
||||
{
|
||||
bad = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << bad << endl;
|
||||
@ -610,7 +627,7 @@ void MeshOptimize3d :: SplitImprove (Mesh & mesh,
|
||||
for(auto i : myrange)
|
||||
{
|
||||
auto [p0,p1] = edges[i];
|
||||
double d_badness = SplitImproveEdge (mesh, goal, elementsonnode, elerrs, locfaces, badmax, p0, p1, ptmp, true);
|
||||
double d_badness = SplitImproveEdge (elementsonnode, locfaces, badmax, p0, p1, ptmp, true);
|
||||
if(d_badness<0.0)
|
||||
{
|
||||
int index = improvement_counter++;
|
||||
@ -633,7 +650,7 @@ void MeshOptimize3d :: SplitImprove (Mesh & mesh,
|
||||
for(auto [d_badness, ei] : edges_with_improvement)
|
||||
{
|
||||
auto [p0,p1] = edges[ei];
|
||||
if (SplitImproveEdge (mesh, goal, elementsonnode, elerrs, locfaces, badmax, p0, p1, ptmp, false) < 0.0)
|
||||
if (SplitImproveEdge (elementsonnode, locfaces, badmax, p0, p1, ptmp, false) < 0.0)
|
||||
cnt++;
|
||||
}
|
||||
topt.Stop();
|
||||
@ -643,8 +660,11 @@ void MeshOptimize3d :: SplitImprove (Mesh & mesh,
|
||||
|
||||
if (goal == OPT_QUALITY)
|
||||
{
|
||||
bad = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << bad << endl;
|
||||
if(testout->good())
|
||||
{
|
||||
bad = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << bad << endl;
|
||||
}
|
||||
|
||||
[[maybe_unused]] int cntill = 0;
|
||||
ne = mesh.GetNE();
|
||||
@ -658,7 +678,7 @@ void MeshOptimize3d :: SplitImprove (Mesh & mesh,
|
||||
}
|
||||
|
||||
|
||||
double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
double MeshOptimize3d :: SwapImproveEdge (
|
||||
const NgBitArray * working_elements,
|
||||
Table<ElementIndex, PointIndex> & elementsonnode,
|
||||
INDEX_3_HASHTABLE<int> & faces,
|
||||
@ -706,8 +726,6 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
}
|
||||
}
|
||||
|
||||
bool have_bad_element = false;
|
||||
|
||||
for (ElementIndex ei : hasbothpoints)
|
||||
{
|
||||
if (mesh[ei].GetType () != TET)
|
||||
@ -727,14 +745,9 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
|
||||
if (mesh[ei].IsDeleted())
|
||||
return 0.0;
|
||||
|
||||
if ((goal == OPT_LEGAL) &&
|
||||
mesh.LegalTet (mesh[ei]) &&
|
||||
CalcBad (mesh.Points(), mesh[ei], 0) >= 1e3)
|
||||
have_bad_element = true;
|
||||
}
|
||||
|
||||
if ((goal == OPT_LEGAL) && !have_bad_element)
|
||||
if(!NeedsOptimization(hasbothpoints))
|
||||
return 0.0;
|
||||
|
||||
int nsuround = hasbothpoints.Size();
|
||||
@ -799,9 +812,9 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
CalcBad (mesh.Points(), el32, 0) +
|
||||
CalcBad (mesh.Points(), el33, 0);
|
||||
|
||||
el31.Flags().illegal_valid = 0;
|
||||
el32.Flags().illegal_valid = 0;
|
||||
el33.Flags().illegal_valid = 0;
|
||||
el31.Touch();
|
||||
el32.Touch();
|
||||
el33.Touch();
|
||||
|
||||
if (!mesh.LegalTet(el31) ||
|
||||
!mesh.LegalTet(el32) ||
|
||||
@ -823,15 +836,15 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
bad2 = CalcBad (mesh.Points(), el21, 0) +
|
||||
CalcBad (mesh.Points(), el22, 0);
|
||||
|
||||
el21.Flags().illegal_valid = 0;
|
||||
el22.Flags().illegal_valid = 0;
|
||||
el21.Touch();
|
||||
el22.Touch();
|
||||
|
||||
if (!mesh.LegalTet(el21) ||
|
||||
!mesh.LegalTet(el22))
|
||||
bad2 += 1e4;
|
||||
|
||||
|
||||
if (goal == OPT_CONFORM && NotTooBad(bad1, bad2))
|
||||
if ((goal == OPT_CONFORM) && NotTooBad(bad1, bad2))
|
||||
{
|
||||
INDEX_3 face(pi3, pi4, pi5);
|
||||
face.Sort();
|
||||
@ -866,8 +879,8 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
mesh[hasbothpoints[1]].Delete();
|
||||
mesh[hasbothpoints[2]].Delete();
|
||||
|
||||
el21.Flags().illegal_valid = 0;
|
||||
el22.Flags().illegal_valid = 0;
|
||||
el21.Touch();
|
||||
el22.Touch();
|
||||
mesh.AddVolumeElement(el21);
|
||||
mesh.AddVolumeElement(el22);
|
||||
}
|
||||
@ -942,10 +955,10 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
CalcBad (mesh.Points(), el4, 0);
|
||||
|
||||
|
||||
el1.Flags().illegal_valid = 0;
|
||||
el2.Flags().illegal_valid = 0;
|
||||
el3.Flags().illegal_valid = 0;
|
||||
el4.Flags().illegal_valid = 0;
|
||||
el1.Touch();
|
||||
el2.Touch();
|
||||
el3.Touch();
|
||||
el4.Touch();
|
||||
|
||||
|
||||
if (goal != OPT_CONFORM)
|
||||
@ -978,10 +991,10 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
CalcBad (mesh.Points(), el3, 0) +
|
||||
CalcBad (mesh.Points(), el4, 0);
|
||||
|
||||
el1.Flags().illegal_valid = 0;
|
||||
el2.Flags().illegal_valid = 0;
|
||||
el3.Flags().illegal_valid = 0;
|
||||
el4.Flags().illegal_valid = 0;
|
||||
el1.Touch();
|
||||
el2.Touch();
|
||||
el3.Touch();
|
||||
el4.Touch();
|
||||
|
||||
if (goal != OPT_CONFORM)
|
||||
{
|
||||
@ -1014,10 +1027,10 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
CalcBad (mesh.Points(), el3b, 0) +
|
||||
CalcBad (mesh.Points(), el4b, 0);
|
||||
|
||||
el1b.Flags().illegal_valid = 0;
|
||||
el2b.Flags().illegal_valid = 0;
|
||||
el3b.Flags().illegal_valid = 0;
|
||||
el4b.Flags().illegal_valid = 0;
|
||||
el1b.Touch();
|
||||
el2b.Touch();
|
||||
el3b.Touch();
|
||||
el4b.Touch();
|
||||
|
||||
if (goal != OPT_CONFORM)
|
||||
{
|
||||
@ -1054,10 +1067,10 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
for (auto i : IntRange(4))
|
||||
mesh[hasbothpoints[i]].Delete();
|
||||
|
||||
el1.Flags().illegal_valid = 0;
|
||||
el2.Flags().illegal_valid = 0;
|
||||
el3.Flags().illegal_valid = 0;
|
||||
el4.Flags().illegal_valid = 0;
|
||||
el1.Touch();
|
||||
el2.Touch();
|
||||
el3.Touch();
|
||||
el4.Touch();
|
||||
mesh.AddVolumeElement (el1);
|
||||
mesh.AddVolumeElement (el2);
|
||||
mesh.AddVolumeElement (el3);
|
||||
@ -1068,10 +1081,10 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
for (auto i : IntRange(4))
|
||||
mesh[hasbothpoints[i]].Delete();
|
||||
|
||||
el1b.Flags().illegal_valid = 0;
|
||||
el2b.Flags().illegal_valid = 0;
|
||||
el3b.Flags().illegal_valid = 0;
|
||||
el4b.Flags().illegal_valid = 0;
|
||||
el1b.Touch();
|
||||
el2b.Touch();
|
||||
el3b.Touch();
|
||||
el4b.Touch();
|
||||
mesh.AddVolumeElement (el1b);
|
||||
mesh.AddVolumeElement (el2b);
|
||||
mesh.AddVolumeElement (el3b);
|
||||
@ -1174,7 +1187,7 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
hel[3] = pi2;
|
||||
|
||||
bad2 += CalcBad (mesh.Points(), hel, 0);
|
||||
hel.Flags().illegal_valid = 0;
|
||||
hel.Touch();
|
||||
if (!mesh.LegalTet(hel)) bad2 += 1e4;
|
||||
|
||||
hel[2] = suroundpts[k % nsuround];
|
||||
@ -1183,7 +1196,7 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
|
||||
bad2 += CalcBad (mesh.Points(), hel, 0);
|
||||
|
||||
hel.Flags().illegal_valid = 0;
|
||||
hel.Touch();
|
||||
if (!mesh.LegalTet(hel)) bad2 += 1e4;
|
||||
}
|
||||
// (*testout) << "bad2," << l << " = " << bad2 << endl;
|
||||
@ -1253,7 +1266,7 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
hel[1] = suroundpts[k % nsuround];
|
||||
hel[2] = suroundpts[(k+1) % nsuround];
|
||||
hel[3] = pi2;
|
||||
hel.Flags().illegal_valid = 0;
|
||||
hel.Touch();
|
||||
|
||||
/*
|
||||
(*testout) << nsuround << "-swap, new el,top = "
|
||||
@ -1289,8 +1302,7 @@ double MeshOptimize3d :: SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
return d_badness;
|
||||
}
|
||||
|
||||
void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
const NgBitArray * working_elements)
|
||||
void MeshOptimize3d :: SwapImprove (const NgBitArray * working_elements)
|
||||
{
|
||||
static Timer t("MeshOptimize3d::SwapImprove"); RegionTimer reg(t);
|
||||
static Timer tloop("MeshOptimize3d::SwapImprove loop");
|
||||
@ -1344,7 +1356,7 @@ void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
}
|
||||
|
||||
// Calculate total badness
|
||||
if (goal == OPT_QUALITY)
|
||||
if (goal == OPT_QUALITY && testout->good())
|
||||
{
|
||||
double bad1 = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << bad1 << endl;
|
||||
@ -1356,6 +1368,8 @@ void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
Array<std::tuple<double, int>> candidate_edges(edges.Size());
|
||||
std::atomic<int> improvement_counter(0);
|
||||
|
||||
UpdateBadness();
|
||||
|
||||
tloop.Start();
|
||||
|
||||
auto num_elements_before = mesh.VolumeElements().Range().Next();
|
||||
@ -1368,7 +1382,7 @@ void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
break;
|
||||
|
||||
auto [pi0, pi1] = edges[i];
|
||||
double d_badness = SwapImproveEdge (mesh, goal, working_elements, elementsonnode, faces, pi0, pi1, true);
|
||||
double d_badness = SwapImproveEdge (working_elements, elementsonnode, faces, pi0, pi1, true);
|
||||
if(d_badness<0.0)
|
||||
{
|
||||
int index = improvement_counter++;
|
||||
@ -1383,7 +1397,7 @@ void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
for(auto [d_badness, ei] : edges_with_improvement)
|
||||
{
|
||||
auto [pi0,pi1] = edges[ei];
|
||||
if(SwapImproveEdge (mesh, goal, working_elements, elementsonnode, faces, pi0, pi1, false) < 0.0)
|
||||
if(SwapImproveEdge (working_elements, elementsonnode, faces, pi0, pi1, false) < 0.0)
|
||||
cnt++;
|
||||
}
|
||||
|
||||
@ -1425,7 +1439,7 @@ void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
|
||||
|
||||
|
||||
void MeshOptimize3d :: SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
void MeshOptimize3d :: SwapImproveSurface (
|
||||
const NgBitArray * working_elements,
|
||||
const NgArray< NgArray<int,PointIndex::BASE>* > * idmaps)
|
||||
{
|
||||
@ -1517,9 +1531,7 @@ void MeshOptimize3d :: SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
if (mesh[ei].IsDeleted())
|
||||
continue;
|
||||
|
||||
if ((goal == OPT_LEGAL) &&
|
||||
mesh.LegalTet (mesh[ei]) &&
|
||||
CalcBad (mesh.Points(), mesh[ei], 0) < 1e3)
|
||||
if (goal == OPT_LEGAL && mesh.LegalTet (mesh[ei]))
|
||||
continue;
|
||||
|
||||
const Element & elemi = mesh[ei];
|
||||
@ -2287,7 +2299,7 @@ void MeshOptimize3d :: SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal,
|
||||
2 -> 3 conversion
|
||||
*/
|
||||
|
||||
double MeshOptimize3d :: SwapImprove2 ( Mesh & mesh, OPTIMIZEGOAL goal, ElementIndex eli1, int face,
|
||||
double MeshOptimize3d :: SwapImprove2 ( ElementIndex eli1, int face,
|
||||
Table<ElementIndex, PointIndex> & elementsonnode,
|
||||
TABLE<SurfaceElementIndex, PointIndex::BASE> & belementsonnode, bool check_only )
|
||||
{
|
||||
@ -2370,6 +2382,10 @@ double MeshOptimize3d :: SwapImprove2 ( Mesh & mesh, OPTIMIZEGOAL goal, ElementI
|
||||
if (elem2.GetType() != TET)
|
||||
continue;
|
||||
|
||||
ArrayMem<ElementIndex, 2> elis = {eli1, eli2};
|
||||
if(!NeedsOptimization(elis))
|
||||
continue;
|
||||
|
||||
int comnodes=0;
|
||||
for (int l = 1; l <= 4; l++)
|
||||
if (elem2.PNum(l) == pi1 || elem2.PNum(l) == pi2 ||
|
||||
@ -2384,8 +2400,7 @@ double MeshOptimize3d :: SwapImprove2 ( Mesh & mesh, OPTIMIZEGOAL goal, ElementI
|
||||
|
||||
if (comnodes == 3)
|
||||
{
|
||||
bad1 = CalcBad (mesh.Points(), elem, 0) +
|
||||
CalcBad (mesh.Points(), elem2, 0);
|
||||
bad1 = elem.GetBadness() + elem2.GetBadness();
|
||||
|
||||
if (!mesh.LegalTet(elem) ||
|
||||
!mesh.LegalTet(elem2))
|
||||
@ -2415,9 +2430,9 @@ double MeshOptimize3d :: SwapImprove2 ( Mesh & mesh, OPTIMIZEGOAL goal, ElementI
|
||||
CalcBad (mesh.Points(), el33, 0);
|
||||
|
||||
|
||||
el31.Flags().illegal_valid = 0;
|
||||
el32.Flags().illegal_valid = 0;
|
||||
el33.Flags().illegal_valid = 0;
|
||||
el31.Touch();
|
||||
el32.Touch();
|
||||
el33.Touch();
|
||||
|
||||
if (!mesh.LegalTet(el31) ||
|
||||
!mesh.LegalTet(el32) ||
|
||||
@ -2436,9 +2451,9 @@ double MeshOptimize3d :: SwapImprove2 ( Mesh & mesh, OPTIMIZEGOAL goal, ElementI
|
||||
|
||||
if (d_badness<0.0)
|
||||
{
|
||||
el31.Flags().illegal_valid = 0;
|
||||
el32.Flags().illegal_valid = 0;
|
||||
el33.Flags().illegal_valid = 0;
|
||||
el31.Touch();
|
||||
el32.Touch();
|
||||
el33.Touch();
|
||||
|
||||
mesh[eli1].Delete();
|
||||
mesh[eli2].Delete();
|
||||
@ -2457,7 +2472,7 @@ double MeshOptimize3d :: SwapImprove2 ( Mesh & mesh, OPTIMIZEGOAL goal, ElementI
|
||||
2 -> 3 conversion
|
||||
*/
|
||||
|
||||
void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal)
|
||||
void MeshOptimize3d :: SwapImprove2 ()
|
||||
{
|
||||
static Timer t("MeshOptimize3d::SwapImprove2"); RegionTimer reg(t);
|
||||
|
||||
@ -2478,8 +2493,11 @@ void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal)
|
||||
PrintMessage (3, "SwapImprove2 ");
|
||||
(*testout) << "\n" << "Start SwapImprove2" << "\n";
|
||||
|
||||
double bad1 = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << bad1 << endl;
|
||||
if(testout->good())
|
||||
{
|
||||
double bad1 = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << bad1 << endl;
|
||||
}
|
||||
|
||||
// find elements on node
|
||||
|
||||
@ -2495,6 +2513,8 @@ void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal)
|
||||
Array<std::tuple<double, ElementIndex, int>> faces_with_improvement;
|
||||
Array<Array<std::tuple<double, ElementIndex, int>>> faces_with_improvement_threadlocal(num_threads);
|
||||
|
||||
UpdateBadness();
|
||||
|
||||
ParallelForRange( Range(ne), [&]( auto myrange )
|
||||
{
|
||||
int tid = ngcore::TaskManager::GetThreadId();
|
||||
@ -2510,9 +2530,7 @@ void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal)
|
||||
if (mesh[eli1].GetType() != TET)
|
||||
continue;
|
||||
|
||||
if ((goal == OPT_LEGAL) &&
|
||||
mesh.LegalTet (mesh[eli1]) &&
|
||||
CalcBad (mesh.Points(), mesh[eli1], 0) < 1e3)
|
||||
if (goal == OPT_LEGAL && mesh.LegalTet (mesh[eli1]))
|
||||
continue;
|
||||
|
||||
if(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(eli1).GetIndex())
|
||||
@ -2520,7 +2538,7 @@ void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal)
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
double d_badness = SwapImprove2( mesh, goal, eli1, j, elementsonnode, belementsonnode, true);
|
||||
double d_badness = SwapImprove2( eli1, j, elementsonnode, belementsonnode, true);
|
||||
if(d_badness<0.0)
|
||||
my_faces_with_improvement.Append( std::make_tuple(d_badness, eli1, j) );
|
||||
}
|
||||
@ -2536,22 +2554,24 @@ void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal)
|
||||
{
|
||||
if(mesh[eli].IsDeleted())
|
||||
continue;
|
||||
if(SwapImprove2( mesh, goal, eli, j, elementsonnode, belementsonnode, false) < 0.0)
|
||||
if(SwapImprove2( eli, j, elementsonnode, belementsonnode, false) < 0.0)
|
||||
cnt++;
|
||||
}
|
||||
|
||||
PrintMessage (5, cnt, " swaps performed");
|
||||
|
||||
mesh.Compress();
|
||||
bad1 = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << bad1 << endl;
|
||||
(*testout) << "swapimprove2 done" << "\n";
|
||||
if(testout->good())
|
||||
{
|
||||
double bad1 = mesh.CalcTotalBad (mp);
|
||||
(*testout) << "Total badness = " << bad1 << endl;
|
||||
(*testout) << "swapimprove2 done" << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
double MeshOptimize3d :: SplitImprove2Element (Mesh & mesh,
|
||||
double MeshOptimize3d :: SplitImprove2Element (
|
||||
ElementIndex ei,
|
||||
const Table<ElementIndex, PointIndex> & elements_of_point,
|
||||
const Array<double> & el_badness,
|
||||
bool check_only)
|
||||
{
|
||||
auto & el = mesh[ei];
|
||||
@ -2559,7 +2579,7 @@ double MeshOptimize3d :: SplitImprove2Element (Mesh & mesh,
|
||||
return false;
|
||||
|
||||
// Optimize only bad elements
|
||||
if(el_badness[ei] < 100)
|
||||
if(el.GetBadness() < 100)
|
||||
return false;
|
||||
|
||||
// search for very flat tets, with two disjoint edges nearly crossing, like a rectangle with diagonals
|
||||
@ -2635,21 +2655,21 @@ double MeshOptimize3d :: SplitImprove2Element (Mesh & mesh,
|
||||
has_both_points1.Append (ei1);
|
||||
}
|
||||
|
||||
double badness_before = el_badness[ei];
|
||||
double badness_before = mesh[ei].GetBadness();
|
||||
double badness_after = 0.0;
|
||||
|
||||
for (auto ei0 : has_both_points0)
|
||||
{
|
||||
if(mesh[ei0].GetType()!=TET)
|
||||
return false;
|
||||
badness_before += el_badness[ei0];
|
||||
badness_before += mesh[ei0].GetBadness();
|
||||
badness_after += SplitElementBadness (mesh.Points(), mp, mesh[ei0], pi0, pi1, pnew);
|
||||
}
|
||||
for (auto ei1 : has_both_points1)
|
||||
{
|
||||
if(mesh[ei1].GetType()!=TET)
|
||||
return false;
|
||||
badness_before += el_badness[ei1];
|
||||
badness_before += mesh[ei1].GetBadness();
|
||||
badness_after += SplitElementBadness (mesh.Points(), mp, mesh[ei1], pi2, pi3, pnew);
|
||||
}
|
||||
|
||||
@ -2659,7 +2679,7 @@ double MeshOptimize3d :: SplitImprove2Element (Mesh & mesh,
|
||||
if(badness_after<badness_before)
|
||||
{
|
||||
PointIndex pinew = mesh.AddPoint (center);
|
||||
el.Flags().illegal_valid = 0;
|
||||
el.Touch();
|
||||
el.Delete();
|
||||
|
||||
for (auto ei1 : has_both_points0)
|
||||
@ -2682,7 +2702,7 @@ double MeshOptimize3d :: SplitImprove2Element (Mesh & mesh,
|
||||
|
||||
// Split two opposite edges of very flat tet and let all 4 new segments have one common vertex
|
||||
// Imagine a square with 2 diagonals -> new point where diagonals cross, remove the flat tet
|
||||
void MeshOptimize3d :: SplitImprove2 (Mesh & mesh)
|
||||
void MeshOptimize3d :: SplitImprove2 ()
|
||||
{
|
||||
static Timer t("MeshOptimize3d::SplitImprove2"); RegionTimer reg(t);
|
||||
static Timer tsearch("Search");
|
||||
@ -2695,18 +2715,7 @@ void MeshOptimize3d :: SplitImprove2 (Mesh & mesh)
|
||||
const char * savetask = multithread.task;
|
||||
multithread.task = "Optimize Volume: Split Improve 2";
|
||||
|
||||
Array<double> el_badness (ne);
|
||||
|
||||
ParallelForRange(Range(ne), [&] (auto myrange)
|
||||
{
|
||||
for (ElementIndex ei : myrange)
|
||||
{
|
||||
if(mp.only3D_domain_nr && mp.only3D_domain_nr != mesh[ei].GetIndex())
|
||||
continue;
|
||||
el_badness[ei] = CalcBad (mesh.Points(), mesh[ei], 0);
|
||||
}
|
||||
});
|
||||
|
||||
UpdateBadness();
|
||||
mesh.BuildBoundaryEdges(false);
|
||||
|
||||
Array<std::tuple<double, ElementIndex>> split_candidates(ne);
|
||||
@ -2719,7 +2728,7 @@ void MeshOptimize3d :: SplitImprove2 (Mesh & mesh)
|
||||
{
|
||||
if(mp.only3D_domain_nr && mp.only3D_domain_nr != mesh[ei].GetIndex())
|
||||
continue;
|
||||
double d_badness = SplitImprove2Element(mesh, ei, elements_of_point, el_badness, true);
|
||||
double d_badness = SplitImprove2Element(ei, elements_of_point, true);
|
||||
if(d_badness<0.0)
|
||||
{
|
||||
int index = improvement_counter++;
|
||||
@ -2736,7 +2745,7 @@ void MeshOptimize3d :: SplitImprove2 (Mesh & mesh)
|
||||
topt.Start();
|
||||
for(auto [d_badness, ei] : elements_with_improvement)
|
||||
{
|
||||
if( SplitImprove2Element(mesh, ei, elements_of_point, el_badness, false) < 0.0)
|
||||
if( SplitImprove2Element(ei, elements_of_point, false) < 0.0)
|
||||
cnt++;
|
||||
}
|
||||
topt.Stop();
|
||||
|
@ -13,32 +13,46 @@ extern double CalcTotalBad (const Mesh::T_POINTS & points,
|
||||
class MeshOptimize3d
|
||||
{
|
||||
const MeshingParameters & mp;
|
||||
Mesh & mesh;
|
||||
OPTIMIZEGOAL goal = OPT_QUALITY;
|
||||
double min_badness = 0;
|
||||
|
||||
bool HasBadElement(FlatArray<ElementIndex> els);
|
||||
bool HasIllegalElement(FlatArray<ElementIndex> els);
|
||||
bool NeedsOptimization(FlatArray<ElementIndex> els);
|
||||
|
||||
public:
|
||||
MeshOptimize3d (const MeshingParameters & amp) : mp(amp) { ; }
|
||||
|
||||
double CombineImproveEdge (Mesh & mesh, const MeshingParameters & mp,
|
||||
MeshOptimize3d (Mesh & m, const MeshingParameters & amp, OPTIMIZEGOAL agoal = OPT_QUALITY) :
|
||||
mesh(m), mp(amp), goal(agoal) { ; }
|
||||
|
||||
void SetGoal(OPTIMIZEGOAL agoal) { goal = agoal; }
|
||||
void SetMinBadness(double badness) { min_badness = badness; }
|
||||
|
||||
tuple<double, double, int> UpdateBadness();
|
||||
|
||||
double CombineImproveEdge (
|
||||
Table<ElementIndex, PointIndex> & elements_of_point,
|
||||
Array<double> & elerrs, PointIndex pi0, PointIndex pi1,
|
||||
PointIndex pi0, PointIndex pi1,
|
||||
FlatArray<bool, PointIndex> is_point_removed, bool check_only=false);
|
||||
|
||||
void CombineImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY);
|
||||
void CombineImprove ();
|
||||
|
||||
void SplitImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY);
|
||||
double SplitImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal, Table<ElementIndex,PointIndex> & elementsonnode, Array<double> &elerrs, NgArray<INDEX_3> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only=false);
|
||||
void SplitImprove ();
|
||||
double SplitImproveEdge (Table<ElementIndex,PointIndex> & elementsonnode, NgArray<INDEX_3> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only=false);
|
||||
|
||||
void SplitImprove2 (Mesh & mesh);
|
||||
double SplitImprove2Element (Mesh & mesh, ElementIndex ei, const Table<ElementIndex, PointIndex> & elements_of_point, const Array<double> & elerrs, bool check_only);
|
||||
void SplitImprove2 ();
|
||||
double SplitImprove2Element (ElementIndex ei, const Table<ElementIndex, PointIndex> & elements_of_point, bool check_only);
|
||||
|
||||
|
||||
double SwapImproveEdge (Mesh & mesh, OPTIMIZEGOAL goal, const NgBitArray * working_elements, Table<ElementIndex,PointIndex> & elementsonnode, INDEX_3_HASHTABLE<int> & faces, PointIndex pi1, PointIndex pi2, bool check_only=false);
|
||||
void SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY,
|
||||
const NgBitArray * working_elements = NULL);
|
||||
void SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY,
|
||||
const NgBitArray * working_elements = NULL,
|
||||
double SwapImproveEdge (const NgBitArray * working_elements, Table<ElementIndex,PointIndex> & elementsonnode, INDEX_3_HASHTABLE<int> & faces, PointIndex pi1, PointIndex pi2, bool check_only=false);
|
||||
void SwapImprove (const NgBitArray * working_elements = NULL);
|
||||
void SwapImproveSurface (const NgBitArray * working_elements = NULL,
|
||||
const NgArray< NgArray<int,PointIndex::BASE>* > * idmaps = NULL);
|
||||
void SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal = OPT_QUALITY);
|
||||
double SwapImprove2 ( Mesh & mesh, OPTIMIZEGOAL goal, ElementIndex eli1, int face, Table<ElementIndex, PointIndex> & elementsonnode, TABLE<SurfaceElementIndex, PointIndex::BASE> & belementsonnode, bool check_only=false );
|
||||
void SwapImprove2 ();
|
||||
double SwapImprove2 (ElementIndex eli1, int face, Table<ElementIndex, PointIndex> & elementsonnode, TABLE<SurfaceElementIndex, PointIndex::BASE> & belementsonnode, bool check_only=false );
|
||||
|
||||
void ImproveMesh() { mesh.ImproveMesh(mp, goal); }
|
||||
|
||||
double
|
||||
CalcBad (const Mesh::T_POINTS & points, const Element & elem, double h)
|
||||
|
@ -603,7 +603,7 @@ namespace netgen
|
||||
{
|
||||
volelements.Append (el);
|
||||
}
|
||||
volelements.Last().Flags().illegal_valid = 0;
|
||||
volelements.Last().Touch();
|
||||
volelements.Last().Flags().fixed = 0;
|
||||
volelements.Last().Flags().deleted = 0;
|
||||
|
||||
@ -626,7 +626,7 @@ namespace netgen
|
||||
*/
|
||||
|
||||
volelements[ei] = el;
|
||||
volelements[ei].Flags().illegal_valid = 0;
|
||||
volelements[ei].Touch();
|
||||
volelements[ei].Flags().fixed = 0;
|
||||
volelements[ei].Flags().deleted = 0;
|
||||
}
|
||||
|
@ -480,7 +480,7 @@ namespace netgen
|
||||
meshed = 0;
|
||||
PrintMessage (5, mesh.GetNOpenElements(), " open faces found");
|
||||
|
||||
MeshOptimize3d optmesh(mp);
|
||||
MeshOptimize3d optmesh(mesh, mp, OPT_REST);
|
||||
|
||||
const char * optstr = "mcmstmcmstmcmstmcm";
|
||||
for (size_t j = 1; j <= strlen(optstr); j++)
|
||||
@ -492,11 +492,11 @@ namespace netgen
|
||||
|
||||
switch (optstr[j-1])
|
||||
{
|
||||
case 'c': optmesh.CombineImprove(mesh, OPT_REST); break;
|
||||
case 'd': optmesh.SplitImprove(mesh, OPT_REST); break;
|
||||
case 's': optmesh.SwapImprove(mesh, OPT_REST); break;
|
||||
case 't': optmesh.SwapImprove2(mesh, OPT_REST); break;
|
||||
case 'm': mesh.ImproveMesh(mp, OPT_REST); break;
|
||||
case 'c': optmesh.CombineImprove(); break;
|
||||
case 'd': optmesh.SplitImprove(); break;
|
||||
case 's': optmesh.SwapImprove(); break;
|
||||
case 't': optmesh.SwapImprove2(); break;
|
||||
case 'm': optmesh.ImproveMesh(); break;
|
||||
}
|
||||
|
||||
}
|
||||
@ -528,6 +528,7 @@ namespace netgen
|
||||
throw NgException ("Stop meshing since surface mesh not consistent");
|
||||
}
|
||||
}
|
||||
RemoveIllegalElements (mesh);
|
||||
}
|
||||
|
||||
void MergeMeshes( Mesh & mesh, Array<MeshingData> & md )
|
||||
@ -682,13 +683,28 @@ namespace netgen
|
||||
*/
|
||||
|
||||
mesh3d.CalcSurfacesOfNode();
|
||||
|
||||
MeshOptimize3d optmesh(mesh3d, mp);
|
||||
|
||||
// optimize only bad elements first
|
||||
optmesh.SetMinBadness(1000.);
|
||||
for(auto i : Range(mp.optsteps3d))
|
||||
{
|
||||
auto [total_badness, max_badness, bad_els] = optmesh.UpdateBadness();
|
||||
if(bad_els==0) break;
|
||||
optmesh.SplitImprove();
|
||||
optmesh.SwapImprove();
|
||||
optmesh.SwapImprove2();
|
||||
}
|
||||
|
||||
// Now optimize all elements
|
||||
optmesh.SetMinBadness(0);
|
||||
|
||||
for (auto i : Range(mp.optsteps3d))
|
||||
{
|
||||
if (multithread.terminate)
|
||||
break;
|
||||
|
||||
MeshOptimize3d optmesh(mp);
|
||||
|
||||
// teterrpow = mp.opterrpow;
|
||||
// for (size_t j = 1; j <= strlen(mp.optimize3d); j++)
|
||||
for (auto j : Range(mp.optimize3d.size()))
|
||||
@ -699,12 +715,16 @@ namespace netgen
|
||||
|
||||
switch (mp.optimize3d[j])
|
||||
{
|
||||
case 'c': optmesh.CombineImprove(mesh3d, OPT_REST); break;
|
||||
case 'd': optmesh.SplitImprove(mesh3d); break;
|
||||
case 'D': optmesh.SplitImprove2(mesh3d); break;
|
||||
case 's': optmesh.SwapImprove(mesh3d); break;
|
||||
case 'c':
|
||||
optmesh.SetGoal(OPT_REST);
|
||||
optmesh.CombineImprove();
|
||||
optmesh.SetGoal(OPT_QUALITY);
|
||||
break;
|
||||
case 'd': optmesh.SplitImprove(); break;
|
||||
case 'D': optmesh.SplitImprove2(); break;
|
||||
case 's': optmesh.SwapImprove(); break;
|
||||
// case 'u': optmesh.SwapImproveSurface(mesh3d); break;
|
||||
case 't': optmesh.SwapImprove2(mesh3d); break;
|
||||
case 't': optmesh.SwapImprove2(); break;
|
||||
#ifdef SOLIDGEOM
|
||||
case 'm': mesh3d.ImproveMesh(*geometry); break;
|
||||
case 'M': mesh3d.ImproveMesh(*geometry); break;
|
||||
@ -744,19 +764,19 @@ namespace netgen
|
||||
nillegal = mesh3d.MarkIllegalElements();
|
||||
|
||||
MeshingParameters dummymp;
|
||||
MeshOptimize3d optmesh(dummymp);
|
||||
MeshOptimize3d optmesh(mesh3d, dummymp, OPT_LEGAL);
|
||||
while (nillegal && (it--) > 0)
|
||||
{
|
||||
if (multithread.terminate)
|
||||
break;
|
||||
|
||||
PrintMessage (5, nillegal, " illegal tets");
|
||||
optmesh.SplitImprove (mesh3d, OPT_LEGAL);
|
||||
optmesh.SplitImprove ();
|
||||
|
||||
mesh3d.MarkIllegalElements(); // test
|
||||
optmesh.SwapImprove (mesh3d, OPT_LEGAL);
|
||||
optmesh.SwapImprove ();
|
||||
mesh3d.MarkIllegalElements(); // test
|
||||
optmesh.SwapImprove2 (mesh3d, OPT_LEGAL);
|
||||
optmesh.SwapImprove2 ();
|
||||
|
||||
oldn = nillegal;
|
||||
nillegal = mesh3d.MarkIllegalElements();
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <gprim/geom3d.hpp>
|
||||
#include <linalg.hpp>
|
||||
|
||||
#include "core/exception.hpp"
|
||||
#include "msghandler.hpp"
|
||||
|
||||
namespace netgen
|
||||
@ -994,7 +995,10 @@ namespace netgen
|
||||
{ return flags.strongrefflag; }
|
||||
|
||||
int Illegal () const
|
||||
{ return flags.illegal; }
|
||||
{
|
||||
NETGEN_CHECK_SAME(flags.illegal_valid, true);
|
||||
return flags.illegal;
|
||||
}
|
||||
int IllegalValid () const
|
||||
{ return flags.illegal_valid; }
|
||||
void SetIllegal (int aillegal)
|
||||
@ -1007,6 +1011,26 @@ namespace netgen
|
||||
flags.illegal = alegal ? 0 : 1;
|
||||
flags.illegal_valid = 1;
|
||||
}
|
||||
|
||||
bool BadnessValid()
|
||||
{ return flags.badness_valid; }
|
||||
|
||||
float GetBadness()
|
||||
{
|
||||
NETGEN_CHECK_SAME(flags.badness_valid, true);
|
||||
return badness;
|
||||
}
|
||||
|
||||
void SetBadness(float value)
|
||||
{
|
||||
badness = value;
|
||||
flags.badness_valid = 1;
|
||||
}
|
||||
|
||||
void Touch() {
|
||||
flags.illegal_valid = 0;
|
||||
flags.badness_valid = 0;
|
||||
}
|
||||
|
||||
void Delete () { flags.deleted = 1; }
|
||||
bool IsDeleted () const
|
||||
|
@ -470,11 +470,11 @@ namespace netgen
|
||||
multithread.terminate != 1)
|
||||
{
|
||||
MeshingParameters dummymp;
|
||||
MeshOptimize3d optmesh(dummymp);
|
||||
MeshOptimize3d optmesh(mesh, dummymp, OPT_QUALITY);
|
||||
for(int i=0; i<numtopimprove; i++)
|
||||
{
|
||||
optmesh.SwapImproveSurface(mesh,OPT_QUALITY,&working_elements,&idmaps);
|
||||
optmesh.SwapImprove(mesh,OPT_QUALITY,&working_elements);
|
||||
optmesh.SwapImproveSurface(&working_elements,&idmaps);
|
||||
optmesh.SwapImprove(&working_elements);
|
||||
|
||||
}
|
||||
|
||||
@ -518,11 +518,11 @@ namespace netgen
|
||||
}
|
||||
|
||||
MeshingParameters dummymp;
|
||||
MeshOptimize3d optmesh(dummymp);
|
||||
MeshOptimize3d optmesh(mesh, dummymp, OPT_QUALITY);
|
||||
for(int i=0; i<numtopimprove && multithread.terminate != 1; i++)
|
||||
{
|
||||
optmesh.SwapImproveSurface(mesh,OPT_QUALITY,NULL,&idmaps);
|
||||
optmesh.SwapImprove(mesh,OPT_QUALITY);
|
||||
optmesh.SwapImproveSurface(NULL,&idmaps);
|
||||
optmesh.SwapImprove();
|
||||
//mesh.UpdateTopology();
|
||||
}
|
||||
mesh.UpdateTopology();
|
||||
|
@ -88,29 +88,34 @@ for bad1,bad2, f1, f2 in zip(data['#trigs'], data2['#trigs'], data['file'], data
|
||||
if bad2>0 and bad2<0.8*bad1:
|
||||
print(f"{GREEN}ntrigs {f1} got better: {bad1} -> {bad2}".ljust(w) + diff + RESET)
|
||||
|
||||
n = len(data)+1
|
||||
fig,ax = plt.subplots(figsize=(10,7))
|
||||
for i,d in enumerate(['min trig angle','min tet angle','max trig angle','max tet angle']):
|
||||
ax = plt.subplot(2,5,i+1)
|
||||
n = len(data) + 1
|
||||
fig, ax = plt.subplots(figsize=(15, 7)) # Adjust figsize as needed
|
||||
plt.xticks([])
|
||||
plt.yticks([])
|
||||
ax.yaxis.grid(False)
|
||||
ax.xaxis.grid(False)
|
||||
for i, d in enumerate(['min trig angle', 'min tet angle', 'max trig angle', 'max tet angle']):
|
||||
plt.subplot(2, 4, i + 1) # Remove ax =
|
||||
plt.title(d)
|
||||
ax.set_xticks([1,2])
|
||||
if len(data[d])==0 or len(data2[d])==0:
|
||||
# plt.xticks([1, 2])
|
||||
if len(data[d]) == 0 or len(data2[d]) == 0:
|
||||
continue
|
||||
|
||||
plt.violinplot([data[d],data2[d]], showmedians=True)
|
||||
plt.violinplot([data[d], data2[d]], showmedians=True)
|
||||
med = statistics.median(data[d])
|
||||
plt.hlines(med, 1,2, linestyle='dotted')
|
||||
if d=='badness':
|
||||
ax.set_yscale('log')
|
||||
ax.set_xticklabels([ref, ref2])
|
||||
plt.hlines(med, 1, 2, linestyle='dotted')
|
||||
if d == 'badness':
|
||||
plt.yscale('log')
|
||||
plt.xticks([1, 2], [ref, ref2])
|
||||
|
||||
for i, d in enumerate(['badness', '#edges', '#trigs', '#tets']):
|
||||
plt.xticks([])
|
||||
plt.subplot(2, 4, 5 + i)
|
||||
plt.title('difference ' + d + ' (in %)')
|
||||
plt.boxplot([100.0 * (y - x) / x for x, y in zip(data[d], data2[d])])
|
||||
plt.hlines(0.0, 0.5, 1.5, linestyle='dotted')
|
||||
|
||||
for i,d in enumerate(['badness','#edges','#trigs','#tets']):
|
||||
ax = plt.subplot(2,5,6+i)
|
||||
plt.title('difference '+d+' (in %)')
|
||||
# plt.violinplot([(y-x)/x for x,y in zip(data[d],data2[d])], showmedians=True)
|
||||
plt.boxplot([100.0*(y-x)/x for x,y in zip(data[d],data2[d])])
|
||||
plt.hlines(0.0, 0.5,1.5, linestyle='dotted')
|
||||
plt.tight_layout() # Adjust layout
|
||||
|
||||
|
||||
# plt.savefig('comparison.png', dpi=100)
|
||||
|
File diff suppressed because it is too large
Load Diff
93
tests/pytest/test_nonnative_master
Normal file
93
tests/pytest/test_nonnative_master
Normal file
@ -0,0 +1,93 @@
|
||||
tstart (must be vertically): (0, 1.82574)
|
||||
tend (must be vertically): (0, -1.82574)
|
||||
sin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)
|
||||
tend (must be vertically): (0, -1.82574)
|
||||
sin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)
|
||||
tend (must be vertically): (0, -1.82574)
|
||||
sin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)
|
||||
tend (must be vertically): (0, -1.82574)
|
||||
sin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)
|
||||
tend (must be vertically): (0, -1.82574)
|
||||
sin (must not be 0) = 0.447214sin (must not be 0) = 0.447214tstart (must be vertically): (0, 1.82574)
|
||||
tend (must be vertically): (0, -1.82574)
|
||||
generate boundarycondition.geo
|
||||
needed 0.12342000007629395 seconds
|
||||
generate boxcyl.geo
|
||||
needed 0.801245927810669 seconds
|
||||
generate circle_on_cube.geo
|
||||
needed 0.48620080947875977 seconds
|
||||
generate cone.geo
|
||||
needed 1.186929702758789 seconds
|
||||
generate cube.geo
|
||||
needed 0.09043073654174805 seconds
|
||||
generate cubeandring.geo
|
||||
needed 2.1420021057128906 seconds
|
||||
generate cubeandspheres.geo
|
||||
needed 0.26427721977233887 seconds
|
||||
generate cubemcyl.geo
|
||||
needed 18.373886108398438 seconds
|
||||
generate cubemsphere.geo
|
||||
needed 3.6954052448272705 seconds
|
||||
generate cylinder.geo
|
||||
needed 0.44164204597473145 seconds
|
||||
generate cylsphere.geo
|
||||
needed 0.8774328231811523 seconds
|
||||
generate ellipsoid.geo
|
||||
needed 1.4510962963104248 seconds
|
||||
generate ellipticcone.geo
|
||||
needed 3.0906074047088623 seconds
|
||||
generate ellipticcyl.geo
|
||||
needed 2.0780415534973145 seconds
|
||||
generate extrusion.geo
|
||||
needed 0.40680599212646484 seconds
|
||||
generate fichera.geo
|
||||
needed 0.1265270709991455 seconds
|
||||
generate hinge.stl
|
||||
needed 5.519087553024292 seconds
|
||||
generate lense.in2d
|
||||
needed 0.05641365051269531 seconds
|
||||
generate lshape3d.geo
|
||||
needed 0.09937620162963867 seconds
|
||||
generate manyholes.geo
|
||||
needed 9.43863034248352 seconds
|
||||
generate manyholes2.geo
|
||||
needed 7.40019965171814 seconds
|
||||
generate matrix.geo
|
||||
needed 3.734792709350586 seconds
|
||||
generate ortho.geo
|
||||
needed 0.09516167640686035 seconds
|
||||
generate part1.stl
|
||||
needed 2.6940107345581055 seconds
|
||||
generate period.geo
|
||||
needed 2.709449291229248 seconds
|
||||
generate revolution.geo
|
||||
needed 7.7064368724823 seconds
|
||||
generate sculpture.geo
|
||||
needed 0.6283819675445557 seconds
|
||||
generate shaft.geo
|
||||
needed 2.921243190765381 seconds
|
||||
generate shell.geo
|
||||
generate sphere.geo
|
||||
needed 0.18424725532531738 seconds
|
||||
generate sphereincube.geo
|
||||
needed 0.6060984134674072 seconds
|
||||
generate square.in2d
|
||||
needed 0.021883487701416016 seconds
|
||||
generate squarecircle.in2d
|
||||
needed 0.04081606864929199 seconds
|
||||
generate squarehole.in2d
|
||||
needed 0.03681302070617676 seconds
|
||||
generate torus.geo
|
||||
needed 6.590093612670898 seconds
|
||||
generate trafo.geo
|
||||
needed 3.2712368965148926 seconds
|
||||
generate twobricks.geo
|
||||
needed 0.13849091529846191 seconds
|
||||
generate twocubes.geo
|
||||
needed 0.13361692428588867 seconds
|
||||
generate twocyl.geo
|
||||
needed 0.8036918640136719 seconds
|
||||
generate plane.stl
|
||||
needed 15.712460041046143 seconds
|
||||
done
|
||||
sin (must not be 0) = 0.447214sin (must not be 0) = 0.447214
|
@ -72,6 +72,8 @@ def getMeshingparameters(filename):
|
||||
return standard[:-1]
|
||||
if filename == "screw.step":
|
||||
return standard[3:] # coarser meshes don't work here
|
||||
if filename == "cylinder.geo":
|
||||
return standard[0:-1] # very fine gives inconsistent reults
|
||||
if filename == "cylsphere.geo":
|
||||
return standard[0:2] + standard[3:] # coarse gives inconsistent reults (other mesh on MacOS)
|
||||
if filename == "part1.stl":
|
||||
|
Loading…
Reference in New Issue
Block a user