xref: /petsc/src/dm/impls/network/network.c (revision 97bb938e2a78cbcdb3296bd3f08e49b1b87cdbbe)
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 /*@
2672c3e9f7SHong Zhang   DMNetworkGetSizes - Gets the the number of subnetworks and coupling subnetworks
2772c3e9f7SHong Zhang 
2872c3e9f7SHong Zhang   Collective on dm
2972c3e9f7SHong Zhang 
3072c3e9f7SHong Zhang   Input Parameters:
3172c3e9f7SHong Zhang + dm - the dm object
3272c3e9f7SHong Zhang . Nsubnet - global number of subnetworks
3372c3e9f7SHong Zhang - NsubnetCouple - global number of coupling subnetworks
3472c3e9f7SHong Zhang 
35*97bb938eSShri Abhyankar   Level: beginner
3672c3e9f7SHong Zhang 
3772c3e9f7SHong Zhang .seealso: DMNetworkCreate()
3872c3e9f7SHong Zhang @*/
3972c3e9f7SHong Zhang PetscErrorCode DMNetworkGetSizes(DM netdm, PetscInt *Nsubnet, PetscInt *Ncsubnet)
4072c3e9f7SHong Zhang {
4172c3e9f7SHong Zhang   DM_Network *network = (DM_Network*) netdm->data;
4272c3e9f7SHong Zhang 
4372c3e9f7SHong Zhang   PetscFunctionBegin;
4472c3e9f7SHong Zhang   *Nsubnet = network->nsubnet;
4572c3e9f7SHong Zhang   *Ncsubnet = network->ncsubnet;
4672c3e9f7SHong Zhang   PetscFunctionReturn(0);
4772c3e9f7SHong Zhang }
4872c3e9f7SHong Zhang 
4972c3e9f7SHong 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 
64*97bb938eSShri Abhyankar    Level: beginner
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 
149*97bb938eSShri Abhyankar   Level: beginner
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;
17072c3e9f7SHong Zhang   PetscInt   i;
1715f2c45f1SShri Abhyankar 
1725f2c45f1SShri Abhyankar   PetscFunctionBegin;
17372c3e9f7SHong Zhang   for (i=0; i < (network->nsubnet-network->ncsubnet); i++) network->subnet[i].edgelist = edgelist[i];
17472c3e9f7SHong Zhang   if (network->ncsubnet) {
17572c3e9f7SHong Zhang     PetscInt j = 0;
17672c3e9f7SHong Zhang     if (!edgelistCouple) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Must provide edgelist_couple");
17772c3e9f7SHong 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 
1877a7aea1fSJed Brown   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 
196*97bb938eSShri Abhyankar   Level: beginner
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;
23472c3e9f7SHong 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;
3349988b915SShri Abhyankar       network->header[i].offsetvarrel[0] = 0;
335caf410d2SHong Zhang       i++;
336caf410d2SHong Zhang     }
337caf410d2SHong Zhang     if (i >= network->subnet[j].eEnd) j++;
338caf410d2SHong Zhang   }
339caf410d2SHong Zhang 
340caf410d2SHong Zhang   /* Count network->subnet[*].nvtx */
341caf410d2SHong Zhang   for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */
342caf410d2SHong Zhang     k = vidxlTog[i-vStart];
343caf410d2SHong Zhang     for (j=0; j < network->nsubnet; j++) {
344caf410d2SHong Zhang       if (network->subnet[j].vStart <= k && k < network->subnet[j].vEnd) {
345caf410d2SHong Zhang         network->subnet[j].nvtx++;
3466500d4abSHong Zhang         break;
3476500d4abSHong Zhang       }
3486500d4abSHong Zhang     }
3496500d4abSHong Zhang   }
3506500d4abSHong Zhang 
351caf410d2SHong Zhang   /* Set network->subnet[*].vertices on array network->subnetvtx */
352caf410d2SHong Zhang   subnetvtx = network->subnetvtx;
3536500d4abSHong Zhang   for (j=0; j<network->nsubnet; j++) {
354caf410d2SHong Zhang     network->subnet[j].vertices = subnetvtx;
355caf410d2SHong Zhang     subnetvtx                  += network->subnet[j].nvtx;
356caf410d2SHong Zhang     network->subnet[j].nvtx = 0;
357caf410d2SHong Zhang   }
358caf410d2SHong Zhang 
359caf410d2SHong Zhang   /* Set vertex array for the subnetworks */
360caf410d2SHong Zhang   for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */
361caf410d2SHong Zhang     network->header[i].index = vidxlTog[i-vStart]; /*  Global vertex index */
362caf410d2SHong Zhang 
363caf410d2SHong Zhang     k = vidxlTog[i-vStart];
364caf410d2SHong Zhang     for (j=0; j < network->nsubnet; j++) {
365caf410d2SHong Zhang       if (network->subnet[j].vStart <= k && k < network->subnet[j].vEnd) {
3666500d4abSHong Zhang         network->header[i].subnetid = j;
3676500d4abSHong Zhang         network->subnet[j].vertices[network->subnet[j].nvtx++] = i;
3686500d4abSHong Zhang         break;
3696500d4abSHong Zhang       }
3706500d4abSHong Zhang     }
371caf410d2SHong Zhang 
3726500d4abSHong Zhang     network->header[i].ndata = 0;
3736500d4abSHong Zhang     ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
374caf410d2SHong Zhang     network->header[i].offset[0] = 0;
3759988b915SShri Abhyankar     network->header[i].offsetvarrel[0] = 0;
3766500d4abSHong Zhang   }
3776500d4abSHong Zhang 
378caf410d2SHong Zhang   ierr = PetscFree2(vidxlTog,eowners);CHKERRQ(ierr);
3795f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
3805f2c45f1SShri Abhyankar }
3815f2c45f1SShri Abhyankar 
38294ef8ddeSSatish Balay /*@C
3832727e31bSShri Abhyankar   DMNetworkGetSubnetworkInfo - Returns the info for the subnetwork
3842727e31bSShri Abhyankar 
3857a7aea1fSJed Brown   Input Parameters:
386caf410d2SHong Zhang + dm - the DM object
3872727e31bSShri Abhyankar - id   - the ID (integer) of the subnetwork
3882727e31bSShri Abhyankar 
3897a7aea1fSJed Brown   Output Parameters:
3902727e31bSShri Abhyankar + nv    - number of vertices (local)
3912727e31bSShri Abhyankar . ne    - number of edges (local)
3922727e31bSShri Abhyankar . vtx   - local vertices for this subnetwork
393a2b725a8SWilliam Gropp - edge  - local edges for this subnetwork
3942727e31bSShri Abhyankar 
3952727e31bSShri Abhyankar   Notes:
3962727e31bSShri Abhyankar   Cannot call this routine before DMNetworkLayoutSetup()
3972727e31bSShri Abhyankar 
39806dd6b0eSSatish Balay   Level: intermediate
39906dd6b0eSSatish Balay 
4002727e31bSShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
4012727e31bSShri Abhyankar @*/
402caf410d2SHong Zhang PetscErrorCode DMNetworkGetSubnetworkInfo(DM dm,PetscInt id,PetscInt *nv, PetscInt *ne,const PetscInt **vtx, const PetscInt **edge)
4032727e31bSShri Abhyankar {
404caf410d2SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
4052727e31bSShri Abhyankar 
4062727e31bSShri Abhyankar   PetscFunctionBegin;
40772c3e9f7SHong 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);
4082727e31bSShri Abhyankar   *nv   = network->subnet[id].nvtx;
4092727e31bSShri Abhyankar   *ne   = network->subnet[id].nedge;
4102727e31bSShri Abhyankar   *vtx  = network->subnet[id].vertices;
4112727e31bSShri Abhyankar   *edge = network->subnet[id].edges;
4122727e31bSShri Abhyankar   PetscFunctionReturn(0);
4132727e31bSShri Abhyankar }
4142727e31bSShri Abhyankar 
4152727e31bSShri Abhyankar /*@C
416caf410d2SHong Zhang   DMNetworkGetSubnetworkCoupleInfo - Returns the info for the coupling subnetwork
417caf410d2SHong Zhang 
4187a7aea1fSJed Brown   Input Parameters:
419caf410d2SHong Zhang + dm - the DM object
420caf410d2SHong Zhang - id   - the ID (integer) of the coupling subnetwork
421caf410d2SHong Zhang 
4227a7aea1fSJed Brown   Output Parameters:
423caf410d2SHong Zhang + ne - number of edges (local)
424caf410d2SHong Zhang - edge  - local edges for this coupling subnetwork
425caf410d2SHong Zhang 
426caf410d2SHong Zhang   Notes:
427caf410d2SHong Zhang   Cannot call this routine before DMNetworkLayoutSetup()
428caf410d2SHong Zhang 
429caf410d2SHong Zhang   Level: intermediate
430caf410d2SHong Zhang 
431caf410d2SHong Zhang .seealso: DMNetworkGetSubnetworkInfo, DMNetworkLayoutSetUp, DMNetworkCreate
432caf410d2SHong Zhang @*/
433caf410d2SHong Zhang PetscErrorCode DMNetworkGetSubnetworkCoupleInfo(DM dm,PetscInt id,PetscInt *ne,const PetscInt **edge)
434caf410d2SHong Zhang {
435caf410d2SHong Zhang   DM_Network *net = (DM_Network*)dm->data;
43672c3e9f7SHong Zhang   PetscInt   id1;
437caf410d2SHong Zhang 
438caf410d2SHong Zhang   PetscFunctionBegin;
43972c3e9f7SHong Zhang   if (net->ncsubnet) {
44072c3e9f7SHong 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);
44172c3e9f7SHong Zhang 
44272c3e9f7SHong Zhang     id1   = id + net->nsubnet - net->ncsubnet;
443caf410d2SHong Zhang     *ne   = net->subnet[id1].nedge;
444caf410d2SHong Zhang     *edge = net->subnet[id1].edges;
44572c3e9f7SHong Zhang   } else {
44672c3e9f7SHong Zhang     *ne   = 0;
44772c3e9f7SHong Zhang     *edge = NULL;
44872c3e9f7SHong Zhang   }
449caf410d2SHong Zhang   PetscFunctionReturn(0);
450caf410d2SHong Zhang }
451caf410d2SHong Zhang 
452caf410d2SHong Zhang /*@C
4535f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
4545f2c45f1SShri Abhyankar 
455d083f849SBarry Smith   Logically collective on dm
4565f2c45f1SShri Abhyankar 
4577a7aea1fSJed Brown   Input Parameters:
4585f2c45f1SShri Abhyankar + dm   - the network object
4595f2c45f1SShri Abhyankar . name - the component name
4605f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
4615f2c45f1SShri Abhyankar 
4627a7aea1fSJed Brown    Output Parameters:
4635f2c45f1SShri Abhyankar .   key - an integer key that defines the component
4645f2c45f1SShri Abhyankar 
4655f2c45f1SShri Abhyankar    Notes
4665f2c45f1SShri Abhyankar    This routine should be called by all processors before calling DMNetworkLayoutSetup().
4675f2c45f1SShri Abhyankar 
468*97bb938eSShri Abhyankar    Level: beginner
4695f2c45f1SShri Abhyankar 
4705f2c45f1SShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
4715f2c45f1SShri Abhyankar @*/
472caf410d2SHong Zhang PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key)
4735f2c45f1SShri Abhyankar {
4745f2c45f1SShri Abhyankar   PetscErrorCode        ierr;
4755f2c45f1SShri Abhyankar   DM_Network            *network = (DM_Network*) dm->data;
4765f2c45f1SShri Abhyankar   DMNetworkComponent    *component=&network->component[network->ncomponent];
4775f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
4785f2c45f1SShri Abhyankar   PetscInt              i;
4795f2c45f1SShri Abhyankar 
4805f2c45f1SShri Abhyankar   PetscFunctionBegin;
4815f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
4825f2c45f1SShri Abhyankar     ierr = PetscStrcmp(component->name,name,&flg);CHKERRQ(ierr);
4835f2c45f1SShri Abhyankar     if (flg) {
4845f2c45f1SShri Abhyankar       *key = i;
4855f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
4865f2c45f1SShri Abhyankar     }
4876d64e262SShri Abhyankar   }
4886d64e262SShri Abhyankar   if(network->ncomponent == MAX_COMPONENTS) {
4896d64e262SShri Abhyankar     SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components registered exceeds the max %D",MAX_COMPONENTS);
4905f2c45f1SShri Abhyankar   }
4915f2c45f1SShri Abhyankar 
4925f2c45f1SShri Abhyankar   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
4935f2c45f1SShri Abhyankar   component->size = size/sizeof(DMNetworkComponentGenericDataType);
4945f2c45f1SShri Abhyankar   *key = network->ncomponent;
4955f2c45f1SShri Abhyankar   network->ncomponent++;
4965f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
4975f2c45f1SShri Abhyankar }
4985f2c45f1SShri Abhyankar 
4995f2c45f1SShri Abhyankar /*@
5005f2c45f1SShri Abhyankar   DMNetworkGetVertexRange - Get the bounds [start, end) for the vertices.
5015f2c45f1SShri Abhyankar 
5025f2c45f1SShri Abhyankar   Not Collective
5035f2c45f1SShri Abhyankar 
5045f2c45f1SShri Abhyankar   Input Parameters:
505a2b725a8SWilliam Gropp . dm - The DMNetwork object
5065f2c45f1SShri Abhyankar 
507fd292e60Sprj-   Output Parameters:
5085f2c45f1SShri Abhyankar + vStart - The first vertex point
5095f2c45f1SShri Abhyankar - vEnd   - One beyond the last vertex point
5105f2c45f1SShri Abhyankar 
511*97bb938eSShri Abhyankar   Level: beginner
5125f2c45f1SShri Abhyankar 
5135f2c45f1SShri Abhyankar .seealso: DMNetworkGetEdgeRange
5145f2c45f1SShri Abhyankar @*/
5155f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
5165f2c45f1SShri Abhyankar {
5175f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
5185f2c45f1SShri Abhyankar 
5195f2c45f1SShri Abhyankar   PetscFunctionBegin;
5205f2c45f1SShri Abhyankar   if (vStart) *vStart = network->vStart;
5215f2c45f1SShri Abhyankar   if (vEnd) *vEnd = network->vEnd;
5225f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5235f2c45f1SShri Abhyankar }
5245f2c45f1SShri Abhyankar 
5255f2c45f1SShri Abhyankar /*@
5265f2c45f1SShri Abhyankar   DMNetworkGetEdgeRange - Get the bounds [start, end) for the edges.
5275f2c45f1SShri Abhyankar 
5285f2c45f1SShri Abhyankar   Not Collective
5295f2c45f1SShri Abhyankar 
5305f2c45f1SShri Abhyankar   Input Parameters:
531a2b725a8SWilliam Gropp . dm - The DMNetwork object
5325f2c45f1SShri Abhyankar 
533fd292e60Sprj-   Output Parameters:
5345f2c45f1SShri Abhyankar + eStart - The first edge point
5355f2c45f1SShri Abhyankar - eEnd   - One beyond the last edge point
5365f2c45f1SShri Abhyankar 
537*97bb938eSShri Abhyankar   Level: beginner
5385f2c45f1SShri Abhyankar 
5395f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange
5405f2c45f1SShri Abhyankar @*/
5415f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
5425f2c45f1SShri Abhyankar {
5435f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
5445f2c45f1SShri Abhyankar 
5455f2c45f1SShri Abhyankar   PetscFunctionBegin;
5465f2c45f1SShri Abhyankar   if (eStart) *eStart = network->eStart;
5475f2c45f1SShri Abhyankar   if (eEnd) *eEnd = network->eEnd;
5485f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5495f2c45f1SShri Abhyankar }
5505f2c45f1SShri Abhyankar 
5517b6afd5bSHong Zhang /*@
552e85e6aecSHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the user global numbering for the edge.
5537b6afd5bSHong Zhang 
5547b6afd5bSHong Zhang   Not Collective
5557b6afd5bSHong Zhang 
5567b6afd5bSHong Zhang   Input Parameters:
5577b6afd5bSHong Zhang + dm - DMNetwork object
558e85e6aecSHong Zhang - p  - edge point
5597b6afd5bSHong Zhang 
560fd292e60Sprj-   Output Parameters:
561e85e6aecSHong Zhang . index - user global numbering for the edge
5627b6afd5bSHong Zhang 
5637b6afd5bSHong Zhang   Level: intermediate
5647b6afd5bSHong Zhang 
565e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalVertexIndex
5667b6afd5bSHong Zhang @*/
567e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
5687b6afd5bSHong Zhang {
5697b6afd5bSHong Zhang   PetscErrorCode    ierr;
5707b6afd5bSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
5717b6afd5bSHong Zhang   PetscInt          offsetp;
5727b6afd5bSHong Zhang   DMNetworkComponentHeader header;
5737b6afd5bSHong Zhang 
5747b6afd5bSHong Zhang   PetscFunctionBegin;
575caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
5767b6afd5bSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
5777b6afd5bSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
578e85e6aecSHong Zhang   *index = header->index;
5797b6afd5bSHong Zhang   PetscFunctionReturn(0);
5807b6afd5bSHong Zhang }
5817b6afd5bSHong Zhang 
5825f2c45f1SShri Abhyankar /*@
583e85e6aecSHong Zhang   DMNetworkGetGlobalVertexIndex - Get the user global numbering for the vertex.
584e85e6aecSHong Zhang 
585e85e6aecSHong Zhang   Not Collective
586e85e6aecSHong Zhang 
587e85e6aecSHong Zhang   Input Parameters:
588e85e6aecSHong Zhang + dm - DMNetwork object
589e85e6aecSHong Zhang - p  - vertex point
590e85e6aecSHong Zhang 
591fd292e60Sprj-   Output Parameters:
592e85e6aecSHong Zhang . index - user global numbering for the vertex
593e85e6aecSHong Zhang 
594e85e6aecSHong Zhang   Level: intermediate
595e85e6aecSHong Zhang 
596e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalEdgeIndex
597e85e6aecSHong Zhang @*/
598e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
599e85e6aecSHong Zhang {
600e85e6aecSHong Zhang   PetscErrorCode    ierr;
601e85e6aecSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
602e85e6aecSHong Zhang   PetscInt          offsetp;
603e85e6aecSHong Zhang   DMNetworkComponentHeader header;
604e85e6aecSHong Zhang 
605e85e6aecSHong Zhang   PetscFunctionBegin;
606caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
607e85e6aecSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
608e85e6aecSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
609e85e6aecSHong Zhang   *index = header->index;
610e85e6aecSHong Zhang   PetscFunctionReturn(0);
611e85e6aecSHong Zhang }
612e85e6aecSHong Zhang 
613c3b11c7cSShri Abhyankar /*
614c3b11c7cSShri Abhyankar   DMNetworkGetComponentKeyOffset - Gets the type along with the offset for indexing the
615c3b11c7cSShri Abhyankar                                     component value from the component data array
616c3b11c7cSShri Abhyankar 
617c3b11c7cSShri Abhyankar   Not Collective
618c3b11c7cSShri Abhyankar 
619c3b11c7cSShri Abhyankar   Input Parameters:
620c3b11c7cSShri Abhyankar + dm      - The DMNetwork object
621c3b11c7cSShri Abhyankar . p       - vertex/edge point
622c3b11c7cSShri Abhyankar - compnum - component number
623c3b11c7cSShri Abhyankar 
624c3b11c7cSShri Abhyankar   Output Parameters:
625c3b11c7cSShri Abhyankar + compkey - the key obtained when registering the component
626c3b11c7cSShri Abhyankar - offset  - offset into the component data array associated with the vertex/edge point
627c3b11c7cSShri Abhyankar 
628c3b11c7cSShri Abhyankar   Notes:
629c3b11c7cSShri Abhyankar   Typical usage:
630c3b11c7cSShri Abhyankar 
631c3b11c7cSShri Abhyankar   DMNetworkGetComponentDataArray(dm, &arr);
632c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
633c3b11c7cSShri Abhyankar   Loop over vertices or edges
634c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
635c3b11c7cSShri Abhyankar     Loop over numcomps
636c3b11c7cSShri Abhyankar       DMNetworkGetComponentKeyOffset(dm,v,compnum,&key,&offset);
637c3b11c7cSShri Abhyankar       compdata = (UserCompDataType)(arr+offset);
638c3b11c7cSShri Abhyankar 
639c3b11c7cSShri Abhyankar   Level: intermediate
640c3b11c7cSShri Abhyankar 
641c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray,
642c3b11c7cSShri Abhyankar */
643c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponentKeyOffset(DM dm,PetscInt p, PetscInt compnum, PetscInt *compkey, PetscInt *offset)
644c3b11c7cSShri Abhyankar {
645c3b11c7cSShri Abhyankar   PetscErrorCode           ierr;
646c3b11c7cSShri Abhyankar   PetscInt                 offsetp;
647c3b11c7cSShri Abhyankar   DMNetworkComponentHeader header;
648c3b11c7cSShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
649c3b11c7cSShri Abhyankar 
650c3b11c7cSShri Abhyankar   PetscFunctionBegin;
651c3b11c7cSShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
652c3b11c7cSShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
653c3b11c7cSShri Abhyankar   if (compkey) *compkey = header->key[compnum];
654c3b11c7cSShri Abhyankar   if (offset) *offset  = offsetp+network->dataheadersize+header->offset[compnum];
655c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
656c3b11c7cSShri Abhyankar }
657c3b11c7cSShri Abhyankar 
658c3b11c7cSShri Abhyankar /*@
659c3b11c7cSShri Abhyankar   DMNetworkGetComponent - Returns the network component and its key
660c3b11c7cSShri Abhyankar 
661c3b11c7cSShri Abhyankar   Not Collective
662c3b11c7cSShri Abhyankar 
6637a7aea1fSJed Brown   Input Parameters:
664c3b11c7cSShri Abhyankar + dm - DMNetwork object
665c3b11c7cSShri Abhyankar . p  - edge or vertex point
666c3b11c7cSShri Abhyankar - compnum - component number
667c3b11c7cSShri Abhyankar 
668c3b11c7cSShri Abhyankar   Output Parameters:
669c3b11c7cSShri Abhyankar + compkey - the key set for this computing during registration
670c3b11c7cSShri Abhyankar - component - the component data
671c3b11c7cSShri Abhyankar 
672c3b11c7cSShri Abhyankar   Notes:
673c3b11c7cSShri Abhyankar   Typical usage:
674c3b11c7cSShri Abhyankar 
675c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
676c3b11c7cSShri Abhyankar   Loop over vertices or edges
677c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
678c3b11c7cSShri Abhyankar     Loop over numcomps
679c3b11c7cSShri Abhyankar       DMNetworkGetComponent(dm,v,compnum,&key,&component);
680c3b11c7cSShri Abhyankar 
681*97bb938eSShri Abhyankar   Level: beginner
682c3b11c7cSShri Abhyankar 
683c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetVariableOffset
684c3b11c7cSShri Abhyankar @*/
685c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponent(DM dm, PetscInt p, PetscInt compnum, PetscInt *key, void **component)
686c3b11c7cSShri Abhyankar {
687c3b11c7cSShri Abhyankar   PetscErrorCode ierr;
688c3b11c7cSShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
689e108cb99SStefano Zampini   PetscInt       offsetd = 0;
690c3b11c7cSShri Abhyankar 
691c3b11c7cSShri Abhyankar   PetscFunctionBegin;
692c3b11c7cSShri Abhyankar   ierr = DMNetworkGetComponentKeyOffset(dm,p,compnum,key,&offsetd);CHKERRQ(ierr);
693c3b11c7cSShri Abhyankar   *component = network->componentdataarray+offsetd;
694c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
695c3b11c7cSShri Abhyankar }
696c3b11c7cSShri Abhyankar 
697e85e6aecSHong Zhang /*@
698325661f6SSatish Balay   DMNetworkAddComponent - Adds a network component at the given point (vertex/edge)
6995f2c45f1SShri Abhyankar 
7005f2c45f1SShri Abhyankar   Not Collective
7015f2c45f1SShri Abhyankar 
7025f2c45f1SShri Abhyankar   Input Parameters:
7035f2c45f1SShri Abhyankar + dm           - The DMNetwork object
7045f2c45f1SShri Abhyankar . p            - vertex/edge point
7055f2c45f1SShri Abhyankar . componentkey - component key returned while registering the component
7065f2c45f1SShri Abhyankar - compvalue    - pointer to the data structure for the component
7075f2c45f1SShri Abhyankar 
708*97bb938eSShri Abhyankar   Level: beginner
7095f2c45f1SShri Abhyankar 
7105f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange, DMNetworkGetEdgeRange, DMNetworkRegisterComponent
7115f2c45f1SShri Abhyankar @*/
7125f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p,PetscInt componentkey,void* compvalue)
7135f2c45f1SShri Abhyankar {
7145f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
71543a39a44SBarry Smith   DMNetworkComponent       *component = &network->component[componentkey];
7165f2c45f1SShri Abhyankar   DMNetworkComponentHeader header = &network->header[p];
7175f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue = &network->cvalue[p];
7185f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
7195f2c45f1SShri Abhyankar 
7205f2c45f1SShri Abhyankar   PetscFunctionBegin;
721fa58f0a9SHong 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);
722fa58f0a9SHong Zhang 
72343a39a44SBarry Smith   header->size[header->ndata] = component->size;
72443a39a44SBarry Smith   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
7255f2c45f1SShri Abhyankar   header->key[header->ndata] = componentkey;
7265f2c45f1SShri Abhyankar   if (header->ndata != 0) header->offset[header->ndata] = header->offset[header->ndata-1] + header->size[header->ndata-1];
7279988b915SShri Abhyankar   header->nvar[header->ndata] = 0;
7285f2c45f1SShri Abhyankar 
7295f2c45f1SShri Abhyankar   cvalue->data[header->ndata] = (void*)compvalue;
7305f2c45f1SShri Abhyankar   header->ndata++;
7315f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7325f2c45f1SShri Abhyankar }
7335f2c45f1SShri Abhyankar 
7345f2c45f1SShri Abhyankar /*@
7359988b915SShri Abhyankar   DMNetworkSetComponentNumVariables - Sets the number of variables for a component
7369988b915SShri Abhyankar 
7379988b915SShri Abhyankar   Not Collective
7389988b915SShri Abhyankar 
7399988b915SShri Abhyankar   Input Parameters:
7409988b915SShri Abhyankar + dm           - The DMNetwork object
7419988b915SShri Abhyankar . p            - vertex/edge point
7429988b915SShri Abhyankar . compnum      - component number (First component added = 0, second = 1, ...)
7439988b915SShri Abhyankar - nvar         - number of variables for the component
7449988b915SShri Abhyankar 
745*97bb938eSShri Abhyankar   Level: beginner
7469988b915SShri Abhyankar 
7479dacc45bSShrirang Abhyankar .seealso: DMNetworkAddComponent(), DMNetworkGetNumComponents(),DMNetworkRegisterComponent()
7489988b915SShri Abhyankar @*/
7499988b915SShri Abhyankar PetscErrorCode DMNetworkSetComponentNumVariables(DM dm, PetscInt p,PetscInt compnum,PetscInt nvar)
7509988b915SShri Abhyankar {
7519988b915SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
7529988b915SShri Abhyankar   DMNetworkComponentHeader header = &network->header[p];
7539988b915SShri Abhyankar   PetscErrorCode           ierr;
7549988b915SShri Abhyankar 
7559988b915SShri Abhyankar   PetscFunctionBegin;
7569988b915SShri Abhyankar   ierr = DMNetworkAddNumVariables(dm,p,nvar);CHKERRQ(ierr);
7579988b915SShri Abhyankar   header->nvar[compnum] = nvar;
7589988b915SShri Abhyankar   if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum-1] + header->nvar[compnum-1];
7599988b915SShri Abhyankar   PetscFunctionReturn(0);
7609988b915SShri Abhyankar }
7619988b915SShri Abhyankar 
7629988b915SShri Abhyankar /*@
7635f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
7645f2c45f1SShri Abhyankar 
7655f2c45f1SShri Abhyankar   Not Collective
7665f2c45f1SShri Abhyankar 
7675f2c45f1SShri Abhyankar   Input Parameters:
7685f2c45f1SShri Abhyankar + dm - The DMNetwork object
769a2b725a8SWilliam Gropp - p  - vertex/edge point
7705f2c45f1SShri Abhyankar 
7715f2c45f1SShri Abhyankar   Output Parameters:
7725f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
7735f2c45f1SShri Abhyankar 
774*97bb938eSShri Abhyankar   Level: beginner
7755f2c45f1SShri Abhyankar 
7765f2c45f1SShri Abhyankar .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent
7775f2c45f1SShri Abhyankar @*/
7785f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
7795f2c45f1SShri Abhyankar {
7805f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7815f2c45f1SShri Abhyankar   PetscInt       offset;
7825f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7835f2c45f1SShri Abhyankar 
7845f2c45f1SShri Abhyankar   PetscFunctionBegin;
7855f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
7865f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
7875f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7885f2c45f1SShri Abhyankar }
7895f2c45f1SShri Abhyankar 
7905f2c45f1SShri Abhyankar /*@
7915f2c45f1SShri Abhyankar   DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector.
7925f2c45f1SShri Abhyankar 
7935f2c45f1SShri Abhyankar   Not Collective
7945f2c45f1SShri Abhyankar 
7955f2c45f1SShri Abhyankar   Input Parameters:
7965f2c45f1SShri Abhyankar + dm     - The DMNetwork object
7975f2c45f1SShri Abhyankar - p      - the edge/vertex point
7985f2c45f1SShri Abhyankar 
7995f2c45f1SShri Abhyankar   Output Parameters:
8005f2c45f1SShri Abhyankar . offset - the offset
8015f2c45f1SShri Abhyankar 
802*97bb938eSShri Abhyankar   Level: beginner
8035f2c45f1SShri Abhyankar 
8045f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
8055f2c45f1SShri Abhyankar @*/
8065f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset)
8075f2c45f1SShri Abhyankar {
8085f2c45f1SShri Abhyankar   PetscErrorCode ierr;
8095f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8105f2c45f1SShri Abhyankar 
8115f2c45f1SShri Abhyankar   PetscFunctionBegin;
8121bb6d2a8SBarry Smith   ierr = PetscSectionGetOffset(network->plex->localSection,p,offset);CHKERRQ(ierr);
8135f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8145f2c45f1SShri Abhyankar }
8155f2c45f1SShri Abhyankar 
8165f2c45f1SShri Abhyankar /*@
8175f2c45f1SShri Abhyankar   DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector.
8185f2c45f1SShri Abhyankar 
8195f2c45f1SShri Abhyankar   Not Collective
8205f2c45f1SShri Abhyankar 
8215f2c45f1SShri Abhyankar   Input Parameters:
8225f2c45f1SShri Abhyankar + dm      - The DMNetwork object
8235f2c45f1SShri Abhyankar - p       - the edge/vertex point
8245f2c45f1SShri Abhyankar 
8255f2c45f1SShri Abhyankar   Output Parameters:
8265f2c45f1SShri Abhyankar . offsetg - the offset
8275f2c45f1SShri Abhyankar 
828*97bb938eSShri Abhyankar   Level: beginner
8295f2c45f1SShri Abhyankar 
8305f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableOffset, DMGetLocalVector
8315f2c45f1SShri Abhyankar @*/
8325f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg)
8335f2c45f1SShri Abhyankar {
8345f2c45f1SShri Abhyankar   PetscErrorCode ierr;
8355f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8365f2c45f1SShri Abhyankar 
8375f2c45f1SShri Abhyankar   PetscFunctionBegin;
8381bb6d2a8SBarry Smith   ierr = PetscSectionGetOffset(network->plex->globalSection,p,offsetg);CHKERRQ(ierr);
8396fefedf4SHong Zhang   if (*offsetg < 0) *offsetg = -(*offsetg + 1); /* Convert to actual global offset for ghost vertex */
8405f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8415f2c45f1SShri Abhyankar }
8425f2c45f1SShri Abhyankar 
84324121865SAdrian Maldonado /*@
8449988b915SShri Abhyankar   DMNetworkGetComponentVariableOffset - Get the offset for accessing the variable associated with a component for the given vertex/edge from the local vector.
8459988b915SShri Abhyankar 
8469988b915SShri Abhyankar   Not Collective
8479988b915SShri Abhyankar 
8489988b915SShri Abhyankar   Input Parameters:
8499988b915SShri Abhyankar + dm     - The DMNetwork object
8509988b915SShri Abhyankar . compnum - component number
8519988b915SShri Abhyankar - p      - the edge/vertex point
8529988b915SShri Abhyankar 
8539988b915SShri Abhyankar   Output Parameters:
8549988b915SShri Abhyankar . offset - the offset
8559988b915SShri Abhyankar 
8569988b915SShri Abhyankar   Level: intermediate
8579988b915SShri Abhyankar 
8589dacc45bSShrirang Abhyankar .seealso: DMNetworkGetVariableGlobalOffset(), DMGetLocalVector(), DMNetworkSetComponentNumVariables()
8599988b915SShri Abhyankar @*/
8609988b915SShri Abhyankar PetscErrorCode DMNetworkGetComponentVariableOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offset)
8619988b915SShri Abhyankar {
8629988b915SShri Abhyankar   PetscErrorCode ierr;
8639988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8649988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
8659988b915SShri Abhyankar   DMNetworkComponentHeader header;
8669988b915SShri Abhyankar 
8679988b915SShri Abhyankar   PetscFunctionBegin;
8689988b915SShri Abhyankar   ierr = DMNetworkGetVariableOffset(dm,p,&offsetp);CHKERRQ(ierr);
8699988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
8709988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
8719988b915SShri Abhyankar   *offset = offsetp + header->offsetvarrel[compnum];
8729988b915SShri Abhyankar   PetscFunctionReturn(0);
8739988b915SShri Abhyankar }
8749988b915SShri Abhyankar 
8759988b915SShri Abhyankar /*@
8769988b915SShri Abhyankar   DMNetworkGetComponentVariableGlobalOffset - Get the global offset for accessing the variable associated with a component for the given vertex/edge from the local vector.
8779988b915SShri Abhyankar 
8789988b915SShri Abhyankar   Not Collective
8799988b915SShri Abhyankar 
8809988b915SShri Abhyankar   Input Parameters:
8819988b915SShri Abhyankar + dm     - The DMNetwork object
8829988b915SShri Abhyankar . compnum - component number
8839988b915SShri Abhyankar - p      - the edge/vertex point
8849988b915SShri Abhyankar 
8859988b915SShri Abhyankar   Output Parameters:
8869988b915SShri Abhyankar . offsetg - the global offset
8879988b915SShri Abhyankar 
8889988b915SShri Abhyankar   Level: intermediate
8899988b915SShri Abhyankar 
8909dacc45bSShrirang Abhyankar .seealso: DMNetworkGetVariableGlobalOffset(), DMNetworkGetComponentVariableOffset(), DMGetLocalVector(), DMNetworkSetComponentNumVariables()
8919988b915SShri Abhyankar @*/
8929988b915SShri Abhyankar PetscErrorCode DMNetworkGetComponentVariableGlobalOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offsetg)
8939988b915SShri Abhyankar {
8949988b915SShri Abhyankar   PetscErrorCode ierr;
8959988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8969988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
8979988b915SShri Abhyankar   DMNetworkComponentHeader header;
8989988b915SShri Abhyankar 
8999988b915SShri Abhyankar   PetscFunctionBegin;
9009988b915SShri Abhyankar   ierr = DMNetworkGetVariableGlobalOffset(dm,p,&offsetp);CHKERRQ(ierr);
9019988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
9029988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
9039988b915SShri Abhyankar   *offsetg = offsetp + header->offsetvarrel[compnum];
9049988b915SShri Abhyankar   PetscFunctionReturn(0);
9059988b915SShri Abhyankar }
9069988b915SShri Abhyankar 
9079988b915SShri Abhyankar /*@
90824121865SAdrian Maldonado   DMNetworkGetEdgeOffset - Get the offset for accessing the variable associated with the given edge from the local subvector.
90924121865SAdrian Maldonado 
91024121865SAdrian Maldonado   Not Collective
91124121865SAdrian Maldonado 
91224121865SAdrian Maldonado   Input Parameters:
91324121865SAdrian Maldonado + dm     - The DMNetwork object
91424121865SAdrian Maldonado - p      - the edge point
91524121865SAdrian Maldonado 
91624121865SAdrian Maldonado   Output Parameters:
91724121865SAdrian Maldonado . offset - the offset
91824121865SAdrian Maldonado 
91924121865SAdrian Maldonado   Level: intermediate
92024121865SAdrian Maldonado 
92124121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
92224121865SAdrian Maldonado @*/
92324121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
92424121865SAdrian Maldonado {
92524121865SAdrian Maldonado   PetscErrorCode ierr;
92624121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
92724121865SAdrian Maldonado 
92824121865SAdrian Maldonado   PetscFunctionBegin;
92924121865SAdrian Maldonado 
93024121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
93124121865SAdrian Maldonado   PetscFunctionReturn(0);
93224121865SAdrian Maldonado }
93324121865SAdrian Maldonado 
93424121865SAdrian Maldonado /*@
93524121865SAdrian Maldonado   DMNetworkGetVertexOffset - Get the offset for accessing the variable associated with the given vertex from the local subvector.
93624121865SAdrian Maldonado 
93724121865SAdrian Maldonado   Not Collective
93824121865SAdrian Maldonado 
93924121865SAdrian Maldonado   Input Parameters:
94024121865SAdrian Maldonado + dm     - The DMNetwork object
94124121865SAdrian Maldonado - p      - the vertex point
94224121865SAdrian Maldonado 
94324121865SAdrian Maldonado   Output Parameters:
94424121865SAdrian Maldonado . offset - the offset
94524121865SAdrian Maldonado 
94624121865SAdrian Maldonado   Level: intermediate
94724121865SAdrian Maldonado 
94824121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
94924121865SAdrian Maldonado @*/
95024121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
95124121865SAdrian Maldonado {
95224121865SAdrian Maldonado   PetscErrorCode ierr;
95324121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
95424121865SAdrian Maldonado 
95524121865SAdrian Maldonado   PetscFunctionBegin;
95624121865SAdrian Maldonado 
95724121865SAdrian Maldonado   p -= network->vStart;
95824121865SAdrian Maldonado 
95924121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
96024121865SAdrian Maldonado   PetscFunctionReturn(0);
96124121865SAdrian Maldonado }
9625f2c45f1SShri Abhyankar /*@
9635f2c45f1SShri Abhyankar   DMNetworkAddNumVariables - Add number of variables associated with a given point.
9645f2c45f1SShri Abhyankar 
9655f2c45f1SShri Abhyankar   Not Collective
9665f2c45f1SShri Abhyankar 
9675f2c45f1SShri Abhyankar   Input Parameters:
9685f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
9695f2c45f1SShri Abhyankar . p    - the vertex/edge point
9705f2c45f1SShri Abhyankar - nvar - number of additional variables
9715f2c45f1SShri Abhyankar 
972*97bb938eSShri Abhyankar   Level: beginner
9735f2c45f1SShri Abhyankar 
9745f2c45f1SShri Abhyankar .seealso: DMNetworkSetNumVariables
9755f2c45f1SShri Abhyankar @*/
9765f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar)
9775f2c45f1SShri Abhyankar {
9785f2c45f1SShri Abhyankar   PetscErrorCode ierr;
9795f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
9805f2c45f1SShri Abhyankar 
9815f2c45f1SShri Abhyankar   PetscFunctionBegin;
9825f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
9835f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9845f2c45f1SShri Abhyankar }
9855f2c45f1SShri Abhyankar 
98627f51fceSHong Zhang /*@
98727f51fceSHong Zhang   DMNetworkGetNumVariables - Gets number of variables for a vertex/edge point.
98827f51fceSHong Zhang 
98927f51fceSHong Zhang   Not Collective
99027f51fceSHong Zhang 
99127f51fceSHong Zhang   Input Parameters:
99227f51fceSHong Zhang + dm   - The DMNetworkObject
99327f51fceSHong Zhang - p    - the vertex/edge point
99427f51fceSHong Zhang 
99527f51fceSHong Zhang   Output Parameters:
99627f51fceSHong Zhang . nvar - number of variables
99727f51fceSHong Zhang 
998*97bb938eSShri Abhyankar   Level: beginner
99927f51fceSHong Zhang 
100027f51fceSHong Zhang .seealso: DMNetworkAddNumVariables, DMNetworkSddNumVariables
100127f51fceSHong Zhang @*/
100227f51fceSHong Zhang PetscErrorCode DMNetworkGetNumVariables(DM dm,PetscInt p,PetscInt *nvar)
100327f51fceSHong Zhang {
100427f51fceSHong Zhang   PetscErrorCode ierr;
100527f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
100627f51fceSHong Zhang 
100727f51fceSHong Zhang   PetscFunctionBegin;
100827f51fceSHong Zhang   ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
100927f51fceSHong Zhang   PetscFunctionReturn(0);
101027f51fceSHong Zhang }
101127f51fceSHong Zhang 
10125f2c45f1SShri Abhyankar /*@
10135f2c45f1SShri Abhyankar   DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point.
10145f2c45f1SShri Abhyankar 
10155f2c45f1SShri Abhyankar   Not Collective
10165f2c45f1SShri Abhyankar 
10175f2c45f1SShri Abhyankar   Input Parameters:
10185f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
10195f2c45f1SShri Abhyankar . p    - the vertex/edge point
10205f2c45f1SShri Abhyankar - nvar - number of variables
10215f2c45f1SShri Abhyankar 
1022*97bb938eSShri Abhyankar   Level: beginner
10235f2c45f1SShri Abhyankar 
10245f2c45f1SShri Abhyankar .seealso: DMNetworkAddNumVariables
10255f2c45f1SShri Abhyankar @*/
10265f2c45f1SShri Abhyankar PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar)
10275f2c45f1SShri Abhyankar {
10285f2c45f1SShri Abhyankar   PetscErrorCode ierr;
10295f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10305f2c45f1SShri Abhyankar 
10315f2c45f1SShri Abhyankar   PetscFunctionBegin;
10325f2c45f1SShri Abhyankar   ierr = PetscSectionSetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
10335f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10345f2c45f1SShri Abhyankar }
10355f2c45f1SShri Abhyankar 
10365f2c45f1SShri Abhyankar /* Sets up the array that holds the data for all components and its associated section. This
10375f2c45f1SShri Abhyankar    function is called during DMSetUp() */
10385f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
10395f2c45f1SShri Abhyankar {
10405f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
10415f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
1042e53b5ba3SHong Zhang   PetscInt                 arr_size,p,offset,offsetp,ncomp,i;
10435f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
10445f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
10455f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
10465f2c45f1SShri Abhyankar 
10475f2c45f1SShri Abhyankar   PetscFunctionBegin;
10485f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
10495f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
105075b160a0SShri Abhyankar   ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
10515f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
10525f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
10535f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
10545f2c45f1SShri Abhyankar     /* Copy header */
10555f2c45f1SShri Abhyankar     header = &network->header[p];
1056302440fdSBarry Smith     ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
10575f2c45f1SShri Abhyankar     /* Copy data */
10585f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
10595f2c45f1SShri Abhyankar     ncomp = header->ndata;
10605f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
10615f2c45f1SShri Abhyankar       offset = offsetp + network->dataheadersize + header->offset[i];
1062302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
10635f2c45f1SShri Abhyankar     }
10645f2c45f1SShri Abhyankar   }
10655f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10665f2c45f1SShri Abhyankar }
10675f2c45f1SShri Abhyankar 
10685f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
10695f2c45f1SShri Abhyankar PetscErrorCode DMNetworkVariablesSetUp(DM dm)
10705f2c45f1SShri Abhyankar {
10715f2c45f1SShri Abhyankar   PetscErrorCode ierr;
10725f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10735f2c45f1SShri Abhyankar 
10745f2c45f1SShri Abhyankar   PetscFunctionBegin;
10755f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
10765f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10775f2c45f1SShri Abhyankar }
10785f2c45f1SShri Abhyankar 
1079*97bb938eSShri Abhyankar /*
10805f2c45f1SShri Abhyankar   DMNetworkGetComponentDataArray - Returns the component data array
10815f2c45f1SShri Abhyankar 
10825f2c45f1SShri Abhyankar   Not Collective
10835f2c45f1SShri Abhyankar 
10845f2c45f1SShri Abhyankar   Input Parameters:
10855f2c45f1SShri Abhyankar . dm - The DMNetwork Object
10865f2c45f1SShri Abhyankar 
10875f2c45f1SShri Abhyankar   Output Parameters:
10885f2c45f1SShri Abhyankar . componentdataarray - array that holds data for all components
10895f2c45f1SShri Abhyankar 
10905f2c45f1SShri Abhyankar   Level: intermediate
10915f2c45f1SShri Abhyankar 
1092a730d845SHong Zhang .seealso: DMNetworkGetComponentKeyOffset, DMNetworkGetNumComponents
1093*97bb938eSShri Abhyankar */
10945f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray)
10955f2c45f1SShri Abhyankar {
10965f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10975f2c45f1SShri Abhyankar 
10985f2c45f1SShri Abhyankar   PetscFunctionBegin;
10995f2c45f1SShri Abhyankar   *componentdataarray = network->componentdataarray;
11005f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
11015f2c45f1SShri Abhyankar }
11025f2c45f1SShri Abhyankar 
110324121865SAdrian Maldonado /* Get a subsection from a range of points */
110424121865SAdrian Maldonado PetscErrorCode DMNetworkGetSubSection_private(PetscSection master, PetscInt pstart, PetscInt pend,PetscSection *subsection)
110524121865SAdrian Maldonado {
110624121865SAdrian Maldonado   PetscErrorCode ierr;
110724121865SAdrian Maldonado   PetscInt       i, nvar;
110824121865SAdrian Maldonado 
110924121865SAdrian Maldonado   PetscFunctionBegin;
111024121865SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)master), subsection);CHKERRQ(ierr);
111124121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
111224121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
111324121865SAdrian Maldonado     ierr = PetscSectionGetDof(master,i,&nvar);CHKERRQ(ierr);
111424121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
111524121865SAdrian Maldonado   }
111624121865SAdrian Maldonado 
111724121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
111824121865SAdrian Maldonado   PetscFunctionReturn(0);
111924121865SAdrian Maldonado }
112024121865SAdrian Maldonado 
112124121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
112224121865SAdrian Maldonado PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
112324121865SAdrian Maldonado {
112424121865SAdrian Maldonado   PetscErrorCode ierr;
112524121865SAdrian Maldonado   PetscInt       i, *subpoints;
112624121865SAdrian Maldonado 
112724121865SAdrian Maldonado   PetscFunctionBegin;
112824121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
112924121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
113024121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
113124121865SAdrian Maldonado     subpoints[i - pstart] = i;
113224121865SAdrian Maldonado   }
1133459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
113424121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
113524121865SAdrian Maldonado   PetscFunctionReturn(0);
113624121865SAdrian Maldonado }
113724121865SAdrian Maldonado 
113824121865SAdrian Maldonado /*@
113924121865SAdrian Maldonado   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute.
114024121865SAdrian Maldonado 
114124121865SAdrian Maldonado   Collective
114224121865SAdrian Maldonado 
114324121865SAdrian Maldonado   Input Parameters:
114424121865SAdrian Maldonado . dm   - The DMNetworkObject
114524121865SAdrian Maldonado 
114624121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
114724121865SAdrian Maldonado 
114824121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
114924121865SAdrian Maldonado 
1150caf410d2SHong 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]).
115124121865SAdrian Maldonado 
115224121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
115324121865SAdrian Maldonado 
115424121865SAdrian Maldonado   Level: intermediate
115524121865SAdrian Maldonado 
115624121865SAdrian Maldonado @*/
115724121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
115824121865SAdrian Maldonado {
115924121865SAdrian Maldonado   PetscErrorCode ierr;
116024121865SAdrian Maldonado   MPI_Comm       comm;
11619852e123SBarry Smith   PetscMPIInt    rank, size;
116224121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
116324121865SAdrian Maldonado 
1164eab1376dSHong Zhang   PetscFunctionBegin;
116524121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
116624121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
11679852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
116824121865SAdrian Maldonado 
116924121865SAdrian Maldonado   /* Create maps for vertices and edges */
117024121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
117124121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
117224121865SAdrian Maldonado 
117324121865SAdrian Maldonado   /* Create local sub-sections */
117424121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
117524121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
117624121865SAdrian Maldonado 
11779852e123SBarry Smith   if (size > 1) {
117824121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
117922bbedd7SHong Zhang 
118024121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
118124121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
118224121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
118324121865SAdrian Maldonado   } else {
118424121865SAdrian Maldonado     /* create structures for vertex */
118524121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
118624121865SAdrian Maldonado     /* create structures for edge */
118724121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
118824121865SAdrian Maldonado   }
118924121865SAdrian Maldonado 
119024121865SAdrian Maldonado   /* Add viewers */
119124121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
119224121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
119324121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
119424121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
119524121865SAdrian Maldonado   PetscFunctionReturn(0);
119624121865SAdrian Maldonado }
11977b6afd5bSHong Zhang 
11985f2c45f1SShri Abhyankar /*@
11995f2c45f1SShri Abhyankar   DMNetworkDistribute - Distributes the network and moves associated component data.
12005f2c45f1SShri Abhyankar 
12015f2c45f1SShri Abhyankar   Collective
12025f2c45f1SShri Abhyankar 
12035f2c45f1SShri Abhyankar   Input Parameter:
1204d3464fd4SAdrian Maldonado + DM - the DMNetwork object
12055f2c45f1SShri Abhyankar - overlap - The overlap of partitions, 0 is the default
12065f2c45f1SShri Abhyankar 
12075f2c45f1SShri Abhyankar   Notes:
12088b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
12095f2c45f1SShri Abhyankar 
12105f2c45f1SShri Abhyankar   Level: intermediate
12115f2c45f1SShri Abhyankar 
12125f2c45f1SShri Abhyankar .seealso: DMNetworkCreate
12135f2c45f1SShri Abhyankar @*/
1214d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
12155f2c45f1SShri Abhyankar {
1216d3464fd4SAdrian Maldonado   MPI_Comm       comm;
12175f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1218d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1219d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1220d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1221caf410d2SHong Zhang   PetscSF        pointsf=NULL;
12225f2c45f1SShri Abhyankar   DM             newDM;
1223caf410d2SHong Zhang   PetscInt       j,e,v,offset,*subnetvtx;
122451ac5effSHong Zhang   PetscPartitioner         part;
1225b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
12265f2c45f1SShri Abhyankar 
12275f2c45f1SShri Abhyankar   PetscFunctionBegin;
1228d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1229d3464fd4SAdrian Maldonado   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
1230d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1231d3464fd4SAdrian Maldonado 
1232d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
12335f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
12345f2c45f1SShri Abhyankar   newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
123551ac5effSHong Zhang 
123651ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
123751ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
123851ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
123951ac5effSHong Zhang 
12405f2c45f1SShri Abhyankar   /* Distribute plex dm and dof section */
124180cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
124251ac5effSHong Zhang 
12435f2c45f1SShri Abhyankar   /* Distribute dof section */
1244d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DofSection);CHKERRQ(ierr);
12455f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
1246d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DataSection);CHKERRQ(ierr);
124751ac5effSHong Zhang 
12485f2c45f1SShri Abhyankar   /* Distribute data and associated section */
124931da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
125024121865SAdrian Maldonado 
12515f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
12525f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
12535f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
12545f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
12556fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
12566fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
12575f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
125824121865SAdrian Maldonado 
12591bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
126092fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1261e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
12625f2c45f1SShri Abhyankar 
1263b9c6e19dSShri Abhyankar   /* Set up subnetwork info in the newDM */
1264b9c6e19dSShri Abhyankar   newDMnetwork->nsubnet  = oldDMnetwork->nsubnet;
1265caf410d2SHong Zhang   newDMnetwork->ncsubnet = oldDMnetwork->ncsubnet;
1266b9c6e19dSShri Abhyankar   ierr = PetscCalloc1(newDMnetwork->nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
1267b9c6e19dSShri Abhyankar   /* Copy over the global number of vertices and edges in each subnetwork. Note that these are already
1268b9c6e19dSShri Abhyankar      calculated in DMNetworkLayoutSetUp()
1269b9c6e19dSShri Abhyankar   */
1270b9c6e19dSShri Abhyankar   for(j=0; j < newDMnetwork->nsubnet; j++) {
1271b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1272b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1273b9c6e19dSShri Abhyankar   }
1274b9c6e19dSShri Abhyankar 
1275b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1276b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1277b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1278b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1279b9c6e19dSShri Abhyankar   }
1280b9c6e19dSShri Abhyankar 
1281b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1282b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1283b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1284b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nvtx++;
1285b9c6e19dSShri Abhyankar   }
1286b9c6e19dSShri Abhyankar 
1287b9c6e19dSShri Abhyankar   /* Now create the vertices and edge arrays for the subnetworks */
1288caf410d2SHong Zhang   ierr = PetscCalloc1(newDMnetwork->vEnd-newDMnetwork->vStart,&newDMnetwork->subnetvtx);CHKERRQ(ierr);
1289caf410d2SHong Zhang   subnetvtx = newDMnetwork->subnetvtx;
1290caf410d2SHong Zhang 
1291b9c6e19dSShri Abhyankar   for (j=0; j<newDMnetwork->nsubnet; j++) {
1292b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr);
1293caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1294caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1295caf410d2SHong Zhang 
1296b9c6e19dSShri Abhyankar     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
1297b9c6e19dSShri Abhyankar        These get updated when the vertices and edges are added. */
1298b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1299b9c6e19dSShri Abhyankar   }
1300b9c6e19dSShri Abhyankar 
1301b9c6e19dSShri Abhyankar   /* Set the vertices and edges in each subnetwork */
1302b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1303b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1304b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1305b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1306b9c6e19dSShri Abhyankar   }
1307b9c6e19dSShri Abhyankar 
1308b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1309b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1310b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1311b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
1312b9c6e19dSShri Abhyankar   }
1313b9c6e19dSShri Abhyankar 
1314caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
131522bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1316caf410d2SHong Zhang 
131724121865SAdrian Maldonado   /* Destroy point SF */
131824121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
131924121865SAdrian Maldonado 
1320d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
1321d3464fd4SAdrian Maldonado   *dm  = newDM;
13225f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13235f2c45f1SShri Abhyankar }
13245f2c45f1SShri Abhyankar 
132524121865SAdrian Maldonado /*@C
132624121865SAdrian Maldonado   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering.
132724121865SAdrian Maldonado 
132824121865SAdrian Maldonado   Input Parameters:
132924121865SAdrian Maldonado + masterSF - the original SF structure
133024121865SAdrian Maldonado - map      - a ISLocalToGlobal mapping that contains the subset of points
133124121865SAdrian Maldonado 
133224121865SAdrian Maldonado   Output Parameters:
133324121865SAdrian Maldonado . subSF    - a subset of the masterSF for the desired subset.
133424121865SAdrian Maldonado */
133524121865SAdrian Maldonado 
133624121865SAdrian Maldonado PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) {
133724121865SAdrian Maldonado 
133824121865SAdrian Maldonado   PetscErrorCode        ierr;
133924121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
134024121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
134124121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
134224121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
134324121865SAdrian Maldonado   const PetscInt        *ilocal;
134424121865SAdrian Maldonado   const PetscSFNode     *iremote;
134524121865SAdrian Maldonado 
134624121865SAdrian Maldonado   PetscFunctionBegin;
134724121865SAdrian Maldonado   ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
134824121865SAdrian Maldonado 
134924121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
135024121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
135124121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
135224121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
135324121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
135424121865SAdrian Maldonado   }
135524121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
135624121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
135724121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
135824121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
135924121865SAdrian Maldonado   ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
136024121865SAdrian Maldonado   ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
136124121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
13624b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
13634b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
136424121865SAdrian Maldonado   nleaves_sub = 0;
136524121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
136624121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
136724121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
13684b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
136924121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
137024121865SAdrian Maldonado       nleaves_sub += 1;
137124121865SAdrian Maldonado     }
137224121865SAdrian Maldonado   }
137324121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
137424121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
137524121865SAdrian Maldonado 
137624121865SAdrian Maldonado   /* Create new subSF */
137724121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
137824121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
13794b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
138024121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
13814b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
138224121865SAdrian Maldonado   PetscFunctionReturn(0);
138324121865SAdrian Maldonado }
138424121865SAdrian Maldonado 
13855f2c45f1SShri Abhyankar /*@C
13865f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
13875f2c45f1SShri Abhyankar 
13885f2c45f1SShri Abhyankar   Not Collective
13895f2c45f1SShri Abhyankar 
13905f2c45f1SShri Abhyankar   Input Parameters:
13915f2c45f1SShri Abhyankar + dm - The DMNetwork object
13925f2c45f1SShri Abhyankar - p  - the vertex point
13935f2c45f1SShri Abhyankar 
1394fd292e60Sprj-   Output Parameters:
13955f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
13965f2c45f1SShri Abhyankar - edges  - List of edge points
13975f2c45f1SShri Abhyankar 
1398*97bb938eSShri Abhyankar   Level: beginner
13995f2c45f1SShri Abhyankar 
14005f2c45f1SShri Abhyankar   Fortran Notes:
14015f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
14025f2c45f1SShri Abhyankar   include petsc.h90 in your code.
14035f2c45f1SShri Abhyankar 
1404d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices
14055f2c45f1SShri Abhyankar @*/
14065f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
14075f2c45f1SShri Abhyankar {
14085f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14095f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14105f2c45f1SShri Abhyankar 
14115f2c45f1SShri Abhyankar   PetscFunctionBegin;
14125f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
14135f2c45f1SShri Abhyankar   ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);
14145f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14155f2c45f1SShri Abhyankar }
14165f2c45f1SShri Abhyankar 
14175f2c45f1SShri Abhyankar /*@C
1418d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
14195f2c45f1SShri Abhyankar 
14205f2c45f1SShri Abhyankar   Not Collective
14215f2c45f1SShri Abhyankar 
14225f2c45f1SShri Abhyankar   Input Parameters:
14235f2c45f1SShri Abhyankar + dm - The DMNetwork object
14245f2c45f1SShri Abhyankar - p  - the edge point
14255f2c45f1SShri Abhyankar 
1426fd292e60Sprj-   Output Parameters:
14275f2c45f1SShri Abhyankar . vertices  - vertices connected to this edge
14285f2c45f1SShri Abhyankar 
1429*97bb938eSShri Abhyankar   Level: beginner
14305f2c45f1SShri Abhyankar 
14315f2c45f1SShri Abhyankar   Fortran Notes:
14325f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
14335f2c45f1SShri Abhyankar   include petsc.h90 in your code.
14345f2c45f1SShri Abhyankar 
14355f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
14365f2c45f1SShri Abhyankar @*/
1437d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
14385f2c45f1SShri Abhyankar {
14395f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14405f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14415f2c45f1SShri Abhyankar 
14425f2c45f1SShri Abhyankar   PetscFunctionBegin;
14435f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
14445f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14455f2c45f1SShri Abhyankar }
14465f2c45f1SShri Abhyankar 
14475f2c45f1SShri Abhyankar /*@
14485f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
14495f2c45f1SShri Abhyankar 
14505f2c45f1SShri Abhyankar   Not Collective
14515f2c45f1SShri Abhyankar 
14525f2c45f1SShri Abhyankar   Input Parameters:
14535f2c45f1SShri Abhyankar + dm - The DMNetwork object
1454a2b725a8SWilliam Gropp - p  - the vertex point
14555f2c45f1SShri Abhyankar 
14565f2c45f1SShri Abhyankar   Output Parameter:
14575f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
14585f2c45f1SShri Abhyankar 
1459*97bb938eSShri Abhyankar   Level: beginner
14605f2c45f1SShri Abhyankar 
1461d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange
14625f2c45f1SShri Abhyankar @*/
14635f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
14645f2c45f1SShri Abhyankar {
14655f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14665f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14675f2c45f1SShri Abhyankar   PetscInt       offsetg;
14685f2c45f1SShri Abhyankar   PetscSection   sectiong;
14695f2c45f1SShri Abhyankar 
14705f2c45f1SShri Abhyankar   PetscFunctionBegin;
1471caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
14725f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
1473e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
14745f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
14755f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
14765f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14775f2c45f1SShri Abhyankar }
14785f2c45f1SShri Abhyankar 
14795f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
14805f2c45f1SShri Abhyankar {
14815f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14825f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
14835f2c45f1SShri Abhyankar 
14845f2c45f1SShri Abhyankar   PetscFunctionBegin;
14855f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
14865f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
14875f2c45f1SShri Abhyankar 
148892fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
1489e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
14909e1d080bSHong Zhang 
14919e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
14929e1d080bSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr);
14935f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14945f2c45f1SShri Abhyankar }
14955f2c45f1SShri Abhyankar 
14961ad426b7SHong Zhang /*@
149717df6e9eSHong Zhang     DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
14981ad426b7SHong Zhang                             -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
14991ad426b7SHong Zhang 
15001ad426b7SHong Zhang     Collective
15011ad426b7SHong Zhang 
15021ad426b7SHong Zhang     Input Parameters:
150383b2e829SHong Zhang +   dm - The DMNetwork object
150483b2e829SHong Zhang .   eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
150583b2e829SHong Zhang -   vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
15061ad426b7SHong Zhang 
15071ad426b7SHong Zhang     Level: intermediate
15081ad426b7SHong Zhang 
15091ad426b7SHong Zhang @*/
151083b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
15111ad426b7SHong Zhang {
15121ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
15138675203cSHong Zhang   PetscErrorCode ierr;
151466b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
15151ad426b7SHong Zhang 
15161ad426b7SHong Zhang   PetscFunctionBegin;
151783b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
151883b2e829SHong Zhang   network->userVertexJacobian = vflg;
15198675203cSHong Zhang 
15208675203cSHong Zhang   if (eflg && !network->Je) {
15218675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
15228675203cSHong Zhang   }
15238675203cSHong Zhang 
152466b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
15258675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
152666b4e0ffSHong Zhang     PetscInt       nedges_total;
15278675203cSHong Zhang     const PetscInt *edges;
15288675203cSHong Zhang 
15298675203cSHong Zhang     /* count nvertex_total */
15308675203cSHong Zhang     nedges_total = 0;
15318675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
15328675203cSHong Zhang 
15338675203cSHong Zhang     vptr[0] = 0;
15348675203cSHong Zhang     for (i=0; i<nVertices; i++) {
15358675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
15368675203cSHong Zhang       nedges_total += nedges;
15378675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
15388675203cSHong Zhang     }
15398675203cSHong Zhang 
15408675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
15418675203cSHong Zhang     network->Jvptr = vptr;
15428675203cSHong Zhang   }
15431ad426b7SHong Zhang   PetscFunctionReturn(0);
15441ad426b7SHong Zhang }
15451ad426b7SHong Zhang 
15461ad426b7SHong Zhang /*@
154783b2e829SHong Zhang     DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
154883b2e829SHong Zhang 
154983b2e829SHong Zhang     Not Collective
155083b2e829SHong Zhang 
155183b2e829SHong Zhang     Input Parameters:
155283b2e829SHong Zhang +   dm - The DMNetwork object
155383b2e829SHong Zhang .   p  - the edge point
15543e97b6e8SHong Zhang -   J - array (size = 3) of Jacobian submatrices for this edge point:
15553e97b6e8SHong Zhang         J[0]: this edge
1556d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
155783b2e829SHong Zhang 
1558*97bb938eSShri Abhyankar     Level: advanced
155983b2e829SHong Zhang 
156083b2e829SHong Zhang .seealso: DMNetworkVertexSetMatrix
156183b2e829SHong Zhang @*/
156283b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
156383b2e829SHong Zhang {
156483b2e829SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
156583b2e829SHong Zhang 
156683b2e829SHong Zhang   PetscFunctionBegin;
15678675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
15688675203cSHong Zhang 
15698675203cSHong Zhang   if (J) {
1570883e35e8SHong Zhang     network->Je[3*p]   = J[0];
1571883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
1572883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
15738675203cSHong Zhang   }
157483b2e829SHong Zhang   PetscFunctionReturn(0);
157583b2e829SHong Zhang }
157683b2e829SHong Zhang 
157783b2e829SHong Zhang /*@
157876ddfea5SHong Zhang     DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
15791ad426b7SHong Zhang 
15801ad426b7SHong Zhang     Not Collective
15811ad426b7SHong Zhang 
15821ad426b7SHong Zhang     Input Parameters:
15831ad426b7SHong Zhang +   dm - The DMNetwork object
15841ad426b7SHong Zhang .   p  - the vertex point
15853e97b6e8SHong Zhang -   J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
15863e97b6e8SHong Zhang         J[0]:       this vertex
15873e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
15883e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
15891ad426b7SHong Zhang 
1590*97bb938eSShri Abhyankar     Level: advanced
15911ad426b7SHong Zhang 
159283b2e829SHong Zhang .seealso: DMNetworkEdgeSetMatrix
15931ad426b7SHong Zhang @*/
1594883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
15955f2c45f1SShri Abhyankar {
15965f2c45f1SShri Abhyankar   PetscErrorCode ierr;
15975f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
15988675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
1599883e35e8SHong Zhang   const PetscInt *edges;
16005f2c45f1SShri Abhyankar 
16015f2c45f1SShri Abhyankar   PetscFunctionBegin;
16028675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1603883e35e8SHong Zhang 
16048675203cSHong Zhang   if (J) {
1605883e35e8SHong Zhang     vptr = network->Jvptr;
16063e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
16073e97b6e8SHong Zhang 
16083e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
1609883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
1610883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
16118675203cSHong Zhang   }
1612883e35e8SHong Zhang   PetscFunctionReturn(0);
1613883e35e8SHong Zhang }
1614883e35e8SHong Zhang 
1615e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16165cf7da58SHong Zhang {
16175cf7da58SHong Zhang   PetscErrorCode ierr;
16185cf7da58SHong Zhang   PetscInt       j;
16195cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
16205cf7da58SHong Zhang 
16215cf7da58SHong Zhang   PetscFunctionBegin;
16225cf7da58SHong Zhang   if (!ghost) {
16235cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16245cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16255cf7da58SHong Zhang     }
16265cf7da58SHong Zhang   } else {
16275cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16285cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16295cf7da58SHong Zhang     }
16305cf7da58SHong Zhang   }
16315cf7da58SHong Zhang   PetscFunctionReturn(0);
16325cf7da58SHong Zhang }
16335cf7da58SHong Zhang 
1634e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16355cf7da58SHong Zhang {
16365cf7da58SHong Zhang   PetscErrorCode ierr;
16375cf7da58SHong Zhang   PetscInt       j,ncols_u;
16385cf7da58SHong Zhang   PetscScalar    val;
16395cf7da58SHong Zhang 
16405cf7da58SHong Zhang   PetscFunctionBegin;
16415cf7da58SHong Zhang   if (!ghost) {
16425cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16435cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16445cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
16455cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16465cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16475cf7da58SHong Zhang     }
16485cf7da58SHong Zhang   } else {
16495cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16505cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16515cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
16525cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16535cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16545cf7da58SHong Zhang     }
16555cf7da58SHong Zhang   }
16565cf7da58SHong Zhang   PetscFunctionReturn(0);
16575cf7da58SHong Zhang }
16585cf7da58SHong Zhang 
1659e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16605cf7da58SHong Zhang {
16615cf7da58SHong Zhang   PetscErrorCode ierr;
16625cf7da58SHong Zhang 
16635cf7da58SHong Zhang   PetscFunctionBegin;
16645cf7da58SHong Zhang   if (Ju) {
16655cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
16665cf7da58SHong Zhang   } else {
16675cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
16685cf7da58SHong Zhang   }
16695cf7da58SHong Zhang   PetscFunctionReturn(0);
16705cf7da58SHong Zhang }
16715cf7da58SHong Zhang 
1672e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1673883e35e8SHong Zhang {
1674883e35e8SHong Zhang   PetscErrorCode ierr;
1675883e35e8SHong Zhang   PetscInt       j,*cols;
1676883e35e8SHong Zhang   PetscScalar    *zeros;
1677883e35e8SHong Zhang 
1678883e35e8SHong Zhang   PetscFunctionBegin;
1679883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
1680883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
1681883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
1682883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
16831ad426b7SHong Zhang   PetscFunctionReturn(0);
16841ad426b7SHong Zhang }
1685a4e85ca8SHong Zhang 
1686e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
16873e97b6e8SHong Zhang {
16883e97b6e8SHong Zhang   PetscErrorCode ierr;
16893e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
16903e97b6e8SHong Zhang   const PetscInt *cols;
16913e97b6e8SHong Zhang   PetscScalar    zero=0.0;
16923e97b6e8SHong Zhang 
16933e97b6e8SHong Zhang   PetscFunctionBegin;
16943e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
16953e97b6e8SHong 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);
16963e97b6e8SHong Zhang 
16973e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
16983e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
16993e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
17003e97b6e8SHong Zhang       col = cols[j] + cstart;
17013e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
17023e97b6e8SHong Zhang     }
17033e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
17043e97b6e8SHong Zhang   }
17053e97b6e8SHong Zhang   PetscFunctionReturn(0);
17063e97b6e8SHong Zhang }
17071ad426b7SHong Zhang 
1708e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1709a4e85ca8SHong Zhang {
1710a4e85ca8SHong Zhang   PetscErrorCode ierr;
1711f4431b8cSHong Zhang 
1712a4e85ca8SHong Zhang   PetscFunctionBegin;
1713a4e85ca8SHong Zhang   if (Ju) {
1714a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1715a4e85ca8SHong Zhang   } else {
1716a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1717a4e85ca8SHong Zhang   }
1718a4e85ca8SHong Zhang   PetscFunctionReturn(0);
1719a4e85ca8SHong Zhang }
1720a4e85ca8SHong Zhang 
172124121865SAdrian 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.
172224121865SAdrian Maldonado */
172324121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
172424121865SAdrian Maldonado {
172524121865SAdrian Maldonado   PetscErrorCode ierr;
172624121865SAdrian Maldonado   PetscInt       i,size,dof;
172724121865SAdrian Maldonado   PetscInt       *glob2loc;
172824121865SAdrian Maldonado 
172924121865SAdrian Maldonado   PetscFunctionBegin;
173024121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
173124121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
173224121865SAdrian Maldonado 
173324121865SAdrian Maldonado   for (i = 0; i < size; i++) {
173424121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
173524121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
173624121865SAdrian Maldonado     glob2loc[i] = dof;
173724121865SAdrian Maldonado   }
173824121865SAdrian Maldonado 
173924121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
174024121865SAdrian Maldonado #if 0
174124121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
174224121865SAdrian Maldonado #endif
174324121865SAdrian Maldonado   PetscFunctionReturn(0);
174424121865SAdrian Maldonado }
174524121865SAdrian Maldonado 
174601ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
17479e1d080bSHong Zhang 
17489e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
17491ad426b7SHong Zhang {
17501ad426b7SHong Zhang   PetscErrorCode ierr;
17511ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
17529e1d080bSHong Zhang   PetscMPIInt    rank, size;
175324121865SAdrian Maldonado   PetscInt       eDof,vDof;
175424121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
17559e1d080bSHong Zhang   MPI_Comm       comm;
175624121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
175724121865SAdrian Maldonado 
17589e1d080bSHong Zhang   PetscFunctionBegin;
175924121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
176024121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
176124121865SAdrian Maldonado   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
176224121865SAdrian Maldonado 
176324121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
176424121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
176524121865SAdrian Maldonado 
176601ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
176724121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
176824121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
176924121865SAdrian Maldonado 
177001ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
177124121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
177224121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
177324121865SAdrian Maldonado 
177401ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
177524121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
177624121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
177724121865SAdrian Maldonado 
177801ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
177924121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
178024121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
178124121865SAdrian Maldonado 
17823f6a6bdaSHong Zhang   bA[0][0] = j11;
17833f6a6bdaSHong Zhang   bA[0][1] = j12;
17843f6a6bdaSHong Zhang   bA[1][0] = j21;
17853f6a6bdaSHong Zhang   bA[1][1] = j22;
178624121865SAdrian Maldonado 
178724121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
178824121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
178924121865SAdrian Maldonado 
179024121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
179124121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
179224121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
179324121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
179424121865SAdrian Maldonado 
179524121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
179624121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
179724121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
179824121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
179924121865SAdrian Maldonado 
180001ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
180124121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
180224121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
180324121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
180424121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
180524121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
180624121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
180724121865SAdrian Maldonado 
180824121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180924121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18109e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
181124121865SAdrian Maldonado 
181224121865SAdrian Maldonado   /* Free structures */
181324121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
181424121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
181524121865SAdrian Maldonado   PetscFunctionReturn(0);
18169e1d080bSHong Zhang }
18179e1d080bSHong Zhang 
18189e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
18199e1d080bSHong Zhang {
18209e1d080bSHong Zhang   PetscErrorCode ierr;
18219e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
18229e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
18239e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
18249e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
18259e1d080bSHong Zhang   Mat            Juser;
18269e1d080bSHong Zhang   PetscSection   sectionGlobal;
18279e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
18289e1d080bSHong Zhang   const PetscInt *edges,*cone;
18299e1d080bSHong Zhang   MPI_Comm       comm;
18309e1d080bSHong Zhang   MatType        mtype;
18319e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
18329e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
18339e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
18349e1d080bSHong Zhang 
18359e1d080bSHong Zhang   PetscFunctionBegin;
18369e1d080bSHong Zhang   mtype = dm->mattype;
18379e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
18389e1d080bSHong Zhang   if (isNest) {
18399e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
1840c6b011d8SStefano Zampini     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
18419e1d080bSHong Zhang     PetscFunctionReturn(0);
18429e1d080bSHong Zhang   }
18439e1d080bSHong Zhang 
18449e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
1845a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
18469e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
1847bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
18481ad426b7SHong Zhang     PetscFunctionReturn(0);
18491ad426b7SHong Zhang   }
18501ad426b7SHong Zhang 
1851bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
1852e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
1853bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
1854bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
18552a945128SHong Zhang 
18562a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
18572a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
185889898e50SHong Zhang 
185989898e50SHong Zhang   /* (1) Set matrix preallocation */
186089898e50SHong Zhang   /*------------------------------*/
1861840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1862840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
1863840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
1864840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
1865840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
1866840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
1867840c2264SHong Zhang 
186889898e50SHong Zhang   /* Set preallocation for edges */
186989898e50SHong Zhang   /*-----------------------------*/
1870840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
1871840c2264SHong Zhang 
1872bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
1873840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
1874840c2264SHong Zhang     /* Get row indices */
1875840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
1876840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
1877840c2264SHong Zhang     if (nrows) {
1878840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
1879840c2264SHong Zhang 
18805cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
1881d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1882840c2264SHong Zhang       for (v=0; v<2; v++) {
1883840c2264SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
1884840c2264SHong Zhang 
18858675203cSHong Zhang         if (network->Je) {
1886840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
18878675203cSHong Zhang         } else Juser = NULL;
1888840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
18895cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1890840c2264SHong Zhang       }
1891840c2264SHong Zhang 
189289898e50SHong Zhang       /* Set preallocation for edge self */
1893840c2264SHong Zhang       cstart = rstart;
18948675203cSHong Zhang       if (network->Je) {
1895840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
18968675203cSHong Zhang       } else Juser = NULL;
18975cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1898840c2264SHong Zhang     }
1899840c2264SHong Zhang   }
1900840c2264SHong Zhang 
190189898e50SHong Zhang   /* Set preallocation for vertices */
190289898e50SHong Zhang   /*--------------------------------*/
1903840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
19048675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
1905840c2264SHong Zhang 
1906840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
1907840c2264SHong Zhang     /* Get row indices */
1908840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1909840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
1910840c2264SHong Zhang     if (!nrows) continue;
1911840c2264SHong Zhang 
1912bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1913bdcb62a2SHong Zhang     if (ghost) {
1914bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1915bdcb62a2SHong Zhang     } else {
1916bdcb62a2SHong Zhang       rows_v = rows;
1917bdcb62a2SHong Zhang     }
1918bdcb62a2SHong Zhang 
1919bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1920840c2264SHong Zhang 
1921840c2264SHong Zhang     /* Get supporting edges and connected vertices */
1922840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1923840c2264SHong Zhang 
1924840c2264SHong Zhang     for (e=0; e<nedges; e++) {
1925840c2264SHong Zhang       /* Supporting edges */
1926840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1927840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1928840c2264SHong Zhang 
19298675203cSHong Zhang       if (network->Jv) {
1930840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
19318675203cSHong Zhang       } else Juser = NULL;
1932bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1933840c2264SHong Zhang 
1934840c2264SHong Zhang       /* Connected vertices */
1935d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
1936840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
1937840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
1938840c2264SHong Zhang 
1939840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1940840c2264SHong Zhang 
19418675203cSHong Zhang       if (network->Jv) {
1942840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
19438675203cSHong Zhang       } else Juser = NULL;
1944e102a522SHong Zhang       if (ghost_vc||ghost) {
1945e102a522SHong Zhang         ghost2 = PETSC_TRUE;
1946e102a522SHong Zhang       } else {
1947e102a522SHong Zhang         ghost2 = PETSC_FALSE;
1948e102a522SHong Zhang       }
1949e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
1950840c2264SHong Zhang     }
1951840c2264SHong Zhang 
195289898e50SHong Zhang     /* Set preallocation for vertex self */
1953840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1954840c2264SHong Zhang     if (!ghost) {
1955840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
19568675203cSHong Zhang       if (network->Jv) {
1957840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
19588675203cSHong Zhang       } else Juser = NULL;
1959bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1960840c2264SHong Zhang     }
1961bdcb62a2SHong Zhang     if (ghost) {
1962bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1963bdcb62a2SHong Zhang     }
1964840c2264SHong Zhang   }
1965840c2264SHong Zhang 
1966840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
1967840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
19685cf7da58SHong Zhang 
19695cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
19705cf7da58SHong Zhang 
19715cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
1972840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
1973840c2264SHong Zhang 
1974840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
1975840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
1976840c2264SHong Zhang   for (j=0; j<localSize; j++) {
1977e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
1978e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
1979840c2264SHong Zhang   }
1980840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
1981840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
1982840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
1983840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
1984840c2264SHong Zhang 
19855cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
19865cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
19875cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
19885cf7da58SHong Zhang 
19895cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
19905cf7da58SHong Zhang 
199189898e50SHong Zhang   /* (2) Set matrix entries for edges */
199289898e50SHong Zhang   /*----------------------------------*/
19931ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
1994bfbc38dcSHong Zhang     /* Get row indices */
19951ad426b7SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
199617df6e9eSHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
19974b976069SHong Zhang     if (nrows) {
199817df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
19991ad426b7SHong Zhang 
2000bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
2001d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2002bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
2003bfbc38dcSHong Zhang         ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr);
2004883e35e8SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
20053e97b6e8SHong Zhang 
20068675203cSHong Zhang         if (network->Je) {
2007a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
20088675203cSHong Zhang         } else Juser = NULL;
2009a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2010bfbc38dcSHong Zhang       }
201117df6e9eSHong Zhang 
2012bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
20133e97b6e8SHong Zhang       cstart = rstart;
20148675203cSHong Zhang       if (network->Je) {
2015a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
20168675203cSHong Zhang       } else Juser = NULL;
2017a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
20181ad426b7SHong Zhang     }
20194b976069SHong Zhang   }
20201ad426b7SHong Zhang 
2021bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
202283b2e829SHong Zhang   /*---------------------------------*/
20231ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2024bfbc38dcSHong Zhang     /* Get row indices */
2025596e729fSHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
2026596e729fSHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
20274b976069SHong Zhang     if (!nrows) continue;
2028596e729fSHong Zhang 
2029bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2030bdcb62a2SHong Zhang     if (ghost) {
2031bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2032bdcb62a2SHong Zhang     } else {
2033bdcb62a2SHong Zhang       rows_v = rows;
2034bdcb62a2SHong Zhang     }
2035bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2036596e729fSHong Zhang 
2037bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2038596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2039596e729fSHong Zhang 
2040596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2041bfbc38dcSHong Zhang       /* Supporting edges */
2042596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
2043596e729fSHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
2044596e729fSHong Zhang 
20458675203cSHong Zhang       if (network->Jv) {
2046a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
20478675203cSHong Zhang       } else Juser = NULL;
2048bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2049596e729fSHong Zhang 
2050bfbc38dcSHong Zhang       /* Connected vertices */
2051d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
20522a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
20532a945128SHong Zhang 
205444aca652SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr);
205544aca652SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
2056a4e85ca8SHong Zhang 
20578675203cSHong Zhang       if (network->Jv) {
2058a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
20598675203cSHong Zhang       } else Juser = NULL;
2060bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2061596e729fSHong Zhang     }
2062596e729fSHong Zhang 
2063bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
20641ad426b7SHong Zhang     if (!ghost) {
2065596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
20668675203cSHong Zhang       if (network->Jv) {
2067a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
20688675203cSHong Zhang       } else Juser = NULL;
2069bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2070bdcb62a2SHong Zhang     }
2071bdcb62a2SHong Zhang     if (ghost) {
2072bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2073bdcb62a2SHong Zhang     }
20741ad426b7SHong Zhang   }
2075a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2076bdcb62a2SHong Zhang 
20771ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20781ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2079dd6f46cdSHong Zhang 
20805f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
20815f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20825f2c45f1SShri Abhyankar }
20835f2c45f1SShri Abhyankar 
20845f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
20855f2c45f1SShri Abhyankar {
20865f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20875f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20882727e31bSShri Abhyankar   PetscInt       j;
20895f2c45f1SShri Abhyankar 
20905f2c45f1SShri Abhyankar   PetscFunctionBegin;
20918415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
209283b2e829SHong Zhang   if (network->Je) {
209383b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
209483b2e829SHong Zhang   }
209583b2e829SHong Zhang   if (network->Jv) {
2096883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
209783b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
20981ad426b7SHong Zhang   }
209913c2a604SAdrian Maldonado 
210013c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
210113c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
210213c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2103f5427c60SHong Zhang   if (network->vltog) {
2104f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2105f5427c60SHong Zhang   }
210613c2a604SAdrian Maldonado   if (network->vertex.sf) {
210713c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
210813c2a604SAdrian Maldonado   }
210913c2a604SAdrian Maldonado   /* edge */
211013c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
211113c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
211213c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
211313c2a604SAdrian Maldonado   if (network->edge.sf) {
211413c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
211513c2a604SAdrian Maldonado   }
21165f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
21175f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
21185f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
211983b2e829SHong Zhang 
21202727e31bSShri Abhyankar   for(j=0; j<network->nsubnet; j++) {
21212727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
21222727e31bSShri Abhyankar   }
2123caf410d2SHong Zhang   ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr);
2124caf410d2SHong Zhang 
2125e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
21265f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
2127caf410d2SHong Zhang   ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
21285f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
21295f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21305f2c45f1SShri Abhyankar }
21315f2c45f1SShri Abhyankar 
21325f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
21335f2c45f1SShri Abhyankar {
21345f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21355f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
2136caf410d2SHong Zhang   PetscBool      iascii;
2137caf410d2SHong Zhang   PetscMPIInt    rank;
2138caf410d2SHong Zhang   PetscInt       p,nsubnet;
21395f2c45f1SShri Abhyankar 
21405f2c45f1SShri Abhyankar   PetscFunctionBegin;
2141caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2142caf410d2SHong Zhang   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
2143caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2144caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2145caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2146caf410d2SHong Zhang   if (iascii) {
2147caf410d2SHong Zhang     const PetscInt    *cone,*vtx,*edges;
2148caf410d2SHong Zhang     PetscInt          vfrom,vto,i,j,nv,ne;
2149caf410d2SHong Zhang 
2150caf410d2SHong Zhang     nsubnet = network->nsubnet - network->ncsubnet; /* num of subnetworks */
2151caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
2152caf410d2SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nsubnet: %D; nsubnetCouple: %D; nEdges: %D; nVertices: %D\n",rank,nsubnet,network->ncsubnet,network->nEdges,network->nVertices);CHKERRQ(ierr);
2153caf410d2SHong Zhang 
2154caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
2155caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2156caf410d2SHong Zhang       if (ne) {
2157caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2158caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2159caf410d2SHong Zhang           p = edges[j];
2160caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2161caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2162caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2163caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2164caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2165caf410d2SHong Zhang         }
2166caf410d2SHong Zhang       }
2167caf410d2SHong Zhang     }
2168caf410d2SHong Zhang     /* Coupling subnets */
2169caf410d2SHong Zhang     nsubnet = network->nsubnet;
2170caf410d2SHong Zhang     for (; i<nsubnet; i++) {
2171caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2172caf410d2SHong Zhang       if (ne) {
2173caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D (couple): nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2174caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2175caf410d2SHong Zhang           p = edges[j];
2176caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2177caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2178caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2179caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2180caf410d2SHong Zhang         }
2181caf410d2SHong Zhang       }
2182caf410d2SHong Zhang     }
2183caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2184caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2185caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
21865f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21875f2c45f1SShri Abhyankar }
21885f2c45f1SShri Abhyankar 
21895f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
21905f2c45f1SShri Abhyankar {
21915f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21925f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21935f2c45f1SShri Abhyankar 
21945f2c45f1SShri Abhyankar   PetscFunctionBegin;
21955f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
21965f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21975f2c45f1SShri Abhyankar }
21985f2c45f1SShri Abhyankar 
21995f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
22005f2c45f1SShri Abhyankar {
22015f2c45f1SShri Abhyankar   PetscErrorCode ierr;
22025f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
22035f2c45f1SShri Abhyankar 
22045f2c45f1SShri Abhyankar   PetscFunctionBegin;
22055f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
22065f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22075f2c45f1SShri Abhyankar }
22085f2c45f1SShri Abhyankar 
22095f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
22105f2c45f1SShri Abhyankar {
22115f2c45f1SShri Abhyankar   PetscErrorCode ierr;
22125f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
22135f2c45f1SShri Abhyankar 
22145f2c45f1SShri Abhyankar   PetscFunctionBegin;
22155f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
22165f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22175f2c45f1SShri Abhyankar }
22185f2c45f1SShri Abhyankar 
22195f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
22205f2c45f1SShri Abhyankar {
22215f2c45f1SShri Abhyankar   PetscErrorCode ierr;
22225f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
22235f2c45f1SShri Abhyankar 
22245f2c45f1SShri Abhyankar   PetscFunctionBegin;
22255f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
22265f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22275f2c45f1SShri Abhyankar }
222822bbedd7SHong Zhang 
222922bbedd7SHong Zhang /*@
2230b2aacc82SHong Zhang   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex globle index
223122bbedd7SHong Zhang 
223222bbedd7SHong Zhang   Not collective
223322bbedd7SHong Zhang 
22347a7aea1fSJed Brown   Input Parameters:
223522bbedd7SHong Zhang + dm - the dm object
223622bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
223722bbedd7SHong Zhang 
22387a7aea1fSJed Brown   Output Parameters:
2239f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
224022bbedd7SHong Zhang 
2241*97bb938eSShri Abhyankar   Level: advanced
224222bbedd7SHong Zhang 
224322bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
224422bbedd7SHong Zhang @*/
224522bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
224622bbedd7SHong Zhang {
224722bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
224822bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
224922bbedd7SHong Zhang 
225022bbedd7SHong Zhang   PetscFunctionBegin;
225122bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
225222bbedd7SHong Zhang   *vg = vltog[vloc];
225322bbedd7SHong Zhang   PetscFunctionReturn(0);
225422bbedd7SHong Zhang }
225522bbedd7SHong Zhang 
225622bbedd7SHong Zhang /*@
225722bbedd7SHong Zhang   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to globle map
225822bbedd7SHong Zhang 
225922bbedd7SHong Zhang   Collective
226022bbedd7SHong Zhang 
226122bbedd7SHong Zhang   Input Parameters:
2262f0fc11ceSJed Brown . dm - the dm object
226322bbedd7SHong Zhang 
2264*97bb938eSShri Abhyankar   Level: advanced
226522bbedd7SHong Zhang 
226663029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
226722bbedd7SHong Zhang @*/
226822bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
226922bbedd7SHong Zhang {
227022bbedd7SHong Zhang   PetscErrorCode    ierr;
227122bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
227222bbedd7SHong Zhang   MPI_Comm          comm;
227363029d29SHong Zhang   PetscMPIInt       rank,size,*displs,*recvcounts,remoterank;
227422bbedd7SHong Zhang   PetscBool         ghost;
227563029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
227622bbedd7SHong Zhang   const PetscSFNode *iremote;
227722bbedd7SHong Zhang   PetscSF           vsf;
227863029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
227963029d29SHong Zhang   VecScatter        ctx;
228063029d29SHong Zhang   PetscScalar       *varr,val;
228163029d29SHong Zhang   const PetscScalar *varr_read;
228222bbedd7SHong Zhang 
228322bbedd7SHong Zhang   PetscFunctionBegin;
228422bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
228522bbedd7SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
228663029d29SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
228722bbedd7SHong Zhang 
228822bbedd7SHong Zhang   if (size == 1) {
228922bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
229022bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
229122bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
229222bbedd7SHong Zhang     network->vltog = vltog;
229322bbedd7SHong Zhang     PetscFunctionReturn(0);
229422bbedd7SHong Zhang   }
229522bbedd7SHong Zhang 
229622bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
229722bbedd7SHong Zhang   if (network->vltog) {
229822bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
229922bbedd7SHong Zhang   }
230022bbedd7SHong Zhang 
230122bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
230222bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
230322bbedd7SHong Zhang   vsf = network->vertex.sf;
230422bbedd7SHong Zhang 
230522bbedd7SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size+1,&displs,size,&recvcounts);CHKERRQ(ierr);
2306f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
230722bbedd7SHong Zhang 
230822bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
230922bbedd7SHong Zhang 
231022bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
231122bbedd7SHong Zhang   vrange[0] = 0;
231222bbedd7SHong Zhang   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRQ(ierr);
231367dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
231422bbedd7SHong Zhang 
231522bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
231622bbedd7SHong Zhang   network->vltog = vltog;
231722bbedd7SHong Zhang 
231863029d29SHong Zhang   /* Set vltog for non-ghost vertices */
231963029d29SHong Zhang   k = 0;
232022bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
232122bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
232263029d29SHong Zhang     if (ghost) continue;
232363029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
232422bbedd7SHong Zhang   }
2325f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
232663029d29SHong Zhang 
232763029d29SHong Zhang   /* Set vltog for ghost vertices */
232863029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
232963029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
233063029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
233163029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
233263029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
233363029d29SHong Zhang   for (i=0; i<nleaves; i++) {
233463029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
233563029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
233663029d29SHong Zhang   }
233763029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
233863029d29SHong Zhang 
233963029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
234063029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
234163029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
234263029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
234363029d29SHong Zhang 
234463029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
234563029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
234663029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
234763029d29SHong Zhang   for (i=0; i<N; i+=2) {
23482e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
234963029d29SHong Zhang     if (remoterank == rank) {
235063029d29SHong Zhang       k = i+1; /* row number */
23512e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
235263029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
235363029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
235463029d29SHong Zhang     }
235563029d29SHong Zhang   }
235663029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
235763029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
235863029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
235963029d29SHong Zhang 
236063029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
236163029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
236263029d29SHong Zhang   k = 0;
236363029d29SHong Zhang   for (i=0; i<nroots; i++) {
236463029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
236563029d29SHong Zhang     if (!ghost) continue;
23662e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
236763029d29SHong Zhang   }
236863029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
236963029d29SHong Zhang 
237063029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
237163029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
237263029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
237322bbedd7SHong Zhang   PetscFunctionReturn(0);
237422bbedd7SHong Zhang }
2375