void randomizeScene(void) { for (int i = 0; i < (int) randFloat(50,100); i++) { // 50 to 100 objects float decideShape = randFloat(0, 1); if (decideShape < 0.7) { // 70% point makeVertex(); finishedShapes.push_back(currentVertices); finishedShapes.back().type = GL_POINTS; clearCurrentVertex(); } else if (decideShape > 0.9) { // 10% polygon for (int i = 0; i < (int)randFloat(3, 7); i++) { // 3 to 7 vertices in a polygon makeVertex(); } finishedShapes.push_back(currentVertices); finishedShapes.back().type = GL_POLYGON; clearCurrentVertex(); } else { // 20% line makeVertex(); makeVertex(); finishedShapes.push_back(currentVertices); finishedShapes.back().type = GL_LINES; clearCurrentVertex(); } } }
vector< vector<double> > MeshTopologyTests::quadPoints(double x0, double y0, double width, double height) { vector< vector<double> > v(4); // defined counterclockwise v[0] = makeVertex(x0,y0); v[1] = makeVertex(x0 + width,y0); v[2] = makeVertex(x0 + width,y0 + height); v[3] = makeVertex(x0,y0 + height); return v; }
vector< vector<double> > MeshTopologyTests::hexPoints(double x0, double y0, double z0, double width, double height, double depth) { vector< vector<double> > v(8); v[0] = makeVertex(x0,y0,z0); v[1] = makeVertex(x0 + width,y0,z0); v[2] = makeVertex(x0 + width,y0 + height,z0); v[3] = makeVertex(x0,y0 + height,z0); v[4] = makeVertex(x0,y0,z0+depth); v[5] = makeVertex(x0 + width,y0,z0 + depth); v[6] = makeVertex(x0 + width,y0 + height,z0 + depth); v[7] = makeVertex(x0,y0 + height,z0 + depth); return v; }
graph* makeGraph(int v , int e){ graph *temp = new graph; int i , j , k,sour , dest,wei,p; vertex *t; temp->noofedges = e; temp->noofvertex = v; temp->v = new vertex*[v]; temp->e = new edge*[e]; for(i = 0 ; i < v ; i ++){ t = makeVertex(i); if(t == NULL){ cout<<"Error Occured"; } temp->v[i] = t; } cout<<"Enter 0 if weighted otherwise 1"<<endl; cin>>j; cout<<"Enter 0 if directed otherwise 1"<<endl; cin>>p; cout<<"Enter the source and destination of edges (between 0 and no. of the edge - 1):- "<<endl; for(i = 0 ; i < e; i++){ cin>>sour>>dest; if(j) wei = 0; else cin>>wei; k = insertAdj(temp->v[sour] , temp->v[dest] , wei); if(p) k = insertAdj(temp->v[dest] , temp->v[sour] , wei); if(k) cout<<"Error in making adjacentylist "; temp->e[i] = makeEdge(temp->v[sour] , temp->v[dest] , wei); } return temp; }
int main(int argc, char *argv[]) { #ifdef HAVE_MPI Teuchos::GlobalMPISession mpiSession(&argc, &argv,0); #endif { // 1D tests CellTopoPtr line_2 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ) ); // let's draw a line vector<double> v0 = makeVertex(0); vector<double> v1 = makeVertex(1); vector<double> v2 = makeVertex(2); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vector<unsigned> line1VertexList; vector<unsigned> line2VertexList; line1VertexList.push_back(0); line1VertexList.push_back(1); line2VertexList.push_back(1); line2VertexList.push_back(2); vector< vector<unsigned> > elementVertices; elementVertices.push_back(line1VertexList); elementVertices.push_back(line2VertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(line_2); cellTopos.push_back(line_2); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); FunctionPtr x = Function::xn(1); FunctionPtr function = x; FunctionPtr fbdr = Function::restrictToCellBoundary(function); vector<FunctionPtr> functions; functions.push_back(function); functions.push_back(function); vector<string> functionNames; functionNames.push_back("function1"); functionNames.push_back("function2"); { XDMFExporter exporter(meshTopology, "function1", false); exporter.exportFunction(function, "function1"); } { XDMFExporter exporter(meshTopology, "boundary1", false); exporter.exportFunction(fbdr, "boundary1"); } { XDMFExporter exporter(meshTopology, "functions1", false); exporter.exportFunction(functions, functionNames); } } { // 2D tests CellTopoPtr quad_4 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() ) ); CellTopoPtr tri_3 = Teuchos::rcp( new shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() ) ); // let's draw a little house vector<double> v0 = makeVertex(-1,0); vector<double> v1 = makeVertex(1,0); vector<double> v2 = makeVertex(1,2); vector<double> v3 = makeVertex(-1,2); vector<double> v4 = makeVertex(0.0,3); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vector<unsigned> quadVertexList; quadVertexList.push_back(0); quadVertexList.push_back(1); quadVertexList.push_back(2); quadVertexList.push_back(3); vector<unsigned> triVertexList; triVertexList.push_back(3); triVertexList.push_back(2); triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(quadVertexList); elementVertices.push_back(triVertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(quad_4); cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); FunctionPtr x2 = Function::xn(2); FunctionPtr y2 = Function::yn(2); FunctionPtr function = x2 + y2; FunctionPtr vect = Function::vectorize(x2, y2); FunctionPtr fbdr = Function::restrictToCellBoundary(function); vector<FunctionPtr> functions; functions.push_back(function); functions.push_back(vect); vector<string> functionNames; functionNames.push_back("function"); functionNames.push_back("vect"); vector<FunctionPtr> bdrfunctions; bdrfunctions.push_back(fbdr); bdrfunctions.push_back(fbdr); vector<string> bdrfunctionNames; bdrfunctionNames.push_back("bdr1"); bdrfunctionNames.push_back("bdr2"); map<int, int> cellIDToNum1DPts; cellIDToNum1DPts[1] = 4; { XDMFExporter exporter(meshTopology, "Grid2D", false); // exporter.exportFunction(function, "function2", 0, 10); // exporter.exportFunction(vect, "vect2", 1, 10, cellIDToNum1DPts); // exporter.exportFunction(fbdr, "boundary2", 0); exporter.exportFunction(functions, functionNames, 1, 10); } { XDMFExporter exporter(meshTopology, "BdrGrid2D", false); // exporter.exportFunction(function, "function2", 0, 10); // exporter.exportFunction(vect, "vect2", 1, 10, cellIDToNum1DPts); // exporter.exportFunction(fbdr, "boundary2", 0); exporter.exportFunction(bdrfunctions, bdrfunctionNames, 1, 10); } //////////////////// DECLARE VARIABLES /////////////////////// // define test variables VarFactory varFactory; VarPtr tau = varFactory.testVar("tau", HDIV); VarPtr v = varFactory.testVar("v", HGRAD); // define trial variables VarPtr uhat = varFactory.traceVar("uhat"); VarPtr fhat = varFactory.fluxVar("fhat"); VarPtr u = varFactory.fieldVar("u"); VarPtr sigma = varFactory.fieldVar("sigma", VECTOR_L2); //////////////////// DEFINE BILINEAR FORM /////////////////////// BFPtr bf = Teuchos::rcp( new BF(varFactory) ); // tau terms: bf->addTerm(sigma, tau); bf->addTerm(u, tau->div()); bf->addTerm(-uhat, tau->dot_normal()); // v terms: bf->addTerm( sigma, v->grad() ); bf->addTerm( fhat, v); //////////////////// BUILD MESH /////////////////////// int H1Order = 4, pToAdd = 2; Teuchos::RCP<Mesh> mesh = Teuchos::rcp( new Mesh (meshTopology, bf, H1Order, pToAdd) ); //////////////////// DEFINE INNER PRODUCT(S) /////////////////////// IPPtr ip = bf->graphNorm(); //////////////////// SPECIFY RHS /////////////////////// RHSPtr rhs = RHS::rhs(); // Teuchos::RCP<RHS> rhs = Teuchos::rcp( new RHS ); FunctionPtr one = Function::constant(1.0); rhs->addTerm( one * v ); //////////////////// CREATE BCs /////////////////////// // Teuchos::RCP<BC> bc = Teuchos::rcp( new BCEasy ); BCPtr bc = BC::bc(); FunctionPtr zero = Function::zero(); SpatialFilterPtr entireBoundary = Teuchos::rcp( new EntireBoundary ); bc->addDirichlet(uhat, entireBoundary, zero); //////////////////// SOLVE & REFINE /////////////////////// Teuchos::RCP<Solution> solution = Teuchos::rcp( new Solution(mesh, bc, rhs, ip) ); solution->solve(false); RefinementStrategy refinementStrategy( solution, 0.2); // Output solution FunctionPtr uSoln = Function::solution(u, solution); FunctionPtr sigmaSoln = Function::solution(sigma, solution); FunctionPtr uhatSoln = Function::solution(uhat, solution); FunctionPtr fhatSoln = Function::solution(fhat, solution); { XDMFExporter exporter(meshTopology, "Poisson", false); exporter.exportFunction(uSoln, "u", 0, 4); exporter.exportFunction(uSoln, "u", 1, 5); exporter.exportFunction(uhatSoln, "uhat", 0, 4); exporter.exportFunction(uhatSoln, "uhat", 1, 5); // exporter.exportFunction(fhatSoln, "fhat", 0, 4); // exporter.exportFunction(fhatSoln, "fhat", 1, 5); } { XDMFExporter exporter(meshTopology, "PoissonSolution", false); exporter.exportSolution(solution, mesh, varFactory, 0, 2, cellIDToSubdivision(mesh, 10)); refinementStrategy.refine(true); solution->solve(false); exporter.exportSolution(solution, mesh, varFactory, 1, 2, cellIDToSubdivision(mesh, 10)); } // exporter.exportFunction(sigmaSoln, "Poisson-s", "sigma", 0, 5); // exporter.exportFunction(uhatSoln, "Poisson-uhat", "uhat", 1, 6); } { // 3D tests CellTopoPtr hex = Teuchos::rcp(new shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() )); // let's draw a little box vector<double> v0 = makeVertex(0,0,0); vector<double> v1 = makeVertex(1,0,0); vector<double> v2 = makeVertex(1,1,0); vector<double> v3 = makeVertex(0,1,0); vector<double> v4 = makeVertex(0,0,1); vector<double> v5 = makeVertex(1,0,1); vector<double> v6 = makeVertex(1,1,1); vector<double> v7 = makeVertex(0,1,1); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vertices.push_back(v5); vertices.push_back(v6); vertices.push_back(v7); vector<unsigned> hexVertexList; hexVertexList.push_back(0); hexVertexList.push_back(1); hexVertexList.push_back(2); hexVertexList.push_back(3); hexVertexList.push_back(4); hexVertexList.push_back(5); hexVertexList.push_back(6); hexVertexList.push_back(7); // vector<unsigned> triVertexList; // triVertexList.push_back(2); // triVertexList.push_back(3); // triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(hexVertexList); // elementVertices.push_back(triVertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(hex); // cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopologyPtr meshTopology = Teuchos::rcp( new MeshTopology(meshGeometry) ); FunctionPtr x = Function::xn(1); FunctionPtr y = Function::yn(1); FunctionPtr z = Function::zn(1); FunctionPtr function = x + y + z; FunctionPtr fbdr = Function::restrictToCellBoundary(function); FunctionPtr vect = Function::vectorize(x, y, z); vector<FunctionPtr> functions; functions.push_back(function); functions.push_back(vect); vector<string> functionNames; functionNames.push_back("function"); functionNames.push_back("vect"); { XDMFExporter exporter(meshTopology, "function3", false); exporter.exportFunction(function, "function3"); } { XDMFExporter exporter(meshTopology, "boundary3", false); exporter.exportFunction(fbdr, "boundary3"); } { XDMFExporter exporter(meshTopology, "vect3", false); exporter.exportFunction(vect, "vect3"); } { XDMFExporter exporter(meshTopology, "functions3", false); exporter.exportFunction(functions, functionNames); } } }
/** * Splits the given line segment at the point (x,y). The new line segment * is returned. The old line segment is shortened (the original start vertex * is unchanged), the new line segment becomes the cut-off tail (keeping * the original end vertex). * * @note If the line segment has a twin it is also split. */ LineSegmentSide &splitLineSegment(LineSegmentSide &frontLeft, Vector2d const &point, bool updateEdgeTips = true) { DENG2_ASSERT(point != frontLeft.from().origin() && point != frontLeft.to().origin()); //LOG_DEBUG("Splitting line segment %p at %s") // << &frontLeft << point.asText(); Vertex *newVert = makeVertex(point); LineSegment &oldSeg = frontLeft.line(); LineSegment &newSeg = *makeLineSegment(oldSeg.from(), oldSeg.to(), oldSeg.front().sectorPtr(), oldSeg.back().sectorPtr(), oldSeg.front().mapSidePtr(), oldSeg.front().partitionMapLine()); // Perform the split, updating vertex and relative segment links. LineSegmentSide &frontRight = newSeg.side(frontLeft.lineSideId()); oldSeg.replaceVertex(frontLeft.lineSideId() ^ LineSegment::To, *newVert); newSeg.replaceVertex(frontLeft.lineSideId(), *newVert); LineSegmentSide &backRight = frontLeft.back(); LineSegmentSide &backLeft = frontRight.back(); if(ConvexSubspaceProxy *convexSet = frontLeft.convexSubspace()) { *convexSet << frontRight; frontRight.setConvexSubspace(convexSet); } frontLeft.setRight(&frontRight); frontRight.setLeft(&frontLeft); // Handle the twin. if(ConvexSubspaceProxy *convexSet = backRight.convexSubspace()) { *convexSet << backLeft; backLeft.setConvexSubspace(convexSet); } backLeft.setRight(&backRight); backRight.setLeft(&backLeft); if(updateEdgeTips) { /// @todo Optimize: Avoid clearing tips by implementing update logic. edgeTipSet(oldSeg.from()).clearByLineSegment(oldSeg); edgeTipSet(oldSeg.to() ).clearByLineSegment(oldSeg); edgeTipSet(newSeg.from()).clearByLineSegment(newSeg); edgeTipSet(newSeg.to() ).clearByLineSegment(newSeg); edgeTipSet(oldSeg.from()) << EdgeTip(oldSeg.front()); edgeTipSet(oldSeg.to()) << EdgeTip(oldSeg.back()); edgeTipSet(newSeg.from()) << EdgeTip(newSeg.front()); edgeTipSet(newSeg.to()) << EdgeTip(newSeg.back()); } return frontRight; }
bool MeshTopologyTests::testEntityConstraints() { bool success = true; // make two simple meshes MeshTopologyPtr mesh2D = makeRectMesh(0.0, 0.0, 2.0, 1.0, 2, 1); MeshTopologyPtr mesh3D = makeHexMesh(0.0, 0.0, 0.0, 2.0, 4.0, 3.0, 2, 2, 1); unsigned vertexDim = 0; unsigned edgeDim = 1; unsigned faceDim = 2; // first, check that unconstrained edges and faces are unconstrained set< unsigned > boundaryEdges; set< unsigned > internalEdges; for (unsigned cellIndex=0; cellIndex<mesh2D->cellCount(); cellIndex++) { CellPtr cell = mesh2D->getCell(cellIndex); unsigned sideCount = cell->getSideCount(); for (unsigned sideOrdinal=0; sideOrdinal<sideCount; sideOrdinal++) { unsigned edgeIndex = cell->entityIndex(edgeDim, sideOrdinal); unsigned numCells = mesh2D->getActiveCellCount(edgeDim,edgeIndex); if (numCells == 1) // boundary edge { boundaryEdges.insert(edgeIndex); } else if (numCells == 2) { internalEdges.insert(edgeIndex); } else { success = false; cout << "testEntityConstraints: In initial 2D mesh, edge " << edgeIndex << " has active cell count of " << numCells << ".\n"; } } } if (internalEdges.size() != 1) { success = false; cout << "testEntityConstraints: In initial 2D mesh, there are " << internalEdges.size() << " internal edges (expected 1).\n"; } for (set<unsigned>::iterator edgeIt=internalEdges.begin(); edgeIt != internalEdges.end(); edgeIt++) { unsigned edgeIndex = *edgeIt; unsigned constrainingEntityIndex = mesh2D->getConstrainingEntity(edgeDim,edgeIndex).first; if (constrainingEntityIndex != edgeIndex) { success = false; cout << "testEntityConstraints: In initial 2D mesh, internal edge is constrained by a different edge.\n"; } } set<unsigned> boundaryFaces; set<unsigned> internalFaces; map<unsigned, vector<unsigned> > faceToEdges; for (unsigned cellIndex=0; cellIndex<mesh3D->cellCount(); cellIndex++) { CellPtr cell = mesh3D->getCell(cellIndex); unsigned sideCount = cell->getSideCount(); for (unsigned sideOrdinal=0; sideOrdinal<sideCount; sideOrdinal++) { unsigned faceIndex = cell->entityIndex(faceDim, sideOrdinal); unsigned numCells = mesh3D->getActiveCellCount(faceDim,faceIndex); if (numCells == 1) // boundary face { boundaryFaces.insert(faceIndex); } else if (numCells == 2) { internalFaces.insert(faceIndex); } else { success = false; cout << "testEntityConstraints: In initial 3D mesh, face " << faceIndex << " has active cell count of " << numCells << ".\n"; } if (faceToEdges.find(faceIndex) == faceToEdges.end()) { CellTopoPtr faceTopo = cell->topology()->getSubcell(faceDim, sideOrdinal); unsigned numEdges = faceTopo->getSubcellCount(edgeDim); vector<unsigned> edgeIndices(numEdges); for (unsigned edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++) { edgeIndices[edgeOrdinal] = mesh3D->getFaceEdgeIndex(faceIndex, edgeOrdinal); } } } } if (internalFaces.size() != 4) { success = false; cout << "testEntityConstraints: In initial 3D mesh, there are " << internalFaces.size() << " internal faces (expected 4).\n"; } for (set<unsigned>::iterator faceIt=internalFaces.begin(); faceIt != internalFaces.end(); faceIt++) { unsigned faceIndex = *faceIt; unsigned constrainingEntityIndex = mesh3D->getConstrainingEntity(faceDim,faceIndex).first; if (constrainingEntityIndex != faceIndex) { success = false; cout << "testEntityConstraints: In initial 3D mesh, internal face is constrained by a different face.\n"; } } // now, make a single refinement in each mesh: unsigned cellToRefine2D = 0, cellToRefine3D = 3; mesh2D->refineCell(cellToRefine2D, RefinementPattern::regularRefinementPatternQuad(), mesh2D->cellCount()); mesh3D->refineCell(cellToRefine3D, RefinementPattern::regularRefinementPatternHexahedron(), mesh3D->cellCount()); // printMeshInfo(mesh2D); // figure out which faces/edges were refined and add the corresponding map<unsigned,pair<IndexType,unsigned> > expectedEdgeConstraints2D; set<unsigned> refinedEdges; for (set<unsigned>::iterator edgeIt=boundaryEdges.begin(); edgeIt != boundaryEdges.end(); edgeIt++) { set<unsigned> children = mesh2D->getChildEntitiesSet(edgeDim, *edgeIt); if (children.size() > 0) { refinedEdges.insert(*edgeIt); boundaryEdges.insert(children.begin(), children.end()); } } for (set<unsigned>::iterator edgeIt=internalEdges.begin(); edgeIt != internalEdges.end(); edgeIt++) { set<unsigned> children = mesh2D->getChildEntitiesSet(edgeDim, *edgeIt); if (children.size() > 0) { refinedEdges.insert(*edgeIt); internalEdges.insert(children.begin(), children.end()); for (set<unsigned>::iterator childIt = children.begin(); childIt != children.end(); childIt++) { unsigned childIndex = *childIt; expectedEdgeConstraints2D[childIndex] = make_pair(*edgeIt, edgeDim); } } } // 1 quad refined: expect 4 refined edges if (refinedEdges.size() != 4) { success = false; cout << "After initial refinement, 2D mesh has " << refinedEdges.size() << " refined edges (expected 4).\n"; } checkConstraints(mesh2D, edgeDim, expectedEdgeConstraints2D); set<unsigned> refinedFaces; map<unsigned,pair<IndexType,unsigned> > expectedFaceConstraints3D; map<unsigned,pair<IndexType,unsigned> > expectedEdgeConstraints3D; for (set<unsigned>::iterator faceIt=boundaryFaces.begin(); faceIt != boundaryFaces.end(); faceIt++) { set<unsigned> children = mesh3D->getChildEntitiesSet(faceDim, *faceIt); if (children.size() > 0) { refinedFaces.insert(*faceIt); boundaryFaces.insert(children.begin(), children.end()); } } for (set<unsigned>::iterator faceIt=internalFaces.begin(); faceIt != internalFaces.end(); faceIt++) { vector<unsigned> children = mesh3D->getChildEntities(faceDim, *faceIt); if (children.size() > 0) { refinedFaces.insert(*faceIt); internalFaces.insert(children.begin(), children.end()); for (unsigned childOrdinal = 0; childOrdinal < children.size(); childOrdinal++) { unsigned childIndex = children[childOrdinal]; expectedFaceConstraints3D[childIndex] = make_pair(*faceIt, faceDim); unsigned numEdges = 4; unsigned internalEdgeCount = 0; // for each child of a quad, we expect to have 2 internal edges for (unsigned edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++) { unsigned edgeIndex = mesh3D->getFaceEdgeIndex(childIndex, edgeOrdinal); unsigned activeCellCount = mesh3D->getActiveCellCount(edgeDim, edgeIndex); if (activeCellCount==2) { internalEdgeCount++; expectedEdgeConstraints3D[edgeIndex] = make_pair(*faceIt, faceDim); } else if (activeCellCount==1) // hanging edge { if (! mesh3D->entityHasParent(edgeDim, edgeIndex)) { cout << "Hanging edge with edgeIndex " << edgeIndex << " (in face " << childIndex << ") does not have a parent edge.\n"; cout << "Edge vertices:\n"; mesh3D->printEntityVertices(edgeDim, edgeIndex); cout << "Face vertices:\n"; mesh3D->printEntityVertices(faceDim, childIndex); success = false; } else { unsigned edgeParentIndex = mesh3D->getEntityParent(edgeDim, edgeIndex); expectedEdgeConstraints3D[edgeIndex] = make_pair(edgeParentIndex, edgeDim); } } else { cout << "Unexpected number of active cells: " << activeCellCount << endl; } } if (internalEdgeCount != 2) { cout << "Expected internalEdgeCount to be 2; was " << internalEdgeCount << endl; success = false; } } } } // 1 hex refined: expect 6 refined faces if (refinedFaces.size() != 6) { success = false; cout << "After initial refinement, 3D mesh has " << refinedFaces.size() << " refined faces (expected 6).\n"; } if (! checkConstraints(mesh3D, faceDim, expectedFaceConstraints3D, "refined 3D mesh") ) { cout << "Failed face constraint check for refined 3D mesh." << endl; success = false; } if (! checkConstraints(mesh3D, edgeDim, expectedEdgeConstraints3D, "refined 3D mesh") ) { cout << "Failed edge constraint check for refined 3D mesh." << endl; success = false; } // now, we refine one of the children of the refined cells in each mesh, to produce a 2-level constraint set<unsigned> edgeChildren2D; set<unsigned> cellsForEdgeChildren2D; for (map<unsigned,pair<IndexType,unsigned> >::iterator edgeConstraint=expectedEdgeConstraints2D.begin(); edgeConstraint != expectedEdgeConstraints2D.end(); edgeConstraint++) { edgeChildren2D.insert(edgeConstraint->first); unsigned cellIndex = mesh2D->getActiveCellIndices(edgeDim, edgeConstraint->first).begin()->first; cellsForEdgeChildren2D.insert(cellIndex); // cout << "cellsForEdgeChildren2D: " << cellIndex << endl; } // one of these has (1,0) as one of its vertices. Let's figure out which one: unsigned vertexIndex; if (! mesh2D->getVertexIndex(makeVertex(1, 0), vertexIndex) ) { cout << "Error: vertex not found.\n"; success = false; } vector< pair<unsigned,unsigned> > cellsForVertex = mesh2D->getActiveCellIndices(vertexDim, vertexIndex); if (cellsForVertex.size() != 2) { cout << "cellsForVertex should have 2 entries; has " << cellsForVertex.size() << endl; success = false; } unsigned childCellForVertex, childCellConstrainedEdge; set<unsigned> childNewlyConstrainingEdges; // the two interior edges that we break for (vector< pair<unsigned,unsigned> >::iterator cellIt=cellsForVertex.begin(); cellIt != cellsForVertex.end(); cellIt++) { // cout << "cellsForVertex: " << cellIt->first << endl; if ( cellsForEdgeChildren2D.find( cellIt->first ) != cellsForEdgeChildren2D.end() ) { // found match childCellForVertex = cellIt->first; // now, figure out which of the "edgeChildren2D" is shared by this cell: CellPtr cell = mesh2D->getCell(childCellForVertex); unsigned numEdges = cell->getSideCount(); for (unsigned edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++) { unsigned edgeIndex = cell->entityIndex(edgeDim, edgeOrdinal); if (edgeChildren2D.find(edgeIndex) != edgeChildren2D.end()) { childCellConstrainedEdge = edgeIndex; } else if ( mesh2D->getActiveCellCount(edgeDim, edgeIndex) == 2 ) { childNewlyConstrainingEdges.insert(edgeIndex); } } } } if (childNewlyConstrainingEdges.size() != 2) { cout << "Expected 2 newly constraining edges after 2nd refinement of 2D mesh, but found " << childNewlyConstrainingEdges.size() << endl; success = false; } // refine the cell that matches (1,0): mesh2D->refineCell(childCellForVertex, RefinementPattern::regularRefinementPatternQuad(), mesh2D->cellCount()); // now, fix the expected edge constraints, then check them... set<unsigned> childEdges = mesh2D->getChildEntitiesSet(edgeDim, childCellConstrainedEdge); if (childEdges.size() != 2) { cout << "Expected 2 child edges, but found " << childEdges.size() << ".\n"; success = false; } for (set<unsigned>::iterator edgeIt = childEdges.begin(); edgeIt != childEdges.end(); edgeIt++) { expectedEdgeConstraints2D[*edgeIt] = expectedEdgeConstraints2D[childCellConstrainedEdge]; } expectedEdgeConstraints2D.erase(childCellConstrainedEdge); for (set<unsigned>::iterator edgeIt = childNewlyConstrainingEdges.begin(); edgeIt != childNewlyConstrainingEdges.end(); edgeIt++) { set<unsigned> newChildEdges = mesh2D->getChildEntitiesSet(edgeDim, *edgeIt); for (set<unsigned>::iterator newEdgeIt = newChildEdges.begin(); newEdgeIt != newChildEdges.end(); newEdgeIt++) { expectedEdgeConstraints2D[*newEdgeIt] = make_pair(*edgeIt,edgeDim); } } if (! checkConstraints(mesh2D, edgeDim, expectedEdgeConstraints2D, "twice-refined 2D mesh") ) { cout << "Failed constraint check for twice-refined 2D mesh." << endl; success = false; } // now, do a second level of refinement for 3D mesh // one of these has (1,2,0) as one of its vertices. Let's figure out which one: if (! mesh3D->getVertexIndex(makeVertex(1, 2, 0), vertexIndex) ) { cout << "Error: vertex not found.\n"; success = false; } cellsForVertex = mesh3D->getActiveCellIndices(vertexDim, vertexIndex); if (cellsForVertex.size() != 4) { cout << "cellsForVertex should have 4 entries; has " << cellsForVertex.size() << endl; success = false; } vector<unsigned> justCellsForVertex; for (vector< pair<unsigned,unsigned> >::iterator entryIt = cellsForVertex.begin(); entryIt != cellsForVertex.end(); entryIt++) { justCellsForVertex.push_back(entryIt->first); } vector<unsigned> childCellIndices = mesh3D->getCell(cellToRefine3D)->getChildIndices(mesh3D); std::sort(childCellIndices.begin(), childCellIndices.end()); vector<unsigned> matches(childCellIndices.size() + cellsForVertex.size()); vector<unsigned>::iterator matchEnd = std::set_intersection(justCellsForVertex.begin(), justCellsForVertex.end(), childCellIndices.begin(), childCellIndices.end(), matches.begin()); matches.resize(matchEnd-matches.begin()); if (matches.size() != 1) { cout << "matches should have exactly one entry, but has " << matches.size(); success = false; } unsigned childCellIndex = matches[0]; CellPtr childCell = mesh3D->getCell(childCellIndex); set<unsigned> childInteriorUnconstrainedFaces; set<unsigned> childInteriorConstrainedFaces; unsigned faceCount = childCell->getSideCount(); for (unsigned faceOrdinal=0; faceOrdinal<faceCount; faceOrdinal++) { unsigned faceIndex = childCell->entityIndex(faceDim, faceOrdinal); if (mesh3D->getActiveCellCount(faceDim, faceIndex) == 1) { // that's an interior constrained face, or a boundary face if (expectedFaceConstraints3D.find(faceIndex) != expectedFaceConstraints3D.end()) { // constrained face childInteriorConstrainedFaces.insert(faceIndex); } } else if (mesh3D->getActiveCellCount(faceDim, faceIndex) == 2) { // an interior unconstrained face childInteriorUnconstrainedFaces.insert(faceIndex); } else { cout << "Error: unexpected active cell count. Expected 1 or 2, but was " << mesh3D->getActiveCellCount(faceDim, faceIndex) << endl; success = false; } } // Camellia::print("childInteriorUnconstrainedFaces", childInteriorUnconstrainedFaces); // Camellia::print("childInteriorConstrainedFaces", childInteriorConstrainedFaces); mesh3D->refineCell(childCellIndex, RefinementPattern::regularRefinementPatternHexahedron(), mesh3D->cellCount()); // update expected face and edge constraints // set<unsigned> edgeConstraintsToDrop; for (set<unsigned>::iterator faceIt=childInteriorConstrainedFaces.begin(); faceIt != childInteriorConstrainedFaces.end(); faceIt++) { unsigned faceIndex = *faceIt; set<unsigned> newChildFaces = mesh3D->getChildEntitiesSet(faceDim, faceIndex); for (set<unsigned>::iterator newChildIt=newChildFaces.begin(); newChildIt != newChildFaces.end(); newChildIt++) { unsigned newChildIndex = *newChildIt; expectedFaceConstraints3D[newChildIndex] = expectedFaceConstraints3D[faceIndex]; // cout << "Expecting two-level face constraint: face " << newChildIndex << " constrained by face " << expectedFaceConstraints3D[newChildIndex].first << endl; } unsigned numEdges = mesh3D->getSubEntityCount(faceDim, faceIndex, edgeDim); set<IndexType> childEdgesOnParentBoundary; for (unsigned edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++) { unsigned edgeIndex = mesh3D->getSubEntityIndex(faceDim, faceIndex, edgeDim, edgeOrdinal); set<unsigned> newChildEdges = mesh3D->getChildEntitiesSet(edgeDim, edgeIndex); for (set<unsigned>::iterator newChildIt=newChildEdges.begin(); newChildIt != newChildEdges.end(); newChildIt++) { unsigned newChildIndex = *newChildIt; expectedEdgeConstraints3D[newChildIndex] = expectedEdgeConstraints3D[edgeIndex]; // cout << "Expecting two-level edge constraint: edge " << newChildIndex << " constrained by "; // cout << typeString(expectedEdgeConstraints3D[newChildIndex].second) << " " << expectedEdgeConstraints3D[newChildIndex].first << endl; childEdgesOnParentBoundary.insert(newChildIndex); // edgeConstraintsToDrop.insert(edgeIndex); } } for (set<unsigned>::iterator newChildIt=newChildFaces.begin(); newChildIt != newChildFaces.end(); newChildIt++) { unsigned newChildFaceIndex = *newChildIt; int numEdges = mesh3D->getSubEntityCount(faceDim, newChildFaceIndex, edgeDim); for (unsigned edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++) { unsigned newChildEdgeIndex = mesh3D->getSubEntityIndex(faceDim, newChildFaceIndex, edgeDim, edgeOrdinal); if (childEdgesOnParentBoundary.find(newChildEdgeIndex) == childEdgesOnParentBoundary.end()) { expectedEdgeConstraints3D[newChildEdgeIndex] = expectedFaceConstraints3D[faceIndex]; } } } expectedFaceConstraints3D.erase(faceIndex); } // for (set<unsigned>::iterator edgeToDropIt=edgeConstraintsToDrop.begin(); edgeToDropIt != edgeConstraintsToDrop.end(); edgeToDropIt++) { // expectedEdgeConstraints3D.erase(*edgeToDropIt); // } for (set<unsigned>::iterator faceIt=childInteriorUnconstrainedFaces.begin(); faceIt != childInteriorUnconstrainedFaces.end(); faceIt++) { unsigned faceIndex = *faceIt; set<unsigned> newChildFaces = mesh3D->getChildEntitiesSet(faceDim, faceIndex); for (set<unsigned>::iterator newChildIt=newChildFaces.begin(); newChildIt != newChildFaces.end(); newChildIt++) { unsigned newChildIndex = *newChildIt; expectedFaceConstraints3D[newChildIndex] = make_pair(faceIndex, faceDim); } expectedFaceConstraints3D.erase(faceIndex); unsigned numEdges = mesh3D->getSubEntityCount(faceDim, faceIndex, edgeDim); set<IndexType> childEdgesOnParentBoundary; for (unsigned edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++) { unsigned edgeIndex = mesh3D->getSubEntityIndex(faceDim, faceIndex, edgeDim, edgeOrdinal); set<unsigned> newChildEdges = mesh3D->getChildEntitiesSet(edgeDim, edgeIndex); for (set<unsigned>::iterator newChildIt=newChildEdges.begin(); newChildIt != newChildEdges.end(); newChildIt++) { unsigned newChildIndex = *newChildIt; if (expectedEdgeConstraints3D.find(newChildIndex) == expectedEdgeConstraints3D.end()) // only impose edge constraint if there is not one already present { expectedEdgeConstraints3D[newChildIndex] = make_pair(edgeIndex,edgeDim); } childEdgesOnParentBoundary.insert(newChildIndex); } } for (set<unsigned>::iterator newChildIt=newChildFaces.begin(); newChildIt != newChildFaces.end(); newChildIt++) { unsigned newChildFaceIndex = *newChildIt; int numEdges = mesh3D->getSubEntityCount(faceDim, newChildFaceIndex, edgeDim); for (unsigned edgeOrdinal=0; edgeOrdinal<numEdges; edgeOrdinal++) { unsigned newChildEdgeIndex = mesh3D->getSubEntityIndex(faceDim, newChildFaceIndex, edgeDim, edgeOrdinal); if (childEdgesOnParentBoundary.find(newChildEdgeIndex) == childEdgesOnParentBoundary.end()) { if (expectedEdgeConstraints3D.find(newChildEdgeIndex) == expectedEdgeConstraints3D.end()) // only impose edge constraint if there is not one already present { expectedEdgeConstraints3D[newChildEdgeIndex] = make_pair(faceIndex, faceDim); } } } } } if (! checkConstraints(mesh3D, edgeDim, expectedEdgeConstraints3D, "twice-refined 3D mesh") ) { cout << "Failed edge constraint check for twice-refined 3D mesh." << endl; success = false; } if (! checkConstraints(mesh3D, faceDim, expectedFaceConstraints3D, "twice-refined 3D mesh") ) { cout << "Failed face constraint check for twice-refined 3D mesh." << endl; success = false; } return success; }
bool MeshTopologyTests::test2DMesh() { bool success = true; CellTopoPtr quad_4 = Camellia::CellTopology::quad(); CellTopoPtr tri_3 = Camellia::CellTopology::triangle(); RefinementPatternPtr quadRefPattern = RefinementPattern::regularRefinementPatternQuad(); RefinementPatternPtr triangleRefPattern = RefinementPattern::regularRefinementPatternTriangle(); // let's draw a little house vector<double> v0 = makeVertex(0,0); vector<double> v1 = makeVertex(1,0); vector<double> v2 = makeVertex(1,1); vector<double> v3 = makeVertex(0,1); vector<double> v4 = makeVertex(0.5,1.5); vector< vector<double> > vertices; vertices.push_back(v0); vertices.push_back(v1); vertices.push_back(v2); vertices.push_back(v3); vertices.push_back(v4); vector<unsigned> quadVertexList; quadVertexList.push_back(0); quadVertexList.push_back(1); quadVertexList.push_back(2); quadVertexList.push_back(3); vector<unsigned> triVertexList; triVertexList.push_back(2); triVertexList.push_back(3); triVertexList.push_back(4); vector< vector<unsigned> > elementVertices; elementVertices.push_back(quadVertexList); elementVertices.push_back(triVertexList); vector< CellTopoPtr > cellTopos; cellTopos.push_back(quad_4); cellTopos.push_back(tri_3); MeshGeometryPtr meshGeometry = Teuchos::rcp( new MeshGeometry(vertices, elementVertices, cellTopos) ); MeshTopology mesh(meshGeometry); if (mesh.cellCount() != 2) { success = false; cout << "After initialization, mesh doesn't have the expected number of cells.\n"; } if (mesh.activeCellCount() != 2) { success = false; cout << "After initialization, mesh doesn't have the expected number of active cells.\n"; } mesh.refineCell(0, quadRefPattern, mesh.cellCount()); if (mesh.cellCount() != 6) { success = false; cout << "After quad refinement, mesh doesn't have the expected number of cells.\n"; } if (mesh.activeCellCount() != 5) { success = false; cout << "After quad refinement, mesh doesn't have the expected number of active cells.\n"; } mesh.refineCell(1, triangleRefPattern, mesh.cellCount()); if (mesh.cellCount() != 10) { success = false; cout << "After triangle refinement, mesh doesn't have the expected number of cells.\n"; } if (mesh.activeCellCount() != 8) { success = false; cout << "After triangle refinement, mesh doesn't have the expected number of active cells.\n"; } // TODO: test more than just the count. Test vertex locations, say. Test constraint counts (should be 0 here after both initial cells refined, 1 constrained edge after the first refinement). return success; }