/* $Id: triang1.cc,v 1.5 1996/11/06 12:26:19 roitzsch Exp $ (C)opyright 1996 by Konrad-Zuse-Center, Berlin All rights reserved. Part of the Kaskade distribution */ #include "triang1.h" #include "utils.h" #include "numerics.h" #include "mzibutil.h" #if NOKASKPLOT == 0 #include "feplot1.h" #endif #include "cmdpars.h" extern CmdPars Cmd; Vector EDG1::p(2); Vector EDG1::e(1); Vector EDG1::f(2); MESH1:: MESH1(const char* inFileName, Bool readMesh) : MESH(inFileName), ptList(0,25), edgList(0,25), ptAlloc(ElementsInBlock), edgAlloc(ElementsInBlock) { noOfPoints = 0; noOfEdges = 0; if (readMesh) readTriangulation(fileName); } //------------------------------------------------------------------------- MESH1:: ~MESH1() { int i; FORALL( ptList,i) delete ptList[i]; FORALL(edgList,i) delete edgList[i]; } //------------------------------------------------------------------------- FEPlot* MESH1:: newFEPlot(int plotType, char* caption, float size) { #if NOKASKPLOT == 0 return new FEPlotMESH1(this, plotType, caption, size); #else return 0; #endif } //------------------------------------------------------------------------- void MESH1:: readTriangulation(const char* fileName0) { int i, maxIndex; DList* ptL = new DList; ptList.push(ptL); DList* edgL = new DList; edgList.push(edgL); BufferedParser parser(fileName0, "end", CommentFlag); if (parser.findWord("Poin") != parser.ok) missingItem("points",fileName0); if (parser.findWord("max") != parser.ok) missingItem("maxIndex",fileName0); 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("triangles",fileName0); readElements(parser, ptAdr); if (parser.findWord("Boun") != parser.ok) missingItem("boundary",fileName0); readBoundary(parser, ptAdr); EDG1* e; DListIter iter(edges()); while ((e=iter.all())) e->setBoundary(); if (infoRefinement) Info(); if (Cmd.isTrue("printMesh")) cout << *this; } //------------------------------------------------------------------------- void MESH1:: readPoints(BufferedParser& parser, Vector& ptAdr) { int ptNo, count=0; PT1* p; while (parser.getValue(&ptNo) == parser.ok) { if (ptNo > ptAdr.high()) pointIndexError(ptNo); p = ptAlloc.Get(); //new PT1; ptAdr[ptNo] = p; parser.getValue(&p->x); p->node = ++count; // used in Find... ptList[0]->add(p); ++noOfPoints; } } //------------------------------------------------------------------------- void MESH1:: readElements(BufferedParser& parser, Vector& ptAdr) { int pNo1, pNo2, classA; EDG1 *e; while (parser.getValue(&pNo1) == parser.ok) { parser.getValue(&pNo2); e = getEDG1(); // new EDG1; e->p1 = ptAdr[pNo1]; e->p2 = ptAdr[pNo2]; setRightHand(e); parser.getValue(&classA); e->classA = classA; SetEP(e); edgList[0]->add(e); ++noOfEdges; } } //------------------------------------------------------------------------- void MESH1:: writeTriangulation(const char* outFileText, const Vector& u) const { int i; int node; EDG1 *ed; PT1 *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\n", p->node, p->x); node++; } fprintf(outFile, "END\n"); fprintf(outFile, "\nElements:\n"); DListIter iterEds(edges()); while ((ed=iterEds.all())) { fprintf(outFile, "%d %d %d\n", (ed->p1)->node, (ed->p2)->node, ed->classA ); } fprintf(outFile, "END\n"); fprintf(outFile, "\nBoundary: \n"); iterPts.reset(); while ((p=iterPts.all())) { if (!p->onBoundary()) continue; if (p->isDirichlet()) fprintf(outFile, "%d d %d\n", p->node, p->classA ); else if (p->isNeumann()) fprintf(outFile, "%d n %d\n", p->node, p->classA ); else if (p->isCauchy()) fprintf(outFile, "%d c %d\n", p->node, p->classA ); } 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 WriteZIB-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 MESH1:: setRightHand(EDG1* e) { if (e->p2->x < e->p1->x) { PT1* p = e->p2; e->p2 = e->p1; e->p1 = p; } } //------------------------------------------------------------------------- void MESH1:: readBoundary(BufferedParser& parser, Vector& ptAdr) { int pNo; PT1 *p; while (parser.getValue(&pNo) == parser.ok) { p = ptAdr[pNo]; if (!p->onBoundary()) boundaryWarning(pNo); p->readBC(parser); } } //------------------------------------------------------------------------- void MESH1:: Refine() { EDG1* e; int noPt[2], noEdg[2]; Timer timer, accTimer; noPt[0] = noOfPoints; noEdg[0] = noOfEdges; DList* edgL = new DList; edgList.push(edgL); DListIter iter(edges()); while ((e=iter.all())) { if (e->mark) RefineEdge(e); } noPt[1] = noOfPoints; noEdg[1] = noOfEdges; ++refStep; if (infoRefinement) refinementInfo (noPt, noEdg); timeInfo(timer, accTimer); if (Cmd.isTrue("printMesh")) cout << *this; } //------------------------------------------------------------------------- void MESH1:: Flatten() { int noReleasedEdges=0; int noPoints=0, noEdges=0; int k; EDG1* ed; PT1* p; DList* edgL = new DList; DList* ptL = new DList; Stack edgToRetain(25), edgToRelease(25); Stack ptToRetain(25); DListIter iterEdg(edges()); DListIter iterPt(points()); while ((ed=iterEdg.allOfHistory())) { if (!ed->refined()) { edgToRetain.push(ed); noEdges++; } else { edgToRelease.push(ed); noReleasedEdges++; } } while ((p=iterPt.allOfHistory())) { ptToRetain.push(p); noPoints++; } while (!edgList.empty()) { delete edgList.pop(); } edgList.push(edgL); while (!ptList.empty()) { delete ptList.pop(); } ptList.push(ptL); for (k=ptToRetain.l; k<=ptToRetain.h; k++) { p = ptToRetain[k]; ptL->add(p); p->depth = 0; } for (k=edgToRetain.l; k<=edgToRetain.h; k++) { ed = edgToRetain[k]; ed->father = nil; ed->depth = 0; edgL->add(ed); } while (!edgToRelease.empty()) { ed = edgToRelease.pop(); edgAlloc.Return(ed); } refStep = 0; maxDepth = 0; ptIterLevel = 0; iterLevel = 0; noOfPoints = noPoints; noOfEdges = noEdges; if (infoRefinement) { cout << "\n Flatten: " << noReleasedEdges << " edges released\n"; cout << " " << noPoints << " points, " << noEdges << " edges retained\n"; } return; } //------------------------------------------------------------------------- Bool MESH1:: RefineEdge(EDG1 *ed) { EDG1 *e1, *e2; PT1 *pm; e1 = getEDG1(); e2 = getEDG1(); ++noOfEdges; pm = ptAlloc.Get(); // new PT1; assert(pm != 0); ++noOfPoints; ed->pm = pm; pm->depth = ed->depth + 1; pm->x = 0.5*(ed->p1->x + ed->p2->x); e1->p1 = ed->p1; e1->p2 = pm; e2->p1 = pm; e2->p2 = ed->p2; e1->father = e2->father = ed; e1->type = e2->type = ed->type; e1->classA = e2->classA = ed->classA; e1->depth = e2->depth = ed->depth + 1; ed->firstSon = e1; DelEP(ed); SetEP(e1); SetEP(e2); edgList[edgList.h]->add(e1); edgList[edgList.h]->add(e2); if (pm->depth > ptList.h) { DList* ptL = new DList; ptList.push(ptL); } ptList[pm->depth]->add(pm); if (e1->depth > maxDepth) maxDepth = e1->depth; return True; } //------------------------------------------------------------------------- // -- SetEP(e): set edge e on its points void MESH1:: SetEP(EDG1 *e) { PT1 *p1, *p2;; int k = 0; p1 = e->p1; if (p1->e1 == 0) { p1->e1 = e; ++k; } else if (p1->e2 == 0) { p1->e2 = e; ++k; } p2 = e->p2; if (p2->e1 == 0) { p2->e1 = e; ++k; } else if (p2->e2 == 0) { p2->e2 = e; ++k; } if (k != 2) { cout << "\n*** SetEP: Edge with impossible state, k = " << k << "\n"; printf("\n e->p1: %p",e->p1); printf("\n e->p2: %p",e->p2); e->print(cout); cout.flush(); abort(); } if (p1->onBoundary() || p2->onBoundary()) e->boundP = BOUNDARY; } //------------------------------------------------------------------------- // -- DelEP(e): delete edge e on its points void MESH1:: DelEP(EDG1 *e) { PT1* p; int k = 0; p = e->p1; if (p->e1 == e) { p->e1 = 0; ++k; } else if (p->e2 == e) { p->e2 = 0; ++k; } p = e->p2; if (p->e1 == e) { p->e1 = 0; ++k; } else if (p->e2 == e) { p->e2 = 0; ++k; } if (k != 2) { cout << "\n*** DelEP: impossible state, k = " << k << ")\n"; cout.flush(); abort(); } } //------------------------------------------------------------------------- void MESH1:: Info() { cout << "\n Triangulation: points edges " << " Depth=" << maxDepth << " Steps=" << refStep << Form("\n%15s%10d%10d", " ", noOfPoints, noOfEdges) << "\n"; } //------------------------------------------------------------------------- int MESH1:: MemSpace() { int space = varAllocator.MemSpace(); space += edgAlloc.MemSpace(); space += ptAlloc.MemSpace(); return space; } //------------------------------------------------------------------------- void MESH1:: refinementInfo(int* noPt, int* noEdg) { int blocks = varAllocator.NoOfBlocks(); blocks += edgAlloc.NoOfBlocks(); blocks += ptAlloc.NoOfBlocks(); int space = MemSpace(); /* FORALL (edgList,depth) { space += edgList[depth]->noOfElements * sizeof(EDG1); if (depth <= ptList.h) space += ptList[depth]->noOfElements * sizeof(PT1); } */ cout << "\n Refine: points edges " << " Depth=" << maxDepth << " Steps=" << refStep << Form("\n%15s%10d%10d", "previous", noPt[0], noEdg[0]); if (infoRefinement > 1) { cout << Form("\n%15s%10d%10d", "generated", noPt[1]-noPt[0], noEdg[1]-noEdg[0]); } cout << Form("\n%15s%10d%10d Space : %1.6f MB","total", noOfPoints, noOfEdges, float(space)/1e6); cout << Form("\n%15s%10.2f%10.2f Blocks: %1d\n","ratio", float(noOfPoints)/noPt[0], float(noOfEdges)/noEdg[0], blocks); if (infoRefinement > 2) { int npDepth, step, np=0, ne=0; cout << "\n Grid Statistics:" << Form("\n%15s%10s%10s%10s", "depth/step", "points", "edges", "(total)"); FORALL (edgList,step) { npDepth = (step<=ptList.h)? ptList[step]->noOfElements : 0; cout << Form("\n%15d%10d%10d", step, npDepth, edgList[step]->noOfElements); np += npDepth; ne += edgList[step]->noOfElements; } cout << Form("\n%15s%10d%10d", "total sum", np, ne); cout << "\n"; } } //------------------------------------------------------------------------- ostream& operator << (ostream& os, const MESH1& t) { PT1* p; EDG1* e; os << "\nTriangulation"; if (t.fileName) os << " " << t.fileName; os <<":\n"; DListIter iterPT (t.points()); DListIter iterEDG(t.edges()); while ((p = iterPT.all())) p->print(cout); while ((e = iterEDG.all())) e->print(cout); os << "\nRefinement step " << t.refStep; os << " -- points: " << t.noOfPoints; os << " edges: " << t.noOfEdges; os << "\n"; return os; } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void PT1:: print(ostream& os) const { os << "Point " << node << " BC " << (int) boundP << " class " << (int) classA << " mark " << (int) mark << " x: " << x << "\n"; } void PT1:: reset() { boundP = INTERIOR; mark = classA = depth = NUL; node = 0; e1 = e2 = 0; } //------------------------------------------------------------------------- void PT1:: getNodeCoord(Vector& v) const { v[1] = x; } //------------------------------------------------------------------------- void PT1:: getCoordinates(Vector& v) const { v[1] = x; } //------------------------------------------------------------------------- void PT1:: readBC(BufferedParser& parser) { readBCValues(&boundP, &classA, parser); } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void EDG1:: compJ(Jacobian& j, Bool /*checkDetJ*/) const { j.J(1,1) = p2->x - p1->x; j.detJ = j.J(1,1); } void EDG1:: compJinv(Jacobian& j) const { compJ(j); j.Jinv(1,1) = 1./j.J(1,1); } //------------------------------------------------------------------------- void EDG1:: print(ostream& os) const { os << "Edge with points " << p1->node << " " << p2->node << " type " << (int) type << " class " << (int) classA << " depth " << (int) depth << "\n"; } void EDG1:: reset() { mark = classA = type = depth = NUL; boundP = INTERIOR; p1 = p2 = pm = 0; node = 0; father = firstSon = 0; error = 0.0; } void EDG1:: setBoundary() { if (p1->onBoundary() || p2->onBoundary()) boundP = BOUNDARY; } //------------------------------------------------------------------------- void EDG1:: getNeighbours(Vector& neighbours) const { if (p1->e1 != this) neighbours[1] = p1->e1; else neighbours[1] = p1->e2; if (p2->e1 != this) neighbours[2] = p2->e1; else neighbours[2] = p2->e2; } //------------------------------------------------------------------------- // -- point at unit coordinate -> point at x void EDG1:: 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; } //------------------------------------------------------------------------- // -- point at x -> unit coordinates void EDG1:: unitCoordinates(const Vector& x, Vector& u) const { u[1] = (x[1] - p1->x) / (p2->x - p1->x); } //------------------------------------------------------------------------- void EDG1:: getNodeCoord(Vector& v) const { v[1] = 0.5*(p1->x + p2->x); } //------------------------------------------------------------------------- void EDG1:: getCoordinates(Vector& cP1, Vector& cP2) const { p1->getCoordinates(cP1); p2->getCoordinates(cP2); } void EDG1:: compNormalVector(Vector& /*n*/, Real* /*length*/) const { notImplemented("compNormalVector"); } //------------------------------------------------------------------------- Real EDG1:: hMax() const { return Abs(p2->x - p1->x); } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void MESH1:: resetElemIter(Bool lastStep) { if (elemIter != 0) { cout << "\n*** resetElemIter: elemIter != 0" << " \t (previous operation not completed?)\n"; cout.flush(); abort(); } if (lastStep) iterLevel = edgList.high(); else iterLevel = 0; } //------------------------------------------------------------------------- PATCH* MESH1:: elemIterAll() { if (elemIter != 0) // iterate rest of list { for (elemIter=elemIter->Next(); elemIter; elemIter=elemIter->Next()) if (!elemIter->refined()) return elemIter; if (++iterLevel > edgList.high()) return 0; } while (1) // iterate new lists on stack { for (elemIter=edgList[iterLevel]->first; elemIter; elemIter=elemIter->Next()) if (!elemIter->refined()) return elemIter; if (++iterLevel > edgList.high()) return 0; } } //------------------------------------------------------------------------- PATCH* MESH1:: elemIterAllOfHistory() { if (elemIter != 0) // iterate rest of list { for (elemIter=elemIter->Next(); elemIter; elemIter=elemIter->Next()) return elemIter; if (++iterLevel > edgList.high()) return 0; } while (1) // iterate new lists on stack { for (elemIter=edgList[iterLevel]->first; elemIter; elemIter=elemIter->Next()) return elemIter; if (++iterLevel > edgList.high()) return 0; } } //------------------------------------------------------------------------- //------------------------------------------------------------------------- PATCH* MESH1:: 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* MESH1:: 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* MESH1:: 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; } }