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