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