xref: /petsc/src/dm/impls/network/network.c (revision 54dfd506e9d5680eebf466ef315538d9ecc78ac4)
1af0996ceSBarry Smith #include <petsc/private/dmnetworkimpl.h>  /*I  "petscdmnetwork.h"  I*/
25f2c45f1SShri Abhyankar 
3*54dfd506SHong Zhang /*
4*54dfd506SHong Zhang   Creates the component header and value objects for a network point
5*54dfd506SHong Zhang */
6*54dfd506SHong Zhang static PetscErrorCode SetUpNetworkHeaderComponentValue(DM dm,DMNetworkComponentHeader header,DMNetworkComponentValue cvalue)
7*54dfd506SHong Zhang {
8*54dfd506SHong Zhang   PetscErrorCode ierr;
9*54dfd506SHong Zhang 
10*54dfd506SHong Zhang   PetscFunctionBegin;
11*54dfd506SHong Zhang   /* Allocate arrays for component information */
12*54dfd506SHong Zhang   ierr = PetscCalloc5(header->maxcomps,&header->size,header->maxcomps,&header->key,header->maxcomps,&header->offset,header->maxcomps,&header->nvar,header->maxcomps,&header->offsetvarrel);CHKERRQ(ierr);
13*54dfd506SHong Zhang   ierr = PetscCalloc1(header->maxcomps,&cvalue->data);CHKERRQ(ierr);
14*54dfd506SHong Zhang 
15*54dfd506SHong Zhang   /* The size of the header is the size of struct _p_DMNetworkComponentHeader. Since the struct contains PetscInt pointers we cannot use sizeof(struct). So, we need to explicitly calculate the size.
16*54dfd506SHong Zhang    If the data header struct changes then this header size calculation needs to be updated. */
17*54dfd506SHong Zhang   header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt);
18*54dfd506SHong Zhang   header->hsize /= sizeof(DMNetworkComponentGenericDataType);
19*54dfd506SHong Zhang   PetscFunctionReturn(0);
20*54dfd506SHong Zhang }
21*54dfd506SHong Zhang 
225f2c45f1SShri Abhyankar /*@
23556ed216SShri Abhyankar   DMNetworkGetPlex - Gets the Plex DM associated with this network DM
24556ed216SShri Abhyankar 
25556ed216SShri Abhyankar   Not collective
26556ed216SShri Abhyankar 
27556ed216SShri Abhyankar   Input Parameters:
282bf73ac6SHong Zhang . dm - the dm object
292bf73ac6SHong Zhang 
302bf73ac6SHong Zhang   Output Parameters:
312bf73ac6SHong Zhang . plexdm - the plex dm object
32556ed216SShri Abhyankar 
33556ed216SShri Abhyankar   Level: Advanced
34556ed216SShri Abhyankar 
35556ed216SShri Abhyankar .seealso: DMNetworkCreate()
36556ed216SShri Abhyankar @*/
372bf73ac6SHong Zhang PetscErrorCode DMNetworkGetPlex(DM dm,DM *plexdm)
38556ed216SShri Abhyankar {
392bf73ac6SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
40556ed216SShri Abhyankar 
41556ed216SShri Abhyankar   PetscFunctionBegin;
42556ed216SShri Abhyankar   *plexdm = network->plex;
43556ed216SShri Abhyankar   PetscFunctionReturn(0);
44556ed216SShri Abhyankar }
45556ed216SShri Abhyankar 
46556ed216SShri Abhyankar /*@
472bf73ac6SHong Zhang   DMNetworkGetNumSubNetworks - Gets the the number of subnetworks
4872c3e9f7SHong Zhang 
492bf73ac6SHong Zhang   Not collective
5072c3e9f7SHong Zhang 
5172c3e9f7SHong Zhang   Input Parameters:
522bf73ac6SHong Zhang . dm - the dm object
532bf73ac6SHong Zhang 
542bf73ac6SHong Zhang   Output Parameters:
552bf73ac6SHong Zhang + nsubnet - local number of subnetworks
562bf73ac6SHong Zhang - Nsubnet - global number of subnetworks
5772c3e9f7SHong Zhang 
5897bb938eSShri Abhyankar   Level: beginner
5972c3e9f7SHong Zhang 
602bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkSetNumSubNetworks()
6172c3e9f7SHong Zhang @*/
622bf73ac6SHong Zhang PetscErrorCode DMNetworkGetNumSubNetworks(DM dm,PetscInt *nsubnet,PetscInt *Nsubnet)
6372c3e9f7SHong Zhang {
642bf73ac6SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
6572c3e9f7SHong Zhang 
6672c3e9f7SHong Zhang   PetscFunctionBegin;
672bf73ac6SHong Zhang   if (nsubnet) *nsubnet = network->nsubnet;
682bf73ac6SHong Zhang   if (Nsubnet) *Nsubnet = network->Nsubnet;
6972c3e9f7SHong Zhang   PetscFunctionReturn(0);
7072c3e9f7SHong Zhang }
7172c3e9f7SHong Zhang 
7272c3e9f7SHong Zhang /*@
732bf73ac6SHong Zhang   DMNetworkSetNumSubNetworks - Sets the number of subnetworks
745f2c45f1SShri Abhyankar 
75d083f849SBarry Smith   Collective on dm
765f2c45f1SShri Abhyankar 
775f2c45f1SShri Abhyankar   Input Parameters:
785f2c45f1SShri Abhyankar + dm - the dm object
792bf73ac6SHong Zhang . nsubnet - local number of subnetworks
802bf73ac6SHong Zhang - Nsubnet - global number of subnetworks
815f2c45f1SShri Abhyankar 
8297bb938eSShri Abhyankar    Level: beginner
831b266c99SBarry Smith 
842bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetNumSubNetworks()
855f2c45f1SShri Abhyankar @*/
862bf73ac6SHong Zhang PetscErrorCode DMNetworkSetNumSubNetworks(DM dm,PetscInt nsubnet,PetscInt Nsubnet)
875f2c45f1SShri Abhyankar {
885f2c45f1SShri Abhyankar   PetscErrorCode ierr;
895f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
905f2c45f1SShri Abhyankar 
915f2c45f1SShri Abhyankar   PetscFunctionBegin;
922bf73ac6SHong Zhang   if (network->Nsubnet != 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network");
932bf73ac6SHong Zhang 
945f2c45f1SShri Abhyankar   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
952bf73ac6SHong Zhang   PetscValidLogicalCollectiveInt(dm,nsubnet,2);
962bf73ac6SHong Zhang   PetscValidLogicalCollectiveInt(dm,Nsubnet,3);
977765340cSHong Zhang 
982bf73ac6SHong Zhang   if (Nsubnet == PETSC_DECIDE) {
992bf73ac6SHong Zhang     if (nsubnet < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of local subnetworks %D cannot be less than 0",nsubnet);
100820f2d46SBarry Smith     ierr = MPIU_Allreduce(&nsubnet,&Nsubnet,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
101caf410d2SHong Zhang   }
1022bf73ac6SHong Zhang   if (Nsubnet < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Number of global subnetworks %D cannot be less than 1",Nsubnet);
103caf410d2SHong Zhang 
1042bf73ac6SHong Zhang   network->Nsubnet  = Nsubnet;
1052bf73ac6SHong Zhang   network->nsubnet  = 0;       /* initia value; will be determind by DMNetworkAddSubnetwork() */
1062bf73ac6SHong Zhang   ierr = PetscCalloc1(Nsubnet,&network->subnet);CHKERRQ(ierr);
107caf410d2SHong Zhang 
1082bf73ac6SHong Zhang   /* num of shared vertices */
1092bf73ac6SHong Zhang   network->nsvtx = 0;
1102bf73ac6SHong Zhang   network->Nsvtx = 0;
1117765340cSHong Zhang   PetscFunctionReturn(0);
1127765340cSHong Zhang }
1137765340cSHong Zhang 
1145f2c45f1SShri Abhyankar /*@
1152bf73ac6SHong Zhang   DMNetworkAddSubnetwork - Add a subnetwork
1165f2c45f1SShri Abhyankar 
1172bf73ac6SHong Zhang   Collective on dm
1185f2c45f1SShri Abhyankar 
1195f2c45f1SShri Abhyankar   Input Parameters:
120e3e68989SHong Zhang + dm - the dm object
1212bf73ac6SHong Zhang . name - name of the subnetwork
1222bf73ac6SHong Zhang . nv - number of local vertices of this subnetwork
1232bf73ac6SHong Zhang . ne - number of local edges of this subnetwork
1242bf73ac6SHong Zhang - edgelist - list of edges for this subnetwork
1252bf73ac6SHong Zhang 
1262bf73ac6SHong Zhang   Output Parameters:
1272bf73ac6SHong Zhang . netnum - global index of the subnetwork
1285f2c45f1SShri Abhyankar 
1295f2c45f1SShri Abhyankar   Notes:
1305f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1312bf73ac6SHong Zhang   not be destroyed before the call to DMNetworkLayoutSetUp()
1325f2c45f1SShri Abhyankar 
13397bb938eSShri Abhyankar   Level: beginner
1345f2c45f1SShri Abhyankar 
135e3e68989SHong Zhang   Example usage:
1362bf73ac6SHong Zhang   Consider the following network:
137e3e68989SHong Zhang .vb
138e3e68989SHong Zhang  network 1: v1 -> v2 -> v0
139e3e68989SHong Zhang .ve
140e3e68989SHong Zhang 
141e3e68989SHong Zhang  The resulting input
1422bf73ac6SHong Zhang    edgelist = [1 2 | 2 0]
143e3e68989SHong Zhang 
1442bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkSetNumSubnetworks()
1455f2c45f1SShri Abhyankar @*/
1462bf73ac6SHong Zhang PetscErrorCode DMNetworkAddSubnetwork(DM dm,const char* name,PetscInt nv,PetscInt ne,PetscInt edgelist[],PetscInt *netnum)
1475f2c45f1SShri Abhyankar {
1482bf73ac6SHong Zhang   PetscErrorCode ierr;
1495f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
1502bf73ac6SHong Zhang   PetscInt       i = network->nsubnet,a[2],b[2];
1515f2c45f1SShri Abhyankar 
1525f2c45f1SShri Abhyankar   PetscFunctionBegin;
1532bf73ac6SHong Zhang   if (name) {
1542bf73ac6SHong Zhang     ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr);
155e3e68989SHong Zhang   }
1562bf73ac6SHong Zhang 
1572bf73ac6SHong Zhang   network->subnet[i].nvtx     = nv;
1582bf73ac6SHong Zhang   network->subnet[i].nedge    = ne;
1592bf73ac6SHong Zhang   network->subnet[i].edgelist = edgelist;
1602bf73ac6SHong Zhang 
1612bf73ac6SHong Zhang   /* Get global number of vertices and edges for subnet[i] */
1622bf73ac6SHong Zhang   a[0] = nv; a[1] = ne;
163820f2d46SBarry Smith   ierr = MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
1642bf73ac6SHong Zhang   network->subnet[i].Nvtx  = b[0];
1652bf73ac6SHong Zhang   network->subnet[i].Nedge = b[1];
1662bf73ac6SHong Zhang 
1672bf73ac6SHong Zhang   /* ----------------------------------------------------------
1682bf73ac6SHong Zhang    p=v or e;
1692bf73ac6SHong Zhang    subnet[0].pStart   = 0
1702bf73ac6SHong Zhang    subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i])
1712bf73ac6SHong Zhang    ----------------------------------------------------------------------- */
1722bf73ac6SHong Zhang   /* GLOBAL subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */
1732bf73ac6SHong Zhang   network->subnet[i].vStart = network->NVertices;
1742bf73ac6SHong Zhang   network->subnet[i].vEnd   = network->subnet[i].vStart + network->subnet[i].Nvtx; /* global vEnd of subnet[i] */
1752bf73ac6SHong Zhang 
1762bf73ac6SHong Zhang   network->nVertices += nv;
1772bf73ac6SHong Zhang   network->NVertices += network->subnet[i].Nvtx;
1782bf73ac6SHong Zhang 
1792bf73ac6SHong Zhang   /* LOCAL subnet[].eStart and eEnd, used by DMNetworkLayoutSetUp() */
1802bf73ac6SHong Zhang   network->subnet[i].eStart = network->nEdges;
1812bf73ac6SHong Zhang   network->subnet[i].eEnd   = network->subnet[i].eStart + ne;
1822bf73ac6SHong Zhang   network->nEdges += ne;
1832bf73ac6SHong Zhang   network->NEdges += network->subnet[i].Nedge;
1842bf73ac6SHong Zhang 
1852bf73ac6SHong Zhang   ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr);
1862bf73ac6SHong Zhang   if (netnum) *netnum = network->nsubnet;
1872bf73ac6SHong Zhang   network->nsubnet++;
1882bf73ac6SHong Zhang   PetscFunctionReturn(0);
1892bf73ac6SHong Zhang }
1902bf73ac6SHong Zhang 
1912bf73ac6SHong Zhang /*
1922bf73ac6SHong Zhang   SetUp a single svtx struct. See SVtx defined in dmnetworkimpl.h
1932bf73ac6SHong Zhang   Set gidx and type if input v=(net,idx) is a from_vertex;
1942bf73ac6SHong Zhang   Get gid, type and index in the svtx array if input v=(net,idx) is a to_vertex.
1952bf73ac6SHong Zhang 
1962bf73ac6SHong Zhang   Input:  Nsvtx, svtx, net, idx, gidx
1972bf73ac6SHong Zhang   Output: gidx, svtype, svtx_idx
1982bf73ac6SHong Zhang  */
1992bf73ac6SHong Zhang static PetscErrorCode SVtxSetUp(PetscInt Nsvtx,SVtx *svtx,PetscInt net,PetscInt idx,PetscInt *gidx,SVtxType *svtype,PetscInt *svtx_idx)
2002bf73ac6SHong Zhang {
2012bf73ac6SHong Zhang   PetscInt i,j,*svto;
2022bf73ac6SHong Zhang   SVtxType vtype;
2032bf73ac6SHong Zhang 
2042bf73ac6SHong Zhang   PetscFunctionBegin;
2052bf73ac6SHong Zhang   if (!Nsvtx) PetscFunctionReturn(0);
2062bf73ac6SHong Zhang 
2072bf73ac6SHong Zhang   vtype = SVNONE;
2082bf73ac6SHong Zhang   for (i=0; i<Nsvtx; i++) {
2092bf73ac6SHong Zhang     if (net == svtx[i].sv[0] && idx == svtx[i].sv[1]) {
2102bf73ac6SHong Zhang       /* (1) input vertex net.idx is a shared from_vertex, set its global index and output its svtype */
2112bf73ac6SHong Zhang       svtx[i].gidx = *gidx; /* set gidx */
2122bf73ac6SHong Zhang       vtype        = SVFROM;
2132bf73ac6SHong Zhang     } else { /* loop over svtx[i].n */
2142bf73ac6SHong Zhang       for (j=1; j<svtx[i].n; j++) {
2152bf73ac6SHong Zhang         svto = svtx[i].sv + 2*j;
2162bf73ac6SHong Zhang         if (net == svto[0] && idx == svto[1]) {
2172bf73ac6SHong Zhang           /* input vertex net.idx is a shared to_vertex, output its global index and its svtype */
2182bf73ac6SHong Zhang           *gidx = svtx[i].gidx; /* output gidx for to_vertex */
2192bf73ac6SHong Zhang           vtype = SVTO;
2202bf73ac6SHong Zhang         }
2212bf73ac6SHong Zhang       }
2222bf73ac6SHong Zhang     }
2232bf73ac6SHong Zhang     if (vtype != SVNONE) break;
2242bf73ac6SHong Zhang   }
2252bf73ac6SHong Zhang   if (svtype)   *svtype   = vtype;
2262bf73ac6SHong Zhang   if (svtx_idx) *svtx_idx = i;
2272bf73ac6SHong Zhang   PetscFunctionReturn(0);
2282bf73ac6SHong Zhang }
2292bf73ac6SHong Zhang 
2302bf73ac6SHong Zhang /*
2312bf73ac6SHong Zhang  Add a new shared vertex sv=(net,idx) to table svtas[ita]
2322bf73ac6SHong Zhang */
2332bf73ac6SHong Zhang static PetscErrorCode TableAddSVtx(PetscTable *svtas,PetscInt ita,PetscInt* tdata,PetscInt *sv_wk,PetscInt *ii,PetscInt *sedgelist,PetscInt k,DM_Network *network,PetscInt **ta2sv)
2342bf73ac6SHong Zhang {
2352bf73ac6SHong Zhang   PetscInt       net,idx,gidx,i=*ii;
2362bf73ac6SHong Zhang   PetscErrorCode ierr;
2372bf73ac6SHong Zhang 
2382bf73ac6SHong Zhang   PetscFunctionBegin;
2392bf73ac6SHong Zhang   net = sv_wk[2*i]   = sedgelist[k];
2402bf73ac6SHong Zhang   idx = sv_wk[2*i+1] = sedgelist[k+1];
2412bf73ac6SHong Zhang   gidx = network->subnet[net].vStart + idx;
2422bf73ac6SHong Zhang   ierr = PetscTableAdd(svtas[ita],gidx+1,tdata[ita]+1,INSERT_VALUES);CHKERRQ(ierr);
2432bf73ac6SHong Zhang   *(ta2sv[ita] + tdata[ita]) = i; /* maps tdata to index of sv_wk; sv_wk keeps (net,idx) info */
2442bf73ac6SHong Zhang   tdata[ita]++; (*ii)++;
2452bf73ac6SHong Zhang   PetscFunctionReturn(0);
2462bf73ac6SHong Zhang }
2472bf73ac6SHong Zhang 
2482bf73ac6SHong Zhang /*
2492bf73ac6SHong Zhang   Create an array of shared vertices. See SVtx and SVtxType in dmnetworkimpl.h
2502bf73ac6SHong Zhang 
2512bf73ac6SHong Zhang   Input:  dm, Nsedgelist, sedgelist
2522bf73ac6SHong Zhang   Output: Nsvtx,svtx
2532bf73ac6SHong Zhang 
2542bf73ac6SHong Zhang   Note: Output svtx is organized as
2552bf73ac6SHong Zhang         sv(net[0],idx[0]) --> sv(net[1],idx[1])
2562bf73ac6SHong Zhang                           --> sv(net[1],idx[1])
2572bf73ac6SHong Zhang                           ...
2582bf73ac6SHong Zhang                           --> sv(net[n-1],idx[n-1])
2592bf73ac6SHong Zhang         and net[0] < net[1] < ... < net[n-1]
2602bf73ac6SHong Zhang         where sv[0] has SVFROM type, sv[i], i>0, has SVTO type.
2612bf73ac6SHong Zhang  */
2622bf73ac6SHong Zhang static PetscErrorCode SVtxCreate(DM dm,PetscInt Nsedgelist,PetscInt *sedgelist,PetscInt *Nsvtx,SVtx **svtx)
2632bf73ac6SHong Zhang {
2642bf73ac6SHong Zhang   PetscErrorCode ierr;
2652bf73ac6SHong Zhang   SVtx           *sedges = NULL;
2662bf73ac6SHong Zhang   PetscInt       *sv,k,j,nsv,*tdata,**ta2sv;
2672bf73ac6SHong Zhang   PetscTable     *svtas;
2682bf73ac6SHong Zhang   PetscInt       gidx,net,idx,i,nta,ita,idx_from,idx_to,n,*sv_wk;
2692bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
2702bf73ac6SHong Zhang   PetscTablePosition ppos;
2712bf73ac6SHong Zhang 
2722bf73ac6SHong Zhang   PetscFunctionBegin;
2732bf73ac6SHong Zhang   /* (1) Crete ctables svtas */
2742bf73ac6SHong Zhang   ierr = PetscCalloc4(Nsedgelist,&svtas,Nsedgelist,&tdata,4*Nsedgelist,&sv_wk,2*Nsedgelist,&ta2sv);CHKERRQ(ierr);
2752bf73ac6SHong Zhang 
2762bf73ac6SHong Zhang   j   = 0;   /* sedgelist counter */
2772bf73ac6SHong Zhang   k   = 0;   /* sedgelist vertex counter j = 4*k */
2782bf73ac6SHong Zhang   i   = 0;   /* sv_wk (vertices added to the ctables) counter */
2792bf73ac6SHong Zhang   nta = 0;   /* num of sv tables created */
2802bf73ac6SHong Zhang 
2812bf73ac6SHong Zhang   /* for j=0 */
2822bf73ac6SHong Zhang   ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr);
2832bf73ac6SHong Zhang   ierr = PetscMalloc1(2*Nsedgelist,&ta2sv[nta]);CHKERRQ(ierr);
2842bf73ac6SHong Zhang 
2852bf73ac6SHong Zhang   ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
2862bf73ac6SHong Zhang   ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
2872bf73ac6SHong Zhang   nta++; k += 4;
2882bf73ac6SHong Zhang 
2892bf73ac6SHong Zhang   for (j = 1; j < Nsedgelist; j++) {
2902bf73ac6SHong Zhang     for (ita = 0; ita < nta; ita++) {
2912bf73ac6SHong Zhang       /* vfrom */
2922bf73ac6SHong Zhang       net = sedgelist[k]; idx = sedgelist[k+1];
2932bf73ac6SHong Zhang       gidx = network->subnet[net].vStart + idx; /* global index of the vertex net.idx before merging shared vertices */
2942bf73ac6SHong Zhang       ierr = PetscTableFind(svtas[ita],gidx+1,&idx_from);CHKERRQ(ierr);
2952bf73ac6SHong Zhang 
2962bf73ac6SHong Zhang       /* vto */
2972bf73ac6SHong Zhang       net = sedgelist[k+2]; idx = sedgelist[k+3];
2982bf73ac6SHong Zhang       gidx = network->subnet[net].vStart + idx;
2992bf73ac6SHong Zhang       ierr = PetscTableFind(svtas[ita],gidx+1,&idx_to);CHKERRQ(ierr);
3002bf73ac6SHong Zhang 
3012bf73ac6SHong Zhang       if (idx_from || idx_to) { /* vfrom or vto is on table svtas[ita] */
3022bf73ac6SHong Zhang         idx_from--; idx_to--;
3032bf73ac6SHong Zhang         if (idx_from < 0) { /* vto is on svtas[ita] */
3042bf73ac6SHong Zhang           ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
3052bf73ac6SHong Zhang           break;
3062bf73ac6SHong Zhang         } else if (idx_to < 0) {
3072bf73ac6SHong Zhang           ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
3082bf73ac6SHong Zhang           break;
3092bf73ac6SHong Zhang         }
3102bf73ac6SHong Zhang       }
3112bf73ac6SHong Zhang     }
3122bf73ac6SHong Zhang 
3132bf73ac6SHong Zhang     if (ita == nta) {
3142bf73ac6SHong Zhang       ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr);
3152bf73ac6SHong Zhang       ierr = PetscMalloc1(2*Nsedgelist, &ta2sv[nta]);CHKERRQ(ierr);
3162bf73ac6SHong Zhang 
3172bf73ac6SHong Zhang       ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
3182bf73ac6SHong Zhang       ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
3192bf73ac6SHong Zhang       nta++;
3202bf73ac6SHong Zhang     }
3212bf73ac6SHong Zhang     k += 4;
3222bf73ac6SHong Zhang   }
3232bf73ac6SHong Zhang 
3242bf73ac6SHong Zhang   /* (2) Construct sedges from ctable
3252bf73ac6SHong Zhang      sedges: edges connect vertex sv[0]=(net[0],idx[0]) to vertices sv[k], k=1,...,n-1;
3264f5c2772SJose E. Roman      net[k], k=0, ...,n-1, are in ascending order */
3272bf73ac6SHong Zhang   ierr = PetscMalloc1(nta,&sedges);CHKERRQ(ierr);
3282bf73ac6SHong Zhang   for (nsv = 0; nsv < nta; nsv++) {
3294f5c2772SJose E. Roman     /* for a single svtx, put shared vertices in ascending order of gidx */
3304f5c2772SJose E. Roman     ierr = PetscTableGetCount(svtas[nsv],&n);CHKERRQ(ierr);
3312bf73ac6SHong Zhang     ierr = PetscCalloc1(2*n,&sv);CHKERRQ(ierr);
3322bf73ac6SHong Zhang     sedges[nsv].sv   = sv;
3332bf73ac6SHong Zhang     sedges[nsv].n    = n;
3342bf73ac6SHong Zhang     sedges[nsv].gidx = -1; /* initialization */
3352bf73ac6SHong Zhang 
3362bf73ac6SHong Zhang     ierr = PetscTableGetHeadPosition(svtas[nsv],&ppos);CHKERRQ(ierr);
3374f5c2772SJose E. Roman     for (k=0; k<n; k++) { /* gidx is sorted in ascending order */
3382bf73ac6SHong Zhang       ierr = PetscTableGetNext(svtas[nsv],&ppos,&gidx,&i);CHKERRQ(ierr);
3392bf73ac6SHong Zhang       gidx--; i--;
3402bf73ac6SHong Zhang 
3412bf73ac6SHong Zhang       j = ta2sv[nsv][i]; /* maps i to index of sv_wk */
3422bf73ac6SHong Zhang       sv[2*k]   = sv_wk[2*j];
3432bf73ac6SHong Zhang       sv[2*k+1] = sv_wk[2*j + 1];
3442bf73ac6SHong Zhang     }
3452bf73ac6SHong Zhang   }
3462bf73ac6SHong Zhang 
3472bf73ac6SHong Zhang   for (j=0; j<nta; j++) {
3482bf73ac6SHong Zhang     ierr = PetscTableDestroy(&svtas[j]);CHKERRQ(ierr);
3492bf73ac6SHong Zhang     ierr = PetscFree(ta2sv[j]);CHKERRQ(ierr);
3502bf73ac6SHong Zhang   }
3512bf73ac6SHong Zhang   ierr = PetscFree4(svtas,tdata,sv_wk,ta2sv);CHKERRQ(ierr);
3522bf73ac6SHong Zhang 
3532bf73ac6SHong Zhang   *Nsvtx = nta;
3542bf73ac6SHong Zhang   *svtx  = sedges;
3552bf73ac6SHong Zhang   PetscFunctionReturn(0);
3562bf73ac6SHong Zhang }
3572bf73ac6SHong Zhang 
3582bf73ac6SHong Zhang static PetscErrorCode DMNetworkLayoutSetUp_Coupling(DM dm)
3592bf73ac6SHong Zhang {
3602bf73ac6SHong Zhang   PetscErrorCode ierr;
3612bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
3622bf73ac6SHong Zhang   PetscInt       i,j,ctr,np,*edges,*subnetvtx,vStart;
3632bf73ac6SHong Zhang   PetscInt       k,*vidxlTog,Nsv=0,Nsubnet=network->Nsubnet;
3642bf73ac6SHong Zhang   PetscInt       *sedgelist=network->sedgelist;
3652bf73ac6SHong Zhang   const PetscInt *cone;
3662bf73ac6SHong Zhang   MPI_Comm       comm;
3672bf73ac6SHong Zhang   PetscMPIInt    size,rank,*recvcounts=NULL,*displs=NULL;
3682bf73ac6SHong Zhang   PetscInt       net,idx,gidx,nmerged,e,v,vfrom,vto,*vrange,*eowners,gidx_from,net_from,sv_idx;
3692bf73ac6SHong Zhang   SVtxType       svtype = SVNONE;
3702bf73ac6SHong Zhang   SVtx           *svtx=NULL;
3712bf73ac6SHong Zhang   PetscSection   sectiong;
3722bf73ac6SHong Zhang 
3732bf73ac6SHong Zhang   PetscFunctionBegin;
3742bf73ac6SHong Zhang   /* This implementation requires user input each subnet by a single processor, thus subnet[net].nvtx=subnet[net].Nvtx */
3752bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
3762bf73ac6SHong 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);
3772bf73ac6SHong Zhang   }
3782bf73ac6SHong Zhang 
3792bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
38055b25c41SPierre Jolivet   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
38155b25c41SPierre Jolivet   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
3822bf73ac6SHong Zhang 
3832bf73ac6SHong Zhang   /* (1) Create svtx[] from sedgelist */
3842bf73ac6SHong Zhang   /* -------------------------------- */
3852bf73ac6SHong Zhang   /* Nsv: global number of SVtx; svtx: shared vertices, see SVtx in dmnetworkimpl.h */
3862bf73ac6SHong Zhang   ierr = SVtxCreate(dm,network->Nsvtx,sedgelist,&Nsv,&svtx);CHKERRQ(ierr);
3872bf73ac6SHong Zhang 
3882bf73ac6SHong Zhang   /* (2) Setup svtx; Shared vto vertices are merged to their vfrom vertex with same global vetex index (gidx) */
3892bf73ac6SHong Zhang   /* -------------------------------------------------------------------------------------------------------- */
3902bf73ac6SHong Zhang   /* (2.1) compute vrage[rank]: global index of 1st local vertex in proc[rank] */
3912bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
3922bf73ac6SHong Zhang   for (i=0; i<size; i++) {displs[i] = i; recvcounts[i] = 1;}
3932bf73ac6SHong Zhang 
3942bf73ac6SHong Zhang   vrange[0] = 0;
3952bf73ac6SHong Zhang   ierr = MPI_Allgatherv(&network->nVertices,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
3962bf73ac6SHong Zhang   for (i=2; i<size+1; i++) {
3972bf73ac6SHong Zhang     vrange[i] += vrange[i-1];
3982bf73ac6SHong Zhang   }
3992bf73ac6SHong Zhang 
4002bf73ac6SHong Zhang   /* (2.2) Create vidxlTog: maps UN-MERGED local vertex index i to global index gidx (plex, excluding ghost vertices) */
4012bf73ac6SHong Zhang   ierr = PetscMalloc1(network->nVertices,&vidxlTog);CHKERRQ(ierr);
4022bf73ac6SHong Zhang   i = 0; gidx = 0;
4032bf73ac6SHong Zhang   nmerged = 0; /* local num of merged vertices */
4042bf73ac6SHong Zhang   network->nsvtx = 0;
4052bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
4062bf73ac6SHong Zhang     for (idx=0; idx<network->subnet[net].Nvtx; idx++) {
4072bf73ac6SHong Zhang       gidx_from = gidx;
4082bf73ac6SHong Zhang       sv_idx    = -1;
4092bf73ac6SHong Zhang 
4102bf73ac6SHong Zhang       ierr = SVtxSetUp(Nsv,svtx,net,idx,&gidx_from,&svtype,&sv_idx);CHKERRQ(ierr);
4112bf73ac6SHong Zhang       if (svtype == SVTO) {
4122bf73ac6SHong Zhang         if (network->subnet[net].nvtx) {/* this proc owns sv_to */
4132bf73ac6SHong Zhang           net_from = svtx[sv_idx].sv[0]; /* subnet num of its shared vertex */
4142bf73ac6SHong Zhang           if (network->subnet[net_from].nvtx == 0) {
4152bf73ac6SHong Zhang             /* this proc does not own v_from, thus a new local coupling vertex */
4162bf73ac6SHong Zhang             network->nsvtx++;
4172bf73ac6SHong Zhang           }
4182bf73ac6SHong Zhang           vidxlTog[i++] = gidx_from;
4192bf73ac6SHong Zhang           nmerged++; /* a coupling vertex -- merged */
4202bf73ac6SHong Zhang         }
4212bf73ac6SHong Zhang       } else {
4222bf73ac6SHong Zhang         if (svtype == SVFROM) {
4232bf73ac6SHong Zhang           if (network->subnet[net].nvtx) {
4242bf73ac6SHong Zhang             /* this proc owns this v_from, a new local coupling vertex */
4252bf73ac6SHong Zhang             network->nsvtx++;
4262bf73ac6SHong Zhang           }
4272bf73ac6SHong Zhang         }
4282bf73ac6SHong Zhang         if (network->subnet[net].nvtx) vidxlTog[i++] = gidx;
4292bf73ac6SHong Zhang         gidx++;
4302bf73ac6SHong Zhang       }
4312bf73ac6SHong Zhang     }
4322bf73ac6SHong Zhang   }
4332bf73ac6SHong Zhang #if defined(PETSC_USE_DEBUG)
4342bf73ac6SHong Zhang   if (i != network->nVertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"%D != %D nVertices",i,network->nVertices);
4352bf73ac6SHong Zhang #endif
4362bf73ac6SHong Zhang 
4372bf73ac6SHong Zhang   /* (2.3) Setup svtable for querry shared vertices */
4382bf73ac6SHong Zhang   for (v=0; v<Nsv; v++) {
4392bf73ac6SHong Zhang     gidx = svtx[v].gidx;
4402bf73ac6SHong Zhang     ierr = PetscTableAdd(network->svtable,gidx+1,v+1,INSERT_VALUES);CHKERRQ(ierr);
4412bf73ac6SHong Zhang   }
4422bf73ac6SHong Zhang 
4432bf73ac6SHong Zhang   /* (2.4) Shared vertices in the subnetworks are merged, update global NVertices: np = sum(local nmerged) */
4442bf73ac6SHong Zhang   ierr = MPI_Allreduce(&nmerged,&np,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
4452bf73ac6SHong Zhang   network->NVertices -= np;
4462bf73ac6SHong Zhang 
4472bf73ac6SHong Zhang   ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr);
4482bf73ac6SHong Zhang   ierr = PetscCalloc1(network->nVertices+network->nsvtx,&network->subnetvtx);CHKERRQ(ierr);
4492bf73ac6SHong Zhang 
4502bf73ac6SHong Zhang   ctr = 0;
4512bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
4522bf73ac6SHong Zhang     for (j = 0; j < network->subnet[net].nedge; j++) {
4532bf73ac6SHong Zhang       /* vfrom: */
4542bf73ac6SHong Zhang       i = network->subnet[net].edgelist[2*j] + (network->subnet[net].vStart - vrange[rank]);
4552bf73ac6SHong Zhang       edges[2*ctr] = vidxlTog[i];
4562bf73ac6SHong Zhang 
4572bf73ac6SHong Zhang       /* vto */
4582bf73ac6SHong Zhang       i = network->subnet[net].edgelist[2*j+1] + (network->subnet[net].vStart - vrange[rank]);
4592bf73ac6SHong Zhang       edges[2*ctr+1] = vidxlTog[i];
4602bf73ac6SHong Zhang       ctr++;
4612bf73ac6SHong Zhang     }
4622bf73ac6SHong Zhang   }
4632bf73ac6SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
4642bf73ac6SHong Zhang   ierr = PetscFree(vidxlTog);CHKERRQ(ierr);
4652bf73ac6SHong Zhang 
4662bf73ac6SHong Zhang   /* (3) Create network->plex */
4672bf73ac6SHong Zhang   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
4682bf73ac6SHong Zhang   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
4692bf73ac6SHong Zhang   ierr = DMSetDimension(network->plex,1);CHKERRQ(ierr);
4702bf73ac6SHong Zhang   if (size == 1) {
4712bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices-nmerged,2,edges);CHKERRQ(ierr);
4722bf73ac6SHong Zhang   } else {
4732bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices-nmerged,PETSC_DECIDE,2,edges,NULL);CHKERRQ(ierr);
4742bf73ac6SHong Zhang   }
4752bf73ac6SHong Zhang 
4762bf73ac6SHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
4772bf73ac6SHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
4782bf73ac6SHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
4792bf73ac6SHong Zhang   vStart = network->vStart;
4802bf73ac6SHong Zhang 
4812bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
4822bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
4832bf73ac6SHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
4842bf73ac6SHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
4852bf73ac6SHong Zhang 
4862bf73ac6SHong Zhang   np = network->pEnd - network->pStart;
4872bf73ac6SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
488*54dfd506SHong Zhang   for (i=0; i<np; i++) {
489*54dfd506SHong Zhang     network->header[i].maxcomps = 1;
490*54dfd506SHong Zhang     ierr = SetUpNetworkHeaderComponentValue(dm,&network->header[i],&network->cvalue[i]);CHKERRQ(ierr);
491*54dfd506SHong Zhang   }
4922bf73ac6SHong Zhang 
4932bf73ac6SHong Zhang   /* (4) Create vidxlTog: maps MERGED plex local vertex index (including ghosts) to User's global vertex index (without merging shared vertices) */
4942bf73ac6SHong Zhang   np = network->vEnd - vStart; /* include ghost vertices */
4952bf73ac6SHong Zhang   ierr = PetscMalloc2(np,&vidxlTog,size+1,&eowners);CHKERRQ(ierr);
4962bf73ac6SHong Zhang 
4972bf73ac6SHong Zhang   ctr = 0;
4982bf73ac6SHong Zhang   for (e=network->eStart; e<network->eEnd; e++) {
4992bf73ac6SHong Zhang     ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
5002bf73ac6SHong Zhang     vidxlTog[cone[0] - vStart] = edges[2*ctr];
5012bf73ac6SHong Zhang     vidxlTog[cone[1] - vStart] = edges[2*ctr+1];
5022bf73ac6SHong Zhang     ctr++;
5032bf73ac6SHong Zhang   }
5042bf73ac6SHong Zhang   ierr = PetscFree(edges);CHKERRQ(ierr);
5052bf73ac6SHong Zhang 
5062bf73ac6SHong Zhang   /* (5) Create vertices and edges array for the subnetworks */
5072bf73ac6SHong Zhang   subnetvtx = network->subnetvtx;
5082bf73ac6SHong Zhang   for (j=0; j < Nsubnet; j++) {
5092bf73ac6SHong Zhang     ierr = PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);CHKERRQ(ierr);
5102bf73ac6SHong Zhang     network->subnet[j].vertices = subnetvtx;
5112bf73ac6SHong Zhang     subnetvtx                  += network->subnet[j].nvtx;
5122bf73ac6SHong Zhang   }
5132bf73ac6SHong Zhang   network->svertices                = subnetvtx;
5142bf73ac6SHong Zhang 
5152bf73ac6SHong Zhang   /* Get edge ownership */
5162bf73ac6SHong Zhang   np = network->eEnd - network->eStart; /* num of local edges */
5172bf73ac6SHong Zhang   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr);
5182bf73ac6SHong Zhang   eowners[0] = 0;
5192bf73ac6SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
5202bf73ac6SHong Zhang 
5212bf73ac6SHong Zhang   e = 0;
5222bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
5232bf73ac6SHong Zhang     v = 0;
5242bf73ac6SHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
5252bf73ac6SHong Zhang 
5262bf73ac6SHong Zhang       /* edge e */
5272bf73ac6SHong Zhang       network->header[e].index    = e + eowners[rank]; /* Global edge index */
5282bf73ac6SHong Zhang       network->header[e].subnetid = i;                 /* Subnetwork id */
5292bf73ac6SHong Zhang       network->subnet[i].edges[j] = e;
5302bf73ac6SHong Zhang       network->header[e].ndata           = 0;
5312bf73ac6SHong Zhang       network->header[e].offset[0]       = 0;
5322bf73ac6SHong Zhang       network->header[e].offsetvarrel[0] = 0;
533*54dfd506SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,e,network->header[e].hsize);CHKERRQ(ierr);
5342bf73ac6SHong Zhang 
5352bf73ac6SHong Zhang       /* connected vertices */
5362bf73ac6SHong Zhang       ierr = DMPlexGetCone(network->plex,e,&cone);CHKERRQ(ierr);
5372bf73ac6SHong Zhang 
5382bf73ac6SHong Zhang       /* vertex cone[0] */
5392bf73ac6SHong Zhang       vfrom = network->subnet[i].edgelist[2*v];
5402bf73ac6SHong Zhang       network->header[cone[0]].index = vidxlTog[cone[0]-vStart]; /*  Global vertex index */
5412bf73ac6SHong Zhang       network->header[cone[0]].subnetid = i;                     /* Subnetwork id */
5422bf73ac6SHong Zhang       network->subnet[i].vertices[vfrom] = cone[0];              /* user's subnet[].dix = petsc's v */
5432bf73ac6SHong Zhang 
5442bf73ac6SHong Zhang       /* vertex cone[1] */
5452bf73ac6SHong Zhang       vto = network->subnet[i].edgelist[2*v+1];
5462bf73ac6SHong Zhang       network->header[cone[1]].index = vidxlTog[cone[1]-vStart]; /*  Global vertex index */
5472bf73ac6SHong Zhang       network->header[cone[1]].subnetid   = i;
5482bf73ac6SHong Zhang       network->subnet[i].vertices[vto]= cone[1];
5492bf73ac6SHong Zhang 
5502bf73ac6SHong Zhang       e++; v++;
5512bf73ac6SHong Zhang     }
5522bf73ac6SHong Zhang   }
5532bf73ac6SHong Zhang 
5542bf73ac6SHong Zhang   /* Set vertex array for the subnetworks */
5552bf73ac6SHong Zhang   k = 0;
5562bf73ac6SHong Zhang   for (v=vStart; v<network->vEnd; v++) { /* local vertices, including ghosts */
5572bf73ac6SHong Zhang     network->header[v].ndata           = 0;
5582bf73ac6SHong Zhang     network->header[v].offset[0]       = 0;
5592bf73ac6SHong Zhang     network->header[v].offsetvarrel[0] = 0;
560*54dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,v,network->header[v].hsize);CHKERRQ(ierr);
5612bf73ac6SHong Zhang 
5622bf73ac6SHong Zhang     /* shared vertex */
5632bf73ac6SHong Zhang     ierr = PetscTableFind(network->svtable,vidxlTog[v-vStart]+1,&i);CHKERRQ(ierr);
5642bf73ac6SHong Zhang     if (i) network->svertices[k++] = v;
5652bf73ac6SHong Zhang   }
5662bf73ac6SHong Zhang #if defined(PETSC_USE_DEBUG)
5672bf73ac6SHong Zhang   if (k != network->nsvtx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"k %D != %D nsvtx",k,network->nsvtx);
5682bf73ac6SHong Zhang #endif
5692bf73ac6SHong Zhang 
5702bf73ac6SHong Zhang   ierr = PetscFree2(vidxlTog,eowners);CHKERRQ(ierr);
5712bf73ac6SHong Zhang 
5722bf73ac6SHong Zhang   network->svtx  = svtx;
5732bf73ac6SHong Zhang   network->Nsvtx = Nsv;
5742bf73ac6SHong Zhang   ierr = PetscFree(sedgelist);CHKERRQ(ierr);
5752bf73ac6SHong Zhang 
5762bf73ac6SHong Zhang   /* Create a global section to be used by DMNetworkIsGhostVertex() which is a non-collective routine */
5772bf73ac6SHong Zhang   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
5785f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5795f2c45f1SShri Abhyankar }
5805f2c45f1SShri Abhyankar 
5815f2c45f1SShri Abhyankar /*@
5825f2c45f1SShri Abhyankar   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
5835f2c45f1SShri Abhyankar 
584d083f849SBarry Smith   Collective on dm
5855f2c45f1SShri Abhyankar 
5867a7aea1fSJed Brown   Input Parameters:
5875f2c45f1SShri Abhyankar . DM - the dmnetwork object
5885f2c45f1SShri Abhyankar 
5895f2c45f1SShri Abhyankar   Notes:
5905f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
5915f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
5925f2c45f1SShri Abhyankar 
5935f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
5945f2c45f1SShri Abhyankar 
59597bb938eSShri Abhyankar   Level: beginner
5965f2c45f1SShri Abhyankar 
5972bf73ac6SHong Zhang .seealso: DMNetworkSetNumSubNetworks(), DMNetworkAddSubnetwork()
5985f2c45f1SShri Abhyankar @*/
5995f2c45f1SShri Abhyankar PetscErrorCode DMNetworkLayoutSetUp(DM dm)
6005f2c45f1SShri Abhyankar {
6015f2c45f1SShri Abhyankar   PetscErrorCode ierr;
6025f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
6032bf73ac6SHong Zhang   PetscInt       i,j,ctr,Nsubnet=network->Nsubnet,*eowners,np,*edges,*subnetvtx;
6042bf73ac6SHong Zhang   PetscInt       e,v,vfrom,vto;
605caf410d2SHong Zhang   const PetscInt *cone;
606caf410d2SHong Zhang   MPI_Comm       comm;
607caf410d2SHong Zhang   PetscMPIInt    size,rank;
6086500d4abSHong Zhang 
6096500d4abSHong Zhang   PetscFunctionBegin;
6102bf73ac6SHong Zhang   if (network->nsubnet != network->Nsubnet) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Must call DMNetworkAddSubnetwork() %D times",network->Nsubnet);
6112bf73ac6SHong Zhang 
6122bf73ac6SHong Zhang   /* Create svtable for querry shared vertices */
6132bf73ac6SHong Zhang   ierr = PetscTableCreate(network->Nsvtx,network->NVertices+1,&network->svtable);CHKERRQ(ierr);
6142bf73ac6SHong Zhang 
6152bf73ac6SHong Zhang   if (network->Nsvtx) {
6162bf73ac6SHong Zhang     ierr = DMNetworkLayoutSetUp_Coupling(dm);CHKERRQ(ierr);
6172bf73ac6SHong Zhang     PetscFunctionReturn(0);
6182bf73ac6SHong Zhang   }
6192bf73ac6SHong Zhang 
620caf410d2SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
621ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
622ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
6236500d4abSHong Zhang 
6242bf73ac6SHong Zhang   /* Create LOCAL edgelist for the network by concatenating local input edgelists of the subnetworks */
6258e71b177SVaclav Hapla   ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr);
626caf410d2SHong Zhang   ctr = 0;
6272bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
6286500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
629ba38b151SHong Zhang       edges[2*ctr]   = network->subnet[i].vStart + network->subnet[i].edgelist[2*j];
630ba38b151SHong Zhang       edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1];
6316500d4abSHong Zhang       ctr++;
6326500d4abSHong Zhang     }
6336500d4abSHong Zhang   }
6347765340cSHong Zhang 
6352bf73ac6SHong Zhang   /* Create network->plex; One dimensional network, numCorners=2 */
6368e71b177SVaclav Hapla   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
6378e71b177SVaclav Hapla   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
6382bf73ac6SHong Zhang   ierr = DMSetDimension(network->plex,1);CHKERRQ(ierr);
639caf410d2SHong Zhang   if (size == 1) {
6402bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices,2,edges);CHKERRQ(ierr);
641caf410d2SHong Zhang   } else {
6422bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices,PETSC_DECIDE,2,edges,NULL);CHKERRQ(ierr);
643acdb140fSBarry Smith   }
6442bf73ac6SHong Zhang   ierr = PetscFree(edges);CHKERRQ(ierr); /* local edge list with global idx used by DMPlexBuildFromCellList() */
6456500d4abSHong Zhang 
6466500d4abSHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
6476500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
6486500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
6496500d4abSHong Zhang 
650caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
651caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
6526500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
6536500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
6546500d4abSHong Zhang 
655caf410d2SHong Zhang   np = network->pEnd - network->pStart;
656caf410d2SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
657*54dfd506SHong Zhang   for (i=0; i < np; i++) {
658*54dfd506SHong Zhang     network->header[i].maxcomps = 1;
659*54dfd506SHong Zhang     ierr = SetUpNetworkHeaderComponentValue(dm,&network->header[i],&network->cvalue[i]);CHKERRQ(ierr);
660*54dfd506SHong Zhang   }
661caf410d2SHong Zhang 
6622bf73ac6SHong Zhang   /* Create edge and vertex arrays for the subnetworks */
6632bf73ac6SHong Zhang   for (j=0; j < network->Nsubnet; j++) {
6646500d4abSHong Zhang     ierr = PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);CHKERRQ(ierr);
6656500d4abSHong Zhang   }
666caf410d2SHong Zhang 
667caf410d2SHong Zhang   /* Get edge ownership */
6682bf73ac6SHong Zhang   ierr = PetscMalloc1(size+1,&eowners);CHKERRQ(ierr);
669caf410d2SHong Zhang   np = network->eEnd - network->eStart;
670ffc4695bSBarry Smith   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr);
671caf410d2SHong Zhang   eowners[0] = 0;
672caf410d2SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
673caf410d2SHong Zhang 
674caf410d2SHong Zhang   /* Set network->subnet[*].vertices on array network->subnetvtx */
6752bf73ac6SHong Zhang   np = 0;
6762bf73ac6SHong Zhang   for (j=0; j<network->Nsubnet; j++) {
6772bf73ac6SHong Zhang     /* sum up subnet[j].Nvtx instead of subnet[j].nvtx, because a subnet might be owned by more than one processor;
6782bf73ac6SHong Zhang        below, subnet[i].vertices[vfrom/vto] requires vfrom/vto =0, ...,Nvtx-1
6792bf73ac6SHong Zhang      */
6802bf73ac6SHong Zhang     if (network->subnet[j].nvtx) np += network->subnet[j].Nvtx;
6812bf73ac6SHong Zhang   }
6822bf73ac6SHong Zhang 
6832bf73ac6SHong Zhang   ierr = PetscCalloc1(np,&network->subnetvtx);CHKERRQ(ierr); /* Maps local vertex to local subnetwork's vertex */
684caf410d2SHong Zhang   subnetvtx = network->subnetvtx;
6852bf73ac6SHong Zhang   for (j=0; j<network->Nsubnet; j++) {
686caf410d2SHong Zhang     network->subnet[j].vertices = subnetvtx;
6872bf73ac6SHong Zhang     if (network->subnet[j].nvtx) subnetvtx += network->subnet[j].Nvtx;
688caf410d2SHong Zhang   }
689caf410d2SHong Zhang 
6902bf73ac6SHong Zhang   /* Setup edge and vertex arrays for subnetworks */
6912bf73ac6SHong Zhang   e = 0;
6922bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
6932bf73ac6SHong Zhang     v = 0;
6942bf73ac6SHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
6952bf73ac6SHong Zhang       /* edge e */
6962bf73ac6SHong Zhang       network->header[e].index    = e + eowners[rank];   /* Global edge index */
6972bf73ac6SHong Zhang       network->header[e].subnetid = i;
6982bf73ac6SHong Zhang       network->subnet[i].edges[j] = e;
699caf410d2SHong Zhang 
7002bf73ac6SHong Zhang       network->header[e].ndata           = 0;
7012bf73ac6SHong Zhang       network->header[e].offset[0]       = 0;
7022bf73ac6SHong Zhang       network->header[e].offsetvarrel[0] = 0;
703*54dfd506SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,e,network->header[e].hsize);CHKERRQ(ierr);
7042bf73ac6SHong Zhang 
7052bf73ac6SHong Zhang       /* connected vertices */
7062bf73ac6SHong Zhang       ierr = DMPlexGetCone(network->plex,e,&cone);CHKERRQ(ierr);
7072bf73ac6SHong Zhang 
7082bf73ac6SHong Zhang       /* vertex cone[0] */
7092bf73ac6SHong Zhang       vfrom = network->subnet[i].edgelist[2*v];     /* =subnet[i].idx, Global index! */
7102bf73ac6SHong Zhang       network->header[cone[0]].index     = vfrom + network->subnet[i].vStart; /* Global vertex index */
7112bf73ac6SHong Zhang       network->header[cone[0]].subnetid  = i;       /* Subnetwork id */
7122bf73ac6SHong Zhang       network->subnet[i].vertices[vfrom] = cone[0]; /* user's subnet[].dix = petsc's v */
7132bf73ac6SHong Zhang 
7142bf73ac6SHong Zhang       /* vertex cone[1] */
7152bf73ac6SHong Zhang       vto   = network->subnet[i].edgelist[2*v+1];   /* =subnet[i].idx, Global index! */
7162bf73ac6SHong Zhang       network->header[cone[1]].index    = vto + network->subnet[i].vStart;  /* Global vertex index */
7172bf73ac6SHong Zhang       network->header[cone[1]].subnetid = i;
7182bf73ac6SHong Zhang       network->subnet[i].vertices[vto]  = cone[1];  /* user's subnet[].dix = petsc's v */
7192bf73ac6SHong Zhang 
7202bf73ac6SHong Zhang       e++; v++;
7216500d4abSHong Zhang     }
7226500d4abSHong Zhang   }
7232bf73ac6SHong Zhang   ierr = PetscFree(eowners);CHKERRQ(ierr);
724caf410d2SHong Zhang 
7252bf73ac6SHong Zhang   for (v = network->vStart; v < network->vEnd; v++) {
7262bf73ac6SHong Zhang     network->header[v].ndata           = 0;
7272bf73ac6SHong Zhang     network->header[v].offset[0]       = 0;
7282bf73ac6SHong Zhang     network->header[v].offsetvarrel[0] = 0;
729*54dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,v,network->header[e].hsize);CHKERRQ(ierr);
7306500d4abSHong Zhang   }
7315f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7325f2c45f1SShri Abhyankar }
7335f2c45f1SShri Abhyankar 
73494ef8ddeSSatish Balay /*@C
7352bf73ac6SHong Zhang   DMNetworkGetSubnetwork - Returns the information about a requested subnetwork
7362bf73ac6SHong Zhang 
7372bf73ac6SHong Zhang   Not collective
7382727e31bSShri Abhyankar 
7397a7aea1fSJed Brown   Input Parameters:
740caf410d2SHong Zhang + dm - the DM object
7412bf73ac6SHong Zhang - netnum - the global index of the subnetwork
7422727e31bSShri Abhyankar 
7437a7aea1fSJed Brown   Output Parameters:
7442727e31bSShri Abhyankar + nv - number of vertices (local)
7452727e31bSShri Abhyankar . ne - number of edges (local)
7462bf73ac6SHong Zhang . vtx - local vertices of the subnetwork
7472bf73ac6SHong Zhang - edge - local edges of the subnetwork
7482727e31bSShri Abhyankar 
7492727e31bSShri Abhyankar   Notes:
7502727e31bSShri Abhyankar   Cannot call this routine before DMNetworkLayoutSetup()
7512727e31bSShri Abhyankar 
75206dd6b0eSSatish Balay   Level: intermediate
75306dd6b0eSSatish Balay 
7542bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkLayoutSetUp()
7552727e31bSShri Abhyankar @*/
7562bf73ac6SHong Zhang PetscErrorCode DMNetworkGetSubnetwork(DM dm,PetscInt netnum,PetscInt *nv,PetscInt *ne,const PetscInt **vtx,const PetscInt **edge)
7572727e31bSShri Abhyankar {
758caf410d2SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
7592727e31bSShri Abhyankar 
7602727e31bSShri Abhyankar   PetscFunctionBegin;
7612bf73ac6SHong 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);
7622bf73ac6SHong Zhang   if (nv) *nv     = network->subnet[netnum].nvtx;
7632bf73ac6SHong Zhang   if (ne) *ne     = network->subnet[netnum].nedge;
7642bf73ac6SHong Zhang   if (vtx) *vtx   = network->subnet[netnum].vertices;
7652bf73ac6SHong Zhang   if (edge) *edge = network->subnet[netnum].edges;
7662bf73ac6SHong Zhang   PetscFunctionReturn(0);
7672bf73ac6SHong Zhang }
7682bf73ac6SHong Zhang 
7692bf73ac6SHong Zhang /*@
7702bf73ac6SHong Zhang   DMNetworkAddSharedVertices - Add shared vertices that connect two given subnetworks
7712bf73ac6SHong Zhang 
7722bf73ac6SHong Zhang   Collective on dm
7732bf73ac6SHong Zhang 
7742bf73ac6SHong Zhang   Input Parameters:
7752bf73ac6SHong Zhang + dm - the dm object
7762bf73ac6SHong Zhang . anetnum - first subnetwork global numbering returned by DMNetworkAddSubnetwork()
7772bf73ac6SHong Zhang . bnetnum - second subnetwork global numbering returned by DMNetworkAddSubnetwork()
7782bf73ac6SHong Zhang . nsvtx - number of vertices that are shared by the two subnetworks
7792bf73ac6SHong Zhang . asvtx - vertex index in the first subnetwork
7802bf73ac6SHong Zhang - bsvtx - vertex index in the second subnetwork
7812bf73ac6SHong Zhang 
7822bf73ac6SHong Zhang   Level: beginner
7832bf73ac6SHong Zhang 
7842bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkGetSharedVertices()
7852bf73ac6SHong Zhang @*/
7862bf73ac6SHong Zhang PetscErrorCode DMNetworkAddSharedVertices(DM dm,PetscInt anetnum,PetscInt bnetnum,PetscInt nsvtx,PetscInt asvtx[],PetscInt bsvtx[])
7872bf73ac6SHong Zhang {
7882bf73ac6SHong Zhang   PetscErrorCode ierr;
7892bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
7902bf73ac6SHong Zhang   PetscInt       i,nsubnet = network->Nsubnet,*sedgelist,Nsvtx=network->Nsvtx;
7912bf73ac6SHong Zhang 
7922bf73ac6SHong Zhang   PetscFunctionBegin;
7932bf73ac6SHong Zhang   if (anetnum == bnetnum) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Subnetworks must have different netnum");
7942bf73ac6SHong Zhang   if (anetnum < 0 || bnetnum < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"netnum cannot be negative");
7952bf73ac6SHong Zhang   if (!Nsvtx) {
7962bf73ac6SHong Zhang     /* allocate network->sedgelist to hold at most 2*nsubnet pairs of shared vertices */
7972bf73ac6SHong Zhang     ierr = PetscMalloc1(2*4*nsubnet,&network->sedgelist);CHKERRQ(ierr);
7982bf73ac6SHong Zhang   }
7992bf73ac6SHong Zhang 
8002bf73ac6SHong Zhang   sedgelist = network->sedgelist;
8012bf73ac6SHong Zhang   for (i=0; i<nsvtx; i++) {
8022bf73ac6SHong Zhang     sedgelist[4*Nsvtx]   = anetnum; sedgelist[4*Nsvtx+1] = asvtx[i];
8032bf73ac6SHong Zhang     sedgelist[4*Nsvtx+2] = bnetnum; sedgelist[4*Nsvtx+3] = bsvtx[i];
8042bf73ac6SHong Zhang     Nsvtx++;
8052bf73ac6SHong Zhang   }
8062bf73ac6SHong Zhang   if (Nsvtx > 2*nsubnet) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"allocate more space for coupling edgelist");
8072bf73ac6SHong Zhang   network->Nsvtx = Nsvtx;
8082727e31bSShri Abhyankar   PetscFunctionReturn(0);
8092727e31bSShri Abhyankar }
8102727e31bSShri Abhyankar 
8112727e31bSShri Abhyankar /*@C
8122bf73ac6SHong Zhang   DMNetworkGetSharedVertices - Returns the info for the shared vertices
8132bf73ac6SHong Zhang 
8142bf73ac6SHong Zhang   Not collective
815caf410d2SHong Zhang 
8167a7aea1fSJed Brown   Input Parameters:
8172bf73ac6SHong Zhang . dm - the DM object
818caf410d2SHong Zhang 
8197a7aea1fSJed Brown   Output Parameters:
8202bf73ac6SHong Zhang + nsv - number of local shared vertices
8212bf73ac6SHong Zhang - svtx - local shared vertices
822caf410d2SHong Zhang 
823caf410d2SHong Zhang   Notes:
824caf410d2SHong Zhang   Cannot call this routine before DMNetworkLayoutSetup()
825caf410d2SHong Zhang 
826caf410d2SHong Zhang   Level: intermediate
827caf410d2SHong Zhang 
8282bf73ac6SHong Zhang .seealso: DMNetworkGetSubnetwork(), DMNetworkLayoutSetUp(), DMNetworkAddSharedVertices()
829caf410d2SHong Zhang @*/
8302bf73ac6SHong Zhang PetscErrorCode DMNetworkGetSharedVertices(DM dm,PetscInt *nsv,const PetscInt **svtx)
831caf410d2SHong Zhang {
832caf410d2SHong Zhang   DM_Network *net = (DM_Network*)dm->data;
833caf410d2SHong Zhang 
834caf410d2SHong Zhang   PetscFunctionBegin;
8352bf73ac6SHong Zhang   if (net->Nsvtx) {
8362bf73ac6SHong Zhang     *nsv  = net->nsvtx;
8372bf73ac6SHong Zhang     *svtx = net->svertices;
83872c3e9f7SHong Zhang   } else {
8392bf73ac6SHong Zhang     *nsv  = 0;
8402bf73ac6SHong Zhang     *svtx = NULL;
84172c3e9f7SHong Zhang   }
842caf410d2SHong Zhang   PetscFunctionReturn(0);
843caf410d2SHong Zhang }
844caf410d2SHong Zhang 
845caf410d2SHong Zhang /*@C
8465f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
8475f2c45f1SShri Abhyankar 
848d083f849SBarry Smith   Logically collective on dm
8495f2c45f1SShri Abhyankar 
8507a7aea1fSJed Brown   Input Parameters:
8515f2c45f1SShri Abhyankar + dm - the network object
8525f2c45f1SShri Abhyankar . name - the component name
8535f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
8545f2c45f1SShri Abhyankar 
8557a7aea1fSJed Brown    Output Parameters:
8565f2c45f1SShri Abhyankar .  key - an integer key that defines the component
8575f2c45f1SShri Abhyankar 
8585f2c45f1SShri Abhyankar    Notes
8595f2c45f1SShri Abhyankar    This routine should be called by all processors before calling DMNetworkLayoutSetup().
8605f2c45f1SShri Abhyankar 
86197bb938eSShri Abhyankar    Level: beginner
8625f2c45f1SShri Abhyankar 
8632bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkLayoutSetUp()
8645f2c45f1SShri Abhyankar @*/
865caf410d2SHong Zhang PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key)
8665f2c45f1SShri Abhyankar {
8675f2c45f1SShri Abhyankar   PetscErrorCode        ierr;
8685f2c45f1SShri Abhyankar   DM_Network            *network = (DM_Network*) dm->data;
869*54dfd506SHong Zhang   DMNetworkComponent    *component=NULL,*newcomponent=NULL;
8705f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
8715f2c45f1SShri Abhyankar   PetscInt              i;
8725f2c45f1SShri Abhyankar 
8735f2c45f1SShri Abhyankar   PetscFunctionBegin;
874*54dfd506SHong Zhang   if (!network->component) {
875*54dfd506SHong Zhang     ierr = PetscCalloc1(network->max_comps_registered,&network->component);CHKERRQ(ierr);
876*54dfd506SHong Zhang   }
877*54dfd506SHong Zhang 
8785f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
879*54dfd506SHong Zhang     ierr = PetscStrcmp(network->component[i].name,name,&flg);CHKERRQ(ierr);
8805f2c45f1SShri Abhyankar     if (flg) {
8815f2c45f1SShri Abhyankar       *key = i;
8825f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
8835f2c45f1SShri Abhyankar     }
8846d64e262SShri Abhyankar   }
885*54dfd506SHong Zhang 
886*54dfd506SHong Zhang   if (network->ncomponent == network->max_comps_registered) {
887*54dfd506SHong Zhang     /* Reached max allowed so resize component */
888*54dfd506SHong Zhang     network->max_comps_registered += 2;
889*54dfd506SHong Zhang     ierr = PetscCalloc1(network->max_comps_registered,&newcomponent);CHKERRQ(ierr);
890*54dfd506SHong Zhang     /* Copy over the previous component info */
891*54dfd506SHong Zhang     for (i=0; i < network->ncomponent; i++) {
892*54dfd506SHong Zhang       ierr = PetscStrcpy(newcomponent[i].name,network->component[i].name);CHKERRQ(ierr);
893*54dfd506SHong Zhang       newcomponent[i].size = network->component[i].size;
8945f2c45f1SShri Abhyankar     }
895*54dfd506SHong Zhang     /* Free old one */
896*54dfd506SHong Zhang     ierr = PetscFree(network->component);CHKERRQ(ierr);
897*54dfd506SHong Zhang     /* Update pointer */
898*54dfd506SHong Zhang     network->component = newcomponent;
899*54dfd506SHong Zhang   }
900*54dfd506SHong Zhang 
901*54dfd506SHong Zhang   component = &network->component[network->ncomponent];
9025f2c45f1SShri Abhyankar 
9035f2c45f1SShri Abhyankar   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
9045f2c45f1SShri Abhyankar   component->size = size/sizeof(DMNetworkComponentGenericDataType);
9055f2c45f1SShri Abhyankar   *key = network->ncomponent;
9065f2c45f1SShri Abhyankar   network->ncomponent++;
9075f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9085f2c45f1SShri Abhyankar }
9095f2c45f1SShri Abhyankar 
9105f2c45f1SShri Abhyankar /*@
9112bf73ac6SHong Zhang   DMNetworkGetVertexRange - Get the bounds [start, end) for the local vertices
9125f2c45f1SShri Abhyankar 
9135f2c45f1SShri Abhyankar   Not Collective
9145f2c45f1SShri Abhyankar 
9155f2c45f1SShri Abhyankar   Input Parameters:
9162bf73ac6SHong Zhang . dm - the DMNetwork object
9175f2c45f1SShri Abhyankar 
918fd292e60Sprj-   Output Parameters:
9192bf73ac6SHong Zhang + vStart - the first vertex point
9202bf73ac6SHong Zhang - vEnd - one beyond the last vertex point
9215f2c45f1SShri Abhyankar 
92297bb938eSShri Abhyankar   Level: beginner
9235f2c45f1SShri Abhyankar 
9242bf73ac6SHong Zhang .seealso: DMNetworkGetEdgeRange()
9255f2c45f1SShri Abhyankar @*/
9265f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
9275f2c45f1SShri Abhyankar {
9285f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*)dm->data;
9295f2c45f1SShri Abhyankar 
9305f2c45f1SShri Abhyankar   PetscFunctionBegin;
9315f2c45f1SShri Abhyankar   if (vStart) *vStart = network->vStart;
9325f2c45f1SShri Abhyankar   if (vEnd) *vEnd = network->vEnd;
9335f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9345f2c45f1SShri Abhyankar }
9355f2c45f1SShri Abhyankar 
9365f2c45f1SShri Abhyankar /*@
9372bf73ac6SHong Zhang   DMNetworkGetEdgeRange - Get the bounds [start, end) for the local edges
9385f2c45f1SShri Abhyankar 
9395f2c45f1SShri Abhyankar   Not Collective
9405f2c45f1SShri Abhyankar 
9415f2c45f1SShri Abhyankar   Input Parameters:
9422bf73ac6SHong Zhang . dm - the DMNetwork object
9435f2c45f1SShri Abhyankar 
944fd292e60Sprj-   Output Parameters:
9455f2c45f1SShri Abhyankar + eStart - The first edge point
9465f2c45f1SShri Abhyankar - eEnd - One beyond the last edge point
9475f2c45f1SShri Abhyankar 
94897bb938eSShri Abhyankar   Level: beginner
9495f2c45f1SShri Abhyankar 
9502bf73ac6SHong Zhang .seealso: DMNetworkGetVertexRange()
9515f2c45f1SShri Abhyankar @*/
9525f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
9535f2c45f1SShri Abhyankar {
9545f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*)dm->data;
9555f2c45f1SShri Abhyankar 
9565f2c45f1SShri Abhyankar   PetscFunctionBegin;
9575f2c45f1SShri Abhyankar   if (eStart) *eStart = network->eStart;
9585f2c45f1SShri Abhyankar   if (eEnd) *eEnd = network->eEnd;
9595f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9605f2c45f1SShri Abhyankar }
9615f2c45f1SShri Abhyankar 
9622bf73ac6SHong Zhang static PetscErrorCode DMNetworkGetIndex(DM dm,PetscInt p,PetscInt *index)
9632bf73ac6SHong Zhang {
9642bf73ac6SHong Zhang   PetscErrorCode    ierr;
9652bf73ac6SHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
9662bf73ac6SHong Zhang   PetscInt          offsetp;
9672bf73ac6SHong Zhang   DMNetworkComponentHeader header;
9682bf73ac6SHong Zhang 
9692bf73ac6SHong Zhang   PetscFunctionBegin;
9702bf73ac6SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
9712bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
9722bf73ac6SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
9732bf73ac6SHong Zhang   *index = header->index;
9742bf73ac6SHong Zhang   PetscFunctionReturn(0);
9752bf73ac6SHong Zhang }
9762bf73ac6SHong Zhang 
9777b6afd5bSHong Zhang /*@
9782bf73ac6SHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the global numbering for the edge on the network
9797b6afd5bSHong Zhang 
9807b6afd5bSHong Zhang   Not Collective
9817b6afd5bSHong Zhang 
9827b6afd5bSHong Zhang   Input Parameters:
9837b6afd5bSHong Zhang + dm - DMNetwork object
984e85e6aecSHong Zhang - p - edge point
9857b6afd5bSHong Zhang 
986fd292e60Sprj-   Output Parameters:
9872bf73ac6SHong Zhang . index - the global numbering for the edge
9887b6afd5bSHong Zhang 
9897b6afd5bSHong Zhang   Level: intermediate
9907b6afd5bSHong Zhang 
9912bf73ac6SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
9927b6afd5bSHong Zhang @*/
993e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
9947b6afd5bSHong Zhang {
9957b6afd5bSHong Zhang   PetscErrorCode ierr;
9967b6afd5bSHong Zhang 
9977b6afd5bSHong Zhang   PetscFunctionBegin;
9982bf73ac6SHong Zhang   ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr);
9997b6afd5bSHong Zhang   PetscFunctionReturn(0);
10007b6afd5bSHong Zhang }
10017b6afd5bSHong Zhang 
10025f2c45f1SShri Abhyankar /*@
10032bf73ac6SHong Zhang   DMNetworkGetGlobalVertexIndex - Get the global numbering for the vertex on the network
1004e85e6aecSHong Zhang 
1005e85e6aecSHong Zhang   Not Collective
1006e85e6aecSHong Zhang 
1007e85e6aecSHong Zhang   Input Parameters:
1008e85e6aecSHong Zhang + dm - DMNetwork object
1009e85e6aecSHong Zhang - p  - vertex point
1010e85e6aecSHong Zhang 
1011fd292e60Sprj-   Output Parameters:
10122bf73ac6SHong Zhang . index - the global numbering for the vertex
1013e85e6aecSHong Zhang 
1014e85e6aecSHong Zhang   Level: intermediate
1015e85e6aecSHong Zhang 
10162bf73ac6SHong Zhang .seealso: DMNetworkGetGlobalEdgeIndex()
1017e85e6aecSHong Zhang @*/
1018e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
1019e85e6aecSHong Zhang {
1020e85e6aecSHong Zhang   PetscErrorCode ierr;
1021e85e6aecSHong Zhang 
1022e85e6aecSHong Zhang   PetscFunctionBegin;
10232bf73ac6SHong Zhang   ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr);
10249988b915SShri Abhyankar   PetscFunctionReturn(0);
10259988b915SShri Abhyankar }
10269988b915SShri Abhyankar 
10279988b915SShri Abhyankar /*@
10285f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
10295f2c45f1SShri Abhyankar 
10305f2c45f1SShri Abhyankar   Not Collective
10315f2c45f1SShri Abhyankar 
10325f2c45f1SShri Abhyankar   Input Parameters:
10332bf73ac6SHong Zhang + dm - the DMNetwork object
1034a2b725a8SWilliam Gropp - p - vertex/edge point
10355f2c45f1SShri Abhyankar 
10365f2c45f1SShri Abhyankar   Output Parameters:
10375f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
10385f2c45f1SShri Abhyankar 
103997bb938eSShri Abhyankar   Level: beginner
10405f2c45f1SShri Abhyankar 
10412bf73ac6SHong Zhang .seealso: DMNetworkRegisterComponent(), DMNetworkAddComponent()
10425f2c45f1SShri Abhyankar @*/
10435f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
10445f2c45f1SShri Abhyankar {
10455f2c45f1SShri Abhyankar   PetscErrorCode ierr;
10465f2c45f1SShri Abhyankar   PetscInt       offset;
10475f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10485f2c45f1SShri Abhyankar 
10495f2c45f1SShri Abhyankar   PetscFunctionBegin;
10505f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
10515f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
10525f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10535f2c45f1SShri Abhyankar }
10545f2c45f1SShri Abhyankar 
10555f2c45f1SShri Abhyankar /*@
10562bf73ac6SHong Zhang   DMNetworkGetLocalVecOffset - Get the offset for accessing the variables associated with a component at the given vertex/edge from the local vector
10575f2c45f1SShri Abhyankar 
10585f2c45f1SShri Abhyankar   Not Collective
10595f2c45f1SShri Abhyankar 
10605f2c45f1SShri Abhyankar   Input Parameters:
10612bf73ac6SHong Zhang + dm - the DMNetwork object
10627d928bffSSatish Balay . p - the edge/vertex point
10632bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
10649988b915SShri Abhyankar 
10659988b915SShri Abhyankar   Output Parameters:
10662bf73ac6SHong Zhang . offset - the local offset
10679988b915SShri Abhyankar 
10689988b915SShri Abhyankar   Level: intermediate
10699988b915SShri Abhyankar 
10702bf73ac6SHong Zhang .seealso: DMGetLocalVector(), DMNetworkGetComponent(), DMNetworkGetGlobalVecOffset()
10719988b915SShri Abhyankar @*/
10722bf73ac6SHong Zhang PetscErrorCode DMNetworkGetLocalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offset)
10739988b915SShri Abhyankar {
10749988b915SShri Abhyankar   PetscErrorCode ierr;
10759988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10769988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
10779988b915SShri Abhyankar   DMNetworkComponentHeader header;
10789988b915SShri Abhyankar 
10799988b915SShri Abhyankar   PetscFunctionBegin;
10802bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->localSection,p,&offsetp);CHKERRQ(ierr);
10812bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
10822bf73ac6SHong Zhang     *offset = offsetp;
10832bf73ac6SHong Zhang     PetscFunctionReturn(0);
10842bf73ac6SHong Zhang   }
10852bf73ac6SHong Zhang 
10869988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
10879988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
10889988b915SShri Abhyankar   *offset = offsetp + header->offsetvarrel[compnum];
10899988b915SShri Abhyankar   PetscFunctionReturn(0);
10909988b915SShri Abhyankar }
10919988b915SShri Abhyankar 
10929988b915SShri Abhyankar /*@
10932bf73ac6SHong Zhang   DMNetworkGetGlobalVecOffset - Get the global offset for accessing the variables associated with a component for the given vertex/edge from the global vector
10949988b915SShri Abhyankar 
10959988b915SShri Abhyankar   Not Collective
10969988b915SShri Abhyankar 
10979988b915SShri Abhyankar   Input Parameters:
10982bf73ac6SHong Zhang + dm - the DMNetwork object
10997d928bffSSatish Balay . p - the edge/vertex point
11002bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
11019988b915SShri Abhyankar 
11029988b915SShri Abhyankar   Output Parameters:
11039988b915SShri Abhyankar . offsetg - the global offset
11049988b915SShri Abhyankar 
11059988b915SShri Abhyankar   Level: intermediate
11069988b915SShri Abhyankar 
11072bf73ac6SHong Zhang .seealso: DMNetworkGetLocalVecOffset(), DMGetGlobalVector(), DMNetworkGetComponent()
11089988b915SShri Abhyankar @*/
11092bf73ac6SHong Zhang PetscErrorCode DMNetworkGetGlobalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offsetg)
11109988b915SShri Abhyankar {
11119988b915SShri Abhyankar   PetscErrorCode ierr;
11129988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11139988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
11149988b915SShri Abhyankar   DMNetworkComponentHeader header;
11159988b915SShri Abhyankar 
11169988b915SShri Abhyankar   PetscFunctionBegin;
11172bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->globalSection,p,&offsetp);CHKERRQ(ierr);
11182bf73ac6SHong Zhang   if (offsetp < 0) offsetp = -(offsetp + 1); /* Convert to actual global offset for ghost vertex */
11192bf73ac6SHong Zhang 
11202bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
11212bf73ac6SHong Zhang     *offsetg = offsetp;
11222bf73ac6SHong Zhang     PetscFunctionReturn(0);
11232bf73ac6SHong Zhang   }
11249988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
11259988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
11269988b915SShri Abhyankar   *offsetg = offsetp + header->offsetvarrel[compnum];
11279988b915SShri Abhyankar   PetscFunctionReturn(0);
11289988b915SShri Abhyankar }
11299988b915SShri Abhyankar 
11309988b915SShri Abhyankar /*@
11312bf73ac6SHong Zhang   DMNetworkGetEdgeOffset - Get the offset for accessing the variables associated with the given edge from the local subvector
113224121865SAdrian Maldonado 
113324121865SAdrian Maldonado   Not Collective
113424121865SAdrian Maldonado 
113524121865SAdrian Maldonado   Input Parameters:
11362bf73ac6SHong Zhang + dm - the DMNetwork object
113724121865SAdrian Maldonado - p - the edge point
113824121865SAdrian Maldonado 
113924121865SAdrian Maldonado   Output Parameters:
114024121865SAdrian Maldonado . offset - the offset
114124121865SAdrian Maldonado 
114224121865SAdrian Maldonado   Level: intermediate
114324121865SAdrian Maldonado 
11442bf73ac6SHong Zhang .seealso: DMNetworkGetLocalVecOffset(), DMGetLocalVector()
114524121865SAdrian Maldonado @*/
114624121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
114724121865SAdrian Maldonado {
114824121865SAdrian Maldonado   PetscErrorCode ierr;
114924121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
115024121865SAdrian Maldonado 
115124121865SAdrian Maldonado   PetscFunctionBegin;
115224121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
115324121865SAdrian Maldonado   PetscFunctionReturn(0);
115424121865SAdrian Maldonado }
115524121865SAdrian Maldonado 
115624121865SAdrian Maldonado /*@
11572bf73ac6SHong Zhang   DMNetworkGetVertexOffset - Get the offset for accessing the variables associated with the given vertex from the local subvector
115824121865SAdrian Maldonado 
115924121865SAdrian Maldonado   Not Collective
116024121865SAdrian Maldonado 
116124121865SAdrian Maldonado   Input Parameters:
11622bf73ac6SHong Zhang + dm - the DMNetwork object
116324121865SAdrian Maldonado - p - the vertex point
116424121865SAdrian Maldonado 
116524121865SAdrian Maldonado   Output Parameters:
116624121865SAdrian Maldonado . offset - the offset
116724121865SAdrian Maldonado 
116824121865SAdrian Maldonado   Level: intermediate
116924121865SAdrian Maldonado 
11702bf73ac6SHong Zhang .seealso: DMNetworkGetEdgeOffset(), DMGetLocalVector()
117124121865SAdrian Maldonado @*/
117224121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
117324121865SAdrian Maldonado {
117424121865SAdrian Maldonado   PetscErrorCode ierr;
117524121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
117624121865SAdrian Maldonado 
117724121865SAdrian Maldonado   PetscFunctionBegin;
117824121865SAdrian Maldonado   p -= network->vStart;
117924121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
118024121865SAdrian Maldonado   PetscFunctionReturn(0);
118124121865SAdrian Maldonado }
11822bf73ac6SHong Zhang 
11835f2c45f1SShri Abhyankar /*@
11842bf73ac6SHong Zhang   DMNetworkAddComponent - Adds a network component and number of variables at the given point (vertex/edge)
11855f2c45f1SShri Abhyankar 
11865f2c45f1SShri Abhyankar   Not Collective
11875f2c45f1SShri Abhyankar 
11885f2c45f1SShri Abhyankar   Input Parameters:
11894dc646bcSBarry Smith + dm - the DMNetwork
11905f2c45f1SShri Abhyankar . p - the vertex/edge point
11912bf73ac6SHong Zhang . componentkey - component key returned while registering the component; ignored if compvalue=NULL
11922bf73ac6SHong Zhang . compvalue - pointer to the data structure for the component, or NULL if not required.
11932bf73ac6SHong Zhang - nvar - number of variables for the component at the vertex/edge point
11945f2c45f1SShri Abhyankar 
119597bb938eSShri Abhyankar   Level: beginner
11965f2c45f1SShri Abhyankar 
11972bf73ac6SHong Zhang .seealso: DMNetworkGetComponent()
11985f2c45f1SShri Abhyankar @*/
11992bf73ac6SHong Zhang PetscErrorCode DMNetworkAddComponent(DM dm,PetscInt p,PetscInt componentkey,void* compvalue,PetscInt nvar)
12005f2c45f1SShri Abhyankar {
12015f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
12025f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
12032bf73ac6SHong Zhang   DMNetworkComponent       *component = &network->component[componentkey];
1204*54dfd506SHong Zhang   DMNetworkComponentHeader header;
1205*54dfd506SHong Zhang   DMNetworkComponentValue  cvalue;
12062bf73ac6SHong Zhang   PetscBool                sharedv=PETSC_FALSE;
1207*54dfd506SHong Zhang   PetscInt                 compnum;
1208*54dfd506SHong Zhang   PetscInt                 *compsize,*compkey,*compoffset,*compnvar,*compoffsetvarrel;
1209*54dfd506SHong Zhang   void*                    *compdata;
12105f2c45f1SShri Abhyankar 
12115f2c45f1SShri Abhyankar   PetscFunctionBegin;
12125f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
12132bf73ac6SHong Zhang   if (!compvalue) PetscFunctionReturn(0);
12142bf73ac6SHong Zhang 
12152bf73ac6SHong Zhang   ierr = DMNetworkIsSharedVertex(dm,p,&sharedv);CHKERRQ(ierr);
12162bf73ac6SHong Zhang   if (sharedv) {
12172bf73ac6SHong Zhang     PetscBool ghost;
12182bf73ac6SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
12192bf73ac6SHong Zhang     if (ghost) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adding a component at a leaf(ghost) shared vertex is not supported");
12202bf73ac6SHong Zhang   }
12212bf73ac6SHong Zhang 
1222*54dfd506SHong Zhang   header = &network->header[p];
1223*54dfd506SHong Zhang   cvalue = &network->cvalue[p];
1224*54dfd506SHong Zhang   if (header->ndata == header->maxcomps) {
1225*54dfd506SHong Zhang     /* Reached limit so resize header component arrays */
1226*54dfd506SHong Zhang     header->maxcomps += 2;
1227*54dfd506SHong Zhang 
1228*54dfd506SHong Zhang     /* Allocate arrays for component information and value */
1229*54dfd506SHong Zhang     ierr = PetscCalloc5(header->maxcomps,&compsize,header->maxcomps,&compkey,header->maxcomps,&compoffset,header->maxcomps,&compnvar,header->maxcomps,&compoffsetvarrel);CHKERRQ(ierr);
1230*54dfd506SHong Zhang     ierr = PetscMalloc1(header->maxcomps,&compdata);CHKERRQ(ierr);
1231*54dfd506SHong Zhang 
1232*54dfd506SHong Zhang     /* Recalculate header size */
1233*54dfd506SHong Zhang     header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt);
1234*54dfd506SHong Zhang 
1235*54dfd506SHong Zhang     header->hsize /= sizeof(DMNetworkComponentGenericDataType);
1236*54dfd506SHong Zhang 
1237*54dfd506SHong Zhang     /* Copy over component info */
1238*54dfd506SHong Zhang     ierr = PetscMemcpy(compsize,header->size,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
1239*54dfd506SHong Zhang     ierr = PetscMemcpy(compkey,header->key,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
1240*54dfd506SHong Zhang     ierr = PetscMemcpy(compoffset,header->offset,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
1241*54dfd506SHong Zhang     ierr = PetscMemcpy(compnvar,header->nvar,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
1242*54dfd506SHong Zhang     ierr = PetscMemcpy(compoffsetvarrel,header->offsetvarrel,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
1243*54dfd506SHong Zhang 
1244*54dfd506SHong Zhang     /* Copy over component data pointers */
1245*54dfd506SHong Zhang     ierr = PetscMemcpy(compdata,cvalue->data,header->ndata*sizeof(void*));CHKERRQ(ierr);
1246*54dfd506SHong Zhang 
1247*54dfd506SHong Zhang     /* Free old arrays */
1248*54dfd506SHong Zhang     ierr = PetscFree5(header->size,header->key,header->offset,header->nvar,header->offsetvarrel);CHKERRQ(ierr);
1249*54dfd506SHong Zhang     ierr = PetscFree(cvalue->data);CHKERRQ(ierr);
1250*54dfd506SHong Zhang 
1251*54dfd506SHong Zhang     /* Update pointers */
1252*54dfd506SHong Zhang     header->size = compsize;
1253*54dfd506SHong Zhang     header->key  = compkey;
1254*54dfd506SHong Zhang     header->offset = compoffset;
1255*54dfd506SHong Zhang     header->nvar = compnvar;
1256*54dfd506SHong Zhang     header->offsetvarrel = compoffsetvarrel;
1257*54dfd506SHong Zhang 
1258*54dfd506SHong Zhang     cvalue->data = compdata;
1259*54dfd506SHong Zhang 
1260*54dfd506SHong Zhang     /* Update DataSection Dofs */
1261*54dfd506SHong Zhang     /* The dofs for datasection point p equals sizeof the header (i.e. header->hsize) + sizes of the components added at point p. With the resizing of the header, we need to update the dofs for point p. Hence, we add the extra size added for the header */
1262*54dfd506SHong Zhang     PetscInt additional_size = (5*(header->maxcomps - header->ndata)*sizeof(PetscInt))/sizeof(DMNetworkComponentGenericDataType);
1263*54dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,p,additional_size);CHKERRQ(ierr);
1264*54dfd506SHong Zhang   }
1265*54dfd506SHong Zhang   header = &network->header[p];
1266*54dfd506SHong Zhang   cvalue = &network->cvalue[p];
1267*54dfd506SHong Zhang 
1268*54dfd506SHong Zhang   compnum = header->ndata;
12692bf73ac6SHong Zhang 
12702bf73ac6SHong Zhang   header->size[compnum] = component->size;
12712bf73ac6SHong Zhang   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
12722bf73ac6SHong Zhang   header->key[compnum] = componentkey;
12732bf73ac6SHong Zhang   if (compnum != 0) header->offset[compnum] = header->offset[compnum-1] + header->size[compnum-1];
12742bf73ac6SHong Zhang   cvalue->data[compnum] = (void*)compvalue;
12752bf73ac6SHong Zhang 
12762bf73ac6SHong Zhang   /* variables */
12772bf73ac6SHong Zhang   header->nvar[compnum] += nvar;
12782bf73ac6SHong Zhang   if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum-1] + header->nvar[compnum-1];
12792bf73ac6SHong Zhang 
12802bf73ac6SHong Zhang   header->ndata++;
12815f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
12825f2c45f1SShri Abhyankar }
12835f2c45f1SShri Abhyankar 
128427f51fceSHong Zhang /*@
12852bf73ac6SHong Zhang   DMNetworkGetComponent - Gets the component key, the component data, and the number of variables at a given network point
128627f51fceSHong Zhang 
128727f51fceSHong Zhang   Not Collective
128827f51fceSHong Zhang 
128927f51fceSHong Zhang   Input Parameters:
12902bf73ac6SHong Zhang + dm - the DMNetwork object
12912bf73ac6SHong Zhang . p - vertex/edge point
129299c90e12SSatish Balay - compnum - component number; use ALL_COMPONENTS if sum up all the components
129327f51fceSHong Zhang 
129427f51fceSHong Zhang   Output Parameters:
12952bf73ac6SHong Zhang + compkey - the key obtained when registering the component (use NULL if not required)
12962bf73ac6SHong Zhang . component - the component data (use NULL if not required)
12972bf73ac6SHong Zhang - nvar  - number of variables (use NULL if not required)
129827f51fceSHong Zhang 
129997bb938eSShri Abhyankar   Level: beginner
130027f51fceSHong Zhang 
13012bf73ac6SHong Zhang .seealso: DMNetworkAddComponent(), DMNetworkGetNumComponents()
130227f51fceSHong Zhang @*/
13032bf73ac6SHong Zhang PetscErrorCode DMNetworkGetComponent(DM dm,PetscInt p,PetscInt compnum,PetscInt *compkey,void **component,PetscInt *nvar)
130427f51fceSHong Zhang {
130527f51fceSHong Zhang   PetscErrorCode ierr;
130627f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
13072bf73ac6SHong Zhang   PetscInt       offset = 0;
13082bf73ac6SHong Zhang   DMNetworkComponentHeader header;
130927f51fceSHong Zhang 
131027f51fceSHong Zhang   PetscFunctionBegin;
13112bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
131227f51fceSHong Zhang     ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
131327f51fceSHong Zhang     PetscFunctionReturn(0);
131427f51fceSHong Zhang   }
131527f51fceSHong Zhang 
13162bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
13172bf73ac6SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);CHKERRQ(ierr);
13185f2c45f1SShri Abhyankar 
13192bf73ac6SHong Zhang   if (compnum >= 0) {
13202bf73ac6SHong Zhang     if (compkey) *compkey = header->key[compnum];
13212bf73ac6SHong Zhang     if (component) {
1322*54dfd506SHong Zhang       offset += header->hsize+header->offset[compnum];
13232bf73ac6SHong Zhang       *component = network->componentdataarray+offset;
13242bf73ac6SHong Zhang     }
13252bf73ac6SHong Zhang   }
13265f2c45f1SShri Abhyankar 
13272bf73ac6SHong Zhang   if (nvar) *nvar = header->nvar[compnum];
1328*54dfd506SHong Zhang 
13295f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13305f2c45f1SShri Abhyankar }
13315f2c45f1SShri Abhyankar 
13322bf73ac6SHong Zhang /*
13332bf73ac6SHong Zhang  Sets up the array that holds the data for all components and its associated section.
13342bf73ac6SHong 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.
13352bf73ac6SHong Zhang */
13365f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
13375f2c45f1SShri Abhyankar {
13385f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
13395f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
1340e53b5ba3SHong Zhang   PetscInt                 arr_size,p,offset,offsetp,ncomp,i;
13412bf73ac6SHong Zhang   MPI_Comm                 comm;
13422bf73ac6SHong Zhang   PetscMPIInt              size,rank;
13435f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
13445f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
13455f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
13465f2c45f1SShri Abhyankar 
13475f2c45f1SShri Abhyankar   PetscFunctionBegin;
13482bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
13492bf73ac6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
13502bf73ac6SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
13512bf73ac6SHong Zhang #if 0
13522bf73ac6SHong Zhang   //------------- new
13532bf73ac6SHong Zhang   if (size > 1) { /* Sync nvar at shared vertices for all processes */
13542bf73ac6SHong Zhang     PetscSF        sf = network->plex->sf;
13552bf73ac6SHong Zhang     const PetscInt *degree;
13562bf73ac6SHong Zhang     PetscInt       i,nleaves_total,*indata,*outdata,nroots,nleaves,nsv,p,ncomp;
13572bf73ac6SHong Zhang     const PetscInt *svtx;
13582bf73ac6SHong Zhang     PetscBool      ghost;
13592bf73ac6SHong Zhang 
13602bf73ac6SHong Zhang     ierr = PetscSFGetGraph(sf,&nroots,&nleaves,NULL,NULL);CHKERRQ(ierr);
13612bf73ac6SHong Zhang     ierr = PetscSFComputeDegreeBegin(sf,&degree);CHKERRQ(ierr);
13622bf73ac6SHong Zhang     ierr = PetscSFComputeDegreeEnd(sf,&degree);CHKERRQ(ierr);
13632bf73ac6SHong Zhang     nleaves_total=0;
13642bf73ac6SHong Zhang     for (i=0; i<nroots; i++) nleaves_total += degree[i];
13652bf73ac6SHong Zhang     printf("[%d] nleaves_total %d\n",rank,nleaves_total);
13662bf73ac6SHong Zhang     MPI_Barrier(comm);
13672bf73ac6SHong Zhang 
13682bf73ac6SHong Zhang     ierr = PetscCalloc2(nleaves_total,&indata,nleaves,&outdata);CHKERRQ(ierr);
13692bf73ac6SHong Zhang 
13702bf73ac6SHong Zhang     /* Leaves copy user's ncomp to outdata */
13712bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nsv,&svtx);CHKERRQ(ierr);
13722bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
13732bf73ac6SHong Zhang       p = svtx[i];
13742bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
13752bf73ac6SHong Zhang       if (!ghost) continue;
13762bf73ac6SHong Zhang 
13772bf73ac6SHong Zhang       header = &network->header[p];
13782bf73ac6SHong Zhang       ncomp = header->ndata;
13792bf73ac6SHong Zhang       printf("[%d] leaf has ncomp %d\n",rank,ncomp);
13802bf73ac6SHong Zhang       outdata[p] = ncomp;
13812bf73ac6SHong Zhang     }
13822bf73ac6SHong Zhang 
13832bf73ac6SHong Zhang     /* Roots gather ncomp from leaves */
13842bf73ac6SHong Zhang     ierr = PetscSFGatherBegin(sf,MPIU_INT,outdata,indata);CHKERRQ(ierr);
13852bf73ac6SHong Zhang     ierr = PetscSFGatherEnd(sf,MPIU_INT,outdata,indata);CHKERRQ(ierr);
13862bf73ac6SHong Zhang     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Gathered data at multi-roots from leaves\n");CHKERRQ(ierr);
13872bf73ac6SHong Zhang     ierr = PetscIntView(nleaves_total,indata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
13882bf73ac6SHong Zhang 
13892bf73ac6SHong Zhang     ierr = PetscFree2(indata,outdata);CHKERRQ(ierr);
13902bf73ac6SHong Zhang   }
13912bf73ac6SHong Zhang   //----------------------
13922bf73ac6SHong Zhang #endif
13932bf73ac6SHong Zhang 
13945f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
13955f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
1396*54dfd506SHong Zhang   ierr = PetscCalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
13975f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
13985f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
13995f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
14005f2c45f1SShri Abhyankar     /* Copy header */
14015f2c45f1SShri Abhyankar     header = &network->header[p];
1402*54dfd506SHong Zhang     DMNetworkComponentHeader headerinfo=(DMNetworkComponentHeader)(componentdataarray+offsetp);
1403*54dfd506SHong Zhang     ierr = PetscMemcpy(headerinfo,header,sizeof(struct _p_DMNetworkComponentHeader));CHKERRQ(ierr);
1404*54dfd506SHong Zhang     PetscInt *headerarr = (PetscInt*)(headerinfo+1);
1405*54dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->size,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
1406*54dfd506SHong Zhang     headerarr += header->maxcomps;
1407*54dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->key,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
1408*54dfd506SHong Zhang     headerarr += header->maxcomps;
1409*54dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offset,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
1410*54dfd506SHong Zhang     headerarr += header->maxcomps;
1411*54dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->nvar,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
1412*54dfd506SHong Zhang     headerarr += header->maxcomps;
1413*54dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offsetvarrel,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
1414*54dfd506SHong Zhang 
14155f2c45f1SShri Abhyankar     /* Copy data */
14165f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
14175f2c45f1SShri Abhyankar     ncomp  = header->ndata;
14182bf73ac6SHong Zhang 
14195f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
1420*54dfd506SHong Zhang       offset = offsetp + header->hsize + header->offset[i];
1421302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
14225f2c45f1SShri Abhyankar     }
14235f2c45f1SShri Abhyankar   }
14245f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14255f2c45f1SShri Abhyankar }
14265f2c45f1SShri Abhyankar 
14275f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
14282bf73ac6SHong Zhang static PetscErrorCode DMNetworkVariablesSetUp(DM dm)
14295f2c45f1SShri Abhyankar {
14305f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14315f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14322bf73ac6SHong Zhang   MPI_Comm       comm;
14332bf73ac6SHong Zhang   PetscMPIInt    size;
14345f2c45f1SShri Abhyankar 
14355f2c45f1SShri Abhyankar   PetscFunctionBegin;
14362bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
14372bf73ac6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
14382bf73ac6SHong Zhang 
14392bf73ac6SHong Zhang   if (size > 1) { /* Sync nvar at shared vertices for all processes */
14402bf73ac6SHong Zhang     PetscSF           sf = network->plex->sf;
14412bf73ac6SHong Zhang     PetscInt          *local_nvar, *remote_nvar,nroots,nleaves,p=-1,i,nsv;
14422bf73ac6SHong Zhang     const PetscInt    *svtx;
14432bf73ac6SHong Zhang     PetscBool         ghost;
14442bf73ac6SHong Zhang     /*
14452bf73ac6SHong Zhang      PetscMPIInt       rank;
14462bf73ac6SHong Zhang      const PetscInt    *ilocal;
14472bf73ac6SHong Zhang      const PetscSFNode *iremote;
14482bf73ac6SHong Zhang      ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
14492bf73ac6SHong Zhang      ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
14502bf73ac6SHong Zhang     */
14512bf73ac6SHong Zhang     ierr = PetscSFGetGraph(sf,&nroots,&nleaves,NULL,NULL);CHKERRQ(ierr);
14522bf73ac6SHong Zhang     ierr = PetscCalloc2(nroots,&local_nvar,nroots,&remote_nvar);CHKERRQ(ierr);
14532bf73ac6SHong Zhang 
14542bf73ac6SHong Zhang     /* Leaves copy user's nvar to local_nvar */
14552bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nsv,&svtx);CHKERRQ(ierr);
14562bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
14572bf73ac6SHong Zhang       p = svtx[i];
14582bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
14592bf73ac6SHong Zhang       if (!ghost) continue;
14602bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
14612bf73ac6SHong Zhang       /* printf("[%d] Before SFReduce: leaf local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
14622bf73ac6SHong Zhang     }
14632bf73ac6SHong Zhang 
14642bf73ac6SHong Zhang     /* Leaves add local_nvar to root remote_nvar */
14652bf73ac6SHong Zhang     ierr = PetscSFReduceBegin(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
14662bf73ac6SHong Zhang     ierr = PetscSFReduceEnd(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
14672bf73ac6SHong Zhang     /* printf("[%d] remote_nvar[%d] = %d\n",rank,p,remote_nvar[p]); */
14682bf73ac6SHong Zhang 
14692bf73ac6SHong Zhang     /* Update roots' local_nvar */
14702bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
14712bf73ac6SHong Zhang       p = svtx[i];
14722bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
14732bf73ac6SHong Zhang       if (ghost) continue;
14742bf73ac6SHong Zhang 
14752bf73ac6SHong Zhang       ierr = PetscSectionAddDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
14762bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
14772bf73ac6SHong Zhang       /* printf("[%d]  After SFReduce: root local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
14782bf73ac6SHong Zhang     }
14792bf73ac6SHong Zhang 
14802bf73ac6SHong Zhang     /* Roots Bcast nvar to leaves */
1481ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
1482ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
14832bf73ac6SHong Zhang 
14842bf73ac6SHong Zhang     /* Leaves reset receved/remote nvar to dm */
14852bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
14862bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
14872bf73ac6SHong Zhang       if (!ghost) continue;
14882bf73ac6SHong Zhang       p = svtx[i];
14892bf73ac6SHong Zhang       /* printf("[%d] leaf reset nvar %d at p= %d \n",rank,remote_nvar[p],p); */
14902bf73ac6SHong Zhang       /* DMNetworkSetNumVariables(dm,p,remote_nvar[p]) */
14912bf73ac6SHong Zhang       ierr = PetscSectionSetDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
14922bf73ac6SHong Zhang     }
14932bf73ac6SHong Zhang 
14942bf73ac6SHong Zhang     ierr = PetscFree2(local_nvar,remote_nvar);CHKERRQ(ierr);
14952bf73ac6SHong Zhang   }
14962bf73ac6SHong Zhang 
14975f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
14985f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14995f2c45f1SShri Abhyankar }
15005f2c45f1SShri Abhyankar 
150124121865SAdrian Maldonado /* Get a subsection from a range of points */
15029dddd249SSatish Balay static PetscErrorCode DMNetworkGetSubSection_private(PetscSection main,PetscInt pstart,PetscInt pend,PetscSection *subsection)
150324121865SAdrian Maldonado {
150424121865SAdrian Maldonado   PetscErrorCode ierr;
150524121865SAdrian Maldonado   PetscInt       i, nvar;
150624121865SAdrian Maldonado 
150724121865SAdrian Maldonado   PetscFunctionBegin;
15089dddd249SSatish Balay   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)main), subsection);CHKERRQ(ierr);
150924121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
151024121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
15119dddd249SSatish Balay     ierr = PetscSectionGetDof(main,i,&nvar);CHKERRQ(ierr);
151224121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
151324121865SAdrian Maldonado   }
151424121865SAdrian Maldonado 
151524121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
151624121865SAdrian Maldonado   PetscFunctionReturn(0);
151724121865SAdrian Maldonado }
151824121865SAdrian Maldonado 
151924121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
15202bf73ac6SHong Zhang static PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
152124121865SAdrian Maldonado {
152224121865SAdrian Maldonado   PetscErrorCode ierr;
152324121865SAdrian Maldonado   PetscInt       i, *subpoints;
152424121865SAdrian Maldonado 
152524121865SAdrian Maldonado   PetscFunctionBegin;
152624121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
152724121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
152824121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
152924121865SAdrian Maldonado     subpoints[i - pstart] = i;
153024121865SAdrian Maldonado   }
1531459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
153224121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
153324121865SAdrian Maldonado   PetscFunctionReturn(0);
153424121865SAdrian Maldonado }
153524121865SAdrian Maldonado 
153624121865SAdrian Maldonado /*@
15372bf73ac6SHong Zhang   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute
153824121865SAdrian Maldonado 
15392bf73ac6SHong Zhang   Collective on dm
154024121865SAdrian Maldonado 
154124121865SAdrian Maldonado   Input Parameters:
15422bf73ac6SHong Zhang . dm - the DMNetworkObject
154324121865SAdrian Maldonado 
154424121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
154524121865SAdrian Maldonado 
154624121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
154724121865SAdrian Maldonado 
1548caf410d2SHong 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]).
154924121865SAdrian Maldonado 
155024121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
155124121865SAdrian Maldonado 
155224121865SAdrian Maldonado   Level: intermediate
155324121865SAdrian Maldonado 
155424121865SAdrian Maldonado @*/
155524121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
155624121865SAdrian Maldonado {
155724121865SAdrian Maldonado   PetscErrorCode ierr;
155824121865SAdrian Maldonado   MPI_Comm       comm;
15599852e123SBarry Smith   PetscMPIInt    rank, size;
156024121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
156124121865SAdrian Maldonado 
1562eab1376dSHong Zhang   PetscFunctionBegin;
156324121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1564ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1565ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
156624121865SAdrian Maldonado 
156724121865SAdrian Maldonado   /* Create maps for vertices and edges */
156824121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
156924121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
157024121865SAdrian Maldonado 
157124121865SAdrian Maldonado   /* Create local sub-sections */
157224121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
157324121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
157424121865SAdrian Maldonado 
15759852e123SBarry Smith   if (size > 1) {
157624121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
157722bbedd7SHong Zhang 
157824121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
157924121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
158024121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
158124121865SAdrian Maldonado   } else {
158224121865SAdrian Maldonado     /* create structures for vertex */
158324121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
158424121865SAdrian Maldonado     /* create structures for edge */
158524121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
158624121865SAdrian Maldonado   }
158724121865SAdrian Maldonado 
158824121865SAdrian Maldonado   /* Add viewers */
158924121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
159024121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
159124121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
159224121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
159324121865SAdrian Maldonado   PetscFunctionReturn(0);
159424121865SAdrian Maldonado }
15957b6afd5bSHong Zhang 
15965f2c45f1SShri Abhyankar /*@
15972bf73ac6SHong Zhang   DMNetworkDistribute - Distributes the network and moves associated component data
15985f2c45f1SShri Abhyankar 
15995f2c45f1SShri Abhyankar   Collective
16005f2c45f1SShri Abhyankar 
16015f2c45f1SShri Abhyankar   Input Parameter:
1602d3464fd4SAdrian Maldonado + DM - the DMNetwork object
16032bf73ac6SHong Zhang - overlap - the overlap of partitions, 0 is the default
16045f2c45f1SShri Abhyankar 
16055f2c45f1SShri Abhyankar   Notes:
16068b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
16075f2c45f1SShri Abhyankar 
16085f2c45f1SShri Abhyankar   Level: intermediate
16095f2c45f1SShri Abhyankar 
16102bf73ac6SHong Zhang .seealso: DMNetworkCreate()
16115f2c45f1SShri Abhyankar @*/
1612d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
16135f2c45f1SShri Abhyankar {
1614d3464fd4SAdrian Maldonado   MPI_Comm       comm;
16155f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1616d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1617d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1618d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1619caf410d2SHong Zhang   PetscSF        pointsf=NULL;
16205f2c45f1SShri Abhyankar   DM             newDM;
16212bf73ac6SHong Zhang   PetscInt       j,e,v,offset,*subnetvtx,nsubnet,gidx,svtx_idx,nv;
16222bf73ac6SHong Zhang   PetscInt       to_net,from_net,*svto;
162351ac5effSHong Zhang   PetscPartitioner         part;
1624b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
16255f2c45f1SShri Abhyankar 
16265f2c45f1SShri Abhyankar   PetscFunctionBegin;
1627d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1628ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1629d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1630d3464fd4SAdrian Maldonado 
16312bf73ac6SHong 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. */
1632d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
16335f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
1634*54dfd506SHong Zhang   newDMnetwork->max_comps_registered = oldDMnetwork->max_comps_registered;
1635*54dfd506SHong Zhang   ierr = PetscMalloc1(newDMnetwork->max_comps_registered,&newDMnetwork->component);CHKERRQ(ierr);
163651ac5effSHong Zhang 
163751ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
163851ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
163951ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
164051ac5effSHong Zhang 
16412bf73ac6SHong Zhang   /* Distribute plex dm */
164280cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
164351ac5effSHong Zhang 
16445f2c45f1SShri Abhyankar   /* Distribute dof section */
16452bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DofSection);CHKERRQ(ierr);
16465f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
164751ac5effSHong Zhang 
16485f2c45f1SShri Abhyankar   /* Distribute data and associated section */
16492bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DataSection);CHKERRQ(ierr);
165031da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
165124121865SAdrian Maldonado 
16525f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
16535f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
16545f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
16555f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
16566fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
16576fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
16585f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
16592bf73ac6SHong Zhang   newDMnetwork->svtable   = oldDMnetwork->svtable;
16602bf73ac6SHong Zhang   oldDMnetwork->svtable   = NULL;
166124121865SAdrian Maldonado 
16621bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
166392fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1664e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
16655f2c45f1SShri Abhyankar 
1666b9c6e19dSShri Abhyankar   /* Set up subnetwork info in the newDM */
16672bf73ac6SHong Zhang   newDMnetwork->Nsubnet = oldDMnetwork->Nsubnet;
16682bf73ac6SHong Zhang   newDMnetwork->Nsvtx   = oldDMnetwork->Nsvtx;
16692bf73ac6SHong Zhang   oldDMnetwork->Nsvtx   = 0;
16702bf73ac6SHong Zhang   newDMnetwork->svtx    = oldDMnetwork->svtx; /* global vertices! */
16712bf73ac6SHong Zhang   oldDMnetwork->svtx    = NULL;
16722bf73ac6SHong Zhang   ierr = PetscCalloc1(newDMnetwork->Nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
16732bf73ac6SHong Zhang 
16742bf73ac6SHong Zhang   /* Copy over the global number of vertices and edges in each subnetwork.
16752bf73ac6SHong Zhang      Note: these are calculated in DMNetworkLayoutSetUp()
1676b9c6e19dSShri Abhyankar   */
16772bf73ac6SHong Zhang   nsubnet = newDMnetwork->Nsubnet;
16782bf73ac6SHong Zhang   for (j = 0; j < nsubnet; j++) {
1679b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1680b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1681b9c6e19dSShri Abhyankar   }
1682b9c6e19dSShri Abhyankar 
1683*54dfd506SHong Zhang   PetscMPIInt rank;
1684*54dfd506SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
1685*54dfd506SHong Zhang 
16862bf73ac6SHong Zhang   /* Get local nedges and nvtx for subnetworks */
1687b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1688b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1689*54dfd506SHong Zhang     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
1690*54dfd506SHong Zhang     /* Update pointers */
1691*54dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
1692*54dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
1693*54dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
1694*54dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
1695*54dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
1696*54dfd506SHong Zhang 
1697b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1698b9c6e19dSShri Abhyankar   }
1699b9c6e19dSShri Abhyankar 
1700b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1701b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1702b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
17032bf73ac6SHong Zhang 
1704*54dfd506SHong Zhang     /* Update pointers */
1705*54dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
1706*54dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
1707*54dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
1708*54dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
1709*54dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
1710*54dfd506SHong Zhang 
17112bf73ac6SHong Zhang     /* shared vertices: use gidx = header->index to check if v is a shared vertex */
17122bf73ac6SHong Zhang     gidx = header->index;
17132bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
17142bf73ac6SHong Zhang     svtx_idx--;
17152bf73ac6SHong Zhang 
17162bf73ac6SHong Zhang     if (svtx_idx < 0) { /* not a shared vertex */
1717b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].nvtx++;
17182bf73ac6SHong Zhang     } else { /* a shared vertex belongs to more than one subnetworks, it is being counted by multiple subnets */
17192bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
17202bf73ac6SHong Zhang       newDMnetwork->subnet[from_net].nvtx++;
17212bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
17222bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
17232bf73ac6SHong Zhang         to_net = svto[0];
17242bf73ac6SHong Zhang         newDMnetwork->subnet[to_net].nvtx++;
17252bf73ac6SHong Zhang       }
17262bf73ac6SHong Zhang     }
1727b9c6e19dSShri Abhyankar   }
1728b9c6e19dSShri Abhyankar 
17292bf73ac6SHong Zhang   /* Get total local nvtx for subnetworks */
17302bf73ac6SHong Zhang   nv = 0;
17312bf73ac6SHong Zhang   for (j=0; j<nsubnet; j++) nv += newDMnetwork->subnet[j].nvtx;
17322bf73ac6SHong Zhang   nv += newDMnetwork->Nsvtx;
1733caf410d2SHong Zhang 
17342bf73ac6SHong Zhang   /* Now create the vertices and edge arrays for the subnetworks */
17352bf73ac6SHong Zhang   ierr = PetscCalloc1(nv,&subnetvtx);CHKERRQ(ierr);
17362bf73ac6SHong Zhang   newDMnetwork->subnetvtx = subnetvtx;
17372bf73ac6SHong Zhang 
17382bf73ac6SHong Zhang   for (j=0; j<nsubnet; j++) {
1739b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr);
1740caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1741caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1742caf410d2SHong Zhang 
17432bf73ac6SHong 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. */
1744b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1745b9c6e19dSShri Abhyankar   }
17462bf73ac6SHong Zhang   newDMnetwork->svertices = subnetvtx;
1747b9c6e19dSShri Abhyankar 
17482bf73ac6SHong Zhang   /* Set the edges and vertices in each subnetwork */
1749b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1750b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1751b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1752b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1753b9c6e19dSShri Abhyankar   }
1754b9c6e19dSShri Abhyankar 
17552bf73ac6SHong Zhang   nv = 0;
1756b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1757b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1758b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
17592bf73ac6SHong Zhang 
17602bf73ac6SHong Zhang     /* coupling vertices: use gidx = header->index to check if v is a coupling vertex */
17612bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,header->index+1,&svtx_idx);CHKERRQ(ierr);
17622bf73ac6SHong Zhang     svtx_idx--;
17632bf73ac6SHong Zhang     if (svtx_idx < 0) {
1764b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
17652bf73ac6SHong Zhang     } else { /* a shared vertex */
17662bf73ac6SHong Zhang       newDMnetwork->svertices[nv++] = v;
17672bf73ac6SHong Zhang 
17682bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
17692bf73ac6SHong Zhang       newDMnetwork->subnet[from_net].vertices[newDMnetwork->subnet[from_net].nvtx++] = v;
17702bf73ac6SHong Zhang 
17712bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
17722bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
17732bf73ac6SHong Zhang         to_net = svto[0];
17742bf73ac6SHong Zhang         newDMnetwork->subnet[to_net].vertices[newDMnetwork->subnet[to_net].nvtx++] = v;
1775b9c6e19dSShri Abhyankar       }
17762bf73ac6SHong Zhang     }
17772bf73ac6SHong Zhang   }
17782bf73ac6SHong Zhang   newDMnetwork->nsvtx = nv;   /* num of local shared vertices */
1779b9c6e19dSShri Abhyankar 
1780caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
178122bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1782caf410d2SHong Zhang 
17832bf73ac6SHong Zhang   /* Free spaces */
178424121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
1785d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
17862bf73ac6SHong Zhang 
1787d3464fd4SAdrian Maldonado   *dm  = newDM;
17885f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
17895f2c45f1SShri Abhyankar }
17905f2c45f1SShri Abhyankar 
179124121865SAdrian Maldonado /*@C
17922bf73ac6SHong Zhang   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering
17932bf73ac6SHong Zhang 
17942bf73ac6SHong Zhang  Collective
179524121865SAdrian Maldonado 
179624121865SAdrian Maldonado   Input Parameters:
17979dddd249SSatish Balay + mainSF - the original SF structure
179824121865SAdrian Maldonado - map - a ISLocalToGlobal mapping that contains the subset of points
179924121865SAdrian Maldonado 
180024121865SAdrian Maldonado   Output Parameters:
18019dddd249SSatish Balay . subSF - a subset of the mainSF for the desired subset.
1802ee300463SSatish Balay 
1803ee300463SSatish Balay   Level: intermediate
18047d928bffSSatish Balay @*/
18059dddd249SSatish Balay PetscErrorCode PetscSFGetSubSF(PetscSF mainsf,ISLocalToGlobalMapping map,PetscSF *subSF)
18062bf73ac6SHong Zhang {
180724121865SAdrian Maldonado   PetscErrorCode        ierr;
180824121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
180924121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
181024121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
181124121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
181224121865SAdrian Maldonado   const PetscInt        *ilocal;
181324121865SAdrian Maldonado   const PetscSFNode     *iremote;
181424121865SAdrian Maldonado 
181524121865SAdrian Maldonado   PetscFunctionBegin;
18169dddd249SSatish Balay   ierr = PetscSFGetGraph(mainsf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
181724121865SAdrian Maldonado 
181824121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
181924121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
182024121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
182124121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
182224121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
182324121865SAdrian Maldonado   }
182424121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
182524121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
182624121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
182724121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
1828ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
1829ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
183024121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
18314b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
18324b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
183324121865SAdrian Maldonado   nleaves_sub = 0;
183424121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
183524121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
183624121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
18374b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
183824121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
183924121865SAdrian Maldonado       nleaves_sub += 1;
184024121865SAdrian Maldonado     }
184124121865SAdrian Maldonado   }
184224121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
184324121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
184424121865SAdrian Maldonado 
184524121865SAdrian Maldonado   /* Create new subSF */
184624121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
184724121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
18484b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
184924121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
18504b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
185124121865SAdrian Maldonado   PetscFunctionReturn(0);
185224121865SAdrian Maldonado }
185324121865SAdrian Maldonado 
18545f2c45f1SShri Abhyankar /*@C
18555f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
18565f2c45f1SShri Abhyankar 
18575f2c45f1SShri Abhyankar   Not Collective
18585f2c45f1SShri Abhyankar 
18595f2c45f1SShri Abhyankar   Input Parameters:
18602bf73ac6SHong Zhang + dm - the DMNetwork object
18615f2c45f1SShri Abhyankar - p  - the vertex point
18625f2c45f1SShri Abhyankar 
1863fd292e60Sprj-   Output Parameters:
18645f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
18652bf73ac6SHong Zhang - edges  - list of edge points
18665f2c45f1SShri Abhyankar 
186797bb938eSShri Abhyankar   Level: beginner
18685f2c45f1SShri Abhyankar 
18695f2c45f1SShri Abhyankar   Fortran Notes:
18705f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
18715f2c45f1SShri Abhyankar   include petsc.h90 in your code.
18725f2c45f1SShri Abhyankar 
18732bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetConnectedVertices()
18745f2c45f1SShri Abhyankar @*/
18755f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
18765f2c45f1SShri Abhyankar {
18775f2c45f1SShri Abhyankar   PetscErrorCode ierr;
18785f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
18795f2c45f1SShri Abhyankar 
18805f2c45f1SShri Abhyankar   PetscFunctionBegin;
18815f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
1882a9b4a83eSHong Zhang   if (edges) {ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);}
18835f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18845f2c45f1SShri Abhyankar }
18855f2c45f1SShri Abhyankar 
18865f2c45f1SShri Abhyankar /*@C
1887d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
18885f2c45f1SShri Abhyankar 
18895f2c45f1SShri Abhyankar   Not Collective
18905f2c45f1SShri Abhyankar 
18915f2c45f1SShri Abhyankar   Input Parameters:
18922bf73ac6SHong Zhang + dm - the DMNetwork object
18935f2c45f1SShri Abhyankar - p - the edge point
18945f2c45f1SShri Abhyankar 
1895fd292e60Sprj-   Output Parameters:
18965f2c45f1SShri Abhyankar . vertices - vertices connected to this edge
18975f2c45f1SShri Abhyankar 
189897bb938eSShri Abhyankar   Level: beginner
18995f2c45f1SShri Abhyankar 
19005f2c45f1SShri Abhyankar   Fortran Notes:
19015f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
19025f2c45f1SShri Abhyankar   include petsc.h90 in your code.
19035f2c45f1SShri Abhyankar 
19042bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetSupportingEdges()
19055f2c45f1SShri Abhyankar @*/
1906d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
19075f2c45f1SShri Abhyankar {
19085f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19095f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19105f2c45f1SShri Abhyankar 
19115f2c45f1SShri Abhyankar   PetscFunctionBegin;
19125f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
19135f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19145f2c45f1SShri Abhyankar }
19155f2c45f1SShri Abhyankar 
19165f2c45f1SShri Abhyankar /*@
19172bf73ac6SHong Zhang   DMNetworkIsSharedVertex - Returns TRUE if the vertex is shared by subnetworks
19182bf73ac6SHong Zhang 
19192bf73ac6SHong Zhang   Not Collective
19202bf73ac6SHong Zhang 
19212bf73ac6SHong Zhang   Input Parameters:
19222bf73ac6SHong Zhang + dm - the DMNetwork object
19232bf73ac6SHong Zhang - p - the vertex point
19242bf73ac6SHong Zhang 
19252bf73ac6SHong Zhang   Output Parameter:
19262bf73ac6SHong Zhang . flag - TRUE if the vertex is shared by subnetworks
19272bf73ac6SHong Zhang 
19282bf73ac6SHong Zhang   Level: beginner
19292bf73ac6SHong Zhang 
19302bf73ac6SHong Zhang .seealso: DMNetworkAddSharedVertices(), DMNetworkIsGhostVertex()
19312bf73ac6SHong Zhang @*/
19322bf73ac6SHong Zhang PetscErrorCode DMNetworkIsSharedVertex(DM dm,PetscInt p,PetscBool *flag)
19332bf73ac6SHong Zhang {
19342bf73ac6SHong Zhang   PetscErrorCode ierr;
19352bf73ac6SHong Zhang   PetscInt       i;
19362bf73ac6SHong Zhang 
19372bf73ac6SHong Zhang   PetscFunctionBegin;
19382bf73ac6SHong Zhang   *flag = PETSC_FALSE;
19392bf73ac6SHong Zhang 
19402bf73ac6SHong Zhang   if (dm->setupcalled) { /* DMNetworkGetGlobalVertexIndex() requires DMSetUp() be called */
19412bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
19422bf73ac6SHong Zhang     PetscInt       gidx;
19432bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVertexIndex(dm,p,&gidx);CHKERRQ(ierr);
19442bf73ac6SHong Zhang     ierr = PetscTableFind(network->svtable,gidx+1,&i);CHKERRQ(ierr);
19452bf73ac6SHong Zhang     if (i) *flag = PETSC_TRUE;
19462bf73ac6SHong Zhang   } else { /* would be removed? */
19472bf73ac6SHong Zhang     PetscInt       nv;
19482bf73ac6SHong Zhang     const PetscInt *vtx;
19492bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nv,&vtx);CHKERRQ(ierr);
19502bf73ac6SHong Zhang     for (i=0; i<nv; i++) {
19512bf73ac6SHong Zhang       if (p == vtx[i]) {
19522bf73ac6SHong Zhang         *flag = PETSC_TRUE;
19532bf73ac6SHong Zhang         break;
19542bf73ac6SHong Zhang       }
19552bf73ac6SHong Zhang     }
19562bf73ac6SHong Zhang   }
19572bf73ac6SHong Zhang   PetscFunctionReturn(0);
19582bf73ac6SHong Zhang }
19592bf73ac6SHong Zhang 
19602bf73ac6SHong Zhang /*@
19615f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
19625f2c45f1SShri Abhyankar 
19635f2c45f1SShri Abhyankar   Not Collective
19645f2c45f1SShri Abhyankar 
19655f2c45f1SShri Abhyankar   Input Parameters:
19662bf73ac6SHong Zhang + dm - the DMNetwork object
1967a2b725a8SWilliam Gropp - p - the vertex point
19685f2c45f1SShri Abhyankar 
19695f2c45f1SShri Abhyankar   Output Parameter:
19705f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
19715f2c45f1SShri Abhyankar 
197297bb938eSShri Abhyankar   Level: beginner
19735f2c45f1SShri Abhyankar 
19742bf73ac6SHong Zhang .seealso: DMNetworkGetConnectedVertices(), DMNetworkGetVertexRange(), DMNetworkIsSharedVertex()
19755f2c45f1SShri Abhyankar @*/
19765f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
19775f2c45f1SShri Abhyankar {
19785f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19795f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19805f2c45f1SShri Abhyankar   PetscInt       offsetg;
19815f2c45f1SShri Abhyankar   PetscSection   sectiong;
19825f2c45f1SShri Abhyankar 
19835f2c45f1SShri Abhyankar   PetscFunctionBegin;
19845f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
1985e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
19865f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
19875f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
19885f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19895f2c45f1SShri Abhyankar }
19905f2c45f1SShri Abhyankar 
19915f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
19925f2c45f1SShri Abhyankar {
19935f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19945f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
19955f2c45f1SShri Abhyankar 
19965f2c45f1SShri Abhyankar   PetscFunctionBegin;
19975f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
19985f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
19995f2c45f1SShri Abhyankar 
200092fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
2001e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
20029e1d080bSHong Zhang 
20039e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
20049e1d080bSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr);
20055f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20065f2c45f1SShri Abhyankar }
20075f2c45f1SShri Abhyankar 
20081ad426b7SHong Zhang /*@
200917df6e9eSHong Zhang   DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
20101ad426b7SHong Zhang       -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
20111ad426b7SHong Zhang 
20121ad426b7SHong Zhang   Collective
20131ad426b7SHong Zhang 
20141ad426b7SHong Zhang   Input Parameters:
20152bf73ac6SHong Zhang + dm - the DMNetwork object
201683b2e829SHong Zhang . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
201783b2e829SHong Zhang - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
20181ad426b7SHong Zhang 
20191ad426b7SHong Zhang  Level: intermediate
20201ad426b7SHong Zhang 
20211ad426b7SHong Zhang @*/
202283b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
20231ad426b7SHong Zhang {
20241ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
20258675203cSHong Zhang   PetscErrorCode ierr;
202666b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
20271ad426b7SHong Zhang 
20281ad426b7SHong Zhang   PetscFunctionBegin;
202983b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
203083b2e829SHong Zhang   network->userVertexJacobian = vflg;
20318675203cSHong Zhang 
20328675203cSHong Zhang   if (eflg && !network->Je) {
20338675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
20348675203cSHong Zhang   }
20358675203cSHong Zhang 
203666b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
20378675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
203866b4e0ffSHong Zhang     PetscInt       nedges_total;
20398675203cSHong Zhang     const PetscInt *edges;
20408675203cSHong Zhang 
20418675203cSHong Zhang     /* count nvertex_total */
20428675203cSHong Zhang     nedges_total = 0;
20438675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
20448675203cSHong Zhang 
20458675203cSHong Zhang     vptr[0] = 0;
20468675203cSHong Zhang     for (i=0; i<nVertices; i++) {
20478675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
20488675203cSHong Zhang       nedges_total += nedges;
20498675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
20508675203cSHong Zhang     }
20518675203cSHong Zhang 
20528675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
20538675203cSHong Zhang     network->Jvptr = vptr;
20548675203cSHong Zhang   }
20551ad426b7SHong Zhang   PetscFunctionReturn(0);
20561ad426b7SHong Zhang }
20571ad426b7SHong Zhang 
20581ad426b7SHong Zhang /*@
205983b2e829SHong Zhang   DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
206083b2e829SHong Zhang 
206183b2e829SHong Zhang   Not Collective
206283b2e829SHong Zhang 
206383b2e829SHong Zhang   Input Parameters:
20642bf73ac6SHong Zhang + dm - the DMNetwork object
206583b2e829SHong Zhang . p - the edge point
20663e97b6e8SHong Zhang - J - array (size = 3) of Jacobian submatrices for this edge point:
20673e97b6e8SHong Zhang         J[0]: this edge
2068d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
206983b2e829SHong Zhang 
207097bb938eSShri Abhyankar   Level: advanced
207183b2e829SHong Zhang 
20722bf73ac6SHong Zhang .seealso: DMNetworkVertexSetMatrix()
207383b2e829SHong Zhang @*/
207483b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
207583b2e829SHong Zhang {
207683b2e829SHong Zhang   DM_Network *network=(DM_Network*)dm->data;
207783b2e829SHong Zhang 
207883b2e829SHong Zhang   PetscFunctionBegin;
20798675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
20808675203cSHong Zhang 
20818675203cSHong Zhang   if (J) {
2082883e35e8SHong Zhang     network->Je[3*p]   = J[0];
2083883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
2084883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
20858675203cSHong Zhang   }
208683b2e829SHong Zhang   PetscFunctionReturn(0);
208783b2e829SHong Zhang }
208883b2e829SHong Zhang 
208983b2e829SHong Zhang /*@
209076ddfea5SHong Zhang   DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
20911ad426b7SHong Zhang 
20921ad426b7SHong Zhang   Not Collective
20931ad426b7SHong Zhang 
20941ad426b7SHong Zhang   Input Parameters:
20951ad426b7SHong Zhang + dm - The DMNetwork object
20961ad426b7SHong Zhang . p - the vertex point
20973e97b6e8SHong Zhang - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
20983e97b6e8SHong Zhang         J[0]:       this vertex
20993e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
21003e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
21011ad426b7SHong Zhang 
210297bb938eSShri Abhyankar   Level: advanced
21031ad426b7SHong Zhang 
21042bf73ac6SHong Zhang .seealso: DMNetworkEdgeSetMatrix()
21051ad426b7SHong Zhang @*/
2106883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
21075f2c45f1SShri Abhyankar {
21085f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21095f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
21108675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
2111883e35e8SHong Zhang   const PetscInt *edges;
21125f2c45f1SShri Abhyankar 
21135f2c45f1SShri Abhyankar   PetscFunctionBegin;
21148675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
2115883e35e8SHong Zhang 
21168675203cSHong Zhang   if (J) {
2117883e35e8SHong Zhang     vptr = network->Jvptr;
21183e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
21193e97b6e8SHong Zhang 
21203e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
2121883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
2122883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
21238675203cSHong Zhang   }
2124883e35e8SHong Zhang   PetscFunctionReturn(0);
2125883e35e8SHong Zhang }
2126883e35e8SHong Zhang 
2127e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
21285cf7da58SHong Zhang {
21295cf7da58SHong Zhang   PetscErrorCode ierr;
21305cf7da58SHong Zhang   PetscInt       j;
21315cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
21325cf7da58SHong Zhang 
21335cf7da58SHong Zhang   PetscFunctionBegin;
21345cf7da58SHong Zhang   if (!ghost) {
21355cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
21365cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
21375cf7da58SHong Zhang     }
21385cf7da58SHong Zhang   } else {
21395cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
21405cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
21415cf7da58SHong Zhang     }
21425cf7da58SHong Zhang   }
21435cf7da58SHong Zhang   PetscFunctionReturn(0);
21445cf7da58SHong Zhang }
21455cf7da58SHong Zhang 
2146e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
21475cf7da58SHong Zhang {
21485cf7da58SHong Zhang   PetscErrorCode ierr;
21495cf7da58SHong Zhang   PetscInt       j,ncols_u;
21505cf7da58SHong Zhang   PetscScalar    val;
21515cf7da58SHong Zhang 
21525cf7da58SHong Zhang   PetscFunctionBegin;
21535cf7da58SHong Zhang   if (!ghost) {
21545cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
21555cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
21565cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
21575cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
21585cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
21595cf7da58SHong Zhang     }
21605cf7da58SHong Zhang   } else {
21615cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
21625cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
21635cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
21645cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
21655cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
21665cf7da58SHong Zhang     }
21675cf7da58SHong Zhang   }
21685cf7da58SHong Zhang   PetscFunctionReturn(0);
21695cf7da58SHong Zhang }
21705cf7da58SHong Zhang 
2171e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
21725cf7da58SHong Zhang {
21735cf7da58SHong Zhang   PetscErrorCode ierr;
21745cf7da58SHong Zhang 
21755cf7da58SHong Zhang   PetscFunctionBegin;
21765cf7da58SHong Zhang   if (Ju) {
21775cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
21785cf7da58SHong Zhang   } else {
21795cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
21805cf7da58SHong Zhang   }
21815cf7da58SHong Zhang   PetscFunctionReturn(0);
21825cf7da58SHong Zhang }
21835cf7da58SHong Zhang 
2184e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2185883e35e8SHong Zhang {
2186883e35e8SHong Zhang   PetscErrorCode ierr;
2187883e35e8SHong Zhang   PetscInt       j,*cols;
2188883e35e8SHong Zhang   PetscScalar    *zeros;
2189883e35e8SHong Zhang 
2190883e35e8SHong Zhang   PetscFunctionBegin;
2191883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
2192883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
2193883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
2194883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
21951ad426b7SHong Zhang   PetscFunctionReturn(0);
21961ad426b7SHong Zhang }
2197a4e85ca8SHong Zhang 
2198e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
21993e97b6e8SHong Zhang {
22003e97b6e8SHong Zhang   PetscErrorCode ierr;
22013e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
22023e97b6e8SHong Zhang   const PetscInt *cols;
22033e97b6e8SHong Zhang   PetscScalar    zero=0.0;
22043e97b6e8SHong Zhang 
22053e97b6e8SHong Zhang   PetscFunctionBegin;
22063e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
22073e97b6e8SHong 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);
22083e97b6e8SHong Zhang 
22093e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
22103e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
22113e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
22123e97b6e8SHong Zhang       col = cols[j] + cstart;
22133e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
22143e97b6e8SHong Zhang     }
22153e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
22163e97b6e8SHong Zhang   }
22173e97b6e8SHong Zhang   PetscFunctionReturn(0);
22183e97b6e8SHong Zhang }
22191ad426b7SHong Zhang 
2220e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2221a4e85ca8SHong Zhang {
2222a4e85ca8SHong Zhang   PetscErrorCode ierr;
2223f4431b8cSHong Zhang 
2224a4e85ca8SHong Zhang   PetscFunctionBegin;
2225a4e85ca8SHong Zhang   if (Ju) {
2226a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2227a4e85ca8SHong Zhang   } else {
2228a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2229a4e85ca8SHong Zhang   }
2230a4e85ca8SHong Zhang   PetscFunctionReturn(0);
2231a4e85ca8SHong Zhang }
2232a4e85ca8SHong Zhang 
223324121865SAdrian 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.
223424121865SAdrian Maldonado */
223524121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
223624121865SAdrian Maldonado {
223724121865SAdrian Maldonado   PetscErrorCode ierr;
223824121865SAdrian Maldonado   PetscInt       i,size,dof;
223924121865SAdrian Maldonado   PetscInt       *glob2loc;
224024121865SAdrian Maldonado 
224124121865SAdrian Maldonado   PetscFunctionBegin;
224224121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
224324121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
224424121865SAdrian Maldonado 
224524121865SAdrian Maldonado   for (i = 0; i < size; i++) {
224624121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
224724121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
224824121865SAdrian Maldonado     glob2loc[i] = dof;
224924121865SAdrian Maldonado   }
225024121865SAdrian Maldonado 
225124121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
225224121865SAdrian Maldonado #if 0
225324121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
225424121865SAdrian Maldonado #endif
225524121865SAdrian Maldonado   PetscFunctionReturn(0);
225624121865SAdrian Maldonado }
225724121865SAdrian Maldonado 
225801ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
22599e1d080bSHong Zhang 
22609e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
22611ad426b7SHong Zhang {
22621ad426b7SHong Zhang   PetscErrorCode ierr;
22631ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
22649e1d080bSHong Zhang   PetscMPIInt    rank, size;
226524121865SAdrian Maldonado   PetscInt       eDof,vDof;
226624121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
22679e1d080bSHong Zhang   MPI_Comm       comm;
226824121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
226924121865SAdrian Maldonado 
22709e1d080bSHong Zhang   PetscFunctionBegin;
227124121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2272ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
2273ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
227424121865SAdrian Maldonado 
227524121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
227624121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
227724121865SAdrian Maldonado 
227801ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
227924121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
228024121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
228124121865SAdrian Maldonado 
228201ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
228324121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
228424121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
228524121865SAdrian Maldonado 
228601ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
228724121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
228824121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
228924121865SAdrian Maldonado 
229001ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
229124121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
229224121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
229324121865SAdrian Maldonado 
22943f6a6bdaSHong Zhang   bA[0][0] = j11;
22953f6a6bdaSHong Zhang   bA[0][1] = j12;
22963f6a6bdaSHong Zhang   bA[1][0] = j21;
22973f6a6bdaSHong Zhang   bA[1][1] = j22;
229824121865SAdrian Maldonado 
229924121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
230024121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
230124121865SAdrian Maldonado 
230224121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
230324121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
230424121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
230524121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
230624121865SAdrian Maldonado 
230724121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
230824121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
230924121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
231024121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
231124121865SAdrian Maldonado 
231201ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
231324121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
231424121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
231524121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
231624121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
231724121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
231824121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
231924121865SAdrian Maldonado 
232024121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
232124121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23229e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
232324121865SAdrian Maldonado 
232424121865SAdrian Maldonado   /* Free structures */
232524121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
232624121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
232724121865SAdrian Maldonado   PetscFunctionReturn(0);
23289e1d080bSHong Zhang }
23299e1d080bSHong Zhang 
23309e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
23319e1d080bSHong Zhang {
23329e1d080bSHong Zhang   PetscErrorCode ierr;
23339e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
23349e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
23359e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
23369e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
23379e1d080bSHong Zhang   Mat            Juser;
23389e1d080bSHong Zhang   PetscSection   sectionGlobal;
23399e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
23409e1d080bSHong Zhang   const PetscInt *edges,*cone;
23419e1d080bSHong Zhang   MPI_Comm       comm;
23429e1d080bSHong Zhang   MatType        mtype;
23439e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
23449e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
23459e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
23469e1d080bSHong Zhang 
23479e1d080bSHong Zhang   PetscFunctionBegin;
23489e1d080bSHong Zhang   mtype = dm->mattype;
23499e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
23509e1d080bSHong Zhang   if (isNest) {
23519e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
2352c6b011d8SStefano Zampini     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
23539e1d080bSHong Zhang     PetscFunctionReturn(0);
23549e1d080bSHong Zhang   }
23559e1d080bSHong Zhang 
23569e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
2357a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
23589e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
2359bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
23601ad426b7SHong Zhang     PetscFunctionReturn(0);
23611ad426b7SHong Zhang   }
23621ad426b7SHong Zhang 
2363bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
2364e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
2365bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
2366bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
23672a945128SHong Zhang 
23682a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
23692a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
237089898e50SHong Zhang 
237189898e50SHong Zhang   /* (1) Set matrix preallocation */
237289898e50SHong Zhang   /*------------------------------*/
2373840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2374840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
2375840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
2376840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
2377840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
2378840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
2379840c2264SHong Zhang 
238089898e50SHong Zhang   /* Set preallocation for edges */
238189898e50SHong Zhang   /*-----------------------------*/
2382840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
2383840c2264SHong Zhang 
2384bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
2385840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
2386840c2264SHong Zhang     /* Get row indices */
23872bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
23882bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
2389840c2264SHong Zhang     if (nrows) {
2390840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
2391840c2264SHong Zhang 
23925cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
2393d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2394840c2264SHong Zhang       for (v=0; v<2; v++) {
23952bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
2396840c2264SHong Zhang 
23978675203cSHong Zhang         if (network->Je) {
2398840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
23998675203cSHong Zhang         } else Juser = NULL;
2400840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
24015cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2402840c2264SHong Zhang       }
2403840c2264SHong Zhang 
240489898e50SHong Zhang       /* Set preallocation for edge self */
2405840c2264SHong Zhang       cstart = rstart;
24068675203cSHong Zhang       if (network->Je) {
2407840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
24088675203cSHong Zhang       } else Juser = NULL;
24095cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2410840c2264SHong Zhang     }
2411840c2264SHong Zhang   }
2412840c2264SHong Zhang 
241389898e50SHong Zhang   /* Set preallocation for vertices */
241489898e50SHong Zhang   /*--------------------------------*/
2415840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
24168675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
2417840c2264SHong Zhang 
2418840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
2419840c2264SHong Zhang     /* Get row indices */
24202bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
24212bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
2422840c2264SHong Zhang     if (!nrows) continue;
2423840c2264SHong Zhang 
2424bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2425bdcb62a2SHong Zhang     if (ghost) {
2426bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2427bdcb62a2SHong Zhang     } else {
2428bdcb62a2SHong Zhang       rows_v = rows;
2429bdcb62a2SHong Zhang     }
2430bdcb62a2SHong Zhang 
2431bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2432840c2264SHong Zhang 
2433840c2264SHong Zhang     /* Get supporting edges and connected vertices */
2434840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2435840c2264SHong Zhang 
2436840c2264SHong Zhang     for (e=0; e<nedges; e++) {
2437840c2264SHong Zhang       /* Supporting edges */
24382bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
24392bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2440840c2264SHong Zhang 
24418675203cSHong Zhang       if (network->Jv) {
2442840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
24438675203cSHong Zhang       } else Juser = NULL;
2444bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2445840c2264SHong Zhang 
2446840c2264SHong Zhang       /* Connected vertices */
2447d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
2448840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
2449840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
2450840c2264SHong Zhang 
24512bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2452840c2264SHong Zhang 
24538675203cSHong Zhang       if (network->Jv) {
2454840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
24558675203cSHong Zhang       } else Juser = NULL;
2456e102a522SHong Zhang       if (ghost_vc||ghost) {
2457e102a522SHong Zhang         ghost2 = PETSC_TRUE;
2458e102a522SHong Zhang       } else {
2459e102a522SHong Zhang         ghost2 = PETSC_FALSE;
2460e102a522SHong Zhang       }
2461e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
2462840c2264SHong Zhang     }
2463840c2264SHong Zhang 
246489898e50SHong Zhang     /* Set preallocation for vertex self */
2465840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2466840c2264SHong Zhang     if (!ghost) {
24672bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
24688675203cSHong Zhang       if (network->Jv) {
2469840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
24708675203cSHong Zhang       } else Juser = NULL;
2471bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2472840c2264SHong Zhang     }
2473bdcb62a2SHong Zhang     if (ghost) {
2474bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2475bdcb62a2SHong Zhang     }
2476840c2264SHong Zhang   }
2477840c2264SHong Zhang 
2478840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
2479840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
24805cf7da58SHong Zhang 
24815cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
24825cf7da58SHong Zhang 
24835cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
2484840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
2485840c2264SHong Zhang 
2486840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
2487840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
2488840c2264SHong Zhang   for (j=0; j<localSize; j++) {
2489e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
2490e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
2491840c2264SHong Zhang   }
2492840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
2493840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
2494840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
2495840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
2496840c2264SHong Zhang 
24975cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
24985cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
24995cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
25005cf7da58SHong Zhang 
25015cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
25025cf7da58SHong Zhang 
250389898e50SHong Zhang   /* (2) Set matrix entries for edges */
250489898e50SHong Zhang   /*----------------------------------*/
25051ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
2506bfbc38dcSHong Zhang     /* Get row indices */
25072bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
25082bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
25094b976069SHong Zhang     if (nrows) {
251017df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
25111ad426b7SHong Zhang 
2512bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
2513d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2514bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
25152bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVecOffset(dm,cone[v],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25162bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
25173e97b6e8SHong Zhang 
25188675203cSHong Zhang         if (network->Je) {
2519a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
25208675203cSHong Zhang         } else Juser = NULL;
2521a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2522bfbc38dcSHong Zhang       }
252317df6e9eSHong Zhang 
2524bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
25253e97b6e8SHong Zhang       cstart = rstart;
25268675203cSHong Zhang       if (network->Je) {
2527a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
25288675203cSHong Zhang       } else Juser = NULL;
2529a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
25301ad426b7SHong Zhang     }
25314b976069SHong Zhang   }
25321ad426b7SHong Zhang 
2533bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
253483b2e829SHong Zhang   /*---------------------------------*/
25351ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2536bfbc38dcSHong Zhang     /* Get row indices */
25372bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
25382bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
25394b976069SHong Zhang     if (!nrows) continue;
2540596e729fSHong Zhang 
2541bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2542bdcb62a2SHong Zhang     if (ghost) {
2543bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2544bdcb62a2SHong Zhang     } else {
2545bdcb62a2SHong Zhang       rows_v = rows;
2546bdcb62a2SHong Zhang     }
2547bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2548596e729fSHong Zhang 
2549bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2550596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2551596e729fSHong Zhang 
2552596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2553bfbc38dcSHong Zhang       /* Supporting edges */
25542bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25552bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2556596e729fSHong Zhang 
25578675203cSHong Zhang       if (network->Jv) {
2558a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
25598675203cSHong Zhang       } else Juser = NULL;
2560bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2561596e729fSHong Zhang 
2562bfbc38dcSHong Zhang       /* Connected vertices */
2563d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
25642a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
25652a945128SHong Zhang 
25662bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,vc,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25672bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2568a4e85ca8SHong Zhang 
25698675203cSHong Zhang       if (network->Jv) {
2570a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
25718675203cSHong Zhang       } else Juser = NULL;
2572bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2573596e729fSHong Zhang     }
2574596e729fSHong Zhang 
2575bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
25761ad426b7SHong Zhang     if (!ghost) {
25772bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25788675203cSHong Zhang       if (network->Jv) {
2579a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
25808675203cSHong Zhang       } else Juser = NULL;
2581bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2582bdcb62a2SHong Zhang     }
2583bdcb62a2SHong Zhang     if (ghost) {
2584bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2585bdcb62a2SHong Zhang     }
25861ad426b7SHong Zhang   }
2587a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2588bdcb62a2SHong Zhang 
25891ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25901ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2591dd6f46cdSHong Zhang 
25925f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
25935f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
25945f2c45f1SShri Abhyankar }
25955f2c45f1SShri Abhyankar 
25965f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
25975f2c45f1SShri Abhyankar {
25985f2c45f1SShri Abhyankar   PetscErrorCode ierr;
25995f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
2600*54dfd506SHong Zhang   PetscInt       j,np;
26015f2c45f1SShri Abhyankar 
26025f2c45f1SShri Abhyankar   PetscFunctionBegin;
26038415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
260483b2e829SHong Zhang   if (network->Je) {
260583b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
260683b2e829SHong Zhang   }
260783b2e829SHong Zhang   if (network->Jv) {
2608883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
260983b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
26101ad426b7SHong Zhang   }
261113c2a604SAdrian Maldonado 
261213c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
261313c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
261413c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2615f5427c60SHong Zhang   if (network->vltog) {
2616f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2617f5427c60SHong Zhang   }
261813c2a604SAdrian Maldonado   if (network->vertex.sf) {
261913c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
262013c2a604SAdrian Maldonado   }
262113c2a604SAdrian Maldonado   /* edge */
262213c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
262313c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
262413c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
262513c2a604SAdrian Maldonado   if (network->edge.sf) {
262613c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
262713c2a604SAdrian Maldonado   }
26285f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
26295f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
26305f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
263183b2e829SHong Zhang 
26322bf73ac6SHong Zhang   for (j=0; j<network->Nsvtx; j++) {
26332bf73ac6SHong Zhang     ierr = PetscFree(network->svtx[j].sv);CHKERRQ(ierr);
26342bf73ac6SHong Zhang   }
26352bf73ac6SHong Zhang   if (network->svtx) {ierr = PetscFree(network->svtx);CHKERRQ(ierr);}
26362bf73ac6SHong Zhang 
26372bf73ac6SHong Zhang   for (j=0; j<network->Nsubnet; j++) {
26382727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
26392727e31bSShri Abhyankar   }
26402bf73ac6SHong Zhang   if (network->subnetvtx) {ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr);}
2641caf410d2SHong Zhang 
26422bf73ac6SHong Zhang   ierr = PetscTableDestroy(&network->svtable);CHKERRQ(ierr);
2643e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
2644*54dfd506SHong Zhang   ierr = PetscFree(network->component);CHKERRQ(ierr);
26455f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
2646*54dfd506SHong Zhang 
2647*54dfd506SHong Zhang   if (network->header) {
2648*54dfd506SHong Zhang     np = network->pEnd - network->pStart;
2649*54dfd506SHong Zhang     for (j=0; j < np; j++) {
2650*54dfd506SHong Zhang       ierr = PetscFree5(network->header[j].size,network->header[j].key,network->header[j].offset,network->header[j].nvar,network->header[j].offsetvarrel);CHKERRQ(ierr);
2651*54dfd506SHong Zhang       ierr = PetscFree(network->cvalue[j].data);CHKERRQ(ierr);
2652*54dfd506SHong Zhang     }
2653caf410d2SHong Zhang     ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
2654*54dfd506SHong Zhang   }
26555f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
26565f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26575f2c45f1SShri Abhyankar }
26585f2c45f1SShri Abhyankar 
26595f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
26605f2c45f1SShri Abhyankar {
26615f2c45f1SShri Abhyankar   PetscErrorCode ierr;
2662caf410d2SHong Zhang   PetscBool      iascii;
2663caf410d2SHong Zhang   PetscMPIInt    rank;
26645f2c45f1SShri Abhyankar 
26655f2c45f1SShri Abhyankar   PetscFunctionBegin;
2666caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2667ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
2668caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2669caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2670caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2671caf410d2SHong Zhang   if (iascii) {
2672caf410d2SHong Zhang     const PetscInt *cone,*vtx,*edges;
26732bf73ac6SHong Zhang     PetscInt       vfrom,vto,i,j,nv,ne,ncv,p,nsubnet;
26742bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
2675caf410d2SHong Zhang 
26762bf73ac6SHong Zhang     nsubnet = network->Nsubnet; /* num of subnetworks */
26772bf73ac6SHong Zhang     if (!rank) {
26782bf73ac6SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  NSubnets: %D; NEdges: %D; NVertices: %D; NSharedVertices: %D.\n",nsubnet,network->NEdges,network->NVertices,network->Nsvtx);CHKERRQ(ierr);
26792bf73ac6SHong Zhang     }
26802bf73ac6SHong Zhang 
26812bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
2682caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
26832bf73ac6SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nEdges: %D; nVertices: %D; nSharedVertices: %D\n",rank,network->nEdges,network->nVertices,ncv);CHKERRQ(ierr);
2684caf410d2SHong Zhang 
2685caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
26862bf73ac6SHong Zhang       ierr = DMNetworkGetSubnetwork(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2687caf410d2SHong Zhang       if (ne) {
26882bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices(include shared vertices) %D\n",i,ne,nv);CHKERRQ(ierr);
2689caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2690caf410d2SHong Zhang           p = edges[j];
2691caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2692caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2693caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2694caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2695caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D ----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2696caf410d2SHong Zhang         }
2697caf410d2SHong Zhang       }
2698caf410d2SHong Zhang     }
26992bf73ac6SHong Zhang 
27002bf73ac6SHong Zhang     /* Shared vertices */
27012bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
27022bf73ac6SHong Zhang     if (ncv) {
27032bf73ac6SHong Zhang       SVtx       *svtx = network->svtx;
27042bf73ac6SHong Zhang       PetscInt    gidx,svtx_idx,nvto,vfrom_net,vfrom_idx,*svto;
27052bf73ac6SHong Zhang       PetscBool   ghost;
27062bf73ac6SHong Zhang       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     SharedVertices:\n");CHKERRQ(ierr);
27072bf73ac6SHong Zhang       for (i=0; i<ncv; i++) {
27082bf73ac6SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,vtx[i],&ghost);CHKERRQ(ierr);
27092bf73ac6SHong Zhang         if (ghost) continue;
27102bf73ac6SHong Zhang 
27112bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVertexIndex(dm,vtx[i],&gidx);CHKERRQ(ierr);
27122bf73ac6SHong Zhang         ierr = PetscTableFind(network->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
27132bf73ac6SHong Zhang         svtx_idx--;
27142bf73ac6SHong Zhang         nvto = svtx[svtx_idx].n;
27152bf73ac6SHong Zhang 
27162bf73ac6SHong Zhang         vfrom_net = svtx[svtx_idx].sv[0];
27172bf73ac6SHong Zhang         vfrom_idx = svtx[svtx_idx].sv[1];
27182bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       svtx %D: global index %D, subnet[%D].%D ---->\n",i,gidx,vfrom_net,vfrom_idx);CHKERRQ(ierr);
27192bf73ac6SHong Zhang         for (j=1; j<nvto; j++) {
27202bf73ac6SHong Zhang           svto = svtx[svtx_idx].sv + 2*j;
27212bf73ac6SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "                                           ----> subnet[%D].%D\n",svto[0],svto[1]);CHKERRQ(ierr);
2722caf410d2SHong Zhang         }
2723caf410d2SHong Zhang       }
2724caf410d2SHong Zhang     }
2725caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2726caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2727caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
27285f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27295f2c45f1SShri Abhyankar }
27305f2c45f1SShri Abhyankar 
27315f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
27325f2c45f1SShri Abhyankar {
27335f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27345f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27355f2c45f1SShri Abhyankar 
27365f2c45f1SShri Abhyankar   PetscFunctionBegin;
27375f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
27385f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27395f2c45f1SShri Abhyankar }
27405f2c45f1SShri Abhyankar 
27415f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
27425f2c45f1SShri Abhyankar {
27435f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27445f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27455f2c45f1SShri Abhyankar 
27465f2c45f1SShri Abhyankar   PetscFunctionBegin;
27475f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
27485f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27495f2c45f1SShri Abhyankar }
27505f2c45f1SShri Abhyankar 
27515f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
27525f2c45f1SShri Abhyankar {
27535f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27545f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27555f2c45f1SShri Abhyankar 
27565f2c45f1SShri Abhyankar   PetscFunctionBegin;
27575f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
27585f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27595f2c45f1SShri Abhyankar }
27605f2c45f1SShri Abhyankar 
27615f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
27625f2c45f1SShri Abhyankar {
27635f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27645f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27655f2c45f1SShri Abhyankar 
27665f2c45f1SShri Abhyankar   PetscFunctionBegin;
27675f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
27685f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27695f2c45f1SShri Abhyankar }
277022bbedd7SHong Zhang 
277122bbedd7SHong Zhang /*@
277264238763SRodolfo Oliveira   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index
277322bbedd7SHong Zhang 
277422bbedd7SHong Zhang   Not collective
277522bbedd7SHong Zhang 
27767a7aea1fSJed Brown   Input Parameters:
277722bbedd7SHong Zhang + dm - the dm object
277822bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
277922bbedd7SHong Zhang 
27807a7aea1fSJed Brown   Output Parameters:
2781f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
278222bbedd7SHong Zhang 
278397bb938eSShri Abhyankar   Level: advanced
278422bbedd7SHong Zhang 
278522bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
278622bbedd7SHong Zhang @*/
278722bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
278822bbedd7SHong Zhang {
278922bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
279022bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
279122bbedd7SHong Zhang 
279222bbedd7SHong Zhang   PetscFunctionBegin;
279322bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
279422bbedd7SHong Zhang   *vg = vltog[vloc];
279522bbedd7SHong Zhang   PetscFunctionReturn(0);
279622bbedd7SHong Zhang }
279722bbedd7SHong Zhang 
279822bbedd7SHong Zhang /*@
279964238763SRodolfo Oliveira   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map
280022bbedd7SHong Zhang 
280122bbedd7SHong Zhang   Collective
280222bbedd7SHong Zhang 
280322bbedd7SHong Zhang   Input Parameters:
2804f0fc11ceSJed Brown . dm - the dm object
280522bbedd7SHong Zhang 
280697bb938eSShri Abhyankar   Level: advanced
280722bbedd7SHong Zhang 
280863029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
280922bbedd7SHong Zhang @*/
281022bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
281122bbedd7SHong Zhang {
281222bbedd7SHong Zhang   PetscErrorCode    ierr;
281322bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
281422bbedd7SHong Zhang   MPI_Comm          comm;
28152bf73ac6SHong Zhang   PetscMPIInt       rank,size,*displs=NULL,*recvcounts=NULL,remoterank;
281622bbedd7SHong Zhang   PetscBool         ghost;
281763029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
281822bbedd7SHong Zhang   const PetscSFNode *iremote;
281922bbedd7SHong Zhang   PetscSF           vsf;
282063029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
282163029d29SHong Zhang   VecScatter        ctx;
282263029d29SHong Zhang   PetscScalar       *varr,val;
282363029d29SHong Zhang   const PetscScalar *varr_read;
282422bbedd7SHong Zhang 
282522bbedd7SHong Zhang   PetscFunctionBegin;
282622bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2827ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
2828ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
282922bbedd7SHong Zhang 
283022bbedd7SHong Zhang   if (size == 1) {
283122bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
283222bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
283322bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
283422bbedd7SHong Zhang     network->vltog = vltog;
283522bbedd7SHong Zhang     PetscFunctionReturn(0);
283622bbedd7SHong Zhang   }
283722bbedd7SHong Zhang 
283822bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
283922bbedd7SHong Zhang   if (network->vltog) {
284022bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
284122bbedd7SHong Zhang   }
284222bbedd7SHong Zhang 
284322bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
284422bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
284522bbedd7SHong Zhang   vsf = network->vertex.sf;
284622bbedd7SHong Zhang 
28472bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
2848f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
284922bbedd7SHong Zhang 
285022bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
285122bbedd7SHong Zhang 
285222bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
285322bbedd7SHong Zhang   vrange[0] = 0;
2854ffc4695bSBarry Smith   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
285567dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
285622bbedd7SHong Zhang 
285722bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
285822bbedd7SHong Zhang   network->vltog = vltog;
285922bbedd7SHong Zhang 
286063029d29SHong Zhang   /* Set vltog for non-ghost vertices */
286163029d29SHong Zhang   k = 0;
286222bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
286322bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
286463029d29SHong Zhang     if (ghost) continue;
286563029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
286622bbedd7SHong Zhang   }
2867f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
286863029d29SHong Zhang 
286963029d29SHong Zhang   /* Set vltog for ghost vertices */
287063029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
287163029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
287263029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
287363029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
287463029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
287563029d29SHong Zhang   for (i=0; i<nleaves; i++) {
287663029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
287763029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
287863029d29SHong Zhang   }
287963029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
288063029d29SHong Zhang 
288163029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
288263029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
288363029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
288463029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
288563029d29SHong Zhang 
288663029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
288763029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
288863029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
288963029d29SHong Zhang   for (i=0; i<N; i+=2) {
28902e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
289163029d29SHong Zhang     if (remoterank == rank) {
289263029d29SHong Zhang       k = i+1; /* row number */
28932e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
289463029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
289563029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
289663029d29SHong Zhang     }
289763029d29SHong Zhang   }
289863029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
289963029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
290063029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
290163029d29SHong Zhang 
290263029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
290363029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
290463029d29SHong Zhang   k = 0;
290563029d29SHong Zhang   for (i=0; i<nroots; i++) {
290663029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
290763029d29SHong Zhang     if (!ghost) continue;
29082e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
290963029d29SHong Zhang   }
291063029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
291163029d29SHong Zhang 
291263029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
291363029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
291463029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
291522bbedd7SHong Zhang   PetscFunctionReturn(0);
291622bbedd7SHong Zhang }
2917