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].vStart + network->subnet[i].edgelist[2*j]; 204 edges[2*ctr+1] = network->subnet[i].vStart + 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->localSection,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->globalSection,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 PetscErrorCode DMNetworkAssembleGraphStructures(DM dm) 1033 { 1034 PetscErrorCode ierr; 1035 MPI_Comm comm; 1036 PetscMPIInt rank, size; 1037 DM_Network *network = (DM_Network*)dm->data; 1038 1039 PetscFunctionBegin; 1040 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1041 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1042 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1043 1044 /* Create maps for vertices and edges */ 1045 ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr); 1046 ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr); 1047 1048 /* Create local sub-sections */ 1049 ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr); 1050 ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr); 1051 1052 if (size > 1) { 1053 ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr); 1054 1055 ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr); 1056 ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr); 1057 ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr); 1058 } else { 1059 /* create structures for vertex */ 1060 ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr); 1061 /* create structures for edge */ 1062 ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr); 1063 } 1064 1065 /* Add viewers */ 1066 ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr); 1067 ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr); 1068 ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr); 1069 ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr); 1070 PetscFunctionReturn(0); 1071 } 1072 1073 /*@ 1074 DMNetworkDistribute - Distributes the network and moves associated component data. 1075 1076 Collective 1077 1078 Input Parameter: 1079 + DM - the DMNetwork object 1080 - overlap - The overlap of partitions, 0 is the default 1081 1082 Notes: 1083 Distributes the network with <overlap>-overlapping partitioning of the edges. 1084 1085 Level: intermediate 1086 1087 .seealso: DMNetworkCreate 1088 @*/ 1089 PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap) 1090 { 1091 MPI_Comm comm; 1092 PetscErrorCode ierr; 1093 PetscMPIInt size; 1094 DM_Network *oldDMnetwork = (DM_Network*)((*dm)->data); 1095 DM_Network *newDMnetwork; 1096 PetscSF pointsf=NULL; 1097 DM newDM; 1098 PetscInt j,e,v,offset,*subnetvtx; 1099 PetscPartitioner part; 1100 DMNetworkComponentHeader header; 1101 1102 PetscFunctionBegin; 1103 ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr); 1104 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1105 if (size == 1) PetscFunctionReturn(0); 1106 1107 ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr); 1108 newDMnetwork = (DM_Network*)newDM->data; 1109 newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType); 1110 1111 /* Enable runtime options for petscpartitioner */ 1112 ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr); 1113 ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); 1114 1115 /* Distribute plex dm and dof section */ 1116 ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr); 1117 1118 /* Distribute dof section */ 1119 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DofSection);CHKERRQ(ierr); 1120 ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr); 1121 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DataSection);CHKERRQ(ierr); 1122 1123 /* Distribute data and associated section */ 1124 ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr); 1125 1126 ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr); 1127 ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr); 1128 ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr); 1129 newDMnetwork->nEdges = newDMnetwork->eEnd - newDMnetwork->eStart; 1130 newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart; 1131 newDMnetwork->NVertices = oldDMnetwork->NVertices; 1132 newDMnetwork->NEdges = oldDMnetwork->NEdges; 1133 1134 /* Set Dof section as the section for dm */ 1135 ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr); 1136 ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr); 1137 1138 /* Set up subnetwork info in the newDM */ 1139 newDMnetwork->nsubnet = oldDMnetwork->nsubnet; 1140 newDMnetwork->ncsubnet = oldDMnetwork->ncsubnet; 1141 ierr = PetscCalloc1(newDMnetwork->nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr); 1142 /* Copy over the global number of vertices and edges in each subnetwork. Note that these are already 1143 calculated in DMNetworkLayoutSetUp() 1144 */ 1145 for(j=0; j < newDMnetwork->nsubnet; j++) { 1146 newDMnetwork->subnet[j].Nvtx = oldDMnetwork->subnet[j].Nvtx; 1147 newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge; 1148 } 1149 1150 for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) { 1151 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr); 1152 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1153 newDMnetwork->subnet[header->subnetid].nedge++; 1154 } 1155 1156 for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) { 1157 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr); 1158 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1159 newDMnetwork->subnet[header->subnetid].nvtx++; 1160 } 1161 1162 /* Now create the vertices and edge arrays for the subnetworks */ 1163 ierr = PetscCalloc1(newDMnetwork->vEnd-newDMnetwork->vStart,&newDMnetwork->subnetvtx);CHKERRQ(ierr); 1164 subnetvtx = newDMnetwork->subnetvtx; 1165 1166 for (j=0; j<newDMnetwork->nsubnet; j++) { 1167 ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr); 1168 newDMnetwork->subnet[j].vertices = subnetvtx; 1169 subnetvtx += newDMnetwork->subnet[j].nvtx; 1170 1171 /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop. 1172 These get updated when the vertices and edges are added. */ 1173 newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0; 1174 } 1175 1176 /* Set the vertices and edges in each subnetwork */ 1177 for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) { 1178 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr); 1179 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1180 newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e; 1181 } 1182 1183 for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) { 1184 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr); 1185 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1186 newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v; 1187 } 1188 1189 newDM->setupcalled = (*dm)->setupcalled; 1190 newDMnetwork->distributecalled = PETSC_TRUE; 1191 1192 /* Destroy point SF */ 1193 ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr); 1194 1195 ierr = DMDestroy(dm);CHKERRQ(ierr); 1196 *dm = newDM; 1197 PetscFunctionReturn(0); 1198 } 1199 1200 /*@C 1201 PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering. 1202 1203 Input Parameters: 1204 + masterSF - the original SF structure 1205 - map - a ISLocalToGlobal mapping that contains the subset of points 1206 1207 Output Parameters: 1208 . subSF - a subset of the masterSF for the desired subset. 1209 */ 1210 1211 PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) { 1212 1213 PetscErrorCode ierr; 1214 PetscInt nroots, nleaves, *ilocal_sub; 1215 PetscInt i, *ilocal_map, nroots_sub, nleaves_sub = 0; 1216 PetscInt *local_points, *remote_points; 1217 PetscSFNode *iremote_sub; 1218 const PetscInt *ilocal; 1219 const PetscSFNode *iremote; 1220 1221 PetscFunctionBegin; 1222 ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); 1223 1224 /* Look for leaves that pertain to the subset of points. Get the local ordering */ 1225 ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr); 1226 ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr); 1227 for (i = 0; i < nleaves; i++) { 1228 if (ilocal_map[i] != -1) nleaves_sub += 1; 1229 } 1230 /* Re-number ilocal with subset numbering. Need information from roots */ 1231 ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr); 1232 for (i = 0; i < nroots; i++) local_points[i] = i; 1233 ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr); 1234 ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr); 1235 ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr); 1236 /* Fill up graph using local (that is, local to the subset) numbering. */ 1237 ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr); 1238 ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr); 1239 nleaves_sub = 0; 1240 for (i = 0; i < nleaves; i++) { 1241 if (ilocal_map[i] != -1) { 1242 ilocal_sub[nleaves_sub] = ilocal_map[i]; 1243 iremote_sub[nleaves_sub].rank = iremote[i].rank; 1244 iremote_sub[nleaves_sub].index = remote_points[ilocal[i]]; 1245 nleaves_sub += 1; 1246 } 1247 } 1248 ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr); 1249 ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr); 1250 1251 /* Create new subSF */ 1252 ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr); 1253 ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr); 1254 ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr); 1255 ierr = PetscFree(ilocal_map);CHKERRQ(ierr); 1256 ierr = PetscFree(iremote_sub);CHKERRQ(ierr); 1257 PetscFunctionReturn(0); 1258 } 1259 1260 /*@C 1261 DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point 1262 1263 Not Collective 1264 1265 Input Parameters: 1266 + dm - The DMNetwork object 1267 - p - the vertex point 1268 1269 Output Paramters: 1270 + nedges - number of edges connected to this vertex point 1271 - edges - List of edge points 1272 1273 Level: intermediate 1274 1275 Fortran Notes: 1276 Since it returns an array, this routine is only available in Fortran 90, and you must 1277 include petsc.h90 in your code. 1278 1279 .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices 1280 @*/ 1281 PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[]) 1282 { 1283 PetscErrorCode ierr; 1284 DM_Network *network = (DM_Network*)dm->data; 1285 1286 PetscFunctionBegin; 1287 ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr); 1288 ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr); 1289 PetscFunctionReturn(0); 1290 } 1291 1292 /*@C 1293 DMNetworkGetConnectedVertices - Return the connected vertices for this edge point 1294 1295 Not Collective 1296 1297 Input Parameters: 1298 + dm - The DMNetwork object 1299 - p - the edge point 1300 1301 Output Paramters: 1302 . vertices - vertices connected to this edge 1303 1304 Level: intermediate 1305 1306 Fortran Notes: 1307 Since it returns an array, this routine is only available in Fortran 90, and you must 1308 include petsc.h90 in your code. 1309 1310 .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges 1311 @*/ 1312 PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[]) 1313 { 1314 PetscErrorCode ierr; 1315 DM_Network *network = (DM_Network*)dm->data; 1316 1317 PetscFunctionBegin; 1318 ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr); 1319 PetscFunctionReturn(0); 1320 } 1321 1322 /*@ 1323 DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex 1324 1325 Not Collective 1326 1327 Input Parameters: 1328 + dm - The DMNetwork object 1329 - p - the vertex point 1330 1331 Output Parameter: 1332 . isghost - TRUE if the vertex is a ghost point 1333 1334 Level: intermediate 1335 1336 .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange 1337 @*/ 1338 PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost) 1339 { 1340 PetscErrorCode ierr; 1341 DM_Network *network = (DM_Network*)dm->data; 1342 PetscInt offsetg; 1343 PetscSection sectiong; 1344 1345 PetscFunctionBegin; 1346 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first"); 1347 *isghost = PETSC_FALSE; 1348 ierr = DMGetGlobalSection(network->plex,§iong);CHKERRQ(ierr); 1349 ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr); 1350 if (offsetg < 0) *isghost = PETSC_TRUE; 1351 PetscFunctionReturn(0); 1352 } 1353 1354 PetscErrorCode DMSetUp_Network(DM dm) 1355 { 1356 PetscErrorCode ierr; 1357 DM_Network *network=(DM_Network*)dm->data; 1358 1359 PetscFunctionBegin; 1360 ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr); 1361 ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr); 1362 1363 ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr); 1364 ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr); 1365 1366 dm->setupcalled = PETSC_TRUE; 1367 ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr); 1368 PetscFunctionReturn(0); 1369 } 1370 1371 /*@ 1372 DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices 1373 -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)? 1374 1375 Collective 1376 1377 Input Parameters: 1378 + dm - The DMNetwork object 1379 . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges 1380 - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices 1381 1382 Level: intermediate 1383 1384 @*/ 1385 PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg) 1386 { 1387 DM_Network *network=(DM_Network*)dm->data; 1388 PetscErrorCode ierr; 1389 PetscInt nVertices = network->nVertices; 1390 1391 PetscFunctionBegin; 1392 network->userEdgeJacobian = eflg; 1393 network->userVertexJacobian = vflg; 1394 1395 if (eflg && !network->Je) { 1396 ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr); 1397 } 1398 1399 if (vflg && !network->Jv && nVertices) { 1400 PetscInt i,*vptr,nedges,vStart=network->vStart; 1401 PetscInt nedges_total; 1402 const PetscInt *edges; 1403 1404 /* count nvertex_total */ 1405 nedges_total = 0; 1406 ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr); 1407 1408 vptr[0] = 0; 1409 for (i=0; i<nVertices; i++) { 1410 ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr); 1411 nedges_total += nedges; 1412 vptr[i+1] = vptr[i] + 2*nedges + 1; 1413 } 1414 1415 ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr); 1416 network->Jvptr = vptr; 1417 } 1418 PetscFunctionReturn(0); 1419 } 1420 1421 /*@ 1422 DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network 1423 1424 Not Collective 1425 1426 Input Parameters: 1427 + dm - The DMNetwork object 1428 . p - the edge point 1429 - J - array (size = 3) of Jacobian submatrices for this edge point: 1430 J[0]: this edge 1431 J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices() 1432 1433 Level: intermediate 1434 1435 .seealso: DMNetworkVertexSetMatrix 1436 @*/ 1437 PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[]) 1438 { 1439 DM_Network *network=(DM_Network*)dm->data; 1440 1441 PetscFunctionBegin; 1442 if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix"); 1443 1444 if (J) { 1445 network->Je[3*p] = J[0]; 1446 network->Je[3*p+1] = J[1]; 1447 network->Je[3*p+2] = J[2]; 1448 } 1449 PetscFunctionReturn(0); 1450 } 1451 1452 /*@ 1453 DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network 1454 1455 Not Collective 1456 1457 Input Parameters: 1458 + dm - The DMNetwork object 1459 . p - the vertex point 1460 - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point: 1461 J[0]: this vertex 1462 J[1+2*i]: i-th supporting edge 1463 J[1+2*i+1]: i-th connected vertex 1464 1465 Level: intermediate 1466 1467 .seealso: DMNetworkEdgeSetMatrix 1468 @*/ 1469 PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[]) 1470 { 1471 PetscErrorCode ierr; 1472 DM_Network *network=(DM_Network*)dm->data; 1473 PetscInt i,*vptr,nedges,vStart=network->vStart; 1474 const PetscInt *edges; 1475 1476 PetscFunctionBegin; 1477 if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix"); 1478 1479 if (J) { 1480 vptr = network->Jvptr; 1481 network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */ 1482 1483 /* Set Jacobian for each supporting edge and connected vertex */ 1484 ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr); 1485 for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i]; 1486 } 1487 PetscFunctionReturn(0); 1488 } 1489 1490 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1491 { 1492 PetscErrorCode ierr; 1493 PetscInt j; 1494 PetscScalar val=(PetscScalar)ncols; 1495 1496 PetscFunctionBegin; 1497 if (!ghost) { 1498 for (j=0; j<nrows; j++) { 1499 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1500 } 1501 } else { 1502 for (j=0; j<nrows; j++) { 1503 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1504 } 1505 } 1506 PetscFunctionReturn(0); 1507 } 1508 1509 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1510 { 1511 PetscErrorCode ierr; 1512 PetscInt j,ncols_u; 1513 PetscScalar val; 1514 1515 PetscFunctionBegin; 1516 if (!ghost) { 1517 for (j=0; j<nrows; j++) { 1518 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1519 val = (PetscScalar)ncols_u; 1520 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1521 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1522 } 1523 } else { 1524 for (j=0; j<nrows; j++) { 1525 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1526 val = (PetscScalar)ncols_u; 1527 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1528 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1529 } 1530 } 1531 PetscFunctionReturn(0); 1532 } 1533 1534 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1535 { 1536 PetscErrorCode ierr; 1537 1538 PetscFunctionBegin; 1539 if (Ju) { 1540 ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1541 } else { 1542 ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1543 } 1544 PetscFunctionReturn(0); 1545 } 1546 1547 PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1548 { 1549 PetscErrorCode ierr; 1550 PetscInt j,*cols; 1551 PetscScalar *zeros; 1552 1553 PetscFunctionBegin; 1554 ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr); 1555 for (j=0; j<ncols; j++) cols[j] = j+ cstart; 1556 ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr); 1557 ierr = PetscFree2(cols,zeros);CHKERRQ(ierr); 1558 PetscFunctionReturn(0); 1559 } 1560 1561 PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1562 { 1563 PetscErrorCode ierr; 1564 PetscInt j,M,N,row,col,ncols_u; 1565 const PetscInt *cols; 1566 PetscScalar zero=0.0; 1567 1568 PetscFunctionBegin; 1569 ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr); 1570 if (nrows != M || ncols != N) SETERRQ4(PetscObjectComm((PetscObject)Ju),PETSC_ERR_USER,"%D by %D must equal %D by %D",nrows,ncols,M,N); 1571 1572 for (row=0; row<nrows; row++) { 1573 ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1574 for (j=0; j<ncols_u; j++) { 1575 col = cols[j] + cstart; 1576 ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr); 1577 } 1578 ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1579 } 1580 PetscFunctionReturn(0); 1581 } 1582 1583 PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1584 { 1585 PetscErrorCode ierr; 1586 1587 PetscFunctionBegin; 1588 if (Ju) { 1589 ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1590 } else { 1591 ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1592 } 1593 PetscFunctionReturn(0); 1594 } 1595 1596 /* 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. 1597 */ 1598 PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog) 1599 { 1600 PetscErrorCode ierr; 1601 PetscInt i,size,dof; 1602 PetscInt *glob2loc; 1603 1604 PetscFunctionBegin; 1605 ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr); 1606 ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr); 1607 1608 for (i = 0; i < size; i++) { 1609 ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr); 1610 dof = (dof >= 0) ? dof : -(dof + 1); 1611 glob2loc[i] = dof; 1612 } 1613 1614 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 1615 #if 0 1616 ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1617 #endif 1618 PetscFunctionReturn(0); 1619 } 1620 1621 #include <petsc/private/matimpl.h> 1622 1623 PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J) 1624 { 1625 PetscErrorCode ierr; 1626 DM_Network *network = (DM_Network*)dm->data; 1627 PetscMPIInt rank, size; 1628 PetscInt eDof,vDof; 1629 Mat j11,j12,j21,j22,bA[2][2]; 1630 MPI_Comm comm; 1631 ISLocalToGlobalMapping eISMap,vISMap; 1632 1633 PetscFunctionBegin; 1634 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1635 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1636 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1637 1638 ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr); 1639 ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr); 1640 1641 ierr = MatCreate(comm, &j11);CHKERRQ(ierr); 1642 ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1643 ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr); 1644 1645 ierr = MatCreate(comm, &j12);CHKERRQ(ierr); 1646 ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr); 1647 ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr); 1648 1649 ierr = MatCreate(comm, &j21);CHKERRQ(ierr); 1650 ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1651 ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr); 1652 1653 ierr = MatCreate(comm, &j22);CHKERRQ(ierr); 1654 ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1655 ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr); 1656 1657 bA[0][0] = j11; 1658 bA[0][1] = j12; 1659 bA[1][0] = j21; 1660 bA[1][1] = j22; 1661 1662 ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr); 1663 ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr); 1664 1665 ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr); 1666 ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr); 1667 ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr); 1668 ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr); 1669 1670 ierr = MatSetUp(j11);CHKERRQ(ierr); 1671 ierr = MatSetUp(j12);CHKERRQ(ierr); 1672 ierr = MatSetUp(j21);CHKERRQ(ierr); 1673 ierr = MatSetUp(j22);CHKERRQ(ierr); 1674 1675 ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr); 1676 ierr = MatSetUp(*J);CHKERRQ(ierr); 1677 ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr); 1678 ierr = MatDestroy(&j11);CHKERRQ(ierr); 1679 ierr = MatDestroy(&j12);CHKERRQ(ierr); 1680 ierr = MatDestroy(&j21);CHKERRQ(ierr); 1681 ierr = MatDestroy(&j22);CHKERRQ(ierr); 1682 1683 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1684 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1685 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1686 1687 /* Free structures */ 1688 ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr); 1689 ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr); 1690 PetscFunctionReturn(0); 1691 } 1692 1693 PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J) 1694 { 1695 PetscErrorCode ierr; 1696 DM_Network *network = (DM_Network*)dm->data; 1697 PetscInt eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize; 1698 PetscInt cstart,ncols,j,e,v; 1699 PetscBool ghost,ghost_vc,ghost2,isNest; 1700 Mat Juser; 1701 PetscSection sectionGlobal; 1702 PetscInt nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */ 1703 const PetscInt *edges,*cone; 1704 MPI_Comm comm; 1705 MatType mtype; 1706 Vec vd_nz,vo_nz; 1707 PetscInt *dnnz,*onnz; 1708 PetscScalar *vdnz,*vonz; 1709 1710 PetscFunctionBegin; 1711 mtype = dm->mattype; 1712 ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr); 1713 if (isNest) { 1714 ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr); 1715 PetscFunctionReturn(0); 1716 } 1717 1718 if (!network->userEdgeJacobian && !network->userVertexJacobian) { 1719 /* user does not provide Jacobian blocks */ 1720 ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr); 1721 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1722 PetscFunctionReturn(0); 1723 } 1724 1725 ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr); 1726 ierr = DMGetGlobalSection(network->plex,§ionGlobal);CHKERRQ(ierr); 1727 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr); 1728 ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 1729 1730 ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr); 1731 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1732 1733 /* (1) Set matrix preallocation */ 1734 /*------------------------------*/ 1735 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1736 ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr); 1737 ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr); 1738 ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr); 1739 ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr); 1740 ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr); 1741 1742 /* Set preallocation for edges */ 1743 /*-----------------------------*/ 1744 ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr); 1745 1746 ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr); 1747 for (e=eStart; e<eEnd; e++) { 1748 /* Get row indices */ 1749 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1750 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1751 if (nrows) { 1752 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1753 1754 /* Set preallocation for conntected vertices */ 1755 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1756 for (v=0; v<2; v++) { 1757 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1758 1759 if (network->Je) { 1760 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1761 } else Juser = NULL; 1762 ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr); 1763 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1764 } 1765 1766 /* Set preallocation for edge self */ 1767 cstart = rstart; 1768 if (network->Je) { 1769 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1770 } else Juser = NULL; 1771 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1772 } 1773 } 1774 1775 /* Set preallocation for vertices */ 1776 /*--------------------------------*/ 1777 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1778 if (vEnd - vStart) vptr = network->Jvptr; 1779 1780 for (v=vStart; v<vEnd; v++) { 1781 /* Get row indices */ 1782 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1783 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1784 if (!nrows) continue; 1785 1786 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1787 if (ghost) { 1788 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1789 } else { 1790 rows_v = rows; 1791 } 1792 1793 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1794 1795 /* Get supporting edges and connected vertices */ 1796 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1797 1798 for (e=0; e<nedges; e++) { 1799 /* Supporting edges */ 1800 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1801 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1802 1803 if (network->Jv) { 1804 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1805 } else Juser = NULL; 1806 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1807 1808 /* Connected vertices */ 1809 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1810 vc = (v == cone[0]) ? cone[1]:cone[0]; 1811 ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr); 1812 1813 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1814 1815 if (network->Jv) { 1816 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1817 } else Juser = NULL; 1818 if (ghost_vc||ghost) { 1819 ghost2 = PETSC_TRUE; 1820 } else { 1821 ghost2 = PETSC_FALSE; 1822 } 1823 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr); 1824 } 1825 1826 /* Set preallocation for vertex self */ 1827 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1828 if (!ghost) { 1829 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1830 if (network->Jv) { 1831 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1832 } else Juser = NULL; 1833 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1834 } 1835 if (ghost) { 1836 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1837 } 1838 } 1839 1840 ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr); 1841 ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr); 1842 1843 ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr); 1844 1845 ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr); 1846 ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr); 1847 1848 ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr); 1849 ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr); 1850 for (j=0; j<localSize; j++) { 1851 dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]); 1852 onnz[j] = (PetscInt)PetscRealPart(vonz[j]); 1853 } 1854 ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr); 1855 ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr); 1856 ierr = VecDestroy(&vd_nz);CHKERRQ(ierr); 1857 ierr = VecDestroy(&vo_nz);CHKERRQ(ierr); 1858 1859 ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr); 1860 ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr); 1861 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1862 1863 ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 1864 1865 /* (2) Set matrix entries for edges */ 1866 /*----------------------------------*/ 1867 for (e=eStart; e<eEnd; e++) { 1868 /* Get row indices */ 1869 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1870 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1871 if (nrows) { 1872 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1873 1874 /* Set matrix entries for conntected vertices */ 1875 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1876 for (v=0; v<2; v++) { 1877 ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr); 1878 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1879 1880 if (network->Je) { 1881 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1882 } else Juser = NULL; 1883 ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1884 } 1885 1886 /* Set matrix entries for edge self */ 1887 cstart = rstart; 1888 if (network->Je) { 1889 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1890 } else Juser = NULL; 1891 ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr); 1892 } 1893 } 1894 1895 /* Set matrix entries for vertices */ 1896 /*---------------------------------*/ 1897 for (v=vStart; v<vEnd; v++) { 1898 /* Get row indices */ 1899 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1900 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1901 if (!nrows) continue; 1902 1903 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1904 if (ghost) { 1905 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1906 } else { 1907 rows_v = rows; 1908 } 1909 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1910 1911 /* Get supporting edges and connected vertices */ 1912 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1913 1914 for (e=0; e<nedges; e++) { 1915 /* Supporting edges */ 1916 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1917 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1918 1919 if (network->Jv) { 1920 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1921 } else Juser = NULL; 1922 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1923 1924 /* Connected vertices */ 1925 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1926 vc = (v == cone[0]) ? cone[1]:cone[0]; 1927 1928 ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr); 1929 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1930 1931 if (network->Jv) { 1932 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1933 } else Juser = NULL; 1934 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1935 } 1936 1937 /* Set matrix entries for vertex self */ 1938 if (!ghost) { 1939 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1940 if (network->Jv) { 1941 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1942 } else Juser = NULL; 1943 ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr); 1944 } 1945 if (ghost) { 1946 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1947 } 1948 } 1949 ierr = PetscFree(rows);CHKERRQ(ierr); 1950 1951 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1952 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1953 1954 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1955 PetscFunctionReturn(0); 1956 } 1957 1958 PetscErrorCode DMDestroy_Network(DM dm) 1959 { 1960 PetscErrorCode ierr; 1961 DM_Network *network = (DM_Network*)dm->data; 1962 PetscInt j; 1963 1964 PetscFunctionBegin; 1965 if (--network->refct > 0) PetscFunctionReturn(0); 1966 if (network->Je) { 1967 ierr = PetscFree(network->Je);CHKERRQ(ierr); 1968 } 1969 if (network->Jv) { 1970 ierr = PetscFree(network->Jvptr);CHKERRQ(ierr); 1971 ierr = PetscFree(network->Jv);CHKERRQ(ierr); 1972 } 1973 1974 ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr); 1975 ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr); 1976 ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr); 1977 if (network->vltog) { 1978 ierr = PetscFree(network->vltog);CHKERRQ(ierr); 1979 } 1980 if (network->vertex.sf) { 1981 ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr); 1982 } 1983 /* edge */ 1984 ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr); 1985 ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr); 1986 ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr); 1987 if (network->edge.sf) { 1988 ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr); 1989 } 1990 ierr = DMDestroy(&network->plex);CHKERRQ(ierr); 1991 ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr); 1992 ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr); 1993 1994 for(j=0; j<network->nsubnet; j++) { 1995 ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr); 1996 } 1997 ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr); 1998 1999 ierr = PetscFree(network->subnet);CHKERRQ(ierr); 2000 ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr); 2001 ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr); 2002 ierr = PetscFree(network);CHKERRQ(ierr); 2003 PetscFunctionReturn(0); 2004 } 2005 2006 PetscErrorCode DMView_Network(DM dm,PetscViewer viewer) 2007 { 2008 PetscErrorCode ierr; 2009 DM_Network *network = (DM_Network*)dm->data; 2010 PetscBool iascii; 2011 PetscMPIInt rank; 2012 PetscInt p,nsubnet; 2013 2014 PetscFunctionBegin; 2015 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first"); 2016 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr); 2017 PetscValidHeaderSpecific(dm,DM_CLASSID, 1); 2018 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2019 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 2020 if (iascii) { 2021 const PetscInt *cone,*vtx,*edges; 2022 PetscInt vfrom,vto,i,j,nv,ne; 2023 2024 nsubnet = network->nsubnet - network->ncsubnet; /* num of subnetworks */ 2025 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 2026 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " [%d] nsubnet: %D; nsubnetCouple: %D; nEdges: %D; nVertices: %D\n",rank,nsubnet,network->ncsubnet,network->nEdges,network->nVertices);CHKERRQ(ierr); 2027 2028 for (i=0; i<nsubnet; i++) { 2029 ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr); 2030 if (ne) { 2031 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " Subnet %D: nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr); 2032 for (j=0; j<ne; j++) { 2033 p = edges[j]; 2034 ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr); 2035 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr); 2036 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr); 2037 ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr); 2038 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr); 2039 } 2040 } 2041 } 2042 /* Coupling subnets */ 2043 nsubnet = network->nsubnet; 2044 for (; i<nsubnet; i++) { 2045 ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr); 2046 if (ne) { 2047 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " Subnet %D (couple): nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr); 2048 for (j=0; j<ne; j++) { 2049 p = edges[j]; 2050 ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr); 2051 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr); 2052 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr); 2053 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr); 2054 } 2055 } 2056 } 2057 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 2058 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 2059 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name); 2060 PetscFunctionReturn(0); 2061 } 2062 2063 PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l) 2064 { 2065 PetscErrorCode ierr; 2066 DM_Network *network = (DM_Network*)dm->data; 2067 2068 PetscFunctionBegin; 2069 ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr); 2070 PetscFunctionReturn(0); 2071 } 2072 2073 PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l) 2074 { 2075 PetscErrorCode ierr; 2076 DM_Network *network = (DM_Network*)dm->data; 2077 2078 PetscFunctionBegin; 2079 ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr); 2080 PetscFunctionReturn(0); 2081 } 2082 2083 PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g) 2084 { 2085 PetscErrorCode ierr; 2086 DM_Network *network = (DM_Network*)dm->data; 2087 2088 PetscFunctionBegin; 2089 ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr); 2090 PetscFunctionReturn(0); 2091 } 2092 2093 PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g) 2094 { 2095 PetscErrorCode ierr; 2096 DM_Network *network = (DM_Network*)dm->data; 2097 2098 PetscFunctionBegin; 2099 ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr); 2100 PetscFunctionReturn(0); 2101 } 2102 2103 /*@ 2104 DMNetworkGetVertexLocalToGlobalOrdering - Get vertex globle index 2105 2106 Not collective 2107 2108 Input Parameters 2109 + dm - the dm object 2110 - vloc - local vertex ordering, start from 0 2111 2112 Output Parameters 2113 + vg - global vertex ordering, start from 0 2114 2115 Level: Advanced 2116 2117 .seealso: DMNetworkSetVertexLocalToGlobalOrdering() 2118 @*/ 2119 PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg) 2120 { 2121 DM_Network *network = (DM_Network*)dm->data; 2122 PetscInt *vltog = network->vltog; 2123 2124 PetscFunctionBegin; 2125 if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first"); 2126 *vg = vltog[vloc]; 2127 PetscFunctionReturn(0); 2128 } 2129 2130 /*@ 2131 DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to globle map 2132 2133 Collective 2134 2135 Input Parameters: 2136 + dm - the dm object 2137 2138 Level: Advanced 2139 2140 .seealso: DMNetworkGetGlobalVertexIndex() 2141 @*/ 2142 PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm) 2143 { 2144 PetscErrorCode ierr; 2145 DM_Network *network=(DM_Network*)dm->data; 2146 MPI_Comm comm; 2147 PetscMPIInt rank,size,*displs,*recvcounts,remoterank; 2148 PetscBool ghost; 2149 PetscInt *vltog,nroots,nleaves,i,*vrange,k,N,lidx; 2150 const PetscSFNode *iremote; 2151 PetscSF vsf; 2152 Vec Vleaves,Vleaves_seq; 2153 VecScatter ctx; 2154 PetscScalar *varr,val; 2155 const PetscScalar *varr_read; 2156 2157 PetscFunctionBegin; 2158 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2159 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 2160 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 2161 2162 if (size == 1) { 2163 nroots = network->vEnd - network->vStart; 2164 ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr); 2165 for (i=0; i<nroots; i++) vltog[i] = i; 2166 network->vltog = vltog; 2167 PetscFunctionReturn(0); 2168 } 2169 2170 if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first"); 2171 if (network->vltog) { 2172 ierr = PetscFree(network->vltog);CHKERRQ(ierr); 2173 } 2174 2175 ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr); 2176 ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr); 2177 vsf = network->vertex.sf; 2178 2179 ierr = PetscMalloc3(size+1,&vrange,size+1,&displs,size,&recvcounts);CHKERRQ(ierr); 2180 ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr); 2181 2182 for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;} 2183 2184 i = nroots - nleaves; /* local number of vertices, excluding ghosts */ 2185 vrange[0] = 0; 2186 ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRQ(ierr); 2187 for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];} 2188 2189 ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr); 2190 network->vltog = vltog; 2191 2192 /* Set vltog for non-ghost vertices */ 2193 k = 0; 2194 for (i=0; i<nroots; i++) { 2195 ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr); 2196 if (ghost) continue; 2197 vltog[i] = vrange[rank] + k++; 2198 } 2199 ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr); 2200 2201 /* Set vltog for ghost vertices */ 2202 /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */ 2203 ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr); 2204 ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr); 2205 ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr); 2206 ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr); 2207 for (i=0; i<nleaves; i++) { 2208 varr[2*i] = (PetscScalar)(iremote[i].rank); /* rank of remote process */ 2209 varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */ 2210 } 2211 ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr); 2212 2213 /* (b) scatter local info to remote processes via VecScatter() */ 2214 ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr); 2215 ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2216 ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2217 2218 /* (c) convert local indices to global indices in parallel vector Vleaves */ 2219 ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr); 2220 ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr); 2221 for (i=0; i<N; i+=2) { 2222 remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]); 2223 if (remoterank == rank) { 2224 k = i+1; /* row number */ 2225 lidx = (PetscInt)PetscRealPart(varr_read[i+1]); 2226 val = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */ 2227 ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr); 2228 } 2229 } 2230 ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr); 2231 ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr); 2232 ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr); 2233 2234 /* (d) Set vltog for ghost vertices by copying local values of Vleaves */ 2235 ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr); 2236 k = 0; 2237 for (i=0; i<nroots; i++) { 2238 ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr); 2239 if (!ghost) continue; 2240 vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++; 2241 } 2242 ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr); 2243 2244 ierr = VecDestroy(&Vleaves);CHKERRQ(ierr); 2245 ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr); 2246 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 2247 PetscFunctionReturn(0); 2248 } 2249