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