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