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