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