1 #include <petsc/private/dmnetworkimpl.h> /*I "petscdmnetwork.h" I*/ 2 3 /* 4 Creates the component header and value objects for a network point 5 */ 6 static PetscErrorCode SetUpNetworkHeaderComponentValue(DM dm,DMNetworkComponentHeader header,DMNetworkComponentValue cvalue) 7 { 8 PetscErrorCode ierr; 9 10 PetscFunctionBegin; 11 /* Allocate arrays for component information */ 12 ierr = PetscCalloc5(header->maxcomps,&header->size,header->maxcomps,&header->key,header->maxcomps,&header->offset,header->maxcomps,&header->nvar,header->maxcomps,&header->offsetvarrel);CHKERRQ(ierr); 13 ierr = PetscCalloc1(header->maxcomps,&cvalue->data);CHKERRQ(ierr); 14 15 /* The size of the header is the size of struct _p_DMNetworkComponentHeader. Since the struct contains PetscInt pointers we cannot use sizeof(struct). So, we need to explicitly calculate the size. 16 If the data header struct changes then this header size calculation needs to be updated. */ 17 header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt); 18 header->hsize /= sizeof(DMNetworkComponentGenericDataType); 19 PetscFunctionReturn(0); 20 } 21 22 /*@ 23 DMNetworkGetPlex - Gets the Plex DM associated with this network DM 24 25 Not collective 26 27 Input Parameters: 28 . dm - the dm object 29 30 Output Parameters: 31 . plexdm - the plex dm object 32 33 Level: Advanced 34 35 .seealso: DMNetworkCreate() 36 @*/ 37 PetscErrorCode DMNetworkGetPlex(DM dm,DM *plexdm) 38 { 39 DM_Network *network = (DM_Network*)dm->data; 40 41 PetscFunctionBegin; 42 *plexdm = network->plex; 43 PetscFunctionReturn(0); 44 } 45 46 /*@ 47 DMNetworkGetNumSubNetworks - Gets the the number of subnetworks 48 49 Not collective 50 51 Input Parameter: 52 . dm - the dm object 53 54 Output Parameters: 55 + nsubnet - local number of subnetworks 56 - Nsubnet - global number of subnetworks 57 58 Level: beginner 59 60 .seealso: DMNetworkCreate(), DMNetworkSetNumSubNetworks() 61 @*/ 62 PetscErrorCode DMNetworkGetNumSubNetworks(DM dm,PetscInt *nsubnet,PetscInt *Nsubnet) 63 { 64 DM_Network *network = (DM_Network*)dm->data; 65 66 PetscFunctionBegin; 67 if (nsubnet) *nsubnet = network->nsubnet; 68 if (Nsubnet) *Nsubnet = network->Nsubnet; 69 PetscFunctionReturn(0); 70 } 71 72 /*@ 73 DMNetworkSetNumSubNetworks - Sets the number of subnetworks 74 75 Collective on dm 76 77 Input Parameters: 78 + dm - the dm object 79 . nsubnet - local number of subnetworks 80 - Nsubnet - global number of subnetworks 81 82 Level: beginner 83 84 .seealso: DMNetworkCreate(), DMNetworkGetNumSubNetworks() 85 @*/ 86 PetscErrorCode DMNetworkSetNumSubNetworks(DM dm,PetscInt nsubnet,PetscInt Nsubnet) 87 { 88 PetscErrorCode ierr; 89 DM_Network *network = (DM_Network*)dm->data; 90 91 PetscFunctionBegin; 92 PetscCheckFalse(network->Nsubnet != 0,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network"); 93 94 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 95 PetscValidLogicalCollectiveInt(dm,nsubnet,2); 96 PetscValidLogicalCollectiveInt(dm,Nsubnet,3); 97 98 if (Nsubnet == PETSC_DECIDE) { 99 PetscCheckFalse(nsubnet < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of local subnetworks %D cannot be less than 0",nsubnet); 100 ierr = MPIU_Allreduce(&nsubnet,&Nsubnet,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 101 } 102 PetscCheckFalse(Nsubnet < 1,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Number of global subnetworks %D cannot be less than 1",Nsubnet); 103 104 network->Nsubnet = Nsubnet; 105 network->nsubnet = 0; /* initia value; will be determind by DMNetworkAddSubnetwork() */ 106 ierr = PetscCalloc1(Nsubnet,&network->subnet);CHKERRQ(ierr); 107 108 /* num of shared vertices */ 109 network->nsvtx = 0; 110 network->Nsvtx = 0; 111 PetscFunctionReturn(0); 112 } 113 114 /*@ 115 DMNetworkAddSubnetwork - Add a subnetwork 116 117 Collective on dm 118 119 Input Parameters: 120 + dm - the dm object 121 . name - name of the subnetwork 122 . ne - number of local edges of this subnetwork 123 - edgelist - list of edges for this subnetwork, this is a one dimensional array with pairs of entries being the two vertices (in global numbering of the vertices) of each edge, 124 $ [first vertex of first edge, second vertex of first edge, first vertex of second edge, second vertex of second edge, etc] 125 126 Output Parameters: 127 . netnum - global index of the subnetwork 128 129 Notes: 130 There is no copy involved in this operation, only the pointer is referenced. The edgelist should 131 not be destroyed before the call to DMNetworkLayoutSetUp() 132 133 A network can comprise of a single subnetwork OR multiple subnetworks. For a single subnetwork, the subnetwork can be read either in serial or parallel. For a multiple subnetworks, 134 each subnetwork topology needs to be set on a unique rank and the communicator size needs to be at least equal to the number of subnetworks. 135 136 Level: beginner 137 138 Example usage: 139 Consider the following networks: 140 1) A sigle subnetwork: 141 .vb 142 network 0: 143 rank[0]: 144 v0 --> v2; v1 --> v2 145 rank[1]: 146 v3 --> v5; v4 --> v5 147 .ve 148 149 The resulting input 150 network 0: 151 rank[0]: 152 ne = 2 153 edgelist = [0 2 | 1 2] 154 rank[1]: 155 ne = 2 156 edgelist = [3 5 | 4 5] 157 158 2) Two subnetworks: 159 .vb 160 subnetwork 0: 161 rank[0]: 162 v0 --> v2; v2 --> v1; v1 --> v3; 163 subnetwork 1: 164 rank[1]: 165 v0 --> v3; v3 --> v2; v2 --> v1; 166 .ve 167 168 The resulting input 169 subnetwork 0: 170 rank[0]: 171 ne = 3 172 edgelist = [0 2 | 2 1 | 1 3] 173 rank[1]: 174 ne = 0 175 edgelist = NULL 176 177 subnetwork 1: 178 rank[0]: 179 ne = 0 180 edgelist = NULL 181 rank[1]: 182 edgelist = [0 3 | 3 2 | 2 1] 183 184 .seealso: DMNetworkCreate(), DMNetworkSetNumSubnetworks() 185 @*/ 186 PetscErrorCode DMNetworkAddSubnetwork(DM dm,const char* name,PetscInt ne,PetscInt edgelist[],PetscInt *netnum) 187 { 188 PetscErrorCode ierr; 189 DM_Network *network = (DM_Network*)dm->data; 190 PetscInt i,Nedge,j,Nvtx,nvtx; 191 PetscBT table; 192 193 PetscFunctionBegin; 194 for (i=0; i<ne; i++) { 195 PetscCheckFalse(edgelist[2*i] == edgelist[2*i+1],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Edge %D has the same vertex %D at each endpoint",i,edgelist[2*i]); 196 } 197 /* Get global total Nvtx = max(edgelist[])+1 for this subnet */ 198 nvtx = -1; i = 0; 199 for (j=0; j<ne; j++) { 200 nvtx = PetscMax(nvtx, edgelist[i]); i++; 201 nvtx = PetscMax(nvtx, edgelist[i]); i++; 202 } 203 nvtx++; 204 ierr = MPIU_Allreduce(&nvtx,&Nvtx,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 205 206 /* Get local nvtx for this subnet */ 207 ierr = PetscBTCreate(Nvtx,&table);CHKERRQ(ierr); 208 ierr = PetscBTMemzero(Nvtx,table);CHKERRQ(ierr); 209 i = 0; 210 for (j=0; j<ne; j++) { 211 ierr = PetscBTSet(table,edgelist[i]);CHKERRQ(ierr); 212 i++; 213 ierr = PetscBTSet(table,edgelist[i]);CHKERRQ(ierr); 214 i++; 215 } 216 nvtx = 0; 217 for (j=0; j<Nvtx; j++) { 218 if (PetscBTLookup(table,j)) nvtx++; 219 } 220 ierr = PetscBTDestroy(&table);CHKERRQ(ierr); 221 222 /* Get global total Nedge for this subnet */ 223 ierr = MPIU_Allreduce(&ne,&Nedge,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 224 225 i = network->nsubnet; 226 if (name) { 227 ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr); 228 } 229 network->subnet[i].nvtx = nvtx; /* include ghost vertices */ 230 network->subnet[i].nedge = ne; 231 network->subnet[i].edgelist = edgelist; 232 network->subnet[i].Nvtx = Nvtx; 233 network->subnet[i].Nedge = Nedge; 234 235 /* ---------------------------------------------------------- 236 p=v or e; 237 subnet[0].pStart = 0 238 subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i]) 239 ----------------------------------------------------------------------- */ 240 /* GLOBAL subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */ 241 network->subnet[i].vStart = network->NVertices; 242 network->subnet[i].vEnd = network->subnet[i].vStart + network->subnet[i].Nvtx; /* global vEnd of subnet[i] */ 243 244 network->nVertices += nvtx; /* include ghost vertices */ 245 network->NVertices += network->subnet[i].Nvtx; 246 247 /* LOCAL subnet[].eStart and eEnd, used by DMNetworkLayoutSetUp() */ 248 network->subnet[i].eStart = network->nEdges; 249 network->subnet[i].eEnd = network->subnet[i].eStart + ne; 250 network->nEdges += ne; 251 network->NEdges += network->subnet[i].Nedge; 252 253 ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr); 254 if (netnum) *netnum = network->nsubnet; 255 network->nsubnet++; 256 PetscFunctionReturn(0); 257 } 258 259 /* 260 SetUp a single svtx struct. See SVtx defined in dmnetworkimpl.h 261 Set gidx and type if input v=(net,idx) is a from_vertex; 262 Get gid, type and index in the svtx array if input v=(net,idx) is a to_vertex. 263 264 Input: Nsvtx, svtx, net, idx, gidx 265 Output: gidx, svtype, svtx_idx 266 */ 267 static PetscErrorCode SVtxSetUp(PetscInt Nsvtx,SVtx *svtx,PetscInt net,PetscInt idx,PetscInt *gidx,SVtxType *svtype,PetscInt *svtx_idx) 268 { 269 PetscInt i,j,*svto; 270 SVtxType vtype; 271 272 PetscFunctionBegin; 273 if (!Nsvtx) PetscFunctionReturn(0); 274 275 vtype = SVNONE; 276 for (i=0; i<Nsvtx; i++) { 277 if (net == svtx[i].sv[0] && idx == svtx[i].sv[1]) { 278 /* (1) input vertex net.idx is a shared from_vertex, set its global index and output its svtype */ 279 svtx[i].gidx = *gidx; /* set gidx */ 280 vtype = SVFROM; 281 } else { /* loop over svtx[i].n */ 282 for (j=1; j<svtx[i].n; j++) { 283 svto = svtx[i].sv + 2*j; 284 if (net == svto[0] && idx == svto[1]) { 285 /* input vertex net.idx is a shared to_vertex, output its global index and its svtype */ 286 *gidx = svtx[i].gidx; /* output gidx for to_vertex */ 287 vtype = SVTO; 288 } 289 } 290 } 291 if (vtype != SVNONE) break; 292 } 293 if (svtype) *svtype = vtype; 294 if (svtx_idx) *svtx_idx = i; 295 PetscFunctionReturn(0); 296 } 297 298 /* 299 Add a new shared vertex sv=(net,idx) to table svtas[ita] 300 */ 301 static PetscErrorCode TableAddSVtx(PetscTable *svtas,PetscInt ita,PetscInt* tdata,PetscInt *sv_wk,PetscInt *ii,PetscInt *sedgelist,PetscInt k,DM_Network *network,PetscInt **ta2sv) 302 { 303 PetscInt net,idx,gidx,i=*ii; 304 PetscErrorCode ierr; 305 306 PetscFunctionBegin; 307 net = sv_wk[2*i] = sedgelist[k]; 308 idx = sv_wk[2*i+1] = sedgelist[k+1]; 309 gidx = network->subnet[net].vStart + idx; 310 ierr = PetscTableAdd(svtas[ita],gidx+1,tdata[ita]+1,INSERT_VALUES);CHKERRQ(ierr); 311 *(ta2sv[ita] + tdata[ita]) = i; /* maps tdata to index of sv_wk; sv_wk keeps (net,idx) info */ 312 tdata[ita]++; (*ii)++; 313 PetscFunctionReturn(0); 314 } 315 316 /* 317 Create an array of shared vertices. See SVtx and SVtxType in dmnetworkimpl.h 318 319 Input: dm, Nsedgelist, sedgelist 320 Output: Nsvtx,svtx 321 322 Note: Output svtx is organized as 323 sv(net[0],idx[0]) --> sv(net[1],idx[1]) 324 --> sv(net[1],idx[1]) 325 ... 326 --> sv(net[n-1],idx[n-1]) 327 and net[0] < net[1] < ... < net[n-1] 328 where sv[0] has SVFROM type, sv[i], i>0, has SVTO type. 329 */ 330 static PetscErrorCode SVtxCreate(DM dm,PetscInt Nsedgelist,PetscInt *sedgelist,PetscInt *Nsvtx,SVtx **svtx) 331 { 332 PetscErrorCode ierr; 333 SVtx *sedges = NULL; 334 PetscInt *sv,k,j,nsv,*tdata,**ta2sv; 335 PetscTable *svtas; 336 PetscInt gidx,net,idx,i,nta,ita,idx_from,idx_to,n,*sv_wk; 337 DM_Network *network = (DM_Network*)dm->data; 338 PetscTablePosition ppos; 339 340 PetscFunctionBegin; 341 /* (1) Crete ctables svtas */ 342 ierr = PetscCalloc4(Nsedgelist,&svtas,Nsedgelist,&tdata,4*Nsedgelist,&sv_wk,2*Nsedgelist,&ta2sv);CHKERRQ(ierr); 343 344 j = 0; /* sedgelist counter */ 345 k = 0; /* sedgelist vertex counter j = 4*k */ 346 i = 0; /* sv_wk (vertices added to the ctables) counter */ 347 nta = 0; /* num of sv tables created */ 348 349 /* for j=0 */ 350 ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr); 351 ierr = PetscMalloc1(2*Nsedgelist,&ta2sv[nta]);CHKERRQ(ierr); 352 353 ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr); 354 ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr); 355 nta++; k += 4; 356 357 for (j = 1; j < Nsedgelist; j++) { 358 for (ita = 0; ita < nta; ita++) { 359 /* vfrom */ 360 net = sedgelist[k]; idx = sedgelist[k+1]; 361 gidx = network->subnet[net].vStart + idx; /* global index of the vertex net.idx before merging shared vertices */ 362 ierr = PetscTableFind(svtas[ita],gidx+1,&idx_from);CHKERRQ(ierr); 363 364 /* vto */ 365 net = sedgelist[k+2]; idx = sedgelist[k+3]; 366 gidx = network->subnet[net].vStart + idx; 367 ierr = PetscTableFind(svtas[ita],gidx+1,&idx_to);CHKERRQ(ierr); 368 369 if (idx_from || idx_to) { /* vfrom or vto is on table svtas[ita] */ 370 idx_from--; idx_to--; 371 if (idx_from < 0) { /* vto is on svtas[ita] */ 372 ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr); 373 break; 374 } else if (idx_to < 0) { 375 ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr); 376 break; 377 } 378 } 379 } 380 381 if (ita == nta) { 382 ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr); 383 ierr = PetscMalloc1(2*Nsedgelist, &ta2sv[nta]);CHKERRQ(ierr); 384 385 ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr); 386 ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr); 387 nta++; 388 } 389 k += 4; 390 } 391 392 /* (2) Construct sedges from ctable 393 sedges: edges connect vertex sv[0]=(net[0],idx[0]) to vertices sv[k], k=1,...,n-1; 394 net[k], k=0, ...,n-1, are in ascending order */ 395 ierr = PetscMalloc1(nta,&sedges);CHKERRQ(ierr); 396 for (nsv = 0; nsv < nta; nsv++) { 397 /* for a single svtx, put shared vertices in ascending order of gidx */ 398 ierr = PetscTableGetCount(svtas[nsv],&n);CHKERRQ(ierr); 399 ierr = PetscCalloc1(2*n,&sv);CHKERRQ(ierr); 400 sedges[nsv].sv = sv; 401 sedges[nsv].n = n; 402 sedges[nsv].gidx = -1; /* initialization */ 403 404 ierr = PetscTableGetHeadPosition(svtas[nsv],&ppos);CHKERRQ(ierr); 405 for (k=0; k<n; k++) { /* gidx is sorted in ascending order */ 406 ierr = PetscTableGetNext(svtas[nsv],&ppos,&gidx,&i);CHKERRQ(ierr); 407 gidx--; i--; 408 409 j = ta2sv[nsv][i]; /* maps i to index of sv_wk */ 410 sv[2*k] = sv_wk[2*j]; 411 sv[2*k+1] = sv_wk[2*j + 1]; 412 } 413 } 414 415 for (j=0; j<nta; j++) { 416 ierr = PetscTableDestroy(&svtas[j]);CHKERRQ(ierr); 417 ierr = PetscFree(ta2sv[j]);CHKERRQ(ierr); 418 } 419 ierr = PetscFree4(svtas,tdata,sv_wk,ta2sv);CHKERRQ(ierr); 420 421 *Nsvtx = nta; 422 *svtx = sedges; 423 PetscFunctionReturn(0); 424 } 425 426 static PetscErrorCode GetEdgelist_Coupling(DM dm,PetscInt *edges,PetscInt *nmerged_ptr,PetscInt *Nsv_ptr,SVtx **svtx_ptr) 427 { 428 PetscErrorCode ierr; 429 MPI_Comm comm; 430 PetscMPIInt size,rank,*recvcounts=NULL,*displs=NULL; 431 DM_Network *network = (DM_Network*)dm->data; 432 PetscInt i,j,ctr,np; 433 PetscInt *vidxlTog,Nsv=0,Nsubnet=network->Nsubnet; 434 PetscInt *sedgelist=network->sedgelist; 435 PetscInt net,idx,gidx,nmerged,v,*vrange,gidx_from,net_from,sv_idx; 436 SVtxType svtype = SVNONE; 437 SVtx *svtx=NULL; 438 439 PetscFunctionBegin; 440 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 441 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 442 ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 443 444 /* (1) Create svtx[] from sedgelist */ 445 /* -------------------------------- */ 446 /* Nsv: global number of SVtx; svtx: shared vertices, see SVtx in dmnetworkimpl.h */ 447 ierr = SVtxCreate(dm,network->Nsvtx,sedgelist,&Nsv,&svtx);CHKERRQ(ierr); 448 449 /* (2) Setup svtx; Shared vto vertices are merged to their vfrom vertex with same global vetex index (gidx) */ 450 /* -------------------------------------------------------------------------------------------------------- */ 451 /* (2.1) compute vrage[rank]: global index of 1st local vertex in proc[rank] */ 452 ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr); 453 for (i=0; i<size; i++) {displs[i] = i; recvcounts[i] = 1;} 454 455 vrange[0] = 0; 456 ierr = MPI_Allgatherv(&network->nVertices,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr); 457 for (i=2; i<size+1; i++) { 458 vrange[i] += vrange[i-1]; 459 } 460 461 /* (2.2) Create vidxlTog: maps UN-MERGED local vertex index i to global index gidx (plex, excluding ghost vertices) */ 462 ierr = PetscMalloc1(network->nVertices,&vidxlTog);CHKERRQ(ierr); 463 i = 0; gidx = 0; 464 nmerged = 0; /* local num of merged vertices */ 465 network->nsvtx = 0; 466 for (net=0; net<Nsubnet; net++) { 467 for (idx=0; idx<network->subnet[net].Nvtx; idx++) { 468 gidx_from = gidx; 469 sv_idx = -1; 470 471 ierr = SVtxSetUp(Nsv,svtx,net,idx,&gidx_from,&svtype,&sv_idx);CHKERRQ(ierr); 472 if (svtype == SVTO) { 473 if (network->subnet[net].nvtx) {/* this proc owns sv_to */ 474 net_from = svtx[sv_idx].sv[0]; /* subnet num of its shared vertex */ 475 if (network->subnet[net_from].nvtx == 0) { 476 /* this proc does not own v_from, thus a new local coupling vertex */ 477 network->nsvtx++; 478 } 479 vidxlTog[i++] = gidx_from; 480 nmerged++; /* a coupling vertex -- merged */ 481 } 482 } else { 483 if (svtype == SVFROM) { 484 if (network->subnet[net].nvtx) { 485 /* this proc owns this v_from, a new local coupling vertex */ 486 network->nsvtx++; 487 } 488 } 489 if (network->subnet[net].nvtx) vidxlTog[i++] = gidx; 490 gidx++; 491 } 492 } 493 } 494 #if defined(PETSC_USE_DEBUG) 495 PetscCheckFalse(i != network->nVertices,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"%D != %D nVertices",i,network->nVertices); 496 #endif 497 498 /* (2.3) Setup svtable for querry shared vertices */ 499 for (v=0; v<Nsv; v++) { 500 gidx = svtx[v].gidx; 501 ierr = PetscTableAdd(network->svtable,gidx+1,v+1,INSERT_VALUES);CHKERRQ(ierr); 502 } 503 504 /* (2.4) Shared vertices in the subnetworks are merged, update global NVertices: np = sum(local nmerged) */ 505 ierr = MPI_Allreduce(&nmerged,&np,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr); 506 network->NVertices -= np; 507 508 ctr = 0; 509 for (net=0; net<Nsubnet; net++) { 510 for (j = 0; j < network->subnet[net].nedge; j++) { 511 /* vfrom: */ 512 i = network->subnet[net].edgelist[2*j] + (network->subnet[net].vStart - vrange[rank]); 513 edges[2*ctr] = vidxlTog[i]; 514 515 /* vto */ 516 i = network->subnet[net].edgelist[2*j+1] + (network->subnet[net].vStart - vrange[rank]); 517 edges[2*ctr+1] = vidxlTog[i]; 518 ctr++; 519 } 520 } 521 ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr); 522 ierr = PetscFree(vidxlTog);CHKERRQ(ierr); 523 524 *nmerged_ptr = nmerged; 525 *Nsv_ptr = Nsv; 526 *svtx_ptr = svtx; 527 ierr = PetscFree(sedgelist);CHKERRQ(ierr); /* created in DMNetworkAddSharedVertices() */ 528 PetscFunctionReturn(0); 529 } 530 531 /*@ 532 DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network 533 534 Not Collective 535 536 Input Parameters: 537 . dm - the dmnetwork object 538 539 Notes: 540 This routine should be called after the network sizes and edgelists have been provided. It creates 541 the bare layout of the network and sets up the network to begin insertion of components. 542 543 All the components should be registered before calling this routine. 544 545 Level: beginner 546 547 .seealso: DMNetworkSetNumSubNetworks(), DMNetworkAddSubnetwork() 548 @*/ 549 PetscErrorCode DMNetworkLayoutSetUp(DM dm) 550 { 551 PetscErrorCode ierr; 552 DM_Network *network = (DM_Network*)dm->data; 553 PetscInt i,j,ctr,Nsubnet=network->Nsubnet,*eowners,np,*edges,*subnetvtx,*subnetedge,e,v,vfrom,vto,net; 554 const PetscInt *cone; 555 MPI_Comm comm; 556 PetscMPIInt size,rank; 557 PetscSection sectiong; 558 PetscInt nmerged=0,Nsv=0; 559 SVtx *svtx=NULL; 560 561 PetscFunctionBegin; 562 PetscCheckFalse(network->nsubnet != network->Nsubnet,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Must call DMNetworkAddSubnetwork() %D times",network->Nsubnet); 563 564 /* This implementation requires user input each subnet by a single processor when Nsubnet>1, thus subnet[net].nvtx=subnet[net].Nvtx when net>0 */ 565 for (net=1; net<Nsubnet; net++) { 566 PetscCheckFalse(network->subnet[net].nvtx && network->subnet[net].nvtx != network->subnet[net].Nvtx,PETSC_COMM_SELF,PETSC_ERR_SUP,"subnetwork %D local num of vertices %D != %D global num",net,network->subnet[net].nvtx,network->subnet[net].Nvtx); 567 } 568 569 /* Create svtable for querry shared vertices */ 570 ierr = PetscTableCreate(network->Nsvtx,network->NVertices+1,&network->svtable);CHKERRQ(ierr); 571 572 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 573 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 574 ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 575 576 /* Create LOCAL edgelist in global vertex ordering for the network by concatenating local input edgelists of the subnetworks */ 577 ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr); 578 579 if (network->Nsvtx) { /* subnetworks are coupled via shared vertices */ 580 ierr = GetEdgelist_Coupling(dm,edges,&nmerged,&Nsv,&svtx);CHKERRMPI(ierr); 581 } else { /* subnetworks are not coupled */ 582 ctr = 0; 583 for (i=0; i < Nsubnet; i++) { 584 for (j = 0; j < network->subnet[i].nedge; j++) { 585 edges[2*ctr] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j]; 586 edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1]; 587 ctr++; 588 } 589 } 590 } 591 network->svtx = svtx; 592 network->Nsvtx = Nsv; 593 594 /* Create network->plex; One dimensional network, numCorners=2 */ 595 ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr); 596 ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr); 597 ierr = DMSetDimension(network->plex,1);CHKERRQ(ierr); 598 599 if (size == 1) { 600 ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices-nmerged,2,edges);CHKERRQ(ierr); 601 } else { 602 ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices-nmerged,PETSC_DECIDE,2,edges,NULL, NULL);CHKERRQ(ierr); 603 } 604 605 ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr); 606 ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr); 607 ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr); 608 609 ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr); 610 ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr); 611 ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr); 612 ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr); 613 614 np = network->pEnd - network->pStart; 615 ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr); 616 for (i=0; i < np; i++) { 617 network->header[i].maxcomps = 1; 618 ierr = SetUpNetworkHeaderComponentValue(dm,&network->header[i],&network->cvalue[i]);CHKERRQ(ierr); 619 } 620 621 /* Create edge and vertex arrays for the subnetworks 622 This implementation assumes that DMNetwork reads 623 (1) a single subnetwork in parallel; or 624 (2) n subnetworks using n processors, one subnetwork/processor. 625 */ 626 ierr = PetscCalloc2(network->nEdges,&subnetedge,network->nVertices+network->nsvtx,&subnetvtx);CHKERRQ(ierr); /* Maps local edge/vertex to local subnetwork's edge/vertex */ 627 network->subnetedge = subnetedge; 628 network->subnetvtx = subnetvtx; 629 for (j=0; j < network->Nsubnet; j++) { 630 network->subnet[j].edges = subnetedge; 631 subnetedge += network->subnet[j].nedge; 632 633 network->subnet[j].vertices = subnetvtx; 634 subnetvtx += network->subnet[j].nvtx; 635 } 636 network->svertices = subnetvtx; 637 638 /* Get edge ownership */ 639 ierr = PetscMalloc1(size+1,&eowners);CHKERRQ(ierr); 640 np = network->eEnd - network->eStart; 641 ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr); 642 eowners[0] = 0; 643 for (i=2; i<=size; i++) eowners[i] += eowners[i-1]; 644 645 /* Setup local edge and vertex arrays for subnetworks */ 646 e = 0; 647 for (i=0; i < Nsubnet; i++) { 648 ctr = 0; 649 for (j = 0; j < network->subnet[i].nedge; j++) { 650 /* edge e */ 651 network->header[e].index = e + eowners[rank]; /* Global edge index */ 652 network->header[e].subnetid = i; 653 network->subnet[i].edges[j] = e; 654 655 network->header[e].ndata = 0; 656 network->header[e].offset[0] = 0; 657 network->header[e].offsetvarrel[0] = 0; 658 ierr = PetscSectionAddDof(network->DataSection,e,network->header[e].hsize);CHKERRQ(ierr); 659 660 /* connected vertices */ 661 ierr = DMPlexGetCone(network->plex,e,&cone);CHKERRQ(ierr); 662 663 /* vertex cone[0] */ 664 v = cone[0]; 665 network->header[v].index = edges[2*e]; /* Global vertex index */ 666 network->header[v].subnetid = i; /* Subnetwork id */ 667 if (Nsubnet == 1) { 668 network->subnet[i].vertices[v - network->vStart] = v; /* user's subnet[].idx = petsc's v */ 669 } else { 670 vfrom = network->subnet[i].edgelist[2*ctr]; /* =subnet[i].idx, Global index! */ 671 network->subnet[i].vertices[vfrom] = v; /* user's subnet[].dix = petsc's v */ 672 } 673 674 /* vertex cone[1] */ 675 v = cone[1]; 676 network->header[v].index = edges[2*e+1]; /* Global vertex index */ 677 network->header[v].subnetid = i; /* Subnetwork id */ 678 if (Nsubnet == 1) { 679 network->subnet[i].vertices[v - network->vStart] = v; /* user's subnet[].idx = petsc's v */ 680 } else { 681 vto = network->subnet[i].edgelist[2*ctr+1]; /* =subnet[i].idx, Global index! */ 682 network->subnet[i].vertices[vto] = v; /* user's subnet[].dix = petsc's v */ 683 } 684 685 e++; ctr++; 686 } 687 } 688 ierr = PetscFree(eowners);CHKERRQ(ierr); 689 ierr = PetscFree(edges);CHKERRQ(ierr); /* local edge list with global idx used by DMPlexBuildFromCellList() */ 690 691 /* Set local vertex array for the subnetworks */ 692 j = 0; 693 for (v = network->vStart; v < network->vEnd; v++) { 694 network->header[v].ndata = 0; 695 network->header[v].offset[0] = 0; 696 network->header[v].offsetvarrel[0] = 0; 697 ierr = PetscSectionAddDof(network->DataSection,v,network->header[e].hsize);CHKERRQ(ierr); 698 699 /* local shared vertex */ 700 ierr = PetscTableFind(network->svtable,network->header[v].index+1,&i);CHKERRQ(ierr); 701 if (i) network->svertices[j++] = v; 702 } 703 704 /* Create a global section to be used by DMNetworkIsGhostVertex() which is a non-collective routine */ 705 /* see snes_tutorials_network-ex1_4 */ 706 ierr = DMGetGlobalSection(network->plex,§iong);CHKERRQ(ierr); 707 PetscFunctionReturn(0); 708 } 709 710 /*@C 711 DMNetworkGetSubnetwork - Returns the information about a requested subnetwork 712 713 Not collective 714 715 Input Parameters: 716 + dm - the DM object 717 - netnum - the global index of the subnetwork 718 719 Output Parameters: 720 + nv - number of vertices (local) 721 . ne - number of edges (local) 722 . vtx - local vertices of the subnetwork 723 - edge - local edges of the subnetwork 724 725 Notes: 726 Cannot call this routine before DMNetworkLayoutSetup() 727 728 The local vertices returned on each rank are determined by DMNetwork. The user does not have any control over what vertices are local. 729 730 Level: intermediate 731 732 .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkLayoutSetUp() 733 @*/ 734 PetscErrorCode DMNetworkGetSubnetwork(DM dm,PetscInt netnum,PetscInt *nv,PetscInt *ne,const PetscInt **vtx,const PetscInt **edge) 735 { 736 DM_Network *network = (DM_Network*)dm->data; 737 738 PetscFunctionBegin; 739 PetscCheckFalse(netnum >= network->Nsubnet,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Subnet index %D exceeds the num of subnets %D",netnum,network->Nsubnet); 740 if (nv) *nv = network->subnet[netnum].nvtx; 741 if (ne) *ne = network->subnet[netnum].nedge; 742 if (vtx) *vtx = network->subnet[netnum].vertices; 743 if (edge) *edge = network->subnet[netnum].edges; 744 PetscFunctionReturn(0); 745 } 746 747 /*@ 748 DMNetworkAddSharedVertices - Add shared vertices that connect two given subnetworks 749 750 Collective on dm 751 752 Input Parameters: 753 + dm - the dm object 754 . anetnum - first subnetwork global numbering returned by DMNetworkAddSubnetwork() 755 . bnetnum - second subnetwork global numbering returned by DMNetworkAddSubnetwork() 756 . nsvtx - number of vertices that are shared by the two subnetworks 757 . asvtx - vertex index in the first subnetwork 758 - bsvtx - vertex index in the second subnetwork 759 760 Level: beginner 761 762 .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkGetSharedVertices() 763 @*/ 764 PetscErrorCode DMNetworkAddSharedVertices(DM dm,PetscInt anetnum,PetscInt bnetnum,PetscInt nsvtx,PetscInt asvtx[],PetscInt bsvtx[]) 765 { 766 PetscErrorCode ierr; 767 DM_Network *network = (DM_Network*)dm->data; 768 PetscInt i,nsubnet = network->Nsubnet,*sedgelist,Nsvtx=network->Nsvtx; 769 770 PetscFunctionBegin; 771 PetscCheckFalse(anetnum == bnetnum,PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Subnetworks must have different netnum"); 772 PetscCheckFalse(anetnum < 0 || bnetnum < 0,PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"netnum cannot be negative"); 773 if (!Nsvtx) { 774 /* allocate network->sedgelist to hold at most 2*nsubnet pairs of shared vertices */ 775 ierr = PetscMalloc1(2*4*nsubnet,&network->sedgelist);CHKERRQ(ierr); 776 } 777 778 sedgelist = network->sedgelist; 779 for (i=0; i<nsvtx; i++) { 780 sedgelist[4*Nsvtx] = anetnum; sedgelist[4*Nsvtx+1] = asvtx[i]; 781 sedgelist[4*Nsvtx+2] = bnetnum; sedgelist[4*Nsvtx+3] = bsvtx[i]; 782 Nsvtx++; 783 } 784 PetscCheckFalse(Nsvtx > 2*nsubnet,PETSC_COMM_SELF,PETSC_ERR_SUP,"allocate more space for coupling edgelist"); 785 network->Nsvtx = Nsvtx; 786 PetscFunctionReturn(0); 787 } 788 789 /*@C 790 DMNetworkGetSharedVertices - Returns the info for the shared vertices 791 792 Not collective 793 794 Input Parameter: 795 . dm - the DM object 796 797 Output Parameters: 798 + nsv - number of local shared vertices 799 - svtx - local shared vertices 800 801 Notes: 802 Cannot call this routine before DMNetworkLayoutSetup() 803 804 Level: intermediate 805 806 .seealso: DMNetworkGetSubnetwork(), DMNetworkLayoutSetUp(), DMNetworkAddSharedVertices() 807 @*/ 808 PetscErrorCode DMNetworkGetSharedVertices(DM dm,PetscInt *nsv,const PetscInt **svtx) 809 { 810 DM_Network *net = (DM_Network*)dm->data; 811 812 PetscFunctionBegin; 813 if (net->Nsvtx) { 814 *nsv = net->nsvtx; 815 *svtx = net->svertices; 816 } else { 817 *nsv = 0; 818 *svtx = NULL; 819 } 820 PetscFunctionReturn(0); 821 } 822 823 /*@C 824 DMNetworkRegisterComponent - Registers the network component 825 826 Logically collective on dm 827 828 Input Parameters: 829 + dm - the network object 830 . name - the component name 831 - size - the storage size in bytes for this component data 832 833 Output Parameters: 834 . key - an integer key that defines the component 835 836 Notes 837 This routine should be called by all processors before calling DMNetworkLayoutSetup(). 838 839 Level: beginner 840 841 .seealso: DMNetworkCreate(), DMNetworkLayoutSetUp() 842 @*/ 843 PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key) 844 { 845 PetscErrorCode ierr; 846 DM_Network *network = (DM_Network*) dm->data; 847 DMNetworkComponent *component=NULL,*newcomponent=NULL; 848 PetscBool flg=PETSC_FALSE; 849 PetscInt i; 850 851 PetscFunctionBegin; 852 if (!network->component) { 853 ierr = PetscCalloc1(network->max_comps_registered,&network->component);CHKERRQ(ierr); 854 } 855 856 for (i=0; i < network->ncomponent; i++) { 857 ierr = PetscStrcmp(network->component[i].name,name,&flg);CHKERRQ(ierr); 858 if (flg) { 859 *key = i; 860 PetscFunctionReturn(0); 861 } 862 } 863 864 if (network->ncomponent == network->max_comps_registered) { 865 /* Reached max allowed so resize component */ 866 network->max_comps_registered += 2; 867 ierr = PetscCalloc1(network->max_comps_registered,&newcomponent);CHKERRQ(ierr); 868 /* Copy over the previous component info */ 869 for (i=0; i < network->ncomponent; i++) { 870 ierr = PetscStrcpy(newcomponent[i].name,network->component[i].name);CHKERRQ(ierr); 871 newcomponent[i].size = network->component[i].size; 872 } 873 /* Free old one */ 874 ierr = PetscFree(network->component);CHKERRQ(ierr); 875 /* Update pointer */ 876 network->component = newcomponent; 877 } 878 879 component = &network->component[network->ncomponent]; 880 881 ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr); 882 component->size = size/sizeof(DMNetworkComponentGenericDataType); 883 *key = network->ncomponent; 884 network->ncomponent++; 885 PetscFunctionReturn(0); 886 } 887 888 /*@ 889 DMNetworkGetVertexRange - Get the bounds [start, end) for the local vertices 890 891 Not Collective 892 893 Input Parameter: 894 . dm - the DMNetwork object 895 896 Output Parameters: 897 + vStart - the first vertex point 898 - vEnd - one beyond the last vertex point 899 900 Level: beginner 901 902 .seealso: DMNetworkGetEdgeRange() 903 @*/ 904 PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd) 905 { 906 DM_Network *network = (DM_Network*)dm->data; 907 908 PetscFunctionBegin; 909 if (vStart) *vStart = network->vStart; 910 if (vEnd) *vEnd = network->vEnd; 911 PetscFunctionReturn(0); 912 } 913 914 /*@ 915 DMNetworkGetEdgeRange - Get the bounds [start, end) for the local edges 916 917 Not Collective 918 919 Input Parameter: 920 . dm - the DMNetwork object 921 922 Output Parameters: 923 + eStart - The first edge point 924 - eEnd - One beyond the last edge point 925 926 Level: beginner 927 928 .seealso: DMNetworkGetVertexRange() 929 @*/ 930 PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd) 931 { 932 DM_Network *network = (DM_Network*)dm->data; 933 934 PetscFunctionBegin; 935 if (eStart) *eStart = network->eStart; 936 if (eEnd) *eEnd = network->eEnd; 937 PetscFunctionReturn(0); 938 } 939 940 static PetscErrorCode DMNetworkGetIndex(DM dm,PetscInt p,PetscInt *index) 941 { 942 PetscErrorCode ierr; 943 DM_Network *network = (DM_Network*)dm->data; 944 PetscInt offsetp; 945 DMNetworkComponentHeader header; 946 947 PetscFunctionBegin; 948 PetscCheckFalse(!dm->setupcalled,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first"); 949 ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr); 950 header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp); 951 *index = header->index; 952 PetscFunctionReturn(0); 953 } 954 955 /*@ 956 DMNetworkGetGlobalEdgeIndex - Get the global numbering for the edge on the network 957 958 Not Collective 959 960 Input Parameters: 961 + dm - DMNetwork object 962 - p - edge point 963 964 Output Parameters: 965 . index - the global numbering for the edge 966 967 Level: intermediate 968 969 .seealso: DMNetworkGetGlobalVertexIndex() 970 @*/ 971 PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index) 972 { 973 PetscErrorCode ierr; 974 975 PetscFunctionBegin; 976 ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr); 977 PetscFunctionReturn(0); 978 } 979 980 /*@ 981 DMNetworkGetGlobalVertexIndex - Get the global numbering for the vertex on the network 982 983 Not Collective 984 985 Input Parameters: 986 + dm - DMNetwork object 987 - p - vertex point 988 989 Output Parameters: 990 . index - the global numbering for the vertex 991 992 Level: intermediate 993 994 .seealso: DMNetworkGetGlobalEdgeIndex() 995 @*/ 996 PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index) 997 { 998 PetscErrorCode ierr; 999 1000 PetscFunctionBegin; 1001 ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr); 1002 PetscFunctionReturn(0); 1003 } 1004 1005 /*@ 1006 DMNetworkGetNumComponents - Get the number of components at a vertex/edge 1007 1008 Not Collective 1009 1010 Input Parameters: 1011 + dm - the DMNetwork object 1012 - p - vertex/edge point 1013 1014 Output Parameters: 1015 . numcomponents - Number of components at the vertex/edge 1016 1017 Level: beginner 1018 1019 .seealso: DMNetworkRegisterComponent(), DMNetworkAddComponent() 1020 @*/ 1021 PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents) 1022 { 1023 PetscErrorCode ierr; 1024 PetscInt offset; 1025 DM_Network *network = (DM_Network*)dm->data; 1026 1027 PetscFunctionBegin; 1028 ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr); 1029 *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata; 1030 PetscFunctionReturn(0); 1031 } 1032 1033 /*@ 1034 DMNetworkGetLocalVecOffset - Get the offset for accessing the variables associated with a component at the given vertex/edge from the local vector 1035 1036 Not Collective 1037 1038 Input Parameters: 1039 + dm - the DMNetwork object 1040 . p - the edge/vertex point 1041 - compnum - component number; use ALL_COMPONENTS if no specific component is requested 1042 1043 Output Parameters: 1044 . offset - the local offset 1045 1046 Level: intermediate 1047 1048 .seealso: DMGetLocalVector(), DMNetworkGetComponent(), DMNetworkGetGlobalVecOffset() 1049 @*/ 1050 PetscErrorCode DMNetworkGetLocalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offset) 1051 { 1052 PetscErrorCode ierr; 1053 DM_Network *network = (DM_Network*)dm->data; 1054 PetscInt offsetp,offsetd; 1055 DMNetworkComponentHeader header; 1056 1057 PetscFunctionBegin; 1058 ierr = PetscSectionGetOffset(network->plex->localSection,p,&offsetp);CHKERRQ(ierr); 1059 if (compnum == ALL_COMPONENTS) { 1060 *offset = offsetp; 1061 PetscFunctionReturn(0); 1062 } 1063 1064 ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr); 1065 header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd); 1066 *offset = offsetp + header->offsetvarrel[compnum]; 1067 PetscFunctionReturn(0); 1068 } 1069 1070 /*@ 1071 DMNetworkGetGlobalVecOffset - Get the global offset for accessing the variables associated with a component for the given vertex/edge from the global vector 1072 1073 Not Collective 1074 1075 Input Parameters: 1076 + dm - the DMNetwork object 1077 . p - the edge/vertex point 1078 - compnum - component number; use ALL_COMPONENTS if no specific component is requested 1079 1080 Output Parameters: 1081 . offsetg - the global offset 1082 1083 Level: intermediate 1084 1085 .seealso: DMNetworkGetLocalVecOffset(), DMGetGlobalVector(), DMNetworkGetComponent() 1086 @*/ 1087 PetscErrorCode DMNetworkGetGlobalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offsetg) 1088 { 1089 PetscErrorCode ierr; 1090 DM_Network *network = (DM_Network*)dm->data; 1091 PetscInt offsetp,offsetd; 1092 DMNetworkComponentHeader header; 1093 1094 PetscFunctionBegin; 1095 ierr = PetscSectionGetOffset(network->plex->globalSection,p,&offsetp);CHKERRQ(ierr); 1096 if (offsetp < 0) offsetp = -(offsetp + 1); /* Convert to actual global offset for ghost vertex */ 1097 1098 if (compnum == ALL_COMPONENTS) { 1099 *offsetg = offsetp; 1100 PetscFunctionReturn(0); 1101 } 1102 ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr); 1103 header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd); 1104 *offsetg = offsetp + header->offsetvarrel[compnum]; 1105 PetscFunctionReturn(0); 1106 } 1107 1108 /*@ 1109 DMNetworkGetEdgeOffset - Get the offset for accessing the variables associated with the given edge from the local subvector 1110 1111 Not Collective 1112 1113 Input Parameters: 1114 + dm - the DMNetwork object 1115 - p - the edge point 1116 1117 Output Parameters: 1118 . offset - the offset 1119 1120 Level: intermediate 1121 1122 .seealso: DMNetworkGetLocalVecOffset(), DMGetLocalVector() 1123 @*/ 1124 PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset) 1125 { 1126 PetscErrorCode ierr; 1127 DM_Network *network = (DM_Network*)dm->data; 1128 1129 PetscFunctionBegin; 1130 ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr); 1131 PetscFunctionReturn(0); 1132 } 1133 1134 /*@ 1135 DMNetworkGetVertexOffset - Get the offset for accessing the variables associated with the given vertex from the local subvector 1136 1137 Not Collective 1138 1139 Input Parameters: 1140 + dm - the DMNetwork object 1141 - p - the vertex point 1142 1143 Output Parameters: 1144 . offset - the offset 1145 1146 Level: intermediate 1147 1148 .seealso: DMNetworkGetEdgeOffset(), DMGetLocalVector() 1149 @*/ 1150 PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset) 1151 { 1152 PetscErrorCode ierr; 1153 DM_Network *network = (DM_Network*)dm->data; 1154 1155 PetscFunctionBegin; 1156 p -= network->vStart; 1157 ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr); 1158 PetscFunctionReturn(0); 1159 } 1160 1161 /*@ 1162 DMNetworkAddComponent - Adds a network component and number of variables at the given point (vertex/edge) 1163 1164 Collective on dm 1165 1166 Input Parameters: 1167 + dm - the DMNetwork 1168 . p - the vertex/edge point. These points are local indices provided by DMNetworkGetSubnetwork() 1169 . componentkey - component key returned while registering the component with DMNetworkRegisterComponent() 1170 . compvalue - pointer to the data structure for the component, or NULL if the component does not require data 1171 - nvar - number of variables for the component at the vertex/edge point, zero if the component does not introduce any degrees of freedom at the point 1172 1173 Notes: 1174 The owning rank and any other ranks that have this point as a ghost location must call this routine to add a component and number of variables in the same order at the given point. 1175 1176 DMNetworkLayoutSetUp() must be called before this routine. 1177 1178 Developer Notes: 1179 The requirement that all the ranks with access to a vertex (as owner or as ghost) add all the components comes from a limitation of the underlying implementation based on DMPLEX. 1180 Level: beginner 1181 1182 .seealso: DMNetworkGetComponent(), DMNetworkGetSubnetwork(), DMNetworkIsGhostVertex(), DMNetworkLayoutSetUp() 1183 @*/ 1184 PetscErrorCode DMNetworkAddComponent(DM dm,PetscInt p,PetscInt componentkey,void* compvalue,PetscInt nvar) 1185 { 1186 PetscErrorCode ierr; 1187 DM_Network *network = (DM_Network*)dm->data; 1188 DMNetworkComponent *component = &network->component[componentkey]; 1189 DMNetworkComponentHeader header; 1190 DMNetworkComponentValue cvalue; 1191 PetscInt compnum; 1192 PetscInt *compsize,*compkey,*compoffset,*compnvar,*compoffsetvarrel; 1193 void* *compdata; 1194 1195 PetscFunctionBegin; 1196 PetscCheckFalse(componentkey < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"componentkey %D cannot be negative. Input a component key returned while registering the component with DMNetworkRegisterComponent()",componentkey); 1197 1198 /* The owning rank and all ghost ranks add nvar */ 1199 ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr); 1200 1201 /* The owning rank and all ghost ranks add a component, including compvalue=NULL */ 1202 header = &network->header[p]; 1203 cvalue = &network->cvalue[p]; 1204 if (header->ndata == header->maxcomps) { 1205 PetscInt additional_size; 1206 1207 /* Reached limit so resize header component arrays */ 1208 header->maxcomps += 2; 1209 1210 /* Allocate arrays for component information and value */ 1211 ierr = PetscCalloc5(header->maxcomps,&compsize,header->maxcomps,&compkey,header->maxcomps,&compoffset,header->maxcomps,&compnvar,header->maxcomps,&compoffsetvarrel);CHKERRQ(ierr); 1212 ierr = PetscMalloc1(header->maxcomps,&compdata);CHKERRQ(ierr); 1213 1214 /* Recalculate header size */ 1215 header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt); 1216 1217 header->hsize /= sizeof(DMNetworkComponentGenericDataType); 1218 1219 /* Copy over component info */ 1220 ierr = PetscMemcpy(compsize,header->size,header->ndata*sizeof(PetscInt));CHKERRQ(ierr); 1221 ierr = PetscMemcpy(compkey,header->key,header->ndata*sizeof(PetscInt));CHKERRQ(ierr); 1222 ierr = PetscMemcpy(compoffset,header->offset,header->ndata*sizeof(PetscInt));CHKERRQ(ierr); 1223 ierr = PetscMemcpy(compnvar,header->nvar,header->ndata*sizeof(PetscInt));CHKERRQ(ierr); 1224 ierr = PetscMemcpy(compoffsetvarrel,header->offsetvarrel,header->ndata*sizeof(PetscInt));CHKERRQ(ierr); 1225 1226 /* Copy over component data pointers */ 1227 ierr = PetscMemcpy(compdata,cvalue->data,header->ndata*sizeof(void*));CHKERRQ(ierr); 1228 1229 /* Free old arrays */ 1230 ierr = PetscFree5(header->size,header->key,header->offset,header->nvar,header->offsetvarrel);CHKERRQ(ierr); 1231 ierr = PetscFree(cvalue->data);CHKERRQ(ierr); 1232 1233 /* Update pointers */ 1234 header->size = compsize; 1235 header->key = compkey; 1236 header->offset = compoffset; 1237 header->nvar = compnvar; 1238 header->offsetvarrel = compoffsetvarrel; 1239 1240 cvalue->data = compdata; 1241 1242 /* Update DataSection Dofs */ 1243 /* The dofs for datasection point p equals sizeof the header (i.e. header->hsize) + sizes of the components added at point p. With the resizing of the header, we need to update the dofs for point p. Hence, we add the extra size added for the header */ 1244 additional_size = (5*(header->maxcomps - header->ndata)*sizeof(PetscInt))/sizeof(DMNetworkComponentGenericDataType); 1245 ierr = PetscSectionAddDof(network->DataSection,p,additional_size);CHKERRQ(ierr); 1246 } 1247 header = &network->header[p]; 1248 cvalue = &network->cvalue[p]; 1249 1250 compnum = header->ndata; 1251 1252 header->size[compnum] = component->size; 1253 ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr); 1254 header->key[compnum] = componentkey; 1255 if (compnum != 0) header->offset[compnum] = header->offset[compnum-1] + header->size[compnum-1]; 1256 cvalue->data[compnum] = (void*)compvalue; 1257 1258 /* variables */ 1259 header->nvar[compnum] += nvar; 1260 if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum-1] + header->nvar[compnum-1]; 1261 1262 header->ndata++; 1263 PetscFunctionReturn(0); 1264 } 1265 1266 /*@ 1267 DMNetworkGetComponent - Gets the component key, the component data, and the number of variables at a given network point 1268 1269 Not Collective 1270 1271 Input Parameters: 1272 + dm - the DMNetwork object 1273 . p - vertex/edge point 1274 - compnum - component number; use ALL_COMPONENTS if sum up all the components 1275 1276 Output Parameters: 1277 + compkey - the key obtained when registering the component (use NULL if not required) 1278 . component - the component data (use NULL if not required) 1279 - nvar - number of variables (use NULL if not required) 1280 1281 Level: beginner 1282 1283 .seealso: DMNetworkAddComponent(), DMNetworkGetNumComponents() 1284 @*/ 1285 PetscErrorCode DMNetworkGetComponent(DM dm,PetscInt p,PetscInt compnum,PetscInt *compkey,void **component,PetscInt *nvar) 1286 { 1287 PetscErrorCode ierr; 1288 DM_Network *network = (DM_Network*)dm->data; 1289 PetscInt offset = 0; 1290 DMNetworkComponentHeader header; 1291 1292 PetscFunctionBegin; 1293 if (compnum == ALL_COMPONENTS) { 1294 ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr); 1295 PetscFunctionReturn(0); 1296 } 1297 1298 ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr); 1299 header = (DMNetworkComponentHeader)(network->componentdataarray+offset); 1300 1301 if (compnum >= 0) { 1302 if (compkey) *compkey = header->key[compnum]; 1303 if (component) { 1304 offset += header->hsize+header->offset[compnum]; 1305 *component = network->componentdataarray+offset; 1306 } 1307 } 1308 1309 if (nvar) *nvar = header->nvar[compnum]; 1310 1311 PetscFunctionReturn(0); 1312 } 1313 1314 /* 1315 Sets up the array that holds the data for all components and its associated section. 1316 It copies the data for all components in a contiguous array called componentdataarray. The component data is stored pointwise with an additional header (metadata) stored for each point. The header has metadata information such as number of components at each point, number of variables for each component, offsets for the components data, etc. 1317 */ 1318 PetscErrorCode DMNetworkComponentSetUp(DM dm) 1319 { 1320 PetscErrorCode ierr; 1321 DM_Network *network = (DM_Network*)dm->data; 1322 PetscInt arr_size,p,offset,offsetp,ncomp,i,*headerarr; 1323 DMNetworkComponentHeader header; 1324 DMNetworkComponentValue cvalue; 1325 DMNetworkComponentHeader headerinfo; 1326 DMNetworkComponentGenericDataType *componentdataarray; 1327 1328 PetscFunctionBegin; 1329 ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr); 1330 ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr); 1331 /* arr_size+1 fixes pipeline test of opensolaris-misc for src/dm/tests/ex10.c -- Do not know why */ 1332 ierr = PetscCalloc1(arr_size+1,&network->componentdataarray);CHKERRQ(ierr); 1333 1334 componentdataarray = network->componentdataarray; 1335 for (p = network->pStart; p < network->pEnd; p++) { 1336 ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr); 1337 /* Copy header */ 1338 header = &network->header[p]; 1339 headerinfo = (DMNetworkComponentHeader)(componentdataarray+offsetp); 1340 ierr = PetscMemcpy(headerinfo,header,sizeof(struct _p_DMNetworkComponentHeader));CHKERRQ(ierr); 1341 headerarr = (PetscInt*)(headerinfo+1); 1342 ierr = PetscMemcpy(headerarr,header->size,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr); 1343 headerarr += header->maxcomps; 1344 ierr = PetscMemcpy(headerarr,header->key,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr); 1345 headerarr += header->maxcomps; 1346 ierr = PetscMemcpy(headerarr,header->offset,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr); 1347 headerarr += header->maxcomps; 1348 ierr = PetscMemcpy(headerarr,header->nvar,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr); 1349 headerarr += header->maxcomps; 1350 ierr = PetscMemcpy(headerarr,header->offsetvarrel,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr); 1351 1352 /* Copy data */ 1353 cvalue = &network->cvalue[p]; 1354 ncomp = header->ndata; 1355 1356 for (i = 0; i < ncomp; i++) { 1357 offset = offsetp + header->hsize + header->offset[i]; 1358 ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr); 1359 } 1360 } 1361 PetscFunctionReturn(0); 1362 } 1363 1364 /* Sets up the section for dofs. This routine is called during DMSetUp() */ 1365 static PetscErrorCode DMNetworkVariablesSetUp(DM dm) 1366 { 1367 PetscErrorCode ierr; 1368 DM_Network *network = (DM_Network*)dm->data; 1369 1370 PetscFunctionBegin; 1371 ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr); 1372 PetscFunctionReturn(0); 1373 } 1374 1375 /* Get a subsection from a range of points */ 1376 static PetscErrorCode DMNetworkGetSubSection_private(PetscSection main,PetscInt pstart,PetscInt pend,PetscSection *subsection) 1377 { 1378 PetscErrorCode ierr; 1379 PetscInt i, nvar; 1380 1381 PetscFunctionBegin; 1382 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)main), subsection);CHKERRQ(ierr); 1383 ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr); 1384 for (i = pstart; i < pend; i++) { 1385 ierr = PetscSectionGetDof(main,i,&nvar);CHKERRQ(ierr); 1386 ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr); 1387 } 1388 1389 ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr); 1390 PetscFunctionReturn(0); 1391 } 1392 1393 /* Create a submap of points with a GlobalToLocal structure */ 1394 static PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map) 1395 { 1396 PetscErrorCode ierr; 1397 PetscInt i, *subpoints; 1398 1399 PetscFunctionBegin; 1400 /* Create index sets to map from "points" to "subpoints" */ 1401 ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr); 1402 for (i = pstart; i < pend; i++) { 1403 subpoints[i - pstart] = i; 1404 } 1405 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr); 1406 ierr = PetscFree(subpoints);CHKERRQ(ierr); 1407 PetscFunctionReturn(0); 1408 } 1409 1410 /*@ 1411 DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute 1412 1413 Collective on dm 1414 1415 Input Parameters: 1416 . dm - the DMNetworkObject 1417 1418 Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are: 1419 1420 points = [0 1 2 3 4 5 6] 1421 1422 where edges = [0,1,2,3] and vertices = [4,5,6]. The new orderings will be specific to the subset (i.e vertices = [0,1,2] <- [4,5,6]). 1423 1424 With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset. 1425 1426 Level: intermediate 1427 1428 @*/ 1429 PetscErrorCode DMNetworkAssembleGraphStructures(DM dm) 1430 { 1431 PetscErrorCode ierr; 1432 MPI_Comm comm; 1433 PetscMPIInt size; 1434 DM_Network *network = (DM_Network*)dm->data; 1435 1436 PetscFunctionBegin; 1437 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1438 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1439 1440 /* Create maps for vertices and edges */ 1441 ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr); 1442 ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr); 1443 1444 /* Create local sub-sections */ 1445 ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr); 1446 ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr); 1447 1448 if (size > 1) { 1449 ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr); 1450 1451 ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr); 1452 ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr); 1453 ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr); 1454 } else { 1455 /* create structures for vertex */ 1456 ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr); 1457 /* create structures for edge */ 1458 ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr); 1459 } 1460 1461 /* Add viewers */ 1462 ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr); 1463 ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr); 1464 ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr); 1465 ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr); 1466 PetscFunctionReturn(0); 1467 } 1468 1469 /* 1470 Add all subnetid for the input vertex v in this process to the btable 1471 vertex_subnetid = supportingedge_subnetid 1472 */ 1473 static inline PetscErrorCode SetSubnetIdLookupBT(DM dm,PetscInt v,PetscInt Nsubnet,PetscBT btable) 1474 { 1475 PetscErrorCode ierr; 1476 PetscInt e,nedges,offset; 1477 const PetscInt *edges; 1478 DM_Network *newDMnetwork = (DM_Network*)dm->data; 1479 DMNetworkComponentHeader header; 1480 1481 PetscFunctionBegin; 1482 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 1483 ierr = PetscBTMemzero(Nsubnet,btable);CHKERRQ(ierr); 1484 for (e=0; e<nedges; e++) { 1485 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,edges[e],&offset);CHKERRQ(ierr); 1486 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset); 1487 ierr = PetscBTSet(btable,header->subnetid);CHKERRQ(ierr); 1488 } 1489 PetscFunctionReturn(0); 1490 } 1491 1492 /*@ 1493 DMNetworkDistribute - Distributes the network and moves associated component data 1494 1495 Collective 1496 1497 Input Parameters: 1498 + DM - the DMNetwork object 1499 - overlap - the overlap of partitions, 0 is the default 1500 1501 Options Database Key: 1502 + -dmnetwork_view - Calls DMView() at the conclusion of DMSetUp() 1503 - -dmnetwork_view_distributed - Calls DMView() at the conclusion of DMNetworkDistribute() 1504 1505 Notes: 1506 Distributes the network with <overlap>-overlapping partitioning of the edges. 1507 1508 Level: intermediate 1509 1510 .seealso: DMNetworkCreate() 1511 @*/ 1512 PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap) 1513 { 1514 MPI_Comm comm; 1515 PetscErrorCode ierr; 1516 PetscMPIInt size; 1517 DM_Network *oldDMnetwork = (DM_Network*)((*dm)->data); 1518 DM_Network *newDMnetwork; 1519 PetscSF pointsf=NULL; 1520 DM newDM; 1521 PetscInt j,e,v,offset,*subnetvtx,*subnetedge,Nsubnet,gidx,svtx_idx,nv; 1522 PetscInt to_net,from_net,*svto; 1523 PetscBT btable; 1524 PetscPartitioner part; 1525 DMNetworkComponentHeader header; 1526 1527 PetscFunctionBegin; 1528 ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr); 1529 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1530 if (size == 1) PetscFunctionReturn(0); 1531 1532 PetscCheckFalse(overlap,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"overlap %D != 0 is not supported yet",overlap); 1533 1534 /* This routine moves the component data to the appropriate processors. It makes use of the DataSection and the componentdataarray to move the component data to appropriate processors and returns a new DataSection and new componentdataarray. */ 1535 ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr); 1536 newDMnetwork = (DM_Network*)newDM->data; 1537 newDMnetwork->max_comps_registered = oldDMnetwork->max_comps_registered; 1538 ierr = PetscMalloc1(newDMnetwork->max_comps_registered,&newDMnetwork->component);CHKERRQ(ierr); 1539 1540 /* Enable runtime options for petscpartitioner */ 1541 ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr); 1542 ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); 1543 1544 /* Distribute plex dm */ 1545 ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr); 1546 1547 /* Distribute dof section */ 1548 ierr = PetscSectionCreate(comm,&newDMnetwork->DofSection);CHKERRQ(ierr); 1549 ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr); 1550 1551 /* Distribute data and associated section */ 1552 ierr = PetscSectionCreate(comm,&newDMnetwork->DataSection);CHKERRQ(ierr); 1553 ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr); 1554 1555 ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr); 1556 ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr); 1557 ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr); 1558 newDMnetwork->nEdges = newDMnetwork->eEnd - newDMnetwork->eStart; 1559 newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart; 1560 newDMnetwork->NVertices = oldDMnetwork->NVertices; 1561 newDMnetwork->NEdges = oldDMnetwork->NEdges; 1562 newDMnetwork->svtable = oldDMnetwork->svtable; /* global table! */ 1563 oldDMnetwork->svtable = NULL; 1564 1565 /* Set Dof section as the section for dm */ 1566 ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr); 1567 ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr); 1568 1569 /* Setup subnetwork info in the newDM */ 1570 newDMnetwork->Nsubnet = oldDMnetwork->Nsubnet; 1571 newDMnetwork->Nsvtx = oldDMnetwork->Nsvtx; 1572 oldDMnetwork->Nsvtx = 0; 1573 newDMnetwork->svtx = oldDMnetwork->svtx; /* global vertices! */ 1574 oldDMnetwork->svtx = NULL; 1575 ierr = PetscCalloc1(newDMnetwork->Nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr); 1576 1577 /* Copy over the global number of vertices and edges in each subnetwork. 1578 Note: these are calculated in DMNetworkLayoutSetUp() 1579 */ 1580 Nsubnet = newDMnetwork->Nsubnet; 1581 for (j = 0; j < Nsubnet; j++) { 1582 newDMnetwork->subnet[j].Nvtx = oldDMnetwork->subnet[j].Nvtx; 1583 newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge; 1584 } 1585 1586 /* Count local nedges for subnetworks */ 1587 for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) { 1588 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr); 1589 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset); 1590 /* Update pointers */ 1591 header->size = (PetscInt*)(header + 1); 1592 header->key = header->size + header->maxcomps; 1593 header->offset = header->key + header->maxcomps; 1594 header->nvar = header->offset + header->maxcomps; 1595 header->offsetvarrel = header->nvar + header->maxcomps; 1596 1597 newDMnetwork->subnet[header->subnetid].nedge++; 1598 } 1599 1600 /* Count local nvtx for subnetworks */ 1601 ierr = PetscBTCreate(Nsubnet,&btable);CHKERRQ(ierr); 1602 for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) { 1603 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr); 1604 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1605 /* Update pointers */ 1606 header->size = (PetscInt*)(header + 1); 1607 header->key = header->size + header->maxcomps; 1608 header->offset = header->key + header->maxcomps; 1609 header->nvar = header->offset + header->maxcomps; 1610 header->offsetvarrel = header->nvar + header->maxcomps; 1611 1612 /* shared vertices: use gidx=header->index to check if v is a shared vertex */ 1613 gidx = header->index; 1614 ierr = PetscTableFind(newDMnetwork->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr); 1615 svtx_idx--; 1616 1617 if (svtx_idx < 0) { /* not a shared vertex */ 1618 newDMnetwork->subnet[header->subnetid].nvtx++; 1619 } else { /* a shared vertex belongs to more than one subnetworks, it is being counted by multiple subnets */ 1620 ierr = SetSubnetIdLookupBT(newDM,v,Nsubnet,btable);CHKERRQ(ierr); 1621 1622 from_net = newDMnetwork->svtx[svtx_idx].sv[0]; 1623 if (PetscBTLookup(btable,from_net)) newDMnetwork->subnet[from_net].nvtx++; /* sv is on from_net */ 1624 1625 for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) { 1626 svto = newDMnetwork->svtx[svtx_idx].sv + 2*j; 1627 to_net = svto[0]; 1628 if (PetscBTLookup(btable,to_net)) newDMnetwork->subnet[to_net].nvtx++; /* sv is on to_net */ 1629 } 1630 } 1631 } 1632 1633 /* Get total local nvtx for subnetworks */ 1634 nv = 0; 1635 for (j=0; j<Nsubnet; j++) nv += newDMnetwork->subnet[j].nvtx; 1636 nv += newDMnetwork->Nsvtx; 1637 1638 /* Now create the vertices and edge arrays for the subnetworks */ 1639 ierr = PetscCalloc2(newDMnetwork->nEdges,&subnetedge,nv,&subnetvtx);CHKERRQ(ierr); /* Maps local vertex to local subnetwork's vertex */ 1640 newDMnetwork->subnetedge = subnetedge; 1641 newDMnetwork->subnetvtx = subnetvtx; 1642 for (j=0; j < newDMnetwork->Nsubnet; j++) { 1643 newDMnetwork->subnet[j].edges = subnetedge; 1644 subnetedge += newDMnetwork->subnet[j].nedge; 1645 1646 newDMnetwork->subnet[j].vertices = subnetvtx; 1647 subnetvtx += newDMnetwork->subnet[j].nvtx; 1648 1649 /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop. These get updated when the vertices and edges are added. */ 1650 newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0; 1651 } 1652 newDMnetwork->svertices = subnetvtx; 1653 1654 /* Set the edges and vertices in each subnetwork */ 1655 for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) { 1656 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr); 1657 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1658 newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e; 1659 } 1660 1661 nv = 0; 1662 for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) { 1663 ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr); 1664 header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr); 1665 1666 /* coupling vertices: use gidx = header->index to check if v is a coupling vertex */ 1667 ierr = PetscTableFind(newDMnetwork->svtable,header->index+1,&svtx_idx);CHKERRQ(ierr); 1668 svtx_idx--; 1669 if (svtx_idx < 0) { 1670 newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v; 1671 } else { /* a shared vertex */ 1672 newDMnetwork->svertices[nv++] = v; 1673 1674 /* add all subnetid for this shared vertex in this process to btable */ 1675 ierr = SetSubnetIdLookupBT(newDM,v,Nsubnet,btable);CHKERRQ(ierr); 1676 1677 from_net = newDMnetwork->svtx[svtx_idx].sv[0]; 1678 if (PetscBTLookup(btable,from_net)) 1679 newDMnetwork->subnet[from_net].vertices[newDMnetwork->subnet[from_net].nvtx++] = v; 1680 1681 for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) { 1682 svto = newDMnetwork->svtx[svtx_idx].sv + 2*j; 1683 to_net = svto[0]; 1684 if (PetscBTLookup(btable,to_net)) 1685 newDMnetwork->subnet[to_net].vertices[newDMnetwork->subnet[to_net].nvtx++] = v; 1686 } 1687 } 1688 } 1689 newDMnetwork->nsvtx = nv; /* num of local shared vertices */ 1690 1691 newDM->setupcalled = (*dm)->setupcalled; 1692 newDMnetwork->distributecalled = PETSC_TRUE; 1693 1694 /* Free spaces */ 1695 ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr); 1696 ierr = DMDestroy(dm);CHKERRQ(ierr); 1697 ierr = PetscBTDestroy(&btable);CHKERRQ(ierr); 1698 1699 /* View distributed dmnetwork */ 1700 ierr = DMViewFromOptions(newDM,NULL,"-dmnetwork_view_distributed");CHKERRQ(ierr); 1701 1702 *dm = newDM; 1703 PetscFunctionReturn(0); 1704 } 1705 1706 /*@C 1707 PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering 1708 1709 Collective 1710 1711 Input Parameters: 1712 + mainSF - the original SF structure 1713 - map - a ISLocalToGlobal mapping that contains the subset of points 1714 1715 Output Parameter: 1716 . subSF - a subset of the mainSF for the desired subset. 1717 1718 Level: intermediate 1719 @*/ 1720 PetscErrorCode PetscSFGetSubSF(PetscSF mainsf,ISLocalToGlobalMapping map,PetscSF *subSF) 1721 { 1722 PetscErrorCode ierr; 1723 PetscInt nroots, nleaves, *ilocal_sub; 1724 PetscInt i, *ilocal_map, nroots_sub, nleaves_sub = 0; 1725 PetscInt *local_points, *remote_points; 1726 PetscSFNode *iremote_sub; 1727 const PetscInt *ilocal; 1728 const PetscSFNode *iremote; 1729 1730 PetscFunctionBegin; 1731 ierr = PetscSFGetGraph(mainsf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr); 1732 1733 /* Look for leaves that pertain to the subset of points. Get the local ordering */ 1734 ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr); 1735 ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr); 1736 for (i = 0; i < nleaves; i++) { 1737 if (ilocal_map[i] != -1) nleaves_sub += 1; 1738 } 1739 /* Re-number ilocal with subset numbering. Need information from roots */ 1740 ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr); 1741 for (i = 0; i < nroots; i++) local_points[i] = i; 1742 ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr); 1743 ierr = PetscSFBcastBegin(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr); 1744 ierr = PetscSFBcastEnd(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr); 1745 /* Fill up graph using local (that is, local to the subset) numbering. */ 1746 ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr); 1747 ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr); 1748 nleaves_sub = 0; 1749 for (i = 0; i < nleaves; i++) { 1750 if (ilocal_map[i] != -1) { 1751 ilocal_sub[nleaves_sub] = ilocal_map[i]; 1752 iremote_sub[nleaves_sub].rank = iremote[i].rank; 1753 iremote_sub[nleaves_sub].index = remote_points[ilocal[i]]; 1754 nleaves_sub += 1; 1755 } 1756 } 1757 ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr); 1758 ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr); 1759 1760 /* Create new subSF */ 1761 ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr); 1762 ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr); 1763 ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr); 1764 ierr = PetscFree(ilocal_map);CHKERRQ(ierr); 1765 ierr = PetscFree(iremote_sub);CHKERRQ(ierr); 1766 PetscFunctionReturn(0); 1767 } 1768 1769 /*@C 1770 DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point 1771 1772 Not Collective 1773 1774 Input Parameters: 1775 + dm - the DMNetwork object 1776 - p - the vertex point 1777 1778 Output Parameters: 1779 + nedges - number of edges connected to this vertex point 1780 - edges - list of edge points 1781 1782 Level: beginner 1783 1784 Fortran Notes: 1785 Since it returns an array, this routine is only available in Fortran 90, and you must 1786 include petsc.h90 in your code. 1787 1788 .seealso: DMNetworkCreate(), DMNetworkGetConnectedVertices() 1789 @*/ 1790 PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[]) 1791 { 1792 PetscErrorCode ierr; 1793 DM_Network *network = (DM_Network*)dm->data; 1794 1795 PetscFunctionBegin; 1796 ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr); 1797 if (edges) {ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);} 1798 PetscFunctionReturn(0); 1799 } 1800 1801 /*@C 1802 DMNetworkGetConnectedVertices - Return the connected vertices for this edge point 1803 1804 Not Collective 1805 1806 Input Parameters: 1807 + dm - the DMNetwork object 1808 - p - the edge point 1809 1810 Output Parameters: 1811 . vertices - vertices connected to this edge 1812 1813 Level: beginner 1814 1815 Fortran Notes: 1816 Since it returns an array, this routine is only available in Fortran 90, and you must 1817 include petsc.h90 in your code. 1818 1819 .seealso: DMNetworkCreate(), DMNetworkGetSupportingEdges() 1820 @*/ 1821 PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[]) 1822 { 1823 PetscErrorCode ierr; 1824 DM_Network *network = (DM_Network*)dm->data; 1825 1826 PetscFunctionBegin; 1827 ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr); 1828 PetscFunctionReturn(0); 1829 } 1830 1831 /*@ 1832 DMNetworkIsSharedVertex - Returns TRUE if the vertex is shared by subnetworks 1833 1834 Not Collective 1835 1836 Input Parameters: 1837 + dm - the DMNetwork object 1838 - p - the vertex point 1839 1840 Output Parameter: 1841 . flag - TRUE if the vertex is shared by subnetworks 1842 1843 Level: beginner 1844 1845 .seealso: DMNetworkAddSharedVertices(), DMNetworkIsGhostVertex() 1846 @*/ 1847 PetscErrorCode DMNetworkIsSharedVertex(DM dm,PetscInt p,PetscBool *flag) 1848 { 1849 PetscErrorCode ierr; 1850 PetscInt i; 1851 1852 PetscFunctionBegin; 1853 *flag = PETSC_FALSE; 1854 1855 if (dm->setupcalled) { /* DMNetworkGetGlobalVertexIndex() requires DMSetUp() be called */ 1856 DM_Network *network = (DM_Network*)dm->data; 1857 PetscInt gidx; 1858 ierr = DMNetworkGetGlobalVertexIndex(dm,p,&gidx);CHKERRQ(ierr); 1859 ierr = PetscTableFind(network->svtable,gidx+1,&i);CHKERRQ(ierr); 1860 if (i) *flag = PETSC_TRUE; 1861 } else { /* would be removed? */ 1862 PetscInt nv; 1863 const PetscInt *vtx; 1864 ierr = DMNetworkGetSharedVertices(dm,&nv,&vtx);CHKERRQ(ierr); 1865 for (i=0; i<nv; i++) { 1866 if (p == vtx[i]) { 1867 *flag = PETSC_TRUE; 1868 break; 1869 } 1870 } 1871 } 1872 PetscFunctionReturn(0); 1873 } 1874 1875 /*@ 1876 DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex 1877 1878 Not Collective 1879 1880 Input Parameters: 1881 + dm - the DMNetwork object 1882 - p - the vertex point 1883 1884 Output Parameter: 1885 . isghost - TRUE if the vertex is a ghost point 1886 1887 Level: beginner 1888 1889 .seealso: DMNetworkGetConnectedVertices(), DMNetworkGetVertexRange(), DMNetworkIsSharedVertex() 1890 @*/ 1891 PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost) 1892 { 1893 PetscErrorCode ierr; 1894 DM_Network *network = (DM_Network*)dm->data; 1895 PetscInt offsetg; 1896 PetscSection sectiong; 1897 1898 PetscFunctionBegin; 1899 *isghost = PETSC_FALSE; 1900 ierr = DMGetGlobalSection(network->plex,§iong);CHKERRQ(ierr); 1901 ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr); 1902 if (offsetg < 0) *isghost = PETSC_TRUE; 1903 PetscFunctionReturn(0); 1904 } 1905 1906 PetscErrorCode DMSetUp_Network(DM dm) 1907 { 1908 PetscErrorCode ierr; 1909 DM_Network *network=(DM_Network*)dm->data; 1910 1911 PetscFunctionBegin; 1912 ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr); 1913 ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr); 1914 1915 ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr); 1916 ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr); 1917 1918 dm->setupcalled = PETSC_TRUE; 1919 1920 /* View dmnetwork */ 1921 ierr = DMViewFromOptions(dm,NULL,"-dmnetwork_view");CHKERRQ(ierr); 1922 PetscFunctionReturn(0); 1923 } 1924 1925 /*@ 1926 DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices 1927 -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)? 1928 1929 Collective 1930 1931 Input Parameters: 1932 + dm - the DMNetwork object 1933 . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges 1934 - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices 1935 1936 Level: intermediate 1937 1938 @*/ 1939 PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg) 1940 { 1941 DM_Network *network=(DM_Network*)dm->data; 1942 PetscErrorCode ierr; 1943 PetscInt nVertices = network->nVertices; 1944 1945 PetscFunctionBegin; 1946 network->userEdgeJacobian = eflg; 1947 network->userVertexJacobian = vflg; 1948 1949 if (eflg && !network->Je) { 1950 ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr); 1951 } 1952 1953 if (vflg && !network->Jv && nVertices) { 1954 PetscInt i,*vptr,nedges,vStart=network->vStart; 1955 PetscInt nedges_total; 1956 const PetscInt *edges; 1957 1958 /* count nvertex_total */ 1959 nedges_total = 0; 1960 ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr); 1961 1962 vptr[0] = 0; 1963 for (i=0; i<nVertices; i++) { 1964 ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr); 1965 nedges_total += nedges; 1966 vptr[i+1] = vptr[i] + 2*nedges + 1; 1967 } 1968 1969 ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr); 1970 network->Jvptr = vptr; 1971 } 1972 PetscFunctionReturn(0); 1973 } 1974 1975 /*@ 1976 DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network 1977 1978 Not Collective 1979 1980 Input Parameters: 1981 + dm - the DMNetwork object 1982 . p - the edge point 1983 - J - array (size = 3) of Jacobian submatrices for this edge point: 1984 J[0]: this edge 1985 J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices() 1986 1987 Level: advanced 1988 1989 .seealso: DMNetworkVertexSetMatrix() 1990 @*/ 1991 PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[]) 1992 { 1993 DM_Network *network=(DM_Network*)dm->data; 1994 1995 PetscFunctionBegin; 1996 PetscCheckFalse(!network->Je,PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix"); 1997 1998 if (J) { 1999 network->Je[3*p] = J[0]; 2000 network->Je[3*p+1] = J[1]; 2001 network->Je[3*p+2] = J[2]; 2002 } 2003 PetscFunctionReturn(0); 2004 } 2005 2006 /*@ 2007 DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network 2008 2009 Not Collective 2010 2011 Input Parameters: 2012 + dm - The DMNetwork object 2013 . p - the vertex point 2014 - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point: 2015 J[0]: this vertex 2016 J[1+2*i]: i-th supporting edge 2017 J[1+2*i+1]: i-th connected vertex 2018 2019 Level: advanced 2020 2021 .seealso: DMNetworkEdgeSetMatrix() 2022 @*/ 2023 PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[]) 2024 { 2025 PetscErrorCode ierr; 2026 DM_Network *network=(DM_Network*)dm->data; 2027 PetscInt i,*vptr,nedges,vStart=network->vStart; 2028 const PetscInt *edges; 2029 2030 PetscFunctionBegin; 2031 PetscCheckFalse(!network->Jv,PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix"); 2032 2033 if (J) { 2034 vptr = network->Jvptr; 2035 network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */ 2036 2037 /* Set Jacobian for each supporting edge and connected vertex */ 2038 ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr); 2039 for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i]; 2040 } 2041 PetscFunctionReturn(0); 2042 } 2043 2044 static inline PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 2045 { 2046 PetscErrorCode ierr; 2047 PetscInt j; 2048 PetscScalar val=(PetscScalar)ncols; 2049 2050 PetscFunctionBegin; 2051 if (!ghost) { 2052 for (j=0; j<nrows; j++) { 2053 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 2054 } 2055 } else { 2056 for (j=0; j<nrows; j++) { 2057 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 2058 } 2059 } 2060 PetscFunctionReturn(0); 2061 } 2062 2063 static inline PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 2064 { 2065 PetscErrorCode ierr; 2066 PetscInt j,ncols_u; 2067 PetscScalar val; 2068 2069 PetscFunctionBegin; 2070 if (!ghost) { 2071 for (j=0; j<nrows; j++) { 2072 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 2073 val = (PetscScalar)ncols_u; 2074 ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 2075 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 2076 } 2077 } else { 2078 for (j=0; j<nrows; j++) { 2079 ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 2080 val = (PetscScalar)ncols_u; 2081 ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr); 2082 ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr); 2083 } 2084 } 2085 PetscFunctionReturn(0); 2086 } 2087 2088 static inline PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz) 2089 { 2090 PetscErrorCode ierr; 2091 2092 PetscFunctionBegin; 2093 if (Ju) { 2094 ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 2095 } else { 2096 ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr); 2097 } 2098 PetscFunctionReturn(0); 2099 } 2100 2101 static inline PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 2102 { 2103 PetscErrorCode ierr; 2104 PetscInt j,*cols; 2105 PetscScalar *zeros; 2106 2107 PetscFunctionBegin; 2108 ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr); 2109 for (j=0; j<ncols; j++) cols[j] = j+ cstart; 2110 ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr); 2111 ierr = PetscFree2(cols,zeros);CHKERRQ(ierr); 2112 PetscFunctionReturn(0); 2113 } 2114 2115 static inline PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 2116 { 2117 PetscErrorCode ierr; 2118 PetscInt j,M,N,row,col,ncols_u; 2119 const PetscInt *cols; 2120 PetscScalar zero=0.0; 2121 2122 PetscFunctionBegin; 2123 ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr); 2124 PetscCheckFalse(nrows != M || ncols != N,PetscObjectComm((PetscObject)Ju),PETSC_ERR_USER,"%D by %D must equal %D by %D",nrows,ncols,M,N); 2125 2126 for (row=0; row<nrows; row++) { 2127 ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 2128 for (j=0; j<ncols_u; j++) { 2129 col = cols[j] + cstart; 2130 ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr); 2131 } 2132 ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr); 2133 } 2134 PetscFunctionReturn(0); 2135 } 2136 2137 static inline PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J) 2138 { 2139 PetscErrorCode ierr; 2140 2141 PetscFunctionBegin; 2142 if (Ju) { 2143 ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 2144 } else { 2145 ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 2146 } 2147 PetscFunctionReturn(0); 2148 } 2149 2150 /* 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. 2151 */ 2152 PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog) 2153 { 2154 PetscErrorCode ierr; 2155 PetscInt i,size,dof; 2156 PetscInt *glob2loc; 2157 2158 PetscFunctionBegin; 2159 ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr); 2160 ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr); 2161 2162 for (i = 0; i < size; i++) { 2163 ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr); 2164 dof = (dof >= 0) ? dof : -(dof + 1); 2165 glob2loc[i] = dof; 2166 } 2167 2168 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 2169 #if 0 2170 ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2171 #endif 2172 PetscFunctionReturn(0); 2173 } 2174 2175 #include <petsc/private/matimpl.h> 2176 2177 PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J) 2178 { 2179 PetscErrorCode ierr; 2180 DM_Network *network = (DM_Network*)dm->data; 2181 PetscInt eDof,vDof; 2182 Mat j11,j12,j21,j22,bA[2][2]; 2183 MPI_Comm comm; 2184 ISLocalToGlobalMapping eISMap,vISMap; 2185 2186 PetscFunctionBegin; 2187 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2188 2189 ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr); 2190 ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr); 2191 2192 ierr = MatCreate(comm, &j11);CHKERRQ(ierr); 2193 ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2194 ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr); 2195 2196 ierr = MatCreate(comm, &j12);CHKERRQ(ierr); 2197 ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr); 2198 ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr); 2199 2200 ierr = MatCreate(comm, &j21);CHKERRQ(ierr); 2201 ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2202 ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr); 2203 2204 ierr = MatCreate(comm, &j22);CHKERRQ(ierr); 2205 ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 2206 ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr); 2207 2208 bA[0][0] = j11; 2209 bA[0][1] = j12; 2210 bA[1][0] = j21; 2211 bA[1][1] = j22; 2212 2213 ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr); 2214 ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr); 2215 2216 ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr); 2217 ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr); 2218 ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr); 2219 ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr); 2220 2221 ierr = MatSetUp(j11);CHKERRQ(ierr); 2222 ierr = MatSetUp(j12);CHKERRQ(ierr); 2223 ierr = MatSetUp(j21);CHKERRQ(ierr); 2224 ierr = MatSetUp(j22);CHKERRQ(ierr); 2225 2226 ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr); 2227 ierr = MatSetUp(*J);CHKERRQ(ierr); 2228 ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr); 2229 ierr = MatDestroy(&j11);CHKERRQ(ierr); 2230 ierr = MatDestroy(&j12);CHKERRQ(ierr); 2231 ierr = MatDestroy(&j21);CHKERRQ(ierr); 2232 ierr = MatDestroy(&j22);CHKERRQ(ierr); 2233 2234 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2235 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2236 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 2237 2238 /* Free structures */ 2239 ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr); 2240 ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr); 2241 PetscFunctionReturn(0); 2242 } 2243 2244 PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J) 2245 { 2246 PetscErrorCode ierr; 2247 DM_Network *network = (DM_Network*)dm->data; 2248 PetscInt eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize; 2249 PetscInt cstart,ncols,j,e,v; 2250 PetscBool ghost,ghost_vc,ghost2,isNest; 2251 Mat Juser; 2252 PetscSection sectionGlobal; 2253 PetscInt nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */ 2254 const PetscInt *edges,*cone; 2255 MPI_Comm comm; 2256 MatType mtype; 2257 Vec vd_nz,vo_nz; 2258 PetscInt *dnnz,*onnz; 2259 PetscScalar *vdnz,*vonz; 2260 2261 PetscFunctionBegin; 2262 mtype = dm->mattype; 2263 ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr); 2264 if (isNest) { 2265 ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr); 2266 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 2267 PetscFunctionReturn(0); 2268 } 2269 2270 if (!network->userEdgeJacobian && !network->userVertexJacobian) { 2271 /* user does not provide Jacobian blocks */ 2272 ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr); 2273 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 2274 PetscFunctionReturn(0); 2275 } 2276 2277 ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr); 2278 ierr = DMGetGlobalSection(network->plex,§ionGlobal);CHKERRQ(ierr); 2279 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr); 2280 ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 2281 2282 ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr); 2283 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 2284 2285 /* (1) Set matrix preallocation */ 2286 /*------------------------------*/ 2287 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2288 ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr); 2289 ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr); 2290 ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr); 2291 ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr); 2292 ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr); 2293 2294 /* Set preallocation for edges */ 2295 /*-----------------------------*/ 2296 ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr); 2297 2298 ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr); 2299 for (e=eStart; e<eEnd; e++) { 2300 /* Get row indices */ 2301 ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr); 2302 ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr); 2303 if (nrows) { 2304 for (j=0; j<nrows; j++) rows[j] = j + rstart; 2305 2306 /* Set preallocation for connected vertices */ 2307 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 2308 for (v=0; v<2; v++) { 2309 ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr); 2310 2311 if (network->Je) { 2312 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 2313 } else Juser = NULL; 2314 ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr); 2315 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 2316 } 2317 2318 /* Set preallocation for edge self */ 2319 cstart = rstart; 2320 if (network->Je) { 2321 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 2322 } else Juser = NULL; 2323 ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 2324 } 2325 } 2326 2327 /* Set preallocation for vertices */ 2328 /*--------------------------------*/ 2329 ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr); 2330 if (vEnd - vStart) vptr = network->Jvptr; 2331 2332 for (v=vStart; v<vEnd; v++) { 2333 /* Get row indices */ 2334 ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr); 2335 ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr); 2336 if (!nrows) continue; 2337 2338 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 2339 if (ghost) { 2340 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 2341 } else { 2342 rows_v = rows; 2343 } 2344 2345 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 2346 2347 /* Get supporting edges and connected vertices */ 2348 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 2349 2350 for (e=0; e<nedges; e++) { 2351 /* Supporting edges */ 2352 ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr); 2353 ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr); 2354 2355 if (network->Jv) { 2356 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 2357 } else Juser = NULL; 2358 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr); 2359 2360 /* Connected vertices */ 2361 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 2362 vc = (v == cone[0]) ? cone[1]:cone[0]; 2363 ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr); 2364 2365 ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr); 2366 2367 if (network->Jv) { 2368 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 2369 } else Juser = NULL; 2370 if (ghost_vc||ghost) { 2371 ghost2 = PETSC_TRUE; 2372 } else { 2373 ghost2 = PETSC_FALSE; 2374 } 2375 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr); 2376 } 2377 2378 /* Set preallocation for vertex self */ 2379 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 2380 if (!ghost) { 2381 ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr); 2382 if (network->Jv) { 2383 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 2384 } else Juser = NULL; 2385 ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr); 2386 } 2387 if (ghost) { 2388 ierr = PetscFree(rows_v);CHKERRQ(ierr); 2389 } 2390 } 2391 2392 ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr); 2393 ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr); 2394 2395 ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr); 2396 2397 ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr); 2398 ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr); 2399 2400 ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr); 2401 ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr); 2402 for (j=0; j<localSize; j++) { 2403 dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]); 2404 onnz[j] = (PetscInt)PetscRealPart(vonz[j]); 2405 } 2406 ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr); 2407 ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr); 2408 ierr = VecDestroy(&vd_nz);CHKERRQ(ierr); 2409 ierr = VecDestroy(&vo_nz);CHKERRQ(ierr); 2410 2411 ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr); 2412 ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr); 2413 ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 2414 2415 ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr); 2416 2417 /* (2) Set matrix entries for edges */ 2418 /*----------------------------------*/ 2419 for (e=eStart; e<eEnd; e++) { 2420 /* Get row indices */ 2421 ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr); 2422 ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr); 2423 if (nrows) { 2424 for (j=0; j<nrows; j++) rows[j] = j + rstart; 2425 2426 /* Set matrix entries for connected vertices */ 2427 ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr); 2428 for (v=0; v<2; v++) { 2429 ierr = DMNetworkGetGlobalVecOffset(dm,cone[v],ALL_COMPONENTS,&cstart);CHKERRQ(ierr); 2430 ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr); 2431 2432 if (network->Je) { 2433 Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */ 2434 } else Juser = NULL; 2435 ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr); 2436 } 2437 2438 /* Set matrix entries for edge self */ 2439 cstart = rstart; 2440 if (network->Je) { 2441 Juser = network->Je[3*e]; /* Jacobian(e,e) */ 2442 } else Juser = NULL; 2443 ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr); 2444 } 2445 } 2446 2447 /* Set matrix entries for vertices */ 2448 /*---------------------------------*/ 2449 for (v=vStart; v<vEnd; v++) { 2450 /* Get row indices */ 2451 ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr); 2452 ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr); 2453 if (!nrows) continue; 2454 2455 ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr); 2456 if (ghost) { 2457 ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr); 2458 } else { 2459 rows_v = rows; 2460 } 2461 for (j=0; j<nrows; j++) rows_v[j] = j + rstart; 2462 2463 /* Get supporting edges and connected vertices */ 2464 ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr); 2465 2466 for (e=0; e<nedges; e++) { 2467 /* Supporting edges */ 2468 ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr); 2469 ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr); 2470 2471 if (network->Jv) { 2472 Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */ 2473 } else Juser = NULL; 2474 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 2475 2476 /* Connected vertices */ 2477 ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr); 2478 vc = (v == cone[0]) ? cone[1]:cone[0]; 2479 2480 ierr = DMNetworkGetGlobalVecOffset(dm,vc,ALL_COMPONENTS,&cstart);CHKERRQ(ierr); 2481 ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr); 2482 2483 if (network->Jv) { 2484 Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */ 2485 } else Juser = NULL; 2486 ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr); 2487 } 2488 2489 /* Set matrix entries for vertex self */ 2490 if (!ghost) { 2491 ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr); 2492 if (network->Jv) { 2493 Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */ 2494 } else Juser = NULL; 2495 ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr); 2496 } 2497 if (ghost) { 2498 ierr = PetscFree(rows_v);CHKERRQ(ierr); 2499 } 2500 } 2501 ierr = PetscFree(rows);CHKERRQ(ierr); 2502 2503 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2504 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2505 2506 ierr = MatSetDM(*J,dm);CHKERRQ(ierr); 2507 PetscFunctionReturn(0); 2508 } 2509 2510 PetscErrorCode DMDestroy_Network(DM dm) 2511 { 2512 PetscErrorCode ierr; 2513 DM_Network *network = (DM_Network*)dm->data; 2514 PetscInt j,np; 2515 2516 PetscFunctionBegin; 2517 if (--network->refct > 0) PetscFunctionReturn(0); 2518 if (network->Je) { 2519 ierr = PetscFree(network->Je);CHKERRQ(ierr); 2520 } 2521 if (network->Jv) { 2522 ierr = PetscFree(network->Jvptr);CHKERRQ(ierr); 2523 ierr = PetscFree(network->Jv);CHKERRQ(ierr); 2524 } 2525 2526 ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr); 2527 ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr); 2528 ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr); 2529 if (network->vltog) { 2530 ierr = PetscFree(network->vltog);CHKERRQ(ierr); 2531 } 2532 if (network->vertex.sf) { 2533 ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr); 2534 } 2535 /* edge */ 2536 ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr); 2537 ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr); 2538 ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr); 2539 if (network->edge.sf) { 2540 ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr); 2541 } 2542 ierr = DMDestroy(&network->plex);CHKERRQ(ierr); 2543 ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr); 2544 ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr); 2545 2546 for (j=0; j<network->Nsvtx; j++) { 2547 ierr = PetscFree(network->svtx[j].sv);CHKERRQ(ierr); 2548 } 2549 if (network->svtx) {ierr = PetscFree(network->svtx);CHKERRQ(ierr);} 2550 ierr = PetscFree2(network->subnetedge,network->subnetvtx);CHKERRQ(ierr); 2551 2552 ierr = PetscTableDestroy(&network->svtable);CHKERRQ(ierr); 2553 ierr = PetscFree(network->subnet);CHKERRQ(ierr); 2554 ierr = PetscFree(network->component);CHKERRQ(ierr); 2555 ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr); 2556 2557 if (network->header) { 2558 np = network->pEnd - network->pStart; 2559 for (j=0; j < np; j++) { 2560 ierr = PetscFree5(network->header[j].size,network->header[j].key,network->header[j].offset,network->header[j].nvar,network->header[j].offsetvarrel);CHKERRQ(ierr); 2561 ierr = PetscFree(network->cvalue[j].data);CHKERRQ(ierr); 2562 } 2563 ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr); 2564 } 2565 ierr = PetscFree(network);CHKERRQ(ierr); 2566 PetscFunctionReturn(0); 2567 } 2568 2569 PetscErrorCode DMView_Network(DM dm,PetscViewer viewer) 2570 { 2571 PetscErrorCode ierr; 2572 PetscBool iascii; 2573 PetscMPIInt rank; 2574 2575 PetscFunctionBegin; 2576 PetscCheckFalse(!dm->setupcalled,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first"); 2577 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr); 2578 PetscValidHeaderSpecific(dm,DM_CLASSID, 1); 2579 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2580 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 2581 if (iascii) { 2582 const PetscInt *cone,*vtx,*edges; 2583 PetscInt vfrom,vto,i,j,nv,ne,ncv,p,nsubnet; 2584 DM_Network *network = (DM_Network*)dm->data; 2585 2586 nsubnet = network->Nsubnet; /* num of subnetworks */ 2587 if (rank == 0) { 2588 ierr = PetscPrintf(PETSC_COMM_SELF," NSubnets: %D; NEdges: %D; NVertices: %D; NSharedVertices: %D.\n",nsubnet,network->NEdges,network->NVertices,network->Nsvtx);CHKERRQ(ierr); 2589 } 2590 2591 ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr); 2592 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 2593 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " [%d] nEdges: %D; nVertices: %D; nSharedVertices: %D\n",rank,network->nEdges,network->nVertices,ncv);CHKERRQ(ierr); 2594 2595 for (i=0; i<nsubnet; i++) { 2596 ierr = DMNetworkGetSubnetwork(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr); 2597 if (ne) { 2598 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " Subnet %D: nEdges %D, nVertices(include shared vertices) %D\n",i,ne,nv);CHKERRQ(ierr); 2599 for (j=0; j<ne; j++) { 2600 p = edges[j]; 2601 ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr); 2602 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr); 2603 ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr); 2604 ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr); 2605 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " edge %D: %D ----> %D\n",p,vfrom,vto);CHKERRQ(ierr); 2606 } 2607 } 2608 } 2609 2610 /* Shared vertices */ 2611 ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr); 2612 if (ncv) { 2613 SVtx *svtx = network->svtx; 2614 PetscInt gidx,svtx_idx,nvto,vfrom_net,vfrom_idx,*svto; 2615 PetscBool ghost; 2616 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " SharedVertices:\n");CHKERRQ(ierr); 2617 for (i=0; i<ncv; i++) { 2618 ierr = DMNetworkIsGhostVertex(dm,vtx[i],&ghost);CHKERRQ(ierr); 2619 if (ghost) continue; 2620 2621 ierr = DMNetworkGetGlobalVertexIndex(dm,vtx[i],&gidx);CHKERRQ(ierr); 2622 ierr = PetscTableFind(network->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr); 2623 svtx_idx--; 2624 nvto = svtx[svtx_idx].n; 2625 2626 vfrom_net = svtx[svtx_idx].sv[0]; 2627 vfrom_idx = svtx[svtx_idx].sv[1]; 2628 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " svtx %D: global index %D, subnet[%D].%D ---->\n",i,gidx,vfrom_net,vfrom_idx);CHKERRQ(ierr); 2629 for (j=1; j<nvto; j++) { 2630 svto = svtx[svtx_idx].sv + 2*j; 2631 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " ----> subnet[%D].%D\n",svto[0],svto[1]);CHKERRQ(ierr); 2632 } 2633 } 2634 } 2635 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 2636 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 2637 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name); 2638 PetscFunctionReturn(0); 2639 } 2640 2641 PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l) 2642 { 2643 PetscErrorCode ierr; 2644 DM_Network *network = (DM_Network*)dm->data; 2645 2646 PetscFunctionBegin; 2647 ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr); 2648 PetscFunctionReturn(0); 2649 } 2650 2651 PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l) 2652 { 2653 PetscErrorCode ierr; 2654 DM_Network *network = (DM_Network*)dm->data; 2655 2656 PetscFunctionBegin; 2657 ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr); 2658 PetscFunctionReturn(0); 2659 } 2660 2661 PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g) 2662 { 2663 PetscErrorCode ierr; 2664 DM_Network *network = (DM_Network*)dm->data; 2665 2666 PetscFunctionBegin; 2667 ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr); 2668 PetscFunctionReturn(0); 2669 } 2670 2671 PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g) 2672 { 2673 PetscErrorCode ierr; 2674 DM_Network *network = (DM_Network*)dm->data; 2675 2676 PetscFunctionBegin; 2677 ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr); 2678 PetscFunctionReturn(0); 2679 } 2680 2681 /*@ 2682 DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index 2683 2684 Not collective 2685 2686 Input Parameters: 2687 + dm - the dm object 2688 - vloc - local vertex ordering, start from 0 2689 2690 Output Parameters: 2691 . vg - global vertex ordering, start from 0 2692 2693 Level: advanced 2694 2695 .seealso: DMNetworkSetVertexLocalToGlobalOrdering() 2696 @*/ 2697 PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg) 2698 { 2699 DM_Network *network = (DM_Network*)dm->data; 2700 PetscInt *vltog = network->vltog; 2701 2702 PetscFunctionBegin; 2703 PetscCheckFalse(!vltog,PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first"); 2704 *vg = vltog[vloc]; 2705 PetscFunctionReturn(0); 2706 } 2707 2708 /*@ 2709 DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map 2710 2711 Collective 2712 2713 Input Parameters: 2714 . dm - the dm object 2715 2716 Level: advanced 2717 2718 .seealso: DMNetworkGetGlobalVertexIndex() 2719 @*/ 2720 PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm) 2721 { 2722 PetscErrorCode ierr; 2723 DM_Network *network=(DM_Network*)dm->data; 2724 MPI_Comm comm; 2725 PetscMPIInt rank,size,*displs=NULL,*recvcounts=NULL,remoterank; 2726 PetscBool ghost; 2727 PetscInt *vltog,nroots,nleaves,i,*vrange,k,N,lidx; 2728 const PetscSFNode *iremote; 2729 PetscSF vsf; 2730 Vec Vleaves,Vleaves_seq; 2731 VecScatter ctx; 2732 PetscScalar *varr,val; 2733 const PetscScalar *varr_read; 2734 2735 PetscFunctionBegin; 2736 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2737 ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr); 2738 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 2739 2740 if (size == 1) { 2741 nroots = network->vEnd - network->vStart; 2742 ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr); 2743 for (i=0; i<nroots; i++) vltog[i] = i; 2744 network->vltog = vltog; 2745 PetscFunctionReturn(0); 2746 } 2747 2748 PetscCheckFalse(!network->distributecalled,comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first"); 2749 if (network->vltog) { 2750 ierr = PetscFree(network->vltog);CHKERRQ(ierr); 2751 } 2752 2753 ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr); 2754 ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr); 2755 vsf = network->vertex.sf; 2756 2757 ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr); 2758 ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr); 2759 2760 for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;} 2761 2762 i = nroots - nleaves; /* local number of vertices, excluding ghosts */ 2763 vrange[0] = 0; 2764 ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr); 2765 for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];} 2766 2767 ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr); 2768 network->vltog = vltog; 2769 2770 /* Set vltog for non-ghost vertices */ 2771 k = 0; 2772 for (i=0; i<nroots; i++) { 2773 ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr); 2774 if (ghost) continue; 2775 vltog[i] = vrange[rank] + k++; 2776 } 2777 ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr); 2778 2779 /* Set vltog for ghost vertices */ 2780 /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */ 2781 ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr); 2782 ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr); 2783 ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr); 2784 ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr); 2785 for (i=0; i<nleaves; i++) { 2786 varr[2*i] = (PetscScalar)(iremote[i].rank); /* rank of remote process */ 2787 varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */ 2788 } 2789 ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr); 2790 2791 /* (b) scatter local info to remote processes via VecScatter() */ 2792 ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr); 2793 ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2794 ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2795 2796 /* (c) convert local indices to global indices in parallel vector Vleaves */ 2797 ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr); 2798 ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr); 2799 for (i=0; i<N; i+=2) { 2800 remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]); 2801 if (remoterank == rank) { 2802 k = i+1; /* row number */ 2803 lidx = (PetscInt)PetscRealPart(varr_read[i+1]); 2804 val = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */ 2805 ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr); 2806 } 2807 } 2808 ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr); 2809 ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr); 2810 ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr); 2811 2812 /* (d) Set vltog for ghost vertices by copying local values of Vleaves */ 2813 ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr); 2814 k = 0; 2815 for (i=0; i<nroots; i++) { 2816 ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr); 2817 if (!ghost) continue; 2818 vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++; 2819 } 2820 ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr); 2821 2822 ierr = VecDestroy(&Vleaves);CHKERRQ(ierr); 2823 ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr); 2824 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 2825 PetscFunctionReturn(0); 2826 } 2827 2828 static inline PetscErrorCode DMISAddSize_private(DM_Network *network,PetscInt p,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *nidx) 2829 { 2830 PetscErrorCode ierr; 2831 PetscInt i,j,ncomps,nvar,key,offset=0; 2832 DMNetworkComponentHeader header; 2833 2834 PetscFunctionBegin; 2835 ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr); 2836 ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata; 2837 header = (DMNetworkComponentHeader)(network->componentdataarray+offset); 2838 2839 for (i=0; i<ncomps; i++) { 2840 key = header->key[i]; 2841 nvar = header->nvar[i]; 2842 for (j=0; j<numkeys; j++) { 2843 if (key == keys[j]) { 2844 if (!blocksize || blocksize[j] == -1) { 2845 *nidx += nvar; 2846 } else { 2847 *nidx += nselectedvar[j]*nvar/blocksize[j]; 2848 } 2849 } 2850 } 2851 } 2852 PetscFunctionReturn(0); 2853 } 2854 2855 static inline PetscErrorCode DMISComputeIdx_private(DM dm,PetscInt p,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],PetscInt *ii,PetscInt *idx) 2856 { 2857 PetscErrorCode ierr; 2858 PetscInt i,j,ncomps,nvar,key,offsetg,k,k1,offset=0; 2859 DM_Network *network = (DM_Network*)dm->data; 2860 DMNetworkComponentHeader header; 2861 2862 PetscFunctionBegin; 2863 ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr); 2864 ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata; 2865 header = (DMNetworkComponentHeader)(network->componentdataarray+offset); 2866 2867 for (i=0; i<ncomps; i++) { 2868 key = header->key[i]; 2869 nvar = header->nvar[i]; 2870 for (j=0; j<numkeys; j++) { 2871 if (key != keys[j]) continue; 2872 2873 ierr = DMNetworkGetGlobalVecOffset(dm,p,i,&offsetg);CHKERRQ(ierr); 2874 if (!blocksize || blocksize[j] == -1) { 2875 for (k=0; k<nvar; k++) idx[(*ii)++] = offsetg + k; 2876 } else { 2877 for (k=0; k<nvar; k+=blocksize[j]) { 2878 for (k1=0; k1<nselectedvar[j]; k1++) idx[(*ii)++] = offsetg + k + selectedvar[j][k1]; 2879 } 2880 } 2881 } 2882 } 2883 PetscFunctionReturn(0); 2884 } 2885 2886 /*@ 2887 DMNetworkCreateIS - Create an index set object from the global vector of the network 2888 2889 Collective 2890 2891 Input Parameters: 2892 + dm - DMNetwork object 2893 . numkeys - number of keys 2894 . keys - array of keys that define the components of the variables you wish to extract 2895 . blocksize - block size of the variables associated to the component 2896 . nselectedvar - number of variables in each block to select 2897 - selectedvar - the offset into the block of each variable in each block to select 2898 2899 Output Parameters: 2900 . is - the index set 2901 2902 Level: Advanced 2903 2904 Notes: 2905 Use blocksize[i] of -1 to indicate select all the variables of the i-th component, for which nselectvar[i] and selectedvar[i] are ignored. Use NULL, NULL, NULL to indicate for all selected components one wishes to obtain all the values of that component. For example, DMNetworkCreateIS(dm,1,&key,NULL,NULL,NULL,&is) will return an is that extracts all the variables for the 0-th component. 2906 2907 .seealso: DMNetworkCreate(), ISCreateGeneral(), DMNetworkCreateLocalIS() 2908 @*/ 2909 PetscErrorCode DMNetworkCreateIS(DM dm,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],IS *is) 2910 { 2911 PetscErrorCode ierr; 2912 MPI_Comm comm; 2913 DM_Network *network = (DM_Network*)dm->data; 2914 PetscInt i,p,estart,eend,vstart,vend,nidx,*idx; 2915 PetscBool ghost; 2916 2917 PetscFunctionBegin; 2918 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2919 2920 /* Check input parameters */ 2921 for (i=0; i<numkeys; i++) { 2922 if (!blocksize || blocksize[i] == -1) continue; 2923 PetscCheckFalse(nselectedvar[i] > blocksize[i],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"number of selectedvariables %D cannot be larger than blocksize %D",nselectedvar[i],blocksize[i]); 2924 } 2925 2926 ierr = DMNetworkGetEdgeRange(dm,&estart,&eend);CHKERRQ(ierr); 2927 ierr = DMNetworkGetVertexRange(dm,&vstart,&vend);CHKERRQ(ierr); 2928 2929 /* Get local number of idx */ 2930 nidx = 0; 2931 for (p=estart; p<eend; p++) { 2932 ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr); 2933 } 2934 for (p=vstart; p<vend; p++) { 2935 ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr); 2936 if (ghost) continue; 2937 ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr); 2938 } 2939 2940 /* Compute idx */ 2941 ierr = PetscMalloc1(nidx,&idx);CHKERRQ(ierr); 2942 i = 0; 2943 for (p=estart; p<eend; p++) { 2944 ierr = DMISComputeIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr); 2945 } 2946 for (p=vstart; p<vend; p++) { 2947 ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr); 2948 if (ghost) continue; 2949 ierr = DMISComputeIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr); 2950 } 2951 2952 /* Create is */ 2953 ierr = ISCreateGeneral(comm,nidx,idx,PETSC_COPY_VALUES,is);CHKERRQ(ierr); 2954 ierr = PetscFree(idx);CHKERRQ(ierr); 2955 PetscFunctionReturn(0); 2956 } 2957 2958 static inline PetscErrorCode DMISComputeLocalIdx_private(DM dm,PetscInt p,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],PetscInt *ii,PetscInt *idx) 2959 { 2960 PetscErrorCode ierr; 2961 PetscInt i,j,ncomps,nvar,key,offsetl,k,k1,offset=0; 2962 DM_Network *network = (DM_Network*)dm->data; 2963 DMNetworkComponentHeader header; 2964 2965 PetscFunctionBegin; 2966 ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr); 2967 ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata; 2968 header = (DMNetworkComponentHeader)(network->componentdataarray+offset); 2969 2970 for (i=0; i<ncomps; i++) { 2971 key = header->key[i]; 2972 nvar = header->nvar[i]; 2973 for (j=0; j<numkeys; j++) { 2974 if (key != keys[j]) continue; 2975 2976 ierr = DMNetworkGetLocalVecOffset(dm,p,i,&offsetl);CHKERRQ(ierr); 2977 if (!blocksize || blocksize[j] == -1) { 2978 for (k=0; k<nvar; k++) idx[(*ii)++] = offsetl + k; 2979 } else { 2980 for (k=0; k<nvar; k+=blocksize[j]) { 2981 for (k1=0; k1<nselectedvar[j]; k1++) idx[(*ii)++] = offsetl + k + selectedvar[j][k1]; 2982 } 2983 } 2984 } 2985 } 2986 PetscFunctionReturn(0); 2987 } 2988 2989 /*@ 2990 DMNetworkCreateLocalIS - Create an index set object from the local vector of the network 2991 2992 Not collective 2993 2994 Input Parameters: 2995 + dm - DMNetwork object 2996 . numkeys - number of keys 2997 . keys - array of keys that define the components of the variables you wish to extract 2998 . blocksize - block size of the variables associated to the component 2999 . nselectedvar - number of variables in each block to select 3000 - selectedvar - the offset into the block of each variable in each block to select 3001 3002 Output Parameters: 3003 . is - the index set 3004 3005 Level: Advanced 3006 3007 Notes: 3008 Use blocksize[i] of -1 to indicate select all the variables of the i-th component, for which nselectvar[i] and selectedvar[i] are ignored. Use NULL, NULL, NULL to indicate for all selected components one wishes to obtain all the values of that component. For example, DMNetworkCreateLocalIS(dm,1,&key,NULL,NULL,NULL,&is) will return an is that extracts all the variables for the 0-th component. 3009 3010 .seealso: DMNetworkCreate(), DMNetworkCreateIS, ISCreateGeneral() 3011 @*/ 3012 PetscErrorCode DMNetworkCreateLocalIS(DM dm,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],IS *is) 3013 { 3014 PetscErrorCode ierr; 3015 DM_Network *network = (DM_Network*)dm->data; 3016 PetscInt i,p,pstart,pend,nidx,*idx; 3017 3018 PetscFunctionBegin; 3019 /* Check input parameters */ 3020 for (i=0; i<numkeys; i++) { 3021 if (!blocksize || blocksize[i] == -1) continue; 3022 PetscCheckFalse(nselectedvar[i] > blocksize[i],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"number of selectedvariables %D cannot be larger than blocksize %D",nselectedvar[i],blocksize[i]); 3023 } 3024 3025 pstart = network->pStart; 3026 pend = network->pEnd; 3027 3028 /* Get local number of idx */ 3029 nidx = 0; 3030 for (p=pstart; p<pend; p++) { 3031 ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr); 3032 } 3033 3034 /* Compute local idx */ 3035 ierr = PetscMalloc1(nidx,&idx);CHKERRQ(ierr); 3036 i = 0; 3037 for (p=pstart; p<pend; p++) { 3038 ierr = DMISComputeLocalIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr); 3039 } 3040 3041 /* Create is */ 3042 ierr = ISCreateGeneral(PETSC_COMM_SELF,nidx,idx,PETSC_COPY_VALUES,is);CHKERRQ(ierr); 3043 ierr = PetscFree(idx);CHKERRQ(ierr); 3044 PetscFunctionReturn(0); 3045 } 3046