mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-31 00:00:33 +05:00
929 lines
23 KiB
C++
929 lines
23 KiB
C++
#include <mystdlib.h>
|
|
#include "meshing.hpp"
|
|
|
|
|
|
namespace netgen
|
|
{
|
|
|
|
void Refinement :: Refine (Mesh & mesh) const
|
|
{
|
|
const_cast<Refinement&> (*this).Refine(mesh);
|
|
}
|
|
|
|
|
|
void Refinement :: Refine (Mesh & mesh)
|
|
{
|
|
if (mesh.GetCommunicator().Rank()==0)
|
|
PrintMessage (3, "Refine mesh");
|
|
Timer t("Refine mesh"); RegionTimer reg(t);
|
|
|
|
|
|
mesh.SetNextMajorTimeStamp();
|
|
|
|
if (ntasks > 1 && id == 0)
|
|
return;
|
|
|
|
|
|
// reduce 2nd order
|
|
mesh.ComputeNVertices();
|
|
mesh.SetNP(mesh.GetNV());
|
|
|
|
if (mesh.mlbetweennodes.Size() < mesh.GetNV())
|
|
{
|
|
mesh.mlbetweennodes.SetSize(mesh.GetNV());
|
|
mesh.mlbetweennodes = INDEX_2(PointIndex::BASE-1,PointIndex::BASE-1);
|
|
}
|
|
|
|
if (mesh.level_nv.Size() == 0)
|
|
mesh.level_nv.Append (mesh.GetNV());
|
|
|
|
|
|
INDEX_2_HASHTABLE<PointIndex> between(mesh.GetNP() + 5);
|
|
|
|
|
|
// new version with consistent ordering across sub-domains
|
|
|
|
NgArray<INDEX_2> parents;
|
|
for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)
|
|
{
|
|
const Segment & el = mesh[si];
|
|
INDEX_2 i2 = INDEX_2::Sort(el[0], el[1]);
|
|
if (!between.Used(i2))
|
|
{
|
|
between.Set (i2, 0);
|
|
parents.Append(i2);
|
|
}
|
|
}
|
|
for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
|
|
{
|
|
const Element2d & el = mesh[sei];
|
|
switch (el.GetType())
|
|
{
|
|
case TRIG:
|
|
case TRIG6:
|
|
{
|
|
static int betw[3][3] =
|
|
{ { 1, 2, 3 },
|
|
{ 0, 2, 4 },
|
|
{ 0, 1, 5 } };
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
auto i2 = PointIndices<2>::Sort(el[betw[j][0]],el[betw[j][1]]);
|
|
if (!between.Used(i2))
|
|
{
|
|
between.Set (i2, 0);
|
|
parents.Append(i2);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case QUAD:
|
|
{
|
|
static int betw[5][3] =
|
|
{ { 0, 1, 4 },
|
|
{ 1, 2, 5 },
|
|
{ 2, 3, 6 },
|
|
{ 0, 3, 7 },
|
|
{ 0, 2, 8 } }; // one diagonal of the quad. should change later to mid-point of edge mid-points
|
|
for (int j = 0; j < 5; j++)
|
|
{
|
|
auto i2 = PointIndices<2>::Sort(el[betw[j][0]],el[betw[j][1]]);
|
|
if (j == 4)
|
|
{
|
|
auto i2a = PointIndices<2>::Sort(el[0], el[2]);
|
|
auto i2b = PointIndices<2>::Sort(el[1], el[3]);
|
|
i2 = i2a[0] < i2b[0] ? i2a : i2b;
|
|
}
|
|
if (!between.Used(i2))
|
|
{
|
|
between.Set (i2, 0);
|
|
parents.Append(i2);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
throw NgException ("currently refinement for quad-elements is not supported");
|
|
}
|
|
}
|
|
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
|
|
{
|
|
const Element & el = mesh[ei];
|
|
switch (el.GetType())
|
|
{
|
|
case TET:
|
|
case TET10:
|
|
{
|
|
static int betw[6][3] =
|
|
{ { 1, 2, 5 },
|
|
{ 1, 3, 6 },
|
|
{ 1, 4, 7 },
|
|
{ 2, 3, 8 },
|
|
{ 2, 4, 9 },
|
|
{ 3, 4, 10 } };
|
|
|
|
for (int j = 0; j < 6; j++)
|
|
{
|
|
INDEX_2 i2 = INDEX_2::Sort(el.PNum(betw[j][0]),el.PNum(betw[j][1]));
|
|
if (!between.Used(i2))
|
|
{
|
|
between.Set (i2, 0);
|
|
parents.Append(i2);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
throw NgException ("currently refinement for non-tet elements is not supported");
|
|
}
|
|
}
|
|
|
|
PrintMessage (5, "have points");
|
|
|
|
NgArray<int> par_nr(parents.Size());
|
|
for (int i = 0; i < par_nr.Size(); i++)
|
|
par_nr[i] = i;
|
|
QuickSort (parents, par_nr);
|
|
mesh.mlbetweennodes.SetSize(mesh.GetNV()+parents.Size());
|
|
for (int i = 0; i < parents.Size(); i++)
|
|
{
|
|
between.Set (parents[i], mesh.GetNV()+i+PointIndex::BASE);
|
|
mesh.mlbetweennodes[mesh.GetNV()+i+PointIndex::BASE] = parents[i];
|
|
}
|
|
|
|
mesh.SetNP(mesh.GetNV() + parents.Size());
|
|
NgArray<bool, PointIndex::BASE> pointset(mesh.GetNP());
|
|
pointset = false;
|
|
|
|
PrintMessage (5, "sorting complete");
|
|
|
|
// refine edges
|
|
NgArray<EdgePointGeomInfo,PointIndex::BASE> epgi;
|
|
|
|
int oldns = mesh.GetNSeg();
|
|
for (SegmentIndex si = 0; si < oldns; si++)
|
|
{
|
|
const Segment & el = mesh.LineSegment(si);
|
|
|
|
INDEX_2 i2 = INDEX_2::Sort(el[0], el[1]);
|
|
PointIndex pinew = between.Get(i2);
|
|
EdgePointGeomInfo ngi;
|
|
|
|
if (pointset[pinew])
|
|
{
|
|
// pinew = between.Get(i2);
|
|
ngi = epgi[pinew];
|
|
}
|
|
else
|
|
{
|
|
pointset[pinew] = true;
|
|
Point<3> pnew;
|
|
geo.PointBetweenEdge(mesh.Point (el[0]),
|
|
mesh.Point (el[1]), 0.5,
|
|
el.surfnr1, el.surfnr2,
|
|
el.epgeominfo[0], el.epgeominfo[1],
|
|
pnew, ngi);
|
|
|
|
// pinew = mesh.AddPoint (pnew);
|
|
mesh.Point(pinew) = pnew;
|
|
// between.Set (i2, pinew);
|
|
|
|
if (pinew >= epgi.Size()+PointIndex::BASE)
|
|
epgi.SetSize (pinew+1-PointIndex::BASE);
|
|
epgi[pinew] = ngi;
|
|
}
|
|
|
|
Segment ns1 = el;
|
|
Segment ns2 = el;
|
|
ns1[1] = pinew;
|
|
ns1.epgeominfo[1] = ngi;
|
|
ns2[0] = pinew;
|
|
ns2.epgeominfo[0] = ngi;
|
|
|
|
mesh.LineSegment(si) = ns1;
|
|
mesh.AddSegment (ns2);
|
|
}
|
|
|
|
PrintMessage (5, "have 1d elements");
|
|
|
|
// refine surface elements
|
|
NgArray<PointGeomInfo,PointIndex::BASE> surfgi (8*mesh.GetNP());
|
|
for (int i = PointIndex::BASE;
|
|
i < surfgi.Size()+PointIndex::BASE; i++)
|
|
surfgi[i].trignum = -1;
|
|
|
|
|
|
int oldnf = mesh.GetNSE();
|
|
for (SurfaceElementIndex sei = 0; sei < oldnf; sei++)
|
|
{
|
|
const Element2d & el = mesh[sei];
|
|
|
|
switch (el.GetType())
|
|
{
|
|
case TRIG:
|
|
case TRIG6:
|
|
{
|
|
NgArrayMem<PointIndex,6> pnums(6);
|
|
NgArrayMem<PointGeomInfo,6> pgis(6);
|
|
|
|
static int betw[3][3] =
|
|
{ { 2, 3, 4 },
|
|
{ 1, 3, 5 },
|
|
{ 1, 2, 6 } };
|
|
|
|
for (int j = 1; j <= 3; j++)
|
|
{
|
|
pnums.Elem(j) = el.PNum(j);
|
|
pgis.Elem(j) = el.GeomInfoPi(j);
|
|
}
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
PointIndex pi1 = pnums.Elem(betw[j][0]);
|
|
PointIndex pi2 = pnums.Elem(betw[j][1]);
|
|
|
|
INDEX_2 i2 (pi1, pi2);
|
|
i2.Sort();
|
|
|
|
Point<3> pb;
|
|
PointGeomInfo pgi;
|
|
geo.PointBetween(mesh.Point (pi1),
|
|
mesh.Point (pi2), 0.5,
|
|
mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(),
|
|
el.GeomInfoPi (betw[j][0]),
|
|
el.GeomInfoPi (betw[j][1]),
|
|
pb, pgi);
|
|
|
|
|
|
pgis.Elem(4+j) = pgi;
|
|
PointIndex pinew = between.Get(i2);
|
|
pnums.Elem(4+j) = pinew;
|
|
if (!pointset[pinew])
|
|
{
|
|
pointset[pinew] = true;
|
|
mesh.Point(pinew) = pb;
|
|
}
|
|
/*
|
|
if (between.Used(i2))
|
|
pnums.Elem(4+j) = between.Get(i2);
|
|
else
|
|
{
|
|
pnums.Elem(4+j) = mesh.AddPoint (pb);
|
|
between.Set (i2, pnums.Get(4+j));
|
|
}
|
|
*/
|
|
if (surfgi.Size() < pnums.Elem(4+j))
|
|
surfgi.SetSize (pnums.Elem(4+j));
|
|
surfgi.Elem(pnums.Elem(4+j)) = pgis.Elem(4+j);
|
|
}
|
|
|
|
|
|
static int reftab[4][3] =
|
|
{ { 1, 6, 5 },
|
|
{ 2, 4, 6 },
|
|
{ 3, 5, 4 },
|
|
{ 6, 4, 5 } };
|
|
|
|
int ind = el.GetIndex();
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
Element2d nel(TRIG);
|
|
for (int k = 1; k <= 3; k++)
|
|
{
|
|
nel.PNum(k) = pnums.Get(reftab[j][k-1]);
|
|
nel.GeomInfoPi(k) = pgis.Get(reftab[j][k-1]);
|
|
}
|
|
nel.SetIndex(ind);
|
|
|
|
if (j == 0)
|
|
mesh[sei] = nel;
|
|
else
|
|
mesh.AddSurfaceElement(nel);
|
|
}
|
|
break;
|
|
}
|
|
case QUAD:
|
|
case QUAD6:
|
|
case QUAD8:
|
|
{
|
|
PointIndex pnums[9];
|
|
PointGeomInfo pgis[9];
|
|
|
|
static int betw[5][3] =
|
|
{ { 0, 1, 4 },
|
|
{ 1, 2, 5 },
|
|
{ 2, 3, 6 },
|
|
{ 0, 3, 7 },
|
|
{ 0, 2, 8 } };
|
|
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
pnums[j] = el[j];
|
|
pgis[j] = el.GeomInfoPi(j+1);
|
|
}
|
|
|
|
for (int j = 0; j < 5; j++)
|
|
{
|
|
int pi1 = pnums[betw[j][0]];
|
|
int pi2 = pnums[betw[j][1]];
|
|
|
|
INDEX_2 i2 (pi1, pi2);
|
|
i2.Sort();
|
|
|
|
if (j == 4)
|
|
{
|
|
auto i2a = PointIndices<2>::Sort(el[0], el[2]);
|
|
auto i2b = PointIndices<2>::Sort(el[1], el[3]);
|
|
i2 = i2a[0] < i2b[0] ? i2a : i2b;
|
|
}
|
|
|
|
Point<3> pb;
|
|
PointGeomInfo pgi;
|
|
geo.PointBetween(mesh.Point (pi1), mesh.Point (pi2), 0.5,
|
|
mesh.GetFaceDescriptor(el.GetIndex ()).SurfNr(),
|
|
el.GeomInfoPi (betw[j][0]+1 ),
|
|
el.GeomInfoPi (betw[j][1]+1 ),
|
|
pb, pgi);
|
|
|
|
pgis[4+j] = pgi;
|
|
PointIndex pinew = between.Get(i2);
|
|
pnums[4+j] = pinew;
|
|
|
|
if (!pointset[pinew])
|
|
{
|
|
pointset[pinew] = true;
|
|
mesh.Point(pinew) = pb;
|
|
}
|
|
|
|
if (surfgi.Size() < pnums[4+j])
|
|
surfgi.SetSize (pnums[4+j]);
|
|
surfgi.Elem(pnums[4+j]) = pgis[4+j];
|
|
}
|
|
|
|
static int reftab[4][4] =
|
|
{
|
|
{ 0, 4, 8, 7 },
|
|
{ 4, 1, 5, 8 },
|
|
{ 7, 8, 6, 3 },
|
|
{ 8, 5, 2, 6 } };
|
|
|
|
|
|
int ind = el.GetIndex();
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
Element2d nel(QUAD);
|
|
for (int k = 0; k < 4; k++)
|
|
{
|
|
nel[k] = pnums[reftab[j][k]];
|
|
nel.GeomInfoPi(k+1) = pgis[reftab[j][k]];
|
|
}
|
|
nel.SetIndex(ind);
|
|
|
|
if (j == 0)
|
|
mesh[sei] = nel;
|
|
else
|
|
mesh.AddSurfaceElement(nel);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
PrintSysError ("Refine: undefined surface element type ", int(el.GetType()));
|
|
}
|
|
}
|
|
|
|
PrintMessage (5, "have 2d elements");
|
|
// cout << "id = " << id << ", ne = " << mesh.GetNE() << endl;
|
|
// refine volume elements
|
|
int oldne = mesh.GetNE();
|
|
mesh.VolumeElements().SetAllocSize(8*oldne);
|
|
for (ElementIndex ei = 0; ei < oldne; ei++)
|
|
{
|
|
const Element & el = mesh[ei];
|
|
switch (el.GetType())
|
|
{
|
|
case TET:
|
|
case TET10:
|
|
{
|
|
NgArrayMem<PointIndex,10> pnums(10);
|
|
static int betw[6][3] =
|
|
{ { 1, 2, 5 },
|
|
{ 1, 3, 6 },
|
|
{ 1, 4, 7 },
|
|
{ 2, 3, 8 },
|
|
{ 2, 4, 9 },
|
|
{ 3, 4, 10 } };
|
|
|
|
int elrev = el.Flags().reverse;
|
|
|
|
for (int j = 1; j <= 4; j++)
|
|
pnums.Elem(j) = el.PNum(j);
|
|
if (elrev)
|
|
swap (pnums.Elem(3), pnums.Elem(4));
|
|
|
|
for (int j = 0; j < 6; j++)
|
|
{
|
|
PointIndex pi1 = pnums.Get(betw[j][0]);
|
|
PointIndex pi2 = pnums.Get(betw[j][1]);
|
|
INDEX_2 i2 (pi1, pi2);
|
|
i2.Sort();
|
|
|
|
/*
|
|
if (between.Used(i2))
|
|
pnums.Elem(5+j) = between.Get(i2);
|
|
else
|
|
{
|
|
pnums.Elem(5+j) = mesh.AddPoint
|
|
(Center (mesh.Point(i2.I1()),
|
|
mesh.Point(i2.I2())));
|
|
between.Set (i2, pnums.Elem(5+j));
|
|
}
|
|
*/
|
|
PointIndex pinew = between.Get(i2);
|
|
pnums.Elem(j+5) = pinew;
|
|
if (!pointset[pinew])
|
|
{
|
|
pointset[pinew] = true;
|
|
mesh.Point(pinew) = Center(mesh.Point(pi1),
|
|
mesh.Point(pi2));
|
|
}
|
|
}
|
|
|
|
static int reftab[8][4] =
|
|
{ { 1, 5, 6, 7 },
|
|
{ 5, 2, 8, 9 },
|
|
{ 6, 8, 3, 10 },
|
|
{ 7, 9, 10, 4 },
|
|
{ 5, 6, 7, 9 },
|
|
{ 5, 6, 9, 8 },
|
|
{ 6, 7, 9, 10 },
|
|
{ 6, 8, 10, 9 } };
|
|
/*
|
|
{ { 1, 5, 6, 7 },
|
|
{ 5, 2, 8, 9 },
|
|
{ 6, 8, 3, 10 },
|
|
{ 7, 9, 10, 4 },
|
|
{ 5, 6, 7, 9 },
|
|
{ 5, 6, 8, 9 },
|
|
{ 6, 7, 9, 10 },
|
|
{ 6, 8, 9, 10 } };
|
|
*/
|
|
static bool reverse[8] =
|
|
{
|
|
false, false, false, false, false, true, false, true
|
|
};
|
|
|
|
int ind = el.GetIndex();
|
|
for (int j = 0; j < 8; j++)
|
|
{
|
|
Element nel(TET);
|
|
for (int k = 1; k <= 4; k++)
|
|
nel.PNum(k) = pnums.Get(reftab[j][k-1]);
|
|
nel.SetIndex(ind);
|
|
nel.Flags().reverse = reverse[j];
|
|
if (elrev)
|
|
{
|
|
nel.Flags().reverse = !nel.Flags().reverse;
|
|
swap (nel.PNum(3), nel.PNum(4));
|
|
}
|
|
|
|
if (j == 0)
|
|
mesh.VolumeElement(ei) = nel;
|
|
else
|
|
mesh.AddVolumeElement (nel);
|
|
}
|
|
break;
|
|
}
|
|
case HEX:
|
|
{
|
|
NgArrayMem<PointIndex,27> pnums(27);
|
|
static int betw[13][3] =
|
|
{ { 1, 2, 9 },
|
|
{ 3, 4, 10 },
|
|
{ 4, 1, 11 },
|
|
{ 2, 3, 12 },
|
|
{ 5, 6, 13 },
|
|
{ 7, 8, 14 },
|
|
{ 8, 5, 15 },
|
|
{ 6, 7, 16 },
|
|
{ 1, 5, 17 },
|
|
{ 2, 6, 18 },
|
|
{ 3, 7, 19 },
|
|
{ 4, 8, 20 },
|
|
{ 2, 8, 21 },
|
|
};
|
|
|
|
/*
|
|
static int fbetw[12][3] =
|
|
{ { 1, 3, 22 },
|
|
{ 2, 4, 22 },
|
|
{ 5, 7, 23 },
|
|
{ 6, 8, 23 },
|
|
{ 1, 6, 24 },
|
|
{ 2, 5, 24 },
|
|
{ 2, 7, 25 },
|
|
{ 3, 6, 25 },
|
|
{ 3, 8, 26 },
|
|
{ 4, 7, 26 },
|
|
{ 1, 8, 27 },
|
|
{ 4, 5, 27 },
|
|
};
|
|
*/
|
|
|
|
// updated by anonymous supporter, donations please to Karo W.
|
|
static int fbetw[12][3] =
|
|
{ { 11, 12, 22 },
|
|
{ 9, 10, 22 },
|
|
{ 13, 14, 23 },
|
|
{ 15, 16, 23 },
|
|
{ 9, 13, 24 },
|
|
{ 17, 18, 24 },
|
|
{ 12, 16, 25 },
|
|
{ 18, 19, 25 },
|
|
{ 19, 20, 26 },
|
|
{ 10, 14, 26 },
|
|
{ 11, 15, 27 },
|
|
{ 17, 20, 27 },
|
|
};
|
|
|
|
pnums = PointIndex(-1);
|
|
|
|
for (int j = 1; j <= 8; j++)
|
|
pnums.Elem(j) = el.PNum(j);
|
|
|
|
|
|
for (int j = 0; j < 13; j++)
|
|
{
|
|
INDEX_2 i2;
|
|
i2.I1() = pnums.Get(betw[j][0]);
|
|
i2.I2() = pnums.Get(betw[j][1]);
|
|
i2.Sort();
|
|
|
|
if (between.Used(i2))
|
|
pnums.Elem(9+j) = between.Get(i2);
|
|
else
|
|
{
|
|
pnums.Elem(9+j) = mesh.AddPoint
|
|
(Center (mesh.Point(i2.I1()),
|
|
mesh.Point(i2.I2())));
|
|
between.Set (i2, pnums.Elem(9+j));
|
|
}
|
|
}
|
|
|
|
for (int j = 0; j < 6; j++)
|
|
{
|
|
INDEX_2 i2a, i2b;
|
|
i2a.I1() = pnums.Get(fbetw[2*j][0]);
|
|
i2a.I2() = pnums.Get(fbetw[2*j][1]);
|
|
i2a.Sort();
|
|
i2b.I1() = pnums.Get(fbetw[2*j+1][0]);
|
|
i2b.I2() = pnums.Get(fbetw[2*j+1][1]);
|
|
i2b.Sort();
|
|
|
|
if (between.Used(i2a))
|
|
pnums.Elem(22+j) = between.Get(i2a);
|
|
else if (between.Used(i2b))
|
|
pnums.Elem(22+j) = between.Get(i2b);
|
|
else
|
|
{
|
|
pnums.Elem(22+j) = mesh.AddPoint
|
|
(Center (mesh.Point(i2a.I1()),
|
|
mesh.Point(i2a.I2())));
|
|
|
|
between.Set (i2a, pnums.Elem(22+j));
|
|
}
|
|
}
|
|
|
|
static int reftab[8][8] =
|
|
{ { 1, 9, 22, 11, 17, 24, 21, 27 },
|
|
{ 9, 2, 12, 22, 24, 18, 25, 21 },
|
|
{ 11, 22, 10, 4, 27, 21, 26, 20},
|
|
{ 22, 12, 3, 10, 21, 25, 19, 26},
|
|
{ 17, 24, 21, 27, 5, 13, 23, 15},
|
|
{ 24, 18, 25, 21, 13, 6, 16, 23},
|
|
{ 27, 21, 26, 20, 15, 23, 14, 8},
|
|
{ 21, 25, 19, 26, 23, 16, 7, 14} };
|
|
|
|
|
|
int ind = el.GetIndex();
|
|
for (int j = 0; j < 8; j++)
|
|
{
|
|
Element nel(HEX);
|
|
for (int k = 1; k <= 8; k++)
|
|
nel.PNum(k) = pnums.Get(reftab[j][k-1]);
|
|
nel.SetIndex(ind);
|
|
|
|
if (j == 0)
|
|
mesh.VolumeElement(ei) = nel;
|
|
else
|
|
mesh.AddVolumeElement (nel);
|
|
}
|
|
break;
|
|
}
|
|
case PRISM:
|
|
{
|
|
NgArrayMem<PointIndex,18> pnums(18);
|
|
static int betw[9][3] =
|
|
{ { 3, 1, 7 },
|
|
{ 1, 2, 8 },
|
|
{ 3, 2, 9 },
|
|
{ 6, 4, 10 },
|
|
{ 4, 5, 11 },
|
|
{ 6, 5, 12 },
|
|
{ 1, 4, 13 },
|
|
{ 3, 6, 14 },
|
|
{ 2, 5, 15 },
|
|
};
|
|
|
|
// he: 15.jul 08, old version is wrong
|
|
// produces double points ad quad faces and inconsistent mesh
|
|
// static int fbetw[6][3] =
|
|
// { { 1, 6, 16 },
|
|
// { 3, 4, 16 },
|
|
// { 1, 5, 17 },
|
|
// { 2, 4, 17 },
|
|
// { 2, 6, 18 },
|
|
// { 3, 5, 18 },
|
|
// };
|
|
|
|
static int fbetw[6][3] =
|
|
{ { 7, 10, 16 },
|
|
{ 14, 13, 16 },
|
|
{ 11, 8, 17 },
|
|
{ 13, 15, 17 },
|
|
{ 12, 9, 18 },
|
|
{ 14, 15, 18 },
|
|
};
|
|
|
|
//int elrev = el.flags.reverse;
|
|
pnums = PointIndex(-1);
|
|
|
|
for (int j = 1; j <= 6; j++)
|
|
pnums.Elem(j) = el.PNum(j);
|
|
// if (elrev)
|
|
// swap (pnums.Elem(3), pnums.Elem(4));
|
|
|
|
for (int j = 0; j < 9; j++)
|
|
{
|
|
INDEX_2 i2;
|
|
i2.I1() = pnums.Get(betw[j][0]);
|
|
i2.I2() = pnums.Get(betw[j][1]);
|
|
i2.Sort();
|
|
|
|
if (between.Used(i2))
|
|
pnums.Elem(7+j) = between.Get(i2);
|
|
else
|
|
{
|
|
pnums.Elem(7+j) = mesh.AddPoint
|
|
(Center (mesh.Point(i2.I1()),
|
|
mesh.Point(i2.I2())));
|
|
between.Set (i2, pnums.Elem(7+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]);
|
|
i2a.Sort();
|
|
i2b.I1() = pnums.Get(fbetw[2*j+1][0]);
|
|
i2b.I2() = pnums.Get(fbetw[2*j+1][1]);
|
|
i2b.Sort();
|
|
|
|
if (between.Used(i2a))
|
|
pnums.Elem(16+j) = between.Get(i2a);
|
|
else if (between.Used(i2b))
|
|
pnums.Elem(16+j) = between.Get(i2b);
|
|
else
|
|
{
|
|
pnums.Elem(16+j) = mesh.AddPoint
|
|
(Center (mesh.Point(i2a.I1()),
|
|
mesh.Point(i2a.I2())));
|
|
|
|
between.Set (i2a, pnums.Elem(16+j));
|
|
}
|
|
}
|
|
|
|
|
|
static int reftab[8][6] =
|
|
{ { 1, 8, 7, 13, 17, 16 },
|
|
{ 7, 8, 9, 16, 17, 18 },
|
|
{ 7, 9, 3, 16, 18, 14 },
|
|
{ 8, 2, 9, 17, 15, 18 },
|
|
{ 13, 17, 16, 4, 11, 10 },
|
|
{ 16, 17, 18, 10, 11, 12 },
|
|
{ 16, 18, 14, 10, 12, 6 },
|
|
{ 17, 15, 18, 11, 5, 12 } };
|
|
|
|
|
|
int ind = el.GetIndex();
|
|
for (int j = 0; j < 8; j++)
|
|
{
|
|
Element nel(PRISM);
|
|
for (int k = 1; k <= 6; k++)
|
|
nel.PNum(k) = pnums.Get(reftab[j][k-1]);
|
|
nel.SetIndex(ind);
|
|
|
|
|
|
//nel.flags.reverse = reverse[j];
|
|
//if (elrev)
|
|
// {
|
|
//nel.flags.reverse = 1 - nel.flags.reverse;
|
|
//swap (nel.PNum(3), nel.PNum(4));
|
|
|
|
|
|
if (j == 0)
|
|
mesh.VolumeElement(ei) = nel;
|
|
else
|
|
mesh.AddVolumeElement (nel);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
PrintSysError ("Refine: undefined volume element type ", int(el.GetType()));
|
|
}
|
|
}
|
|
|
|
|
|
// update identification tables
|
|
for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)
|
|
{
|
|
NgArray<int,PointIndex::BASE> identmap;
|
|
mesh.GetIdentifications().GetMap (i, identmap);
|
|
|
|
for (int j = 1; j <= between.GetNBags(); j++)
|
|
for (int k = 1; k <= between.GetBagSize(j); k++)
|
|
{
|
|
INDEX_2 i2;
|
|
PointIndex newpi;
|
|
between.GetData (j, k, i2, newpi);
|
|
INDEX_2 oi2(identmap.Get(i2.I1()),
|
|
identmap.Get(i2.I2()));
|
|
oi2.Sort();
|
|
if (between.Used (oi2))
|
|
{
|
|
PointIndex onewpi = between.Get(oi2);
|
|
mesh.GetIdentifications().Add (newpi, onewpi, i);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
PrintMessage (5, "have 3d elements");
|
|
mesh.ComputeNVertices();
|
|
mesh.RebuildSurfaceElementLists();
|
|
|
|
mesh.level_nv.Append (mesh.GetNV());
|
|
|
|
#ifdef PARALLEL
|
|
if (mesh.GetCommunicator().Size() > 1)
|
|
{
|
|
mesh.GetParallelTopology().IdentifyVerticesAfterRefinement();
|
|
mesh.GetCommunicator().Barrier();
|
|
mesh.GetParallelTopology().EnumeratePointsGlobally();
|
|
}
|
|
#endif
|
|
|
|
PrintMessage (5, "mesh updates complete");
|
|
return;
|
|
|
|
int cnttrials = 10;
|
|
int wrongels = 0;
|
|
for (int i = 1; i <= mesh.GetNE(); i++)
|
|
if (mesh.VolumeElement(i).Volume(mesh.Points()) < 0)
|
|
{
|
|
wrongels++;
|
|
mesh.VolumeElement(i).Flags().badel = 1;
|
|
}
|
|
else
|
|
mesh.VolumeElement(i).Flags().badel = 0;
|
|
|
|
if (wrongels)
|
|
{
|
|
cout << "WARNING: " << wrongels << " with wrong orientation found" << endl;
|
|
|
|
int np = mesh.GetNP();
|
|
NgArray<Point<3> > should(np);
|
|
NgArray<Point<3> > can(np);
|
|
for (int i = 1; i <= np; i++)
|
|
{
|
|
should.Elem(i) = can.Elem(i) = mesh.Point(i);
|
|
}
|
|
for (int i = 1; i <= between.GetNBags(); i++)
|
|
for (int j = 1; j <= between.GetBagSize(i); j++)
|
|
{
|
|
INDEX_2 parent;
|
|
PointIndex child;
|
|
between.GetData (i, j, parent, child);
|
|
can.Elem(child) = Center (can.Elem(parent.I1()),
|
|
can.Elem(parent.I2()));
|
|
}
|
|
|
|
NgBitArray boundp(np);
|
|
boundp.Clear();
|
|
for (auto & sel : mesh.SurfaceElements())
|
|
for (auto pi : sel.PNums())
|
|
boundp.Set(pi);
|
|
|
|
|
|
double lam = 0.5;
|
|
|
|
while (lam < 0.9 && cnttrials > 0)
|
|
{
|
|
lam = 2;
|
|
do
|
|
{
|
|
lam *= 0.5;
|
|
cnttrials--;
|
|
|
|
cout << "lam = " << lam << endl;
|
|
|
|
for (int i = 1; i <= np; i++)
|
|
if (boundp.Test(i))
|
|
{
|
|
for (int j = 0; j < 3; j++)
|
|
mesh.Point(i)(j) =
|
|
lam * should.Get(i)(j) +
|
|
(1-lam) * can.Get(i)(j);
|
|
}
|
|
else
|
|
mesh.Point(i) = can.Get(i);
|
|
|
|
|
|
NgBitArray free (mesh.GetNP()), fhelp(mesh.GetNP());
|
|
free.Clear();
|
|
for (int i = 1; i <= mesh.GetNE(); i++)
|
|
{
|
|
const Element & el = mesh.VolumeElement(i);
|
|
if (el.Volume(mesh.Points()) < 0)
|
|
for (int j = 1; j <= el.GetNP(); j++)
|
|
free.Set (el.PNum(j));
|
|
}
|
|
for (int k = 1; k <= 3; k++)
|
|
{
|
|
fhelp.Clear();
|
|
for (int i = 1; i <= mesh.GetNE(); i++)
|
|
{
|
|
const Element & el = mesh.VolumeElement(i);
|
|
int freeel = 0;
|
|
for (int j = 1; j <= el.GetNP(); j++)
|
|
if (free.Test(el.PNum(j)))
|
|
freeel = 1;
|
|
if (freeel)
|
|
for (int j = 1; j <= el.GetNP(); j++)
|
|
fhelp.Set (el.PNum(j));
|
|
}
|
|
free.Or (fhelp);
|
|
}
|
|
|
|
(*testout) << "smooth points: " << endl;
|
|
for (int i = 1; i <= free.Size(); i++)
|
|
if (free.Test(i))
|
|
(*testout) << "p " << i << endl;
|
|
|
|
(*testout) << "surf points: " << endl;
|
|
for (auto & sel : mesh.SurfaceElements())
|
|
for (auto pi : sel.PNums())
|
|
(*testout) << pi << endl;
|
|
|
|
mesh.CalcSurfacesOfNode();
|
|
free.Invert();
|
|
mesh.FixPoints (free);
|
|
MeshingParameters dummymp;
|
|
mesh.ImproveMesh (dummymp, OPT_REST);
|
|
|
|
|
|
wrongels = 0;
|
|
for (int i = 1; i <= mesh.GetNE(); i++)
|
|
{
|
|
if (mesh.VolumeElement(i).Volume(mesh.Points()) < 0)
|
|
{
|
|
wrongels++;
|
|
mesh.VolumeElement(i).Flags().badel = 1;
|
|
(*testout) << "wrong el: ";
|
|
for (int j = 1; j <= 4; j++)
|
|
(*testout) << mesh.VolumeElement(i).PNum(j) << " ";
|
|
(*testout) << endl;
|
|
}
|
|
else
|
|
mesh.VolumeElement(i).Flags().badel = 0;
|
|
}
|
|
cout << "wrongels = " << wrongels << endl;
|
|
}
|
|
while (wrongels && cnttrials > 0);
|
|
|
|
for (int i = 1; i <= np; i++)
|
|
can.Elem(i) = mesh.Point(i);
|
|
}
|
|
}
|
|
|
|
if (cnttrials <= 0)
|
|
{
|
|
cerr << "ERROR: Sorry, reverted elements" << endl;
|
|
}
|
|
|
|
mesh.ComputeNVertices();
|
|
}
|
|
}
|