1 #include <petsc/private/dmnetworkimpl.h> /*I "petscdmnetwork.h" I*/ 2 3 /*@ 4 DMNetworkGetPlex - Gets the Plex DM associated with this network DM 5 6 Not collective 7 8 Input Parameters: 9 + netdm - the dm object 10 - plexmdm - the plex dm object 11 12 Level: Advanced 13 14 .seealso: DMNetworkCreate() 15 @*/ 16 PetscErrorCode DMNetworkGetPlex(DM netdm, DM *plexdm) 17 { 18 DM_Network *network = (DM_Network*) netdm->data; 19 20 PetscFunctionBegin; 21 *plexdm = network->plex; 22 PetscFunctionReturn(0); 23 } 24 25 /*@ 26 DMNetworkSetSizes - Sets the number of subnetworks, local and global vertices and edges for each subnetwork. 27 28 Collective on dm 29 30 Input Parameters: 31 + dm - the dm object 32 . Nsubnet - global number of subnetworks 33 . nV - number of local vertices for each subnetwork 34 . nE - number of local edges for each subnetwork 35 . NsubnetCouple - global number of coupling subnetworks 36 - nec - number of local edges for each coupling subnetwork 37 38 You cannot change the sizes once they have been set. nV, nE are arrays of length Nsubnet, and nec is array of length NsubnetCouple. 39 40 Level: intermediate 41 42 .seealso: DMNetworkCreate() 43 @*/ 44 PetscErrorCode DMNetworkSetSizes(DM dm,PetscInt Nsubnet,PetscInt nV[], PetscInt nE[],PetscInt NsubnetCouple,PetscInt nec[]) 45 { 46 PetscErrorCode ierr; 47 DM_Network *network = (DM_Network*) dm->data; 48 PetscInt a[2],b[2],i; 49 50 PetscFunctionBegin; 51 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 52 if (Nsubnet <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subnetworks %D cannot be less than 1",Nsubnet); 53 if (NsubnetCouple < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of coupling subnetworks %D cannot be less than 0",NsubnetCouple); 54 55 PetscValidLogicalCollectiveInt(dm,Nsubnet,2); 56 if (NsubnetCouple) PetscValidLogicalCollectiveInt(dm,NsubnetCouple,5); 57 if (network->nsubnet != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network"); 58 59 if (!nV || !nE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Local vertex size or edge size must be provided"); 60 61 network->nsubnet = Nsubnet + NsubnetCouple; 62 network->ncsubnet = NsubnetCouple; 63 ierr = PetscCalloc1(Nsubnet+NsubnetCouple,&network->subnet);CHKERRQ(ierr); 64 65 /* ---------------------------------------------------------- 66 p=v or e; P=V or E 67 subnet[0].pStart = 0 68 subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i]) 69 ----------------------------------------------------------------------- */ 70 for (i=0; i < Nsubnet; i++) { 71 /* Get global number of vertices and edges for subnet[i] */ 72 a[0] = nV[i]; a[1] = nE[i]; /* local number of vertices (excluding ghost) and edges */ 73 ierr = MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 74 network->subnet[i].Nvtx = b[0]; 75 network->subnet[i].Nedge = b[1]; 76 77 network->subnet[i].nvtx = nV[i]; /* local nvtx, without ghost */ 78 79 /* global subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */ 80 network->subnet[i].vStart = network->NVertices; 81 network->subnet[i].vEnd = network->subnet[i].vStart + network->subnet[i].Nvtx; 82 83 network->nVertices += nV[i]; 84 network->NVertices += network->subnet[i].Nvtx; 85 86 network->subnet[i].nedge = nE[i]; 87 network->subnet[i].eStart = network->nEdges; 88 network->subnet[i].eEnd = network->subnet[i].eStart + nE[i]; 89 network->nEdges += nE[i]; 90 network->NEdges += network->subnet[i].Nedge; 91 } 92 93 /* coupling subnetwork */ 94 for (; i < Nsubnet+NsubnetCouple; i++) { 95 /* Get global number of coupling edges for subnet[i] */ 96 ierr = MPIU_Allreduce(nec+(i-Nsubnet),&network->subnet[i].Nedge,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 97 98 network->subnet[i].nvtx = 0; /* We design coupling subnetwork such that it does not have its own vertices */ 99 network->subnet[i].vStart = network->nVertices; 100 network->subnet[i].vEnd = network->subnet[i].vStart; 101 102 network->subnet[i].nedge = nec[i-Nsubnet]; 103 network->subnet[i].eStart = network->nEdges; 104 network->subnet[i].eEnd = network->subnet[i].eStart + nec[i-Nsubnet]; 105 network->nEdges += nec[i-Nsubnet]; 106 network->NEdges += network->subnet[i].Nedge; 107 } 108 PetscFunctionReturn(0); 109 } 110 111 /*@ 112 DMNetworkSetEdgeList - Sets the list of local edges (vertex connectivity) for the network 113 114 Logically collective on dm 115 116 Input Parameters: 117 + dm - the dm object 118 . edgelist - list of edges for each subnetwork 119 - edgelistCouple - list of edges for each coupling subnetwork 120 121 Notes: 122 There is no copy involved in this operation, only the pointer is referenced. The edgelist should 123 not be destroyed before the call to DMNetworkLayoutSetUp 124 125 Level: intermediate 126 127 Example usage: 128 Consider the following 2 separate networks and a coupling network: 129 130 .vb 131 network 0: v0 -> v1 -> v2 -> v3 132 network 1: v1 -> v2 -> v0 133 coupling network: network 1: v2 -> network 0: v0 134 .ve 135 136 The resulting input 137 edgelist[0] = [0 1 | 1 2 | 2 3]; 138 edgelist[1] = [1 2 | 2 0] 139 edgelistCouple[0] = [(network)1 (v)2 (network)0 (v)0]. 140 141 .seealso: DMNetworkCreate, DMNetworkSetSizes 142 @*/ 143 PetscErrorCode DMNetworkSetEdgeList(DM dm,PetscInt *edgelist[],PetscInt *edgelistCouple[]) 144 { 145 DM_Network *network = (DM_Network*) dm->data; 146 PetscInt i,nsubnet,ncsubnet=network->ncsubnet; 147 148 PetscFunctionBegin; 149 nsubnet = network->nsubnet - ncsubnet; 150 for(i=0; i < nsubnet; i++) { 151 network->subnet[i].edgelist = edgelist[i]; 152 } 153 if (edgelistCouple) { 154 PetscInt j; 155 j = 0; 156 nsubnet = network->nsubnet; 157 while (i < nsubnet) network->subnet[i++].edgelist = edgelistCouple[j++]; 158 } 159 PetscFunctionReturn(0); 160 } 161 162 /*@ 163 DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network 164 165 Collective on dm 166 167 Input Parameters 168 . DM - the dmnetwork object 169 170 Notes: 171 This routine should be called after the network sizes and edgelists have been provided. It creates 172 the bare layout of the network and sets up the network to begin insertion of components. 173 174 All the components should be registered before calling this routine. 175 176 Level: intermediate 177 178 .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList 179 @*/ 180 PetscErrorCode DMNetworkLayoutSetUp(DM dm) 181 { 182 PetscErrorCode ierr; 183 DM_Network *network = (DM_Network*)dm->data; 184 PetscInt numCorners=2,spacedim=2,dim = 1; /* One dimensional network */ 185 PetscReal *vertexcoords=NULL; 186 PetscInt i,j,ctr,nsubnet,*eowners,np,*edges,*subnetvtx,vStart; 187 PetscInt k,netid,vid, *vidxlTog,*edgelist_couple=NULL; 188 const PetscInt *cone; 189 MPI_Comm comm; 190 PetscMPIInt size,rank; 191 192 PetscFunctionBegin; 193 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 194 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 195 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 196 197 /* Create the local edgelist for the network by concatenating local input edgelists of the subnetworks */ 198 ierr = PetscCalloc2(numCorners*network->nVertices,&vertexcoords,2*network->nEdges,&edges);CHKERRQ(ierr); 199 nsubnet = network->nsubnet - network->ncsubnet; 200 ctr = 0; 201 for (i=0; i < nsubnet; i++) { 202 for (j = 0; j < network->subnet[i].nedge; j++) { 203 edges[2*ctr] = network->subnet[i].eStart + network->subnet[i].edgelist[2*j]; 204 edges[2*ctr+1] = network->subnet[i].eStart + network->subnet[i].edgelist[2*j+1]; 205 ctr++; 206 } 207 } 208 209 /* Append local coupling edgelists of the subnetworks */ 210 i = nsubnet; /* netid of coupling subnet */ 211 nsubnet = network->nsubnet; 212 while (i < nsubnet) { 213 edgelist_couple = network->subnet[i].edgelist; 214 k = 0; 215 for (j = 0; j < network->subnet[i].nedge; j++) { 216 netid = edgelist_couple[k]; vid = edgelist_couple[k+1]; 217 edges[2*ctr] = network->subnet[netid].vStart + vid; k += 2; 218 219 netid = edgelist_couple[k]; vid = edgelist_couple[k+1]; 220 edges[2*ctr+1] = network->subnet[netid].vStart + vid; k+=2; 221 ctr++; 222 } 223 i++; 224 } 225 /* 226 if (rank == 0) { 227 ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] edgelist:\n",rank); 228 for(i=0; i < network->nEdges; i++) { 229 ierr = PetscPrintf(PETSC_COMM_SELF,"[%D %D]",edges[2*i],edges[2*i+1]);CHKERRQ(ierr); 230 printf("\n"); 231 } 232 } 233 */ 234 235 /* Create network->plex */ 236 #if defined(PETSC_USE_64BIT_INDICES) 237 { 238 int *edges64; 239 np = network->nEdges*numCorners; 240 ierr = PetscMalloc1(np,&edges64);CHKERRQ(ierr); 241 for (i=0; i<np; i++) edges64[i] = (int)edges[i]; 242 243 if (size == 1) { 244 ierr = DMPlexCreateFromCellList(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges64,spacedim,(const double*)vertexcoords,&network->plex);CHKERRQ(ierr); 245 } else { 246 ierr = DMPlexCreateFromCellListParallel(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges64,spacedim,(const PetscReal*)vertexcoords,NULL,&network->plex);CHKERRQ(ierr); 247 } 248 ierr = PetscFree(edges64);CHKERRQ(ierr); 249 } 250 #else 251 if (size == 1) { 252 ierr = DMPlexCreateFromCellList(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges,spacedim,(const double*)vertexcoords,&network->plex);CHKERRQ(ierr); 253 } else { 254 ierr = DMPlexCreateFromCellListParallel(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges,spacedim,(const PetscReal*)vertexcoords,NULL,&network->plex);CHKERRQ(ierr); 255 } 256 #endif 257 258 ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr); 259 ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr); 260 ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr); 261 vStart = network->vStart; 262 263 ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr); 264 ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr); 265 ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr); 266 ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr); 267 268 network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType); 269 np = network->pEnd - network->pStart; 270 ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr); 271 272 /* Create vidxlTog: maps local vertex index to global index */ 273 np = network->vEnd - vStart; 274 ierr = PetscMalloc2(np,&vidxlTog,size+1,&eowners);CHKERRQ(ierr); 275 ctr = 0; 276 for (i=network->eStart; i<network->eEnd; i++) { 277 ierr = DMNetworkGetConnectedVertices(dm,i,&cone);CHKERRQ(ierr); 278 vidxlTog[cone[0] - vStart] = edges[2*ctr]; 279 vidxlTog[cone[1] - vStart] = edges[2*ctr+1]; 280 ctr++; 281 } 282 ierr = PetscFree2(vertexcoords,edges);CHKERRQ(ierr); 283 284 /* Create vertices and edges array for the subnetworks */ 285 for (j=0; j < network->nsubnet; j++) { 286 ierr = PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);CHKERRQ(ierr); 287 288 /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop. 289 These get updated when the vertices and edges are added. */ 290 network->subnet[j].nvtx = 0; 291 network->subnet[j].nedge = 0; 292 } 293 ierr = PetscCalloc1(np,&network->subnetvtx);CHKERRQ(ierr); 294 295 296 /* Get edge ownership */ 297 np = network->eEnd - network->eStart; 298 ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRQ(ierr); 299 eowners[0] = 0; 300 for (i=2; i<=size; i++) eowners[i] += eowners[i-1]; 301 302 i = 0; j = 0; 303 while (i < np) { /* local edges, including coupling edges */ 304 network->header[i].index = i + eowners[rank]; /* Global edge index */ 305 306 if (j < network->nsubnet && i < network->subnet[j].eEnd) { 307 network->header[i].subnetid = j; /* Subnetwork id */ 308 network->subnet[j].edges[network->subnet[j].nedge++] = i; 309 310 network->header[i].ndata = 0; 311 ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr); 312 network->header[i].offset[0] = 0; 313 i++; 314 } 315 if (i >= network->subnet[j].eEnd) j++; 316 } 317 318 /* Count network->subnet[*].nvtx */ 319 for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */ 320 k = vidxlTog[i-vStart]; 321 for (j=0; j < network->nsubnet; j++) { 322 if (network->subnet[j].vStart <= k && k < network->subnet[j].vEnd) { 323 network->subnet[j].nvtx++; 324 break; 325 } 326 } 327 } 328 329 /* Set network->subnet[*].vertices on array network->subnetvtx */ 330 subnetvtx = network->subnetvtx; 331 for (j=0; j<network->nsubnet; j++) { 332 network->subnet[j].vertices = subnetvtx; 333 subnetvtx += network->subnet[j].nvtx; 334 network->subnet[j].nvtx = 0; 335 } 336 337 /* Set vertex array for the subnetworks */ 338 for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */ 339 network->header[i].index = vidxlTog[i-vStart]; /* Global vertex index */ 340 341 k = vidxlTog[i-vStart]; 342 for (j=0; j < network->nsubnet; j++) { 343 if (network->subnet[j].vStart <= k && k < network->subnet[j].vEnd) { 344 network->header[i].subnetid = j; 345 network->subnet[j].vertices[network->subnet[j].nvtx++] = i; 346 break; 347 } 348 } 349 350 network->header[i].ndata = 0; 351 ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr); 352 network->header[i].offset[0] = 0; 353 } 354 355 ierr = PetscFree2(vidxlTog,eowners);CHKERRQ(ierr); 356 PetscFunctionReturn(0); 357 } 358 359 /*@C 360 DMNetworkGetSubnetworkInfo - Returns the info for the subnetwork 361 362 Input Parameters 363 + dm - the DM object 364 - id - the ID (integer) of the subnetwork 365 366 Output Parameters 367 + nv - number of vertices (local) 368 . ne - number of edges (local) 369 . vtx - local vertices for this subnetwork 370 . edge - local edges for this subnetwork 371 372 Notes: 373 Cannot call this routine before DMNetworkLayoutSetup() 374 375 Level: intermediate 376 377 .seealso: DMNetworkLayoutSetUp, DMNetworkCreate 378 @*/ 379 PetscErrorCode DMNetworkGetSubnetworkInfo(DM dm,PetscInt id,PetscInt *nv, PetscInt *ne,const PetscInt **vtx, const PetscInt **edge) 380 { 381 DM_Network *network = (DM_Network*)dm->data; 382 383 PetscFunctionBegin; 384 *nv = network->subnet[id].nvtx; 385 *ne = network->subnet[id].nedge; 386 *vtx = network->subnet[id].vertices; 387 *edge = network->subnet[id].edges; 388 PetscFunctionReturn(0); 389 } 390 391 /*@C 392 DMNetworkGetSubnetworkCoupleInfo - Returns the info for the coupling subnetwork 393 394 Input Parameters 395 + dm - the DM object 396 - id - the ID (integer) of the coupling subnetwork 397 398 Output Parameters 399 + ne - number of edges (local) 400 - edge - local edges for this coupling subnetwork 401 402 Notes: 403 Cannot call this routine before DMNetworkLayoutSetup() 404 405 Level: intermediate 406 407 .seealso: DMNetworkGetSubnetworkInfo, DMNetworkLayoutSetUp, DMNetworkCreate 408 @*/ 409 PetscErrorCode DMNetworkGetSubnetworkCoupleInfo(DM dm,PetscInt id,PetscInt *ne,const PetscInt **edge) 410 { 411 DM_Network *net = (DM_Network*)dm->data; 412 PetscInt id1 = id + net->nsubnet - net->ncsubnet; 413 414 PetscFunctionBegin; 415 *ne = net->subnet[id1].nedge; 416 *edge = net->subnet[id1].edges; 417 PetscFunctionReturn(0); 418 } 419 420 /*@C 421 DMNetworkRegisterComponent - Registers the network component 422 423 Logically collective on dm 424 425 Input Parameters 426 + dm - the network object 427 . name - the component name 428 - size - the storage size in bytes for this component data 429 430 Output Parameters 431 . key - an integer key that defines the component 432 433 Notes 434 This routine should be called by all processors before calling DMNetworkLayoutSetup(). 435 436 Level: intermediate 437 438 .seealso: DMNetworkLayoutSetUp, DMNetworkCreate 439 @*/ 440 PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key) 441 { 442 PetscErrorCode ierr; 443 DM_Network *network = (DM_Network*) dm->data; 444 DMNetworkComponent *component=&network->component[network->ncomponent]; 445 PetscBool flg=PETSC_FALSE; 446 PetscInt i; 447 448 PetscFunctionBegin; 449 for (i=0; i < network->ncomponent; i++) { 450 ierr = PetscStrcmp(component->name,name,&flg);CHKERRQ(ierr); 451 if (flg) { 452 *key = i; 453 PetscFunctionReturn(0); 454 } 455 } 456 if(network->ncomponent == MAX_COMPONENTS) { 457 SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components registered exceeds the max %D",MAX_COMPONENTS); 458 } 459 460 ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr); 461 component->size = size/sizeof(DMNetworkComponentGenericDataType); 462 *key = network->ncomponent; 463 network->ncomponent++; 464 PetscFunctionReturn(0); 465 } 466 467 /*@ 468 DMNetworkGetVertexRange - Get the bounds [start, end) for the vertices. 469 470 Not Collective 471 472 Input Parameters: 473 + dm - The DMNetwork object 474 475 Output Paramters: 476 + vStart - The first vertex point 477 - vEnd - One beyond the last vertex point 478 479 Level: intermediate 480 481 .seealso: DMNetworkGetEdgeRange 482 @*/ 483 PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd) 484 { 485 DM_Network *network = (DM_Network*)dm->data; 486 487 PetscFunctionBegin; 488 if (vStart) *vStart = network->vStart; 489 if (vEnd) *vEnd = network->vEnd; 490 PetscFunctionReturn(0); 491 } 492 493 /*@ 494 DMNetworkGetEdgeRange - Get the bounds [start, end) for the edges. 495 496 Not Collective 497 498 Input Parameters: 499 + dm - The DMNetwork object 500 501 Output Paramters: 502 + eStart - The first edge point 503 - eEnd - One beyond the last edge point 504 505 Level: intermediate 506 507 .seealso: DMNetworkGetVertexRange 508 @*/ 509 PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd) 510 { 511 DM_Network *network = (DM_Network*)dm->data; 512 513 PetscFunctionBegin; 514 if (eStart) *eStart = network->eStart; 515 if (eEnd) *eEnd = network->eEnd; 516 PetscFunctionReturn(0); 517 } 518 519 /*@ 520 DMNetworkGetGlobalEdgeIndex - Get the user global numbering for the edge. 521 522 Not Collective 523 524 Input Parameters: 525 + dm - DMNetwork object 526 - p - edge point 527 528 Output Paramters: 529 . index - user global numbering for the edge 530 531 Level: intermediate 532 533 .seealso: DMNetworkGetGlobalVertexIndex 534 @*/ 535 PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index) 536 { 537 PetscErrorCode ierr; 538 DM_Network *network = (DM_Network*)dm->data; 539 PetscInt offsetp; 540 DMNetworkComponentHeader header; 541 542 PetscFunctionBegin; 543 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first"); 544 ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr); 545 header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp); 546 *index = header->index; 547 PetscFunctionReturn(0); 548 } 549 550 /*@ 551 DMNetworkGetGlobalVertexIndex - Get the user global numbering for the vertex. 552 553 Not Collective 554 555 Input Parameters: 556 + dm - DMNetwork object 557 - p - vertex point 558 559 Output Paramters: 560 . index - user global numbering for the vertex 561 562 Level: intermediate 563 564 .seealso: DMNetworkGetGlobalEdgeIndex 565 @*/ 566 PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index) 567 { 568 PetscErrorCode ierr; 569 DM_Network *network = (DM_Network*)dm->data; 570 PetscInt offsetp; 571 DMNetworkComponentHeader header; 572 573 PetscFunctionBegin; 574 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first"); 575 ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr); 576 header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp); 577 *index = header->index; 578 PetscFunctionReturn(0); 579 } 580 581 /* 582 DMNetworkGetComponentKeyOffset - Gets the type along with the offset for indexing the 583 component value from the component data array 584 585 Not Collective 586 587 Input Parameters: 588 + dm - The DMNetwork object 589 . p - vertex/edge point 590 - compnum - component number 591 592 Output Parameters: 593 + compkey - the key obtained when registering the component 594 - offset - offset into the component data array associated with the vertex/edge point 595 596 Notes: 597 Typical usage: 598 599 DMNetworkGetComponentDataArray(dm, &arr); 600 DMNetworkGetVertex/EdgeRange(dm,&Start,&End); 601 Loop over vertices or edges 602 DMNetworkGetNumComponents(dm,v,&numcomps); 603 Loop over numcomps 604 DMNetworkGetComponentKeyOffset(dm,v,compnum,&key,&offset); 605 compdata = (UserCompDataType)(arr+offset); 606 607 Level: intermediate 608 609 .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray, 610 */ 611 PetscErrorCode DMNetworkGetComponentKeyOffset(DM dm,PetscInt p, PetscInt compnum, PetscInt *compkey, PetscInt *offset) 612 { 613 PetscErrorCode ierr; 614 PetscInt offsetp; 615 DMNetworkComponentHeader header; 616 DM_Network *network = (DM_Network*)dm->data; 617 618 PetscFunctionBegin; 619 ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr); 620 header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp); 621 if (compkey) *compkey = header->key[compnum]; 622 if (offset) *offset = offsetp+network->dataheadersize+header->offset[compnum]; 623 PetscFunctionReturn(0); 624 } 625 626 /*@ 627 DMNetworkGetComponent - Returns the network component and its key 628 629 Not Collective 630 631 Input Parameters 632 + dm - DMNetwork object 633 . p - edge or vertex point 634 - compnum - component number 635 636 Output Parameters: 637 + compkey - the key set for this computing during registration 638 - component - the component data 639 640 Notes: 641 Typical usage: 642 643 DMNetworkGetVertex/EdgeRange(dm,&Start,&End); 644 Loop over vertices or edges 645 DMNetworkGetNumComponents(dm,v,&numcomps); 646 Loop over numcomps 647 DMNetworkGetComponent(dm,v,compnum,&key,&component); 648 649 Level: intermediate 650 651 .seealso: DMNetworkGetNumComponents, DMNetworkGetVariableOffset 652 @*/ 653 PetscErrorCode DMNetworkGetComponent(DM dm, PetscInt p, PetscInt compnum, PetscInt *key, void **component) 654 { 655 PetscErrorCode ierr; 656 DM_Network *network = (DM_Network*)dm->data; 657 PetscInt offsetd = 0; 658 659 PetscFunctionBegin; 660 ierr = DMNetworkGetComponentKeyOffset(dm,p,compnum,key,&offsetd);CHKERRQ(ierr); 661 *component = network->componentdataarray+offsetd; 662 PetscFunctionReturn(0); 663 } 664 665 /*@ 666 DMNetworkAddComponent - Adds a network component at the given point (vertex/edge) 667 668 Not Collective 669 670 Input Parameters: 671 + dm - The DMNetwork object 672 . p - vertex/edge point 673 . componentkey - component key returned while registering the component 674 - compvalue - pointer to the data structure for the component 675 676 Level: intermediate 677 678 .seealso: DMNetworkGetVertexRange, DMNetworkGetEdgeRange, DMNetworkRegisterComponent 679 @*/ 680 PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p,PetscInt componentkey,void* compvalue) 681 { 682 DM_Network *network = (DM_Network*)dm->data; 683 DMNetworkComponent *component = &network->component[componentkey]; 684 DMNetworkComponentHeader header = &network->header[p]; 685 DMNetworkComponentValue cvalue = &network->cvalue[p]; 686 PetscErrorCode ierr; 687 688 PetscFunctionBegin; 689 if (header->ndata == MAX_DATA_AT_POINT) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components at a point exceeds the max %D",MAX_DATA_AT_POINT); 690 691 header->size[header->ndata] = component->size; 692 ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr); 693 header->key[header->ndata] = componentkey; 694 if (header->ndata != 0) header->offset[header->ndata] = header->offset[header->ndata-1] + header->size[header->ndata-1]; 695 696 cvalue->data[header->ndata] = (void*)compvalue; 697 header->ndata++; 698 PetscFunctionReturn(0); 699 } 700 701 /*@ 702 DMNetworkGetNumComponents - Get the number of components at a vertex/edge 703 704 Not Collective 705 706 Input Parameters: 707 + dm - The DMNetwork object 708 . p - vertex/edge point 709 710 Output Parameters: 711 . numcomponents - Number of components at the vertex/edge 712 713 Level: intermediate 714 715 .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent 716 @*/ 717 PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents) 718 { 719 PetscErrorCode ierr; 720 PetscInt offset; 721 DM_Network *network = (DM_Network*)dm->data; 722 723 PetscFunctionBegin; 724 ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr); 725 *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata; 726 PetscFunctionReturn(0); 727 } 728 729 /*@ 730 DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector. 731 732 Not Collective 733 734 Input Parameters: 735 + dm - The DMNetwork object 736 - p - the edge/vertex point 737 738 Output Parameters: 739 . offset - the offset 740 741 Level: intermediate 742 743 .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector 744 @*/ 745 PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset) 746 { 747 PetscErrorCode ierr; 748 DM_Network *network = (DM_Network*)dm->data; 749 750 PetscFunctionBegin; 751 ierr = PetscSectionGetOffset(network->plex->defaultSection,p,offset);CHKERRQ(ierr); 752 PetscFunctionReturn(0); 753 } 754 755 /*@ 756 DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector. 757 758 Not Collective 759 760 Input Parameters: 761 + dm - The DMNetwork object 762 - p - the edge/vertex point 763 764 Output Parameters: 765 . offsetg - the offset 766 767 Level: intermediate 768 769 .seealso: DMNetworkGetVariableOffset, DMGetLocalVector 770 @*/ 771 PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg) 772 { 773 PetscErrorCode ierr; 774 DM_Network *network = (DM_Network*)dm->data; 775 776 PetscFunctionBegin; 777 ierr = PetscSectionGetOffset(network->plex->defaultGlobalSection,p,offsetg);CHKERRQ(ierr); 778 if (*offsetg < 0) *offsetg = -(*offsetg + 1); /* Convert to actual global offset for ghost vertex */ 779 PetscFunctionReturn(0); 780 } 781 782 /*@ 783 DMNetworkGetEdgeOffset - Get the offset for accessing the variable associated with the given edge from the local subvector. 784 785 Not Collective 786 787 Input Parameters: 788 + dm - The DMNetwork object 789 - p - the edge point 790 791 Output Parameters: 792 . offset - the offset 793 794 Level: intermediate 795 796 .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector 797 @*/ 798 PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset) 799 { 800 PetscErrorCode ierr; 801 DM_Network *network = (DM_Network*)dm->data; 802 803 PetscFunctionBegin; 804 805 ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr); 806 PetscFunctionReturn(0); 807 } 808 809 /*@ 810 DMNetworkGetVertexOffset - Get the offset for accessing the variable associated with the given vertex from the local subvector. 811 812 Not Collective 813 814 Input Parameters: 815 + dm - The DMNetwork object 816 - p - the vertex point 817 818 Output Parameters: 819 . offset - the offset 820 821 Level: intermediate 822 823 .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector 824 @*/ 825 PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset) 826 { 827 PetscErrorCode ierr; 828 DM_Network *network = (DM_Network*)dm->data; 829 830 PetscFunctionBegin; 831 832 p -= network->vStart; 833 834 ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr); 835 PetscFunctionReturn(0); 836 } 837 /*@ 838 DMNetworkAddNumVariables - Add number of variables associated with a given point. 839 840 Not Collective 841 842 Input Parameters: 843 + dm - The DMNetworkObject 844 . p - the vertex/edge point 845 - nvar - number of additional variables 846 847 Level: intermediate 848 849 .seealso: DMNetworkSetNumVariables 850 @*/ 851 PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar) 852 { 853 PetscErrorCode ierr; 854 DM_Network *network = (DM_Network*)dm->data; 855 856 PetscFunctionBegin; 857 ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr); 858 PetscFunctionReturn(0); 859 } 860 861 /*@ 862 DMNetworkGetNumVariables - Gets number of variables for a vertex/edge point. 863 864 Not Collective 865 866 Input Parameters: 867 + dm - The DMNetworkObject 868 - p - the vertex/edge point 869 870 Output Parameters: 871 . nvar - number of variables 872 873 Level: intermediate 874 875 .seealso: DMNetworkAddNumVariables, DMNetworkSddNumVariables 876 @*/ 877 PetscErrorCode DMNetworkGetNumVariables(DM dm,PetscInt p,PetscInt *nvar) 878 { 879 PetscErrorCode ierr; 880 DM_Network *network = (DM_Network*)dm->data; 881 882 PetscFunctionBegin; 883 ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr); 884 PetscFunctionReturn(0); 885 } 886 887 /*@ 888 DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point. 889 890 Not Collective 891 892 Input Parameters: 893 + dm - The DMNetworkObject 894 . p - the vertex/edge point 895 - nvar - number of variables 896 897 Level: intermediate 898 899 .seealso: DMNetworkAddNumVariables 900 @*/ 901 PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar) 902 { 903 PetscErrorCode ierr; 904 DM_Network *network = (DM_Network*)dm->data; 905 906 PetscFunctionBegin; 907 ierr = PetscSectionSetDof(network->DofSection,p,nvar);CHKERRQ(ierr); 908 PetscFunctionReturn(0); 909 } 910 911 /* Sets up the array that holds the data for all components and its associated section. This 912 function is called during DMSetUp() */ 913 PetscErrorCode DMNetworkComponentSetUp(DM dm) 914 { 915 PetscErrorCode ierr; 916 DM_Network *network = (DM_Network*)dm->data; 917 PetscInt arr_size,p,offset,offsetp,ncomp,i; 918 DMNetworkComponentHeader header; 919 DMNetworkComponentValue cvalue; 920 DMNetworkComponentGenericDataType *componentdataarray; 921 922 PetscFunctionBegin; 923 ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr); 924 ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr); 925 ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr); 926 componentdataarray = network->componentdataarray; 927 for (p = network->pStart; p < network->pEnd; p++) { 928 ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr); 929 /* Copy header */ 930 header = &network->header[p]; 931 ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr); 932 /* Copy data */ 933 cvalue = &network->cvalue[p]; 934 ncomp = header->ndata; 935 for (i = 0; i < ncomp; i++) { 936 offset = offsetp + network->dataheadersize + header->offset[i]; 937 ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr); 938 } 939 } 940 PetscFunctionReturn(0); 941 } 942 943 /* Sets up the section for dofs. This routine is called during DMSetUp() */ 944 PetscErrorCode DMNetworkVariablesSetUp(DM dm) 945 { 946 PetscErrorCode ierr; 947 DM_Network *network = (DM_Network*)dm->data; 948 949 PetscFunctionBegin; 950 ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr); 951 PetscFunctionReturn(0); 952 } 953 954 /*@C 955 DMNetworkGetComponentDataArray - Returns the component data array 956 957 Not Collective 958 959 Input Parameters: 960 . dm - The DMNetwork Object 961 962 Output Parameters: 963 . componentdataarray - array that holds data for all components 964 965 Level: intermediate 966 967 .seealso: DMNetworkGetComponentKeyOffset, DMNetworkGetNumComponents 968 @*/ 969 PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray) 970 { 971 DM_Network *network = (DM_Network*)dm->data; 972 973 PetscFunctionBegin; 974 *componentdataarray = network->componentdataarray; 975 PetscFunctionReturn(0); 976 } 977 978 /* Get a subsection from a range of points */ 979 PetscErrorCode DMNetworkGetSubSection_private(PetscSection master, PetscInt pstart, PetscInt pend,PetscSection *subsection) 980 { 981 PetscErrorCode ierr; 982 PetscInt i, nvar; 983 984 PetscFunctionBegin; 985 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)master), subsection);CHKERRQ(ierr); 986 ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr); 987 for (i = pstart; i < pend; i++) { 988 ierr = PetscSectionGetDof(master,i,&nvar);CHKERRQ(ierr); 989 ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr); 990 } 991 992 ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr); 993 PetscFunctionReturn(0); 994 } 995 996 /* Create a submap of points with a GlobalToLocal structure */ 997 PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map) 998 { 999 PetscErrorCode ierr; 1000 PetscInt i, *subpoints; 1001 1002 PetscFunctionBegin; 1003 /* Create index sets to map from "points" to "subpoints" */ 1004 ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr); 1005 for (i = pstart; i < pend; i++) { 1006 subpoints[i - pstart] = i; 1007 } 1008 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr); 1009 ierr = PetscFree(subpoints);CHKERRQ(ierr); 1010 PetscFunctionReturn(0); 1011 } 1012 1013 /*@ 1014 DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute. 1015 1016 Collective 1017 1018 Input Parameters: 1019 . dm - The DMNetworkObject 1020 1021 Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are: 1022 1023 points = [0 1 2 3 4 5 6] 1024 1025 where edges = [0,1,2,3] and vertices = [4,5,6]. The new orderings will be specific to the subset (i.e vertices = [0,1,2] <- [4,5,6]). 1026 1027 With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset. 1028 1029 Level: intermediate 1030 1031 @*/ 1032 1033 PetscErrorCode DMNetworkAssembleGraphStructures(DM dm) 1034 { 1035 PetscErrorCode ierr; 1036 MPI_Comm comm; 1037 PetscMPIInt rank, size; 1038 DM_Network *network = (DM_Network*)dm->data; 1039 1040 PetscFunctionBegin; 1041 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1042 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1043 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1044 1045 /* Create maps for vertices and edges */ 1046 ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr); 1047 ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr); 1048 1049 /* Create local sub-sections */ 1050 ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr); 1051 ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr); 1052 1053 if (size > 1) { 1054 ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr); 1055 1056 ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr); 1057 ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr); 1058 ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr); 1059 } else { 1060 /* create structures for vertex */ 1061 ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr); 1062 /* create structures for edge */ 1063 ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr); 1064 } 1065 1066 /* Add viewers */ 1067 ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr); 1068 ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr); 1069 ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr); 1070 ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr); 1071 PetscFunctionReturn(0); 1072 } 1073 1074 /*@ 1075 DMNetworkDistribute - Distributes the network and moves associated component data. 1076 1077 Collective 1078 1079 Input Parameter: 1080 + DM - the DMNetwork object 1081 - overlap - The overlap of partitions, 0 is the default 1082 1083 Notes: 1084 Distributes the network with <overlap>-overlapping partitioning of the edges. 1085 1086 Level: intermediate 1087 1088 .seealso: DMNetworkCreate 1089 @*/ 1090 PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap) 1091 { 1092 MPI_Comm comm; 1093 PetscErrorCode ierr; 1094 PetscMPIInt size; 1095 DM_Network *oldDMnetwork = (DM_Network*)((*dm)->data); 1096 DM_Network *newDMnetwork; 1097 PetscSF pointsf=NULL; 1098 DM newDM; 1099 PetscInt j,e,v,offset,*subnetvtx; 1100 PetscPartitioner part; 1101 DMNetworkComponentHeader header; 1102 1103 PetscFunctionBegin; 1104 ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr); 1105 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1106 if (size == 1) PetscFunctionReturn(0); 1107 1108 ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr); 1109 newDMnetwork = (DM_Network*)newDM->data; 1110 newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType); 1111 1112 /* Enable runtime options for petscpartitioner */ 1113 ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr); 1114 ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); 1115 1116 /* Distribute plex dm and dof section */ 1117 ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr); 1118 1119 /* Distribute dof section */ 1120 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DofSection);CHKERRQ(ierr); 1121 ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr); 1122 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DataSection);CHKERRQ(ierr); 1123 1124 /* Distribute data and associated section */ 1125 ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr); 1126 1127 ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr); 1128 ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr); 1129 ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr); 1130 newDMnetwork->nEdges = newDMnetwork->eEnd - newDMnetwork->eStart; 1131 newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart; 1132 newDMnetwork->NVertices = oldDMnetwork->NVertices; 1133 newDMnetwork->NEdges = oldDMnetwork->NEdges; 1134 1135 /* Set Dof section as the default section for dm */ 1136 ierr = DMSetSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr); 1137 ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr); 1138 1139 /* Set up subnetwork info in the newDM */ 1140 newDMnetwork->nsubnet = oldDMnetwork->nsubnet; 1141 newDMnetwork->ncsubnet = oldDMnetwork->ncsubnet; 1142 ierr = PetscCalloc1(newDMnetwork->nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr); 1143 /* Copy over the global number of vertices and edges in each subnetwork. Note that these are already 1144 calculated in DMNetworkLayoutSetUp() 1145 */ 1146 for(j=0; j < newDMnetwork->nsubnet; j++) { 1147 newDMnetwork->subnet[j].Nvtx = oldDMnetwork->subnet[j].Nvtx; 1148 newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge; 1149 } 1150 1151 for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) { 1152 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr); 1153 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1154 newDMnetwork->subnet[header->subnetid].nedge++; 1155 } 1156 1157 for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) { 1158 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr); 1159 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1160 newDMnetwork->subnet[header->subnetid].nvtx++; 1161 } 1162 1163 /* Now create the vertices and edge arrays for the subnetworks */ 1164 ierr = PetscCalloc1(newDMnetwork->vEnd-newDMnetwork->vStart,&newDMnetwork->subnetvtx);CHKERRQ(ierr); 1165 subnetvtx = newDMnetwork->subnetvtx; 1166 1167 for (j=0; j<newDMnetwork->nsubnet; j++) { 1168 ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr); 1169 newDMnetwork->subnet[j].vertices = subnetvtx; 1170 subnetvtx += newDMnetwork->subnet[j].nvtx; 1171 1172 /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop. 1173 These get updated when the vertices and edges are added. */ 1174 newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0; 1175 } 1176 1177 /* Set the vertices and edges in each subnetwork */ 1178 for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) { 1179 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr); 1180 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1181 newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e; 1182 } 1183 1184 for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) { 1185 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr); 1186 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1187 newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v; 1188 } 1189 1190 newDM->setupcalled = (*dm)->setupcalled; 1191 newDMnetwork->distributecalled = PETSC_TRUE; 1192 1193 /* Destroy point SF */ 1194 ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr); 1195 1196 ierr = DMDestroy(dm);CHKERRQ(ierr); 1197 *dm = newDM; 1198 PetscFunctionReturn(0); 1199 } 1200 1201 /*@C 1202 PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering. 1203 1204 Input Parameters: 1205 + masterSF - the original SF structure 1206 - map - a ISLocalToGlobal mapping that contains the subset of points 1207 1208 Output Parameters: 1209 . subSF - a subset of the masterSF for the desired subset. 1210 */ 1211 1212 PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) { 1213 1214 PetscErrorCode ierr; 1215 PetscInt nroots, nleaves, *ilocal_sub; 1216 PetscInt i, *ilocal_map, nroots_sub, nleaves_sub = 0; 1217 PetscInt *local_points, *remote_points; 1218 PetscSFNode *iremote_sub; 1219 const PetscInt *ilocal; 1220 const PetscSFNode *iremote; 1221 1222 PetscFunctionBegin; 1223 ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); 1224 1225 /* Look for leaves that pertain to the subset of points. Get the local ordering */ 1226 ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr); 1227 ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr); 1228 for (i = 0; i < nleaves; i++) { 1229 if (ilocal_map[i] != -1) nleaves_sub += 1; 1230 } 1231 /* Re-number ilocal with subset numbering. Need information from roots */ 1232 ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr); 1233 for (i = 0; i < nroots; i++) local_points[i] = i; 1234 ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr); 1235 ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr); 1236 ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr); 1237 /* Fill up graph using local (that is, local to the subset) numbering. */ 1238 ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr); 1239 ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr); 1240 nleaves_sub = 0; 1241 for (i = 0; i < nleaves; i++) { 1242 if (ilocal_map[i] != -1) { 1243 ilocal_sub[nleaves_sub] = ilocal_map[i]; 1244 iremote_sub[nleaves_sub].rank = iremote[i].rank; 1245 iremote_sub[nleaves_sub].index = remote_points[ilocal[i]]; 1246 nleaves_sub += 1; 1247 } 1248 } 1249 ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr); 1250 ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr); 1251 1252 /* Create new subSF */ 1253 ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr); 1254 ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr); 1255 ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr); 1256 ierr = PetscFree(ilocal_map);CHKERRQ(ierr); 1257 ierr = PetscFree(iremote_sub);CHKERRQ(ierr); 1258 PetscFunctionReturn(0); 1259 } 1260 1261 /*@C 1262 DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point 1263 1264 Not Collective 1265 1266 Input Parameters: 1267 + dm - The DMNetwork object 1268 - p - the vertex point 1269 1270 Output Paramters: 1271 + nedges - number of edges connected to this vertex point 1272 - edges - List of edge points 1273 1274 Level: intermediate 1275 1276 Fortran Notes: 1277 Since it returns an array, this routine is only available in Fortran 90, and you must 1278 include petsc.h90 in your code. 1279 1280 .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices 1281 @*/ 1282 PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[]) 1283 { 1284 PetscErrorCode ierr; 1285 DM_Network *network = (DM_Network*)dm->data; 1286 1287 PetscFunctionBegin; 1288 ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr); 1289 ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr); 1290 PetscFunctionReturn(0); 1291 } 1292 1293 /*@C 1294 DMNetworkGetConnectedVertices - Return the connected vertices for this edge point 1295 1296 Not Collective 1297 1298 Input Parameters: 1299 + dm - The DMNetwork object 1300 - p - the edge point 1301 1302 Output Paramters: 1303 . vertices - vertices connected to this edge 1304 1305 Level: intermediate 1306 1307 Fortran Notes: 1308 Since it returns an array, this routine is only available in Fortran 90, and you must 1309 include petsc.h90 in your code. 1310 1311 .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges 1312 @*/ 1313 PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[]) 1314 { 1315 PetscErrorCode ierr; 1316 DM_Network *network = (DM_Network*)dm->data; 1317 1318 PetscFunctionBegin; 1319 ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr); 1320 PetscFunctionReturn(0); 1321 } 1322 1323 /*@ 1324 DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex 1325 1326 Not Collective 1327 1328 Input Parameters: 1329 + dm - The DMNetwork object 1330 . p - the vertex point 1331 1332 Output Parameter: 1333 . isghost - TRUE if the vertex is a ghost point 1334 1335 Level: intermediate 1336 1337 .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange 1338 @*/ 1339 PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost) 1340 { 1341 PetscErrorCode ierr; 1342 DM_Network *network = (DM_Network*)dm->data; 1343 PetscInt offsetg; 1344 PetscSection sectiong; 1345 1346 PetscFunctionBegin; 1347 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first"); 1348 *isghost = PETSC_FALSE; 1349 ierr = DMGetGlobalSection(network->plex,§iong);CHKERRQ(ierr); 1350 ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr); 1351 if (offsetg < 0) *isghost = PETSC_TRUE; 1352 PetscFunctionReturn(0); 1353 } 1354 1355 PetscErrorCode DMSetUp_Network(DM dm) 1356 { 1357 PetscErrorCode ierr; 1358 DM_Network *network=(DM_Network*)dm->data; 1359 1360 PetscFunctionBegin; 1361 ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr); 1362 ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr); 1363 1364 ierr = DMSetSection(network->plex,network->DofSection);CHKERRQ(ierr); 1365 ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr); 1366 1367 dm->setupcalled = PETSC_TRUE; 1368 ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr); 1369 PetscFunctionReturn(0); 1370 } 1371 1372 /*@ 1373 DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices 1374 -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)? 1375 1376 Collective 1377 1378 Input Parameters: 1379 + dm - The DMNetwork object 1380 . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges 1381 - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices 1382 1383 Level: intermediate 1384 1385 @*/ 1386 PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg) 1387 { 1388 DM_Network *network=(DM_Network*)dm->data; 1389 PetscErrorCode ierr; 1390 PetscInt nVertices = network->nVertices; 1391 1392 PetscFunctionBegin; 1393 network->userEdgeJacobian = eflg; 1394 network->userVertexJacobian = vflg; 1395 1396 if (eflg && !network->Je) { 1397 ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr); 1398 } 1399 1400 if (vflg && !network->Jv && nVertices) { 1401 PetscInt i,*vptr,nedges,vStart=network->vStart; 1402 PetscInt nedges_total; 1403 const PetscInt *edges; 1404 1405 /* count nvertex_total */ 1406 nedges_total = 0; 1407 ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr); 1408 1409 vptr[0] = 0; 1410 for (i=0; i<nVertices; i++) { 1411 ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr); 1412 nedges_total += nedges; 1413 vptr[i+1] = vptr[i] + 2*nedges + 1; 1414 } 1415 1416 ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr); 1417 network->Jvptr = vptr; 1418 } 1419 PetscFunctionReturn(0); 1420 } 1421 1422 /*@ 1423 DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network 1424 1425 Not Collective 1426 1427 Input Parameters: 1428 + dm - The DMNetwork object 1429 . p - the edge point 1430 - J - array (size = 3) of Jacobian submatrices for this edge point: 1431 J[0]: this edge 1432 J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices() 1433 1434 Level: intermediate 1435 1436 .seealso: DMNetworkVertexSetMatrix 1437 @*/ 1438 PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[]) 1439 { 1440 DM_Network *network=(DM_Network*)dm->data; 1441 1442 PetscFunctionBegin; 1443 if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix"); 1444 1445 if (J) { 1446 network->Je[3*p] = J[0]; 1447 network->Je[3*p+1] = J[1]; 1448 network->Je[3*p+2] = J[2]; 1449 } 1450 PetscFunctionReturn(0); 1451 } 1452 1453 /*@ 1454 DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network 1455 1456 Not Collective 1457 1458 Input Parameters: 1459 + dm - The DMNetwork object 1460 . p - the vertex point 1461 - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point: 1462 J[0]: this vertex 1463 J[1+2*i]: i-th supporting edge 1464 J[1+2*i+1]: i-th connected vertex 1465 1466 Level: intermediate 1467 1468 .seealso: DMNetworkEdgeSetMatrix 1469 @*/ 1470 PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[]) 1471 { 1472 PetscErrorCode ierr; 1473 DM_Network *network=(DM_Network*)dm->data; 1474 PetscInt i,*vptr,nedges,vStart=network->vStart; 1475 const PetscInt *edges; 1476 1477 PetscFunctionBegin; 1478 if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix"); 1479 1480 if (J) { 1481 vptr = network->Jvptr; 1482 network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */ 1483 1484 /* Set Jacobian for each supporting edge and connected vertex */ 1485 ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr); 1486 for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i]; 1487 } 1488 PetscFunctionReturn(0); 1489 } 1490 1491 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1492 { 1493 PetscErrorCode ierr; 1494 PetscInt j; 1495 PetscScalar val=(PetscScalar)ncols; 1496 1497 PetscFunctionBegin; 1498 if (!ghost) { 1499 for (j=0; j<nrows; j++) { 1500 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1501 } 1502 } else { 1503 for (j=0; j<nrows; j++) { 1504 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1505 } 1506 } 1507 PetscFunctionReturn(0); 1508 } 1509 1510 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1511 { 1512 PetscErrorCode ierr; 1513 PetscInt j,ncols_u; 1514 PetscScalar val; 1515 1516 PetscFunctionBegin; 1517 if (!ghost) { 1518 for (j=0; j<nrows; j++) { 1519 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1520 val = (PetscScalar)ncols_u; 1521 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1522 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1523 } 1524 } else { 1525 for (j=0; j<nrows; j++) { 1526 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1527 val = (PetscScalar)ncols_u; 1528 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1529 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1530 } 1531 } 1532 PetscFunctionReturn(0); 1533 } 1534 1535 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1536 { 1537 PetscErrorCode ierr; 1538 1539 PetscFunctionBegin; 1540 if (Ju) { 1541 ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1542 } else { 1543 ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1544 } 1545 PetscFunctionReturn(0); 1546 } 1547 1548 PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1549 { 1550 PetscErrorCode ierr; 1551 PetscInt j,*cols; 1552 PetscScalar *zeros; 1553 1554 PetscFunctionBegin; 1555 ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr); 1556 for (j=0; j<ncols; j++) cols[j] = j+ cstart; 1557 ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr); 1558 ierr = PetscFree2(cols,zeros);CHKERRQ(ierr); 1559 PetscFunctionReturn(0); 1560 } 1561 1562 PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1563 { 1564 PetscErrorCode ierr; 1565 PetscInt j,M,N,row,col,ncols_u; 1566 const PetscInt *cols; 1567 PetscScalar zero=0.0; 1568 1569 PetscFunctionBegin; 1570 ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr); 1571 if (nrows != M || ncols != N) SETERRQ4(PetscObjectComm((PetscObject)Ju),PETSC_ERR_USER,"%D by %D must equal %D by %D",nrows,ncols,M,N); 1572 1573 for (row=0; row<nrows; row++) { 1574 ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1575 for (j=0; j<ncols_u; j++) { 1576 col = cols[j] + cstart; 1577 ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr); 1578 } 1579 ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1580 } 1581 PetscFunctionReturn(0); 1582 } 1583 1584 PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1585 { 1586 PetscErrorCode ierr; 1587 1588 PetscFunctionBegin; 1589 if (Ju) { 1590 ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1591 } else { 1592 ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1593 } 1594 PetscFunctionReturn(0); 1595 } 1596 1597 /* Creates a GlobalToLocal mapping with a Local and Global section. This is akin to the routine DMGetLocalToGlobalMapping but without the need of providing a dm. 1598 */ 1599 PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog) 1600 { 1601 PetscErrorCode ierr; 1602 PetscInt i,size,dof; 1603 PetscInt *glob2loc; 1604 1605 PetscFunctionBegin; 1606 ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr); 1607 ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr); 1608 1609 for (i = 0; i < size; i++) { 1610 ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr); 1611 dof = (dof >= 0) ? dof : -(dof + 1); 1612 glob2loc[i] = dof; 1613 } 1614 1615 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 1616 #if 0 1617 ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1618 #endif 1619 PetscFunctionReturn(0); 1620 } 1621 1622 #include <petsc/private/matimpl.h> 1623 1624 PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J) 1625 { 1626 PetscErrorCode ierr; 1627 DM_Network *network = (DM_Network*)dm->data; 1628 PetscMPIInt rank, size; 1629 PetscInt eDof,vDof; 1630 Mat j11,j12,j21,j22,bA[2][2]; 1631 MPI_Comm comm; 1632 ISLocalToGlobalMapping eISMap,vISMap; 1633 1634 PetscFunctionBegin; 1635 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1636 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1637 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1638 1639 ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr); 1640 ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr); 1641 1642 ierr = MatCreate(comm, &j11);CHKERRQ(ierr); 1643 ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1644 ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr); 1645 1646 ierr = MatCreate(comm, &j12);CHKERRQ(ierr); 1647 ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr); 1648 ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr); 1649 1650 ierr = MatCreate(comm, &j21);CHKERRQ(ierr); 1651 ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1652 ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr); 1653 1654 ierr = MatCreate(comm, &j22);CHKERRQ(ierr); 1655 ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1656 ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr); 1657 1658 bA[0][0] = j11; 1659 bA[0][1] = j12; 1660 bA[1][0] = j21; 1661 bA[1][1] = j22; 1662 1663 ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr); 1664 ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr); 1665 1666 ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr); 1667 ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr); 1668 ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr); 1669 ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr); 1670 1671 ierr = MatSetUp(j11);CHKERRQ(ierr); 1672 ierr = MatSetUp(j12);CHKERRQ(ierr); 1673 ierr = MatSetUp(j21);CHKERRQ(ierr); 1674 ierr = MatSetUp(j22);CHKERRQ(ierr); 1675 1676 ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr); 1677 ierr = MatSetUp(*J);CHKERRQ(ierr); 1678 ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr); 1679 ierr = MatDestroy(&j11);CHKERRQ(ierr); 1680 ierr = MatDestroy(&j12);CHKERRQ(ierr); 1681 ierr = MatDestroy(&j21);CHKERRQ(ierr); 1682 ierr = MatDestroy(&j22);CHKERRQ(ierr); 1683 1684 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1685 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1686 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1687 1688 /* Free structures */ 1689 ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr); 1690 ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr); 1691 PetscFunctionReturn(0); 1692 } 1693 1694 PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J) 1695 { 1696 PetscErrorCode ierr; 1697 DM_Network *network = (DM_Network*)dm->data; 1698 PetscInt eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize; 1699 PetscInt cstart,ncols,j,e,v; 1700 PetscBool ghost,ghost_vc,ghost2,isNest; 1701 Mat Juser; 1702 PetscSection sectionGlobal; 1703 PetscInt nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */ 1704 const PetscInt *edges,*cone; 1705 MPI_Comm comm; 1706 MatType mtype; 1707 Vec vd_nz,vo_nz; 1708 PetscInt *dnnz,*onnz; 1709 PetscScalar *vdnz,*vonz; 1710 1711 PetscFunctionBegin; 1712 mtype = dm->mattype; 1713 ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr); 1714 if (isNest) { 1715 ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr); 1716 PetscFunctionReturn(0); 1717 } 1718 1719 if (!network->userEdgeJacobian && !network->userVertexJacobian) { 1720 /* user does not provide Jacobian blocks */ 1721 ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr); 1722 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1723 PetscFunctionReturn(0); 1724 } 1725 1726 ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr); 1727 ierr = DMGetGlobalSection(network->plex,§ionGlobal);CHKERRQ(ierr); 1728 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr); 1729 ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 1730 1731 ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr); 1732 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1733 1734 /* (1) Set matrix preallocation */ 1735 /*------------------------------*/ 1736 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1737 ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr); 1738 ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr); 1739 ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr); 1740 ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr); 1741 ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr); 1742 1743 /* Set preallocation for edges */ 1744 /*-----------------------------*/ 1745 ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr); 1746 1747 ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr); 1748 for (e=eStart; e<eEnd; e++) { 1749 /* Get row indices */ 1750 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1751 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1752 if (nrows) { 1753 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1754 1755 /* Set preallocation for conntected vertices */ 1756 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1757 for (v=0; v<2; v++) { 1758 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1759 1760 if (network->Je) { 1761 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1762 } else Juser = NULL; 1763 ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr); 1764 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1765 } 1766 1767 /* Set preallocation for edge self */ 1768 cstart = rstart; 1769 if (network->Je) { 1770 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1771 } else Juser = NULL; 1772 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1773 } 1774 } 1775 1776 /* Set preallocation for vertices */ 1777 /*--------------------------------*/ 1778 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1779 if (vEnd - vStart) vptr = network->Jvptr; 1780 1781 for (v=vStart; v<vEnd; v++) { 1782 /* Get row indices */ 1783 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1784 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1785 if (!nrows) continue; 1786 1787 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1788 if (ghost) { 1789 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1790 } else { 1791 rows_v = rows; 1792 } 1793 1794 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1795 1796 /* Get supporting edges and connected vertices */ 1797 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1798 1799 for (e=0; e<nedges; e++) { 1800 /* Supporting edges */ 1801 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1802 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1803 1804 if (network->Jv) { 1805 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1806 } else Juser = NULL; 1807 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1808 1809 /* Connected vertices */ 1810 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1811 vc = (v == cone[0]) ? cone[1]:cone[0]; 1812 ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr); 1813 1814 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1815 1816 if (network->Jv) { 1817 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1818 } else Juser = NULL; 1819 if (ghost_vc||ghost) { 1820 ghost2 = PETSC_TRUE; 1821 } else { 1822 ghost2 = PETSC_FALSE; 1823 } 1824 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr); 1825 } 1826 1827 /* Set preallocation for vertex self */ 1828 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1829 if (!ghost) { 1830 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1831 if (network->Jv) { 1832 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1833 } else Juser = NULL; 1834 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1835 } 1836 if (ghost) { 1837 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1838 } 1839 } 1840 1841 ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr); 1842 ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr); 1843 1844 ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr); 1845 1846 ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr); 1847 ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr); 1848 1849 ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr); 1850 ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr); 1851 for (j=0; j<localSize; j++) { 1852 dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]); 1853 onnz[j] = (PetscInt)PetscRealPart(vonz[j]); 1854 } 1855 ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr); 1856 ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr); 1857 ierr = VecDestroy(&vd_nz);CHKERRQ(ierr); 1858 ierr = VecDestroy(&vo_nz);CHKERRQ(ierr); 1859 1860 ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr); 1861 ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr); 1862 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1863 1864 ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 1865 1866 /* (2) Set matrix entries for edges */ 1867 /*----------------------------------*/ 1868 for (e=eStart; e<eEnd; e++) { 1869 /* Get row indices */ 1870 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1871 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1872 if (nrows) { 1873 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1874 1875 /* Set matrix entries for conntected vertices */ 1876 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1877 for (v=0; v<2; v++) { 1878 ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr); 1879 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1880 1881 if (network->Je) { 1882 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1883 } else Juser = NULL; 1884 ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1885 } 1886 1887 /* Set matrix entries for edge self */ 1888 cstart = rstart; 1889 if (network->Je) { 1890 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1891 } else Juser = NULL; 1892 ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr); 1893 } 1894 } 1895 1896 /* Set matrix entries for vertices */ 1897 /*---------------------------------*/ 1898 for (v=vStart; v<vEnd; v++) { 1899 /* Get row indices */ 1900 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1901 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1902 if (!nrows) continue; 1903 1904 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1905 if (ghost) { 1906 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1907 } else { 1908 rows_v = rows; 1909 } 1910 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1911 1912 /* Get supporting edges and connected vertices */ 1913 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1914 1915 for (e=0; e<nedges; e++) { 1916 /* Supporting edges */ 1917 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1918 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1919 1920 if (network->Jv) { 1921 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1922 } else Juser = NULL; 1923 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1924 1925 /* Connected vertices */ 1926 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1927 vc = (v == cone[0]) ? cone[1]:cone[0]; 1928 1929 ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr); 1930 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1931 1932 if (network->Jv) { 1933 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1934 } else Juser = NULL; 1935 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1936 } 1937 1938 /* Set matrix entries for vertex self */ 1939 if (!ghost) { 1940 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1941 if (network->Jv) { 1942 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1943 } else Juser = NULL; 1944 ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr); 1945 } 1946 if (ghost) { 1947 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1948 } 1949 } 1950 ierr = PetscFree(rows);CHKERRQ(ierr); 1951 1952 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1953 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1954 1955 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1956 PetscFunctionReturn(0); 1957 } 1958 1959 PetscErrorCode DMDestroy_Network(DM dm) 1960 { 1961 PetscErrorCode ierr; 1962 DM_Network *network = (DM_Network*)dm->data; 1963 PetscInt j; 1964 1965 PetscFunctionBegin; 1966 if (--network->refct > 0) PetscFunctionReturn(0); 1967 if (network->Je) { 1968 ierr = PetscFree(network->Je);CHKERRQ(ierr); 1969 } 1970 if (network->Jv) { 1971 ierr = PetscFree(network->Jvptr);CHKERRQ(ierr); 1972 ierr = PetscFree(network->Jv);CHKERRQ(ierr); 1973 } 1974 1975 ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr); 1976 ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr); 1977 ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr); 1978 if (network->vltog) { 1979 ierr = PetscFree(network->vltog);CHKERRQ(ierr); 1980 } 1981 if (network->vertex.sf) { 1982 ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr); 1983 } 1984 /* edge */ 1985 ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr); 1986 ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr); 1987 ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr); 1988 if (network->edge.sf) { 1989 ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr); 1990 } 1991 ierr = DMDestroy(&network->plex);CHKERRQ(ierr); 1992 ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr); 1993 ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr); 1994 1995 for(j=0; j<network->nsubnet; j++) { 1996 ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr); 1997 } 1998 ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr); 1999 2000 ierr = PetscFree(network->subnet);CHKERRQ(ierr); 2001 ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr); 2002 ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr); 2003 ierr = PetscFree(network);CHKERRQ(ierr); 2004 PetscFunctionReturn(0); 2005 } 2006 2007 PetscErrorCode DMView_Network(DM dm,PetscViewer viewer) 2008 { 2009 PetscErrorCode ierr; 2010 DM_Network *network = (DM_Network*)dm->data; 2011 PetscBool iascii; 2012 PetscMPIInt rank; 2013 PetscInt p,nsubnet; 2014 2015 PetscFunctionBegin; 2016 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first"); 2017 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr); 2018 PetscValidHeaderSpecific(dm,DM_CLASSID, 1); 2019 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2020 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 2021 if (iascii) { 2022 const PetscInt *cone,*vtx,*edges; 2023 PetscInt vfrom,vto,i,j,nv,ne; 2024 2025 nsubnet = network->nsubnet - network->ncsubnet; /* num of subnetworks */ 2026 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 2027 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " [%d] nsubnet: %D; nsubnetCouple: %D; nEdges: %D; nVertices: %D\n",rank,nsubnet,network->ncsubnet,network->nEdges,network->nVertices);CHKERRQ(ierr); 2028 2029 for (i=0; i<nsubnet; i++) { 2030 ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr); 2031 if (ne) { 2032 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " Subnet %D: nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr); 2033 for (j=0; j<ne; j++) { 2034 p = edges[j]; 2035 ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr); 2036 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr); 2037 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr); 2038 ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr); 2039 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr); 2040 } 2041 } 2042 } 2043 /* Coupling subnets */ 2044 nsubnet = network->nsubnet; 2045 for (; i<nsubnet; i++) { 2046 ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr); 2047 if (ne) { 2048 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " Subnet %D (couple): nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr); 2049 for (j=0; j<ne; j++) { 2050 p = edges[j]; 2051 ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr); 2052 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr); 2053 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr); 2054 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr); 2055 } 2056 } 2057 } 2058 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 2059 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 2060 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name); 2061 PetscFunctionReturn(0); 2062 } 2063 2064 PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l) 2065 { 2066 PetscErrorCode ierr; 2067 DM_Network *network = (DM_Network*)dm->data; 2068 2069 PetscFunctionBegin; 2070 ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr); 2071 PetscFunctionReturn(0); 2072 } 2073 2074 PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l) 2075 { 2076 PetscErrorCode ierr; 2077 DM_Network *network = (DM_Network*)dm->data; 2078 2079 PetscFunctionBegin; 2080 ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr); 2081 PetscFunctionReturn(0); 2082 } 2083 2084 PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g) 2085 { 2086 PetscErrorCode ierr; 2087 DM_Network *network = (DM_Network*)dm->data; 2088 2089 PetscFunctionBegin; 2090 ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr); 2091 PetscFunctionReturn(0); 2092 } 2093 2094 PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g) 2095 { 2096 PetscErrorCode ierr; 2097 DM_Network *network = (DM_Network*)dm->data; 2098 2099 PetscFunctionBegin; 2100 ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr); 2101 PetscFunctionReturn(0); 2102 } 2103 2104 /*@ 2105 DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to globle map 2106 2107 Not collective 2108 2109 Input Parameters 2110 + dm - the dm object 2111 - vloc - local vertex ordering, start from 0 2112 2113 Output Parameters 2114 + vg - global vertex ordering, start from 0 2115 2116 Level: Advanced 2117 2118 .seealso: DMNetworkSetVertexLocalToGlobalOrdering() 2119 @*/ 2120 PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg) 2121 { 2122 DM_Network *network = (DM_Network*)dm->data; 2123 PetscInt *vltog = network->vltog; 2124 2125 PetscFunctionBegin; 2126 if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first"); 2127 *vg = vltog[vloc]; 2128 PetscFunctionReturn(0); 2129 } 2130 2131 /*@ 2132 DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to globle map 2133 2134 Collective 2135 2136 Input Parameters: 2137 + dm - the dm object 2138 2139 Level: Advanced 2140 2141 .seealso: DMNetworkCreate() 2142 @*/ 2143 PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm) 2144 { 2145 PetscErrorCode ierr; 2146 DM_Network *network=(DM_Network*)dm->data; 2147 MPI_Comm comm; 2148 PetscMPIInt rank,size,*displs,*recvcounts; 2149 PetscBool ghost; 2150 PetscInt *vltog,nroots,nleaves,i,*vrange,k=0,kg=0; 2151 const PetscSFNode *iremote; 2152 PetscSF vsf; 2153 2154 PetscFunctionBegin; 2155 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2156 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 2157 2158 if (size == 1) { 2159 nroots = network->vEnd - network->vStart; 2160 ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr); 2161 for (i=0; i<nroots; i++) vltog[i] = i; 2162 network->vltog = vltog; 2163 PetscFunctionReturn(0); 2164 } 2165 2166 if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first"); 2167 if (network->vltog) { 2168 ierr = PetscFree(network->vltog);CHKERRQ(ierr); 2169 } 2170 2171 ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr); 2172 ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr); 2173 vsf = network->vertex.sf; 2174 2175 ierr = PetscMalloc3(size+1,&vrange,size+1,&displs,size,&recvcounts);CHKERRQ(ierr); 2176 ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr); 2177 2178 for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;} 2179 2180 i = nroots - nleaves; /* local number of vertices, excluding ghosts */ 2181 vrange[0] = 0; 2182 ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRQ(ierr); 2183 for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];} 2184 2185 ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr); 2186 network->vltog = vltog; 2187 2188 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2189 for (i=0; i<nroots; i++) { 2190 ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr); 2191 if (!ghost) { 2192 vltog[i] = vrange[rank] + k; k++; 2193 } else { 2194 vltog[i] = vrange[iremote[kg].rank] + iremote[kg].index; kg++; 2195 } 2196 } 2197 ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr); 2198 PetscFunctionReturn(0); 2199 } 2200