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