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