Actual source code: ex3.c
1: static char help[] = "This example tests subnetwork coupling. \n\
2: \n\n";
4: #include <petscdmnetwork.h>
6: typedef struct {
7: PetscInt id;
8: } Comp0;
10: typedef struct {
11: PetscScalar val;
12: } Comp1;
14: int main(int argc, char **argv)
15: {
16: PetscMPIInt size, rank;
17: DM dmnetwork;
18: PetscInt i, j, net, Nsubnet, nsubnet, ne, nv, nvar, v, ncomp, compkey0, compkey1, compkey, goffset, row;
19: PetscInt numEdges[10], *edgelist[10], asvtx, bsvtx;
20: const PetscInt *vtx, *edges;
21: PetscBool sharedv, ghost, distribute = PETSC_TRUE, test = PETSC_FALSE;
22: Vec X;
23: Comp0 comp0;
24: Comp1 comp1;
25: PetscScalar val;
28: PetscInitialize(&argc, &argv, (char *)0, help);
29: MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
30: MPI_Comm_size(PETSC_COMM_WORLD, &size);
32: /* Create a network of subnetworks */
33: nsubnet = 1;
34: if (size == 1) nsubnet = 2;
36: /* Create a dmnetwork and register components */
37: DMNetworkCreate(PETSC_COMM_WORLD, &dmnetwork);
38: DMNetworkRegisterComponent(dmnetwork, "comp0", sizeof(Comp0), &compkey0);
39: DMNetworkRegisterComponent(dmnetwork, "comp1", sizeof(Comp1), &compkey1);
41: /* Set componnet values - intentionally take rank-dependent value for test */
42: comp0.id = rank;
43: comp1.val = 10.0 * rank;
45: /* Set number of subnetworks, numbers of vertices and edges over each subnetwork */
46: DMNetworkSetNumSubNetworks(dmnetwork, nsubnet, PETSC_DECIDE);
47: DMNetworkGetNumSubNetworks(dmnetwork, NULL, &Nsubnet);
49: /* Input subnetworks; when size>1, process[i] creates subnetwork[i] */
50: for (i = 0; i < Nsubnet; i++) numEdges[i] = 0;
51: for (i = 0; i < Nsubnet; i++) {
52: if (i == 0 && (size == 1 || (rank == i && size > 1))) {
53: numEdges[i] = 3;
54: PetscMalloc1(2 * numEdges[i], &edgelist[i]);
55: edgelist[i][0] = 0;
56: edgelist[i][1] = 2;
57: edgelist[i][2] = 2;
58: edgelist[i][3] = 1;
59: edgelist[i][4] = 1;
60: edgelist[i][5] = 3;
62: } else if (i == 1 && (size == 1 || (rank == i && size > 1))) {
63: numEdges[i] = 3;
64: PetscMalloc1(2 * numEdges[i], &edgelist[i]);
65: edgelist[i][0] = 0;
66: edgelist[i][1] = 3;
67: edgelist[i][2] = 3;
68: edgelist[i][3] = 2;
69: edgelist[i][4] = 2;
70: edgelist[i][5] = 1;
72: } else if (i > 1 && (size == 1 || (rank == i && size > 1))) {
73: numEdges[i] = 3;
74: PetscMalloc1(2 * numEdges[i], &edgelist[i]);
75: for (j = 0; j < numEdges[i]; j++) {
76: edgelist[i][2 * j] = j;
77: edgelist[i][2 * j + 1] = j + 1;
78: }
79: }
80: }
82: /* Add subnetworks */
83: for (i = 0; i < Nsubnet; i++) {
84: PetscInt netNum = -1;
85: DMNetworkAddSubnetwork(dmnetwork, NULL, numEdges[i], edgelist[i], &netNum);
86: }
88: /* Add shared vertices -- all processes hold this info at current implementation */
89: asvtx = bsvtx = 0;
90: for (j = 1; j < Nsubnet; j++) {
91: /* vertex subnet[0].0 shares with vertex subnet[j].0 */
92: DMNetworkAddSharedVertices(dmnetwork, 0, j, 1, &asvtx, &bsvtx);
93: }
95: /* Setup the network layout */
96: DMNetworkLayoutSetUp(dmnetwork);
98: /* Get Subnetwork(); Add nvar=1 to subnet[0] and nvar=2 to other subnets */
99: for (net = 0; net < Nsubnet; net++) {
100: DMNetworkGetSubnetwork(dmnetwork, net, &nv, &ne, &vtx, &edges);
101: for (v = 0; v < nv; v++) {
102: DMNetworkIsSharedVertex(dmnetwork, vtx[v], &sharedv);
103: if (sharedv) continue;
105: if (!net) {
106: DMNetworkAddComponent(dmnetwork, vtx[v], compkey0, &comp0, 1);
107: } else {
108: DMNetworkAddComponent(dmnetwork, vtx[v], compkey1, &comp1, 2);
109: }
110: }
111: }
113: /* Add components and nvar to shared vertex -- owning and all ghost ranks must call DMNetworkAddComponent() */
114: DMNetworkGetSharedVertices(dmnetwork, &nv, &vtx);
115: for (v = 0; v < nv; v++) {
116: DMNetworkAddComponent(dmnetwork, vtx[v], compkey0, &comp0, 1);
117: DMNetworkAddComponent(dmnetwork, vtx[v], compkey1, &comp1, 2);
118: }
120: /* Enable runtime option of graph partition type -- must be called before DMSetUp() */
121: if (size > 1) {
122: DM plexdm;
123: PetscPartitioner part;
124: DMNetworkGetPlex(dmnetwork, &plexdm);
125: DMPlexGetPartitioner(plexdm, &part);
126: PetscPartitionerSetType(part, PETSCPARTITIONERSIMPLE);
127: PetscOptionsSetValue(NULL, "-dm_plex_csr_alg", "mat"); /* for parmetis */
128: }
130: /* Setup dmnetwork */
131: DMSetUp(dmnetwork);
133: /* Redistribute the network layout; use '-distribute false' to skip */
134: PetscOptionsGetBool(NULL, NULL, "-distribute", &distribute, NULL);
135: if (distribute) {
136: DMNetworkDistribute(&dmnetwork, 0);
137: DMView(dmnetwork, PETSC_VIEWER_STDOUT_WORLD);
138: }
140: /* Create a global vector */
141: DMCreateGlobalVector(dmnetwork, &X);
142: VecSet(X, 0.0);
144: /* Set X values at shared vertex */
145: DMNetworkGetSharedVertices(dmnetwork, &nv, &vtx);
146: for (v = 0; v < nv; v++) {
147: DMNetworkIsGhostVertex(dmnetwork, vtx[v], &ghost);
148: if (ghost) continue;
150: /* only one process holds a non-ghost vertex */
151: DMNetworkGetComponent(dmnetwork, vtx[v], ALL_COMPONENTS, NULL, NULL, &nvar);
152: DMNetworkGetNumComponents(dmnetwork, vtx[v], &ncomp);
153: /* PetscPrintf(PETSC_COMM_SELF,"[%d] shared v %" PetscInt_FMT ": nvar %" PetscInt_FMT ", ncomp %" PetscInt_FMT "\n",rank,vtx[v],nvar,ncomp); */
154: for (j = 0; j < ncomp; j++) {
155: DMNetworkGetComponent(dmnetwork, vtx[v], j, &compkey, NULL, &nvar);
156: DMNetworkGetGlobalVecOffset(dmnetwork, vtx[v], j, &goffset);
157: for (i = 0; i < nvar; i++) {
158: row = goffset + i;
159: val = compkey + 1.0;
160: VecSetValues(X, 1, &row, &val, INSERT_VALUES);
161: }
162: }
163: }
164: VecAssemblyBegin(X);
165: VecAssemblyEnd(X);
166: VecView(X, PETSC_VIEWER_STDOUT_WORLD);
168: /* Test DMNetworkGetSubnetwork() */
169: PetscOptionsGetBool(NULL, NULL, "-test_getsubnet", &test, NULL);
170: if (test) {
171: net = 0;
172: PetscOptionsGetInt(NULL, NULL, "-subnet", &net, NULL);
173: DMNetworkGetSubnetwork(dmnetwork, net, &nv, &ne, &vtx, &edges);
174: PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[%d] subnet %" PetscInt_FMT ": nv %" PetscInt_FMT ", ne %" PetscInt_FMT "\n", rank, net, nv, ne);
175: PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT);
176: MPI_Barrier(PETSC_COMM_WORLD);
178: for (i = 0; i < nv; i++) {
179: DMNetworkIsGhostVertex(dmnetwork, vtx[i], &ghost);
180: DMNetworkIsSharedVertex(dmnetwork, vtx[i], &sharedv);
182: DMNetworkGetNumComponents(dmnetwork, vtx[i], &ncomp);
183: if (sharedv || ghost) PetscPrintf(PETSC_COMM_SELF, " [%d] v %" PetscInt_FMT " is shared %d, is ghost %d, ncomp %" PetscInt_FMT "\n", rank, vtx[i], sharedv, ghost, ncomp);
185: for (j = 0; j < ncomp; j++) {
186: void *component;
187: DMNetworkGetComponent(dmnetwork, vtx[i], j, &compkey, (void **)&component, NULL);
188: if (compkey == 0) {
189: PetscPrintf(PETSC_COMM_SELF, " [%d] v %" PetscInt_FMT " compkey %" PetscInt_FMT ", mycomp0->id %" PetscInt_FMT "\n", rank, vtx[i], compkey, ((Comp0 *)component)->id);
190: } else if (compkey == 1) {
191: PetscPrintf(PETSC_COMM_SELF, " [%d] v %" PetscInt_FMT " compkey %" PetscInt_FMT ", mycomp1->val %g\n", rank, vtx[i], compkey, (double)PetscRealPart(((Comp1 *)component)->val));
192: }
193: }
194: }
195: }
197: /* Free work space */
198: VecDestroy(&X);
199: for (i = 0; i < Nsubnet; i++) {
200: if (size == 1 || rank == i) PetscFree(edgelist[i]);
201: }
203: DMDestroy(&dmnetwork);
204: PetscFinalize();
205: return 0;
206: }
208: /*TEST
210: build:
211: requires: !single double defined(PETSC_HAVE_ATTRIBUTEALIGNED)
213: test:
214: args:
216: test:
217: suffix: 2
218: nsize: 2
219: args: -options_left no
221: test:
222: suffix: 3
223: nsize: 4
224: args: -options_left no
226: TEST*/