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