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->nNodes >= 0 || network->NNodes >= 0) && (network->nNodes != nV || network->NNodes != 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->nNodes,network->NNodes); 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->nNodes = nV; 68 network->NNodes = 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->nNodes) { 130 ierr = PetscCalloc1(numCorners*network->nNodes,&vertexcoords);CHKERRQ(ierr); 131 } 132 ierr = DMPlexCreateFromCellList(PetscObjectComm((PetscObject)dm),dim,network->nEdges,network->nNodes,numCorners,PETSC_FALSE,network->edges,spacedim,vertexcoords,&network->plex);CHKERRQ(ierr); 133 if (network->nNodes) { 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 DMNetworkGetComponentTypeOffset - 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 DMNetworkGetComponentTypeOffset(dm,v,compnum,&key,&offset); 409 compdata = (UserCompDataType)(arr+offset); 410 411 Level: intermediate 412 413 .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray, 414 @*/ 415 PetscErrorCode DMNetworkGetComponentTypeOffset(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 node */ 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: DMNetworkGetComponentTypeOffset, 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->nNodes = newDMnetwork->vEnd - newDMnetwork->vStart; 834 newDMnetwork->NNodes = oldDMnetwork->NNodes; 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 907 PetscFunctionReturn(0); 908 } 909 910 /*@C 911 DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point 912 913 Not Collective 914 915 Input Parameters: 916 + dm - The DMNetwork object 917 - p - the vertex point 918 919 Output Paramters: 920 + nedges - number of edges connected to this vertex point 921 - edges - List of edge points 922 923 Level: intermediate 924 925 Fortran Notes: 926 Since it returns an array, this routine is only available in Fortran 90, and you must 927 include petsc.h90 in your code. 928 929 .seealso: DMNetworkCreate, DMNetworkGetConnectedNodes 930 @*/ 931 PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[]) 932 { 933 PetscErrorCode ierr; 934 DM_Network *network = (DM_Network*)dm->data; 935 936 PetscFunctionBegin; 937 ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr); 938 ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr); 939 PetscFunctionReturn(0); 940 } 941 942 /*@C 943 DMNetworkGetConnectedNodes - Return the connected vertices for this edge point 944 945 Not Collective 946 947 Input Parameters: 948 + dm - The DMNetwork object 949 - p - the edge point 950 951 Output Paramters: 952 . vertices - vertices connected to this edge 953 954 Level: intermediate 955 956 Fortran Notes: 957 Since it returns an array, this routine is only available in Fortran 90, and you must 958 include petsc.h90 in your code. 959 960 .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges 961 @*/ 962 PetscErrorCode DMNetworkGetConnectedNodes(DM dm,PetscInt edge,const PetscInt *vertices[]) 963 { 964 PetscErrorCode ierr; 965 DM_Network *network = (DM_Network*)dm->data; 966 967 PetscFunctionBegin; 968 ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr); 969 PetscFunctionReturn(0); 970 } 971 972 /*@ 973 DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex 974 975 Not Collective 976 977 Input Parameters: 978 + dm - The DMNetwork object 979 . p - the vertex point 980 981 Output Parameter: 982 . isghost - TRUE if the vertex is a ghost point 983 984 Level: intermediate 985 986 .seealso: DMNetworkCreate, DMNetworkGetConnectedNodes, DMNetworkGetVertexRange 987 @*/ 988 PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost) 989 { 990 PetscErrorCode ierr; 991 DM_Network *network = (DM_Network*)dm->data; 992 PetscInt offsetg; 993 PetscSection sectiong; 994 995 PetscFunctionBegin; 996 *isghost = PETSC_FALSE; 997 ierr = DMGetDefaultGlobalSection(network->plex,§iong);CHKERRQ(ierr); 998 ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr); 999 if (offsetg < 0) *isghost = PETSC_TRUE; 1000 PetscFunctionReturn(0); 1001 } 1002 1003 PetscErrorCode DMSetUp_Network(DM dm) 1004 { 1005 PetscErrorCode ierr; 1006 DM_Network *network=(DM_Network*)dm->data; 1007 1008 PetscFunctionBegin; 1009 ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr); 1010 ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr); 1011 1012 ierr = DMSetDefaultSection(network->plex,network->DofSection);CHKERRQ(ierr); 1013 ierr = DMGetDefaultGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr); 1014 PetscFunctionReturn(0); 1015 } 1016 1017 /*@ 1018 DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices 1019 -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)? 1020 1021 Collective 1022 1023 Input Parameters: 1024 + dm - The DMNetwork object 1025 . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges 1026 - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices 1027 1028 Level: intermediate 1029 1030 @*/ 1031 PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg) 1032 { 1033 DM_Network *network=(DM_Network*)dm->data; 1034 1035 PetscFunctionBegin; 1036 network->userEdgeJacobian = eflg; 1037 network->userVertexJacobian = vflg; 1038 PetscFunctionReturn(0); 1039 } 1040 1041 /*@ 1042 DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network 1043 1044 Not Collective 1045 1046 Input Parameters: 1047 + dm - The DMNetwork object 1048 . p - the edge point 1049 - J - array (size = 3) of Jacobian submatrices for this edge point: 1050 J[0]: this edge 1051 J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedNodes() 1052 1053 Level: intermediate 1054 1055 .seealso: DMNetworkVertexSetMatrix 1056 @*/ 1057 PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[]) 1058 { 1059 PetscErrorCode ierr; 1060 DM_Network *network=(DM_Network*)dm->data; 1061 1062 PetscFunctionBegin; 1063 if (!network->userEdgeJacobian) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix"); 1064 if (!network->Je) { 1065 ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr); 1066 } 1067 network->Je[3*p] = J[0]; 1068 network->Je[3*p+1] = J[1]; 1069 network->Je[3*p+2] = J[2]; 1070 PetscFunctionReturn(0); 1071 } 1072 1073 /*@ 1074 DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network 1075 1076 Not Collective 1077 1078 Input Parameters: 1079 + dm - The DMNetwork object 1080 . p - the vertex point 1081 - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point: 1082 J[0]: this vertex 1083 J[1+2*i]: i-th supporting edge 1084 J[1+2*i+1]: i-th connected vertex 1085 1086 Level: intermediate 1087 1088 .seealso: DMNetworkEdgeSetMatrix 1089 @*/ 1090 PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[]) 1091 { 1092 PetscErrorCode ierr; 1093 DM_Network *network=(DM_Network*)dm->data; 1094 PetscInt i,*vptr,nedges,vStart,vEnd; 1095 const PetscInt *edges; 1096 1097 PetscFunctionBegin; 1098 if (!network->userVertexJacobian) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix"); 1099 1100 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1101 1102 if (!network->Jv) { 1103 PetscInt nNodes = network->nNodes,nedges_total; 1104 /* count nvertex_total */ 1105 nedges_total = 0; 1106 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1107 ierr = PetscMalloc1(nNodes+1,&vptr);CHKERRQ(ierr); 1108 1109 vptr[0] = 0; 1110 for (i=0; i<nNodes; i++) { 1111 ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr); 1112 nedges_total += nedges; 1113 vptr[i+1] = vptr[i] + 2*nedges + 1; 1114 } 1115 1116 ierr = PetscCalloc1(2*nedges_total+nNodes,&network->Jv);CHKERRQ(ierr); 1117 network->Jvptr = vptr; 1118 } 1119 1120 vptr = network->Jvptr; 1121 network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */ 1122 1123 /* Set Jacobian for each supporting edge and connected vertex */ 1124 ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr); 1125 for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i]; 1126 PetscFunctionReturn(0); 1127 } 1128 1129 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1130 { 1131 PetscErrorCode ierr; 1132 PetscInt j; 1133 PetscScalar val=(PetscScalar)ncols; 1134 1135 PetscFunctionBegin; 1136 if (!ghost) { 1137 for (j=0; j<nrows; j++) { 1138 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1139 } 1140 } else { 1141 for (j=0; j<nrows; j++) { 1142 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1143 } 1144 } 1145 PetscFunctionReturn(0); 1146 } 1147 1148 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1149 { 1150 PetscErrorCode ierr; 1151 PetscInt j,ncols_u; 1152 PetscScalar val; 1153 1154 PetscFunctionBegin; 1155 if (!ghost) { 1156 for (j=0; j<nrows; j++) { 1157 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1158 val = (PetscScalar)ncols_u; 1159 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1160 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1161 } 1162 } else { 1163 for (j=0; j<nrows; j++) { 1164 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1165 val = (PetscScalar)ncols_u; 1166 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1167 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1168 } 1169 } 1170 PetscFunctionReturn(0); 1171 } 1172 1173 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1174 { 1175 PetscErrorCode ierr; 1176 1177 PetscFunctionBegin; 1178 if (Ju) { 1179 ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1180 } else { 1181 ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1182 } 1183 PetscFunctionReturn(0); 1184 } 1185 1186 PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1187 { 1188 PetscErrorCode ierr; 1189 PetscInt j,*cols; 1190 PetscScalar *zeros; 1191 1192 PetscFunctionBegin; 1193 ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr); 1194 for (j=0; j<ncols; j++) cols[j] = j+ cstart; 1195 ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr); 1196 ierr = PetscFree2(cols,zeros);CHKERRQ(ierr); 1197 PetscFunctionReturn(0); 1198 } 1199 1200 PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1201 { 1202 PetscErrorCode ierr; 1203 PetscInt j,M,N,row,col,ncols_u; 1204 const PetscInt *cols; 1205 PetscScalar zero=0.0; 1206 1207 PetscFunctionBegin; 1208 ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr); 1209 if (nrows != M || ncols != N) SETERRQ4(PetscObjectComm((PetscObject)Ju),PETSC_ERR_USER,"%D by %D must equal %D by %D",nrows,ncols,M,N); 1210 1211 for (row=0; row<nrows; row++) { 1212 ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1213 for (j=0; j<ncols_u; j++) { 1214 col = cols[j] + cstart; 1215 ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr); 1216 } 1217 ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1218 } 1219 PetscFunctionReturn(0); 1220 } 1221 1222 PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1223 { 1224 PetscErrorCode ierr; 1225 1226 PetscFunctionBegin; 1227 if (Ju) { 1228 ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1229 } else { 1230 ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1231 } 1232 PetscFunctionReturn(0); 1233 } 1234 1235 1236 /* 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. 1237 */ 1238 PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog) 1239 { 1240 PetscErrorCode ierr; 1241 PetscInt i, size, dof; 1242 PetscInt *glob2loc; 1243 1244 PetscFunctionBegin; 1245 ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr); 1246 ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr); 1247 1248 for (i = 0; i < size; i++) { 1249 ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr); 1250 dof = (dof >= 0) ? dof : -(dof + 1); 1251 glob2loc[i] = dof; 1252 } 1253 1254 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 1255 #if 0 1256 ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1257 #endif 1258 PetscFunctionReturn(0); 1259 } 1260 1261 PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J) 1262 { 1263 PetscErrorCode ierr; 1264 PetscMPIInt rank, size; 1265 DM_Network *network = (DM_Network*) dm->data; 1266 PetscInt eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize; 1267 PetscInt cstart,ncols,j,e,v; 1268 PetscBool ghost,ghost_vc,ghost2,isNest; 1269 Mat Juser; 1270 PetscSection sectionGlobal; 1271 PetscInt nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */ 1272 const PetscInt *edges,*cone; 1273 MPI_Comm comm; 1274 MatType mtype; 1275 Vec vd_nz,vo_nz; 1276 PetscInt *dnnz,*onnz; 1277 PetscScalar *vdnz,*vonz; 1278 1279 PetscFunctionBegin; 1280 mtype = dm->mattype; 1281 ierr = PetscStrcmp(mtype, MATNEST, &isNest);CHKERRQ(ierr); 1282 1283 if (isNest) { 1284 /* ierr = DMCreateMatrix_Network_Nest(); */ 1285 PetscInt eDof, vDof; 1286 Mat j11, j12, j21, j22, bA[2][2]; 1287 ISLocalToGlobalMapping eISMap, vISMap; 1288 1289 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1290 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1291 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1292 1293 ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr); 1294 ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr); 1295 1296 ierr = MatCreate(PETSC_COMM_WORLD, &j11);CHKERRQ(ierr); 1297 ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1298 ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr); 1299 1300 ierr = MatCreate(PETSC_COMM_WORLD, &j12);CHKERRQ(ierr); 1301 ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr); 1302 ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr); 1303 1304 ierr = MatCreate(PETSC_COMM_WORLD, &j21);CHKERRQ(ierr); 1305 ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1306 ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr); 1307 1308 ierr = MatCreate(PETSC_COMM_WORLD, &j22);CHKERRQ(ierr); 1309 ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1310 ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr); 1311 1312 bA[0][0] = j11; 1313 bA[0][1] = j12; 1314 bA[1][0] = j21; 1315 bA[1][1] = j22; 1316 1317 ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr); 1318 ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr); 1319 1320 ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr); 1321 ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr); 1322 ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr); 1323 ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr); 1324 1325 ierr = MatSetUp(j11);CHKERRQ(ierr); 1326 ierr = MatSetUp(j12);CHKERRQ(ierr); 1327 ierr = MatSetUp(j21);CHKERRQ(ierr); 1328 ierr = MatSetUp(j22);CHKERRQ(ierr); 1329 1330 ierr = MatCreateNest(PETSC_COMM_WORLD,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr); 1331 ierr = MatSetUp(*J);CHKERRQ(ierr); 1332 ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr); 1333 ierr = MatDestroy(&j11);CHKERRQ(ierr); 1334 ierr = MatDestroy(&j12);CHKERRQ(ierr); 1335 ierr = MatDestroy(&j21);CHKERRQ(ierr); 1336 ierr = MatDestroy(&j22);CHKERRQ(ierr); 1337 1338 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1339 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1340 1341 /* Free structures */ 1342 ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr); 1343 ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr); 1344 1345 PetscFunctionReturn(0); 1346 } else if (!network->userEdgeJacobian && !network->userVertexJacobian) { 1347 /* user does not provide Jacobian blocks */ 1348 ierr = DMCreateMatrix(network->plex,J);CHKERRQ(ierr); 1349 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1350 PetscFunctionReturn(0); 1351 } 1352 1353 ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr); 1354 ierr = DMGetDefaultGlobalSection(network->plex,§ionGlobal);CHKERRQ(ierr); 1355 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr); 1356 ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 1357 1358 ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr); 1359 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1360 1361 /* (1) Set matrix preallocation */ 1362 /*------------------------------*/ 1363 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1364 ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr); 1365 ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr); 1366 ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr); 1367 ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr); 1368 ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr); 1369 1370 /* Set preallocation for edges */ 1371 /*-----------------------------*/ 1372 ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr); 1373 1374 ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr); 1375 for (e=eStart; e<eEnd; e++) { 1376 /* Get row indices */ 1377 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1378 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1379 if (nrows) { 1380 if (!network->Je) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Je"); 1381 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1382 1383 /* Set preallocation for conntected vertices */ 1384 ierr = DMNetworkGetConnectedNodes(dm,e,&cone);CHKERRQ(ierr); 1385 for (v=0; v<2; v++) { 1386 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1387 1388 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1389 ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr); 1390 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1391 } 1392 1393 /* Set preallocation for edge self */ 1394 cstart = rstart; 1395 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1396 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1397 } 1398 } 1399 1400 /* Set preallocation for vertices */ 1401 /*--------------------------------*/ 1402 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1403 if (vEnd - vStart) { 1404 if (!network->Jv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Jv"); 1405 vptr = network->Jvptr; 1406 if (!vptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide vptr"); 1407 } 1408 1409 for (v=vStart; v<vEnd; v++) { 1410 /* Get row indices */ 1411 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1412 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1413 if (!nrows) continue; 1414 1415 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1416 if (ghost) { 1417 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1418 } else { 1419 rows_v = rows; 1420 } 1421 1422 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1423 1424 /* Get supporting edges and connected vertices */ 1425 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1426 1427 for (e=0; e<nedges; e++) { 1428 /* Supporting edges */ 1429 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1430 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1431 1432 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1433 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1434 1435 /* Connected vertices */ 1436 ierr = DMNetworkGetConnectedNodes(dm,edges[e],&cone);CHKERRQ(ierr); 1437 vc = (v == cone[0]) ? cone[1]:cone[0]; 1438 ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr); 1439 1440 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1441 1442 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1443 if (ghost_vc||ghost) { 1444 ghost2 = PETSC_TRUE; 1445 } else { 1446 ghost2 = PETSC_FALSE; 1447 } 1448 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr); 1449 } 1450 1451 /* Set preallocation for vertex self */ 1452 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1453 if (!ghost) { 1454 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1455 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1456 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1457 } 1458 if (ghost) { 1459 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1460 } 1461 } 1462 1463 ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr); 1464 ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr); 1465 1466 ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr); 1467 1468 ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr); 1469 ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr); 1470 1471 ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr); 1472 ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr); 1473 for (j=0; j<localSize; j++) { 1474 dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]); 1475 onnz[j] = (PetscInt)PetscRealPart(vonz[j]); 1476 } 1477 ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr); 1478 ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr); 1479 ierr = VecDestroy(&vd_nz);CHKERRQ(ierr); 1480 ierr = VecDestroy(&vo_nz);CHKERRQ(ierr); 1481 1482 ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr); 1483 ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr); 1484 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1485 1486 ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 1487 1488 /* (2) Set matrix entries for edges */ 1489 /*----------------------------------*/ 1490 for (e=eStart; e<eEnd; e++) { 1491 /* Get row indices */ 1492 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1493 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1494 if (nrows) { 1495 if (!network->Je) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Je"); 1496 1497 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1498 1499 /* Set matrix entries for conntected vertices */ 1500 ierr = DMNetworkGetConnectedNodes(dm,e,&cone);CHKERRQ(ierr); 1501 for (v=0; v<2; v++) { 1502 ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr); 1503 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1504 1505 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1506 ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1507 } 1508 1509 /* Set matrix entries for edge self */ 1510 cstart = rstart; 1511 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1512 ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr); 1513 } 1514 } 1515 1516 /* Set matrix entries for vertices */ 1517 /*---------------------------------*/ 1518 for (v=vStart; v<vEnd; v++) { 1519 /* Get row indices */ 1520 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1521 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1522 if (!nrows) continue; 1523 1524 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1525 if (ghost) { 1526 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1527 } else { 1528 rows_v = rows; 1529 } 1530 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1531 1532 /* Get supporting edges and connected vertices */ 1533 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1534 1535 for (e=0; e<nedges; e++) { 1536 /* Supporting edges */ 1537 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1538 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1539 1540 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1541 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1542 1543 /* Connected vertices */ 1544 ierr = DMNetworkGetConnectedNodes(dm,edges[e],&cone);CHKERRQ(ierr); 1545 vc = (v == cone[0]) ? cone[1]:cone[0]; 1546 1547 ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr); 1548 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1549 1550 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1551 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1552 } 1553 1554 /* Set matrix entries for vertex self */ 1555 if (!ghost) { 1556 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1557 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1558 ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr); 1559 } 1560 if (ghost) { 1561 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1562 } 1563 } 1564 ierr = PetscFree(rows);CHKERRQ(ierr); 1565 1566 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1567 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1568 1569 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1570 PetscFunctionReturn(0); 1571 } 1572 1573 PetscErrorCode DMDestroy_Network(DM dm) 1574 { 1575 PetscErrorCode ierr; 1576 DM_Network *network = (DM_Network*) dm->data; 1577 1578 PetscFunctionBegin; 1579 if (--network->refct > 0) PetscFunctionReturn(0); 1580 if (network->Je) { 1581 ierr = PetscFree(network->Je);CHKERRQ(ierr); 1582 } 1583 if (network->Jv) { 1584 ierr = PetscFree(network->Jvptr);CHKERRQ(ierr); 1585 ierr = PetscFree(network->Jv);CHKERRQ(ierr); 1586 } 1587 1588 ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr); 1589 ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr); 1590 ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr); 1591 if (network->vertex.sf) { 1592 ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr); 1593 } 1594 /* edge */ 1595 ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr); 1596 ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr); 1597 ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr); 1598 if (network->edge.sf) { 1599 ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr); 1600 } 1601 ierr = DMDestroy(&network->plex);CHKERRQ(ierr); 1602 network->edges = NULL; 1603 ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr); 1604 ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr); 1605 1606 ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr); 1607 ierr = PetscFree(network->cvalue);CHKERRQ(ierr); 1608 ierr = PetscFree(network->header);CHKERRQ(ierr); 1609 ierr = PetscFree(network);CHKERRQ(ierr); 1610 PetscFunctionReturn(0); 1611 } 1612 1613 PetscErrorCode DMView_Network(DM dm, PetscViewer viewer) 1614 { 1615 PetscErrorCode ierr; 1616 DM_Network *network = (DM_Network*) dm->data; 1617 1618 PetscFunctionBegin; 1619 ierr = DMView(network->plex,viewer);CHKERRQ(ierr); 1620 PetscFunctionReturn(0); 1621 } 1622 1623 PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l) 1624 { 1625 PetscErrorCode ierr; 1626 DM_Network *network = (DM_Network*) dm->data; 1627 1628 PetscFunctionBegin; 1629 ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr); 1630 PetscFunctionReturn(0); 1631 } 1632 1633 PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l) 1634 { 1635 PetscErrorCode ierr; 1636 DM_Network *network = (DM_Network*) dm->data; 1637 1638 PetscFunctionBegin; 1639 ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr); 1640 PetscFunctionReturn(0); 1641 } 1642 1643 PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g) 1644 { 1645 PetscErrorCode ierr; 1646 DM_Network *network = (DM_Network*) dm->data; 1647 1648 PetscFunctionBegin; 1649 ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr); 1650 PetscFunctionReturn(0); 1651 } 1652 1653 PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g) 1654 { 1655 PetscErrorCode ierr; 1656 DM_Network *network = (DM_Network*) dm->data; 1657 1658 PetscFunctionBegin; 1659 ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr); 1660 PetscFunctionReturn(0); 1661 } 1662