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