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