1af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
25e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h>
35e5bbd0aSStefano Zampini #include <petsc/private/pcbddcstructsimpl.h>
49de2952eSStefano Zampini #include <petsc/private/hashmapi.h>
52daa06b4SStefano Zampini #include <petsc/private/pcbddcgraphhashmap.h>
69de2952eSStefano Zampini #include <petscsf.h>
7674ae819SStefano Zampini
PCBDDCDestroyGraphCandidatesIS(PetscCtxRt ctx)8*2a8381b2SBarry Smith PetscErrorCode PCBDDCDestroyGraphCandidatesIS(PetscCtxRt ctx)
9d71ae5a4SJacob Faibussowitsch {
10*2a8381b2SBarry Smith PCBDDCGraphCandidates cand = *(PCBDDCGraphCandidates *)ctx;
1132fe681dSStefano Zampini
1232fe681dSStefano Zampini PetscFunctionBegin;
1332fe681dSStefano Zampini for (PetscInt i = 0; i < cand->nfc; i++) PetscCall(ISDestroy(&cand->Faces[i]));
1432fe681dSStefano Zampini for (PetscInt i = 0; i < cand->nec; i++) PetscCall(ISDestroy(&cand->Edges[i]));
1532fe681dSStefano Zampini PetscCall(PetscFree(cand->Faces));
1632fe681dSStefano Zampini PetscCall(PetscFree(cand->Edges));
1732fe681dSStefano Zampini PetscCall(ISDestroy(&cand->Vertices));
1832fe681dSStefano Zampini PetscCall(PetscFree(cand));
193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2032fe681dSStefano Zampini }
2132fe681dSStefano Zampini
PCBDDCGraphGetDirichletDofsB(PCBDDCGraph graph,IS * dirdofs)22d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphGetDirichletDofsB(PCBDDCGraph graph, IS *dirdofs)
23d71ae5a4SJacob Faibussowitsch {
24d62866d3SStefano Zampini PetscFunctionBegin;
25d62866d3SStefano Zampini if (graph->dirdofsB) {
269566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)graph->dirdofsB));
27d62866d3SStefano Zampini } else if (graph->has_dirichlet) {
28d62866d3SStefano Zampini PetscInt i, size;
29d62866d3SStefano Zampini PetscInt *dirdofs_idxs;
30d62866d3SStefano Zampini
31d62866d3SStefano Zampini size = 0;
32d62866d3SStefano Zampini for (i = 0; i < graph->nvtxs; i++) {
339de2952eSStefano Zampini if (graph->nodes[i].count > 1 && graph->nodes[i].special_dof == PCBDDCGRAPH_DIRICHLET_MARK) size++;
34d62866d3SStefano Zampini }
35d62866d3SStefano Zampini
369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &dirdofs_idxs));
37d62866d3SStefano Zampini size = 0;
38d62866d3SStefano Zampini for (i = 0; i < graph->nvtxs; i++) {
399de2952eSStefano Zampini if (graph->nodes[i].count > 1 && graph->nodes[i].special_dof == PCBDDCGRAPH_DIRICHLET_MARK) dirdofs_idxs[size++] = i;
40d62866d3SStefano Zampini }
419566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, dirdofs_idxs, PETSC_OWN_POINTER, &graph->dirdofsB));
429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)graph->dirdofsB));
43d62866d3SStefano Zampini }
44d62866d3SStefano Zampini *dirdofs = graph->dirdofsB;
453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
46d62866d3SStefano Zampini }
47d62866d3SStefano Zampini
PCBDDCGraphGetDirichletDofs(PCBDDCGraph graph,IS * dirdofs)48d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphGetDirichletDofs(PCBDDCGraph graph, IS *dirdofs)
49d71ae5a4SJacob Faibussowitsch {
501b968477SStefano Zampini PetscFunctionBegin;
51a07ea27aSStefano Zampini if (graph->dirdofs) {
529566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)graph->dirdofs));
53a07ea27aSStefano Zampini } else if (graph->has_dirichlet) {
54a07ea27aSStefano Zampini PetscInt i, size;
55a07ea27aSStefano Zampini PetscInt *dirdofs_idxs;
56a07ea27aSStefano Zampini
571b968477SStefano Zampini size = 0;
581b968477SStefano Zampini for (i = 0; i < graph->nvtxs; i++) {
599de2952eSStefano Zampini if (graph->nodes[i].special_dof == PCBDDCGRAPH_DIRICHLET_MARK) size++;
601b968477SStefano Zampini }
611b968477SStefano Zampini
629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &dirdofs_idxs));
631b968477SStefano Zampini size = 0;
641b968477SStefano Zampini for (i = 0; i < graph->nvtxs; i++) {
659de2952eSStefano Zampini if (graph->nodes[i].special_dof == PCBDDCGRAPH_DIRICHLET_MARK) dirdofs_idxs[size++] = i;
661b968477SStefano Zampini }
679566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)graph->l2gmap), size, dirdofs_idxs, PETSC_OWN_POINTER, &graph->dirdofs));
689566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)graph->dirdofs));
691b968477SStefano Zampini }
70a07ea27aSStefano Zampini *dirdofs = graph->dirdofs;
713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
721b968477SStefano Zampini }
731b968477SStefano Zampini
PCBDDCGraphASCIIView(PCBDDCGraph graph,PetscInt verbosity_level,PetscViewer viewer)74d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphASCIIView(PCBDDCGraph graph, PetscInt verbosity_level, PetscViewer viewer)
75d71ae5a4SJacob Faibussowitsch {
762b510759SStefano Zampini PetscInt i, j, tabs;
7793fb5fd3SStefano Zampini PetscInt *queue_in_global_numbering;
78674ae819SStefano Zampini
79674ae819SStefano Zampini PetscFunctionBegin;
8094d400adSStefano Zampini if (!viewer) PetscCall(PetscViewerASCIIGetStdout(graph->seq_graph ? PETSC_COMM_SELF : PetscObjectComm((PetscObject)graph->l2gmap), &viewer));
819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer));
829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "--------------------------------------------------\n"));
849566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer));
859de2952eSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Local BDDC graph for subdomain %04d (seq %d)\n", PetscGlobalRank, graph->seq_graph));
8663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Number of vertices %" PetscInt_FMT "\n", graph->nvtxs));
8763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Number of local subdomains %" PetscInt_FMT "\n", graph->n_local_subs ? graph->n_local_subs : 1));
8863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Custom minimal size %" PetscInt_FMT "\n", graph->custom_minimal_size));
891690c2aeSBarry Smith if (graph->maxcount != PETSC_INT_MAX) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Max count %" PetscInt_FMT "\n", graph->maxcount));
9063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Topological two dim? %s (set %s)\n", PetscBools[graph->twodim], PetscBools[graph->twodimset]));
91d4890cceSStefano Zampini if (verbosity_level > 2) {
92674ae819SStefano Zampini for (i = 0; i < graph->nvtxs; i++) {
9363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":\n", i));
949de2952eSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " which_dof: %" PetscInt_FMT "\n", graph->nodes[i].which_dof));
959de2952eSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " special_dof: %" PetscInt_FMT "\n", graph->nodes[i].special_dof));
969de2952eSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " shared by: %" PetscInt_FMT "\n", graph->nodes[i].count));
979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
989de2952eSStefano Zampini if (graph->nodes[i].count) {
999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " set of neighbours:"));
1009de2952eSStefano Zampini for (j = 0; j < graph->nodes[i].count; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, graph->nodes[i].neighbours_set[j]));
1019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
102674ae819SStefano Zampini }
1039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1059de2952eSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " number of local groups: %" PetscInt_FMT "\n", graph->nodes[i].local_groups_count));
1069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1079de2952eSStefano Zampini if (graph->nodes[i].local_groups_count) {
1089de2952eSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " groups:"));
1099de2952eSStefano Zampini for (j = 0; j < graph->nodes[i].local_groups_count; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, graph->nodes[i].local_groups[j]));
1109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
1119de2952eSStefano Zampini }
1129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1149de2952eSStefano Zampini
115d4890cceSStefano Zampini if (verbosity_level > 3) {
1161633d1f0SStefano Zampini if (graph->xadj) {
1179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " local adj list:"));
1189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
11948a46eb9SPierre Jolivet for (j = graph->xadj[i]; j < graph->xadj[i + 1]; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, graph->adjncy[j]));
1209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
1219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
123ec1c413dSStefano Zampini } else {
1249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " no adj info\n"));
125674ae819SStefano Zampini }
126e49050b4SStefano Zampini }
12748a46eb9SPierre Jolivet if (graph->n_local_subs) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " local sub id: %" PetscInt_FMT "\n", graph->local_subs[i]));
1289de2952eSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " interface subset id: %" PetscInt_FMT "\n", graph->nodes[i].subset));
1299de2952eSStefano Zampini if (graph->nodes[i].subset && graph->subset_ncc) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " ncc for subset: %" PetscInt_FMT "\n", graph->subset_ncc[graph->nodes[i].subset - 1]));
130674ae819SStefano Zampini }
131e49050b4SStefano Zampini }
13263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Total number of connected components %" PetscInt_FMT "\n", graph->ncc));
1339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->cptr[graph->ncc], &queue_in_global_numbering));
1349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(graph->l2gmap, graph->cptr[graph->ncc], graph->queue, queue_in_global_numbering));
135674ae819SStefano Zampini for (i = 0; i < graph->ncc; i++) {
1361ce3d396SStefano Zampini PetscInt node_num = graph->queue[graph->cptr[i]];
1371ce3d396SStefano Zampini PetscBool printcc = PETSC_FALSE;
1389de2952eSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " cc %" PetscInt_FMT " (size %" PetscInt_FMT ", fid %" PetscInt_FMT ", neighs:", i, graph->cptr[i + 1] - graph->cptr[i], graph->nodes[node_num].which_dof));
1399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1409de2952eSStefano Zampini for (j = 0; j < graph->nodes[node_num].count; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, graph->nodes[node_num].neighbours_set[j]));
141d4890cceSStefano Zampini if (verbosity_level > 1) {
1429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "):"));
143ac530a7eSPierre Jolivet if (verbosity_level > 2 || graph->twodim || graph->nodes[node_num].count > 2 || (graph->nodes[node_num].count == 2 && graph->nodes[node_num].special_dof == PCBDDCGRAPH_NEUMANN_MARK)) printcc = PETSC_TRUE;
1441ce3d396SStefano Zampini if (printcc) {
14548a46eb9SPierre Jolivet for (j = graph->cptr[i]; j < graph->cptr[i + 1]; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT " (%" PetscInt_FMT ")", graph->queue[j], queue_in_global_numbering[j]));
1461ce3d396SStefano Zampini }
147d4890cceSStefano Zampini } else {
1489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ")"));
149d4890cceSStefano Zampini }
1509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
1519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetTab(viewer, tabs));
1529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
153674ae819SStefano Zampini }
1549566063dSJacob Faibussowitsch PetscCall(PetscFree(queue_in_global_numbering));
1559566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer));
1563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
157674ae819SStefano Zampini }
158674ae819SStefano Zampini
PCBDDCGraphRestoreCandidatesIS(PCBDDCGraph graph,PetscInt * n_faces,IS * FacesIS[],PetscInt * n_edges,IS * EdgesIS[],IS * VerticesIS)159d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphRestoreCandidatesIS(PCBDDCGraph graph, PetscInt *n_faces, IS *FacesIS[], PetscInt *n_edges, IS *EdgesIS[], IS *VerticesIS)
160d71ae5a4SJacob Faibussowitsch {
161c8272957SStefano Zampini PetscInt i;
16232fe681dSStefano Zampini PetscContainer gcand;
163c8272957SStefano Zampini
164c8272957SStefano Zampini PetscFunctionBegin;
16532fe681dSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)graph->l2gmap, "_PCBDDCGraphCandidatesIS", (PetscObject *)&gcand));
16632fe681dSStefano Zampini if (gcand) {
16732fe681dSStefano Zampini if (n_faces) *n_faces = 0;
16832fe681dSStefano Zampini if (n_edges) *n_edges = 0;
16932fe681dSStefano Zampini if (FacesIS) *FacesIS = NULL;
17032fe681dSStefano Zampini if (EdgesIS) *EdgesIS = NULL;
17132fe681dSStefano Zampini if (VerticesIS) *VerticesIS = NULL;
17232fe681dSStefano Zampini }
173c8272957SStefano Zampini if (n_faces) {
174c8272957SStefano Zampini if (FacesIS) {
17557508eceSPierre Jolivet for (i = 0; i < *n_faces; i++) PetscCall(ISDestroy(&(*FacesIS)[i]));
1769566063dSJacob Faibussowitsch PetscCall(PetscFree(*FacesIS));
177c8272957SStefano Zampini }
178c8272957SStefano Zampini *n_faces = 0;
179c8272957SStefano Zampini }
180c8272957SStefano Zampini if (n_edges) {
181c8272957SStefano Zampini if (EdgesIS) {
18257508eceSPierre Jolivet for (i = 0; i < *n_edges; i++) PetscCall(ISDestroy(&(*EdgesIS)[i]));
1839566063dSJacob Faibussowitsch PetscCall(PetscFree(*EdgesIS));
184c8272957SStefano Zampini }
185c8272957SStefano Zampini *n_edges = 0;
186c8272957SStefano Zampini }
1871baa6e33SBarry Smith if (VerticesIS) PetscCall(ISDestroy(VerticesIS));
1883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
189c8272957SStefano Zampini }
190c8272957SStefano Zampini
PCBDDCGraphGetCandidatesIS(PCBDDCGraph graph,PetscInt * n_faces,IS * FacesIS[],PetscInt * n_edges,IS * EdgesIS[],IS * VerticesIS)191d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphGetCandidatesIS(PCBDDCGraph graph, PetscInt *n_faces, IS *FacesIS[], PetscInt *n_edges, IS *EdgesIS[], IS *VerticesIS)
192d71ae5a4SJacob Faibussowitsch {
193674ae819SStefano Zampini IS *ISForFaces, *ISForEdges, ISForVertices;
194be12c134Sstefano_zampini PetscInt i, nfc, nec, nvc, *idx, *mark;
19532fe681dSStefano Zampini PetscContainer gcand;
196674ae819SStefano Zampini
197674ae819SStefano Zampini PetscFunctionBegin;
19832fe681dSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)graph->l2gmap, "_PCBDDCGraphCandidatesIS", (PetscObject *)&gcand));
19932fe681dSStefano Zampini if (gcand) {
20032fe681dSStefano Zampini PCBDDCGraphCandidates cand;
20132fe681dSStefano Zampini
202*2a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(gcand, &cand));
20332fe681dSStefano Zampini if (n_faces) *n_faces = cand->nfc;
20432fe681dSStefano Zampini if (FacesIS) *FacesIS = cand->Faces;
20532fe681dSStefano Zampini if (n_edges) *n_edges = cand->nec;
20632fe681dSStefano Zampini if (EdgesIS) *EdgesIS = cand->Edges;
20732fe681dSStefano Zampini if (VerticesIS) *VerticesIS = cand->Vertices;
2083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
20932fe681dSStefano Zampini }
2109566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(graph->ncc, &mark));
211da81f932SPierre Jolivet /* loop on ccs to evaluate number of faces, edges and vertices */
212674ae819SStefano Zampini nfc = 0;
213674ae819SStefano Zampini nec = 0;
214674ae819SStefano Zampini nvc = 0;
215674ae819SStefano Zampini for (i = 0; i < graph->ncc; i++) {
2161e1f2d93SStefano Zampini PetscInt repdof = graph->queue[graph->cptr[i]];
2179de2952eSStefano Zampini if (graph->cptr[i + 1] - graph->cptr[i] > graph->custom_minimal_size && graph->nodes[repdof].count <= graph->maxcount) {
2189de2952eSStefano Zampini if (!graph->twodim && graph->nodes[repdof].count == 2 && graph->nodes[repdof].special_dof != PCBDDCGRAPH_NEUMANN_MARK) {
219674ae819SStefano Zampini nfc++;
220be12c134Sstefano_zampini mark[i] = 2;
221be12c134Sstefano_zampini } else {
222674ae819SStefano Zampini nec++;
223be12c134Sstefano_zampini mark[i] = 1;
224674ae819SStefano Zampini }
225674ae819SStefano Zampini } else {
226674ae819SStefano Zampini nvc += graph->cptr[i + 1] - graph->cptr[i];
227674ae819SStefano Zampini }
228674ae819SStefano Zampini }
229adfc4fb2SStefano Zampini
230674ae819SStefano Zampini /* allocate IS arrays for faces, edges. Vertices need a single index set. */
23148a46eb9SPierre Jolivet if (FacesIS) PetscCall(PetscMalloc1(nfc, &ISForFaces));
23248a46eb9SPierre Jolivet if (EdgesIS) PetscCall(PetscMalloc1(nec, &ISForEdges));
23348a46eb9SPierre Jolivet if (VerticesIS) PetscCall(PetscMalloc1(nvc, &idx));
234cf5a6209SStefano Zampini
235674ae819SStefano Zampini /* loop on ccs to compute index sets for faces and edges */
236acc113dbSStefano Zampini if (!graph->queue_sorted) {
237acc113dbSStefano Zampini PetscInt *queue_global;
238acc113dbSStefano Zampini
2399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->cptr[graph->ncc], &queue_global));
2409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(graph->l2gmap, graph->cptr[graph->ncc], graph->queue, queue_global));
24148a46eb9SPierre Jolivet for (i = 0; i < graph->ncc; i++) PetscCall(PetscSortIntWithArray(graph->cptr[i + 1] - graph->cptr[i], &queue_global[graph->cptr[i]], &graph->queue[graph->cptr[i]]));
2429566063dSJacob Faibussowitsch PetscCall(PetscFree(queue_global));
243acc113dbSStefano Zampini graph->queue_sorted = PETSC_TRUE;
244acc113dbSStefano Zampini }
245674ae819SStefano Zampini nfc = 0;
246674ae819SStefano Zampini nec = 0;
247674ae819SStefano Zampini for (i = 0; i < graph->ncc; i++) {
248be12c134Sstefano_zampini if (mark[i] == 2) {
24948a46eb9SPierre Jolivet if (FacesIS) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, graph->cptr[i + 1] - graph->cptr[i], &graph->queue[graph->cptr[i]], PETSC_USE_POINTER, &ISForFaces[nfc]));
250674ae819SStefano Zampini nfc++;
251be12c134Sstefano_zampini } else if (mark[i] == 1) {
25248a46eb9SPierre Jolivet if (EdgesIS) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, graph->cptr[i + 1] - graph->cptr[i], &graph->queue[graph->cptr[i]], PETSC_USE_POINTER, &ISForEdges[nec]));
253674ae819SStefano Zampini nec++;
254674ae819SStefano Zampini }
255674ae819SStefano Zampini }
256be12c134Sstefano_zampini
257674ae819SStefano Zampini /* index set for vertices */
258cf5a6209SStefano Zampini if (VerticesIS) {
259b8ffe317SStefano Zampini nvc = 0;
260674ae819SStefano Zampini for (i = 0; i < graph->ncc; i++) {
261be12c134Sstefano_zampini if (!mark[i]) {
262adfc4fb2SStefano Zampini PetscInt j;
263adfc4fb2SStefano Zampini
264674ae819SStefano Zampini for (j = graph->cptr[i]; j < graph->cptr[i + 1]; j++) {
265674ae819SStefano Zampini idx[nvc] = graph->queue[j];
266674ae819SStefano Zampini nvc++;
267674ae819SStefano Zampini }
268674ae819SStefano Zampini }
269674ae819SStefano Zampini }
270674ae819SStefano Zampini /* sort vertex set (by local ordering) */
2719566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nvc, idx));
2729566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nvc, idx, PETSC_OWN_POINTER, &ISForVertices));
273674ae819SStefano Zampini }
2749566063dSJacob Faibussowitsch PetscCall(PetscFree(mark));
275be12c134Sstefano_zampini
276674ae819SStefano Zampini /* get back info */
277a873d5d0SStefano Zampini if (n_faces) *n_faces = nfc;
278c8272957SStefano Zampini if (FacesIS) *FacesIS = ISForFaces;
279a873d5d0SStefano Zampini if (n_edges) *n_edges = nec;
280c8272957SStefano Zampini if (EdgesIS) *EdgesIS = ISForEdges;
281c8272957SStefano Zampini if (VerticesIS) *VerticesIS = ISForVertices;
2823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
283674ae819SStefano Zampini }
284674ae819SStefano Zampini
PCBDDCGraphComputeConnectedComponents(PCBDDCGraph graph)285d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphComputeConnectedComponents(PCBDDCGraph graph)
286d71ae5a4SJacob Faibussowitsch {
2879de2952eSStefano Zampini PetscBool adapt_interface;
288674ae819SStefano Zampini MPI_Comm interface_comm;
2899de2952eSStefano Zampini PetscBT cornerp = NULL;
290674ae819SStefano Zampini
291674ae819SStefano Zampini PetscFunctionBegin;
292f4f49eeaSPierre Jolivet PetscCall(PetscObjectGetComm((PetscObject)graph->l2gmap, &interface_comm));
2939de2952eSStefano Zampini /* compute connected components locally */
2949566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponentsLocal(graph));
2959de2952eSStefano Zampini if (graph->seq_graph) PetscFunctionReturn(PETSC_SUCCESS);
2961c7a958bSStefano Zampini
2979de2952eSStefano Zampini if (graph->active_coords && !graph->multi_element) { /* face based corner selection XXX multi_element */
2984f819b78SStefano Zampini PetscBT excluded;
2991c7a958bSStefano Zampini PetscReal *wdist;
3001c7a958bSStefano Zampini PetscInt n_neigh, *neigh, *n_shared, **shared;
3011c7a958bSStefano Zampini PetscInt maxc, ns;
3021c7a958bSStefano Zampini
3039566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(graph->nvtxs, &cornerp));
3049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(graph->l2gmap, &n_neigh, &neigh, &n_shared, &shared));
3051c7a958bSStefano Zampini for (ns = 1, maxc = 0; ns < n_neigh; ns++) maxc = PetscMax(maxc, n_shared[ns]);
3069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxc * graph->cdim, &wdist));
3079566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(maxc, &excluded));
3081c7a958bSStefano Zampini
3091c7a958bSStefano Zampini for (ns = 1; ns < n_neigh; ns++) { /* first proc is self */
3101c7a958bSStefano Zampini PetscReal *anchor, mdist;
3114f819b78SStefano Zampini PetscInt fst, j, k, d, cdim = graph->cdim, n = n_shared[ns];
31251ab8ad6SStefano Zampini PetscInt point1, point2, point3, point4;
3131c7a958bSStefano Zampini
3141c7a958bSStefano Zampini /* import coordinates on shared interface */
3159566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(n, excluded));
3164f819b78SStefano Zampini for (j = 0, fst = -1, k = 0; j < n; j++) {
3174f819b78SStefano Zampini PetscBool skip = PETSC_FALSE;
3184f819b78SStefano Zampini for (d = 0; d < cdim; d++) {
3194f819b78SStefano Zampini PetscReal c = graph->coords[shared[ns][j] * cdim + d];
3204f819b78SStefano Zampini skip = (PetscBool)(skip || c == PETSC_MAX_REAL);
3214f819b78SStefano Zampini wdist[k++] = c;
3224f819b78SStefano Zampini }
323ac530a7eSPierre Jolivet if (skip) PetscCall(PetscBTSet(excluded, j));
324ac530a7eSPierre Jolivet else if (fst == -1) fst = j;
3254f819b78SStefano Zampini }
3264f819b78SStefano Zampini if (fst == -1) continue;
3271c7a958bSStefano Zampini
32851ab8ad6SStefano Zampini /* the dofs are sorted by global numbering, so each rank starts from the same id
32951ab8ad6SStefano Zampini and it will detect the same corners from the given set */
3301c7a958bSStefano Zampini
3311c7a958bSStefano Zampini /* find the farthest point from the starting one */
33251ab8ad6SStefano Zampini anchor = wdist + fst * cdim;
3331c7a958bSStefano Zampini mdist = -1.0;
3344f819b78SStefano Zampini point1 = fst;
3354f819b78SStefano Zampini for (j = fst; j < n; j++) {
3361c7a958bSStefano Zampini PetscReal dist = 0.0;
3371c7a958bSStefano Zampini
3384f819b78SStefano Zampini if (PetscUnlikely(PetscBTLookup(excluded, j))) continue;
3391c7a958bSStefano Zampini for (d = 0; d < cdim; d++) dist += (wdist[j * cdim + d] - anchor[d]) * (wdist[j * cdim + d] - anchor[d]);
3409371c9d4SSatish Balay if (dist > mdist) {
3419371c9d4SSatish Balay mdist = dist;
3429371c9d4SSatish Balay point1 = j;
3439371c9d4SSatish Balay }
3441c7a958bSStefano Zampini }
3451c7a958bSStefano Zampini
3461c7a958bSStefano Zampini /* find the farthest point from point1 */
3471c7a958bSStefano Zampini anchor = wdist + point1 * cdim;
3481c7a958bSStefano Zampini mdist = -1.0;
3494f819b78SStefano Zampini point2 = point1;
3504f819b78SStefano Zampini for (j = fst; j < n; j++) {
3511c7a958bSStefano Zampini PetscReal dist = 0.0;
3521c7a958bSStefano Zampini
3534f819b78SStefano Zampini if (PetscUnlikely(PetscBTLookup(excluded, j))) continue;
3541c7a958bSStefano Zampini for (d = 0; d < cdim; d++) dist += (wdist[j * cdim + d] - anchor[d]) * (wdist[j * cdim + d] - anchor[d]);
3559371c9d4SSatish Balay if (dist > mdist) {
3569371c9d4SSatish Balay mdist = dist;
3579371c9d4SSatish Balay point2 = j;
3589371c9d4SSatish Balay }
3591c7a958bSStefano Zampini }
3601c7a958bSStefano Zampini
3611c7a958bSStefano Zampini /* find the third point maximizing the triangle area */
3621c7a958bSStefano Zampini point3 = point2;
3631c7a958bSStefano Zampini if (cdim > 2) {
3641c7a958bSStefano Zampini PetscReal a = 0.0;
3651c7a958bSStefano Zampini
3661c7a958bSStefano Zampini for (d = 0; d < cdim; d++) a += (wdist[point1 * cdim + d] - wdist[point2 * cdim + d]) * (wdist[point1 * cdim + d] - wdist[point2 * cdim + d]);
367fff73eb4SStefano Zampini a = PetscSqrtReal(a);
3681c7a958bSStefano Zampini mdist = -1.0;
3694f819b78SStefano Zampini for (j = fst; j < n; j++) {
370fff73eb4SStefano Zampini PetscReal area, b = 0.0, c = 0.0, s;
3711c7a958bSStefano Zampini
3724f819b78SStefano Zampini if (PetscUnlikely(PetscBTLookup(excluded, j))) continue;
3731c7a958bSStefano Zampini for (d = 0; d < cdim; d++) {
3741c7a958bSStefano Zampini b += (wdist[point1 * cdim + d] - wdist[j * cdim + d]) * (wdist[point1 * cdim + d] - wdist[j * cdim + d]);
3751c7a958bSStefano Zampini c += (wdist[point2 * cdim + d] - wdist[j * cdim + d]) * (wdist[point2 * cdim + d] - wdist[j * cdim + d]);
3761c7a958bSStefano Zampini }
377fff73eb4SStefano Zampini b = PetscSqrtReal(b);
378fff73eb4SStefano Zampini c = PetscSqrtReal(c);
379fff73eb4SStefano Zampini s = 0.5 * (a + b + c);
3804f819b78SStefano Zampini
3814f819b78SStefano Zampini /* Heron's formula, area squared */
3824f819b78SStefano Zampini area = s * (s - a) * (s - b) * (s - c);
3839371c9d4SSatish Balay if (area > mdist) {
3849371c9d4SSatish Balay mdist = area;
3859371c9d4SSatish Balay point3 = j;
3869371c9d4SSatish Balay }
3871c7a958bSStefano Zampini }
3881c7a958bSStefano Zampini }
3891c7a958bSStefano Zampini
39051ab8ad6SStefano Zampini /* find the farthest point from point3 different from point1 and point2 */
39151ab8ad6SStefano Zampini anchor = wdist + point3 * cdim;
39251ab8ad6SStefano Zampini mdist = -1.0;
39351ab8ad6SStefano Zampini point4 = point3;
39451ab8ad6SStefano Zampini for (j = fst; j < n; j++) {
39551ab8ad6SStefano Zampini PetscReal dist = 0.0;
39651ab8ad6SStefano Zampini
39751ab8ad6SStefano Zampini if (PetscUnlikely(PetscBTLookup(excluded, j)) || j == point1 || j == point2 || j == point3) continue;
39851ab8ad6SStefano Zampini for (d = 0; d < cdim; d++) dist += (wdist[j * cdim + d] - anchor[d]) * (wdist[j * cdim + d] - anchor[d]);
3999371c9d4SSatish Balay if (dist > mdist) {
4009371c9d4SSatish Balay mdist = dist;
4019371c9d4SSatish Balay point4 = j;
4029371c9d4SSatish Balay }
40351ab8ad6SStefano Zampini }
40451ab8ad6SStefano Zampini
4059566063dSJacob Faibussowitsch PetscCall(PetscBTSet(cornerp, shared[ns][point1]));
4069566063dSJacob Faibussowitsch PetscCall(PetscBTSet(cornerp, shared[ns][point2]));
4079566063dSJacob Faibussowitsch PetscCall(PetscBTSet(cornerp, shared[ns][point3]));
40851ab8ad6SStefano Zampini PetscCall(PetscBTSet(cornerp, shared[ns][point4]));
4094f819b78SStefano Zampini
4101c7a958bSStefano Zampini /* all dofs having the same coordinates will be primal */
4114f819b78SStefano Zampini for (j = fst; j < n; j++) {
41251ab8ad6SStefano Zampini PetscBool same[] = {PETSC_TRUE, PETSC_TRUE, PETSC_TRUE, PETSC_TRUE};
4131c7a958bSStefano Zampini
4144f819b78SStefano Zampini if (PetscUnlikely(PetscBTLookup(excluded, j))) continue;
4151c7a958bSStefano Zampini for (d = 0; d < cdim; d++) {
4161c7a958bSStefano Zampini same[0] = (PetscBool)(same[0] && (PetscAbsReal(wdist[j * cdim + d] - wdist[point1 * cdim + d]) < PETSC_SMALL));
4171c7a958bSStefano Zampini same[1] = (PetscBool)(same[1] && (PetscAbsReal(wdist[j * cdim + d] - wdist[point2 * cdim + d]) < PETSC_SMALL));
4181c7a958bSStefano Zampini same[2] = (PetscBool)(same[2] && (PetscAbsReal(wdist[j * cdim + d] - wdist[point3 * cdim + d]) < PETSC_SMALL));
41951ab8ad6SStefano Zampini same[3] = (PetscBool)(same[3] && (PetscAbsReal(wdist[j * cdim + d] - wdist[point4 * cdim + d]) < PETSC_SMALL));
4201c7a958bSStefano Zampini }
42148a46eb9SPierre Jolivet if (same[0] || same[1] || same[2] || same[3]) PetscCall(PetscBTSet(cornerp, shared[ns][j]));
4221c7a958bSStefano Zampini }
4231c7a958bSStefano Zampini }
4249566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&excluded));
4259566063dSJacob Faibussowitsch PetscCall(PetscFree(wdist));
4269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap, &n_neigh, &neigh, &n_shared, &shared));
4271c7a958bSStefano Zampini }
4281c7a958bSStefano Zampini
4299de2952eSStefano Zampini /* Adapt connected components if needed */
4309de2952eSStefano Zampini adapt_interface = (cornerp || graph->multi_element) ? PETSC_TRUE : PETSC_FALSE;
4319de2952eSStefano Zampini for (PetscInt i = 0; i < graph->n_subsets && !adapt_interface; i++) {
4321c7a958bSStefano Zampini if (graph->subset_ncc[i] > 1) adapt_interface = PETSC_TRUE;
433674ae819SStefano Zampini }
4345440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &adapt_interface, 1, MPI_C_BOOL, MPI_LOR, interface_comm));
4359de2952eSStefano Zampini if (adapt_interface) {
4369de2952eSStefano Zampini PetscSF msf;
4379de2952eSStefano Zampini const PetscInt *n_ref_sharing;
4389de2952eSStefano Zampini PetscInt *labels, *rootlabels, *mrlabels;
4399de2952eSStefano Zampini PetscInt nr, nmr, nrs, ncc, cum_queue;
440674ae819SStefano Zampini
4419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->nvtxs, &labels));
4429566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(labels, graph->nvtxs));
4439de2952eSStefano Zampini for (PetscInt i = 0, k = 0; i < graph->ncc; i++) {
4441c7a958bSStefano Zampini PetscInt s = 1;
4459de2952eSStefano Zampini for (PetscInt j = graph->cptr[i]; j < graph->cptr[i + 1]; j++) {
4461c7a958bSStefano Zampini if (cornerp && PetscBTLookup(cornerp, graph->queue[j])) {
4479de2952eSStefano Zampini labels[graph->queue[j]] = -(k + s + 1);
4481c7a958bSStefano Zampini s += 1;
4491c7a958bSStefano Zampini } else {
4509de2952eSStefano Zampini labels[graph->queue[j]] = -(k + 1);
4511c7a958bSStefano Zampini }
4521c7a958bSStefano Zampini }
4531c7a958bSStefano Zampini k += s;
4541c7a958bSStefano Zampini }
4559de2952eSStefano Zampini PetscCall(PetscSFGetGraph(graph->interface_ref_sf, &nr, NULL, NULL, NULL));
4569de2952eSStefano Zampini PetscCall(PetscSFGetGraph(graph->interface_subset_sf, &nrs, NULL, NULL, NULL));
4579de2952eSStefano Zampini PetscCall(PetscSFGetMultiSF(graph->interface_subset_sf, &msf));
4589de2952eSStefano Zampini PetscCall(PetscSFGetGraph(msf, &nmr, NULL, NULL, NULL));
4599de2952eSStefano Zampini PetscCall(PetscCalloc2(nmr, &mrlabels, nrs, &rootlabels));
460b3cdcd63SStefano Zampini
4619de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeBegin(graph->interface_subset_sf, &n_ref_sharing));
4629de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeEnd(graph->interface_subset_sf, &n_ref_sharing));
4639de2952eSStefano Zampini PetscCall(PetscSFGatherBegin(graph->interface_subset_sf, MPIU_INT, labels, mrlabels));
4649de2952eSStefano Zampini PetscCall(PetscSFGatherEnd(graph->interface_subset_sf, MPIU_INT, labels, mrlabels));
465b3cdcd63SStefano Zampini
4669de2952eSStefano Zampini /* analyze contributions from processes
4679de2952eSStefano Zampini The structure of mrlabels is suitable to find intersections of ccs.
4689de2952eSStefano Zampini supposing the root subset has dimension 5 and leaves with labels:
4699de2952eSStefano Zampini 0: [4 4 7 4 7], (2 connected components)
4709de2952eSStefano Zampini 1: [3 2 2 3 2], (2 connected components)
4719de2952eSStefano Zampini 2: [1 1 6 5 6], (3 connected components)
4729de2952eSStefano Zampini the multiroot data and the new labels corresponding to intersected connected components will be (column major)
473b3cdcd63SStefano Zampini
4749de2952eSStefano Zampini 4 4 7 4 7
4759de2952eSStefano Zampini mrlabels 3 2 2 3 2
4769de2952eSStefano Zampini 1 1 6 5 6
4779de2952eSStefano Zampini ---------
4789de2952eSStefano Zampini rootlabels 0 1 2 3 2
4799de2952eSStefano Zampini */
4809de2952eSStefano Zampini for (PetscInt i = 0, rcumlabels = 0, mcumlabels = 0; i < nr; i++) {
4819de2952eSStefano Zampini const PetscInt subset_size = graph->interface_ref_rsize[i];
4829de2952eSStefano Zampini const PetscInt *n_sharing = n_ref_sharing + rcumlabels;
4839de2952eSStefano Zampini const PetscInt *mrbuffer = mrlabels + mcumlabels;
4849de2952eSStefano Zampini PetscInt *rbuffer = rootlabels + rcumlabels;
485b3cdcd63SStefano Zampini PetscInt subset_counter = 0;
486ec1c413dSStefano Zampini
4879de2952eSStefano Zampini for (PetscInt j = 0; j < subset_size; j++) {
4889de2952eSStefano Zampini if (!rbuffer[j]) { /* found a new cc */
4899de2952eSStefano Zampini const PetscInt *jlabels = mrbuffer + j * n_sharing[0];
4909de2952eSStefano Zampini rbuffer[j] = ++subset_counter;
491ec1c413dSStefano Zampini
4929de2952eSStefano Zampini for (PetscInt k = j + 1; k < subset_size; k++) { /* check for other nodes in new cc */
4939de2952eSStefano Zampini PetscBool same_set = PETSC_TRUE;
4949de2952eSStefano Zampini const PetscInt *klabels = mrbuffer + k * n_sharing[0];
4959de2952eSStefano Zampini
4969de2952eSStefano Zampini for (PetscInt s = 0; s < n_sharing[0]; s++) {
4979de2952eSStefano Zampini if (jlabels[s] != klabels[s]) {
498674ae819SStefano Zampini same_set = PETSC_FALSE;
499674ae819SStefano Zampini break;
500674ae819SStefano Zampini }
501674ae819SStefano Zampini }
5029de2952eSStefano Zampini if (same_set) rbuffer[k] = subset_counter;
503674ae819SStefano Zampini }
504674ae819SStefano Zampini }
505674ae819SStefano Zampini }
5069de2952eSStefano Zampini if (subset_size) {
5079de2952eSStefano Zampini rcumlabels += subset_size;
5089de2952eSStefano Zampini mcumlabels += n_sharing[0] * subset_size;
509674ae819SStefano Zampini }
5109de2952eSStefano Zampini }
5119de2952eSStefano Zampini
5129de2952eSStefano Zampini /* Now communicate the intersected labels */
5139de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(graph->interface_subset_sf, MPIU_INT, rootlabels, labels, MPI_REPLACE));
5149de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(graph->interface_subset_sf, MPIU_INT, rootlabels, labels, MPI_REPLACE));
5159de2952eSStefano Zampini PetscCall(PetscFree2(mrlabels, rootlabels));
5169de2952eSStefano Zampini
5179de2952eSStefano Zampini /* and adapt local connected components */
5189de2952eSStefano Zampini PetscInt *ocptr, *oqueue;
5199de2952eSStefano Zampini PetscBool *touched;
5209de2952eSStefano Zampini
5219de2952eSStefano Zampini PetscCall(PetscMalloc3(graph->ncc + 1, &ocptr, graph->cptr[graph->ncc], &oqueue, graph->cptr[graph->ncc], &touched));
5229de2952eSStefano Zampini PetscCall(PetscArraycpy(ocptr, graph->cptr, graph->ncc + 1));
5239de2952eSStefano Zampini PetscCall(PetscArraycpy(oqueue, graph->queue, graph->cptr[graph->ncc]));
5249de2952eSStefano Zampini PetscCall(PetscArrayzero(touched, graph->cptr[graph->ncc]));
5259de2952eSStefano Zampini
5269de2952eSStefano Zampini ncc = 0;
5279de2952eSStefano Zampini cum_queue = 0;
5289de2952eSStefano Zampini for (PetscInt i = 0; i < graph->ncc; i++) {
5299de2952eSStefano Zampini for (PetscInt j = ocptr[i]; j < ocptr[i + 1]; j++) {
5309de2952eSStefano Zampini const PetscInt jlabel = labels[oqueue[j]];
5319de2952eSStefano Zampini
5329de2952eSStefano Zampini if (jlabel) {
533b3cdcd63SStefano Zampini graph->cptr[ncc] = cum_queue;
534b3cdcd63SStefano Zampini ncc++;
5359de2952eSStefano Zampini for (PetscInt k = j; k < ocptr[i + 1]; k++) { /* check for other nodes in new cc */
5369de2952eSStefano Zampini if (labels[oqueue[k]] == jlabel) {
5379de2952eSStefano Zampini graph->queue[cum_queue++] = oqueue[k];
5389de2952eSStefano Zampini labels[oqueue[k]] = 0;
539674ae819SStefano Zampini }
540674ae819SStefano Zampini }
541b3cdcd63SStefano Zampini }
5429de2952eSStefano Zampini }
5439de2952eSStefano Zampini }
5449de2952eSStefano Zampini PetscCall(PetscFree3(ocptr, oqueue, touched));
5459566063dSJacob Faibussowitsch PetscCall(PetscFree(labels));
5469de2952eSStefano Zampini graph->cptr[ncc] = cum_queue;
5479de2952eSStefano Zampini graph->queue_sorted = PETSC_FALSE;
5489de2952eSStefano Zampini graph->ncc = ncc;
549674ae819SStefano Zampini }
5509566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&cornerp));
5518e4af1ccSStefano Zampini
552cc0a5675Sstefano_zampini /* Determine if we are in 2D or 3D */
553cc0a5675Sstefano_zampini if (!graph->twodimset) {
554cc0a5675Sstefano_zampini PetscBool twodim = PETSC_TRUE;
5559de2952eSStefano Zampini for (PetscInt i = 0; i < graph->ncc; i++) {
556cc0a5675Sstefano_zampini PetscInt repdof = graph->queue[graph->cptr[i]];
557cc0a5675Sstefano_zampini PetscInt ccsize = graph->cptr[i + 1] - graph->cptr[i];
5589de2952eSStefano Zampini if (graph->nodes[repdof].count > 2 && ccsize > graph->custom_minimal_size) {
559cc0a5675Sstefano_zampini twodim = PETSC_FALSE;
560cc0a5675Sstefano_zampini break;
561cc0a5675Sstefano_zampini }
562cc0a5675Sstefano_zampini }
5635440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&twodim, &graph->twodim, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)graph->l2gmap)));
564cc0a5675Sstefano_zampini graph->twodimset = PETSC_TRUE;
565cc0a5675Sstefano_zampini }
5663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
567674ae819SStefano Zampini }
568674ae819SStefano Zampini
PCBDDCGraphComputeCC_Private(PCBDDCGraph graph,PetscInt pid,PetscInt * PETSC_RESTRICT queue_tip,PetscInt n_prev,PetscInt * n_added)5699de2952eSStefano Zampini static inline PetscErrorCode PCBDDCGraphComputeCC_Private(PCBDDCGraph graph, PetscInt pid, PetscInt *PETSC_RESTRICT queue_tip, PetscInt n_prev, PetscInt *n_added)
570d71ae5a4SJacob Faibussowitsch {
5719de2952eSStefano Zampini PetscInt i, j, n = 0;
5729de2952eSStefano Zampini
5739de2952eSStefano Zampini const PetscInt *PETSC_RESTRICT xadj = graph->xadj;
5749de2952eSStefano Zampini const PetscInt *PETSC_RESTRICT adjncy = graph->adjncy;
5759de2952eSStefano Zampini const PetscInt *PETSC_RESTRICT subset_idxs = graph->subset_idxs[pid - 1];
5769de2952eSStefano Zampini const PetscInt *PETSC_RESTRICT local_subs = graph->local_subs;
5779de2952eSStefano Zampini const PetscInt subset_size = graph->subset_size[pid - 1];
5789de2952eSStefano Zampini
5799de2952eSStefano Zampini PCBDDCGraphNode *PETSC_RESTRICT nodes = graph->nodes;
5809de2952eSStefano Zampini
5819de2952eSStefano Zampini const PetscBool havecsr = (PetscBool)(!!xadj);
5829de2952eSStefano Zampini const PetscBool havesubs = (PetscBool)(!!graph->n_local_subs);
583b3cdcd63SStefano Zampini
584b3cdcd63SStefano Zampini PetscFunctionBegin;
585b3cdcd63SStefano Zampini if (havecsr && !havesubs) {
586b3cdcd63SStefano Zampini for (i = -n_prev; i < 0; i++) {
5879de2952eSStefano Zampini const PetscInt start_dof = queue_tip[i];
5889de2952eSStefano Zampini
58954fffbccSStefano Zampini /* we assume that if a dof has a size 1 adjacency list and the corresponding entry is negative, it is connected to all dofs */
59054fffbccSStefano Zampini if (xadj[start_dof + 1] - xadj[start_dof] == 1 && adjncy[xadj[start_dof]] < 0) {
5919de2952eSStefano Zampini for (j = 0; j < subset_size; j++) { /* pid \in [1,graph->n_subsets] */
5929de2952eSStefano Zampini const PetscInt dof = subset_idxs[j];
5939de2952eSStefano Zampini
5949de2952eSStefano Zampini if (!nodes[dof].touched && nodes[dof].subset == pid) {
5959de2952eSStefano Zampini nodes[dof].touched = PETSC_TRUE;
59654fffbccSStefano Zampini queue_tip[n] = dof;
59754fffbccSStefano Zampini n++;
59854fffbccSStefano Zampini }
59954fffbccSStefano Zampini }
60054fffbccSStefano Zampini } else {
601b3cdcd63SStefano Zampini for (j = xadj[start_dof]; j < xadj[start_dof + 1]; j++) {
6029de2952eSStefano Zampini const PetscInt dof = adjncy[j];
6039de2952eSStefano Zampini
6049de2952eSStefano Zampini if (!nodes[dof].touched && nodes[dof].subset == pid) {
6059de2952eSStefano Zampini nodes[dof].touched = PETSC_TRUE;
606b3cdcd63SStefano Zampini queue_tip[n] = dof;
607b3cdcd63SStefano Zampini n++;
608b3cdcd63SStefano Zampini }
609b3cdcd63SStefano Zampini }
610b3cdcd63SStefano Zampini }
61154fffbccSStefano Zampini }
612b3cdcd63SStefano Zampini } else if (havecsr && havesubs) {
6139de2952eSStefano Zampini const PetscInt sid = local_subs[queue_tip[-n_prev]];
6149de2952eSStefano Zampini
615b3cdcd63SStefano Zampini for (i = -n_prev; i < 0; i++) {
6169de2952eSStefano Zampini const PetscInt start_dof = queue_tip[i];
6179de2952eSStefano Zampini
61854fffbccSStefano Zampini /* we assume that if a dof has a size 1 adjacency list and the corresponding entry is negative, it is connected to all dofs belonging to the local sub */
61954fffbccSStefano Zampini if (xadj[start_dof + 1] - xadj[start_dof] == 1 && adjncy[xadj[start_dof]] < 0) {
6209de2952eSStefano Zampini for (j = 0; j < subset_size; j++) { /* pid \in [1,graph->n_subsets] */
6219de2952eSStefano Zampini const PetscInt dof = subset_idxs[j];
6229de2952eSStefano Zampini
6239de2952eSStefano Zampini if (!nodes[dof].touched && nodes[dof].subset == pid && local_subs[dof] == sid) {
6249de2952eSStefano Zampini nodes[dof].touched = PETSC_TRUE;
62554fffbccSStefano Zampini queue_tip[n] = dof;
62654fffbccSStefano Zampini n++;
62754fffbccSStefano Zampini }
62854fffbccSStefano Zampini }
62954fffbccSStefano Zampini } else {
630b3cdcd63SStefano Zampini for (j = xadj[start_dof]; j < xadj[start_dof + 1]; j++) {
6319de2952eSStefano Zampini const PetscInt dof = adjncy[j];
6329de2952eSStefano Zampini
6339de2952eSStefano Zampini if (!nodes[dof].touched && nodes[dof].subset == pid && local_subs[dof] == sid) {
6349de2952eSStefano Zampini nodes[dof].touched = PETSC_TRUE;
635b3cdcd63SStefano Zampini queue_tip[n] = dof;
636b3cdcd63SStefano Zampini n++;
637b3cdcd63SStefano Zampini }
638b3cdcd63SStefano Zampini }
639b3cdcd63SStefano Zampini }
64054fffbccSStefano Zampini }
6411c7a958bSStefano Zampini } else if (havesubs) { /* sub info only */
6429de2952eSStefano Zampini const PetscInt sid = local_subs[queue_tip[-n_prev]];
6439de2952eSStefano Zampini
6449de2952eSStefano Zampini for (j = 0; j < subset_size; j++) { /* pid \in [1,graph->n_subsets] */
6459de2952eSStefano Zampini const PetscInt dof = subset_idxs[j];
6469de2952eSStefano Zampini
6479de2952eSStefano Zampini if (!nodes[dof].touched && nodes[dof].subset == pid && local_subs[dof] == sid) {
6489de2952eSStefano Zampini nodes[dof].touched = PETSC_TRUE;
649b3cdcd63SStefano Zampini queue_tip[n] = dof;
650b3cdcd63SStefano Zampini n++;
651b3cdcd63SStefano Zampini }
652b3cdcd63SStefano Zampini }
6531c7a958bSStefano Zampini } else {
6549de2952eSStefano Zampini for (j = 0; j < subset_size; j++) { /* pid \in [1,graph->n_subsets] */
6559de2952eSStefano Zampini const PetscInt dof = subset_idxs[j];
6569de2952eSStefano Zampini
6579de2952eSStefano Zampini if (!nodes[dof].touched && nodes[dof].subset == pid) {
6589de2952eSStefano Zampini nodes[dof].touched = PETSC_TRUE;
6591c7a958bSStefano Zampini queue_tip[n] = dof;
6601c7a958bSStefano Zampini n++;
6611c7a958bSStefano Zampini }
6621c7a958bSStefano Zampini }
663b3cdcd63SStefano Zampini }
664b3cdcd63SStefano Zampini *n_added = n;
6653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
666b3cdcd63SStefano Zampini }
667b3cdcd63SStefano Zampini
PCBDDCGraphComputeConnectedComponentsLocal(PCBDDCGraph graph)668d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphComputeConnectedComponentsLocal(PCBDDCGraph graph)
669d71ae5a4SJacob Faibussowitsch {
6709de2952eSStefano Zampini PetscInt ncc, cum_queue;
671674ae819SStefano Zampini
672674ae819SStefano Zampini PetscFunctionBegin;
67328b400f6SJacob Faibussowitsch PetscCheck(graph->setupcalled, PetscObjectComm((PetscObject)graph->l2gmap), PETSC_ERR_ORDER, "PCBDDCGraphSetUp should be called first");
674b3cdcd63SStefano Zampini /* quiet return if there isn't any local info */
6753ba16761SJacob Faibussowitsch if (!graph->xadj && !graph->n_local_subs) PetscFunctionReturn(PETSC_SUCCESS);
676674ae819SStefano Zampini
677674ae819SStefano Zampini /* reset any previous search of connected components */
6789de2952eSStefano Zampini for (PetscInt i = 0; i < graph->nvtxs; i++) graph->nodes[i].touched = PETSC_FALSE;
6799de2952eSStefano Zampini if (!graph->seq_graph) {
6809de2952eSStefano Zampini for (PetscInt i = 0; i < graph->nvtxs; i++) {
6819de2952eSStefano Zampini if (graph->nodes[i].special_dof == PCBDDCGRAPH_DIRICHLET_MARK || graph->nodes[i].count < 2) graph->nodes[i].touched = PETSC_TRUE;
6824a060362SStefano Zampini }
683b3cdcd63SStefano Zampini }
684674ae819SStefano Zampini
685674ae819SStefano Zampini /* begin search for connected components */
686674ae819SStefano Zampini cum_queue = 0;
687674ae819SStefano Zampini ncc = 0;
6889de2952eSStefano Zampini for (PetscInt n = 0; n < graph->n_subsets; n++) {
6899de2952eSStefano Zampini const PetscInt *subset_idxs = graph->subset_idxs[n];
6909de2952eSStefano Zampini const PetscInt pid = n + 1; /* partition labeled by 0 is discarded */
6919de2952eSStefano Zampini
692b3cdcd63SStefano Zampini PetscInt found = 0, prev = 0, first = 0, ncc_pid = 0;
6939de2952eSStefano Zampini
694b3cdcd63SStefano Zampini while (found != graph->subset_size[n]) {
695b3cdcd63SStefano Zampini PetscInt added = 0;
6969de2952eSStefano Zampini
697b3cdcd63SStefano Zampini if (!prev) { /* search for new starting dof */
6989de2952eSStefano Zampini while (graph->nodes[subset_idxs[first]].touched) first++;
6999de2952eSStefano Zampini graph->nodes[subset_idxs[first]].touched = PETSC_TRUE;
7009de2952eSStefano Zampini graph->queue[cum_queue] = subset_idxs[first];
701674ae819SStefano Zampini graph->cptr[ncc] = cum_queue;
702b3cdcd63SStefano Zampini prev = 1;
703b3cdcd63SStefano Zampini cum_queue++;
704b3cdcd63SStefano Zampini found++;
705674ae819SStefano Zampini ncc_pid++;
706b3cdcd63SStefano Zampini ncc++;
707674ae819SStefano Zampini }
7089566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeCC_Private(graph, pid, graph->queue + cum_queue, prev, &added));
709b3cdcd63SStefano Zampini if (!added) {
710674ae819SStefano Zampini graph->subset_ncc[n] = ncc_pid;
711b3cdcd63SStefano Zampini graph->cptr[ncc] = cum_queue;
712b3cdcd63SStefano Zampini }
713b3cdcd63SStefano Zampini prev = added;
714b3cdcd63SStefano Zampini found += added;
715b3cdcd63SStefano Zampini cum_queue += added;
716b3cdcd63SStefano Zampini if (added && found == graph->subset_size[n]) {
717b3cdcd63SStefano Zampini graph->subset_ncc[n] = ncc_pid;
718b3cdcd63SStefano Zampini graph->cptr[ncc] = cum_queue;
719b3cdcd63SStefano Zampini }
720b3cdcd63SStefano Zampini }
721674ae819SStefano Zampini }
722674ae819SStefano Zampini graph->ncc = ncc;
723acc113dbSStefano Zampini graph->queue_sorted = PETSC_FALSE;
7243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
725674ae819SStefano Zampini }
726674ae819SStefano Zampini
PCBDDCGraphSetUp(PCBDDCGraph graph,PetscInt custom_minimal_size,IS neumann_is,IS dirichlet_is,PetscInt n_ISForDofs,IS ISForDofs[],IS custom_primal_vertices)727d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphSetUp(PCBDDCGraph graph, PetscInt custom_minimal_size, IS neumann_is, IS dirichlet_is, PetscInt n_ISForDofs, IS ISForDofs[], IS custom_primal_vertices)
728d71ae5a4SJacob Faibussowitsch {
7299de2952eSStefano Zampini IS subset;
730674ae819SStefano Zampini MPI_Comm comm;
7312daa06b4SStefano Zampini PetscHMapPCBDDCGraphNode subsetmaps;
732674ae819SStefano Zampini const PetscInt *is_indices;
7332daa06b4SStefano Zampini PetscInt *queue_global, *nodecount, **nodeneighs, *subset_sizes;
7342daa06b4SStefano Zampini PetscInt i, j, k, nodes_touched, is_size, nvtxs = graph->nvtxs;
7359de2952eSStefano Zampini PetscMPIInt size, rank;
736674ae819SStefano Zampini
737674ae819SStefano Zampini PetscFunctionBegin;
7387a0e7b2cSstefano_zampini PetscValidLogicalCollectiveInt(graph->l2gmap, custom_minimal_size, 2);
7397a0e7b2cSstefano_zampini if (neumann_is) {
7407a0e7b2cSstefano_zampini PetscValidHeaderSpecific(neumann_is, IS_CLASSID, 3);
7417a0e7b2cSstefano_zampini PetscCheckSameComm(graph->l2gmap, 1, neumann_is, 3);
7427a0e7b2cSstefano_zampini }
743a07ea27aSStefano Zampini graph->has_dirichlet = PETSC_FALSE;
744a07ea27aSStefano Zampini if (dirichlet_is) {
7457a0e7b2cSstefano_zampini PetscValidHeaderSpecific(dirichlet_is, IS_CLASSID, 4);
746a07ea27aSStefano Zampini PetscCheckSameComm(graph->l2gmap, 1, dirichlet_is, 4);
747a07ea27aSStefano Zampini graph->has_dirichlet = PETSC_TRUE;
748a07ea27aSStefano Zampini }
7497a0e7b2cSstefano_zampini PetscValidLogicalCollectiveInt(graph->l2gmap, n_ISForDofs, 5);
7507a0e7b2cSstefano_zampini for (i = 0; i < n_ISForDofs; i++) {
7517a0e7b2cSstefano_zampini PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 6);
7527a0e7b2cSstefano_zampini PetscCheckSameComm(graph->l2gmap, 1, ISForDofs[i], 6);
7537a0e7b2cSstefano_zampini }
7547a0e7b2cSstefano_zampini if (custom_primal_vertices) {
755ab8c8b98SStefano Zampini PetscValidHeaderSpecific(custom_primal_vertices, IS_CLASSID, 7);
7567a0e7b2cSstefano_zampini PetscCheckSameComm(graph->l2gmap, 1, custom_primal_vertices, 7);
7577a0e7b2cSstefano_zampini }
7589de2952eSStefano Zampini for (i = 0; i < nvtxs; i++) graph->nodes[i].touched = PETSC_FALSE;
7599de2952eSStefano Zampini
760f4f49eeaSPierre Jolivet PetscCall(PetscObjectGetComm((PetscObject)graph->l2gmap, &comm));
7619de2952eSStefano Zampini PetscCallMPI(MPI_Comm_size(comm, &size));
7629de2952eSStefano Zampini PetscCallMPI(MPI_Comm_rank(comm, &rank));
763b3cdcd63SStefano Zampini
764674ae819SStefano Zampini /* custom_minimal_size */
76514f95afaSStefano Zampini graph->custom_minimal_size = custom_minimal_size;
7667a0e7b2cSstefano_zampini
7679de2952eSStefano Zampini /* get node info from l2gmap */
7689de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(graph->l2gmap, NULL, &nodecount, &nodeneighs));
76951b0f6cfSStefano Zampini
770674ae819SStefano Zampini /* Allocate space for storing the set of neighbours for each node */
7719de2952eSStefano Zampini graph->multi_element = PETSC_FALSE;
7729de2952eSStefano Zampini for (i = 0; i < nvtxs; i++) {
7739de2952eSStefano Zampini graph->nodes[i].count = nodecount[i];
7749de2952eSStefano Zampini if (!graph->seq_graph) {
7759de2952eSStefano Zampini PetscCall(PetscMalloc1(nodecount[i], &graph->nodes[i].neighbours_set));
7769de2952eSStefano Zampini PetscCall(PetscArraycpy(graph->nodes[i].neighbours_set, nodeneighs[i], nodecount[i]));
7779de2952eSStefano Zampini
7789de2952eSStefano Zampini if (!graph->multi_element) {
7799de2952eSStefano Zampini PetscInt nself;
7809de2952eSStefano Zampini for (j = 0, nself = 0; j < graph->nodes[i].count; j++)
7819de2952eSStefano Zampini if (graph->nodes[i].neighbours_set[j] == rank) nself++;
7829de2952eSStefano Zampini if (nself > 1) graph->multi_element = PETSC_TRUE;
783674ae819SStefano Zampini }
7849de2952eSStefano Zampini } else {
7859de2952eSStefano Zampini PetscCall(PetscCalloc1(nodecount[i], &graph->nodes[i].neighbours_set));
786674ae819SStefano Zampini }
787674ae819SStefano Zampini }
7889de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(graph->l2gmap, NULL, &nodecount, &nodeneighs));
7895440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &graph->multi_element, 1, MPI_C_BOOL, MPI_LOR, comm));
7909de2952eSStefano Zampini
7919de2952eSStefano Zampini /* compute local groups */
7929de2952eSStefano Zampini if (graph->multi_element) {
7939de2952eSStefano Zampini const PetscInt *idxs, *indegree;
7949de2952eSStefano Zampini IS is, lis;
7959de2952eSStefano Zampini PetscLayout layout;
7969de2952eSStefano Zampini PetscSF sf, multisf;
7979de2952eSStefano Zampini PetscInt n, nmulti, c, *multi_root_subs, *start;
7989de2952eSStefano Zampini
7990b61a303SStefano Zampini PetscCheck(!nvtxs || graph->local_subs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing local subdomain information");
8009de2952eSStefano Zampini
8019de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetIndices(graph->l2gmap, &idxs));
8029de2952eSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nvtxs, idxs, PETSC_USE_POINTER, &is));
8039de2952eSStefano Zampini PetscCall(ISRenumber(is, NULL, &n, &lis));
8049de2952eSStefano Zampini PetscCall(ISDestroy(&is));
8059de2952eSStefano Zampini
8069de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreIndices(graph->l2gmap, &idxs));
8079de2952eSStefano Zampini PetscCall(ISGetIndices(lis, &idxs));
8089de2952eSStefano Zampini PetscCall(PetscLayoutCreate(PETSC_COMM_SELF, &layout));
8099de2952eSStefano Zampini PetscCall(PetscLayoutSetSize(layout, n));
8109de2952eSStefano Zampini PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
8119de2952eSStefano Zampini PetscCall(PetscSFSetGraphLayout(sf, layout, nvtxs, NULL, PETSC_OWN_POINTER, idxs));
8129de2952eSStefano Zampini PetscCall(PetscLayoutDestroy(&layout));
8139de2952eSStefano Zampini PetscCall(PetscSFGetMultiSF(sf, &multisf));
8149de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeBegin(sf, &indegree));
8159de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeEnd(sf, &indegree));
8169de2952eSStefano Zampini PetscCall(PetscSFGetGraph(multisf, &nmulti, NULL, NULL, NULL));
8179de2952eSStefano Zampini PetscCall(PetscMalloc2(nmulti, &multi_root_subs, n + 1, &start));
8189de2952eSStefano Zampini start[0] = 0;
8199de2952eSStefano Zampini for (i = 0; i < n; i++) start[i + 1] = start[i] + indegree[i];
8209de2952eSStefano Zampini PetscCall(PetscSFGatherBegin(sf, MPIU_INT, graph->local_subs, multi_root_subs));
8219de2952eSStefano Zampini PetscCall(PetscSFGatherEnd(sf, MPIU_INT, graph->local_subs, multi_root_subs));
8229de2952eSStefano Zampini for (i = 0; i < nvtxs; i++) {
8239de2952eSStefano Zampini PetscInt gid = idxs[i];
8249de2952eSStefano Zampini
8259de2952eSStefano Zampini graph->nodes[i].local_sub = graph->local_subs[i];
8269de2952eSStefano Zampini for (j = 0, c = 0; j < graph->nodes[i].count; j++) {
8279de2952eSStefano Zampini if (graph->nodes[i].neighbours_set[j] == rank) c++;
8289de2952eSStefano Zampini }
8299de2952eSStefano Zampini PetscCheck(c == indegree[idxs[i]], PETSC_COMM_SELF, PETSC_ERR_PLIB, "%" PetscInt_FMT " != %" PetscInt_FMT, c, indegree[idxs[i]]);
8309de2952eSStefano Zampini PetscCall(PetscMalloc1(c, &graph->nodes[i].local_groups));
8319de2952eSStefano Zampini for (j = 0; j < c; j++) graph->nodes[i].local_groups[j] = multi_root_subs[start[gid] + j];
8329de2952eSStefano Zampini PetscCall(PetscSortInt(c, graph->nodes[i].local_groups));
8339de2952eSStefano Zampini graph->nodes[i].local_groups_count = c;
8349de2952eSStefano Zampini }
8359de2952eSStefano Zampini PetscCall(PetscFree2(multi_root_subs, start));
8369de2952eSStefano Zampini PetscCall(ISRestoreIndices(lis, &idxs));
8379de2952eSStefano Zampini PetscCall(ISDestroy(&lis));
8389de2952eSStefano Zampini PetscCall(PetscSFDestroy(&sf));
8399de2952eSStefano Zampini }
8407fb0e2dbSStefano Zampini
84167c9da69SStefano Zampini /*
84267c9da69SStefano Zampini Get info for dofs splitting
8435777c63cSStefano Zampini User can specify just a subset; an additional field is considered as a complementary field
84467c9da69SStefano Zampini */
8450c85b387SStefano Zampini for (i = 0, k = 0; i < n_ISForDofs; i++) {
8460c85b387SStefano Zampini PetscInt bs;
8470c85b387SStefano Zampini
8489566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(ISForDofs[i], &bs));
8490c85b387SStefano Zampini k += bs;
8500c85b387SStefano Zampini }
8519de2952eSStefano Zampini for (i = 0; i < nvtxs; i++) graph->nodes[i].which_dof = k; /* by default a dof belongs to the complement set */
8520c85b387SStefano Zampini for (i = 0, k = 0; i < n_ISForDofs; i++) {
8530c85b387SStefano Zampini PetscInt bs;
8540c85b387SStefano Zampini
8559566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ISForDofs[i], &is_size));
8569566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(ISForDofs[i], &bs));
857835f2295SStefano Zampini PetscCall(ISGetIndices(ISForDofs[i], &is_indices));
8580c85b387SStefano Zampini for (j = 0; j < is_size / bs; j++) {
8590c85b387SStefano Zampini PetscInt b;
8600c85b387SStefano Zampini
8610c85b387SStefano Zampini for (b = 0; b < bs; b++) {
8620c85b387SStefano Zampini PetscInt jj = bs * j + b;
8630c85b387SStefano Zampini
8649de2952eSStefano Zampini if (is_indices[jj] > -1 && is_indices[jj] < nvtxs) { /* out of bounds indices (if any) are skipped */
8659de2952eSStefano Zampini graph->nodes[is_indices[jj]].which_dof = k + b;
8660c85b387SStefano Zampini }
867674ae819SStefano Zampini }
86867c9da69SStefano Zampini }
869835f2295SStefano Zampini PetscCall(ISRestoreIndices(ISForDofs[i], &is_indices));
8700c85b387SStefano Zampini k += bs;
8715777c63cSStefano Zampini }
8725777c63cSStefano Zampini
873674ae819SStefano Zampini /* Take into account Neumann nodes */
874674ae819SStefano Zampini if (neumann_is) {
8759566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(neumann_is, &is_size));
876835f2295SStefano Zampini PetscCall(ISGetIndices(neumann_is, &is_indices));
877674ae819SStefano Zampini for (i = 0; i < is_size; i++) {
8789de2952eSStefano Zampini if (is_indices[i] > -1 && is_indices[i] < nvtxs) { /* out of bounds indices (if any) are skipped */
8799de2952eSStefano Zampini graph->nodes[is_indices[i]].special_dof = PCBDDCGRAPH_NEUMANN_MARK;
880674ae819SStefano Zampini }
8813c629590SStefano Zampini }
882835f2295SStefano Zampini PetscCall(ISRestoreIndices(neumann_is, &is_indices));
883674ae819SStefano Zampini }
8849de2952eSStefano Zampini
8859de2952eSStefano Zampini /* Take into account Dirichlet nodes (they overwrite any mark previously set) */
886674ae819SStefano Zampini if (dirichlet_is) {
8879566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirichlet_is, &is_size));
888835f2295SStefano Zampini PetscCall(ISGetIndices(dirichlet_is, &is_indices));
889674ae819SStefano Zampini for (i = 0; i < is_size; i++) {
8909de2952eSStefano Zampini if (is_indices[i] > -1 && is_indices[i] < nvtxs) { /* out of bounds indices (if any) are skipped */
8919de2952eSStefano Zampini if (!graph->seq_graph) { /* dirichlet nodes treated as internal */
8929de2952eSStefano Zampini graph->nodes[is_indices[i]].touched = PETSC_TRUE;
8939de2952eSStefano Zampini graph->nodes[is_indices[i]].subset = 0;
8947a0e7b2cSstefano_zampini }
8959de2952eSStefano Zampini graph->nodes[is_indices[i]].special_dof = PCBDDCGRAPH_DIRICHLET_MARK;
896674ae819SStefano Zampini }
8973c629590SStefano Zampini }
898835f2295SStefano Zampini PetscCall(ISRestoreIndices(dirichlet_is, &is_indices));
8997fb0e2dbSStefano Zampini }
90051b0f6cfSStefano Zampini
9019de2952eSStefano Zampini /* mark special nodes (if any) -> each will become a single dof equivalence class (i.e. point constraint for BDDC) */
902674ae819SStefano Zampini if (custom_primal_vertices) {
9039566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(custom_primal_vertices, &is_size));
904835f2295SStefano Zampini PetscCall(ISGetIndices(custom_primal_vertices, &is_indices));
9057a0e7b2cSstefano_zampini for (i = 0, j = 0; i < is_size; i++) {
9069de2952eSStefano Zampini if (is_indices[i] > -1 && is_indices[i] < nvtxs && graph->nodes[is_indices[i]].special_dof != PCBDDCGRAPH_DIRICHLET_MARK) { /* out of bounds indices (if any) are skipped */
9079de2952eSStefano Zampini graph->nodes[is_indices[i]].special_dof = PCBDDCGRAPH_SPECIAL_MARK - j;
9089b70a373SStefano Zampini j++;
9099b70a373SStefano Zampini }
9109b70a373SStefano Zampini }
911835f2295SStefano Zampini PetscCall(ISRestoreIndices(custom_primal_vertices, &is_indices));
91217eb1463SStefano Zampini }
9139b70a373SStefano Zampini
9149de2952eSStefano Zampini /* mark interior nodes as touched and belonging to partition number 0 */
9159de2952eSStefano Zampini if (!graph->seq_graph) {
9169de2952eSStefano Zampini for (i = 0; i < nvtxs; i++) {
9172daa06b4SStefano Zampini const PetscInt icount = graph->nodes[i].count;
9189de2952eSStefano Zampini if (graph->nodes[i].count < 2) {
9199de2952eSStefano Zampini graph->nodes[i].touched = PETSC_TRUE;
9209de2952eSStefano Zampini graph->nodes[i].subset = 0;
9212daa06b4SStefano Zampini } else {
9222daa06b4SStefano Zampini if (graph->multi_element) {
9232daa06b4SStefano Zampini graph->nodes[i].shared = PETSC_FALSE;
9242daa06b4SStefano Zampini for (k = 0; k < icount; k++)
9252daa06b4SStefano Zampini if (graph->nodes[i].neighbours_set[k] != rank) {
9262daa06b4SStefano Zampini graph->nodes[i].shared = PETSC_TRUE;
9272daa06b4SStefano Zampini break;
9282daa06b4SStefano Zampini }
9292daa06b4SStefano Zampini } else {
9302daa06b4SStefano Zampini graph->nodes[i].shared = PETSC_TRUE;
931674ae819SStefano Zampini }
932674ae819SStefano Zampini }
933b3cdcd63SStefano Zampini }
9342daa06b4SStefano Zampini } else {
9352daa06b4SStefano Zampini for (i = 0; i < nvtxs; i++) graph->nodes[i].shared = PETSC_TRUE;
9362daa06b4SStefano Zampini }
937b3cdcd63SStefano Zampini
938674ae819SStefano Zampini /* init graph structure and compute default subsets */
939674ae819SStefano Zampini nodes_touched = 0;
9409de2952eSStefano Zampini for (i = 0; i < nvtxs; i++)
9419de2952eSStefano Zampini if (graph->nodes[i].touched) nodes_touched++;
9429de2952eSStefano Zampini
9437babac9bSStefano Zampini /* allocated space for queues */
9449de2952eSStefano Zampini if (graph->seq_graph) {
9459de2952eSStefano Zampini PetscCall(PetscMalloc2(nvtxs + 1, &graph->cptr, nvtxs, &graph->queue));
9467babac9bSStefano Zampini } else {
9479de2952eSStefano Zampini PetscInt nused = nvtxs - nodes_touched;
9489566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nused + 1, &graph->cptr, nused, &graph->queue));
9497babac9bSStefano Zampini }
9507babac9bSStefano Zampini
9512daa06b4SStefano Zampini graph->ncc = 0;
9522daa06b4SStefano Zampini PetscCall(PetscHMapPCBDDCGraphNodeCreate(&subsetmaps));
9532daa06b4SStefano Zampini PetscCall(PetscCalloc1(nvtxs, &subset_sizes));
9542daa06b4SStefano Zampini for (i = 0; i < nvtxs; i++) {
9552daa06b4SStefano Zampini PetscHashIter iter;
9562daa06b4SStefano Zampini PetscBool missing;
9572daa06b4SStefano Zampini PetscInt subset;
9582daa06b4SStefano Zampini
9592daa06b4SStefano Zampini if (graph->nodes[i].touched) continue;
9609de2952eSStefano Zampini graph->nodes[i].touched = PETSC_TRUE;
9612daa06b4SStefano Zampini PetscCall(PetscHMapPCBDDCGraphNodePut(subsetmaps, &graph->nodes[i], &iter, &missing));
9622daa06b4SStefano Zampini if (missing) {
963674ae819SStefano Zampini graph->ncc++;
9642daa06b4SStefano Zampini PetscCall(PetscHMapPCBDDCGraphNodeIterSet(subsetmaps, iter, graph->ncc));
9652daa06b4SStefano Zampini subset = graph->ncc;
9662daa06b4SStefano Zampini } else PetscCall(PetscHMapPCBDDCGraphNodeIterGet(subsetmaps, iter, &subset));
9672daa06b4SStefano Zampini subset_sizes[subset - 1] += 1;
9682daa06b4SStefano Zampini graph->nodes[i].subset = subset;
969674ae819SStefano Zampini }
9702daa06b4SStefano Zampini
9712daa06b4SStefano Zampini graph->cptr[0] = 0;
9722daa06b4SStefano Zampini for (i = 0; i < graph->ncc; i++) graph->cptr[i + 1] = graph->cptr[i] + subset_sizes[i];
9732daa06b4SStefano Zampini for (i = 0; i < graph->ncc; i++) subset_sizes[i] = 0;
9742daa06b4SStefano Zampini
9752daa06b4SStefano Zampini for (i = 0; i < nvtxs; i++) {
9762daa06b4SStefano Zampini const PetscInt subset = graph->nodes[i].subset - 1;
9772daa06b4SStefano Zampini if (subset < 0) continue;
9782daa06b4SStefano Zampini PetscCheck(subset_sizes[subset] + graph->cptr[subset] < graph->cptr[subset + 1], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error for subset %" PetscInt_FMT, subset);
9792daa06b4SStefano Zampini graph->queue[subset_sizes[subset] + graph->cptr[subset]] = i;
9802daa06b4SStefano Zampini subset_sizes[subset] += 1;
9812daa06b4SStefano Zampini }
9822daa06b4SStefano Zampini for (i = 0; i < graph->ncc; i++) PetscCheck(subset_sizes[i] + graph->cptr[i] == graph->cptr[i + 1], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error for subset %" PetscInt_FMT, i);
9832daa06b4SStefano Zampini
9842daa06b4SStefano Zampini PetscCall(PetscHMapPCBDDCGraphNodeDestroy(&subsetmaps));
9852daa06b4SStefano Zampini PetscCall(PetscFree(subset_sizes));
9869de2952eSStefano Zampini
9879de2952eSStefano Zampini /* set default number of subsets */
988674ae819SStefano Zampini graph->n_subsets = graph->ncc;
9899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->n_subsets, &graph->subset_ncc));
990ad540459SPierre Jolivet for (i = 0; i < graph->n_subsets; i++) graph->subset_ncc[i] = 1;
991ec1c413dSStefano Zampini
9929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &graph->subset_ref_node));
9939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->cptr[graph->ncc], &queue_global));
9949de2952eSStefano Zampini PetscCall(PetscMalloc2(graph->ncc, &graph->subset_size, graph->ncc, &graph->subset_idxs));
9959de2952eSStefano Zampini if (graph->multi_element) PetscCall(PetscMalloc1(graph->ncc, &graph->gsubset_size));
9969de2952eSStefano Zampini else graph->gsubset_size = graph->subset_size;
9979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(graph->l2gmap, graph->cptr[graph->ncc], graph->queue, queue_global));
9989de2952eSStefano Zampini
9999de2952eSStefano Zampini PetscHMapI cnt_unique;
10009de2952eSStefano Zampini
10019de2952eSStefano Zampini PetscCall(PetscHMapICreate(&cnt_unique));
1002ec1c413dSStefano Zampini for (j = 0; j < graph->ncc; j++) {
10031690c2aeSBarry Smith PetscInt c = 0, ref_node = PETSC_INT_MAX;
10049de2952eSStefano Zampini
10059de2952eSStefano Zampini for (k = graph->cptr[j]; k < graph->cptr[j + 1]; k++) {
10069de2952eSStefano Zampini ref_node = PetscMin(ref_node, queue_global[k]);
10079de2952eSStefano Zampini if (graph->multi_element) {
10089de2952eSStefano Zampini PetscBool missing;
10099de2952eSStefano Zampini PetscHashIter iter;
10109de2952eSStefano Zampini
10119de2952eSStefano Zampini PetscCall(PetscHMapIPut(cnt_unique, queue_global[k], &iter, &missing));
10129de2952eSStefano Zampini if (missing) c++;
1013f0321c90SStefano Zampini }
10149de2952eSStefano Zampini }
10159de2952eSStefano Zampini graph->gsubset_size[j] = c;
10169de2952eSStefano Zampini graph->subset_size[j] = graph->cptr[j + 1] - graph->cptr[j];
10179de2952eSStefano Zampini graph->subset_ref_node[j] = ref_node;
10189de2952eSStefano Zampini if (graph->multi_element) PetscCall(PetscHMapIClear(cnt_unique));
10199de2952eSStefano Zampini }
10209de2952eSStefano Zampini PetscCall(PetscHMapIDestroy(&cnt_unique));
102148bebe3cSStefano Zampini
1022b3cdcd63SStefano Zampini /* save information on subsets (needed when analyzing the connected components) */
10232f566a09SStefano Zampini if (graph->ncc) {
10249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->cptr[graph->ncc], &graph->subset_idxs[0]));
10259566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(graph->subset_idxs[0], graph->cptr[graph->ncc]));
1026ac530a7eSPierre Jolivet for (j = 1; j < graph->ncc; j++) graph->subset_idxs[j] = graph->subset_idxs[j - 1] + graph->subset_size[j - 1];
10279566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(graph->subset_idxs[0], graph->queue, graph->cptr[graph->ncc]));
1028ec1c413dSStefano Zampini }
1029b3cdcd63SStefano Zampini
10309de2952eSStefano Zampini /* check consistency and create SF to analyze components on the interface between subdomains */
10319de2952eSStefano Zampini if (!graph->seq_graph) {
10329de2952eSStefano Zampini PetscSF msf;
10339de2952eSStefano Zampini PetscLayout map;
10349de2952eSStefano Zampini const PetscInt *degree;
10359de2952eSStefano Zampini PetscInt nr, nmr, *rdata;
10369de2952eSStefano Zampini PetscBool valid = PETSC_TRUE;
10379de2952eSStefano Zampini PetscInt subset_N;
10389de2952eSStefano Zampini IS subset_n;
10399de2952eSStefano Zampini const PetscInt *idxs;
10409de2952eSStefano Zampini
10419de2952eSStefano Zampini PetscCall(ISCreateGeneral(comm, graph->n_subsets, graph->subset_ref_node, PETSC_USE_POINTER, &subset));
10429de2952eSStefano Zampini PetscCall(ISRenumber(subset, NULL, &subset_N, &subset_n));
10439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset));
10449de2952eSStefano Zampini
10459de2952eSStefano Zampini PetscCall(PetscSFCreate(comm, &graph->interface_ref_sf));
10469de2952eSStefano Zampini PetscCall(PetscLayoutCreateFromSizes(comm, PETSC_DECIDE, subset_N, 1, &map));
10479de2952eSStefano Zampini PetscCall(ISGetIndices(subset_n, &idxs));
10489de2952eSStefano Zampini PetscCall(PetscSFSetGraphLayout(graph->interface_ref_sf, map, graph->n_subsets, NULL, PETSC_OWN_POINTER, idxs));
10499de2952eSStefano Zampini PetscCall(ISRestoreIndices(subset_n, &idxs));
10509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n));
10519de2952eSStefano Zampini PetscCall(PetscLayoutDestroy(&map));
10529de2952eSStefano Zampini
10539de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeBegin(graph->interface_ref_sf, °ree));
10549de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeEnd(graph->interface_ref_sf, °ree));
10559de2952eSStefano Zampini PetscCall(PetscSFGetMultiSF(graph->interface_ref_sf, &msf));
10569de2952eSStefano Zampini PetscCall(PetscSFGetGraph(graph->interface_ref_sf, &nr, NULL, NULL, NULL));
10579de2952eSStefano Zampini PetscCall(PetscSFGetGraph(msf, &nmr, NULL, NULL, NULL));
10589de2952eSStefano Zampini PetscCall(PetscCalloc1(nmr, &rdata));
10599de2952eSStefano Zampini PetscCall(PetscSFGatherBegin(graph->interface_ref_sf, MPIU_INT, graph->gsubset_size, rdata));
10609de2952eSStefano Zampini PetscCall(PetscSFGatherEnd(graph->interface_ref_sf, MPIU_INT, graph->gsubset_size, rdata));
10619de2952eSStefano Zampini for (PetscInt i = 0, c = 0; i < nr && valid; i++) {
10629de2952eSStefano Zampini for (PetscInt j = 0; j < degree[i]; j++) {
10639de2952eSStefano Zampini if (rdata[j + c] != rdata[c]) valid = PETSC_FALSE;
10649de2952eSStefano Zampini }
10659de2952eSStefano Zampini c += degree[i];
10669de2952eSStefano Zampini }
10679de2952eSStefano Zampini PetscCall(PetscFree(rdata));
10685440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &valid, 1, MPI_C_BOOL, MPI_LAND, comm));
10699de2952eSStefano Zampini PetscCheck(valid, comm, PETSC_ERR_PLIB, "Initial local subsets are not consistent");
10709de2952eSStefano Zampini
10719de2952eSStefano Zampini /* Now create SF with each root extended to gsubset_size roots */
1072e4ebd542SJose E. Roman PetscInt mss = 0;
10739de2952eSStefano Zampini const PetscSFNode *subs_remote;
10749de2952eSStefano Zampini
10759de2952eSStefano Zampini PetscCall(PetscSFGetGraph(graph->interface_ref_sf, NULL, NULL, NULL, &subs_remote));
1076e4ebd542SJose E. Roman for (PetscInt i = 0; i < graph->n_subsets; i++) mss = PetscMax(graph->subset_size[i], mss);
10779de2952eSStefano Zampini
10789de2952eSStefano Zampini PetscInt nri, nli, *start_rsize, *cum_rsize;
10799de2952eSStefano Zampini PetscCall(PetscCalloc1(graph->n_subsets + 1, &start_rsize));
10809de2952eSStefano Zampini PetscCall(PetscCalloc1(nr, &graph->interface_ref_rsize));
10819de2952eSStefano Zampini PetscCall(PetscMalloc1(nr + 1, &cum_rsize));
10829de2952eSStefano Zampini PetscCall(PetscSFReduceBegin(graph->interface_ref_sf, MPIU_INT, graph->gsubset_size, graph->interface_ref_rsize, MPI_REPLACE));
10839de2952eSStefano Zampini PetscCall(PetscSFReduceEnd(graph->interface_ref_sf, MPIU_INT, graph->gsubset_size, graph->interface_ref_rsize, MPI_REPLACE));
10849de2952eSStefano Zampini
10859de2952eSStefano Zampini nri = 0;
10869de2952eSStefano Zampini cum_rsize[0] = 0;
1087e4ebd542SJose E. Roman for (PetscInt i = 0; i < nr; i++) {
10889de2952eSStefano Zampini nri += graph->interface_ref_rsize[i];
10899de2952eSStefano Zampini cum_rsize[i + 1] = cum_rsize[i] + graph->interface_ref_rsize[i];
10909de2952eSStefano Zampini }
10919de2952eSStefano Zampini nli = graph->cptr[graph->ncc];
10929de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(graph->interface_ref_sf, MPIU_INT, cum_rsize, start_rsize, MPI_REPLACE));
10939de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(graph->interface_ref_sf, MPIU_INT, cum_rsize, start_rsize, MPI_REPLACE));
10949de2952eSStefano Zampini PetscCall(PetscFree(cum_rsize));
10959de2952eSStefano Zampini
10969de2952eSStefano Zampini PetscInt *ilocal, *queue_global_uniq;
10979de2952eSStefano Zampini PetscSFNode *iremote;
10989de2952eSStefano Zampini PetscBool *touched;
10999de2952eSStefano Zampini
11009de2952eSStefano Zampini PetscCall(PetscSFCreate(comm, &graph->interface_subset_sf));
11019de2952eSStefano Zampini PetscCall(PetscMalloc1(nli, &ilocal));
11029de2952eSStefano Zampini PetscCall(PetscMalloc1(nli, &iremote));
11039de2952eSStefano Zampini PetscCall(PetscMalloc2(mss, &queue_global_uniq, mss, &touched));
1104e4ebd542SJose E. Roman for (PetscInt i = 0, nli = 0; i < graph->n_subsets; i++) {
11056497c311SBarry Smith const PetscMPIInt rr = (PetscMPIInt)subs_remote[i].rank;
11069de2952eSStefano Zampini const PetscInt start = start_rsize[i];
11079de2952eSStefano Zampini const PetscInt subset_size = graph->subset_size[i];
11089de2952eSStefano Zampini const PetscInt gsubset_size = graph->gsubset_size[i];
11099de2952eSStefano Zampini const PetscInt *subset_idxs = graph->subset_idxs[i];
11109de2952eSStefano Zampini const PetscInt *lsub_queue_global = queue_global + graph->cptr[i];
11119de2952eSStefano Zampini
11129de2952eSStefano Zampini k = subset_size;
11139de2952eSStefano Zampini PetscCall(PetscArrayzero(touched, subset_size));
11149de2952eSStefano Zampini PetscCall(PetscArraycpy(queue_global_uniq, lsub_queue_global, subset_size));
11159de2952eSStefano Zampini PetscCall(PetscSortRemoveDupsInt(&k, queue_global_uniq));
11169de2952eSStefano Zampini PetscCheck(k == gsubset_size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid local subset %" PetscInt_FMT " size %" PetscInt_FMT " != %" PetscInt_FMT, i, k, gsubset_size);
11179de2952eSStefano Zampini
11189de2952eSStefano Zampini PetscInt t = 0, j = 0;
11199de2952eSStefano Zampini while (t < subset_size) {
11209de2952eSStefano Zampini while (j < subset_size && touched[j]) j++;
11219de2952eSStefano Zampini PetscCheck(j < subset_size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " >= %" PetscInt_FMT, j, subset_size);
11229de2952eSStefano Zampini const PetscInt ls = graph->nodes[subset_idxs[j]].local_sub;
11239de2952eSStefano Zampini
11249de2952eSStefano Zampini for (k = j; k < subset_size; k++) {
11259de2952eSStefano Zampini if (graph->nodes[subset_idxs[k]].local_sub == ls) {
11269de2952eSStefano Zampini PetscInt ig;
11279de2952eSStefano Zampini
11289de2952eSStefano Zampini PetscCall(PetscFindInt(lsub_queue_global[k], gsubset_size, queue_global_uniq, &ig));
11299de2952eSStefano Zampini ilocal[nli] = subset_idxs[k];
11309de2952eSStefano Zampini iremote[nli].rank = rr;
11319de2952eSStefano Zampini iremote[nli].index = start + ig;
11329de2952eSStefano Zampini touched[k] = PETSC_TRUE;
11339de2952eSStefano Zampini nli++;
11349de2952eSStefano Zampini t++;
11359de2952eSStefano Zampini }
11369de2952eSStefano Zampini }
11379de2952eSStefano Zampini }
11389de2952eSStefano Zampini }
11399de2952eSStefano Zampini PetscCheck(nli == graph->cptr[graph->ncc], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid ilocal size %" PetscInt_FMT " != %" PetscInt_FMT, nli, graph->cptr[graph->ncc]);
11409de2952eSStefano Zampini PetscCall(PetscSFSetGraph(graph->interface_subset_sf, nri, nli, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
11419de2952eSStefano Zampini PetscCall(PetscFree(start_rsize));
11429de2952eSStefano Zampini PetscCall(PetscFree2(queue_global_uniq, touched));
11439de2952eSStefano Zampini }
11449de2952eSStefano Zampini PetscCall(PetscFree(queue_global));
1145ec1c413dSStefano Zampini
1146ec1c413dSStefano Zampini /* free workspace */
1147b3cdcd63SStefano Zampini graph->setupcalled = PETSC_TRUE;
11483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1149674ae819SStefano Zampini }
1150674ae819SStefano Zampini
PCBDDCGraphResetCoords(PCBDDCGraph graph)1151d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphResetCoords(PCBDDCGraph graph)
1152d71ae5a4SJacob Faibussowitsch {
1153ab8c8b98SStefano Zampini PetscFunctionBegin;
11543ba16761SJacob Faibussowitsch if (!graph) PetscFunctionReturn(PETSC_SUCCESS);
11559566063dSJacob Faibussowitsch PetscCall(PetscFree(graph->coords));
1156ab8c8b98SStefano Zampini graph->cdim = 0;
1157ab8c8b98SStefano Zampini graph->cnloc = 0;
1158ab8c8b98SStefano Zampini graph->cloc = PETSC_FALSE;
11593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1160ab8c8b98SStefano Zampini }
1161ab8c8b98SStefano Zampini
PCBDDCGraphResetCSR(PCBDDCGraph graph)1162d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphResetCSR(PCBDDCGraph graph)
1163d71ae5a4SJacob Faibussowitsch {
1164674ae819SStefano Zampini PetscFunctionBegin;
11653ba16761SJacob Faibussowitsch if (!graph) PetscFunctionReturn(PETSC_SUCCESS);
1166a1dbd327SStefano Zampini if (graph->freecsr) {
11679566063dSJacob Faibussowitsch PetscCall(PetscFree(graph->xadj));
11689566063dSJacob Faibussowitsch PetscCall(PetscFree(graph->adjncy));
1169a1dbd327SStefano Zampini } else {
1170a1dbd327SStefano Zampini graph->xadj = NULL;
1171a1dbd327SStefano Zampini graph->adjncy = NULL;
1172a1dbd327SStefano Zampini }
1173c8272957SStefano Zampini graph->freecsr = PETSC_FALSE;
1174575ad6abSStefano Zampini graph->nvtxs_csr = 0;
11753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1176674ae819SStefano Zampini }
1177674ae819SStefano Zampini
PCBDDCGraphReset(PCBDDCGraph graph)1178d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphReset(PCBDDCGraph graph)
1179d71ae5a4SJacob Faibussowitsch {
1180674ae819SStefano Zampini PetscFunctionBegin;
11813ba16761SJacob Faibussowitsch if (!graph) PetscFunctionReturn(PETSC_SUCCESS);
11829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&graph->l2gmap));
11839566063dSJacob Faibussowitsch PetscCall(PetscFree(graph->subset_ncc));
11849566063dSJacob Faibussowitsch PetscCall(PetscFree(graph->subset_ref_node));
11859de2952eSStefano Zampini for (PetscInt i = 0; i < graph->nvtxs; i++) {
11869de2952eSStefano Zampini PetscCall(PetscFree(graph->nodes[i].neighbours_set));
11879de2952eSStefano Zampini PetscCall(PetscFree(graph->nodes[i].local_groups));
11889de2952eSStefano Zampini }
11899de2952eSStefano Zampini PetscCall(PetscFree(graph->nodes));
11909566063dSJacob Faibussowitsch PetscCall(PetscFree2(graph->cptr, graph->queue));
119148a46eb9SPierre Jolivet if (graph->subset_idxs) PetscCall(PetscFree(graph->subset_idxs[0]));
11929566063dSJacob Faibussowitsch PetscCall(PetscFree2(graph->subset_size, graph->subset_idxs));
11939de2952eSStefano Zampini if (graph->multi_element) PetscCall(PetscFree(graph->gsubset_size));
11949de2952eSStefano Zampini PetscCall(PetscFree(graph->interface_ref_rsize));
11959de2952eSStefano Zampini PetscCall(PetscSFDestroy(&graph->interface_subset_sf));
11969de2952eSStefano Zampini PetscCall(PetscSFDestroy(&graph->interface_ref_sf));
11979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&graph->dirdofs));
11989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&graph->dirdofsB));
11991baa6e33SBarry Smith if (graph->n_local_subs) PetscCall(PetscFree(graph->local_subs));
12009de2952eSStefano Zampini graph->multi_element = PETSC_FALSE;
1201a07ea27aSStefano Zampini graph->has_dirichlet = PETSC_FALSE;
1202cc0a5675Sstefano_zampini graph->twodimset = PETSC_FALSE;
1203cc0a5675Sstefano_zampini graph->twodim = PETSC_FALSE;
1204674ae819SStefano Zampini graph->nvtxs = 0;
12057babac9bSStefano Zampini graph->nvtxs_global = 0;
1206674ae819SStefano Zampini graph->n_subsets = 0;
1207674ae819SStefano Zampini graph->custom_minimal_size = 1;
12084f1b2e48SStefano Zampini graph->n_local_subs = 0;
12091690c2aeSBarry Smith graph->maxcount = PETSC_INT_MAX;
12109de2952eSStefano Zampini graph->seq_graph = PETSC_FALSE;
1211fb597685SStefano Zampini graph->setupcalled = PETSC_FALSE;
12123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1213674ae819SStefano Zampini }
1214674ae819SStefano Zampini
PCBDDCGraphInit(PCBDDCGraph graph,ISLocalToGlobalMapping l2gmap,PetscInt N,PetscInt maxcount)1215d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphInit(PCBDDCGraph graph, ISLocalToGlobalMapping l2gmap, PetscInt N, PetscInt maxcount)
1216d71ae5a4SJacob Faibussowitsch {
1217674ae819SStefano Zampini PetscInt n;
1218674ae819SStefano Zampini
1219674ae819SStefano Zampini PetscFunctionBegin;
12204f572ea9SToby Isaac PetscAssertPointer(graph, 1);
1221674ae819SStefano Zampini PetscValidHeaderSpecific(l2gmap, IS_LTOGM_CLASSID, 2);
12227babac9bSStefano Zampini PetscValidLogicalCollectiveInt(l2gmap, N, 3);
1223be12c134Sstefano_zampini PetscValidLogicalCollectiveInt(l2gmap, maxcount, 4);
12248e61c736SStefano Zampini /* raise an error if already allocated */
122528b400f6SJacob Faibussowitsch PetscCheck(!graph->nvtxs_global, PetscObjectComm((PetscObject)l2gmap), PETSC_ERR_PLIB, "BDDCGraph already initialized");
1226674ae819SStefano Zampini /* set number of vertices */
12279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)l2gmap));
1228674ae819SStefano Zampini graph->l2gmap = l2gmap;
12299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(l2gmap, &n));
1230674ae819SStefano Zampini graph->nvtxs = n;
12317fb0e2dbSStefano Zampini graph->nvtxs_global = N;
1232674ae819SStefano Zampini /* allocate used space */
12339de2952eSStefano Zampini PetscCall(PetscCalloc1(graph->nvtxs, &graph->nodes));
123463602bcaSStefano Zampini /* use -1 as a default value for which_dof array */
12359de2952eSStefano Zampini for (n = 0; n < graph->nvtxs; n++) graph->nodes[n].which_dof = -1;
12369de2952eSStefano Zampini
1237674ae819SStefano Zampini /* zeroes workspace for values of ncc */
12380a545947SLisandro Dalcin graph->subset_ncc = NULL;
12390a545947SLisandro Dalcin graph->subset_ref_node = NULL;
1240be12c134Sstefano_zampini /* maxcount for cc */
1241be12c134Sstefano_zampini graph->maxcount = maxcount;
12423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1243674ae819SStefano Zampini }
1244674ae819SStefano Zampini
PCBDDCGraphDestroy(PCBDDCGraph * graph)1245d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphDestroy(PCBDDCGraph *graph)
1246d71ae5a4SJacob Faibussowitsch {
1247674ae819SStefano Zampini PetscFunctionBegin;
12489566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(*graph));
12499566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCoords(*graph));
12509566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphReset(*graph));
12519566063dSJacob Faibussowitsch PetscCall(PetscFree(*graph));
12523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1253674ae819SStefano Zampini }
1254674ae819SStefano Zampini
PCBDDCGraphCreate(PCBDDCGraph * graph)1255d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGraphCreate(PCBDDCGraph *graph)
1256d71ae5a4SJacob Faibussowitsch {
1257674ae819SStefano Zampini PCBDDCGraph new_graph;
1258674ae819SStefano Zampini
1259674ae819SStefano Zampini PetscFunctionBegin;
12609566063dSJacob Faibussowitsch PetscCall(PetscNew(&new_graph));
1261674ae819SStefano Zampini new_graph->custom_minimal_size = 1;
1262674ae819SStefano Zampini *graph = new_graph;
12633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1264674ae819SStefano Zampini }
1265