netgen/libsrc/meshing/bisect.cpp
Joachim Schoeberl 8f73a00d2d code cleanup
2024-12-15 18:00:50 +01:00

4179 lines
99 KiB
C++

#include <mystdlib.h>
#include <core/array.hpp>
#include "bisect.hpp"
#include "validate.hpp"
#include "meshing.hpp" // quickfix for parallel
#define noDEBUG
namespace netgen
{
class MarkedTet
{
public:
/// pnums of tet
PointIndex pnums[4];
/// material number
int matindex;
/// element marked for refinement
/// marked = 1: marked by element marker, marked = 2 due to closure
unsigned int marked:2;
/// flag of Arnold-Mukherjee algorithm
unsigned int flagged:1;
/// tetedge (local coordinates 0..3)
unsigned int tetedge1:3;
unsigned int tetedge2:3;
// marked edge of faces
// face_j : face without node j,
// mark_k : edge without node k
char faceedges[4];
// unsigned char faceedges[4];
bool incorder;
unsigned int order:6;
int8_t newest_vertex;
MarkedTet() = default;
/*
{
for (int i = 0; i < 4; i++) { faceedges[i] = 127; }
}
*/
MarkedTet (const MarkedTet&) = default;
MarkedTet (MarkedTet &&) = default;
MarkedTet & operator= (const MarkedTet&) = default;
MarkedTet & operator= (MarkedTet&&) = default;
};
ostream & operator<< (ostream & ost, const MarkedTet & mt)
{
for(int i=0; i<4; i++)
ost << mt.pnums[i] << " ";
ost << mt.matindex << " " << int(mt.marked) << " " << int(mt.flagged) << " " << int(mt.tetedge1) << " " << int(mt.tetedge2) << " ";
ost << "faceedges = ";
for(int i=0; i<4; i++)
ost << int(mt.faceedges[i]) << " ";
ost << " order = ";
ost << mt.incorder << " " << int(mt.order) << "\n";
return ost;
}
istream & operator>> (istream & ost, MarkedTet & mt)
{
for(int i=0; i<4; i++)
ost >> mt.pnums[i];
ost >> mt.matindex;
int auxint;
ost >> auxint;
mt.marked = auxint;
ost >> auxint;
mt.flagged = auxint;
ost >> auxint;
mt.tetedge1 = auxint;
ost >> auxint;
mt.tetedge2 = auxint;
char auxchar;
for(int i=0; i<4; i++)
{
ost >> auxchar;
mt.faceedges[i] = auxchar;
}
ost >> mt.incorder;
ost >> auxint;
mt.order = auxint;
return ost;
}
class MarkedPrism
{
public:
/// 6 point numbers
PointIndex pnums[6];
/// material number
int matindex;
/// marked for refinement
int marked;
/// edge without node k (0,1,2)
int markededge;
bool incorder;
unsigned int order:6;
};
ostream & operator<< (ostream & ost, const MarkedPrism & mp)
{
for(int i=0; i<6; i++)
ost << mp.pnums[i] << " ";
ost << mp.matindex << " " << mp.marked << " " << mp.markededge << " " << mp.incorder << " " << int(mp.order) << "\n";
return ost;
}
istream & operator>> (istream & ist, MarkedPrism & mp)
{
for(int i=0; i<6; i++)
ist >> mp.pnums[i];
ist >> mp.matindex >> mp.marked >> mp.markededge >> mp.incorder;
int auxint;
ist >> auxint;
mp.order = auxint;
return ist;
}
class MarkedIdentification
{
public:
// number of points of one face (3 or 4) - or edge (in 2d)
int np;
/// 6 or 8 point numbers - or 4 in 2d
PointIndex pnums[8];
/// marked for refinement
int marked;
/// edge starting with node k (0,1,2, or 3)
int markededge;
bool incorder;
unsigned int order:6;
};
ostream & operator<< (ostream & ost, const MarkedIdentification & mi)
{
ost << mi.np << " ";
for(int i=0; i<2*mi.np; i++)
ost << mi.pnums[i] << " ";
ost << mi.marked << " " << mi.markededge << " " << mi.incorder << " " << int(mi.order) << "\n";
return ost;
}
istream & operator>> (istream & ist, MarkedIdentification & mi)
{
ist >> mi.np;
for(int i=0; i<2*mi.np; i++)
ist >> mi.pnums[i];
ist >> mi.marked >> mi.markededge >> mi.incorder;
int auxint;
ist >> auxint;
mi.order = auxint;
return ist;
}
class MarkedTri
{
public:
MarkedTri () = default;
MarkedTri (const MarkedTri&) = default;
MarkedTri (MarkedTri &&) = default;
MarkedTri & operator= (const MarkedTri&) = default;
MarkedTri & operator= (MarkedTri&&) = default;
/// three point numbers
PointIndex pnums[3];
/// three geominfos
PointGeomInfo pgeominfo[3];
/// marked for refinement
int marked;
/// edge without node k
int markededge;
/// surface id
int surfid;
bool incorder;
unsigned int order:6;
int8_t newest_vertex;
};
ostream & operator<< (ostream & ost, const MarkedTri & mt)
{
for(int i=0; i<3; i++)
ost << mt.pnums[i] << " ";
for(int i=0; i<3; i++)
ost << mt.pgeominfo[i] << " ";
ost << mt.marked << " " << mt.markededge << " " << mt.surfid << " " << mt.incorder << " " << int(mt.order) << "\n";
return ost;
}
istream & operator>> (istream & ist, MarkedTri & mt)
{
for(int i=0; i<3; i++)
ist >> mt.pnums[i];
for(int i=0; i<3; i++)
ist >> mt.pgeominfo[i];
ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder;
int auxint;
ist >> auxint;
mt.order = auxint;
return ist;
}
class MarkedQuad
{
public:
/// point numbers
PointIndex pnums[4];
///
PointGeomInfo pgeominfo[4];
/// marked for refinement
int marked;
/// marked edge: 0/2 = vertical, 1/3 = horizontal
int markededge;
/// surface id
int surfid;
bool incorder;
unsigned int order:6;
};
ostream & operator<< (ostream & ost, const MarkedQuad & mt)
{
for(int i=0; i<4; i++)
ost << mt.pnums[i] << " ";
for(int i=0; i<4; i++)
ost << mt.pgeominfo[i] << " ";
ost << mt.marked << " " << mt.markededge << " " << mt.surfid << " " << mt.incorder << " " << int(mt.order) << "\n";
return ost;
}
istream & operator>> (istream & ist, MarkedQuad & mt)
{
for(int i=0; i<4; i++)
ist >> mt.pnums[i];
for(int i=0; i<4; i++)
ist >> mt.pgeominfo[i];
ist >> mt.marked >> mt.markededge >> mt.surfid >> mt.incorder;
int auxint;
ist >> auxint;
mt.order = auxint;
return ist;
}
void PrettyPrint(ostream & ost, const MarkedTet & mt)
{
int te1 = mt.tetedge1;
int te2 = mt.tetedge2;
int order = mt.order;
ost << "MT: " << mt.pnums[0] << " - " << mt.pnums[1] << " - "
<< mt.pnums[2] << " - " << mt.pnums[3] << endl
<< "marked edge: " << te1 << " - " << te2
<< ", order = " << order << endl;
//for (int k = 0; k < 4; k++)
// ost << int(mt.faceedges[k]) << " ";
for (int k = 0; k < 4; k++)
{
ost << "face";
for (int j=0; j<4; j++)
if(j != k)
ost << " " << mt.pnums[j];
for(int i=0; i<3; i++)
for(int j=i+1; j<4; j++)
if(i != k && j != k && int(mt.faceedges[k]) == 6-k-i-j)
ost << " marked edge " << mt.pnums[i] << " " << mt.pnums[j] << endl;
}
ost << endl;
}
int BTSortEdges (const Mesh & mesh,
const NgArray< NgArray<int,PointIndex::BASE>* > & idmaps,
INDEX_2_CLOSED_HASHTABLE<int> & edgenumber)
{
PrintMessage(4,"sorting ... ");
// if (mesh.PureTetMesh())
if (1)
{
// new, fast version
NgArray<INDEX_2> edges;
NgArray<int> eclasses;
int i, j, k;
int cntedges = 0;
int go_on;
int ned(0);
// enumerate edges:
for (i = 1; i <= mesh.GetNE(); i++)
{
const Element & el = mesh.VolumeElement (i);
static int tetedges[6][2] =
{ { 1, 2 },
{ 1, 3 },
{ 1, 4 },
{ 2, 3 },
{ 2, 4 },
{ 3, 4 } } ;
static int prismedges[9][2] =
{ { 1, 2 },
{ 1, 3 },
{ 2, 3 },
{ 4, 5 },
{ 4, 6 },
{ 5, 6 },
{ 1, 4 },
{ 2, 5 },
{ 3, 6 } };
int pyramidedges[6][2] =
{ { 1, 2 },
{ 3, 4 },
{ 1, 5 },
{ 2, 5 },
{ 3, 5 },
{ 4, 5 } };
int (*tip)[2] = NULL;
switch (el.GetType())
{
case TET:
case TET10:
{
tip = tetedges;
ned = 6;
break;
}
case PRISM:
case PRISM12:
{
tip = prismedges;
ned = 6;
break;
}
case PYRAMID:
{
tip = pyramidedges;
ned = 6;
break;
}
default:
throw NgException("Bisect, element type not handled in switch");
}
for (j = 0; j < ned; j++)
{
PointIndices<2> i2(el.PNum(tip[j][0]), el.PNum(tip[j][1]));
i2.Sort();
//(*testout) << "edge " << i2 << endl;
if (!edgenumber.Used(i2))
{
cntedges++;
edges.Append (i2);
edgenumber.Set(i2, cntedges);
}
}
}
// additional surface edges:
for (i = 1; i <= mesh.GetNSE(); i++)
{
const Element2d & el = mesh.SurfaceElement (i);
static int trigedges[3][2] =
{ { 1, 2 },
{ 2, 3 },
{ 3, 1 } };
static int quadedges[4][2] =
{ { 1, 2 },
{ 2, 3 },
{ 3, 4 },
{ 4, 1 } };
int (*tip)[2] = NULL;
switch (el.GetType())
{
case TRIG:
case TRIG6:
{
tip = trigedges;
ned = 3;
break;
}
case QUAD:
case QUAD6:
{
tip = quadedges;
ned = 4;
break;
}
default:
{
cerr << "Error: Sort for Bisect, SE has " << el.GetNP() << " points" << endl;
ned = 0;
}
}
for (j = 0; j < ned; j++)
{
PointIndices<2> i2(el.PNum(tip[j][0]), el.PNum(tip[j][1]));
i2.Sort();
if (!edgenumber.Used(i2))
{
cntedges++;
edges.Append (i2);
edgenumber.Set(i2, cntedges);
}
}
}
eclasses.SetSize (cntedges);
for (i = 1; i <= cntedges; i++)
eclasses.Elem(i) = i;
// identify edges in element stack
do
{
go_on = 0;
for (i = 1; i <= mesh.GetNE(); i++)
{
const Element & el = mesh.VolumeElement (i);
if (el.GetType() != PRISM &&
el.GetType() != PRISM12 &&
el.GetType() != PYRAMID)
continue;
int prismpairs[3][4] =
{ { 1, 2, 4, 5 },
{ 2, 3, 5, 6 },
{ 1, 3, 4, 6 } };
int pyramidpairs[3][4] =
{ { 1, 2, 4, 3 },
{ 1, 5, 4, 5 },
{ 2, 5, 3, 5 } };
int (*pairs)[4] = NULL;
switch (el.GetType())
{
case PRISM:
case PRISM12:
{
pairs = prismpairs;
break;
}
case PYRAMID:
{
pairs = pyramidpairs;
break;
}
default:
throw NgException("Bisect, element type not handled in switch, 2");
}
for (j = 0; j < 3; j++)
{
PointIndices<2> e1 (el.PNum(pairs[j][0]),
el.PNum(pairs[j][1]));
PointIndices<2> e2 (el.PNum(pairs[j][2]),
el.PNum(pairs[j][3]));
e1.Sort();
e2.Sort();
int eclass1 = edgenumber.Get (e1);
int eclass2 = edgenumber.Get (e2);
// (*testout) << "identify edges " << eclass1 << "-" << eclass2 << endl;
if (eclasses.Get(eclass1) >
eclasses.Get(eclass2))
{
eclasses.Elem(eclass1) =
eclasses.Get(eclass2);
go_on = 1;
}
else if (eclasses.Get(eclass2) >
eclasses.Get(eclass1))
{
eclasses.Elem(eclass2) =
eclasses.Get(eclass1);
go_on = 1;
}
}
}
for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
{
const Element2d & el2d = mesh[sei];
for(i = 0; i < el2d.GetNP(); i++)
{
PointIndices<2> e1(el2d[i], el2d[(i+1) % el2d.GetNP()]);
e1.Sort();
PointIndices<2> e2;
for(k = 0; k < idmaps.Size(); k++)
{
e2[0] = (*idmaps[k])[e1[0]];
e2[1] = (*idmaps[k])[e1[1]];
if(e2.I1() == 0 || e2.I2() == 0 ||
e1.I1() == e2.I1() || e1.I2() == e2.I2())
continue;
e2.Sort();
if(!edgenumber.Used(e2))
continue;
int eclass1 = edgenumber.Get (e1);
int eclass2 = edgenumber.Get (e2);
if (eclasses.Get(eclass1) >
eclasses.Get(eclass2))
{
eclasses.Elem(eclass1) =
eclasses.Get(eclass2);
go_on = 1;
}
else if (eclasses.Get(eclass2) >
eclasses.Get(eclass1))
{
eclasses.Elem(eclass2) =
eclasses.Get(eclass1);
go_on = 1;
}
}
}
}
}
while (go_on);
// for (i = 1; i <= cntedges; i++)
// {
// (*testout) << "edge " << i << ": "
// << edges.Get(i).I1() << "-" << edges.Get(i).I2()
// << ", class = " << eclasses.Get(i) << endl;
// }
// compute classlength:
NgArray<double> edgelength(cntedges);
/*
for (i = 1; i <= cntedges; i++)
edgelength.Elem(i) = 1e20;
*/
for (i = 1; i <= cntedges; i++)
{
INDEX_2 edge = edges.Get(i);
double elen = Dist (mesh.Point(edge.I1()),
mesh.Point(edge.I2()));
edgelength.Elem (i) = elen;
}
/*
for (i = 1; i <= mesh.GetNE(); i++)
{
const Element & el = mesh.VolumeElement (i);
if (el.GetType() == TET)
{
for (j = 1; j <= 3; j++)
for (k = j+1; k <= 4; k++)
{
INDEX_2 i2(el.PNum(j), el.PNum(k));
i2.Sort();
int enr = edgenumber.Get(i2);
double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));
if (elen < edgelength.Get(enr))
edgelength.Set (enr, elen);
}
}
else if (el.GetType() == PRISM)
{
for (j = 1; j <= 3; j++)
{
k = (j % 3) + 1;
INDEX_2 i2(el.PNum(j), el.PNum(k));
i2.Sort();
int enr = edgenumber.Get(i2);
double elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));
if (elen < edgelength.Get(enr))
edgelength.Set (enr, elen);
i2 = INDEX_2(el.PNum(j+3), el.PNum(k+3));
i2.Sort();
enr = edgenumber.Get(i2);
elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));
if (elen < edgelength.Get(enr))
edgelength.Set (enr, elen);
if (!edgenumber.Used(i2))
{
cntedges++;
edgenumber.Set(i2, cntedges);
}
i2 = INDEX_2(el.PNum(j), el.PNum(j+3));
i2.Sort();
enr = edgenumber.Get(i2);
elen = Dist (mesh.Point (i2.I1()), mesh.Point (i2.I2()));
if (elen < edgelength.Get(enr))
edgelength.Set (enr, elen);
}
}
}
*/
for (i = 1; i <= cntedges; i++)
{
if (eclasses.Get(i) != i)
{
if (edgelength.Get(i) < edgelength.Get(eclasses.Get(i)))
edgelength.Elem(eclasses.Get(i)) = edgelength.Get(i);
edgelength.Elem(i) = 1e20;
}
}
TABLE<int> eclasstab(cntedges);
for (i = 1; i <= cntedges; i++)
eclasstab.Add1 (eclasses.Get(i), i);
// sort edges:
NgArray<int> sorted(cntedges);
QuickSort (edgelength, sorted);
int cnt = 0;
for (i = 1; i <= cntedges; i++)
{
int ii = sorted.Get(i);
for (j = 1; j <= eclasstab.EntrySize(ii); j++)
{
cnt++;
edgenumber.Set (edges.Get(eclasstab.Get(ii, j)), cnt);
}
}
return cnt;
}
else
{
// old version
int i, j;
int cnt = 0;
int found;
double len2, maxlen2;
INDEX_2 ep;
// sort edges by length, parallel edges (on prisms)
// are added in blocks
do
{
found = 0;
maxlen2 = 1e30;
for (i = 1; i <= mesh.GetNE(); i++)
{
const Element & el = mesh.VolumeElement (i);
int ned;
int tetedges[6][2] =
{ { 1, 2 },
{ 1, 3 },
{ 1, 4 },
{ 2, 3 },
{ 2, 4 },
{ 3, 4 } };
int prismedges[6][2] =
{ { 1, 2 },
{ 1, 3 },
{ 2, 4 },
{ 4, 5 },
{ 4, 6 },
{ 5, 6 } };
int pyramidedges[6][2] =
{ { 1, 2 },
{ 3, 4 },
{ 1, 5 },
{ 2, 5 },
{ 3, 5 },
{ 4, 5 } };
int (*tip)[2];
switch (el.GetType())
{
case TET:
{
tip = tetedges;
ned = 6;
break;
}
case PRISM:
{
tip = prismedges;
ned = 6;
break;
}
case PYRAMID:
{
tip = pyramidedges;
ned = 6;
break;
}
default:
throw NgException("Bisect, element type not handled in switch, 3");
}
for (j = 0; j < ned; j++)
{
PointIndices<2> i2(el.PNum(tip[j][0]), el.PNum(tip[j][1]));
i2.Sort();
if (!edgenumber.Used(i2))
{
len2 = Dist (mesh.Point (i2.I1()),
mesh.Point (i2.I2()));
if (len2 < maxlen2)
{
maxlen2 = len2;
ep = i2;
found = 1;
}
}
}
}
if (found)
{
cnt++;
edgenumber.Set (ep, cnt);
// find connected edges:
int go_on = 0;
do
{
go_on = 0;
for (i = 1; i <= mesh.GetNE(); i++)
{
const Element & el = mesh.VolumeElement (i);
if (el.GetNP() != 6) continue;
int prismpairs[3][4] =
{ { 1, 2, 4, 5 },
{ 2, 3, 5, 6 },
{ 1, 3, 4, 6 } };
int pyramidpairs[3][4] =
{ { 1, 2, 4, 3 },
{ 1, 5, 4, 5 },
{ 2, 5, 3, 5 } };
int (*pairs)[4];
switch (el.GetType())
{
case PRISM:
{
pairs = prismpairs;
break;
}
case PYRAMID:
{
pairs = pyramidpairs;
break;
}
default:
throw NgException("Bisect, element type not handled in switch, 3a");
}
for (j = 0; j < 3; j++)
{
PointIndices<2> e1 (el.PNum(pairs[j][0]),
el.PNum(pairs[j][1]));
PointIndices<2> e2 (el.PNum(pairs[j][2]),
el.PNum(pairs[j][3]));
e1.Sort();
e2.Sort();
int used1 = edgenumber.Used (e1);
int used2 = edgenumber.Used (e2);
if (used1 && !used2)
{
cnt++;
edgenumber.Set (e2, cnt);
go_on = 1;
}
if (used2 && !used1)
{
cnt++;
edgenumber.Set (e1, cnt);
go_on = 1;
}
}
}
}
while (go_on);
}
}
while (found);
return cnt;
}
}
void BTDefineMarkedTet (const Element & el,
INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
MarkedTet & mt)
{
for (int i = 0; i < 4; i++)
mt.pnums[i] = el[i];
mt.marked = 0;
mt.flagged = 0;
mt.incorder = 0;
mt.order = 1;
int val = 0;
// find marked edge of tet:
for (int i = 0; i < 3; i++)
for (int j = i+1; j < 4; j++)
{
PointIndices<2> i2(mt.pnums[i], mt.pnums[j]);
i2.Sort();
int hval = edgenumber.Get(i2);
if (hval > val)
{
val = hval;
mt.tetedge1 = i;
mt.tetedge2 = j;
}
}
// find marked edges of faces:
for (int k = 0; k < 4; k++)
{
val = 0;
for (int i = 0; i < 3; i++)
for (int j = i+1; j < 4; j++)
if (i != k && j != k)
{
PointIndices<2> i2(mt.pnums[i], mt.pnums[j]);
i2.Sort();
int hval = edgenumber.Get(i2);
if (hval > val)
{
val = hval;
int hi = 6 - k - i - j;
mt.faceedges[k] = char(hi);
}
}
}
}
void BTDefineMarkedPrism (const Element & el,
INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
MarkedPrism & mp)
{
if (el.GetType() == PRISM ||
el.GetType() == PRISM12)
{
for (int i = 0; i < 6; i++)
mp.pnums[i] = el[i];
}
else if (el.GetType() == PYRAMID)
{
static int map[6] =
{ 1, 2, 5, 4, 3, 5 };
for (int i = 0; i < 6; i++)
mp.pnums[i] = el.PNum(map[i]);
}
else if (el.GetType() == TET ||
el.GetType() == TET10)
{
static int map[6] =
{ 1, 4, 3, 2, 4, 3 };
for (int i = 0; i < 6; i++)
mp.pnums[i] = el.PNum(map[i]);
}
else
{
PrintSysError ("Define marked prism called for non-prism and non-pyramid");
}
mp.marked = 0;
mp.incorder = 0;
mp.order = 1;
int val = 0;
for (int i = 0; i < 2; i++)
for (int j = i+1; j < 3; j++)
{
PointIndices<2> i2(mp.pnums[i], mp.pnums[j]);
i2.Sort();
int hval = edgenumber.Get(i2);
if (hval > val)
{
val = hval;
mp.markededge = 3 - i - j;
}
}
}
bool BTDefineMarkedId(const Element2d & el,
INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
const NgArray<int,PointIndex::BASE> & idmap,
MarkedIdentification & mi)
{
bool identified = true;
mi.np = el.GetNP();
// int min1(0),min2(0);
PointIndex min1(PointIndex::INVALID), min2(PointIndex::INVALID);
for(int j = 0; identified && j < mi.np; j++)
{
mi.pnums[j] = el[j];
mi.pnums[j+mi.np] = idmap[el[j]];
if(j == 0 || el[j] < min1)
min1 = el[j];
if(j == 0 || mi.pnums[j+mi.np] < min2)
min2 = mi.pnums[j+mi.np];
identified = (mi.pnums[j+mi.np].IsValid() && mi.pnums[j+mi.np] != mi.pnums[j]);
}
identified = identified && (min1 < min2);
if(identified)
{
mi.marked = 0;
mi.incorder = 0;
mi.order = 1;
int val = 0;
for (int i = 0; i < mi.np; i++)
{
PointIndices<2> i2(mi.pnums[i], mi.pnums[(i+1)%mi.np]);
i2.Sort();
int hval = edgenumber.Get(i2);
if (hval > val)
{
val = hval;
mi.markededge = i;
}
}
}
return identified;
}
void BTDefineMarkedTri (const Element2d & el,
INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
MarkedTri & mt)
{
for (int i = 0; i < 3; i++)
{
mt.pnums[i] = el[i];
mt.pgeominfo[i] = el.GeomInfoPi (i+1);
}
mt.marked = 0;
mt.surfid = el.GetIndex();
mt.incorder = 0;
mt.order = 1;
int val = 0;
for (int i = 0; i < 2; i++)
for (int j = i+1; j < 3; j++)
{
PointIndices<2> i2(mt.pnums[i], mt.pnums[j]);
i2.Sort();
int hval = edgenumber.Get(i2);
if (hval > val)
{
val = hval;
mt.markededge = 3 - i - j;
}
}
}
void PrettyPrint(ostream & ost, const MarkedTri & mt)
{
ost << "MarkedTrig: " << endl;
ost << " pnums = "; for (int i=0; i<3; i++) ost << mt.pnums[i] << " "; ost << endl;
ost << " marked = " << mt.marked << ", markededge=" << mt.markededge << endl;
for(int i=0; i<2; i++)
for(int j=i+1; j<3; j++)
if(mt.markededge == 3-i-j)
ost << " marked edge pnums = " << mt.pnums[i] << " " << mt.pnums[j] << endl;
}
void PrettyPrint(ostream & ost, const MarkedQuad & mq)
{
ost << "MarkedQuad: " << endl;
ost << " pnums = "; for (int i=0; i<4; i++) ost << mq.pnums[i] << " "; ost << endl;
ost << " marked = " << mq.marked << ", markededge=" << mq.markededge << endl;
}
void BTDefineMarkedQuad (const Element2d & el,
INDEX_2_CLOSED_HASHTABLE<int> & edgenumber,
MarkedQuad & mq)
{
for (int i = 0; i < 4; i++)
{
mq.pnums[i] = el[i];
mq.pgeominfo[i] = el.GeomInfoPi (i+1);
}
Swap (mq.pnums[2], mq.pnums[3]);
Swap (mq.pgeominfo[2], mq.pgeominfo[3]);
mq.marked = 0;
mq.markededge = 0;
mq.surfid = el.GetIndex();
}
// mark elements due to local h
int BTMarkTets (T_MTETS & mtets,
T_MPRISMS & mprisms,
const Mesh & mesh)
{
int marked = 0;
int np = mesh.GetNP();
Vector hv(np);
for (int i = 0; i < np; i++)
hv(i) = mesh.GetH (mesh.Point(i+1));
double hfac = 1;
for (int step = 1; step <= 2; step++)
{
for (int i = 1; i <= mtets.Size(); i++)
{
double h = 0;
for (int j = 0; j < 3; j++)
for (int k = j+1; k < 4; k++)
{
const Point<3> & p1 = mesh.Point (mtets[i-1].pnums[j]);
const Point<3> & p2 = mesh.Point (mtets[i-1].pnums[k]);
double hh = Dist2 (p1, p2);
if (hh > h) h = hh;
}
h = sqrt (h);
double hshould = 1e10;
for (int j = 0; j < 4; j++)
{
double hi = hv (mtets[i-1].pnums[j]-IndexBASE<PointIndex>());
if (hi < hshould)
hshould = hi;
}
if (step == 1)
{
if (h / hshould > hfac)
hfac = h / hshould;
}
else
{
if (h > hshould * hfac)
{
mtets[i-1].marked = 1;
marked = 1;
}
else
mtets[i-1].marked = 0;
}
}
for (int i = 1; i <= mprisms.Size(); i++)
{
double h = 0;
for (int j = 0; j < 2; j++)
for (int k = j+1; k < 3; k++)
{
const Point<3> & p1 = mesh.Point (mprisms.Get(i).pnums[j]);
const Point<3> & p2 = mesh.Point (mprisms.Get(i).pnums[k]);
double hh = Dist2 (p1, p2);
if (hh > h) h = hh;
}
h = sqrt (h);
double hshould = 1e10;
for (int j = 0; j < 6; j++)
{
double hi = hv (mprisms.Get(i).pnums[j]-IndexBASE<PointIndex>());
if (hi < hshould)
hshould = hi;
}
if (step == 1)
{
if (h / hshould > hfac)
hfac = h / hshould;
}
else
{
if (h > hshould * hfac)
{
mprisms.Elem(i).marked = 1;
marked = 1;
}
else
mprisms.Elem(i).marked = 0;
}
}
if (step == 1)
{
if (hfac > 2)
hfac /= 2;
else
hfac = 1;
}
}
return marked;
}
void BTBisectTet (const MarkedTet & oldtet, PointIndex newp,
MarkedTet & newtet1, MarkedTet & newtet2)
{
#ifdef DEBUG
*testout << "bisect tet " << oldtet << endl;
#endif
// points vis a vis from tet-edge
int vis1, vis2;
vis1 = 0;
while (vis1 == oldtet.tetedge1 || vis1 == oldtet.tetedge2)
vis1++;
vis2 = 6 - vis1 - oldtet.tetedge1 - oldtet.tetedge2;
// is tet of type P ?
int istypep = 0;
for (int i = 0; i < 4; i++)
{
int cnt = 0;
for (int j = 0; j < 4; j++)
if (oldtet.faceedges[j] == i)
cnt++;
if (cnt == 3)
istypep = 1;
}
for (int i = 0; i < 4; i++)
{
newtet1.pnums[i] = oldtet.pnums[i];
newtet2.pnums[i] = oldtet.pnums[i];
}
newtet1.flagged = istypep && !oldtet.flagged;
newtet2.flagged = istypep && !oldtet.flagged;
int nm = oldtet.marked - 1;
if (nm < 0) nm = 0;
newtet1.marked = nm;
newtet2.marked = nm;
newtet1.newest_vertex = oldtet.newest_vertex;
#ifdef DEBUG
*testout << "newtet1,before = " << newtet1 << endl;
*testout << "newtet2,before = " << newtet2 << endl;
#endif
for (int i = 0; i < 4; i++)
{
if (i == oldtet.tetedge1)
{
newtet2.newest_vertex = i;
newtet2.pnums[i] = newp;
newtet2.faceedges[i] = oldtet.faceedges[i]; // inherited face
newtet2.faceedges[vis1] = i; // cut faces
newtet2.faceedges[vis2] = i;
int j = 0;
while (j == i || j == oldtet.faceedges[i])
j++;
int k = 6 - i - oldtet.faceedges[i] - j;
newtet2.tetedge1 = j; // tet-edge
newtet2.tetedge2 = k;
// new face:
if (istypep && oldtet.flagged)
{
int hi = 6 - oldtet.tetedge1 - j - k;
newtet2.faceedges[oldtet.tetedge2] = char(hi);
}
else
newtet2.faceedges[oldtet.tetedge2] = oldtet.tetedge1;
#ifdef DEBUG
*testout << "i = " << i << ", j = " << j << " k = " << k
<< " oldtet.tetedge1 = " << oldtet.tetedge1
<< " oldtet.tetedge2 = " << oldtet.tetedge2
<< " 6-oldtet.tetedge1-j-k = " << 6 - oldtet.tetedge1 - j - k
<< " 6-oldtet.tetedge1-j-k = " << short(6 - oldtet.tetedge1 - j - k)
<< endl;
*testout << "vis1 = " << vis1 << ", vis2 = " << vis2 << endl;
for (int j = 0; j < 4; j++)
if (newtet2.faceedges[j] > 3)
{
*testout << "ERROR1" << endl;
}
#endif
}
if (i == oldtet.tetedge2)
{
newtet1.pnums[i] = newp;
newtet1.faceedges[i] = oldtet.faceedges[i]; // inherited face
newtet1.faceedges[vis1] = i;
newtet1.faceedges[vis2] = i;
int j = 0;
while (j == i || j == oldtet.faceedges[i])
j++;
int k = 6 - i - oldtet.faceedges[i] - j;
newtet1.tetedge1 = j;
newtet1.tetedge2 = k;
// new face:
if (istypep && oldtet.flagged)
{
int hi = 6 - oldtet.tetedge2 - j - k;
newtet1.faceedges[oldtet.tetedge1] = char(hi);
}
else
newtet1.faceedges[oldtet.tetedge1] = oldtet.tetedge2;
#ifdef DEBUG
for (int j = 0; j < 4; j++)
if (newtet2.faceedges[j] > 3)
{
*testout << "ERROR2" << endl;
}
#endif
}
}
newtet1.matindex = oldtet.matindex;
newtet2.matindex = oldtet.matindex;
newtet1.incorder = 0;
newtet1.order = oldtet.order;
newtet2.incorder = 0;
newtet2.order = oldtet.order;
// *testout << "newtet1 = " << newtet1 << endl;
// *testout << "newtet2 = " << newtet2 << endl;
}
void BTBisectPrism (const MarkedPrism & oldprism, PointIndex newp1, PointIndex newp2,
MarkedPrism & newprism1, MarkedPrism & newprism2)
{
for (int i = 0; i < 6; i++)
{
newprism1.pnums[i] = oldprism.pnums[i];
newprism2.pnums[i] = oldprism.pnums[i];
}
int pe1 = 0;
if (pe1 == oldprism.markededge)
pe1++;
int pe2 = 3 - oldprism.markededge - pe1;
newprism1.pnums[pe2] = newp1;
newprism1.pnums[pe2+3] = newp2;
newprism1.markededge = pe2;
newprism2.pnums[pe1] = newp1;
newprism2.pnums[pe1+3] = newp2;
newprism2.markededge = pe1;
newprism1.matindex = oldprism.matindex;
newprism2.matindex = oldprism.matindex;
int nm = oldprism.marked - 1;
if (nm < 0) nm = 0;
newprism1.marked = nm;
newprism2.marked = nm;
newprism1.incorder = 0;
newprism1.order = oldprism.order;
newprism2.incorder = 0;
newprism2.order = oldprism.order;
}
void BTBisectIdentification (const MarkedIdentification & oldid,
NgArray<PointIndex> & newp,
MarkedIdentification & newid1,
MarkedIdentification & newid2)
{
for(int i=0; i<2*oldid.np; i++)
{
newid1.pnums[i] = oldid.pnums[i];
newid2.pnums[i] = oldid.pnums[i];
}
newid1.np = newid2.np = oldid.np;
if(oldid.np == 2)
{
newid1.pnums[1] = newp[0];
newid2.pnums[0] = newp[0];
newid1.pnums[3] = newp[1];
newid2.pnums[2] = newp[1];
newid1.markededge = 0;
newid2.markededge = 0;
}
if(oldid.np == 3)
{
newid1.pnums[(oldid.markededge+1)%3] = newp[0];
newid1.pnums[(oldid.markededge+1)%3+3] = newp[1];
newid1.markededge = (oldid.markededge+2)%3;
newid2.pnums[oldid.markededge] = newp[0];
newid2.pnums[oldid.markededge+3] = newp[1];
newid2.markededge = (oldid.markededge+1)%3;
}
else if(oldid.np == 4)
{
newid1.pnums[(oldid.markededge+1)%4] = newp[0];
newid1.pnums[(oldid.markededge+2)%4] = newp[2];
newid1.pnums[(oldid.markededge+1)%4+4] = newp[1];
newid1.pnums[(oldid.markededge+2)%4+4] = newp[3];
newid1.markededge = (oldid.markededge+3)%4;
newid2.pnums[oldid.markededge] = newp[0];
newid2.pnums[(oldid.markededge+3)%4] = newp[2];
newid2.pnums[oldid.markededge+4] = newp[1];
newid2.pnums[(oldid.markededge+3)%4+4] = newp[3];
newid2.markededge = (oldid.markededge+1)%4;
}
int nm = oldid.marked - 1;
if (nm < 0) nm = 0;
newid1.marked = newid2.marked = nm;
newid1.incorder = newid2.incorder = 0;
newid1.order = newid2.order = oldid.order;
}
void BTBisectTri (const MarkedTri & oldtri, PointIndex newp, const PointGeomInfo & newpgi,
MarkedTri & newtri1, MarkedTri & newtri2)
{
for (int i = 0; i < 3; i++)
{
newtri1.pnums[i] = oldtri.pnums[i];
newtri1.pgeominfo[i] = oldtri.pgeominfo[i];
newtri2.pnums[i] = oldtri.pnums[i];
newtri2.pgeominfo[i] = oldtri.pgeominfo[i];
}
int pe1 = 0;
if (pe1 == oldtri.markededge)
pe1++;
int pe2 = 3 - oldtri.markededge - pe1;
newtri1.pnums[pe2] = newp;
newtri1.pgeominfo[pe2] = newpgi;
newtri1.markededge = pe2;
newtri1.newest_vertex = oldtri.newest_vertex;
newtri2.pnums[pe1] = newp;
newtri2.pgeominfo[pe1] = newpgi;
newtri2.markededge = pe1;
newtri2.newest_vertex = pe1;
newtri1.surfid = oldtri.surfid;
newtri2.surfid = oldtri.surfid;
int nm = oldtri.marked - 1;
if (nm < 0) nm = 0;
newtri1.marked = nm;
newtri2.marked = nm;
newtri1.incorder = 0;
newtri1.order = oldtri.order;
newtri2.incorder = 0;
newtri2.order = oldtri.order;
}
void BTBisectQuad (const MarkedQuad & oldquad,
PointIndex newp1, const PointGeomInfo & npgi1,
PointIndex newp2, const PointGeomInfo & npgi2,
MarkedQuad & newquad1, MarkedQuad & newquad2)
{
for (int i = 0; i < 4; i++)
{
newquad1.pnums[i] = oldquad.pnums[i];
newquad1.pgeominfo[i] = oldquad.pgeominfo[i];
newquad2.pnums[i] = oldquad.pnums[i];
newquad2.pgeominfo[i] = oldquad.pgeominfo[i];
}
/* if (oldquad.marked==1) // he/sz: 2d quads or 3d prism
{
newquad1.pnums[1] = newp1;
newquad1.pgeominfo[1] = npgi1;
newquad1.pnums[3] = newp2;
newquad1.pgeominfo[3] = npgi2;
newquad2.pnums[0] = newp1;
newquad2.pgeominfo[0] = npgi1;
newquad2.pnums[2] = newp2;
newquad2.pgeominfo[2] = npgi2;
}
else if (oldquad.marked==2) // he/sz: 2d quads only
{
newquad1.pnums[0] = newp1;
newquad1.pnums[1] = newp2;
newquad1.pnums[3] = oldquad.pnums[2];
newquad1.pnums[2] = oldquad.pnums[0];
newquad1.pgeominfo[0] = npgi1;
newquad1.pgeominfo[1] = npgi2;
newquad1.pgeominfo[3] = oldquad.pgeominfo[2];
newquad1.pgeominfo[2] = oldquad.pgeominfo[0];
newquad2.pnums[0] = newp2;
newquad2.pnums[1] = newp1;
newquad2.pnums[3] = oldquad.pnums[1];
newquad2.pnums[2] = oldquad.pnums[3];
newquad2.pgeominfo[0] = npgi2;
newquad2.pgeominfo[1] = npgi1;
newquad2.pgeominfo[3] = oldquad.pgeominfo[1];
newquad2.pgeominfo[2] = oldquad.pgeominfo[3];
}
*/
if (oldquad.markededge==0 || oldquad.markededge==2)
{
newquad1.pnums[1] = newp1;
newquad1.pgeominfo[1] = npgi1;
newquad1.pnums[3] = newp2;
newquad1.pgeominfo[3] = npgi2;
newquad2.pnums[0] = newp1;
newquad2.pgeominfo[0] = npgi1;
newquad2.pnums[2] = newp2;
newquad2.pgeominfo[2] = npgi2;
}
else // 1 || 3
{
newquad1.pnums[2] = newp1;
newquad1.pgeominfo[2] = npgi1;
newquad1.pnums[3] = newp2;
newquad1.pgeominfo[3] = npgi2;
newquad2.pnums[0] = newp1;
newquad2.pgeominfo[0] = npgi1;
newquad2.pnums[1] = newp2;
newquad2.pgeominfo[1] = npgi2;
}
newquad1.surfid = oldquad.surfid;
newquad2.surfid = oldquad.surfid;
int nm = oldquad.marked - 1;
if (nm < 0) nm = 0;
newquad1.marked = nm;
newquad2.marked = nm;
if (nm==1)
{
newquad1.markededge=1;
newquad2.markededge=1;
}
else
{
newquad1.markededge=0;
newquad2.markededge=0;
}
}
int MarkHangingIdentifications(T_MIDS & mids,
const INDEX_2_CLOSED_HASHTABLE<PointIndex> & cutedges)
{
int hanging = 0;
for (int i = 1; i <= mids.Size(); i++)
{
if (mids.Elem(i).marked)
{
hanging = 1;
continue;
}
const int np = mids.Get(i).np;
for(int j = 0; j < np; j++)
{
PointIndices<2> edge1(mids.Get(i).pnums[j],
mids.Get(i).pnums[(j+1) % np]);
PointIndices<2> edge2(mids.Get(i).pnums[j+np],
mids.Get(i).pnums[((j+1) % np) + np]);
edge1.Sort();
edge2.Sort();
if (cutedges.Used (edge1) ||
cutedges.Used (edge2))
{
mids.Elem(i).marked = 1;
hanging = 1;
}
}
}
return hanging;
}
/*
void IdentifyCutEdges(Mesh & mesh,
INDEX_2_CLOSED_HASHTABLE<int> & cutedges)
{
int i,j,k;
NgArray< NgArray<int,PointIndex::BASE>* > idmaps;
for(i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)
{
idmaps.Append(new NgArray<int,PointIndex::BASE>);
mesh.GetIdentifications().GetMap(i,*idmaps.Last());
}
for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
{
const Element2d & el2d = mesh[sei];
for(i = 0; i < el2d.GetNP(); i++)
{
INDEX_2 e1(el2d[i], el2d[(i+1) % el2d.GetNP()]);
e1.Sort();
if(!cutedges.Used(e1))
continue;
for(k = 0; k < idmaps.Size(); k++)
{
INDEX_2 e2((*idmaps[k])[e1.I1()],
(*idmaps[k])[e1.I2()]);
if(e2.I1() == 0 || e2.I2() == 0 ||
e1.I1() == e2.I1() || e1.I2() == e2.I2())
continue;
e2.Sort();
if(cutedges.Used(e2))
continue;
Point3d np = Center(mesh.Point(e2.I1()),
mesh.Point(e2.I2()));
int newp = mesh.AddPoint(np);
cutedges.Set(e2,newp);
(*testout) << "DAAA" << endl;
}
}
}
for(i=0; i<idmaps.Size(); i++)
delete idmaps[i];
idmaps.DeleteAll();
}
*/
int MarkHangingTets (T_MTETS & mtets,
const INDEX_2_CLOSED_HASHTABLE<PointIndex> & cutedges,
NgTaskManager tm)
{
static int timer = NgProfiler::CreateTimer ("MarkHangingTets");
NgProfiler::RegionTimer reg (timer);
int hanging = 0;
// for (int i = 1; i <= mtets.Size(); i++)
ParallelForRange
(tm, mtets.Size(), [&] (size_t begin, size_t end)
{
bool my_hanging = false;
for (size_t i = begin; i < end; i++)
{
MarkedTet & teti = mtets[i];
if (teti.marked)
{
my_hanging = true;
continue;
}
for (int j = 0; j < 3; j++)
for (int k = j+1; k < 4; k++)
{
PointIndices<2> edge(teti.pnums[j],
teti.pnums[k]);
edge.Sort();
if (cutedges.Used (edge))
{
teti.marked = 1;
my_hanging = true;
}
}
}
if (my_hanging) hanging = true;
});
return hanging;
}
int MarkHangingPrisms (T_MPRISMS & mprisms,
const INDEX_2_CLOSED_HASHTABLE<PointIndex> & cutedges)
{
int hanging = 0;
for (int i = 1; i <= mprisms.Size(); i++)
{
if (mprisms.Elem(i).marked)
{
hanging = 1;
continue;
}
for (int j = 0; j < 2; j++)
for (int k = j+1; k < 3; k++)
{
PointIndices<2> edge1(mprisms.Get(i).pnums[j],
mprisms.Get(i).pnums[k]);
PointIndices<2> edge2(mprisms.Get(i).pnums[j+3],
mprisms.Get(i).pnums[k+3]);
edge1.Sort();
edge2.Sort();
if (cutedges.Used (edge1) ||
cutedges.Used (edge2))
{
mprisms.Elem(i).marked = 1;
hanging = 1;
}
}
}
return hanging;
}
bool MarkHangingTris (T_MTRIS & mtris,
const INDEX_2_CLOSED_HASHTABLE<PointIndex> & cutedges,
NgTaskManager tm)
{
bool hanging = false;
// for (int i = 1; i <= mtris.Size(); i++)
// for (auto & tri : mtris)
ParallelForRange
(tm, mtris.Size(), [&] (size_t begin, size_t end)
{
bool my_hanging = false;
for (size_t i = begin; i < end; i++)
{
auto & tri = mtris[i];
if (tri.marked)
{
my_hanging = true;
continue;
}
for (int j = 0; j < 2; j++)
for (int k = j+1; k < 3; k++)
{
PointIndices<2> edge(tri.pnums[j],
tri.pnums[k]);
edge.Sort();
if (cutedges.Used (edge))
{
tri.marked = 1;
my_hanging = true;
}
}
}
if (my_hanging) hanging = true;
});
return hanging;
}
int MarkHangingQuads (T_MQUADS & mquads,
const INDEX_2_CLOSED_HASHTABLE<PointIndex> & cutedges)
{
int hanging = 0;
for (int i = 1; i <= mquads.Size(); i++)
{
if (mquads.Elem(i).marked)
{
hanging = 1;
continue;
}
PointIndices<2> edge1(mquads.Get(i).pnums[0],
mquads.Get(i).pnums[1]);
PointIndices<2> edge2(mquads.Get(i).pnums[2],
mquads.Get(i).pnums[3]);
edge1.Sort();
edge2.Sort();
if (cutedges.Used (edge1) ||
cutedges.Used (edge2))
{
mquads.Elem(i).marked = 1;
mquads.Elem(i).markededge = 0;
hanging = 1;
continue;
}
// he/sz: second case: split horizontally
PointIndices<2> edge3(mquads.Get(i).pnums[1],
mquads.Get(i).pnums[3]);
PointIndices<2> edge4(mquads.Get(i).pnums[2],
mquads.Get(i).pnums[0]);
edge3.Sort();
edge4.Sort();
if (cutedges.Used (edge3) ||
cutedges.Used (edge4))
{
mquads.Elem(i).marked = 1;
mquads.Elem(i).markededge = 1;
hanging = 1;
continue;
}
}
return hanging;
}
void ConnectToNodeRec (int node, int tonode,
const TABLE<int> & conto, NgArray<int> & connecttonode)
{
// (*testout) << "connect " << node << " to " << tonode << endl;
for (int i = 1; i <= conto.EntrySize(node); i++)
{
int n2 = conto.Get(node, i);
if (!connecttonode.Get(n2))
{
connecttonode.Elem(n2) = tonode;
ConnectToNodeRec (n2, tonode, conto, connecttonode);
}
}
}
BisectionInfo::BisectionInfo()
{
mtets = make_unique<T_MTETS>();
mprisms = make_unique<T_MPRISMS>();
mids = make_unique<T_MIDS>();
mtris = make_unique<T_MTRIS>();
mquads = make_unique<T_MQUADS>();
}
BisectionInfo::~BisectionInfo() {}
void WriteMarkedElements(const Mesh& mesh, ostream & ost)
{
ost << "Marked Elements\n";
const auto& mtets = *mesh.bisectioninfo.mtets;
const auto& mprisms = *mesh.bisectioninfo.mprisms;
const auto& mids = *mesh.bisectioninfo.mids;
const auto& mtris = *mesh.bisectioninfo.mtris;
const auto& mquads = *mesh.bisectioninfo.mquads;
ost << mtets.Size() << "\n";
for(int i=0; i<mtets.Size(); i++)
ost << mtets[i];
ost << mprisms.Size() << "\n";
for(int i=0; i<mprisms.Size(); i++)
ost << mprisms[i];
ost << mids.Size() << "\n";
for(int i=0; i<mids.Size(); i++)
ost << mids[i];
ost << mtris.Size() << "\n";
for(int i=0; i<mtris.Size(); i++)
ost << mtris[i];
ost << mquads.Size() << "\n";
for(int i=0; i<mquads.Size(); i++)
ost << mquads[i];
ost << endl;
}
bool ReadMarkedElements(istream & ist, const Mesh & mesh)
{
auto& mtets = *mesh.bisectioninfo.mtets;
auto& mprisms = *mesh.bisectioninfo.mprisms;
auto& mids = *mesh.bisectioninfo.mids;
auto& mtris = *mesh.bisectioninfo.mtris;
auto& mquads = *mesh.bisectioninfo.mquads;
string auxstring("");
if(ist)
ist >> auxstring;
if(auxstring != "Marked")
return false;
if(ist)
ist >> auxstring;
if(auxstring != "Elements")
return false;
int size;
ist >> size;
mtets.SetSize(size);
constexpr auto PI0 = IndexBASE<PointIndex>();
for(int i=0; i<size; i++)
{
ist >> mtets[i];
if(mtets[i].pnums[0] >= PI0+mesh.GetNV() ||
mtets[i].pnums[1] >= PI0+mesh.GetNV() ||
mtets[i].pnums[2] >= PI0+mesh.GetNV() ||
mtets[i].pnums[3] >= PI0+mesh.GetNV())
return false;
}
ist >> size;
mprisms.SetSize(size);
for(int i=0; i<size; i++)
ist >> mprisms[i];
ist >> size;
mids.SetSize(size);
for(int i=0; i<size; i++)
ist >> mids[i];
ist >> size;
mtris.SetSize(size);
for(int i=0; i<size; i++)
ist >> mtris[i];
ist >> size;
mquads.SetSize(size);
for(int i=0; i<size; i++)
ist >> mquads[i];
return true;
}
void BisectTetsCopyMesh (Mesh & mesh, const NetgenGeometry *,
BisectionOptions & opt,
const NgArray< NgArray<int,PointIndex::BASE>* > & idmaps,
const string & refinfofile)
{
auto& mtets = *mesh.bisectioninfo.mtets;
auto& mprisms = *mesh.bisectioninfo.mprisms;
auto& mids = *mesh.bisectioninfo.mids;
auto& mtris = *mesh.bisectioninfo.mtris;
auto& mquads = *mesh.bisectioninfo.mquads;
if (mesh.GetDimension() < 2)
throw Exception ("Mesh bisection is available in 2D and 3D");
// mtets.SetName ("bisection, tets");
// mprisms.SetName ("bisection, prisms");
// mtris.SetName ("bisection, trigs");
// nmquads.SetName ("bisection, quads");
// mids.SetName ("bisection, identifications");
//int np = mesh.GetNP();
int ne = mesh.GetNE();
int nse = mesh.GetNSE();
/*
if (mtets.Size() + mprisms.Size() == mesh.GetNE())
return;
*/
bool readok = false;
if(refinfofile != "")
{
PrintMessage(3,"Reading marked-element information from \"",refinfofile,"\"");
ifstream ist(refinfofile.c_str());
readok = ReadMarkedElements(ist,mesh);
ist.close();
}
if(!readok)
{
PrintMessage(3,"resetting marked-element information");
mtets.SetSize(0);
mprisms.SetSize(0);
mids.SetSize(0);
mtris.SetSize(0);
mquads.SetSize(0);
INDEX_2_HASHTABLE<int> shortedges(100);
for (int i = 1; i <= ne; i++)
{
const Element & el = mesh.VolumeElement(i);
if (el.GetType() == PRISM ||
el.GetType() == PRISM12)
{
for (int j = 1; j <= 3; j++)
{
PointIndices<2> se(el.PNum(j), el.PNum(j+3));
se.Sort();
shortedges.Set (se, 1);
}
}
}
// INDEX_2_HASHTABLE<int> edgenumber(np);
INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*ne+4*nse);
BTSortEdges (mesh, idmaps, edgenumber);
for (int i = 1; i <= ne; i++)
{
const Element & el = mesh.VolumeElement(i);
switch (el.GetType())
{
case TET:
case TET10:
{
// if tet has short edge, it is handled as degenerated prism
int foundse = 0;
for (int j = 1; j <= 3; j++)
for (int k = j+1; k <= 4; k++)
{
PointIndices<2> se(el.PNum(j), el.PNum(k));
se.Sort();
if (shortedges.Used (se))
{
// cout << "tet converted to prism" << endl;
foundse = 1;
int p3 = 1;
while (p3 == j || p3 == k)
p3++;
int p4 = 10 - j - k - p3;
// even permutation ?
int pi[4];
pi[0] = j;
pi[1] = k;
pi[2] = p3;
pi[3] = p4;
int cnt = 0;
for (int l = 1; l <= 4; l++)
for (int m = 0; m < 3; m++)
if (pi[m] > pi[m+1])
{
Swap (pi[m], pi[m+1]);
cnt++;
}
if (cnt % 2)
Swap (p3, p4);
Element hel = el;
hel.PNum(1) = el.PNum(j);
hel.PNum(2) = el.PNum(k);
hel.PNum(3) = el.PNum(p3);
hel.PNum(4) = el.PNum(p4);
MarkedPrism mp;
BTDefineMarkedPrism (hel, edgenumber, mp);
mp.matindex = el.GetIndex();
mprisms.Append (mp);
}
}
if (!foundse)
{
MarkedTet mt;
BTDefineMarkedTet (el, edgenumber, mt);
mt.matindex = el.GetIndex();
mtets.Append (mt);
}
break;
}
case PYRAMID:
{
// eventually rotate
MarkedPrism mp;
PointIndices<2> se(el.PNum(1), el.PNum(2));
se.Sort();
if (shortedges.Used (se))
{
Element hel = el;
hel.PNum(1) = el.PNum(2);
hel.PNum(2) = el.PNum(3);
hel.PNum(3) = el.PNum(4);
hel.PNum(4) = el.PNum(1);
BTDefineMarkedPrism (hel, edgenumber, mp);
}
else
{
BTDefineMarkedPrism (el, edgenumber, mp);
}
mp.matindex = el.GetIndex();
mprisms.Append (mp);
break;
}
case PRISM:
case PRISM12:
{
MarkedPrism mp;
BTDefineMarkedPrism (el, edgenumber, mp);
mp.matindex = el.GetIndex();
mprisms.Append (mp);
break;
}
default:
throw NgException("Bisect, element type not handled in switch, 4");
}
}
for (int i = 1; i <= nse; i++)
{
const Element2d & el = mesh.SurfaceElement(i);
if (el.GetType() == TRIG ||
el.GetType() == TRIG6)
{
MarkedTri mt;
BTDefineMarkedTri (el, edgenumber, mt);
mtris.Append (mt);
}
else
{
MarkedQuad mq;
BTDefineMarkedQuad (el, edgenumber, mq);
mquads.Append (mq);
}
if(mesh.GetDimension() == 3)
{
MarkedIdentification mi;
for(int j=0; j<idmaps.Size(); j++)
if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi))
mids.Append(mi);
}
}
if(mesh.GetDimension() == 2)
{
for (SegmentIndex j=0; j<mesh.GetNSeg(); j++)
{
auto seg = mesh[j];
for (auto map : idmaps)
{
if (seg[0].IsValid() && seg[1].IsValid() && (*map)[seg[0]] && (*map)[seg[1]])
{
MarkedIdentification mi;
mi.np = 2;
mi.pnums[0] = seg[0];
mi.pnums[1] = seg[1];
mi.pnums[2] = (*map)[seg[0]];
mi.pnums[3] = (*map)[seg[1]];
auto min1 = mi.pnums[0] < mi.pnums[1] ? mi.pnums[0] : mi.pnums[1];
auto min2 = mi.pnums[2] < mi.pnums[3] ? mi.pnums[2] : mi.pnums[3];
if (min1 > min2)
continue;
mi.marked = 0;
mi.markededge = 0;
mi.incorder = 0;
mids.Append(mi);
}
}
}
}
}
mesh.mlparentelement.SetSize(ne);
for (int i = 1; i <= ne; i++)
mesh.mlparentelement.Elem(i) = 0;
mesh.mlparentsurfaceelement.SetSize(nse);
for (int i = 1; i <= nse; i++)
mesh.mlparentsurfaceelement.Elem(i) = 0;
if (printmessage_importance>0)
{
ostringstream str1,str2;
str1 << "copied " << mtets.Size() << " tets, " << mprisms.Size() << " prisms";
str2 << " " << mtris.Size() << " trigs, " << mquads.Size() << " quads";
PrintMessage(4,str1.str());
PrintMessage(4,str2.str());
}
}
/*
void UpdateEdgeMarks2(Mesh & mesh,
const NgArray< NgArray<int,PointIndex::BASE>* > & idmaps)
{
NgArray< NgArray<MarkedTet>*,PointIndex::BASE > mtets_old(mesh.GetNP());
NgArray< NgArray<MarkedPrism>*,PointIndex::BASE > mprisms_old(mesh.GetNP());
NgArray< NgArray<MarkedIdentification>*,PointIndex::BASE > mids_old(mesh.GetNP());
NgArray< NgArray<MarkedTri>*,PointIndex::BASE > mtris_old(mesh.GetNP());
NgArray< NgArray<MarkedQuad>*,PointIndex::BASE > mquads_old(mesh.GetNP());
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
mtets_old[i] = new NgArray<MarkedTet>;
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
mprisms_old[i] = new NgArray<MarkedPrism>;
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
mids_old[i] = new NgArray<MarkedIdentification>;
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
mtris_old[i] = new NgArray<MarkedTri>;
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
mquads_old[i] = new NgArray<MarkedQuad>;
for(int i=0; i<mtets.Size(); i++)
mtets_old[mtets[i].pnums[0]]->Append(mtets[i]);
for(int i=0; i<mprisms.Size(); i++)
mprisms_old[mprisms[i].pnums[0]]->Append(mprisms[i]);
for(int i=0; i<mids.Size(); i++)
mids_old[mids[i].pnums[0]]->Append(mids[i]);
for(int i=0; i<mtris.Size(); i++)
{
(*testout) << "i " << i << endl;
(*testout) << "mtris[i] " << mtris[i].pnums[0] << " " << mtris[i].pnums[1] << " " << mtris[i].pnums[2] << endl;
mtris_old[mtris[i].pnums[0]]->Append(mtris[i]);
}
for(int i=0; i<mquads.Size(); i++)
mquads_old[mquads[i].pnums[0]]->Append(mquads[i]);
int np = mesh.GetNP();
int ne = mesh.GetNE();
int nse = mesh.GetNSE();
int i, j, k, l, m;
// if (mtets.Size() + mprisms.Size() == mesh.GetNE())
// return;
mtets.SetSize(0);
mprisms.SetSize(0);
mids.SetSize(0);
mtris.SetSize(0);
mquads.SetSize(0);
INDEX_2_HASHTABLE<int> shortedges(100);
for (i = 1; i <= ne; i++)
{
const Element & el = mesh.VolumeElement(i);
if (el.GetType() == PRISM ||
el.GetType() == PRISM12)
{
for (j = 1; j <= 3; j++)
{
INDEX_2 se(el.PNum(j), el.PNum(j+3));
se.Sort();
shortedges.Set (se, 1);
}
}
}
// INDEX_2_HASHTABLE<int> edgenumber(np);
INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*ne+4*nse);
BTSortEdges (mesh, idmaps, edgenumber);
for (i = 1; i <= ne; i++)
{
const Element & el = mesh.VolumeElement(i);
switch (el.GetType())
{
case TET:
case TET10:
{
// if tet has short edge, it is handled as degenerated prism
int foundse = 0;
for (j = 1; j <= 3; j++)
for (k = j+1; k <= 4; k++)
{
INDEX_2 se(el.PNum(j), el.PNum(k));
se.Sort();
if (shortedges.Used (se))
{
// cout << "tet converted to prism" << endl;
foundse = 1;
int p3 = 1;
while (p3 == j || p3 == k)
p3++;
int p4 = 10 - j - k - p3;
// even permutation ?
int pi[4];
pi[0] = j;
pi[1] = k;
pi[2] = p3;
pi[3] = p4;
int cnt = 0;
for (l = 1; l <= 4; l++)
for (m = 0; m < 3; m++)
if (pi[m] > pi[m+1])
{
Swap (pi[m], pi[m+1]);
cnt++;
}
if (cnt % 2)
Swap (p3, p4);
Element hel = el;
hel.PNum(1) = el.PNum(j);
hel.PNum(2) = el.PNum(k);
hel.PNum(3) = el.PNum(p3);
hel.PNum(4) = el.PNum(p4);
MarkedPrism mp;
BTDefineMarkedPrism (hel, edgenumber, mp);
mp.matindex = el.GetIndex();
mprisms.Append (mp);
}
}
if (!foundse)
{
MarkedTet mt;
int oldind = -1;
for(l = 0; oldind < 0 && l<mtets_old[el[0]]->Size(); l++)
if(el[1] == (*mtets_old[el[0]])[l].pnums[1] &&
el[2] == (*mtets_old[el[0]])[l].pnums[2] &&
el[3] == (*mtets_old[el[0]])[l].pnums[3])
oldind = l;
if(oldind >= 0)
mtets.Append((*mtets_old[el[0]])[oldind]);
else
{
BTDefineMarkedTet (el, edgenumber, mt);
mt.matindex = el.GetIndex();
mtets.Append (mt);
}
}
break;
}
case PYRAMID:
{
// eventually rotate
MarkedPrism mp;
INDEX_2 se(el.PNum(1), el.PNum(2));
se.Sort();
if (shortedges.Used (se))
{
Element hel = el;
hel.PNum(1) = el.PNum(2);
hel.PNum(2) = el.PNum(3);
hel.PNum(3) = el.PNum(4);
hel.PNum(4) = el.PNum(1);
BTDefineMarkedPrism (hel, edgenumber, mp);
}
else
{
BTDefineMarkedPrism (el, edgenumber, mp);
}
mp.matindex = el.GetIndex();
mprisms.Append (mp);
break;
}
case PRISM:
case PRISM12:
{
MarkedPrism mp;
BTDefineMarkedPrism (el, edgenumber, mp);
mp.matindex = el.GetIndex();
mprisms.Append (mp);
break;
}
}
}
for (i = 1; i <= nse; i++)
{
const Element2d & el = mesh.SurfaceElement(i);
if (el.GetType() == TRIG ||
el.GetType() == TRIG6)
{
MarkedTri mt;
BTDefineMarkedTri (el, edgenumber, mt);
mtris.Append (mt);
}
else
{
MarkedQuad mq;
BTDefineMarkedQuad (el, edgenumber, mq);
mquads.Append (mq);
}
MarkedIdentification mi;
for(j=0; j<idmaps.Size(); j++)
if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi))
{
mids.Append(mi);
int oldind = -1;
for(l = 0; oldind < 0 && l<mids_old[mi.pnums[0]]->Size(); l++)
{
bool equal = true;
for(int m = 1; equal && m < mi.np; m++)
equal = (mi.pnums[m] == (*mids_old[el[0]])[l].pnums[m]);
if(equal)
oldind = l;
}
if(oldind >= 0)
mids.Last() = (*mids_old[mi.pnums[0]])[oldind];
}
}
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
delete mtets_old[i];
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
delete mprisms_old[i];
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
delete mids_old[i];
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
delete mtris_old[i];
for(int i=PointIndex::BASE; i<mesh.GetNP()+PointIndex::BASE; i++)
delete mquads_old[i];
}
*/
void UpdateEdgeMarks (Mesh & mesh,
const NgArray< NgArray<int,PointIndex::BASE>* > & idmaps)
//const NgArray < NgArray<Element>* > & elements_before,
//const NgArray < NgArray<int>* > & markedelts_num,
// const NgArray < NgArray<Element2d>* > & surfelements_before,
// const NgArray < NgArray<int>* > & markedsurfelts_num)
{
/*
T_MTETS mtets_old; mtets_old.Copy(mtets);
T_MPRISMS mprisms_old; mprisms_old.Copy(mprisms);
T_MIDS mids_old; mids_old.Copy(mids);
T_MTRIS mtris_old; mtris_old.Copy(mtris);
T_MQUADS mquads_old; mquads_old.Copy(mquads);
*/
auto& mtets = *mesh.bisectioninfo.mtets;
auto& mprisms = *mesh.bisectioninfo.mprisms;
auto& mids = *mesh.bisectioninfo.mids;
auto& mtris = *mesh.bisectioninfo.mtris;
auto& mquads = *mesh.bisectioninfo.mquads;
T_MTETS mtets_old (mtets);
T_MPRISMS mprisms_old (mprisms);
T_MIDS mids_old (mids);
T_MTRIS mtris_old (mtris);
T_MQUADS mquads_old (mquads);
mtets.SetSize(0);
mprisms.SetSize(0);
mids.SetSize(0);
mtris.SetSize(0);
mquads.SetSize(0);
//int nv = mesh.GetNV();
INDEX_2_CLOSED_HASHTABLE<int> edgenumber(9*mesh.GetNE()+4*mesh.GetNSE());
int maxnum = BTSortEdges (mesh, idmaps, edgenumber);
for(int m = 0; m < mtets_old.Size(); m++)
{
MarkedTet & mt = mtets_old[m];
//(*testout) << "old mt " << mt;
PointIndices<2> edge (mt.pnums[mt.tetedge1],mt.pnums[mt.tetedge2]);
edge.Sort();
if(edgenumber.Used(edge))
{
int val = edgenumber.Get(edge);
//(*testout) << "set voledge " << edge << " from " << val;
if(val <= maxnum)
{
val += 2*maxnum;
edgenumber.Set(edge,val);
}
else if(val <= 2*maxnum)
{
val += maxnum;
edgenumber.Set(edge,val);
}
//(*testout) << " to " << val << endl;
}
for(int k=0; k<4; k++)
for(int i=0; i<3; i++)
for(int j=i+1; i != k && j<4; j++)
if(j != k && int(mt.faceedges[k]) == 6-k-i-j)
{
edge[0] = mt.pnums[i];
edge[1] = mt.pnums[j];
edge.Sort();
if(edgenumber.Used(edge))
{
int val = edgenumber.Get(edge);
//(*testout) << "set faceedge " << edge << " from " << val;
if(val <= maxnum)
{
val += maxnum;
edgenumber.Set(edge,val);
}
//(*testout) << " to " << val << endl;
}
}
}
for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
const Element & el = mesh[ei];
//int pos = elements_before[el[0]]->Pos(el);
//int elnum = (pos >= 0) ? (*markedelts_num[el[0]])[pos] : -1;
switch (el.GetType())
{
case TET:
case TET10:
{
//if(elnum >= 0)
// {
// mtets.Append(mtets_old[elnum]);
// }
//else
// {
MarkedTet mt;
BTDefineMarkedTet (el, edgenumber, mt);
mt.matindex = el.GetIndex();
mtets.Append (mt);
//(*testout) << "mtet " << mtets.Last() << endl;
break;
}
case PYRAMID:
{
cerr << "Refinement :: UpdateEdgeMarks not yet implemented for pyramids"
<< endl;
break;
}
case PRISM:
case PRISM12:
{
cerr << "Refinement :: UpdateEdgeMarks not yet implemented for prisms"
<< endl;
break;
}
default:
throw NgException("Bisect, element type not handled in switch, 6");
}
}
for(SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
{
const Element2d & el = mesh[sei];
/*
for(int k=0; k<3; k++)
auxind3[k] = el[k];
auxind3.Sort();
int pos = oldfaces[auxind3[0]]->Pos(auxind3);
if(pos < 0)
cout << "UIUIUI" << endl;
*/
switch (el.GetType())
{
case TRIG:
case TRIG6:
{
MarkedTri mt;
BTDefineMarkedTri (el, edgenumber, mt);
mtris.Append (mt);
break;
}
case QUAD:
case QUAD6:
{
MarkedQuad mt;
BTDefineMarkedQuad (el, edgenumber, mt);
mquads.Append (mt);
break;
}
default:
throw NgException("Bisect, element type not handled in switch, 5");
}
MarkedIdentification mi;
for(int j=0; j<idmaps.Size(); j++)
if(BTDefineMarkedId(el, edgenumber, *idmaps[j], mi))
mids.Append(mi);
/*
int pos = surfelements_before[el[0]]->Pos(el);
int elnum = (pos >= 0) ? (*markedsurfelts_num[el[0]])[pos] : -1;
switch (el.GetType())
{
case TRIG:
case TRIG6:
{
if(elnum >= 0)
mtris.Append(mtris_old[elnum]);
else
{
MarkedTri mt;
BTDefineMarkedTri (el, edgenumber, mt);
mtris.Append (mt);
(*testout) << "(new) ";
}
(*testout) << "mtri " << mtris.Last();
break;
}
case QUAD:
case QUAD6:
{
if(elnum >= 0)
mquads.Append(mquads_old[elnum]);
else
{
MarkedQuad mt;
BTDefineMarkedQuad (el, edgenumber, mt);
mquads.Append (mt);
}
break;
}
}
*/
}
/*
for(int i=0; i<oldfaces.Size(); i++)
{
delete oldfaces[i];
delete oldmarkededges[i];
}
*/
}
void Refinement :: Bisect (Mesh & mesh,
BisectionOptions & opt,
NgArray<double> * quality_loss) const
{
PrintMessage(1,"Mesh bisection");
PushStatus("Mesh bisection");
auto& mtets = *mesh.bisectioninfo.mtets;
auto& mprisms = *mesh.bisectioninfo.mprisms;
auto& mids = *mesh.bisectioninfo.mids;
auto& mtris = *mesh.bisectioninfo.mtris;
auto& mquads = *mesh.bisectioninfo.mquads;
static int timer = NgProfiler::CreateTimer ("Bisect");
static int timer1 = NgProfiler::CreateTimer ("Bisect 1");
static int timer1a = NgProfiler::CreateTimer ("Bisect 1a");
static int timer1b = NgProfiler::CreateTimer ("Bisect 1b");
static int timer2 = NgProfiler::CreateTimer ("Bisect 2");
static int timer2a = NgProfiler::CreateTimer ("Bisect 2a");
static int timer2b = NgProfiler::CreateTimer ("Bisect 2b");
// static int timer2c = NgProfiler::CreateTimer ("Bisect 2c");
static int timer3 = NgProfiler::CreateTimer ("Bisect 3");
static int timer3a = NgProfiler::CreateTimer ("Bisect 3a");
static int timer3b = NgProfiler::CreateTimer ("Bisect 3b");
static int timer_bisecttet = NgProfiler::CreateTimer ("Bisect tets");
static int timer_bisecttrig = NgProfiler::CreateTimer ("Bisect trigs");
static int timer_bisectsegms = NgProfiler::CreateTimer ("Bisect segms");
NgProfiler::RegionTimer reg1 (timer);
(*opt.tracer)("Bisect", false);
NgProfiler::StartTimer (timer1);
NgProfiler::StartTimer (timer1a);
static int localizetimer = NgProfiler::CreateTimer("localize edgepoints");
NgProfiler::RegionTimer * loct = new NgProfiler::RegionTimer(localizetimer);
LocalizeEdgePoints(mesh);
delete loct;
NgArray< NgArray<int,PointIndex::BASE>* > idmaps;
for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)
{
if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)
{
idmaps.Append(new NgArray<int,PointIndex::BASE>);
mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true);
}
}
string refelementinfofileread = "";
string refelementinfofilewrite = "";
if(opt.refinementfilename)
{
ifstream inf(opt.refinementfilename);
string st;
inf >> st;
if(st == "refinementinfo")
{
while(inf)
{
while(inf && st != "markedelementsfile")
inf >> st;
if(inf)
inf >> st;
if(st == "read" && inf)
ReadEnclString(inf,refelementinfofileread,'\"');
else if(st == "write" && inf)
ReadEnclString(inf,refelementinfofilewrite,'\"');
}
}
inf.close();
}
mesh.ComputeNVertices();
// if (mesh.mglevels == 1 || idmaps.Size() > 0)
if (mesh.level_nv.Size() == 0) // || idmaps.Size() ????
{
BisectTetsCopyMesh(mesh, NULL, opt, idmaps, refelementinfofileread);
mesh.level_nv.Append (mesh.GetNV());
}
int np = mesh.GetNV();
mesh.SetNP(np);
#ifdef PARALLEL
if (mesh.GetCommunicator().Size() > 1)
{
mesh.GetParallelTopology().IdentifyVerticesAfterRefinement();
mesh.GetCommunicator().Barrier();
mesh.GetParallelTopology().EnumeratePointsGlobally();
}
#endif
// int ne = mesh.GetNE();
// int nse = mesh.GetNSE();
// int i, j, l;
// int initnp = np;
// int maxsteps = 3;
// mesh.mglevels++;
/*
if (opt.refinementfilename || opt.usemarkedelements)
maxsteps = 3;
*/
if (opt.refine_p)
{
int ne = mesh.GetNE();
int nse = mesh.GetNSE();
int ox,oy,oz;
for (ElementIndex ei = 0; ei < ne; ei++)
if (mesh[ei].TestRefinementFlag())
{
mesh[ei].GetOrder(ox,oy,oz);
mesh[ei].SetOrder (ox+1,oy+1,oz+1);
if (mesh[ei].TestStrongRefinementFlag())
mesh[ei].SetOrder (ox+2,oy+2,oz+2);
}
for (SurfaceElementIndex sei = 0; sei < nse; sei++)
if (mesh[sei].TestRefinementFlag())
{
mesh[sei].GetOrder(ox,oy);
mesh[sei].SetOrder(ox+1,oy+1);
if (mesh[sei].TestStrongRefinementFlag())
mesh[sei].SetOrder(ox+2,oy+2);
}
#ifndef SABINE //Nachbarelemente mit ordx,ordy,ordz
NgArray<int,PointIndex::BASE> v_order (mesh.GetNP());
v_order = 0;
for (ElementIndex ei = 0; ei < ne; ei++)
for (int j = 0; j < mesh[ei].GetNP(); j++)
if (mesh[ei].GetOrder() > v_order[mesh[ei][j]])
v_order[mesh[ei][j]] = mesh[ei].GetOrder();
for (SurfaceElementIndex sei = 0; sei < nse; sei++)
for (int j = 0; j < mesh[sei].GetNP(); j++)
if (mesh[sei].GetOrder() > v_order[mesh[sei][j]])
v_order[mesh[sei][j]] = mesh[sei].GetOrder();
for (ElementIndex ei = 0; ei < ne; ei++)
for (int j = 0; j < mesh[ei].GetNP(); j++)
if (mesh[ei].GetOrder() < v_order[mesh[ei][j]]-1)
mesh[ei].SetOrder(v_order[mesh[ei][j]]-1);
for (SurfaceElementIndex sei = 0; sei < nse; sei++)
for (int j = 0; j < mesh[sei].GetNP(); j++)
if (mesh[sei].GetOrder() < v_order[mesh[sei][j]]-1)
mesh[sei].SetOrder(v_order[mesh[sei][j]]-1);
#endif
PopStatus();
return;
}
// INDEX_2_HASHTABLE<int> cutedges(10 + 5 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size()));
INDEX_2_CLOSED_HASHTABLE<PointIndex> cutedges(10 + 9 * (mtets.Size()+mprisms.Size()+mtris.Size()+mquads.Size()));
bool noprojection = false;
NgProfiler::StopTimer (timer1a);
for (int l = 1; l <= 1; l++)
{
int marked = 0;
if (opt.refinementfilename)
{
ifstream inf(opt.refinementfilename);
PrintMessage(3,"load refinementinfo from file ",opt.refinementfilename);
string st;
inf >> st;
if(st == "refinementinfo")
// new version
{
for(int i=1; i<=mtets.Size(); i++)
mtets[i-1].marked = 0;
for(int i=1; i<=mprisms.Size(); i++)
mprisms.Elem(i).marked = 0;
for(int i=1; i<=mtris.Size(); i++)
mtris.Elem(i).marked = 0;
for(int i=1; i<=mquads.Size(); i++)
mquads.Elem(i).marked = 0;
for(int i=1; i<=mprisms.Size(); i++)
mids.Elem(i).marked = 0;
inf >> st;
while(inf)
{
if(st[0] == '#')
{
inf.ignore(10000,'\n');
inf >> st;
}
else if(st == "markedelementsfile")
{
inf >> st;
ReadEnclString(inf,st,'\"');
inf >> st;
}
else if(st == "noprojection")
{
noprojection = true;
inf >> st;
}
else if(st == "refine")
{
inf >> st;
if(st == "elements")
{
inf >> st;
bool isint = true;
for(string::size_type ii=0; isint && ii<st.size(); ii++)
isint = (isdigit(st[ii]) != 0);
while(inf && isint)
{
mtets[atoi(st.c_str())-1].marked = 3;
marked = 1;
inf >> st;
isint = true;
for(string::size_type ii=0; isint && ii<st.size(); ii++)
isint = (isdigit(st[ii]) != 0);
}
}
else if(st == "orthobrick")
{
double bounds[6];
for(int i=0; i<6; i++)
inf >> bounds[i];
int cnt = 0;
for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
const Element & el = mesh[ei];
//
Point<3> center(0,0,0);
for(int i=0; i<el.GetNP(); i++)
{
const MeshPoint & point = mesh[el[i]];
center(0) += point(0);
center(1) += point(1);
center(2) += point(2);
}
for(int i=0; i<3; i++)
center(i) *= 1./double(el.GetNP());
if(bounds[0] <= center(0) && center(0) <= bounds[3] &&
bounds[1] <= center(1) && center(1) <= bounds[4] &&
bounds[2] <= center(2) && center(2) <= bounds[5])
{
mtets[ei].marked = 3;
cnt++;
}
// bool contained = false;
// for(int i=0; !contained && i<el.GetNP(); i++)
// {
// const MeshPoint & point = mesh[el[i]];
// contained = (bounds[0] <= point.X() && point.X() <= bounds[3] &&
// bounds[1] <= point.Y() && point.Y() <= bounds[4] &&
// bounds[2] <= point.Z() && point.Z() <= bounds[5]);
// }
// if(contained)
// {
// mtets[ei].marked = 3;
// cnt++;
// }
}
ostringstream strstr;
strstr.precision(2);
strstr << "marked " << float(cnt)/float(mesh.GetNE())*100.
#ifdef WIN32
<< "%%"
#else
<< "%"
#endif
<<" of the elements";
PrintMessage(4,strstr.str());
if(cnt > 0)
marked = 1;
inf >> st;
}
else
{
throw NgException("something wrong with refinementinfo file");
}
}
}
}
else
{
inf.close();
inf.open(opt.refinementfilename);
char ch;
for (int i = 1; i <= mtets.Size(); i++)
{
inf >> ch;
if(!inf)
throw NgException("something wrong with refinementinfo file (old format)");
mtets[i-1].marked = (ch == '1');
}
marked = 1;
}
inf.close();
}
else if (opt.usemarkedelements)
{
int cntm = 0;
// all in one !
if (mprisms.Size())
{
int cnttet = 0;
int cntprism = 0;
for (int i = 1; i <= mesh.GetNE(); i++)
{
if (mesh.VolumeElement(i).GetType() == TET ||
mesh.VolumeElement(i).GetType() == TET10)
{
cnttet++;
mtets[cnttet-1].marked =
(opt.onlyonce ? 3 : 1) * mesh.VolumeElement(i).TestRefinementFlag();
if (mtets[cnttet-1].marked)
cntm++;
}
else
{
cntprism++;
mprisms.Elem(cntprism).marked =
2 * mesh.VolumeElement(i).TestRefinementFlag();
if (mprisms.Elem(cntprism).marked)
cntm++;
}
}
}
else
for (int i = 1; i <= mtets.Size(); i++)
{
mtets[i-1].marked =
(opt.onlyonce ? 1 : 3) * mesh.VolumeElement(i).TestRefinementFlag();
if (mtets[i-1].marked)
cntm++;
}
// (*testout) << "mtets = " << mtets << endl;
/*
for (i = 1; i <= mtris.Size(); i++)
mtris.Elem(i).marked = 0;
for (i = 1; i <= mquads.Size(); i++)
mquads.Elem(i).marked = 0;
*/
if (printmessage_importance>0)
{
ostringstream str;
str << "marked elements: " << cntm;
PrintMessage(4,str.str());
}
int cnttrig = 0;
int cntquad = 0;
for (int i = 1; i <= mesh.GetNSE(); i++)
{
if (mesh.SurfaceElement(i).GetType() == TRIG ||
mesh.SurfaceElement(i).GetType() == TRIG6)
{
cnttrig++;
mtris.Elem(cnttrig).marked =
mesh.SurfaceElement(i).TestRefinementFlag() ? (opt.onlyonce ? 1 : 2) : 0;
// mtris.Elem(cnttrig).marked = 0;
if (mtris.Elem(cnttrig).marked)
cntm++;
}
else
{
cntquad++;
// 2d: marked=2, 3d prisms: marked=1
mquads.Elem(cntquad).marked =
mesh.SurfaceElement(i).TestRefinementFlag() ? 4-mesh.GetDimension() : 0 ;
// mquads.Elem(cntquad).marked = 0;
if (mquads.Elem(cntquad).marked)
cntm++;
}
}
if (printmessage_importance>0)
{
ostringstream str;
str << "with surface-elements: " << cntm;
PrintMessage(4,str.str());
}
// he/sz: das wird oben schon richtig gemacht.
// hier sind die quads vergessen!
/*
if (mesh.GetDimension() == 2)
{
cntm = 0;
for (i = 1; i <= mtris.Size(); i++)
{
mtris.Elem(i).marked =
2 * mesh.SurfaceElement(i).TestRefinementFlag();
// mtris.Elem(i).marked = 2;
if (mtris.Elem(i).marked)
cntm++;
}
if (!cntm)
{
for (i = 1; i <= mtris.Size(); i++)
{
mtris.Elem(i).marked = 2;
cntm++;
}
}
cout << "trigs: " << mtris.Size() << " ";
cout << "marked: " << cntm << endl;
}
*/
marked = (cntm > 0);
}
else
{
marked = BTMarkTets (mtets, mprisms, mesh);
}
if (!marked) break;
//(*testout) << "mtets " << mtets << endl;
if (opt.refine_p)
{
PrintMessage(3,"refine p");
for (int i = 1; i <= mtets.Size(); i++)
mtets[i-1].incorder = mtets[i-1].marked ? 1 : 0;
for (int i = 1; i <= mtets.Size(); i++)
if (mtets[i-1].incorder)
mtets[i-1].marked = 0;
for (int i = 1; i <= mprisms.Size(); i++)
mprisms.Elem(i).incorder = mprisms.Elem(i).marked ? 1 : 0;
for (int i = 1; i <= mprisms.Size(); i++)
if (mprisms.Elem(i).incorder)
mprisms.Elem(i).marked = 0;
for (int i = 1; i <= mtris.Size(); i++)
mtris.Elem(i).incorder = mtris.Elem(i).marked ? 1 : 0;
for (int i = 1; i <= mtris.Size(); i++)
{
if (mtris.Elem(i).incorder)
mtris.Elem(i).marked = 0;
}
}
if (opt.refine_hp)
{
PrintMessage(3,"refine hp");
NgBitArray singv(np);
singv.Clear();
if (mesh.GetDimension() == 3)
{
for (int i = 1; i <= mesh.GetNSeg(); i++)
{
const Segment & seg = mesh.LineSegment(i);
singv.Set (seg[0]);
singv.Set (seg[1]);
}
/*
for ( i=1; i<= mesh.GetNSE(); i++)
{
const Element2d & sel = mesh.SurfaceElement(i);
for(int j=1; j<=sel.GetNP(); j++)
singv.Set(sel.PNum(j));
}
*/
}
else
{
// vertices with 2 different bnds
NgArray<int> bndind(np);
bndind = 0;
for (int i = 1; i <= mesh.GetNSeg(); i++)
{
const Segment & seg = mesh.LineSegment(i);
for (int j = 0; j < 2; j++)
{
int pi = (j == 0) ? seg[0] : seg[1];
if (bndind.Elem(pi) == 0)
bndind.Elem(pi) = seg.edgenr;
else if (bndind.Elem(pi) != seg.edgenr)
singv.Set (pi);
}
}
}
for (int i = 1; i <= mtets.Size(); i++)
mtets[i-1].incorder = 1;
for (int i = 1; i <= mtets.Size(); i++)
{
if (!mtets[i-1].marked)
mtets[i-1].incorder = 0;
for (int j = 0; j < 4; j++)
if (singv.Test (mtets[i-1].pnums[j]))
mtets[i-1].incorder = 0;
}
for (int i = 1; i <= mtets.Size(); i++)
if (mtets[i-1].incorder)
mtets[i-1].marked = 0;
for (int i = 1; i <= mprisms.Size(); i++)
mprisms.Elem(i).incorder = 1;
for (int i = 1; i <= mprisms.Size(); i++)
{
if (!mprisms.Elem(i).marked)
mprisms.Elem(i).incorder = 0;
for (int j = 0; j < 6; j++)
if (singv.Test (mprisms.Elem(i).pnums[j]))
mprisms.Elem(i).incorder = 0;
}
for (int i = 1; i <= mprisms.Size(); i++)
if (mprisms.Elem(i).incorder)
mprisms.Elem(i).marked = 0;
for (int i = 1; i <= mtris.Size(); i++)
mtris.Elem(i).incorder = 1;
for (int i = 1; i <= mtris.Size(); i++)
{
if (!mtris.Elem(i).marked)
mtris.Elem(i).incorder = 0;
for (int j = 0; j < 3; j++)
if (singv.Test (mtris.Elem(i).pnums[j]))
mtris.Elem(i).incorder = 0;
}
for (int i = 1; i <= mtris.Size(); i++)
{
if (mtris.Elem(i).incorder)
mtris.Elem(i).marked = 0;
}
}
int hangingvol, hangingsurf, hangingedge;
//cout << "write?" << endl;
//string yn;
//cin >> yn;
(*testout) << "refine volume elements" << endl;
do
{
// refine volume elements
NgProfiler::StartTimer (timer_bisecttet);
(*opt.tracer)("bisecttet", false);
size_t nel = mtets.Size();
for (size_t i = 0; i < nel; i++)
if (mtets[i].marked)
{
MarkedTet oldtet = mtets[i];
INDEX_2 edge(oldtet.pnums[oldtet.tetedge1],
oldtet.pnums[oldtet.tetedge2]);
edge.Sort();
PointIndex newp;
if (auto optnewp = cutedges.GetIfUsed(edge))
{
newp = *optnewp;
}
else
{
Point<3> npt = Center (mesh.Point (edge.I1()),
mesh.Point (edge.I2()));
newp = mesh.AddPoint (npt);
cutedges.Set (edge, newp);
}
MarkedTet newtet1, newtet2;
BTBisectTet (oldtet, newp, newtet1, newtet2);
mtets[i] = newtet1;
mtets.Append (newtet2);
mesh.mlparentelement.Append (i+1);
}
NgProfiler::StopTimer (timer_bisecttet);
(*opt.tracer)("bisecttet", true);
int npr = mprisms.Size();
for (int i = 1; i <= npr; i++)
if (mprisms.Elem(i).marked)
{
MarkedPrism oldprism;
MarkedPrism newprism1, newprism2;
PointIndex newp1, newp2;
oldprism = mprisms.Get(i);
int pi1 = 0;
if (pi1 == oldprism.markededge)
pi1++;
int pi2 = 3-pi1-oldprism.markededge;
INDEX_2 edge1(oldprism.pnums[pi1],
oldprism.pnums[pi2]);
INDEX_2 edge2(oldprism.pnums[pi1+3],
oldprism.pnums[pi2+3]);
edge1.Sort();
edge2.Sort();
if (cutedges.Used (edge1))
newp1 = cutedges.Get(edge1);
else
{
Point<3> npt = Center (mesh.Point (edge1.I1()),
mesh.Point (edge1.I2()));
newp1 = mesh.AddPoint (npt);
cutedges.Set (edge1, newp1);
}
if (cutedges.Used (edge2))
newp2 = cutedges.Get(edge2);
else
{
Point<3> npt = Center (mesh.Point (edge2.I1()),
mesh.Point (edge2.I2()));
newp2 = mesh.AddPoint (npt);
cutedges.Set (edge2, newp2);
}
BTBisectPrism (oldprism, newp1, newp2, newprism1, newprism2);
//if(yn == "y")
// (*testout) << "bisected prism " << oldprism << "and got " << newprism1 << "and " << newprism2 << endl;
mprisms.Elem(i) = newprism1;
mprisms.Append (newprism2);
}
int nid = mids.Size();
for (int i = 1; i <= nid; i++)
if (mids.Elem(i).marked)
{
MarkedIdentification oldid,newid1,newid2;
NgArray<PointIndex> newp;
oldid = mids.Get(i);
NgArray<INDEX_2> edges;
edges.Append(INDEX_2(oldid.pnums[oldid.markededge],
oldid.pnums[(oldid.markededge+1)%oldid.np]));
edges.Append(INDEX_2(oldid.pnums[oldid.markededge + oldid.np],
oldid.pnums[(oldid.markededge+1)%oldid.np + oldid.np]));
if(oldid.np == 4)
{
edges.Append(INDEX_2(oldid.pnums[(oldid.markededge+2)%oldid.np],
oldid.pnums[(oldid.markededge+3)%oldid.np]));
edges.Append(INDEX_2(oldid.pnums[(oldid.markededge+2)%oldid.np + oldid.np],
oldid.pnums[(oldid.markededge+3)%oldid.np + oldid.np]));
}
for (int j = 0; j < edges.Size(); j++)
{
edges[j].Sort();
if(cutedges.Used(edges[j]))
newp.Append(cutedges.Get(edges[j]));
else
{
Point<3> npt = Center (mesh.Point (edges[j].I1()),
mesh.Point (edges[j].I2()));
newp.Append(mesh.AddPoint(npt));
cutedges.Set(edges[j],newp[j]);
}
}
BTBisectIdentification(oldid,newp,newid1,newid2);
mids.Elem(i) = newid1;
mids.Append(newid2);
}
//IdentifyCutEdges(mesh, cutedges);
(*opt.tracer)("mark elements", false);
hangingvol =
MarkHangingTets (mtets, cutedges, opt.task_manager) +
MarkHangingPrisms (mprisms, cutedges) +
MarkHangingIdentifications (mids, cutedges);
(*opt.tracer)("mark elements", true);
size_t nsel = mtris.Size();
NgProfiler::StartTimer (timer_bisecttrig);
(*opt.tracer)("Bisect trigs", false);
for (size_t i = 0; i < nsel; i++)
if (mtris[i].marked)
{
MarkedTri newtri1, newtri2;
PointIndex newp;
MarkedTri oldtri = mtris[i];
PointIndex oldpi1 = oldtri.pnums[(oldtri.markededge+1)%3];
PointIndex oldpi2 = oldtri.pnums[(oldtri.markededge+2)%3];
INDEX_2 edge(oldpi1, oldpi2);
edge.Sort();
int si = mesh.GetFaceDescriptor (oldtri.surfid).SurfNr();
PointGeomInfo npgi;
PointGeomInfo gi1 = oldtri.pgeominfo[(oldtri.markededge+1)%3];
PointGeomInfo gi2 = oldtri.pgeominfo[(oldtri.markededge+2)%3];
if (cutedges.Used (edge))
{
newp = cutedges.Get(edge);
npgi.u = 0.5*(gi1.u + gi2.u);
npgi.v = 0.5*(gi1.v + gi2.v);
geo.ProjectPointGI (si, mesh[newp], npgi);
}
else
{
Point<3> npt = Center (mesh.Point (edge.I1()),
mesh.Point (edge.I2()));
newp = mesh.AddPoint (npt);
cutedges.Set (edge, newp);
geo.PointBetween (mesh.Point (oldpi1), mesh.Point (oldpi2),
0.5, si, gi1, gi2, mesh.Point (newp), npgi);
}
BTBisectTri (oldtri, newp, npgi, newtri1, newtri2);
mtris[i] = newtri1;
mtris.Append (newtri2);
mesh.mlparentsurfaceelement.Append (i+1);
}
NgProfiler::StopTimer (timer_bisecttrig);
(*opt.tracer)("Bisect trigs", true);
int nquad = mquads.Size();
for (int i = 1; i <= nquad; i++)
if (mquads.Elem(i).marked)
{
MarkedQuad oldquad;
MarkedQuad newquad1, newquad2;
PointIndex newp1, newp2;
oldquad = mquads.Get(i);
/*
INDEX_2 edge1(oldquad.pnums[0],
oldquad.pnums[1]);
INDEX_2 edge2(oldquad.pnums[2],
oldquad.pnums[3]);
*/
INDEX_2 edge1, edge2;
PointGeomInfo pgi11, pgi12, pgi21, pgi22;
if (oldquad.markededge==0 || oldquad.markededge==2)
{
edge1.I1()=oldquad.pnums[0]; pgi11=oldquad.pgeominfo[0];
edge1.I2()=oldquad.pnums[1]; pgi12=oldquad.pgeominfo[1];
edge2.I1()=oldquad.pnums[2]; pgi21=oldquad.pgeominfo[2];
edge2.I2()=oldquad.pnums[3]; pgi22=oldquad.pgeominfo[3];
}
else // 3 || 1
{
edge1.I1()=oldquad.pnums[0]; pgi11=oldquad.pgeominfo[0];
edge1.I2()=oldquad.pnums[2]; pgi12=oldquad.pgeominfo[2];
edge2.I1()=oldquad.pnums[1]; pgi21=oldquad.pgeominfo[1];
edge2.I2()=oldquad.pnums[3]; pgi22=oldquad.pgeominfo[3];
}
edge1.Sort();
edge2.Sort();
if (cutedges.Used (edge1))
{
newp1 = cutedges.Get(edge1);
}
else
{
Point<3> np1 = Center (mesh.Point (edge1.I1()),
mesh.Point (edge1.I2()));
newp1 = mesh.AddPoint (np1);
cutedges.Set (edge1, newp1);
}
if (cutedges.Used (edge2))
{
newp2 = cutedges.Get(edge2);
}
else
{
Point<3> np2 = Center (mesh.Point (edge2.I1()),
mesh.Point (edge2.I2()));
newp2 = mesh.AddPoint (np2);
cutedges.Set (edge2, newp2);
}
PointGeomInfo npgi1, npgi2;
int si = mesh.GetFaceDescriptor (oldquad.surfid).SurfNr();
geo.PointBetween(mesh.Point (edge1.I1()), mesh.Point (edge1.I2()),
0.5, si,
pgi11,
pgi12,
mesh.Point (newp1), npgi1);
geo.PointBetween (mesh.Point (edge2.I1()), mesh.Point (edge2.I2()),
0.5, si,
pgi21,
pgi22,
mesh.Point (newp2), npgi2);
BTBisectQuad (oldquad, newp1, npgi1, newp2, npgi2,
newquad1, newquad2);
mquads.Elem(i) = newquad1;
mquads.Append (newquad2);
}
NgProfiler::StartTimer (timer1b);
hangingsurf =
MarkHangingTris (mtris, cutedges, opt.task_manager) +
MarkHangingQuads (mquads, cutedges);
hangingedge = mesh.GetDimension() == 3 ? 0 : MarkHangingIdentifications(mids, cutedges);
NgProfiler::StopTimer (timer1b);
NgProfiler::StartTimer (timer_bisectsegms);
int nseg = mesh.GetNSeg ();
for (int i = 1; i <= nseg; i++)
{
Segment & seg = mesh.LineSegment (i);
INDEX_2 edge(seg[0], seg[1]);
edge.Sort();
if (cutedges.Used (edge))
{
hangingedge = 1;
Segment nseg1 = seg;
Segment nseg2 = seg;
int newpi = cutedges.Get(edge);
nseg1[1] = newpi;
nseg2[0] = newpi;
EdgePointGeomInfo newepgi;
geo.PointBetweenEdge(mesh.Point (seg[0]), mesh.Point (seg[1]),
0.5, seg.surfnr1, seg.surfnr2,
seg.epgeominfo[0], seg.epgeominfo[1],
mesh.Point (newpi), newepgi);
nseg1.epgeominfo[1] = newepgi;
nseg2.epgeominfo[0] = newepgi;
mesh.LineSegment (i) = nseg1;
mesh.AddSegment (nseg2);
}
}
NgProfiler::StopTimer (timer_bisectsegms);
}
while (hangingvol || hangingsurf || hangingedge);
/*
if (printmessage_importance>0)
{
ostringstream strstr;
strstr << mtets.Size() << " tets" << endl
<< mtris.Size() << " trigs" << endl;
if (mprisms.Size())
{
strstr << mprisms.Size() << " prisms" << endl
<< mquads.Size() << " quads" << endl;
}
strstr << mesh.GetNP() << " points";
PrintMessage(4,strstr.str());
}
*/
PrintMessage (4, mtets.Size(), " tets");
PrintMessage (4, mtris.Size(), " trigs");
if (mprisms.Size())
{
PrintMessage (4, mprisms.Size(), " prisms");
PrintMessage (4, mquads.Size(), " quads");
}
PrintMessage (4, mesh.GetNP(), " points");
}
NgProfiler::StopTimer (timer1);
// (*testout) << "mtets = " << mtets << endl;
if (opt.refine_hp)
{
//
NgArray<int> v_order (mesh.GetNP());
v_order = 0;
if (mesh.GetDimension() == 3)
{
for (int i = 1; i <= mtets.Size(); i++)
if (mtets[i-1].incorder)
mtets[i-1].order++;
for (int i = 0; i < mtets.Size(); i++)
for (int j = 0; j < 4; j++)
if (int(mtets[i].order) > v_order.Elem(mtets[i].pnums[j]))
v_order.Elem(mtets[i].pnums[j]) = mtets[i].order;
for (int i = 0; i < mtets.Size(); i++)
for (int j = 0; j < 4; j++)
if (int(mtets[i].order) < v_order.Elem(mtets[i].pnums[j])-1)
mtets[i].order = v_order.Elem(mtets[i].pnums[j])-1;
}
else
{
for (int i = 1; i <= mtris.Size(); i++)
if (mtris.Elem(i).incorder)
{
mtris.Elem(i).order++;
}
for (int i = 0; i < mtris.Size(); i++)
for (int j = 0; j < 3; j++)
if (int(mtris[i].order) > v_order.Elem(mtris[i].pnums[j]))
v_order.Elem(mtris[i].pnums[j]) = mtris[i].order;
for (int i = 0; i < mtris.Size(); i++)
{
for (int j = 0; j < 3; j++)
if (int(mtris[i].order) < v_order.Elem(mtris[i].pnums[j])-1)
mtris[i].order = v_order.Elem(mtris[i].pnums[j])-1;
}
}
}
NgProfiler::StartTimer (timer2);
NgProfiler::StartTimer (timer2a);
mtets.SetAllocSize (mtets.Size());
mprisms.SetAllocSize (mprisms.Size());
mids.SetAllocSize (mids.Size());
mtris.SetAllocSize (mtris.Size());
mquads.SetAllocSize (mquads.Size());
(*opt.tracer)("copy tets", false);
mesh.ClearVolumeElements();
mesh.VolumeElements().SetAllocSize (mtets.Size()+mprisms.Size());
mesh.VolumeElements().SetSize(mtets.Size());
/*
for (int i = 1; i <= mtets.Size(); i++)
{
Element el(TET);
el.SetIndex (mtets.Get(i).matindex);
for (int j = 1; j <= 4; j++)
el.PNum(j) = mtets.Get(i).pnums[j-1];
el.SetOrder (mtets.Get(i).order);
mesh.AddVolumeElement (el);
}
*/
ParallelForRange
(opt.task_manager, mtets.Size(), [&] (size_t begin, size_t end)
{
for (size_t i = begin; i < end; i++)
{
Element el(TET);
auto & tet = mtets[i];
el.SetIndex (tet.matindex);
el.SetOrder (tet.order);
for (int j = 0; j < 4; j++)
el[j] = tet.pnums[j];
el.NewestVertex() = tet.newest_vertex;
mesh.SetVolumeElement (ElementIndex(i), el);
}
});
(*opt.tracer)("copy tets", true);
for (int i = 1; i <= mprisms.Size(); i++)
{
Element el(PRISM);
el.SetIndex (mprisms.Get(i).matindex);
for (int j = 1; j <= 6; j++)
el.PNum(j) = mprisms.Get(i).pnums[j-1];
el.SetOrder (mprisms.Get(i).order);
// degenerated prism ?
static const int map1[] = { 3, 2, 5, 6, 1 };
static const int map2[] = { 1, 3, 6, 4, 2 };
static const int map3[] = { 2, 1, 4, 5, 3 };
const int * map = NULL;
int deg1 = 0, deg2 = 0, deg3 = 0;
// int deg = 0;
if (el.PNum(1) == el.PNum(4)) { map = map1; deg1 = 1; }
if (el.PNum(2) == el.PNum(5)) { map = map2; deg2 = 1; }
if (el.PNum(3) == el.PNum(6)) { map = map3; deg3 = 1; }
switch (deg1+deg2+deg3)
{
case 1:
{
for (int j = 1; j <= 5; j++)
el.PNum(j) = mprisms.Get(i).pnums[map[j-1]-1];
el.SetType (PYRAMID);
break;
}
case 2:
{
static const int tetmap1[] = { 1, 2, 3, 4 };
static const int tetmap2[] = { 2, 3, 1, 5 };
static const int tetmap3[] = { 3, 1, 2, 6 };
if (!deg1) map = tetmap1;
if (!deg2) map = tetmap2;
if (!deg3) map = tetmap3;
for (int j = 1; j <= 4; j++)
el.PNum(j) = mprisms.Get(i).pnums[map[j-1]-1];
/*
if (!deg1) el.PNum(4) = el.PNum(4);
if (!deg2) el.PNum(4) = el.PNum(5);
if (!deg3) el.PNum(4) = el.PNum(6);
*/
el.SetType(TET);
break;
}
default:
;
}
mesh.AddVolumeElement (el);
}
mesh.ClearSurfaceElements();
mesh.SurfaceElements().SetAllocSize (mtris.Size()+mquads.Size());
NgProfiler::StopTimer (timer2a);
NgProfiler::StartTimer (timer2b);
/*
for (auto & trig : mtris)
{
Element2d el(TRIG);
el.SetIndex (trig.surfid);
el.SetOrder (trig.order);
for (int j = 0; j < 3; j++)
{
el[j] = trig.pnums[j];
el.GeomInfoPi(j+1) = trig.pgeominfo[j];
}
mesh.AddSurfaceElement (el);
}
*/
mesh.SurfaceElements().SetSize(mtris.Size());
// for (size_t i = 0; i < mtris.Size(); i++)
ParallelForRange
(opt.task_manager, mtris.Size(), [&] (size_t begin, size_t end)
{
for (size_t i = begin; i < end; i++)
{
Element2d el(TRIG);
auto & trig = mtris[i];
el.SetIndex (trig.surfid);
el.SetOrder (trig.order);
for (int j = 0; j < 3; j++)
{
el[j] = trig.pnums[j];
el.GeomInfoPi(j+1) = trig.pgeominfo[j];
}
el.NewestVertex() = trig.newest_vertex;
mesh.SetSurfaceElement (SurfaceElementIndex(i), el);
}
});
mesh.RebuildSurfaceElementLists();
for (int i = 1; i <= mquads.Size(); i++)
{
Element2d el(QUAD);
el.SetIndex (mquads.Get(i).surfid);
for (int j = 1; j <= 4; j++)
el.PNum(j) = mquads.Get(i).pnums[j-1];
Swap (el.PNum(3), el.PNum(4));
mesh.AddSurfaceElement (el);
}
NgProfiler::StopTimer (timer2b);
// write multilevel hierarchy to mesh:
np = mesh.GetNP();
mesh.mlbetweennodes.SetSize(np);
// if (mesh.mglevels <= 2)
if (mesh.level_nv.Size() <= 1)
{
PrintMessage(4,"RESETTING mlbetweennodes");
for (int i = 1; i <= np; i++)
{
mesh.mlbetweennodes.Elem(i).I1() = 0;
mesh.mlbetweennodes.Elem(i).I2() = 0;
}
}
mesh.level_nv.Append (np);
/*
for (i = 1; i <= cutedges.GetNBags(); i++)
for (j = 1; j <= cutedges.GetBagSize(i); j++)
{
INDEX_2 edge;
int newpi;
cutedges.GetData (i, j, edge, newpi);
mesh.mlbetweennodes.Elem(newpi) = edge;
}
*/
NgBitArray isnewpoint(np);
isnewpoint.Clear();
{
static Timer t("update mlbetween"); RegionTimer reg(t);
for (int i = 0; i < cutedges.Size(); i++)
if (cutedges.UsedPos0(i))
{
INDEX_2 edge;
PointIndex newpi;
cutedges.GetData0 (i, edge, newpi);
isnewpoint.Set(newpi);
mesh.mlbetweennodes.Elem(newpi) = edge;
}
}
/*
mesh.PrintMemInfo (cout);
cout << "tets ";
mtets.PrintMemInfo (cout);
cout << "prims ";
mprisms.PrintMemInfo (cout);
cout << "tris ";
mtris.PrintMemInfo (cout);
cout << "quads ";
mquads.PrintMemInfo (cout);
cout << "cutedges ";
cutedges.PrintMemInfo (cout);
*/
/*
// find connected nodes (close nodes)
TABLE<int> conto(np);
for (i = 1; i <= mprisms.Size(); i++)
for (j = 1; j <= 6; j++)
{
int n1 = mprisms.Get(i).pnums[j-1];
int n2 = mprisms.Get(i).pnums[(j+2)%6];
// if (n1 != n2)
{
int found = 0;
for (k = 1; k <= conto.EntrySize(n1); k++)
if (conto.Get(n1, k) == n2)
{
found = 1;
break;
}
if (!found)
conto.Add (n1, n2);
}
}
mesh.connectedtonode.SetSize(np);
for (i = 1; i <= np; i++)
mesh.connectedtonode.Elem(i) = 0;
// (*testout) << "connection table: " << endl;
// for (i = 1; i <= np; i++)
// {
// (*testout) << "node " << i << ": ";
// for (j = 1; j <= conto.EntrySize(i); j++)
// (*testout) << conto.Get(i, j) << " ";
// (*testout) << endl;
// }
for (i = 1; i <= np; i++)
if (mesh.connectedtonode.Elem(i) == 0)
{
mesh.connectedtonode.Elem(i) = i;
ConnectToNodeRec (i, i, conto, mesh.connectedtonode);
}
*/
// mesh.BuildConnectedNodes();
{
static Timer t("ComputeNV"); RegionTimer reg(t);
mesh.ComputeNVertices();
}
(*opt.tracer)("call RebuildSurfElList", false);
mesh.RebuildSurfaceElementLists();
(*opt.tracer)("call RebuildSurfElList", true);
// update identification tables
for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)
{
NgArray<int,PointIndex::BASE> identmap;
mesh.GetIdentifications().GetMap (i, identmap);
/*
for (j = 1; j <= cutedges.GetNBags(); j++)
for (k = 1; k <= cutedges.GetBagSize(j); k++)
{
INDEX_2 i2;
int newpi;
cutedges.GetData (j, k, i2, newpi);
INDEX_2 oi2(identmap.Get(i2.I1()),
identmap.Get(i2.I2()));
oi2.Sort();
if (cutedges.Used (oi2))
{
int onewpi = cutedges.Get(oi2);
mesh.GetIdentifications().Add (newpi, onewpi, i);
}
}
*/
for (int j = 0; j < cutedges.Size(); j++)
if (cutedges.UsedPos0(j))
{
INDEX_2 i2;
PointIndex newpi;
cutedges.GetData0 (j, i2, newpi);
INDEX_2 oi2(identmap.Get(i2.I1()),
identmap.Get(i2.I2()));
oi2.Sort();
if (cutedges.Used (oi2))
{
PointIndex onewpi = cutedges.Get(oi2);
mesh.GetIdentifications().Add (newpi, onewpi, i);
}
}
}
(*opt.tracer)("Bisect", true);
// Repair works only for tets!
bool do_repair = mesh.PureTetMesh ();
do_repair = false; // JS, March 2009: multigrid crashes
//if(mesh.mglevels == 3)
// noprojection = true;
//noprojection = true;
if(noprojection)
{
do_repair = false;
for(int ii=1; ii<=mesh.GetNP(); ii++)
{
if(isnewpoint.Test(ii) && mesh.mlbetweennodes[ii][0].IsValid())
{
mesh.Point(ii) = Center(mesh.Point(mesh.mlbetweennodes[ii][0]),
mesh.Point(mesh.mlbetweennodes[ii][1]));
}
}
}
// Check/Repair
static bool repaired_once;
// if(mesh.mglevels == 1)
if(mesh.level_nv.Size() == 1)
repaired_once = false;
//mesh.Save("before.vol");
static int reptimer = NgProfiler::CreateTimer("check/repair");
NgProfiler::RegionTimer * regt(NULL);
regt = new NgProfiler::RegionTimer(reptimer);
NgArray<ElementIndex> bad_elts;
NgArray<double> pure_badness;
if(do_repair || quality_loss != NULL)
{
pure_badness.SetSize(mesh.GetNP()+2);
GetPureBadness(mesh,pure_badness,isnewpoint);
}
if(do_repair) // by Markus W
{
const double max_worsening = 1;
const bool uselocalworsening = false;
// bool repaired = false;
Validate(mesh,bad_elts,pure_badness,max_worsening,uselocalworsening);
if (printmessage_importance>0)
{
ostringstream strstr;
for(int ii=0; ii<bad_elts.Size(); ii++)
strstr << "bad element " << bad_elts[ii] << "\n";
PrintMessage(1,strstr.str());
}
if(repaired_once || bad_elts.Size() > 0)
{
clock_t t1(clock());
// update id-maps
int j=0;
for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)
{
if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)
{
mesh.GetIdentifications().GetMap(i,*idmaps[j],true);
j++;
}
}
// do the repair
try
{
RepairBisection(mesh,bad_elts,isnewpoint,*this,
pure_badness,
max_worsening,uselocalworsening,
idmaps);
// repaired = true;
repaired_once = true;
}
catch(NgException & ex)
{
PrintMessage(1,string("Problem: ") + ex.What());
}
if (printmessage_importance>0)
{
ostringstream strstr;
strstr << "Time for Repair: " << double(clock() - t1)/double(CLOCKS_PER_SEC) << endl
<< "bad elements after repair: " << bad_elts << endl;
PrintMessage(1,strstr.str());
}
if(quality_loss != NULL)
Validate(mesh,bad_elts,pure_badness,1e100,uselocalworsening,quality_loss);
if(idmaps.Size() == 0)
UpdateEdgeMarks(mesh,idmaps);
/*
if(1==1)
UpdateEdgeMarks(mesh,idmaps);
else
mesh.mglevels = 1;
*/
//mesh.ImproveMesh();
}
}
delete regt;
for(int i=0; i<idmaps.Size(); i++)
delete idmaps[i];
idmaps.DeleteAll();
NgProfiler::StopTimer (timer2);
NgProfiler::StartTimer (timer3);
NgProfiler::StartTimer (timer3a);
(*opt.tracer)("topology from bisect", false);
mesh.UpdateTopology(opt.task_manager, opt.tracer);
(*opt.tracer)("topology from bisect", true);
NgProfiler::StopTimer (timer3a);
if(refelementinfofilewrite != "")
{
PrintMessage(3,"writing marked-elements information to \"",refelementinfofilewrite,"\"");
ofstream ofst(refelementinfofilewrite.c_str());
WriteMarkedElements(mesh, ofst);
ofst.close();
}
NgProfiler::StartTimer (timer3b);
mesh.CalcSurfacesOfNode();
NgProfiler::StopTimer (timer3b);
PrintMessage (1, "Bisection done");
PopStatus();
NgProfiler::StopTimer (timer3);
}
BisectionOptions :: BisectionOptions ()
{
outfilename = NULL;
mlfilename = NULL;
refinementfilename = NULL;
femcode = NULL;
maxlevel = 50;
usemarkedelements = 0;
refine_hp = 0;
refine_p = 0;
}
}