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*/