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