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