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 #include <petsc/private/matimpl.h> 1260 PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J) 1261 { 1262 PetscErrorCode ierr; 1263 PetscMPIInt rank, size; 1264 DM_Network *network = (DM_Network*) dm->data; 1265 PetscInt eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize; 1266 PetscInt cstart,ncols,j,e,v; 1267 PetscBool ghost,ghost_vc,ghost2,isNest; 1268 Mat Juser; 1269 PetscSection sectionGlobal; 1270 PetscInt nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */ 1271 const PetscInt *edges,*cone; 1272 MPI_Comm comm; 1273 MatType mtype; 1274 Vec vd_nz,vo_nz; 1275 PetscInt *dnnz,*onnz; 1276 PetscScalar *vdnz,*vonz; 1277 1278 PetscFunctionBegin; 1279 mtype = dm->mattype; 1280 ierr = PetscStrcmp(mtype, MATNEST, &isNest);CHKERRQ(ierr); 1281 1282 if (isNest) { 1283 /* ierr = DMCreateMatrix_Network_Nest(); */ 1284 PetscInt eDof, vDof; 1285 Mat j11, j12, j21, j22, bA[2][2]; 1286 ISLocalToGlobalMapping eISMap, vISMap; 1287 1288 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1289 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1290 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1291 1292 ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr); 1293 ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr); 1294 1295 ierr = MatCreate(comm, &j11);CHKERRQ(ierr); 1296 ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1297 ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr); 1298 1299 ierr = MatCreate(comm, &j12);CHKERRQ(ierr); 1300 ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr); 1301 ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr); 1302 1303 ierr = MatCreate(comm, &j21);CHKERRQ(ierr); 1304 ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1305 ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr); 1306 1307 ierr = MatCreate(comm, &j22);CHKERRQ(ierr); 1308 ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1309 ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr); 1310 1311 bA[0][0] = j11; 1312 bA[0][1] = j12; 1313 bA[1][0] = j21; 1314 bA[1][1] = j22; 1315 1316 ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr); 1317 ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr); 1318 1319 ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr); 1320 ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr); 1321 ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr); 1322 ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr); 1323 1324 ierr = MatSetUp(j11);CHKERRQ(ierr); 1325 ierr = MatSetUp(j12);CHKERRQ(ierr); 1326 ierr = MatSetUp(j21);CHKERRQ(ierr); 1327 ierr = MatSetUp(j22);CHKERRQ(ierr); 1328 1329 ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr); 1330 ierr = MatSetUp(*J);CHKERRQ(ierr); 1331 ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr); 1332 ierr = MatDestroy(&j11);CHKERRQ(ierr); 1333 ierr = MatDestroy(&j12);CHKERRQ(ierr); 1334 ierr = MatDestroy(&j21);CHKERRQ(ierr); 1335 ierr = MatDestroy(&j22);CHKERRQ(ierr); 1336 1337 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1338 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1339 1340 /* Free structures */ 1341 ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr); 1342 ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr); 1343 1344 PetscFunctionReturn(0); 1345 } else if (!network->userEdgeJacobian && !network->userVertexJacobian) { 1346 /* user does not provide Jacobian blocks */ 1347 ierr = DMCreateMatrix(network->plex,J);CHKERRQ(ierr); 1348 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1349 PetscFunctionReturn(0); 1350 } 1351 1352 ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr); 1353 ierr = DMGetDefaultGlobalSection(network->plex,§ionGlobal);CHKERRQ(ierr); 1354 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr); 1355 ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 1356 1357 ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr); 1358 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1359 1360 /* (1) Set matrix preallocation */ 1361 /*------------------------------*/ 1362 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1363 ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr); 1364 ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr); 1365 ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr); 1366 ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr); 1367 ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr); 1368 1369 /* Set preallocation for edges */ 1370 /*-----------------------------*/ 1371 ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr); 1372 1373 ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr); 1374 for (e=eStart; e<eEnd; e++) { 1375 /* Get row indices */ 1376 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1377 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1378 if (nrows) { 1379 if (!network->Je) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Je"); 1380 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1381 1382 /* Set preallocation for conntected vertices */ 1383 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1384 for (v=0; v<2; v++) { 1385 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1386 1387 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1388 ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr); 1389 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1390 } 1391 1392 /* Set preallocation for edge self */ 1393 cstart = rstart; 1394 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1395 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1396 } 1397 } 1398 1399 /* Set preallocation for vertices */ 1400 /*--------------------------------*/ 1401 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1402 if (vEnd - vStart) { 1403 if (!network->Jv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Jv"); 1404 vptr = network->Jvptr; 1405 if (!vptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide vptr"); 1406 } 1407 1408 for (v=vStart; v<vEnd; v++) { 1409 /* Get row indices */ 1410 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1411 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1412 if (!nrows) continue; 1413 1414 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1415 if (ghost) { 1416 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1417 } else { 1418 rows_v = rows; 1419 } 1420 1421 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1422 1423 /* Get supporting edges and connected vertices */ 1424 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1425 1426 for (e=0; e<nedges; e++) { 1427 /* Supporting edges */ 1428 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1429 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1430 1431 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1432 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1433 1434 /* Connected vertices */ 1435 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1436 vc = (v == cone[0]) ? cone[1]:cone[0]; 1437 ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr); 1438 1439 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1440 1441 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1442 if (ghost_vc||ghost) { 1443 ghost2 = PETSC_TRUE; 1444 } else { 1445 ghost2 = PETSC_FALSE; 1446 } 1447 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr); 1448 } 1449 1450 /* Set preallocation for vertex self */ 1451 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1452 if (!ghost) { 1453 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1454 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1455 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1456 } 1457 if (ghost) { 1458 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1459 } 1460 } 1461 1462 ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr); 1463 ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr); 1464 1465 ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr); 1466 1467 ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr); 1468 ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr); 1469 1470 ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr); 1471 ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr); 1472 for (j=0; j<localSize; j++) { 1473 dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]); 1474 onnz[j] = (PetscInt)PetscRealPart(vonz[j]); 1475 } 1476 ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr); 1477 ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr); 1478 ierr = VecDestroy(&vd_nz);CHKERRQ(ierr); 1479 ierr = VecDestroy(&vo_nz);CHKERRQ(ierr); 1480 1481 ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr); 1482 ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr); 1483 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1484 1485 ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 1486 1487 /* (2) Set matrix entries for edges */ 1488 /*----------------------------------*/ 1489 for (e=eStart; e<eEnd; e++) { 1490 /* Get row indices */ 1491 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1492 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1493 if (nrows) { 1494 if (!network->Je) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Je"); 1495 1496 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1497 1498 /* Set matrix entries for conntected vertices */ 1499 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1500 for (v=0; v<2; v++) { 1501 ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr); 1502 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1503 1504 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1505 ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1506 } 1507 1508 /* Set matrix entries for edge self */ 1509 cstart = rstart; 1510 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1511 ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr); 1512 } 1513 } 1514 1515 /* Set matrix entries for vertices */ 1516 /*---------------------------------*/ 1517 for (v=vStart; v<vEnd; v++) { 1518 /* Get row indices */ 1519 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1520 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1521 if (!nrows) continue; 1522 1523 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1524 if (ghost) { 1525 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1526 } else { 1527 rows_v = rows; 1528 } 1529 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1530 1531 /* Get supporting edges and connected vertices */ 1532 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1533 1534 for (e=0; e<nedges; e++) { 1535 /* Supporting edges */ 1536 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1537 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1538 1539 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1540 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1541 1542 /* Connected vertices */ 1543 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1544 vc = (v == cone[0]) ? cone[1]:cone[0]; 1545 1546 ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr); 1547 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1548 1549 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1550 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1551 } 1552 1553 /* Set matrix entries for vertex self */ 1554 if (!ghost) { 1555 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1556 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1557 ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr); 1558 } 1559 if (ghost) { 1560 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1561 } 1562 } 1563 ierr = PetscFree(rows);CHKERRQ(ierr); 1564 1565 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1566 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1567 1568 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1569 PetscFunctionReturn(0); 1570 } 1571 1572 PetscErrorCode DMDestroy_Network(DM dm) 1573 { 1574 PetscErrorCode ierr; 1575 DM_Network *network = (DM_Network*) dm->data; 1576 1577 PetscFunctionBegin; 1578 if (--network->refct > 0) PetscFunctionReturn(0); 1579 if (network->Je) { 1580 ierr = PetscFree(network->Je);CHKERRQ(ierr); 1581 } 1582 if (network->Jv) { 1583 ierr = PetscFree(network->Jvptr);CHKERRQ(ierr); 1584 ierr = PetscFree(network->Jv);CHKERRQ(ierr); 1585 } 1586 1587 ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr); 1588 ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr); 1589 ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr); 1590 if (network->vertex.sf) { 1591 ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr); 1592 } 1593 /* edge */ 1594 ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr); 1595 ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr); 1596 ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr); 1597 if (network->edge.sf) { 1598 ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr); 1599 } 1600 ierr = DMDestroy(&network->plex);CHKERRQ(ierr); 1601 network->edges = NULL; 1602 ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr); 1603 ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr); 1604 1605 ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr); 1606 ierr = PetscFree(network->cvalue);CHKERRQ(ierr); 1607 ierr = PetscFree(network->header);CHKERRQ(ierr); 1608 ierr = PetscFree(network);CHKERRQ(ierr); 1609 PetscFunctionReturn(0); 1610 } 1611 1612 PetscErrorCode DMView_Network(DM dm, PetscViewer viewer) 1613 { 1614 PetscErrorCode ierr; 1615 DM_Network *network = (DM_Network*) dm->data; 1616 1617 PetscFunctionBegin; 1618 ierr = DMView(network->plex,viewer);CHKERRQ(ierr); 1619 PetscFunctionReturn(0); 1620 } 1621 1622 PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l) 1623 { 1624 PetscErrorCode ierr; 1625 DM_Network *network = (DM_Network*) dm->data; 1626 1627 PetscFunctionBegin; 1628 ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr); 1629 PetscFunctionReturn(0); 1630 } 1631 1632 PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l) 1633 { 1634 PetscErrorCode ierr; 1635 DM_Network *network = (DM_Network*) dm->data; 1636 1637 PetscFunctionBegin; 1638 ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr); 1639 PetscFunctionReturn(0); 1640 } 1641 1642 PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g) 1643 { 1644 PetscErrorCode ierr; 1645 DM_Network *network = (DM_Network*) dm->data; 1646 1647 PetscFunctionBegin; 1648 ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr); 1649 PetscFunctionReturn(0); 1650 } 1651 1652 PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g) 1653 { 1654 PetscErrorCode ierr; 1655 DM_Network *network = (DM_Network*) dm->data; 1656 1657 PetscFunctionBegin; 1658 ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr); 1659 PetscFunctionReturn(0); 1660 } 1661