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