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