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 PetscInt nVertices = network->nVertices; 1279 1280 PetscFunctionBegin; 1281 network->userEdgeJacobian = eflg; 1282 network->userVertexJacobian = vflg; 1283 1284 if (eflg && !network->Je) { 1285 ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr); 1286 } 1287 1288 if (vflg && !network->Jv && nVertices) { 1289 PetscInt i,*vptr,nedges,vStart=network->vStart; 1290 PetscInt nedges_total; 1291 const PetscInt *edges; 1292 1293 /* count nvertex_total */ 1294 nedges_total = 0; 1295 ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr); 1296 1297 vptr[0] = 0; 1298 for (i=0; i<nVertices; i++) { 1299 ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr); 1300 nedges_total += nedges; 1301 vptr[i+1] = vptr[i] + 2*nedges + 1; 1302 } 1303 1304 ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr); 1305 network->Jvptr = vptr; 1306 } 1307 PetscFunctionReturn(0); 1308 } 1309 1310 /*@ 1311 DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network 1312 1313 Not Collective 1314 1315 Input Parameters: 1316 + dm - The DMNetwork object 1317 . p - the edge point 1318 - J - array (size = 3) of Jacobian submatrices for this edge point: 1319 J[0]: this edge 1320 J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices() 1321 1322 Level: intermediate 1323 1324 .seealso: DMNetworkVertexSetMatrix 1325 @*/ 1326 PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[]) 1327 { 1328 DM_Network *network=(DM_Network*)dm->data; 1329 1330 PetscFunctionBegin; 1331 if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix"); 1332 1333 if (J) { 1334 network->Je[3*p] = J[0]; 1335 network->Je[3*p+1] = J[1]; 1336 network->Je[3*p+2] = J[2]; 1337 } 1338 PetscFunctionReturn(0); 1339 } 1340 1341 /*@ 1342 DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network 1343 1344 Not Collective 1345 1346 Input Parameters: 1347 + dm - The DMNetwork object 1348 . p - the vertex point 1349 - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point: 1350 J[0]: this vertex 1351 J[1+2*i]: i-th supporting edge 1352 J[1+2*i+1]: i-th connected vertex 1353 1354 Level: intermediate 1355 1356 .seealso: DMNetworkEdgeSetMatrix 1357 @*/ 1358 PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[]) 1359 { 1360 PetscErrorCode ierr; 1361 DM_Network *network=(DM_Network*)dm->data; 1362 PetscInt i,*vptr,nedges,vStart=network->vStart; 1363 const PetscInt *edges; 1364 1365 PetscFunctionBegin; 1366 if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix"); 1367 1368 if (J) { 1369 vptr = network->Jvptr; 1370 network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */ 1371 1372 /* Set Jacobian for each supporting edge and connected vertex */ 1373 ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr); 1374 for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i]; 1375 } 1376 PetscFunctionReturn(0); 1377 } 1378 1379 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1380 { 1381 PetscErrorCode ierr; 1382 PetscInt j; 1383 PetscScalar val=(PetscScalar)ncols; 1384 1385 PetscFunctionBegin; 1386 if (!ghost) { 1387 for (j=0; j<nrows; j++) { 1388 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1389 } 1390 } else { 1391 for (j=0; j<nrows; j++) { 1392 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1393 } 1394 } 1395 PetscFunctionReturn(0); 1396 } 1397 1398 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1399 { 1400 PetscErrorCode ierr; 1401 PetscInt j,ncols_u; 1402 PetscScalar val; 1403 1404 PetscFunctionBegin; 1405 if (!ghost) { 1406 for (j=0; j<nrows; j++) { 1407 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1408 val = (PetscScalar)ncols_u; 1409 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1410 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1411 } 1412 } else { 1413 for (j=0; j<nrows; j++) { 1414 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1415 val = (PetscScalar)ncols_u; 1416 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 1417 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 1418 } 1419 } 1420 PetscFunctionReturn(0); 1421 } 1422 1423 PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 1424 { 1425 PetscErrorCode ierr; 1426 1427 PetscFunctionBegin; 1428 if (Ju) { 1429 ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1430 } else { 1431 ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 1432 } 1433 PetscFunctionReturn(0); 1434 } 1435 1436 PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1437 { 1438 PetscErrorCode ierr; 1439 PetscInt j,*cols; 1440 PetscScalar *zeros; 1441 1442 PetscFunctionBegin; 1443 ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr); 1444 for (j=0; j<ncols; j++) cols[j] = j+ cstart; 1445 ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr); 1446 ierr = PetscFree2(cols,zeros);CHKERRQ(ierr); 1447 PetscFunctionReturn(0); 1448 } 1449 1450 PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1451 { 1452 PetscErrorCode ierr; 1453 PetscInt j,M,N,row,col,ncols_u; 1454 const PetscInt *cols; 1455 PetscScalar zero=0.0; 1456 1457 PetscFunctionBegin; 1458 ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr); 1459 if (nrows != M || ncols != N) SETERRQ4(PetscObjectComm((PetscObject)Ju),PETSC_ERR_USER,"%D by %D must equal %D by %D",nrows,ncols,M,N); 1460 1461 for (row=0; row<nrows; row++) { 1462 ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1463 for (j=0; j<ncols_u; j++) { 1464 col = cols[j] + cstart; 1465 ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr); 1466 } 1467 ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 1468 } 1469 PetscFunctionReturn(0); 1470 } 1471 1472 PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 1473 { 1474 PetscErrorCode ierr; 1475 1476 PetscFunctionBegin; 1477 if (Ju) { 1478 ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1479 } else { 1480 ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1481 } 1482 PetscFunctionReturn(0); 1483 } 1484 1485 /* 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. 1486 */ 1487 PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog) 1488 { 1489 PetscErrorCode ierr; 1490 PetscInt i, size, dof; 1491 PetscInt *glob2loc; 1492 1493 PetscFunctionBegin; 1494 ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr); 1495 ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr); 1496 1497 for (i = 0; i < size; i++) { 1498 ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr); 1499 dof = (dof >= 0) ? dof : -(dof + 1); 1500 glob2loc[i] = dof; 1501 } 1502 1503 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 1504 #if 0 1505 ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1506 #endif 1507 PetscFunctionReturn(0); 1508 } 1509 1510 #include <petsc/private/matimpl.h> 1511 PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J) 1512 { 1513 PetscErrorCode ierr; 1514 PetscMPIInt rank, size; 1515 DM_Network *network = (DM_Network*)dm->data; 1516 PetscInt eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize; 1517 PetscInt cstart,ncols,j,e,v; 1518 PetscBool ghost,ghost_vc,ghost2,isNest; 1519 Mat Juser; 1520 PetscSection sectionGlobal; 1521 PetscInt nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */ 1522 const PetscInt *edges,*cone; 1523 MPI_Comm comm; 1524 MatType mtype; 1525 Vec vd_nz,vo_nz; 1526 PetscInt *dnnz,*onnz; 1527 PetscScalar *vdnz,*vonz; 1528 1529 PetscFunctionBegin; 1530 mtype = dm->mattype; 1531 ierr = PetscStrcmp(mtype, MATNEST, &isNest);CHKERRQ(ierr); 1532 1533 if (isNest) { 1534 /* ierr = DMCreateMatrix_Network_Nest(); */ 1535 PetscInt eDof, vDof; 1536 Mat j11, j12, j21, j22, bA[2][2]; 1537 ISLocalToGlobalMapping eISMap, vISMap; 1538 1539 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1540 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1541 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1542 1543 ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr); 1544 ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr); 1545 1546 ierr = MatCreate(comm, &j11);CHKERRQ(ierr); 1547 ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1548 ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr); 1549 1550 ierr = MatCreate(comm, &j12);CHKERRQ(ierr); 1551 ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr); 1552 ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr); 1553 1554 ierr = MatCreate(comm, &j21);CHKERRQ(ierr); 1555 ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1556 ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr); 1557 1558 ierr = MatCreate(comm, &j22);CHKERRQ(ierr); 1559 ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1560 ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr); 1561 1562 bA[0][0] = j11; 1563 bA[0][1] = j12; 1564 bA[1][0] = j21; 1565 bA[1][1] = j22; 1566 1567 ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr); 1568 ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr); 1569 1570 ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr); 1571 ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr); 1572 ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr); 1573 ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr); 1574 1575 ierr = MatSetUp(j11);CHKERRQ(ierr); 1576 ierr = MatSetUp(j12);CHKERRQ(ierr); 1577 ierr = MatSetUp(j21);CHKERRQ(ierr); 1578 ierr = MatSetUp(j22);CHKERRQ(ierr); 1579 1580 ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr); 1581 ierr = MatSetUp(*J);CHKERRQ(ierr); 1582 ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr); 1583 ierr = MatDestroy(&j11);CHKERRQ(ierr); 1584 ierr = MatDestroy(&j12);CHKERRQ(ierr); 1585 ierr = MatDestroy(&j21);CHKERRQ(ierr); 1586 ierr = MatDestroy(&j22);CHKERRQ(ierr); 1587 1588 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1589 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1590 1591 /* Free structures */ 1592 ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr); 1593 ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr); 1594 1595 PetscFunctionReturn(0); 1596 } else if (!network->userEdgeJacobian && !network->userVertexJacobian) { 1597 /* user does not provide Jacobian blocks */ 1598 ierr = DMCreateMatrix(network->plex,J);CHKERRQ(ierr); 1599 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1600 PetscFunctionReturn(0); 1601 } 1602 1603 ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr); 1604 ierr = DMGetDefaultGlobalSection(network->plex,§ionGlobal);CHKERRQ(ierr); 1605 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr); 1606 ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 1607 1608 ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr); 1609 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1610 1611 /* (1) Set matrix preallocation */ 1612 /*------------------------------*/ 1613 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1614 ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr); 1615 ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr); 1616 ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr); 1617 ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr); 1618 ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr); 1619 1620 /* Set preallocation for edges */ 1621 /*-----------------------------*/ 1622 ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr); 1623 1624 ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr); 1625 for (e=eStart; e<eEnd; e++) { 1626 /* Get row indices */ 1627 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1628 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1629 if (nrows) { 1630 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1631 1632 /* Set preallocation for conntected vertices */ 1633 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1634 for (v=0; v<2; v++) { 1635 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1636 1637 if (network->Je) { 1638 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1639 } else Juser = NULL; 1640 ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr); 1641 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1642 } 1643 1644 /* Set preallocation for edge self */ 1645 cstart = rstart; 1646 if (network->Je) { 1647 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1648 } else Juser = NULL; 1649 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1650 } 1651 } 1652 1653 /* Set preallocation for vertices */ 1654 /*--------------------------------*/ 1655 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 1656 if (vEnd - vStart) vptr = network->Jvptr; 1657 1658 for (v=vStart; v<vEnd; v++) { 1659 /* Get row indices */ 1660 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1661 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1662 if (!nrows) continue; 1663 1664 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1665 if (ghost) { 1666 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1667 } else { 1668 rows_v = rows; 1669 } 1670 1671 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1672 1673 /* Get supporting edges and connected vertices */ 1674 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1675 1676 for (e=0; e<nedges; e++) { 1677 /* Supporting edges */ 1678 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1679 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1680 1681 if (network->Jv) { 1682 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1683 } else Juser = NULL; 1684 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 1685 1686 /* Connected vertices */ 1687 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1688 vc = (v == cone[0]) ? cone[1]:cone[0]; 1689 ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr); 1690 1691 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1692 1693 if (network->Jv) { 1694 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1695 } else Juser = NULL; 1696 if (ghost_vc||ghost) { 1697 ghost2 = PETSC_TRUE; 1698 } else { 1699 ghost2 = PETSC_FALSE; 1700 } 1701 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr); 1702 } 1703 1704 /* Set preallocation for vertex self */ 1705 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1706 if (!ghost) { 1707 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1708 if (network->Jv) { 1709 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1710 } else Juser = NULL; 1711 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 1712 } 1713 if (ghost) { 1714 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1715 } 1716 } 1717 1718 ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr); 1719 ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr); 1720 1721 ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr); 1722 1723 ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr); 1724 ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr); 1725 1726 ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr); 1727 ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr); 1728 for (j=0; j<localSize; j++) { 1729 dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]); 1730 onnz[j] = (PetscInt)PetscRealPart(vonz[j]); 1731 } 1732 ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr); 1733 ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr); 1734 ierr = VecDestroy(&vd_nz);CHKERRQ(ierr); 1735 ierr = VecDestroy(&vo_nz);CHKERRQ(ierr); 1736 1737 ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr); 1738 ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr); 1739 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1740 1741 ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 1742 1743 /* (2) Set matrix entries for edges */ 1744 /*----------------------------------*/ 1745 for (e=eStart; e<eEnd; e++) { 1746 /* Get row indices */ 1747 ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr); 1748 ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr); 1749 if (nrows) { 1750 for (j=0; j<nrows; j++) rows[j] = j + rstart; 1751 1752 /* Set matrix entries for conntected vertices */ 1753 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 1754 for (v=0; v<2; v++) { 1755 ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr); 1756 ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr); 1757 1758 if (network->Je) { 1759 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 1760 } else Juser = NULL; 1761 ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 1762 } 1763 1764 /* Set matrix entries for edge self */ 1765 cstart = rstart; 1766 if (network->Je) { 1767 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 1768 } else Juser = NULL; 1769 ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr); 1770 } 1771 } 1772 1773 /* Set matrix entries for vertices */ 1774 /*---------------------------------*/ 1775 for (v=vStart; v<vEnd; v++) { 1776 /* Get row indices */ 1777 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr); 1778 ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr); 1779 if (!nrows) continue; 1780 1781 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 1782 if (ghost) { 1783 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 1784 } else { 1785 rows_v = rows; 1786 } 1787 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 1788 1789 /* Get supporting edges and connected vertices */ 1790 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1791 1792 for (e=0; e<nedges; e++) { 1793 /* Supporting edges */ 1794 ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr); 1795 ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr); 1796 1797 if (network->Jv) { 1798 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 1799 } else Juser = NULL; 1800 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1801 1802 /* Connected vertices */ 1803 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 1804 vc = (v == cone[0]) ? cone[1]:cone[0]; 1805 1806 ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr); 1807 ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr); 1808 1809 if (network->Jv) { 1810 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 1811 } else Juser = NULL; 1812 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 1813 } 1814 1815 /* Set matrix entries for vertex self */ 1816 if (!ghost) { 1817 ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr); 1818 if (network->Jv) { 1819 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 1820 } else Juser = NULL; 1821 ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr); 1822 } 1823 if (ghost) { 1824 ierr = PetscFree(rows_v);CHKERRQ(ierr); 1825 } 1826 } 1827 ierr = PetscFree(rows);CHKERRQ(ierr); 1828 1829 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1830 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1831 1832 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 1833 PetscFunctionReturn(0); 1834 } 1835 1836 PetscErrorCode DMDestroy_Network(DM dm) 1837 { 1838 PetscErrorCode ierr; 1839 DM_Network *network = (DM_Network*)dm->data; 1840 PetscInt j; 1841 1842 PetscFunctionBegin; 1843 if (--network->refct > 0) PetscFunctionReturn(0); 1844 if (network->Je) { 1845 ierr = PetscFree(network->Je);CHKERRQ(ierr); 1846 } 1847 if (network->Jv) { 1848 ierr = PetscFree(network->Jvptr);CHKERRQ(ierr); 1849 ierr = PetscFree(network->Jv);CHKERRQ(ierr); 1850 } 1851 1852 ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr); 1853 ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr); 1854 ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr); 1855 if (network->vertex.sf) { 1856 ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr); 1857 } 1858 /* edge */ 1859 ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr); 1860 ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr); 1861 ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr); 1862 if (network->edge.sf) { 1863 ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr); 1864 } 1865 ierr = DMDestroy(&network->plex);CHKERRQ(ierr); 1866 network->edges = NULL; 1867 ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr); 1868 ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr); 1869 1870 for(j=0; j < network->nsubnet; j++) { 1871 ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr); 1872 ierr = PetscFree(network->subnet[j].vertices);CHKERRQ(ierr); 1873 } 1874 ierr = PetscFree(network->subnet);CHKERRQ(ierr); 1875 ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr); 1876 ierr = PetscFree(network->cvalue);CHKERRQ(ierr); 1877 ierr = PetscFree(network->header);CHKERRQ(ierr); 1878 ierr = PetscFree(network);CHKERRQ(ierr); 1879 PetscFunctionReturn(0); 1880 } 1881 1882 PetscErrorCode DMView_Network(DM dm,PetscViewer viewer) 1883 { 1884 PetscErrorCode ierr; 1885 DM_Network *network = (DM_Network*)dm->data; 1886 1887 PetscFunctionBegin; 1888 ierr = DMView(network->plex,viewer);CHKERRQ(ierr); 1889 PetscFunctionReturn(0); 1890 } 1891 1892 PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l) 1893 { 1894 PetscErrorCode ierr; 1895 DM_Network *network = (DM_Network*)dm->data; 1896 1897 PetscFunctionBegin; 1898 ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr); 1899 PetscFunctionReturn(0); 1900 } 1901 1902 PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l) 1903 { 1904 PetscErrorCode ierr; 1905 DM_Network *network = (DM_Network*)dm->data; 1906 1907 PetscFunctionBegin; 1908 ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr); 1909 PetscFunctionReturn(0); 1910 } 1911 1912 PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g) 1913 { 1914 PetscErrorCode ierr; 1915 DM_Network *network = (DM_Network*)dm->data; 1916 1917 PetscFunctionBegin; 1918 ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr); 1919 PetscFunctionReturn(0); 1920 } 1921 1922 PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g) 1923 { 1924 PetscErrorCode ierr; 1925 DM_Network *network = (DM_Network*)dm->data; 1926 1927 PetscFunctionBegin; 1928 ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr); 1929 PetscFunctionReturn(0); 1930 } 1931