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