void fixVolumes ( RegionMesh& mesh, const std::vector<bool>& elSign, Switch& sw ) { for ( ID i = 0; i < mesh.numVolumes(); i++ ) { if ( ! elSign[ i ] ) { mesh.volume (i).reversePoints(); } } sw.create ("HAS_VOLUMES", true); }
Real checkVolumes ( RegionMesh const& mesh, std::vector<bool>& elSign, Switch& sw ) { Real meas = 0.0; Real lmeas = 0.0; elSign.clear(); elSign.reserve ( mesh.numVolumes() ); typedef typename RegionMesh::elementShape_Type GeoShape; switch ( GeoShape::S_shape ) { case TETRA: { CurrentFE fe ( feTetraP1, geoLinearTetra, quadRuleTetra1pt ); for ( ID i = 0; i < mesh.numVolumes(); i++ ) { fe.updateJac ( mesh.volume ( i ) ); lmeas = fe.measure(); meas += lmeas; elSign.push_back ( lmeas > 0.0 ); } } break; case HEXA: { CurrentFE fe ( feHexaQ1, geoBilinearHexa, quadRuleHexa1pt ); for ( ID i = 0; i < mesh.numVolumes(); i++ ) { fe.updateJac ( mesh.volume ( i ) ); lmeas = fe.measure(); meas += lmeas; elSign.push_back ( lmeas > 0.0 ); } } break; default: sw.create ( "SKIP_ORIENTATION_TEST", true ); return 0; } if ( std::find ( elSign.begin(), elSign.end(), false ) != elSign.end() ) { sw.create ( "HAS_NEGATIVE_VOLUMES", true ); } return meas; }
void getVolumeFromFaces ( RegionMesh const& mesh, Real vols[ 3 ], std::ostream& err = std::cerr ) { MeshUtility::GetCoordComponent getx ( 0 ); MeshUtility::GetCoordComponent gety ( 1 ); MeshUtility::GetCoordComponent getz ( 2 ); vols[ 0 ] = 0.0; vols[ 1 ] = 0.0; vols[ 2 ] = 0.0; typedef typename RegionMesh::facetShape_Type GeoBShape; typedef typename RegionMesh::facet_Type facet_Type; typedef boost::shared_ptr<CurrentFEManifold> current_fe_type; current_fe_type bdfe; switch ( GeoBShape::S_shape ) { case TRIANGLE: bdfe = current_fe_type ( new CurrentFEManifold ( feTriaP1, geoLinearTria, quadRuleTria1pt ) ); for ( ID i = 0; i < mesh.numBFaces(); i++ ) { bdfe->update ( mesh.face ( i ), UPDATE_W_ROOT_DET_METRIC | UPDATE_NORMALS | UPDATE_QUAD_NODES ); vols[ 0 ] += bdfe->normalIntegral ( getx ); vols[ 1 ] += bdfe->normalIntegral ( gety ); vols[ 2 ] += bdfe->normalIntegral ( getz ); } break; case QUAD: bdfe = current_fe_type ( new CurrentFEManifold ( feQuadQ1, geoBilinearQuad, quadRuleQuad1pt ) ); for ( ID i = 0; i < mesh.numBFaces(); i++ ) { bdfe->update ( mesh.face ( i ), UPDATE_W_ROOT_DET_METRIC | UPDATE_NORMALS | UPDATE_QUAD_NODES ); vols[ 0 ] += bdfe->normalIntegral ( getx ); vols[ 1 ] += bdfe->normalIntegral ( gety ); vols[ 2 ] += bdfe->normalIntegral ( getz ); } break; default: err << "Only tria and quad surface elements may be checked for volume orientation at the moment" << std::endl; ASSERT0 ( false, "ABORT CONDITION OCCURRED" ); } }
Real testClosedDomain ( RegionMesh const& mesh, std::ostream& err = std::cerr ) { typedef typename RegionMesh::facet_Type facet_Type; typedef boost::shared_ptr<CurrentFEManifold> current_fe_type; current_fe_type bdfe; MeshUtility::GetOnes ones; Real test ( 0.0 ); switch ( RegionMesh::facetShape_Type::S_shape ) { case TRIANGLE: bdfe = current_fe_type ( new CurrentFEManifold ( feTriaP1, geoLinearTria, quadRuleTria1pt ) ); for ( ID i = 0; i < mesh.numBFaces(); i++ ) { bdfe->update ( mesh.face ( i ), UPDATE_W_ROOT_DET_METRIC | UPDATE_NORMALS | UPDATE_QUAD_NODES ); test += bdfe->normalIntegral ( ones ); } break; case QUAD: bdfe = current_fe_type ( new CurrentFEManifold ( feQuadQ1, geoBilinearQuad, quadRuleQuad1pt ) ); for ( ID i = 0; i < mesh.numBFaces(); i++ ) { bdfe->update ( mesh.face ( i ), UPDATE_W_ROOT_DET_METRIC | UPDATE_NORMALS | UPDATE_QUAD_NODES ); test += bdfe->normalIntegral ( ones ); } break; default: err << "Only tria and quad surface elements may be checked for volume orientation at the moment" << std::endl; ASSERT0 ( false, "ABORT CONDITION OCCURRED" ); } return test; }
bool readFreeFemFile( RegionMesh<LinearTriangle, MC> & mesh, const std::string & fileName, markerID_Type regionFlag, bool /*useless*/ = false) { MeshElementBareHandler<BareEdge> _be; std::pair<BareEdge, bool> _edge; typedef LinearTriangle GeoShape; typename RegionMesh<GeoShape, MC>::point_Type * pp = 0; typename RegionMesh<GeoShape, MC>::edge_Type * pe = 0; typename RegionMesh<GeoShape, MC>::face_Type * pf = 0; std::ifstream __is ( fileName.c_str() ); if( __is.fail() ) { std::cerr << " Error in readFreeFemFile: File " << fileName << " not found or locked" << std::endl; abort(); } // first row: how many vertices, triangles, edges UInt __nv, __nt, __ne, i1, i2, i3; __is >> __nv >> __nt >> __ne; #ifdef DEBUG debugStream ( 8000 ) << "number of vertices: "<< __nv << "\n"; debugStream ( 8000 ) << "number of triangles: "<< __nt << "\n"; debugStream ( 8000 ) << "number of edges: "<< __ne << "\n"; #endif // first section: read the list of vertices // on each row find the two coordinates and the label for each node std::vector<Real> __x(2*__nv); std::vector<bool> __isonboundary(__nv); std::vector<UInt> __whichboundary(__nv); #ifdef DEBUG debugStream ( 8000 ) << "reading "<< __nv << " nodes\n"; #endif // count the number of nodes on the boundary UInt __nbv( 0 ); // reading vertices for ( UInt __i = 0; __i < __nv; ++ __i ) { __is >> __x[ 2 * __i ] >> __x[ 2 * __i + 1 ] >> __whichboundary[ __i ]; __isonboundary[ __i ] = __whichboundary[ __i ]; __nbv += __isonboundary[ __i ]; } // second section: read the list of triangles // on each row find the three nodes and the label for each triangle std::vector<int> __triangle_nodes( 3 * __nt ); std::vector<int> __triangle_label( __nt ); #ifdef DEBUG debugStream ( 8000 ) << "reading "<< __nt << " triangles\n"; #endif std::map<UInt,UInt> edge_to_firstAdjacentElementIdentity, edge_to_firstAdjacentElementPosition; // reading vertices for ( UInt __i = 0; __i < __nt; ++__i ) { __is >> __triangle_nodes[ 3 * __i ] >> __triangle_nodes[ 3 * __i + 1 ] >> __triangle_nodes[ 3 * __i + 2 ] >> __triangle_label[ __i ]; //from 1-based numbering to 0-based numbering __triangle_nodes[3 * __i]--; __triangle_nodes[3 * __i+1]--; __triangle_nodes[3 * __i+2]--; // dump first the existing edges, to maintain the correct numbering // if everything is correct the numbering in the bareedge // structure will reflect the actual edge numbering std::pair<UInt, bool> _check; i1 = __triangle_nodes[ 3 * __i ]; i2 = __triangle_nodes[ 3 * __i + 1 ]; i3 = __triangle_nodes[ 3 * __i + 2 ]; _edge = makeBareEdge( i1, i2 ); _check = _be.addIfNotThere( _edge.first ); edge_to_firstAdjacentElementIdentity[ _check.first ] = __i; edge_to_firstAdjacentElementPosition[ _check.first ] = 0; _edge = makeBareEdge( i2, i3 ); _check = _be.addIfNotThere( _edge.first ); edge_to_firstAdjacentElementIdentity[ _check.first ] = __i; edge_to_firstAdjacentElementPosition[ _check.first ] = 1; _edge = makeBareEdge( i3, i1 ); _check = _be.addIfNotThere( _edge.first ); edge_to_firstAdjacentElementIdentity[ _check.first ] = __i; edge_to_firstAdjacentElementPosition[ _check.first ] = 2; } // ( __triangle[ 3 * i + 2] > __triangle[ 3 * i + 1 ] ) // third section: read the list of edges // NOTE: only boundary edges are stored // on each row find the two nodes and the label for each edge std::vector<int> __edge_nodes( 2 * __ne ); std::vector<int> __edge_label( __ne ); // reading edges for ( UInt __i = 0; __i < __ne; ++__i ) { __is >> __edge_nodes[ 2 * __i ] >> __edge_nodes[ 2 * __i + 1 ] >> __edge_label[ __i ]; } //from 1-based numbering to 0-based numbering for(UInt i(0); i<__edge_nodes.size(); i++) __edge_nodes[i]--; // Set mesh properties // Add Marker to list of Markers mesh.setMarkerID( regionFlag ); // Till now I only have information about boundary edges - I don't know the MAX num of edges // Euler formula: ne = nv + nt - 1 mesh.setMaxNumEdges ( _be.size() ); mesh.setMaxNumGlobalEdges( _be.size() ); // Here the REAL number of edges (all of them) mesh.setNumEdges ( _be.size() ); mesh.setNumBEdges ( __ne ); mesh.setMaxNumFaces ( __nt ); mesh.setMaxNumGlobalFaces( __nt ); // Here the REAL number of edges (all of them) mesh.setNumFaces ( __nt); mesh.setMaxNumPoints ( __nv, true ); mesh.setMaxNumGlobalPoints( __nv ); mesh.setNumVertices ( __nv ); mesh.setNumGlobalVertices ( __nv ); mesh.numBVertices() = __nbv; mesh.setNumBPoints( mesh.numBVertices() ); #ifdef DEBUG debugStream ( 8000 ) << "number of points : " << mesh.numPoints() << "\n"; debugStream ( 8000 ) << "number of boundary points : " << mesh.numBPoints() << "\n"; debugStream ( 8000 ) << "number of vertices : " << mesh.numVertices() << "\n"; debugStream ( 8000 ) << "number of boundary vertices : " << mesh.numBVertices() << "\n"; #endif for ( UInt __i = 0; __i < __nv; ++__i ) { pp = &mesh.addPoint( __isonboundary[ __i ], true ); pp->setMarkerID( __whichboundary[ __i ] ); pp->x() = __x[ 2 * __i ]; pp->y() = __x[ 2 * __i + 1 ]; pp->z() = 0; pp->setId( __i ); } // add the edges to the mesh for ( UInt __i = 0; __i < __ne; ++__i ) { pe = &( mesh.addEdge( true ) ); pe->setMarkerID( markerID_Type( __edge_label[ __i ] ) ); pe->setPoint( 0, mesh.point( __edge_nodes[ 2 * __i ] ) ); pe->setPoint( 1, mesh.point( __edge_nodes[ 2 * __i + 1 ] ) ); pe->setId( __i ); _edge = makeBareEdge( __edge_nodes[ 2 * __i ], __edge_nodes[ 2 * __i + 1 ] ); UInt map_it( _be.id( _edge.first ) ); pe->firstAdjacentElementIdentity() = edge_to_firstAdjacentElementIdentity[ map_it ]; pe->firstAdjacentElementPosition() = edge_to_firstAdjacentElementPosition[ map_it ]; } // add the triangles to the mesh for ( UInt __i = 0; __i < __nt; ++__i ) { pf = &( mesh.addFace(true) ); pf->setId( __i ); pf->setMarkerID( markerID_Type( __triangle_label[ __i ] ) ); pf->setPoint( 0, mesh.point( __triangle_nodes[ 3 * __i ] ) ); pf->setPoint( 1, mesh.point( __triangle_nodes[ 3 * __i + 1 ] ) ); pf->setPoint( 2, mesh.point( __triangle_nodes[ 3 * __i + 2 ] ) ); } return true; } // Function readFreeFemFile
int main (int argc, char** argv) { #ifdef HAVE_MPI MPI_Init (&argc, &argv); std::cout << "MPI Initialization" << std::endl; boost::shared_ptr<Epetra_Comm> comm ( new Epetra_MpiComm ( MPI_COMM_WORLD ) ); #else boost::shared_ptr<Epetra_Comm> comm ( new Epetra_SerialComm ); #endif using namespace LifeV; using namespace LifeV::MeshUtility; using namespace std; GetPot datafile ( "data" ); string dirname = datafile ( "mesh_dir", "." ); //"../data/mesh/mesh++/"; if (*dirname.rbegin() != '/'); dirname += "/"; string fname = dirname + datafile ( "mesh_file", "cube_47785.m++" ); //dirname+"cube_47785.m++"; string outfile = "testBuilders.dat"; ofstream ofile (outfile.c_str() ); if (ofile.fail() ) { cerr << " Error: Cannot creat output file" << endl; abort(); } RegionMesh<LinearTetra> aMesh ( comm ); typedef RegionMesh<LinearTetra> mesh_Type; // aMesh.test3DBuilder(); // aMesh.readMppFile(mystream, id, m); ID m = 1; readMppFile (aMesh, fname, m); cout << " **********************************************************" << endl; cout << " ****************** CHECKING MESH WITH INTERNAL CHECKER" << endl; aMesh.check (0, true, true); Switch sw; cout << " **********************************************************" << endl; cout << " ****************** CLEANING edges and faces " << endl; aMesh.edgeList.clear(); aMesh.faceList.clear(); checkMesh3D (aMesh, sw, true, true, cerr, cout, ofile); aMesh.showMe(); cout << " Now building local Edges/faces Stuff" << endl << endl; aMesh.updateElementEdges(); aMesh.updateElementFaces(); aMesh.showMe(); cout << " Now cleaning local Edges/faces Stuff" << endl << endl; aMesh.cleanElementRidges(); aMesh.cleanElementFacets(); aMesh.showMe(); cout << " **********************************************************" << endl; cout << " ****************** BUILDING ALL EDGES" << endl; UInt bedges_found, iedges_found; buildEdges (aMesh, ofile, cerr, bedges_found, iedges_found, true, true, true); cout << " **********************************************************" << endl; cout << " ****************** BUILDING ALL FACES" << endl; UInt bfaces_found, ifaces_found; buildFaces (aMesh, ofile, cerr, bfaces_found, ifaces_found, true, true, true); aMesh.showMe(); cout << " Now building again local Edges/faces Stuff" << endl << endl; aMesh.updateElementEdges(); aMesh.updateElementFaces(); aMesh.showMe(); checkMesh3D (aMesh, sw, true, true, cerr, cout, ofile); ofile.close(); ///THIS PART IS ONLY TO VERIFY IF THESE ROUTINES COMPILE PROPERLY cerr << "Fixing bpoints" << endl; fixBoundaryPoints (aMesh, ofile, cerr, true); cerr << "Fixing edge markers" << endl; setBoundaryEdgesMarker (aMesh, ofile, cerr, true); cerr << "Fixing faces marker" << endl; setBoundaryFacesMarker (aMesh, ofile, cerr, true); cerr << "Fixing points marker" << endl; setBoundaryPointsMarker (aMesh, ofile, cerr, true); cerr << endl; dummyVect disp (3 * aMesh.numPoints() ); MeshUtility::MeshTransformer<mesh_Type> transformer (aMesh); transformer.moveMesh (disp, 3); MeshUtility::MeshStatistics::meshSize sizes = MeshUtility::MeshStatistics::computeSize (aMesh); cerr << "Hmin =" << sizes.minH << " Hmax=" << sizes.maxH << std::endl; mesh_Type::points_Type newPointList = aMesh.pointList; mesh_Type::faces_Type newFaceList = aMesh.faceList; Utilities::fixAfterShallowCopy (newFaceList, newPointList); for (mesh_Type::faces_Type::iterator i = newFaceList.begin(); i < newFaceList.end(); ++i) { ID theId = i->point (0).id(); if (& (i->point (0) ) != & (newPointList[theId]) ) { cerr << "ERROR: Error after renumbering Faces" << std::endl; break; } } aMesh.faceList[2].replaceFlag (EntityFlags::CUTTED); aMesh.faceList.reorderAccordingToFlag (EntityFlags::CUTTED, &Flag::testOneSet); if (aMesh.faceList[0].flag() != EntityFlags::CUTTED) { cerr << "ERROR: Reordering is not working" << std::endl; } cout << "Number of cutted faces (should be 1) " << aMesh.faceList.countElementsWithFlag (EntityFlags::CUTTED, &Flag::testOneSet) << std::endl; // Reset all flags to default aMesh.edgeList.changeAccordingToFunctor (ResetFlag<mesh_Type::edge_Type>() ); aMesh.edge (0).setMarkerID (10); aMesh.edge (5).setMarkerID (10); aMesh.edge (10).setMarkerID (15); vector<ID> watermarks (2); watermarks[0] = 10; watermarks[1] = 15; // change flags according to marker iD SetFlagAccordingToWatermarks changeFlags (EntityFlags::CUTTED, watermarks); aMesh.edgeList.changeAccordingToFunctor (changeFlags); std::cout << "Number of cutted edges (should be 3) " << aMesh.edgeList.countElementsWithFlag (EntityFlags::CUTTED, &Flag::testOneSet) << std::endl; aMesh.edgeList.changeAccordingToFunctor ( ResetFlag<mesh_Type::edge_Type>() ); aMesh.edge (0).setMarkerID (10); aMesh.edge (5).setMarkerID (12); aMesh.edge (10).setMarkerID (15); SetFlagAccordingToMarkerRanges changer ( &Flag::turnOn ); //I may use the default constructor changer.insert (std::make_pair (10, 12), EntityFlags::INTERNAL_INTERFACE); changer.insert (std::make_pair (15, 18), EntityFlags::CUTTED); aMesh.edgeList.changeAccordingToFunctor (changer); cout << "Number of cutted edges (should be 1) " << aMesh.edgeList.countElementsWithFlag (EntityFlags::CUTTED, &Flag::testOneSet) << std::endl; cout << "Number of internal interface edges (should be 2) " << aMesh.edgeList.countElementsWithFlag (EntityFlags::INTERNAL_INTERFACE, &Flag::testOneSet) << std::endl; SetFlagAccordingToWatermark<std::equal_to<markerID_Type> > changer2 (EntityFlags::INTERNAL_INTERFACE, 12000, Flag::turnOn); aMesh.faceList.changeAccordingToFunctor (changer2); #ifdef HAVE_MPI MPI_Finalize(); #endif return ( EXIT_SUCCESS ); }
bool checkMesh3D ( RegionMesh& mesh, Switch& sw, bool fix = true, bool verbose = false, std::ostream& out = std::cerr, std::ostream& err = std::cerr, std::ostream& clog = std::clog ) { verbose = verbose && ( mesh.comm()->MyPID() == 0 ); typedef typename RegionMesh::point_Type point_Type; if ( mesh.storedPoints() == 0 ) { err << "FATAL: mesh does not store points: I cannot do anything" << std::endl; sw.create ( "ABORT_CONDITION", true ); sw.create ( "NOT_HAS_POINTS", true ); return false; } if (verbose) { out << " Check point marker ids" << std::endl; } if ( !MeshUtility::checkIsMarkerSet ( mesh.pointList ) ) { if (verbose) { err << "WARNING: Not all points have marker id set" << std::endl; } sw.create ( "POINTS_MARKER_UNSET", true ); } //------------------------------------------------------------------------- // VOLUMES //------------------------------------------------------------------------- if ( mesh.storedVolumes() == 0 ) { if (verbose) err << "FATAL: mesh does not store volumes: I cannot do anything" << std::endl; sw.create ( "ABORT_CONDITION", true ); sw.create ( "NOT_HAS_VOLUMES", true ); return false; } if ( !MeshUtility::checkId ( mesh.volumeList ) ) { if (verbose) { err << "ERROR: volume ids were wrongly set" << std::endl; err << "FIXED" << std::endl; } if ( fix ) { sw.create ( "FIXED_VOLUMES_ID", true ); } if ( fix ) { MeshUtility::fixId ( mesh.volumeList ); } } if (verbose) { out << " Check volum marker ids" << std::endl; } if ( !MeshUtility::checkIsMarkerSet ( mesh.volumeList ) ) { if (verbose) { err << "WARNING: Not all volumes have marker flag set" << std::endl; } sw.create ( "VOLUMES_MARKER_UNSET", true ); if ( fix ) { if (verbose) { out << "Fixing volume marker ids" << std::endl; } for ( typename RegionMesh::volumes_Type::iterator iv = mesh.volumeList.begin(); iv != mesh.volumeList.end(); ++iv ) { if ( iv->isMarkerUnset() ) { iv->setMarkerID ( mesh.markerID() ); } } } } if ( mesh.numElements() < mesh.storedVolumes() ) { if (verbose) err << "WARNING: Mesh Volumes must be at least " << mesh.storedVolumes() << std::endl; if ( fix ) { mesh.setNumVolumes ( mesh.storedVolumes() ); } if ( fix ) { sw.create ( "FIXED_VOLUME_COUNTER", true ); } } // test now orientation boost::shared_ptr<std::vector<bool> > elSign ( new std::vector<bool> ); Real meshMeasure = checkVolumes ( mesh, *elSign, sw ); UInt positive; if ( sw.test ( "SKIP_ORIENTATION_TEST" ) ) { if (verbose) { clog << "W: ELEMENT ORIENTATION NOT IMPLEMENTED YET FOR THIS TYPE OF ELEMENTS, SKIP" << std::endl; err << "W: ELEMENT ORIENTATION NOT IMPLEMENTED YET FOR THIS TYPE OF ELEMENTS, SKIP" << std::endl; } } else if ( sw.test ( "HAS_NEGATIVE_VOLUMES" ) ) { if (verbose) { out << "Checking volume orientation" << std::endl; } positive = count ( elSign->begin(), elSign->end(), true ); if ( verbose ) clog << positive << "W: positive elements out of" << mesh.storedVolumes() << std::endl; if ( fix ) { if ( verbose ) { clog << "Fixing negative elements" << std::endl; } fixVolumes ( mesh, *elSign, sw ); } if ( sw.test ( "ABORT_CONDITION" ) ) { if (verbose) err << "ABORT: Cannot fix volumes, this element is not supported" << std::endl; return false; } else { sw.unset ( "HAS_NEGATIVE_VOLUMES" ); meshMeasure = checkVolumes ( mesh, *elSign, sw ); if ( sw.test ( "HAS_NEGATIVE_VOLUMES" ) ) { if ( fix ) { if ( verbose ) { err << "ABORT: Cannot fix volumes: something wrong with this mesh" << std::endl; } sw.create ( "ABORT_CONDITION", true ); } return false; } } } if ( verbose ) clog << "Volume enclosed by the mesh= " << meshMeasure << std::endl << "(Computed by integrating mesh elements measures)" << std::endl << "(Using 1 point Quadrature rule)" << std::endl; //----------------------------------------------------- // BOUNDARY FACES //----------------------------------------------------- boost::shared_ptr<MeshUtility::temporaryFaceContainer_Type> bfaces ( new MeshUtility::temporaryFaceContainer_Type ); UInt numInternalFaces, numFaces; if (verbose) { out << "Finding boundary faces from mesh topology" << std::endl; } UInt bFacesFound = MeshUtility::findBoundaryFaces ( mesh, *bfaces, numInternalFaces ); numFaces = bFacesFound + numInternalFaces; MeshUtility::EnquireBFace<RegionMesh> enquireBFace (*bfaces ); UInt meshNumBoundaryFaces ( mesh.numBFaces() + mesh.faceList.countElementsWithFlag ( EntityFlags::SUBDOMAIN_INTERFACE, &Flag::testOneSet ) ); if ( mesh.storedFaces() == 0 || meshNumBoundaryFaces > mesh.storedFaces() || bFacesFound > mesh.storedFaces() || bFacesFound > meshNumBoundaryFaces ) { // Something strange with boundary faces if (verbose) { err << "ERROR: Not all boundary faces stored" << std::endl; err << "Found " << bFacesFound << " stored " << mesh.storedFaces() << "B faces declared in mesh " << meshNumBoundaryFaces << std::endl; } if ( fix ) { sw.create ( "BUILD_BFACES", true ); if (verbose) { out << "Building boundary faces from topology data" << std::endl; } MeshUtility::buildFaces ( mesh, clog, err, bFacesFound, numInternalFaces, true, false, false, bfaces.get() ); } if (verbose) { err << "After buildFaces" << std::endl; err << "Found " << bFacesFound << " stored " << mesh.storedFaces() << "B faces declared in mesh " << meshNumBoundaryFaces << std::endl; } } else { if ( mesh.storedFaces() == 0 ) { if ( verbose ) { err << "ABORT CONDITION: cannot find boundary faces" << std::endl; } sw.create ( "NOT_HAS_FACES", true ); sw.create ( "ABORT_CONDITION", true ); } // The mesh declares to have the correct boundary faces. Yet, are we sure that the flag has been properly set // and that they are stored first? If fix is set we don't trust anybody! // // Make sure that flags are set using the info in bfaces, which depends ONLY on the mesh topology. No messing bout with markers // Make sure BFaces are stored first if (fix) { if (verbose) { out << "Rearranging faces so that boundary faces are first" << std::endl; } MeshUtility::rearrangeFaces ( mesh, clog, err, sw, numFaces, bFacesFound, verbose, bfaces.get() ); } if ( meshNumBoundaryFaces != bFacesFound) { if ( verbose ) { err << " ERROR: Number of B faces does not correspond to real one" << std::endl; } if (fix) { if ( verbose ) { err << "FIXED Number of B faces has been fixed to:" << bFacesFound << std::endl; } mesh.setNumBFaces ( bFacesFound); } } if ( !MeshUtility::checkId ( mesh.faceList ) ) { if ( verbose ) { err << "ERROR: face ids were wrongly set" << std::endl; err << "FIXED" << std::endl; } if ( fix ) { sw.create ( "FIXED_FACES_ID", true ); MeshUtility::fixId ( mesh.faceList ); } } // Check Consistency with the mesh. if ( fix ) { if (verbose) { out << "Make sure that adjacent elements of boundary faces are correct" << std::endl; } MeshUtility::fixBoundaryFaces ( mesh, clog, err, sw, numFaces, bFacesFound, false, verbose, bfaces.get() ); } if ( mesh.numBFaces() == 0 ) { if ( verbose ) { err << " MeshBFaces counter is unset" << std::endl; } if ( fix ) { mesh.setNumBFaces ( mesh.storedFaces() ); sw.create ( "FIXED_BFACE_COUNTER", true ); mesh.setLinkSwitch ( "HAS_BOUNDARY_FACETS" ); } } if ( !MeshUtility::checkIsMarkerSet ( mesh.faceList ) ) { if (verbose) { out << "Fix markers id for faces" << std::endl; } if ( verbose ) { err << "WARNING: Not all faces have marker flag set" << std::endl; } sw.create ( "FACE_MARKER_UNSET", true ); if ( fix ) { MeshUtility::setBoundaryFacesMarker ( mesh, clog, err, verbose ); } if ( fix && MeshUtility::checkIsMarkerSet ( mesh.faceList ) ) { sw.create ( "FACE_MARKER_UNSET", false ); sw.create ( "FACE_MARKER_FIXED", true ); } } } if ( mesh.numFaces() != bFacesFound + numInternalFaces ) { if ( verbose ) { err << "WARNING Number of faces incorrectly set" << std::endl; err << " It was " << mesh.numFaces() << std::endl; err << " It should be " << bFacesFound + numInternalFaces << std::endl; } if ( fix ) { if ( verbose ) { err << " Fixing" << std::endl; } mesh.setNumFaces ( bFacesFound + numInternalFaces ); sw.create ( "FIXED_FACE_COUNTER", true ); } } if ( fix && mesh.storedFaces() == bFacesFound + numInternalFaces) { mesh.setLinkSwitch ( "HAS_ALL_FACETS" ); } if (verbose) { out << std::endl; out << " Boundary faces found :" << bFacesFound << std::endl; out << " Num Faces Stored stored :" << mesh.storedFaces() << std::endl; out << " Num faces in mesh :" << mesh.numFaces() << std::endl; out << " Boundary faces counter gives:" << mesh.numBFaces() << std::endl; out << std::endl; } //----------------------------------------------------- // BOUNDARY EDGES //----------------------------------------------------- boost::shared_ptr<MeshUtility::temporaryEdgeContainer_Type> bedges ( new MeshUtility::temporaryEdgeContainer_Type ); UInt bEdgesFound = MeshUtility::findBoundaryEdges ( mesh, *bedges ); MeshUtility::EnquireBEdge<RegionMesh> enquireBEdge (*bedges ); UInt intedge (0); UInt Ned (0); MeshUtility::temporaryEdgeContainer_Type iedges; if ( mesh.storedEdges() == 0 || mesh.numBEdges() > mesh.storedEdges() || bEdgesFound > mesh.storedEdges() ) { if (verbose) { err << "WARNING: mesh does not store (all) boundary edges" << std::endl; } sw.create ( "NOT_HAS_EDGES", true ); if ( fix ) { if (verbose) { out << "Build boundary edges" << std::endl; } MeshUtility::buildEdges ( mesh, clog, err, bEdgesFound, intedge, true, false, false, bedges.get() ); } Ned = bEdgesFound + intedge; if ( fix ) { sw.create ( "BUILD_BEDGES", true ); } } else { // Make sure BEdges are first // Here I need to use a method that does not require the proper // setting of boundary Points! // With the edges I am being a bit sloppy. I am trusting the given mesh // todo do the same it was done for faces! if ( mesh.numBEdges() != bEdgesFound) { if ( verbose ) { err << " ERROR: Number of BEdges does not correspond to real one" << std::endl; } if (fix) { if ( verbose ) { err << "FIXED Number of BEdges has been fixed to:" << bEdgesFound << std::endl; } mesh.setNumBEdges ( bEdgesFound); } } if ( fix ) { if (verbose) { out << "Reorder edges so that boundary are first" << std::endl; } mesh.edgeList.reorderAccordingToFlag (EntityFlags::PHYSICAL_BOUNDARY, &Flag::testOneSet); sw.create ( "FIXED_BEDGES_FIRST" ); } if ( !MeshUtility::checkId ( mesh.edgeList ) ) { if ( verbose ) { err << "ERROR: edge ids were wrongly set" << std::endl; } if (fix) { if ( verbose ) { err << "FIXED" << std::endl; } sw.create ( "FIXED_EDGES_ID", true ); MeshUtility::fixId ( mesh.edgeList ); } } if ( !MeshUtility::checkIsMarkerSet ( mesh.edgeList ) ) { if ( verbose ) { err << "WARNING: Not all edges have marker flag set" << std::endl; } sw.create ( "EDGE_MARKER_UNSET", true ); if ( fix ) { if (verbose) { out << "Fix boundary edges marker" << std::endl; } MeshUtility::setBoundaryEdgesMarker ( mesh, clog, err, verbose ); } if ( fix && MeshUtility::checkIsMarkerSet ( mesh.edgeList ) ) { sw.unset ( "EDGE_MARKER_UNSET" ); sw.create ( "EDGE_MARKER_FIXED", true ); } } if (verbose) { out << "Computing number of internal edges"; } if ( fix ) { Ned = bEdgesFound + MeshUtility::findInternalEdges ( mesh, *bedges, iedges ); } } iedges.clear(); MeshUtility::temporaryEdgeContainer_Type tmp; iedges.swap (tmp); if ( mesh.numBEdges() != bEdgesFound ) { if ( verbose ) err << "WARNING: number of found boundary edges:" << bEdgesFound << std::endl << " does not match that declared in mesh, i.e. " << mesh.numBEdges() << std::endl; if ( mesh.numBEdges() == 0 ) { if ( fix ) { if ( verbose ) { err << "FIXING" << std::endl; } sw.create ( "FIXED_BEDGES_COUNTER", true ); mesh.setNumBEdges ( bEdgesFound ); } } } if ( Ned != mesh.numEdges() ) { if ( fix ) { if ( verbose ) err << "WARNING: Counter of number of edges badly set: Should be (actual number)" << Ned << std::endl << "It is instead equal to " << mesh.numEdges() << std::endl; err << " **FIXED" << std::endl; mesh.setNumEdges ( Ned ); } } UInt nbed; UInt counte = MeshUtility::testDomainTopology ( mesh, nbed ); if ( counte == 0 ) { if ( verbose ) { out << "**DOMAIN SURFACE IS (TOPOLOGICALLY) CLOSED" << std::endl; } } else { sw.create ( "DOMAIN_NOT_CLOSED", true ); if ( verbose ) err << "WARNING: DOMAIN APPEARS TO HAVE AN OPEN BOUNDARY (TOPOLOGY CHECK)" << std::endl << "Number of inconsistent edges:" << counte << std::endl; } //----------------------------------------------------- // POINTS //----------------------------------------------------- if (verbose) { out << "Checking vertexes" << std::endl; } UInt numVerticesFound = mesh.pointList.countElementsWithFlag (EntityFlags::VERTEX, &Flag::testOneSet); if (numVerticesFound != mesh.numVertices() ) { if ( verbose ) { err << "warning: The number of Points with vertex flag on does not coincide with the declared one." << std::endl; } if (fix) { if ( verbose ) { err << "It will be fixed now" << std::endl; } // unset the flag. It will be remade for (UInt i = 0; i < mesh.numPoints(); ++i) { mesh.point (i).unSetFlag (EntityFlags::VERTEX); } // Find the real vertices and set the flag for (UInt i = 0; i < mesh.numElements(); ++i) for (UInt j = 0; j < mesh.numLocalVertices(); ++j) { ID k = mesh.element (i).point (j).localId(); mesh.pointList (k).setFlag (EntityFlags::VERTEX); } numVerticesFound = mesh.pointList.countElementsWithFlag ( EntityFlags::VERTEX, &Flag::testOneSet); mesh.setNumVertices (numVerticesFound); UInt numBVerticesFound = mesh.pointList.countElementsWithFlag ( EntityFlags::VERTEX | EntityFlags::PHYSICAL_BOUNDARY, &Flag::testAllSet); mesh.setNumBVertices (numBVerticesFound); sw.create ( "FIXED_VERTICES_COUNTER", true ); } } // Now that boundary faces have been correctly set we may work out // boundaty points if (fix) { if (verbose) { out << "Fix boundary points using boundary faces info" << std::endl; } MeshUtility::fixBoundaryPoints (mesh, clog, err, verbose); } MeshUtility::EnquireBPoint<RegionMesh> enquirebpoint ( mesh ); UInt foundBPoints = mesh.pointList.countElementsWithFlag (EntityFlags::PHYSICAL_BOUNDARY, &Flag::testOneSet); if (verbose) { out << "B Points Found " << foundBPoints << std::endl; } if ( foundBPoints == 0 || foundBPoints < mesh.storedBPoints() ) { if ( verbose ) { err << "ERROR Bpoints indicator not correctly set" << std::endl; } } else { if ( fix ) { sw.create ( "FIXED_BOUNDARY_POINTS", true ); } } // Now that we are sure that (jus) boundary points are flagged as such we check if the marker id is set if (verbose) { out << "Chsck point marker Ids" << std::endl; } if ( ! MeshUtility::checkIsMarkerSet ( mesh.pointList ) ) { if (verbose) { err << "Points MARKER id incorrectly set" << std::endl; } if ( fix ) { if ( verbose ) { err << " Fixing Points Marker ID" << std::endl << "If unset the boundary will inherit the strongest among faces" << std::endl; } if ( verbose ) { err << " The internal will be set to the domain flag" << std::endl; } MeshUtility::setBoundaryPointsMarker ( mesh, clog, err, false ); // fix marker at interior points. It takes if ( ! MeshUtility::checkIsMarkerSet ( mesh.pointList ) ) { // Maybe boundary points marker is fine, this is enough bool boundaryIsOk (true); std::vector<point_Type const*> listOfPt = mesh.pointList.extractElementsWithFlag ( EntityFlags::PHYSICAL_BOUNDARY, &Flag::testOneSet); for (typename std::vector<point_Type const*>::const_iterator it = listOfPt.begin(); it < listOfPt.end(); ++it) { boundaryIsOk = boundaryIsOk | (*it)->isMarkerSet(); } std::vector<point_Type const*>().swap (listOfPt); // save memory if ( verbose ) { clog << " Marker ID on boundary points is fine. Internal points may have marker unset" << std::endl; } if (verbose) { err << "Cannot Fix Points MARKER" << std::endl; } if ( verbose && boundaryIsOk ) { err << "But boundary points are fine" << std::endl; } sw.create ( "POINT_MARKER_UNSET", true ); } else { if (verbose) { err << "FIXED" << std::endl; } sw.create ( "FIXED_POINT_MARKER", true ); } } } if ( mesh.storedBPoints() == 0 ) { if ( verbose ) { err << "WARNING B. Points COUNTER incorrectly set" << std::endl; } if ( fix ) { MeshUtility::setBoundaryPointsCounters ( mesh ) ; if ( verbose ) { err << " FIXED" << std::endl; } sw.create ( "FIXED_BPOINTS_COUNTER", true ); } } if ( mesh.numPoints() == 0 ) { if ( verbose ) { err << "WARNING Points Counter unset" << std::endl; } if ( fix ) { mesh.numPoints() = mesh.storedPoints(); sw.create ( "FIXED_POINTS_COUNTER", true ); } } //----------------------------------------------------- // FINAL CHECKS //----------------------------------------------------- if ( verbose ) out << " ******** COUNTERS CONTENT **********************************" << std::endl << " Num Volumes : " << mesh.numVolumes() << std::endl << " Num Vertices : " << mesh.numVertices() << std::endl << " Num B. Vertices: " << mesh.numBVertices() << std::endl << " Num Points : " << mesh.numPoints() << std::endl << " Num B. Points : " << mesh.numBPoints() << std::endl << " Num Edges : " << mesh.numEdges() << std::endl << " Num B. Edges : " << mesh.numBEdges() << std::endl << " Num Faces : " << mesh.numFaces() << std::endl << " Num B. Faces : " << mesh.numBFaces() << std::endl << " ******** END COUNTERS **********************************" << std::endl; bool eulok1 = ( 2 * mesh.numFaces() - mesh.numLocalFaces() * mesh.numVolumes() - mesh.numBFaces() ) == 0; bool eulok2 ( true ); if ( RegionMesh::elementShape_Type::S_shape == TETRA ) { if ( verbose ) { out << std::endl << "Checking Euler formulae: "; } eulok2 = ( mesh.numEdges() - mesh.numVolumes() - mesh.numVertices() - ( 3 * mesh.numBFaces() - 2 * mesh.numBVertices() ) / 4 ) == 0; } if ( ! ( eulok1 && eulok2 ) ) { if ( verbose ) err << "WARNING: The following Euler formula(s) are not satisfied" << std::endl; sw.create ( "NOT_EULER_OK" ); } else { if ( verbose ) { out << std::endl << " ok." << std::endl; } } if ( !eulok1 ) { if ( verbose ) err << " 2*nFaces = nFacesPerVolume*nVolumes + nBoundaryFaces" << std::endl << " 2*" << mesh.numFaces() << " != " << mesh.numLocalFaces() << " * " << mesh.numVolumes() << " + " << mesh.numBFaces() << std::endl; } if ( !eulok2 ) { if ( verbose ) err << " nEdges = nVolumes + nVertices + (3*nBoundaryFaces - 2*nBoundaryVertices)/4" << std::endl << " " << mesh.numEdges() << " != " << mesh.numVolumes() << " + " << mesh.numVertices() << " + (3*" << mesh.numBFaces() << " - 2*" << mesh.numBVertices() << ")/4" << std::endl; } mesh.setLinkSwitch ( "HAS_BEEN_CHECKED" ); return true; }
static void check_face (RegionMesh<LinearTetra>& mesh, ID i, ID j) { ID faceId = mesh.localFaceId (i, j); if ( (ID) faceId != NotAnId) { RegionMesh<LinearTetra>::face_Type& face = mesh.face (faceId); if (0) fprintf (stdout, " face: %5d %5d, ", faceId, face.id() ); ID v0, v1, v2, gv0, gv1, gv2; v0 = LinearTetra::faceToPoint (j, 0); v1 = LinearTetra::faceToPoint (j, 1); v2 = LinearTetra::faceToPoint (j, 2); // fprintf(stdout, "[%5d %5d %5d], ", v0, v1, v2); gv0 = mesh.element (i).point (v0).id(); gv1 = mesh.element (i).point (v1).id(); gv2 = mesh.element (i).point (v2).id(); fprintf (stdout, "[ %7d %7d %7d ], ", gv0, gv1, gv2); int mark = 0; if (face.flag() & EntityFlags::PHYSICAL_BOUNDARY) { mark = 1; } if (face.flag() & EntityFlags::SUBDOMAIN_INTERFACE) { mark += 2; } fprintf (stdout, "mark: %d, ", mark); ID vol0, vol1; ID pos0, pos1; vol0 = face.firstAdjacentElementIdentity(); pos0 = face.firstAdjacentElementPosition(); vol1 = face.secondAdjacentElementIdentity(); pos1 = face.secondAdjacentElementPosition(); if (vol0 == NotAnId) { vol0 = -1; } if (vol1 == NotAnId) { vol1 = -1; } if (pos0 == NotAnId) { pos0 = -1; } if (pos1 == NotAnId) { pos1 = -1; } fprintf (stdout, "first: %5d %d, second: %5d %d", vol0, pos0, vol1, pos1); fprintf (stdout, "\n"); } else { fprintf (stdout, "Invalid face!!!\n"); } }