xref: /petsc/src/dm/impls/network/network.c (revision 72c3e9f75377571692fadbeb1ecb4701468ed11b)
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 /*@
26*72c3e9f7SHong Zhang   DMNetworkGetSizes - Gets the the number of subnetworks and coupling subnetworks
27*72c3e9f7SHong Zhang 
28*72c3e9f7SHong Zhang   Collective on dm
29*72c3e9f7SHong Zhang 
30*72c3e9f7SHong Zhang   Input Parameters:
31*72c3e9f7SHong Zhang + dm - the dm object
32*72c3e9f7SHong Zhang . Nsubnet - global number of subnetworks
33*72c3e9f7SHong Zhang - NsubnetCouple - global number of coupling subnetworks
34*72c3e9f7SHong Zhang 
35*72c3e9f7SHong Zhang   Level: Intermediate
36*72c3e9f7SHong Zhang 
37*72c3e9f7SHong Zhang .seealso: DMNetworkCreate()
38*72c3e9f7SHong Zhang @*/
39*72c3e9f7SHong Zhang PetscErrorCode DMNetworkGetSizes(DM netdm, PetscInt *Nsubnet, PetscInt *Ncsubnet)
40*72c3e9f7SHong Zhang {
41*72c3e9f7SHong Zhang   DM_Network *network = (DM_Network*) netdm->data;
42*72c3e9f7SHong Zhang 
43*72c3e9f7SHong Zhang   PetscFunctionBegin;
44*72c3e9f7SHong Zhang   *Nsubnet = network->nsubnet;
45*72c3e9f7SHong Zhang   *Ncsubnet = network->ncsubnet;
46*72c3e9f7SHong Zhang   PetscFunctionReturn(0);
47*72c3e9f7SHong Zhang }
48*72c3e9f7SHong Zhang 
49*72c3e9f7SHong Zhang /*@
50e2aaf10cSShri Abhyankar   DMNetworkSetSizes - Sets the number of subnetworks, local and global vertices and edges for each subnetwork.
515f2c45f1SShri Abhyankar 
52d083f849SBarry Smith   Collective on dm
535f2c45f1SShri Abhyankar 
545f2c45f1SShri Abhyankar   Input Parameters:
555f2c45f1SShri Abhyankar + dm - the dm object
56caf410d2SHong Zhang . Nsubnet - global number of subnetworks
57caf410d2SHong Zhang . nV - number of local vertices for each subnetwork
58caf410d2SHong Zhang . nE - number of local edges for each subnetwork
59caf410d2SHong Zhang . NsubnetCouple - global number of coupling subnetworks
60caf410d2SHong Zhang - nec - number of local edges for each coupling subnetwork
615f2c45f1SShri Abhyankar 
62caf410d2SHong 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.
635f2c45f1SShri Abhyankar 
641b266c99SBarry Smith    Level: intermediate
651b266c99SBarry Smith 
661b266c99SBarry Smith .seealso: DMNetworkCreate()
675f2c45f1SShri Abhyankar @*/
68caf410d2SHong Zhang PetscErrorCode DMNetworkSetSizes(DM dm,PetscInt Nsubnet,PetscInt nV[], PetscInt nE[],PetscInt NsubnetCouple,PetscInt nec[])
695f2c45f1SShri Abhyankar {
705f2c45f1SShri Abhyankar   PetscErrorCode ierr;
715f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*) dm->data;
72e2aaf10cSShri Abhyankar   PetscInt       a[2],b[2],i;
735f2c45f1SShri Abhyankar 
745f2c45f1SShri Abhyankar   PetscFunctionBegin;
755f2c45f1SShri Abhyankar   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
76e2aaf10cSShri Abhyankar   if (Nsubnet <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subnetworks %D cannot be less than 1",Nsubnet);
777765340cSHong Zhang   if (NsubnetCouple < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of coupling subnetworks %D cannot be less than 0",NsubnetCouple);
787765340cSHong Zhang 
79caf410d2SHong Zhang   PetscValidLogicalCollectiveInt(dm,Nsubnet,2);
80caf410d2SHong Zhang   if (NsubnetCouple) PetscValidLogicalCollectiveInt(dm,NsubnetCouple,5);
817765340cSHong Zhang   if (network->nsubnet != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network");
827765340cSHong Zhang 
83caf410d2SHong Zhang   if (!nV || !nE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Local vertex size or edge size must be provided");
84f025b11dSHong Zhang 
85caf410d2SHong Zhang   network->nsubnet  = Nsubnet + NsubnetCouple;
86caf410d2SHong Zhang   network->ncsubnet = NsubnetCouple;
87caf410d2SHong Zhang   ierr = PetscCalloc1(Nsubnet+NsubnetCouple,&network->subnet);CHKERRQ(ierr);
88caf410d2SHong Zhang 
89caf410d2SHong Zhang   /* ----------------------------------------------------------
90caf410d2SHong Zhang    p=v or e; P=V or E
91caf410d2SHong Zhang    subnet[0].pStart   = 0
92caf410d2SHong Zhang    subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i])
93caf410d2SHong Zhang    ----------------------------------------------------------------------- */
94caf410d2SHong Zhang   for (i=0; i < Nsubnet; i++) {
95caf410d2SHong Zhang     /* Get global number of vertices and edges for subnet[i] */
96caf410d2SHong Zhang     a[0] = nV[i]; a[1] = nE[i]; /* local number of vertices (excluding ghost) and edges */
977765340cSHong Zhang     ierr = MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
98071fcb05SBarry Smith     network->subnet[i].Nvtx = b[0];
99071fcb05SBarry Smith     network->subnet[i].Nedge = b[1];
1007765340cSHong Zhang 
101caf410d2SHong Zhang     network->subnet[i].nvtx   = nV[i]; /* local nvtx, without ghost */
1027765340cSHong Zhang 
103caf410d2SHong Zhang     /* global subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */
104caf410d2SHong Zhang     network->subnet[i].vStart = network->NVertices;
1057765340cSHong Zhang     network->subnet[i].vEnd   = network->subnet[i].vStart + network->subnet[i].Nvtx;
106caf410d2SHong Zhang 
107caf410d2SHong Zhang     network->nVertices += nV[i];
1087765340cSHong Zhang     network->NVertices += network->subnet[i].Nvtx;
1097765340cSHong Zhang 
1107765340cSHong Zhang     network->subnet[i].nedge  = nE[i];
1117765340cSHong Zhang     network->subnet[i].eStart = network->nEdges;
112caf410d2SHong Zhang     network->subnet[i].eEnd   = network->subnet[i].eStart + nE[i];
113caf410d2SHong Zhang     network->nEdges += nE[i];
114caf410d2SHong Zhang     network->NEdges += network->subnet[i].Nedge;
115caf410d2SHong Zhang   }
116caf410d2SHong Zhang 
117caf410d2SHong Zhang   /* coupling subnetwork */
118caf410d2SHong Zhang   for (; i < Nsubnet+NsubnetCouple; i++) {
119caf410d2SHong Zhang     /* Get global number of coupling edges for subnet[i] */
120caf410d2SHong Zhang     ierr = MPIU_Allreduce(nec+(i-Nsubnet),&network->subnet[i].Nedge,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
121caf410d2SHong Zhang 
122caf410d2SHong Zhang     network->subnet[i].nvtx   = 0; /* We design coupling subnetwork such that it does not have its own vertices */
123caf410d2SHong Zhang     network->subnet[i].vStart = network->nVertices;
124caf410d2SHong Zhang     network->subnet[i].vEnd   = network->subnet[i].vStart;
125caf410d2SHong Zhang 
126caf410d2SHong Zhang     network->subnet[i].nedge  = nec[i-Nsubnet];
127caf410d2SHong Zhang     network->subnet[i].eStart = network->nEdges;
128caf410d2SHong Zhang     network->subnet[i].eEnd = network->subnet[i].eStart + nec[i-Nsubnet];
129caf410d2SHong Zhang     network->nEdges += nec[i-Nsubnet];
1307765340cSHong Zhang     network->NEdges += network->subnet[i].Nedge;
1317765340cSHong Zhang   }
1327765340cSHong Zhang   PetscFunctionReturn(0);
1337765340cSHong Zhang }
1347765340cSHong Zhang 
1355f2c45f1SShri Abhyankar /*@
1365f2c45f1SShri Abhyankar   DMNetworkSetEdgeList - Sets the list of local edges (vertex connectivity) for the network
1375f2c45f1SShri Abhyankar 
138d083f849SBarry Smith   Logically collective on dm
1395f2c45f1SShri Abhyankar 
1405f2c45f1SShri Abhyankar   Input Parameters:
141e3e68989SHong Zhang + dm - the dm object
142e3e68989SHong Zhang . edgelist - list of edges for each subnetwork
143e3e68989SHong Zhang - edgelistCouple - list of edges for each coupling subnetwork
1445f2c45f1SShri Abhyankar 
1455f2c45f1SShri Abhyankar   Notes:
1465f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1475f2c45f1SShri Abhyankar   not be destroyed before the call to DMNetworkLayoutSetUp
1485f2c45f1SShri Abhyankar 
1495f2c45f1SShri Abhyankar   Level: intermediate
1505f2c45f1SShri Abhyankar 
151e3e68989SHong Zhang   Example usage:
152e3e68989SHong Zhang   Consider the following 2 separate networks and a coupling network:
153e3e68989SHong Zhang 
154e3e68989SHong Zhang .vb
155e3e68989SHong Zhang  network 0: v0 -> v1 -> v2 -> v3
156e3e68989SHong Zhang  network 1: v1 -> v2 -> v0
157e3e68989SHong Zhang  coupling network: network 1: v2 -> network 0: v0
158e3e68989SHong Zhang .ve
159e3e68989SHong Zhang 
160e3e68989SHong Zhang  The resulting input
161e3e68989SHong Zhang    edgelist[0] = [0 1 | 1 2 | 2 3];
162e3e68989SHong Zhang    edgelist[1] = [1 2 | 2 0]
163e3e68989SHong Zhang    edgelistCouple[0] = [(network)1 (v)2 (network)0 (v)0].
164e3e68989SHong Zhang 
1655f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkSetSizes
1665f2c45f1SShri Abhyankar @*/
1674e18019cSBarry Smith PetscErrorCode DMNetworkSetEdgeList(DM dm,PetscInt *edgelist[],PetscInt *edgelistCouple[])
1685f2c45f1SShri Abhyankar {
1695f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*) dm->data;
170*72c3e9f7SHong Zhang   PetscInt   i;
1715f2c45f1SShri Abhyankar 
1725f2c45f1SShri Abhyankar   PetscFunctionBegin;
173*72c3e9f7SHong Zhang   for (i=0; i < (network->nsubnet-network->ncsubnet); i++) network->subnet[i].edgelist = edgelist[i];
174*72c3e9f7SHong Zhang   if (network->ncsubnet) {
175*72c3e9f7SHong Zhang     PetscInt j = 0;
176*72c3e9f7SHong Zhang     if (!edgelistCouple) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Must provide edgelist_couple");
177*72c3e9f7SHong Zhang     while (i < network->nsubnet) network->subnet[i++].edgelist = edgelistCouple[j++];
178e3e68989SHong Zhang   }
1795f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
1805f2c45f1SShri Abhyankar }
1815f2c45f1SShri Abhyankar 
1825f2c45f1SShri Abhyankar /*@
1835f2c45f1SShri Abhyankar   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
1845f2c45f1SShri Abhyankar 
185d083f849SBarry Smith   Collective on dm
1865f2c45f1SShri Abhyankar 
1875f2c45f1SShri Abhyankar   Input Parameters
1885f2c45f1SShri Abhyankar . DM - the dmnetwork object
1895f2c45f1SShri Abhyankar 
1905f2c45f1SShri Abhyankar   Notes:
1915f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
1925f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
1935f2c45f1SShri Abhyankar 
1945f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
1955f2c45f1SShri Abhyankar 
1965f2c45f1SShri Abhyankar   Level: intermediate
1975f2c45f1SShri Abhyankar 
1985f2c45f1SShri Abhyankar .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList
1995f2c45f1SShri Abhyankar @*/
2005f2c45f1SShri Abhyankar PetscErrorCode DMNetworkLayoutSetUp(DM dm)
2015f2c45f1SShri Abhyankar {
2025f2c45f1SShri Abhyankar   PetscErrorCode ierr;
2035f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
204caf410d2SHong Zhang   PetscInt       numCorners=2,spacedim=2,dim = 1; /* One dimensional network */
2053ebf9fb9SHong Zhang   PetscReal      *vertexcoords=NULL;
206caf410d2SHong Zhang   PetscInt       i,j,ctr,nsubnet,*eowners,np,*edges,*subnetvtx,vStart;
207caf410d2SHong Zhang   PetscInt       k,netid,vid, *vidxlTog,*edgelist_couple=NULL;
208caf410d2SHong Zhang   const PetscInt *cone;
209caf410d2SHong Zhang   MPI_Comm       comm;
210caf410d2SHong Zhang   PetscMPIInt    size,rank;
2116500d4abSHong Zhang 
2126500d4abSHong Zhang   PetscFunctionBegin;
213caf410d2SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
214caf410d2SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
215caf410d2SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
2166500d4abSHong Zhang 
217caf410d2SHong Zhang   /* Create the local edgelist for the network by concatenating local input edgelists of the subnetworks */
218caf410d2SHong Zhang   ierr = PetscCalloc2(numCorners*network->nVertices,&vertexcoords,2*network->nEdges,&edges);CHKERRQ(ierr);
2197765340cSHong Zhang   nsubnet = network->nsubnet - network->ncsubnet;
220caf410d2SHong Zhang   ctr = 0;
2217765340cSHong Zhang   for (i=0; i < nsubnet; i++) {
2226500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
223ba38b151SHong Zhang       edges[2*ctr]   = network->subnet[i].vStart + network->subnet[i].edgelist[2*j];
224ba38b151SHong Zhang       edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1];
2256500d4abSHong Zhang       ctr++;
2266500d4abSHong Zhang     }
2276500d4abSHong Zhang   }
2287765340cSHong Zhang 
229caf410d2SHong Zhang   /* Append local coupling edgelists of the subnetworks */
2307765340cSHong Zhang   i       = nsubnet; /* netid of coupling subnet */
2317765340cSHong Zhang   nsubnet = network->nsubnet;
2327765340cSHong Zhang   while (i < nsubnet) {
233991cf414SHong Zhang     edgelist_couple = network->subnet[i].edgelist;
234*72c3e9f7SHong Zhang 
2356500d4abSHong Zhang     k = 0;
2366500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
2376500d4abSHong Zhang       netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
238caf410d2SHong Zhang       edges[2*ctr] = network->subnet[netid].vStart + vid; k += 2;
2396500d4abSHong Zhang 
2406500d4abSHong Zhang       netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
241caf410d2SHong Zhang       edges[2*ctr+1] = network->subnet[netid].vStart + vid; k+=2;
2426500d4abSHong Zhang       ctr++;
2436500d4abSHong Zhang     }
2447765340cSHong Zhang     i++;
2457765340cSHong Zhang   }
246caf410d2SHong Zhang   /*
247caf410d2SHong Zhang   if (rank == 0) {
248caf410d2SHong Zhang     ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] edgelist:\n",rank);
2496500d4abSHong Zhang     for(i=0; i < network->nEdges; i++) {
250caf410d2SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"[%D %D]",edges[2*i],edges[2*i+1]);CHKERRQ(ierr);
2516500d4abSHong Zhang       printf("\n");
2526500d4abSHong Zhang     }
253caf410d2SHong Zhang   }
254caf410d2SHong Zhang    */
2556500d4abSHong Zhang 
256caf410d2SHong Zhang   /* Create network->plex */
257acdb140fSBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
258acdb140fSBarry Smith   {
259caf410d2SHong Zhang     int *edges64;
260caf410d2SHong Zhang     np = network->nEdges*numCorners;
261caf410d2SHong Zhang     ierr = PetscMalloc1(np,&edges64);CHKERRQ(ierr);
262caf410d2SHong Zhang     for (i=0; i<np; i++) edges64[i] = (int)edges[i];
263caf410d2SHong Zhang 
264caf410d2SHong Zhang     if (size == 1) {
265caf410d2SHong Zhang       ierr = DMPlexCreateFromCellList(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges64,spacedim,(const double*)vertexcoords,&network->plex);CHKERRQ(ierr);
266caf410d2SHong Zhang     } else {
2673ebf9fb9SHong Zhang       ierr = DMPlexCreateFromCellListParallel(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges64,spacedim,(const PetscReal*)vertexcoords,NULL,&network->plex);CHKERRQ(ierr);
268acdb140fSBarry Smith     }
269caf410d2SHong Zhang     ierr = PetscFree(edges64);CHKERRQ(ierr);
270acdb140fSBarry Smith   }
271acdb140fSBarry Smith #else
272caf410d2SHong Zhang   if (size == 1) {
273caf410d2SHong Zhang     ierr = DMPlexCreateFromCellList(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges,spacedim,(const double*)vertexcoords,&network->plex);CHKERRQ(ierr);
274caf410d2SHong Zhang   } else {
2753ebf9fb9SHong Zhang     ierr = DMPlexCreateFromCellListParallel(comm,dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,(const int*)edges,spacedim,(const PetscReal*)vertexcoords,NULL,&network->plex);CHKERRQ(ierr);
2766500d4abSHong Zhang   }
277caf410d2SHong Zhang #endif
2786500d4abSHong Zhang 
2796500d4abSHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
2806500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
2816500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
282caf410d2SHong Zhang   vStart = network->vStart;
2836500d4abSHong Zhang 
284caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
285caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
2866500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
2876500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
2886500d4abSHong Zhang 
289caf410d2SHong Zhang   network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
290caf410d2SHong Zhang   np = network->pEnd - network->pStart;
291caf410d2SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
292caf410d2SHong Zhang 
293caf410d2SHong Zhang   /* Create vidxlTog: maps local vertex index to global index */
294caf410d2SHong Zhang   np = network->vEnd - vStart;
295caf410d2SHong Zhang   ierr = PetscMalloc2(np,&vidxlTog,size+1,&eowners);CHKERRQ(ierr);
296caf410d2SHong Zhang   ctr = 0;
297caf410d2SHong Zhang   for (i=network->eStart; i<network->eEnd; i++) {
298caf410d2SHong Zhang     ierr = DMNetworkGetConnectedVertices(dm,i,&cone);CHKERRQ(ierr);
299caf410d2SHong Zhang     vidxlTog[cone[0] - vStart] = edges[2*ctr];
300caf410d2SHong Zhang     vidxlTog[cone[1] - vStart] = edges[2*ctr+1];
301caf410d2SHong Zhang     ctr++;
302caf410d2SHong Zhang   }
303caf410d2SHong Zhang   ierr = PetscFree2(vertexcoords,edges);CHKERRQ(ierr);
304caf410d2SHong Zhang 
3056500d4abSHong Zhang   /* Create vertices and edges array for the subnetworks */
3066500d4abSHong Zhang   for (j=0; j < network->nsubnet; j++) {
3076500d4abSHong Zhang     ierr = PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);CHKERRQ(ierr);
308caf410d2SHong Zhang 
3096500d4abSHong Zhang     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
3106500d4abSHong Zhang        These get updated when the vertices and edges are added. */
311caf410d2SHong Zhang     network->subnet[j].nvtx  = 0;
312caf410d2SHong Zhang     network->subnet[j].nedge = 0;
3136500d4abSHong Zhang   }
314caf410d2SHong Zhang   ierr = PetscCalloc1(np,&network->subnetvtx);CHKERRQ(ierr);
3156500d4abSHong Zhang 
316caf410d2SHong Zhang 
317caf410d2SHong Zhang   /* Get edge ownership */
318caf410d2SHong Zhang   np = network->eEnd - network->eStart;
319caf410d2SHong Zhang   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRQ(ierr);
320caf410d2SHong Zhang   eowners[0] = 0;
321caf410d2SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
322caf410d2SHong Zhang 
323caf410d2SHong Zhang   i = 0; j = 0;
324caf410d2SHong Zhang   while (i < np) { /* local edges, including coupling edges */
325caf410d2SHong Zhang     network->header[i].index = i + eowners[rank];   /* Global edge index */
326caf410d2SHong Zhang 
327caf410d2SHong Zhang     if (j < network->nsubnet && i < network->subnet[j].eEnd) {
3286500d4abSHong Zhang       network->header[i].subnetid = j; /* Subnetwork id */
3296500d4abSHong Zhang       network->subnet[j].edges[network->subnet[j].nedge++] = i;
330caf410d2SHong Zhang 
331caf410d2SHong Zhang       network->header[i].ndata = 0;
332caf410d2SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
333caf410d2SHong Zhang       network->header[i].offset[0] = 0;
334caf410d2SHong Zhang       i++;
335caf410d2SHong Zhang     }
336caf410d2SHong Zhang     if (i >= network->subnet[j].eEnd) j++;
337caf410d2SHong Zhang   }
338caf410d2SHong Zhang 
339caf410d2SHong Zhang   /* Count network->subnet[*].nvtx */
340caf410d2SHong Zhang   for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */
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) {
344caf410d2SHong Zhang         network->subnet[j].nvtx++;
3456500d4abSHong Zhang         break;
3466500d4abSHong Zhang       }
3476500d4abSHong Zhang     }
3486500d4abSHong Zhang   }
3496500d4abSHong Zhang 
350caf410d2SHong Zhang   /* Set network->subnet[*].vertices on array network->subnetvtx */
351caf410d2SHong Zhang   subnetvtx = network->subnetvtx;
3526500d4abSHong Zhang   for (j=0; j<network->nsubnet; j++) {
353caf410d2SHong Zhang     network->subnet[j].vertices = subnetvtx;
354caf410d2SHong Zhang     subnetvtx                  += network->subnet[j].nvtx;
355caf410d2SHong Zhang     network->subnet[j].nvtx = 0;
356caf410d2SHong Zhang   }
357caf410d2SHong Zhang 
358caf410d2SHong Zhang   /* Set vertex array for the subnetworks */
359caf410d2SHong Zhang   for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */
360caf410d2SHong Zhang     network->header[i].index = vidxlTog[i-vStart]; /*  Global vertex index */
361caf410d2SHong Zhang 
362caf410d2SHong Zhang     k = vidxlTog[i-vStart];
363caf410d2SHong Zhang     for (j=0; j < network->nsubnet; j++) {
364caf410d2SHong Zhang       if (network->subnet[j].vStart <= k && k < network->subnet[j].vEnd) {
3656500d4abSHong Zhang         network->header[i].subnetid = j;
3666500d4abSHong Zhang         network->subnet[j].vertices[network->subnet[j].nvtx++] = i;
3676500d4abSHong Zhang         break;
3686500d4abSHong Zhang       }
3696500d4abSHong Zhang     }
370caf410d2SHong Zhang 
3716500d4abSHong Zhang     network->header[i].ndata = 0;
3726500d4abSHong Zhang     ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
373caf410d2SHong Zhang     network->header[i].offset[0] = 0;
3746500d4abSHong Zhang   }
3756500d4abSHong Zhang 
376caf410d2SHong Zhang   ierr = PetscFree2(vidxlTog,eowners);CHKERRQ(ierr);
3775f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
3785f2c45f1SShri Abhyankar }
3795f2c45f1SShri Abhyankar 
38094ef8ddeSSatish Balay /*@C
3812727e31bSShri Abhyankar   DMNetworkGetSubnetworkInfo - Returns the info for the subnetwork
3822727e31bSShri Abhyankar 
3832727e31bSShri Abhyankar   Input Parameters
384caf410d2SHong Zhang + dm - the DM object
3852727e31bSShri Abhyankar - id   - the ID (integer) of the subnetwork
3862727e31bSShri Abhyankar 
3872727e31bSShri Abhyankar   Output Parameters
3882727e31bSShri Abhyankar + nv    - number of vertices (local)
3892727e31bSShri Abhyankar . ne    - number of edges (local)
3902727e31bSShri Abhyankar . vtx   - local vertices for this subnetwork
391a2b725a8SWilliam Gropp - edge  - local edges for this subnetwork
3922727e31bSShri Abhyankar 
3932727e31bSShri Abhyankar   Notes:
3942727e31bSShri Abhyankar   Cannot call this routine before DMNetworkLayoutSetup()
3952727e31bSShri Abhyankar 
39606dd6b0eSSatish Balay   Level: intermediate
39706dd6b0eSSatish Balay 
3982727e31bSShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
3992727e31bSShri Abhyankar @*/
400caf410d2SHong Zhang PetscErrorCode DMNetworkGetSubnetworkInfo(DM dm,PetscInt id,PetscInt *nv, PetscInt *ne,const PetscInt **vtx, const PetscInt **edge)
4012727e31bSShri Abhyankar {
402caf410d2SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
4032727e31bSShri Abhyankar 
4042727e31bSShri Abhyankar   PetscFunctionBegin;
405*72c3e9f7SHong Zhang   if (id >= network->nsubnet) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Subnet ID %D exceeds the num of subnets %D",id,network->nsubnet);
4062727e31bSShri Abhyankar   *nv   = network->subnet[id].nvtx;
4072727e31bSShri Abhyankar   *ne   = network->subnet[id].nedge;
4082727e31bSShri Abhyankar   *vtx  = network->subnet[id].vertices;
4092727e31bSShri Abhyankar   *edge = network->subnet[id].edges;
4102727e31bSShri Abhyankar   PetscFunctionReturn(0);
4112727e31bSShri Abhyankar }
4122727e31bSShri Abhyankar 
4132727e31bSShri Abhyankar /*@C
414caf410d2SHong Zhang   DMNetworkGetSubnetworkCoupleInfo - Returns the info for the coupling subnetwork
415caf410d2SHong Zhang 
416caf410d2SHong Zhang   Input Parameters
417caf410d2SHong Zhang + dm - the DM object
418caf410d2SHong Zhang - id   - the ID (integer) of the coupling subnetwork
419caf410d2SHong Zhang 
420caf410d2SHong Zhang   Output Parameters
421caf410d2SHong Zhang + ne - number of edges (local)
422caf410d2SHong Zhang - edge  - local edges for this coupling subnetwork
423caf410d2SHong Zhang 
424caf410d2SHong Zhang   Notes:
425caf410d2SHong Zhang   Cannot call this routine before DMNetworkLayoutSetup()
426caf410d2SHong Zhang 
427caf410d2SHong Zhang   Level: intermediate
428caf410d2SHong Zhang 
429caf410d2SHong Zhang .seealso: DMNetworkGetSubnetworkInfo, DMNetworkLayoutSetUp, DMNetworkCreate
430caf410d2SHong Zhang @*/
431caf410d2SHong Zhang PetscErrorCode DMNetworkGetSubnetworkCoupleInfo(DM dm,PetscInt id,PetscInt *ne,const PetscInt **edge)
432caf410d2SHong Zhang {
433caf410d2SHong Zhang   DM_Network *net = (DM_Network*)dm->data;
434*72c3e9f7SHong Zhang   PetscInt   id1;
435caf410d2SHong Zhang 
436caf410d2SHong Zhang   PetscFunctionBegin;
437*72c3e9f7SHong Zhang   if (net->ncsubnet) {
438*72c3e9f7SHong Zhang     if (id >= net->ncsubnet) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Subnet ID %D exceeds the num of coupling subnets %D",id,net->ncsubnet);
439*72c3e9f7SHong Zhang 
440*72c3e9f7SHong Zhang     id1   = id + net->nsubnet - net->ncsubnet;
441caf410d2SHong Zhang     *ne   = net->subnet[id1].nedge;
442caf410d2SHong Zhang     *edge = net->subnet[id1].edges;
443*72c3e9f7SHong Zhang   } else {
444*72c3e9f7SHong Zhang     *ne   = 0;
445*72c3e9f7SHong Zhang     *edge = NULL;
446*72c3e9f7SHong Zhang   }
447caf410d2SHong Zhang   PetscFunctionReturn(0);
448caf410d2SHong Zhang }
449caf410d2SHong Zhang 
450caf410d2SHong Zhang /*@C
4515f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
4525f2c45f1SShri Abhyankar 
453d083f849SBarry Smith   Logically collective on dm
4545f2c45f1SShri Abhyankar 
4555f2c45f1SShri Abhyankar   Input Parameters
4565f2c45f1SShri Abhyankar + dm   - the network object
4575f2c45f1SShri Abhyankar . name - the component name
4585f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
4595f2c45f1SShri Abhyankar 
4605f2c45f1SShri Abhyankar    Output Parameters
4615f2c45f1SShri Abhyankar .   key - an integer key that defines the component
4625f2c45f1SShri Abhyankar 
4635f2c45f1SShri Abhyankar    Notes
4645f2c45f1SShri Abhyankar    This routine should be called by all processors before calling DMNetworkLayoutSetup().
4655f2c45f1SShri Abhyankar 
4665f2c45f1SShri Abhyankar    Level: intermediate
4675f2c45f1SShri Abhyankar 
4685f2c45f1SShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
4695f2c45f1SShri Abhyankar @*/
470caf410d2SHong Zhang PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key)
4715f2c45f1SShri Abhyankar {
4725f2c45f1SShri Abhyankar   PetscErrorCode        ierr;
4735f2c45f1SShri Abhyankar   DM_Network            *network = (DM_Network*) dm->data;
4745f2c45f1SShri Abhyankar   DMNetworkComponent    *component=&network->component[network->ncomponent];
4755f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
4765f2c45f1SShri Abhyankar   PetscInt              i;
4775f2c45f1SShri Abhyankar 
4785f2c45f1SShri Abhyankar   PetscFunctionBegin;
4795f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
4805f2c45f1SShri Abhyankar     ierr = PetscStrcmp(component->name,name,&flg);CHKERRQ(ierr);
4815f2c45f1SShri Abhyankar     if (flg) {
4825f2c45f1SShri Abhyankar       *key = i;
4835f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
4845f2c45f1SShri Abhyankar     }
4856d64e262SShri Abhyankar   }
4866d64e262SShri Abhyankar   if(network->ncomponent == MAX_COMPONENTS) {
4876d64e262SShri Abhyankar     SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components registered exceeds the max %D",MAX_COMPONENTS);
4885f2c45f1SShri Abhyankar   }
4895f2c45f1SShri Abhyankar 
4905f2c45f1SShri Abhyankar   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
4915f2c45f1SShri Abhyankar   component->size = size/sizeof(DMNetworkComponentGenericDataType);
4925f2c45f1SShri Abhyankar   *key = network->ncomponent;
4935f2c45f1SShri Abhyankar   network->ncomponent++;
4945f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
4955f2c45f1SShri Abhyankar }
4965f2c45f1SShri Abhyankar 
4975f2c45f1SShri Abhyankar /*@
4985f2c45f1SShri Abhyankar   DMNetworkGetVertexRange - Get the bounds [start, end) for the vertices.
4995f2c45f1SShri Abhyankar 
5005f2c45f1SShri Abhyankar   Not Collective
5015f2c45f1SShri Abhyankar 
5025f2c45f1SShri Abhyankar   Input Parameters:
503a2b725a8SWilliam Gropp . dm - The DMNetwork object
5045f2c45f1SShri Abhyankar 
5055f2c45f1SShri Abhyankar   Output Paramters:
5065f2c45f1SShri Abhyankar + vStart - The first vertex point
5075f2c45f1SShri Abhyankar - vEnd   - One beyond the last vertex point
5085f2c45f1SShri Abhyankar 
5095f2c45f1SShri Abhyankar   Level: intermediate
5105f2c45f1SShri Abhyankar 
5115f2c45f1SShri Abhyankar .seealso: DMNetworkGetEdgeRange
5125f2c45f1SShri Abhyankar @*/
5135f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
5145f2c45f1SShri Abhyankar {
5155f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
5165f2c45f1SShri Abhyankar 
5175f2c45f1SShri Abhyankar   PetscFunctionBegin;
5185f2c45f1SShri Abhyankar   if (vStart) *vStart = network->vStart;
5195f2c45f1SShri Abhyankar   if (vEnd) *vEnd = network->vEnd;
5205f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5215f2c45f1SShri Abhyankar }
5225f2c45f1SShri Abhyankar 
5235f2c45f1SShri Abhyankar /*@
5245f2c45f1SShri Abhyankar   DMNetworkGetEdgeRange - Get the bounds [start, end) for the edges.
5255f2c45f1SShri Abhyankar 
5265f2c45f1SShri Abhyankar   Not Collective
5275f2c45f1SShri Abhyankar 
5285f2c45f1SShri Abhyankar   Input Parameters:
529a2b725a8SWilliam Gropp . dm - The DMNetwork object
5305f2c45f1SShri Abhyankar 
5315f2c45f1SShri Abhyankar   Output Paramters:
5325f2c45f1SShri Abhyankar + eStart - The first edge point
5335f2c45f1SShri Abhyankar - eEnd   - One beyond the last edge point
5345f2c45f1SShri Abhyankar 
5355f2c45f1SShri Abhyankar   Level: intermediate
5365f2c45f1SShri Abhyankar 
5375f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange
5385f2c45f1SShri Abhyankar @*/
5395f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
5405f2c45f1SShri Abhyankar {
5415f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
5425f2c45f1SShri Abhyankar 
5435f2c45f1SShri Abhyankar   PetscFunctionBegin;
5445f2c45f1SShri Abhyankar   if (eStart) *eStart = network->eStart;
5455f2c45f1SShri Abhyankar   if (eEnd) *eEnd = network->eEnd;
5465f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5475f2c45f1SShri Abhyankar }
5485f2c45f1SShri Abhyankar 
5497b6afd5bSHong Zhang /*@
550e85e6aecSHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the user global numbering for the edge.
5517b6afd5bSHong Zhang 
5527b6afd5bSHong Zhang   Not Collective
5537b6afd5bSHong Zhang 
5547b6afd5bSHong Zhang   Input Parameters:
5557b6afd5bSHong Zhang + dm - DMNetwork object
556e85e6aecSHong Zhang - p  - edge point
5577b6afd5bSHong Zhang 
5587b6afd5bSHong Zhang   Output Paramters:
559e85e6aecSHong Zhang . index - user global numbering for the edge
5607b6afd5bSHong Zhang 
5617b6afd5bSHong Zhang   Level: intermediate
5627b6afd5bSHong Zhang 
563e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalVertexIndex
5647b6afd5bSHong Zhang @*/
565e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
5667b6afd5bSHong Zhang {
5677b6afd5bSHong Zhang   PetscErrorCode    ierr;
5687b6afd5bSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
5697b6afd5bSHong Zhang   PetscInt          offsetp;
5707b6afd5bSHong Zhang   DMNetworkComponentHeader header;
5717b6afd5bSHong Zhang 
5727b6afd5bSHong Zhang   PetscFunctionBegin;
573caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
5747b6afd5bSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
5757b6afd5bSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
576e85e6aecSHong Zhang   *index = header->index;
5777b6afd5bSHong Zhang   PetscFunctionReturn(0);
5787b6afd5bSHong Zhang }
5797b6afd5bSHong Zhang 
5805f2c45f1SShri Abhyankar /*@
581e85e6aecSHong Zhang   DMNetworkGetGlobalVertexIndex - Get the user global numbering for the vertex.
582e85e6aecSHong Zhang 
583e85e6aecSHong Zhang   Not Collective
584e85e6aecSHong Zhang 
585e85e6aecSHong Zhang   Input Parameters:
586e85e6aecSHong Zhang + dm - DMNetwork object
587e85e6aecSHong Zhang - p  - vertex point
588e85e6aecSHong Zhang 
589e85e6aecSHong Zhang   Output Paramters:
590e85e6aecSHong Zhang . index - user global numbering for the vertex
591e85e6aecSHong Zhang 
592e85e6aecSHong Zhang   Level: intermediate
593e85e6aecSHong Zhang 
594e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalEdgeIndex
595e85e6aecSHong Zhang @*/
596e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
597e85e6aecSHong Zhang {
598e85e6aecSHong Zhang   PetscErrorCode    ierr;
599e85e6aecSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
600e85e6aecSHong Zhang   PetscInt          offsetp;
601e85e6aecSHong Zhang   DMNetworkComponentHeader header;
602e85e6aecSHong Zhang 
603e85e6aecSHong Zhang   PetscFunctionBegin;
604caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
605e85e6aecSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
606e85e6aecSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
607e85e6aecSHong Zhang   *index = header->index;
608e85e6aecSHong Zhang   PetscFunctionReturn(0);
609e85e6aecSHong Zhang }
610e85e6aecSHong Zhang 
611c3b11c7cSShri Abhyankar /*
612c3b11c7cSShri Abhyankar   DMNetworkGetComponentKeyOffset - Gets the type along with the offset for indexing the
613c3b11c7cSShri Abhyankar                                     component value from the component data array
614c3b11c7cSShri Abhyankar 
615c3b11c7cSShri Abhyankar   Not Collective
616c3b11c7cSShri Abhyankar 
617c3b11c7cSShri Abhyankar   Input Parameters:
618c3b11c7cSShri Abhyankar + dm      - The DMNetwork object
619c3b11c7cSShri Abhyankar . p       - vertex/edge point
620c3b11c7cSShri Abhyankar - compnum - component number
621c3b11c7cSShri Abhyankar 
622c3b11c7cSShri Abhyankar   Output Parameters:
623c3b11c7cSShri Abhyankar + compkey - the key obtained when registering the component
624c3b11c7cSShri Abhyankar - offset  - offset into the component data array associated with the vertex/edge point
625c3b11c7cSShri Abhyankar 
626c3b11c7cSShri Abhyankar   Notes:
627c3b11c7cSShri Abhyankar   Typical usage:
628c3b11c7cSShri Abhyankar 
629c3b11c7cSShri Abhyankar   DMNetworkGetComponentDataArray(dm, &arr);
630c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
631c3b11c7cSShri Abhyankar   Loop over vertices or edges
632c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
633c3b11c7cSShri Abhyankar     Loop over numcomps
634c3b11c7cSShri Abhyankar       DMNetworkGetComponentKeyOffset(dm,v,compnum,&key,&offset);
635c3b11c7cSShri Abhyankar       compdata = (UserCompDataType)(arr+offset);
636c3b11c7cSShri Abhyankar 
637c3b11c7cSShri Abhyankar   Level: intermediate
638c3b11c7cSShri Abhyankar 
639c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray,
640c3b11c7cSShri Abhyankar */
641c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponentKeyOffset(DM dm,PetscInt p, PetscInt compnum, PetscInt *compkey, PetscInt *offset)
642c3b11c7cSShri Abhyankar {
643c3b11c7cSShri Abhyankar   PetscErrorCode           ierr;
644c3b11c7cSShri Abhyankar   PetscInt                 offsetp;
645c3b11c7cSShri Abhyankar   DMNetworkComponentHeader header;
646c3b11c7cSShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
647c3b11c7cSShri Abhyankar 
648c3b11c7cSShri Abhyankar   PetscFunctionBegin;
649c3b11c7cSShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
650c3b11c7cSShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
651c3b11c7cSShri Abhyankar   if (compkey) *compkey = header->key[compnum];
652c3b11c7cSShri Abhyankar   if (offset) *offset  = offsetp+network->dataheadersize+header->offset[compnum];
653c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
654c3b11c7cSShri Abhyankar }
655c3b11c7cSShri Abhyankar 
656c3b11c7cSShri Abhyankar /*@
657c3b11c7cSShri Abhyankar   DMNetworkGetComponent - Returns the network component and its key
658c3b11c7cSShri Abhyankar 
659c3b11c7cSShri Abhyankar   Not Collective
660c3b11c7cSShri Abhyankar 
661c3b11c7cSShri Abhyankar   Input Parameters
662c3b11c7cSShri Abhyankar + dm - DMNetwork object
663c3b11c7cSShri Abhyankar . p  - edge or vertex point
664c3b11c7cSShri Abhyankar - compnum - component number
665c3b11c7cSShri Abhyankar 
666c3b11c7cSShri Abhyankar   Output Parameters:
667c3b11c7cSShri Abhyankar + compkey - the key set for this computing during registration
668c3b11c7cSShri Abhyankar - component - the component data
669c3b11c7cSShri Abhyankar 
670c3b11c7cSShri Abhyankar   Notes:
671c3b11c7cSShri Abhyankar   Typical usage:
672c3b11c7cSShri Abhyankar 
673c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
674c3b11c7cSShri Abhyankar   Loop over vertices or edges
675c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
676c3b11c7cSShri Abhyankar     Loop over numcomps
677c3b11c7cSShri Abhyankar       DMNetworkGetComponent(dm,v,compnum,&key,&component);
678c3b11c7cSShri Abhyankar 
679c3b11c7cSShri Abhyankar   Level: intermediate
680c3b11c7cSShri Abhyankar 
681c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetVariableOffset
682c3b11c7cSShri Abhyankar @*/
683c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponent(DM dm, PetscInt p, PetscInt compnum, PetscInt *key, void **component)
684c3b11c7cSShri Abhyankar {
685c3b11c7cSShri Abhyankar   PetscErrorCode ierr;
686c3b11c7cSShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
687e108cb99SStefano Zampini   PetscInt       offsetd = 0;
688c3b11c7cSShri Abhyankar 
689c3b11c7cSShri Abhyankar   PetscFunctionBegin;
690c3b11c7cSShri Abhyankar   ierr = DMNetworkGetComponentKeyOffset(dm,p,compnum,key,&offsetd);CHKERRQ(ierr);
691c3b11c7cSShri Abhyankar   *component = network->componentdataarray+offsetd;
692c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
693c3b11c7cSShri Abhyankar }
694c3b11c7cSShri Abhyankar 
695e85e6aecSHong Zhang /*@
696325661f6SSatish Balay   DMNetworkAddComponent - Adds a network component at the given point (vertex/edge)
6975f2c45f1SShri Abhyankar 
6985f2c45f1SShri Abhyankar   Not Collective
6995f2c45f1SShri Abhyankar 
7005f2c45f1SShri Abhyankar   Input Parameters:
7015f2c45f1SShri Abhyankar + dm           - The DMNetwork object
7025f2c45f1SShri Abhyankar . p            - vertex/edge point
7035f2c45f1SShri Abhyankar . componentkey - component key returned while registering the component
7045f2c45f1SShri Abhyankar - compvalue    - pointer to the data structure for the component
7055f2c45f1SShri Abhyankar 
7065f2c45f1SShri Abhyankar   Level: intermediate
7075f2c45f1SShri Abhyankar 
7085f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange, DMNetworkGetEdgeRange, DMNetworkRegisterComponent
7095f2c45f1SShri Abhyankar @*/
7105f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p,PetscInt componentkey,void* compvalue)
7115f2c45f1SShri Abhyankar {
7125f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
71343a39a44SBarry Smith   DMNetworkComponent       *component = &network->component[componentkey];
7145f2c45f1SShri Abhyankar   DMNetworkComponentHeader header = &network->header[p];
7155f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue = &network->cvalue[p];
7165f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
7175f2c45f1SShri Abhyankar 
7185f2c45f1SShri Abhyankar   PetscFunctionBegin;
719fa58f0a9SHong 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);
720fa58f0a9SHong Zhang 
72143a39a44SBarry Smith   header->size[header->ndata] = component->size;
72243a39a44SBarry Smith   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
7235f2c45f1SShri Abhyankar   header->key[header->ndata] = componentkey;
7245f2c45f1SShri Abhyankar   if (header->ndata != 0) header->offset[header->ndata] = header->offset[header->ndata-1] + header->size[header->ndata-1];
7255f2c45f1SShri Abhyankar 
7265f2c45f1SShri Abhyankar   cvalue->data[header->ndata] = (void*)compvalue;
7275f2c45f1SShri Abhyankar   header->ndata++;
7285f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7295f2c45f1SShri Abhyankar }
7305f2c45f1SShri Abhyankar 
7315f2c45f1SShri Abhyankar /*@
7325f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
7335f2c45f1SShri Abhyankar 
7345f2c45f1SShri Abhyankar   Not Collective
7355f2c45f1SShri Abhyankar 
7365f2c45f1SShri Abhyankar   Input Parameters:
7375f2c45f1SShri Abhyankar + dm - The DMNetwork object
738a2b725a8SWilliam Gropp - p  - vertex/edge point
7395f2c45f1SShri Abhyankar 
7405f2c45f1SShri Abhyankar   Output Parameters:
7415f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
7425f2c45f1SShri Abhyankar 
7435f2c45f1SShri Abhyankar   Level: intermediate
7445f2c45f1SShri Abhyankar 
7455f2c45f1SShri Abhyankar .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent
7465f2c45f1SShri Abhyankar @*/
7475f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
7485f2c45f1SShri Abhyankar {
7495f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7505f2c45f1SShri Abhyankar   PetscInt       offset;
7515f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7525f2c45f1SShri Abhyankar 
7535f2c45f1SShri Abhyankar   PetscFunctionBegin;
7545f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
7555f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
7565f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7575f2c45f1SShri Abhyankar }
7585f2c45f1SShri Abhyankar 
7595f2c45f1SShri Abhyankar /*@
7605f2c45f1SShri Abhyankar   DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector.
7615f2c45f1SShri Abhyankar 
7625f2c45f1SShri Abhyankar   Not Collective
7635f2c45f1SShri Abhyankar 
7645f2c45f1SShri Abhyankar   Input Parameters:
7655f2c45f1SShri Abhyankar + dm     - The DMNetwork object
7665f2c45f1SShri Abhyankar - p      - the edge/vertex point
7675f2c45f1SShri Abhyankar 
7685f2c45f1SShri Abhyankar   Output Parameters:
7695f2c45f1SShri Abhyankar . offset - the offset
7705f2c45f1SShri Abhyankar 
7715f2c45f1SShri Abhyankar   Level: intermediate
7725f2c45f1SShri Abhyankar 
7735f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
7745f2c45f1SShri Abhyankar @*/
7755f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset)
7765f2c45f1SShri Abhyankar {
7775f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7785f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7795f2c45f1SShri Abhyankar 
7805f2c45f1SShri Abhyankar   PetscFunctionBegin;
7811bb6d2a8SBarry Smith   ierr = PetscSectionGetOffset(network->plex->localSection,p,offset);CHKERRQ(ierr);
7825f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7835f2c45f1SShri Abhyankar }
7845f2c45f1SShri Abhyankar 
7855f2c45f1SShri Abhyankar /*@
7865f2c45f1SShri Abhyankar   DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector.
7875f2c45f1SShri Abhyankar 
7885f2c45f1SShri Abhyankar   Not Collective
7895f2c45f1SShri Abhyankar 
7905f2c45f1SShri Abhyankar   Input Parameters:
7915f2c45f1SShri Abhyankar + dm      - The DMNetwork object
7925f2c45f1SShri Abhyankar - p       - the edge/vertex point
7935f2c45f1SShri Abhyankar 
7945f2c45f1SShri Abhyankar   Output Parameters:
7955f2c45f1SShri Abhyankar . offsetg - the offset
7965f2c45f1SShri Abhyankar 
7975f2c45f1SShri Abhyankar   Level: intermediate
7985f2c45f1SShri Abhyankar 
7995f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableOffset, DMGetLocalVector
8005f2c45f1SShri Abhyankar @*/
8015f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg)
8025f2c45f1SShri Abhyankar {
8035f2c45f1SShri Abhyankar   PetscErrorCode ierr;
8045f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8055f2c45f1SShri Abhyankar 
8065f2c45f1SShri Abhyankar   PetscFunctionBegin;
8071bb6d2a8SBarry Smith   ierr = PetscSectionGetOffset(network->plex->globalSection,p,offsetg);CHKERRQ(ierr);
8086fefedf4SHong Zhang   if (*offsetg < 0) *offsetg = -(*offsetg + 1); /* Convert to actual global offset for ghost vertex */
8095f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8105f2c45f1SShri Abhyankar }
8115f2c45f1SShri Abhyankar 
81224121865SAdrian Maldonado /*@
81324121865SAdrian Maldonado   DMNetworkGetEdgeOffset - Get the offset for accessing the variable associated with the given edge from the local subvector.
81424121865SAdrian Maldonado 
81524121865SAdrian Maldonado   Not Collective
81624121865SAdrian Maldonado 
81724121865SAdrian Maldonado   Input Parameters:
81824121865SAdrian Maldonado + dm     - The DMNetwork object
81924121865SAdrian Maldonado - p      - the edge point
82024121865SAdrian Maldonado 
82124121865SAdrian Maldonado   Output Parameters:
82224121865SAdrian Maldonado . offset - the offset
82324121865SAdrian Maldonado 
82424121865SAdrian Maldonado   Level: intermediate
82524121865SAdrian Maldonado 
82624121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
82724121865SAdrian Maldonado @*/
82824121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
82924121865SAdrian Maldonado {
83024121865SAdrian Maldonado   PetscErrorCode ierr;
83124121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
83224121865SAdrian Maldonado 
83324121865SAdrian Maldonado   PetscFunctionBegin;
83424121865SAdrian Maldonado 
83524121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
83624121865SAdrian Maldonado   PetscFunctionReturn(0);
83724121865SAdrian Maldonado }
83824121865SAdrian Maldonado 
83924121865SAdrian Maldonado /*@
84024121865SAdrian Maldonado   DMNetworkGetVertexOffset - Get the offset for accessing the variable associated with the given vertex from the local subvector.
84124121865SAdrian Maldonado 
84224121865SAdrian Maldonado   Not Collective
84324121865SAdrian Maldonado 
84424121865SAdrian Maldonado   Input Parameters:
84524121865SAdrian Maldonado + dm     - The DMNetwork object
84624121865SAdrian Maldonado - p      - the vertex point
84724121865SAdrian Maldonado 
84824121865SAdrian Maldonado   Output Parameters:
84924121865SAdrian Maldonado . offset - the offset
85024121865SAdrian Maldonado 
85124121865SAdrian Maldonado   Level: intermediate
85224121865SAdrian Maldonado 
85324121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
85424121865SAdrian Maldonado @*/
85524121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
85624121865SAdrian Maldonado {
85724121865SAdrian Maldonado   PetscErrorCode ierr;
85824121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
85924121865SAdrian Maldonado 
86024121865SAdrian Maldonado   PetscFunctionBegin;
86124121865SAdrian Maldonado 
86224121865SAdrian Maldonado   p -= network->vStart;
86324121865SAdrian Maldonado 
86424121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
86524121865SAdrian Maldonado   PetscFunctionReturn(0);
86624121865SAdrian Maldonado }
8675f2c45f1SShri Abhyankar /*@
8685f2c45f1SShri Abhyankar   DMNetworkAddNumVariables - Add number of variables associated with a given point.
8695f2c45f1SShri Abhyankar 
8705f2c45f1SShri Abhyankar   Not Collective
8715f2c45f1SShri Abhyankar 
8725f2c45f1SShri Abhyankar   Input Parameters:
8735f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
8745f2c45f1SShri Abhyankar . p    - the vertex/edge point
8755f2c45f1SShri Abhyankar - nvar - number of additional variables
8765f2c45f1SShri Abhyankar 
8775f2c45f1SShri Abhyankar   Level: intermediate
8785f2c45f1SShri Abhyankar 
8795f2c45f1SShri Abhyankar .seealso: DMNetworkSetNumVariables
8805f2c45f1SShri Abhyankar @*/
8815f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar)
8825f2c45f1SShri Abhyankar {
8835f2c45f1SShri Abhyankar   PetscErrorCode ierr;
8845f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8855f2c45f1SShri Abhyankar 
8865f2c45f1SShri Abhyankar   PetscFunctionBegin;
8875f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
8885f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8895f2c45f1SShri Abhyankar }
8905f2c45f1SShri Abhyankar 
89127f51fceSHong Zhang /*@
89227f51fceSHong Zhang   DMNetworkGetNumVariables - Gets number of variables for a vertex/edge point.
89327f51fceSHong Zhang 
89427f51fceSHong Zhang   Not Collective
89527f51fceSHong Zhang 
89627f51fceSHong Zhang   Input Parameters:
89727f51fceSHong Zhang + dm   - The DMNetworkObject
89827f51fceSHong Zhang - p    - the vertex/edge point
89927f51fceSHong Zhang 
90027f51fceSHong Zhang   Output Parameters:
90127f51fceSHong Zhang . nvar - number of variables
90227f51fceSHong Zhang 
90327f51fceSHong Zhang   Level: intermediate
90427f51fceSHong Zhang 
90527f51fceSHong Zhang .seealso: DMNetworkAddNumVariables, DMNetworkSddNumVariables
90627f51fceSHong Zhang @*/
90727f51fceSHong Zhang PetscErrorCode DMNetworkGetNumVariables(DM dm,PetscInt p,PetscInt *nvar)
90827f51fceSHong Zhang {
90927f51fceSHong Zhang   PetscErrorCode ierr;
91027f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
91127f51fceSHong Zhang 
91227f51fceSHong Zhang   PetscFunctionBegin;
91327f51fceSHong Zhang   ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
91427f51fceSHong Zhang   PetscFunctionReturn(0);
91527f51fceSHong Zhang }
91627f51fceSHong Zhang 
9175f2c45f1SShri Abhyankar /*@
9185f2c45f1SShri Abhyankar   DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point.
9195f2c45f1SShri Abhyankar 
9205f2c45f1SShri Abhyankar   Not Collective
9215f2c45f1SShri Abhyankar 
9225f2c45f1SShri Abhyankar   Input Parameters:
9235f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
9245f2c45f1SShri Abhyankar . p    - the vertex/edge point
9255f2c45f1SShri Abhyankar - nvar - number of variables
9265f2c45f1SShri Abhyankar 
9275f2c45f1SShri Abhyankar   Level: intermediate
9285f2c45f1SShri Abhyankar 
9295f2c45f1SShri Abhyankar .seealso: DMNetworkAddNumVariables
9305f2c45f1SShri Abhyankar @*/
9315f2c45f1SShri Abhyankar PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar)
9325f2c45f1SShri Abhyankar {
9335f2c45f1SShri Abhyankar   PetscErrorCode ierr;
9345f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
9355f2c45f1SShri Abhyankar 
9365f2c45f1SShri Abhyankar   PetscFunctionBegin;
9375f2c45f1SShri Abhyankar   ierr = PetscSectionSetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
9385f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9395f2c45f1SShri Abhyankar }
9405f2c45f1SShri Abhyankar 
9415f2c45f1SShri Abhyankar /* Sets up the array that holds the data for all components and its associated section. This
9425f2c45f1SShri Abhyankar    function is called during DMSetUp() */
9435f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
9445f2c45f1SShri Abhyankar {
9455f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
9465f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
947e53b5ba3SHong Zhang   PetscInt                 arr_size,p,offset,offsetp,ncomp,i;
9485f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
9495f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
9505f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
9515f2c45f1SShri Abhyankar 
9525f2c45f1SShri Abhyankar   PetscFunctionBegin;
9535f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
9545f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
95575b160a0SShri Abhyankar   ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
9565f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
9575f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
9585f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
9595f2c45f1SShri Abhyankar     /* Copy header */
9605f2c45f1SShri Abhyankar     header = &network->header[p];
961302440fdSBarry Smith     ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
9625f2c45f1SShri Abhyankar     /* Copy data */
9635f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
9645f2c45f1SShri Abhyankar     ncomp = header->ndata;
9655f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
9665f2c45f1SShri Abhyankar       offset = offsetp + network->dataheadersize + header->offset[i];
967302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
9685f2c45f1SShri Abhyankar     }
9695f2c45f1SShri Abhyankar   }
9705f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9715f2c45f1SShri Abhyankar }
9725f2c45f1SShri Abhyankar 
9735f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
9745f2c45f1SShri Abhyankar PetscErrorCode DMNetworkVariablesSetUp(DM dm)
9755f2c45f1SShri Abhyankar {
9765f2c45f1SShri Abhyankar   PetscErrorCode ierr;
9775f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
9785f2c45f1SShri Abhyankar 
9795f2c45f1SShri Abhyankar   PetscFunctionBegin;
9805f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
9815f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9825f2c45f1SShri Abhyankar }
9835f2c45f1SShri Abhyankar 
9845f2c45f1SShri Abhyankar /*@C
9855f2c45f1SShri Abhyankar   DMNetworkGetComponentDataArray - Returns the component data array
9865f2c45f1SShri Abhyankar 
9875f2c45f1SShri Abhyankar   Not Collective
9885f2c45f1SShri Abhyankar 
9895f2c45f1SShri Abhyankar   Input Parameters:
9905f2c45f1SShri Abhyankar . dm - The DMNetwork Object
9915f2c45f1SShri Abhyankar 
9925f2c45f1SShri Abhyankar   Output Parameters:
9935f2c45f1SShri Abhyankar . componentdataarray - array that holds data for all components
9945f2c45f1SShri Abhyankar 
9955f2c45f1SShri Abhyankar   Level: intermediate
9965f2c45f1SShri Abhyankar 
997a730d845SHong Zhang .seealso: DMNetworkGetComponentKeyOffset, DMNetworkGetNumComponents
9985f2c45f1SShri Abhyankar @*/
9995f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray)
10005f2c45f1SShri Abhyankar {
10015f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10025f2c45f1SShri Abhyankar 
10035f2c45f1SShri Abhyankar   PetscFunctionBegin;
10045f2c45f1SShri Abhyankar   *componentdataarray = network->componentdataarray;
10055f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10065f2c45f1SShri Abhyankar }
10075f2c45f1SShri Abhyankar 
100824121865SAdrian Maldonado /* Get a subsection from a range of points */
100924121865SAdrian Maldonado PetscErrorCode DMNetworkGetSubSection_private(PetscSection master, PetscInt pstart, PetscInt pend,PetscSection *subsection)
101024121865SAdrian Maldonado {
101124121865SAdrian Maldonado   PetscErrorCode ierr;
101224121865SAdrian Maldonado   PetscInt       i, nvar;
101324121865SAdrian Maldonado 
101424121865SAdrian Maldonado   PetscFunctionBegin;
101524121865SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)master), subsection);CHKERRQ(ierr);
101624121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
101724121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
101824121865SAdrian Maldonado     ierr = PetscSectionGetDof(master,i,&nvar);CHKERRQ(ierr);
101924121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
102024121865SAdrian Maldonado   }
102124121865SAdrian Maldonado 
102224121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
102324121865SAdrian Maldonado   PetscFunctionReturn(0);
102424121865SAdrian Maldonado }
102524121865SAdrian Maldonado 
102624121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
102724121865SAdrian Maldonado PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
102824121865SAdrian Maldonado {
102924121865SAdrian Maldonado   PetscErrorCode ierr;
103024121865SAdrian Maldonado   PetscInt       i, *subpoints;
103124121865SAdrian Maldonado 
103224121865SAdrian Maldonado   PetscFunctionBegin;
103324121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
103424121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
103524121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
103624121865SAdrian Maldonado     subpoints[i - pstart] = i;
103724121865SAdrian Maldonado   }
1038459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
103924121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
104024121865SAdrian Maldonado   PetscFunctionReturn(0);
104124121865SAdrian Maldonado }
104224121865SAdrian Maldonado 
104324121865SAdrian Maldonado /*@
104424121865SAdrian Maldonado   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute.
104524121865SAdrian Maldonado 
104624121865SAdrian Maldonado   Collective
104724121865SAdrian Maldonado 
104824121865SAdrian Maldonado   Input Parameters:
104924121865SAdrian Maldonado . dm   - The DMNetworkObject
105024121865SAdrian Maldonado 
105124121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
105224121865SAdrian Maldonado 
105324121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
105424121865SAdrian Maldonado 
1055caf410d2SHong 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]).
105624121865SAdrian Maldonado 
105724121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
105824121865SAdrian Maldonado 
105924121865SAdrian Maldonado   Level: intermediate
106024121865SAdrian Maldonado 
106124121865SAdrian Maldonado @*/
106224121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
106324121865SAdrian Maldonado {
106424121865SAdrian Maldonado   PetscErrorCode ierr;
106524121865SAdrian Maldonado   MPI_Comm       comm;
10669852e123SBarry Smith   PetscMPIInt    rank, size;
106724121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
106824121865SAdrian Maldonado 
1069eab1376dSHong Zhang   PetscFunctionBegin;
107024121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
107124121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
10729852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
107324121865SAdrian Maldonado 
107424121865SAdrian Maldonado   /* Create maps for vertices and edges */
107524121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
107624121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
107724121865SAdrian Maldonado 
107824121865SAdrian Maldonado   /* Create local sub-sections */
107924121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
108024121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
108124121865SAdrian Maldonado 
10829852e123SBarry Smith   if (size > 1) {
108324121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
108422bbedd7SHong Zhang 
108524121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
108624121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
108724121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
108824121865SAdrian Maldonado   } else {
108924121865SAdrian Maldonado     /* create structures for vertex */
109024121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
109124121865SAdrian Maldonado     /* create structures for edge */
109224121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
109324121865SAdrian Maldonado   }
109424121865SAdrian Maldonado 
109524121865SAdrian Maldonado   /* Add viewers */
109624121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
109724121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
109824121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
109924121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
110024121865SAdrian Maldonado   PetscFunctionReturn(0);
110124121865SAdrian Maldonado }
11027b6afd5bSHong Zhang 
11035f2c45f1SShri Abhyankar /*@
11045f2c45f1SShri Abhyankar   DMNetworkDistribute - Distributes the network and moves associated component data.
11055f2c45f1SShri Abhyankar 
11065f2c45f1SShri Abhyankar   Collective
11075f2c45f1SShri Abhyankar 
11085f2c45f1SShri Abhyankar   Input Parameter:
1109d3464fd4SAdrian Maldonado + DM - the DMNetwork object
11105f2c45f1SShri Abhyankar - overlap - The overlap of partitions, 0 is the default
11115f2c45f1SShri Abhyankar 
11125f2c45f1SShri Abhyankar   Notes:
11138b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
11145f2c45f1SShri Abhyankar 
11155f2c45f1SShri Abhyankar   Level: intermediate
11165f2c45f1SShri Abhyankar 
11175f2c45f1SShri Abhyankar .seealso: DMNetworkCreate
11185f2c45f1SShri Abhyankar @*/
1119d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
11205f2c45f1SShri Abhyankar {
1121d3464fd4SAdrian Maldonado   MPI_Comm       comm;
11225f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1123d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1124d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1125d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1126caf410d2SHong Zhang   PetscSF        pointsf=NULL;
11275f2c45f1SShri Abhyankar   DM             newDM;
1128caf410d2SHong Zhang   PetscInt       j,e,v,offset,*subnetvtx;
112951ac5effSHong Zhang   PetscPartitioner         part;
1130b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
11315f2c45f1SShri Abhyankar 
11325f2c45f1SShri Abhyankar   PetscFunctionBegin;
1133d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1134d3464fd4SAdrian Maldonado   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
1135d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1136d3464fd4SAdrian Maldonado 
1137d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
11385f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
11395f2c45f1SShri Abhyankar   newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
114051ac5effSHong Zhang 
114151ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
114251ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
114351ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
114451ac5effSHong Zhang 
11455f2c45f1SShri Abhyankar   /* Distribute plex dm and dof section */
114680cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
114751ac5effSHong Zhang 
11485f2c45f1SShri Abhyankar   /* Distribute dof section */
1149d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DofSection);CHKERRQ(ierr);
11505f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
1151d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DataSection);CHKERRQ(ierr);
115251ac5effSHong Zhang 
11535f2c45f1SShri Abhyankar   /* Distribute data and associated section */
115431da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
115524121865SAdrian Maldonado 
11565f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
11575f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
11585f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
11595f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
11606fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
11616fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
11625f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
116324121865SAdrian Maldonado 
11641bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
116592fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1166e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
11675f2c45f1SShri Abhyankar 
1168b9c6e19dSShri Abhyankar   /* Set up subnetwork info in the newDM */
1169b9c6e19dSShri Abhyankar   newDMnetwork->nsubnet  = oldDMnetwork->nsubnet;
1170caf410d2SHong Zhang   newDMnetwork->ncsubnet = oldDMnetwork->ncsubnet;
1171b9c6e19dSShri Abhyankar   ierr = PetscCalloc1(newDMnetwork->nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
1172b9c6e19dSShri Abhyankar   /* Copy over the global number of vertices and edges in each subnetwork. Note that these are already
1173b9c6e19dSShri Abhyankar      calculated in DMNetworkLayoutSetUp()
1174b9c6e19dSShri Abhyankar   */
1175b9c6e19dSShri Abhyankar   for(j=0; j < newDMnetwork->nsubnet; j++) {
1176b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1177b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1178b9c6e19dSShri Abhyankar   }
1179b9c6e19dSShri Abhyankar 
1180b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1181b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1182b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1183b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1184b9c6e19dSShri Abhyankar   }
1185b9c6e19dSShri Abhyankar 
1186b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1187b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1188b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1189b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nvtx++;
1190b9c6e19dSShri Abhyankar   }
1191b9c6e19dSShri Abhyankar 
1192b9c6e19dSShri Abhyankar   /* Now create the vertices and edge arrays for the subnetworks */
1193caf410d2SHong Zhang   ierr = PetscCalloc1(newDMnetwork->vEnd-newDMnetwork->vStart,&newDMnetwork->subnetvtx);CHKERRQ(ierr);
1194caf410d2SHong Zhang   subnetvtx = newDMnetwork->subnetvtx;
1195caf410d2SHong Zhang 
1196b9c6e19dSShri Abhyankar   for (j=0; j<newDMnetwork->nsubnet; j++) {
1197b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr);
1198caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1199caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1200caf410d2SHong Zhang 
1201b9c6e19dSShri Abhyankar     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
1202b9c6e19dSShri Abhyankar        These get updated when the vertices and edges are added. */
1203b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1204b9c6e19dSShri Abhyankar   }
1205b9c6e19dSShri Abhyankar 
1206b9c6e19dSShri Abhyankar   /* Set the vertices and edges in each subnetwork */
1207b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1208b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1209b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1210b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1211b9c6e19dSShri Abhyankar   }
1212b9c6e19dSShri Abhyankar 
1213b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1214b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1215b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1216b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
1217b9c6e19dSShri Abhyankar   }
1218b9c6e19dSShri Abhyankar 
1219caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
122022bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1221caf410d2SHong Zhang 
122224121865SAdrian Maldonado   /* Destroy point SF */
122324121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
122424121865SAdrian Maldonado 
1225d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
1226d3464fd4SAdrian Maldonado   *dm  = newDM;
12275f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
12285f2c45f1SShri Abhyankar }
12295f2c45f1SShri Abhyankar 
123024121865SAdrian Maldonado /*@C
123124121865SAdrian Maldonado   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering.
123224121865SAdrian Maldonado 
123324121865SAdrian Maldonado   Input Parameters:
123424121865SAdrian Maldonado + masterSF - the original SF structure
123524121865SAdrian Maldonado - map      - a ISLocalToGlobal mapping that contains the subset of points
123624121865SAdrian Maldonado 
123724121865SAdrian Maldonado   Output Parameters:
123824121865SAdrian Maldonado . subSF    - a subset of the masterSF for the desired subset.
123924121865SAdrian Maldonado */
124024121865SAdrian Maldonado 
124124121865SAdrian Maldonado PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) {
124224121865SAdrian Maldonado 
124324121865SAdrian Maldonado   PetscErrorCode        ierr;
124424121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
124524121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
124624121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
124724121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
124824121865SAdrian Maldonado   const PetscInt        *ilocal;
124924121865SAdrian Maldonado   const PetscSFNode     *iremote;
125024121865SAdrian Maldonado 
125124121865SAdrian Maldonado   PetscFunctionBegin;
125224121865SAdrian Maldonado   ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
125324121865SAdrian Maldonado 
125424121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
125524121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
125624121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
125724121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
125824121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
125924121865SAdrian Maldonado   }
126024121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
126124121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
126224121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
126324121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
126424121865SAdrian Maldonado   ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
126524121865SAdrian Maldonado   ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
126624121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
12674b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
12684b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
126924121865SAdrian Maldonado   nleaves_sub = 0;
127024121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
127124121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
127224121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
12734b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
127424121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
127524121865SAdrian Maldonado       nleaves_sub += 1;
127624121865SAdrian Maldonado     }
127724121865SAdrian Maldonado   }
127824121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
127924121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
128024121865SAdrian Maldonado 
128124121865SAdrian Maldonado   /* Create new subSF */
128224121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
128324121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
12844b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
128524121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
12864b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
128724121865SAdrian Maldonado   PetscFunctionReturn(0);
128824121865SAdrian Maldonado }
128924121865SAdrian Maldonado 
12905f2c45f1SShri Abhyankar /*@C
12915f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
12925f2c45f1SShri Abhyankar 
12935f2c45f1SShri Abhyankar   Not Collective
12945f2c45f1SShri Abhyankar 
12955f2c45f1SShri Abhyankar   Input Parameters:
12965f2c45f1SShri Abhyankar + dm - The DMNetwork object
12975f2c45f1SShri Abhyankar - p  - the vertex point
12985f2c45f1SShri Abhyankar 
12995f2c45f1SShri Abhyankar   Output Paramters:
13005f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
13015f2c45f1SShri Abhyankar - edges  - List of edge points
13025f2c45f1SShri Abhyankar 
13035f2c45f1SShri Abhyankar   Level: intermediate
13045f2c45f1SShri Abhyankar 
13055f2c45f1SShri Abhyankar   Fortran Notes:
13065f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
13075f2c45f1SShri Abhyankar   include petsc.h90 in your code.
13085f2c45f1SShri Abhyankar 
1309d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices
13105f2c45f1SShri Abhyankar @*/
13115f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
13125f2c45f1SShri Abhyankar {
13135f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13145f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
13155f2c45f1SShri Abhyankar 
13165f2c45f1SShri Abhyankar   PetscFunctionBegin;
13175f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
13185f2c45f1SShri Abhyankar   ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);
13195f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13205f2c45f1SShri Abhyankar }
13215f2c45f1SShri Abhyankar 
13225f2c45f1SShri Abhyankar /*@C
1323d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
13245f2c45f1SShri Abhyankar 
13255f2c45f1SShri Abhyankar   Not Collective
13265f2c45f1SShri Abhyankar 
13275f2c45f1SShri Abhyankar   Input Parameters:
13285f2c45f1SShri Abhyankar + dm - The DMNetwork object
13295f2c45f1SShri Abhyankar - p  - the edge point
13305f2c45f1SShri Abhyankar 
13315f2c45f1SShri Abhyankar   Output Paramters:
13325f2c45f1SShri Abhyankar . vertices  - vertices connected to this edge
13335f2c45f1SShri Abhyankar 
13345f2c45f1SShri Abhyankar   Level: intermediate
13355f2c45f1SShri Abhyankar 
13365f2c45f1SShri Abhyankar   Fortran Notes:
13375f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
13385f2c45f1SShri Abhyankar   include petsc.h90 in your code.
13395f2c45f1SShri Abhyankar 
13405f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
13415f2c45f1SShri Abhyankar @*/
1342d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
13435f2c45f1SShri Abhyankar {
13445f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13455f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
13465f2c45f1SShri Abhyankar 
13475f2c45f1SShri Abhyankar   PetscFunctionBegin;
13485f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
13495f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13505f2c45f1SShri Abhyankar }
13515f2c45f1SShri Abhyankar 
13525f2c45f1SShri Abhyankar /*@
13535f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
13545f2c45f1SShri Abhyankar 
13555f2c45f1SShri Abhyankar   Not Collective
13565f2c45f1SShri Abhyankar 
13575f2c45f1SShri Abhyankar   Input Parameters:
13585f2c45f1SShri Abhyankar + dm - The DMNetwork object
1359a2b725a8SWilliam Gropp - p  - the vertex point
13605f2c45f1SShri Abhyankar 
13615f2c45f1SShri Abhyankar   Output Parameter:
13625f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
13635f2c45f1SShri Abhyankar 
13645f2c45f1SShri Abhyankar   Level: intermediate
13655f2c45f1SShri Abhyankar 
1366d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange
13675f2c45f1SShri Abhyankar @*/
13685f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
13695f2c45f1SShri Abhyankar {
13705f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13715f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
13725f2c45f1SShri Abhyankar   PetscInt       offsetg;
13735f2c45f1SShri Abhyankar   PetscSection   sectiong;
13745f2c45f1SShri Abhyankar 
13755f2c45f1SShri Abhyankar   PetscFunctionBegin;
1376caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
13775f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
1378e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
13795f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
13805f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
13815f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13825f2c45f1SShri Abhyankar }
13835f2c45f1SShri Abhyankar 
13845f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
13855f2c45f1SShri Abhyankar {
13865f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13875f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
13885f2c45f1SShri Abhyankar 
13895f2c45f1SShri Abhyankar   PetscFunctionBegin;
13905f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
13915f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
13925f2c45f1SShri Abhyankar 
139392fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
1394e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
13959e1d080bSHong Zhang 
13969e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
13979e1d080bSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr);
13985f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13995f2c45f1SShri Abhyankar }
14005f2c45f1SShri Abhyankar 
14011ad426b7SHong Zhang /*@
140217df6e9eSHong Zhang     DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
14031ad426b7SHong Zhang                             -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
14041ad426b7SHong Zhang 
14051ad426b7SHong Zhang     Collective
14061ad426b7SHong Zhang 
14071ad426b7SHong Zhang     Input Parameters:
140883b2e829SHong Zhang +   dm - The DMNetwork object
140983b2e829SHong Zhang .   eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
141083b2e829SHong Zhang -   vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
14111ad426b7SHong Zhang 
14121ad426b7SHong Zhang     Level: intermediate
14131ad426b7SHong Zhang 
14141ad426b7SHong Zhang @*/
141583b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
14161ad426b7SHong Zhang {
14171ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
14188675203cSHong Zhang   PetscErrorCode ierr;
141966b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
14201ad426b7SHong Zhang 
14211ad426b7SHong Zhang   PetscFunctionBegin;
142283b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
142383b2e829SHong Zhang   network->userVertexJacobian = vflg;
14248675203cSHong Zhang 
14258675203cSHong Zhang   if (eflg && !network->Je) {
14268675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
14278675203cSHong Zhang   }
14288675203cSHong Zhang 
142966b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
14308675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
143166b4e0ffSHong Zhang     PetscInt       nedges_total;
14328675203cSHong Zhang     const PetscInt *edges;
14338675203cSHong Zhang 
14348675203cSHong Zhang     /* count nvertex_total */
14358675203cSHong Zhang     nedges_total = 0;
14368675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
14378675203cSHong Zhang 
14388675203cSHong Zhang     vptr[0] = 0;
14398675203cSHong Zhang     for (i=0; i<nVertices; i++) {
14408675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
14418675203cSHong Zhang       nedges_total += nedges;
14428675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
14438675203cSHong Zhang     }
14448675203cSHong Zhang 
14458675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
14468675203cSHong Zhang     network->Jvptr = vptr;
14478675203cSHong Zhang   }
14481ad426b7SHong Zhang   PetscFunctionReturn(0);
14491ad426b7SHong Zhang }
14501ad426b7SHong Zhang 
14511ad426b7SHong Zhang /*@
145283b2e829SHong Zhang     DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
145383b2e829SHong Zhang 
145483b2e829SHong Zhang     Not Collective
145583b2e829SHong Zhang 
145683b2e829SHong Zhang     Input Parameters:
145783b2e829SHong Zhang +   dm - The DMNetwork object
145883b2e829SHong Zhang .   p  - the edge point
14593e97b6e8SHong Zhang -   J - array (size = 3) of Jacobian submatrices for this edge point:
14603e97b6e8SHong Zhang         J[0]: this edge
1461d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
146283b2e829SHong Zhang 
146383b2e829SHong Zhang     Level: intermediate
146483b2e829SHong Zhang 
146583b2e829SHong Zhang .seealso: DMNetworkVertexSetMatrix
146683b2e829SHong Zhang @*/
146783b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
146883b2e829SHong Zhang {
146983b2e829SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
147083b2e829SHong Zhang 
147183b2e829SHong Zhang   PetscFunctionBegin;
14728675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
14738675203cSHong Zhang 
14748675203cSHong Zhang   if (J) {
1475883e35e8SHong Zhang     network->Je[3*p]   = J[0];
1476883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
1477883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
14788675203cSHong Zhang   }
147983b2e829SHong Zhang   PetscFunctionReturn(0);
148083b2e829SHong Zhang }
148183b2e829SHong Zhang 
148283b2e829SHong Zhang /*@
148376ddfea5SHong Zhang     DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
14841ad426b7SHong Zhang 
14851ad426b7SHong Zhang     Not Collective
14861ad426b7SHong Zhang 
14871ad426b7SHong Zhang     Input Parameters:
14881ad426b7SHong Zhang +   dm - The DMNetwork object
14891ad426b7SHong Zhang .   p  - the vertex point
14903e97b6e8SHong Zhang -   J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
14913e97b6e8SHong Zhang         J[0]:       this vertex
14923e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
14933e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
14941ad426b7SHong Zhang 
14951ad426b7SHong Zhang     Level: intermediate
14961ad426b7SHong Zhang 
149783b2e829SHong Zhang .seealso: DMNetworkEdgeSetMatrix
14981ad426b7SHong Zhang @*/
1499883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
15005f2c45f1SShri Abhyankar {
15015f2c45f1SShri Abhyankar   PetscErrorCode ierr;
15025f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
15038675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
1504883e35e8SHong Zhang   const PetscInt *edges;
15055f2c45f1SShri Abhyankar 
15065f2c45f1SShri Abhyankar   PetscFunctionBegin;
15078675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1508883e35e8SHong Zhang 
15098675203cSHong Zhang   if (J) {
1510883e35e8SHong Zhang     vptr = network->Jvptr;
15113e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
15123e97b6e8SHong Zhang 
15133e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
1514883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
1515883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
15168675203cSHong Zhang   }
1517883e35e8SHong Zhang   PetscFunctionReturn(0);
1518883e35e8SHong Zhang }
1519883e35e8SHong Zhang 
1520e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
15215cf7da58SHong Zhang {
15225cf7da58SHong Zhang   PetscErrorCode ierr;
15235cf7da58SHong Zhang   PetscInt       j;
15245cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
15255cf7da58SHong Zhang 
15265cf7da58SHong Zhang   PetscFunctionBegin;
15275cf7da58SHong Zhang   if (!ghost) {
15285cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
15295cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
15305cf7da58SHong Zhang     }
15315cf7da58SHong Zhang   } else {
15325cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
15335cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
15345cf7da58SHong Zhang     }
15355cf7da58SHong Zhang   }
15365cf7da58SHong Zhang   PetscFunctionReturn(0);
15375cf7da58SHong Zhang }
15385cf7da58SHong Zhang 
1539e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
15405cf7da58SHong Zhang {
15415cf7da58SHong Zhang   PetscErrorCode ierr;
15425cf7da58SHong Zhang   PetscInt       j,ncols_u;
15435cf7da58SHong Zhang   PetscScalar    val;
15445cf7da58SHong Zhang 
15455cf7da58SHong Zhang   PetscFunctionBegin;
15465cf7da58SHong Zhang   if (!ghost) {
15475cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
15485cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
15495cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
15505cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
15515cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
15525cf7da58SHong Zhang     }
15535cf7da58SHong Zhang   } else {
15545cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
15555cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
15565cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
15575cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
15585cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
15595cf7da58SHong Zhang     }
15605cf7da58SHong Zhang   }
15615cf7da58SHong Zhang   PetscFunctionReturn(0);
15625cf7da58SHong Zhang }
15635cf7da58SHong Zhang 
1564e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
15655cf7da58SHong Zhang {
15665cf7da58SHong Zhang   PetscErrorCode ierr;
15675cf7da58SHong Zhang 
15685cf7da58SHong Zhang   PetscFunctionBegin;
15695cf7da58SHong Zhang   if (Ju) {
15705cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
15715cf7da58SHong Zhang   } else {
15725cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
15735cf7da58SHong Zhang   }
15745cf7da58SHong Zhang   PetscFunctionReturn(0);
15755cf7da58SHong Zhang }
15765cf7da58SHong Zhang 
1577e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1578883e35e8SHong Zhang {
1579883e35e8SHong Zhang   PetscErrorCode ierr;
1580883e35e8SHong Zhang   PetscInt       j,*cols;
1581883e35e8SHong Zhang   PetscScalar    *zeros;
1582883e35e8SHong Zhang 
1583883e35e8SHong Zhang   PetscFunctionBegin;
1584883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
1585883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
1586883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
1587883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
15881ad426b7SHong Zhang   PetscFunctionReturn(0);
15891ad426b7SHong Zhang }
1590a4e85ca8SHong Zhang 
1591e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
15923e97b6e8SHong Zhang {
15933e97b6e8SHong Zhang   PetscErrorCode ierr;
15943e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
15953e97b6e8SHong Zhang   const PetscInt *cols;
15963e97b6e8SHong Zhang   PetscScalar    zero=0.0;
15973e97b6e8SHong Zhang 
15983e97b6e8SHong Zhang   PetscFunctionBegin;
15993e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
16003e97b6e8SHong 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);
16013e97b6e8SHong Zhang 
16023e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
16033e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
16043e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
16053e97b6e8SHong Zhang       col = cols[j] + cstart;
16063e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
16073e97b6e8SHong Zhang     }
16083e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
16093e97b6e8SHong Zhang   }
16103e97b6e8SHong Zhang   PetscFunctionReturn(0);
16113e97b6e8SHong Zhang }
16121ad426b7SHong Zhang 
1613e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1614a4e85ca8SHong Zhang {
1615a4e85ca8SHong Zhang   PetscErrorCode ierr;
1616f4431b8cSHong Zhang 
1617a4e85ca8SHong Zhang   PetscFunctionBegin;
1618a4e85ca8SHong Zhang   if (Ju) {
1619a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1620a4e85ca8SHong Zhang   } else {
1621a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1622a4e85ca8SHong Zhang   }
1623a4e85ca8SHong Zhang   PetscFunctionReturn(0);
1624a4e85ca8SHong Zhang }
1625a4e85ca8SHong Zhang 
162624121865SAdrian 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.
162724121865SAdrian Maldonado */
162824121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
162924121865SAdrian Maldonado {
163024121865SAdrian Maldonado   PetscErrorCode ierr;
163124121865SAdrian Maldonado   PetscInt       i,size,dof;
163224121865SAdrian Maldonado   PetscInt       *glob2loc;
163324121865SAdrian Maldonado 
163424121865SAdrian Maldonado   PetscFunctionBegin;
163524121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
163624121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
163724121865SAdrian Maldonado 
163824121865SAdrian Maldonado   for (i = 0; i < size; i++) {
163924121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
164024121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
164124121865SAdrian Maldonado     glob2loc[i] = dof;
164224121865SAdrian Maldonado   }
164324121865SAdrian Maldonado 
164424121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
164524121865SAdrian Maldonado #if 0
164624121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
164724121865SAdrian Maldonado #endif
164824121865SAdrian Maldonado   PetscFunctionReturn(0);
164924121865SAdrian Maldonado }
165024121865SAdrian Maldonado 
165101ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
16529e1d080bSHong Zhang 
16539e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
16541ad426b7SHong Zhang {
16551ad426b7SHong Zhang   PetscErrorCode ierr;
16561ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
16579e1d080bSHong Zhang   PetscMPIInt    rank, size;
165824121865SAdrian Maldonado   PetscInt       eDof,vDof;
165924121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
16609e1d080bSHong Zhang   MPI_Comm       comm;
166124121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
166224121865SAdrian Maldonado 
16639e1d080bSHong Zhang   PetscFunctionBegin;
166424121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
166524121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
166624121865SAdrian Maldonado   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
166724121865SAdrian Maldonado 
166824121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
166924121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
167024121865SAdrian Maldonado 
167101ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
167224121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
167324121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
167424121865SAdrian Maldonado 
167501ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
167624121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
167724121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
167824121865SAdrian Maldonado 
167901ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
168024121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
168124121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
168224121865SAdrian Maldonado 
168301ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
168424121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
168524121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
168624121865SAdrian Maldonado 
16873f6a6bdaSHong Zhang   bA[0][0] = j11;
16883f6a6bdaSHong Zhang   bA[0][1] = j12;
16893f6a6bdaSHong Zhang   bA[1][0] = j21;
16903f6a6bdaSHong Zhang   bA[1][1] = j22;
169124121865SAdrian Maldonado 
169224121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
169324121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
169424121865SAdrian Maldonado 
169524121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
169624121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
169724121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
169824121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
169924121865SAdrian Maldonado 
170024121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
170124121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
170224121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
170324121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
170424121865SAdrian Maldonado 
170501ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
170624121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
170724121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
170824121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
170924121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
171024121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
171124121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
171224121865SAdrian Maldonado 
171324121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
171424121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17159e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
171624121865SAdrian Maldonado 
171724121865SAdrian Maldonado   /* Free structures */
171824121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
171924121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
172024121865SAdrian Maldonado   PetscFunctionReturn(0);
17219e1d080bSHong Zhang }
17229e1d080bSHong Zhang 
17239e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
17249e1d080bSHong Zhang {
17259e1d080bSHong Zhang   PetscErrorCode ierr;
17269e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
17279e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
17289e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
17299e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
17309e1d080bSHong Zhang   Mat            Juser;
17319e1d080bSHong Zhang   PetscSection   sectionGlobal;
17329e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
17339e1d080bSHong Zhang   const PetscInt *edges,*cone;
17349e1d080bSHong Zhang   MPI_Comm       comm;
17359e1d080bSHong Zhang   MatType        mtype;
17369e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
17379e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
17389e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
17399e1d080bSHong Zhang 
17409e1d080bSHong Zhang   PetscFunctionBegin;
17419e1d080bSHong Zhang   mtype = dm->mattype;
17429e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
17439e1d080bSHong Zhang   if (isNest) {
17449e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
17459e1d080bSHong Zhang     PetscFunctionReturn(0);
17469e1d080bSHong Zhang   }
17479e1d080bSHong Zhang 
17489e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
1749a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
17509e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
1751bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
17521ad426b7SHong Zhang     PetscFunctionReturn(0);
17531ad426b7SHong Zhang   }
17541ad426b7SHong Zhang 
1755bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
1756e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
1757bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
1758bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
17592a945128SHong Zhang 
17602a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
17612a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
176289898e50SHong Zhang 
176389898e50SHong Zhang   /* (1) Set matrix preallocation */
176489898e50SHong Zhang   /*------------------------------*/
1765840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1766840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
1767840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
1768840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
1769840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
1770840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
1771840c2264SHong Zhang 
177289898e50SHong Zhang   /* Set preallocation for edges */
177389898e50SHong Zhang   /*-----------------------------*/
1774840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
1775840c2264SHong Zhang 
1776bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
1777840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
1778840c2264SHong Zhang     /* Get row indices */
1779840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
1780840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
1781840c2264SHong Zhang     if (nrows) {
1782840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
1783840c2264SHong Zhang 
17845cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
1785d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1786840c2264SHong Zhang       for (v=0; v<2; v++) {
1787840c2264SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
1788840c2264SHong Zhang 
17898675203cSHong Zhang         if (network->Je) {
1790840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
17918675203cSHong Zhang         } else Juser = NULL;
1792840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
17935cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1794840c2264SHong Zhang       }
1795840c2264SHong Zhang 
179689898e50SHong Zhang       /* Set preallocation for edge self */
1797840c2264SHong Zhang       cstart = rstart;
17988675203cSHong Zhang       if (network->Je) {
1799840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
18008675203cSHong Zhang       } else Juser = NULL;
18015cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1802840c2264SHong Zhang     }
1803840c2264SHong Zhang   }
1804840c2264SHong Zhang 
180589898e50SHong Zhang   /* Set preallocation for vertices */
180689898e50SHong Zhang   /*--------------------------------*/
1807840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
18088675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
1809840c2264SHong Zhang 
1810840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
1811840c2264SHong Zhang     /* Get row indices */
1812840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1813840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
1814840c2264SHong Zhang     if (!nrows) continue;
1815840c2264SHong Zhang 
1816bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1817bdcb62a2SHong Zhang     if (ghost) {
1818bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1819bdcb62a2SHong Zhang     } else {
1820bdcb62a2SHong Zhang       rows_v = rows;
1821bdcb62a2SHong Zhang     }
1822bdcb62a2SHong Zhang 
1823bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1824840c2264SHong Zhang 
1825840c2264SHong Zhang     /* Get supporting edges and connected vertices */
1826840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1827840c2264SHong Zhang 
1828840c2264SHong Zhang     for (e=0; e<nedges; e++) {
1829840c2264SHong Zhang       /* Supporting edges */
1830840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1831840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1832840c2264SHong Zhang 
18338675203cSHong Zhang       if (network->Jv) {
1834840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
18358675203cSHong Zhang       } else Juser = NULL;
1836bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1837840c2264SHong Zhang 
1838840c2264SHong Zhang       /* Connected vertices */
1839d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
1840840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
1841840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
1842840c2264SHong Zhang 
1843840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1844840c2264SHong Zhang 
18458675203cSHong Zhang       if (network->Jv) {
1846840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
18478675203cSHong Zhang       } else Juser = NULL;
1848e102a522SHong Zhang       if (ghost_vc||ghost) {
1849e102a522SHong Zhang         ghost2 = PETSC_TRUE;
1850e102a522SHong Zhang       } else {
1851e102a522SHong Zhang         ghost2 = PETSC_FALSE;
1852e102a522SHong Zhang       }
1853e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
1854840c2264SHong Zhang     }
1855840c2264SHong Zhang 
185689898e50SHong Zhang     /* Set preallocation for vertex self */
1857840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1858840c2264SHong Zhang     if (!ghost) {
1859840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
18608675203cSHong Zhang       if (network->Jv) {
1861840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
18628675203cSHong Zhang       } else Juser = NULL;
1863bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1864840c2264SHong Zhang     }
1865bdcb62a2SHong Zhang     if (ghost) {
1866bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1867bdcb62a2SHong Zhang     }
1868840c2264SHong Zhang   }
1869840c2264SHong Zhang 
1870840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
1871840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
18725cf7da58SHong Zhang 
18735cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
18745cf7da58SHong Zhang 
18755cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
1876840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
1877840c2264SHong Zhang 
1878840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
1879840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
1880840c2264SHong Zhang   for (j=0; j<localSize; j++) {
1881e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
1882e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
1883840c2264SHong Zhang   }
1884840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
1885840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
1886840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
1887840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
1888840c2264SHong Zhang 
18895cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
18905cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
18915cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
18925cf7da58SHong Zhang 
18935cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
18945cf7da58SHong Zhang 
189589898e50SHong Zhang   /* (2) Set matrix entries for edges */
189689898e50SHong Zhang   /*----------------------------------*/
18971ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
1898bfbc38dcSHong Zhang     /* Get row indices */
18991ad426b7SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
190017df6e9eSHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
19014b976069SHong Zhang     if (nrows) {
190217df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
19031ad426b7SHong Zhang 
1904bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
1905d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1906bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
1907bfbc38dcSHong Zhang         ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr);
1908883e35e8SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
19093e97b6e8SHong Zhang 
19108675203cSHong Zhang         if (network->Je) {
1911a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
19128675203cSHong Zhang         } else Juser = NULL;
1913a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1914bfbc38dcSHong Zhang       }
191517df6e9eSHong Zhang 
1916bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
19173e97b6e8SHong Zhang       cstart = rstart;
19188675203cSHong Zhang       if (network->Je) {
1919a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
19208675203cSHong Zhang       } else Juser = NULL;
1921a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
19221ad426b7SHong Zhang     }
19234b976069SHong Zhang   }
19241ad426b7SHong Zhang 
1925bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
192683b2e829SHong Zhang   /*---------------------------------*/
19271ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
1928bfbc38dcSHong Zhang     /* Get row indices */
1929596e729fSHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1930596e729fSHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
19314b976069SHong Zhang     if (!nrows) continue;
1932596e729fSHong Zhang 
1933bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1934bdcb62a2SHong Zhang     if (ghost) {
1935bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1936bdcb62a2SHong Zhang     } else {
1937bdcb62a2SHong Zhang       rows_v = rows;
1938bdcb62a2SHong Zhang     }
1939bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1940596e729fSHong Zhang 
1941bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
1942596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1943596e729fSHong Zhang 
1944596e729fSHong Zhang     for (e=0; e<nedges; e++) {
1945bfbc38dcSHong Zhang       /* Supporting edges */
1946596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1947596e729fSHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1948596e729fSHong Zhang 
19498675203cSHong Zhang       if (network->Jv) {
1950a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
19518675203cSHong Zhang       } else Juser = NULL;
1952bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
1953596e729fSHong Zhang 
1954bfbc38dcSHong Zhang       /* Connected vertices */
1955d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
19562a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
19572a945128SHong Zhang 
195844aca652SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr);
195944aca652SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1960a4e85ca8SHong Zhang 
19618675203cSHong Zhang       if (network->Jv) {
1962a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
19638675203cSHong Zhang       } else Juser = NULL;
1964bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
1965596e729fSHong Zhang     }
1966596e729fSHong Zhang 
1967bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
19681ad426b7SHong Zhang     if (!ghost) {
1969596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
19708675203cSHong Zhang       if (network->Jv) {
1971a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
19728675203cSHong Zhang       } else Juser = NULL;
1973bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
1974bdcb62a2SHong Zhang     }
1975bdcb62a2SHong Zhang     if (ghost) {
1976bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1977bdcb62a2SHong Zhang     }
19781ad426b7SHong Zhang   }
1979a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
1980bdcb62a2SHong Zhang 
19811ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19821ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1983dd6f46cdSHong Zhang 
19845f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
19855f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19865f2c45f1SShri Abhyankar }
19875f2c45f1SShri Abhyankar 
19885f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
19895f2c45f1SShri Abhyankar {
19905f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19915f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19922727e31bSShri Abhyankar   PetscInt       j;
19935f2c45f1SShri Abhyankar 
19945f2c45f1SShri Abhyankar   PetscFunctionBegin;
19958415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
199683b2e829SHong Zhang   if (network->Je) {
199783b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
199883b2e829SHong Zhang   }
199983b2e829SHong Zhang   if (network->Jv) {
2000883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
200183b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
20021ad426b7SHong Zhang   }
200313c2a604SAdrian Maldonado 
200413c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
200513c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
200613c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2007f5427c60SHong Zhang   if (network->vltog) {
2008f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2009f5427c60SHong Zhang   }
201013c2a604SAdrian Maldonado   if (network->vertex.sf) {
201113c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
201213c2a604SAdrian Maldonado   }
201313c2a604SAdrian Maldonado   /* edge */
201413c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
201513c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
201613c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
201713c2a604SAdrian Maldonado   if (network->edge.sf) {
201813c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
201913c2a604SAdrian Maldonado   }
20205f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
20215f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
20225f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
202383b2e829SHong Zhang 
20242727e31bSShri Abhyankar   for(j=0; j<network->nsubnet; j++) {
20252727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
20262727e31bSShri Abhyankar   }
2027caf410d2SHong Zhang   ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr);
2028caf410d2SHong Zhang 
2029e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
20305f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
2031caf410d2SHong Zhang   ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
20325f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
20335f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20345f2c45f1SShri Abhyankar }
20355f2c45f1SShri Abhyankar 
20365f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
20375f2c45f1SShri Abhyankar {
20385f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20395f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
2040caf410d2SHong Zhang   PetscBool      iascii;
2041caf410d2SHong Zhang   PetscMPIInt    rank;
2042caf410d2SHong Zhang   PetscInt       p,nsubnet;
20435f2c45f1SShri Abhyankar 
20445f2c45f1SShri Abhyankar   PetscFunctionBegin;
2045caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2046caf410d2SHong Zhang   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
2047caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2048caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2049caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2050caf410d2SHong Zhang   if (iascii) {
2051caf410d2SHong Zhang     const PetscInt    *cone,*vtx,*edges;
2052caf410d2SHong Zhang     PetscInt          vfrom,vto,i,j,nv,ne;
2053caf410d2SHong Zhang 
2054caf410d2SHong Zhang     nsubnet = network->nsubnet - network->ncsubnet; /* num of subnetworks */
2055caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
2056caf410d2SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nsubnet: %D; nsubnetCouple: %D; nEdges: %D; nVertices: %D\n",rank,nsubnet,network->ncsubnet,network->nEdges,network->nVertices);CHKERRQ(ierr);
2057caf410d2SHong Zhang 
2058caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
2059caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2060caf410d2SHong Zhang       if (ne) {
2061caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2062caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2063caf410d2SHong Zhang           p = edges[j];
2064caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2065caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2066caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2067caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2068caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2069caf410d2SHong Zhang         }
2070caf410d2SHong Zhang       }
2071caf410d2SHong Zhang     }
2072caf410d2SHong Zhang     /* Coupling subnets */
2073caf410d2SHong Zhang     nsubnet = network->nsubnet;
2074caf410d2SHong Zhang     for (; i<nsubnet; i++) {
2075caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2076caf410d2SHong Zhang       if (ne) {
2077caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D (couple): nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2078caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2079caf410d2SHong Zhang           p = edges[j];
2080caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2081caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2082caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2083caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2084caf410d2SHong Zhang         }
2085caf410d2SHong Zhang       }
2086caf410d2SHong Zhang     }
2087caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2088caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2089caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
20905f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20915f2c45f1SShri Abhyankar }
20925f2c45f1SShri Abhyankar 
20935f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
20945f2c45f1SShri Abhyankar {
20955f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20965f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20975f2c45f1SShri Abhyankar 
20985f2c45f1SShri Abhyankar   PetscFunctionBegin;
20995f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
21005f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21015f2c45f1SShri Abhyankar }
21025f2c45f1SShri Abhyankar 
21035f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
21045f2c45f1SShri Abhyankar {
21055f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21065f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21075f2c45f1SShri Abhyankar 
21085f2c45f1SShri Abhyankar   PetscFunctionBegin;
21095f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
21105f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21115f2c45f1SShri Abhyankar }
21125f2c45f1SShri Abhyankar 
21135f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
21145f2c45f1SShri Abhyankar {
21155f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21165f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21175f2c45f1SShri Abhyankar 
21185f2c45f1SShri Abhyankar   PetscFunctionBegin;
21195f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
21205f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21215f2c45f1SShri Abhyankar }
21225f2c45f1SShri Abhyankar 
21235f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
21245f2c45f1SShri Abhyankar {
21255f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21265f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21275f2c45f1SShri Abhyankar 
21285f2c45f1SShri Abhyankar   PetscFunctionBegin;
21295f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
21305f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21315f2c45f1SShri Abhyankar }
213222bbedd7SHong Zhang 
213322bbedd7SHong Zhang /*@
2134b2aacc82SHong Zhang   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex globle index
213522bbedd7SHong Zhang 
213622bbedd7SHong Zhang   Not collective
213722bbedd7SHong Zhang 
213822bbedd7SHong Zhang   Input Parameters
213922bbedd7SHong Zhang + dm - the dm object
214022bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
214122bbedd7SHong Zhang 
214222bbedd7SHong Zhang   Output Parameters
214322bbedd7SHong Zhang +  vg  - global vertex ordering, start from 0
214422bbedd7SHong Zhang 
214522bbedd7SHong Zhang   Level: Advanced
214622bbedd7SHong Zhang 
214722bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
214822bbedd7SHong Zhang @*/
214922bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
215022bbedd7SHong Zhang {
215122bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
215222bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
215322bbedd7SHong Zhang 
215422bbedd7SHong Zhang   PetscFunctionBegin;
215522bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
215622bbedd7SHong Zhang   *vg = vltog[vloc];
215722bbedd7SHong Zhang   PetscFunctionReturn(0);
215822bbedd7SHong Zhang }
215922bbedd7SHong Zhang 
216022bbedd7SHong Zhang /*@
216122bbedd7SHong Zhang   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to globle map
216222bbedd7SHong Zhang 
216322bbedd7SHong Zhang   Collective
216422bbedd7SHong Zhang 
216522bbedd7SHong Zhang   Input Parameters:
216622bbedd7SHong Zhang + dm - the dm object
216722bbedd7SHong Zhang 
216822bbedd7SHong Zhang   Level: Advanced
216922bbedd7SHong Zhang 
217063029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
217122bbedd7SHong Zhang @*/
217222bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
217322bbedd7SHong Zhang {
217422bbedd7SHong Zhang   PetscErrorCode    ierr;
217522bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
217622bbedd7SHong Zhang   MPI_Comm          comm;
217763029d29SHong Zhang   PetscMPIInt       rank,size,*displs,*recvcounts,remoterank;
217822bbedd7SHong Zhang   PetscBool         ghost;
217963029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
218022bbedd7SHong Zhang   const PetscSFNode *iremote;
218122bbedd7SHong Zhang   PetscSF           vsf;
218263029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
218363029d29SHong Zhang   VecScatter        ctx;
218463029d29SHong Zhang   PetscScalar       *varr,val;
218563029d29SHong Zhang   const PetscScalar *varr_read;
218622bbedd7SHong Zhang 
218722bbedd7SHong Zhang   PetscFunctionBegin;
218822bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
218922bbedd7SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
219063029d29SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
219122bbedd7SHong Zhang 
219222bbedd7SHong Zhang   if (size == 1) {
219322bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
219422bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
219522bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
219622bbedd7SHong Zhang     network->vltog = vltog;
219722bbedd7SHong Zhang     PetscFunctionReturn(0);
219822bbedd7SHong Zhang   }
219922bbedd7SHong Zhang 
220022bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
220122bbedd7SHong Zhang   if (network->vltog) {
220222bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
220322bbedd7SHong Zhang   }
220422bbedd7SHong Zhang 
220522bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
220622bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
220722bbedd7SHong Zhang   vsf = network->vertex.sf;
220822bbedd7SHong Zhang 
220922bbedd7SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size+1,&displs,size,&recvcounts);CHKERRQ(ierr);
2210f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
221122bbedd7SHong Zhang 
221222bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
221322bbedd7SHong Zhang 
221422bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
221522bbedd7SHong Zhang   vrange[0] = 0;
221622bbedd7SHong Zhang   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRQ(ierr);
221767dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
221822bbedd7SHong Zhang 
221922bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
222022bbedd7SHong Zhang   network->vltog = vltog;
222122bbedd7SHong Zhang 
222263029d29SHong Zhang   /* Set vltog for non-ghost vertices */
222363029d29SHong Zhang   k = 0;
222422bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
222522bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
222663029d29SHong Zhang     if (ghost) continue;
222763029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
222822bbedd7SHong Zhang   }
2229f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
223063029d29SHong Zhang 
223163029d29SHong Zhang   /* Set vltog for ghost vertices */
223263029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
223363029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
223463029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
223563029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
223663029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
223763029d29SHong Zhang   for (i=0; i<nleaves; i++) {
223863029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
223963029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
224063029d29SHong Zhang   }
224163029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
224263029d29SHong Zhang 
224363029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
224463029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
224563029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
224663029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
224763029d29SHong Zhang 
224863029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
224963029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
225063029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
225163029d29SHong Zhang   for (i=0; i<N; i+=2) {
22522e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
225363029d29SHong Zhang     if (remoterank == rank) {
225463029d29SHong Zhang       k = i+1; /* row number */
22552e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
225663029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
225763029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
225863029d29SHong Zhang     }
225963029d29SHong Zhang   }
226063029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
226163029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
226263029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
226363029d29SHong Zhang 
226463029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
226563029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
226663029d29SHong Zhang   k = 0;
226763029d29SHong Zhang   for (i=0; i<nroots; i++) {
226863029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
226963029d29SHong Zhang     if (!ghost) continue;
22702e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
227163029d29SHong Zhang   }
227263029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
227363029d29SHong Zhang 
227463029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
227563029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
227663029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
227722bbedd7SHong Zhang   PetscFunctionReturn(0);
227822bbedd7SHong Zhang }
2279