/* $Id: triang3.cc,v 1.5 1996/10/11 16:13:22 roitzsch Exp $ (C)opyright 1996 by Konrad-Zuse-Center, Berlin All rights reserved. Part of the Kaskade distribution */ #include "triang3.h" #include "utils.h" #include "numerics.h" #include "mzibutil.h" #include "triangtempl.h" #include "cmdpars.h" extern CmdPars Cmd; Vector EDG3::p(2); Vector TR3::p(3); Vector TR3::e(3); Vector TR3::f(3); Vector TET3::p(4); Vector TET3::e(6); Vector TET3::f(4); //------------------------------------------------------------------------- static const Real oneSixth = 1./6.; //------------------------------------------------------------------------- StaticAllocator TR3::alloc(ElementsInBlock); //------------------------------------------------------------------------- MESH3:: MESH3(const char* inFileName, Bool readMesh) : MESH(inFileName), ptList(0,25), trList(0,25), edgList(0,25), tetList(0,25), ptAlloc(ElementsInBlock), edgAlloc(6*ElementsInBlock), tetAlloc(5*ElementsInBlock) { noOfPoints = 0; noOfEdges = 0; noOfTriangles = 0; noOfTetrahedra = 0; // if (Cmd.isTrue("Circle")) circle = True; // else circle = False; // if (Cmd.isTrue("Cylinder")) cylinder = True; // else cylinder = False; if (Cmd.isSet("refTetrahedron","BeyStabilDiag")) { rightHand = False; refinementType = BeyStabilDiag; } else { rightHand = True; refinementType = ShortDiag; } if (readMesh) readTriangulation(inFileName); } //------------------------------------------------------------------------- //------------------------------------------------------------------------- EFMESH3:: EFMESH3(const char* inFileName, Bool /*readMesh*/) : MESH3(inFileName, False), EFTetAlloc(5*ElementsInBlock) { readTriangulation(fileName); } //------------------------------------------------------------------------- MESH3:: ~MESH3() { int i; FORALL( trList,i) delete trList[i]; FORALL( ptList,i) delete ptList[i]; FORALL(edgList,i) delete edgList[i]; FORALL(tetList,i) delete tetList[i]; } //------------------------------------------------------------------------- void MESH3:: readTriangulation(const char* fileName0) { if (Cmd.isTrue("readHyperFormat")) readHyperFormat(fileName0); else if (Cmd.isTrue("readGrapeFormat")) readGrapeFormat(fileName0); else if (Cmd.isTrue("readZIBFormat")) readZIBFormat(fileName0); else if (Cmd.isTrue("readOldFormat")) readOldZIBFormat(fileName0); else readZIBFormat(fileName0); } //------------------------------------------------------------------------- void MESH3:: readOldZIBFormat(const char* /*fileName0*/) { int ptdim, tetdim, bounddim; int rc, i, k; int classA; int dirTrDim, trNo; char ch, line[256] ; PT3 *p; TR3 *t=0; TET3 *td; int maxIndex; DList* ptL = new DList; ptList.push(ptL); DList* edgL = new DList; edgList.push(edgL); DList* trL = new DList; trList.push(trL); DList* tetL = new DList; tetList.push(tetL); // BufferedParser parser(fileName, "end", CommentFlag); Parser parser(fileName, "end", CommentFlag); if (parser.getLine(line) != parser.ok) missingItem("line",fileName); if (parser.getLine(line) != parser.ok) missingItem("line",fileName); rc = sscanf(line,"Dimension:(%d,%d,%d,%d)", &ptdim,&tetdim,&dirTrDim,&bounddim); maxIndex = ptdim - 1; checkMaxIndex(maxIndex); noOfTetrahedra = tetdim; Vector ptAdr(0,maxIndex); // for point addresses FORALL(ptAdr,i) ptAdr[i] = 0; int ptNo, count=0; double x, y, z; for (i=1; i<= ptdim; i++) { if (parser.getLine(line) != parser.ok) missingItem("line",fileName); ch = ' '; rc = sscanf(line, "%d:(%le,%le,%le),%c%d", &ptNo, &x, &y, &z, &ch, &classA); if (rc==0) break; if (ptNo > ptAdr.high()) pointIndexError(ptNo); p = ptAlloc.Get(); // new PT3; ptAdr[ptNo] = p; p->x = x; p->y = y; p->z = z; p->classA = 0; if (rc==6) p->classA = classA; if ((ch=='D')||(ch=='d')) p->boundP = DIRICHLET; else if ((ch=='I')||(ch=='i')) p->boundP = INTERIOR; else if ((ch=='N')||(ch=='n')) p->boundP = NEUMANN; else if ((ch=='C')||(ch=='c')) p->boundP = CAUCHY; else p->boundP = INTERIOR; p->node = ++count; // used in Find... ptList[0]->add(p); } noOfPoints=count; if (parser.findWord("end") != parser.ok) missingItem("end",fileName); parser.skipRestOfLine(); int pNo1, pNo2 ,pNo3, pNo4, tetNo; for (i=1; i<= tetdim; i++) { classA = 0; if (parser.getLine(line) != parser.ok) missingItem("line",fileName); rc = sscanf(line,"%d:(%d,%d,%d,%d),%d", &tetNo,&pNo1,&pNo2,&pNo3,&pNo4, &classA); if (rc==0) break; if ((pNo1>maxIndex)||(pNo2>maxIndex)||(pNo3>maxIndex)||(pNo4>maxIndex)) { cout << "\n *** ReadTri: bound check error reading tetrahedron\n"; return; } td = getTET3(); // new TET3; td->p1 = ptAdr[pNo1]; td->p2 = ptAdr[pNo2]; td->p3 = ptAdr[pNo3]; td->p4 = ptAdr[pNo4]; td->classA = classA; SetTPts(td,0); tetList[0]->add(td); } // -- compute edges and faces: Vector*> edsOfPts(noOfPoints); FORALL(edsOfPts,i) edsOfPts[i] = new Stack(15); Vector*> trsOfPts(noOfPoints); FORALL(trsOfPts,i) trsOfPts[i] = new Stack(15); DListIter iterTet(tetras()); while ((td=iterTet.all())) completeTetrahedron(td, edsOfPts, trsOfPts); if (parser.findWord("end") != parser.ok) missingItem("end",fileName); parser.skipRestOfLine(); PT3 *pt1, *pt2, *pt3; for (i=1; i<= dirTrDim; i++) { if (parser.getLine(line) != parser.ok) missingItem("line",fileName); ch = ' '; classA = 0; rc = sscanf(line,"%d:(%d,%d,%d),%c%d,(%le,%le,%le)", &trNo,&pNo1,&pNo2,&pNo3,&ch,&classA,&x,&y,&z); if (rc==0) break; pt1 = ptAdr[pNo1]; pt2 = ptAdr[pNo2]; pt3 = ptAdr[pNo3]; Stack& trs = *trsOfPts[pt1->node]; FORALL(trs,k) { t = trs[k]; if (PinTr(pt1,t) && PinTr(pt2,t) && PinTr(pt3,t)) break; } if (!t->onBoundary()) boundaryWarning(pNo1,pNo2,pNo3); t->classA = classA; if ((ch == 'd') || (ch == 'D')) { t->boundP = DIRICHLET; (t->e1)->boundP = DIRICHLET; (t->e2)->boundP = DIRICHLET; (t->e3)->boundP = DIRICHLET; (t->e1)->classA = classA; (t->e2)->classA = classA; (t->e3)->classA = classA; } else if ( (ch == 'c') || (ch == 'C')) { t->boundP = CAUCHY; if ((t->e1)->boundP != DIRICHLET) { (t->e1)->boundP = CAUCHY; (t->e1)->classA = classA; } if ((t->e2)->boundP != DIRICHLET) { (t->e2)->boundP = CAUCHY; (t->e2)->classA = classA; } if ((t->e3)->boundP != DIRICHLET) { (t->e3)->boundP = CAUCHY; (t->e3)->classA = classA; } } else if ( (ch == 'n') || (ch == 'N')) { t->boundP = NEUMANN; if ((t->e1)->boundP != DIRICHLET) { (t->e1)->boundP = NEUMANN; (t->e1)->classA = classA; } if ((t->e2)->boundP != DIRICHLET) { (t->e2)->boundP = NEUMANN; (t->e2)->classA = classA; } if ((t->e3)->boundP != DIRICHLET) { (t->e3)->boundP = NEUMANN; (t->e3)->classA = classA; } } } DListIter iterTr(triangles()); while ((t=iterTr.all())) setNeighbsOfTetra(t); iterTr.reset(); while ((t=iterTr.all())) if ( !(t->onBoundary()) ) { trList[0]->remove(t); delete t; } iterTet.reset(); while ((td=iterTet.all())) td->setBoundary(); FORALL(edsOfPts,i) delete edsOfPts[i]; FORALL(trsOfPts,i) delete trsOfPts[i]; if (infoRefinement) Info(); if (Cmd.isTrue("printMesh")) cout << *this; return; } //------------------------------------------------------------------------- void MESH3:: readGrapeFormat(const char* /*fileName0*/) { int i, j, maxIndex, noOfTds; int count=0; int classA, pNo1, pNo2 ,pNo3, pNo4; PT3 *p, *pt1=0, *pt2=0, *pt3=0; TR3* t=0; TET3* td; DList* ptL = new DList; ptList.push(ptL); DList* tetL = new DList; tetList.push(tetL); DList* trL = new DList; trList.push(trL); DList* edgL = new DList; edgList.push(edgL); BufferedParser parser(fileName, "end", CommentFlag); parser.getValue(&noOfTds); parser.getValue(&maxIndex); checkMaxIndex(maxIndex); Vector ptAdr(0,maxIndex); // for point addresses FORALL(ptAdr,i) ptAdr[i] = 0; for (i=1; i <= maxIndex; i++) { p = ptAlloc.Get(); // new PT3; ptAdr[i] = p; parser.getValue(&p->x); parser.getValue(&p->y); parser.getValue(&p->z); p->node = ++count; // used in Find... ptList[0]->add(p); ++noOfPoints; } rightHand = False; for (i=1; i <= noOfTds; i++) { parser.getValue(&pNo1); parser.getValue(&pNo2); parser.getValue(&pNo3); parser.getValue(&pNo4); parser.getValue(&classA); td = getTET3(); // new TET3; td->p1 = ptAdr[pNo1]; td->p2 = ptAdr[pNo2]; td->p3 = ptAdr[pNo3]; td->p4 = ptAdr[pNo4]; td->classA = 1; SetTPts(td,0); tetList[0]->add(td); ++noOfTetrahedra; } // -- compute edges and faces: Vector*> edsOfPts(noOfPoints); FORALL(edsOfPts,i) edsOfPts[i] = new Stack(15); Vector*> trsOfPts(noOfPoints); FORALL(trsOfPts,i) trsOfPts[i] = new Stack(15); DListIter iterTet(tetras()); while ((td=iterTet.all())) completeTetrahedron(td, edsOfPts, trsOfPts); int no, pNo[5]; iterTet.reset(); while ((td=iterTet.all())) { parser.getValue(&no); pNo[1]=no; parser.getValue(&no); pNo[2]=no; parser.getValue(&no); pNo[3]=no; parser.getValue(&no); pNo[4]=no; for (j=1; j<=4; j++) { if (pNo[j] != -1) continue; if ( j == 1) { pt1 = td->p2; pt2 = td->p3; pt3 = td->p4; } else if ( j == 2) { pt1 = td->p1; pt2 = td->p3; pt3 = td->p4; } else if ( j == 3) { pt1 = td->p1; pt2 = td->p2; pt3 = td->p4; } else if ( j == 4) { pt1 = td->p1; pt2 = td->p2; pt3 = td->p3; } Stack& trs = *trsOfPts[pt1->node]; FORALL(trs,i) { t = trs[i]; if (PinTr(pt1,t) && PinTr(pt2,t) && PinTr(pt3,t)) break; } if (!t->onBoundary()) boundaryWarning(pNo1,pNo2,pNo3); t->boundP = DIRICHLET; t->classA = 1; t->e1->boundP = t->e2->boundP = t->e3->boundP = DIRICHLET; t->e1->classA = t->e2->classA = t->e3->classA = 1; t->p1->boundP = t->p2->boundP = t->p3->boundP = DIRICHLET; t->p1->classA = t->p2->classA = t->p3->classA = 1; } } DListIter iterTr(triangles()); while ((t=iterTr.all())) setNeighbsOfTetra(t); iterTr.reset(); while ((t=iterTr.all())) if ( !(t->onBoundary()) ) { trList[0]->remove(t); delete t; } iterTet.reset(); while ((td=iterTet.all())) td->setBoundary(); FORALL(edsOfPts,i) delete edsOfPts[i]; FORALL(trsOfPts,i) delete trsOfPts[i]; if (infoRefinement) Info(); if (Cmd.isTrue("printMesh")) cout << *this; } //------------------------------------------------------------------------- void MESH3:: readZIBFormat(const char* /*fileName0*/) { int i, maxIndex; TR3* t; TET3* td; DList* ptL = new DList; ptList.push(ptL); DList* tetL = new DList; tetList.push(tetL); DList* trL = new DList; trList.push(trL); DList* edgL = new DList; edgList.push(edgL); BufferedParser parser(fileName, "end", CommentFlag); if (parser.findWord("Poin") != parser.ok) missingItem("points",fileName); if (parser.findWord("max") != parser.ok) missingItem("maxIndex",fileName); parser.getValue(&maxIndex); checkMaxIndex(maxIndex); Vector ptAdr(0,maxIndex); // for point addresses FORALL(ptAdr,i) ptAdr[i] = 0; readPoints(parser, ptAdr); if (parser.findWord("Elem") != parser.ok) missingItem("tetrahedra",fileName); readElements(parser, ptAdr); // -- compute edges and faces: Vector*> edsOfPts(noOfPoints); FORALL(edsOfPts,i) edsOfPts[i] = new Stack(15); Vector*> trsOfPts(noOfPoints); FORALL(trsOfPts,i) trsOfPts[i] = new Stack(15); DListIter iterTet(tetras()); while ((td=iterTet.all())) completeTetrahedron(td, edsOfPts, trsOfPts); if (parser.findWord("Boun") != parser.ok) missingItem("boundary",fileName); readBoundary(parser, ptAdr, trsOfPts); DListIter iterTr(triangles()); while ((t=iterTr.all())) setNeighbsOfTetra(t); iterTr.reset(); while ((t=iterTr.all())) if ( !(t->onBoundary()) ) { trList[0]->remove(t); delete t; } iterTet.reset(); while ((td=iterTet.all())) td->setBoundary(); FORALL(edsOfPts,i) delete edsOfPts[i]; FORALL(trsOfPts,i) delete trsOfPts[i]; if (infoRefinement) Info(); if (Cmd.isTrue("printMesh")) cout << *this; } //------------------------------------------------------------------------- void MESH3:: readPoints(BufferedParser& parser, Vector& ptAdr) { int ptNo, count=0; PT3* p; while (parser.getValue(&ptNo) == parser.ok) { if (ptNo > ptAdr.high()) pointIndexError(ptNo); p = ptAlloc.Get(); // new PT3; ptAdr[ptNo] = p; parser.getValue(&p->x); parser.getValue(&p->y); parser.getValue(&p->z); p->node = ++count; // used in Find... ptList[0]->add(p); ++noOfPoints; } } //------------------------------------------------------------------------- void MESH3:: readElements(BufferedParser& parser, Vector& ptAdr) { int pNo1, pNo2 ,pNo3, pNo4, classA; TET3 *td; while (parser.getValue(&pNo1) == parser.ok) { parser.getValue(&pNo2); parser.getValue(&pNo3); parser.getValue(&pNo4); td = getTET3(); // new TET3; td->p1 = ptAdr[pNo1]; td->p2 = ptAdr[pNo2]; td->p3 = ptAdr[pNo3]; td->p4 = ptAdr[pNo4]; parser.getValue(&classA); // int -> char td->classA = classA; SetTPts(td,0); tetList[0]->add(td); ++noOfTetrahedra; } } //------------------------------------------------------------------------- void MESH3:: readBoundary(BufferedParser& parser, Vector& ptAdr, Vector*>& trsOfPts) { int i, pNo1, pNo2 ,pNo3, pNo; PT3 *pt1, *pt2, *pt3, *p; TR3 *t = 0; while (parser.getValue(&pNo1) == parser.ok) // triangles on boundaries { parser.getValue(&pNo2); parser.getValue(&pNo3); pt1 = ptAdr[pNo1]; pt2 = ptAdr[pNo2]; pt3 = ptAdr[pNo3]; Stack& trs = *trsOfPts[pt1->node]; FORALL(trs,i) { t = trs[i]; if (PinTr(pt1,t) && PinTr(pt2,t) && PinTr(pt3,t)) break; } if (!t->onBoundary()) boundaryWarning(pNo1,pNo2,pNo3); t->readBC(parser); } if (parser.findWord("Poin") == parser.ok) // additional BCs on points { while (parser.getValue(&pNo) == parser.ok) { p = ptAdr[pNo]; p->readBC(parser); } } } //------------------------------------------------------------------------- void MESH3:: readHyperFormat(const char* /*fileName0*/) { int i, nPoints, nEdges, nTriangles, nTetrahedrons; int pointsSection, trianglesSection, tetrahedronsSection; int pointDataSection, triangleDataSection, tetrahedronDataSection; TR3* t; TET3* td; DList* ptL = new DList; ptList.push(ptL); DList* tetL = new DList; tetList.push(tetL); DList* trL = new DList; trList.push(trL); DList* edgL = new DList; edgList.push(edgL); BufferedParser parser(fileName, "end", CommentFlag); if (parser.findWord("nPoints") != parser.ok) missingItem("nPoints",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); parser.getValue(&nPoints); checkMaxIndex(nPoints); noOfPoints = nPoints; if (parser.findWord("nEdges") != parser.ok) missingItem("nEdges",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); parser.getValue(&nEdges); checkMaxIndex(nEdges); if (parser.findWord("nTriangles") != parser.ok) missingItem("nTriangles",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); parser.getValue(&nTriangles); checkMaxIndex(nTriangles); if (parser.findWord("nTetrahedrons") != parser.ok) missingItem("nTetrahedrons",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); parser.getValue(&nTetrahedrons); //cout << "\n nTetrahedrons = " << nTetrahedrons << "\n"; checkMaxIndex(nTetrahedrons); noOfTetrahedra = nTetrahedrons; if (parser.findWord("Points") != parser.ok) missingItem("Points",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(&pointsSection); //cout << "\n pointsSection = " << pointsSection << "\n"; checkMaxIndex(pointsSection); if (parser.findWord("Triangles") != parser.ok) missingItem("Triangles",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(&trianglesSection); //cout << "\n trianglesSection = " << trianglesSection << "\n"; checkMaxIndex(trianglesSection); if (parser.findWord("Tetrahedrons") != parser.ok) missingItem("Tetrahedrons",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(&tetrahedronsSection); //cout << "\n tetrahedronsSection = " << tetrahedronsSection << "\n"; checkMaxIndex(tetrahedronsSection); if (parser.findWord("PointData") != parser.ok) missingItem("PointData",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(&pointDataSection); //cout << "\n pointDataSection = " << pointDataSection << "\n"; checkMaxIndex(pointDataSection); if (parser.findWord("TriangleData") != parser.ok) missingItem("TriangleData",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(&triangleDataSection); //cout << "\n triangleDataSection = " << triangleDataSection << "\n"; checkMaxIndex(triangleDataSection); if (parser.findWord("TetrahedronData") != parser.ok) missingItem("TetrahedronData",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(&tetrahedronDataSection); //cout << "\n tetrahedronDataSection = " << tetrahedronDataSection << "\n"; checkMaxIndex(tetrahedronDataSection); Vector ptAdr(0,nPoints); // for point addresses FORALL(ptAdr,i) ptAdr[i] = 0; readHyperPoints(parser, pointsSection, ptAdr); readHyperElements(parser, tetrahedronsSection, ptAdr); readHyperClass(parser, tetrahedronDataSection); // -- compute edges and faces: Vector*> edsOfPts(noOfPoints); FORALL(edsOfPts,i) edsOfPts[i] = new Stack(15); Vector*> trsOfPts(noOfPoints); FORALL(trsOfPts,i) trsOfPts[i] = new Stack(15); DListIter iterTet(tetras()); while ((td=iterTet.all())) completeTetrahedron(td, edsOfPts, trsOfPts); //cout << "\n readHyperBoundary\n"; readHyperBoundary(parser, trianglesSection, triangleDataSection, ptAdr, trsOfPts); DListIter iterTr(triangles()); while ((t=iterTr.all())) setNeighbsOfTetra(t); iterTr.reset(); while ((t=iterTr.all())) if ( !(t->onBoundary()) ) { trList[0]->remove(t); delete t; } iterTet.reset(); while ((td=iterTet.all())) td->setBoundary(); FORALL(edsOfPts,i) delete edsOfPts[i]; FORALL(trsOfPts,i) delete trsOfPts[i]; if (infoRefinement) Info(); if (Cmd.isTrue("printMesh")) cout << *this; } //------------------------------------------------------------------------- void MESH3:: readHyperPoints(BufferedParser& parser, int pointsSection, Vector& ptAdr) { int count=0; PT3* p; int section = 0; while (section != pointsSection) { if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(§ion); } for (int i=1; i<=noOfPoints; i++) { p = ptAlloc.Get(); // new PT3; ptAdr[i] = p; parser.getValue(&p->x); parser.getValue(&p->y); parser.getValue(&p->z); p->node = ++count; // used in Find... // cout << "\n p = " << p->x << " , " << p->y << " , " << p->z << "\n"; ptList[0]->add(p); } } //------------------------------------------------------------------------- void MESH3:: readHyperElements(BufferedParser& parser, int tetrahedronsSection, Vector& ptAdr) { int pNo1, pNo2 ,pNo3, pNo4; TET3 *td; int section = 0; while (section != tetrahedronsSection) { if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(§ion); } for (int i=1; i<=noOfTetrahedra; i++) { parser.getValue(&pNo1); parser.getValue(&pNo2); parser.getValue(&pNo3); parser.getValue(&pNo4); td = getTET3(); // new TET3; td->p1 = ptAdr[pNo1]; td->p2 = ptAdr[pNo2]; td->p3 = ptAdr[pNo3]; td->p4 = ptAdr[pNo4]; SetTPts(td,0); // cout << "\n tet = " << pNo1 << ", " << pNo2 << ", " << pNo3 << ", " << pNo4 << "\n"; tetList[0]->add(td); } } //------------------------------------------------------------------------- void MESH3:: readHyperClass(BufferedParser& parser, int tetrahedronDataSection) { int classA; TET3 *td; int section = 0; while (section != tetrahedronDataSection) { if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(§ion); } DListIter iterTet(tetras()); while ((td=iterTet.all())) { parser.getValue(&classA); // int -> char td->classA = classA; //cout << "\n tet->class = " << classA << "\n"; } } //------------------------------------------------------------------------- void MESH3:: readHyperBoundary(BufferedParser& parser, int trianglesSection, int triangleDataSection, Vector& ptAdr, Vector*>& trsOfPts) { int i, pNo1, pNo2 ,pNo3, pNo4, pNo5; PT3 *pt1, *pt2, *pt3; TR3 *t = 0; Vector trClass(noOfTriangles), trBound(noOfTriangles); parser.rewind(); if (parser.findWord("TetrahedronData") != parser.ok) missingItem("TetrahedronData",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); int section = 0; while (section != triangleDataSection) { if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(§ion); } for (i=1; i<=noOfTriangles; i++) // triangles on boundaries { parser.getValue(&pNo1); parser.getValue(&pNo2); trBound[i] = pNo1; trClass[i] = pNo2; // cout << "\n class, boundP = " << pNo1 << ", " << pNo2 << "\n"; } parser.rewind(); if (parser.findWord("TetrahedronData") != parser.ok) missingItem("TetrahedronData",fileName); if (parser.findWord("=") != parser.ok) missingItem("=",fileName); section = 0; while (section != trianglesSection) { if (parser.findChar('@') != parser.ok) missingItem("@",fileName); parser.getValue(§ion); } for (int j=1; j<=noOfTriangles; j++) // triangles on boundaries { parser.getValue(&pNo1); parser.getValue(&pNo2); parser.getValue(&pNo3); parser.getValue(&pNo4); parser.getValue(&pNo5); // cout << "\ntriangles = " << pNo1 << pNo2 << pNo3 << pNo4 << pNo5 << "\n"; pt1 = ptAdr[pNo1]; pt2 = ptAdr[pNo2]; pt3 = ptAdr[pNo3]; Stack& trs = *trsOfPts[pt1->node]; FORALL(trs,i) { t = trs[i]; if (PinTr(pt1,t) && PinTr(pt2,t) && PinTr(pt3,t)) break; } if ( t->onBoundary() ) { t->classA = trClass[j]; t->boundP = trBound[j]; t->readHyperBC(parser); } } /* if (parser.findWord("Poin") == parser.ok) // additional BCs on points { while (parser.getValue(&pNo) == parser.ok) { p = ptAdr[pNo]; p->readBC(parser); } } */ } //------------------------------------------------------------------------- //------------------------------------------------------------------------- Bool MESH3:: pointOnEdge(PT3* p, EDG3* ed) { return (ed->p1 == p || ed->p2 == p); } //------------------------------------------------------------------------- Bool MESH3:: edgeOnTri(EDG3* ed, TR3* t) { return (t->e1 == ed || t->e2 == ed || t->e3 == ed); } //------------------------------------------------------------------------- EDG3* MESH3:: FindEdgByPts(PT3 *p1, PT3 *p2, Vector*>& edsOfPts) { int i; EDG3 *ed; Stack& edges = *edsOfPts[p1->node]; FORALL(edges,i) { ed = edges[i]; if (pointOnEdge(p1,ed) && pointOnEdge(p2,ed)) return ed; } ed = edgAlloc.Get(); // new EDG3; ed->p1 = p1; ed->p2 = p2; edsOfPts[p1->node]->push(ed); edsOfPts[p2->node]->push(ed); edgList[0]->add(ed); ++noOfEdges; return ed; } //------------------------------------------------------------------------- TR3* MESH3:: FindTrByEds(PT3 *p1, PT3 *p2, PT3 *p3, EDG3 *e1, EDG3 *e2, EDG3 *e3, Vector*>& trsOfPts) { int i; TR3 *t; Stack& trs = *trsOfPts[p1->node]; FORALL(trs,i) { t = trs[i]; if (edgeOnTri(e1,t) && edgeOnTri(e2,t) && edgeOnTri(e3,t)) return t; } t = new TR3; noOfTriangles++; t->e1 = e1; t->e2 = e2; t->e3 = e3; SetTP(t,0); trsOfPts[p1->node]->push(t); trsOfPts[p2->node]->push(t); trsOfPts[p3->node]->push(t); trList[0]->add(t); return t; } //------------------------------------------------------------------------- int MESH3:: completeTetrahedron(TET3 *td, Vector*>& edsOfPts, Vector*>& trsOfPts) { PT3 *p1 = td->p1, *p2 = td->p2, *p3 = td->p3, *p4 = td->p4; EDG3 *e1, *e2, *e3, *e4, *e5, *e6; TR3 *t1, *t2, *t3, *t4; td->e1 = FindEdgByPts(p1,p3,edsOfPts); td->e2 = FindEdgByPts(p2,p3,edsOfPts); td->e3 = FindEdgByPts(p1,p2,edsOfPts); td->e4 = FindEdgByPts(p3,p4,edsOfPts); td->e5 = FindEdgByPts(p2,p4,edsOfPts); td->e6 = FindEdgByPts(p1,p4,edsOfPts); e1 = td->e1; e2 = td->e2; e3 = td->e3; e4 = td->e4; e5 = td->e5; e6 = td->e6; t1 = FindTrByEds(p2,p3,p4,e2,e4,e5,trsOfPts); t2 = FindTrByEds(p1,p3,p4,e1,e4,e6,trsOfPts); t3 = FindTrByEds(p1,p2,p4,e3,e5,e6,trsOfPts); t4 = FindTrByEds(p1,p2,p3,e1,e2,e3,trsOfPts); // neighborhood of this tetrahedron int k = 0; if ((t1->t31)==0) { t1->t31 = td; k++; } else if ((t1->t32)==0) { t1->t32 = td; k++; } if ((t2->t31)==0) { t2->t31 = td; k++; } else if ((t2->t32)==0) { t2->t32 = td; k++; } if ((t3->t31)==0) { t3->t31 = td; k++; } else if ((t3->t32)==0) { t3->t32 = td; k++; } if ((t4->t31)==0) { t4->t31 = td; k++; } else if ((t4->t32)==0) { t4->t32 = td; k++; } if (k!=4) { cout << "\n*** Tetra: impossible state (completeTetrahedron), k= " << k << "\n"; cout.flush(); abort(); } return True; } //------------------------------------------------------------------------- void MESH3:: setNeighbsOfTetra(TR3* t) { TET3 *tet1 = t->t31, *tet2 = t->t32; if (tet2 != nil) { if (!PinTr(tet2->p1,t)) { if (tet1) tet2->n1 = tet1; else { tet2->n1 = t; SetTP(tet2,t,2,3,4); } } else if (!PinTr(tet2->p2,t)) { if (tet1) tet2->n2 = tet1; else { tet2->n2 = t; SetTP(tet2,t,1,4,3); } } else if (!PinTr(tet2->p3,t)) { if (tet1) tet2->n3 = tet1; else { tet2->n3 = t; SetTP(tet2,t,1,2,4); } } else if (!PinTr(tet2->p4,t)) { if (tet1) tet2->n4 = tet1; else { tet2->n4 = t; SetTP(tet2,t,1,3,2); } } } if (tet1 != nil) { if (!PinTr(tet1->p1,t)) { if (tet2) tet1->n1 = tet2; else { tet1->n1 = t; SetTP(tet1,t,2,3,4); } } else if (!PinTr(tet1->p2,t)) { if (tet2) tet1->n2 = tet2; else { tet1->n2 = t; SetTP(tet1,t,1,4,3); } } else if (!PinTr(tet1->p3,t)) { if (tet2) tet1->n3 = tet2; else { tet1->n3 = t; SetTP(tet1,t,1,2,4); } } else if (!PinTr(tet1->p4,t)) { if (tet2) tet1->n4 = tet2; else { tet1->n4 = t; SetTP(tet1,t,1,3,2); } } } return; } //------------------------------------------------------------------------- void MESH3:: writeTriangulation(const char* /*outFileText*/, const Vector& u) const { if (Cmd.isTrue("writeGrapeFormat")) writeGrapeFormat (fileName, u); if (Cmd.isTrue("writeAVSFormat")) writeAVSFormat (fileName, u); if (Cmd.isTrue("writeHyperFormat")) writeHyperFormat (fileName, u); if (Cmd.isTrue("writeZIBFormat")) writeZIBFormat (fileName, u); } //------------------------------------------------------------------------- void MESH3:: writeZIBFormat(const char* outFileText, const Vector& u)const { int i; int node; TET3 *tet; TR3 *t; PT3 *p; FILE *outFile; Vector PNodes(noOfPoints); // saving the node numbers for later reuse i = 0; DListIter PIter(points()); while ((p=PIter.all())) PNodes[++i] = p->node; char* outText = new char[strlen(outFileText)+10]; strcpy(outText, outFileText); strcpy(strchr(outText,'.'),".zib.geo"); outFile = fopen(outText, "w"); if (outFile==0) { cout << "\n*** writeTriangulation: could not open file " << outText << "\n"; cout.flush(); abort(); } fprintf(outFile, "# %s\n\n", fileName); fprintf(outFile, "Points: maxIndex %d\n", noOfPoints); node = 0; DListIter iterPts(points()); while ((p=iterPts.all())) { p->node = node+1; fprintf(outFile, " %d %e %e %e\n", p->node, p->x, p->y, p->z); node++; } fprintf(outFile, "END\n"); fprintf(outFile, "\nElements:\n"); DListIter iterTet(tetras()); while ((tet=iterTet.all())) { fprintf(outFile, "%d %d %d %d %d\n", (tet->p1)->node, (tet->p2)->node, (tet->p3)->node, (tet->p4)->node, tet->classA ); } fprintf(outFile, "END\n"); fprintf(outFile, "\nBoundary: #faces\n"); DListIter iterTrs(triangles()); while ((t=iterTrs.all())) { if (!t->onBoundary()) continue; if (t->isDirichlet()) { if (t->isoP == CIRCULAR) fprintf(outFile, "%d %d %d D %d S\n", (t->p1)->node, (t->p2)->node,(t->p3)->node,t->classA); else if (t->isoP == CYLINDRICAL) fprintf(outFile, "%d %d %d D %d C\n", (t->p1)->node, (t->p2)->node,(t->p3)->node,t->classA); else fprintf(outFile, "%d %d %d D %d P\n", (t->p1)->node, (t->p2)->node,(t->p3)->node,t->classA); } else if (t->isNeumann()) { if (t->isoP == CIRCULAR) fprintf(outFile, "%d %d %d N %d S\n", (t->p1)->node, (t->p2)->node,(t->p3)->node,t->classA); else if (t->isoP == CYLINDRICAL) fprintf(outFile, "%d %d %d N %d C\n", (t->p1)->node, (t->p2)->node,(t->p3)->node,t->classA); else fprintf(outFile, "%d %d %d N %d P\n", (t->p1)->node, (t->p2)->node,(t->p3)->node,t->classA); } else if (t->isCauchy()) { if (t->isoP == CIRCULAR) fprintf(outFile, "%d %d %d C %d S\n", (t->p1)->node, (t->p2)->node,(t->p3)->node,t->classA); else if (t->isoP == CYLINDRICAL) fprintf(outFile, "%d %d %d C %d C\n", (t->p1)->node, (t->p2)->node,(t->p3)->node,t->classA); else fprintf(outFile, "%d %d %d C %d P\n", (t->p1)->node, (t->p2)->node,(t->p3)->node,t->classA); } else fprintf(outFile, "%d %d %d I \n", (t->p1)->node, (t->p2)->node,(t->p3)->node ); } fprintf(outFile, "END\n"); // output of values at the nodes located in the points fprintf(outFile, "\nValues in nodes: \n"); i = 0; iterPts.reset(); while ((p=iterPts.all())) fprintf(outFile, "%e\n", u[PNodes[++i]]); fprintf(outFile, "END\n"); cout << "\n ZIB-Data ok.; written to " << outText << "\n"; delete outText; fclose(outFile); // restore of node numbers i = 0; PIter.reset(); while ((p=PIter.all())) p->node = PNodes[++i]; } //------------------------------------------------------------------------- void MESH3:: writeHyperFormat(const char* outFileText, const Vector& u) const { FILE *outFile; int i; TET3 *tet; TR3 *t; EDG3 *ed; PT3 *p, *p1, *p2, *p3, *p4; PATCH *n1, *n2, *n3, *n4; Vector PNodes(noOfPoints), ENodes(noOfEdges), TrNodes(noOfTriangles), TetNodes(noOfTetrahedra); Vector TetMark(noOfTetrahedra); // saving the node numbers for later reuse and temorary node numbering i = 0; DListIter PIter(points()); while ((p=PIter.all())) { PNodes[++i] = p->node; p->node = i; } i = 0; DListIter EIter(edges()); while ((ed=EIter.all())) { ENodes[++i] = ed->node; ed->node = i; } i = 0; DListIter TrIter(triangles()); while ((t=TrIter.all())) { TrNodes[++i] = t->node; t->node = i; } i = 0; DListIter TetIter(tetras()); while ((tet=TetIter.all())) { TetNodes[++i] = tet->node; tet->node = i; TetMark[i] = tet->mark; tet->mark = 0; } char* outText = new char[strlen(outFileText)+10]; strcpy(outText, outFileText); strcpy(strchr(outText,'.'),".hyper"); outFile = fopen(outText, "w"); if (outFile==0) { cout << "\n*** writeHyper: could not open file " << outText << "\n"; cout.flush(); abort(); } fprintf(outFile, "# HyperMesh ASCII 0.2 \n"); fprintf(outFile, "# \n"); fprintf(outFile, "# \n"); fprintf(outFile, "nPoints = %d \n", noOfPoints); fprintf(outFile, "nEdges = %d \n", noOfEdges); fprintf(outFile, "nTriangles = %d \n", noOfTriangles); fprintf(outFile, "nTetrahedrons = %d \n", noOfTetrahedra); fprintf(outFile, "# \n"); fprintf(outFile, "Points { double[3] } = @1 \n"); fprintf(outFile, "Edges { int[2] } = @2 \n"); fprintf(outFile, "Triangles { int[5] } = @3 \n"); fprintf(outFile, "Tetrahedrons { int[4] } = @4 \n"); fprintf(outFile, "TriangleEncoding = points tetrahedrons \n"); fprintf(outFile, "TetrahedronEncoding = points \n"); fprintf(outFile, "PointData { double } = @5 \n"); fprintf(outFile, "TriangleData { byte[2] } = @6 \n"); fprintf(outFile, "TetrahedronData { byte[2] } = @7 \n"); fprintf(outFile, "# \n"); fprintf(outFile, "#End of Header. Data follows.\n"); fprintf(outFile, "# \n"); fprintf(outFile, "\n@1 \n"); DListIter iterPts(points()); // coordinates of the points while ((p=iterPts.all())) { fprintf(outFile, "%e %e %e\n", p->x, p->y, p->z); } fprintf(outFile, "\n@2 \n"); DListIter iterEds(edges()); while ((ed=iterEds.all())) { fprintf(outFile, "%d %d\n", (ed->p1)->node, (ed->p2)->node); } fprintf(outFile, "\n@3 \n"); int trsMark[1+4]; Vector trBoundP(noOfTriangles), trClassA(noOfTriangles); DListIter iterTets(tetras()); TET3 *nbTet = 0; int trsM; i = 0; while ((tet=iterTets.all())) { tet->getMarkedTriangles(trsMark); p1=tet->p1; p2=tet->p2; p3=tet->p3; p4=tet->p4; n1=tet->n1; n2=tet->n2; n3=tet->n3; n4=tet->n4; if ( !(tet->orient()) ) { p1 = tet->p2; p2 = tet->p1; n1 = tet->n2; n2 = tet->n1; trsM =trsMark[1]; trsMark[1] = trsMark[2]; trsMark[2] = trsM; } if (!trsMark[1]) { fprintf(outFile, "%d %d %d ", p3->node, p2->node, p4->node); nbTet = n1->castToTET3(); if ( nbTet ) { fprintf(outFile, " %d %d", tet->node, nbTet->node ); nbTet->markTriangles(tet); trBoundP[++i] = INTERIOR; trClassA[i] = 1; } else { fprintf(outFile, " %d 0", tet->node); t = n1->castToTR3(); trBoundP[++i] = t->boundP; trClassA[i] = t->classA; } fprintf(outFile, "\n"); } if (!trsMark[2]) { fprintf(outFile, "%d %d %d ", p1->node, p3->node, p4->node); nbTet = n2->castToTET3(); if ( nbTet ) { fprintf(outFile, " %d %d", tet->node, nbTet->node); nbTet->markTriangles(tet); trBoundP[++i] = INTERIOR; trClassA[i] = 1; } else { fprintf(outFile, " %d 0", tet->node); t = n2->castToTR3(); trBoundP[++i] = t->boundP; trClassA[i] = t->classA; } fprintf(outFile, "\n"); } if (!trsMark[3]) { fprintf(outFile, "%d %d %d ", p2->node, p1->node, p4->node); nbTet = n3->castToTET3(); if ( nbTet ) { fprintf(outFile, " %d %d", tet->node, nbTet->node); nbTet->markTriangles(tet); trBoundP[++i] = INTERIOR; trClassA[i] = 1; } else { fprintf(outFile, " %d 0", tet->node); t = n3->castToTR3(); trBoundP[++i] = t->boundP; trClassA[i] = t->classA; } fprintf(outFile, "\n"); } if (!trsMark[4]) { fprintf(outFile, "%d %d %d ", p1->node, p2->node, p3->node); nbTet = n4->castToTET3(); if ( nbTet ) { fprintf(outFile, " %d %d", tet->node, nbTet->node); nbTet->markTriangles(tet); trBoundP[++i] = INTERIOR; trClassA[i] = 1; } else { fprintf(outFile, " %d 0", tet->node); t = n4->castToTR3(); trBoundP[++i] = t->boundP; trClassA[i] = t->classA; } fprintf(outFile, "\n"); } } fprintf(outFile, "\n@4 \n"); iterTets.reset(); while ((tet=iterTets.all())) { p1=tet->p1; p2=tet->p2; p3=tet->p3; p4=tet->p4; if ( !(tet->orient()) ) { p1 = tet->p2; p2 = tet->p1; } fprintf(outFile, "%d %d %d %d\n", p1->node, p2->node, p3->node, p4->node); } fprintf(outFile, "\n@5 \n"); // data at points iterPts.reset(); while ((p=iterPts.all())) fprintf(outFile, "%e\n", u[PNodes[p->node]]); fprintf(outFile, "\n@6 \n"); // data at triangles for (i=1; i<= noOfTriangles; i++) { fprintf(outFile, "%d %d \n", trBoundP[i], trClassA[i]); } fprintf(outFile, "\n@7 \n"); // data at tetrahedra iterTets.reset(); while ((tet=iterTets.all())) fprintf(outFile, "%d\n", tet->classA); fprintf(outFile, "\n#End of file.\n"); // data at tetrahedra cout << "\n Hyper-Data ok.; written to " << outText << "\n"; delete outText; fclose(outFile); // restore of node numbers i = 0; PIter.reset(); while ((p=PIter.all())) p->node = PNodes[++i]; i = 0; EIter.reset(); while ((ed=EIter.all())) ed->node = ENodes[++i]; i = 0; TrIter.reset(); while ((t=TrIter.all())) t->node = TrNodes[++i]; i = 0; TetIter.reset(); while ((tet=TetIter.all())) { tet->node = TetNodes[++i]; tet->mark = TetMark[i]; } return; } //------------------------------------------------------------------------- void MESH3:: writeGrapeFormat(const char* outFileText, const Vector& u) const { FILE *outFile; int i; int node; int k[4]; TET3 *tet; PT3 *p; Vector PNodes(noOfPoints), TetNodes(noOfTetrahedra); i = 0; DListIter PIter(points()); while ((p=PIter.all())) PNodes[++i] = p->node; i = 0; DListIter TIter(tetras()); while ((tet=TIter.all())) TetNodes[++i] = tet->node; char* outText = new char[strlen(outFileText)+10]; strcpy(outText, outFileText); strcpy(strchr(outText,'.'),".grape"); outFile = fopen(outText, "w"); if (outFile==0) { cout << "\n*** grapeTriangulation: could not open file " << outText << "\n"; cout.flush(); abort(); } fprintf(outFile, "%d\n", noOfTetrahedra); fprintf(outFile, "%d\n", noOfPoints); node = 0; DListIter iterPts(points()); while ((p=iterPts.all())) { p->node = node+1; fprintf(outFile, "%e %e %e\n", p->x, p->y, p->z); node++; } node = 0; DListIter iterTet(tetras()); while ((tet=iterTet.all())) { tet->node = node+1; if (tet->orient()) fprintf(outFile, "%d %d %d %d %d\n", (tet->p1)->node, (tet->p2)->node, (tet->p4)->node, (tet->p3)->node, tet->classA ); else fprintf(outFile, "%d %d %d %d %d\n", (tet->p1)->node, (tet->p2)->node, (tet->p3)->node, (tet->p4)->node, tet->classA ); node++; } iterTet.reset(); while ((tet=iterTet.all())) { TET3* n; n = (tet->n1)->castToTET3(); if ( n == nil ) k[0] = -1; else k[0] = n->node; n = (tet->n2)->castToTET3(); if ( n == nil ) k[1] = -1; else k[1] = n->node; if (tet->orient()) { n = (tet->n3)->castToTET3(); if ( n == nil ) k[3] = -1; else k[3] = n->node; n = (tet->n4)->castToTET3(); if ( n == nil ) k[2] = -1; else k[2] = n->node; } else { n = (tet->n3)->castToTET3(); if ( n == nil ) k[2] = -1; else k[2] = n->node; n = (tet->n4)->castToTET3(); if ( n == nil ) k[3] = -1; else k[3] = n->node; } fprintf(outFile, "%d %d %d %d\n", k[0], k[1], k[2], k[3]); } fprintf(outFile, "1\n"); i = 0; iterPts.reset(); while ((p=iterPts.all())) fprintf(outFile, "%e\n", u[PNodes[++i]]); cout << "\n GRAPE-Data ok.; written to " << outText << "\n"; delete outText; fclose(outFile); i = 0; PIter.reset(); while ((p=PIter.all())) p->node = PNodes[++i]; i = 0; TIter.reset(); while ((tet=TIter.all())) tet->node = TetNodes[++i]; return; } //------------------------------------------------------------------------- void MESH3:: writeAVSFormat(const char* outFileText, const Vector& u) const { int i; int node, noOfPValues, noOfTetValues, noOfModValues; int noOfComponents, noOfElems; TET3 *tet; PT3 *p; FILE *outFile; Vector PNodes(noOfPoints); i = 0; DListIter PIter(points()); while ((p=PIter.all())) PNodes[++i] = p->node; char* outText = new char[strlen(outFileText)+10]; strcpy(outText, outFileText); strcpy(strchr(outText,'.'),".AVS"); outFile = fopen(outText, "w"); if (outFile==0) { cout << "\n*** AVSTriangulation: could not open file " << outText << "\n"; cout.flush(); abort(); } noOfPValues = 1; noOfTetValues = 1; noOfModValues = 0; fprintf(outFile, "%d %d %d %d %d\n", noOfPoints,noOfTetrahedra,noOfPValues,noOfTetValues, noOfModValues); node = 0; DListIter iterPts(points()); while ((p=iterPts.all())) { p->node = node; fprintf(outFile, "%d %e %e %e\n", p->node, p->x, p->y, p->z); node++; } node = 0; DListIter iterTet(tetras()); while ((tet=iterTet.all())) { fprintf(outFile, "%d %d tet %d %d %d %d\n", node, tet->classA, (tet->p1)->node, (tet->p2)->node, (tet->p3)->node, (tet->p4)->node ); node++; } noOfComponents = 1; noOfElems = 1; fprintf(outFile, "%d %d\n", noOfComponents,noOfElems); fprintf(outFile, "Temperature, Degree\n"); i = 0; iterPts.reset(); while ((p=iterPts.all())) { fprintf(outFile, "%d %e\n", i, u[PNodes[i+1]]); i++; } fprintf(outFile, "%d %d\n", noOfComponents,noOfElems); fprintf(outFile, "Material, ClassA\n"); i = 0; iterTet.reset(); while ((tet=iterTet.all())) { fprintf(outFile, "%d %d\n", i, int(tet->classA)); i++; } cout << "\n AVS-Data ok.; written to " << outText << "\n"; delete outText; fclose(outFile); i = 0; PIter.reset(); while ((p=PIter.all())) p->node = PNodes[++i]; } //------------------------------------------------------------------------- void MESH3:: Refine() { TET3* tet; int noPt[3], noEdg[3], noTr[3], noTet[3]; Timer timer, accTimer; noPt[0] = noOfPoints; noEdg[0] = noOfEdges; noTr[0] = noOfTriangles; noTet[0] = noOfTetrahedra; RemoveGreen(); // delete all green tetras noPt[1] = noOfPoints; noTr[1] = noOfTriangles; noEdg[1] = noOfEdges; noTet[1] = noOfTetrahedra; DList* tetL = new DList; tetList.push(tetL); moreRedTd = 0; DListIter iter(tetras()); while ((tet=iter.all())) RefineTetra(tet); // Algorithm: For all tetrahedra: // (1) look if there are 3 refined edges, // two of these on different faces, // and refine it red this case, // (2) if no neighbor tetrahedron exists, "father neighbor" // tetrahedron needs to be red refined (green refined at // the last level). // This routine does not use recursion. if (infoRefinement >= 2) cout << "\n Refine: moreRedTd ="; moreRedTd = 1; while (moreRedTd) { moreRedTd = 0; iter.reset(); while ((tet=iter.all())) CloseRedTet(tet); if (infoRefinement >= 2) cout << " " << moreRedTd; if (moreRedTd == 0) break; iter.reset(); while ((tet=iter.all())) RefineTetra(tet); } noPt[2] = noOfPoints; noTr[2] = noOfTriangles; noEdg[2] = noOfEdges; noTet[2] = noOfTetrahedra; MakeGreen(); // now: tetrahedra with a boundary face are marked when generated // iter.reset(); // while (tet=iter.all()) tet->setBoundary(); ++refStep; if (Cmd.isTrue("triCheck")) consistencyCheck(); if (infoRefinement) refinementInfo (noPt, noEdg, noTr, noTet); timeInfo(timer, accTimer); if (Cmd.isTrue("printMesh")) cout << *this; } //------------------------------------------------------------------------- int MESH3:: CloseRedTet(TET3 *tet) { TR3 *t; TR3 *trs[1+4]; EDG3 *ed, *edSon1, *edSon2; EDG3 *eds[1+6]; int i, noOfRefEds; // request to refine a further tetrahedron tet if ( (tet->mark) == True) { moreRedTd++; return True; } noOfRefEds = TestEdsInTd(tet); if ( noOfRefEds < 3) return True; if ( noOfRefEds > 3) { tet->mark = True; moreRedTd++; return True; } tet->mark = True; tet->getTriangles(trs); for (i=1; i<=4; i++) if (TestFace(trs[i]) == 3) {tet->mark = False; break;} if ( tet->mark == True) { moreRedTd++; tet->returnTriangles(trs); return True; } tet->getEdges(eds); for (i=1; i<=6; i++) { ed = eds[i]; edSon1 = ed->firstSon; if ( (edSon1) != 0) { edSon2 = edSon1->next; if ( (edSon1->firstSon != 0) || (edSon2->firstSon != 0) ) { tet->mark = True; moreRedTd++; tet->returnTriangles(trs); return True; } } } TET3 *nbTet; for (i=1; i<=4; i++) { t = trs[i]; nbTet = t->t32; if (nbTet == 0) continue; if (nbTet->refined()) { if (testSons(t,nbTet) > 0) { tet->mark = True; moreRedTd++; tet->returnTriangles(trs); return True; } } } tet->returnTriangles(trs); return True; } //------------------------------------------------------------------------- void MESH3:: RemoveGreen() { RelGreen3Td(); RelGreen2ATd(); RelGreen2BTd(); RelGreen1Td(); RelGreen(); RelGreenIrr(); return; } //------------------------------------------------------------------------- int MESH3:: MakeGreen() { TET3* tet; moreGreen1Td = 0; moreGreen2ATd = 0; moreGreen2BTd = 0; moreGreen3Td = 0; DListIter iter(tetras()); while ((tet=iter.all())) MarkGreenTd(tet); if (infoRefinement >= 2) cout << "\n GREEN-I -Closure: moreGreen-I-Td = " << moreGreen1Td<< "\n"; iter.reset(); while ((tet=iter.all())) { if (!MkGreen1Td(tet)) { cout << "*** Tri: failed making GREEN-I tetrahedra (CloseRef)\n"; cout.flush(); abort(); //return False; } } if (infoRefinement >= 2) cout << " GREEN-II -Closure: moreGreen-IIA-Td = " << moreGreen2ATd; iter.reset(); while ((tet=iter.all())) { if (!MkGreen2ATd(tet)) { cout << "Tri: failed making GREEN-II tetrahedra (CloseRef)\n"; cout.flush(); abort(); // return False; } } if (infoRefinement >= 2) cout << " moreGreen-IIB-Td = " << moreGreen2BTd << "\n"; iter.reset(); while ((tet=iter.all())) { if (!MkGreen2BTd(tet)) { cout << "Tri: failed making GREEN-II tetrahedra (CloseRef)\n"; cout.flush(); abort(); // return False; } } if (infoRefinement >= 2) cout << " GREEN-III-Closure: moreGreen-III-Td = " << moreGreen3Td <<"\n"; iter.reset(); while ((tet=iter.all())) { if (!MkGreen3Td(tet)) { cout << "Tri: failed making GREEN-III tetrahedra (CloseRef)\n"; return False; } } return True; } //-------------------------------------------------------------------------------- int MESH3:: RefineTetra(TET3 *td) { // internal routine to refine a tetrahedron, loTrues for if (td->mark) td->mark = False; /* return if not marked */ else return True; if ((td->firstSon)!=0) { cout << "\n*** RefineTetra:??????? marked but already refined \n"; return True; // return if already marked } moreRedTd++; if (refinementType == ShortDiag) { if ( !(RefineTdShortDiag(td)) ) { cout << "\n*** RefineTetra: tetrahedron not refined \n"; cout.flush(); abort(); } } else if (refinementType == BeyStabilDiag) { if ( !(RefineTdBey(td)) ) { cout << "\n*** RefineTetra: tetrahedron not refined \n"; cout.flush(); abort(); } } else { cout << "\n*** RefineTetra: unknown refinement type requested\n"; cout.flush(); abort(); } return True; } //------------------------------------------------------------------------- int MESH3:: RefineTdShortDiag(TET3 *td) { // Refinement of a tetrahedron // Method of Zang (Select the shortest diagonal in the octahedron) TET3 *td1, *td2, *td3, *td4, *td5, *td6, *td7, *td8; TR3 *tr, *tr1, *tr2, *tr3, *tr4, *it1, *it2, *it3, *it4, *it5, *it6, *it7, *it8, *t11=0, *t12=0, *t13=0, *t14=0, *t21=0, *t22=0, *t23=0, *t24=0, *t31=0, *t32=0, *t33=0, *t34=0, *t41=0, *t42=0, *t43=0, *t44=0, *t1, *t2, *t3, *t4; TR3 *trs[1+4]; PT3 *p1 = td->p1,*p2 = td->p2, *p3 = td->p3, *p4 = td->p4, *p5, *p6, *p7, *p8, *p9, *p10; EDG3 *e1 = td->e1, *e2 = td->e2, *e3 = td->e3, *e4 = td->e4, *e5 = td->e5, *e6 = td->e6, *ie1, *ed; PATCH *n1=td->n1, *n2=td->n2, *n3=td->n3, *n4=td->n4; Real len59, len78, len610; int k, diag59=False, diag78=False, diag610=False; int depth; td->getTriangles(trs); t1=trs[1]; t2=trs[2]; t3=trs[3]; t4=trs[4]; // Get 8 new tetrahedra, 8 new triangles, 1 new edges // return False if not enough space td1 = getTET3(); // new TET3; td2 = getTET3(); td3 = getTET3(); td4 = getTET3(); td5 = getTET3(); td6 = getTET3(); td7 = getTET3(); td8 = getTET3(); noOfTetrahedra += 7; it1 = new TR3; // new TR3; it2 = new TR3; it3 = new TR3; it4 = new TR3; it5 = new TR3; it6 = new TR3; it7 = new TR3; it8 = new TR3; noOfTriangles += 8; ie1 = edgAlloc.Get(); // new EDG3; noOfEdges += 1; if ( (td8==0)||(it8==0)||(ie1==0) ) { cout << " no memory in RefineTd \n"; return False; } depth = (td->depth) + 1; ie1->depth = depth; if (ie1->depth > edgList.h) // create new list at depth if necessary { DList* edgL = new DList; edgList.push(edgL); } edgList[ie1->depth]->add(ie1); it1->depth = depth; it2->depth = depth; it3->depth = depth; it4->depth = depth; it5->depth = depth; it6->depth = depth; it7->depth = depth; it8->depth = depth; // Set the "son" triangles tik, i=1,2,3,4; k=1,2,3,4; // each triangle is refined // Triangle 1 if (!RefineTr(t1)) { cout << " failed in RefineTr called by RefineTd \n"; return False; } setTypeOfInnerEdges(t1); tr1 = t1->firstSon; if (tr1==0) return False; // No space for Refinement // Triangle 2 if (!RefineTr(t2)) { cout << " failed in RefineTr called by RefineTd \n"; return False; } tr2 = t2->firstSon; setTypeOfInnerEdges(t2); if (tr2==0) return False; // No space for Refinement // Triangle 3 if (!RefineTr(t3)) { cout << " failed in RefineTr called by RefineTd \n"; return False; } setTypeOfInnerEdges(t3); tr3 = t3->firstSon; if (tr3==0) return False; /* No space for Refinement */ // Triangle 4 if (!RefineTr(t4)) { cout << " failed in RefineTr called by RefineTd \n"; return False; } setTypeOfInnerEdges(t4); tr4 = t4->firstSon; if (tr4==0) return False; /* No space for Refinement */ p5 = e3->pm; p6 = e5->pm; p7 = e2->pm; p8 = e6->pm; p9 = e4->pm; p10= e1->pm; // one new edge in the octahedron len59 = Length(p5,p9); len78 = Length(p7,p8); len610 = Length(p6,p10); if ( (len59 <= len78) && (len59 <= len610) ) { ie1->p1 = p5; ie1->p2 = p9; diag59 = True; } else if ( (len78 <= len59) && (len78 <= len610) ) { ie1->p1 = p7; ie1->p2 = p8; diag78 = True; } else { ie1->p1 = p6; ie1->p2 = p10; diag610 = True; } ie1->pm = 0; // ie1->bound = 0; // new faces tr = tr1; for (k = 0; k<4; k++) { if (PinTr(p2,tr)) t12 = tr; else if (PinTr(p3,tr)) t13 = tr; else if (PinTr(p4,tr)) t14 = tr; else { t11 = tr; ed = EdinTr(tr,p6,p7); it2->e1 = ed; if(diag78) it5->e1 = ed; else if(diag610) it7->e1 = ed; ed = EdinTr(tr,p7,p9); it3->e1 = ed; if(diag59||diag78) it7->e1 = ed; ed = EdinTr(tr,p6,p9); it4->e1 = ed; if(diag59) it5->e1 = ed; else if(diag610) it8->e2 = ed; } tr = tr->next; } tr = tr2; for (k = 0; k<4; k++) { if (PinTr(p1,tr)) t21 = tr; else if (PinTr(p3,tr)) t23 = tr; else if (PinTr(p4,tr)) t24 = tr; else { t22 = tr; ed = EdinTr(tr,p8,p10); it1->e1 = ed; if(diag78) it8->e1 = ed; else if(diag610) it6->e1 = ed; ed = EdinTr(tr,p8,p9); it4->e2 = ed; if(diag59) it6->e1 = ed; else if(diag78) it7->e2 = ed; ed = EdinTr(tr,p9,p10); it3->e2 = ed; if(diag59||diag610) it8->e1 = ed; } tr = tr->next; } tr = tr3; for (k = 0; k<4; k++) { if (PinTr(p1,tr)) t31 = tr; else if (PinTr(p2,tr)) t32 = tr; else if (PinTr(p4,tr)) t34 = tr; else { t33 = tr; ed = EdinTr(tr,p5,p8); it1->e2 = ed; if(diag59||diag78) it6->e2 = ed; ed = EdinTr(tr,p6,p8); it4->e3 = ed; if(diag78) it5->e2 = ed; else if(diag610) it6->e2 = ed; ed = EdinTr(tr,p6,p5); it2->e2 = ed; if(diag59||diag610) it5->e2 = ed; } tr = tr->next; } tr = tr4; for (k = 0; k<4; k++) { if (PinTr(p1,tr)) t41 = tr; else if (PinTr(p2,tr)) t42 = tr; else if (PinTr(p3,tr)) t43 = tr; else { t44 = tr; ed = EdinTr(tr,p5,p10); it1->e3 = ed; if(diag59) it8->e2 = ed; else if(diag610) it5->e1 = ed; ed = EdinTr(tr,p7,p10); it3->e3 = ed; if(diag610) it7->e2 = ed; else if(diag78) it8->e2 = ed; ed = EdinTr(tr,p5,p7); it2->e3 = ed; if(diag59) it7->e2 = ed; else if(diag78) it6->e1 = ed; } tr = tr->next; } // four new triangles on the octahedron SetTP(it1,0); SetTP(it2,0); SetTP(it3,0); SetTP(it4,0); // four new edges in the octahedron it5->e3 = ie1; it6->e3 = ie1; it7->e3 = ie1; it8->e3 = ie1; SetTP(it5,0); SetTP(it6,0); SetTP(it7,0); SetTP(it8,0); // Build the new tetrahedra. // tetrahedra generated by chopping off the 4 corners SetTdP(td1,t21,t31,t41,it1,td); SetTdE(td1,t21,t31,t41,it1); neighbourAtFace(td1,n2,t21); neighbourAtFace(td1,n3,t31); neighbourAtFace(td1,n4,t41); SetTdP(td2,t12,t32,t42,it2,td); SetTdE(td2,t12,t32,t42,it2); neighbourAtFace(td2,n1,t12); neighbourAtFace(td2,n3,t32); neighbourAtFace(td2,n4,t42); SetTdP(td3,t13,t23,t43,it3,td); SetTdE(td3,t13,t23,t43,it3); neighbourAtFace(td3,n1,t13); neighbourAtFace(td3,n2,t23); neighbourAtFace(td3,n4,t43); SetTdP(td4,t14,t24,t34,it4,td); SetTdE(td4,t14,t24,t34,it4); neighbourAtFace(td4,n1,t14); neighbourAtFace(td4,n2,t24); neighbourAtFace(td4,n3,t34); // tetrahedra generated by the inner octahedron if (diag59) { SetTdP(td5,t33,it5,it4,it6,td); SetTdE(td5,t33,it5,it4,it6); neighbourAtFace(td5,n3,t33); innerNeighbourAtFace(td5,it5,td6); innerNeighbourAtFace(td5,it4,td4); innerNeighbourAtFace(td5,it6,td7); innerNeighbourAtFace(td4,it4,td5); SetTdP(td6,t11,it7,it2,it5,td); SetTdE(td6,t11,it7,it2,it5); neighbourAtFace(td6,n1,t11); innerNeighbourAtFace(td6,it7,td8); innerNeighbourAtFace(td6,it2,td2); innerNeighbourAtFace(td6,it5,td5); innerNeighbourAtFace(td2,it2,td6); SetTdP(td7,t22,it8,it6,it1,td); SetTdE(td7,t22,it8,it6,it1); neighbourAtFace(td7,n2,t22); innerNeighbourAtFace(td7,it8,td8); innerNeighbourAtFace(td7,it6,td5); innerNeighbourAtFace(td7,it1,td1); innerNeighbourAtFace(td1,it1,td7); SetTdP(td8,t44,it3,it8,it7,td); SetTdE(td8,t44,it3,it8,it7); neighbourAtFace(td8,n4,t44); innerNeighbourAtFace(td8,it3,td3); innerNeighbourAtFace(td8,it8,td7); innerNeighbourAtFace(td8,it7,td6); innerNeighbourAtFace(td3,it3,td8); } else if (diag78) { SetTdP(td5,t33,it5,it2,it6,td); SetTdE(td5,t33,it5,it2,it6); neighbourAtFace(td5,n3,t33); innerNeighbourAtFace(td5,it5,td6); innerNeighbourAtFace(td5,it2,td2); innerNeighbourAtFace(td5,it6,td7); innerNeighbourAtFace(td2,it2,td5); SetTdP(td6,t11,it7,it4,it5,td); SetTdE(td6,t11,it7,it4,it5); neighbourAtFace(td6,n1,t11); innerNeighbourAtFace(td6,it7,td8); innerNeighbourAtFace(td6,it4,td4); innerNeighbourAtFace(td6,it5,td5); innerNeighbourAtFace(td4,it4,td6); SetTdP(td7,t44,it8,it6,it1,td); SetTdE(td7,t44,it8,it6,it1); neighbourAtFace(td7,n4,t44); innerNeighbourAtFace(td7,it8,td8); innerNeighbourAtFace(td7,it6,td5); innerNeighbourAtFace(td7,it1,td1); innerNeighbourAtFace(td1,it1,td7); SetTdP(td8,t22,it3,it8,it7,td); SetTdE(td8,t22,it3,it8,it7); neighbourAtFace(td8,n2,t22); innerNeighbourAtFace(td8,it3,td3); innerNeighbourAtFace(td8,it8,td7); innerNeighbourAtFace(td8,it7,td6); innerNeighbourAtFace(td3,it3,td8); } else { SetTdP(td5,t33,it5,it1,it6,td); SetTdE(td5,t33,it5,it1,it6); neighbourAtFace(td5,n3,t33); innerNeighbourAtFace(td5,it5,td7); innerNeighbourAtFace(td5,it1,td1); innerNeighbourAtFace(td5,it6,td6); innerNeighbourAtFace(td1,it1,td5); SetTdP(td6,t22,it6,it8,it4,td); SetTdE(td6,t22,it6,it8,it4); neighbourAtFace(td6,n2,t22); innerNeighbourAtFace(td6,it6,td5); innerNeighbourAtFace(td6,it8,td8); innerNeighbourAtFace(td6,it4,td4); innerNeighbourAtFace(td4,it4,td6); SetTdP(td7,t44,it2,it5,it7,td); SetTdE(td7,t44,it2,it5,it7); neighbourAtFace(td7,n4,t44); innerNeighbourAtFace(td7,it2,td2); innerNeighbourAtFace(td7,it5,td5); innerNeighbourAtFace(td7,it7,td8); innerNeighbourAtFace(td2,it2,td7); SetTdP(td8,t11,it3,it8,it7,td); SetTdE(td8,t11,it3,it8,it7); neighbourAtFace(td8,n1,t11); innerNeighbourAtFace(td8,it3,td3); innerNeighbourAtFace(td8,it8,td6); innerNeighbourAtFace(td8,it7,td7); innerNeighbourAtFace(td3,it3,td8); } td1->type = T_WHITE; td2->type = T_WHITE; td3->type = T_WHITE; td4->type = T_WHITE; td5->type = T_WHITE; td6->type = T_WHITE; td7->type = T_WHITE; td8->type = T_WHITE; td->firstSon = td1; td->type = T_RED; tetList[tetList.h]->add(td1); tetList[tetList.h]->add(td2); tetList[tetList.h]->add(td3); tetList[tetList.h]->add(td4); tetList[tetList.h]->add(td5); tetList[tetList.h]->add(td6); tetList[tetList.h]->add(td7); tetList[tetList.h]->add(td8); // destruction of the faces delete it1; delete it2; delete it3; delete it4; delete it5; delete it6; delete it7; delete it8; if ( !(t1->onBoundary()) ) { delete t11; delete t12; delete t13; delete t14; } if ( !(t2->onBoundary()) ) { delete t21; delete t22; delete t23; delete t24; } if ( !(t3->onBoundary()) ) { delete t31; delete t32; delete t33; delete t34; } if ( !(t4->onBoundary()) ) { delete t41; delete t42; delete t43; delete t44; } td->returnTriangles(trs); return True; } //------------------------------------------------------------------------- int MESH3:: faceNoInTd(TR3 *t, TET3 *tet) { PT3 *p1=tet->p1, *p2=tet->p2, *p3=tet->p3, *p4=tet->p4; if ( PinTr(p2,t) && PinTr(p3,t) && PinTr(p4,t) ) return 1; if ( PinTr(p1,t) && PinTr(p3,t) && PinTr(p4,t) ) return 2; if ( PinTr(p1,t) && PinTr(p2,t) && PinTr(p4,t) ) return 3; if ( PinTr(p1,t) && PinTr(p2,t) && PinTr(p3,t) ) return 4; return 0; } void MESH3:: innerNeighbourAtFace(TET3* td, TR3* t, TET3* neighbourTd) { int noN = faceNoInTd(t,td); if (neighbourTd == 0) cout << "\n\terror in innerNeighbourAtFace: neighbourTd == 0\n"; switch (noN) { case 1 : if (td->n1 != 0) cout << "\n\terror in innerNeighbourAtFace\n"; td->n1 = neighbourTd; return; case 2 : if (td->n2 != 0) cout << "\n\terror in innerNeighbourAtFace\n"; td->n2 = neighbourTd; return; case 3 : if (td->n3 != 0) cout << "\n\terror in innerNeighbourAtFace\n"; td->n3 = neighbourTd; return; case 4 : if (td->n4 != 0) cout << "\n\terror in innerNeighbourAtFace\n"; td->n4 = neighbourTd; return; default: break; } cout << "\n\n dangerous situation in innerNeighbourAtFace\n"; return; } void MESH3:: setNeighbourInTd(TET3* td, PATCH* n, int noOfNeighbour) { switch (noOfNeighbour) { case 1 : td->n1 = n; return; case 2 : td->n2 = n; return; case 3 : td->n3 = n; return; case 4 : td->n4 = n; return; default: cout << "\n\n error in setNeighbourInTd\n"; return; } } void MESH3:: neighbourAtFace(TET3* td, PATCH* N, TR3* t) { TET3 *nb, *nbSon; int no, no1, no2, noN; noN = faceNoInTd(t,td); nb = N->castToTET3(); if ( nb == nil ) // N is boundary face { setNeighbourInTd(td,t,noN); switch (noN) { case 1 : SetTP(td,t,2,3,4); td->boundP=BOUNDARY; return; case 2 : SetTP(td,t,1,4,3); td->boundP=BOUNDARY; return; case 3 : SetTP(td,t,1,2,4); td->boundP=BOUNDARY; return; case 4 : SetTP(td,t,1,3,2); td->boundP=BOUNDARY; return; default: cout << "\n\n error in neighbourAtFace\n"; return; } } nbSon = nb->firstSon; // N is tetrahedron if (nbSon == nil) { setNeighbourInTd(td,nb,noN); if(!nb->mark) { no = faceNoInTd(t,nb); if (no) setNeighbourInTd(nb,td,no); } return; } int iEnd = 0; if (nb->type == T_RED) iEnd = 8; else if (nb->type == T_GREEN_1) iEnd = 2; else if (nb->type == T_GREEN_2A) iEnd = 4; else if (nb->type == T_GREEN_2B) iEnd = 3; else if (nb->type == T_GREEN_3) iEnd = 4; for (int i=1; i<=iEnd; i++) { no1 = faceNoInTd(t,nbSon); if ( no1 ) { if ( nbSon->firstSon != 0 ) { int jEnd = 0; if (nbSon->type == T_RED) jEnd = 8; else if (nbSon->type == T_GREEN_1) jEnd = 2; else if (nbSon->type == T_GREEN_2A) jEnd = 4; else if (nbSon->type == T_GREEN_2B) jEnd = 3; else if (nbSon->type == T_GREEN_3) jEnd = 4; TET3* nbSonSon = nbSon->firstSon; for (int j=1; j<=jEnd; j++) { no2 = faceNoInTd(t,nbSonSon); if ( no2 ) { setNeighbourInTd(nbSonSon,td,no2); setNeighbourInTd(td,nbSonSon,noN); return; } else nbSonSon = nbSonSon->next; } } setNeighbourInTd(nbSon,td,no1); setNeighbourInTd(td,nbSon,noN); return; } else nbSon = nbSon->next; } return; } //------------------------------------------------------------------------- int MESH3:: RefineTdBey(TET3 *td) { TET3 *td1, *td2, *td3, *td4, *td5, *td6, *td7, *td8; TR3 *tr=0, *tr1=0, *tr2=0, *tr3=0, *tr4=0, *it1=0, *it2=0, *it3=0, *it4=0, *it5=0, *it6=0, *it7=0, *it8, *t11=0, *t12=0, *t13=0, *t14=0, *t21=0, *t22=0, *t23=0, *t24=0, *t31=0, *t32=0, *t33=0, *t34=0, *t41=0, *t42=0, *t43=0, *t44=0, *t1, *t2, *t3, *t4; TR3 *trs[1+4]; PT3 *p1 = td->p1,*p2 = td->p2, *p3 = td->p3, *p4 = td->p4, *p5, *p6, *p7, *p8, *p9, *p10; EDG3 *e1 = td->e1, *e2 = td->e2, *e3 = td->e3, *e4 = td->e4, *e5 = td->e5, *e6 = td->e6, *ie1, *ed; PATCH *n1=td->n1, *n2=td->n2, *n3=td->n3, *n4=td->n4; int k; int depth; // Regular refinement of a tetrahedron, Method of J. Bey td->getTriangles(trs); t1=trs[1]; t2=trs[2]; t3=trs[3]; t4=trs[4]; // Get 8 new tetrahedra, 8 new triangles, 1 new edges // return False if not enough space td1 = getTET3(); // new TET3; td2 = getTET3(); td3 = getTET3(); td4 = getTET3(); td5 = getTET3(); td6 = getTET3(); td7 = getTET3(); td8 = getTET3(); noOfTetrahedra += 7; it1 = new TR3; // new TR3; it2 = new TR3; it3 = new TR3; it4 = new TR3; it5 = new TR3; it6 = new TR3; it7 = new TR3; it8 = new TR3; noOfTriangles += 8; ie1 = edgAlloc.Get(); // new EDG3; noOfEdges += 1; if ((td8==0)||(it8==0)||(ie1==0)) { cout << " no memory in RefineTd \n"; return False; } depth = (td->depth) + 1; ie1->depth = depth; if (ie1->depth > edgList.h) // create new list at depth if necessary { DList* edgL = new DList; edgList.push(edgL); } edgList[ie1->depth]->add(ie1); it1->depth = depth; it2->depth = depth; it3->depth = depth; it4->depth = depth; it5->depth = depth; it6->depth = depth; it7->depth = depth; it8->depth = depth; // Set the "son" triangles tik, i=1,2,3,4; k=1,2,3,4; // if neeccessary refine the triangles // Triangle 1 if (!RefineTr(t1)) { cout << " failed in RefineTr called by RefineTd \n"; return False; } setTypeOfInnerEdges(t1); tr1 = t1->firstSon; if (tr1==0) return False; // No space for Refinement // Triangle 2 if (!RefineTr(t2)) { cout << " failed in RefineTr called by RefineTd \n"; return False; } tr2 = t2->firstSon; setTypeOfInnerEdges(t2); if (tr2==0) return False; // No space for Refinement // Triangle 3 if (!RefineTr(t3)) { cout << " failed in RefineTr called by RefineTd \n"; return False; } setTypeOfInnerEdges(t3); tr3 = t3->firstSon; if (tr3==0) return False; /* No space for Refinement */ // Triangle 4 if (!RefineTr(t4)) { cout << " failed in RefineTr called by RefineTd \n"; return False; } setTypeOfInnerEdges(t4); tr4 = t4->firstSon; if (tr4==0) return False; /* No space for Refinement */ p5 = e3->pm; p6 = e5->pm; p7 = e2->pm; p8 = e6->pm; p9 = e4->pm; p10= e1->pm; // one new edge in the octahedron ie1->p1 = p6; ie1->p2 = p10; ie1->pm = 0; // new faces tr = tr1; for (k = 0; k<4; k++) { if (PinTr(p2,tr)) t12 = tr; else if (PinTr(p3,tr)) t13 = tr; else if (PinTr(p4,tr)) t14 = tr; else { t11 = tr; ed = EdinTr(tr,p6,p7); it2->e1 = ed; it7->e1 = ed; ed = EdinTr(tr,p7,p9); it3->e1 = ed; ed = EdinTr(tr,p6,p9); it4->e1 = ed; it8->e2 = ed; } tr = tr->next; } tr = tr2; for (k = 0; k<4; k++) { if (PinTr(p1,tr)) t21 = tr; else if (PinTr(p3,tr)) t23 = tr; else if (PinTr(p4,tr)) t24 = tr; else { t22 = tr; ed = EdinTr(tr,p8,p10); it1->e1 = ed; it6->e1 = ed; ed = EdinTr(tr,p8,p9); it4->e2 = ed; ed = EdinTr(tr,p9,p10); it3->e2 = ed; it8->e1 = ed; } tr = tr->next; } tr = tr3; for (k = 0; k<4; k++) { if (PinTr(p1,tr)) t31 = tr; else if (PinTr(p2,tr)) t32 = tr; else if (PinTr(p4,tr)) t34 = tr; else { t33 = tr; ed = EdinTr(tr,p5,p8); it1->e2 = ed; ed = EdinTr(tr,p6,p8); it4->e3 = ed; it6->e2 = ed; ed = EdinTr(tr,p6,p5); it2->e2 = ed; it5->e2 = ed; } tr = tr->next; } tr = tr4; for (k = 0; k<4; k++) { if (PinTr(p1,tr)) t41 = tr; else if (PinTr(p2,tr)) t42 = tr; else if (PinTr(p3,tr)) t43 = tr; else { t44 = tr; ed = EdinTr(tr,p5,p10); it1->e3 = ed; it5->e1 = ed; ed = EdinTr(tr,p7,p10); it3->e3 = ed; it7->e2 = ed; ed = EdinTr(tr,p5,p7); it2->e3 = ed; } tr = tr->next; } // four new triangles on the octahedron SetTP(it1,0); SetTP(it2,0); SetTP(it3,0); SetTP(it4,0); // four new triangles in the octahedron it5->e3 = ie1; it6->e3 = ie1; it7->e3 = ie1; it8->e3 = ie1; SetTP(it5,0); SetTP(it6,0); SetTP(it7,0); SetTP(it8,0); // Build the new tetrahedra. // tetrahedra generated by chopping off the 4 corners td1->p1 = p1; td1->p2 = p5; td1->p3 = p10; td1->p4 = p8; SetTdPBey(td1,td); SetTdE(td1,it1,t21,t31,t41); neighbourAtFace(td1,n2,t21); neighbourAtFace(td1,n3,t31); neighbourAtFace(td1,n4,t41); td2->p1 = p5; td2->p2 = p2; td2->p3 = p7; td2->p4 = p6; SetTdPBey(td2,td); SetTdE(td2,t12,it2,t32,t42); neighbourAtFace(td2,n1,t12); neighbourAtFace(td2,n3,t32); neighbourAtFace(td2,n4,t42); td3->p1 = p10; td3->p2 = p7; td3->p3 = p3; td3->p4 = p9; SetTdPBey(td3,td); SetTdE(td3,t13,t23,it3,t43); neighbourAtFace(td3,n1,t13); neighbourAtFace(td3,n2,t23); neighbourAtFace(td3,n4,t43); td4->p1 = p8; td4->p2 = p6; td4->p3 = p9; td4->p4 = p4; SetTdPBey(td4,td); SetTdE(td4,t14,t24,t34,it4); neighbourAtFace(td4,n1,t14); neighbourAtFace(td4,n2,t24); neighbourAtFace(td4,n3,t34); // tetrahedra generated by the inner octahedron td5->p1 = p5; td5->p2 = p10; td5->p3 = p8; td5->p4 = p6; SetTdPBey(td5,td); SetTdE(td5,it6,t33,it5,it1); neighbourAtFace(td5,n3,t33); td6->p1 = p5; td6->p2 = p10; td6->p3 = p7; td6->p4 = p6; SetTdPBey(td6,td); SetTdE(td6,it7,it2,it5,t44); neighbourAtFace(td6,n4,t44); td7->p1 = p10; td7->p2 = p8; td7->p3 = p6; td7->p4 = p9; SetTdPBey(td7,td); SetTdE(td7,it4,it8,t22,it6); neighbourAtFace(td7,n2,t22); td8->p1 = p10; td8->p2 = p7; td8->p3 = p6; td8->p4 = p9; SetTdPBey(td8,td); SetTdE(td8,t11,it8,it3,it7); neighbourAtFace(td8,n1,t11); innerNeighbourAtFace(td1,it1,td5); innerNeighbourAtFace(td2,it2,td6); innerNeighbourAtFace(td3,it3,td8); innerNeighbourAtFace(td4,it4,td7); innerNeighbourAtFace(td5,it6,td7); innerNeighbourAtFace(td5,it5,td6); innerNeighbourAtFace(td5,it1,td1); innerNeighbourAtFace(td6,it7,td8); innerNeighbourAtFace(td6,it2,td2); innerNeighbourAtFace(td6,it5,td5); innerNeighbourAtFace(td7,it4,td4); innerNeighbourAtFace(td7,it8,td8); innerNeighbourAtFace(td7,it6,td5); innerNeighbourAtFace(td8,it8,td7); innerNeighbourAtFace(td8,it3,td3); innerNeighbourAtFace(td8,it7,td6); td1->type = T_WHITE; td2->type = T_WHITE; td3->type = T_WHITE; td4->type = T_WHITE; td5->type = T_WHITE; td6->type = T_WHITE; td7->type = T_WHITE; td8->type = T_WHITE; td->firstSon = td1; td->type = T_RED; tetList[tetList.h]->add(td1); tetList[tetList.h]->add(td2); tetList[tetList.h]->add(td3); tetList[tetList.h]->add(td4); tetList[tetList.h]->add(td5); tetList[tetList.h]->add(td6); tetList[tetList.h]->add(td7); tetList[tetList.h]->add(td8); // destruction of the faces delete it1; delete it2; delete it3; delete it4; delete it5; delete it6; delete it7; delete it8; if ( !(t1->onBoundary()) ) { delete t11; delete t12; delete t13; delete t14; } if ( !(t2->onBoundary()) ) { delete t21; delete t22; delete t23; delete t24; } if ( !(t3->onBoundary()) ) { delete t31; delete t32; delete t33; delete t34; } if ( !(t4->onBoundary()) ) { delete t41; delete t42; delete t43; delete t44; } td->returnTriangles(trs); return True; } //------------------------------------------------------------------------- EDG3* MESH3:: findEdgInNeighbour(PT3* p1, PT3* p2, TET3* td) { TET3 *tdSon; EDG3 *e; int iEnd; tdSon = td->firstSon; if (tdSon == nil) { cout << "\n\n error in findEdgInNeighbour: tdSon == nil\n" ; return 0; } iEnd = 8; if (td->type == T_GREEN_2B) iEnd = 3; for (int i=1; i<=iEnd; i++) { e = EdinTet(p1,p2,tdSon); if (e != 0) return e; else tdSon = tdSon->next; } return 0; } //------------------------------------------------------------------------- void MESH3:: setTypeOfInnerEdges(TR3 *t) { TR3 *tSon4; tSon4 = t->firstSon->next->next->next; tSon4->e1->type = T_RED; tSon4->e2->type = T_RED; tSon4->e3->type = T_RED; return; } int MESH3:: RefineTr(TR3 *t) { TR3 *t1, *t2, *t3, *t4; EDG3 *e1 = t->e1, *e2 = t->e2, *e3 = t->e3, *ereg, *ie1,*ie2,*ie3, *e11, *e12, *e21, *e22, *e31, *e32; TET3 *nt; int depth = (t->depth)+1; Bool nbRefined, nbFits; // Get 4 new triangles, 3 new edges, return False if not enough space t1 = new TR3; t2 = new TR3; t3 = new TR3; t4 = new TR3; // Set the "son" edges eik, i=1,2,3; k=1,2; // if neeccessary refine the edges if ((e1->firstSon)==0) /* Edge not refined */ { e11 = RefineEdg(e1); if (e11==0) return False; /* No space for Refinement */ } else e11 = e1->firstSon; /* Take the existing "son" edge */ e12 = e11->next; if ((e11->p1)==(t->p3)) { ereg = e11; e11 = e12; e12 = ereg; } if ((e2->firstSon)==0) { e21 = RefineEdg(e2); if (e21==0) return False; } else e21 = e2->firstSon; e22 = e21->next; if ((e21->p1)==(t->p1)) { ereg = e21; e21 = e22; e22 = ereg; } if ((e3->firstSon)==0) { e31 = RefineEdg(e3); if (e31==0) return False; } else e31 = e3->firstSon; e32 = e31->next; if ((e31->p1)==(t->p2)) { ereg = e31; e31 = e32; e32 = ereg; } ie1 = edgAlloc.Get(); ie2 = edgAlloc.Get(); ie3 = edgAlloc.Get(); if ((t4==0)||(ie3==0)) return False; ie1->depth = ie2->depth = ie3->depth = depth; ie1->boundP = t->boundP; ie2->boundP = t->boundP; ie3->boundP = t->boundP; ie1->classA = t->classA; ie2->classA = t->classA; ie3->classA = t->classA; ie1->isoP = t->isoP; ie2->isoP = t->isoP; ie3->isoP = t->isoP; // Build the new triangles. InnerEdges(t,e1,e2,e3,ie1,ie2,ie3); nt = t->t32; // looking for the second neighbour nbFits = False; nbRefined = False; if ( nt != 0 ) { if ( PinTet(t->p1,nt) && PinTet(t->p2,nt) && PinTet(t->p3,nt) ) nbFits = True; if ( nt->refined() ) nbRefined=True; } if ( nbFits && nbRefined ) { EDG3 *ne1, *ne2, *ne3; ne1 = findEdgInNeighbour(ie1->p1,ie1->p2,nt); ne2 = findEdgInNeighbour(ie2->p1,ie2->p2,nt); ne3 = findEdgInNeighbour(ie3->p1,ie3->p2,nt); edgAlloc.Return(ie1); edgAlloc.Return(ie2); edgAlloc.Return(ie3); ie1=ne1; ie2=ne2; ie3=ne3; } else { noOfEdges += 3; noOfTriangles += 3; if (depth > edgList.h) // create new list at depth if necessary { DList* edgL = new DList; edgList.push(edgL); } edgList[depth]->add(ie1); edgList[depth]->add(ie2); edgList[depth]->add(ie3); } t1->e1 = e32; t1->e2 = e11; t1->e3 = ie1; t2->e1 = e12; t2->e2 = e21; t2->e3 = ie2; t3->e1 = e22; t3->e2 = e31; t3->e3 = ie3; t4->e3 = ie1; t4->e2 = ie3; t4->e1 = ie2; SetTP(t1,t); SetTP(t2,t); SetTP(t3,t); SetTP(t4,t); t->firstSon = t1; t->type = T_RED; t1->next = t2; t2->next = t3, t3->next = t4; t2->prev = t1; t3->prev = t2, t4->prev = t3; if (t->boundP != INTERIOR) { if (depth > trList.h) // create new list at depth if necessary { DList* trL = new DList; trList.push(trL); } trList[depth]->add(t1); trList[depth]->add(t2); trList[depth]->add(t3); trList[depth]->add(t4); // noOfTriangles += 3; } return True; } //------------------------------------------------------------------------- EDG3* MESH3:: RefineEdg(EDG3 *ed) { EDG3 *e1, *e2; PT3 *pm = 0; int depth; // Refinement of an edge. // -- Get two new edges; return False if not enough space e1 = edgAlloc.Get(); e2 = edgAlloc.Get(); if (e2==0) return 0; noOfEdges++; pm = ptAlloc.Get(); pm->reset(); noOfPoints++; // Call the user midpoint routine and set the new fields pm->classA = ed->classA; pm->boundP = ed->boundP; pm->depth = ed->depth + 1; if ( (ed->isoP == CIRCULAR) && (ed->boundP != INTERIOR) ) setXYZpmCircle(pm, ed); else if ( (ed->boundP != INTERIOR) && (ed->isoP == CYLINDRICAL) ) setXYZpmCyl(pm, ed); else { pm->x = HALF*(ed->p1->x + ed->p2->x); pm->y = HALF*(ed->p1->y + ed->p2->y); pm->z = HALF*(ed->p1->z + ed->p2->z); } e1->p1 = ed->p1; e1->p2 = pm; e1->boundP = ed->boundP; e1->father = ed; e1->type = ed->type; e2->p1 = pm; e2->p2 = ed->p2; e2->boundP = ed->boundP; e2->father = ed; e2->type = ed->type; e1->classA = e2->classA = ed->classA; e1->isoP = e2->isoP = ed->isoP; ed->firstSon = e1; ed->pm =pm; e1->depth = e2->depth = ed->depth+1; depth = e1->depth; if (depth > edgList.h) // create new list at depth if necessary { DList* edgL = new DList; edgList.push(edgL); } edgList[depth]->add(e1); edgList[depth]->add(e2); if (pm->depth > ptList.h) { DList* ptL = new DList; ptList.push(ptL); } ptList[pm->depth]->add(pm); return e1; } //------------------------------------------------------------------------- void MESH3:: SetTP(TR3 *t,TR3 *f) { PT3 *P11 = (t->e1)->p1, *P12 = (t->e1)->p2, *P21 = (t->e2)->p1, *P22 = (t->e2)->p2, *P31 = (t->e3)->p1, *P32 = (t->e3)->p2; // set the points of a triangle, computed from the edges t->p1 = ((P31==P11)||(P31==P12))?P32:P31; t->p2 = ((P11==P21)||(P11==P22))?P12:P11; t->p3=((P21==P31)||(P21==P32))?P22:P21; t->father = f; if (f!=0) { t->depth = (f->depth)+1; t->classA = f->classA; t->isoP = f->isoP; t->boundP = f->boundP; } else t->boundP = INTERIOR; if ( (t->depth) > maxDepth ) maxDepth = t->depth; return; } //------------------------------------------------------------------------- void MESH3:: SetTP(TET3 *tet, TR3 *t, int noP1, int noP2, int noP3) { PT3 *tetPts[1+4]; tet->getPoints(tetPts); EDG3 *e1 = t->e1, *e2 = t->e2, *e3 = t->e3; PT3 *P11 = e1->p1, *P12 = e1->p2, *P21 = e2->p1, *P22 = e2->p2, *P31 = e3->p1, *P32 = e3->p2; t->p1 = tetPts[noP1]; t->p2 = tetPts[noP2]; t->p3 = tetPts[noP3]; if( (P11!=t->p1) && (P12!=t->p1) ) t->e1 = e1; else if( (P21!=t->p1) && (P22!=t->p1) ) t->e1 = e2; else if( (P31!=t->p1) && (P32!=t->p1) ) t->e1 = e3; if( (P11!=t->p2) && (P12!=t->p2) ) t->e2 = e1; else if( (P21!=t->p2) && (P22!=t->p2) ) t->e2 = e2; else if( (P31!=t->p2) && (P32!=t->p2) ) t->e2 = e3; if( (P11!=t->p3) && (P12!=t->p3) ) t->e3 = e1; else if( (P21!=t->p3) && (P22!=t->p3) ) t->e3 = e2; else if( (P31!=t->p3) && (P32!=t->p3) ) t->e3 = e3; return; } //------------------------------------------------------------------------- void TET3:: completeT(TR3 *t,TR3 *ft) const { /* PT3 *P11 = (t->e1)->p1, *P12 = (t->e1)->p2, *P21 = (t->e2)->p1, *P22 = (t->e2)->p2, *P31 = (t->e3)->p1, *P32 = (t->e3)->p2; t->p1 = ((P31==P11)||(P31==P12))?P32:P31; t->p2 = ((P11==P21)||(P11==P22))?P12:P11; t->p3=((P21==P31)||(P21==P32))?P22:P21; */ t->father = ft; if (ft!=0) { t->depth = (ft->depth)+1; t->classA = ft->classA; t->isoP = ft->isoP; t->boundP = ft->boundP; } else t->boundP = INTERIOR; return; } //------------------------------------------------------------------------- int MESH3:: TdVolume(TET3 *tet) { Real x1, x2, x3, y1, y2, y3, z1, z2, z3; Real det; PT3 *P1, *P2, *P3, *P4; // computes the Jacobian and the orientation of the edges P1 = tet->p1; P2 = tet->p2; P3 = tet->p3; P4 = tet->p4; x1 = (P2->x) - (P1->x); x2 = (P2->y) - (P1->y); x3 = (P2->z) - (P1->z); y1 = (P3->x) - (P1->x); y2 = (P3->y) - (P1->y); y3 = (P3->z) - (P1->z); z1 = (P4->x) - (P1->x); z2 = (P4->y) - (P1->y); z3 = (P4->z) - (P1->z); det = x1*(y2*z3 - y3*z2) - x2*(y1*z3 -y3*z1) + x3*(y1*z2 - y2*z1); tet->detJ = det; // the volume of the td: fabs(det)*SIXTH ; return tet->orient(); } //------------------------------------------------------------------------- void MESH3:: SetTdP(TET3 *td, TR3* t1, TR3* t2, TR3* t3, TR3* t4, TET3 *f) { PT3 *P11 = t1->p1, *P12 = t1->p2, *P13 = t1->p3, *P21 = t2->p1, *P22 = t2->p2, *P23 = t2->p3, *P31 = t3->p1, *P32 = t3->p2, *P33 = t3->p3, *P41 = t4->p1, *P42 = t4->p2, *P43 = t4->p3; PT3 *P2, *P3; // set the points of a tetrahedron td, computed from the faces; // td inherits properties of its father f if ((P31!=P11)&&(P31!=P12)&&(P31!=P13)) td->p1 = P31; else if ((P32!=P11)&&(P32!=P12)&&(P32!=P13)) td->p1 = P32; else td->p1 = P33; if ((P41!=P21)&&(P41!=P22)&&(P41!=P23)) td->p2 = P41; else if ((P42!=P21)&&(P42!=P22)&&(P42!=P23)) td->p2 = P42; else td->p2 = P43; if ((P11!=P31)&&(P11!=P32)&&(P11!=P33)) td->p3 = P11; else if ((P12!=P31)&&(P12!=P32)&&(P12!=P33)) td->p3 = P12; else td->p3 = P13; if ((P21!=P41)&&(P21!=P42)&&(P21!=P43)) td->p4 = P21; else if ((P22!=P41)&&(P22!=P42)&&(P22!=P43)) td->p4 = P22; else td->p4 = P23; TdVolume(td); if (rightHand) { P2 = td->p2; P3 = td->p3; if (!(td->orient())) { td->p2 = P3; td->p3 = P2; td->detJ = Abs(td->detJ); // td->orient = True; } } td->n1 = nil; td->n2 = nil; td->n3 = nil; td->n4 = nil; td->father = f; if (f!=0) { td->depth = f->depth +1; td->classA = f->classA; } if (td->depth > maxDepth) maxDepth = td->depth; return; } //------------------------------------------------------------------------- void MESH3:: SetTdPBey(TET3 *td,TET3 *f) { // set the points of a tetrahedron td, computed from the faces; // td inherits properties of its father f TdVolume(td); td->n1 = nil; td->n2 = nil; td->n3 = nil; td->n4 = nil; td->father = f; if (f!=0) { td->depth = (f->depth)+1; td->classA = f->classA; } if ( (td->depth)> maxDepth ) maxDepth = td->depth; return; } //------------------------------------------------------------------------- void MESH3:: SetTPts(TET3 *td, TET3 *f) { PT3 *P2, *P3; // computes volume and orientation in the tetrahedron td; // td inherits properties of its father f TdVolume(td); // determinant if (rightHand) { P2 = td->p2; P3 = td->p3; if (!(td->orient())) { td->p2 = P3; td->p3 = P2; td->detJ = Abs(td->detJ); // td->orient() = True; } } td->father = f; if (f != 0) { td->depth = (f->depth)+1; td->classA = f->classA; } if ( (td->depth)> maxDepth ) maxDepth = td->depth; return; } //------------------------------------------------------------------------- EDG3* MESH3:: FindTdE(TET3 */*td*/,TR3 *t1,TR3 *t2,TR3 *t3,TR3 *t4,PT3 *p1,PT3 *p2) { EDG3 *E11, *E12, *E13, *E21, *E22, *E23, *E31, *E32, *E33, *E41, *E42, *E43; E11 = t1->e1; if ( ((E11->p1==p1)&&(E11->p2==p2))||((E11->p1==p2)&&(E11->p2==p1))) return E11; E12 = t1->e2; if ( ((E12->p1==p1)&&(E12->p2==p2))||((E12->p1==p2)&&(E12->p2==p1))) return E12; E13 = t1->e3; if ( ((E13->p1==p1)&&(E13->p2==p2))||((E13->p1==p2)&&(E13->p2==p1))) return E13; E21 = t2->e1; if ( ((E21->p1==p1)&&(E21->p2==p2))||((E21->p1==p2)&&(E21->p2==p1))) return E21; E22 = t2->e2; if ( ((E22->p1==p1)&&(E22->p2==p2))||((E22->p1==p2)&&(E22->p2==p1))) return E22; E23 = t2->e3; if ( ((E23->p1==p1)&&(E23->p2==p2))||((E23->p1==p2)&&(E23->p2==p1))) return E23; E31 = t3->e1; if ( ((E31->p1==p1)&&(E31->p2==p2))||((E31->p1==p2)&&(E31->p2==p1))) return E31; E32 = t3->e2; if ( ((E32->p1==p1)&&(E32->p2==p2))||((E32->p1==p2)&&(E32->p2==p1))) return E32; E33 = t3->e3; if ( ((E33->p1==p1)&&(E33->p2==p2))||((E33->p1==p2)&&(E33->p2==p1))) return E33; E41 = t4->e1; if ( ((E41->p1==p1)&&(E41->p2==p2))||((E41->p1==p2)&&(E41->p2==p1))) return E41; E42 = t4->e2; if ( ((E42->p1==p1)&&(E42->p2==p2))||((E42->p1==p2)&&(E42->p2==p1))) return E42; E43 = t4->e3; if ( ((E43->p1==p1)&&(E43->p2==p2))||((E43->p1==p2)&&(E43->p2==p1))) return E43; return 0; } //------------------------------------------------------------------------- void MESH3:: SetTdE(TET3 *td,TR3 *t1,TR3 *t2,TR3 *t3,TR3 *t4) { PT3 *P1 = td->p1, *P2 = td->p2, *P3 = td->p3, *P4 = td->p4; // set the edges of a tetrahedron td td->e1 = FindTdE(td,t1,t2,t3,t4,P1,P3); td->e2 = FindTdE(td,t1,t2,t3,t4,P2,P3); td->e3 = FindTdE(td,t1,t2,t3,t4,P1,P2); td->e4 = FindTdE(td,t1,t2,t3,t4,P3,P4); td->e5 = FindTdE(td,t1,t2,t3,t4,P2,P4); td->e6 = FindTdE(td,t1,t2,t3,t4,P1,P4); return; } //------------------------------------------------------------------------- void MESH3:: InnerEdges(TR3 *t,EDG3 *e1,EDG3 *e2,EDG3 *e3,EDG3 *ie1, EDG3 *ie2,EDG3 *ie3) { // sets the points of the inner edges *ie1,*ie2,*ie3; // Edges of the triangle t to be refined: *e1,*e2,*e3 ie1->p1 = e1->pm; ie1->p2 = e3->pm; ie1->type = T_GREEN_3; ie1->classA = t->classA; // !!! ie1->isoP = t->isoP; ie1->boundP = t->boundP; ie2->p1 = e2->pm; ie2->p2 = e1->pm; ie2->type = T_GREEN_3; ie2->classA = t->classA; ie2->isoP = t->isoP; ie2->boundP = t->boundP; ie3->p1 = e3->pm; ie3->p2 = e2->pm; ie3->type = T_GREEN_3; ie3->classA = t->classA; ie3->isoP = t->isoP; ie3->boundP = t->boundP; return; } //------------------------------------------------------------------------- int MESH3:: MkGreen(TR3 *t) { PT3 *p1, *p2; EDG3 *e1 = t->e1,*e2 = t->e2,*e3 = t->e3, *eNew=0; TR3 *t1New=0, *t2New=0; TET3 *nt; int depth; Bool nbRefined, nbFits; // generates two green triangles as sons of t if (t->firstSon != 0) return True; // Testing if one neighbor triangle is refined and setting pi, ei // corresponding to this neighbor if ( (e1->type == T_GREEN_1) || (e2->type == T_GREEN_1) || (e3->type == T_GREEN_1) ) cout << "Alarm in MkGreen: one edge already green \n"; if ((e1->firstSon)!=0) { p1 = t->p1; p2 = t->p2; e1 = t->e1; e2 = t->e2; e3 = t->e3; } else { if ((e2->firstSon)!=0) { p1 = t->p2; p2 = t->p3; e1 = t->e2; e2 = t->e3; e3 = t->e1; } else { if ((e3->firstSon)!=0) { p1 = t->p3; p2 = t->p1; e1 = t->e3; e2 = t->e1; e3 = t->e2; } else return True; /* nothing to refine */ } } // Get one new edge and two new triangles eNew = edgAlloc.Get(); t1New = new TR3; t2New = new TR3; // Set the fields for the new objects eNew->p1 = p1; eNew->p2 = (e1->firstSon)->p2; nt = t->t32; // looking for the second neighbour nbFits = False; nbRefined = False; if ( nt != 0 ) { if ( PinTet(t->p1,nt) && PinTet(t->p2,nt) && PinTet(t->p3,nt) ) nbFits = True; if ( nt->refined() ) nbRefined=True; } if ( nbFits && nbRefined ) { EDG3 *ne1; ne1 = findEdgInNeighbour(eNew->p1,eNew->p2,nt); edgAlloc.Return(eNew); eNew=ne1; } else { noOfEdges++; noOfTriangles++; eNew->type = T_GREEN_1; eNew->classA = t->classA; eNew->isoP = t->isoP; eNew->boundP = t->boundP; depth = t->depth+1; eNew->depth = depth; if (depth > edgList.h) // create new list at depth if necessary { DList* edgL = new DList; edgList.push(edgL); } edgList[depth]->add(eNew); } t1New->e1 = e3; t1New->e3 = eNew; t1New->type = T_GREEN_1; t2New->e1 = e2; t2New->e2 = eNew; t2New->type = T_GREEN_1; if ((e1->p1)==p2) // test for orientation { t1New->e2 = e1->firstSon; t2New->e3 = (e1->firstSon)->next; } else { t1New->e2 = (e1->firstSon)->next; t2New->e3 = e1->firstSon; } SetTP(t1New,t); SetTP(t2New,t); t->firstSon = t1New; t->type = T_GREEN_1; // Append two new ones at their depth list depth = t1New->depth; t1New->next = t2New; t2New->prev = t1New; if (t->boundP != INTERIOR) { if ( depth > trList.h ) // create new list at depth if necessary { DList* trL = new DList; trList.push(trL); } trList[depth]->add(t1New); trList[depth]->add(t2New); // noOfTriangles++; } return True; } //------------------------------------------------------------------------- int MESH3:: MkGreenIrr(TR3 *t) { TR3 *t1=0, *t2=0, *t3=0; EDG3 *e1 = t->e1, *e2 = t->e2, *e3 = t->e3, *ereg, *ie1=0,*ie2=0, *e11=0, *e12=0, *e21=0, *e22=0, *e31=0, *e32=0; TET3 *nt; int depth; Bool nbFits, nbRefined, edgeChanged=False; //cout << "\n MkGreenIrr \n"; // generates three green triangles as sons of t if (t->firstSon != 0) return True; // Get 3 new triangles, 2 new edges t1 = new TR3; t2 = new TR3; t3 = new TR3; ie1 = edgAlloc.Get(); ie2 = edgAlloc.Get(); ie1->depth = t->depth+1; ie2->depth = t->depth+1; ie1->next = ie2; ie2->prev = ie1; // boundary value on the new triangles and edges ie1->boundP = t->boundP; ie1->type = T_GREEN_2B; ie1->classA = t->classA; ie1->isoP = t->isoP; ie2->boundP = t->boundP; ie2->type = T_GREEN_2B; ie2->classA = t->classA; ie2->isoP = t->isoP; // Set the "son" edges eik, i=1,2,3; k=1,2; // if neeccessary refine the edges nt = t->t32; // looking for the second neighbour nbFits = False; nbRefined = False; if ( nt != 0 ) { if ( PinTet(t->p1,nt) && PinTet(t->p2,nt) && PinTet(t->p3,nt) ) nbFits = True; if ( nt->refined() ) nbRefined=True; } if ((e1->firstSon)==0) /* Edge e1 not refined */ { ie1->p1 = e3->pm; ie1->p2 = e2->pm; ie2->p1 = e3->pm; ie2->p2 = t->p3; if ( nbFits && nbRefined ) { EDG3 *ne1, *ne2; ne1 = findEdgInNeighbour(ie1->p1,ie1->p2,nt); ne2 = findEdgInNeighbour(ie2->p1,ie2->p2,nt); if ( ne2 == 0 ) { ie2->p1 = e2->pm; ie2->p2 = t->p2; ne2 = findEdgInNeighbour(ie2->p1,ie2->p2,nt); edgeChanged = True; } edgAlloc.Return(ie1); edgAlloc.Return(ie2); ie1=ne1; ie2=ne2; } else { noOfEdges += 2; noOfTriangles += 2; depth = ie1->depth; if (depth > edgList.h) // create new list at depth if necessary { DList* edgL = new DList; edgList.push(edgL); } edgList[depth]->add(ie1); edgList[depth]->add(ie2); } e21 = e2->firstSon; e22 = e21->next; if ( (e21->p1) == (t->p3) ) {ereg=e21; e21 = e22; e22 = ereg;} e31 = e3->firstSon; e32 = e31->next; if ( (e31->p1) == (t->p2) ) {ereg=e31; e31 = e32; e32 = ereg;} if (edgeChanged) { EDG3* e = e22; e22 = e32; e32 = e;} t1->e1 = e31; t1->e2 = ie1; t1->e3 = e21; t2->e1 = e1; t2->e2 = ie2; t2->e3 = e32; t3->e1 = ie1; t3->e2 = ie2; t3->e3 = e22; } else if ((e2->firstSon)==0) /* Edge e2 not refined */ { ie1->p1 = e1->pm; ie1->p2 = e3->pm; ie2->p1 = e1->pm; ie2->p2 = t->p1; if ( nbFits && nbRefined ) { EDG3 *ne1, *ne2; ne1 = findEdgInNeighbour(ie1->p1,ie1->p2,nt); ne2 = findEdgInNeighbour(ie2->p1,ie2->p2,nt); if ( ne2 == 0 ) { ie2->p1 = e3->pm; ie2->p2 = t->p3; ne2 = findEdgInNeighbour(ie2->p1,ie2->p2,nt); edgeChanged = True; } edgAlloc.Return(ie1); edgAlloc.Return(ie2); ie1=ne1; ie2=ne2; } else { noOfEdges += 2; noOfTriangles += 2; depth = ie1->depth; if (depth > edgList.h) // create new list at depth if necessary { DList* edgL = new DList; edgList.push(edgL); } edgList[depth]->add(ie1); edgList[depth]->add(ie2); } e11 = e1->firstSon; e12 = e11->next; if ( (e11->p1) == (t->p3) ) {ereg=e11; e11 = e12; e12 = ereg;} e31 = e3->firstSon; e32 = e31->next; if ( (e31->p1) == (t->p2) ) {ereg=e31; e31 = e32; e32 = ereg;} if (edgeChanged) { EDG3* e = e12; e12 = e31; e31 = e;} t1->e1 = e32; t1->e2 = e11; t1->e3 = ie1; t2->e1 = e12; t2->e2 = e2; t2->e3 = ie2; t3->e1 = e31; t3->e2 = ie1; t3->e3 = ie2; } else if ((e3->firstSon)==0) /* Edge e3 not refined */ { ie1->p1 = e2->pm; ie1->p2 = e1->pm; ie2->p1 = e2->pm; ie2->p2 = t->p2; if ( nbFits && nbRefined ) { EDG3 *ne1, *ne2; ne1 = findEdgInNeighbour(ie1->p1,ie1->p2,nt); ne2 = findEdgInNeighbour(ie2->p1,ie2->p2,nt); if ( ne2 == 0 ) { ie2->p1 = e1->pm; ie2->p2 = t->p1; ne2 = findEdgInNeighbour(ie2->p1,ie2->p2,nt); edgeChanged = True; } edgAlloc.Return(ie1); edgAlloc.Return(ie2); ie1=ne1; ie2=ne2; } else { noOfEdges += 2; noOfTriangles += 2; depth = ie1->depth; if (depth > edgList.h) // create new list at depth if necessary { DList* edgL = new DList; edgList.push(edgL); } edgList[depth]->add(ie1); edgList[depth]->add(ie2); } e11 = e1->firstSon; e12 = e11->next; if ( (e11->p1) == (t->p3) ) {ereg=e11; e11 = e12; e12 = ereg;} e21 = e2->firstSon; e22 = e21->next; if ( (e21->p1) == (t->p3) ) {ereg=e21; e21 = e22; e22 = ereg;} if (edgeChanged) { EDG3* e = e11; e11 = e21; e21 = e;} t1->e1 = e12; t1->e2 = e22; t1->e3 = ie1; t2->e1 = ie2; t2->e2 = e21; t2->e3 = e3; t3->e1 = e11; t3->e2 = ie1; t3->e3 = ie2; } // Build the new triangles. t1->type = T_GREEN_2B; SetTP(t1,t); t2->type = T_GREEN_2B; SetTP(t2,t); t3->type = T_GREEN_2B; SetTP(t3,t); t->firstSon = t1; t->type = T_GREEN_2B; // Append two new ones at their depth list depth = t1->depth; t1->next = t2; t2->next = t3; t2->prev = t1; t3->prev = t2; if (t->boundP != INTERIOR) { if (depth > trList.h) // create new list at depth if necessary { DList* trL = new DList; trList.push(trL); } trList[depth]->add(t1); trList[depth]->add(t2); trList[depth]->add(t3); // noOfTriangles += 2; } return True; } //------------------------------------------------------------------------ int MESH3:: MarkGreenTd(TET3 *td) { EDG3 *eds[1+6], *ed; TR3 *trs[1+4]; int i, noOfRefEdg = 0; // marks green tetrahedra to be refined if ( (td->type) != T_WHITE ) cout << " Alarm in MarkGreenTd: td not white \n"; td->getEdges(eds); for (i=1; i<=6; i++) { ed = eds[i]; if ( (ed->firstSon) != 0 ) noOfRefEdg++; } if ( noOfRefEdg == 1) { td->mark = T_GREEN_1; moreGreen1Td++; } else if ( noOfRefEdg == 2) { td->mark = T_GREEN_2A; moreGreen2ATd++; td->getTriangles(trs); for ( i=1; i <= 4; i++) { if ( TestFace(trs[i]) == 2 ) { td->mark = T_GREEN_2B; moreGreen2ATd--; moreGreen2BTd++; } } td->returnTriangles(trs); } else if ( noOfRefEdg == 3) { td->mark = T_GREEN_3; moreGreen3Td++; } else td->mark = False; return True; } //------------------------------------------------------------------------- int MESH3:: MkGreen1Td(TET3 *td) { PT3 *p1=0, *p2=0, *p3=0, *p4=0, *pm=0; TR3 *t=0, *t1=0, *t2=0, *t3=0, *t4=0; TR3 *t1New=0, *t21=0, *t22=0, *t41=0, *t42=0; TR3 *trs[1+4]; TET3 *td1,*td2; PATCH *n1=0, *n2=0, *n3=0, *n4=0; EDG3 *e1=td->e1,*e2=td->e2,*e3=td->e3,*e4=td->e4, *e5=td->e5, *e6=td->e6; EDG3 *ed, *e1New=0, *e2New=0, *e3New=0; int refEdges=0, depth = (td->depth)+1; // refinement of td into two green tetrahedra if (td->mark == T_GREEN_1) td->mark = False; else return True; td->getTriangles(trs); // Get one new triangle and two tetrahedra, // if not enough space: return False t1New = new TR3; noOfTriangles++; t1New->depth = depth; td1 = getTET3(); td2 = getTET3(); noOfTetrahedra++; // Testing which edge is refined ed = e1; if ( (ed->firstSon)!=0 ) { refEdges +=1; p1=td->p1; p2=td->p2; p3=td->p3; p4=td->p4; pm = ed->pm; e3New = e5; t1 = trs[1]; t2 = trs[2]; t3 = trs[3]; t4 = trs[4]; n1 = td->n1; n2 = td->n2; n3 = td->n3; n4 = td->n4; } ed = e2; if ( (ed->firstSon)!=0 ) { refEdges +=1; if (refEdges > 1 ) { cout << "\n\n alarm in MkGreenI \n"; return False; } p1=td->p3; p2=td->p1; p3=td->p2; p4=td->p4; pm = ed->pm; e3New = e6; t1 = trs[3]; t2 = trs[1]; t3 = trs[2]; t4 = trs[4]; n1 = td->n3; n2 = td->n1; n3 = td->n2; n4 = td->n4; } ed = e3; if ( (ed->firstSon)!=0 ) { refEdges +=1; if (refEdges > 1 ) { cout << "\n\n alarm in MkGreenI \n"; return False; } p1=td->p2; p2=td->p3; p3=td->p1; p4=td->p4; pm = ed->pm; e3New = e4; t1 = trs[2]; t2 = trs[3]; t3 = trs[1]; t4 = trs[4]; n1 = td->n2; n2 = td->n3; n3 = td->n1; n4 = td->n4; } ed = e4; if ( (ed->firstSon)!=0 ) { refEdges +=1; if (refEdges > 1 ) { cout << "\n\n alarm in MkGreenI \n"; return False; } p1=td->p4; p2=td->p1; p3=td->p3; p4=td->p2; pm = ed->pm; e3New = e3; t1 = trs[4]; t2 = trs[1]; t3 = trs[3]; t4 = trs[2]; n1 = td->n4; n2 = td->n1; n3 = td->n3; n4 = td->n2; } ed = e5; if ( (ed->firstSon)!=0 ) { refEdges +=1; if (refEdges > 1 ) { cout << "\n\n alarm in MkGreenI \n"; return False; } p1=td->p2; p2=td->p3; p3=td->p4; p4=td->p1; pm = ed->pm; e3New = e1; t1 = trs[2]; t2 = trs[3]; t3 = trs[4]; t4 = trs[1]; n1 = td->n2; n2 = td->n3; n3 = td->n4; n4 = td->n1; } ed = e6; if ( (ed->firstSon)!=0 ) { refEdges +=1; if (refEdges > 1 ) { cout << "\n\n alarm in MkGreenI \n"; return False; } p1=td->p1; p2=td->p3; p3=td->p4; p4=td->p2; pm = ed->pm; e3New = e2; t1 = trs[1]; t2 = trs[3]; t3 = trs[4]; t4 = trs[2]; n1 = td->n1; n2 = td->n3; n3 = td->n4; n4 = td->n2; } // Set the fields for the new objects MkGreen(t2); t = t2->firstSon; if ( PinTr(p1,t) ) { t21 = t; t22 = t->next; } else { t22 = t; t21 = t->next; } e1New = EdinTr(t,p4,pm); MkGreen(t4); t = t4->firstSon; if ( PinTr(p1,t) ) { t41 = t; t42 = t->next; } else { t42 = t; t41 = t->next; } e2New = EdinTr(t,p2,pm); t1New->e1 = e1New; t1New->e2 = e2New; t1New->e3 = e3New; SetTP(t1New,0); t1New->type = T_GREEN_3; SetTdP(td1,t21,t3,t41,t1New,td); SetTdE(td1,t21,t3,t41,t1New); neighbourAtFace(td1,n2,t21); neighbourAtFace(td1,n3,t3); neighbourAtFace(td1,n4,t41); td1->type = T_GREEN_1; SetTdP(td2,t22,t1,t42,t1New,td); SetTdE(td2,t22,t1,t42,t1New); neighbourAtFace(td2,n2,t22); neighbourAtFace(td2,n1,t1); neighbourAtFace(td2,n4,t42); td2->type = T_GREEN_1; innerNeighbourAtFace(td1,t1New,td2); innerNeighbourAtFace(td2,t1New,td1); td->firstSon = td1; td->type = T_GREEN_1; tetList[tetList.h]->add(td1); tetList[tetList.h]->add(td2); // destruction of the faces delete t1New; if ( !(t2->onBoundary()) ) { delete t21; delete t22; } if ( !(t4->onBoundary()) ) { delete t41; delete t42; } td->returnTriangles(trs); return True; } //------------------------------------------------------------------------- int MESH3:: MkGreen2ATd(TET3 *td) { PT3 *p1=0, *p2=0, *p3=0, *p4=0, *pm1=0, *pm2=0; TR3 *t=0, *t1=0, *t2=0, *t3=0, *t4=0; TR3 *t1New=0, *t2New=0, *t3New=0, *t4New=0; TR3 *t11=0, *t12=0, *t21=0, *t22=0, *t31=0, *t32=0, *t41=0, *t42=0; TR3 *trs[1+4]; TET3 *td1=0, *td2=0, *td3=0, *td4=0; PATCH *n1=0, *n2=0, *n3=0, *n4=0; EDG3 *e1=td->e1,*e2=td->e2,*e3=td->e3,*e4=td->e4, *e5=td->e5, *e6=td->e6; EDG3 *ed, *edNew=0; EDG3 *e1New, *e2New, *e3New, *e4New, *e5New, *e6New, *e7New, *e8New; int refEdges, depth = (td->depth)+1; // Refinement of td into four green tetrahedra if ( (td->mark == T_GREEN_2A) ) td->mark = False; else return True; td->getTriangles(trs); // Get one new edge, four new triangles and four tetrahedra, // if not enough space: return False edNew = edgAlloc.Get(); noOfEdges += 1; edNew->depth = depth; if (depth > edgList.h) // create new list at depth if necessary { DList* edgL = new DList; edgList.push(edgL); } edgList[depth]->add(edNew); t1New = new TR3; t2New = new TR3; t3New = new TR3; t4New = new TR3; noOfTriangles += 4; td1 = getTET3(); td2 = getTET3(); td3 = getTET3(); td4 = getTET3(); noOfTetrahedra += 3; // Test which edge is refined refEdges = 0; ed = e1; if ( (ed->firstSon)!=0 ) { refEdges++; p1=td->p1; p2=td->p2; p3=td->p3; p4=td->p4; pm1 = e1->pm; pm2 = e5->pm; t1 = trs[1]; t2 = trs[2]; t3 = trs[3]; t4 = trs[4]; n1 = td->n1; n2 = td->n2; n3 = td->n3; n4 = td->n4; } ed = e2; if ( (ed->firstSon)!=0 ) { refEdges++; if ( refEdges > 1) cout << "Alarm in MkGreen2AT3 \n"; p1=td->p3; p2=td->p1; p3=td->p2; p4=td->p4; pm1 = e2->pm; pm2 = e6->pm; t1 = trs[3]; t2 = trs[1]; t3 = trs[2]; t4 = trs[4]; n1 = td->n3; n2 = td->n1; n3 = td->n2; n4 = td->n4; } ed = e3; if ( (ed->firstSon)!=0 ) { refEdges++; if ( refEdges > 1) cout << "Alarm in MkGreen2AT3 \n"; p1=td->p2; p2=td->p3; p3=td->p1; p4=td->p4; pm1 = e3->pm; pm2 = e4->pm; t1 = trs[2]; t2 = trs[3]; t3 = trs[1]; t4 = trs[4]; n1 = td->n2; n2 = td->n3; n3 = td->n1; n4 = td->n4; } // Set the fields for the new objects MkGreen(t1); t = t1->firstSon; if ( PinTr(p4,t) ) { t11 = t; t12 = t->next; } else { t12 = t; t11 = t->next; } MkGreen(t2); t = t2->firstSon; if ( PinTr(p1,t) ) { t21 = t; t22 = t->next; } else { t22 = t; t21 = t->next; } MkGreen(t3); t = t3->firstSon; if ( PinTr(p2,t) ) { t31 = t; t32 = t->next; } else { t32 = t; t31 = t->next; } MkGreen(t4); t = t4->firstSon; if ( PinTr(p3,t) ) { t41 = t; t42 = t->next; } else { t42 = t; t41 = t->next; } edNew->p1 = pm1; edNew->p2 = pm2; edNew->pm = 0; edNew->type = T_GREEN_2A; e1New = EdinTr(t12,p2,pm2); e2New = EdinTr(t22,p4,pm1); e3New = EdinTr(t11,p4,pm2); e4New = EdinTr(t41,p2,pm1); e5New = EdinTr(t11,p3,pm2); e6New = EdinTr(t22,p3,pm1); e7New = EdinTr(t32,p1,pm2); e8New = EdinTr(t21,p1,pm1); t1New->e1 = edNew; t1New->e2 = e2New; t1New->e3 = e3New; SetTP(t1New,0); t1New->type = T_GREEN_2A; t2New->e1 = e1New; t2New->e2 = e4New; t2New->e3 = edNew; SetTP(t2New,0); t2New->type = T_GREEN_2A; t3New->e1 = edNew; t3New->e2 = e5New; t3New->e3 = e6New; SetTP(t3New,0); t3New->type = T_GREEN_2A; t4New->e1 = edNew; t4New->e2 = e7New; t4New->e3 = e8New; SetTP(t4New,0); t4New->type = T_GREEN_2A; SetTdP(td1,t11,t22,t1New,t3New,td); SetTdE(td1,t11,t22,t1New,t3New); neighbourAtFace(td1,n1,t11); neighbourAtFace(td1,n2,t22); td1->type = T_GREEN_2A; SetTdP(td2,t12,t2New,t41,t3New,td); SetTdE(td2,t12,t2New,t41,t3New); neighbourAtFace(td2,n1,t12); neighbourAtFace(td2,n4,t41); td2->type = T_GREEN_2A; SetTdP(td3,t32,t21,t1New,t4New,td); SetTdE(td3,t32,t21,t1New,t4New); neighbourAtFace(td3,n3,t32); neighbourAtFace(td3,n2,t21); td3->type = T_GREEN_2A; SetTdP(td4,t31,t42,t2New,t4New,td); SetTdE(td4,t31,t42,t2New,t4New); neighbourAtFace(td4,n4,t42); neighbourAtFace(td4,n3,t31); td4->type = T_GREEN_2A; innerNeighbourAtFace(td1,t1New,td3); innerNeighbourAtFace(td1,t3New,td2); innerNeighbourAtFace(td2,t2New,td4); innerNeighbourAtFace(td2,t3New,td1); innerNeighbourAtFace(td3,t1New,td1); innerNeighbourAtFace(td3,t4New,td4); innerNeighbourAtFace(td4,t2New,td2); innerNeighbourAtFace(td4,t4New,td3); td->firstSon = td1; td->type = T_GREEN_2A; tetList[tetList.h]->add(td1); tetList[tetList.h]->add(td2); tetList[tetList.h]->add(td3); tetList[tetList.h]->add(td4); // destruction of the faces delete t1New; delete t2New; delete t3New; delete t4New; if ( !(t1->onBoundary()) ) { delete t11; delete t12; } if ( !(t2->onBoundary()) ) { delete t21; delete t22; } if ( !(t3->onBoundary()) ) { delete t31; delete t32; } if ( !(t4->onBoundary()) ) { delete t41; delete t42; } td->returnTriangles(trs); return True; } //------------------------------------------------------------------------- int MESH3:: MkGreen2BTd(TET3 *td) { PT3 *p1=0, *p2=0, *p3=0, *p4=0; TR3 *t=0, *t1=0, *t2=0, *t3=0, *t4=0; TR3 *trs[1+4]; TR3 *t1New=0, *t2New=0; TR3 *t11=0, *t12=0, *t21=0, *t22=0, *t23=0, *t31=0, *t32=0; TET3 *td1=0, *td2=0, *td3=0; PATCH *n1=0, *n2=0, *n3=0, *n4=0; EDG3 *e1=0, *e2=0, *e3=0, *e4=0, *e5=0, *e6=0; EDG3 *e1New=0, *e2New=0, *e3New=0, *e4New=0; int i, depth = (td->depth)+1; // Refinement of td into three green tetrahedra if ( (td->mark == T_GREEN_2B) ) td->mark = False; else return True; td->getTriangles(trs); // Get two new triangles and three tetrahedra, // if not enough space: return False t1New = new TR3; t2New = new TR3; noOfTriangles += 2; t1New->depth = t2New->depth = depth; td1 = getTET3(); td2 = getTET3(); td3 = getTET3(); noOfTetrahedra += 2; // Testing which face is green-2B refined // The actual case is transformed on the td with e4, e6 refined. for (i=1; i<=4; i++) { t = trs[i]; if ( TestFace(t) > 1 ) { MkGreenIrr(t); if ( i==1 ) { if ( (td->e2)->firstSon == 0) { t1 = trs[3]; t2 = trs[1]; t3 = trs[2]; t4 = trs[4]; n1 = td->n3; n2 = td->n1; n3 = td->n2; n4 = td->n4; e1 = td->e2; e2 = td->e3; e3 = td->e1; e4 = td->e5; e5 = td->e6; e6 = td->e4; p1 = td->p3; p2 = td->p1; p3 = td->p2; p4 = td->p4; } else if ( (td->e4)->firstSon == 0) { t1 = trs[4]; t2 = trs[1]; t3 = trs[3]; t4 = trs[2]; n1 = td->n4; n2 = td->n1; n3 = td->n3; n4 = td->n2; e1 = td->e4; e2 = td->e1; e3 = td->e6; e4 = td->e2; e5 = td->e3; e6 = td->e5; p1 = td->p4; p2 = td->p1; p3 = td->p3; p4 = td->p2; } else if ( (td->e5)->firstSon == 0) { t1 = trs[2]; t2 = trs[1]; t3 = trs[4]; t4 = trs[3]; n1 = td->n2; n2 = td->n1; n3 = td->n4; n4 = td->n3; e1 = td->e5; e2 = td->e6; e3 = td->e3; e4 = td->e4; e5 = td->e1; e6 = td->e2; p1 = td->p2; p2 = td->p1; p3 = td->p4; p4 = td->p3; } } else if ( i==2 ) { if ( (td->e1)->firstSon == 0) { t1 = trs[1]; t2 = trs[2]; t3 = trs[3]; t4 = trs[4]; n1 = td->n1; n2 = td->n2; n3 = td->n3; n4 = td->n4; e1 = td->e1; e2 = td->e2; e3 = td->e3; e4 = td->e4; e5 = td->e5; e6 = td->e6; p1 = td->p1; p2 = td->p2; p3 = td->p3; p4 = td->p4; } else if ( (td->e4)->firstSon == 0) { t1 = trs[3]; t2 = trs[2]; t3 = trs[4]; t4 = trs[1]; n1 = td->n3; n2 = td->n2; n3 = td->n4; n4 = td->n1; e1 = td->e4; e2 = td->e5; e3 = td->e2; e4 = td->e6; e5 = td->e3; e6 = td->e1; p1 = td->p3; p2 = td->p2; p3 = td->p4; p4 = td->p1; } else if ( (td->e6)->firstSon == 0) { t1 = trs[4]; t2 = trs[2]; t3 = trs[1]; t4 = trs[3]; n1 = td->n4; n2 = td->n2; n3 = td->n1; n4 = td->n3; e1 = td->e6; e2 = td->e3; e3 = td->e5; e4 = td->e1; e5 = td->e2; e6 = td->e4; p1 = td->p4; p2 = td->p2; p3 = td->p1; p4 = td->p3; } } else if ( i==3 ) { if ( (td->e3)->firstSon == 0) { t1 = trs[2]; t2 = trs[3]; t3 = trs[1]; t4 = trs[4]; n1 = td->n2; n2 = td->n3; n3 = td->n1; n4 = td->n4; e1 = td->e3; e2 = td->e1; e3 = td->e2; e4 = td->e6; e5 = td->e4; e6 = td->e5; p1 = td->p2; p2 = td->p3; p3 = td->p1; p4 = td->p4; } else if ( (td->e5)->firstSon == 0) { t1 = trs[4]; t2 = trs[3]; t3 = trs[2]; t4 = trs[1]; n1 = td->n4; n2 = td->n3; n3 = td->n2; n4 = td->n1; e1 = td->e5; e2 = td->e2; e3 = td->e4; e4 = td->e3; e5 = td->e1; e6 = td->e6; p1 = td->p4; p2 = td->p3; p3 = td->p2; p4 = td->p1; } else if ( (td->e6)->firstSon == 0) { t1 = trs[1]; t2 = trs[3]; t3 = trs[4]; t4 = trs[2]; n1 = td->n1; n2 = td->n3; n3 = td->n4; n4 = td->n2; e1 = td->e6; e2 = td->e4; e3 = td->e1; e4 = td->e5; e5 = td->e2; e6 = td->e3; p1 = td->p1; p2 = td->p3; p3 = td->p4; p4 = td->p2; } } else if ( i==4 ) { if ( (td->e1)->firstSon == 0) { t1 = trs[3]; t2 = trs[4]; t3 = trs[1]; t4 = trs[2]; n1 = td->n3; n2 = td->n4; n3 = td->n1; n4 = td->n2; e1 = td->e1; e2 = td->e6; e3 = td->e4; e4 = td->e3; e5 = td->e5; e6 = td->e2; p1 = td->p3; p2 = td->p4; p3 = td->p1; p4 = td->p2; } else if ( (td->e2)->firstSon == 0) { t1 = trs[2]; t2 = trs[4]; t3 = trs[3]; t4 = trs[1]; n1 = td->n2; n2 = td->n4; n3 = td->n3; n4 = td->n1; e1 = td->e2; e2 = td->e4; e3 = td->e5; e4 = td->e1; e5 = td->e6; e6 = td->e3; p1 = td->p2; p2 = td->p4; p3 = td->p3; p4 = td->p1; } else if ( (td->e3)->firstSon == 0) { t1 = trs[1]; t2 = trs[4]; t3 = trs[2]; t4 = trs[3]; n1 = td->n1; n2 = td->n4; n3 = td->n2; n4 = td->n3; e1 = td->e3; e2 = td->e5; e3 = td->e6; e4 = td->e2; e5 = td->e4; e6 = td->e1; p1 = td->p1; p2 = td->p4; p3 = td->p2; p4 = td->p3; } } break; } } // After Transform we can work on the reference td with refined e4, e6 MkGreen(t1); t = t1->firstSon; if ( PinTr(p4,t) ) { t11 = t; t12 = t->next; } else { t12 = t; t11 = t->next; } MkGreen(t3); t = t3->firstSon; if ( PinTr(p4,t) ) { t31 = t; t32 = t->next; } else { t32 = t; t31 = t->next; } // subfaces of the grenn-IIB refined face t21 = t2->firstSon; t23 = t21->next; t22 = t23->next; // Set the fields for the new objects e1New = EdinTr(t12,p2,e4->pm); e3New = EdinTr(t32,p2,e6->pm); e2New = EdinTr(t21,e4->pm,e6->pm); t1New->e1 = e1New; t1New->e2 = e2New; t1New->e3 = e3New; SetTP(t1New,0); t1New->type = T_GREEN_2B; SetTdP(td1,t11,t21,t1New,t31,td); SetTdE(td1,t11,t21,t1New,t31); neighbourAtFace(td1,n1,t11); neighbourAtFace(td1,n2,t21); neighbourAtFace(td1,n3,t31); td1->type = T_GREEN_2B; if ( PinTr(e6->pm,t23) ) { e4New = EdinTr(t23,p3,e6->pm); t2New->e1 = e2; t2New->e2 = e4New; t2New->e3 = e3New; SetTP(t2New,0); t2New->type = T_GREEN_2B; SetTdP(td2,t1New,t2New,t12,t22,td); SetTdE(td2,t1New,t2New,t12,t22); neighbourAtFace(td2,n1,t12); neighbourAtFace(td2,n2,t22); td2->type = T_GREEN_2B; SetTdP(td3,t23,t32,t2New,t4,td); SetTdE(td3,t23,t32,t2New,t4); neighbourAtFace(td3,n2,t23); neighbourAtFace(td3,n3,t32); neighbourAtFace(td3,n4,t4); td3->type = T_GREEN_2B; } else { e4New = EdinTr(t23,p1,e4->pm); t2New->e1 = e1New; t2New->e2 = e4New; t2New->e3 = e3; SetTP(t2New,0); t2New->type = T_GREEN_2B; SetTdP(td2,t1New,t2New,t32,t22,td); SetTdE(td2,t1New,t2New,t32,t22); neighbourAtFace(td2,n3,t32); neighbourAtFace(td2,n2,t22); td2->type = T_GREEN_2B; SetTdP(td3,t23,t12,t2New,t4,td); SetTdE(td3,t23,t12,t2New,t4); neighbourAtFace(td3,n2,t23); neighbourAtFace(td3,n1,t12); neighbourAtFace(td3,n4,t4); td3->type = T_GREEN_2B; } innerNeighbourAtFace(td1,t1New,td2); innerNeighbourAtFace(td2,t1New,td1); innerNeighbourAtFace(td2,t2New,td3); innerNeighbourAtFace(td3,t2New,td2); td->firstSon = td1; td->type = T_GREEN_2B; tetList[tetList.h]->add(td1); tetList[tetList.h]->add(td2); tetList[tetList.h]->add(td3); // destruction of the faces delete t1New; delete t2New; if ( !(t1->onBoundary()) ) { delete t11; delete t12; } if ( !(t3->onBoundary()) ) { delete t31; delete t32; } if ( !(t2->onBoundary()) ) { delete t21; delete t22; delete t23; } td->returnTriangles(trs); return True; } //------------------------------------------------------------------------- int MESH3:: MkGreen3Td(TET3 *td) { PT3 *p1, *p2, *p3, *p4; PT3 *p6,*p7,*p9; TR3 *t, *t1, *t2, *t3, *t4, *trs[1+4]; TR3 *s=0, *s1=0, *s2=0, *s3=0, *s4=0; TR3 *t1New=0, *t2New=0, *t3New=0, *t4New=0, *t5New=0, *t6New=0, *t7New=0, *t8New=0, *t9New=0; TET3 *td1,*td2,*td3,*td4; PATCH *n1, *n2, *n3, *n4; EDG3 *e1=td->e1,*e2=td->e2,*e3=td->e3,*e4=td->e4, *e5=td->e5, *e6=td->e6; EDG3 *e1New, *e2New,*e3New; EDG3 *e14, *e24, *e34; int i, depth = (td->depth)+1; // Refinement of td into four green tetrahedra if (td->mark == T_GREEN_3) td->mark = False; else return True; td->getTriangles(trs); for (i=1; i<=4; i++) { t = trs[i]; if ( TestFace(t) > 1 ) { RefineTr(t); break; } } // Get three new edges, nine new triangles and four tetrahedra, // if not enough space: return False t1New = new TR3; t2New = new TR3; t3New = new TR3; noOfTriangles += 3; t1New->depth = depth; t2New->depth = depth; t3New->depth = depth; td1 = getTET3(); td2 = getTET3(); td3 = getTET3(); td4 = getTET3(); noOfTetrahedra += 3; // Testing if one neighbor tetrahedron is refined and setting pi, ei // corresponding to this neighbor t = trs[1]; if ( (t->firstSon)!=0 && (t->type == T_RED) ) { p1=td->p1; p2=td->p2; p3=td->p3; p4=td->p4; p6 = e5->pm; p7 = e2->pm; p9 = e4->pm; t1 = trs[1]; t2 = trs[2]; t3 = trs[3]; t4 = trs[4]; n1 = td->n1; n2 = td->n2; n3 = td->n3; n4 = td->n4; } else { t = trs[2]; if ( (t->firstSon)!=0 && (t->type == T_RED) ) { p1=td->p2; p2=td->p4; p3=td->p3; p4=td->p1; p6 = e6->pm; p7 = e4->pm; p9 = e1->pm; t1 = trs[2]; t2 = trs[4]; t3 = trs[3]; t4 = trs[1]; n1 = td->n2; n2 = td->n4; n3 = td->n3; n4 = td->n1; } else { t = trs[3]; if ( (t->firstSon)!=0 && (t->type == T_RED) ) { p1=td->p3; p2=td->p4; p3=td->p1; p4=td->p2; p6 = e5->pm; p7 = e6->pm; p9 = e3->pm; t1 = trs[3]; t2 = trs[4]; t3 = trs[1]; t4 = trs[2]; n1 = td->n3; n2 = td->n4; n3 = td->n1; n4 = td->n2; } else { t = trs[4]; if ( (t->firstSon)!=0 && (t->type == T_RED) ) { p1=td->p4; p2=td->p1; p3=td->p3; p4=td->p2; p6 = e3->pm; p7 = e1->pm; p9 = e2->pm; t1 = trs[4]; t2 = trs[1]; t3 = trs[3]; t4 = trs[2]; n1 = td->n4; n2 = td->n1; n3 = td->n3; n4 = td->n2; } else return False; } } } // Set the fields for the new objects MkGreen(t2); MkGreen(t3); MkGreen(t4); s = t1->firstSon; for (i=0;i<4;i++) { if (PinTr(p2,s)) s2 = s; else if (PinTr(p3,s)) s1 = s; else if (PinTr(p4,s)) s3 = s; else {s4 = s;} s = s->next; } s = t2->firstSon; e1New = EdinTr(s,p1,p9); if (PinTr(p4,s)) { t4New = s; t5New = s->next; } else { t5New = s; t4New = s->next; } s = t4->firstSon; e2New = EdinTr(s,p1,p7); if (PinTr(p2,s)) { t7New = s; t6New = s->next; } else { t6New = s; t7New = s->next; } s = t3->firstSon; e3New = EdinTr(s,p1,p6); if (PinTr(p2,s)) { t8New = s; t9New = s->next; } else { t9New = s; t8New = s->next; } e14 = EdinTr(s1,p7,p9); e24 = EdinTr(s2,p6,p7); e34 = EdinTr(s3,p6,p9); t1New->e1 = e1New; t1New->e2 = e14; t1New->e3 = e2New; t2New->e1 = e2New; t2New->e2 = e24; t2New->e3 = e3New; t3New->e1 = e3New; t3New->e2 = e34; t3New->e3 = e1New; SetTP(t1New,0); t1New->type = T_GREEN_3; SetTP(t2New,0); t2New->type = T_GREEN_3; SetTP(t3New,0); t3New->type = T_GREEN_3; SetTdP(td1,s1,t1New,t5New,t6New,td); SetTdE(td1,s1,t1New,t5New,t6New); neighbourAtFace(td1,n1,s1); neighbourAtFace(td1,n2,t5New); neighbourAtFace(td1,n4,t6New); td1->type = T_GREEN_3; SetTdP(td2,s2,t2New,t7New,t8New,td); SetTdE(td2,s2,t2New,t7New,t8New); neighbourAtFace(td2,n1,s2); neighbourAtFace(td2,n4,t7New); neighbourAtFace(td2,n3,t8New); td2->type = T_GREEN_3; SetTdP(td3,s3,t3New,t9New,t4New,td); SetTdE(td3,s3,t3New,t9New,t4New); neighbourAtFace(td3,n1,s3); neighbourAtFace(td3,n3,t9New); neighbourAtFace(td3,n2,t4New); td3->type = T_GREEN_3; SetTdP(td4,s4,t1New,t2New,t3New,td); SetTdE(td4,s4,t1New,t2New,t3New); neighbourAtFace(td4,n1,s4); td4->type = T_GREEN_3; innerNeighbourAtFace(td1,t1New,td4); innerNeighbourAtFace(td2,t2New,td4); innerNeighbourAtFace(td3,t3New,td4); innerNeighbourAtFace(td4,t1New,td1); innerNeighbourAtFace(td4,t2New,td2); innerNeighbourAtFace(td4,t3New,td3); td->firstSon = td1; td->type = T_GREEN_3; tetList[tetList.h]->add(td1); tetList[tetList.h]->add(td2); tetList[tetList.h]->add(td3); tetList[tetList.h]->add(td4); // destruction of the faces delete t1New; delete t2New; delete t3New; if ( !(t1->onBoundary()) ) { delete s1; delete s2; delete s3; delete s4; } if ( !(t2->onBoundary()) ) { delete t4New; delete t5New; } if ( !(t3->onBoundary()) ) { delete t8New; delete t9New; } if ( !(t4->onBoundary()) ) { delete t6New; delete t7New; } td->returnTriangles(trs); return True; } //------------------------------------------------------------------------- void MESH3:: RelGreen() { TR3 *t1old, *t2old, *tFather; EDG3 *eMid = 0, *ed, *edNext; int k, depth; // remove all green triangles (on the boundary) FORALL_DOWNWARD(trList,depth) { TR3 *t = trList[depth]->first; while (t!=0) { k = 0; tFather = t->father; if (tFather==0) { t = t->next; continue; } if ((tFather->type)!=T_GREEN_1) { t = t->next; continue; } // Remove two green triangles, print internal error message // if the green edge is not found t1old = t; t2old = t->next; if (((t->e1)->type)==T_GREEN_1) { eMid = t->e1; k++;} if (((t->e2)->type)==T_GREEN_1) { eMid = t->e2; k++;} if (((t->e3)->type)==T_GREEN_1) { eMid = t->e3; k++;} if (k!=1) { cout << "\n*** RemoveGreen: Triangle with impossible state k=" << k << "\n"; } t = t2old->next; // Remove the two green triangles; return the space trList[t1old->depth]->remove(t1old); trList[t2old->depth]->remove(t2old); delete t1old; delete t2old; noOfTriangles--; tFather->firstSon = 0; tFather->type = T_WHITE; tFather->mark = False; edgList[eMid->depth]->remove(eMid); edgAlloc.Return(eMid); noOfEdges--; } } FORALL_DOWNWARD(edgList,depth) { ed = edgList[depth]->first; while (ed!=0) { edNext = ed->next; if ( (ed->type)==T_GREEN_1 || ((ed->type)==T_GREEN_3) ) { edgList[ed->depth]->remove(ed); edgAlloc.Return(ed); noOfEdges--; noOfTriangles--; } ed = edNext; } } return; } //------------------------------------------------------------------------- void MESH3:: RelGreenIrr() { TR3 *t1,*t2,*t3,*tFather; EDG3 *e1Mid = 0, *e2Mid = 0, *ed, *edNext; int k, depth; // remove all irregular green triangles ( on the boundary) FORALL_DOWNWARD(trList,depth) { TR3 *t = trList[depth]->first; // -- Loop for all triangles; ApplyT could not be used while (t != 0) { tFather = t->father; if (tFather==0) { t = t->next; continue; } if (tFather->type != T_GREEN_2B) { t = t->next; continue; } // -- Remove three green triangles, print internal error message // if the green edge is not found t1 = t; t2 = t1->next; t3 = t2->next; k = 0; if (((t1->e1)->type)==T_GREEN_2B) { e1Mid = t1->e1; k++;} if (((t1->e2)->type)==T_GREEN_2B) { e1Mid = t1->e2; k++;} if (((t1->e3)->type)==T_GREEN_2B) { e1Mid = t1->e3; k++;} if (k != 1) cout << "\n*** 1RelGreenIrr: Triangle with impossible state k=" << k << "\n"; k = 0; if (((t2->e1)->type)==T_GREEN_2B) { e2Mid = t2->e1; k++;} if (((t2->e2)->type)==T_GREEN_2B) { e2Mid = t2->e2; k++;} if (((t2->e3)->type)==T_GREEN_2B) { e2Mid = t2->e3; k++;} if (k!=1) cout << "\n*** 2RelGreenIrr: Triangle with impossible state k=" << k << "\n"; t = t3->next; // next while-step // Remove the three green triangles; return the space trList[t1->depth]->remove(t1); trList[t2->depth]->remove(t2); trList[t3->depth]->remove(t3); delete t1; delete t2; delete t3; noOfTriangles -= 2; tFather->firstSon = 0; tFather->type = T_WHITE; edgList[e1Mid->depth]->remove(e1Mid); edgList[e2Mid->depth]->remove(e2Mid); edgAlloc.Return(e1Mid); edgAlloc.Return(e2Mid); noOfEdges -= 2; } } FORALL_DOWNWARD(edgList,depth) { ed = edgList[depth]->first; while (ed!=0) { edNext = ed->next; if ((ed->type)!=T_GREEN_2B) { ed = edNext; continue; } edgList[ed->depth]->remove(ed); edgAlloc.Return(ed); noOfEdges--; noOfTriangles -= 1; ed = edNext; } } return; } //------------------------------------------------------------------------- void MESH3:: RelGreen1Td() { TET3 *td1old,*td2old,*tdFather; TET3 *td = tetList[refStep]->first; // remove all Green-I tetrahedra while (td != 0) { tdFather = td->father; if (tdFather == 0) { td = td->next; continue; } if (tdFather->type != T_GREEN_1) { td = td->next; continue; } // -- two Green-I tetrahedra td1old = td; td2old = td->next; td = td2old->next; if (td1old->mark) tdFather->mark = True; // refine father else if (td2old->mark) tdFather->mark = True; // refine father else tdFather->mark = False; // -- correct the white neighbors correctWhiteNbs(td1old); correctWhiteNbs(td2old); // -- Remove the two Green-I tetrahedra from the list of tetrahedra tetList[refStep]->remove(td1old); tetList[refStep]->remove(td2old); returnTET3(td1old); returnTET3(td2old); tdFather->firstSon = 0; tdFather->type = T_WHITE; noOfTetrahedra--; noOfTriangles--; } return; } //------------------------------------------------------------------------- void MESH3:: RelGreen2ATd() { TET3 *td1old,*td2old,*td3old,*td4old,*tdFather; EDG3 *edMid=0; TET3 *td = tetList[refStep]->first; // remove all green-2A tetrahedra while (td != 0) { tdFather = td->father; if (tdFather==0) { td = td->next; continue; } if (tdFather->type != T_GREEN_2A) { td = td->next; continue; } // Remove four green-2A tetrahedra, print internal error message // if the inner green-2A edge is not found td1old = td; td2old = td->next; td3old = td2old->next; td4old = td3old->next; td = td4old->next; if (td1old->mark) tdFather->mark = True; // refine father else if (td2old->mark) tdFather->mark = True; // refine father else if (td3old->mark) tdFather->mark = True; // refine father else if (td4old->mark) tdFather->mark = True; // refine father else tdFather->mark = False; // inner edge if ((td1old->e1)->type == T_GREEN_2A) edMid = td1old->e1; else if ((td1old->e2)->type == T_GREEN_2A) edMid = td1old->e2; else if ((td1old->e3)->type == T_GREEN_2A) edMid = td1old->e3; else if ((td1old->e4)->type == T_GREEN_2A) edMid = td1old->e4; else if ((td1old->e5)->type == T_GREEN_2A) edMid = td1old->e5; else if ((td1old->e6)->type == T_GREEN_2A) edMid = td1old->e6; if (edMid == 0) cout << "\n\nAlarm in RelGreen2ATd: edMid == 0\n"; // -- correct the white neighbours correctWhiteNbs(td1old); correctWhiteNbs(td2old); correctWhiteNbs(td3old); correctWhiteNbs(td4old); // Remove the four green ones from the list of tetrahedra tetList[refStep]->remove(td1old); tetList[refStep]->remove(td2old); tetList[refStep]->remove(td3old); tetList[refStep]->remove(td4old); returnTET3(td1old); returnTET3(td2old); returnTET3(td3old); returnTET3(td4old); tdFather->firstSon = 0; tdFather->type = T_WHITE; noOfTetrahedra -= 3; noOfTriangles -= 4; edgList[edMid->depth]->remove(edMid); edgAlloc.Return(edMid); noOfEdges -=1; } return; } //------------------------------------------------------------------------- void MESH3:: RelGreen2BTd() { TET3 *td1old,*td2old,*td3old,*tdFather; TET3 *td = tetList[refStep]->first; // remove all green-2B tetrahedra while (td != 0) { tdFather = td->father; if (tdFather == 0) { td = td->next; continue; } if (tdFather->type != T_GREEN_2B) { td = td->next; continue; } // Remove three green2B tetrahedra td1old = td; td2old = td->next; td3old = td2old->next; td = td3old->next; // next while-step if (td1old->mark) tdFather->mark = True; // refine father else if (td2old->mark) tdFather->mark = True; // refine father else if (td3old->mark) tdFather->mark = True; // refine father else tdFather->mark = False; // -- correct the white neighbours correctWhiteNbs(td1old); correctWhiteNbs(td2old); correctWhiteNbs(td3old); // Remove the three green ones from the list of tetrahedra tetList[refStep]->remove(td1old); tetList[refStep]->remove(td2old); tetList[refStep]->remove(td3old); returnTET3(td1old); returnTET3(td2old); returnTET3(td3old); tdFather->firstSon = 0; tdFather->type = T_WHITE; noOfTetrahedra -=2; noOfTriangles -= 2; } return; } //------------------------------------------------------------------------- void MESH3:: RelGreen3Td() { TET3 *td1old,*td2old,*td3old,*td4old,*tdFather; TET3 *td = tetList[refStep]->first; // remove all green-III tetrahedra while (td != 0) { tdFather = td->father; if (tdFather==0) { td = td->next; continue; } if ((tdFather->type)!=T_GREEN_3) { td = td->next; continue; } // Remove four green tetrahedra, print internal error message // if the inner green faces are not found td1old = td; td2old = td->next; td3old = td2old->next; td4old = td3old->next; td = td4old->next; // next step in while if (td1old->mark) tdFather->mark = True; // refine father else if (td2old->mark) tdFather->mark = True; // refine father else if (td3old->mark) tdFather->mark = True; // refine father else if (td4old->mark) tdFather->mark = True; // refine father else tdFather->mark = False; // -- correct the white neighbours correctWhiteNbs(td1old); correctWhiteNbs(td2old); correctWhiteNbs(td3old); correctWhiteNbs(td4old); // Substitute the old (father) tetrahedron for the four green ones // in the list of tetrahedra; return the space tetList[refStep]->remove(td1old); tetList[refStep]->remove(td2old); tetList[refStep]->remove(td3old); tetList[refStep]->remove(td4old); returnTET3(td1old); returnTET3(td2old); returnTET3(td3old); returnTET3(td4old); tdFather->firstSon = 0; tdFather->type = T_WHITE; noOfTetrahedra -= 3; noOfTriangles -= 3; } return; } //------------------------------------------------------------------------- //------------------------------------------------------------------------- Bool TET3:: noTdinNb(TET3* tet) { TET* nbTet; nbTet = n1->castToTET3(); if ( nbTet == tet) return True; nbTet = n2->castToTET3(); if ( nbTet == tet) return True; nbTet = n3->castToTET3(); if ( nbTet == tet) return True; nbTet = n4->castToTET3(); if ( nbTet == tet) return True; return False; } //------------------------------------------------------------------------- void TET3:: correctNbinTet(TET3 *tet) { TET* nbTet; nbTet = n1->castToTET3(); if ( nbTet == tet) {n1 = tet->father; return; } nbTet = n2->castToTET3(); if ( nbTet == tet) {n2 = tet->father; return; } nbTet = n3->castToTET3(); if ( nbTet == tet) {n3 = tet->father; return; } nbTet = n4->castToTET3(); if ( nbTet == tet) {n4 = tet->father; return; } // cout << "\nImpossible state in correctNbinTet\n"; } void MESH3:: correctWhiteNbs(TET3 *tet) { TET3* nbTet; Vector nbs(4); int i; tet->getNeighbours(nbs); FORALL(nbs,i) { if (nbs[i]) { nbTet = nbs[i]->castToTET3(); nbTet->correctNbinTet(tet); // if ( (nbTet->type != T_GREEN_1) && (nbTet->type != T_GREEN_2A) && // (nbTet->type != T_GREEN_2B) && (nbTet->type != T_GREEN_3) ) } } } //------------------------------------------------------------------------- int MESH3:: CheckTd(TET3 *td) { TET3 *nbTd; PATCH *n1=td->n1, *n2=td->n2, *n3=td->n3, *n4=td->n4; if ( n1 == 0 ) { cout << "\n\tneighbour 1==0:\n"; td->print(cout); (td->p2)->print(cout); (td->p3)->print(cout); (td->p4)->print(cout); } if ( n2 == 0 ) { cout << "\n\tneighbour 2==0:\n"; td->print(cout); (td->p1)->print(cout); (td->p3)->print(cout); (td->p4)->print(cout); } if ( n3 == 0 ) { cout << "\n\tneighbour 3==0:\n"; td->print(cout); (td->p1)->print(cout); (td->p2)->print(cout); (td->p4)->print(cout); } if ( n4 == 0 ) { cout << "\n\tneighbour 4==0:\n"; td->print(cout); (td->p1)->print(cout); (td->p2)->print(cout); (td->p3)->print(cout); } nbTd = n1->castToTET3(); if ( nbTd ) { if( !nbTd->noTdinNb(td) ) { cout << "\n\t error in neighbor relation\n"; td->print(cout); nbTd->print(cout); } } nbTd = n2->castToTET3(); if ( nbTd ) { if( !nbTd->noTdinNb(td) ) { cout << "\n\t error in neighbor relation\n"; td->print(cout); nbTd->print(cout); } } nbTd = n3->castToTET3(); if ( nbTd ) { if( !nbTd->noTdinNb(td) ) { cout << "\n\t error in neighbor relation\n"; td->print(cout); nbTd->print(cout); } } nbTd = n4->castToTET3(); if ( nbTd ) { if( !nbTd->noTdinNb(td) ) { cout << "\n\t error in neighbor relation\n"; td->print(cout); nbTd->print(cout); } } if ( n1->castToTET3() && n2->castToTET3() && n3->castToTET3() && n4->castToTET3() ) { if (td->boundP != INTERIOR) { cout << "\n\t error in boundary definition: boundP != INTERIOR\n"; td->print(cout); } } else { if (td->boundP != BOUNDARY) { cout << "\n\t error in boundary definition: boundP != BOUNDARY\n"; td->print(cout); } } return True; } //------------------------------------------------------------------------- int MESH3:: consistencyCheck() { PT3 *p; TET3 *tet; //int no, noInner, noBound, noWithFather, noWithoutFather; //int noWhite, noRed, noGreenI, noGreenIIA, noGreenIIB, noGreenIII; DListIter iterTET(tetras()); cout << "\n\t Begin of consistencyCheck:\n"; cout << "\n\t no of points = " << noOfPoints << "\n"; cout << "\t no of edges = " << noOfEdges << "\n"; cout << "\t no of triangles = " << noOfTriangles << "\n"; cout << "\t no of tetrahedra = " << noOfTetrahedra << "\n"; int eulerC = noOfPoints - noOfEdges + noOfTriangles - noOfTetrahedra; cout << "\n\t Euler's characteristic = " << eulerC << "\n"; if (eulerC != 1) cout << "\n\t Dangerous: Euler's characteristic not 1\n\n"; Vector PNodes(noOfPoints); // saving the node numbers for later reuse int i = 0; DListIter PIter(points()); while ((p=PIter.all())) { PNodes[++i] = p->node; p->node = i; } while ((tet=iterTET.all())) { if(!CheckTd(tet)) return False;; } // restore of node numbers i = 0; PIter.reset(); while ((p=PIter.all())) p->node = PNodes[++i]; CompAngles(); /* no = 0; noInner = 0; noBound = 0; while (p =iterPT.all()) { no++; if ( p->boundP == DIRICHLET ) noBound++; if ( p->boundP == INTERIOR ) noInner++; } cout << "\n\t no of points in list = " << no; cout << "\n\t no of boundary points = " << noBound; cout << "\n\t no of inner points = " << noInner; no = 0; noInner = 0; noBound = 0; noWithFather=0; noWithoutFather=0; noWhite=0; noRed=0; noGreenI=0; noGreenIIA=0; noGreenIIB=0; noGreenIII=0; noZero=0; noGreen=0; while (e =iterEDG.all()) { no++; if ( e->boundP == DIRICHLET ) noBound++; if ( e->boundP == INTERIOR ) noInner++; if ( e->type == T_WHITE ) noWhite++; if ( e->type == T_RED ) noRed++; if ( e->type == T_GREEN_1 ) noGreenI++; if ( e->type == T_GREEN_2A) noGreenIIA++; if ( e->type == T_GREEN_2B) noGreenIIB++; if ( e->type == T_GREEN_3 ) noGreenIII++; if ( e->type == T_GREEN ) noGreen++; if ( e->type == T_ZERO ) noZero++; if ( e->father != 0 ) noWithFather++; else if ( e->father == 0 ) noWithoutFather++; } cout << "\n\t no of edges in list = " << no; cout << "\n\t no of boundary edges = " << noBound; cout << "\n\t no of inner edges = " << noInner; cout << "\n\t no of edges with father = " << noWithFather; cout << "\n\t no of edges without father = " << noWithoutFather; cout << "\n\t no of white edges = " << noWhite; cout << "\n\t no of red edges = " << noRed; cout << "\n\t no of greenI edges = " << noGreenI; cout << "\n\t no of greenIIA edges = " << noGreenIIA; cout << "\n\t no of greenIIB edges = " << noGreenIIB; cout << "\n\t no of greenIII edges = " << noGreenIII; cout << "\n\t no of green edges = " << noGreen; cout << "\n\t no of zero edges = " << noZero; no = 0; iterTET.reset(); while (tet=iterTET.all()) no++; cout << "\n\t no of tets in list = " << no << "\n"; */ cout << "\n\t End of consistencyCheck.\n"; cout << "\n\t ----------------------------------------------------------\n\n"; return True; } //------------------------------------------------------------------------- int MESH3:: CheckAngle(TR3 *t) { PT3 *p1=t->p1, *p2=t->p2, *p3=t->p3; Real e1X, e1Y, e1Z; Real e2X, e2Y, e2Z; Real s12, s11, s22; Real alpha1, alpha2, alpha3; int classI; e1X = p2->x - p1->x; e1Y = p2->y - p1->y; e1Z = p2->z - p1->z; e2X = p3->x - p1->x; e2Y = p3->y - p1->y; e2Z = p3->z - p1->z; s12 = e1X*e2X + e1Y*e2Y + e1Z*e2Z; s11 = sqrt(e1X*e1X + e1Y*e1Y + e1Z*e1Z); s22 = sqrt(e2X*e2X + e2Y*e2Y + e2Z*e2Z); alpha1 = 180.0*acos(s12/(s11*s22))/REALPI; if (alpha1 > alphaMax) alphaMax = alpha1; if (alpha1 < alphaMin) alphaMin = alpha1; e1X = p1->x - p2->x; e1Y = p1->y - p2->y; e1Z = p1->z - p2->z; e2X = p3->x - p2->x; e2Y = p3->y - p2->y; e2Z = p3->z - p2->z; s12 = e1X*e2X + e1Y*e2Y + e1Z*e2Z; s11 = sqrt(e1X*e1X + e1Y*e1Y + e1Z*e1Z); s22 = sqrt(e2X*e2X + e2Y*e2Y + e2Z*e2Z); alpha2 = 180.0*acos(s12/(s11*s22))/REALPI; if (alpha2 > alphaMax) alphaMax = alpha2; if (alpha2 < alphaMin) alphaMin = alpha2; alpha3 = 180.0-alpha1-alpha2; if (alpha3 > alphaMax) alphaMax = alpha3; if (alpha3 < alphaMin) alphaMin = alpha3; classI = (int)(alpha1/5); alpha[classI]++; classI = (int)(alpha2/5); alpha[classI]++; classI = (int)(alpha3/5); alpha[classI]++; if ( (alpha1 < 10.) || (alpha2 < 10.) || (alpha3 < 10.) ) { cout << " alphas: " << alpha1 << alpha2 << alpha3 << "\n"; cout << " P1 : " << p1->x << p1->y << p1->z << "\n"; cout << " P2 : " << p2->x << p2->y << p2->z << "\n"; cout << " P3 : " << p3->x << p3->y << p3->z << "\n"; } return True; } //------------------------------------------------------------------------- int MESH3:: CheckCircle(TET3 *tet) { PT3 *p1, *p2, *p3, *p4; Real e1X, e1Y, e1Z; Real e2X, e2Y, e2Z; Real dyz, dxz, dxy; Real len, rhoT, sigma, vT, sT, hT; EDG3 *eds[1+6]; int i; TR3 *t1, *t2, *t3, *t4; TR3 *trs[1+4]; Real x1, x2, x3, y1, y2, y3, z1, z2, z3; tet->getTriangles(trs); t1 = trs[1]; t2 = trs[2]; t3 = trs[3]; t4 = trs[4]; p1 = tet->p1; p2 = tet->p2; p3 = tet->p3; p4 = tet->p4; x1 = (p2->x) - (p1->x); x2 = (p2->y) - (p1->y); x3 = (p2->z) - (p1->z); y1 = (p3->x) - (p1->x); y2 = (p3->y) - (p1->y); y3 = (p3->z) - (p1->z); z1 = (p4->x) - (p1->x); z2 = (p4->y) - (p1->y); z3 = (p4->z) - (p1->z); vT = SIXTH*Abs(x1*(y2*z3 - y3*z2) - x2*(y1*z3 -y3*z1) + x3*(y1*z2 - y2*z1)); // = tet->volume; sT = ZERO; p1=t1->p1; p2=t1->p2, p3=t1->p3; e1X = p2->x - p1->x; e1Y = p2->y - p1->y; e1Z = p2->z - p1->z; e2X = p3->x - p1->x; e2Y = p3->y - p1->y; e2Z = p3->z - p1->z; dyz = e1Y*e2Z - e1Z*e2Y; dxz = e1Z*e2X - e1X*e2Z; dxy = e1X*e2Y - e1Y*e2X; sT += sqrt(dyz*dyz + dxz*dxz + dxy*dxy); p1=t2->p1; p2=t2->p2, p3=t2->p3; e1X = p2->x - p1->x; e1Y = p2->y - p1->y; e1Z = p2->z - p1->z; e2X = p3->x - p1->x; e2Y = p3->y - p1->y; e2Z = p3->z - p1->z; dyz = e1Y*e2Z - e1Z*e2Y; dxz = e1Z*e2X - e1X*e2Z; dxy = e1X*e2Y - e1Y*e2X; sT += sqrt(dyz*dyz + dxz*dxz + dxy*dxy); p1=t3->p1; p2=t3->p2, p3=t3->p3; e1X = p2->x - p1->x; e1Y = p2->y - p1->y; e1Z = p2->z - p1->z; e2X = p3->x - p1->x; e2Y = p3->y - p1->y; e2Z = p3->z - p1->z; dyz = e1Y*e2Z - e1Z*e2Y; dxz = e1Z*e2X - e1X*e2Z; dxy = e1X*e2Y - e1Y*e2X; sT += sqrt(dyz*dyz + dxz*dxz + dxy*dxy); p1=t4->p1; p2=t4->p2, p3=t4->p3; e1X = p2->x - p1->x; e1Y = p2->y - p1->y; e1Z = p2->z - p1->z; e2X = p3->x - p1->x; e2Y = p3->y - p1->y; e2Z = p3->z - p1->z; dyz = e1Y*e2Z - e1Z*e2Y; dxz = e1Z*e2X - e1X*e2Z; dxy = e1X*e2Y - e1Y*e2X; sT += sqrt(dyz*dyz + dxz*dxz + dxy*dxy); sT = 0.5*sT; rhoT =6.0*vT/sT; hT =ZERO; tet->getEdges(eds); for (i=1;i<=6;i++) { e1X = (eds[i]->p1)->x; e1Y = (eds[i]->p1)->y; e1Z = (eds[i]->p1)->z; e2X = (eds[i]->p2)->x; e2Y = (eds[i]->p2)->y; e2Z = (eds[i]->p2)->z; e2X = e2X - e1X; e2Y = e2Y - e1Y; e2Z = e2Z - e1Z; len = sqrt(e2X*e2X + e2Y*e2Y + e2Z*e2Z); if (len > hT) hT = len; } sigma = hT/rhoT; if (sigma > sigmaMax) sigmaMax = sigma; tet->returnTriangles(trs); return True; } //------------------------------------------------------------------------- int MESH3:: CompAngles() { TET3 *tet; TR3 *t; int i, noOfAngles=0; for (i=0;i<36;i++) { alpha[i] = 0; } alphaMax = ZERO; alphaMin = 90.0; DListIter iterTR(triangles()); while ((t=iterTR.all())) CheckAngle(t); cout << "\n\t ----------------------------------------------------------\n"; cout << "\t angles on boundary faces: \n"; cout << "\n\t max. angle = " << alphaMax << "\n"; cout << "\t min. angle = " << alphaMin << "\n\n"; for (i=0;i<36;i++) { cout << "\t no of angles between " << i*5 << "and " << (i+1)*5 << ": " << alpha[i] << "\n"; noOfAngles += alpha[i]; } cout << "\n\t total no of angles = " << noOfAngles << "\n"; cout << "\n\t ----------------------------------------------------------\n"; sigmaMax = ZERO; DListIter iterTET(tetras()); while ((tet=iterTET.all())) CheckCircle(tet); cout << "\t sigmaT = " << sigmaMax << "\n"; cout << "\n\t ----------------------------------------------------------\n"; return True; } //------------------------------------------------------------------------- Real MESH3:: Length(PT3 *p1, PT3 *p2) { double sum = ZERO, diff; diff = (p1->x) - (p2->x); sum += diff * diff; diff = (p1->y) - (p2->y); sum += diff * diff; diff = (p1->z) - (p2->z); sum += diff * diff; return sum; } //------------------------------------------------------------------------- int MESH3:: PinTr(PT3 *p, TR3 *tr) { PT3 *p1 = tr->p1, *p2 = tr->p2, *p3 = tr->p3; if (p==p1 || p==p2 || p==p3) return True; else return False; } //------------------------------------------------------------------------- int MESH3:: PinTet(PT3 *p, TET3 *tet) { PT3 *p1 = tet->p1, *p2 = tet->p2, *p3 = tet->p3, *p4 = tet->p4; if (p==p1 || p==p2 || p==p3 || p==p4) return True; else return False; } //------------------------------------------------------------------------- EDG3* MESH3:: EdinTr(TR3 *tr,PT3 *p1,PT3 *p2) { EDG3 *e1 = tr->e1, *e2 = tr->e2, *e3 = tr->e3; PT3 *pt1, *pt2; pt1 = e1->p1; pt2 = e1->p2; if ( ((p1 == pt1)&&(p2 == pt2)) || ((p2 == pt1)&&(p1 == pt2)) ) return e1; pt1 = e2->p1; pt2 = e2->p2; if ( ((p1 == pt1)&&(p2 == pt2)) || ((p2 == pt1)&&(p1 == pt2)) ) return e2; pt1 = e3->p1; pt2 = e3->p2; if ( ((p1 == pt1)&&(p2 == pt2)) || ((p2 == pt1)&&(p1 == pt2)) ) return e3; cout << "\nEdinTr(...): edge not found\n"; cout.flush(); abort(); return 0; } //------------------------------------------------------------------------- EDG3* MESH3:: EdinTet(PT3 *p1,PT3 *p2,TET3 *td) { EDG3 *e1 = td->e1, *e2 = td->e2, *e3 = td->e3, *e4 = td->e4, *e5 = td->e5, *e6 = td->e6; PT3 *pt1, *pt2; pt1 = e1->p1; pt2 = e1->p2; if ( ((p1 == pt1)&&(p2 == pt2)) || ((p2 == pt1)&&(p1 == pt2)) ) return e1; pt1 = e2->p1; pt2 = e2->p2; if ( ((p1 == pt1)&&(p2 == pt2)) || ((p2 == pt1)&&(p1 == pt2)) ) return e2; pt1 = e3->p1; pt2 = e3->p2; if ( ((p1 == pt1)&&(p2 == pt2)) || ((p2 == pt1)&&(p1 == pt2)) ) return e3; pt1 = e4->p1; pt2 = e4->p2; if ( ((p1 == pt1)&&(p2 == pt2)) || ((p2 == pt1)&&(p1 == pt2)) ) return e4; pt1 = e5->p1; pt2 = e5->p2; if ( ((p1 == pt1)&&(p2 == pt2)) || ((p2 == pt1)&&(p1 == pt2)) ) return e5; pt1 = e6->p1; pt2 = e6->p2; if ( ((p1 == pt1)&&(p2 == pt2)) || ((p2 == pt1)&&(p1 == pt2)) ) return e6; return 0; } //------------------------------------------------------------------------- int MESH3:: TestFace(TR3 *tr) { EDG3 *eds[1+3]; int i, noOfRefEdg = 0; tr->getEdges(eds); for (i=1; i<=3; i++) { if ( (eds[i]->firstSon) != 0) noOfRefEdg++; } return noOfRefEdg; } //------------------------------------------------------------------------- int MESH3:: TestEdsInTd(TET3 *tet) { EDG3 *eds[1+6]; int i, noOfRefEdg = 0; tet->getEdges(eds); for (i=1; i<=6; i++) { if ( (eds[i]->firstSon) != 0) noOfRefEdg++; } return noOfRefEdg; } //------------------------------------------------------------------------- int MESH3:: testSons(TR3 *t, TET3 *tet) { EDG3 *e1=t->e1, *e2=t->e2, *e3=t->e3, *ed=0; PT3 *pm1, *pm2, *pm3; TET3 *tetSon; int noOfRefEdg = 0, i; pm1 = e1->pm; pm2 = e2->pm; pm3 = e3->pm; tetSon = tet->firstSon; for (i=1; i<=8; i++) { ed = EdinTet(pm1,pm2,tetSon); if (ed != 0) if (ed->refined()) noOfRefEdg++; ed = EdinTet(pm1,pm3,tetSon); if (ed != 0) if (ed->refined()) noOfRefEdg++; ed = EdinTet(pm2,pm3,tetSon); if (ed != 0) if (ed->refined()) noOfRefEdg++; if ( noOfRefEdg > 0 ) return noOfRefEdg; tetSon = tetSon->next; } return noOfRefEdg; } //------------------------------------------------------------------------- ostream& operator << (ostream& os, MESH3& t) { PT3* p; EDG3* e; TR3* tr; TET3 * tet; os << "\nTriangulation 3D"; if (t.fileName) os << " " << t.fileName; os << ":\n"; DListIter iterPT (t.points()); DListIter iterTR (t.triangles()); DListIter iterEDG(t.edges()); DListIter iterTET(t.tetras()); while ((p =iterPT.all())) p->print(cout); while ((e =iterEDG.all())) e->print(cout); while ((tr=iterTR.all())) tr->print(cout); while ((tet=iterTET.all())) tet->print(cout); os << "\nRefinement step " << t.refStep; os << " -- points: " << t.noOfPoints; os << " edges: " << t.noOfEdges; os << " triangles: " << t.noOfTriangles; os << " tetras: " << t.noOfTetrahedra; os << "\n"; return os; } //------------------------------------------------------------------------- void MESH3:: Info() { cout << "\n Triangulation: points edges tri's tetra's " << " Depth=" << maxDepth << " Steps=" << refStep << Form("\n%15s%8d%8d%8d%8d", " ", noOfPoints, noOfEdges, noOfTriangles, noOfTetrahedra) << "\n"; } //------------------------------------------------------------------------- int MESH3:: MemSpace() { int space = varAllocator.MemSpace(); space += tetAlloc.MemSpace(); space += edgAlloc.MemSpace(); space += ptAlloc.MemSpace(); space += trList[0]->first->alloc.MemSpace(); return space; } //------------------------------------------------------------------------- int EFMESH3:: MemSpace() { int space = varAllocator.MemSpace(); space += EFTetAlloc.MemSpace(); space += edgAlloc.MemSpace(); space += ptAlloc.MemSpace(); space += trList[0]->first->alloc.MemSpace(); return space; } //------------------------------------------------------------------------- void MESH3:: refinementInfo(int* noPt, int* noEdg, int* noTr, int* noTet) { int blocks = varAllocator.NoOfBlocks(); blocks += tetAlloc.NoOfBlocks(); blocks += edgAlloc.NoOfBlocks(); blocks += ptAlloc.NoOfBlocks(); blocks += trList[0]->first->alloc.NoOfBlocks(); int space = MemSpace(); cout << "\n Refine: points edges tri's tetra's " << " Depth=" << maxDepth << " Steps=" << refStep << Form("\n%15s%8d%8d%8d%8d", "previous", noPt[0], noEdg[0], noTr[0], noTet[0]); if (infoRefinement > 1) { cout << Form("\n%15s%8d%8d%8d%8d", "removed", noPt[1]-noPt[0], noEdg[1]-noEdg[0] , noTr[1]-noTr[0], noTet[1]-noTet[0]) << Form("\n%15s%8d%8d%8d%8d", "generated", noPt[2]-noPt[1], noEdg[2]-noEdg[1], noTr[2]-noTr[1], noTet[2]-noTet[1]) << Form("\n%15s%8d%8d%8d%8d", "added", noOfPoints-noPt[2], noOfEdges-noEdg[2], noOfTriangles-noTr[2], noOfTetrahedra-noTet[2]) << " for green closure"; } cout << Form("\n%15s%8d%8d%8d%8d Space : %1.6f MB","total", noOfPoints, noOfEdges, noOfTriangles,noOfTetrahedra, float(space)/1e6); cout << Form("\n%15s%8.2f%8.2f%8.2f%8.2f Blocks: %1d\n","ratio", float(noOfPoints)/noPt[0], float(noOfEdges)/noEdg[0], float(noOfTriangles)/noTr[0], float(noOfTetrahedra)/noTet[0], blocks); if (infoRefinement > 2) { int npDepth, neDepth, ntDepth, step, np=0, ne=0, nt=0, ntet=0; cout << "\n Grid Statistics:" << Form("\n%15s%8s%8s%8s%8s%10s", "depth", "points", "edges", "tri's","tetra's","(total)"); FORALL(trList, step) { npDepth = (step<= ptList.h)? ptList[step]->noOfElements : 0; neDepth = (step<=edgList.h)? edgList[step]->noOfElements : 0; ntDepth = (step<= trList.h)? trList[step]->noOfElements : 0; cout << Form("\n%15d%8d%8d%8d%8d", step, npDepth, neDepth, ntDepth, tetList[step]->noOfElements); np += npDepth; ne += neDepth; nt += ntDepth; ntet +=tetList[step]->noOfElements; } cout << Form("\n%15s%8d%8d%8d%8d", "total sum", np, ne, nt, ntet); cout << "\n"; } } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void PT3:: print(ostream& os) const { os << "Point " << node << " BC " << (int) boundP << " class " << (int) classA << " mark " << (int) mark << " x: " << x << " y: " << y << " z: " << z << "\n"; } //------------------------------------------------------------------------- void PT3:: reset() { boundP = INTERIOR; mark = classA = depth = NUL; node = 0; } //------------------------------------------------------------------------- void PT3:: getNodeCoord(Vector& v) const { v[1]=x; v[2]=y; v[3]=z; } //------------------------------------------------------------------------- void PT3:: getCoordinates(Vector& v) const { v[1]=x; v[2]=y; v[3]=z; } //------------------------------------------------------------------------- void PT3:: readBC(BufferedParser& parser) { readBCValues(&boundP, &classA, parser); } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void EDG3:: print(ostream& os) const { os << "Edge with points " << p1->node << " " << p2->node << " type " << (int) type << " BC " << (int) boundP << " class " << (int) classA << " isoP " << (int) isoP << " depth " << (int) depth << "\n"; } void EDG3:: reset() { boundP = INTERIOR; isoP = PLANE; classA = type = depth = mark = NUL; p1 = p2 = pm = 0; node = 0; father = firstSon = 0; } //------------------------------------------------------------------------- void EDG3:: compNormalVector(Vector& /*n*/, Real* /*length*/) const { notImplemented("EDG3::compNormalVector"); } //------------------------------------------------------------------------- // -- point at unit coordinate -> point at x void EDG3:: realCoordinates(const Vector& u, Vector& x) const { Real L1 = 1.0 - u[1]; Real L2 = u[1]; x[1] = L1*p1->x + L2*p2->x; x[2] = L1*p1->y + L2*p2->y; x[3] = L1*p1->z + L2*p2->z; } //------------------------------------------------------------------------- void EDG3:: getNodeCoord(Vector& v) const { v[1] = 0.5*(p1->x + p2->x); v[2] = 0.5*(p1->y + p2->y); v[3] = 0.5*(p1->z + p2->z); } //------------------------------------------------------------------------- void EDG3:: getCoordinates(Vector& cP1, Vector& cP2) const { p1->getCoordinates(cP1); p2->getCoordinates(cP2); } //------------------------------------------------------------------------- Real EDG3:: hMax() const { return sqrt(sqr(p2->x - p1->x) + sqr(p2->y - p1->y) + sqr(p2->z - p1->z)); } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void TR3:: print(ostream& os) const { TR::print(os); os << " type " << (int) type << " BC " << (int) boundP << " class " << (int) classA << " isoP " << (int) isoP << " mark "<< (int)mark << " depth " << (int) depth << "\n"; } void TR3:: reset() { p1 = p2 = p3 = 0; e1 = e2 = e3 = 0; mark = classA = depth = NUL; isoP = PLANE; boundP = INTERIOR; type = MESH::T_WHITE; next = prev = father = firstSon = 0; node = 0; t31 = t32 = 0; } //------------------------------------------------------------------------- void TR3:: getEdges(EDG3* eds[]) const { eds[1] = e1; eds[2] = e2; eds[3] = e3; } //------------------------------------------------------------------------- // -- point at unit coordinate -> point at x void TR3:: realCoordinates(const Vector& u, Vector& x) const { Real L1 = 1.0 - u[1] - u[2]; Real L2 = u[1]; Real L3 = u[2]; x[1] = L1*p1->x + L2*p2->x + L3*p3->x; x[2] = L1*p1->y + L2*p2->y + L3*p3->y; x[3] = L1*p1->z + L2*p2->z + L3*p3->z; } //------------------------------------------------------------------------- void TR3:: getCoordinates(Vector& cP1, Vector& cP2, Vector& cP3) const { p1->getCoordinates(cP1); p2->getCoordinates(cP2); p3->getCoordinates(cP3); } //------------------------------------------------------------------------- Real TR3:: volume() const { Vector u(3), v(3), w(3); u[1] = p2->x - p1->x; u[2] = p2->y - p1->y; u[3] = p2->z - p1->z; v[1] = p3->x - p1->x; v[2] = p3->y - p1->y; v[3] = p3->z - p1->z; CrossProduct(w,u,v); return 0.5 * Norm(w); } //------------------------------------------------------------------------- void TR3:: readBC(BufferedParser& parser) { readBCValues(&boundP, &classA, &isoP, parser); if (isoP > e1->isoP) e1->isoP = isoP; if (isoP > e2->isoP) e2->isoP = isoP; if (isoP > e3->isoP) e3->isoP = isoP; if (boundP == DIRICHLET) { e1->boundP = e2->boundP = e3->boundP = boundP; e1->classA = e2->classA = e3->classA = classA; p1->boundP = p2->boundP = p3->boundP = boundP; p1->classA = p2->classA = p3->classA = classA; } else if (boundP == CAUCHY || boundP == NEUMANN) { if (e1->boundP != DIRICHLET) { e1->boundP = boundP; e1->classA = classA; } if (e2->boundP != DIRICHLET) { e2->boundP = boundP; e2->classA = classA; } if (e3->boundP != DIRICHLET) { e3->boundP = boundP; e3->classA = classA; } if (p1->boundP != DIRICHLET) { p1->boundP = boundP; p1->classA = classA; } if (p2->boundP != DIRICHLET) { p2->boundP = boundP; p2->classA = classA; } if (p3->boundP != DIRICHLET) { p3->boundP = boundP; p3->classA = classA; } } else { cout << "\n*** readBC: Invalid Boundary Type for Face " << boundP << "\n"; cout.flush(); abort(); } } //------------------------------------------------------------------------- void TR3:: readHyperBC(BufferedParser& /*parser*/) { if (boundP == DIRICHLET) { e1->boundP = e2->boundP = e3->boundP = boundP; e1->classA = e2->classA = e3->classA = classA; p1->boundP = p2->boundP = p3->boundP = boundP; p1->classA = p2->classA = p3->classA = classA; } else if (boundP == CAUCHY || boundP == NEUMANN) { if (e1->boundP != DIRICHLET) { e1->boundP = boundP; e1->classA = classA; } if (e2->boundP != DIRICHLET) { e2->boundP = boundP; e2->classA = classA; } if (e3->boundP != DIRICHLET) { e3->boundP = boundP; e3->classA = classA; } if (p1->boundP != DIRICHLET) { p1->boundP = boundP; p1->classA = classA; } if (p2->boundP != DIRICHLET) { p2->boundP = boundP; p2->classA = classA; } if (p3->boundP != DIRICHLET) { p3->boundP = boundP; p3->classA = classA; } } else { cout << "\n*** readBC: Invalid Boundary Type for Face " << boundP << "\n"; cout.flush(); abort(); } } //------------------------------------------------------------------------- void TET3:: compJ(Jacobian& j, Bool /*checkDetJ*/) const { j.J(1,1) = p2->x - p1->x; // Jacobian J(i,k) = dx(k)/dr(i) j.J(2,1) = p3->x - p1->x; j.J(3,1) = p4->x - p1->x; j.J(1,2) = p2->y - p1->y; j.J(2,2) = p3->y - p1->y; j.J(3,2) = p4->y - p1->y; j.J(1,3) = p2->z - p1->z; j.J(2,3) = p3->z - p1->z; j.J(3,3) = p4->z - p1->z; j.detJ = detJ; // = j.J(1,1) * (j.J(2,2)*j.J(3,3) - j.J(3,2)*j.J(2,3)) // + j.J(3,1) * (j.J(1,2)*j.J(2,3) - j.J(2,2)*j.J(1,3)) // + j.J(2,1) * (j.J(1,3)*j.J(3,2) - j.J(3,3)*j.J(1,2)); // if (j.detJ <= 0.0) cout << "\n*** Jacobi-Det. <= 0 " << j.detJ // << " encountered\n"; } void TET3:: compJinv(Jacobian& j) const { int i, k; compJ(j); j.Jinv(1,1) = j.J(2,2)*j.J(3,3) - j.J(3,2)*j.J(2,3); j.Jinv(1,2) = j.J(1,3)*j.J(3,2) - j.J(1,2)*j.J(3,3); j.Jinv(1,3) = j.J(1,2)*j.J(2,3) - j.J(1,3)*j.J(2,2); j.Jinv(2,1) = j.J(2,3)*j.J(3,1) - j.J(3,3)*j.J(2,1); j.Jinv(2,2) = j.J(1,1)*j.J(3,3) - j.J(3,1)*j.J(1,3); j.Jinv(2,3) = j.J(1,3)*j.J(2,1) - j.J(2,3)*j.J(1,1); j.Jinv(3,1) = j.J(2,1)*j.J(3,2) - j.J(3,1)*j.J(2,2); j.Jinv(3,2) = j.J(1,2)*j.J(3,1) - j.J(3,2)*j.J(1,1); j.Jinv(3,3) = j.J(1,1)*j.J(2,2) - j.J(2,1)*j.J(1,2); for (i=1; i<=3; ++i) for (k=1; k<=3; ++k) j.Jinv(i,k) /= j.detJ; } //------------------------------------------------------------------------- void TET3:: print(ostream& os) const { TET::print(os); os << " type " << (int) type << " class " << (int) classA << " mark " << (int)mark << " depth " << (int) depth << "\n"; } //------------------------------------------------------------------------- void TET3:: reset() { mark = classA = depth = NUL; boundP = INTERIOR; detJ = -1.0; father = firstSon = 0; node = 0; type = MESH::T_WHITE; error = 0.0; p1 = p2 = p3 = p4 = 0; n1 = n2 = n3 = n4 = 0; e1 = e2 = e3 = e4 = e5 = e6 = 0; } void TET3:: setBoundary() { if ( !(n1->castToTET3() && n2->castToTET3() && n3->castToTET3() && n4->castToTET3()) ) boundP = BOUNDARY; } //------------------------------------------------------------------------- void TET3:: getPoints(PT3* pts[]) const { pts[1] = p1; pts[2] = p2; pts[3] = p3; pts[4] = p4; } //------------------------------------------------------------------------- void TET3:: getEdges(EDG3* eds[]) const { eds[1] = e1; eds[2] = e2; eds[3] = e3; eds[4] = e4; eds[5] = e5; eds[6] = e6; } //------------------------------------------------------------------------- void TET3:: getEdgeOrientation(Vector& orient) const { int i; FORALL(orient,i) orient[i] = False; if (p1->node == 0 || p2->node == 0 || p3->node == 0 ||p4->node == 0) // !!! { cout <<"\n*** TET3:: getEdgeOrientation: node == 0 !\n"; cout.flush(); abort(); } if (p1->node < p2->node) orient[1] = True; if (p2->node < p3->node) orient[2] = True; if (p3->node < p1->node) orient[3] = True; if (p3->node < p4->node) orient[4] = True; if (p2->node < p4->node) orient[5] = True; if (p1->node < p4->node) orient[6] = True; } //------------------------------------------------------------------------- void TET3:: markTriangles(TET3* tet) { TET* nbTet; nbTet = n1->castToTET3(); if ( nbTet == tet) { mark++; return; } nbTet = n2->castToTET3(); if ( nbTet == tet) { mark += 2; return; } nbTet = n3->castToTET3(); if ( nbTet == tet) { mark += 4; return; } nbTet = n4->castToTET3(); if ( nbTet == tet) { mark += 8; return; } cout << "\n Impossible state in markTriangles\n"; } //------------------------------------------------------------------------- void TET3:: getMarkedTriangles(int trsMark[]) { for (int i=1; i<=4; i++) trsMark[i] = 0; switch (mark) { case 0: break; case 1: trsMark[1] = 1; break; case 2: trsMark[2] = 1; break; case 3: trsMark[2] = 1; trsMark[1] = 1; break; case 4: trsMark[3] = 1; break; case 5: trsMark[3] = 1; trsMark[1] = 1; break; case 6: trsMark[3] = 1; trsMark[2] = 1; break; case 7: trsMark[3] = 1; trsMark[2] = 1; trsMark[1] = 1; break; case 8: trsMark[4] = 1; break; case 9: trsMark[4] = 1; trsMark[1] = 1; break; case 10: trsMark[4] = 1; trsMark[2] = 1; break; case 11: trsMark[4] = 1; trsMark[2] = 1; trsMark[1] = 1; break; case 12: trsMark[4] = 1; trsMark[3] = 1; break; case 13: trsMark[4] = 1; trsMark[3] = 1; trsMark[1] = 1; break; case 14: trsMark[4] = 1; trsMark[3] = 1; trsMark[2] = 1; break; case 15: trsMark[4] = 1; trsMark[3] = 1; trsMark[2] = 1; trsMark[1] = 1; break; default: cout << "\n dangerous state in getMarkedTriangles\n"; } return; } //------------------------------------------------------------------------- void TET3:: getAllFaces(Vector& trs) const { TR3 *t1, *t2, *t3, *t4; TET3 *nt; void *t; // t1 if ( (nt = n1->castToTET3()) ) { t1 = new TR3; t1->boundP = INTERIOR; t1->depth = depth; t1->p1 = p2; t1->p2 = p3; t1->p3 = p4; t1->e1 = e4; t1->e2 = e5; t1->e3 = e2; completeT(t1,0); // t1->t31 = this; causing warnings, subst. by the next two lines t = (void*) this; t1->t31 = (TET3*) t; t1->t32 = nt; } else { t1 = n1->castToTR3(); // t1->t31 = this; causing warnings, subst. by the next two lines t = (void*) this; t1->t31 = (TET3*) t; t1->t32 = 0; } // t2 if ( (nt = n2->castToTET3()) ) { t2 = new TR3; t2->boundP = INTERIOR; t2->depth = depth; t2->p1 = p1; t2->p2 = p4; t2->p3 = p3; t2->e1 = e4; t2->e2 = e1; t2->e3 = e6; completeT(t2,0); // t2->t31 = this; causing warnings, subst. by the next two lines t = (void*) this; t2->t31 = (TET3*) t; t2->t32 = nt; } else { t2 = n2->castToTR3(); // t2->t31 = this; causing warnings, subst. by the next two lines t = (void*) this; t2->t31 = (TET3*) t; t2->t32 = 0; } // t3 if ( (nt = n3->castToTET3()) ) { t3 = new TR3; t3->boundP = INTERIOR; t3->depth = depth; t3->p1 = p1; t3->p2 = p2; t3->p3 = p4; t3->e1 = e5; t3->e2 = e6; t3->e3 = e3; completeT(t3,0); // t3->t31 = this; causing warnings, subst. by the next two lines t = (void*) this; t3->t31 = (TET3*) t; t3->t32 = nt; } else { t3 = n3->castToTR3(); // t3->t31 = this; causing warnings, subst. by the next two lines t = (void*) this; t3->t31 = (TET3*) t; t3->t32 = 0; } // t4 if ( (nt = n4->castToTET3()) ) { t4 = new TR3; t4->boundP = INTERIOR; t4->depth = depth; t4->p1 = p1; t4->p2 = p3; t4->p3 = p2; t4->e1 = e2; t4->e2 = e3; t4->e3 = e1; completeT(t4,0); // t4->t31 = this; causing warnings, subst. by the next two lines t = (void*) this; t4->t31 = (TET3*) t; t4->t32 = nt; } else { t4 = n4->castToTR3(); // t4->t31 = this; causing warnings, subst. by the next two lines t = (void*) this; t4->t31 = (TET3*) t; t4->t32 = 0; } trs[1] = t1; trs[2] = t2; trs[3] = t3; trs[4] = t4; } //------------------------------------------------------------------------- void TET3:: getTriangles(TR3* trs[]) { TR3 *t1, *t2, *t3, *t4; TET3 *nt; // t1 if ( (nt = n1->castToTET3()) ) { t1 = new TR3; t1->boundP = INTERIOR; t1->depth = depth; t1->p1 = p2; t1->p2 = p3; t1->p3 = p4; t1->e1 = e4; t1->e2 = e5; t1->e3 = e2; completeT(t1,0); t1->t31 = this; t1->t32 = nt; } else { t1 = n1->castToTR3(); t1->t31 = this; t1->t32 = 0; } // t2 if ( (nt = n2->castToTET3()) ) { t2 = new TR3; t2->boundP = INTERIOR; t2->depth = depth; t2->p1 = p1; t2->p2 = p4; t2->p3 = p3; t2->e1 = e4; t2->e2 = e1; t2->e3 = e6; completeT(t2,0); t2->t31 = this; t2->t32 = nt; } else { t2 = n2->castToTR3(); t2->t31 = this; t2->t32 = 0; } // t3 if ( (nt = n3->castToTET3()) ) { t3 = new TR3; t3->boundP = INTERIOR; t3->depth = depth; t3->p1 = p1; t3->p2 = p2; t3->p3 = p4; t3->e1 = e5; t3->e2 = e6; t3->e3 = e3; completeT(t3,0); t3->t31 = this; t3->t32 = nt; } else { t3 = n3->castToTR3(); t3->t31 = this; t3->t32 = 0; } // t4 if ( (nt = n4->castToTET3()) ) { t4 = new TR3; t4->boundP = INTERIOR; t4->depth = depth; t4->p1 = p1; t4->p2 = p3; t4->p3 = p2; t4->e1 = e2; t4->e2 = e3; t4->e3 = e1; completeT(t4,0); t4->t31 = this; t4->t32 = nt; } else { t4 = n4->castToTR3(); t4->t31 = this; t4->t32 = 0; } trs[1] = t1; trs[2] = t2; trs[3] = t3; trs[4] = t4; } //------------------------------------------------------------------------- void TET3:: returnFaces(Vector& trs) const { for (int i=1; i<=4; i++) if (!(trs[i]->onBoundary())) delete trs[i]; } //------------------------------------------------------------------------- void TET3:: returnTriangles(TR3* trs[]) const { for (int i=1; i<=4; i++) if (!(trs[i]->onBoundary())) delete trs[i]; } //------------------------------------------------------------------------- void TET3:: getNeighbours(Vector& neighbours) const { neighbours[1] = n1->castToTET3(); neighbours[2] = n2->castToTET3(); neighbours[3] = n3->castToTET3(); neighbours[4] = n4->castToTET3(); } //------------------------------------------------------------------------- // -- point at unit coordinate -> point at x void TET3:: realCoordinates(const Vector& u, Vector& x) const { Real L1 = 1.0 - u[1] - u[2] - u[3]; Real L2 = u[1]; Real L3 = u[2]; Real L4 = u[3]; x[1] = L1*p1->x + L2*p2->x + L3*p3->x + L4*p4->x; x[2] = L1*p1->y + L2*p2->y + L3*p3->y + L4*p4->y; x[3] = L1*p1->z + L2*p2->z + L3*p3->z + L4*p4->z; } //------------------------------------------------------------------------- // -- point at x -> unit coordinates void TET3:: unitCoordinates(const Vector& x, Vector& u) const { int i, k; Jacobian J; Vector xn(3); compJinv(J); xn[1] = x[1] - p1->x; xn[2] = x[2] - p1->y; xn[3] = x[3] - p1->z; for (i=1; i<=3; ++i) { u[i] = 0.0; for (k=1; k<=3; ++k) u[i] += J.Jinv(k,i) * xn[k]; } // Jacobian is transposed! } //------------------------------------------------------------------------- void TET3:: getCoordinates(Vector& cP1, Vector& cP2, Vector& cP3, Vector& cP4) const { p1->getCoordinates(cP1); p2->getCoordinates(cP2); p3->getCoordinates(cP3); p4->getCoordinates(cP4); } //------------------------------------------------------------------------- Real TET3:: volume() const { return oneSixth*Abs(detJ); } //------------------------------------------------------------------------- int TET3:: NoOfSons() const { if (type == MESH::T_RED) return 8; else if (type == MESH::T_GREEN_1) return 2; else if (type == MESH::T_GREEN_2A) return 4; else if (type == MESH::T_GREEN_2B) return 3; else if (type == MESH::T_GREEN_3) return 4; else { cout << "\n*** TET3::NoOfSons(): unknown type " << type << "\n"; cout.flush(); abort(); return 0; } } //------------------------------------------------------------------------- Bool TET3:: isGreen() const { switch(type) { case MESH::T_GREEN: case MESH::T_GREEN_1: case MESH::T_GREEN_2A: case MESH::T_GREEN_2B: case MESH::T_GREEN_3: return True; default: return False; } } Bool TR3:: isGreen() const { switch(type) { case MESH::T_GREEN: case MESH::T_GREEN_1: case MESH::T_GREEN_2A: case MESH::T_GREEN_2B: case MESH::T_GREEN_3: return True; default: return False; } } Bool EDG3:: isGreen() const { switch(type) { case MESH::T_GREEN: case MESH::T_GREEN_1: case MESH::T_GREEN_2A: case MESH::T_GREEN_2B: case MESH::T_GREEN_3: return True; default: return False; } } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void EFTET3:: reset() { for (int i=0; i<4; ++i) faceNode[i] = 0; TET3::reset(); } void EFTET3:: getFaceNodes(Vector& nodes) const { int i; for (i=1; i<=4; ++i) nodes[i] = faceNode[i-1]; } int& EFTET3:: getFaceNode(int face) { return faceNode[face-1]; } int& EFTET3:: getMyFaceNode(PATCH* patch) { if (n1 == patch) return faceNode[0]; if (n2 == patch) return faceNode[1]; if (n3 == patch) return faceNode[2]; if (n4 == patch) return faceNode[3]; cout << "\n*** EFTET3:: getMyFaceNode: patch not found\n"; cout.flush(); abort(); return faceNode[0]; // dummy return } //------------------------------------------------------------------------- /*-------------------------------------------------------------------------*/ void MESH3:: setXYZpmCircle(PT3* pm, const EDG3* ed) { Real midPointX, midPointY, midPointZ, radius_new; Real hx1, hy1, hz1, hx2, hy2, hz2, radius; PT3 *P1 = ed->p1, *P2 = ed->p2, *p = pm; // P1,P2 on surface of the ball midPointX = 0.0; midPointY = 0.0; midPointZ = 0.0; hx1 = P1->x-midPointX; hy1 = P1->y-midPointY; hz1 = P1->z-midPointZ; radius = sqrt(hx1*hx1+hy1*hy1+hz1*hz1); p->x = (P1->x)+((P2->x)-(P1->x))*HALF; p->y = (P1->y)+((P2->y)-(P1->y))*HALF; p->z = (P1->z)+((P2->z)-(P1->z))*HALF; hx2 = p->x-midPointX; hy2 = p->y-midPointY; hz2 = p->z-midPointZ; radius_new = sqrt(hx2*hx2+hy2*hy2+hz2*hz2); p->x = midPointX + radius*hx2/radius_new; p->y = midPointY + radius*hy2/radius_new; p->z = midPointZ + radius*hz2/radius_new; } /*-------------------------------------------------------------------------*/ void MESH3:: setXYZpmCyl(PT3* pm, const EDG3* ed) { Real radius,hx1,hy1,hx2,hy2; Real radius_new; PT3 *P1 = ed->p1, *P2 = ed->p2; hx1 = P1->x; hy1 = P1->y; radius = sqrt(hx1*hx1+hy1*hy1); pm->x = (P1->x)+((P2->x)-(P1->x))*HALF; pm->y = (P1->y)+((P2->y)-(P1->y))*HALF; pm->z = (P1->z)+((P2->z)-(P1->z))*HALF; hx2 = pm->x; hy2 = pm->y; radius_new = sqrt(hx2*hx2+hy2*hy2); pm->x = radius*hx2/radius_new; pm->y = radius*hy2/radius_new; } //------------------------------------------------------------------------- void MESH3:: resetElemIter(Bool lastStep) { if (elemIter != 0) { cout << "\n*** resetElemIter: elemIter != 0" << " \t (previous operation not completed?)\n"; cout.flush(); abort(); } if (lastStep) iterLevel = tetList.high(); else iterLevel = 0; } //------------------------------------------------------------------------- PATCH* MESH3:: elemIterAll() { if (elemIter != 0) // iterate rest of list { for (elemIter=elemIter->Next(); elemIter; elemIter=elemIter->Next()) if (!elemIter->refined()) return elemIter; if (++iterLevel > tetList.high()) return 0; } while (1) // iterate new lists on stack { for (elemIter=tetList[iterLevel]->first; elemIter; elemIter=elemIter->Next()) if (!elemIter->refined()) return elemIter; if (++iterLevel > tetList.high()) return 0; } } //------------------------------------------------------------------------- PATCH* MESH3:: elemIterAllOfHistory() { if (elemIter != 0) // iterate rest of list { for (elemIter=elemIter->Next(); elemIter; elemIter=elemIter->Next()) return elemIter; if (++iterLevel > tetList.high()) return 0; } while (1) // iterate new lists on stack { for (elemIter=tetList[iterLevel]->first; elemIter; elemIter=elemIter->Next()) return elemIter; if (++iterLevel > tetList.high()) return 0; } } //------------------------------------------------------------------------- PATCH* MESH3:: edgIterAll() { if (edgIter != 0) // iterate rest of list { for (edgIter=edgIter->Next(); edgIter; edgIter=edgIter->Next()) if (!edgIter->refined()) return edgIter; if (++edgIterLevel > edgList.high()) return 0; } while (1) // iterate new lists on stack { for (edgIter=edgList[edgIterLevel]->first; edgIter; edgIter=edgIter->Next()) if (!edgIter->refined()) return edgIter; if (++edgIterLevel > edgList.high()) return 0; } } //------------------------------------------------------------------------- PATCH* MESH3:: edgIterAllOfHistory() { if (edgIter != 0) // iterate rest of list { for (edgIter=edgIter->Next(); edgIter; edgIter=edgIter->Next()) return edgIter; if (++edgIterLevel > edgList.high()) return 0; } while (1) // iterate new lists on stack { for (edgIter=edgList[edgIterLevel]->first; edgIter; edgIter=edgIter->Next()) return edgIter; if (++edgIterLevel > edgList.high()) return 0; } } //------------------------------------------------------------------------- PATCH* MESH3:: ptIterAll() { if (ptIter != 0) // iterate rest of list { for (ptIter=ptIter->Next(); ptIter; ptIter=ptIter->Next()) if (!ptIter->refined()) return ptIter; if (++ptIterLevel > ptList.high()) return 0; } while (1) // iterate new lists on stack { for (ptIter=ptList[ptIterLevel]->first; ptIter; ptIter=ptIter->Next()) if (!ptIter->refined()) return ptIter; if (++ptIterLevel > ptList.high()) return 0; } }