Merge branch 'fix_parallel_optimize2d' into 'master'

Fix parallel optimize2d

See merge request jschoeberl/netgen!487
This commit is contained in:
Matthias Hochsteger 2022-03-02 14:11:21 +00:00
commit c6c8f52878
10 changed files with 73 additions and 113 deletions

View File

@ -242,7 +242,7 @@ namespace ngcore
TNestedTask (const function<void(TaskInfo&)> & _func,
int _mynr, int _total,
atomic<int> & _endcnt, int prod_tid)
: func(&_func), mynr(_mynr), total(_total), endcnt(&_endcnt), producing_thread(prod_tid)
: func(&_func), mynr(_mynr), total(_total), producing_thread(prod_tid), endcnt(&_endcnt)
{
;
}

View File

@ -980,11 +980,10 @@ namespace netgen
static Timer timer_opt2d("Optimization 2D");
RegionTimer reg(timer_opt2d);
auto meshopt = MeshOptimize2d(mesh);
meshopt.SetFaceIndex(0);
for(auto i : Range(mparam.optsteps2d))
for(auto k : Range(mesh.GetNFD()))
{
PrintMessage(3, "Optimization step ", i);
meshopt.SetFaceIndex(k+1);
int innerstep = 0;
for(auto optstep : mparam.optimize2d)
{

View File

@ -33,7 +33,7 @@ namespace netgen
}
HPRefElement :: HPRefElement(Element & el) :
np(el.GetNV()), index(el.GetIndex()), levelx(0), levely(0), levelz(0), type(HP_NONE), domin(-1), domout(-1) //domin,out for segements
type(HP_NONE), index(el.GetIndex()), levelx(0), levely(0), levelz(0), np(el.GetNV()), domin(-1), domout(-1) //domin,out for segements
{
//Reset();
for (int i=0; i<np ; i++)
@ -48,7 +48,7 @@ namespace netgen
HPRefElement :: HPRefElement(Element2d & el) :
levelx(0), levely(0), levelz(0), type(HP_NONE), index(el.GetIndex()), np(el.GetNV()), domin(-1), domout(-1) //domin,out for segements
type(HP_NONE), index(el.GetIndex()), levelx(0), levely(0), levelz(0), np(el.GetNV()), domin(-1), domout(-1) //domin,out for segements
{
//Reset();
@ -63,7 +63,7 @@ namespace netgen
}
HPRefElement :: HPRefElement(Segment & el) :
levelx(0), levely(0), levelz(0), type(HP_NONE), np(2), domin(el.domin), domout(el.domout), singedge_left(el.singedge_left), singedge_right(el.singedge_right)
type(HP_NONE), levelx(0), levely(0), levelz(0), np(2), domin(el.domin), domout(el.domout), singedge_left(el.singedge_left), singedge_right(el.singedge_right)
{
//Reset();
for (int i=0; i<np ; i++)
@ -84,7 +84,7 @@ namespace netgen
}
HPRefElement :: HPRefElement(HPRefElement & el) :
np(el.np), levelx(el.levelx), levely(el.levely), levelz(el.levelz), type(el.type), domin(el.domin), domout(el.domout), index(el.index), si(el.si), coarse_elnr(el.coarse_elnr), singedge_left(el.singedge_left), singedge_right(el.singedge_right)
type(el.type), index(el.index), si(el.si), levelx(el.levelx), levely(el.levely), levelz(el.levelz), np(el.np), coarse_elnr(el.coarse_elnr), domin(el.domin), domout(el.domout), singedge_left(el.singedge_left), singedge_right(el.singedge_right)
{
//Reset();

View File

@ -18,6 +18,27 @@ namespace netgen
{ tnr = atnr; sidenr = asidenr; }
};
// check if element is quad with at least one surface point -> relevant for optimization
// (quads with 4 edge points are not optimized and can be ignored)
bool checkMixedElement(const Mesh & mesh, FlatArray<SurfaceElementIndex> seia)
{
bool mixed = false;
ParallelForRange( Range(seia), [&] (auto myrange) NETGEN_LAMBDA_INLINE
{
for (SurfaceElementIndex i : myrange)
{
const auto & sel = mesh[i];
if(sel.GetNP() == 3)
continue;
for(auto i : Range(sel.GetNP()))
if(mesh[sel[i]].Type() == SURFACEPOINT)
mixed = true;
}
});
return mixed;
}
bool MeshOptimize2d :: EdgeSwapping (const int usemetric,
Array<Neighbour> &neighbors,
@ -181,35 +202,14 @@ namespace netgen
timerstart.Start();
Array<SurfaceElementIndex> seia;
bool mixed = false;
mesh.GetSurfaceElementsOfFace (faceindex, seia);
if(faceindex==0)
{
seia.SetSize(mesh.GetNSE());
ParallelFor( Range(seia), [&] (auto i) NETGEN_LAMBDA_INLINE
{
SurfaceElementIndex sei(i);
seia[i] = sei;
if (mesh[sei].GetNP() != 3)
{
const auto & sel = mesh[sei];
for(auto i : Range(sel.GetNP()))
if(mesh[sel[i]].Type() == INNERPOINT)
mixed = true;
}
});
}
else
{
mesh.GetSurfaceElementsOfFace (faceindex, seia);
for (SurfaceElementIndex sei : seia)
if (mesh[sei].GetNP() != 3)
mixed = true;
}
if(mixed)
if(checkMixedElement(mesh, seia))
{
timerstart.Stop();
return GenericImprove();
}
Array<Neighbour> neighbors(mesh.GetNSE());
auto elements_on_node = mesh.CreatePoint2SurfaceElementTable(faceindex);
@ -595,25 +595,14 @@ namespace netgen
Array<SurfaceElementIndex> seia;
mesh.GetSurfaceElementsOfFace (faceindex, seia);
if(faceindex)
mesh.GetSurfaceElementsOfFace (faceindex, seia);
else
{
seia.SetSize(mesh.GetNSE());
ParallelFor( IntRange(mesh.GetNSE()), [&seia] (auto i) NETGEN_LAMBDA_INLINE
{ seia[i] = i; });
}
bool mixed = false;
ParallelFor( Range(seia), [&] (auto i) NETGEN_LAMBDA_INLINE
{
if (mesh[seia[i]].GetNP() != 3)
mixed = true;
});
if(mixed)
if(checkMixedElement(mesh, seia))
{
timerstart1.Stop();
timerstart.Stop();
return;
}
int np = mesh.GetNP();
@ -625,18 +614,8 @@ namespace netgen
BuildEdgeList( mesh, elementsonnode, edges );
Array<bool,PointIndex> fixed(np);
ParallelFor( fixed.Range(), [&fixed] (auto i) NETGEN_LAMBDA_INLINE
{ fixed[i] = false; });
ParallelFor( edges.Range(), [&] (auto i) NETGEN_LAMBDA_INLINE
{
auto [pi0, pi1] = edges[i];
if (mesh.IsSegment (pi0, pi1))
{
fixed[pi0] = true;
fixed[pi1] = true;
}
});
ParallelFor( fixed.Range(), [&] (auto i) NETGEN_LAMBDA_INLINE
{ fixed[i] = mesh[i].Type() != SURFACEPOINT; });
timerstart1.Stop();

View File

@ -6414,25 +6414,17 @@ namespace netgen
static int timer = NgProfiler::CreateTimer ("GetSurfaceElementsOfFace");
NgProfiler::RegionTimer reg (timer);
/*
sei.SetSize (0);
for (SurfaceElementIndex i = 0; i < GetNSE(); i++)
{
if ( (*this)[i].GetIndex () == facenr && (*this)[i][0] >= PointIndex::BASE &&
!(*this)[i].IsDeleted() )
{
sei.Append (i);
}
}
*/
if(facenr==0)
{
sei.SetSize(GetNSE());
ParallelForRange( IntRange(GetNSE()), [&sei] (auto myrange)
{
for(auto i : myrange)
sei[i] = i;
});
return;
}
/* Philippose - 01/10/2009
Commented out the following lines, and activated the originally
commented out lines above because of a bug which causes corruption
of the variable "facedecoding" when a mesh is converted to second order
*/
// int size1 = sei.Size();
sei.SetSize(0);
SurfaceElementIndex si = facedecoding[facenr-1].firstelement;
@ -6446,16 +6438,6 @@ namespace netgen
si = (*this)[si].next;
}
/*
// *testout << "with list = " << endl << sei << endl;
if (size1 != sei.Size())
{
cout << "size mismatch" << endl;
exit(1);
}
*/
}

View File

@ -41,7 +41,7 @@ namespace netgen
Meshing2 :: Meshing2 (const NetgenGeometry& ageo,
const MeshingParameters & mp,
const Box<3> & aboundingbox)
: geo(ageo), adfront(aboundingbox), boundingbox(aboundingbox)
: adfront(aboundingbox), boundingbox(aboundingbox), geo(ageo)
{
static Timer t("Mesing2::Meshing2"); RegionTimer r(t);

View File

@ -663,8 +663,8 @@ namespace netgen
// if (elrev)
// swap (pnums.Elem(3), pnums.Elem(4));
for (int j = 0; j < 9; j++)
{
for (int j = 0; j < 9; j++)
{
INDEX_2 i2;
i2.I1() = pnums.Get(betw[j][0]);
i2.I2() = pnums.Get(betw[j][1]);
@ -679,10 +679,10 @@ namespace netgen
mesh.Point(i2.I2())));
between.Set (i2, pnums.Elem(7+j));
}
}
}
for (int j = 0; j < 3; j++)
{
for (int j = 0; j < 3; j++)
{
INDEX_2 i2a, i2b;
i2a.I1() = pnums.Get(fbetw[2*j][0]);
i2a.I2() = pnums.Get(fbetw[2*j][1]);

View File

@ -338,7 +338,7 @@ namespace netgen
: points(apoints), elements(aelements), elementsonpoint(* new Table<int,PointIndex>()), own_elementsonpoint(true), mp(amp)
{
static Timer tim("PointFunction - build elementsonpoint table"); RegionTimer reg(tim);
elementsonpoint = std::move(ngcore::CreateSortedTable<int, PointIndex>( elements.Range(),
elementsonpoint = ngcore::CreateSortedTable<int, PointIndex>( elements.Range(),
[&](auto & table, ElementIndex ei)
{
const auto & el = elements[ei];
@ -348,7 +348,7 @@ namespace netgen
for (PointIndex pi : el.PNums())
table.Add (pi, ei);
}, points.Size()));
}, points.Size());
}
void PointFunction :: SetPointIndex (PointIndex aactpind)

View File

@ -203,20 +203,20 @@ namespace netgen
if(auto quad_dominated = OCCGeometry::global_shape_properties[face.TShape()].quad_dominated; quad_dominated.has_value())
local_mp.quad = *quad_dominated;
bool failed = OCCMeshFace(*this, mesh, glob2loc, local_mp, nr, PARAMETERSPACE, true);
if(failed)
failed = OCCMeshFace(*this, mesh, glob2loc, local_mp, nr, PLANESPACE, false);
bool failed = OCCMeshFace(*this, mesh, glob2loc, local_mp, nr, PARAMETERSPACE, true);
if(failed)
failed = OCCMeshFace(*this, mesh, glob2loc, local_mp, nr, PLANESPACE, false);
if(failed)
{
facemeshstatus[nr] = -1;
PrintError ("Problem in Surface mesh generation");
}
else
{
facemeshstatus[nr] = 1;
}
return failed;
if(failed)
{
facemeshstatus[nr] = -1;
PrintError ("Problem in Surface mesh generation");
}
else
{
facemeshstatus[nr] = 1;
}
return failed;
}
void OCCGeometry :: PrintNrShapes ()

View File

@ -2372,7 +2372,7 @@ degen_tol : double
vector<TopoDS_Wire> wires;
for(auto& w : *swires)
wires.push_back(TopoDS::Wire(w));
return std::move(wires);
return wires;
}, py::arg("edges"), py::arg("tol")=1e-8, py::arg("shared")=true);
py::class_<WorkPlane, shared_ptr<WorkPlane>> (m, "WorkPlane")