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 1178 PetscFunctionBegin; 1179 network->userEdgeJacobian = eflg; 1180 network->userVertexJacobian = vflg; 1181 PetscFunctionReturn(0); 1182 } 1183 1184 /*@ 1185 DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network 1186 1187 Not Collective 1188 1189 Input Parameters: 1190 + dm - The DMNetwork object 1191 . p - the edge point 1192 - J - array (size = 3) of Jacobian submatrices for this edge point: 1193 J[0]: this edge 1194 J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices() 1195 1196 Level: intermediate 1197 1198 .seealso: DMNetworkVertexSetMatrix 1199 @*/ 1200 PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[]) 1201 { 1202 PetscErrorCode ierr; 1203 DM_Network *network=(DM_Network*)dm->data; 1204 1205 PetscFunctionBegin; 1206 if (!network->userEdgeJacobian) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix"); 1207 if (!network->Je) { 1208 ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr); 1209 } 1210 network->Je[3*p] = J[0]; 1211 network->Je[3*p+1] = J[1]; 1212 network->Je[3*p+2] = J[2]; 1213 PetscFunctionReturn(0); 1214 } 1215 1216 /*@ 1217 DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network 1218 1219 Not Collective 1220 1221 Input Parameters: 1222 + dm - The DMNetwork object 1223 . p - the vertex point 1224 - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point: 1225 J[0]: this vertex 1226 J[1+2*i]: i-th supporting edge 1227 J[1+2*i+1]: i-th connected vertex 1228 1229 Level: intermediate 1230 1231 .seealso: DMNetworkEdgeSetMatrix 1232 @*/ 1233 PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[]) 1234 { 1235 PetscErrorCode ierr; 1236 DM_Network *network=(DM_Network*)dm->data; 1237 PetscInt i,*vptr,nedges,vStart,vEnd; 1238 const PetscInt *edges; 1239 1240 PetscFunctionBegin; 1241 if (!network->userVertexJacobian) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix"); 1242 1243 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1244 1245 if (!network->Jv) { 1246 PetscInt nVertices = network->nVertices,nedges_total; 1247 /* count nvertex_total */ 1248 nedges_total = 0; 1249 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1250 ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr); 1251 1252 vptr[0] = 0; 1253 for (i=0; i<nVertices; i++) { 1254 ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr); 1255 nedges_total += nedges; 1256 vptr[i+1] = vptr[i] + 2*nedges + 1; 1257 } 1258 1259 ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr); 1260 network->Jvptr = vptr; 1261 } 1262 1263 vptr = network->Jvptr; 1264 network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */ 1265 1266 /* Set Jacobian for each supporting edge and connected vertex */ 1267 ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr); 1268 for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i]; 1269 PetscFunctionReturn(0); 1270 } 1271 1272 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1273 { 1274 PetscErrorCode ierr; 1275 PetscInt j; 1276 PetscScalar val=(PetscScalar)ncols; 1277 1278 PetscFunctionBegin; 1279 if (!ghost) { 1280 for (j=0; j<nrows; j++) { 1281 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1282 } 1283 } else { 1284 for (j=0; j<nrows; j++) { 1285 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1286 } 1287 } 1288 PetscFunctionReturn(0); 1289 } 1290 1291 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1292 { 1293 PetscErrorCode ierr; 1294 PetscInt j,ncols_u; 1295 PetscScalar val; 1296 1297 PetscFunctionBegin; 1298 if (!ghost) { 1299 for (j=0; j<nrows; j++) { 1300 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1301 val = (PetscScalar)ncols_u; 1302 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1303 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1304 } 1305 } else { 1306 for (j=0; j<nrows; j++) { 1307 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1308 val = (PetscScalar)ncols_u; 1309 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1310 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1311 } 1312 } 1313 PetscFunctionReturn(0); 1314 } 1315 1316 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1317 { 1318 PetscErrorCode ierr; 1319 1320 PetscFunctionBegin; 1321 if (Ju) { 1322 ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1323 } else { 1324 ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1325 } 1326 PetscFunctionReturn(0); 1327 } 1328 1329 PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1330 { 1331 PetscErrorCode ierr; 1332 PetscInt j,*cols; 1333 PetscScalar *zeros; 1334 1335 PetscFunctionBegin; 1336 ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr); 1337 for (j=0; j<ncols; j++) cols[j] = j+ cstart; 1338 ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr); 1339 ierr = PetscFree2(cols,zeros);CHKERRQ(ierr); 1340 PetscFunctionReturn(0); 1341 } 1342 1343 PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1344 { 1345 PetscErrorCode ierr; 1346 PetscInt j,M,N,row,col,ncols_u; 1347 const PetscInt *cols; 1348 PetscScalar zero=0.0; 1349 1350 PetscFunctionBegin; 1351 ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr); 1352 if (nrows != M || ncols != N) SETERRQ4(PetscObjectComm((PetscObject)Ju),PETSC_ERR_USER,"%D by %D must equal %D by %D",nrows,ncols,M,N); 1353 1354 for (row=0; row<nrows; row++) { 1355 ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1356 for (j=0; j<ncols_u; j++) { 1357 col = cols[j] + cstart; 1358 ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr); 1359 } 1360 ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1361 } 1362 PetscFunctionReturn(0); 1363 } 1364 1365 PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1366 { 1367 PetscErrorCode ierr; 1368 1369 PetscFunctionBegin; 1370 if (Ju) { 1371 ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1372 } else { 1373 ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1374 } 1375 PetscFunctionReturn(0); 1376 } 1377 1378 /* 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. 1379 */ 1380 PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog) 1381 { 1382 PetscErrorCode ierr; 1383 PetscInt i, size, dof; 1384 PetscInt *glob2loc; 1385 1386 PetscFunctionBegin; 1387 ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr); 1388 ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr); 1389 1390 for (i = 0; i < size; i++) { 1391 ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr); 1392 dof = (dof >= 0) ? dof : -(dof + 1); 1393 glob2loc[i] = dof; 1394 } 1395 1396 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 1397 #if 0 1398 ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1399 #endif 1400 PetscFunctionReturn(0); 1401 } 1402 1403 #include <petsc/private/matimpl.h> 1404 PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J) 1405 { 1406 PetscErrorCode ierr; 1407 PetscMPIInt rank, size; 1408 DM_Network *network = (DM_Network*) dm->data; 1409 PetscInt eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize; 1410 PetscInt cstart,ncols,j,e,v; 1411 PetscBool ghost,ghost_vc,ghost2,isNest; 1412 Mat Juser; 1413 PetscSection sectionGlobal; 1414 PetscInt nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */ 1415 const PetscInt *edges,*cone; 1416 MPI_Comm comm; 1417 MatType mtype; 1418 Vec vd_nz,vo_nz; 1419 PetscInt *dnnz,*onnz; 1420 PetscScalar *vdnz,*vonz; 1421 1422 PetscFunctionBegin; 1423 mtype = dm->mattype; 1424 ierr = PetscStrcmp(mtype, MATNEST, &isNest);CHKERRQ(ierr); 1425 1426 if (isNest) { 1427 /* ierr = DMCreateMatrix_Network_Nest(); */ 1428 PetscInt eDof, vDof; 1429 Mat j11, j12, j21, j22, bA[2][2]; 1430 ISLocalToGlobalMapping eISMap, vISMap; 1431 1432 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1433 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1434 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1435 1436 ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr); 1437 ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr); 1438 1439 ierr = MatCreate(comm, &j11);CHKERRQ(ierr); 1440 ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1441 ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr); 1442 1443 ierr = MatCreate(comm, &j12);CHKERRQ(ierr); 1444 ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr); 1445 ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr); 1446 1447 ierr = MatCreate(comm, &j21);CHKERRQ(ierr); 1448 ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1449 ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr); 1450 1451 ierr = MatCreate(comm, &j22);CHKERRQ(ierr); 1452 ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1453 ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr); 1454 1455 bA[0][0] = j11; 1456 bA[0][1] = j12; 1457 bA[1][0] = j21; 1458 bA[1][1] = j22; 1459 1460 ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr); 1461 ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr); 1462 1463 ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr); 1464 ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr); 1465 ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr); 1466 ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr); 1467 1468 ierr = MatSetUp(j11);CHKERRQ(ierr); 1469 ierr = MatSetUp(j12);CHKERRQ(ierr); 1470 ierr = MatSetUp(j21);CHKERRQ(ierr); 1471 ierr = MatSetUp(j22);CHKERRQ(ierr); 1472 1473 ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr); 1474 ierr = MatSetUp(*J);CHKERRQ(ierr); 1475 ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr); 1476 ierr = MatDestroy(&j11);CHKERRQ(ierr); 1477 ierr = MatDestroy(&j12);CHKERRQ(ierr); 1478 ierr = MatDestroy(&j21);CHKERRQ(ierr); 1479 ierr = MatDestroy(&j22);CHKERRQ(ierr); 1480 1481 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1482 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1483 1484 /* Free structures */ 1485 ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr); 1486 ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr); 1487 1488 PetscFunctionReturn(0); 1489 } else if (!network->userEdgeJacobian && !network->userVertexJacobian) { 1490 /* user does not provide Jacobian blocks */ 1491 ierr = DMCreateMatrix(network->plex,J);CHKERRQ(ierr); 1492 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1493 PetscFunctionReturn(0); 1494 } 1495 1496 ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr); 1497 ierr = DMGetDefaultGlobalSection(network->plex,§ionGlobal);CHKERRQ(ierr); 1498 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr); 1499 ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 1500 1501 ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr); 1502 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1503 1504 /* (1) Set matrix preallocation */ 1505 /*------------------------------*/ 1506 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1507 ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr); 1508 ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr); 1509 ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr); 1510 ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr); 1511 ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr); 1512 1513 /* Set preallocation for edges */ 1514 /*-----------------------------*/ 1515 ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr); 1516 1517 ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr); 1518 for (e=eStart; e<eEnd; e++) { 1519 /* Get row indices */ 1520 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1521 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1522 if (nrows) { 1523 if (!network->Je) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Je"); 1524 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1525 1526 /* Set preallocation for conntected vertices */ 1527 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1528 for (v=0; v<2; v++) { 1529 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1530 1531 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1532 ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr); 1533 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1534 } 1535 1536 /* Set preallocation for edge self */ 1537 cstart = rstart; 1538 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1539 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1540 } 1541 } 1542 1543 /* Set preallocation for vertices */ 1544 /*--------------------------------*/ 1545 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1546 if (vEnd - vStart) { 1547 if (!network->Jv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Jv"); 1548 vptr = network->Jvptr; 1549 if (!vptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide vptr"); 1550 } 1551 1552 for (v=vStart; v<vEnd; v++) { 1553 /* Get row indices */ 1554 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1555 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1556 if (!nrows) continue; 1557 1558 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1559 if (ghost) { 1560 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1561 } else { 1562 rows_v = rows; 1563 } 1564 1565 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1566 1567 /* Get supporting edges and connected vertices */ 1568 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1569 1570 for (e=0; e<nedges; e++) { 1571 /* Supporting edges */ 1572 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1573 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1574 1575 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1576 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1577 1578 /* Connected vertices */ 1579 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1580 vc = (v == cone[0]) ? cone[1]:cone[0]; 1581 ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr); 1582 1583 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1584 1585 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1586 if (ghost_vc||ghost) { 1587 ghost2 = PETSC_TRUE; 1588 } else { 1589 ghost2 = PETSC_FALSE; 1590 } 1591 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr); 1592 } 1593 1594 /* Set preallocation for vertex self */ 1595 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1596 if (!ghost) { 1597 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1598 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1599 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1600 } 1601 if (ghost) { 1602 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1603 } 1604 } 1605 1606 ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr); 1607 ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr); 1608 1609 ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr); 1610 1611 ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr); 1612 ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr); 1613 1614 ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr); 1615 ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr); 1616 for (j=0; j<localSize; j++) { 1617 dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]); 1618 onnz[j] = (PetscInt)PetscRealPart(vonz[j]); 1619 } 1620 ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr); 1621 ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr); 1622 ierr = VecDestroy(&vd_nz);CHKERRQ(ierr); 1623 ierr = VecDestroy(&vo_nz);CHKERRQ(ierr); 1624 1625 ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr); 1626 ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr); 1627 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1628 1629 ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 1630 1631 /* (2) Set matrix entries for edges */ 1632 /*----------------------------------*/ 1633 for (e=eStart; e<eEnd; e++) { 1634 /* Get row indices */ 1635 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1636 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1637 if (nrows) { 1638 if (!network->Je) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Uer must provide Je"); 1639 1640 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1641 1642 /* Set matrix entries for conntected vertices */ 1643 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1644 for (v=0; v<2; v++) { 1645 ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr); 1646 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1647 1648 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1649 ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1650 } 1651 1652 /* Set matrix entries for edge self */ 1653 cstart = rstart; 1654 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1655 ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr); 1656 } 1657 } 1658 1659 /* Set matrix entries for vertices */ 1660 /*---------------------------------*/ 1661 for (v=vStart; v<vEnd; v++) { 1662 /* Get row indices */ 1663 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1664 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1665 if (!nrows) continue; 1666 1667 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1668 if (ghost) { 1669 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1670 } else { 1671 rows_v = rows; 1672 } 1673 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1674 1675 /* Get supporting edges and connected vertices */ 1676 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1677 1678 for (e=0; e<nedges; e++) { 1679 /* Supporting edges */ 1680 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1681 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1682 1683 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1684 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1685 1686 /* Connected vertices */ 1687 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1688 vc = (v == cone[0]) ? cone[1]:cone[0]; 1689 1690 ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr); 1691 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1692 1693 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1694 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1695 } 1696 1697 /* Set matrix entries for vertex self */ 1698 if (!ghost) { 1699 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1700 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1701 ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr); 1702 } 1703 if (ghost) { 1704 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1705 } 1706 } 1707 ierr = PetscFree(rows);CHKERRQ(ierr); 1708 1709 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1710 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1711 1712 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1713 PetscFunctionReturn(0); 1714 } 1715 1716 PetscErrorCode DMDestroy_Network(DM dm) 1717 { 1718 PetscErrorCode ierr; 1719 DM_Network *network = (DM_Network*) dm->data; 1720 PetscInt j; 1721 1722 PetscFunctionBegin; 1723 if (--network->refct > 0) PetscFunctionReturn(0); 1724 if (network->Je) { 1725 ierr = PetscFree(network->Je);CHKERRQ(ierr); 1726 } 1727 if (network->Jv) { 1728 ierr = PetscFree(network->Jvptr);CHKERRQ(ierr); 1729 ierr = PetscFree(network->Jv);CHKERRQ(ierr); 1730 } 1731 1732 ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr); 1733 ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr); 1734 ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr); 1735 if (network->vertex.sf) { 1736 ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr); 1737 } 1738 /* edge */ 1739 ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr); 1740 ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr); 1741 ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr); 1742 if (network->edge.sf) { 1743 ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr); 1744 } 1745 ierr = DMDestroy(&network->plex);CHKERRQ(ierr); 1746 network->edges = NULL; 1747 ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr); 1748 ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr); 1749 1750 for(j=0; j < network->nsubnet; j++) { 1751 ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr); 1752 ierr = PetscFree(network->subnet[j].vertices);CHKERRQ(ierr); 1753 } 1754 ierr = PetscFree(network->subnet);CHKERRQ(ierr); 1755 ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr); 1756 ierr = PetscFree(network->cvalue);CHKERRQ(ierr); 1757 ierr = PetscFree(network->header);CHKERRQ(ierr); 1758 ierr = PetscFree(network);CHKERRQ(ierr); 1759 PetscFunctionReturn(0); 1760 } 1761 1762 PetscErrorCode DMView_Network(DM dm, PetscViewer viewer) 1763 { 1764 PetscErrorCode ierr; 1765 DM_Network *network = (DM_Network*) dm->data; 1766 1767 PetscFunctionBegin; 1768 ierr = DMView(network->plex,viewer);CHKERRQ(ierr); 1769 PetscFunctionReturn(0); 1770 } 1771 1772 PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l) 1773 { 1774 PetscErrorCode ierr; 1775 DM_Network *network = (DM_Network*) dm->data; 1776 1777 PetscFunctionBegin; 1778 ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr); 1779 PetscFunctionReturn(0); 1780 } 1781 1782 PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l) 1783 { 1784 PetscErrorCode ierr; 1785 DM_Network *network = (DM_Network*) dm->data; 1786 1787 PetscFunctionBegin; 1788 ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr); 1789 PetscFunctionReturn(0); 1790 } 1791 1792 PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g) 1793 { 1794 PetscErrorCode ierr; 1795 DM_Network *network = (DM_Network*) dm->data; 1796 1797 PetscFunctionBegin; 1798 ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr); 1799 PetscFunctionReturn(0); 1800 } 1801 1802 PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g) 1803 { 1804 PetscErrorCode ierr; 1805 DM_Network *network = (DM_Network*) dm->data; 1806 1807 PetscFunctionBegin; 1808 ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr); 1809 PetscFunctionReturn(0); 1810 } 1811