xref: /petsc/src/dm/impls/network/network.c (revision 22bbedd764687ec5cdd2f3b688cbf0a0633faf32)
1af0996ceSBarry Smith #include <petsc/private/dmnetworkimpl.h>  /*I  "petscdmnetwork.h"  I*/
25f2c45f1SShri Abhyankar 
35f2c45f1SShri Abhyankar /*@
4556ed216SShri Abhyankar   DMNetworkGetPlex - Gets the Plex DM associated with this network DM
5556ed216SShri Abhyankar 
6556ed216SShri Abhyankar   Not collective
7556ed216SShri Abhyankar 
8556ed216SShri Abhyankar   Input Parameters:
9556ed216SShri Abhyankar + netdm - the dm object
10556ed216SShri Abhyankar - plexmdm - the plex dm object
11556ed216SShri Abhyankar 
12556ed216SShri Abhyankar   Level: Advanced
13556ed216SShri Abhyankar 
14556ed216SShri Abhyankar .seealso: DMNetworkCreate()
15556ed216SShri Abhyankar @*/
16556ed216SShri Abhyankar PetscErrorCode DMNetworkGetPlex(DM netdm, DM *plexdm)
17556ed216SShri Abhyankar {
18556ed216SShri Abhyankar   DM_Network *network = (DM_Network*) netdm->data;
19556ed216SShri Abhyankar 
20556ed216SShri Abhyankar   PetscFunctionBegin;
21556ed216SShri Abhyankar   *plexdm = network->plex;
22556ed216SShri Abhyankar   PetscFunctionReturn(0);
23556ed216SShri Abhyankar }
24556ed216SShri Abhyankar 
25556ed216SShri Abhyankar /*@
26e2aaf10cSShri Abhyankar   DMNetworkSetSizes - Sets the number of subnetworks, local and global vertices and edges for each subnetwork.
275f2c45f1SShri Abhyankar 
28d083f849SBarry Smith   Collective on dm
295f2c45f1SShri Abhyankar 
305f2c45f1SShri Abhyankar   Input Parameters:
315f2c45f1SShri Abhyankar + dm - the dm object
32caf410d2SHong Zhang . Nsubnet - global number of subnetworks
33caf410d2SHong Zhang . nV - number of local vertices for each subnetwork
34caf410d2SHong Zhang . nE - number of local edges for each subnetwork
35caf410d2SHong Zhang . NsubnetCouple - global number of coupling subnetworks
36caf410d2SHong Zhang - nec - number of local edges for each coupling subnetwork
375f2c45f1SShri Abhyankar 
38caf410d2SHong Zhang    You cannot change the sizes once they have been set. nV, nE are arrays of length Nsubnet, and nec is array of length NsubnetCouple.
395f2c45f1SShri Abhyankar 
401b266c99SBarry Smith    Level: intermediate
411b266c99SBarry Smith 
421b266c99SBarry Smith .seealso: DMNetworkCreate()
435f2c45f1SShri Abhyankar @*/
44caf410d2SHong Zhang PetscErrorCode DMNetworkSetSizes(DM dm,PetscInt Nsubnet,PetscInt nV[], PetscInt nE[],PetscInt NsubnetCouple,PetscInt nec[])
455f2c45f1SShri Abhyankar {
465f2c45f1SShri Abhyankar   PetscErrorCode ierr;
475f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*) dm->data;
48e2aaf10cSShri Abhyankar   PetscInt       a[2],b[2],i;
495f2c45f1SShri Abhyankar 
505f2c45f1SShri Abhyankar   PetscFunctionBegin;
515f2c45f1SShri Abhyankar   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
52e2aaf10cSShri Abhyankar   if (Nsubnet <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subnetworks %D cannot be less than 1",Nsubnet);
537765340cSHong Zhang   if (NsubnetCouple < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of coupling subnetworks %D cannot be less than 0",NsubnetCouple);
547765340cSHong Zhang 
55caf410d2SHong Zhang   PetscValidLogicalCollectiveInt(dm,Nsubnet,2);
56caf410d2SHong Zhang   if (NsubnetCouple) PetscValidLogicalCollectiveInt(dm,NsubnetCouple,5);
577765340cSHong Zhang   if (network->nsubnet != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network");
587765340cSHong Zhang 
59caf410d2SHong Zhang   if (!nV || !nE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Local vertex size or edge size must be provided");
60f025b11dSHong Zhang 
61caf410d2SHong Zhang   network->nsubnet  = Nsubnet + NsubnetCouple;
62caf410d2SHong Zhang   network->ncsubnet = NsubnetCouple;
63caf410d2SHong Zhang   ierr = PetscCalloc1(Nsubnet+NsubnetCouple,&network->subnet);CHKERRQ(ierr);
64caf410d2SHong Zhang 
65caf410d2SHong Zhang   /* ----------------------------------------------------------
66caf410d2SHong Zhang    p=v or e; P=V or E
67caf410d2SHong Zhang    subnet[0].pStart   = 0
68caf410d2SHong Zhang    subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i])
69caf410d2SHong Zhang    ----------------------------------------------------------------------- */
70caf410d2SHong Zhang   for (i=0; i < Nsubnet; i++) {
71caf410d2SHong Zhang     /* Get global number of vertices and edges for subnet[i] */
72caf410d2SHong Zhang     a[0] = nV[i]; a[1] = nE[i]; /* local number of vertices (excluding ghost) and edges */
737765340cSHong Zhang     ierr = MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
74071fcb05SBarry Smith     network->subnet[i].Nvtx = b[0];
75071fcb05SBarry Smith     network->subnet[i].Nedge = b[1];
767765340cSHong Zhang 
77caf410d2SHong Zhang     network->subnet[i].nvtx   = nV[i]; /* local nvtx, without ghost */
787765340cSHong Zhang 
79caf410d2SHong Zhang     /* global subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */
80caf410d2SHong Zhang     network->subnet[i].vStart = network->NVertices;
817765340cSHong Zhang     network->subnet[i].vEnd   = network->subnet[i].vStart + network->subnet[i].Nvtx;
82caf410d2SHong Zhang 
83caf410d2SHong Zhang     network->nVertices += nV[i];
847765340cSHong Zhang     network->NVertices += network->subnet[i].Nvtx;
857765340cSHong Zhang 
867765340cSHong Zhang     network->subnet[i].nedge  = nE[i];
877765340cSHong Zhang     network->subnet[i].eStart = network->nEdges;
88caf410d2SHong Zhang     network->subnet[i].eEnd   = network->subnet[i].eStart + nE[i];
89caf410d2SHong Zhang     network->nEdges += nE[i];
90caf410d2SHong Zhang     network->NEdges += network->subnet[i].Nedge;
91caf410d2SHong Zhang   }
92caf410d2SHong Zhang 
93caf410d2SHong Zhang   /* coupling subnetwork */
94caf410d2SHong Zhang   for (; i < Nsubnet+NsubnetCouple; i++) {
95caf410d2SHong Zhang     /* Get global number of coupling edges for subnet[i] */
96caf410d2SHong Zhang     ierr = MPIU_Allreduce(nec+(i-Nsubnet),&network->subnet[i].Nedge,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
97caf410d2SHong Zhang 
98caf410d2SHong Zhang     network->subnet[i].nvtx   = 0; /* We design coupling subnetwork such that it does not have its own vertices */
99caf410d2SHong Zhang     network->subnet[i].vStart = network->nVertices;
100caf410d2SHong Zhang     network->subnet[i].vEnd   = network->subnet[i].vStart;
101caf410d2SHong Zhang 
102caf410d2SHong Zhang     network->subnet[i].nedge  = nec[i-Nsubnet];
103caf410d2SHong Zhang     network->subnet[i].eStart = network->nEdges;
104caf410d2SHong Zhang     network->subnet[i].eEnd = network->subnet[i].eStart + nec[i-Nsubnet];
105caf410d2SHong Zhang     network->nEdges += nec[i-Nsubnet];
1067765340cSHong Zhang     network->NEdges += network->subnet[i].Nedge;
1077765340cSHong Zhang   }
1087765340cSHong Zhang   PetscFunctionReturn(0);
1097765340cSHong Zhang }
1107765340cSHong Zhang 
1115f2c45f1SShri Abhyankar /*@
1125f2c45f1SShri Abhyankar   DMNetworkSetEdgeList - Sets the list of local edges (vertex connectivity) for the network
1135f2c45f1SShri Abhyankar 
114d083f849SBarry Smith   Logically collective on dm
1155f2c45f1SShri Abhyankar 
1165f2c45f1SShri Abhyankar   Input Parameters:
117e3e68989SHong Zhang + dm - the dm object
118e3e68989SHong Zhang . edgelist - list of edges for each subnetwork
119e3e68989SHong Zhang - edgelistCouple - list of edges for each coupling subnetwork
1205f2c45f1SShri Abhyankar 
1215f2c45f1SShri Abhyankar   Notes:
1225f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1235f2c45f1SShri Abhyankar   not be destroyed before the call to DMNetworkLayoutSetUp
1245f2c45f1SShri Abhyankar 
1255f2c45f1SShri Abhyankar   Level: intermediate
1265f2c45f1SShri Abhyankar 
127e3e68989SHong Zhang   Example usage:
128e3e68989SHong Zhang   Consider the following 2 separate networks and a coupling network:
129e3e68989SHong Zhang 
130e3e68989SHong Zhang .vb
131e3e68989SHong Zhang  network 0: v0 -> v1 -> v2 -> v3
132e3e68989SHong Zhang  network 1: v1 -> v2 -> v0
133e3e68989SHong Zhang  coupling network: network 1: v2 -> network 0: v0
134e3e68989SHong Zhang .ve
135e3e68989SHong Zhang 
136e3e68989SHong Zhang  The resulting input
137e3e68989SHong Zhang    edgelist[0] = [0 1 | 1 2 | 2 3];
138e3e68989SHong Zhang    edgelist[1] = [1 2 | 2 0]
139e3e68989SHong Zhang    edgelistCouple[0] = [(network)1 (v)2 (network)0 (v)0].
140e3e68989SHong Zhang 
1415f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkSetSizes
1425f2c45f1SShri Abhyankar @*/
1434e18019cSBarry Smith PetscErrorCode DMNetworkSetEdgeList(DM dm,PetscInt *edgelist[],PetscInt *edgelistCouple[])
1445f2c45f1SShri Abhyankar {
1455f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*) dm->data;
146e3e68989SHong Zhang   PetscInt   i,nsubnet,ncsubnet=network->ncsubnet;
1475f2c45f1SShri Abhyankar 
1485f2c45f1SShri Abhyankar   PetscFunctionBegin;
149e3e68989SHong Zhang   nsubnet = network->nsubnet - ncsubnet;
150e3e68989SHong Zhang   for(i=0; i < nsubnet; i++) {
151e2aaf10cSShri Abhyankar     network->subnet[i].edgelist = edgelist[i];
152e2aaf10cSShri Abhyankar   }
153e3e68989SHong Zhang   if (edgelistCouple) {
154e3e68989SHong Zhang     PetscInt j;
155e3e68989SHong Zhang     j = 0;
156e3e68989SHong Zhang     nsubnet = network->nsubnet;
157e3e68989SHong Zhang     while (i < nsubnet) network->subnet[i++].edgelist = edgelistCouple[j++];
158e3e68989SHong Zhang   }
1595f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
1605f2c45f1SShri Abhyankar }
1615f2c45f1SShri Abhyankar 
1625f2c45f1SShri Abhyankar /*@
1635f2c45f1SShri Abhyankar   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
1645f2c45f1SShri Abhyankar 
165d083f849SBarry Smith   Collective on dm
1665f2c45f1SShri Abhyankar 
1675f2c45f1SShri Abhyankar   Input Parameters
1685f2c45f1SShri Abhyankar . DM - the dmnetwork object
1695f2c45f1SShri Abhyankar 
1705f2c45f1SShri Abhyankar   Notes:
1715f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
1725f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
1735f2c45f1SShri Abhyankar 
1745f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
1755f2c45f1SShri Abhyankar 
1765f2c45f1SShri Abhyankar   Level: intermediate
1775f2c45f1SShri Abhyankar 
1785f2c45f1SShri Abhyankar .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList
1795f2c45f1SShri Abhyankar @*/
1805f2c45f1SShri Abhyankar PetscErrorCode DMNetworkLayoutSetUp(DM dm)
1815f2c45f1SShri Abhyankar {
1825f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1835f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
184caf410d2SHong Zhang   PetscInt       numCorners=2,spacedim=2,dim = 1; /* One dimensional network */
1853ebf9fb9SHong Zhang   PetscReal      *vertexcoords=NULL;
186caf410d2SHong Zhang   PetscInt       i,j,ctr,nsubnet,*eowners,np,*edges,*subnetvtx,vStart;
187caf410d2SHong Zhang   PetscInt       k,netid,vid, *vidxlTog,*edgelist_couple=NULL;
188caf410d2SHong Zhang   const PetscInt *cone;
189caf410d2SHong Zhang   MPI_Comm       comm;
190caf410d2SHong Zhang   PetscMPIInt    size,rank;
1916500d4abSHong Zhang 
1926500d4abSHong Zhang   PetscFunctionBegin;
193caf410d2SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
194caf410d2SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
195caf410d2SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1966500d4abSHong Zhang 
197caf410d2SHong Zhang   /* Create the local edgelist for the network by concatenating local input edgelists of the subnetworks */
198caf410d2SHong Zhang   ierr = PetscCalloc2(numCorners*network->nVertices,&vertexcoords,2*network->nEdges,&edges);CHKERRQ(ierr);
1997765340cSHong Zhang   nsubnet = network->nsubnet - network->ncsubnet;
200caf410d2SHong Zhang   ctr = 0;
2017765340cSHong Zhang   for (i=0; i < nsubnet; i++) {
2026500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
203caf410d2SHong Zhang       edges[2*ctr]   = network->subnet[i].eStart + network->subnet[i].edgelist[2*j];
204caf410d2SHong Zhang       edges[2*ctr+1] = network->subnet[i].eStart + network->subnet[i].edgelist[2*j+1];
2056500d4abSHong Zhang       ctr++;
2066500d4abSHong Zhang     }
2076500d4abSHong Zhang   }
2087765340cSHong Zhang 
209caf410d2SHong Zhang   /* Append local coupling edgelists of the subnetworks */
2107765340cSHong Zhang   i       = nsubnet; /* netid of coupling subnet */
2117765340cSHong Zhang   nsubnet = network->nsubnet;
2127765340cSHong Zhang   while (i < nsubnet) {
213991cf414SHong Zhang     edgelist_couple = network->subnet[i].edgelist;
2146500d4abSHong Zhang     k = 0;
2156500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
2166500d4abSHong Zhang       netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
217caf410d2SHong Zhang       edges[2*ctr] = network->subnet[netid].vStart + vid; k += 2;
2186500d4abSHong Zhang 
2196500d4abSHong Zhang       netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
220caf410d2SHong Zhang       edges[2*ctr+1] = network->subnet[netid].vStart + vid; k+=2;
2216500d4abSHong Zhang       ctr++;
2226500d4abSHong Zhang     }
2237765340cSHong Zhang     i++;
2247765340cSHong Zhang   }
225caf410d2SHong Zhang   /*
226caf410d2SHong Zhang   if (rank == 0) {
227caf410d2SHong Zhang     ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] edgelist:\n",rank);
2286500d4abSHong Zhang     for(i=0; i < network->nEdges; i++) {
229caf410d2SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"[%D %D]",edges[2*i],edges[2*i+1]);CHKERRQ(ierr);
2306500d4abSHong Zhang       printf("\n");
2316500d4abSHong Zhang     }
232caf410d2SHong Zhang   }
233caf410d2SHong Zhang    */
2346500d4abSHong Zhang 
235caf410d2SHong Zhang   /* Create network->plex */
236acdb140fSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
237acdb140fSBarry Smith   {
238caf410d2SHong Zhang     int *edges64;
239caf410d2SHong Zhang     np = network->nEdges*numCorners;
240caf410d2SHong Zhang     ierr = PetscMalloc1(np,&edges64);CHKERRQ(ierr);
241caf410d2SHong Zhang     for (i=0; i<np; i++) edges64[i] = (int)edges[i];
242caf410d2SHong Zhang 
243caf410d2SHong Zhang     if (size == 1) {
244caf410d2SHong Zhang       ierr = DMPlexCreateFromCellList(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges64,spacedim,(const double*)vertexcoords,&network->plex);CHKERRQ(ierr);
245caf410d2SHong Zhang     } else {
2463ebf9fb9SHong Zhang       ierr = DMPlexCreateFromCellListParallel(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges64,spacedim,(const PetscReal*)vertexcoords,NULL,&network->plex);CHKERRQ(ierr);
247acdb140fSBarry Smith     }
248caf410d2SHong Zhang     ierr = PetscFree(edges64);CHKERRQ(ierr);
249acdb140fSBarry Smith   }
250acdb140fSBarry Smith #else
251caf410d2SHong Zhang   if (size == 1) {
252caf410d2SHong Zhang     ierr = DMPlexCreateFromCellList(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges,spacedim,(const double*)vertexcoords,&network->plex);CHKERRQ(ierr);
253caf410d2SHong Zhang   } else {
2543ebf9fb9SHong Zhang     ierr = DMPlexCreateFromCellListParallel(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges,spacedim,(const PetscReal*)vertexcoords,NULL,&network->plex);CHKERRQ(ierr);
2556500d4abSHong Zhang   }
256caf410d2SHong Zhang #endif
2576500d4abSHong Zhang 
2586500d4abSHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
2596500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
2606500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
261caf410d2SHong Zhang   vStart = network->vStart;
2626500d4abSHong Zhang 
263caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
264caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
2656500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
2666500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
2676500d4abSHong Zhang 
268caf410d2SHong Zhang   network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
269caf410d2SHong Zhang   np = network->pEnd - network->pStart;
270caf410d2SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
271caf410d2SHong Zhang 
272caf410d2SHong Zhang   /* Create vidxlTog: maps local vertex index to global index */
273caf410d2SHong Zhang   np = network->vEnd - vStart;
274caf410d2SHong Zhang   ierr = PetscMalloc2(np,&vidxlTog,size+1,&eowners);CHKERRQ(ierr);
275caf410d2SHong Zhang   ctr = 0;
276caf410d2SHong Zhang   for (i=network->eStart; i<network->eEnd; i++) {
277caf410d2SHong Zhang     ierr = DMNetworkGetConnectedVertices(dm,i,&cone);CHKERRQ(ierr);
278caf410d2SHong Zhang     vidxlTog[cone[0] - vStart] = edges[2*ctr];
279caf410d2SHong Zhang     vidxlTog[cone[1] - vStart] = edges[2*ctr+1];
280caf410d2SHong Zhang     ctr++;
281caf410d2SHong Zhang   }
282caf410d2SHong Zhang   ierr = PetscFree2(vertexcoords,edges);CHKERRQ(ierr);
283caf410d2SHong Zhang 
2846500d4abSHong Zhang   /* Create vertices and edges array for the subnetworks */
2856500d4abSHong Zhang   for (j=0; j < network->nsubnet; j++) {
2866500d4abSHong Zhang     ierr = PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);CHKERRQ(ierr);
287caf410d2SHong Zhang 
2886500d4abSHong Zhang     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
2896500d4abSHong Zhang        These get updated when the vertices and edges are added. */
290caf410d2SHong Zhang     network->subnet[j].nvtx  = 0;
291caf410d2SHong Zhang     network->subnet[j].nedge = 0;
2926500d4abSHong Zhang   }
293caf410d2SHong Zhang   ierr = PetscCalloc1(np,&network->subnetvtx);CHKERRQ(ierr);
2946500d4abSHong Zhang 
295caf410d2SHong Zhang 
296caf410d2SHong Zhang   /* Get edge ownership */
297caf410d2SHong Zhang   np = network->eEnd - network->eStart;
298caf410d2SHong Zhang   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRQ(ierr);
299caf410d2SHong Zhang   eowners[0] = 0;
300caf410d2SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
301caf410d2SHong Zhang 
302caf410d2SHong Zhang   i = 0; j = 0;
303caf410d2SHong Zhang   while (i < np) { /* local edges, including coupling edges */
304caf410d2SHong Zhang     network->header[i].index = i + eowners[rank];   /* Global edge index */
305caf410d2SHong Zhang 
306caf410d2SHong Zhang     if (j < network->nsubnet && i < network->subnet[j].eEnd) {
3076500d4abSHong Zhang       network->header[i].subnetid = j; /* Subnetwork id */
3086500d4abSHong Zhang       network->subnet[j].edges[network->subnet[j].nedge++] = i;
309caf410d2SHong Zhang 
310caf410d2SHong Zhang       network->header[i].ndata = 0;
311caf410d2SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
312caf410d2SHong Zhang       network->header[i].offset[0] = 0;
313caf410d2SHong Zhang       i++;
314caf410d2SHong Zhang     }
315caf410d2SHong Zhang     if (i >= network->subnet[j].eEnd) j++;
316caf410d2SHong Zhang   }
317caf410d2SHong Zhang 
318caf410d2SHong Zhang   /* Count network->subnet[*].nvtx */
319caf410d2SHong Zhang   for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */
320caf410d2SHong Zhang     k = vidxlTog[i-vStart];
321caf410d2SHong Zhang     for (j=0; j < network->nsubnet; j++) {
322caf410d2SHong Zhang       if (network->subnet[j].vStart <= k && k < network->subnet[j].vEnd) {
323caf410d2SHong Zhang         network->subnet[j].nvtx++;
3246500d4abSHong Zhang         break;
3256500d4abSHong Zhang       }
3266500d4abSHong Zhang     }
3276500d4abSHong Zhang   }
3286500d4abSHong Zhang 
329caf410d2SHong Zhang   /* Set network->subnet[*].vertices on array network->subnetvtx */
330caf410d2SHong Zhang   subnetvtx = network->subnetvtx;
3316500d4abSHong Zhang   for (j=0; j<network->nsubnet; j++) {
332caf410d2SHong Zhang     network->subnet[j].vertices = subnetvtx;
333caf410d2SHong Zhang     subnetvtx                  += network->subnet[j].nvtx;
334caf410d2SHong Zhang     network->subnet[j].nvtx = 0;
335caf410d2SHong Zhang   }
336caf410d2SHong Zhang 
337caf410d2SHong Zhang   /* Set vertex array for the subnetworks */
338caf410d2SHong Zhang   for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */
339caf410d2SHong Zhang     network->header[i].index = vidxlTog[i-vStart]; /*  Global vertex index */
340caf410d2SHong Zhang 
341caf410d2SHong Zhang     k = vidxlTog[i-vStart];
342caf410d2SHong Zhang     for (j=0; j < network->nsubnet; j++) {
343caf410d2SHong Zhang       if (network->subnet[j].vStart <= k && k < network->subnet[j].vEnd) {
3446500d4abSHong Zhang         network->header[i].subnetid = j;
3456500d4abSHong Zhang         network->subnet[j].vertices[network->subnet[j].nvtx++] = i;
3466500d4abSHong Zhang         break;
3476500d4abSHong Zhang       }
3486500d4abSHong Zhang     }
349caf410d2SHong Zhang 
3506500d4abSHong Zhang     network->header[i].ndata = 0;
3516500d4abSHong Zhang     ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
352caf410d2SHong Zhang     network->header[i].offset[0] = 0;
3536500d4abSHong Zhang   }
3546500d4abSHong Zhang 
355caf410d2SHong Zhang   ierr = PetscFree2(vidxlTog,eowners);CHKERRQ(ierr);
3565f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
3575f2c45f1SShri Abhyankar }
3585f2c45f1SShri Abhyankar 
35994ef8ddeSSatish Balay /*@C
3602727e31bSShri Abhyankar   DMNetworkGetSubnetworkInfo - Returns the info for the subnetwork
3612727e31bSShri Abhyankar 
3622727e31bSShri Abhyankar   Input Parameters
363caf410d2SHong Zhang + dm - the DM object
3642727e31bSShri Abhyankar - id   - the ID (integer) of the subnetwork
3652727e31bSShri Abhyankar 
3662727e31bSShri Abhyankar   Output Parameters
3672727e31bSShri Abhyankar + nv    - number of vertices (local)
3682727e31bSShri Abhyankar . ne    - number of edges (local)
3692727e31bSShri Abhyankar . vtx   - local vertices for this subnetwork
3702727e31bSShri Abhyankar . edge  - local edges for this subnetwork
3712727e31bSShri Abhyankar 
3722727e31bSShri Abhyankar   Notes:
3732727e31bSShri Abhyankar   Cannot call this routine before DMNetworkLayoutSetup()
3742727e31bSShri Abhyankar 
37506dd6b0eSSatish Balay   Level: intermediate
37606dd6b0eSSatish Balay 
3772727e31bSShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
3782727e31bSShri Abhyankar @*/
379caf410d2SHong Zhang PetscErrorCode DMNetworkGetSubnetworkInfo(DM dm,PetscInt id,PetscInt *nv, PetscInt *ne,const PetscInt **vtx, const PetscInt **edge)
3802727e31bSShri Abhyankar {
381caf410d2SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
3822727e31bSShri Abhyankar 
3832727e31bSShri Abhyankar   PetscFunctionBegin;
3842727e31bSShri Abhyankar   *nv   = network->subnet[id].nvtx;
3852727e31bSShri Abhyankar   *ne   = network->subnet[id].nedge;
3862727e31bSShri Abhyankar   *vtx  = network->subnet[id].vertices;
3872727e31bSShri Abhyankar   *edge = network->subnet[id].edges;
3882727e31bSShri Abhyankar   PetscFunctionReturn(0);
3892727e31bSShri Abhyankar }
3902727e31bSShri Abhyankar 
3912727e31bSShri Abhyankar /*@C
392caf410d2SHong Zhang   DMNetworkGetSubnetworkCoupleInfo - Returns the info for the coupling subnetwork
393caf410d2SHong Zhang 
394caf410d2SHong Zhang   Input Parameters
395caf410d2SHong Zhang + dm - the DM object
396caf410d2SHong Zhang - id   - the ID (integer) of the coupling subnetwork
397caf410d2SHong Zhang 
398caf410d2SHong Zhang   Output Parameters
399caf410d2SHong Zhang + ne - number of edges (local)
400caf410d2SHong Zhang - edge  - local edges for this coupling subnetwork
401caf410d2SHong Zhang 
402caf410d2SHong Zhang   Notes:
403caf410d2SHong Zhang   Cannot call this routine before DMNetworkLayoutSetup()
404caf410d2SHong Zhang 
405caf410d2SHong Zhang   Level: intermediate
406caf410d2SHong Zhang 
407caf410d2SHong Zhang .seealso: DMNetworkGetSubnetworkInfo, DMNetworkLayoutSetUp, DMNetworkCreate
408caf410d2SHong Zhang @*/
409caf410d2SHong Zhang PetscErrorCode DMNetworkGetSubnetworkCoupleInfo(DM dm,PetscInt id,PetscInt *ne,const PetscInt **edge)
410caf410d2SHong Zhang {
411caf410d2SHong Zhang   DM_Network *net = (DM_Network*)dm->data;
412caf410d2SHong Zhang   PetscInt   id1 = id + net->nsubnet - net->ncsubnet;
413caf410d2SHong Zhang 
414caf410d2SHong Zhang   PetscFunctionBegin;
415caf410d2SHong Zhang   *ne   = net->subnet[id1].nedge;
416caf410d2SHong Zhang   *edge = net->subnet[id1].edges;
417caf410d2SHong Zhang   PetscFunctionReturn(0);
418caf410d2SHong Zhang }
419caf410d2SHong Zhang 
420caf410d2SHong Zhang /*@C
4215f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
4225f2c45f1SShri Abhyankar 
423d083f849SBarry Smith   Logically collective on dm
4245f2c45f1SShri Abhyankar 
4255f2c45f1SShri Abhyankar   Input Parameters
4265f2c45f1SShri Abhyankar + dm   - the network object
4275f2c45f1SShri Abhyankar . name - the component name
4285f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
4295f2c45f1SShri Abhyankar 
4305f2c45f1SShri Abhyankar    Output Parameters
4315f2c45f1SShri Abhyankar .   key - an integer key that defines the component
4325f2c45f1SShri Abhyankar 
4335f2c45f1SShri Abhyankar    Notes
4345f2c45f1SShri Abhyankar    This routine should be called by all processors before calling DMNetworkLayoutSetup().
4355f2c45f1SShri Abhyankar 
4365f2c45f1SShri Abhyankar    Level: intermediate
4375f2c45f1SShri Abhyankar 
4385f2c45f1SShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
4395f2c45f1SShri Abhyankar @*/
440caf410d2SHong Zhang PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key)
4415f2c45f1SShri Abhyankar {
4425f2c45f1SShri Abhyankar   PetscErrorCode        ierr;
4435f2c45f1SShri Abhyankar   DM_Network            *network = (DM_Network*) dm->data;
4445f2c45f1SShri Abhyankar   DMNetworkComponent    *component=&network->component[network->ncomponent];
4455f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
4465f2c45f1SShri Abhyankar   PetscInt              i;
4475f2c45f1SShri Abhyankar 
4485f2c45f1SShri Abhyankar   PetscFunctionBegin;
4495f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
4505f2c45f1SShri Abhyankar     ierr = PetscStrcmp(component->name,name,&flg);CHKERRQ(ierr);
4515f2c45f1SShri Abhyankar     if (flg) {
4525f2c45f1SShri Abhyankar       *key = i;
4535f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
4545f2c45f1SShri Abhyankar     }
4556d64e262SShri Abhyankar   }
4566d64e262SShri Abhyankar   if(network->ncomponent == MAX_COMPONENTS) {
4576d64e262SShri Abhyankar     SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components registered exceeds the max %D",MAX_COMPONENTS);
4585f2c45f1SShri Abhyankar   }
4595f2c45f1SShri Abhyankar 
4605f2c45f1SShri Abhyankar   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
4615f2c45f1SShri Abhyankar   component->size = size/sizeof(DMNetworkComponentGenericDataType);
4625f2c45f1SShri Abhyankar   *key = network->ncomponent;
4635f2c45f1SShri Abhyankar   network->ncomponent++;
4645f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
4655f2c45f1SShri Abhyankar }
4665f2c45f1SShri Abhyankar 
4675f2c45f1SShri Abhyankar /*@
4685f2c45f1SShri Abhyankar   DMNetworkGetVertexRange - Get the bounds [start, end) for the vertices.
4695f2c45f1SShri Abhyankar 
4705f2c45f1SShri Abhyankar   Not Collective
4715f2c45f1SShri Abhyankar 
4725f2c45f1SShri Abhyankar   Input Parameters:
4735f2c45f1SShri Abhyankar + dm - The DMNetwork object
4745f2c45f1SShri Abhyankar 
4755f2c45f1SShri Abhyankar   Output Paramters:
4765f2c45f1SShri Abhyankar + vStart - The first vertex point
4775f2c45f1SShri Abhyankar - vEnd   - One beyond the last vertex point
4785f2c45f1SShri Abhyankar 
4795f2c45f1SShri Abhyankar   Level: intermediate
4805f2c45f1SShri Abhyankar 
4815f2c45f1SShri Abhyankar .seealso: DMNetworkGetEdgeRange
4825f2c45f1SShri Abhyankar @*/
4835f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
4845f2c45f1SShri Abhyankar {
4855f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
4865f2c45f1SShri Abhyankar 
4875f2c45f1SShri Abhyankar   PetscFunctionBegin;
4885f2c45f1SShri Abhyankar   if (vStart) *vStart = network->vStart;
4895f2c45f1SShri Abhyankar   if (vEnd) *vEnd = network->vEnd;
4905f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
4915f2c45f1SShri Abhyankar }
4925f2c45f1SShri Abhyankar 
4935f2c45f1SShri Abhyankar /*@
4945f2c45f1SShri Abhyankar   DMNetworkGetEdgeRange - Get the bounds [start, end) for the edges.
4955f2c45f1SShri Abhyankar 
4965f2c45f1SShri Abhyankar   Not Collective
4975f2c45f1SShri Abhyankar 
4985f2c45f1SShri Abhyankar   Input Parameters:
4995f2c45f1SShri Abhyankar + dm - The DMNetwork object
5005f2c45f1SShri Abhyankar 
5015f2c45f1SShri Abhyankar   Output Paramters:
5025f2c45f1SShri Abhyankar + eStart - The first edge point
5035f2c45f1SShri Abhyankar - eEnd   - One beyond the last edge point
5045f2c45f1SShri Abhyankar 
5055f2c45f1SShri Abhyankar   Level: intermediate
5065f2c45f1SShri Abhyankar 
5075f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange
5085f2c45f1SShri Abhyankar @*/
5095f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
5105f2c45f1SShri Abhyankar {
5115f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
5125f2c45f1SShri Abhyankar 
5135f2c45f1SShri Abhyankar   PetscFunctionBegin;
5145f2c45f1SShri Abhyankar   if (eStart) *eStart = network->eStart;
5155f2c45f1SShri Abhyankar   if (eEnd) *eEnd = network->eEnd;
5165f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5175f2c45f1SShri Abhyankar }
5185f2c45f1SShri Abhyankar 
5197b6afd5bSHong Zhang /*@
520e85e6aecSHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the user global numbering for the edge.
5217b6afd5bSHong Zhang 
5227b6afd5bSHong Zhang   Not Collective
5237b6afd5bSHong Zhang 
5247b6afd5bSHong Zhang   Input Parameters:
5257b6afd5bSHong Zhang + dm - DMNetwork object
526e85e6aecSHong Zhang - p  - edge point
5277b6afd5bSHong Zhang 
5287b6afd5bSHong Zhang   Output Paramters:
529e85e6aecSHong Zhang . index - user global numbering for the edge
5307b6afd5bSHong Zhang 
5317b6afd5bSHong Zhang   Level: intermediate
5327b6afd5bSHong Zhang 
533e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalVertexIndex
5347b6afd5bSHong Zhang @*/
535e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
5367b6afd5bSHong Zhang {
5377b6afd5bSHong Zhang   PetscErrorCode    ierr;
5387b6afd5bSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
5397b6afd5bSHong Zhang   PetscInt          offsetp;
5407b6afd5bSHong Zhang   DMNetworkComponentHeader header;
5417b6afd5bSHong Zhang 
5427b6afd5bSHong Zhang   PetscFunctionBegin;
543caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
5447b6afd5bSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
5457b6afd5bSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
546e85e6aecSHong Zhang   *index = header->index;
5477b6afd5bSHong Zhang   PetscFunctionReturn(0);
5487b6afd5bSHong Zhang }
5497b6afd5bSHong Zhang 
5505f2c45f1SShri Abhyankar /*@
551e85e6aecSHong Zhang   DMNetworkGetGlobalVertexIndex - Get the user global numbering for the vertex.
552e85e6aecSHong Zhang 
553e85e6aecSHong Zhang   Not Collective
554e85e6aecSHong Zhang 
555e85e6aecSHong Zhang   Input Parameters:
556e85e6aecSHong Zhang + dm - DMNetwork object
557e85e6aecSHong Zhang - p  - vertex point
558e85e6aecSHong Zhang 
559e85e6aecSHong Zhang   Output Paramters:
560e85e6aecSHong Zhang . index - user global numbering for the vertex
561e85e6aecSHong Zhang 
562e85e6aecSHong Zhang   Level: intermediate
563e85e6aecSHong Zhang 
564e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalEdgeIndex
565e85e6aecSHong Zhang @*/
566e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
567e85e6aecSHong Zhang {
568e85e6aecSHong Zhang   PetscErrorCode    ierr;
569e85e6aecSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
570e85e6aecSHong Zhang   PetscInt          offsetp;
571e85e6aecSHong Zhang   DMNetworkComponentHeader header;
572e85e6aecSHong Zhang 
573e85e6aecSHong Zhang   PetscFunctionBegin;
574caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
575e85e6aecSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
576e85e6aecSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
577e85e6aecSHong Zhang   *index = header->index;
578e85e6aecSHong Zhang   PetscFunctionReturn(0);
579e85e6aecSHong Zhang }
580e85e6aecSHong Zhang 
581c3b11c7cSShri Abhyankar /*
582c3b11c7cSShri Abhyankar   DMNetworkGetComponentKeyOffset - Gets the type along with the offset for indexing the
583c3b11c7cSShri Abhyankar                                     component value from the component data array
584c3b11c7cSShri Abhyankar 
585c3b11c7cSShri Abhyankar   Not Collective
586c3b11c7cSShri Abhyankar 
587c3b11c7cSShri Abhyankar   Input Parameters:
588c3b11c7cSShri Abhyankar + dm      - The DMNetwork object
589c3b11c7cSShri Abhyankar . p       - vertex/edge point
590c3b11c7cSShri Abhyankar - compnum - component number
591c3b11c7cSShri Abhyankar 
592c3b11c7cSShri Abhyankar   Output Parameters:
593c3b11c7cSShri Abhyankar + compkey - the key obtained when registering the component
594c3b11c7cSShri Abhyankar - offset  - offset into the component data array associated with the vertex/edge point
595c3b11c7cSShri Abhyankar 
596c3b11c7cSShri Abhyankar   Notes:
597c3b11c7cSShri Abhyankar   Typical usage:
598c3b11c7cSShri Abhyankar 
599c3b11c7cSShri Abhyankar   DMNetworkGetComponentDataArray(dm, &arr);
600c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
601c3b11c7cSShri Abhyankar   Loop over vertices or edges
602c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
603c3b11c7cSShri Abhyankar     Loop over numcomps
604c3b11c7cSShri Abhyankar       DMNetworkGetComponentKeyOffset(dm,v,compnum,&key,&offset);
605c3b11c7cSShri Abhyankar       compdata = (UserCompDataType)(arr+offset);
606c3b11c7cSShri Abhyankar 
607c3b11c7cSShri Abhyankar   Level: intermediate
608c3b11c7cSShri Abhyankar 
609c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray,
610c3b11c7cSShri Abhyankar */
611c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponentKeyOffset(DM dm,PetscInt p, PetscInt compnum, PetscInt *compkey, PetscInt *offset)
612c3b11c7cSShri Abhyankar {
613c3b11c7cSShri Abhyankar   PetscErrorCode           ierr;
614c3b11c7cSShri Abhyankar   PetscInt                 offsetp;
615c3b11c7cSShri Abhyankar   DMNetworkComponentHeader header;
616c3b11c7cSShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
617c3b11c7cSShri Abhyankar 
618c3b11c7cSShri Abhyankar   PetscFunctionBegin;
619c3b11c7cSShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
620c3b11c7cSShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
621c3b11c7cSShri Abhyankar   if (compkey) *compkey = header->key[compnum];
622c3b11c7cSShri Abhyankar   if (offset) *offset  = offsetp+network->dataheadersize+header->offset[compnum];
623c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
624c3b11c7cSShri Abhyankar }
625c3b11c7cSShri Abhyankar 
626c3b11c7cSShri Abhyankar /*@
627c3b11c7cSShri Abhyankar   DMNetworkGetComponent - Returns the network component and its key
628c3b11c7cSShri Abhyankar 
629c3b11c7cSShri Abhyankar   Not Collective
630c3b11c7cSShri Abhyankar 
631c3b11c7cSShri Abhyankar   Input Parameters
632c3b11c7cSShri Abhyankar + dm - DMNetwork object
633c3b11c7cSShri Abhyankar . p  - edge or vertex point
634c3b11c7cSShri Abhyankar - compnum - component number
635c3b11c7cSShri Abhyankar 
636c3b11c7cSShri Abhyankar   Output Parameters:
637c3b11c7cSShri Abhyankar + compkey - the key set for this computing during registration
638c3b11c7cSShri Abhyankar - component - the component data
639c3b11c7cSShri Abhyankar 
640c3b11c7cSShri Abhyankar   Notes:
641c3b11c7cSShri Abhyankar   Typical usage:
642c3b11c7cSShri Abhyankar 
643c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
644c3b11c7cSShri Abhyankar   Loop over vertices or edges
645c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
646c3b11c7cSShri Abhyankar     Loop over numcomps
647c3b11c7cSShri Abhyankar       DMNetworkGetComponent(dm,v,compnum,&key,&component);
648c3b11c7cSShri Abhyankar 
649c3b11c7cSShri Abhyankar   Level: intermediate
650c3b11c7cSShri Abhyankar 
651c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetVariableOffset
652c3b11c7cSShri Abhyankar @*/
653c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponent(DM dm, PetscInt p, PetscInt compnum, PetscInt *key, void **component)
654c3b11c7cSShri Abhyankar {
655c3b11c7cSShri Abhyankar   PetscErrorCode ierr;
656c3b11c7cSShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
657e108cb99SStefano Zampini   PetscInt       offsetd = 0;
658c3b11c7cSShri Abhyankar 
659c3b11c7cSShri Abhyankar   PetscFunctionBegin;
660c3b11c7cSShri Abhyankar   ierr = DMNetworkGetComponentKeyOffset(dm,p,compnum,key,&offsetd);CHKERRQ(ierr);
661c3b11c7cSShri Abhyankar   *component = network->componentdataarray+offsetd;
662c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
663c3b11c7cSShri Abhyankar }
664c3b11c7cSShri Abhyankar 
665e85e6aecSHong Zhang /*@
666325661f6SSatish Balay   DMNetworkAddComponent - Adds a network component at the given point (vertex/edge)
6675f2c45f1SShri Abhyankar 
6685f2c45f1SShri Abhyankar   Not Collective
6695f2c45f1SShri Abhyankar 
6705f2c45f1SShri Abhyankar   Input Parameters:
6715f2c45f1SShri Abhyankar + dm           - The DMNetwork object
6725f2c45f1SShri Abhyankar . p            - vertex/edge point
6735f2c45f1SShri Abhyankar . componentkey - component key returned while registering the component
6745f2c45f1SShri Abhyankar - compvalue    - pointer to the data structure for the component
6755f2c45f1SShri Abhyankar 
6765f2c45f1SShri Abhyankar   Level: intermediate
6775f2c45f1SShri Abhyankar 
6785f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange, DMNetworkGetEdgeRange, DMNetworkRegisterComponent
6795f2c45f1SShri Abhyankar @*/
6805f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p,PetscInt componentkey,void* compvalue)
6815f2c45f1SShri Abhyankar {
6825f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
68343a39a44SBarry Smith   DMNetworkComponent       *component = &network->component[componentkey];
6845f2c45f1SShri Abhyankar   DMNetworkComponentHeader header = &network->header[p];
6855f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue = &network->cvalue[p];
6865f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
6875f2c45f1SShri Abhyankar 
6885f2c45f1SShri Abhyankar   PetscFunctionBegin;
689fa58f0a9SHong Zhang   if (header->ndata == MAX_DATA_AT_POINT) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components at a point exceeds the max %D",MAX_DATA_AT_POINT);
690fa58f0a9SHong Zhang 
69143a39a44SBarry Smith   header->size[header->ndata] = component->size;
69243a39a44SBarry Smith   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
6935f2c45f1SShri Abhyankar   header->key[header->ndata] = componentkey;
6945f2c45f1SShri Abhyankar   if (header->ndata != 0) header->offset[header->ndata] = header->offset[header->ndata-1] + header->size[header->ndata-1];
6955f2c45f1SShri Abhyankar 
6965f2c45f1SShri Abhyankar   cvalue->data[header->ndata] = (void*)compvalue;
6975f2c45f1SShri Abhyankar   header->ndata++;
6985f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
6995f2c45f1SShri Abhyankar }
7005f2c45f1SShri Abhyankar 
7015f2c45f1SShri Abhyankar /*@
7025f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
7035f2c45f1SShri Abhyankar 
7045f2c45f1SShri Abhyankar   Not Collective
7055f2c45f1SShri Abhyankar 
7065f2c45f1SShri Abhyankar   Input Parameters:
7075f2c45f1SShri Abhyankar + dm - The DMNetwork object
7085f2c45f1SShri Abhyankar . p  - vertex/edge point
7095f2c45f1SShri Abhyankar 
7105f2c45f1SShri Abhyankar   Output Parameters:
7115f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
7125f2c45f1SShri Abhyankar 
7135f2c45f1SShri Abhyankar   Level: intermediate
7145f2c45f1SShri Abhyankar 
7155f2c45f1SShri Abhyankar .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent
7165f2c45f1SShri Abhyankar @*/
7175f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
7185f2c45f1SShri Abhyankar {
7195f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7205f2c45f1SShri Abhyankar   PetscInt       offset;
7215f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7225f2c45f1SShri Abhyankar 
7235f2c45f1SShri Abhyankar   PetscFunctionBegin;
7245f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
7255f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
7265f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7275f2c45f1SShri Abhyankar }
7285f2c45f1SShri Abhyankar 
7295f2c45f1SShri Abhyankar /*@
7305f2c45f1SShri Abhyankar   DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector.
7315f2c45f1SShri Abhyankar 
7325f2c45f1SShri Abhyankar   Not Collective
7335f2c45f1SShri Abhyankar 
7345f2c45f1SShri Abhyankar   Input Parameters:
7355f2c45f1SShri Abhyankar + dm     - The DMNetwork object
7365f2c45f1SShri Abhyankar - p      - the edge/vertex point
7375f2c45f1SShri Abhyankar 
7385f2c45f1SShri Abhyankar   Output Parameters:
7395f2c45f1SShri Abhyankar . offset - the offset
7405f2c45f1SShri Abhyankar 
7415f2c45f1SShri Abhyankar   Level: intermediate
7425f2c45f1SShri Abhyankar 
7435f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
7445f2c45f1SShri Abhyankar @*/
7455f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset)
7465f2c45f1SShri Abhyankar {
7475f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7485f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7495f2c45f1SShri Abhyankar 
7505f2c45f1SShri Abhyankar   PetscFunctionBegin;
7515f78ed8bSShri Abhyankar   ierr = PetscSectionGetOffset(network->plex->defaultSection,p,offset);CHKERRQ(ierr);
7525f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7535f2c45f1SShri Abhyankar }
7545f2c45f1SShri Abhyankar 
7555f2c45f1SShri Abhyankar /*@
7565f2c45f1SShri Abhyankar   DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector.
7575f2c45f1SShri Abhyankar 
7585f2c45f1SShri Abhyankar   Not Collective
7595f2c45f1SShri Abhyankar 
7605f2c45f1SShri Abhyankar   Input Parameters:
7615f2c45f1SShri Abhyankar + dm      - The DMNetwork object
7625f2c45f1SShri Abhyankar - p       - the edge/vertex point
7635f2c45f1SShri Abhyankar 
7645f2c45f1SShri Abhyankar   Output Parameters:
7655f2c45f1SShri Abhyankar . offsetg - the offset
7665f2c45f1SShri Abhyankar 
7675f2c45f1SShri Abhyankar   Level: intermediate
7685f2c45f1SShri Abhyankar 
7695f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableOffset, DMGetLocalVector
7705f2c45f1SShri Abhyankar @*/
7715f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg)
7725f2c45f1SShri Abhyankar {
7735f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7745f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7755f2c45f1SShri Abhyankar 
7765f2c45f1SShri Abhyankar   PetscFunctionBegin;
7775f78ed8bSShri Abhyankar   ierr = PetscSectionGetOffset(network->plex->defaultGlobalSection,p,offsetg);CHKERRQ(ierr);
7786fefedf4SHong Zhang   if (*offsetg < 0) *offsetg = -(*offsetg + 1); /* Convert to actual global offset for ghost vertex */
7795f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7805f2c45f1SShri Abhyankar }
7815f2c45f1SShri Abhyankar 
78224121865SAdrian Maldonado /*@
78324121865SAdrian Maldonado   DMNetworkGetEdgeOffset - Get the offset for accessing the variable associated with the given edge from the local subvector.
78424121865SAdrian Maldonado 
78524121865SAdrian Maldonado   Not Collective
78624121865SAdrian Maldonado 
78724121865SAdrian Maldonado   Input Parameters:
78824121865SAdrian Maldonado + dm     - The DMNetwork object
78924121865SAdrian Maldonado - p      - the edge point
79024121865SAdrian Maldonado 
79124121865SAdrian Maldonado   Output Parameters:
79224121865SAdrian Maldonado . offset - the offset
79324121865SAdrian Maldonado 
79424121865SAdrian Maldonado   Level: intermediate
79524121865SAdrian Maldonado 
79624121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
79724121865SAdrian Maldonado @*/
79824121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
79924121865SAdrian Maldonado {
80024121865SAdrian Maldonado   PetscErrorCode ierr;
80124121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
80224121865SAdrian Maldonado 
80324121865SAdrian Maldonado   PetscFunctionBegin;
80424121865SAdrian Maldonado 
80524121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
80624121865SAdrian Maldonado   PetscFunctionReturn(0);
80724121865SAdrian Maldonado }
80824121865SAdrian Maldonado 
80924121865SAdrian Maldonado /*@
81024121865SAdrian Maldonado   DMNetworkGetVertexOffset - Get the offset for accessing the variable associated with the given vertex from the local subvector.
81124121865SAdrian Maldonado 
81224121865SAdrian Maldonado   Not Collective
81324121865SAdrian Maldonado 
81424121865SAdrian Maldonado   Input Parameters:
81524121865SAdrian Maldonado + dm     - The DMNetwork object
81624121865SAdrian Maldonado - p      - the vertex point
81724121865SAdrian Maldonado 
81824121865SAdrian Maldonado   Output Parameters:
81924121865SAdrian Maldonado . offset - the offset
82024121865SAdrian Maldonado 
82124121865SAdrian Maldonado   Level: intermediate
82224121865SAdrian Maldonado 
82324121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
82424121865SAdrian Maldonado @*/
82524121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
82624121865SAdrian Maldonado {
82724121865SAdrian Maldonado   PetscErrorCode ierr;
82824121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
82924121865SAdrian Maldonado 
83024121865SAdrian Maldonado   PetscFunctionBegin;
83124121865SAdrian Maldonado 
83224121865SAdrian Maldonado   p -= network->vStart;
83324121865SAdrian Maldonado 
83424121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
83524121865SAdrian Maldonado   PetscFunctionReturn(0);
83624121865SAdrian Maldonado }
8375f2c45f1SShri Abhyankar /*@
8385f2c45f1SShri Abhyankar   DMNetworkAddNumVariables - Add number of variables associated with a given point.
8395f2c45f1SShri Abhyankar 
8405f2c45f1SShri Abhyankar   Not Collective
8415f2c45f1SShri Abhyankar 
8425f2c45f1SShri Abhyankar   Input Parameters:
8435f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
8445f2c45f1SShri Abhyankar . p    - the vertex/edge point
8455f2c45f1SShri Abhyankar - nvar - number of additional variables
8465f2c45f1SShri Abhyankar 
8475f2c45f1SShri Abhyankar   Level: intermediate
8485f2c45f1SShri Abhyankar 
8495f2c45f1SShri Abhyankar .seealso: DMNetworkSetNumVariables
8505f2c45f1SShri Abhyankar @*/
8515f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar)
8525f2c45f1SShri Abhyankar {
8535f2c45f1SShri Abhyankar   PetscErrorCode ierr;
8545f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8555f2c45f1SShri Abhyankar 
8565f2c45f1SShri Abhyankar   PetscFunctionBegin;
8575f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
8585f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8595f2c45f1SShri Abhyankar }
8605f2c45f1SShri Abhyankar 
86127f51fceSHong Zhang /*@
86227f51fceSHong Zhang   DMNetworkGetNumVariables - Gets number of variables for a vertex/edge point.
86327f51fceSHong Zhang 
86427f51fceSHong Zhang   Not Collective
86527f51fceSHong Zhang 
86627f51fceSHong Zhang   Input Parameters:
86727f51fceSHong Zhang + dm   - The DMNetworkObject
86827f51fceSHong Zhang - p    - the vertex/edge point
86927f51fceSHong Zhang 
87027f51fceSHong Zhang   Output Parameters:
87127f51fceSHong Zhang . nvar - number of variables
87227f51fceSHong Zhang 
87327f51fceSHong Zhang   Level: intermediate
87427f51fceSHong Zhang 
87527f51fceSHong Zhang .seealso: DMNetworkAddNumVariables, DMNetworkSddNumVariables
87627f51fceSHong Zhang @*/
87727f51fceSHong Zhang PetscErrorCode DMNetworkGetNumVariables(DM dm,PetscInt p,PetscInt *nvar)
87827f51fceSHong Zhang {
87927f51fceSHong Zhang   PetscErrorCode ierr;
88027f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
88127f51fceSHong Zhang 
88227f51fceSHong Zhang   PetscFunctionBegin;
88327f51fceSHong Zhang   ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
88427f51fceSHong Zhang   PetscFunctionReturn(0);
88527f51fceSHong Zhang }
88627f51fceSHong Zhang 
8875f2c45f1SShri Abhyankar /*@
8885f2c45f1SShri Abhyankar   DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point.
8895f2c45f1SShri Abhyankar 
8905f2c45f1SShri Abhyankar   Not Collective
8915f2c45f1SShri Abhyankar 
8925f2c45f1SShri Abhyankar   Input Parameters:
8935f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
8945f2c45f1SShri Abhyankar . p    - the vertex/edge point
8955f2c45f1SShri Abhyankar - nvar - number of variables
8965f2c45f1SShri Abhyankar 
8975f2c45f1SShri Abhyankar   Level: intermediate
8985f2c45f1SShri Abhyankar 
8995f2c45f1SShri Abhyankar .seealso: DMNetworkAddNumVariables
9005f2c45f1SShri Abhyankar @*/
9015f2c45f1SShri Abhyankar PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar)
9025f2c45f1SShri Abhyankar {
9035f2c45f1SShri Abhyankar   PetscErrorCode ierr;
9045f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
9055f2c45f1SShri Abhyankar 
9065f2c45f1SShri Abhyankar   PetscFunctionBegin;
9075f2c45f1SShri Abhyankar   ierr = PetscSectionSetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
9085f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9095f2c45f1SShri Abhyankar }
9105f2c45f1SShri Abhyankar 
9115f2c45f1SShri Abhyankar /* Sets up the array that holds the data for all components and its associated section. This
9125f2c45f1SShri Abhyankar    function is called during DMSetUp() */
9135f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
9145f2c45f1SShri Abhyankar {
9155f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
9165f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
917e53b5ba3SHong Zhang   PetscInt                 arr_size,p,offset,offsetp,ncomp,i;
9185f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
9195f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
9205f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
9215f2c45f1SShri Abhyankar 
9225f2c45f1SShri Abhyankar   PetscFunctionBegin;
9235f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
9245f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
92575b160a0SShri Abhyankar   ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
9265f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
9275f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
9285f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
9295f2c45f1SShri Abhyankar     /* Copy header */
9305f2c45f1SShri Abhyankar     header = &network->header[p];
931302440fdSBarry Smith     ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
9325f2c45f1SShri Abhyankar     /* Copy data */
9335f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
9345f2c45f1SShri Abhyankar     ncomp = header->ndata;
9355f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
9365f2c45f1SShri Abhyankar       offset = offsetp + network->dataheadersize + header->offset[i];
937302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
9385f2c45f1SShri Abhyankar     }
9395f2c45f1SShri Abhyankar   }
9405f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9415f2c45f1SShri Abhyankar }
9425f2c45f1SShri Abhyankar 
9435f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
9445f2c45f1SShri Abhyankar PetscErrorCode DMNetworkVariablesSetUp(DM dm)
9455f2c45f1SShri Abhyankar {
9465f2c45f1SShri Abhyankar   PetscErrorCode ierr;
9475f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
9485f2c45f1SShri Abhyankar 
9495f2c45f1SShri Abhyankar   PetscFunctionBegin;
9505f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
9515f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9525f2c45f1SShri Abhyankar }
9535f2c45f1SShri Abhyankar 
9545f2c45f1SShri Abhyankar /*@C
9555f2c45f1SShri Abhyankar   DMNetworkGetComponentDataArray - Returns the component data array
9565f2c45f1SShri Abhyankar 
9575f2c45f1SShri Abhyankar   Not Collective
9585f2c45f1SShri Abhyankar 
9595f2c45f1SShri Abhyankar   Input Parameters:
9605f2c45f1SShri Abhyankar . dm - The DMNetwork Object
9615f2c45f1SShri Abhyankar 
9625f2c45f1SShri Abhyankar   Output Parameters:
9635f2c45f1SShri Abhyankar . componentdataarray - array that holds data for all components
9645f2c45f1SShri Abhyankar 
9655f2c45f1SShri Abhyankar   Level: intermediate
9665f2c45f1SShri Abhyankar 
967a730d845SHong Zhang .seealso: DMNetworkGetComponentKeyOffset, DMNetworkGetNumComponents
9685f2c45f1SShri Abhyankar @*/
9695f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray)
9705f2c45f1SShri Abhyankar {
9715f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
9725f2c45f1SShri Abhyankar 
9735f2c45f1SShri Abhyankar   PetscFunctionBegin;
9745f2c45f1SShri Abhyankar   *componentdataarray = network->componentdataarray;
9755f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9765f2c45f1SShri Abhyankar }
9775f2c45f1SShri Abhyankar 
97824121865SAdrian Maldonado /* Get a subsection from a range of points */
97924121865SAdrian Maldonado PetscErrorCode DMNetworkGetSubSection_private(PetscSection master, PetscInt pstart, PetscInt pend,PetscSection *subsection)
98024121865SAdrian Maldonado {
98124121865SAdrian Maldonado   PetscErrorCode ierr;
98224121865SAdrian Maldonado   PetscInt       i, nvar;
98324121865SAdrian Maldonado 
98424121865SAdrian Maldonado   PetscFunctionBegin;
98524121865SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)master), subsection);CHKERRQ(ierr);
98624121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
98724121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
98824121865SAdrian Maldonado     ierr = PetscSectionGetDof(master,i,&nvar);CHKERRQ(ierr);
98924121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
99024121865SAdrian Maldonado   }
99124121865SAdrian Maldonado 
99224121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
99324121865SAdrian Maldonado   PetscFunctionReturn(0);
99424121865SAdrian Maldonado }
99524121865SAdrian Maldonado 
99624121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
99724121865SAdrian Maldonado PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
99824121865SAdrian Maldonado {
99924121865SAdrian Maldonado   PetscErrorCode ierr;
100024121865SAdrian Maldonado   PetscInt       i, *subpoints;
100124121865SAdrian Maldonado 
100224121865SAdrian Maldonado   PetscFunctionBegin;
100324121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
100424121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
100524121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
100624121865SAdrian Maldonado     subpoints[i - pstart] = i;
100724121865SAdrian Maldonado   }
1008459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
100924121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
101024121865SAdrian Maldonado   PetscFunctionReturn(0);
101124121865SAdrian Maldonado }
101224121865SAdrian Maldonado 
101324121865SAdrian Maldonado /*@
101424121865SAdrian Maldonado   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute.
101524121865SAdrian Maldonado 
101624121865SAdrian Maldonado   Collective
101724121865SAdrian Maldonado 
101824121865SAdrian Maldonado   Input Parameters:
101924121865SAdrian Maldonado . dm   - The DMNetworkObject
102024121865SAdrian Maldonado 
102124121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
102224121865SAdrian Maldonado 
102324121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
102424121865SAdrian Maldonado 
1025caf410d2SHong 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]).
102624121865SAdrian Maldonado 
102724121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
102824121865SAdrian Maldonado 
102924121865SAdrian Maldonado   Level: intermediate
103024121865SAdrian Maldonado 
103124121865SAdrian Maldonado @*/
1032*22bbedd7SHong Zhang 
103324121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
103424121865SAdrian Maldonado {
103524121865SAdrian Maldonado   PetscErrorCode ierr;
103624121865SAdrian Maldonado   MPI_Comm       comm;
10379852e123SBarry Smith   PetscMPIInt    rank, size;
103824121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
103924121865SAdrian Maldonado 
1040eab1376dSHong Zhang   PetscFunctionBegin;
104124121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
104224121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
10439852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
104424121865SAdrian Maldonado 
104524121865SAdrian Maldonado   /* Create maps for vertices and edges */
104624121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
104724121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
104824121865SAdrian Maldonado 
104924121865SAdrian Maldonado   /* Create local sub-sections */
105024121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
105124121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
105224121865SAdrian Maldonado 
10539852e123SBarry Smith   if (size > 1) {
105424121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
1055*22bbedd7SHong Zhang 
105624121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
105724121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
105824121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
105924121865SAdrian Maldonado   } else {
106024121865SAdrian Maldonado     /* create structures for vertex */
106124121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
106224121865SAdrian Maldonado     /* create structures for edge */
106324121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
106424121865SAdrian Maldonado   }
106524121865SAdrian Maldonado 
106624121865SAdrian Maldonado   /* Add viewers */
106724121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
106824121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
106924121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
107024121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
107124121865SAdrian Maldonado   PetscFunctionReturn(0);
107224121865SAdrian Maldonado }
10737b6afd5bSHong Zhang 
10745f2c45f1SShri Abhyankar /*@
10755f2c45f1SShri Abhyankar   DMNetworkDistribute - Distributes the network and moves associated component data.
10765f2c45f1SShri Abhyankar 
10775f2c45f1SShri Abhyankar   Collective
10785f2c45f1SShri Abhyankar 
10795f2c45f1SShri Abhyankar   Input Parameter:
1080d3464fd4SAdrian Maldonado + DM - the DMNetwork object
10815f2c45f1SShri Abhyankar - overlap - The overlap of partitions, 0 is the default
10825f2c45f1SShri Abhyankar 
10835f2c45f1SShri Abhyankar   Notes:
10848b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
10855f2c45f1SShri Abhyankar 
10865f2c45f1SShri Abhyankar   Level: intermediate
10875f2c45f1SShri Abhyankar 
10885f2c45f1SShri Abhyankar .seealso: DMNetworkCreate
10895f2c45f1SShri Abhyankar @*/
1090d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
10915f2c45f1SShri Abhyankar {
1092d3464fd4SAdrian Maldonado   MPI_Comm       comm;
10935f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1094d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1095d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1096d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1097caf410d2SHong Zhang   PetscSF        pointsf=NULL;
10985f2c45f1SShri Abhyankar   DM             newDM;
1099caf410d2SHong Zhang   PetscInt       j,e,v,offset,*subnetvtx;
110051ac5effSHong Zhang   PetscPartitioner         part;
1101b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
11025f2c45f1SShri Abhyankar 
11035f2c45f1SShri Abhyankar   PetscFunctionBegin;
1104d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1105d3464fd4SAdrian Maldonado   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
1106d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1107d3464fd4SAdrian Maldonado 
1108d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
11095f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
11105f2c45f1SShri Abhyankar   newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
111151ac5effSHong Zhang 
111251ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
111351ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
111451ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
111551ac5effSHong Zhang 
11165f2c45f1SShri Abhyankar   /* Distribute plex dm and dof section */
111780cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
111851ac5effSHong Zhang 
11195f2c45f1SShri Abhyankar   /* Distribute dof section */
1120d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DofSection);CHKERRQ(ierr);
11215f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
1122d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DataSection);CHKERRQ(ierr);
112351ac5effSHong Zhang 
11245f2c45f1SShri Abhyankar   /* Distribute data and associated section */
112531da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
112624121865SAdrian Maldonado 
11275f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
11285f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
11295f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
11305f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
11316fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
11326fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
11335f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
113424121865SAdrian Maldonado 
11355f2c45f1SShri Abhyankar   /* Set Dof section as the default section for dm */
1136e87a4003SBarry Smith   ierr = DMSetSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1137e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
11385f2c45f1SShri Abhyankar 
1139b9c6e19dSShri Abhyankar   /* Set up subnetwork info in the newDM */
1140b9c6e19dSShri Abhyankar   newDMnetwork->nsubnet  = oldDMnetwork->nsubnet;
1141caf410d2SHong Zhang   newDMnetwork->ncsubnet = oldDMnetwork->ncsubnet;
1142b9c6e19dSShri Abhyankar   ierr = PetscCalloc1(newDMnetwork->nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
1143b9c6e19dSShri Abhyankar   /* Copy over the global number of vertices and edges in each subnetwork. Note that these are already
1144b9c6e19dSShri Abhyankar      calculated in DMNetworkLayoutSetUp()
1145b9c6e19dSShri Abhyankar   */
1146b9c6e19dSShri Abhyankar   for(j=0; j < newDMnetwork->nsubnet; j++) {
1147b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1148b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1149b9c6e19dSShri Abhyankar   }
1150b9c6e19dSShri Abhyankar 
1151b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1152b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1153b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1154b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1155b9c6e19dSShri Abhyankar   }
1156b9c6e19dSShri Abhyankar 
1157b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1158b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1159b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1160b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nvtx++;
1161b9c6e19dSShri Abhyankar   }
1162b9c6e19dSShri Abhyankar 
1163b9c6e19dSShri Abhyankar   /* Now create the vertices and edge arrays for the subnetworks */
1164caf410d2SHong Zhang   ierr = PetscCalloc1(newDMnetwork->vEnd-newDMnetwork->vStart,&newDMnetwork->subnetvtx);CHKERRQ(ierr);
1165caf410d2SHong Zhang   subnetvtx = newDMnetwork->subnetvtx;
1166caf410d2SHong Zhang 
1167b9c6e19dSShri Abhyankar   for (j=0; j<newDMnetwork->nsubnet; j++) {
1168b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr);
1169caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1170caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1171caf410d2SHong Zhang 
1172b9c6e19dSShri Abhyankar     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
1173b9c6e19dSShri Abhyankar        These get updated when the vertices and edges are added. */
1174b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1175b9c6e19dSShri Abhyankar   }
1176b9c6e19dSShri Abhyankar 
1177b9c6e19dSShri Abhyankar   /* Set the vertices and edges in each subnetwork */
1178b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1179b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1180b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1181b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1182b9c6e19dSShri Abhyankar   }
1183b9c6e19dSShri Abhyankar 
1184b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1185b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1186b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1187b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
1188b9c6e19dSShri Abhyankar   }
1189b9c6e19dSShri Abhyankar 
1190caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
1191*22bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1192caf410d2SHong Zhang 
119324121865SAdrian Maldonado   /* Destroy point SF */
119424121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
119524121865SAdrian Maldonado 
1196d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
1197d3464fd4SAdrian Maldonado   *dm  = newDM;
11985f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
11995f2c45f1SShri Abhyankar }
12005f2c45f1SShri Abhyankar 
120124121865SAdrian Maldonado /*@C
120224121865SAdrian Maldonado   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering.
120324121865SAdrian Maldonado 
120424121865SAdrian Maldonado   Input Parameters:
120524121865SAdrian Maldonado + masterSF - the original SF structure
120624121865SAdrian Maldonado - map      - a ISLocalToGlobal mapping that contains the subset of points
120724121865SAdrian Maldonado 
120824121865SAdrian Maldonado   Output Parameters:
120924121865SAdrian Maldonado . subSF    - a subset of the masterSF for the desired subset.
121024121865SAdrian Maldonado */
121124121865SAdrian Maldonado 
121224121865SAdrian Maldonado PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) {
121324121865SAdrian Maldonado 
121424121865SAdrian Maldonado   PetscErrorCode        ierr;
121524121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
121624121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
121724121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
121824121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
121924121865SAdrian Maldonado   const PetscInt        *ilocal;
122024121865SAdrian Maldonado   const PetscSFNode     *iremote;
122124121865SAdrian Maldonado 
122224121865SAdrian Maldonado   PetscFunctionBegin;
122324121865SAdrian Maldonado   ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
122424121865SAdrian Maldonado 
122524121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
122624121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
122724121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
122824121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
122924121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
123024121865SAdrian Maldonado   }
123124121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
123224121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
123324121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
123424121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
123524121865SAdrian Maldonado   ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
123624121865SAdrian Maldonado   ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
123724121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
12384b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
12394b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
124024121865SAdrian Maldonado   nleaves_sub = 0;
124124121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
124224121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
124324121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
12444b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
124524121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
124624121865SAdrian Maldonado       nleaves_sub += 1;
124724121865SAdrian Maldonado     }
124824121865SAdrian Maldonado   }
124924121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
125024121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
125124121865SAdrian Maldonado 
125224121865SAdrian Maldonado   /* Create new subSF */
125324121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
125424121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
12554b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
125624121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
12574b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
125824121865SAdrian Maldonado   PetscFunctionReturn(0);
125924121865SAdrian Maldonado }
126024121865SAdrian Maldonado 
12615f2c45f1SShri Abhyankar /*@C
12625f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
12635f2c45f1SShri Abhyankar 
12645f2c45f1SShri Abhyankar   Not Collective
12655f2c45f1SShri Abhyankar 
12665f2c45f1SShri Abhyankar   Input Parameters:
12675f2c45f1SShri Abhyankar + dm - The DMNetwork object
12685f2c45f1SShri Abhyankar - p  - the vertex point
12695f2c45f1SShri Abhyankar 
12705f2c45f1SShri Abhyankar   Output Paramters:
12715f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
12725f2c45f1SShri Abhyankar - edges  - List of edge points
12735f2c45f1SShri Abhyankar 
12745f2c45f1SShri Abhyankar   Level: intermediate
12755f2c45f1SShri Abhyankar 
12765f2c45f1SShri Abhyankar   Fortran Notes:
12775f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
12785f2c45f1SShri Abhyankar   include petsc.h90 in your code.
12795f2c45f1SShri Abhyankar 
1280d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices
12815f2c45f1SShri Abhyankar @*/
12825f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
12835f2c45f1SShri Abhyankar {
12845f2c45f1SShri Abhyankar   PetscErrorCode ierr;
12855f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
12865f2c45f1SShri Abhyankar 
12875f2c45f1SShri Abhyankar   PetscFunctionBegin;
12885f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
12895f2c45f1SShri Abhyankar   ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);
12905f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
12915f2c45f1SShri Abhyankar }
12925f2c45f1SShri Abhyankar 
12935f2c45f1SShri Abhyankar /*@C
1294d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
12955f2c45f1SShri Abhyankar 
12965f2c45f1SShri Abhyankar   Not Collective
12975f2c45f1SShri Abhyankar 
12985f2c45f1SShri Abhyankar   Input Parameters:
12995f2c45f1SShri Abhyankar + dm - The DMNetwork object
13005f2c45f1SShri Abhyankar - p  - the edge point
13015f2c45f1SShri Abhyankar 
13025f2c45f1SShri Abhyankar   Output Paramters:
13035f2c45f1SShri Abhyankar . vertices  - vertices connected to this edge
13045f2c45f1SShri Abhyankar 
13055f2c45f1SShri Abhyankar   Level: intermediate
13065f2c45f1SShri Abhyankar 
13075f2c45f1SShri Abhyankar   Fortran Notes:
13085f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
13095f2c45f1SShri Abhyankar   include petsc.h90 in your code.
13105f2c45f1SShri Abhyankar 
13115f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
13125f2c45f1SShri Abhyankar @*/
1313d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
13145f2c45f1SShri Abhyankar {
13155f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13165f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
13175f2c45f1SShri Abhyankar 
13185f2c45f1SShri Abhyankar   PetscFunctionBegin;
13195f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
13205f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13215f2c45f1SShri Abhyankar }
13225f2c45f1SShri Abhyankar 
13235f2c45f1SShri Abhyankar /*@
13245f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
13255f2c45f1SShri Abhyankar 
13265f2c45f1SShri Abhyankar   Not Collective
13275f2c45f1SShri Abhyankar 
13285f2c45f1SShri Abhyankar   Input Parameters:
13295f2c45f1SShri Abhyankar + dm - The DMNetwork object
13305f2c45f1SShri Abhyankar . p  - the vertex point
13315f2c45f1SShri Abhyankar 
13325f2c45f1SShri Abhyankar   Output Parameter:
13335f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
13345f2c45f1SShri Abhyankar 
13355f2c45f1SShri Abhyankar   Level: intermediate
13365f2c45f1SShri Abhyankar 
1337d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange
13385f2c45f1SShri Abhyankar @*/
13395f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
13405f2c45f1SShri Abhyankar {
13415f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13425f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
13435f2c45f1SShri Abhyankar   PetscInt       offsetg;
13445f2c45f1SShri Abhyankar   PetscSection   sectiong;
13455f2c45f1SShri Abhyankar 
13465f2c45f1SShri Abhyankar   PetscFunctionBegin;
1347caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
13485f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
1349e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
13505f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
13515f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
13525f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13535f2c45f1SShri Abhyankar }
13545f2c45f1SShri Abhyankar 
13555f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
13565f2c45f1SShri Abhyankar {
13575f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13585f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
13595f2c45f1SShri Abhyankar 
13605f2c45f1SShri Abhyankar   PetscFunctionBegin;
13615f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
13625f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
13635f2c45f1SShri Abhyankar 
1364e87a4003SBarry Smith   ierr = DMSetSection(network->plex,network->DofSection);CHKERRQ(ierr);
1365e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
13669e1d080bSHong Zhang 
13679e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
13689e1d080bSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr);
13695f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13705f2c45f1SShri Abhyankar }
13715f2c45f1SShri Abhyankar 
13721ad426b7SHong Zhang /*@
137317df6e9eSHong Zhang     DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
13741ad426b7SHong Zhang                             -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
13751ad426b7SHong Zhang 
13761ad426b7SHong Zhang     Collective
13771ad426b7SHong Zhang 
13781ad426b7SHong Zhang     Input Parameters:
137983b2e829SHong Zhang +   dm - The DMNetwork object
138083b2e829SHong Zhang .   eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
138183b2e829SHong Zhang -   vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
13821ad426b7SHong Zhang 
13831ad426b7SHong Zhang     Level: intermediate
13841ad426b7SHong Zhang 
13851ad426b7SHong Zhang @*/
138683b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
13871ad426b7SHong Zhang {
13881ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
13898675203cSHong Zhang   PetscErrorCode ierr;
139066b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
13911ad426b7SHong Zhang 
13921ad426b7SHong Zhang   PetscFunctionBegin;
139383b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
139483b2e829SHong Zhang   network->userVertexJacobian = vflg;
13958675203cSHong Zhang 
13968675203cSHong Zhang   if (eflg && !network->Je) {
13978675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
13988675203cSHong Zhang   }
13998675203cSHong Zhang 
140066b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
14018675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
140266b4e0ffSHong Zhang     PetscInt       nedges_total;
14038675203cSHong Zhang     const PetscInt *edges;
14048675203cSHong Zhang 
14058675203cSHong Zhang     /* count nvertex_total */
14068675203cSHong Zhang     nedges_total = 0;
14078675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
14088675203cSHong Zhang 
14098675203cSHong Zhang     vptr[0] = 0;
14108675203cSHong Zhang     for (i=0; i<nVertices; i++) {
14118675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
14128675203cSHong Zhang       nedges_total += nedges;
14138675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
14148675203cSHong Zhang     }
14158675203cSHong Zhang 
14168675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
14178675203cSHong Zhang     network->Jvptr = vptr;
14188675203cSHong Zhang   }
14191ad426b7SHong Zhang   PetscFunctionReturn(0);
14201ad426b7SHong Zhang }
14211ad426b7SHong Zhang 
14221ad426b7SHong Zhang /*@
142383b2e829SHong Zhang     DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
142483b2e829SHong Zhang 
142583b2e829SHong Zhang     Not Collective
142683b2e829SHong Zhang 
142783b2e829SHong Zhang     Input Parameters:
142883b2e829SHong Zhang +   dm - The DMNetwork object
142983b2e829SHong Zhang .   p  - the edge point
14303e97b6e8SHong Zhang -   J - array (size = 3) of Jacobian submatrices for this edge point:
14313e97b6e8SHong Zhang         J[0]: this edge
1432d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
143383b2e829SHong Zhang 
143483b2e829SHong Zhang     Level: intermediate
143583b2e829SHong Zhang 
143683b2e829SHong Zhang .seealso: DMNetworkVertexSetMatrix
143783b2e829SHong Zhang @*/
143883b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
143983b2e829SHong Zhang {
144083b2e829SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
144183b2e829SHong Zhang 
144283b2e829SHong Zhang   PetscFunctionBegin;
14438675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
14448675203cSHong Zhang 
14458675203cSHong Zhang   if (J) {
1446883e35e8SHong Zhang     network->Je[3*p]   = J[0];
1447883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
1448883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
14498675203cSHong Zhang   }
145083b2e829SHong Zhang   PetscFunctionReturn(0);
145183b2e829SHong Zhang }
145283b2e829SHong Zhang 
145383b2e829SHong Zhang /*@
145476ddfea5SHong Zhang     DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
14551ad426b7SHong Zhang 
14561ad426b7SHong Zhang     Not Collective
14571ad426b7SHong Zhang 
14581ad426b7SHong Zhang     Input Parameters:
14591ad426b7SHong Zhang +   dm - The DMNetwork object
14601ad426b7SHong Zhang .   p  - the vertex point
14613e97b6e8SHong Zhang -   J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
14623e97b6e8SHong Zhang         J[0]:       this vertex
14633e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
14643e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
14651ad426b7SHong Zhang 
14661ad426b7SHong Zhang     Level: intermediate
14671ad426b7SHong Zhang 
146883b2e829SHong Zhang .seealso: DMNetworkEdgeSetMatrix
14691ad426b7SHong Zhang @*/
1470883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
14715f2c45f1SShri Abhyankar {
14725f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14735f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
14748675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
1475883e35e8SHong Zhang   const PetscInt *edges;
14765f2c45f1SShri Abhyankar 
14775f2c45f1SShri Abhyankar   PetscFunctionBegin;
14788675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1479883e35e8SHong Zhang 
14808675203cSHong Zhang   if (J) {
1481883e35e8SHong Zhang     vptr = network->Jvptr;
14823e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
14833e97b6e8SHong Zhang 
14843e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
1485883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
1486883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
14878675203cSHong Zhang   }
1488883e35e8SHong Zhang   PetscFunctionReturn(0);
1489883e35e8SHong Zhang }
1490883e35e8SHong Zhang 
1491e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
14925cf7da58SHong Zhang {
14935cf7da58SHong Zhang   PetscErrorCode ierr;
14945cf7da58SHong Zhang   PetscInt       j;
14955cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
14965cf7da58SHong Zhang 
14975cf7da58SHong Zhang   PetscFunctionBegin;
14985cf7da58SHong Zhang   if (!ghost) {
14995cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
15005cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
15015cf7da58SHong Zhang     }
15025cf7da58SHong Zhang   } else {
15035cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
15045cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
15055cf7da58SHong Zhang     }
15065cf7da58SHong Zhang   }
15075cf7da58SHong Zhang   PetscFunctionReturn(0);
15085cf7da58SHong Zhang }
15095cf7da58SHong Zhang 
1510e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
15115cf7da58SHong Zhang {
15125cf7da58SHong Zhang   PetscErrorCode ierr;
15135cf7da58SHong Zhang   PetscInt       j,ncols_u;
15145cf7da58SHong Zhang   PetscScalar    val;
15155cf7da58SHong Zhang 
15165cf7da58SHong Zhang   PetscFunctionBegin;
15175cf7da58SHong Zhang   if (!ghost) {
15185cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
15195cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
15205cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
15215cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
15225cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
15235cf7da58SHong Zhang     }
15245cf7da58SHong Zhang   } else {
15255cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
15265cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
15275cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
15285cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
15295cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
15305cf7da58SHong Zhang     }
15315cf7da58SHong Zhang   }
15325cf7da58SHong Zhang   PetscFunctionReturn(0);
15335cf7da58SHong Zhang }
15345cf7da58SHong Zhang 
1535e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
15365cf7da58SHong Zhang {
15375cf7da58SHong Zhang   PetscErrorCode ierr;
15385cf7da58SHong Zhang 
15395cf7da58SHong Zhang   PetscFunctionBegin;
15405cf7da58SHong Zhang   if (Ju) {
15415cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
15425cf7da58SHong Zhang   } else {
15435cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
15445cf7da58SHong Zhang   }
15455cf7da58SHong Zhang   PetscFunctionReturn(0);
15465cf7da58SHong Zhang }
15475cf7da58SHong Zhang 
1548e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1549883e35e8SHong Zhang {
1550883e35e8SHong Zhang   PetscErrorCode ierr;
1551883e35e8SHong Zhang   PetscInt       j,*cols;
1552883e35e8SHong Zhang   PetscScalar    *zeros;
1553883e35e8SHong Zhang 
1554883e35e8SHong Zhang   PetscFunctionBegin;
1555883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
1556883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
1557883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
1558883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
15591ad426b7SHong Zhang   PetscFunctionReturn(0);
15601ad426b7SHong Zhang }
1561a4e85ca8SHong Zhang 
1562e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
15633e97b6e8SHong Zhang {
15643e97b6e8SHong Zhang   PetscErrorCode ierr;
15653e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
15663e97b6e8SHong Zhang   const PetscInt *cols;
15673e97b6e8SHong Zhang   PetscScalar    zero=0.0;
15683e97b6e8SHong Zhang 
15693e97b6e8SHong Zhang   PetscFunctionBegin;
15703e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
15713e97b6e8SHong 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);
15723e97b6e8SHong Zhang 
15733e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
15743e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
15753e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
15763e97b6e8SHong Zhang       col = cols[j] + cstart;
15773e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
15783e97b6e8SHong Zhang     }
15793e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
15803e97b6e8SHong Zhang   }
15813e97b6e8SHong Zhang   PetscFunctionReturn(0);
15823e97b6e8SHong Zhang }
15831ad426b7SHong Zhang 
1584e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1585a4e85ca8SHong Zhang {
1586a4e85ca8SHong Zhang   PetscErrorCode ierr;
1587f4431b8cSHong Zhang 
1588a4e85ca8SHong Zhang   PetscFunctionBegin;
1589a4e85ca8SHong Zhang   if (Ju) {
1590a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1591a4e85ca8SHong Zhang   } else {
1592a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1593a4e85ca8SHong Zhang   }
1594a4e85ca8SHong Zhang   PetscFunctionReturn(0);
1595a4e85ca8SHong Zhang }
1596a4e85ca8SHong Zhang 
159724121865SAdrian 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.
159824121865SAdrian Maldonado */
159924121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
160024121865SAdrian Maldonado {
160124121865SAdrian Maldonado   PetscErrorCode ierr;
160224121865SAdrian Maldonado   PetscInt       i,size,dof;
160324121865SAdrian Maldonado   PetscInt       *glob2loc;
160424121865SAdrian Maldonado 
160524121865SAdrian Maldonado   PetscFunctionBegin;
160624121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
160724121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
160824121865SAdrian Maldonado 
160924121865SAdrian Maldonado   for (i = 0; i < size; i++) {
161024121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
161124121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
161224121865SAdrian Maldonado     glob2loc[i] = dof;
161324121865SAdrian Maldonado   }
161424121865SAdrian Maldonado 
161524121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
161624121865SAdrian Maldonado #if 0
161724121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
161824121865SAdrian Maldonado #endif
161924121865SAdrian Maldonado   PetscFunctionReturn(0);
162024121865SAdrian Maldonado }
162124121865SAdrian Maldonado 
162201ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
16239e1d080bSHong Zhang 
16249e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
16251ad426b7SHong Zhang {
16261ad426b7SHong Zhang   PetscErrorCode ierr;
16271ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
16289e1d080bSHong Zhang   PetscMPIInt    rank, size;
162924121865SAdrian Maldonado   PetscInt       eDof,vDof;
163024121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
16319e1d080bSHong Zhang   MPI_Comm       comm;
163224121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
163324121865SAdrian Maldonado 
16349e1d080bSHong Zhang   PetscFunctionBegin;
163524121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
163624121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
163724121865SAdrian Maldonado   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
163824121865SAdrian Maldonado 
163924121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
164024121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
164124121865SAdrian Maldonado 
164201ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
164324121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
164424121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
164524121865SAdrian Maldonado 
164601ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
164724121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
164824121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
164924121865SAdrian Maldonado 
165001ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
165124121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
165224121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
165324121865SAdrian Maldonado 
165401ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
165524121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
165624121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
165724121865SAdrian Maldonado 
16583f6a6bdaSHong Zhang   bA[0][0] = j11;
16593f6a6bdaSHong Zhang   bA[0][1] = j12;
16603f6a6bdaSHong Zhang   bA[1][0] = j21;
16613f6a6bdaSHong Zhang   bA[1][1] = j22;
166224121865SAdrian Maldonado 
166324121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
166424121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
166524121865SAdrian Maldonado 
166624121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
166724121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
166824121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
166924121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
167024121865SAdrian Maldonado 
167124121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
167224121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
167324121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
167424121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
167524121865SAdrian Maldonado 
167601ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
167724121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
167824121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
167924121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
168024121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
168124121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
168224121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
168324121865SAdrian Maldonado 
168424121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
168524121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16869e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
168724121865SAdrian Maldonado 
168824121865SAdrian Maldonado   /* Free structures */
168924121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
169024121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
169124121865SAdrian Maldonado   PetscFunctionReturn(0);
16929e1d080bSHong Zhang }
16939e1d080bSHong Zhang 
16949e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
16959e1d080bSHong Zhang {
16969e1d080bSHong Zhang   PetscErrorCode ierr;
16979e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
16989e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
16999e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
17009e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
17019e1d080bSHong Zhang   Mat            Juser;
17029e1d080bSHong Zhang   PetscSection   sectionGlobal;
17039e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
17049e1d080bSHong Zhang   const PetscInt *edges,*cone;
17059e1d080bSHong Zhang   MPI_Comm       comm;
17069e1d080bSHong Zhang   MatType        mtype;
17079e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
17089e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
17099e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
17109e1d080bSHong Zhang 
17119e1d080bSHong Zhang   PetscFunctionBegin;
17129e1d080bSHong Zhang   mtype = dm->mattype;
17139e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
17149e1d080bSHong Zhang   if (isNest) {
17159e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
17169e1d080bSHong Zhang     PetscFunctionReturn(0);
17179e1d080bSHong Zhang   }
17189e1d080bSHong Zhang 
17199e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
1720a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
17219e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
1722bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
17231ad426b7SHong Zhang     PetscFunctionReturn(0);
17241ad426b7SHong Zhang   }
17251ad426b7SHong Zhang 
1726bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
1727e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
1728bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
1729bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
17302a945128SHong Zhang 
17312a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
17322a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
173389898e50SHong Zhang 
173489898e50SHong Zhang   /* (1) Set matrix preallocation */
173589898e50SHong Zhang   /*------------------------------*/
1736840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1737840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
1738840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
1739840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
1740840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
1741840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
1742840c2264SHong Zhang 
174389898e50SHong Zhang   /* Set preallocation for edges */
174489898e50SHong Zhang   /*-----------------------------*/
1745840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
1746840c2264SHong Zhang 
1747bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
1748840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
1749840c2264SHong Zhang     /* Get row indices */
1750840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
1751840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
1752840c2264SHong Zhang     if (nrows) {
1753840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
1754840c2264SHong Zhang 
17555cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
1756d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1757840c2264SHong Zhang       for (v=0; v<2; v++) {
1758840c2264SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
1759840c2264SHong Zhang 
17608675203cSHong Zhang         if (network->Je) {
1761840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
17628675203cSHong Zhang         } else Juser = NULL;
1763840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
17645cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1765840c2264SHong Zhang       }
1766840c2264SHong Zhang 
176789898e50SHong Zhang       /* Set preallocation for edge self */
1768840c2264SHong Zhang       cstart = rstart;
17698675203cSHong Zhang       if (network->Je) {
1770840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
17718675203cSHong Zhang       } else Juser = NULL;
17725cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1773840c2264SHong Zhang     }
1774840c2264SHong Zhang   }
1775840c2264SHong Zhang 
177689898e50SHong Zhang   /* Set preallocation for vertices */
177789898e50SHong Zhang   /*--------------------------------*/
1778840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
17798675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
1780840c2264SHong Zhang 
1781840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
1782840c2264SHong Zhang     /* Get row indices */
1783840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1784840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
1785840c2264SHong Zhang     if (!nrows) continue;
1786840c2264SHong Zhang 
1787bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1788bdcb62a2SHong Zhang     if (ghost) {
1789bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1790bdcb62a2SHong Zhang     } else {
1791bdcb62a2SHong Zhang       rows_v = rows;
1792bdcb62a2SHong Zhang     }
1793bdcb62a2SHong Zhang 
1794bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1795840c2264SHong Zhang 
1796840c2264SHong Zhang     /* Get supporting edges and connected vertices */
1797840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1798840c2264SHong Zhang 
1799840c2264SHong Zhang     for (e=0; e<nedges; e++) {
1800840c2264SHong Zhang       /* Supporting edges */
1801840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1802840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1803840c2264SHong Zhang 
18048675203cSHong Zhang       if (network->Jv) {
1805840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
18068675203cSHong Zhang       } else Juser = NULL;
1807bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1808840c2264SHong Zhang 
1809840c2264SHong Zhang       /* Connected vertices */
1810d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
1811840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
1812840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
1813840c2264SHong Zhang 
1814840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1815840c2264SHong Zhang 
18168675203cSHong Zhang       if (network->Jv) {
1817840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
18188675203cSHong Zhang       } else Juser = NULL;
1819e102a522SHong Zhang       if (ghost_vc||ghost) {
1820e102a522SHong Zhang         ghost2 = PETSC_TRUE;
1821e102a522SHong Zhang       } else {
1822e102a522SHong Zhang         ghost2 = PETSC_FALSE;
1823e102a522SHong Zhang       }
1824e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
1825840c2264SHong Zhang     }
1826840c2264SHong Zhang 
182789898e50SHong Zhang     /* Set preallocation for vertex self */
1828840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1829840c2264SHong Zhang     if (!ghost) {
1830840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
18318675203cSHong Zhang       if (network->Jv) {
1832840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
18338675203cSHong Zhang       } else Juser = NULL;
1834bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1835840c2264SHong Zhang     }
1836bdcb62a2SHong Zhang     if (ghost) {
1837bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1838bdcb62a2SHong Zhang     }
1839840c2264SHong Zhang   }
1840840c2264SHong Zhang 
1841840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
1842840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
18435cf7da58SHong Zhang 
18445cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
18455cf7da58SHong Zhang 
18465cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
1847840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
1848840c2264SHong Zhang 
1849840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
1850840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
1851840c2264SHong Zhang   for (j=0; j<localSize; j++) {
1852e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
1853e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
1854840c2264SHong Zhang   }
1855840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
1856840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
1857840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
1858840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
1859840c2264SHong Zhang 
18605cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
18615cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
18625cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
18635cf7da58SHong Zhang 
18645cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
18655cf7da58SHong Zhang 
186689898e50SHong Zhang   /* (2) Set matrix entries for edges */
186789898e50SHong Zhang   /*----------------------------------*/
18681ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
1869bfbc38dcSHong Zhang     /* Get row indices */
18701ad426b7SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
187117df6e9eSHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
18724b976069SHong Zhang     if (nrows) {
187317df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
18741ad426b7SHong Zhang 
1875bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
1876d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1877bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
1878bfbc38dcSHong Zhang         ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr);
1879883e35e8SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
18803e97b6e8SHong Zhang 
18818675203cSHong Zhang         if (network->Je) {
1882a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
18838675203cSHong Zhang         } else Juser = NULL;
1884a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1885bfbc38dcSHong Zhang       }
188617df6e9eSHong Zhang 
1887bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
18883e97b6e8SHong Zhang       cstart = rstart;
18898675203cSHong Zhang       if (network->Je) {
1890a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
18918675203cSHong Zhang       } else Juser = NULL;
1892a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
18931ad426b7SHong Zhang     }
18944b976069SHong Zhang   }
18951ad426b7SHong Zhang 
1896bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
189783b2e829SHong Zhang   /*---------------------------------*/
18981ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
1899bfbc38dcSHong Zhang     /* Get row indices */
1900596e729fSHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1901596e729fSHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
19024b976069SHong Zhang     if (!nrows) continue;
1903596e729fSHong Zhang 
1904bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1905bdcb62a2SHong Zhang     if (ghost) {
1906bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1907bdcb62a2SHong Zhang     } else {
1908bdcb62a2SHong Zhang       rows_v = rows;
1909bdcb62a2SHong Zhang     }
1910bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1911596e729fSHong Zhang 
1912bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
1913596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1914596e729fSHong Zhang 
1915596e729fSHong Zhang     for (e=0; e<nedges; e++) {
1916bfbc38dcSHong Zhang       /* Supporting edges */
1917596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1918596e729fSHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1919596e729fSHong Zhang 
19208675203cSHong Zhang       if (network->Jv) {
1921a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
19228675203cSHong Zhang       } else Juser = NULL;
1923bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
1924596e729fSHong Zhang 
1925bfbc38dcSHong Zhang       /* Connected vertices */
1926d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
19272a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
19282a945128SHong Zhang 
192944aca652SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr);
193044aca652SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1931a4e85ca8SHong Zhang 
19328675203cSHong Zhang       if (network->Jv) {
1933a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
19348675203cSHong Zhang       } else Juser = NULL;
1935bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
1936596e729fSHong Zhang     }
1937596e729fSHong Zhang 
1938bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
19391ad426b7SHong Zhang     if (!ghost) {
1940596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
19418675203cSHong Zhang       if (network->Jv) {
1942a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
19438675203cSHong Zhang       } else Juser = NULL;
1944bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
1945bdcb62a2SHong Zhang     }
1946bdcb62a2SHong Zhang     if (ghost) {
1947bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1948bdcb62a2SHong Zhang     }
19491ad426b7SHong Zhang   }
1950a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
1951bdcb62a2SHong Zhang 
19521ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19531ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1954dd6f46cdSHong Zhang 
19555f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
19565f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19575f2c45f1SShri Abhyankar }
19585f2c45f1SShri Abhyankar 
19595f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
19605f2c45f1SShri Abhyankar {
19615f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19625f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19632727e31bSShri Abhyankar   PetscInt       j;
19645f2c45f1SShri Abhyankar 
19655f2c45f1SShri Abhyankar   PetscFunctionBegin;
19668415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
196783b2e829SHong Zhang   if (network->Je) {
196883b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
196983b2e829SHong Zhang   }
197083b2e829SHong Zhang   if (network->Jv) {
1971883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
197283b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
19731ad426b7SHong Zhang   }
197413c2a604SAdrian Maldonado 
197513c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
197613c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
197713c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
197813c2a604SAdrian Maldonado   if (network->vertex.sf) {
197913c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
198013c2a604SAdrian Maldonado   }
198113c2a604SAdrian Maldonado   /* edge */
198213c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
198313c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
198413c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
198513c2a604SAdrian Maldonado   if (network->edge.sf) {
198613c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
198713c2a604SAdrian Maldonado   }
19885f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
19895f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
19905f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
199183b2e829SHong Zhang 
19922727e31bSShri Abhyankar   for(j=0; j<network->nsubnet; j++) {
19932727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
19942727e31bSShri Abhyankar   }
1995caf410d2SHong Zhang   ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr);
1996caf410d2SHong Zhang 
1997e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
19985f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
1999caf410d2SHong Zhang   ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
20005f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
20015f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20025f2c45f1SShri Abhyankar }
20035f2c45f1SShri Abhyankar 
20045f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
20055f2c45f1SShri Abhyankar {
20065f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20075f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
2008caf410d2SHong Zhang   PetscBool      iascii;
2009caf410d2SHong Zhang   PetscMPIInt    rank;
2010caf410d2SHong Zhang   PetscInt       p,nsubnet;
20115f2c45f1SShri Abhyankar 
20125f2c45f1SShri Abhyankar   PetscFunctionBegin;
2013caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2014caf410d2SHong Zhang   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
2015caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2016caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2017caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2018caf410d2SHong Zhang   if (iascii) {
2019caf410d2SHong Zhang     const PetscInt    *cone,*vtx,*edges;
2020caf410d2SHong Zhang     PetscInt          vfrom,vto,i,j,nv,ne;
2021caf410d2SHong Zhang 
2022caf410d2SHong Zhang     nsubnet = network->nsubnet - network->ncsubnet; /* num of subnetworks */
2023caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
2024caf410d2SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nsubnet: %D; nsubnetCouple: %D; nEdges: %D; nVertices: %D\n",rank,nsubnet,network->ncsubnet,network->nEdges,network->nVertices);CHKERRQ(ierr);
2025caf410d2SHong Zhang 
2026caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
2027caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2028caf410d2SHong Zhang       if (ne) {
2029caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2030caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2031caf410d2SHong Zhang           p = edges[j];
2032caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2033caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2034caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2035caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2036caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2037caf410d2SHong Zhang         }
2038caf410d2SHong Zhang       }
2039caf410d2SHong Zhang     }
2040caf410d2SHong Zhang     /* Coupling subnets */
2041caf410d2SHong Zhang     nsubnet = network->nsubnet;
2042caf410d2SHong Zhang     for (; i<nsubnet; i++) {
2043caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2044caf410d2SHong Zhang       if (ne) {
2045caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D (couple): nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2046caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2047caf410d2SHong Zhang           p = edges[j];
2048caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2049caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2050caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2051caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2052caf410d2SHong Zhang         }
2053caf410d2SHong Zhang       }
2054caf410d2SHong Zhang     }
2055caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2056caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2057caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
20585f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20595f2c45f1SShri Abhyankar }
20605f2c45f1SShri Abhyankar 
20615f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
20625f2c45f1SShri Abhyankar {
20635f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20645f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20655f2c45f1SShri Abhyankar 
20665f2c45f1SShri Abhyankar   PetscFunctionBegin;
20675f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
20685f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20695f2c45f1SShri Abhyankar }
20705f2c45f1SShri Abhyankar 
20715f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
20725f2c45f1SShri Abhyankar {
20735f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20745f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20755f2c45f1SShri Abhyankar 
20765f2c45f1SShri Abhyankar   PetscFunctionBegin;
20775f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
20785f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20795f2c45f1SShri Abhyankar }
20805f2c45f1SShri Abhyankar 
20815f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
20825f2c45f1SShri Abhyankar {
20835f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20845f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20855f2c45f1SShri Abhyankar 
20865f2c45f1SShri Abhyankar   PetscFunctionBegin;
20875f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
20885f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20895f2c45f1SShri Abhyankar }
20905f2c45f1SShri Abhyankar 
20915f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
20925f2c45f1SShri Abhyankar {
20935f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20945f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20955f2c45f1SShri Abhyankar 
20965f2c45f1SShri Abhyankar   PetscFunctionBegin;
20975f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
20985f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20995f2c45f1SShri Abhyankar }
2100*22bbedd7SHong Zhang 
2101*22bbedd7SHong Zhang /*@
2102*22bbedd7SHong Zhang   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to globle map
2103*22bbedd7SHong Zhang 
2104*22bbedd7SHong Zhang   Not collective
2105*22bbedd7SHong Zhang 
2106*22bbedd7SHong Zhang   Input Parameters
2107*22bbedd7SHong Zhang + dm - the dm object
2108*22bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
2109*22bbedd7SHong Zhang 
2110*22bbedd7SHong Zhang   Output Parameters
2111*22bbedd7SHong Zhang +  vg  - global vertex ordering, start from 0
2112*22bbedd7SHong Zhang 
2113*22bbedd7SHong Zhang   Level: Advanced
2114*22bbedd7SHong Zhang 
2115*22bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
2116*22bbedd7SHong Zhang @*/
2117*22bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
2118*22bbedd7SHong Zhang {
2119*22bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
2120*22bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
2121*22bbedd7SHong Zhang 
2122*22bbedd7SHong Zhang   PetscFunctionBegin;
2123*22bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
2124*22bbedd7SHong Zhang   *vg = vltog[vloc];
2125*22bbedd7SHong Zhang   PetscFunctionReturn(0);
2126*22bbedd7SHong Zhang }
2127*22bbedd7SHong Zhang 
2128*22bbedd7SHong Zhang /*@
2129*22bbedd7SHong Zhang   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to globle map
2130*22bbedd7SHong Zhang 
2131*22bbedd7SHong Zhang   Collective
2132*22bbedd7SHong Zhang 
2133*22bbedd7SHong Zhang   Input Parameters:
2134*22bbedd7SHong Zhang + dm - the dm object
2135*22bbedd7SHong Zhang 
2136*22bbedd7SHong Zhang   Level: Advanced
2137*22bbedd7SHong Zhang 
2138*22bbedd7SHong Zhang .seealso: DMNetworkCreate()
2139*22bbedd7SHong Zhang @*/
2140*22bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
2141*22bbedd7SHong Zhang {
2142*22bbedd7SHong Zhang   PetscErrorCode    ierr;
2143*22bbedd7SHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
2144*22bbedd7SHong Zhang   MPI_Comm          comm;
2145*22bbedd7SHong Zhang   PetscMPIInt       rank,size,*displs,*recvcounts;
2146*22bbedd7SHong Zhang   PetscBool         ghost;
2147*22bbedd7SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k=0,kg=0;
2148*22bbedd7SHong Zhang   const PetscInt    *ilocal;
2149*22bbedd7SHong Zhang   const PetscSFNode *iremote;
2150*22bbedd7SHong Zhang   PetscSF           vsf;
2151*22bbedd7SHong Zhang 
2152*22bbedd7SHong Zhang   PetscFunctionBegin;
2153*22bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2154*22bbedd7SHong Zhang   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
2155*22bbedd7SHong Zhang 
2156*22bbedd7SHong Zhang   if (size == 1) {
2157*22bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
2158*22bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
2159*22bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
2160*22bbedd7SHong Zhang     network->vltog = vltog;
2161*22bbedd7SHong Zhang     PetscFunctionReturn(0);
2162*22bbedd7SHong Zhang   }
2163*22bbedd7SHong Zhang 
2164*22bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
2165*22bbedd7SHong Zhang   if (network->vltog) {
2166*22bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2167*22bbedd7SHong Zhang   }
2168*22bbedd7SHong Zhang 
2169*22bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
2170*22bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
2171*22bbedd7SHong Zhang   vsf = network->vertex.sf;
2172*22bbedd7SHong Zhang   /*
2173*22bbedd7SHong Zhang    ierr = PetscPrintf(MPI_COMM_WORLD,"\n DMNetworkVertexLocalToGlobalOrdering, network->vertex.sf:\n");CHKERRQ(ierr);
2174*22bbedd7SHong Zhang    ierr = PetscSFView(network->vertex.sf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
2175*22bbedd7SHong Zhang    */
2176*22bbedd7SHong Zhang 
2177*22bbedd7SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size+1,&displs,size,&recvcounts);CHKERRQ(ierr);
2178*22bbedd7SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
2179*22bbedd7SHong Zhang 
2180*22bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
2181*22bbedd7SHong Zhang 
2182*22bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
2183*22bbedd7SHong Zhang   vrange[0] = 0;
2184*22bbedd7SHong Zhang   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRQ(ierr);
2185*22bbedd7SHong Zhang   for (i=2; i<=size+1; i++) {vrange[i] += vrange[i-1];}
2186*22bbedd7SHong Zhang 
2187*22bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
2188*22bbedd7SHong Zhang   network->vltog = vltog;
2189*22bbedd7SHong Zhang 
2190*22bbedd7SHong Zhang   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
2191*22bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
2192*22bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
2193*22bbedd7SHong Zhang     if (!ghost) {
2194*22bbedd7SHong Zhang       vltog[i] = vrange[rank] + k; k++;
2195*22bbedd7SHong Zhang     } else {
2196*22bbedd7SHong Zhang       vltog[i] = vrange[iremote[kg].rank] + iremote[kg].index; kg++;
2197*22bbedd7SHong Zhang     }
2198*22bbedd7SHong Zhang   }
2199*22bbedd7SHong Zhang   PetscFunctionReturn(0);
2200*22bbedd7SHong Zhang }
2201