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