topology.cpp serif/discretization/domain/mesh/topology.hpp utility serif/utils/error/errors.hpp serif serif::discretization serif::discretization::domain serif::discretization::domain::mesh #include"serif/discretization/domain/mesh/topology.hpp" #include<utility> #include"serif/utils/error/errors.hpp" namespaceserif::discretization::domain::mesh{ conststd::vector<int>MeshTopology::s_noElements{}; namespace{ [[nodiscard]]std::size_tas_index(constintid)noexcept{ returnstatic_cast<std::size_t>(id); } [[nodiscard]]boolin_range(constintid,conststd::size_tsize)noexcept{ returnid>=0&&as_index(id)<size; } } MeshTopology::MeshTopology(MeshTopologyDatadata) :m_elementDomainIDs(std::move(data.elementDomainIDs)), m_faceElements(std::move(data.faceElements)), m_elementNeighbors(m_elementDomainIDs.size()), m_boundaryElementBoundaryIDs(std::move(data.boundaryElementBoundaryIDs)), m_boundaryElementFaceIDs(std::move(data.boundaryElementFaceIDs)), m_boundaryElementsByFace(m_faceElements.size()){ usingnamespaceutils::errors; serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(m_boundaryElementBoundaryIDs.size()==m_boundaryElementFaceIDs.size(),"EachtopologyboundaryelementrequiresbothaboundaryIDandafaceID."); //Faceconnectivitydeterminesadjacencyindependentlyofbackendnumberingconventions. for(constFaceElements&face:m_faceElements){ constintfirstElementID=face.firstElementID; constintsecondElementID=face.secondElementID; serif_ensure<SERiFErrorCode::OUT_OF_RANGE_ERROR>((firstElementID==-1||in_range(firstElementID,m_elementDomainIDs.size()))&&(secondElementID==-1||in_range(secondElementID,m_elementDomainIDs.size())),"Topologyfaceelementsmustbevalidelementindicesor-1fortheexterior;received{}and{}for{}elements.",firstElementID,secondElementID,m_elementDomainIDs.size()); if(firstElementID<0||secondElementID<0){ continue; } m_elementNeighbors[as_index(firstElementID)].push_back(secondElementID); m_elementNeighbors[as_index(secondElementID)].push_back(firstElementID); } //Afacecancarryseveralboundarylabels;retainallofthemforschemavalidation. for(std::size_tboundaryElementID=0;boundaryElementID<m_boundaryElementFaceIDs.size();++boundaryElementID){ constintfaceID=m_boundaryElementFaceIDs[boundaryElementID]; serif_ensure<SERiFErrorCode::OUT_OF_RANGE_ERROR>(faceID==-1||in_range(faceID,m_faceElements.size()),"Topologyboundaryface{}mustbeavalidfaceindexor-1foranunresolvedface.",faceID); if(in_range(faceID,m_boundaryElementsByFace.size())){ m_boundaryElementsByFace[as_index(faceID)].push_back(static_cast<int>(boundaryElementID)); } } } intMeshTopology::element_count()constnoexcept{ returnstatic_cast<int>(m_elementDomainIDs.size()); } intMeshTopology::face_count()constnoexcept{ returnstatic_cast<int>(m_faceElements.size()); } intMeshTopology::boundary_element_count()constnoexcept{ returnstatic_cast<int>(m_boundaryElementBoundaryIDs.size()); } intMeshTopology::element_domain_id(constintelementID)const{ if(!in_range(elementID,m_elementDomainIDs.size())){ return0; } returnm_elementDomainIDs[as_index(elementID)]; } intMeshTopology::boundary_element_boundary_id(constintboundaryElementID)const{ if(!in_range(boundaryElementID,m_boundaryElementBoundaryIDs.size())){ return0; } returnm_boundaryElementBoundaryIDs[as_index(boundaryElementID)]; } FaceElementsMeshTopology::face_elements(constintfaceID)const{ if(!in_range(faceID,m_faceElements.size())){ returnFaceElements{}; } returnm_faceElements[as_index(faceID)]; } conststd::vector<int>&MeshTopology::element_neighbors(constintelementID)const{ if(!in_range(elementID,m_elementNeighbors.size())){ returns_noElements; } returnm_elementNeighbors[as_index(elementID)]; } intMeshTopology::boundary_element_face(constintboundaryElementID)const{ if(!in_range(boundaryElementID,m_boundaryElementFaceIDs.size())){ return-1; } returnm_boundaryElementFaceIDs[as_index(boundaryElementID)]; } conststd::vector<int>&MeshTopology::boundary_elements_on_face(constintfaceID)const{ if(!in_range(faceID,m_boundaryElementsByFace.size())){ returns_noElements; } returnm_boundaryElementsByFace[as_index(faceID)]; } }