xref: /petsc/src/dm/impls/network/network.c (revision 5b3f975a8dc79d7af4a98cd23eb03d61410e37db)
1af0996ceSBarry Smith #include <petsc/private/dmnetworkimpl.h>  /*I  "petscdmnetwork.h"  I*/
25f2c45f1SShri Abhyankar 
354dfd506SHong Zhang /*
454dfd506SHong Zhang   Creates the component header and value objects for a network point
554dfd506SHong Zhang */
654dfd506SHong Zhang static PetscErrorCode SetUpNetworkHeaderComponentValue(DM dm,DMNetworkComponentHeader header,DMNetworkComponentValue cvalue)
754dfd506SHong Zhang {
854dfd506SHong Zhang   PetscErrorCode ierr;
954dfd506SHong Zhang 
1054dfd506SHong Zhang   PetscFunctionBegin;
1154dfd506SHong Zhang   /* Allocate arrays for component information */
1254dfd506SHong 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);
1354dfd506SHong Zhang   ierr = PetscCalloc1(header->maxcomps,&cvalue->data);CHKERRQ(ierr);
1454dfd506SHong Zhang 
1554dfd506SHong 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.
1654dfd506SHong Zhang    If the data header struct changes then this header size calculation needs to be updated. */
1754dfd506SHong Zhang   header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt);
1854dfd506SHong Zhang   header->hsize /= sizeof(DMNetworkComponentGenericDataType);
1954dfd506SHong Zhang   PetscFunctionReturn(0);
2054dfd506SHong Zhang }
2154dfd506SHong 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);
48854dfd506SHong Zhang   for (i=0; i<np; i++) {
48954dfd506SHong Zhang     network->header[i].maxcomps = 1;
49054dfd506SHong Zhang     ierr = SetUpNetworkHeaderComponentValue(dm,&network->header[i],&network->cvalue[i]);CHKERRQ(ierr);
49154dfd506SHong 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;
53354dfd506SHong 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;
56054dfd506SHong 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);
65754dfd506SHong Zhang   for (i=0; i < np; i++) {
65854dfd506SHong Zhang     network->header[i].maxcomps = 1;
65954dfd506SHong Zhang     ierr = SetUpNetworkHeaderComponentValue(dm,&network->header[i],&network->cvalue[i]);CHKERRQ(ierr);
66054dfd506SHong 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;
70354dfd506SHong 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;
72954dfd506SHong 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;
86954dfd506SHong Zhang   DMNetworkComponent    *component=NULL,*newcomponent=NULL;
8705f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
8715f2c45f1SShri Abhyankar   PetscInt              i;
8725f2c45f1SShri Abhyankar 
8735f2c45f1SShri Abhyankar   PetscFunctionBegin;
87454dfd506SHong Zhang   if (!network->component) {
87554dfd506SHong Zhang     ierr = PetscCalloc1(network->max_comps_registered,&network->component);CHKERRQ(ierr);
87654dfd506SHong Zhang   }
87754dfd506SHong Zhang 
8785f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
87954dfd506SHong 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   }
88554dfd506SHong Zhang 
88654dfd506SHong Zhang   if (network->ncomponent == network->max_comps_registered) {
88754dfd506SHong Zhang     /* Reached max allowed so resize component */
88854dfd506SHong Zhang     network->max_comps_registered += 2;
88954dfd506SHong Zhang     ierr = PetscCalloc1(network->max_comps_registered,&newcomponent);CHKERRQ(ierr);
89054dfd506SHong Zhang     /* Copy over the previous component info */
89154dfd506SHong Zhang     for (i=0; i < network->ncomponent; i++) {
89254dfd506SHong Zhang       ierr = PetscStrcpy(newcomponent[i].name,network->component[i].name);CHKERRQ(ierr);
89354dfd506SHong Zhang       newcomponent[i].size = network->component[i].size;
8945f2c45f1SShri Abhyankar     }
89554dfd506SHong Zhang     /* Free old one */
89654dfd506SHong Zhang     ierr = PetscFree(network->component);CHKERRQ(ierr);
89754dfd506SHong Zhang     /* Update pointer */
89854dfd506SHong Zhang     network->component = newcomponent;
89954dfd506SHong Zhang   }
90054dfd506SHong Zhang 
90154dfd506SHong 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];
120454dfd506SHong Zhang   DMNetworkComponentHeader header;
120554dfd506SHong Zhang   DMNetworkComponentValue  cvalue;
12062bf73ac6SHong Zhang   PetscBool                sharedv=PETSC_FALSE;
120754dfd506SHong Zhang   PetscInt                 compnum;
120854dfd506SHong Zhang   PetscInt                 *compsize,*compkey,*compoffset,*compnvar,*compoffsetvarrel;
120954dfd506SHong 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 
122254dfd506SHong Zhang   header = &network->header[p];
122354dfd506SHong Zhang   cvalue = &network->cvalue[p];
122454dfd506SHong Zhang   if (header->ndata == header->maxcomps) {
122554dfd506SHong Zhang     /* Reached limit so resize header component arrays */
122654dfd506SHong Zhang     header->maxcomps += 2;
122754dfd506SHong Zhang 
122854dfd506SHong Zhang     /* Allocate arrays for component information and value */
122954dfd506SHong Zhang     ierr = PetscCalloc5(header->maxcomps,&compsize,header->maxcomps,&compkey,header->maxcomps,&compoffset,header->maxcomps,&compnvar,header->maxcomps,&compoffsetvarrel);CHKERRQ(ierr);
123054dfd506SHong Zhang     ierr = PetscMalloc1(header->maxcomps,&compdata);CHKERRQ(ierr);
123154dfd506SHong Zhang 
123254dfd506SHong Zhang     /* Recalculate header size */
123354dfd506SHong Zhang     header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt);
123454dfd506SHong Zhang 
123554dfd506SHong Zhang     header->hsize /= sizeof(DMNetworkComponentGenericDataType);
123654dfd506SHong Zhang 
123754dfd506SHong Zhang     /* Copy over component info */
123854dfd506SHong Zhang     ierr = PetscMemcpy(compsize,header->size,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
123954dfd506SHong Zhang     ierr = PetscMemcpy(compkey,header->key,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
124054dfd506SHong Zhang     ierr = PetscMemcpy(compoffset,header->offset,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
124154dfd506SHong Zhang     ierr = PetscMemcpy(compnvar,header->nvar,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
124254dfd506SHong Zhang     ierr = PetscMemcpy(compoffsetvarrel,header->offsetvarrel,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
124354dfd506SHong Zhang 
124454dfd506SHong Zhang     /* Copy over component data pointers */
124554dfd506SHong Zhang     ierr = PetscMemcpy(compdata,cvalue->data,header->ndata*sizeof(void*));CHKERRQ(ierr);
124654dfd506SHong Zhang 
124754dfd506SHong Zhang     /* Free old arrays */
124854dfd506SHong Zhang     ierr = PetscFree5(header->size,header->key,header->offset,header->nvar,header->offsetvarrel);CHKERRQ(ierr);
124954dfd506SHong Zhang     ierr = PetscFree(cvalue->data);CHKERRQ(ierr);
125054dfd506SHong Zhang 
125154dfd506SHong Zhang     /* Update pointers */
125254dfd506SHong Zhang     header->size = compsize;
125354dfd506SHong Zhang     header->key  = compkey;
125454dfd506SHong Zhang     header->offset = compoffset;
125554dfd506SHong Zhang     header->nvar = compnvar;
125654dfd506SHong Zhang     header->offsetvarrel = compoffsetvarrel;
125754dfd506SHong Zhang 
125854dfd506SHong Zhang     cvalue->data = compdata;
125954dfd506SHong Zhang 
126054dfd506SHong Zhang     /* Update DataSection Dofs */
126154dfd506SHong 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 */
126254dfd506SHong Zhang     PetscInt additional_size = (5*(header->maxcomps - header->ndata)*sizeof(PetscInt))/sizeof(DMNetworkComponentGenericDataType);
126354dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,p,additional_size);CHKERRQ(ierr);
126454dfd506SHong Zhang   }
126554dfd506SHong Zhang   header = &network->header[p];
126654dfd506SHong Zhang   cvalue = &network->cvalue[p];
126754dfd506SHong Zhang 
126854dfd506SHong 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) {
132254dfd506SHong 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];
132854dfd506SHong 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);
139654dfd506SHong 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];
140254dfd506SHong Zhang     DMNetworkComponentHeader headerinfo=(DMNetworkComponentHeader)(componentdataarray+offsetp);
140354dfd506SHong Zhang     ierr = PetscMemcpy(headerinfo,header,sizeof(struct _p_DMNetworkComponentHeader));CHKERRQ(ierr);
140454dfd506SHong Zhang     PetscInt *headerarr = (PetscInt*)(headerinfo+1);
140554dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->size,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
140654dfd506SHong Zhang     headerarr += header->maxcomps;
140754dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->key,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
140854dfd506SHong Zhang     headerarr += header->maxcomps;
140954dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offset,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
141054dfd506SHong Zhang     headerarr += header->maxcomps;
141154dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->nvar,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
141254dfd506SHong Zhang     headerarr += header->maxcomps;
141354dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offsetvarrel,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
141454dfd506SHong 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++) {
142054dfd506SHong 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 
1605*5b3f975aSHong Zhang   Options Database Key:
1606*5b3f975aSHong Zhang + -dmnetwork_view - Calls DMView() at the conclusion of DMSetUp()
1607*5b3f975aSHong Zhang - -dmnetwork_view_distributed - Calls DMView() at the conclusion of DMNetworkDistribute()
1608*5b3f975aSHong Zhang 
16095f2c45f1SShri Abhyankar   Notes:
16108b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
16115f2c45f1SShri Abhyankar 
16125f2c45f1SShri Abhyankar   Level: intermediate
16135f2c45f1SShri Abhyankar 
16142bf73ac6SHong Zhang .seealso: DMNetworkCreate()
16155f2c45f1SShri Abhyankar @*/
1616d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
16175f2c45f1SShri Abhyankar {
1618d3464fd4SAdrian Maldonado   MPI_Comm       comm;
16195f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1620d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1621d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1622d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1623caf410d2SHong Zhang   PetscSF        pointsf=NULL;
16245f2c45f1SShri Abhyankar   DM             newDM;
16252bf73ac6SHong Zhang   PetscInt       j,e,v,offset,*subnetvtx,nsubnet,gidx,svtx_idx,nv;
16262bf73ac6SHong Zhang   PetscInt       to_net,from_net,*svto;
162751ac5effSHong Zhang   PetscPartitioner         part;
1628b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
16295f2c45f1SShri Abhyankar 
16305f2c45f1SShri Abhyankar   PetscFunctionBegin;
1631d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1632ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1633d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1634d3464fd4SAdrian Maldonado 
1635*5b3f975aSHong Zhang   if (overlap) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"overlap %D != 0 is not supported yet",overlap);
1636*5b3f975aSHong Zhang 
16372bf73ac6SHong 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. */
1638d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
16395f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
164054dfd506SHong Zhang   newDMnetwork->max_comps_registered = oldDMnetwork->max_comps_registered;
164154dfd506SHong Zhang   ierr = PetscMalloc1(newDMnetwork->max_comps_registered,&newDMnetwork->component);CHKERRQ(ierr);
164251ac5effSHong Zhang 
164351ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
164451ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
164551ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
164651ac5effSHong Zhang 
16472bf73ac6SHong Zhang   /* Distribute plex dm */
164880cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
164951ac5effSHong Zhang 
16505f2c45f1SShri Abhyankar   /* Distribute dof section */
16512bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DofSection);CHKERRQ(ierr);
16525f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
165351ac5effSHong Zhang 
16545f2c45f1SShri Abhyankar   /* Distribute data and associated section */
16552bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DataSection);CHKERRQ(ierr);
165631da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
165724121865SAdrian Maldonado 
16585f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
16595f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
16605f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
16615f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
16626fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
16636fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
16645f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
16652bf73ac6SHong Zhang   newDMnetwork->svtable   = oldDMnetwork->svtable;
16662bf73ac6SHong Zhang   oldDMnetwork->svtable   = NULL;
166724121865SAdrian Maldonado 
16681bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
166992fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1670e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
16715f2c45f1SShri Abhyankar 
1672b9c6e19dSShri Abhyankar   /* Set up subnetwork info in the newDM */
16732bf73ac6SHong Zhang   newDMnetwork->Nsubnet = oldDMnetwork->Nsubnet;
16742bf73ac6SHong Zhang   newDMnetwork->Nsvtx   = oldDMnetwork->Nsvtx;
16752bf73ac6SHong Zhang   oldDMnetwork->Nsvtx   = 0;
16762bf73ac6SHong Zhang   newDMnetwork->svtx    = oldDMnetwork->svtx; /* global vertices! */
16772bf73ac6SHong Zhang   oldDMnetwork->svtx    = NULL;
16782bf73ac6SHong Zhang   ierr = PetscCalloc1(newDMnetwork->Nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
16792bf73ac6SHong Zhang 
16802bf73ac6SHong Zhang   /* Copy over the global number of vertices and edges in each subnetwork.
16812bf73ac6SHong Zhang      Note: these are calculated in DMNetworkLayoutSetUp()
1682b9c6e19dSShri Abhyankar   */
16832bf73ac6SHong Zhang   nsubnet = newDMnetwork->Nsubnet;
16842bf73ac6SHong Zhang   for (j = 0; j < nsubnet; j++) {
1685b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1686b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1687b9c6e19dSShri Abhyankar   }
1688b9c6e19dSShri Abhyankar 
168954dfd506SHong Zhang   PetscMPIInt rank;
169054dfd506SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
169154dfd506SHong Zhang 
16922bf73ac6SHong Zhang   /* Get local nedges and nvtx for subnetworks */
1693b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1694b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
169554dfd506SHong Zhang     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
169654dfd506SHong Zhang     /* Update pointers */
169754dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
169854dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
169954dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
170054dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
170154dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
170254dfd506SHong Zhang 
1703b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1704b9c6e19dSShri Abhyankar   }
1705b9c6e19dSShri Abhyankar 
1706b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1707b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1708b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
17092bf73ac6SHong Zhang 
171054dfd506SHong Zhang     /* Update pointers */
171154dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
171254dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
171354dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
171454dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
171554dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
171654dfd506SHong Zhang 
17172bf73ac6SHong Zhang     /* shared vertices: use gidx = header->index to check if v is a shared vertex */
17182bf73ac6SHong Zhang     gidx = header->index;
17192bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
17202bf73ac6SHong Zhang     svtx_idx--;
17212bf73ac6SHong Zhang 
17222bf73ac6SHong Zhang     if (svtx_idx < 0) { /* not a shared vertex */
1723b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].nvtx++;
17242bf73ac6SHong Zhang     } else { /* a shared vertex belongs to more than one subnetworks, it is being counted by multiple subnets */
17252bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
17262bf73ac6SHong Zhang       newDMnetwork->subnet[from_net].nvtx++;
17272bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
17282bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
17292bf73ac6SHong Zhang         to_net = svto[0];
17302bf73ac6SHong Zhang         newDMnetwork->subnet[to_net].nvtx++;
17312bf73ac6SHong Zhang       }
17322bf73ac6SHong Zhang     }
1733b9c6e19dSShri Abhyankar   }
1734b9c6e19dSShri Abhyankar 
17352bf73ac6SHong Zhang   /* Get total local nvtx for subnetworks */
17362bf73ac6SHong Zhang   nv = 0;
17372bf73ac6SHong Zhang   for (j=0; j<nsubnet; j++) nv += newDMnetwork->subnet[j].nvtx;
17382bf73ac6SHong Zhang   nv += newDMnetwork->Nsvtx;
1739caf410d2SHong Zhang 
17402bf73ac6SHong Zhang   /* Now create the vertices and edge arrays for the subnetworks */
17412bf73ac6SHong Zhang   ierr = PetscCalloc1(nv,&subnetvtx);CHKERRQ(ierr);
17422bf73ac6SHong Zhang   newDMnetwork->subnetvtx = subnetvtx;
17432bf73ac6SHong Zhang 
17442bf73ac6SHong Zhang   for (j=0; j<nsubnet; j++) {
1745b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr);
1746caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1747caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1748caf410d2SHong Zhang 
17492bf73ac6SHong 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. */
1750b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1751b9c6e19dSShri Abhyankar   }
17522bf73ac6SHong Zhang   newDMnetwork->svertices = subnetvtx;
1753b9c6e19dSShri Abhyankar 
17542bf73ac6SHong Zhang   /* Set the edges and vertices in each subnetwork */
1755b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1756b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1757b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1758b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1759b9c6e19dSShri Abhyankar   }
1760b9c6e19dSShri Abhyankar 
17612bf73ac6SHong Zhang   nv = 0;
1762b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1763b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1764b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
17652bf73ac6SHong Zhang 
17662bf73ac6SHong Zhang     /* coupling vertices: use gidx = header->index to check if v is a coupling vertex */
17672bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,header->index+1,&svtx_idx);CHKERRQ(ierr);
17682bf73ac6SHong Zhang     svtx_idx--;
17692bf73ac6SHong Zhang     if (svtx_idx < 0) {
1770b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
17712bf73ac6SHong Zhang     } else { /* a shared vertex */
17722bf73ac6SHong Zhang       newDMnetwork->svertices[nv++] = v;
17732bf73ac6SHong Zhang 
17742bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
17752bf73ac6SHong Zhang       newDMnetwork->subnet[from_net].vertices[newDMnetwork->subnet[from_net].nvtx++] = v;
17762bf73ac6SHong Zhang 
17772bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
17782bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
17792bf73ac6SHong Zhang         to_net = svto[0];
17802bf73ac6SHong Zhang         newDMnetwork->subnet[to_net].vertices[newDMnetwork->subnet[to_net].nvtx++] = v;
1781b9c6e19dSShri Abhyankar       }
17822bf73ac6SHong Zhang     }
17832bf73ac6SHong Zhang   }
17842bf73ac6SHong Zhang   newDMnetwork->nsvtx = nv;   /* num of local shared vertices */
1785b9c6e19dSShri Abhyankar 
1786caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
178722bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1788caf410d2SHong Zhang 
17892bf73ac6SHong Zhang   /* Free spaces */
179024121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
1791d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
17922bf73ac6SHong Zhang 
1793*5b3f975aSHong Zhang   /* View distributed dmnetwork */
1794*5b3f975aSHong Zhang   ierr = DMViewFromOptions(newDM,NULL,"-dmnetwork_view_distributed");CHKERRQ(ierr);
1795*5b3f975aSHong Zhang 
1796d3464fd4SAdrian Maldonado   *dm  = newDM;
17975f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
17985f2c45f1SShri Abhyankar }
17995f2c45f1SShri Abhyankar 
180024121865SAdrian Maldonado /*@C
18012bf73ac6SHong Zhang   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering
18022bf73ac6SHong Zhang 
18032bf73ac6SHong Zhang  Collective
180424121865SAdrian Maldonado 
180524121865SAdrian Maldonado   Input Parameters:
18069dddd249SSatish Balay + mainSF - the original SF structure
180724121865SAdrian Maldonado - map - a ISLocalToGlobal mapping that contains the subset of points
180824121865SAdrian Maldonado 
180924121865SAdrian Maldonado   Output Parameters:
18109dddd249SSatish Balay . subSF - a subset of the mainSF for the desired subset.
1811ee300463SSatish Balay 
1812ee300463SSatish Balay   Level: intermediate
18137d928bffSSatish Balay @*/
18149dddd249SSatish Balay PetscErrorCode PetscSFGetSubSF(PetscSF mainsf,ISLocalToGlobalMapping map,PetscSF *subSF)
18152bf73ac6SHong Zhang {
181624121865SAdrian Maldonado   PetscErrorCode        ierr;
181724121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
181824121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
181924121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
182024121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
182124121865SAdrian Maldonado   const PetscInt        *ilocal;
182224121865SAdrian Maldonado   const PetscSFNode     *iremote;
182324121865SAdrian Maldonado 
182424121865SAdrian Maldonado   PetscFunctionBegin;
18259dddd249SSatish Balay   ierr = PetscSFGetGraph(mainsf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
182624121865SAdrian Maldonado 
182724121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
182824121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
182924121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
183024121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
183124121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
183224121865SAdrian Maldonado   }
183324121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
183424121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
183524121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
183624121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
1837ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
1838ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
183924121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
18404b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
18414b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
184224121865SAdrian Maldonado   nleaves_sub = 0;
184324121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
184424121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
184524121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
18464b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
184724121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
184824121865SAdrian Maldonado       nleaves_sub += 1;
184924121865SAdrian Maldonado     }
185024121865SAdrian Maldonado   }
185124121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
185224121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
185324121865SAdrian Maldonado 
185424121865SAdrian Maldonado   /* Create new subSF */
185524121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
185624121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
18574b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
185824121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
18594b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
186024121865SAdrian Maldonado   PetscFunctionReturn(0);
186124121865SAdrian Maldonado }
186224121865SAdrian Maldonado 
18635f2c45f1SShri Abhyankar /*@C
18645f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
18655f2c45f1SShri Abhyankar 
18665f2c45f1SShri Abhyankar   Not Collective
18675f2c45f1SShri Abhyankar 
18685f2c45f1SShri Abhyankar   Input Parameters:
18692bf73ac6SHong Zhang + dm - the DMNetwork object
18705f2c45f1SShri Abhyankar - p  - the vertex point
18715f2c45f1SShri Abhyankar 
1872fd292e60Sprj-   Output Parameters:
18735f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
18742bf73ac6SHong Zhang - edges  - list of edge points
18755f2c45f1SShri Abhyankar 
187697bb938eSShri Abhyankar   Level: beginner
18775f2c45f1SShri Abhyankar 
18785f2c45f1SShri Abhyankar   Fortran Notes:
18795f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
18805f2c45f1SShri Abhyankar   include petsc.h90 in your code.
18815f2c45f1SShri Abhyankar 
18822bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetConnectedVertices()
18835f2c45f1SShri Abhyankar @*/
18845f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
18855f2c45f1SShri Abhyankar {
18865f2c45f1SShri Abhyankar   PetscErrorCode ierr;
18875f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
18885f2c45f1SShri Abhyankar 
18895f2c45f1SShri Abhyankar   PetscFunctionBegin;
18905f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
1891a9b4a83eSHong Zhang   if (edges) {ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);}
18925f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18935f2c45f1SShri Abhyankar }
18945f2c45f1SShri Abhyankar 
18955f2c45f1SShri Abhyankar /*@C
1896d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
18975f2c45f1SShri Abhyankar 
18985f2c45f1SShri Abhyankar   Not Collective
18995f2c45f1SShri Abhyankar 
19005f2c45f1SShri Abhyankar   Input Parameters:
19012bf73ac6SHong Zhang + dm - the DMNetwork object
19025f2c45f1SShri Abhyankar - p - the edge point
19035f2c45f1SShri Abhyankar 
1904fd292e60Sprj-   Output Parameters:
19055f2c45f1SShri Abhyankar . vertices - vertices connected to this edge
19065f2c45f1SShri Abhyankar 
190797bb938eSShri Abhyankar   Level: beginner
19085f2c45f1SShri Abhyankar 
19095f2c45f1SShri Abhyankar   Fortran Notes:
19105f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
19115f2c45f1SShri Abhyankar   include petsc.h90 in your code.
19125f2c45f1SShri Abhyankar 
19132bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetSupportingEdges()
19145f2c45f1SShri Abhyankar @*/
1915d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
19165f2c45f1SShri Abhyankar {
19175f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19185f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19195f2c45f1SShri Abhyankar 
19205f2c45f1SShri Abhyankar   PetscFunctionBegin;
19215f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
19225f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19235f2c45f1SShri Abhyankar }
19245f2c45f1SShri Abhyankar 
19255f2c45f1SShri Abhyankar /*@
19262bf73ac6SHong Zhang   DMNetworkIsSharedVertex - Returns TRUE if the vertex is shared by subnetworks
19272bf73ac6SHong Zhang 
19282bf73ac6SHong Zhang   Not Collective
19292bf73ac6SHong Zhang 
19302bf73ac6SHong Zhang   Input Parameters:
19312bf73ac6SHong Zhang + dm - the DMNetwork object
19322bf73ac6SHong Zhang - p - the vertex point
19332bf73ac6SHong Zhang 
19342bf73ac6SHong Zhang   Output Parameter:
19352bf73ac6SHong Zhang . flag - TRUE if the vertex is shared by subnetworks
19362bf73ac6SHong Zhang 
19372bf73ac6SHong Zhang   Level: beginner
19382bf73ac6SHong Zhang 
19392bf73ac6SHong Zhang .seealso: DMNetworkAddSharedVertices(), DMNetworkIsGhostVertex()
19402bf73ac6SHong Zhang @*/
19412bf73ac6SHong Zhang PetscErrorCode DMNetworkIsSharedVertex(DM dm,PetscInt p,PetscBool *flag)
19422bf73ac6SHong Zhang {
19432bf73ac6SHong Zhang   PetscErrorCode ierr;
19442bf73ac6SHong Zhang   PetscInt       i;
19452bf73ac6SHong Zhang 
19462bf73ac6SHong Zhang   PetscFunctionBegin;
19472bf73ac6SHong Zhang   *flag = PETSC_FALSE;
19482bf73ac6SHong Zhang 
19492bf73ac6SHong Zhang   if (dm->setupcalled) { /* DMNetworkGetGlobalVertexIndex() requires DMSetUp() be called */
19502bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
19512bf73ac6SHong Zhang     PetscInt       gidx;
19522bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVertexIndex(dm,p,&gidx);CHKERRQ(ierr);
19532bf73ac6SHong Zhang     ierr = PetscTableFind(network->svtable,gidx+1,&i);CHKERRQ(ierr);
19542bf73ac6SHong Zhang     if (i) *flag = PETSC_TRUE;
19552bf73ac6SHong Zhang   } else { /* would be removed? */
19562bf73ac6SHong Zhang     PetscInt       nv;
19572bf73ac6SHong Zhang     const PetscInt *vtx;
19582bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nv,&vtx);CHKERRQ(ierr);
19592bf73ac6SHong Zhang     for (i=0; i<nv; i++) {
19602bf73ac6SHong Zhang       if (p == vtx[i]) {
19612bf73ac6SHong Zhang         *flag = PETSC_TRUE;
19622bf73ac6SHong Zhang         break;
19632bf73ac6SHong Zhang       }
19642bf73ac6SHong Zhang     }
19652bf73ac6SHong Zhang   }
19662bf73ac6SHong Zhang   PetscFunctionReturn(0);
19672bf73ac6SHong Zhang }
19682bf73ac6SHong Zhang 
19692bf73ac6SHong Zhang /*@
19705f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
19715f2c45f1SShri Abhyankar 
19725f2c45f1SShri Abhyankar   Not Collective
19735f2c45f1SShri Abhyankar 
19745f2c45f1SShri Abhyankar   Input Parameters:
19752bf73ac6SHong Zhang + dm - the DMNetwork object
1976a2b725a8SWilliam Gropp - p - the vertex point
19775f2c45f1SShri Abhyankar 
19785f2c45f1SShri Abhyankar   Output Parameter:
19795f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
19805f2c45f1SShri Abhyankar 
198197bb938eSShri Abhyankar   Level: beginner
19825f2c45f1SShri Abhyankar 
19832bf73ac6SHong Zhang .seealso: DMNetworkGetConnectedVertices(), DMNetworkGetVertexRange(), DMNetworkIsSharedVertex()
19845f2c45f1SShri Abhyankar @*/
19855f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
19865f2c45f1SShri Abhyankar {
19875f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19885f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19895f2c45f1SShri Abhyankar   PetscInt       offsetg;
19905f2c45f1SShri Abhyankar   PetscSection   sectiong;
19915f2c45f1SShri Abhyankar 
19925f2c45f1SShri Abhyankar   PetscFunctionBegin;
19935f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
1994e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
19955f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
19965f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
19975f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19985f2c45f1SShri Abhyankar }
19995f2c45f1SShri Abhyankar 
20005f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
20015f2c45f1SShri Abhyankar {
20025f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20035f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
20045f2c45f1SShri Abhyankar 
20055f2c45f1SShri Abhyankar   PetscFunctionBegin;
20065f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
20075f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
20085f2c45f1SShri Abhyankar 
200992fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
2010e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
20119e1d080bSHong Zhang 
20129e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
2013*5b3f975aSHong Zhang 
2014*5b3f975aSHong Zhang   /* View dmnetwork */
2015*5b3f975aSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dmnetwork_view");CHKERRQ(ierr);
20165f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20175f2c45f1SShri Abhyankar }
20185f2c45f1SShri Abhyankar 
20191ad426b7SHong Zhang /*@
202017df6e9eSHong Zhang   DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
20211ad426b7SHong Zhang       -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
20221ad426b7SHong Zhang 
20231ad426b7SHong Zhang   Collective
20241ad426b7SHong Zhang 
20251ad426b7SHong Zhang   Input Parameters:
20262bf73ac6SHong Zhang + dm - the DMNetwork object
202783b2e829SHong Zhang . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
202883b2e829SHong Zhang - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
20291ad426b7SHong Zhang 
20301ad426b7SHong Zhang  Level: intermediate
20311ad426b7SHong Zhang 
20321ad426b7SHong Zhang @*/
203383b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
20341ad426b7SHong Zhang {
20351ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
20368675203cSHong Zhang   PetscErrorCode ierr;
203766b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
20381ad426b7SHong Zhang 
20391ad426b7SHong Zhang   PetscFunctionBegin;
204083b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
204183b2e829SHong Zhang   network->userVertexJacobian = vflg;
20428675203cSHong Zhang 
20438675203cSHong Zhang   if (eflg && !network->Je) {
20448675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
20458675203cSHong Zhang   }
20468675203cSHong Zhang 
204766b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
20488675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
204966b4e0ffSHong Zhang     PetscInt       nedges_total;
20508675203cSHong Zhang     const PetscInt *edges;
20518675203cSHong Zhang 
20528675203cSHong Zhang     /* count nvertex_total */
20538675203cSHong Zhang     nedges_total = 0;
20548675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
20558675203cSHong Zhang 
20568675203cSHong Zhang     vptr[0] = 0;
20578675203cSHong Zhang     for (i=0; i<nVertices; i++) {
20588675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
20598675203cSHong Zhang       nedges_total += nedges;
20608675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
20618675203cSHong Zhang     }
20628675203cSHong Zhang 
20638675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
20648675203cSHong Zhang     network->Jvptr = vptr;
20658675203cSHong Zhang   }
20661ad426b7SHong Zhang   PetscFunctionReturn(0);
20671ad426b7SHong Zhang }
20681ad426b7SHong Zhang 
20691ad426b7SHong Zhang /*@
207083b2e829SHong Zhang   DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
207183b2e829SHong Zhang 
207283b2e829SHong Zhang   Not Collective
207383b2e829SHong Zhang 
207483b2e829SHong Zhang   Input Parameters:
20752bf73ac6SHong Zhang + dm - the DMNetwork object
207683b2e829SHong Zhang . p - the edge point
20773e97b6e8SHong Zhang - J - array (size = 3) of Jacobian submatrices for this edge point:
20783e97b6e8SHong Zhang         J[0]: this edge
2079d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
208083b2e829SHong Zhang 
208197bb938eSShri Abhyankar   Level: advanced
208283b2e829SHong Zhang 
20832bf73ac6SHong Zhang .seealso: DMNetworkVertexSetMatrix()
208483b2e829SHong Zhang @*/
208583b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
208683b2e829SHong Zhang {
208783b2e829SHong Zhang   DM_Network *network=(DM_Network*)dm->data;
208883b2e829SHong Zhang 
208983b2e829SHong Zhang   PetscFunctionBegin;
20908675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
20918675203cSHong Zhang 
20928675203cSHong Zhang   if (J) {
2093883e35e8SHong Zhang     network->Je[3*p]   = J[0];
2094883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
2095883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
20968675203cSHong Zhang   }
209783b2e829SHong Zhang   PetscFunctionReturn(0);
209883b2e829SHong Zhang }
209983b2e829SHong Zhang 
210083b2e829SHong Zhang /*@
210176ddfea5SHong Zhang   DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
21021ad426b7SHong Zhang 
21031ad426b7SHong Zhang   Not Collective
21041ad426b7SHong Zhang 
21051ad426b7SHong Zhang   Input Parameters:
21061ad426b7SHong Zhang + dm - The DMNetwork object
21071ad426b7SHong Zhang . p - the vertex point
21083e97b6e8SHong Zhang - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
21093e97b6e8SHong Zhang         J[0]:       this vertex
21103e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
21113e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
21121ad426b7SHong Zhang 
211397bb938eSShri Abhyankar   Level: advanced
21141ad426b7SHong Zhang 
21152bf73ac6SHong Zhang .seealso: DMNetworkEdgeSetMatrix()
21161ad426b7SHong Zhang @*/
2117883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
21185f2c45f1SShri Abhyankar {
21195f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21205f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
21218675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
2122883e35e8SHong Zhang   const PetscInt *edges;
21235f2c45f1SShri Abhyankar 
21245f2c45f1SShri Abhyankar   PetscFunctionBegin;
21258675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
2126883e35e8SHong Zhang 
21278675203cSHong Zhang   if (J) {
2128883e35e8SHong Zhang     vptr = network->Jvptr;
21293e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
21303e97b6e8SHong Zhang 
21313e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
2132883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
2133883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
21348675203cSHong Zhang   }
2135883e35e8SHong Zhang   PetscFunctionReturn(0);
2136883e35e8SHong Zhang }
2137883e35e8SHong Zhang 
2138e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
21395cf7da58SHong Zhang {
21405cf7da58SHong Zhang   PetscErrorCode ierr;
21415cf7da58SHong Zhang   PetscInt       j;
21425cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
21435cf7da58SHong Zhang 
21445cf7da58SHong Zhang   PetscFunctionBegin;
21455cf7da58SHong Zhang   if (!ghost) {
21465cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
21475cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
21485cf7da58SHong Zhang     }
21495cf7da58SHong Zhang   } else {
21505cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
21515cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
21525cf7da58SHong Zhang     }
21535cf7da58SHong Zhang   }
21545cf7da58SHong Zhang   PetscFunctionReturn(0);
21555cf7da58SHong Zhang }
21565cf7da58SHong Zhang 
2157e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
21585cf7da58SHong Zhang {
21595cf7da58SHong Zhang   PetscErrorCode ierr;
21605cf7da58SHong Zhang   PetscInt       j,ncols_u;
21615cf7da58SHong Zhang   PetscScalar    val;
21625cf7da58SHong Zhang 
21635cf7da58SHong Zhang   PetscFunctionBegin;
21645cf7da58SHong Zhang   if (!ghost) {
21655cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
21665cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
21675cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
21685cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
21695cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
21705cf7da58SHong Zhang     }
21715cf7da58SHong Zhang   } else {
21725cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
21735cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
21745cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
21755cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
21765cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
21775cf7da58SHong Zhang     }
21785cf7da58SHong Zhang   }
21795cf7da58SHong Zhang   PetscFunctionReturn(0);
21805cf7da58SHong Zhang }
21815cf7da58SHong Zhang 
2182e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
21835cf7da58SHong Zhang {
21845cf7da58SHong Zhang   PetscErrorCode ierr;
21855cf7da58SHong Zhang 
21865cf7da58SHong Zhang   PetscFunctionBegin;
21875cf7da58SHong Zhang   if (Ju) {
21885cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
21895cf7da58SHong Zhang   } else {
21905cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
21915cf7da58SHong Zhang   }
21925cf7da58SHong Zhang   PetscFunctionReturn(0);
21935cf7da58SHong Zhang }
21945cf7da58SHong Zhang 
2195e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2196883e35e8SHong Zhang {
2197883e35e8SHong Zhang   PetscErrorCode ierr;
2198883e35e8SHong Zhang   PetscInt       j,*cols;
2199883e35e8SHong Zhang   PetscScalar    *zeros;
2200883e35e8SHong Zhang 
2201883e35e8SHong Zhang   PetscFunctionBegin;
2202883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
2203883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
2204883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
2205883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
22061ad426b7SHong Zhang   PetscFunctionReturn(0);
22071ad426b7SHong Zhang }
2208a4e85ca8SHong Zhang 
2209e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
22103e97b6e8SHong Zhang {
22113e97b6e8SHong Zhang   PetscErrorCode ierr;
22123e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
22133e97b6e8SHong Zhang   const PetscInt *cols;
22143e97b6e8SHong Zhang   PetscScalar    zero=0.0;
22153e97b6e8SHong Zhang 
22163e97b6e8SHong Zhang   PetscFunctionBegin;
22173e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
22183e97b6e8SHong 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);
22193e97b6e8SHong Zhang 
22203e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
22213e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
22223e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
22233e97b6e8SHong Zhang       col = cols[j] + cstart;
22243e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
22253e97b6e8SHong Zhang     }
22263e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
22273e97b6e8SHong Zhang   }
22283e97b6e8SHong Zhang   PetscFunctionReturn(0);
22293e97b6e8SHong Zhang }
22301ad426b7SHong Zhang 
2231e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2232a4e85ca8SHong Zhang {
2233a4e85ca8SHong Zhang   PetscErrorCode ierr;
2234f4431b8cSHong Zhang 
2235a4e85ca8SHong Zhang   PetscFunctionBegin;
2236a4e85ca8SHong Zhang   if (Ju) {
2237a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2238a4e85ca8SHong Zhang   } else {
2239a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2240a4e85ca8SHong Zhang   }
2241a4e85ca8SHong Zhang   PetscFunctionReturn(0);
2242a4e85ca8SHong Zhang }
2243a4e85ca8SHong Zhang 
224424121865SAdrian 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.
224524121865SAdrian Maldonado */
224624121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
224724121865SAdrian Maldonado {
224824121865SAdrian Maldonado   PetscErrorCode ierr;
224924121865SAdrian Maldonado   PetscInt       i,size,dof;
225024121865SAdrian Maldonado   PetscInt       *glob2loc;
225124121865SAdrian Maldonado 
225224121865SAdrian Maldonado   PetscFunctionBegin;
225324121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
225424121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
225524121865SAdrian Maldonado 
225624121865SAdrian Maldonado   for (i = 0; i < size; i++) {
225724121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
225824121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
225924121865SAdrian Maldonado     glob2loc[i] = dof;
226024121865SAdrian Maldonado   }
226124121865SAdrian Maldonado 
226224121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
226324121865SAdrian Maldonado #if 0
226424121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
226524121865SAdrian Maldonado #endif
226624121865SAdrian Maldonado   PetscFunctionReturn(0);
226724121865SAdrian Maldonado }
226824121865SAdrian Maldonado 
226901ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
22709e1d080bSHong Zhang 
22719e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
22721ad426b7SHong Zhang {
22731ad426b7SHong Zhang   PetscErrorCode ierr;
22741ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
22759e1d080bSHong Zhang   PetscMPIInt    rank, size;
227624121865SAdrian Maldonado   PetscInt       eDof,vDof;
227724121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
22789e1d080bSHong Zhang   MPI_Comm       comm;
227924121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
228024121865SAdrian Maldonado 
22819e1d080bSHong Zhang   PetscFunctionBegin;
228224121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2283ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
2284ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
228524121865SAdrian Maldonado 
228624121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
228724121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
228824121865SAdrian Maldonado 
228901ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
229024121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
229124121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
229224121865SAdrian Maldonado 
229301ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
229424121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
229524121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
229624121865SAdrian Maldonado 
229701ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
229824121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
229924121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
230024121865SAdrian Maldonado 
230101ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
230224121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
230324121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
230424121865SAdrian Maldonado 
23053f6a6bdaSHong Zhang   bA[0][0] = j11;
23063f6a6bdaSHong Zhang   bA[0][1] = j12;
23073f6a6bdaSHong Zhang   bA[1][0] = j21;
23083f6a6bdaSHong Zhang   bA[1][1] = j22;
230924121865SAdrian Maldonado 
231024121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
231124121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
231224121865SAdrian Maldonado 
231324121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
231424121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
231524121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
231624121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
231724121865SAdrian Maldonado 
231824121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
231924121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
232024121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
232124121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
232224121865SAdrian Maldonado 
232301ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
232424121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
232524121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
232624121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
232724121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
232824121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
232924121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
233024121865SAdrian Maldonado 
233124121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
233224121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23339e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
233424121865SAdrian Maldonado 
233524121865SAdrian Maldonado   /* Free structures */
233624121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
233724121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
233824121865SAdrian Maldonado   PetscFunctionReturn(0);
23399e1d080bSHong Zhang }
23409e1d080bSHong Zhang 
23419e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
23429e1d080bSHong Zhang {
23439e1d080bSHong Zhang   PetscErrorCode ierr;
23449e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
23459e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
23469e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
23479e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
23489e1d080bSHong Zhang   Mat            Juser;
23499e1d080bSHong Zhang   PetscSection   sectionGlobal;
23509e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
23519e1d080bSHong Zhang   const PetscInt *edges,*cone;
23529e1d080bSHong Zhang   MPI_Comm       comm;
23539e1d080bSHong Zhang   MatType        mtype;
23549e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
23559e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
23569e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
23579e1d080bSHong Zhang 
23589e1d080bSHong Zhang   PetscFunctionBegin;
23599e1d080bSHong Zhang   mtype = dm->mattype;
23609e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
23619e1d080bSHong Zhang   if (isNest) {
23629e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
2363c6b011d8SStefano Zampini     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
23649e1d080bSHong Zhang     PetscFunctionReturn(0);
23659e1d080bSHong Zhang   }
23669e1d080bSHong Zhang 
23679e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
2368a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
23699e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
2370bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
23711ad426b7SHong Zhang     PetscFunctionReturn(0);
23721ad426b7SHong Zhang   }
23731ad426b7SHong Zhang 
2374bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
2375e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
2376bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
2377bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
23782a945128SHong Zhang 
23792a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
23802a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
238189898e50SHong Zhang 
238289898e50SHong Zhang   /* (1) Set matrix preallocation */
238389898e50SHong Zhang   /*------------------------------*/
2384840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2385840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
2386840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
2387840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
2388840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
2389840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
2390840c2264SHong Zhang 
239189898e50SHong Zhang   /* Set preallocation for edges */
239289898e50SHong Zhang   /*-----------------------------*/
2393840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
2394840c2264SHong Zhang 
2395bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
2396840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
2397840c2264SHong Zhang     /* Get row indices */
23982bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
23992bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
2400840c2264SHong Zhang     if (nrows) {
2401840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
2402840c2264SHong Zhang 
24035cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
2404d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2405840c2264SHong Zhang       for (v=0; v<2; v++) {
24062bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
2407840c2264SHong Zhang 
24088675203cSHong Zhang         if (network->Je) {
2409840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
24108675203cSHong Zhang         } else Juser = NULL;
2411840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
24125cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2413840c2264SHong Zhang       }
2414840c2264SHong Zhang 
241589898e50SHong Zhang       /* Set preallocation for edge self */
2416840c2264SHong Zhang       cstart = rstart;
24178675203cSHong Zhang       if (network->Je) {
2418840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
24198675203cSHong Zhang       } else Juser = NULL;
24205cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2421840c2264SHong Zhang     }
2422840c2264SHong Zhang   }
2423840c2264SHong Zhang 
242489898e50SHong Zhang   /* Set preallocation for vertices */
242589898e50SHong Zhang   /*--------------------------------*/
2426840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
24278675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
2428840c2264SHong Zhang 
2429840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
2430840c2264SHong Zhang     /* Get row indices */
24312bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
24322bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
2433840c2264SHong Zhang     if (!nrows) continue;
2434840c2264SHong Zhang 
2435bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2436bdcb62a2SHong Zhang     if (ghost) {
2437bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2438bdcb62a2SHong Zhang     } else {
2439bdcb62a2SHong Zhang       rows_v = rows;
2440bdcb62a2SHong Zhang     }
2441bdcb62a2SHong Zhang 
2442bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2443840c2264SHong Zhang 
2444840c2264SHong Zhang     /* Get supporting edges and connected vertices */
2445840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2446840c2264SHong Zhang 
2447840c2264SHong Zhang     for (e=0; e<nedges; e++) {
2448840c2264SHong Zhang       /* Supporting edges */
24492bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
24502bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2451840c2264SHong Zhang 
24528675203cSHong Zhang       if (network->Jv) {
2453840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
24548675203cSHong Zhang       } else Juser = NULL;
2455bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2456840c2264SHong Zhang 
2457840c2264SHong Zhang       /* Connected vertices */
2458d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
2459840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
2460840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
2461840c2264SHong Zhang 
24622bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2463840c2264SHong Zhang 
24648675203cSHong Zhang       if (network->Jv) {
2465840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
24668675203cSHong Zhang       } else Juser = NULL;
2467e102a522SHong Zhang       if (ghost_vc||ghost) {
2468e102a522SHong Zhang         ghost2 = PETSC_TRUE;
2469e102a522SHong Zhang       } else {
2470e102a522SHong Zhang         ghost2 = PETSC_FALSE;
2471e102a522SHong Zhang       }
2472e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
2473840c2264SHong Zhang     }
2474840c2264SHong Zhang 
247589898e50SHong Zhang     /* Set preallocation for vertex self */
2476840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2477840c2264SHong Zhang     if (!ghost) {
24782bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
24798675203cSHong Zhang       if (network->Jv) {
2480840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
24818675203cSHong Zhang       } else Juser = NULL;
2482bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2483840c2264SHong Zhang     }
2484bdcb62a2SHong Zhang     if (ghost) {
2485bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2486bdcb62a2SHong Zhang     }
2487840c2264SHong Zhang   }
2488840c2264SHong Zhang 
2489840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
2490840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
24915cf7da58SHong Zhang 
24925cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
24935cf7da58SHong Zhang 
24945cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
2495840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
2496840c2264SHong Zhang 
2497840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
2498840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
2499840c2264SHong Zhang   for (j=0; j<localSize; j++) {
2500e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
2501e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
2502840c2264SHong Zhang   }
2503840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
2504840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
2505840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
2506840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
2507840c2264SHong Zhang 
25085cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
25095cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
25105cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
25115cf7da58SHong Zhang 
25125cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
25135cf7da58SHong Zhang 
251489898e50SHong Zhang   /* (2) Set matrix entries for edges */
251589898e50SHong Zhang   /*----------------------------------*/
25161ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
2517bfbc38dcSHong Zhang     /* Get row indices */
25182bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
25192bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
25204b976069SHong Zhang     if (nrows) {
252117df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
25221ad426b7SHong Zhang 
2523bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
2524d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2525bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
25262bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVecOffset(dm,cone[v],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25272bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
25283e97b6e8SHong Zhang 
25298675203cSHong Zhang         if (network->Je) {
2530a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
25318675203cSHong Zhang         } else Juser = NULL;
2532a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2533bfbc38dcSHong Zhang       }
253417df6e9eSHong Zhang 
2535bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
25363e97b6e8SHong Zhang       cstart = rstart;
25378675203cSHong Zhang       if (network->Je) {
2538a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
25398675203cSHong Zhang       } else Juser = NULL;
2540a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
25411ad426b7SHong Zhang     }
25424b976069SHong Zhang   }
25431ad426b7SHong Zhang 
2544bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
254583b2e829SHong Zhang   /*---------------------------------*/
25461ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2547bfbc38dcSHong Zhang     /* Get row indices */
25482bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
25492bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
25504b976069SHong Zhang     if (!nrows) continue;
2551596e729fSHong Zhang 
2552bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2553bdcb62a2SHong Zhang     if (ghost) {
2554bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2555bdcb62a2SHong Zhang     } else {
2556bdcb62a2SHong Zhang       rows_v = rows;
2557bdcb62a2SHong Zhang     }
2558bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2559596e729fSHong Zhang 
2560bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2561596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2562596e729fSHong Zhang 
2563596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2564bfbc38dcSHong Zhang       /* Supporting edges */
25652bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25662bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2567596e729fSHong Zhang 
25688675203cSHong Zhang       if (network->Jv) {
2569a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
25708675203cSHong Zhang       } else Juser = NULL;
2571bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2572596e729fSHong Zhang 
2573bfbc38dcSHong Zhang       /* Connected vertices */
2574d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
25752a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
25762a945128SHong Zhang 
25772bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,vc,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25782bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2579a4e85ca8SHong Zhang 
25808675203cSHong Zhang       if (network->Jv) {
2581a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
25828675203cSHong Zhang       } else Juser = NULL;
2583bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2584596e729fSHong Zhang     }
2585596e729fSHong Zhang 
2586bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
25871ad426b7SHong Zhang     if (!ghost) {
25882bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25898675203cSHong Zhang       if (network->Jv) {
2590a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
25918675203cSHong Zhang       } else Juser = NULL;
2592bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2593bdcb62a2SHong Zhang     }
2594bdcb62a2SHong Zhang     if (ghost) {
2595bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2596bdcb62a2SHong Zhang     }
25971ad426b7SHong Zhang   }
2598a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2599bdcb62a2SHong Zhang 
26001ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
26011ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2602dd6f46cdSHong Zhang 
26035f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
26045f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26055f2c45f1SShri Abhyankar }
26065f2c45f1SShri Abhyankar 
26075f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
26085f2c45f1SShri Abhyankar {
26095f2c45f1SShri Abhyankar   PetscErrorCode ierr;
26105f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
261154dfd506SHong Zhang   PetscInt       j,np;
26125f2c45f1SShri Abhyankar 
26135f2c45f1SShri Abhyankar   PetscFunctionBegin;
26148415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
261583b2e829SHong Zhang   if (network->Je) {
261683b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
261783b2e829SHong Zhang   }
261883b2e829SHong Zhang   if (network->Jv) {
2619883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
262083b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
26211ad426b7SHong Zhang   }
262213c2a604SAdrian Maldonado 
262313c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
262413c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
262513c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2626f5427c60SHong Zhang   if (network->vltog) {
2627f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2628f5427c60SHong Zhang   }
262913c2a604SAdrian Maldonado   if (network->vertex.sf) {
263013c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
263113c2a604SAdrian Maldonado   }
263213c2a604SAdrian Maldonado   /* edge */
263313c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
263413c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
263513c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
263613c2a604SAdrian Maldonado   if (network->edge.sf) {
263713c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
263813c2a604SAdrian Maldonado   }
26395f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
26405f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
26415f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
264283b2e829SHong Zhang 
26432bf73ac6SHong Zhang   for (j=0; j<network->Nsvtx; j++) {
26442bf73ac6SHong Zhang     ierr = PetscFree(network->svtx[j].sv);CHKERRQ(ierr);
26452bf73ac6SHong Zhang   }
26462bf73ac6SHong Zhang   if (network->svtx) {ierr = PetscFree(network->svtx);CHKERRQ(ierr);}
26472bf73ac6SHong Zhang 
26482bf73ac6SHong Zhang   for (j=0; j<network->Nsubnet; j++) {
26492727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
26502727e31bSShri Abhyankar   }
26512bf73ac6SHong Zhang   if (network->subnetvtx) {ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr);}
2652caf410d2SHong Zhang 
26532bf73ac6SHong Zhang   ierr = PetscTableDestroy(&network->svtable);CHKERRQ(ierr);
2654e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
265554dfd506SHong Zhang   ierr = PetscFree(network->component);CHKERRQ(ierr);
26565f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
265754dfd506SHong Zhang 
265854dfd506SHong Zhang   if (network->header) {
265954dfd506SHong Zhang     np = network->pEnd - network->pStart;
266054dfd506SHong Zhang     for (j=0; j < np; j++) {
266154dfd506SHong 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);
266254dfd506SHong Zhang       ierr = PetscFree(network->cvalue[j].data);CHKERRQ(ierr);
266354dfd506SHong Zhang     }
2664caf410d2SHong Zhang     ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
266554dfd506SHong Zhang   }
26665f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
26675f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26685f2c45f1SShri Abhyankar }
26695f2c45f1SShri Abhyankar 
26705f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
26715f2c45f1SShri Abhyankar {
26725f2c45f1SShri Abhyankar   PetscErrorCode ierr;
2673caf410d2SHong Zhang   PetscBool      iascii;
2674caf410d2SHong Zhang   PetscMPIInt    rank;
26755f2c45f1SShri Abhyankar 
26765f2c45f1SShri Abhyankar   PetscFunctionBegin;
2677caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2678ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
2679caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2680caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2681caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2682caf410d2SHong Zhang   if (iascii) {
2683caf410d2SHong Zhang     const PetscInt *cone,*vtx,*edges;
26842bf73ac6SHong Zhang     PetscInt       vfrom,vto,i,j,nv,ne,ncv,p,nsubnet;
26852bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
2686caf410d2SHong Zhang 
26872bf73ac6SHong Zhang     nsubnet = network->Nsubnet; /* num of subnetworks */
26882bf73ac6SHong Zhang     if (!rank) {
26892bf73ac6SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  NSubnets: %D; NEdges: %D; NVertices: %D; NSharedVertices: %D.\n",nsubnet,network->NEdges,network->NVertices,network->Nsvtx);CHKERRQ(ierr);
26902bf73ac6SHong Zhang     }
26912bf73ac6SHong Zhang 
26922bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
2693caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
26942bf73ac6SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nEdges: %D; nVertices: %D; nSharedVertices: %D\n",rank,network->nEdges,network->nVertices,ncv);CHKERRQ(ierr);
2695caf410d2SHong Zhang 
2696caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
26972bf73ac6SHong Zhang       ierr = DMNetworkGetSubnetwork(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2698caf410d2SHong Zhang       if (ne) {
26992bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices(include shared vertices) %D\n",i,ne,nv);CHKERRQ(ierr);
2700caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2701caf410d2SHong Zhang           p = edges[j];
2702caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2703caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2704caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2705caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2706caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D ----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2707caf410d2SHong Zhang         }
2708caf410d2SHong Zhang       }
2709caf410d2SHong Zhang     }
27102bf73ac6SHong Zhang 
27112bf73ac6SHong Zhang     /* Shared vertices */
27122bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
27132bf73ac6SHong Zhang     if (ncv) {
27142bf73ac6SHong Zhang       SVtx       *svtx = network->svtx;
27152bf73ac6SHong Zhang       PetscInt    gidx,svtx_idx,nvto,vfrom_net,vfrom_idx,*svto;
27162bf73ac6SHong Zhang       PetscBool   ghost;
27172bf73ac6SHong Zhang       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     SharedVertices:\n");CHKERRQ(ierr);
27182bf73ac6SHong Zhang       for (i=0; i<ncv; i++) {
27192bf73ac6SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,vtx[i],&ghost);CHKERRQ(ierr);
27202bf73ac6SHong Zhang         if (ghost) continue;
27212bf73ac6SHong Zhang 
27222bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVertexIndex(dm,vtx[i],&gidx);CHKERRQ(ierr);
27232bf73ac6SHong Zhang         ierr = PetscTableFind(network->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
27242bf73ac6SHong Zhang         svtx_idx--;
27252bf73ac6SHong Zhang         nvto = svtx[svtx_idx].n;
27262bf73ac6SHong Zhang 
27272bf73ac6SHong Zhang         vfrom_net = svtx[svtx_idx].sv[0];
27282bf73ac6SHong Zhang         vfrom_idx = svtx[svtx_idx].sv[1];
27292bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       svtx %D: global index %D, subnet[%D].%D ---->\n",i,gidx,vfrom_net,vfrom_idx);CHKERRQ(ierr);
27302bf73ac6SHong Zhang         for (j=1; j<nvto; j++) {
27312bf73ac6SHong Zhang           svto = svtx[svtx_idx].sv + 2*j;
27322bf73ac6SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "                                           ----> subnet[%D].%D\n",svto[0],svto[1]);CHKERRQ(ierr);
2733caf410d2SHong Zhang         }
2734caf410d2SHong Zhang       }
2735caf410d2SHong Zhang     }
2736caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2737caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2738caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
27395f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27405f2c45f1SShri Abhyankar }
27415f2c45f1SShri Abhyankar 
27425f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
27435f2c45f1SShri Abhyankar {
27445f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27455f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27465f2c45f1SShri Abhyankar 
27475f2c45f1SShri Abhyankar   PetscFunctionBegin;
27485f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
27495f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27505f2c45f1SShri Abhyankar }
27515f2c45f1SShri Abhyankar 
27525f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
27535f2c45f1SShri Abhyankar {
27545f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27555f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27565f2c45f1SShri Abhyankar 
27575f2c45f1SShri Abhyankar   PetscFunctionBegin;
27585f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
27595f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27605f2c45f1SShri Abhyankar }
27615f2c45f1SShri Abhyankar 
27625f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
27635f2c45f1SShri Abhyankar {
27645f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27655f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27665f2c45f1SShri Abhyankar 
27675f2c45f1SShri Abhyankar   PetscFunctionBegin;
27685f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
27695f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27705f2c45f1SShri Abhyankar }
27715f2c45f1SShri Abhyankar 
27725f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
27735f2c45f1SShri Abhyankar {
27745f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27755f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27765f2c45f1SShri Abhyankar 
27775f2c45f1SShri Abhyankar   PetscFunctionBegin;
27785f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
27795f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27805f2c45f1SShri Abhyankar }
278122bbedd7SHong Zhang 
278222bbedd7SHong Zhang /*@
278364238763SRodolfo Oliveira   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index
278422bbedd7SHong Zhang 
278522bbedd7SHong Zhang   Not collective
278622bbedd7SHong Zhang 
27877a7aea1fSJed Brown   Input Parameters:
278822bbedd7SHong Zhang + dm - the dm object
278922bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
279022bbedd7SHong Zhang 
27917a7aea1fSJed Brown   Output Parameters:
2792f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
279322bbedd7SHong Zhang 
279497bb938eSShri Abhyankar   Level: advanced
279522bbedd7SHong Zhang 
279622bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
279722bbedd7SHong Zhang @*/
279822bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
279922bbedd7SHong Zhang {
280022bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
280122bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
280222bbedd7SHong Zhang 
280322bbedd7SHong Zhang   PetscFunctionBegin;
280422bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
280522bbedd7SHong Zhang   *vg = vltog[vloc];
280622bbedd7SHong Zhang   PetscFunctionReturn(0);
280722bbedd7SHong Zhang }
280822bbedd7SHong Zhang 
280922bbedd7SHong Zhang /*@
281064238763SRodolfo Oliveira   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map
281122bbedd7SHong Zhang 
281222bbedd7SHong Zhang   Collective
281322bbedd7SHong Zhang 
281422bbedd7SHong Zhang   Input Parameters:
2815f0fc11ceSJed Brown . dm - the dm object
281622bbedd7SHong Zhang 
281797bb938eSShri Abhyankar   Level: advanced
281822bbedd7SHong Zhang 
281963029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
282022bbedd7SHong Zhang @*/
282122bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
282222bbedd7SHong Zhang {
282322bbedd7SHong Zhang   PetscErrorCode    ierr;
282422bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
282522bbedd7SHong Zhang   MPI_Comm          comm;
28262bf73ac6SHong Zhang   PetscMPIInt       rank,size,*displs=NULL,*recvcounts=NULL,remoterank;
282722bbedd7SHong Zhang   PetscBool         ghost;
282863029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
282922bbedd7SHong Zhang   const PetscSFNode *iremote;
283022bbedd7SHong Zhang   PetscSF           vsf;
283163029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
283263029d29SHong Zhang   VecScatter        ctx;
283363029d29SHong Zhang   PetscScalar       *varr,val;
283463029d29SHong Zhang   const PetscScalar *varr_read;
283522bbedd7SHong Zhang 
283622bbedd7SHong Zhang   PetscFunctionBegin;
283722bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2838ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
2839ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
284022bbedd7SHong Zhang 
284122bbedd7SHong Zhang   if (size == 1) {
284222bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
284322bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
284422bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
284522bbedd7SHong Zhang     network->vltog = vltog;
284622bbedd7SHong Zhang     PetscFunctionReturn(0);
284722bbedd7SHong Zhang   }
284822bbedd7SHong Zhang 
284922bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
285022bbedd7SHong Zhang   if (network->vltog) {
285122bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
285222bbedd7SHong Zhang   }
285322bbedd7SHong Zhang 
285422bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
285522bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
285622bbedd7SHong Zhang   vsf = network->vertex.sf;
285722bbedd7SHong Zhang 
28582bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
2859f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
286022bbedd7SHong Zhang 
286122bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
286222bbedd7SHong Zhang 
286322bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
286422bbedd7SHong Zhang   vrange[0] = 0;
2865ffc4695bSBarry Smith   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
286667dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
286722bbedd7SHong Zhang 
286822bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
286922bbedd7SHong Zhang   network->vltog = vltog;
287022bbedd7SHong Zhang 
287163029d29SHong Zhang   /* Set vltog for non-ghost vertices */
287263029d29SHong Zhang   k = 0;
287322bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
287422bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
287563029d29SHong Zhang     if (ghost) continue;
287663029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
287722bbedd7SHong Zhang   }
2878f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
287963029d29SHong Zhang 
288063029d29SHong Zhang   /* Set vltog for ghost vertices */
288163029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
288263029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
288363029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
288463029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
288563029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
288663029d29SHong Zhang   for (i=0; i<nleaves; i++) {
288763029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
288863029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
288963029d29SHong Zhang   }
289063029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
289163029d29SHong Zhang 
289263029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
289363029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
289463029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
289563029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
289663029d29SHong Zhang 
289763029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
289863029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
289963029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
290063029d29SHong Zhang   for (i=0; i<N; i+=2) {
29012e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
290263029d29SHong Zhang     if (remoterank == rank) {
290363029d29SHong Zhang       k = i+1; /* row number */
29042e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
290563029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
290663029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
290763029d29SHong Zhang     }
290863029d29SHong Zhang   }
290963029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
291063029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
291163029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
291263029d29SHong Zhang 
291363029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
291463029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
291563029d29SHong Zhang   k = 0;
291663029d29SHong Zhang   for (i=0; i<nroots; i++) {
291763029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
291863029d29SHong Zhang     if (!ghost) continue;
29192e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
292063029d29SHong Zhang   }
292163029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
292263029d29SHong Zhang 
292363029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
292463029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
292563029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
292622bbedd7SHong Zhang   PetscFunctionReturn(0);
292722bbedd7SHong Zhang }
2928