connected.hpp cstddef optional vector serif/discretization/domain/concepts.hpp serif/discretization/domain/mesh/topology.hpp serif/discretization/domain/relation/relations.hpp serif/discretization/domain/relation/validation/runtime.hpp serif/discretization/domain/schema/concepts.hpp serif/discretization/domain/schema/validation/validator.hpp src/include/serif/discretization/domain/schema/validation/all.hpp serif::discretization::domain::schema::validation::RelationValidator< FullyConnected< DomainT > > serif::discretization::domain::schema::validation::FullyConnected serif serif::discretization serif::discretization::domain serif::discretization::domain::schema serif::discretization::domain::schema::validation File containing the specialization of RelationValidator for FullyConnected relations. This relation enforces that a domain is fully connected, meaning that all elements of the domain are reachable from any other element of the domain. Emily M. Boudreaux #pragmaonce #include<cstddef> #include<optional> #include<vector> #include"serif/discretization/domain/concepts.hpp" #include"serif/discretization/domain/mesh/topology.hpp" #include"serif/discretization/domain/relation/relations.hpp" #include"serif/discretization/domain/relation/validation/runtime.hpp" #include"serif/discretization/domain/schema/concepts.hpp" #include"serif/discretization/domain/schema/validation/validator.hpp" //FullyConnected<DomainT>:walkthedomainfromoneofitselementsandcheckwe //reachallofthem. namespaceserif::discretization::domain::schema::validation{ usingrelation::FullyConnected; usingrelation::validation::RelationValidationResult; usingrelation::validation::RelationValidationFailure; template<IsDomainOrSetDomainT> structRelationValidator<FullyConnected<DomainT>>{ template<IsSchemaSchemaT> [[nodiscard]]staticRelationValidationResultvalidate(constmesh::MeshTopology&topology){ static_assert(SchemaT::templatecontains_domain<DomainT>(),"Domainnotpresent,cannotdetermineconnectedness."); constintelementCount=topology.element_count(); //WeshouldbecarefulherethatIhavenotaccidentallyintroducedanissueduetothespecializedvectorbooloverride.Ithinkthisissafethough. std::vector<bool>belongsToDomain(static_cast<std::size_t>(elementCount),false); intdomainElementCount=0; intfirstDomainElement=-1; for(intelementID=0;elementID<elementCount;++elementID){ constintdomainID=topology.element_domain_id(elementID); constboolbelongs=SchemaT::templatedomain_id_belongs_to<DomainT>(domainID); belongsToDomain[static_cast<std::size_t>(elementID)]=belongs; if(!belongs){ continue; } ++domainElementCount; if(firstDomainElement<0){ firstDomainElement=elementID; } } if(domainElementCount==0){ return{ .failure=RelationValidationFailure::DomainAbsent, .connectedDiagnostics=RelationValidationResult::ConnectedDiagnostics{ .domainElementCount=0, .visitedElementCount=0 }}; } std::vector<bool>visited(static_cast<std::size_t>(elementCount),false); std::vector<int>pending; pending.reserve(static_cast<std::size_t>(domainElementCount)); pending.push_back(firstDomainElement); intvisitedElementCount=0; while(!pending.empty()){ constintelementID=pending.back(); pending.pop_back(); if(visited[static_cast<std::size_t>(elementID)]){ continue; } visited[static_cast<std::size_t>(elementID)]=true; ++visitedElementCount; for(constintneighborElementID:topology.element_neighbors(elementID)){ conststd::size_tneighborIndex=static_cast<std::size_t>(neighborElementID); if(belongsToDomain[neighborIndex]&&!visited[neighborIndex]){ pending.push_back(neighborElementID); } } } if(visitedElementCount==domainElementCount){ return{ .connectedDiagnostics=RelationValidationResult::ConnectedDiagnostics{.domainElementCount=domainElementCount,.visitedElementCount=visitedElementCount} }; } intdisconnectedElementID=-1; for(intelementID=0;elementID<elementCount;++elementID){ conststd::size_tindex=static_cast<std::size_t>(elementID); if(belongsToDomain[index]&&!visited[index]){ disconnectedElementID=elementID; break; } } return{ .failure=RelationValidationFailure::DomainDisconnected, .connectedDiagnostics=RelationValidationResult::ConnectedDiagnostics{ .elementID=disconnectedElementID, .domainElementCount=domainElementCount, .visitedElementCount=visitedElementCount }}; } }; }