xref: /petsc/src/dm/impls/network/network.c (revision 99c90e1218fd953acf7c03ffb7f9fa28ff0cd2be)
1af0996ceSBarry Smith #include <petsc/private/dmnetworkimpl.h>  /*I  "petscdmnetwork.h"  I*/
25f2c45f1SShri Abhyankar 
35f2c45f1SShri Abhyankar /*@
4556ed216SShri Abhyankar   DMNetworkGetPlex - Gets the Plex DM associated with this network DM
5556ed216SShri Abhyankar 
6556ed216SShri Abhyankar   Not collective
7556ed216SShri Abhyankar 
8556ed216SShri Abhyankar   Input Parameters:
92bf73ac6SHong Zhang . dm - the dm object
102bf73ac6SHong Zhang 
112bf73ac6SHong Zhang   Output Parameters:
122bf73ac6SHong Zhang . plexdm - the plex dm object
13556ed216SShri Abhyankar 
14556ed216SShri Abhyankar   Level: Advanced
15556ed216SShri Abhyankar 
16556ed216SShri Abhyankar .seealso: DMNetworkCreate()
17556ed216SShri Abhyankar @*/
182bf73ac6SHong Zhang PetscErrorCode DMNetworkGetPlex(DM dm,DM *plexdm)
19556ed216SShri Abhyankar {
202bf73ac6SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
21556ed216SShri Abhyankar 
22556ed216SShri Abhyankar   PetscFunctionBegin;
23556ed216SShri Abhyankar   *plexdm = network->plex;
24556ed216SShri Abhyankar   PetscFunctionReturn(0);
25556ed216SShri Abhyankar }
26556ed216SShri Abhyankar 
27556ed216SShri Abhyankar /*@
282bf73ac6SHong Zhang   DMNetworkGetNumSubNetworks - Gets the the number of subnetworks
2972c3e9f7SHong Zhang 
302bf73ac6SHong Zhang   Not collective
3172c3e9f7SHong Zhang 
3272c3e9f7SHong Zhang   Input Parameters:
332bf73ac6SHong Zhang . dm - the dm object
342bf73ac6SHong Zhang 
352bf73ac6SHong Zhang   Output Parameters:
362bf73ac6SHong Zhang + nsubnet - local number of subnetworks
372bf73ac6SHong Zhang - Nsubnet - global number of subnetworks
3872c3e9f7SHong Zhang 
3997bb938eSShri Abhyankar   Level: beginner
4072c3e9f7SHong Zhang 
412bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkSetNumSubNetworks()
4272c3e9f7SHong Zhang @*/
432bf73ac6SHong Zhang PetscErrorCode DMNetworkGetNumSubNetworks(DM dm,PetscInt *nsubnet,PetscInt *Nsubnet)
4472c3e9f7SHong Zhang {
452bf73ac6SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
4672c3e9f7SHong Zhang 
4772c3e9f7SHong Zhang   PetscFunctionBegin;
482bf73ac6SHong Zhang   if (nsubnet) *nsubnet = network->nsubnet;
492bf73ac6SHong Zhang   if (Nsubnet) *Nsubnet = network->Nsubnet;
5072c3e9f7SHong Zhang   PetscFunctionReturn(0);
5172c3e9f7SHong Zhang }
5272c3e9f7SHong Zhang 
5372c3e9f7SHong Zhang /*@
542bf73ac6SHong Zhang   DMNetworkSetNumSubNetworks - Sets the number of subnetworks
555f2c45f1SShri Abhyankar 
56d083f849SBarry Smith   Collective on dm
575f2c45f1SShri Abhyankar 
585f2c45f1SShri Abhyankar   Input Parameters:
595f2c45f1SShri Abhyankar + dm - the dm object
602bf73ac6SHong Zhang . nsubnet - local number of subnetworks
612bf73ac6SHong Zhang - Nsubnet - global number of subnetworks
625f2c45f1SShri Abhyankar 
6397bb938eSShri Abhyankar    Level: beginner
641b266c99SBarry Smith 
652bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetNumSubNetworks()
665f2c45f1SShri Abhyankar @*/
672bf73ac6SHong Zhang PetscErrorCode DMNetworkSetNumSubNetworks(DM dm,PetscInt nsubnet,PetscInt Nsubnet)
685f2c45f1SShri Abhyankar {
695f2c45f1SShri Abhyankar   PetscErrorCode ierr;
705f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
715f2c45f1SShri Abhyankar 
725f2c45f1SShri Abhyankar   PetscFunctionBegin;
732bf73ac6SHong Zhang   if (network->Nsubnet != 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network");
742bf73ac6SHong Zhang 
755f2c45f1SShri Abhyankar   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
762bf73ac6SHong Zhang   PetscValidLogicalCollectiveInt(dm,nsubnet,2);
772bf73ac6SHong Zhang   PetscValidLogicalCollectiveInt(dm,Nsubnet,3);
787765340cSHong Zhang 
792bf73ac6SHong Zhang   if (Nsubnet == PETSC_DECIDE) {
802bf73ac6SHong Zhang     if (nsubnet < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of local subnetworks %D cannot be less than 0",nsubnet);
8155b25c41SPierre Jolivet     ierr = MPIU_Allreduce(&nsubnet,&Nsubnet,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
82caf410d2SHong Zhang   }
832bf73ac6SHong Zhang   if (Nsubnet < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Number of global subnetworks %D cannot be less than 1",Nsubnet);
84caf410d2SHong Zhang 
852bf73ac6SHong Zhang   network->Nsubnet  = Nsubnet;
862bf73ac6SHong Zhang   network->nsubnet  = 0;       /* initia value; will be determind by DMNetworkAddSubnetwork() */
872bf73ac6SHong Zhang   ierr = PetscCalloc1(Nsubnet,&network->subnet);CHKERRQ(ierr);
88caf410d2SHong Zhang 
892bf73ac6SHong Zhang   /* num of shared vertices */
902bf73ac6SHong Zhang   network->nsvtx = 0;
912bf73ac6SHong Zhang   network->Nsvtx = 0;
927765340cSHong Zhang   PetscFunctionReturn(0);
937765340cSHong Zhang }
947765340cSHong Zhang 
955f2c45f1SShri Abhyankar /*@
962bf73ac6SHong Zhang   DMNetworkAddSubnetwork - Add a subnetwork
975f2c45f1SShri Abhyankar 
982bf73ac6SHong Zhang   Collective on dm
995f2c45f1SShri Abhyankar 
1005f2c45f1SShri Abhyankar   Input Parameters:
101e3e68989SHong Zhang + dm - the dm object
1022bf73ac6SHong Zhang . name - name of the subnetwork
1032bf73ac6SHong Zhang . nv - number of local vertices of this subnetwork
1042bf73ac6SHong Zhang . ne - number of local edges of this subnetwork
1052bf73ac6SHong Zhang - edgelist - list of edges for this subnetwork
1062bf73ac6SHong Zhang 
1072bf73ac6SHong Zhang   Output Parameters:
1082bf73ac6SHong Zhang . netnum - global index of the subnetwork
1095f2c45f1SShri Abhyankar 
1105f2c45f1SShri Abhyankar   Notes:
1115f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1122bf73ac6SHong Zhang   not be destroyed before the call to DMNetworkLayoutSetUp()
1135f2c45f1SShri Abhyankar 
11497bb938eSShri Abhyankar   Level: beginner
1155f2c45f1SShri Abhyankar 
116e3e68989SHong Zhang   Example usage:
1172bf73ac6SHong Zhang   Consider the following network:
118e3e68989SHong Zhang .vb
119e3e68989SHong Zhang  network 1: v1 -> v2 -> v0
120e3e68989SHong Zhang .ve
121e3e68989SHong Zhang 
122e3e68989SHong Zhang  The resulting input
1232bf73ac6SHong Zhang    edgelist = [1 2 | 2 0]
124e3e68989SHong Zhang 
1252bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkSetNumSubnetworks()
1265f2c45f1SShri Abhyankar @*/
1272bf73ac6SHong Zhang PetscErrorCode DMNetworkAddSubnetwork(DM dm,const char* name,PetscInt nv,PetscInt ne,PetscInt edgelist[],PetscInt *netnum)
1285f2c45f1SShri Abhyankar {
1292bf73ac6SHong Zhang   PetscErrorCode ierr;
1305f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
1312bf73ac6SHong Zhang   PetscInt       i = network->nsubnet,a[2],b[2];
1325f2c45f1SShri Abhyankar 
1335f2c45f1SShri Abhyankar   PetscFunctionBegin;
1342bf73ac6SHong Zhang   if (name) {
1352bf73ac6SHong Zhang     ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr);
136e3e68989SHong Zhang   }
1372bf73ac6SHong Zhang 
1382bf73ac6SHong Zhang   network->subnet[i].nvtx     = nv;
1392bf73ac6SHong Zhang   network->subnet[i].nedge    = ne;
1402bf73ac6SHong Zhang   network->subnet[i].edgelist = edgelist;
1412bf73ac6SHong Zhang 
1422bf73ac6SHong Zhang   /* Get global number of vertices and edges for subnet[i] */
1432bf73ac6SHong Zhang   a[0] = nv; a[1] = ne;
14455b25c41SPierre Jolivet   ierr = MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
1452bf73ac6SHong Zhang   network->subnet[i].Nvtx  = b[0];
1462bf73ac6SHong Zhang   network->subnet[i].Nedge = b[1];
1472bf73ac6SHong Zhang 
1482bf73ac6SHong Zhang   /* ----------------------------------------------------------
1492bf73ac6SHong Zhang    p=v or e;
1502bf73ac6SHong Zhang    subnet[0].pStart   = 0
1512bf73ac6SHong Zhang    subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i])
1522bf73ac6SHong Zhang    ----------------------------------------------------------------------- */
1532bf73ac6SHong Zhang   /* GLOBAL subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */
1542bf73ac6SHong Zhang   network->subnet[i].vStart = network->NVertices;
1552bf73ac6SHong Zhang   network->subnet[i].vEnd   = network->subnet[i].vStart + network->subnet[i].Nvtx; /* global vEnd of subnet[i] */
1562bf73ac6SHong Zhang 
1572bf73ac6SHong Zhang   network->nVertices += nv;
1582bf73ac6SHong Zhang   network->NVertices += network->subnet[i].Nvtx;
1592bf73ac6SHong Zhang 
1602bf73ac6SHong Zhang   /* LOCAL subnet[].eStart and eEnd, used by DMNetworkLayoutSetUp() */
1612bf73ac6SHong Zhang   network->subnet[i].eStart = network->nEdges;
1622bf73ac6SHong Zhang   network->subnet[i].eEnd   = network->subnet[i].eStart + ne;
1632bf73ac6SHong Zhang   network->nEdges += ne;
1642bf73ac6SHong Zhang   network->NEdges += network->subnet[i].Nedge;
1652bf73ac6SHong Zhang 
1662bf73ac6SHong Zhang   ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr);
1672bf73ac6SHong Zhang   if (netnum) *netnum = network->nsubnet;
1682bf73ac6SHong Zhang   network->nsubnet++;
1692bf73ac6SHong Zhang   PetscFunctionReturn(0);
1702bf73ac6SHong Zhang }
1712bf73ac6SHong Zhang 
1722bf73ac6SHong Zhang /*
1732bf73ac6SHong Zhang   SetUp a single svtx struct. See SVtx defined in dmnetworkimpl.h
1742bf73ac6SHong Zhang   Set gidx and type if input v=(net,idx) is a from_vertex;
1752bf73ac6SHong Zhang   Get gid, type and index in the svtx array if input v=(net,idx) is a to_vertex.
1762bf73ac6SHong Zhang 
1772bf73ac6SHong Zhang   Input:  Nsvtx, svtx, net, idx, gidx
1782bf73ac6SHong Zhang   Output: gidx, svtype, svtx_idx
1792bf73ac6SHong Zhang  */
1802bf73ac6SHong Zhang static PetscErrorCode SVtxSetUp(PetscInt Nsvtx,SVtx *svtx,PetscInt net,PetscInt idx,PetscInt *gidx,SVtxType *svtype,PetscInt *svtx_idx)
1812bf73ac6SHong Zhang {
1822bf73ac6SHong Zhang   PetscInt i,j,*svto;
1832bf73ac6SHong Zhang   SVtxType vtype;
1842bf73ac6SHong Zhang 
1852bf73ac6SHong Zhang   PetscFunctionBegin;
1862bf73ac6SHong Zhang   if (!Nsvtx) PetscFunctionReturn(0);
1872bf73ac6SHong Zhang 
1882bf73ac6SHong Zhang   vtype = SVNONE;
1892bf73ac6SHong Zhang   for (i=0; i<Nsvtx; i++) {
1902bf73ac6SHong Zhang     if (net == svtx[i].sv[0] && idx == svtx[i].sv[1]) {
1912bf73ac6SHong Zhang       /* (1) input vertex net.idx is a shared from_vertex, set its global index and output its svtype */
1922bf73ac6SHong Zhang       svtx[i].gidx = *gidx; /* set gidx */
1932bf73ac6SHong Zhang       vtype        = SVFROM;
1942bf73ac6SHong Zhang     } else { /* loop over svtx[i].n */
1952bf73ac6SHong Zhang       for (j=1; j<svtx[i].n; j++) {
1962bf73ac6SHong Zhang         svto = svtx[i].sv + 2*j;
1972bf73ac6SHong Zhang         if (net == svto[0] && idx == svto[1]) {
1982bf73ac6SHong Zhang           /* input vertex net.idx is a shared to_vertex, output its global index and its svtype */
1992bf73ac6SHong Zhang           *gidx = svtx[i].gidx; /* output gidx for to_vertex */
2002bf73ac6SHong Zhang           vtype = SVTO;
2012bf73ac6SHong Zhang         }
2022bf73ac6SHong Zhang       }
2032bf73ac6SHong Zhang     }
2042bf73ac6SHong Zhang     if (vtype != SVNONE) break;
2052bf73ac6SHong Zhang   }
2062bf73ac6SHong Zhang   if (svtype)   *svtype   = vtype;
2072bf73ac6SHong Zhang   if (svtx_idx) *svtx_idx = i;
2082bf73ac6SHong Zhang   PetscFunctionReturn(0);
2092bf73ac6SHong Zhang }
2102bf73ac6SHong Zhang 
2112bf73ac6SHong Zhang /*
2122bf73ac6SHong Zhang  Add a new shared vertex sv=(net,idx) to table svtas[ita]
2132bf73ac6SHong Zhang */
2142bf73ac6SHong Zhang static PetscErrorCode TableAddSVtx(PetscTable *svtas,PetscInt ita,PetscInt* tdata,PetscInt *sv_wk,PetscInt *ii,PetscInt *sedgelist,PetscInt k,DM_Network *network,PetscInt **ta2sv)
2152bf73ac6SHong Zhang {
2162bf73ac6SHong Zhang   PetscInt       net,idx,gidx,i=*ii;
2172bf73ac6SHong Zhang   PetscErrorCode ierr;
2182bf73ac6SHong Zhang 
2192bf73ac6SHong Zhang   PetscFunctionBegin;
2202bf73ac6SHong Zhang   net = sv_wk[2*i]   = sedgelist[k];
2212bf73ac6SHong Zhang   idx = sv_wk[2*i+1] = sedgelist[k+1];
2222bf73ac6SHong Zhang   gidx = network->subnet[net].vStart + idx;
2232bf73ac6SHong Zhang   ierr = PetscTableAdd(svtas[ita],gidx+1,tdata[ita]+1,INSERT_VALUES);CHKERRQ(ierr);
2242bf73ac6SHong Zhang   *(ta2sv[ita] + tdata[ita]) = i; /* maps tdata to index of sv_wk; sv_wk keeps (net,idx) info */
2252bf73ac6SHong Zhang   tdata[ita]++; (*ii)++;
2262bf73ac6SHong Zhang   PetscFunctionReturn(0);
2272bf73ac6SHong Zhang }
2282bf73ac6SHong Zhang 
2292bf73ac6SHong Zhang /*
2302bf73ac6SHong Zhang   Create an array of shared vertices. See SVtx and SVtxType in dmnetworkimpl.h
2312bf73ac6SHong Zhang 
2322bf73ac6SHong Zhang   Input:  dm, Nsedgelist, sedgelist
2332bf73ac6SHong Zhang   Output: Nsvtx,svtx
2342bf73ac6SHong Zhang 
2352bf73ac6SHong Zhang   Note: Output svtx is organized as
2362bf73ac6SHong Zhang         sv(net[0],idx[0]) --> sv(net[1],idx[1])
2372bf73ac6SHong Zhang                           --> sv(net[1],idx[1])
2382bf73ac6SHong Zhang                           ...
2392bf73ac6SHong Zhang                           --> sv(net[n-1],idx[n-1])
2402bf73ac6SHong Zhang         and net[0] < net[1] < ... < net[n-1]
2412bf73ac6SHong Zhang         where sv[0] has SVFROM type, sv[i], i>0, has SVTO type.
2422bf73ac6SHong Zhang  */
2432bf73ac6SHong Zhang static PetscErrorCode SVtxCreate(DM dm,PetscInt Nsedgelist,PetscInt *sedgelist,PetscInt *Nsvtx,SVtx **svtx)
2442bf73ac6SHong Zhang {
2452bf73ac6SHong Zhang   PetscErrorCode ierr;
2462bf73ac6SHong Zhang   SVtx           *sedges = NULL;
2472bf73ac6SHong Zhang   PetscInt       *sv,k,j,nsv,*tdata,**ta2sv;
2482bf73ac6SHong Zhang   PetscTable     *svtas;
2492bf73ac6SHong Zhang   PetscInt       gidx,net,idx,i,nta,ita,idx_from,idx_to,n,*sv_wk;
2502bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
2512bf73ac6SHong Zhang   PetscTablePosition ppos;
2522bf73ac6SHong Zhang 
2532bf73ac6SHong Zhang   PetscFunctionBegin;
2542bf73ac6SHong Zhang   /* (1) Crete ctables svtas */
2552bf73ac6SHong Zhang   ierr = PetscCalloc4(Nsedgelist,&svtas,Nsedgelist,&tdata,4*Nsedgelist,&sv_wk,2*Nsedgelist,&ta2sv);CHKERRQ(ierr);
2562bf73ac6SHong Zhang 
2572bf73ac6SHong Zhang   j   = 0;   /* sedgelist counter */
2582bf73ac6SHong Zhang   k   = 0;   /* sedgelist vertex counter j = 4*k */
2592bf73ac6SHong Zhang   i   = 0;   /* sv_wk (vertices added to the ctables) counter */
2602bf73ac6SHong Zhang   nta = 0;   /* num of sv tables created */
2612bf73ac6SHong Zhang 
2622bf73ac6SHong Zhang   /* for j=0 */
2632bf73ac6SHong Zhang   ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr);
2642bf73ac6SHong Zhang   ierr = PetscMalloc1(2*Nsedgelist,&ta2sv[nta]);CHKERRQ(ierr);
2652bf73ac6SHong Zhang 
2662bf73ac6SHong Zhang   ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
2672bf73ac6SHong Zhang   ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
2682bf73ac6SHong Zhang   nta++; k += 4;
2692bf73ac6SHong Zhang 
2702bf73ac6SHong Zhang   for (j = 1; j < Nsedgelist; j++) {
2712bf73ac6SHong Zhang     for (ita = 0; ita < nta; ita++) {
2722bf73ac6SHong Zhang       /* vfrom */
2732bf73ac6SHong Zhang       net = sedgelist[k]; idx = sedgelist[k+1];
2742bf73ac6SHong Zhang       gidx = network->subnet[net].vStart + idx; /* global index of the vertex net.idx before merging shared vertices */
2752bf73ac6SHong Zhang       ierr = PetscTableFind(svtas[ita],gidx+1,&idx_from);CHKERRQ(ierr);
2762bf73ac6SHong Zhang 
2772bf73ac6SHong Zhang       /* vto */
2782bf73ac6SHong Zhang       net = sedgelist[k+2]; idx = sedgelist[k+3];
2792bf73ac6SHong Zhang       gidx = network->subnet[net].vStart + idx;
2802bf73ac6SHong Zhang       ierr = PetscTableFind(svtas[ita],gidx+1,&idx_to);CHKERRQ(ierr);
2812bf73ac6SHong Zhang 
2822bf73ac6SHong Zhang       if (idx_from || idx_to) { /* vfrom or vto is on table svtas[ita] */
2832bf73ac6SHong Zhang         idx_from--; idx_to--;
2842bf73ac6SHong Zhang         if (idx_from < 0) { /* vto is on svtas[ita] */
2852bf73ac6SHong Zhang           ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
2862bf73ac6SHong Zhang           break;
2872bf73ac6SHong Zhang         } else if (idx_to < 0) {
2882bf73ac6SHong Zhang           ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
2892bf73ac6SHong Zhang           break;
2902bf73ac6SHong Zhang         }
2912bf73ac6SHong Zhang       }
2922bf73ac6SHong Zhang     }
2932bf73ac6SHong Zhang 
2942bf73ac6SHong Zhang     if (ita == nta) {
2952bf73ac6SHong Zhang       ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr);
2962bf73ac6SHong Zhang       ierr = PetscMalloc1(2*Nsedgelist, &ta2sv[nta]);CHKERRQ(ierr);
2972bf73ac6SHong Zhang 
2982bf73ac6SHong Zhang       ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
2992bf73ac6SHong Zhang       ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
3002bf73ac6SHong Zhang       nta++;
3012bf73ac6SHong Zhang     }
3022bf73ac6SHong Zhang     k += 4;
3032bf73ac6SHong Zhang   }
3042bf73ac6SHong Zhang 
3052bf73ac6SHong Zhang   /* (2) Construct sedges from ctable
3062bf73ac6SHong Zhang      sedges: edges connect vertex sv[0]=(net[0],idx[0]) to vertices sv[k], k=1,...,n-1;
3074f5c2772SJose E. Roman      net[k], k=0, ...,n-1, are in ascending order */
3082bf73ac6SHong Zhang   ierr = PetscMalloc1(nta,&sedges);CHKERRQ(ierr);
3092bf73ac6SHong Zhang   for (nsv = 0; nsv < nta; nsv++) {
3104f5c2772SJose E. Roman     /* for a single svtx, put shared vertices in ascending order of gidx */
3114f5c2772SJose E. Roman     ierr = PetscTableGetCount(svtas[nsv],&n);CHKERRQ(ierr);
3122bf73ac6SHong Zhang     ierr = PetscCalloc1(2*n,&sv);CHKERRQ(ierr);
3132bf73ac6SHong Zhang     sedges[nsv].sv   = sv;
3142bf73ac6SHong Zhang     sedges[nsv].n    = n;
3152bf73ac6SHong Zhang     sedges[nsv].gidx = -1; /* initialization */
3162bf73ac6SHong Zhang 
3172bf73ac6SHong Zhang     ierr = PetscTableGetHeadPosition(svtas[nsv],&ppos);CHKERRQ(ierr);
3184f5c2772SJose E. Roman     for (k=0; k<n; k++) { /* gidx is sorted in ascending order */
3192bf73ac6SHong Zhang       ierr = PetscTableGetNext(svtas[nsv],&ppos,&gidx,&i);CHKERRQ(ierr);
3202bf73ac6SHong Zhang       gidx--; i--;
3212bf73ac6SHong Zhang 
3222bf73ac6SHong Zhang       j = ta2sv[nsv][i]; /* maps i to index of sv_wk */
3232bf73ac6SHong Zhang       sv[2*k]   = sv_wk[2*j];
3242bf73ac6SHong Zhang       sv[2*k+1] = sv_wk[2*j + 1];
3252bf73ac6SHong Zhang     }
3262bf73ac6SHong Zhang   }
3272bf73ac6SHong Zhang 
3282bf73ac6SHong Zhang   for (j=0; j<nta; j++) {
3292bf73ac6SHong Zhang     ierr = PetscTableDestroy(&svtas[j]);CHKERRQ(ierr);
3302bf73ac6SHong Zhang     ierr = PetscFree(ta2sv[j]);CHKERRQ(ierr);
3312bf73ac6SHong Zhang   }
3322bf73ac6SHong Zhang   ierr = PetscFree4(svtas,tdata,sv_wk,ta2sv);CHKERRQ(ierr);
3332bf73ac6SHong Zhang 
3342bf73ac6SHong Zhang   *Nsvtx = nta;
3352bf73ac6SHong Zhang   *svtx  = sedges;
3362bf73ac6SHong Zhang   PetscFunctionReturn(0);
3372bf73ac6SHong Zhang }
3382bf73ac6SHong Zhang 
3392bf73ac6SHong Zhang static PetscErrorCode DMNetworkLayoutSetUp_Coupling(DM dm)
3402bf73ac6SHong Zhang {
3412bf73ac6SHong Zhang   PetscErrorCode ierr;
3422bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
3432bf73ac6SHong Zhang   PetscInt       i,j,ctr,np,*edges,*subnetvtx,vStart;
3442bf73ac6SHong Zhang   PetscInt       k,*vidxlTog,Nsv=0,Nsubnet=network->Nsubnet;
3452bf73ac6SHong Zhang   PetscInt       *sedgelist=network->sedgelist;
3462bf73ac6SHong Zhang   const PetscInt *cone;
3472bf73ac6SHong Zhang   MPI_Comm       comm;
3482bf73ac6SHong Zhang   PetscMPIInt    size,rank,*recvcounts=NULL,*displs=NULL;
3492bf73ac6SHong Zhang   PetscInt       net,idx,gidx,nmerged,e,v,vfrom,vto,*vrange,*eowners,gidx_from,net_from,sv_idx;
3502bf73ac6SHong Zhang   SVtxType       svtype = SVNONE;
3512bf73ac6SHong Zhang   SVtx           *svtx=NULL;
3522bf73ac6SHong Zhang   PetscSection   sectiong;
3532bf73ac6SHong Zhang 
3542bf73ac6SHong Zhang   PetscFunctionBegin;
3552bf73ac6SHong Zhang   /* This implementation requires user input each subnet by a single processor, thus subnet[net].nvtx=subnet[net].Nvtx */
3562bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
3572bf73ac6SHong Zhang     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);
3582bf73ac6SHong Zhang   }
3592bf73ac6SHong Zhang 
3602bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
36155b25c41SPierre Jolivet   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
36255b25c41SPierre Jolivet   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
3632bf73ac6SHong Zhang 
3642bf73ac6SHong Zhang   /* (1) Create svtx[] from sedgelist */
3652bf73ac6SHong Zhang   /* -------------------------------- */
3662bf73ac6SHong Zhang   /* Nsv: global number of SVtx; svtx: shared vertices, see SVtx in dmnetworkimpl.h */
3672bf73ac6SHong Zhang   ierr = SVtxCreate(dm,network->Nsvtx,sedgelist,&Nsv,&svtx);CHKERRQ(ierr);
3682bf73ac6SHong Zhang 
3692bf73ac6SHong Zhang   /* (2) Setup svtx; Shared vto vertices are merged to their vfrom vertex with same global vetex index (gidx) */
3702bf73ac6SHong Zhang   /* -------------------------------------------------------------------------------------------------------- */
3712bf73ac6SHong Zhang   /* (2.1) compute vrage[rank]: global index of 1st local vertex in proc[rank] */
3722bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
3732bf73ac6SHong Zhang   for (i=0; i<size; i++) {displs[i] = i; recvcounts[i] = 1;}
3742bf73ac6SHong Zhang 
3752bf73ac6SHong Zhang   vrange[0] = 0;
3762bf73ac6SHong Zhang   ierr = MPI_Allgatherv(&network->nVertices,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
3772bf73ac6SHong Zhang   for (i=2; i<size+1; i++) {
3782bf73ac6SHong Zhang     vrange[i] += vrange[i-1];
3792bf73ac6SHong Zhang   }
3802bf73ac6SHong Zhang 
3812bf73ac6SHong Zhang   /* (2.2) Create vidxlTog: maps UN-MERGED local vertex index i to global index gidx (plex, excluding ghost vertices) */
3822bf73ac6SHong Zhang   ierr = PetscMalloc1(network->nVertices,&vidxlTog);CHKERRQ(ierr);
3832bf73ac6SHong Zhang   i = 0; gidx = 0;
3842bf73ac6SHong Zhang   nmerged = 0; /* local num of merged vertices */
3852bf73ac6SHong Zhang   network->nsvtx = 0;
3862bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
3872bf73ac6SHong Zhang     for (idx=0; idx<network->subnet[net].Nvtx; idx++) {
3882bf73ac6SHong Zhang       gidx_from = gidx;
3892bf73ac6SHong Zhang       sv_idx    = -1;
3902bf73ac6SHong Zhang 
3912bf73ac6SHong Zhang       ierr = SVtxSetUp(Nsv,svtx,net,idx,&gidx_from,&svtype,&sv_idx);CHKERRQ(ierr);
3922bf73ac6SHong Zhang       if (svtype == SVTO) {
3932bf73ac6SHong Zhang         if (network->subnet[net].nvtx) {/* this proc owns sv_to */
3942bf73ac6SHong Zhang           net_from = svtx[sv_idx].sv[0]; /* subnet num of its shared vertex */
3952bf73ac6SHong Zhang           if (network->subnet[net_from].nvtx == 0) {
3962bf73ac6SHong Zhang             /* this proc does not own v_from, thus a new local coupling vertex */
3972bf73ac6SHong Zhang             network->nsvtx++;
3982bf73ac6SHong Zhang           }
3992bf73ac6SHong Zhang           vidxlTog[i++] = gidx_from;
4002bf73ac6SHong Zhang           nmerged++; /* a coupling vertex -- merged */
4012bf73ac6SHong Zhang         }
4022bf73ac6SHong Zhang       } else {
4032bf73ac6SHong Zhang         if (svtype == SVFROM) {
4042bf73ac6SHong Zhang           if (network->subnet[net].nvtx) {
4052bf73ac6SHong Zhang             /* this proc owns this v_from, a new local coupling vertex */
4062bf73ac6SHong Zhang             network->nsvtx++;
4072bf73ac6SHong Zhang           }
4082bf73ac6SHong Zhang         }
4092bf73ac6SHong Zhang         if (network->subnet[net].nvtx) vidxlTog[i++] = gidx;
4102bf73ac6SHong Zhang         gidx++;
4112bf73ac6SHong Zhang       }
4122bf73ac6SHong Zhang     }
4132bf73ac6SHong Zhang   }
4142bf73ac6SHong Zhang #if defined(PETSC_USE_DEBUG)
4152bf73ac6SHong Zhang   if (i != network->nVertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"%D != %D nVertices",i,network->nVertices);
4162bf73ac6SHong Zhang #endif
4172bf73ac6SHong Zhang 
4182bf73ac6SHong Zhang   /* (2.3) Setup svtable for querry shared vertices */
4192bf73ac6SHong Zhang   for (v=0; v<Nsv; v++) {
4202bf73ac6SHong Zhang     gidx = svtx[v].gidx;
4212bf73ac6SHong Zhang     ierr = PetscTableAdd(network->svtable,gidx+1,v+1,INSERT_VALUES);CHKERRQ(ierr);
4222bf73ac6SHong Zhang   }
4232bf73ac6SHong Zhang 
4242bf73ac6SHong Zhang   /* (2.4) Shared vertices in the subnetworks are merged, update global NVertices: np = sum(local nmerged) */
4252bf73ac6SHong Zhang   ierr = MPI_Allreduce(&nmerged,&np,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
4262bf73ac6SHong Zhang   network->NVertices -= np;
4272bf73ac6SHong Zhang 
4282bf73ac6SHong Zhang   ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr);
4292bf73ac6SHong Zhang   ierr = PetscCalloc1(network->nVertices+network->nsvtx,&network->subnetvtx);CHKERRQ(ierr);
4302bf73ac6SHong Zhang 
4312bf73ac6SHong Zhang   ctr = 0;
4322bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
4332bf73ac6SHong Zhang     for (j = 0; j < network->subnet[net].nedge; j++) {
4342bf73ac6SHong Zhang       /* vfrom: */
4352bf73ac6SHong Zhang       i = network->subnet[net].edgelist[2*j] + (network->subnet[net].vStart - vrange[rank]);
4362bf73ac6SHong Zhang       edges[2*ctr] = vidxlTog[i];
4372bf73ac6SHong Zhang 
4382bf73ac6SHong Zhang       /* vto */
4392bf73ac6SHong Zhang       i = network->subnet[net].edgelist[2*j+1] + (network->subnet[net].vStart - vrange[rank]);
4402bf73ac6SHong Zhang       edges[2*ctr+1] = vidxlTog[i];
4412bf73ac6SHong Zhang       ctr++;
4422bf73ac6SHong Zhang     }
4432bf73ac6SHong Zhang   }
4442bf73ac6SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
4452bf73ac6SHong Zhang   ierr = PetscFree(vidxlTog);CHKERRQ(ierr);
4462bf73ac6SHong Zhang 
4472bf73ac6SHong Zhang   /* (3) Create network->plex */
4482bf73ac6SHong Zhang   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
4492bf73ac6SHong Zhang   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
4502bf73ac6SHong Zhang   ierr = DMSetDimension(network->plex,1);CHKERRQ(ierr);
4512bf73ac6SHong Zhang   if (size == 1) {
4522bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices-nmerged,2,edges);CHKERRQ(ierr);
4532bf73ac6SHong Zhang   } else {
4542bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices-nmerged,PETSC_DECIDE,2,edges,NULL);CHKERRQ(ierr);
4552bf73ac6SHong Zhang   }
4562bf73ac6SHong Zhang 
4572bf73ac6SHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
4582bf73ac6SHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
4592bf73ac6SHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
4602bf73ac6SHong Zhang   vStart = network->vStart;
4612bf73ac6SHong Zhang 
4622bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
4632bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
4642bf73ac6SHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
4652bf73ac6SHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
4662bf73ac6SHong Zhang 
4672bf73ac6SHong Zhang   network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
4682bf73ac6SHong Zhang   np = network->pEnd - network->pStart;
4692bf73ac6SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
4702bf73ac6SHong Zhang 
4712bf73ac6SHong Zhang   /* (4) Create vidxlTog: maps MERGED plex local vertex index (including ghosts) to User's global vertex index (without merging shared vertices) */
4722bf73ac6SHong Zhang   np = network->vEnd - vStart; /* include ghost vertices */
4732bf73ac6SHong Zhang   ierr = PetscMalloc2(np,&vidxlTog,size+1,&eowners);CHKERRQ(ierr);
4742bf73ac6SHong Zhang 
4752bf73ac6SHong Zhang   ctr = 0;
4762bf73ac6SHong Zhang   for (e=network->eStart; e<network->eEnd; e++) {
4772bf73ac6SHong Zhang     ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
4782bf73ac6SHong Zhang     vidxlTog[cone[0] - vStart] = edges[2*ctr];
4792bf73ac6SHong Zhang     vidxlTog[cone[1] - vStart] = edges[2*ctr+1];
4802bf73ac6SHong Zhang     ctr++;
4812bf73ac6SHong Zhang   }
4822bf73ac6SHong Zhang   ierr = PetscFree(edges);CHKERRQ(ierr);
4832bf73ac6SHong Zhang 
4842bf73ac6SHong Zhang   /* (5) Create vertices and edges array for the subnetworks */
4852bf73ac6SHong Zhang   subnetvtx = network->subnetvtx;
4862bf73ac6SHong Zhang   for (j=0; j < Nsubnet; j++) {
4872bf73ac6SHong Zhang     ierr = PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);CHKERRQ(ierr);
4882bf73ac6SHong Zhang     network->subnet[j].vertices = subnetvtx;
4892bf73ac6SHong Zhang     subnetvtx                  += network->subnet[j].nvtx;
4902bf73ac6SHong Zhang   }
4912bf73ac6SHong Zhang   network->svertices                = subnetvtx;
4922bf73ac6SHong Zhang 
4932bf73ac6SHong Zhang   /* Get edge ownership */
4942bf73ac6SHong Zhang   np = network->eEnd - network->eStart; /* num of local edges */
4952bf73ac6SHong Zhang   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr);
4962bf73ac6SHong Zhang   eowners[0] = 0;
4972bf73ac6SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
4982bf73ac6SHong Zhang 
4992bf73ac6SHong Zhang   e = 0;
5002bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
5012bf73ac6SHong Zhang     v = 0;
5022bf73ac6SHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
5032bf73ac6SHong Zhang 
5042bf73ac6SHong Zhang       /* edge e */
5052bf73ac6SHong Zhang       network->header[e].index    = e + eowners[rank]; /* Global edge index */
5062bf73ac6SHong Zhang       network->header[e].subnetid = i;                 /* Subnetwork id */
5072bf73ac6SHong Zhang       network->subnet[i].edges[j] = e;
5082bf73ac6SHong Zhang       network->header[e].ndata           = 0;
5092bf73ac6SHong Zhang       network->header[e].offset[0]       = 0;
5102bf73ac6SHong Zhang       network->header[e].offsetvarrel[0] = 0;
5112bf73ac6SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,e,network->dataheadersize);CHKERRQ(ierr);
5122bf73ac6SHong Zhang 
5132bf73ac6SHong Zhang       /* connected vertices */
5142bf73ac6SHong Zhang       ierr = DMPlexGetCone(network->plex,e,&cone);CHKERRQ(ierr);
5152bf73ac6SHong Zhang 
5162bf73ac6SHong Zhang       /* vertex cone[0] */
5172bf73ac6SHong Zhang       vfrom = network->subnet[i].edgelist[2*v];
5182bf73ac6SHong Zhang       network->header[cone[0]].index = vidxlTog[cone[0]-vStart]; /*  Global vertex index */
5192bf73ac6SHong Zhang       network->header[cone[0]].subnetid = i;                     /* Subnetwork id */
5202bf73ac6SHong Zhang       network->subnet[i].vertices[vfrom] = cone[0];              /* user's subnet[].dix = petsc's v */
5212bf73ac6SHong Zhang 
5222bf73ac6SHong Zhang       /* vertex cone[1] */
5232bf73ac6SHong Zhang       vto = network->subnet[i].edgelist[2*v+1];
5242bf73ac6SHong Zhang       network->header[cone[1]].index = vidxlTog[cone[1]-vStart]; /*  Global vertex index */
5252bf73ac6SHong Zhang       network->header[cone[1]].subnetid   = i;
5262bf73ac6SHong Zhang       network->subnet[i].vertices[vto]= cone[1];
5272bf73ac6SHong Zhang 
5282bf73ac6SHong Zhang       e++; v++;
5292bf73ac6SHong Zhang     }
5302bf73ac6SHong Zhang   }
5312bf73ac6SHong Zhang 
5322bf73ac6SHong Zhang   /* Set vertex array for the subnetworks */
5332bf73ac6SHong Zhang   k = 0;
5342bf73ac6SHong Zhang   for (v=vStart; v<network->vEnd; v++) { /* local vertices, including ghosts */
5352bf73ac6SHong Zhang     network->header[v].ndata           = 0;
5362bf73ac6SHong Zhang     network->header[v].offset[0]       = 0;
5372bf73ac6SHong Zhang     network->header[v].offsetvarrel[0] = 0;
5382bf73ac6SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,v,network->dataheadersize);CHKERRQ(ierr);
5392bf73ac6SHong Zhang 
5402bf73ac6SHong Zhang     /* shared vertex */
5412bf73ac6SHong Zhang     ierr = PetscTableFind(network->svtable,vidxlTog[v-vStart]+1,&i);CHKERRQ(ierr);
5422bf73ac6SHong Zhang     if (i) network->svertices[k++] = v;
5432bf73ac6SHong Zhang   }
5442bf73ac6SHong Zhang #if defined(PETSC_USE_DEBUG)
5452bf73ac6SHong Zhang   if (k != network->nsvtx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"k %D != %D nsvtx",k,network->nsvtx);
5462bf73ac6SHong Zhang #endif
5472bf73ac6SHong Zhang 
5482bf73ac6SHong Zhang   ierr = PetscFree2(vidxlTog,eowners);CHKERRQ(ierr);
5492bf73ac6SHong Zhang 
5502bf73ac6SHong Zhang   network->svtx  = svtx;
5512bf73ac6SHong Zhang   network->Nsvtx = Nsv;
5522bf73ac6SHong Zhang   ierr = PetscFree(sedgelist);CHKERRQ(ierr);
5532bf73ac6SHong Zhang 
5542bf73ac6SHong Zhang   /* Create a global section to be used by DMNetworkIsGhostVertex() which is a non-collective routine */
5552bf73ac6SHong Zhang   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
5565f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5575f2c45f1SShri Abhyankar }
5585f2c45f1SShri Abhyankar 
5595f2c45f1SShri Abhyankar /*@
5605f2c45f1SShri Abhyankar   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
5615f2c45f1SShri Abhyankar 
562d083f849SBarry Smith   Collective on dm
5635f2c45f1SShri Abhyankar 
5647a7aea1fSJed Brown   Input Parameters:
5655f2c45f1SShri Abhyankar . DM - the dmnetwork object
5665f2c45f1SShri Abhyankar 
5675f2c45f1SShri Abhyankar   Notes:
5685f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
5695f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
5705f2c45f1SShri Abhyankar 
5715f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
5725f2c45f1SShri Abhyankar 
57397bb938eSShri Abhyankar   Level: beginner
5745f2c45f1SShri Abhyankar 
5752bf73ac6SHong Zhang .seealso: DMNetworkSetNumSubNetworks(), DMNetworkAddSubnetwork()
5765f2c45f1SShri Abhyankar @*/
5775f2c45f1SShri Abhyankar PetscErrorCode DMNetworkLayoutSetUp(DM dm)
5785f2c45f1SShri Abhyankar {
5795f2c45f1SShri Abhyankar   PetscErrorCode ierr;
5805f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
5812bf73ac6SHong Zhang   PetscInt       i,j,ctr,Nsubnet=network->Nsubnet,*eowners,np,*edges,*subnetvtx;
5822bf73ac6SHong Zhang   PetscInt       e,v,vfrom,vto;
583caf410d2SHong Zhang   const PetscInt *cone;
584caf410d2SHong Zhang   MPI_Comm       comm;
585caf410d2SHong Zhang   PetscMPIInt    size,rank;
5866500d4abSHong Zhang 
5876500d4abSHong Zhang   PetscFunctionBegin;
5882bf73ac6SHong Zhang   if (network->nsubnet != network->Nsubnet) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Must call DMNetworkAddSubnetwork() %D times",network->Nsubnet);
5892bf73ac6SHong Zhang 
5902bf73ac6SHong Zhang   /* Create svtable for querry shared vertices */
5912bf73ac6SHong Zhang   ierr = PetscTableCreate(network->Nsvtx,network->NVertices+1,&network->svtable);CHKERRQ(ierr);
5922bf73ac6SHong Zhang 
5932bf73ac6SHong Zhang   if (network->Nsvtx) {
5942bf73ac6SHong Zhang     ierr = DMNetworkLayoutSetUp_Coupling(dm);CHKERRQ(ierr);
5952bf73ac6SHong Zhang     PetscFunctionReturn(0);
5962bf73ac6SHong Zhang   }
5972bf73ac6SHong Zhang 
598caf410d2SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
599ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
600ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
6016500d4abSHong Zhang 
6022bf73ac6SHong Zhang   /* Create LOCAL edgelist for the network by concatenating local input edgelists of the subnetworks */
6038e71b177SVaclav Hapla   ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr);
604caf410d2SHong Zhang   ctr = 0;
6052bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
6066500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
607ba38b151SHong Zhang       edges[2*ctr]   = network->subnet[i].vStart + network->subnet[i].edgelist[2*j];
608ba38b151SHong Zhang       edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1];
6096500d4abSHong Zhang       ctr++;
6106500d4abSHong Zhang     }
6116500d4abSHong Zhang   }
6127765340cSHong Zhang 
6132bf73ac6SHong Zhang   /* Create network->plex; One dimensional network, numCorners=2 */
6148e71b177SVaclav Hapla   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
6158e71b177SVaclav Hapla   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
6162bf73ac6SHong Zhang   ierr = DMSetDimension(network->plex,1);CHKERRQ(ierr);
617caf410d2SHong Zhang   if (size == 1) {
6182bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices,2,edges);CHKERRQ(ierr);
619caf410d2SHong Zhang   } else {
6202bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices,PETSC_DECIDE,2,edges,NULL);CHKERRQ(ierr);
621acdb140fSBarry Smith   }
6222bf73ac6SHong Zhang   ierr = PetscFree(edges);CHKERRQ(ierr); /* local edge list with global idx used by DMPlexBuildFromCellList() */
6236500d4abSHong Zhang 
6246500d4abSHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
6256500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
6266500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
6276500d4abSHong Zhang 
628caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
629caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
6306500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
6316500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
6326500d4abSHong Zhang 
633caf410d2SHong Zhang   network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
634caf410d2SHong Zhang   np = network->pEnd - network->pStart;
635caf410d2SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
636caf410d2SHong Zhang 
6372bf73ac6SHong Zhang   /* Create edge and vertex arrays for the subnetworks */
6382bf73ac6SHong Zhang   for (j=0; j < network->Nsubnet; j++) {
6396500d4abSHong Zhang     ierr = PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);CHKERRQ(ierr);
6406500d4abSHong Zhang   }
641caf410d2SHong Zhang 
642caf410d2SHong Zhang   /* Get edge ownership */
6432bf73ac6SHong Zhang   ierr = PetscMalloc1(size+1,&eowners);CHKERRQ(ierr);
644caf410d2SHong Zhang   np = network->eEnd - network->eStart;
645ffc4695bSBarry Smith   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr);
646caf410d2SHong Zhang   eowners[0] = 0;
647caf410d2SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
648caf410d2SHong Zhang 
649caf410d2SHong Zhang   /* Set network->subnet[*].vertices on array network->subnetvtx */
6502bf73ac6SHong Zhang   np = 0;
6512bf73ac6SHong Zhang   for (j=0; j<network->Nsubnet; j++) {
6522bf73ac6SHong Zhang     /* sum up subnet[j].Nvtx instead of subnet[j].nvtx, because a subnet might be owned by more than one processor;
6532bf73ac6SHong Zhang        below, subnet[i].vertices[vfrom/vto] requires vfrom/vto =0, ...,Nvtx-1
6542bf73ac6SHong Zhang      */
6552bf73ac6SHong Zhang     if (network->subnet[j].nvtx) np += network->subnet[j].Nvtx;
6562bf73ac6SHong Zhang   }
6572bf73ac6SHong Zhang 
6582bf73ac6SHong Zhang   ierr = PetscCalloc1(np,&network->subnetvtx);CHKERRQ(ierr); /* Maps local vertex to local subnetwork's vertex */
659caf410d2SHong Zhang   subnetvtx = network->subnetvtx;
6602bf73ac6SHong Zhang   for (j=0; j<network->Nsubnet; j++) {
661caf410d2SHong Zhang     network->subnet[j].vertices = subnetvtx;
6622bf73ac6SHong Zhang     if (network->subnet[j].nvtx) subnetvtx += network->subnet[j].Nvtx;
663caf410d2SHong Zhang   }
664caf410d2SHong Zhang 
6652bf73ac6SHong Zhang   /* Setup edge and vertex arrays for subnetworks */
6662bf73ac6SHong Zhang   e = 0;
6672bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
6682bf73ac6SHong Zhang     v = 0;
6692bf73ac6SHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
6702bf73ac6SHong Zhang       /* edge e */
6712bf73ac6SHong Zhang       network->header[e].index    = e + eowners[rank];   /* Global edge index */
6722bf73ac6SHong Zhang       network->header[e].subnetid = i;
6732bf73ac6SHong Zhang       network->subnet[i].edges[j] = e;
674caf410d2SHong Zhang 
6752bf73ac6SHong Zhang       network->header[e].ndata           = 0;
6762bf73ac6SHong Zhang       network->header[e].offset[0]       = 0;
6772bf73ac6SHong Zhang       network->header[e].offsetvarrel[0] = 0;
6782bf73ac6SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,e,network->dataheadersize);CHKERRQ(ierr);
6792bf73ac6SHong Zhang 
6802bf73ac6SHong Zhang       /* connected vertices */
6812bf73ac6SHong Zhang       ierr = DMPlexGetCone(network->plex,e,&cone);CHKERRQ(ierr);
6822bf73ac6SHong Zhang 
6832bf73ac6SHong Zhang       /* vertex cone[0] */
6842bf73ac6SHong Zhang       vfrom = network->subnet[i].edgelist[2*v];     /* =subnet[i].idx, Global index! */
6852bf73ac6SHong Zhang       network->header[cone[0]].index     = vfrom + network->subnet[i].vStart; /* Global vertex index */
6862bf73ac6SHong Zhang       network->header[cone[0]].subnetid  = i;       /* Subnetwork id */
6872bf73ac6SHong Zhang       network->subnet[i].vertices[vfrom] = cone[0]; /* user's subnet[].dix = petsc's v */
6882bf73ac6SHong Zhang 
6892bf73ac6SHong Zhang       /* vertex cone[1] */
6902bf73ac6SHong Zhang       vto   = network->subnet[i].edgelist[2*v+1];   /* =subnet[i].idx, Global index! */
6912bf73ac6SHong Zhang       network->header[cone[1]].index    = vto + network->subnet[i].vStart;  /* Global vertex index */
6922bf73ac6SHong Zhang       network->header[cone[1]].subnetid = i;
6932bf73ac6SHong Zhang       network->subnet[i].vertices[vto]  = cone[1];  /* user's subnet[].dix = petsc's v */
6942bf73ac6SHong Zhang 
6952bf73ac6SHong Zhang       e++; v++;
6966500d4abSHong Zhang     }
6976500d4abSHong Zhang   }
6982bf73ac6SHong Zhang   ierr = PetscFree(eowners);CHKERRQ(ierr);
699caf410d2SHong Zhang 
7002bf73ac6SHong Zhang   for (v = network->vStart; v < network->vEnd; v++) {
7012bf73ac6SHong Zhang     network->header[v].ndata           = 0;
7022bf73ac6SHong Zhang     network->header[v].offset[0]       = 0;
7032bf73ac6SHong Zhang     network->header[v].offsetvarrel[0] = 0;
7042bf73ac6SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,v,network->dataheadersize);CHKERRQ(ierr);
7056500d4abSHong Zhang   }
7065f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7075f2c45f1SShri Abhyankar }
7085f2c45f1SShri Abhyankar 
70994ef8ddeSSatish Balay /*@C
7102bf73ac6SHong Zhang   DMNetworkGetSubnetwork - Returns the information about a requested subnetwork
7112bf73ac6SHong Zhang 
7122bf73ac6SHong Zhang   Not collective
7132727e31bSShri Abhyankar 
7147a7aea1fSJed Brown   Input Parameters:
715caf410d2SHong Zhang + dm - the DM object
7162bf73ac6SHong Zhang - netnum - the global index of the subnetwork
7172727e31bSShri Abhyankar 
7187a7aea1fSJed Brown   Output Parameters:
7192727e31bSShri Abhyankar + nv - number of vertices (local)
7202727e31bSShri Abhyankar . ne - number of edges (local)
7212bf73ac6SHong Zhang . vtx - local vertices of the subnetwork
7222bf73ac6SHong Zhang - edge - local edges of the subnetwork
7232727e31bSShri Abhyankar 
7242727e31bSShri Abhyankar   Notes:
7252727e31bSShri Abhyankar   Cannot call this routine before DMNetworkLayoutSetup()
7262727e31bSShri Abhyankar 
72706dd6b0eSSatish Balay   Level: intermediate
72806dd6b0eSSatish Balay 
7292bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkLayoutSetUp()
7302727e31bSShri Abhyankar @*/
7312bf73ac6SHong Zhang PetscErrorCode DMNetworkGetSubnetwork(DM dm,PetscInt netnum,PetscInt *nv,PetscInt *ne,const PetscInt **vtx,const PetscInt **edge)
7322727e31bSShri Abhyankar {
733caf410d2SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
7342727e31bSShri Abhyankar 
7352727e31bSShri Abhyankar   PetscFunctionBegin;
7362bf73ac6SHong Zhang   if (netnum >= network->Nsubnet) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Subnet index %D exceeds the num of subnets %D",netnum,network->Nsubnet);
7372bf73ac6SHong Zhang   if (nv) *nv     = network->subnet[netnum].nvtx;
7382bf73ac6SHong Zhang   if (ne) *ne     = network->subnet[netnum].nedge;
7392bf73ac6SHong Zhang   if (vtx) *vtx   = network->subnet[netnum].vertices;
7402bf73ac6SHong Zhang   if (edge) *edge = network->subnet[netnum].edges;
7412bf73ac6SHong Zhang   PetscFunctionReturn(0);
7422bf73ac6SHong Zhang }
7432bf73ac6SHong Zhang 
7442bf73ac6SHong Zhang /*@
7452bf73ac6SHong Zhang   DMNetworkAddSharedVertices - Add shared vertices that connect two given subnetworks
7462bf73ac6SHong Zhang 
7472bf73ac6SHong Zhang   Collective on dm
7482bf73ac6SHong Zhang 
7492bf73ac6SHong Zhang   Input Parameters:
7502bf73ac6SHong Zhang + dm - the dm object
7512bf73ac6SHong Zhang . anetnum - first subnetwork global numbering returned by DMNetworkAddSubnetwork()
7522bf73ac6SHong Zhang . bnetnum - second subnetwork global numbering returned by DMNetworkAddSubnetwork()
7532bf73ac6SHong Zhang . nsvtx - number of vertices that are shared by the two subnetworks
7542bf73ac6SHong Zhang . asvtx - vertex index in the first subnetwork
7552bf73ac6SHong Zhang - bsvtx - vertex index in the second subnetwork
7562bf73ac6SHong Zhang 
7572bf73ac6SHong Zhang   Level: beginner
7582bf73ac6SHong Zhang 
7592bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkGetSharedVertices()
7602bf73ac6SHong Zhang @*/
7612bf73ac6SHong Zhang PetscErrorCode DMNetworkAddSharedVertices(DM dm,PetscInt anetnum,PetscInt bnetnum,PetscInt nsvtx,PetscInt asvtx[],PetscInt bsvtx[])
7622bf73ac6SHong Zhang {
7632bf73ac6SHong Zhang   PetscErrorCode ierr;
7642bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
7652bf73ac6SHong Zhang   PetscInt       i,nsubnet = network->Nsubnet,*sedgelist,Nsvtx=network->Nsvtx;
7662bf73ac6SHong Zhang 
7672bf73ac6SHong Zhang   PetscFunctionBegin;
7682bf73ac6SHong Zhang   if (anetnum == bnetnum) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Subnetworks must have different netnum");
7692bf73ac6SHong Zhang   if (anetnum < 0 || bnetnum < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"netnum cannot be negative");
7702bf73ac6SHong Zhang   if (!Nsvtx) {
7712bf73ac6SHong Zhang     /* allocate network->sedgelist to hold at most 2*nsubnet pairs of shared vertices */
7722bf73ac6SHong Zhang     ierr = PetscMalloc1(2*4*nsubnet,&network->sedgelist);CHKERRQ(ierr);
7732bf73ac6SHong Zhang   }
7742bf73ac6SHong Zhang 
7752bf73ac6SHong Zhang   sedgelist = network->sedgelist;
7762bf73ac6SHong Zhang   for (i=0; i<nsvtx; i++) {
7772bf73ac6SHong Zhang     sedgelist[4*Nsvtx]   = anetnum; sedgelist[4*Nsvtx+1] = asvtx[i];
7782bf73ac6SHong Zhang     sedgelist[4*Nsvtx+2] = bnetnum; sedgelist[4*Nsvtx+3] = bsvtx[i];
7792bf73ac6SHong Zhang     Nsvtx++;
7802bf73ac6SHong Zhang   }
7812bf73ac6SHong Zhang   if (Nsvtx > 2*nsubnet) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"allocate more space for coupling edgelist");
7822bf73ac6SHong Zhang   network->Nsvtx = Nsvtx;
7832727e31bSShri Abhyankar   PetscFunctionReturn(0);
7842727e31bSShri Abhyankar }
7852727e31bSShri Abhyankar 
7862727e31bSShri Abhyankar /*@C
7872bf73ac6SHong Zhang   DMNetworkGetSharedVertices - Returns the info for the shared vertices
7882bf73ac6SHong Zhang 
7892bf73ac6SHong Zhang   Not collective
790caf410d2SHong Zhang 
7917a7aea1fSJed Brown   Input Parameters:
7922bf73ac6SHong Zhang . dm - the DM object
793caf410d2SHong Zhang 
7947a7aea1fSJed Brown   Output Parameters:
7952bf73ac6SHong Zhang + nsv - number of local shared vertices
7962bf73ac6SHong Zhang - svtx - local shared vertices
797caf410d2SHong Zhang 
798caf410d2SHong Zhang   Notes:
799caf410d2SHong Zhang   Cannot call this routine before DMNetworkLayoutSetup()
800caf410d2SHong Zhang 
801caf410d2SHong Zhang   Level: intermediate
802caf410d2SHong Zhang 
8032bf73ac6SHong Zhang .seealso: DMNetworkGetSubnetwork(), DMNetworkLayoutSetUp(), DMNetworkAddSharedVertices()
804caf410d2SHong Zhang @*/
8052bf73ac6SHong Zhang PetscErrorCode DMNetworkGetSharedVertices(DM dm,PetscInt *nsv,const PetscInt **svtx)
806caf410d2SHong Zhang {
807caf410d2SHong Zhang   DM_Network *net = (DM_Network*)dm->data;
808caf410d2SHong Zhang 
809caf410d2SHong Zhang   PetscFunctionBegin;
8102bf73ac6SHong Zhang   if (net->Nsvtx) {
8112bf73ac6SHong Zhang     *nsv  = net->nsvtx;
8122bf73ac6SHong Zhang     *svtx = net->svertices;
81372c3e9f7SHong Zhang   } else {
8142bf73ac6SHong Zhang     *nsv  = 0;
8152bf73ac6SHong Zhang     *svtx = NULL;
81672c3e9f7SHong Zhang   }
817caf410d2SHong Zhang   PetscFunctionReturn(0);
818caf410d2SHong Zhang }
819caf410d2SHong Zhang 
820caf410d2SHong Zhang /*@C
8215f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
8225f2c45f1SShri Abhyankar 
823d083f849SBarry Smith   Logically collective on dm
8245f2c45f1SShri Abhyankar 
8257a7aea1fSJed Brown   Input Parameters:
8265f2c45f1SShri Abhyankar + dm - the network object
8275f2c45f1SShri Abhyankar . name - the component name
8285f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
8295f2c45f1SShri Abhyankar 
8307a7aea1fSJed Brown    Output Parameters:
8315f2c45f1SShri Abhyankar .  key - an integer key that defines the component
8325f2c45f1SShri Abhyankar 
8335f2c45f1SShri Abhyankar    Notes
8345f2c45f1SShri Abhyankar    This routine should be called by all processors before calling DMNetworkLayoutSetup().
8355f2c45f1SShri Abhyankar 
83697bb938eSShri Abhyankar    Level: beginner
8375f2c45f1SShri Abhyankar 
8382bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkLayoutSetUp()
8395f2c45f1SShri Abhyankar @*/
840caf410d2SHong Zhang PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key)
8415f2c45f1SShri Abhyankar {
8425f2c45f1SShri Abhyankar   PetscErrorCode        ierr;
8435f2c45f1SShri Abhyankar   DM_Network            *network = (DM_Network*) dm->data;
8445f2c45f1SShri Abhyankar   DMNetworkComponent    *component=&network->component[network->ncomponent];
8455f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
8465f2c45f1SShri Abhyankar   PetscInt              i;
8475f2c45f1SShri Abhyankar 
8485f2c45f1SShri Abhyankar   PetscFunctionBegin;
8495f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
8505f2c45f1SShri Abhyankar     ierr = PetscStrcmp(component->name,name,&flg);CHKERRQ(ierr);
8515f2c45f1SShri Abhyankar     if (flg) {
8525f2c45f1SShri Abhyankar       *key = i;
8535f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
8545f2c45f1SShri Abhyankar     }
8556d64e262SShri Abhyankar   }
856a9b4a83eSHong Zhang   if (network->ncomponent == MAX_NETCOMPONENTS) {
857a9b4a83eSHong Zhang     SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components registered exceeds the max %D",MAX_NETCOMPONENTS);
8585f2c45f1SShri Abhyankar   }
8595f2c45f1SShri Abhyankar 
8605f2c45f1SShri Abhyankar   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
8615f2c45f1SShri Abhyankar   component->size = size/sizeof(DMNetworkComponentGenericDataType);
8625f2c45f1SShri Abhyankar   *key = network->ncomponent;
8635f2c45f1SShri Abhyankar   network->ncomponent++;
8645f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8655f2c45f1SShri Abhyankar }
8665f2c45f1SShri Abhyankar 
8675f2c45f1SShri Abhyankar /*@
8682bf73ac6SHong Zhang   DMNetworkGetVertexRange - Get the bounds [start, end) for the local vertices
8695f2c45f1SShri Abhyankar 
8705f2c45f1SShri Abhyankar   Not Collective
8715f2c45f1SShri Abhyankar 
8725f2c45f1SShri Abhyankar   Input Parameters:
8732bf73ac6SHong Zhang . dm - the DMNetwork object
8745f2c45f1SShri Abhyankar 
875fd292e60Sprj-   Output Parameters:
8762bf73ac6SHong Zhang + vStart - the first vertex point
8772bf73ac6SHong Zhang - vEnd - one beyond the last vertex point
8785f2c45f1SShri Abhyankar 
87997bb938eSShri Abhyankar   Level: beginner
8805f2c45f1SShri Abhyankar 
8812bf73ac6SHong Zhang .seealso: DMNetworkGetEdgeRange()
8825f2c45f1SShri Abhyankar @*/
8835f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
8845f2c45f1SShri Abhyankar {
8855f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*)dm->data;
8865f2c45f1SShri Abhyankar 
8875f2c45f1SShri Abhyankar   PetscFunctionBegin;
8885f2c45f1SShri Abhyankar   if (vStart) *vStart = network->vStart;
8895f2c45f1SShri Abhyankar   if (vEnd) *vEnd = network->vEnd;
8905f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8915f2c45f1SShri Abhyankar }
8925f2c45f1SShri Abhyankar 
8935f2c45f1SShri Abhyankar /*@
8942bf73ac6SHong Zhang   DMNetworkGetEdgeRange - Get the bounds [start, end) for the local edges
8955f2c45f1SShri Abhyankar 
8965f2c45f1SShri Abhyankar   Not Collective
8975f2c45f1SShri Abhyankar 
8985f2c45f1SShri Abhyankar   Input Parameters:
8992bf73ac6SHong Zhang . dm - the DMNetwork object
9005f2c45f1SShri Abhyankar 
901fd292e60Sprj-   Output Parameters:
9025f2c45f1SShri Abhyankar + eStart - The first edge point
9035f2c45f1SShri Abhyankar - eEnd - One beyond the last edge point
9045f2c45f1SShri Abhyankar 
90597bb938eSShri Abhyankar   Level: beginner
9065f2c45f1SShri Abhyankar 
9072bf73ac6SHong Zhang .seealso: DMNetworkGetVertexRange()
9085f2c45f1SShri Abhyankar @*/
9095f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
9105f2c45f1SShri Abhyankar {
9115f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*)dm->data;
9125f2c45f1SShri Abhyankar 
9135f2c45f1SShri Abhyankar   PetscFunctionBegin;
9145f2c45f1SShri Abhyankar   if (eStart) *eStart = network->eStart;
9155f2c45f1SShri Abhyankar   if (eEnd) *eEnd = network->eEnd;
9165f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9175f2c45f1SShri Abhyankar }
9185f2c45f1SShri Abhyankar 
9192bf73ac6SHong Zhang static PetscErrorCode DMNetworkGetIndex(DM dm,PetscInt p,PetscInt *index)
9202bf73ac6SHong Zhang {
9212bf73ac6SHong Zhang   PetscErrorCode    ierr;
9222bf73ac6SHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
9232bf73ac6SHong Zhang   PetscInt          offsetp;
9242bf73ac6SHong Zhang   DMNetworkComponentHeader header;
9252bf73ac6SHong Zhang 
9262bf73ac6SHong Zhang   PetscFunctionBegin;
9272bf73ac6SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
9282bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
9292bf73ac6SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
9302bf73ac6SHong Zhang   *index = header->index;
9312bf73ac6SHong Zhang   PetscFunctionReturn(0);
9322bf73ac6SHong Zhang }
9332bf73ac6SHong Zhang 
9347b6afd5bSHong Zhang /*@
9352bf73ac6SHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the global numbering for the edge on the network
9367b6afd5bSHong Zhang 
9377b6afd5bSHong Zhang   Not Collective
9387b6afd5bSHong Zhang 
9397b6afd5bSHong Zhang   Input Parameters:
9407b6afd5bSHong Zhang + dm - DMNetwork object
941e85e6aecSHong Zhang - p - edge point
9427b6afd5bSHong Zhang 
943fd292e60Sprj-   Output Parameters:
9442bf73ac6SHong Zhang . index - the global numbering for the edge
9457b6afd5bSHong Zhang 
9467b6afd5bSHong Zhang   Level: intermediate
9477b6afd5bSHong Zhang 
9482bf73ac6SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
9497b6afd5bSHong Zhang @*/
950e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
9517b6afd5bSHong Zhang {
9527b6afd5bSHong Zhang   PetscErrorCode ierr;
9537b6afd5bSHong Zhang 
9547b6afd5bSHong Zhang   PetscFunctionBegin;
9552bf73ac6SHong Zhang   ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr);
9567b6afd5bSHong Zhang   PetscFunctionReturn(0);
9577b6afd5bSHong Zhang }
9587b6afd5bSHong Zhang 
9595f2c45f1SShri Abhyankar /*@
9602bf73ac6SHong Zhang   DMNetworkGetGlobalVertexIndex - Get the global numbering for the vertex on the network
961e85e6aecSHong Zhang 
962e85e6aecSHong Zhang   Not Collective
963e85e6aecSHong Zhang 
964e85e6aecSHong Zhang   Input Parameters:
965e85e6aecSHong Zhang + dm - DMNetwork object
966e85e6aecSHong Zhang - p  - vertex point
967e85e6aecSHong Zhang 
968fd292e60Sprj-   Output Parameters:
9692bf73ac6SHong Zhang . index - the global numbering for the vertex
970e85e6aecSHong Zhang 
971e85e6aecSHong Zhang   Level: intermediate
972e85e6aecSHong Zhang 
9732bf73ac6SHong Zhang .seealso: DMNetworkGetGlobalEdgeIndex()
974e85e6aecSHong Zhang @*/
975e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
976e85e6aecSHong Zhang {
977e85e6aecSHong Zhang   PetscErrorCode ierr;
978e85e6aecSHong Zhang 
979e85e6aecSHong Zhang   PetscFunctionBegin;
9802bf73ac6SHong Zhang   ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr);
9819988b915SShri Abhyankar   PetscFunctionReturn(0);
9829988b915SShri Abhyankar }
9839988b915SShri Abhyankar 
9849988b915SShri Abhyankar /*@
9855f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
9865f2c45f1SShri Abhyankar 
9875f2c45f1SShri Abhyankar   Not Collective
9885f2c45f1SShri Abhyankar 
9895f2c45f1SShri Abhyankar   Input Parameters:
9902bf73ac6SHong Zhang + dm - the DMNetwork object
991a2b725a8SWilliam Gropp - p - vertex/edge point
9925f2c45f1SShri Abhyankar 
9935f2c45f1SShri Abhyankar   Output Parameters:
9945f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
9955f2c45f1SShri Abhyankar 
99697bb938eSShri Abhyankar   Level: beginner
9975f2c45f1SShri Abhyankar 
9982bf73ac6SHong Zhang .seealso: DMNetworkRegisterComponent(), DMNetworkAddComponent()
9995f2c45f1SShri Abhyankar @*/
10005f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
10015f2c45f1SShri Abhyankar {
10025f2c45f1SShri Abhyankar   PetscErrorCode ierr;
10035f2c45f1SShri Abhyankar   PetscInt       offset;
10045f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10055f2c45f1SShri Abhyankar 
10065f2c45f1SShri Abhyankar   PetscFunctionBegin;
10075f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
10085f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
10095f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10105f2c45f1SShri Abhyankar }
10115f2c45f1SShri Abhyankar 
10125f2c45f1SShri Abhyankar /*@
10132bf73ac6SHong Zhang   DMNetworkGetLocalVecOffset - Get the offset for accessing the variables associated with a component at the given vertex/edge from the local vector
10145f2c45f1SShri Abhyankar 
10155f2c45f1SShri Abhyankar   Not Collective
10165f2c45f1SShri Abhyankar 
10175f2c45f1SShri Abhyankar   Input Parameters:
10182bf73ac6SHong Zhang + dm - the DMNetwork object
10197d928bffSSatish Balay . p - the edge/vertex point
10202bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
10219988b915SShri Abhyankar 
10229988b915SShri Abhyankar   Output Parameters:
10232bf73ac6SHong Zhang . offset - the local offset
10249988b915SShri Abhyankar 
10259988b915SShri Abhyankar   Level: intermediate
10269988b915SShri Abhyankar 
10272bf73ac6SHong Zhang .seealso: DMGetLocalVector(), DMNetworkGetComponent(), DMNetworkGetGlobalVecOffset()
10289988b915SShri Abhyankar @*/
10292bf73ac6SHong Zhang PetscErrorCode DMNetworkGetLocalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offset)
10309988b915SShri Abhyankar {
10319988b915SShri Abhyankar   PetscErrorCode ierr;
10329988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10339988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
10349988b915SShri Abhyankar   DMNetworkComponentHeader header;
10359988b915SShri Abhyankar 
10369988b915SShri Abhyankar   PetscFunctionBegin;
10372bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->localSection,p,&offsetp);CHKERRQ(ierr);
10382bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
10392bf73ac6SHong Zhang     *offset = offsetp;
10402bf73ac6SHong Zhang     PetscFunctionReturn(0);
10412bf73ac6SHong Zhang   }
10422bf73ac6SHong Zhang 
10439988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
10449988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
10459988b915SShri Abhyankar   *offset = offsetp + header->offsetvarrel[compnum];
10469988b915SShri Abhyankar   PetscFunctionReturn(0);
10479988b915SShri Abhyankar }
10489988b915SShri Abhyankar 
10499988b915SShri Abhyankar /*@
10502bf73ac6SHong Zhang   DMNetworkGetGlobalVecOffset - Get the global offset for accessing the variables associated with a component for the given vertex/edge from the global vector
10519988b915SShri Abhyankar 
10529988b915SShri Abhyankar   Not Collective
10539988b915SShri Abhyankar 
10549988b915SShri Abhyankar   Input Parameters:
10552bf73ac6SHong Zhang + dm - the DMNetwork object
10567d928bffSSatish Balay . p - the edge/vertex point
10572bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
10589988b915SShri Abhyankar 
10599988b915SShri Abhyankar   Output Parameters:
10609988b915SShri Abhyankar . offsetg - the global offset
10619988b915SShri Abhyankar 
10629988b915SShri Abhyankar   Level: intermediate
10639988b915SShri Abhyankar 
10642bf73ac6SHong Zhang .seealso: DMNetworkGetLocalVecOffset(), DMGetGlobalVector(), DMNetworkGetComponent()
10659988b915SShri Abhyankar @*/
10662bf73ac6SHong Zhang PetscErrorCode DMNetworkGetGlobalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offsetg)
10679988b915SShri Abhyankar {
10689988b915SShri Abhyankar   PetscErrorCode ierr;
10699988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10709988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
10719988b915SShri Abhyankar   DMNetworkComponentHeader header;
10729988b915SShri Abhyankar 
10739988b915SShri Abhyankar   PetscFunctionBegin;
10742bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->globalSection,p,&offsetp);CHKERRQ(ierr);
10752bf73ac6SHong Zhang   if (offsetp < 0) offsetp = -(offsetp + 1); /* Convert to actual global offset for ghost vertex */
10762bf73ac6SHong Zhang 
10772bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
10782bf73ac6SHong Zhang     *offsetg = offsetp;
10792bf73ac6SHong Zhang     PetscFunctionReturn(0);
10802bf73ac6SHong Zhang   }
10819988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
10829988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
10839988b915SShri Abhyankar   *offsetg = offsetp + header->offsetvarrel[compnum];
10849988b915SShri Abhyankar   PetscFunctionReturn(0);
10859988b915SShri Abhyankar }
10869988b915SShri Abhyankar 
10879988b915SShri Abhyankar /*@
10882bf73ac6SHong Zhang   DMNetworkGetEdgeOffset - Get the offset for accessing the variables associated with the given edge from the local subvector
108924121865SAdrian Maldonado 
109024121865SAdrian Maldonado   Not Collective
109124121865SAdrian Maldonado 
109224121865SAdrian Maldonado   Input Parameters:
10932bf73ac6SHong Zhang + dm - the DMNetwork object
109424121865SAdrian Maldonado - p - the edge point
109524121865SAdrian Maldonado 
109624121865SAdrian Maldonado   Output Parameters:
109724121865SAdrian Maldonado . offset - the offset
109824121865SAdrian Maldonado 
109924121865SAdrian Maldonado   Level: intermediate
110024121865SAdrian Maldonado 
11012bf73ac6SHong Zhang .seealso: DMNetworkGetLocalVecOffset(), DMGetLocalVector()
110224121865SAdrian Maldonado @*/
110324121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
110424121865SAdrian Maldonado {
110524121865SAdrian Maldonado   PetscErrorCode ierr;
110624121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
110724121865SAdrian Maldonado 
110824121865SAdrian Maldonado   PetscFunctionBegin;
110924121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
111024121865SAdrian Maldonado   PetscFunctionReturn(0);
111124121865SAdrian Maldonado }
111224121865SAdrian Maldonado 
111324121865SAdrian Maldonado /*@
11142bf73ac6SHong Zhang   DMNetworkGetVertexOffset - Get the offset for accessing the variables associated with the given vertex from the local subvector
111524121865SAdrian Maldonado 
111624121865SAdrian Maldonado   Not Collective
111724121865SAdrian Maldonado 
111824121865SAdrian Maldonado   Input Parameters:
11192bf73ac6SHong Zhang + dm - the DMNetwork object
112024121865SAdrian Maldonado - p - the vertex point
112124121865SAdrian Maldonado 
112224121865SAdrian Maldonado   Output Parameters:
112324121865SAdrian Maldonado . offset - the offset
112424121865SAdrian Maldonado 
112524121865SAdrian Maldonado   Level: intermediate
112624121865SAdrian Maldonado 
11272bf73ac6SHong Zhang .seealso: DMNetworkGetEdgeOffset(), DMGetLocalVector()
112824121865SAdrian Maldonado @*/
112924121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
113024121865SAdrian Maldonado {
113124121865SAdrian Maldonado   PetscErrorCode ierr;
113224121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
113324121865SAdrian Maldonado 
113424121865SAdrian Maldonado   PetscFunctionBegin;
113524121865SAdrian Maldonado   p -= network->vStart;
113624121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
113724121865SAdrian Maldonado   PetscFunctionReturn(0);
113824121865SAdrian Maldonado }
11392bf73ac6SHong Zhang 
11405f2c45f1SShri Abhyankar /*@
11412bf73ac6SHong Zhang   DMNetworkAddComponent - Adds a network component and number of variables at the given point (vertex/edge)
11425f2c45f1SShri Abhyankar 
11435f2c45f1SShri Abhyankar   Not Collective
11445f2c45f1SShri Abhyankar 
11455f2c45f1SShri Abhyankar   Input Parameters:
11462bf73ac6SHong Zhang + dm - the DMNetworkObject
11475f2c45f1SShri Abhyankar . p - the vertex/edge point
11482bf73ac6SHong Zhang . componentkey - component key returned while registering the component; ignored if compvalue=NULL
11492bf73ac6SHong Zhang . compvalue - pointer to the data structure for the component, or NULL if not required.
11502bf73ac6SHong Zhang - nvar - number of variables for the component at the vertex/edge point
11515f2c45f1SShri Abhyankar 
115297bb938eSShri Abhyankar   Level: beginner
11535f2c45f1SShri Abhyankar 
11542bf73ac6SHong Zhang .seealso: DMNetworkGetComponent()
11555f2c45f1SShri Abhyankar @*/
11562bf73ac6SHong Zhang PetscErrorCode DMNetworkAddComponent(DM dm,PetscInt p,PetscInt componentkey,void* compvalue,PetscInt nvar)
11575f2c45f1SShri Abhyankar {
11585f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
11595f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
11602bf73ac6SHong Zhang   DMNetworkComponent       *component = &network->component[componentkey];
11612bf73ac6SHong Zhang   DMNetworkComponentHeader header = &network->header[p];
11622bf73ac6SHong Zhang   DMNetworkComponentValue  cvalue = &network->cvalue[p];
11632bf73ac6SHong Zhang   PetscBool                sharedv=PETSC_FALSE;
11642bf73ac6SHong Zhang   PetscInt                 compnum=header->ndata;
11655f2c45f1SShri Abhyankar 
11665f2c45f1SShri Abhyankar   PetscFunctionBegin;
11675f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
11682bf73ac6SHong Zhang   if (!compvalue) PetscFunctionReturn(0);
11692bf73ac6SHong Zhang 
11702bf73ac6SHong Zhang   ierr = DMNetworkIsSharedVertex(dm,p,&sharedv);CHKERRQ(ierr);
11712bf73ac6SHong Zhang   if (sharedv) {
11722bf73ac6SHong Zhang     PetscBool ghost;
11732bf73ac6SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
11742bf73ac6SHong Zhang     if (ghost) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adding a component at a leaf(ghost) shared vertex is not supported");
11752bf73ac6SHong Zhang   }
11762bf73ac6SHong Zhang 
1177a9b4a83eSHong Zhang   if (compnum == MAX_NETCOMPONENTS) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components at a point exceeds the max %D",MAX_NETCOMPONENTS);
11782bf73ac6SHong Zhang 
11792bf73ac6SHong Zhang   header->size[compnum] = component->size;
11802bf73ac6SHong Zhang   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
11812bf73ac6SHong Zhang   header->key[compnum] = componentkey;
11822bf73ac6SHong Zhang   if (compnum != 0) header->offset[compnum] = header->offset[compnum-1] + header->size[compnum-1];
11832bf73ac6SHong Zhang   cvalue->data[compnum] = (void*)compvalue;
11842bf73ac6SHong Zhang 
11852bf73ac6SHong Zhang   /* variables */
11862bf73ac6SHong Zhang   header->nvar[compnum] += nvar;
11872bf73ac6SHong Zhang   if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum-1] + header->nvar[compnum-1];
11882bf73ac6SHong Zhang 
11892bf73ac6SHong Zhang   header->ndata++;
11905f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
11915f2c45f1SShri Abhyankar }
11925f2c45f1SShri Abhyankar 
119327f51fceSHong Zhang /*@
11942bf73ac6SHong Zhang   DMNetworkGetComponent - Gets the component key, the component data, and the number of variables at a given network point
119527f51fceSHong Zhang 
119627f51fceSHong Zhang   Not Collective
119727f51fceSHong Zhang 
119827f51fceSHong Zhang   Input Parameters:
11992bf73ac6SHong Zhang + dm - the DMNetwork object
12002bf73ac6SHong Zhang . p - vertex/edge point
1201*99c90e12SSatish Balay - compnum - component number; use ALL_COMPONENTS if sum up all the components
120227f51fceSHong Zhang 
120327f51fceSHong Zhang   Output Parameters:
12042bf73ac6SHong Zhang + compkey - the key obtained when registering the component (use NULL if not required)
12052bf73ac6SHong Zhang . component - the component data (use NULL if not required)
12062bf73ac6SHong Zhang - nvar  - number of variables (use NULL if not required)
120727f51fceSHong Zhang 
120897bb938eSShri Abhyankar   Level: beginner
120927f51fceSHong Zhang 
12102bf73ac6SHong Zhang .seealso: DMNetworkAddComponent(), DMNetworkGetNumComponents()
121127f51fceSHong Zhang @*/
12122bf73ac6SHong Zhang PetscErrorCode DMNetworkGetComponent(DM dm,PetscInt p,PetscInt compnum,PetscInt *compkey,void **component,PetscInt *nvar)
121327f51fceSHong Zhang {
121427f51fceSHong Zhang   PetscErrorCode ierr;
121527f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
12162bf73ac6SHong Zhang   PetscInt       offset = 0;
12172bf73ac6SHong Zhang   DMNetworkComponentHeader header;
121827f51fceSHong Zhang 
121927f51fceSHong Zhang   PetscFunctionBegin;
12202bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
122127f51fceSHong Zhang     ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
122227f51fceSHong Zhang     PetscFunctionReturn(0);
122327f51fceSHong Zhang   }
122427f51fceSHong Zhang 
12252bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
12262bf73ac6SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);CHKERRQ(ierr);
12275f2c45f1SShri Abhyankar 
12282bf73ac6SHong Zhang   if (compnum >= 0) {
12292bf73ac6SHong Zhang     if (compkey) *compkey = header->key[compnum];
12302bf73ac6SHong Zhang     if (component) {
12312bf73ac6SHong Zhang       offset += network->dataheadersize+header->offset[compnum];
12322bf73ac6SHong Zhang       *component = network->componentdataarray+offset;
12332bf73ac6SHong Zhang     }
12342bf73ac6SHong Zhang   }
12355f2c45f1SShri Abhyankar 
12362bf73ac6SHong Zhang   if (nvar) *nvar = header->nvar[compnum];
12375f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
12385f2c45f1SShri Abhyankar }
12395f2c45f1SShri Abhyankar 
12402bf73ac6SHong Zhang /*
12412bf73ac6SHong Zhang  Sets up the array that holds the data for all components and its associated section.
12422bf73ac6SHong Zhang  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.
12432bf73ac6SHong Zhang */
12445f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
12455f2c45f1SShri Abhyankar {
12465f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
12475f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
1248e53b5ba3SHong Zhang   PetscInt                 arr_size,p,offset,offsetp,ncomp,i;
12492bf73ac6SHong Zhang   MPI_Comm                 comm;
12502bf73ac6SHong Zhang   PetscMPIInt              size,rank;
12515f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
12525f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
12535f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
12545f2c45f1SShri Abhyankar 
12555f2c45f1SShri Abhyankar   PetscFunctionBegin;
12562bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
12572bf73ac6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
12582bf73ac6SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
12592bf73ac6SHong Zhang #if 0
12602bf73ac6SHong Zhang   //------------- new
12612bf73ac6SHong Zhang   if (size > 1) { /* Sync nvar at shared vertices for all processes */
12622bf73ac6SHong Zhang     PetscSF        sf = network->plex->sf;
12632bf73ac6SHong Zhang     const PetscInt *degree;
12642bf73ac6SHong Zhang     PetscInt       i,nleaves_total,*indata,*outdata,nroots,nleaves,nsv,p,ncomp;
12652bf73ac6SHong Zhang     const PetscInt *svtx;
12662bf73ac6SHong Zhang     PetscBool      ghost;
12672bf73ac6SHong Zhang 
12682bf73ac6SHong Zhang     ierr = PetscSFGetGraph(sf,&nroots,&nleaves,NULL,NULL);CHKERRQ(ierr);
12692bf73ac6SHong Zhang     ierr = PetscSFComputeDegreeBegin(sf,&degree);CHKERRQ(ierr);
12702bf73ac6SHong Zhang     ierr = PetscSFComputeDegreeEnd(sf,&degree);CHKERRQ(ierr);
12712bf73ac6SHong Zhang     nleaves_total=0;
12722bf73ac6SHong Zhang     for (i=0; i<nroots; i++) nleaves_total += degree[i];
12732bf73ac6SHong Zhang     printf("[%d] nleaves_total %d\n",rank,nleaves_total);
12742bf73ac6SHong Zhang     MPI_Barrier(comm);
12752bf73ac6SHong Zhang 
12762bf73ac6SHong Zhang     ierr = PetscCalloc2(nleaves_total,&indata,nleaves,&outdata);CHKERRQ(ierr);
12772bf73ac6SHong Zhang 
12782bf73ac6SHong Zhang     /* Leaves copy user's ncomp to outdata */
12792bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nsv,&svtx);CHKERRQ(ierr);
12802bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
12812bf73ac6SHong Zhang       p = svtx[i];
12822bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
12832bf73ac6SHong Zhang       if (!ghost) continue;
12842bf73ac6SHong Zhang 
12852bf73ac6SHong Zhang       header = &network->header[p];
12862bf73ac6SHong Zhang       ncomp = header->ndata;
12872bf73ac6SHong Zhang       printf("[%d] leaf has ncomp %d\n",rank,ncomp);
12882bf73ac6SHong Zhang       outdata[p] = ncomp;
12892bf73ac6SHong Zhang     }
12902bf73ac6SHong Zhang 
12912bf73ac6SHong Zhang     /* Roots gather ncomp from leaves */
12922bf73ac6SHong Zhang     ierr = PetscSFGatherBegin(sf,MPIU_INT,outdata,indata);CHKERRQ(ierr);
12932bf73ac6SHong Zhang     ierr = PetscSFGatherEnd(sf,MPIU_INT,outdata,indata);CHKERRQ(ierr);
12942bf73ac6SHong Zhang     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Gathered data at multi-roots from leaves\n");CHKERRQ(ierr);
12952bf73ac6SHong Zhang     ierr = PetscIntView(nleaves_total,indata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
12962bf73ac6SHong Zhang 
12972bf73ac6SHong Zhang     ierr = PetscFree2(indata,outdata);CHKERRQ(ierr);
12982bf73ac6SHong Zhang   }
12992bf73ac6SHong Zhang   //----------------------
13002bf73ac6SHong Zhang #endif
13012bf73ac6SHong Zhang 
13025f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
13035f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
130475b160a0SShri Abhyankar   ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
13055f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
13065f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
13075f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
13085f2c45f1SShri Abhyankar     /* Copy header */
13095f2c45f1SShri Abhyankar     header = &network->header[p];
1310302440fdSBarry Smith     ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
13115f2c45f1SShri Abhyankar     /* Copy data */
13125f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
13135f2c45f1SShri Abhyankar     ncomp = header->ndata;
13142bf73ac6SHong Zhang 
13155f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
13165f2c45f1SShri Abhyankar       offset = offsetp + network->dataheadersize + header->offset[i];
1317302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
13185f2c45f1SShri Abhyankar     }
13195f2c45f1SShri Abhyankar   }
13205f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13215f2c45f1SShri Abhyankar }
13225f2c45f1SShri Abhyankar 
13235f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
13242bf73ac6SHong Zhang static PetscErrorCode DMNetworkVariablesSetUp(DM dm)
13255f2c45f1SShri Abhyankar {
13265f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13275f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
13282bf73ac6SHong Zhang   MPI_Comm       comm;
13292bf73ac6SHong Zhang   PetscMPIInt    size;
13305f2c45f1SShri Abhyankar 
13315f2c45f1SShri Abhyankar   PetscFunctionBegin;
13322bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
13332bf73ac6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
13342bf73ac6SHong Zhang 
13352bf73ac6SHong Zhang   if (size > 1) { /* Sync nvar at shared vertices for all processes */
13362bf73ac6SHong Zhang     PetscSF           sf = network->plex->sf;
13372bf73ac6SHong Zhang     PetscInt          *local_nvar, *remote_nvar,nroots,nleaves,p=-1,i,nsv;
13382bf73ac6SHong Zhang     const PetscInt    *svtx;
13392bf73ac6SHong Zhang     PetscBool         ghost;
13402bf73ac6SHong Zhang     /*
13412bf73ac6SHong Zhang      PetscMPIInt       rank;
13422bf73ac6SHong Zhang      const PetscInt    *ilocal;
13432bf73ac6SHong Zhang      const PetscSFNode *iremote;
13442bf73ac6SHong Zhang      ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
13452bf73ac6SHong Zhang      ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
13462bf73ac6SHong Zhang     */
13472bf73ac6SHong Zhang     ierr = PetscSFGetGraph(sf,&nroots,&nleaves,NULL,NULL);CHKERRQ(ierr);
13482bf73ac6SHong Zhang     ierr = PetscCalloc2(nroots,&local_nvar,nroots,&remote_nvar);CHKERRQ(ierr);
13492bf73ac6SHong Zhang 
13502bf73ac6SHong Zhang     /* Leaves copy user's nvar to local_nvar */
13512bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nsv,&svtx);CHKERRQ(ierr);
13522bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
13532bf73ac6SHong Zhang       p = svtx[i];
13542bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
13552bf73ac6SHong Zhang       if (!ghost) continue;
13562bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
13572bf73ac6SHong Zhang       /* printf("[%d] Before SFReduce: leaf local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
13582bf73ac6SHong Zhang     }
13592bf73ac6SHong Zhang 
13602bf73ac6SHong Zhang     /* Leaves add local_nvar to root remote_nvar */
13612bf73ac6SHong Zhang     ierr = PetscSFReduceBegin(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
13622bf73ac6SHong Zhang     ierr = PetscSFReduceEnd(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
13632bf73ac6SHong Zhang     /* printf("[%d] remote_nvar[%d] = %d\n",rank,p,remote_nvar[p]); */
13642bf73ac6SHong Zhang 
13652bf73ac6SHong Zhang     /* Update roots' local_nvar */
13662bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
13672bf73ac6SHong Zhang       p = svtx[i];
13682bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
13692bf73ac6SHong Zhang       if (ghost) continue;
13702bf73ac6SHong Zhang 
13712bf73ac6SHong Zhang       ierr = PetscSectionAddDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
13722bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
13732bf73ac6SHong Zhang       /* printf("[%d]  After SFReduce: root local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
13742bf73ac6SHong Zhang     }
13752bf73ac6SHong Zhang 
13762bf73ac6SHong Zhang     /* Roots Bcast nvar to leaves */
1377ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
1378ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
13792bf73ac6SHong Zhang 
13802bf73ac6SHong Zhang     /* Leaves reset receved/remote nvar to dm */
13812bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
13822bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
13832bf73ac6SHong Zhang       if (!ghost) continue;
13842bf73ac6SHong Zhang       p = svtx[i];
13852bf73ac6SHong Zhang       /* printf("[%d] leaf reset nvar %d at p= %d \n",rank,remote_nvar[p],p); */
13862bf73ac6SHong Zhang       /* DMNetworkSetNumVariables(dm,p,remote_nvar[p]) */
13872bf73ac6SHong Zhang       ierr = PetscSectionSetDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
13882bf73ac6SHong Zhang     }
13892bf73ac6SHong Zhang 
13902bf73ac6SHong Zhang     ierr = PetscFree2(local_nvar,remote_nvar);CHKERRQ(ierr);
13912bf73ac6SHong Zhang   }
13922bf73ac6SHong Zhang 
13935f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
13945f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13955f2c45f1SShri Abhyankar }
13965f2c45f1SShri Abhyankar 
139724121865SAdrian Maldonado /* Get a subsection from a range of points */
13989dddd249SSatish Balay static PetscErrorCode DMNetworkGetSubSection_private(PetscSection main,PetscInt pstart,PetscInt pend,PetscSection *subsection)
139924121865SAdrian Maldonado {
140024121865SAdrian Maldonado   PetscErrorCode ierr;
140124121865SAdrian Maldonado   PetscInt       i, nvar;
140224121865SAdrian Maldonado 
140324121865SAdrian Maldonado   PetscFunctionBegin;
14049dddd249SSatish Balay   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)main), subsection);CHKERRQ(ierr);
140524121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
140624121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
14079dddd249SSatish Balay     ierr = PetscSectionGetDof(main,i,&nvar);CHKERRQ(ierr);
140824121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
140924121865SAdrian Maldonado   }
141024121865SAdrian Maldonado 
141124121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
141224121865SAdrian Maldonado   PetscFunctionReturn(0);
141324121865SAdrian Maldonado }
141424121865SAdrian Maldonado 
141524121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
14162bf73ac6SHong Zhang static PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
141724121865SAdrian Maldonado {
141824121865SAdrian Maldonado   PetscErrorCode ierr;
141924121865SAdrian Maldonado   PetscInt       i, *subpoints;
142024121865SAdrian Maldonado 
142124121865SAdrian Maldonado   PetscFunctionBegin;
142224121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
142324121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
142424121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
142524121865SAdrian Maldonado     subpoints[i - pstart] = i;
142624121865SAdrian Maldonado   }
1427459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
142824121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
142924121865SAdrian Maldonado   PetscFunctionReturn(0);
143024121865SAdrian Maldonado }
143124121865SAdrian Maldonado 
143224121865SAdrian Maldonado /*@
14332bf73ac6SHong Zhang   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute
143424121865SAdrian Maldonado 
14352bf73ac6SHong Zhang   Collective on dm
143624121865SAdrian Maldonado 
143724121865SAdrian Maldonado   Input Parameters:
14382bf73ac6SHong Zhang . dm - the DMNetworkObject
143924121865SAdrian Maldonado 
144024121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
144124121865SAdrian Maldonado 
144224121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
144324121865SAdrian Maldonado 
1444caf410d2SHong Zhang   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]).
144524121865SAdrian Maldonado 
144624121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
144724121865SAdrian Maldonado 
144824121865SAdrian Maldonado   Level: intermediate
144924121865SAdrian Maldonado 
145024121865SAdrian Maldonado @*/
145124121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
145224121865SAdrian Maldonado {
145324121865SAdrian Maldonado   PetscErrorCode ierr;
145424121865SAdrian Maldonado   MPI_Comm       comm;
14559852e123SBarry Smith   PetscMPIInt    rank, size;
145624121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
145724121865SAdrian Maldonado 
1458eab1376dSHong Zhang   PetscFunctionBegin;
145924121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1460ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1461ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
146224121865SAdrian Maldonado 
146324121865SAdrian Maldonado   /* Create maps for vertices and edges */
146424121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
146524121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
146624121865SAdrian Maldonado 
146724121865SAdrian Maldonado   /* Create local sub-sections */
146824121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
146924121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
147024121865SAdrian Maldonado 
14719852e123SBarry Smith   if (size > 1) {
147224121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
147322bbedd7SHong Zhang 
147424121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
147524121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
147624121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
147724121865SAdrian Maldonado   } else {
147824121865SAdrian Maldonado     /* create structures for vertex */
147924121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
148024121865SAdrian Maldonado     /* create structures for edge */
148124121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
148224121865SAdrian Maldonado   }
148324121865SAdrian Maldonado 
148424121865SAdrian Maldonado   /* Add viewers */
148524121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
148624121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
148724121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
148824121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
148924121865SAdrian Maldonado   PetscFunctionReturn(0);
149024121865SAdrian Maldonado }
14917b6afd5bSHong Zhang 
14925f2c45f1SShri Abhyankar /*@
14932bf73ac6SHong Zhang   DMNetworkDistribute - Distributes the network and moves associated component data
14945f2c45f1SShri Abhyankar 
14955f2c45f1SShri Abhyankar   Collective
14965f2c45f1SShri Abhyankar 
14975f2c45f1SShri Abhyankar   Input Parameter:
1498d3464fd4SAdrian Maldonado + DM - the DMNetwork object
14992bf73ac6SHong Zhang - overlap - the overlap of partitions, 0 is the default
15005f2c45f1SShri Abhyankar 
15015f2c45f1SShri Abhyankar   Notes:
15028b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
15035f2c45f1SShri Abhyankar 
15045f2c45f1SShri Abhyankar   Level: intermediate
15055f2c45f1SShri Abhyankar 
15062bf73ac6SHong Zhang .seealso: DMNetworkCreate()
15075f2c45f1SShri Abhyankar @*/
1508d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
15095f2c45f1SShri Abhyankar {
1510d3464fd4SAdrian Maldonado   MPI_Comm       comm;
15115f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1512d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1513d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1514d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1515caf410d2SHong Zhang   PetscSF        pointsf=NULL;
15165f2c45f1SShri Abhyankar   DM             newDM;
15172bf73ac6SHong Zhang   PetscInt       j,e,v,offset,*subnetvtx,nsubnet,gidx,svtx_idx,nv;
15182bf73ac6SHong Zhang   PetscInt       to_net,from_net,*svto;
151951ac5effSHong Zhang   PetscPartitioner         part;
1520b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
15215f2c45f1SShri Abhyankar 
15225f2c45f1SShri Abhyankar   PetscFunctionBegin;
1523d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1524ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1525d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1526d3464fd4SAdrian Maldonado 
15272bf73ac6SHong Zhang   /* 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. */
1528d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
15295f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
15305f2c45f1SShri Abhyankar   newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
153151ac5effSHong Zhang 
153251ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
153351ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
153451ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
153551ac5effSHong Zhang 
15362bf73ac6SHong Zhang   /* Distribute plex dm */
153780cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
153851ac5effSHong Zhang 
15395f2c45f1SShri Abhyankar   /* Distribute dof section */
15402bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DofSection);CHKERRQ(ierr);
15415f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
154251ac5effSHong Zhang 
15435f2c45f1SShri Abhyankar   /* Distribute data and associated section */
15442bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DataSection);CHKERRQ(ierr);
154531da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
154624121865SAdrian Maldonado 
15475f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
15485f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
15495f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
15505f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
15516fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
15526fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
15535f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
15542bf73ac6SHong Zhang   newDMnetwork->svtable   = oldDMnetwork->svtable;
15552bf73ac6SHong Zhang   oldDMnetwork->svtable   = NULL;
155624121865SAdrian Maldonado 
15571bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
155892fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1559e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
15605f2c45f1SShri Abhyankar 
1561b9c6e19dSShri Abhyankar   /* Set up subnetwork info in the newDM */
15622bf73ac6SHong Zhang   newDMnetwork->Nsubnet = oldDMnetwork->Nsubnet;
15632bf73ac6SHong Zhang   newDMnetwork->Nsvtx   = oldDMnetwork->Nsvtx;
15642bf73ac6SHong Zhang   oldDMnetwork->Nsvtx   = 0;
15652bf73ac6SHong Zhang   newDMnetwork->svtx    = oldDMnetwork->svtx; /* global vertices! */
15662bf73ac6SHong Zhang   oldDMnetwork->svtx    = NULL;
15672bf73ac6SHong Zhang   ierr = PetscCalloc1(newDMnetwork->Nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
15682bf73ac6SHong Zhang 
15692bf73ac6SHong Zhang   /* Copy over the global number of vertices and edges in each subnetwork.
15702bf73ac6SHong Zhang      Note: these are calculated in DMNetworkLayoutSetUp()
1571b9c6e19dSShri Abhyankar   */
15722bf73ac6SHong Zhang   nsubnet = newDMnetwork->Nsubnet;
15732bf73ac6SHong Zhang   for (j = 0; j < nsubnet; j++) {
1574b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1575b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1576b9c6e19dSShri Abhyankar   }
1577b9c6e19dSShri Abhyankar 
15782bf73ac6SHong Zhang   /* Get local nedges and nvtx for subnetworks */
1579b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1580b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1581b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1582b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1583b9c6e19dSShri Abhyankar   }
1584b9c6e19dSShri Abhyankar 
1585b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1586b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1587b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
15882bf73ac6SHong Zhang 
15892bf73ac6SHong Zhang     /* shared vertices: use gidx = header->index to check if v is a shared vertex */
15902bf73ac6SHong Zhang     gidx = header->index;
15912bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
15922bf73ac6SHong Zhang     svtx_idx--;
15932bf73ac6SHong Zhang 
15942bf73ac6SHong Zhang     if (svtx_idx < 0) { /* not a shared vertex */
1595b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].nvtx++;
15962bf73ac6SHong Zhang     } else { /* a shared vertex belongs to more than one subnetworks, it is being counted by multiple subnets */
15972bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
15982bf73ac6SHong Zhang       newDMnetwork->subnet[from_net].nvtx++;
15992bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
16002bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
16012bf73ac6SHong Zhang         to_net = svto[0];
16022bf73ac6SHong Zhang         newDMnetwork->subnet[to_net].nvtx++;
16032bf73ac6SHong Zhang       }
16042bf73ac6SHong Zhang     }
1605b9c6e19dSShri Abhyankar   }
1606b9c6e19dSShri Abhyankar 
16072bf73ac6SHong Zhang   /* Get total local nvtx for subnetworks */
16082bf73ac6SHong Zhang   nv = 0;
16092bf73ac6SHong Zhang   for (j=0; j<nsubnet; j++) nv += newDMnetwork->subnet[j].nvtx;
16102bf73ac6SHong Zhang   nv += newDMnetwork->Nsvtx;
1611caf410d2SHong Zhang 
16122bf73ac6SHong Zhang   /* Now create the vertices and edge arrays for the subnetworks */
16132bf73ac6SHong Zhang   ierr = PetscCalloc1(nv,&subnetvtx);CHKERRQ(ierr);
16142bf73ac6SHong Zhang   newDMnetwork->subnetvtx = subnetvtx;
16152bf73ac6SHong Zhang 
16162bf73ac6SHong Zhang   for (j=0; j<nsubnet; j++) {
1617b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr);
1618caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1619caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1620caf410d2SHong Zhang 
16212bf73ac6SHong Zhang     /* 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. */
1622b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1623b9c6e19dSShri Abhyankar   }
16242bf73ac6SHong Zhang   newDMnetwork->svertices = subnetvtx;
1625b9c6e19dSShri Abhyankar 
16262bf73ac6SHong Zhang   /* Set the edges and vertices in each subnetwork */
1627b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1628b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1629b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1630b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1631b9c6e19dSShri Abhyankar   }
1632b9c6e19dSShri Abhyankar 
16332bf73ac6SHong Zhang   nv = 0;
1634b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1635b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1636b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
16372bf73ac6SHong Zhang 
16382bf73ac6SHong Zhang     /* coupling vertices: use gidx = header->index to check if v is a coupling vertex */
16392bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,header->index+1,&svtx_idx);CHKERRQ(ierr);
16402bf73ac6SHong Zhang     svtx_idx--;
16412bf73ac6SHong Zhang     if (svtx_idx < 0) {
1642b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
16432bf73ac6SHong Zhang     } else { /* a shared vertex */
16442bf73ac6SHong Zhang       newDMnetwork->svertices[nv++] = v;
16452bf73ac6SHong Zhang 
16462bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
16472bf73ac6SHong Zhang       newDMnetwork->subnet[from_net].vertices[newDMnetwork->subnet[from_net].nvtx++] = v;
16482bf73ac6SHong Zhang 
16492bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
16502bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
16512bf73ac6SHong Zhang         to_net = svto[0];
16522bf73ac6SHong Zhang         newDMnetwork->subnet[to_net].vertices[newDMnetwork->subnet[to_net].nvtx++] = v;
1653b9c6e19dSShri Abhyankar       }
16542bf73ac6SHong Zhang     }
16552bf73ac6SHong Zhang   }
16562bf73ac6SHong Zhang   newDMnetwork->nsvtx = nv;   /* num of local shared vertices */
1657b9c6e19dSShri Abhyankar 
1658caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
165922bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1660caf410d2SHong Zhang 
16612bf73ac6SHong Zhang   /* Free spaces */
166224121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
1663d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
16642bf73ac6SHong Zhang 
1665d3464fd4SAdrian Maldonado   *dm  = newDM;
16665f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
16675f2c45f1SShri Abhyankar }
16685f2c45f1SShri Abhyankar 
166924121865SAdrian Maldonado /*@C
16702bf73ac6SHong Zhang   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering
16712bf73ac6SHong Zhang 
16722bf73ac6SHong Zhang  Collective
167324121865SAdrian Maldonado 
167424121865SAdrian Maldonado   Input Parameters:
16759dddd249SSatish Balay + mainSF - the original SF structure
167624121865SAdrian Maldonado - map - a ISLocalToGlobal mapping that contains the subset of points
167724121865SAdrian Maldonado 
167824121865SAdrian Maldonado   Output Parameters:
16799dddd249SSatish Balay . subSF - a subset of the mainSF for the desired subset.
1680ee300463SSatish Balay 
1681ee300463SSatish Balay   Level: intermediate
16827d928bffSSatish Balay @*/
16839dddd249SSatish Balay PetscErrorCode PetscSFGetSubSF(PetscSF mainsf,ISLocalToGlobalMapping map,PetscSF *subSF)
16842bf73ac6SHong Zhang {
168524121865SAdrian Maldonado   PetscErrorCode        ierr;
168624121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
168724121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
168824121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
168924121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
169024121865SAdrian Maldonado   const PetscInt        *ilocal;
169124121865SAdrian Maldonado   const PetscSFNode     *iremote;
169224121865SAdrian Maldonado 
169324121865SAdrian Maldonado   PetscFunctionBegin;
16949dddd249SSatish Balay   ierr = PetscSFGetGraph(mainsf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
169524121865SAdrian Maldonado 
169624121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
169724121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
169824121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
169924121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
170024121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
170124121865SAdrian Maldonado   }
170224121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
170324121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
170424121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
170524121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
1706ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
1707ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
170824121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
17094b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
17104b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
171124121865SAdrian Maldonado   nleaves_sub = 0;
171224121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
171324121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
171424121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
17154b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
171624121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
171724121865SAdrian Maldonado       nleaves_sub += 1;
171824121865SAdrian Maldonado     }
171924121865SAdrian Maldonado   }
172024121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
172124121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
172224121865SAdrian Maldonado 
172324121865SAdrian Maldonado   /* Create new subSF */
172424121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
172524121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
17264b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
172724121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
17284b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
172924121865SAdrian Maldonado   PetscFunctionReturn(0);
173024121865SAdrian Maldonado }
173124121865SAdrian Maldonado 
17325f2c45f1SShri Abhyankar /*@C
17335f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
17345f2c45f1SShri Abhyankar 
17355f2c45f1SShri Abhyankar   Not Collective
17365f2c45f1SShri Abhyankar 
17375f2c45f1SShri Abhyankar   Input Parameters:
17382bf73ac6SHong Zhang + dm - the DMNetwork object
17395f2c45f1SShri Abhyankar - p  - the vertex point
17405f2c45f1SShri Abhyankar 
1741fd292e60Sprj-   Output Parameters:
17425f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
17432bf73ac6SHong Zhang - edges  - list of edge points
17445f2c45f1SShri Abhyankar 
174597bb938eSShri Abhyankar   Level: beginner
17465f2c45f1SShri Abhyankar 
17475f2c45f1SShri Abhyankar   Fortran Notes:
17485f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
17495f2c45f1SShri Abhyankar   include petsc.h90 in your code.
17505f2c45f1SShri Abhyankar 
17512bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetConnectedVertices()
17525f2c45f1SShri Abhyankar @*/
17535f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
17545f2c45f1SShri Abhyankar {
17555f2c45f1SShri Abhyankar   PetscErrorCode ierr;
17565f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
17575f2c45f1SShri Abhyankar 
17585f2c45f1SShri Abhyankar   PetscFunctionBegin;
17595f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
1760a9b4a83eSHong Zhang   if (edges) {ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);}
17615f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
17625f2c45f1SShri Abhyankar }
17635f2c45f1SShri Abhyankar 
17645f2c45f1SShri Abhyankar /*@C
1765d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
17665f2c45f1SShri Abhyankar 
17675f2c45f1SShri Abhyankar   Not Collective
17685f2c45f1SShri Abhyankar 
17695f2c45f1SShri Abhyankar   Input Parameters:
17702bf73ac6SHong Zhang + dm - the DMNetwork object
17715f2c45f1SShri Abhyankar - p - the edge point
17725f2c45f1SShri Abhyankar 
1773fd292e60Sprj-   Output Parameters:
17745f2c45f1SShri Abhyankar . vertices - vertices connected to this edge
17755f2c45f1SShri Abhyankar 
177697bb938eSShri Abhyankar   Level: beginner
17775f2c45f1SShri Abhyankar 
17785f2c45f1SShri Abhyankar   Fortran Notes:
17795f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
17805f2c45f1SShri Abhyankar   include petsc.h90 in your code.
17815f2c45f1SShri Abhyankar 
17822bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetSupportingEdges()
17835f2c45f1SShri Abhyankar @*/
1784d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
17855f2c45f1SShri Abhyankar {
17865f2c45f1SShri Abhyankar   PetscErrorCode ierr;
17875f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
17885f2c45f1SShri Abhyankar 
17895f2c45f1SShri Abhyankar   PetscFunctionBegin;
17905f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
17915f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
17925f2c45f1SShri Abhyankar }
17935f2c45f1SShri Abhyankar 
17945f2c45f1SShri Abhyankar /*@
17952bf73ac6SHong Zhang   DMNetworkIsSharedVertex - Returns TRUE if the vertex is shared by subnetworks
17962bf73ac6SHong Zhang 
17972bf73ac6SHong Zhang   Not Collective
17982bf73ac6SHong Zhang 
17992bf73ac6SHong Zhang   Input Parameters:
18002bf73ac6SHong Zhang + dm - the DMNetwork object
18012bf73ac6SHong Zhang - p - the vertex point
18022bf73ac6SHong Zhang 
18032bf73ac6SHong Zhang   Output Parameter:
18042bf73ac6SHong Zhang . flag - TRUE if the vertex is shared by subnetworks
18052bf73ac6SHong Zhang 
18062bf73ac6SHong Zhang   Level: beginner
18072bf73ac6SHong Zhang 
18082bf73ac6SHong Zhang .seealso: DMNetworkAddSharedVertices(), DMNetworkIsGhostVertex()
18092bf73ac6SHong Zhang @*/
18102bf73ac6SHong Zhang PetscErrorCode DMNetworkIsSharedVertex(DM dm,PetscInt p,PetscBool *flag)
18112bf73ac6SHong Zhang {
18122bf73ac6SHong Zhang   PetscErrorCode ierr;
18132bf73ac6SHong Zhang   PetscInt       i;
18142bf73ac6SHong Zhang 
18152bf73ac6SHong Zhang   PetscFunctionBegin;
18162bf73ac6SHong Zhang   *flag = PETSC_FALSE;
18172bf73ac6SHong Zhang 
18182bf73ac6SHong Zhang   if (dm->setupcalled) { /* DMNetworkGetGlobalVertexIndex() requires DMSetUp() be called */
18192bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
18202bf73ac6SHong Zhang     PetscInt       gidx;
18212bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVertexIndex(dm,p,&gidx);CHKERRQ(ierr);
18222bf73ac6SHong Zhang     ierr = PetscTableFind(network->svtable,gidx+1,&i);CHKERRQ(ierr);
18232bf73ac6SHong Zhang     if (i) *flag = PETSC_TRUE;
18242bf73ac6SHong Zhang   } else { /* would be removed? */
18252bf73ac6SHong Zhang     PetscInt       nv;
18262bf73ac6SHong Zhang     const PetscInt *vtx;
18272bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nv,&vtx);CHKERRQ(ierr);
18282bf73ac6SHong Zhang     for (i=0; i<nv; i++) {
18292bf73ac6SHong Zhang       if (p == vtx[i]) {
18302bf73ac6SHong Zhang         *flag = PETSC_TRUE;
18312bf73ac6SHong Zhang         break;
18322bf73ac6SHong Zhang       }
18332bf73ac6SHong Zhang     }
18342bf73ac6SHong Zhang   }
18352bf73ac6SHong Zhang   PetscFunctionReturn(0);
18362bf73ac6SHong Zhang }
18372bf73ac6SHong Zhang 
18382bf73ac6SHong Zhang /*@
18395f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
18405f2c45f1SShri Abhyankar 
18415f2c45f1SShri Abhyankar   Not Collective
18425f2c45f1SShri Abhyankar 
18435f2c45f1SShri Abhyankar   Input Parameters:
18442bf73ac6SHong Zhang + dm - the DMNetwork object
1845a2b725a8SWilliam Gropp - p - the vertex point
18465f2c45f1SShri Abhyankar 
18475f2c45f1SShri Abhyankar   Output Parameter:
18485f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
18495f2c45f1SShri Abhyankar 
185097bb938eSShri Abhyankar   Level: beginner
18515f2c45f1SShri Abhyankar 
18522bf73ac6SHong Zhang .seealso: DMNetworkGetConnectedVertices(), DMNetworkGetVertexRange(), DMNetworkIsSharedVertex()
18535f2c45f1SShri Abhyankar @*/
18545f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
18555f2c45f1SShri Abhyankar {
18565f2c45f1SShri Abhyankar   PetscErrorCode ierr;
18575f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
18585f2c45f1SShri Abhyankar   PetscInt       offsetg;
18595f2c45f1SShri Abhyankar   PetscSection   sectiong;
18605f2c45f1SShri Abhyankar 
18615f2c45f1SShri Abhyankar   PetscFunctionBegin;
18625f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
1863e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
18645f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
18655f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
18665f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18675f2c45f1SShri Abhyankar }
18685f2c45f1SShri Abhyankar 
18695f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
18705f2c45f1SShri Abhyankar {
18715f2c45f1SShri Abhyankar   PetscErrorCode ierr;
18725f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
18735f2c45f1SShri Abhyankar 
18745f2c45f1SShri Abhyankar   PetscFunctionBegin;
18755f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
18765f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
18775f2c45f1SShri Abhyankar 
187892fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
1879e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
18809e1d080bSHong Zhang 
18819e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
18829e1d080bSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr);
18835f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18845f2c45f1SShri Abhyankar }
18855f2c45f1SShri Abhyankar 
18861ad426b7SHong Zhang /*@
188717df6e9eSHong Zhang   DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
18881ad426b7SHong Zhang       -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
18891ad426b7SHong Zhang 
18901ad426b7SHong Zhang   Collective
18911ad426b7SHong Zhang 
18921ad426b7SHong Zhang   Input Parameters:
18932bf73ac6SHong Zhang + dm - the DMNetwork object
189483b2e829SHong Zhang . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
189583b2e829SHong Zhang - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
18961ad426b7SHong Zhang 
18971ad426b7SHong Zhang  Level: intermediate
18981ad426b7SHong Zhang 
18991ad426b7SHong Zhang @*/
190083b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
19011ad426b7SHong Zhang {
19021ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
19038675203cSHong Zhang   PetscErrorCode ierr;
190466b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
19051ad426b7SHong Zhang 
19061ad426b7SHong Zhang   PetscFunctionBegin;
190783b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
190883b2e829SHong Zhang   network->userVertexJacobian = vflg;
19098675203cSHong Zhang 
19108675203cSHong Zhang   if (eflg && !network->Je) {
19118675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
19128675203cSHong Zhang   }
19138675203cSHong Zhang 
191466b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
19158675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
191666b4e0ffSHong Zhang     PetscInt       nedges_total;
19178675203cSHong Zhang     const PetscInt *edges;
19188675203cSHong Zhang 
19198675203cSHong Zhang     /* count nvertex_total */
19208675203cSHong Zhang     nedges_total = 0;
19218675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
19228675203cSHong Zhang 
19238675203cSHong Zhang     vptr[0] = 0;
19248675203cSHong Zhang     for (i=0; i<nVertices; i++) {
19258675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
19268675203cSHong Zhang       nedges_total += nedges;
19278675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
19288675203cSHong Zhang     }
19298675203cSHong Zhang 
19308675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
19318675203cSHong Zhang     network->Jvptr = vptr;
19328675203cSHong Zhang   }
19331ad426b7SHong Zhang   PetscFunctionReturn(0);
19341ad426b7SHong Zhang }
19351ad426b7SHong Zhang 
19361ad426b7SHong Zhang /*@
193783b2e829SHong Zhang   DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
193883b2e829SHong Zhang 
193983b2e829SHong Zhang   Not Collective
194083b2e829SHong Zhang 
194183b2e829SHong Zhang   Input Parameters:
19422bf73ac6SHong Zhang + dm - the DMNetwork object
194383b2e829SHong Zhang . p - the edge point
19443e97b6e8SHong Zhang - J - array (size = 3) of Jacobian submatrices for this edge point:
19453e97b6e8SHong Zhang         J[0]: this edge
1946d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
194783b2e829SHong Zhang 
194897bb938eSShri Abhyankar   Level: advanced
194983b2e829SHong Zhang 
19502bf73ac6SHong Zhang .seealso: DMNetworkVertexSetMatrix()
195183b2e829SHong Zhang @*/
195283b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
195383b2e829SHong Zhang {
195483b2e829SHong Zhang   DM_Network *network=(DM_Network*)dm->data;
195583b2e829SHong Zhang 
195683b2e829SHong Zhang   PetscFunctionBegin;
19578675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
19588675203cSHong Zhang 
19598675203cSHong Zhang   if (J) {
1960883e35e8SHong Zhang     network->Je[3*p]   = J[0];
1961883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
1962883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
19638675203cSHong Zhang   }
196483b2e829SHong Zhang   PetscFunctionReturn(0);
196583b2e829SHong Zhang }
196683b2e829SHong Zhang 
196783b2e829SHong Zhang /*@
196876ddfea5SHong Zhang   DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
19691ad426b7SHong Zhang 
19701ad426b7SHong Zhang   Not Collective
19711ad426b7SHong Zhang 
19721ad426b7SHong Zhang   Input Parameters:
19731ad426b7SHong Zhang + dm - The DMNetwork object
19741ad426b7SHong Zhang . p - the vertex point
19753e97b6e8SHong Zhang - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
19763e97b6e8SHong Zhang         J[0]:       this vertex
19773e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
19783e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
19791ad426b7SHong Zhang 
198097bb938eSShri Abhyankar   Level: advanced
19811ad426b7SHong Zhang 
19822bf73ac6SHong Zhang .seealso: DMNetworkEdgeSetMatrix()
19831ad426b7SHong Zhang @*/
1984883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
19855f2c45f1SShri Abhyankar {
19865f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19875f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
19888675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
1989883e35e8SHong Zhang   const PetscInt *edges;
19905f2c45f1SShri Abhyankar 
19915f2c45f1SShri Abhyankar   PetscFunctionBegin;
19928675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1993883e35e8SHong Zhang 
19948675203cSHong Zhang   if (J) {
1995883e35e8SHong Zhang     vptr = network->Jvptr;
19963e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
19973e97b6e8SHong Zhang 
19983e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
1999883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
2000883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
20018675203cSHong Zhang   }
2002883e35e8SHong Zhang   PetscFunctionReturn(0);
2003883e35e8SHong Zhang }
2004883e35e8SHong Zhang 
2005e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
20065cf7da58SHong Zhang {
20075cf7da58SHong Zhang   PetscErrorCode ierr;
20085cf7da58SHong Zhang   PetscInt       j;
20095cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
20105cf7da58SHong Zhang 
20115cf7da58SHong Zhang   PetscFunctionBegin;
20125cf7da58SHong Zhang   if (!ghost) {
20135cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
20145cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
20155cf7da58SHong Zhang     }
20165cf7da58SHong Zhang   } else {
20175cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
20185cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
20195cf7da58SHong Zhang     }
20205cf7da58SHong Zhang   }
20215cf7da58SHong Zhang   PetscFunctionReturn(0);
20225cf7da58SHong Zhang }
20235cf7da58SHong Zhang 
2024e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
20255cf7da58SHong Zhang {
20265cf7da58SHong Zhang   PetscErrorCode ierr;
20275cf7da58SHong Zhang   PetscInt       j,ncols_u;
20285cf7da58SHong Zhang   PetscScalar    val;
20295cf7da58SHong Zhang 
20305cf7da58SHong Zhang   PetscFunctionBegin;
20315cf7da58SHong Zhang   if (!ghost) {
20325cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
20335cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
20345cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
20355cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
20365cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
20375cf7da58SHong Zhang     }
20385cf7da58SHong Zhang   } else {
20395cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
20405cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
20415cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
20425cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
20435cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
20445cf7da58SHong Zhang     }
20455cf7da58SHong Zhang   }
20465cf7da58SHong Zhang   PetscFunctionReturn(0);
20475cf7da58SHong Zhang }
20485cf7da58SHong Zhang 
2049e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
20505cf7da58SHong Zhang {
20515cf7da58SHong Zhang   PetscErrorCode ierr;
20525cf7da58SHong Zhang 
20535cf7da58SHong Zhang   PetscFunctionBegin;
20545cf7da58SHong Zhang   if (Ju) {
20555cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
20565cf7da58SHong Zhang   } else {
20575cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
20585cf7da58SHong Zhang   }
20595cf7da58SHong Zhang   PetscFunctionReturn(0);
20605cf7da58SHong Zhang }
20615cf7da58SHong Zhang 
2062e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2063883e35e8SHong Zhang {
2064883e35e8SHong Zhang   PetscErrorCode ierr;
2065883e35e8SHong Zhang   PetscInt       j,*cols;
2066883e35e8SHong Zhang   PetscScalar    *zeros;
2067883e35e8SHong Zhang 
2068883e35e8SHong Zhang   PetscFunctionBegin;
2069883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
2070883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
2071883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
2072883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
20731ad426b7SHong Zhang   PetscFunctionReturn(0);
20741ad426b7SHong Zhang }
2075a4e85ca8SHong Zhang 
2076e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
20773e97b6e8SHong Zhang {
20783e97b6e8SHong Zhang   PetscErrorCode ierr;
20793e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
20803e97b6e8SHong Zhang   const PetscInt *cols;
20813e97b6e8SHong Zhang   PetscScalar    zero=0.0;
20823e97b6e8SHong Zhang 
20833e97b6e8SHong Zhang   PetscFunctionBegin;
20843e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
20853e97b6e8SHong Zhang   if (nrows != M || ncols != N) SETERRQ4(PetscObjectComm((PetscObject)Ju),PETSC_ERR_USER,"%D by %D must equal %D by %D",nrows,ncols,M,N);
20863e97b6e8SHong Zhang 
20873e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
20883e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
20893e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
20903e97b6e8SHong Zhang       col = cols[j] + cstart;
20913e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
20923e97b6e8SHong Zhang     }
20933e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
20943e97b6e8SHong Zhang   }
20953e97b6e8SHong Zhang   PetscFunctionReturn(0);
20963e97b6e8SHong Zhang }
20971ad426b7SHong Zhang 
2098e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2099a4e85ca8SHong Zhang {
2100a4e85ca8SHong Zhang   PetscErrorCode ierr;
2101f4431b8cSHong Zhang 
2102a4e85ca8SHong Zhang   PetscFunctionBegin;
2103a4e85ca8SHong Zhang   if (Ju) {
2104a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2105a4e85ca8SHong Zhang   } else {
2106a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2107a4e85ca8SHong Zhang   }
2108a4e85ca8SHong Zhang   PetscFunctionReturn(0);
2109a4e85ca8SHong Zhang }
2110a4e85ca8SHong Zhang 
211124121865SAdrian Maldonado /* 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.
211224121865SAdrian Maldonado */
211324121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
211424121865SAdrian Maldonado {
211524121865SAdrian Maldonado   PetscErrorCode ierr;
211624121865SAdrian Maldonado   PetscInt       i,size,dof;
211724121865SAdrian Maldonado   PetscInt       *glob2loc;
211824121865SAdrian Maldonado 
211924121865SAdrian Maldonado   PetscFunctionBegin;
212024121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
212124121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
212224121865SAdrian Maldonado 
212324121865SAdrian Maldonado   for (i = 0; i < size; i++) {
212424121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
212524121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
212624121865SAdrian Maldonado     glob2loc[i] = dof;
212724121865SAdrian Maldonado   }
212824121865SAdrian Maldonado 
212924121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
213024121865SAdrian Maldonado #if 0
213124121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
213224121865SAdrian Maldonado #endif
213324121865SAdrian Maldonado   PetscFunctionReturn(0);
213424121865SAdrian Maldonado }
213524121865SAdrian Maldonado 
213601ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
21379e1d080bSHong Zhang 
21389e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
21391ad426b7SHong Zhang {
21401ad426b7SHong Zhang   PetscErrorCode ierr;
21411ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
21429e1d080bSHong Zhang   PetscMPIInt    rank, size;
214324121865SAdrian Maldonado   PetscInt       eDof,vDof;
214424121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
21459e1d080bSHong Zhang   MPI_Comm       comm;
214624121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
214724121865SAdrian Maldonado 
21489e1d080bSHong Zhang   PetscFunctionBegin;
214924121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2150ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
2151ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
215224121865SAdrian Maldonado 
215324121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
215424121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
215524121865SAdrian Maldonado 
215601ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
215724121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
215824121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
215924121865SAdrian Maldonado 
216001ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
216124121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
216224121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
216324121865SAdrian Maldonado 
216401ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
216524121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
216624121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
216724121865SAdrian Maldonado 
216801ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
216924121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
217024121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
217124121865SAdrian Maldonado 
21723f6a6bdaSHong Zhang   bA[0][0] = j11;
21733f6a6bdaSHong Zhang   bA[0][1] = j12;
21743f6a6bdaSHong Zhang   bA[1][0] = j21;
21753f6a6bdaSHong Zhang   bA[1][1] = j22;
217624121865SAdrian Maldonado 
217724121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
217824121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
217924121865SAdrian Maldonado 
218024121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
218124121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
218224121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
218324121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
218424121865SAdrian Maldonado 
218524121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
218624121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
218724121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
218824121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
218924121865SAdrian Maldonado 
219001ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
219124121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
219224121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
219324121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
219424121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
219524121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
219624121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
219724121865SAdrian Maldonado 
219824121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
219924121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22009e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
220124121865SAdrian Maldonado 
220224121865SAdrian Maldonado   /* Free structures */
220324121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
220424121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
220524121865SAdrian Maldonado   PetscFunctionReturn(0);
22069e1d080bSHong Zhang }
22079e1d080bSHong Zhang 
22089e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
22099e1d080bSHong Zhang {
22109e1d080bSHong Zhang   PetscErrorCode ierr;
22119e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
22129e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
22139e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
22149e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
22159e1d080bSHong Zhang   Mat            Juser;
22169e1d080bSHong Zhang   PetscSection   sectionGlobal;
22179e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
22189e1d080bSHong Zhang   const PetscInt *edges,*cone;
22199e1d080bSHong Zhang   MPI_Comm       comm;
22209e1d080bSHong Zhang   MatType        mtype;
22219e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
22229e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
22239e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
22249e1d080bSHong Zhang 
22259e1d080bSHong Zhang   PetscFunctionBegin;
22269e1d080bSHong Zhang   mtype = dm->mattype;
22279e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
22289e1d080bSHong Zhang   if (isNest) {
22299e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
2230c6b011d8SStefano Zampini     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
22319e1d080bSHong Zhang     PetscFunctionReturn(0);
22329e1d080bSHong Zhang   }
22339e1d080bSHong Zhang 
22349e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
2235a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
22369e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
2237bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
22381ad426b7SHong Zhang     PetscFunctionReturn(0);
22391ad426b7SHong Zhang   }
22401ad426b7SHong Zhang 
2241bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
2242e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
2243bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
2244bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
22452a945128SHong Zhang 
22462a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
22472a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
224889898e50SHong Zhang 
224989898e50SHong Zhang   /* (1) Set matrix preallocation */
225089898e50SHong Zhang   /*------------------------------*/
2251840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2252840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
2253840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
2254840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
2255840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
2256840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
2257840c2264SHong Zhang 
225889898e50SHong Zhang   /* Set preallocation for edges */
225989898e50SHong Zhang   /*-----------------------------*/
2260840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
2261840c2264SHong Zhang 
2262bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
2263840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
2264840c2264SHong Zhang     /* Get row indices */
22652bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
22662bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
2267840c2264SHong Zhang     if (nrows) {
2268840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
2269840c2264SHong Zhang 
22705cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
2271d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2272840c2264SHong Zhang       for (v=0; v<2; v++) {
22732bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
2274840c2264SHong Zhang 
22758675203cSHong Zhang         if (network->Je) {
2276840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
22778675203cSHong Zhang         } else Juser = NULL;
2278840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
22795cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2280840c2264SHong Zhang       }
2281840c2264SHong Zhang 
228289898e50SHong Zhang       /* Set preallocation for edge self */
2283840c2264SHong Zhang       cstart = rstart;
22848675203cSHong Zhang       if (network->Je) {
2285840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
22868675203cSHong Zhang       } else Juser = NULL;
22875cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2288840c2264SHong Zhang     }
2289840c2264SHong Zhang   }
2290840c2264SHong Zhang 
229189898e50SHong Zhang   /* Set preallocation for vertices */
229289898e50SHong Zhang   /*--------------------------------*/
2293840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
22948675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
2295840c2264SHong Zhang 
2296840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
2297840c2264SHong Zhang     /* Get row indices */
22982bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
22992bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
2300840c2264SHong Zhang     if (!nrows) continue;
2301840c2264SHong Zhang 
2302bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2303bdcb62a2SHong Zhang     if (ghost) {
2304bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2305bdcb62a2SHong Zhang     } else {
2306bdcb62a2SHong Zhang       rows_v = rows;
2307bdcb62a2SHong Zhang     }
2308bdcb62a2SHong Zhang 
2309bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2310840c2264SHong Zhang 
2311840c2264SHong Zhang     /* Get supporting edges and connected vertices */
2312840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2313840c2264SHong Zhang 
2314840c2264SHong Zhang     for (e=0; e<nedges; e++) {
2315840c2264SHong Zhang       /* Supporting edges */
23162bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
23172bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2318840c2264SHong Zhang 
23198675203cSHong Zhang       if (network->Jv) {
2320840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
23218675203cSHong Zhang       } else Juser = NULL;
2322bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2323840c2264SHong Zhang 
2324840c2264SHong Zhang       /* Connected vertices */
2325d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
2326840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
2327840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
2328840c2264SHong Zhang 
23292bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2330840c2264SHong Zhang 
23318675203cSHong Zhang       if (network->Jv) {
2332840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
23338675203cSHong Zhang       } else Juser = NULL;
2334e102a522SHong Zhang       if (ghost_vc||ghost) {
2335e102a522SHong Zhang         ghost2 = PETSC_TRUE;
2336e102a522SHong Zhang       } else {
2337e102a522SHong Zhang         ghost2 = PETSC_FALSE;
2338e102a522SHong Zhang       }
2339e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
2340840c2264SHong Zhang     }
2341840c2264SHong Zhang 
234289898e50SHong Zhang     /* Set preallocation for vertex self */
2343840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2344840c2264SHong Zhang     if (!ghost) {
23452bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
23468675203cSHong Zhang       if (network->Jv) {
2347840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
23488675203cSHong Zhang       } else Juser = NULL;
2349bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2350840c2264SHong Zhang     }
2351bdcb62a2SHong Zhang     if (ghost) {
2352bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2353bdcb62a2SHong Zhang     }
2354840c2264SHong Zhang   }
2355840c2264SHong Zhang 
2356840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
2357840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
23585cf7da58SHong Zhang 
23595cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
23605cf7da58SHong Zhang 
23615cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
2362840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
2363840c2264SHong Zhang 
2364840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
2365840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
2366840c2264SHong Zhang   for (j=0; j<localSize; j++) {
2367e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
2368e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
2369840c2264SHong Zhang   }
2370840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
2371840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
2372840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
2373840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
2374840c2264SHong Zhang 
23755cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
23765cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
23775cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
23785cf7da58SHong Zhang 
23795cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
23805cf7da58SHong Zhang 
238189898e50SHong Zhang   /* (2) Set matrix entries for edges */
238289898e50SHong Zhang   /*----------------------------------*/
23831ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
2384bfbc38dcSHong Zhang     /* Get row indices */
23852bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
23862bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
23874b976069SHong Zhang     if (nrows) {
238817df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
23891ad426b7SHong Zhang 
2390bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
2391d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2392bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
23932bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVecOffset(dm,cone[v],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
23942bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
23953e97b6e8SHong Zhang 
23968675203cSHong Zhang         if (network->Je) {
2397a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
23988675203cSHong Zhang         } else Juser = NULL;
2399a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2400bfbc38dcSHong Zhang       }
240117df6e9eSHong Zhang 
2402bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
24033e97b6e8SHong Zhang       cstart = rstart;
24048675203cSHong Zhang       if (network->Je) {
2405a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
24068675203cSHong Zhang       } else Juser = NULL;
2407a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
24081ad426b7SHong Zhang     }
24094b976069SHong Zhang   }
24101ad426b7SHong Zhang 
2411bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
241283b2e829SHong Zhang   /*---------------------------------*/
24131ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2414bfbc38dcSHong Zhang     /* Get row indices */
24152bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
24162bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
24174b976069SHong Zhang     if (!nrows) continue;
2418596e729fSHong Zhang 
2419bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2420bdcb62a2SHong Zhang     if (ghost) {
2421bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2422bdcb62a2SHong Zhang     } else {
2423bdcb62a2SHong Zhang       rows_v = rows;
2424bdcb62a2SHong Zhang     }
2425bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2426596e729fSHong Zhang 
2427bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2428596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2429596e729fSHong Zhang 
2430596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2431bfbc38dcSHong Zhang       /* Supporting edges */
24322bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
24332bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2434596e729fSHong Zhang 
24358675203cSHong Zhang       if (network->Jv) {
2436a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
24378675203cSHong Zhang       } else Juser = NULL;
2438bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2439596e729fSHong Zhang 
2440bfbc38dcSHong Zhang       /* Connected vertices */
2441d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
24422a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
24432a945128SHong Zhang 
24442bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,vc,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
24452bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2446a4e85ca8SHong Zhang 
24478675203cSHong Zhang       if (network->Jv) {
2448a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
24498675203cSHong Zhang       } else Juser = NULL;
2450bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2451596e729fSHong Zhang     }
2452596e729fSHong Zhang 
2453bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
24541ad426b7SHong Zhang     if (!ghost) {
24552bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
24568675203cSHong Zhang       if (network->Jv) {
2457a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
24588675203cSHong Zhang       } else Juser = NULL;
2459bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2460bdcb62a2SHong Zhang     }
2461bdcb62a2SHong Zhang     if (ghost) {
2462bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2463bdcb62a2SHong Zhang     }
24641ad426b7SHong Zhang   }
2465a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2466bdcb62a2SHong Zhang 
24671ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24681ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2469dd6f46cdSHong Zhang 
24705f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
24715f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
24725f2c45f1SShri Abhyankar }
24735f2c45f1SShri Abhyankar 
24745f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
24755f2c45f1SShri Abhyankar {
24765f2c45f1SShri Abhyankar   PetscErrorCode ierr;
24775f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
24782727e31bSShri Abhyankar   PetscInt       j;
24795f2c45f1SShri Abhyankar 
24805f2c45f1SShri Abhyankar   PetscFunctionBegin;
24818415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
248283b2e829SHong Zhang   if (network->Je) {
248383b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
248483b2e829SHong Zhang   }
248583b2e829SHong Zhang   if (network->Jv) {
2486883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
248783b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
24881ad426b7SHong Zhang   }
248913c2a604SAdrian Maldonado 
249013c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
249113c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
249213c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2493f5427c60SHong Zhang   if (network->vltog) {
2494f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2495f5427c60SHong Zhang   }
249613c2a604SAdrian Maldonado   if (network->vertex.sf) {
249713c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
249813c2a604SAdrian Maldonado   }
249913c2a604SAdrian Maldonado   /* edge */
250013c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
250113c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
250213c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
250313c2a604SAdrian Maldonado   if (network->edge.sf) {
250413c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
250513c2a604SAdrian Maldonado   }
25065f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
25075f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
25085f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
250983b2e829SHong Zhang 
25102bf73ac6SHong Zhang   for (j=0; j<network->Nsvtx; j++) {
25112bf73ac6SHong Zhang     ierr = PetscFree(network->svtx[j].sv);CHKERRQ(ierr);
25122bf73ac6SHong Zhang   }
25132bf73ac6SHong Zhang   if (network->svtx) {ierr = PetscFree(network->svtx);CHKERRQ(ierr);}
25142bf73ac6SHong Zhang 
25152bf73ac6SHong Zhang   for (j=0; j<network->Nsubnet; j++) {
25162727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
25172727e31bSShri Abhyankar   }
25182bf73ac6SHong Zhang   if (network->subnetvtx) {ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr);}
2519caf410d2SHong Zhang 
25202bf73ac6SHong Zhang   ierr = PetscTableDestroy(&network->svtable);CHKERRQ(ierr);
2521e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
25225f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
2523caf410d2SHong Zhang   ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
25245f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
25255f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
25265f2c45f1SShri Abhyankar }
25275f2c45f1SShri Abhyankar 
25285f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
25295f2c45f1SShri Abhyankar {
25305f2c45f1SShri Abhyankar   PetscErrorCode ierr;
2531caf410d2SHong Zhang   PetscBool      iascii;
2532caf410d2SHong Zhang   PetscMPIInt    rank;
25335f2c45f1SShri Abhyankar 
25345f2c45f1SShri Abhyankar   PetscFunctionBegin;
2535caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2536ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
2537caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2538caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2539caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2540caf410d2SHong Zhang   if (iascii) {
2541caf410d2SHong Zhang     const PetscInt *cone,*vtx,*edges;
25422bf73ac6SHong Zhang     PetscInt       vfrom,vto,i,j,nv,ne,ncv,p,nsubnet;
25432bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
2544caf410d2SHong Zhang 
25452bf73ac6SHong Zhang     nsubnet = network->Nsubnet; /* num of subnetworks */
25462bf73ac6SHong Zhang     if (!rank) {
25472bf73ac6SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  NSubnets: %D; NEdges: %D; NVertices: %D; NSharedVertices: %D.\n",nsubnet,network->NEdges,network->NVertices,network->Nsvtx);CHKERRQ(ierr);
25482bf73ac6SHong Zhang     }
25492bf73ac6SHong Zhang 
25502bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
2551caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
25522bf73ac6SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nEdges: %D; nVertices: %D; nSharedVertices: %D\n",rank,network->nEdges,network->nVertices,ncv);CHKERRQ(ierr);
2553caf410d2SHong Zhang 
2554caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
25552bf73ac6SHong Zhang       ierr = DMNetworkGetSubnetwork(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2556caf410d2SHong Zhang       if (ne) {
25572bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices(include shared vertices) %D\n",i,ne,nv);CHKERRQ(ierr);
2558caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2559caf410d2SHong Zhang           p = edges[j];
2560caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2561caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2562caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2563caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2564caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D ----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2565caf410d2SHong Zhang         }
2566caf410d2SHong Zhang       }
2567caf410d2SHong Zhang     }
25682bf73ac6SHong Zhang 
25692bf73ac6SHong Zhang     /* Shared vertices */
25702bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
25712bf73ac6SHong Zhang     if (ncv) {
25722bf73ac6SHong Zhang       SVtx       *svtx = network->svtx;
25732bf73ac6SHong Zhang       PetscInt    gidx,svtx_idx,nvto,vfrom_net,vfrom_idx,*svto;
25742bf73ac6SHong Zhang       PetscBool   ghost;
25752bf73ac6SHong Zhang       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     SharedVertices:\n");CHKERRQ(ierr);
25762bf73ac6SHong Zhang       for (i=0; i<ncv; i++) {
25772bf73ac6SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,vtx[i],&ghost);CHKERRQ(ierr);
25782bf73ac6SHong Zhang         if (ghost) continue;
25792bf73ac6SHong Zhang 
25802bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVertexIndex(dm,vtx[i],&gidx);CHKERRQ(ierr);
25812bf73ac6SHong Zhang         ierr = PetscTableFind(network->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
25822bf73ac6SHong Zhang         svtx_idx--;
25832bf73ac6SHong Zhang         nvto = svtx[svtx_idx].n;
25842bf73ac6SHong Zhang 
25852bf73ac6SHong Zhang         vfrom_net = svtx[svtx_idx].sv[0];
25862bf73ac6SHong Zhang         vfrom_idx = svtx[svtx_idx].sv[1];
25872bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       svtx %D: global index %D, subnet[%D].%D ---->\n",i,gidx,vfrom_net,vfrom_idx);CHKERRQ(ierr);
25882bf73ac6SHong Zhang         for (j=1; j<nvto; j++) {
25892bf73ac6SHong Zhang           svto = svtx[svtx_idx].sv + 2*j;
25902bf73ac6SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "                                           ----> subnet[%D].%D\n",svto[0],svto[1]);CHKERRQ(ierr);
2591caf410d2SHong Zhang         }
2592caf410d2SHong Zhang       }
2593caf410d2SHong Zhang     }
2594caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2595caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2596caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
25975f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
25985f2c45f1SShri Abhyankar }
25995f2c45f1SShri Abhyankar 
26005f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
26015f2c45f1SShri Abhyankar {
26025f2c45f1SShri Abhyankar   PetscErrorCode ierr;
26035f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
26045f2c45f1SShri Abhyankar 
26055f2c45f1SShri Abhyankar   PetscFunctionBegin;
26065f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
26075f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26085f2c45f1SShri Abhyankar }
26095f2c45f1SShri Abhyankar 
26105f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
26115f2c45f1SShri Abhyankar {
26125f2c45f1SShri Abhyankar   PetscErrorCode ierr;
26135f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
26145f2c45f1SShri Abhyankar 
26155f2c45f1SShri Abhyankar   PetscFunctionBegin;
26165f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
26175f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26185f2c45f1SShri Abhyankar }
26195f2c45f1SShri Abhyankar 
26205f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
26215f2c45f1SShri Abhyankar {
26225f2c45f1SShri Abhyankar   PetscErrorCode ierr;
26235f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
26245f2c45f1SShri Abhyankar 
26255f2c45f1SShri Abhyankar   PetscFunctionBegin;
26265f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
26275f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26285f2c45f1SShri Abhyankar }
26295f2c45f1SShri Abhyankar 
26305f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
26315f2c45f1SShri Abhyankar {
26325f2c45f1SShri Abhyankar   PetscErrorCode ierr;
26335f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
26345f2c45f1SShri Abhyankar 
26355f2c45f1SShri Abhyankar   PetscFunctionBegin;
26365f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
26375f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26385f2c45f1SShri Abhyankar }
263922bbedd7SHong Zhang 
264022bbedd7SHong Zhang /*@
264164238763SRodolfo Oliveira   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index
264222bbedd7SHong Zhang 
264322bbedd7SHong Zhang   Not collective
264422bbedd7SHong Zhang 
26457a7aea1fSJed Brown   Input Parameters:
264622bbedd7SHong Zhang + dm - the dm object
264722bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
264822bbedd7SHong Zhang 
26497a7aea1fSJed Brown   Output Parameters:
2650f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
265122bbedd7SHong Zhang 
265297bb938eSShri Abhyankar   Level: advanced
265322bbedd7SHong Zhang 
265422bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
265522bbedd7SHong Zhang @*/
265622bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
265722bbedd7SHong Zhang {
265822bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
265922bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
266022bbedd7SHong Zhang 
266122bbedd7SHong Zhang   PetscFunctionBegin;
266222bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
266322bbedd7SHong Zhang   *vg = vltog[vloc];
266422bbedd7SHong Zhang   PetscFunctionReturn(0);
266522bbedd7SHong Zhang }
266622bbedd7SHong Zhang 
266722bbedd7SHong Zhang /*@
266864238763SRodolfo Oliveira   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map
266922bbedd7SHong Zhang 
267022bbedd7SHong Zhang   Collective
267122bbedd7SHong Zhang 
267222bbedd7SHong Zhang   Input Parameters:
2673f0fc11ceSJed Brown . dm - the dm object
267422bbedd7SHong Zhang 
267597bb938eSShri Abhyankar   Level: advanced
267622bbedd7SHong Zhang 
267763029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
267822bbedd7SHong Zhang @*/
267922bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
268022bbedd7SHong Zhang {
268122bbedd7SHong Zhang   PetscErrorCode    ierr;
268222bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
268322bbedd7SHong Zhang   MPI_Comm          comm;
26842bf73ac6SHong Zhang   PetscMPIInt       rank,size,*displs=NULL,*recvcounts=NULL,remoterank;
268522bbedd7SHong Zhang   PetscBool         ghost;
268663029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
268722bbedd7SHong Zhang   const PetscSFNode *iremote;
268822bbedd7SHong Zhang   PetscSF           vsf;
268963029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
269063029d29SHong Zhang   VecScatter        ctx;
269163029d29SHong Zhang   PetscScalar       *varr,val;
269263029d29SHong Zhang   const PetscScalar *varr_read;
269322bbedd7SHong Zhang 
269422bbedd7SHong Zhang   PetscFunctionBegin;
269522bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2696ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
2697ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
269822bbedd7SHong Zhang 
269922bbedd7SHong Zhang   if (size == 1) {
270022bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
270122bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
270222bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
270322bbedd7SHong Zhang     network->vltog = vltog;
270422bbedd7SHong Zhang     PetscFunctionReturn(0);
270522bbedd7SHong Zhang   }
270622bbedd7SHong Zhang 
270722bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
270822bbedd7SHong Zhang   if (network->vltog) {
270922bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
271022bbedd7SHong Zhang   }
271122bbedd7SHong Zhang 
271222bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
271322bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
271422bbedd7SHong Zhang   vsf = network->vertex.sf;
271522bbedd7SHong Zhang 
27162bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
2717f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
271822bbedd7SHong Zhang 
271922bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
272022bbedd7SHong Zhang 
272122bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
272222bbedd7SHong Zhang   vrange[0] = 0;
2723ffc4695bSBarry Smith   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
272467dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
272522bbedd7SHong Zhang 
272622bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
272722bbedd7SHong Zhang   network->vltog = vltog;
272822bbedd7SHong Zhang 
272963029d29SHong Zhang   /* Set vltog for non-ghost vertices */
273063029d29SHong Zhang   k = 0;
273122bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
273222bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
273363029d29SHong Zhang     if (ghost) continue;
273463029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
273522bbedd7SHong Zhang   }
2736f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
273763029d29SHong Zhang 
273863029d29SHong Zhang   /* Set vltog for ghost vertices */
273963029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
274063029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
274163029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
274263029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
274363029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
274463029d29SHong Zhang   for (i=0; i<nleaves; i++) {
274563029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
274663029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
274763029d29SHong Zhang   }
274863029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
274963029d29SHong Zhang 
275063029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
275163029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
275263029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
275363029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
275463029d29SHong Zhang 
275563029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
275663029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
275763029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
275863029d29SHong Zhang   for (i=0; i<N; i+=2) {
27592e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
276063029d29SHong Zhang     if (remoterank == rank) {
276163029d29SHong Zhang       k = i+1; /* row number */
27622e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
276363029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
276463029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
276563029d29SHong Zhang     }
276663029d29SHong Zhang   }
276763029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
276863029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
276963029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
277063029d29SHong Zhang 
277163029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
277263029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
277363029d29SHong Zhang   k = 0;
277463029d29SHong Zhang   for (i=0; i<nroots; i++) {
277563029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
277663029d29SHong Zhang     if (!ghost) continue;
27772e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
277863029d29SHong Zhang   }
277963029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
278063029d29SHong Zhang 
278163029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
278263029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
278363029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
278422bbedd7SHong Zhang   PetscFunctionReturn(0);
278522bbedd7SHong Zhang }
2786