xref: /petsc/src/dm/impls/network/network.c (revision 9988b9150345559c6b28853d7486979214bd010a)
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 
3572c3e9f7SHong Zhang   Level: Intermediate
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 
641b266c99SBarry Smith    Level: intermediate
651b266c99SBarry Smith 
661b266c99SBarry Smith .seealso: DMNetworkCreate()
675f2c45f1SShri Abhyankar @*/
68caf410d2SHong Zhang PetscErrorCode DMNetworkSetSizes(DM dm,PetscInt Nsubnet,PetscInt nV[], PetscInt nE[],PetscInt NsubnetCouple,PetscInt nec[])
695f2c45f1SShri Abhyankar {
705f2c45f1SShri Abhyankar   PetscErrorCode ierr;
715f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*) dm->data;
72e2aaf10cSShri Abhyankar   PetscInt       a[2],b[2],i;
735f2c45f1SShri Abhyankar 
745f2c45f1SShri Abhyankar   PetscFunctionBegin;
755f2c45f1SShri Abhyankar   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
76e2aaf10cSShri Abhyankar   if (Nsubnet <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subnetworks %D cannot be less than 1",Nsubnet);
777765340cSHong Zhang   if (NsubnetCouple < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of coupling subnetworks %D cannot be less than 0",NsubnetCouple);
787765340cSHong Zhang 
79caf410d2SHong Zhang   PetscValidLogicalCollectiveInt(dm,Nsubnet,2);
80caf410d2SHong Zhang   if (NsubnetCouple) PetscValidLogicalCollectiveInt(dm,NsubnetCouple,5);
817765340cSHong Zhang   if (network->nsubnet != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network");
827765340cSHong Zhang 
83caf410d2SHong Zhang   if (!nV || !nE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Local vertex size or edge size must be provided");
84f025b11dSHong Zhang 
85caf410d2SHong Zhang   network->nsubnet  = Nsubnet + NsubnetCouple;
86caf410d2SHong Zhang   network->ncsubnet = NsubnetCouple;
87caf410d2SHong Zhang   ierr = PetscCalloc1(Nsubnet+NsubnetCouple,&network->subnet);CHKERRQ(ierr);
88caf410d2SHong Zhang 
89caf410d2SHong Zhang   /* ----------------------------------------------------------
90caf410d2SHong Zhang    p=v or e; P=V or E
91caf410d2SHong Zhang    subnet[0].pStart   = 0
92caf410d2SHong Zhang    subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i])
93caf410d2SHong Zhang    ----------------------------------------------------------------------- */
94caf410d2SHong Zhang   for (i=0; i < Nsubnet; i++) {
95caf410d2SHong Zhang     /* Get global number of vertices and edges for subnet[i] */
96caf410d2SHong Zhang     a[0] = nV[i]; a[1] = nE[i]; /* local number of vertices (excluding ghost) and edges */
977765340cSHong Zhang     ierr = MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
98071fcb05SBarry Smith     network->subnet[i].Nvtx = b[0];
99071fcb05SBarry Smith     network->subnet[i].Nedge = b[1];
1007765340cSHong Zhang 
101caf410d2SHong Zhang     network->subnet[i].nvtx   = nV[i]; /* local nvtx, without ghost */
1027765340cSHong Zhang 
103caf410d2SHong Zhang     /* global subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */
104caf410d2SHong Zhang     network->subnet[i].vStart = network->NVertices;
1057765340cSHong Zhang     network->subnet[i].vEnd   = network->subnet[i].vStart + network->subnet[i].Nvtx;
106caf410d2SHong Zhang 
107caf410d2SHong Zhang     network->nVertices += nV[i];
1087765340cSHong Zhang     network->NVertices += network->subnet[i].Nvtx;
1097765340cSHong Zhang 
1107765340cSHong Zhang     network->subnet[i].nedge  = nE[i];
1117765340cSHong Zhang     network->subnet[i].eStart = network->nEdges;
112caf410d2SHong Zhang     network->subnet[i].eEnd   = network->subnet[i].eStart + nE[i];
113caf410d2SHong Zhang     network->nEdges += nE[i];
114caf410d2SHong Zhang     network->NEdges += network->subnet[i].Nedge;
115caf410d2SHong Zhang   }
116caf410d2SHong Zhang 
117caf410d2SHong Zhang   /* coupling subnetwork */
118caf410d2SHong Zhang   for (; i < Nsubnet+NsubnetCouple; i++) {
119caf410d2SHong Zhang     /* Get global number of coupling edges for subnet[i] */
120caf410d2SHong Zhang     ierr = MPIU_Allreduce(nec+(i-Nsubnet),&network->subnet[i].Nedge,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
121caf410d2SHong Zhang 
122caf410d2SHong Zhang     network->subnet[i].nvtx   = 0; /* We design coupling subnetwork such that it does not have its own vertices */
123caf410d2SHong Zhang     network->subnet[i].vStart = network->nVertices;
124caf410d2SHong Zhang     network->subnet[i].vEnd   = network->subnet[i].vStart;
125caf410d2SHong Zhang 
126caf410d2SHong Zhang     network->subnet[i].nedge  = nec[i-Nsubnet];
127caf410d2SHong Zhang     network->subnet[i].eStart = network->nEdges;
128caf410d2SHong Zhang     network->subnet[i].eEnd = network->subnet[i].eStart + nec[i-Nsubnet];
129caf410d2SHong Zhang     network->nEdges += nec[i-Nsubnet];
1307765340cSHong Zhang     network->NEdges += network->subnet[i].Nedge;
1317765340cSHong Zhang   }
1327765340cSHong Zhang   PetscFunctionReturn(0);
1337765340cSHong Zhang }
1347765340cSHong Zhang 
1355f2c45f1SShri Abhyankar /*@
1365f2c45f1SShri Abhyankar   DMNetworkSetEdgeList - Sets the list of local edges (vertex connectivity) for the network
1375f2c45f1SShri Abhyankar 
138d083f849SBarry Smith   Logically collective on dm
1395f2c45f1SShri Abhyankar 
1405f2c45f1SShri Abhyankar   Input Parameters:
141e3e68989SHong Zhang + dm - the dm object
142e3e68989SHong Zhang . edgelist - list of edges for each subnetwork
143e3e68989SHong Zhang - edgelistCouple - list of edges for each coupling subnetwork
1445f2c45f1SShri Abhyankar 
1455f2c45f1SShri Abhyankar   Notes:
1465f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1475f2c45f1SShri Abhyankar   not be destroyed before the call to DMNetworkLayoutSetUp
1485f2c45f1SShri Abhyankar 
1495f2c45f1SShri Abhyankar   Level: intermediate
1505f2c45f1SShri Abhyankar 
151e3e68989SHong Zhang   Example usage:
152e3e68989SHong Zhang   Consider the following 2 separate networks and a coupling network:
153e3e68989SHong Zhang 
154e3e68989SHong Zhang .vb
155e3e68989SHong Zhang  network 0: v0 -> v1 -> v2 -> v3
156e3e68989SHong Zhang  network 1: v1 -> v2 -> v0
157e3e68989SHong Zhang  coupling network: network 1: v2 -> network 0: v0
158e3e68989SHong Zhang .ve
159e3e68989SHong Zhang 
160e3e68989SHong Zhang  The resulting input
161e3e68989SHong Zhang    edgelist[0] = [0 1 | 1 2 | 2 3];
162e3e68989SHong Zhang    edgelist[1] = [1 2 | 2 0]
163e3e68989SHong Zhang    edgelistCouple[0] = [(network)1 (v)2 (network)0 (v)0].
164e3e68989SHong Zhang 
1655f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkSetSizes
1665f2c45f1SShri Abhyankar @*/
1674e18019cSBarry Smith PetscErrorCode DMNetworkSetEdgeList(DM dm,PetscInt *edgelist[],PetscInt *edgelistCouple[])
1685f2c45f1SShri Abhyankar {
1695f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*) dm->data;
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 
1875f2c45f1SShri Abhyankar   Input Parameters
1885f2c45f1SShri Abhyankar . DM - the dmnetwork object
1895f2c45f1SShri Abhyankar 
1905f2c45f1SShri Abhyankar   Notes:
1915f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
1925f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
1935f2c45f1SShri Abhyankar 
1945f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
1955f2c45f1SShri Abhyankar 
1965f2c45f1SShri Abhyankar   Level: intermediate
1975f2c45f1SShri Abhyankar 
1985f2c45f1SShri Abhyankar .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList
1995f2c45f1SShri Abhyankar @*/
2005f2c45f1SShri Abhyankar PetscErrorCode DMNetworkLayoutSetUp(DM dm)
2015f2c45f1SShri Abhyankar {
2025f2c45f1SShri Abhyankar   PetscErrorCode ierr;
2035f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
204caf410d2SHong Zhang   PetscInt       numCorners=2,spacedim=2,dim = 1; /* One dimensional network */
2053ebf9fb9SHong Zhang   PetscReal      *vertexcoords=NULL;
206caf410d2SHong Zhang   PetscInt       i,j,ctr,nsubnet,*eowners,np,*edges,*subnetvtx,vStart;
207caf410d2SHong Zhang   PetscInt       k,netid,vid, *vidxlTog,*edgelist_couple=NULL;
208caf410d2SHong Zhang   const PetscInt *cone;
209caf410d2SHong Zhang   MPI_Comm       comm;
210caf410d2SHong Zhang   PetscMPIInt    size,rank;
2116500d4abSHong Zhang 
2126500d4abSHong Zhang   PetscFunctionBegin;
213caf410d2SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
214caf410d2SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
215caf410d2SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
2166500d4abSHong Zhang 
217caf410d2SHong Zhang   /* Create the local edgelist for the network by concatenating local input edgelists of the subnetworks */
218caf410d2SHong Zhang   ierr = PetscCalloc2(numCorners*network->nVertices,&vertexcoords,2*network->nEdges,&edges);CHKERRQ(ierr);
2197765340cSHong Zhang   nsubnet = network->nsubnet - network->ncsubnet;
220caf410d2SHong Zhang   ctr = 0;
2217765340cSHong Zhang   for (i=0; i < nsubnet; i++) {
2226500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
223ba38b151SHong Zhang       edges[2*ctr]   = network->subnet[i].vStart + network->subnet[i].edgelist[2*j];
224ba38b151SHong Zhang       edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1];
2256500d4abSHong Zhang       ctr++;
2266500d4abSHong Zhang     }
2276500d4abSHong Zhang   }
2287765340cSHong Zhang 
229caf410d2SHong Zhang   /* Append local coupling edgelists of the subnetworks */
2307765340cSHong Zhang   i       = nsubnet; /* netid of coupling subnet */
2317765340cSHong Zhang   nsubnet = network->nsubnet;
2327765340cSHong Zhang   while (i < nsubnet) {
233991cf414SHong Zhang     edgelist_couple = network->subnet[i].edgelist;
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;
334*9988b915SShri 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;
375*9988b915SShri 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 
3852727e31bSShri Abhyankar   Input Parameters
386caf410d2SHong Zhang + dm - the DM object
3872727e31bSShri Abhyankar - id   - the ID (integer) of the subnetwork
3882727e31bSShri Abhyankar 
3892727e31bSShri Abhyankar   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 
418caf410d2SHong Zhang   Input Parameters
419caf410d2SHong Zhang + dm - the DM object
420caf410d2SHong Zhang - id   - the ID (integer) of the coupling subnetwork
421caf410d2SHong Zhang 
422caf410d2SHong Zhang   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 
4575f2c45f1SShri Abhyankar   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 
4625f2c45f1SShri Abhyankar    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 
4685f2c45f1SShri Abhyankar    Level: intermediate
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 
5075f2c45f1SShri Abhyankar   Output Paramters:
5085f2c45f1SShri Abhyankar + vStart - The first vertex point
5095f2c45f1SShri Abhyankar - vEnd   - One beyond the last vertex point
5105f2c45f1SShri Abhyankar 
5115f2c45f1SShri Abhyankar   Level: intermediate
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 
5335f2c45f1SShri Abhyankar   Output Paramters:
5345f2c45f1SShri Abhyankar + eStart - The first edge point
5355f2c45f1SShri Abhyankar - eEnd   - One beyond the last edge point
5365f2c45f1SShri Abhyankar 
5375f2c45f1SShri Abhyankar   Level: intermediate
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 
5607b6afd5bSHong Zhang   Output Paramters:
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 
591e85e6aecSHong Zhang   Output Paramters:
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 
663c3b11c7cSShri Abhyankar   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 
681c3b11c7cSShri Abhyankar   Level: intermediate
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 
7085f2c45f1SShri Abhyankar   Level: intermediate
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];
727*9988b915SShri 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 /*@
735*9988b915SShri Abhyankar   DMNetworkSetComponentNumVariables - Sets the number of variables for a component
736*9988b915SShri Abhyankar 
737*9988b915SShri Abhyankar   Not Collective
738*9988b915SShri Abhyankar 
739*9988b915SShri Abhyankar   Input Parameters:
740*9988b915SShri Abhyankar + dm           - The DMNetwork object
741*9988b915SShri Abhyankar . p            - vertex/edge point
742*9988b915SShri Abhyankar . compnum      - component number (First component added = 0, second = 1, ...)
743*9988b915SShri Abhyankar - nvar         - number of variables for the component
744*9988b915SShri Abhyankar 
745*9988b915SShri Abhyankar   Level: intermediate
746*9988b915SShri Abhyankar 
747*9988b915SShri Abhyankar .seealso: DMNetworkAddComponent, DMNetworkGetNumComponents,DMNetworkRegisterComponent
748*9988b915SShri Abhyankar @*/
749*9988b915SShri Abhyankar PetscErrorCode DMNetworkSetComponentNumVariables(DM dm, PetscInt p,PetscInt compnum,PetscInt nvar)
750*9988b915SShri Abhyankar {
751*9988b915SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
752*9988b915SShri Abhyankar   DMNetworkComponentHeader header = &network->header[p];
753*9988b915SShri Abhyankar   PetscErrorCode           ierr;
754*9988b915SShri Abhyankar 
755*9988b915SShri Abhyankar   PetscFunctionBegin;
756*9988b915SShri Abhyankar 
757*9988b915SShri Abhyankar   ierr = DMNetworkAddNumVariables(dm,p,nvar);CHKERRQ(ierr);
758*9988b915SShri Abhyankar   header->nvar[compnum] = nvar;
759*9988b915SShri Abhyankar   if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum-1] + header->nvar[compnum-1];
760*9988b915SShri Abhyankar 
761*9988b915SShri Abhyankar   PetscFunctionReturn(0);
762*9988b915SShri Abhyankar }
763*9988b915SShri Abhyankar 
764*9988b915SShri Abhyankar /*@
7655f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
7665f2c45f1SShri Abhyankar 
7675f2c45f1SShri Abhyankar   Not Collective
7685f2c45f1SShri Abhyankar 
7695f2c45f1SShri Abhyankar   Input Parameters:
7705f2c45f1SShri Abhyankar + dm - The DMNetwork object
771a2b725a8SWilliam Gropp - p  - vertex/edge point
7725f2c45f1SShri Abhyankar 
7735f2c45f1SShri Abhyankar   Output Parameters:
7745f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
7755f2c45f1SShri Abhyankar 
7765f2c45f1SShri Abhyankar   Level: intermediate
7775f2c45f1SShri Abhyankar 
7785f2c45f1SShri Abhyankar .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent
7795f2c45f1SShri Abhyankar @*/
7805f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
7815f2c45f1SShri Abhyankar {
7825f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7835f2c45f1SShri Abhyankar   PetscInt       offset;
7845f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7855f2c45f1SShri Abhyankar 
7865f2c45f1SShri Abhyankar   PetscFunctionBegin;
7875f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
7885f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
7895f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7905f2c45f1SShri Abhyankar }
7915f2c45f1SShri Abhyankar 
7925f2c45f1SShri Abhyankar /*@
7935f2c45f1SShri Abhyankar   DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector.
7945f2c45f1SShri Abhyankar 
7955f2c45f1SShri Abhyankar   Not Collective
7965f2c45f1SShri Abhyankar 
7975f2c45f1SShri Abhyankar   Input Parameters:
7985f2c45f1SShri Abhyankar + dm     - The DMNetwork object
7995f2c45f1SShri Abhyankar - p      - the edge/vertex point
8005f2c45f1SShri Abhyankar 
8015f2c45f1SShri Abhyankar   Output Parameters:
8025f2c45f1SShri Abhyankar . offset - the offset
8035f2c45f1SShri Abhyankar 
8045f2c45f1SShri Abhyankar   Level: intermediate
8055f2c45f1SShri Abhyankar 
8065f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
8075f2c45f1SShri Abhyankar @*/
8085f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset)
8095f2c45f1SShri Abhyankar {
8105f2c45f1SShri Abhyankar   PetscErrorCode ierr;
8115f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8125f2c45f1SShri Abhyankar 
8135f2c45f1SShri Abhyankar   PetscFunctionBegin;
8141bb6d2a8SBarry Smith   ierr = PetscSectionGetOffset(network->plex->localSection,p,offset);CHKERRQ(ierr);
8155f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8165f2c45f1SShri Abhyankar }
8175f2c45f1SShri Abhyankar 
8185f2c45f1SShri Abhyankar /*@
8195f2c45f1SShri Abhyankar   DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector.
8205f2c45f1SShri Abhyankar 
8215f2c45f1SShri Abhyankar   Not Collective
8225f2c45f1SShri Abhyankar 
8235f2c45f1SShri Abhyankar   Input Parameters:
8245f2c45f1SShri Abhyankar + dm      - The DMNetwork object
8255f2c45f1SShri Abhyankar - p       - the edge/vertex point
8265f2c45f1SShri Abhyankar 
8275f2c45f1SShri Abhyankar   Output Parameters:
8285f2c45f1SShri Abhyankar . offsetg - the offset
8295f2c45f1SShri Abhyankar 
8305f2c45f1SShri Abhyankar   Level: intermediate
8315f2c45f1SShri Abhyankar 
8325f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableOffset, DMGetLocalVector
8335f2c45f1SShri Abhyankar @*/
8345f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg)
8355f2c45f1SShri Abhyankar {
8365f2c45f1SShri Abhyankar   PetscErrorCode ierr;
8375f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8385f2c45f1SShri Abhyankar 
8395f2c45f1SShri Abhyankar   PetscFunctionBegin;
8401bb6d2a8SBarry Smith   ierr = PetscSectionGetOffset(network->plex->globalSection,p,offsetg);CHKERRQ(ierr);
8416fefedf4SHong Zhang   if (*offsetg < 0) *offsetg = -(*offsetg + 1); /* Convert to actual global offset for ghost vertex */
8425f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8435f2c45f1SShri Abhyankar }
8445f2c45f1SShri Abhyankar 
84524121865SAdrian Maldonado /*@
846*9988b915SShri Abhyankar   DMNetworkGetComponentVariableOffset - Get the offset for accessing the variable associated with a component for the given vertex/edge from the local vector.
847*9988b915SShri Abhyankar 
848*9988b915SShri Abhyankar   Not Collective
849*9988b915SShri Abhyankar 
850*9988b915SShri Abhyankar   Input Parameters:
851*9988b915SShri Abhyankar + dm     - The DMNetwork object
852*9988b915SShri Abhyankar . compnum - component number
853*9988b915SShri Abhyankar - p      - the edge/vertex point
854*9988b915SShri Abhyankar 
855*9988b915SShri Abhyankar   Output Parameters:
856*9988b915SShri Abhyankar . offset - the offset
857*9988b915SShri Abhyankar 
858*9988b915SShri Abhyankar   Level: intermediate
859*9988b915SShri Abhyankar 
860*9988b915SShri Abhyankar .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector, DMNetworkSetComponentNumVariables
861*9988b915SShri Abhyankar @*/
862*9988b915SShri Abhyankar PetscErrorCode DMNetworkGetComponentVariableOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offset)
863*9988b915SShri Abhyankar {
864*9988b915SShri Abhyankar   PetscErrorCode ierr;
865*9988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
866*9988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
867*9988b915SShri Abhyankar   DMNetworkComponentHeader header;
868*9988b915SShri Abhyankar 
869*9988b915SShri Abhyankar   PetscFunctionBegin;
870*9988b915SShri Abhyankar   ierr = DMNetworkGetVariableOffset(dm,p,&offsetp);CHKERRQ(ierr);
871*9988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
872*9988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
873*9988b915SShri Abhyankar   *offset = offsetp + header->offsetvarrel[compnum];
874*9988b915SShri Abhyankar   PetscFunctionReturn(0);
875*9988b915SShri Abhyankar }
876*9988b915SShri Abhyankar 
877*9988b915SShri Abhyankar /*@
878*9988b915SShri Abhyankar   DMNetworkGetComponentVariableGlobalOffset - Get the global offset for accessing the variable associated with a component for the given vertex/edge from the local vector.
879*9988b915SShri Abhyankar 
880*9988b915SShri Abhyankar   Not Collective
881*9988b915SShri Abhyankar 
882*9988b915SShri Abhyankar   Input Parameters:
883*9988b915SShri Abhyankar + dm     - The DMNetwork object
884*9988b915SShri Abhyankar . compnum - component number
885*9988b915SShri Abhyankar - p      - the edge/vertex point
886*9988b915SShri Abhyankar 
887*9988b915SShri Abhyankar   Output Parameters:
888*9988b915SShri Abhyankar . offsetg - the global offset
889*9988b915SShri Abhyankar 
890*9988b915SShri Abhyankar   Level: intermediate
891*9988b915SShri Abhyankar 
892*9988b915SShri Abhyankar .seealso: DMNetworkGetVariableGlobalOffset, DMNetworkGetComponentVariableOffset, DMGetLocalVector, DMNetworkSetComponentNumVariables
893*9988b915SShri Abhyankar @*/
894*9988b915SShri Abhyankar PetscErrorCode DMNetworkGetComponentVariableGlobalOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offsetg)
895*9988b915SShri Abhyankar {
896*9988b915SShri Abhyankar   PetscErrorCode ierr;
897*9988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
898*9988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
899*9988b915SShri Abhyankar   DMNetworkComponentHeader header;
900*9988b915SShri Abhyankar 
901*9988b915SShri Abhyankar   PetscFunctionBegin;
902*9988b915SShri Abhyankar   ierr = DMNetworkGetVariableGlobalOffset(dm,p,&offsetp);CHKERRQ(ierr);
903*9988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
904*9988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
905*9988b915SShri Abhyankar   *offsetg = offsetp + header->offsetvarrel[compnum];
906*9988b915SShri Abhyankar   PetscFunctionReturn(0);
907*9988b915SShri Abhyankar }
908*9988b915SShri Abhyankar 
909*9988b915SShri Abhyankar /*@
91024121865SAdrian Maldonado   DMNetworkGetEdgeOffset - Get the offset for accessing the variable associated with the given edge from the local subvector.
91124121865SAdrian Maldonado 
91224121865SAdrian Maldonado   Not Collective
91324121865SAdrian Maldonado 
91424121865SAdrian Maldonado   Input Parameters:
91524121865SAdrian Maldonado + dm     - The DMNetwork object
91624121865SAdrian Maldonado - p      - the edge point
91724121865SAdrian Maldonado 
91824121865SAdrian Maldonado   Output Parameters:
91924121865SAdrian Maldonado . offset - the offset
92024121865SAdrian Maldonado 
92124121865SAdrian Maldonado   Level: intermediate
92224121865SAdrian Maldonado 
92324121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
92424121865SAdrian Maldonado @*/
92524121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
92624121865SAdrian Maldonado {
92724121865SAdrian Maldonado   PetscErrorCode ierr;
92824121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
92924121865SAdrian Maldonado 
93024121865SAdrian Maldonado   PetscFunctionBegin;
93124121865SAdrian Maldonado 
93224121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
93324121865SAdrian Maldonado   PetscFunctionReturn(0);
93424121865SAdrian Maldonado }
93524121865SAdrian Maldonado 
93624121865SAdrian Maldonado /*@
93724121865SAdrian Maldonado   DMNetworkGetVertexOffset - Get the offset for accessing the variable associated with the given vertex from the local subvector.
93824121865SAdrian Maldonado 
93924121865SAdrian Maldonado   Not Collective
94024121865SAdrian Maldonado 
94124121865SAdrian Maldonado   Input Parameters:
94224121865SAdrian Maldonado + dm     - The DMNetwork object
94324121865SAdrian Maldonado - p      - the vertex point
94424121865SAdrian Maldonado 
94524121865SAdrian Maldonado   Output Parameters:
94624121865SAdrian Maldonado . offset - the offset
94724121865SAdrian Maldonado 
94824121865SAdrian Maldonado   Level: intermediate
94924121865SAdrian Maldonado 
95024121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
95124121865SAdrian Maldonado @*/
95224121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
95324121865SAdrian Maldonado {
95424121865SAdrian Maldonado   PetscErrorCode ierr;
95524121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
95624121865SAdrian Maldonado 
95724121865SAdrian Maldonado   PetscFunctionBegin;
95824121865SAdrian Maldonado 
95924121865SAdrian Maldonado   p -= network->vStart;
96024121865SAdrian Maldonado 
96124121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
96224121865SAdrian Maldonado   PetscFunctionReturn(0);
96324121865SAdrian Maldonado }
9645f2c45f1SShri Abhyankar /*@
9655f2c45f1SShri Abhyankar   DMNetworkAddNumVariables - Add number of variables associated with a given point.
9665f2c45f1SShri Abhyankar 
9675f2c45f1SShri Abhyankar   Not Collective
9685f2c45f1SShri Abhyankar 
9695f2c45f1SShri Abhyankar   Input Parameters:
9705f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
9715f2c45f1SShri Abhyankar . p    - the vertex/edge point
9725f2c45f1SShri Abhyankar - nvar - number of additional variables
9735f2c45f1SShri Abhyankar 
9745f2c45f1SShri Abhyankar   Level: intermediate
9755f2c45f1SShri Abhyankar 
9765f2c45f1SShri Abhyankar .seealso: DMNetworkSetNumVariables
9775f2c45f1SShri Abhyankar @*/
9785f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar)
9795f2c45f1SShri Abhyankar {
9805f2c45f1SShri Abhyankar   PetscErrorCode ierr;
9815f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
9825f2c45f1SShri Abhyankar 
9835f2c45f1SShri Abhyankar   PetscFunctionBegin;
9845f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
9855f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9865f2c45f1SShri Abhyankar }
9875f2c45f1SShri Abhyankar 
98827f51fceSHong Zhang /*@
98927f51fceSHong Zhang   DMNetworkGetNumVariables - Gets number of variables for a vertex/edge point.
99027f51fceSHong Zhang 
99127f51fceSHong Zhang   Not Collective
99227f51fceSHong Zhang 
99327f51fceSHong Zhang   Input Parameters:
99427f51fceSHong Zhang + dm   - The DMNetworkObject
99527f51fceSHong Zhang - p    - the vertex/edge point
99627f51fceSHong Zhang 
99727f51fceSHong Zhang   Output Parameters:
99827f51fceSHong Zhang . nvar - number of variables
99927f51fceSHong Zhang 
100027f51fceSHong Zhang   Level: intermediate
100127f51fceSHong Zhang 
100227f51fceSHong Zhang .seealso: DMNetworkAddNumVariables, DMNetworkSddNumVariables
100327f51fceSHong Zhang @*/
100427f51fceSHong Zhang PetscErrorCode DMNetworkGetNumVariables(DM dm,PetscInt p,PetscInt *nvar)
100527f51fceSHong Zhang {
100627f51fceSHong Zhang   PetscErrorCode ierr;
100727f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
100827f51fceSHong Zhang 
100927f51fceSHong Zhang   PetscFunctionBegin;
101027f51fceSHong Zhang   ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
101127f51fceSHong Zhang   PetscFunctionReturn(0);
101227f51fceSHong Zhang }
101327f51fceSHong Zhang 
10145f2c45f1SShri Abhyankar /*@
10155f2c45f1SShri Abhyankar   DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point.
10165f2c45f1SShri Abhyankar 
10175f2c45f1SShri Abhyankar   Not Collective
10185f2c45f1SShri Abhyankar 
10195f2c45f1SShri Abhyankar   Input Parameters:
10205f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
10215f2c45f1SShri Abhyankar . p    - the vertex/edge point
10225f2c45f1SShri Abhyankar - nvar - number of variables
10235f2c45f1SShri Abhyankar 
10245f2c45f1SShri Abhyankar   Level: intermediate
10255f2c45f1SShri Abhyankar 
10265f2c45f1SShri Abhyankar .seealso: DMNetworkAddNumVariables
10275f2c45f1SShri Abhyankar @*/
10285f2c45f1SShri Abhyankar PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar)
10295f2c45f1SShri Abhyankar {
10305f2c45f1SShri Abhyankar   PetscErrorCode ierr;
10315f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10325f2c45f1SShri Abhyankar 
10335f2c45f1SShri Abhyankar   PetscFunctionBegin;
10345f2c45f1SShri Abhyankar   ierr = PetscSectionSetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
10355f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10365f2c45f1SShri Abhyankar }
10375f2c45f1SShri Abhyankar 
10385f2c45f1SShri Abhyankar /* Sets up the array that holds the data for all components and its associated section. This
10395f2c45f1SShri Abhyankar    function is called during DMSetUp() */
10405f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
10415f2c45f1SShri Abhyankar {
10425f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
10435f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
1044e53b5ba3SHong Zhang   PetscInt                 arr_size,p,offset,offsetp,ncomp,i;
10455f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
10465f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
10475f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
10485f2c45f1SShri Abhyankar 
10495f2c45f1SShri Abhyankar   PetscFunctionBegin;
10505f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
10515f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
105275b160a0SShri Abhyankar   ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
10535f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
10545f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
10555f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
10565f2c45f1SShri Abhyankar     /* Copy header */
10575f2c45f1SShri Abhyankar     header = &network->header[p];
1058302440fdSBarry Smith     ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
10595f2c45f1SShri Abhyankar     /* Copy data */
10605f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
10615f2c45f1SShri Abhyankar     ncomp = header->ndata;
10625f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
10635f2c45f1SShri Abhyankar       offset = offsetp + network->dataheadersize + header->offset[i];
1064302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
10655f2c45f1SShri Abhyankar     }
10665f2c45f1SShri Abhyankar   }
10675f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10685f2c45f1SShri Abhyankar }
10695f2c45f1SShri Abhyankar 
10705f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
10715f2c45f1SShri Abhyankar PetscErrorCode DMNetworkVariablesSetUp(DM dm)
10725f2c45f1SShri Abhyankar {
10735f2c45f1SShri Abhyankar   PetscErrorCode ierr;
10745f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10755f2c45f1SShri Abhyankar 
10765f2c45f1SShri Abhyankar   PetscFunctionBegin;
10775f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
10785f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10795f2c45f1SShri Abhyankar }
10805f2c45f1SShri Abhyankar 
10815f2c45f1SShri Abhyankar /*@C
10825f2c45f1SShri Abhyankar   DMNetworkGetComponentDataArray - Returns the component data array
10835f2c45f1SShri Abhyankar 
10845f2c45f1SShri Abhyankar   Not Collective
10855f2c45f1SShri Abhyankar 
10865f2c45f1SShri Abhyankar   Input Parameters:
10875f2c45f1SShri Abhyankar . dm - The DMNetwork Object
10885f2c45f1SShri Abhyankar 
10895f2c45f1SShri Abhyankar   Output Parameters:
10905f2c45f1SShri Abhyankar . componentdataarray - array that holds data for all components
10915f2c45f1SShri Abhyankar 
10925f2c45f1SShri Abhyankar   Level: intermediate
10935f2c45f1SShri Abhyankar 
1094a730d845SHong Zhang .seealso: DMNetworkGetComponentKeyOffset, DMNetworkGetNumComponents
10955f2c45f1SShri Abhyankar @*/
10965f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray)
10975f2c45f1SShri Abhyankar {
10985f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10995f2c45f1SShri Abhyankar 
11005f2c45f1SShri Abhyankar   PetscFunctionBegin;
11015f2c45f1SShri Abhyankar   *componentdataarray = network->componentdataarray;
11025f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
11035f2c45f1SShri Abhyankar }
11045f2c45f1SShri Abhyankar 
110524121865SAdrian Maldonado /* Get a subsection from a range of points */
110624121865SAdrian Maldonado PetscErrorCode DMNetworkGetSubSection_private(PetscSection master, PetscInt pstart, PetscInt pend,PetscSection *subsection)
110724121865SAdrian Maldonado {
110824121865SAdrian Maldonado   PetscErrorCode ierr;
110924121865SAdrian Maldonado   PetscInt       i, nvar;
111024121865SAdrian Maldonado 
111124121865SAdrian Maldonado   PetscFunctionBegin;
111224121865SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)master), subsection);CHKERRQ(ierr);
111324121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
111424121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
111524121865SAdrian Maldonado     ierr = PetscSectionGetDof(master,i,&nvar);CHKERRQ(ierr);
111624121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
111724121865SAdrian Maldonado   }
111824121865SAdrian Maldonado 
111924121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
112024121865SAdrian Maldonado   PetscFunctionReturn(0);
112124121865SAdrian Maldonado }
112224121865SAdrian Maldonado 
112324121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
112424121865SAdrian Maldonado PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
112524121865SAdrian Maldonado {
112624121865SAdrian Maldonado   PetscErrorCode ierr;
112724121865SAdrian Maldonado   PetscInt       i, *subpoints;
112824121865SAdrian Maldonado 
112924121865SAdrian Maldonado   PetscFunctionBegin;
113024121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
113124121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
113224121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
113324121865SAdrian Maldonado     subpoints[i - pstart] = i;
113424121865SAdrian Maldonado   }
1135459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
113624121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
113724121865SAdrian Maldonado   PetscFunctionReturn(0);
113824121865SAdrian Maldonado }
113924121865SAdrian Maldonado 
114024121865SAdrian Maldonado /*@
114124121865SAdrian Maldonado   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute.
114224121865SAdrian Maldonado 
114324121865SAdrian Maldonado   Collective
114424121865SAdrian Maldonado 
114524121865SAdrian Maldonado   Input Parameters:
114624121865SAdrian Maldonado . dm   - The DMNetworkObject
114724121865SAdrian Maldonado 
114824121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
114924121865SAdrian Maldonado 
115024121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
115124121865SAdrian Maldonado 
1152caf410d2SHong 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]).
115324121865SAdrian Maldonado 
115424121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
115524121865SAdrian Maldonado 
115624121865SAdrian Maldonado   Level: intermediate
115724121865SAdrian Maldonado 
115824121865SAdrian Maldonado @*/
115924121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
116024121865SAdrian Maldonado {
116124121865SAdrian Maldonado   PetscErrorCode ierr;
116224121865SAdrian Maldonado   MPI_Comm       comm;
11639852e123SBarry Smith   PetscMPIInt    rank, size;
116424121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
116524121865SAdrian Maldonado 
1166eab1376dSHong Zhang   PetscFunctionBegin;
116724121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
116824121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
11699852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
117024121865SAdrian Maldonado 
117124121865SAdrian Maldonado   /* Create maps for vertices and edges */
117224121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
117324121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
117424121865SAdrian Maldonado 
117524121865SAdrian Maldonado   /* Create local sub-sections */
117624121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
117724121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
117824121865SAdrian Maldonado 
11799852e123SBarry Smith   if (size > 1) {
118024121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
118122bbedd7SHong Zhang 
118224121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
118324121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
118424121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
118524121865SAdrian Maldonado   } else {
118624121865SAdrian Maldonado     /* create structures for vertex */
118724121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
118824121865SAdrian Maldonado     /* create structures for edge */
118924121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
119024121865SAdrian Maldonado   }
119124121865SAdrian Maldonado 
119224121865SAdrian Maldonado   /* Add viewers */
119324121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
119424121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
119524121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
119624121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
119724121865SAdrian Maldonado   PetscFunctionReturn(0);
119824121865SAdrian Maldonado }
11997b6afd5bSHong Zhang 
12005f2c45f1SShri Abhyankar /*@
12015f2c45f1SShri Abhyankar   DMNetworkDistribute - Distributes the network and moves associated component data.
12025f2c45f1SShri Abhyankar 
12035f2c45f1SShri Abhyankar   Collective
12045f2c45f1SShri Abhyankar 
12055f2c45f1SShri Abhyankar   Input Parameter:
1206d3464fd4SAdrian Maldonado + DM - the DMNetwork object
12075f2c45f1SShri Abhyankar - overlap - The overlap of partitions, 0 is the default
12085f2c45f1SShri Abhyankar 
12095f2c45f1SShri Abhyankar   Notes:
12108b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
12115f2c45f1SShri Abhyankar 
12125f2c45f1SShri Abhyankar   Level: intermediate
12135f2c45f1SShri Abhyankar 
12145f2c45f1SShri Abhyankar .seealso: DMNetworkCreate
12155f2c45f1SShri Abhyankar @*/
1216d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
12175f2c45f1SShri Abhyankar {
1218d3464fd4SAdrian Maldonado   MPI_Comm       comm;
12195f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1220d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1221d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1222d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1223caf410d2SHong Zhang   PetscSF        pointsf=NULL;
12245f2c45f1SShri Abhyankar   DM             newDM;
1225caf410d2SHong Zhang   PetscInt       j,e,v,offset,*subnetvtx;
122651ac5effSHong Zhang   PetscPartitioner         part;
1227b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
12285f2c45f1SShri Abhyankar 
12295f2c45f1SShri Abhyankar   PetscFunctionBegin;
1230d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1231d3464fd4SAdrian Maldonado   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
1232d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1233d3464fd4SAdrian Maldonado 
1234d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
12355f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
12365f2c45f1SShri Abhyankar   newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
123751ac5effSHong Zhang 
123851ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
123951ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
124051ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
124151ac5effSHong Zhang 
12425f2c45f1SShri Abhyankar   /* Distribute plex dm and dof section */
124380cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
124451ac5effSHong Zhang 
12455f2c45f1SShri Abhyankar   /* Distribute dof section */
1246d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DofSection);CHKERRQ(ierr);
12475f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
1248d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DataSection);CHKERRQ(ierr);
124951ac5effSHong Zhang 
12505f2c45f1SShri Abhyankar   /* Distribute data and associated section */
125131da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
125224121865SAdrian Maldonado 
12535f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
12545f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
12555f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
12565f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
12576fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
12586fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
12595f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
126024121865SAdrian Maldonado 
12611bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
126292fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1263e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
12645f2c45f1SShri Abhyankar 
1265b9c6e19dSShri Abhyankar   /* Set up subnetwork info in the newDM */
1266b9c6e19dSShri Abhyankar   newDMnetwork->nsubnet  = oldDMnetwork->nsubnet;
1267caf410d2SHong Zhang   newDMnetwork->ncsubnet = oldDMnetwork->ncsubnet;
1268b9c6e19dSShri Abhyankar   ierr = PetscCalloc1(newDMnetwork->nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
1269b9c6e19dSShri Abhyankar   /* Copy over the global number of vertices and edges in each subnetwork. Note that these are already
1270b9c6e19dSShri Abhyankar      calculated in DMNetworkLayoutSetUp()
1271b9c6e19dSShri Abhyankar   */
1272b9c6e19dSShri Abhyankar   for(j=0; j < newDMnetwork->nsubnet; j++) {
1273b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1274b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1275b9c6e19dSShri Abhyankar   }
1276b9c6e19dSShri Abhyankar 
1277b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1278b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1279b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1280b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1281b9c6e19dSShri Abhyankar   }
1282b9c6e19dSShri Abhyankar 
1283b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1284b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1285b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1286b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nvtx++;
1287b9c6e19dSShri Abhyankar   }
1288b9c6e19dSShri Abhyankar 
1289b9c6e19dSShri Abhyankar   /* Now create the vertices and edge arrays for the subnetworks */
1290caf410d2SHong Zhang   ierr = PetscCalloc1(newDMnetwork->vEnd-newDMnetwork->vStart,&newDMnetwork->subnetvtx);CHKERRQ(ierr);
1291caf410d2SHong Zhang   subnetvtx = newDMnetwork->subnetvtx;
1292caf410d2SHong Zhang 
1293b9c6e19dSShri Abhyankar   for (j=0; j<newDMnetwork->nsubnet; j++) {
1294b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr);
1295caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1296caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1297caf410d2SHong Zhang 
1298b9c6e19dSShri Abhyankar     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
1299b9c6e19dSShri Abhyankar        These get updated when the vertices and edges are added. */
1300b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1301b9c6e19dSShri Abhyankar   }
1302b9c6e19dSShri Abhyankar 
1303b9c6e19dSShri Abhyankar   /* Set the vertices and edges in each subnetwork */
1304b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1305b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1306b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1307b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1308b9c6e19dSShri Abhyankar   }
1309b9c6e19dSShri Abhyankar 
1310b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1311b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1312b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1313b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
1314b9c6e19dSShri Abhyankar   }
1315b9c6e19dSShri Abhyankar 
1316caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
131722bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1318caf410d2SHong Zhang 
131924121865SAdrian Maldonado   /* Destroy point SF */
132024121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
132124121865SAdrian Maldonado 
1322d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
1323d3464fd4SAdrian Maldonado   *dm  = newDM;
13245f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13255f2c45f1SShri Abhyankar }
13265f2c45f1SShri Abhyankar 
132724121865SAdrian Maldonado /*@C
132824121865SAdrian Maldonado   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering.
132924121865SAdrian Maldonado 
133024121865SAdrian Maldonado   Input Parameters:
133124121865SAdrian Maldonado + masterSF - the original SF structure
133224121865SAdrian Maldonado - map      - a ISLocalToGlobal mapping that contains the subset of points
133324121865SAdrian Maldonado 
133424121865SAdrian Maldonado   Output Parameters:
133524121865SAdrian Maldonado . subSF    - a subset of the masterSF for the desired subset.
133624121865SAdrian Maldonado */
133724121865SAdrian Maldonado 
133824121865SAdrian Maldonado PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) {
133924121865SAdrian Maldonado 
134024121865SAdrian Maldonado   PetscErrorCode        ierr;
134124121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
134224121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
134324121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
134424121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
134524121865SAdrian Maldonado   const PetscInt        *ilocal;
134624121865SAdrian Maldonado   const PetscSFNode     *iremote;
134724121865SAdrian Maldonado 
134824121865SAdrian Maldonado   PetscFunctionBegin;
134924121865SAdrian Maldonado   ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
135024121865SAdrian Maldonado 
135124121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
135224121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
135324121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
135424121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
135524121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
135624121865SAdrian Maldonado   }
135724121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
135824121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
135924121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
136024121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
136124121865SAdrian Maldonado   ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
136224121865SAdrian Maldonado   ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
136324121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
13644b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
13654b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
136624121865SAdrian Maldonado   nleaves_sub = 0;
136724121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
136824121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
136924121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
13704b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
137124121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
137224121865SAdrian Maldonado       nleaves_sub += 1;
137324121865SAdrian Maldonado     }
137424121865SAdrian Maldonado   }
137524121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
137624121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
137724121865SAdrian Maldonado 
137824121865SAdrian Maldonado   /* Create new subSF */
137924121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
138024121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
13814b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
138224121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
13834b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
138424121865SAdrian Maldonado   PetscFunctionReturn(0);
138524121865SAdrian Maldonado }
138624121865SAdrian Maldonado 
13875f2c45f1SShri Abhyankar /*@C
13885f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
13895f2c45f1SShri Abhyankar 
13905f2c45f1SShri Abhyankar   Not Collective
13915f2c45f1SShri Abhyankar 
13925f2c45f1SShri Abhyankar   Input Parameters:
13935f2c45f1SShri Abhyankar + dm - The DMNetwork object
13945f2c45f1SShri Abhyankar - p  - the vertex point
13955f2c45f1SShri Abhyankar 
13965f2c45f1SShri Abhyankar   Output Paramters:
13975f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
13985f2c45f1SShri Abhyankar - edges  - List of edge points
13995f2c45f1SShri Abhyankar 
14005f2c45f1SShri Abhyankar   Level: intermediate
14015f2c45f1SShri Abhyankar 
14025f2c45f1SShri Abhyankar   Fortran Notes:
14035f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
14045f2c45f1SShri Abhyankar   include petsc.h90 in your code.
14055f2c45f1SShri Abhyankar 
1406d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices
14075f2c45f1SShri Abhyankar @*/
14085f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
14095f2c45f1SShri Abhyankar {
14105f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14115f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14125f2c45f1SShri Abhyankar 
14135f2c45f1SShri Abhyankar   PetscFunctionBegin;
14145f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
14155f2c45f1SShri Abhyankar   ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);
14165f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14175f2c45f1SShri Abhyankar }
14185f2c45f1SShri Abhyankar 
14195f2c45f1SShri Abhyankar /*@C
1420d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
14215f2c45f1SShri Abhyankar 
14225f2c45f1SShri Abhyankar   Not Collective
14235f2c45f1SShri Abhyankar 
14245f2c45f1SShri Abhyankar   Input Parameters:
14255f2c45f1SShri Abhyankar + dm - The DMNetwork object
14265f2c45f1SShri Abhyankar - p  - the edge point
14275f2c45f1SShri Abhyankar 
14285f2c45f1SShri Abhyankar   Output Paramters:
14295f2c45f1SShri Abhyankar . vertices  - vertices connected to this edge
14305f2c45f1SShri Abhyankar 
14315f2c45f1SShri Abhyankar   Level: intermediate
14325f2c45f1SShri Abhyankar 
14335f2c45f1SShri Abhyankar   Fortran Notes:
14345f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
14355f2c45f1SShri Abhyankar   include petsc.h90 in your code.
14365f2c45f1SShri Abhyankar 
14375f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
14385f2c45f1SShri Abhyankar @*/
1439d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
14405f2c45f1SShri Abhyankar {
14415f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14425f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14435f2c45f1SShri Abhyankar 
14445f2c45f1SShri Abhyankar   PetscFunctionBegin;
14455f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
14465f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14475f2c45f1SShri Abhyankar }
14485f2c45f1SShri Abhyankar 
14495f2c45f1SShri Abhyankar /*@
14505f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
14515f2c45f1SShri Abhyankar 
14525f2c45f1SShri Abhyankar   Not Collective
14535f2c45f1SShri Abhyankar 
14545f2c45f1SShri Abhyankar   Input Parameters:
14555f2c45f1SShri Abhyankar + dm - The DMNetwork object
1456a2b725a8SWilliam Gropp - p  - the vertex point
14575f2c45f1SShri Abhyankar 
14585f2c45f1SShri Abhyankar   Output Parameter:
14595f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
14605f2c45f1SShri Abhyankar 
14615f2c45f1SShri Abhyankar   Level: intermediate
14625f2c45f1SShri Abhyankar 
1463d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange
14645f2c45f1SShri Abhyankar @*/
14655f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
14665f2c45f1SShri Abhyankar {
14675f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14685f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14695f2c45f1SShri Abhyankar   PetscInt       offsetg;
14705f2c45f1SShri Abhyankar   PetscSection   sectiong;
14715f2c45f1SShri Abhyankar 
14725f2c45f1SShri Abhyankar   PetscFunctionBegin;
1473caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
14745f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
1475e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
14765f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
14775f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
14785f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14795f2c45f1SShri Abhyankar }
14805f2c45f1SShri Abhyankar 
14815f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
14825f2c45f1SShri Abhyankar {
14835f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14845f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
14855f2c45f1SShri Abhyankar 
14865f2c45f1SShri Abhyankar   PetscFunctionBegin;
14875f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
14885f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
14895f2c45f1SShri Abhyankar 
149092fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
1491e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
14929e1d080bSHong Zhang 
14939e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
14949e1d080bSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr);
14955f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14965f2c45f1SShri Abhyankar }
14975f2c45f1SShri Abhyankar 
14981ad426b7SHong Zhang /*@
149917df6e9eSHong Zhang     DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
15001ad426b7SHong Zhang                             -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
15011ad426b7SHong Zhang 
15021ad426b7SHong Zhang     Collective
15031ad426b7SHong Zhang 
15041ad426b7SHong Zhang     Input Parameters:
150583b2e829SHong Zhang +   dm - The DMNetwork object
150683b2e829SHong Zhang .   eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
150783b2e829SHong Zhang -   vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
15081ad426b7SHong Zhang 
15091ad426b7SHong Zhang     Level: intermediate
15101ad426b7SHong Zhang 
15111ad426b7SHong Zhang @*/
151283b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
15131ad426b7SHong Zhang {
15141ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
15158675203cSHong Zhang   PetscErrorCode ierr;
151666b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
15171ad426b7SHong Zhang 
15181ad426b7SHong Zhang   PetscFunctionBegin;
151983b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
152083b2e829SHong Zhang   network->userVertexJacobian = vflg;
15218675203cSHong Zhang 
15228675203cSHong Zhang   if (eflg && !network->Je) {
15238675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
15248675203cSHong Zhang   }
15258675203cSHong Zhang 
152666b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
15278675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
152866b4e0ffSHong Zhang     PetscInt       nedges_total;
15298675203cSHong Zhang     const PetscInt *edges;
15308675203cSHong Zhang 
15318675203cSHong Zhang     /* count nvertex_total */
15328675203cSHong Zhang     nedges_total = 0;
15338675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
15348675203cSHong Zhang 
15358675203cSHong Zhang     vptr[0] = 0;
15368675203cSHong Zhang     for (i=0; i<nVertices; i++) {
15378675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
15388675203cSHong Zhang       nedges_total += nedges;
15398675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
15408675203cSHong Zhang     }
15418675203cSHong Zhang 
15428675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
15438675203cSHong Zhang     network->Jvptr = vptr;
15448675203cSHong Zhang   }
15451ad426b7SHong Zhang   PetscFunctionReturn(0);
15461ad426b7SHong Zhang }
15471ad426b7SHong Zhang 
15481ad426b7SHong Zhang /*@
154983b2e829SHong Zhang     DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
155083b2e829SHong Zhang 
155183b2e829SHong Zhang     Not Collective
155283b2e829SHong Zhang 
155383b2e829SHong Zhang     Input Parameters:
155483b2e829SHong Zhang +   dm - The DMNetwork object
155583b2e829SHong Zhang .   p  - the edge point
15563e97b6e8SHong Zhang -   J - array (size = 3) of Jacobian submatrices for this edge point:
15573e97b6e8SHong Zhang         J[0]: this edge
1558d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
155983b2e829SHong Zhang 
156083b2e829SHong Zhang     Level: intermediate
156183b2e829SHong Zhang 
156283b2e829SHong Zhang .seealso: DMNetworkVertexSetMatrix
156383b2e829SHong Zhang @*/
156483b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
156583b2e829SHong Zhang {
156683b2e829SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
156783b2e829SHong Zhang 
156883b2e829SHong Zhang   PetscFunctionBegin;
15698675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
15708675203cSHong Zhang 
15718675203cSHong Zhang   if (J) {
1572883e35e8SHong Zhang     network->Je[3*p]   = J[0];
1573883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
1574883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
15758675203cSHong Zhang   }
157683b2e829SHong Zhang   PetscFunctionReturn(0);
157783b2e829SHong Zhang }
157883b2e829SHong Zhang 
157983b2e829SHong Zhang /*@
158076ddfea5SHong Zhang     DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
15811ad426b7SHong Zhang 
15821ad426b7SHong Zhang     Not Collective
15831ad426b7SHong Zhang 
15841ad426b7SHong Zhang     Input Parameters:
15851ad426b7SHong Zhang +   dm - The DMNetwork object
15861ad426b7SHong Zhang .   p  - the vertex point
15873e97b6e8SHong Zhang -   J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
15883e97b6e8SHong Zhang         J[0]:       this vertex
15893e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
15903e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
15911ad426b7SHong Zhang 
15921ad426b7SHong Zhang     Level: intermediate
15931ad426b7SHong Zhang 
159483b2e829SHong Zhang .seealso: DMNetworkEdgeSetMatrix
15951ad426b7SHong Zhang @*/
1596883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
15975f2c45f1SShri Abhyankar {
15985f2c45f1SShri Abhyankar   PetscErrorCode ierr;
15995f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
16008675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
1601883e35e8SHong Zhang   const PetscInt *edges;
16025f2c45f1SShri Abhyankar 
16035f2c45f1SShri Abhyankar   PetscFunctionBegin;
16048675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1605883e35e8SHong Zhang 
16068675203cSHong Zhang   if (J) {
1607883e35e8SHong Zhang     vptr = network->Jvptr;
16083e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
16093e97b6e8SHong Zhang 
16103e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
1611883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
1612883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
16138675203cSHong Zhang   }
1614883e35e8SHong Zhang   PetscFunctionReturn(0);
1615883e35e8SHong Zhang }
1616883e35e8SHong Zhang 
1617e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16185cf7da58SHong Zhang {
16195cf7da58SHong Zhang   PetscErrorCode ierr;
16205cf7da58SHong Zhang   PetscInt       j;
16215cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
16225cf7da58SHong Zhang 
16235cf7da58SHong Zhang   PetscFunctionBegin;
16245cf7da58SHong Zhang   if (!ghost) {
16255cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16265cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16275cf7da58SHong Zhang     }
16285cf7da58SHong Zhang   } else {
16295cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16305cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16315cf7da58SHong Zhang     }
16325cf7da58SHong Zhang   }
16335cf7da58SHong Zhang   PetscFunctionReturn(0);
16345cf7da58SHong Zhang }
16355cf7da58SHong Zhang 
1636e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16375cf7da58SHong Zhang {
16385cf7da58SHong Zhang   PetscErrorCode ierr;
16395cf7da58SHong Zhang   PetscInt       j,ncols_u;
16405cf7da58SHong Zhang   PetscScalar    val;
16415cf7da58SHong Zhang 
16425cf7da58SHong Zhang   PetscFunctionBegin;
16435cf7da58SHong Zhang   if (!ghost) {
16445cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16455cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16465cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
16475cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16485cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16495cf7da58SHong Zhang     }
16505cf7da58SHong Zhang   } else {
16515cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16525cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16535cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
16545cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16555cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16565cf7da58SHong Zhang     }
16575cf7da58SHong Zhang   }
16585cf7da58SHong Zhang   PetscFunctionReturn(0);
16595cf7da58SHong Zhang }
16605cf7da58SHong Zhang 
1661e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16625cf7da58SHong Zhang {
16635cf7da58SHong Zhang   PetscErrorCode ierr;
16645cf7da58SHong Zhang 
16655cf7da58SHong Zhang   PetscFunctionBegin;
16665cf7da58SHong Zhang   if (Ju) {
16675cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
16685cf7da58SHong Zhang   } else {
16695cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
16705cf7da58SHong Zhang   }
16715cf7da58SHong Zhang   PetscFunctionReturn(0);
16725cf7da58SHong Zhang }
16735cf7da58SHong Zhang 
1674e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1675883e35e8SHong Zhang {
1676883e35e8SHong Zhang   PetscErrorCode ierr;
1677883e35e8SHong Zhang   PetscInt       j,*cols;
1678883e35e8SHong Zhang   PetscScalar    *zeros;
1679883e35e8SHong Zhang 
1680883e35e8SHong Zhang   PetscFunctionBegin;
1681883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
1682883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
1683883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
1684883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
16851ad426b7SHong Zhang   PetscFunctionReturn(0);
16861ad426b7SHong Zhang }
1687a4e85ca8SHong Zhang 
1688e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
16893e97b6e8SHong Zhang {
16903e97b6e8SHong Zhang   PetscErrorCode ierr;
16913e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
16923e97b6e8SHong Zhang   const PetscInt *cols;
16933e97b6e8SHong Zhang   PetscScalar    zero=0.0;
16943e97b6e8SHong Zhang 
16953e97b6e8SHong Zhang   PetscFunctionBegin;
16963e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
16973e97b6e8SHong 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);
16983e97b6e8SHong Zhang 
16993e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
17003e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
17013e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
17023e97b6e8SHong Zhang       col = cols[j] + cstart;
17033e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
17043e97b6e8SHong Zhang     }
17053e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
17063e97b6e8SHong Zhang   }
17073e97b6e8SHong Zhang   PetscFunctionReturn(0);
17083e97b6e8SHong Zhang }
17091ad426b7SHong Zhang 
1710e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1711a4e85ca8SHong Zhang {
1712a4e85ca8SHong Zhang   PetscErrorCode ierr;
1713f4431b8cSHong Zhang 
1714a4e85ca8SHong Zhang   PetscFunctionBegin;
1715a4e85ca8SHong Zhang   if (Ju) {
1716a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1717a4e85ca8SHong Zhang   } else {
1718a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1719a4e85ca8SHong Zhang   }
1720a4e85ca8SHong Zhang   PetscFunctionReturn(0);
1721a4e85ca8SHong Zhang }
1722a4e85ca8SHong Zhang 
172324121865SAdrian 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.
172424121865SAdrian Maldonado */
172524121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
172624121865SAdrian Maldonado {
172724121865SAdrian Maldonado   PetscErrorCode ierr;
172824121865SAdrian Maldonado   PetscInt       i,size,dof;
172924121865SAdrian Maldonado   PetscInt       *glob2loc;
173024121865SAdrian Maldonado 
173124121865SAdrian Maldonado   PetscFunctionBegin;
173224121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
173324121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
173424121865SAdrian Maldonado 
173524121865SAdrian Maldonado   for (i = 0; i < size; i++) {
173624121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
173724121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
173824121865SAdrian Maldonado     glob2loc[i] = dof;
173924121865SAdrian Maldonado   }
174024121865SAdrian Maldonado 
174124121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
174224121865SAdrian Maldonado #if 0
174324121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
174424121865SAdrian Maldonado #endif
174524121865SAdrian Maldonado   PetscFunctionReturn(0);
174624121865SAdrian Maldonado }
174724121865SAdrian Maldonado 
174801ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
17499e1d080bSHong Zhang 
17509e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
17511ad426b7SHong Zhang {
17521ad426b7SHong Zhang   PetscErrorCode ierr;
17531ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
17549e1d080bSHong Zhang   PetscMPIInt    rank, size;
175524121865SAdrian Maldonado   PetscInt       eDof,vDof;
175624121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
17579e1d080bSHong Zhang   MPI_Comm       comm;
175824121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
175924121865SAdrian Maldonado 
17609e1d080bSHong Zhang   PetscFunctionBegin;
176124121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
176224121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
176324121865SAdrian Maldonado   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
176424121865SAdrian Maldonado 
176524121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
176624121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
176724121865SAdrian Maldonado 
176801ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
176924121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
177024121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
177124121865SAdrian Maldonado 
177201ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
177324121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
177424121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
177524121865SAdrian Maldonado 
177601ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
177724121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
177824121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
177924121865SAdrian Maldonado 
178001ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
178124121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
178224121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
178324121865SAdrian Maldonado 
17843f6a6bdaSHong Zhang   bA[0][0] = j11;
17853f6a6bdaSHong Zhang   bA[0][1] = j12;
17863f6a6bdaSHong Zhang   bA[1][0] = j21;
17873f6a6bdaSHong Zhang   bA[1][1] = j22;
178824121865SAdrian Maldonado 
178924121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
179024121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
179124121865SAdrian Maldonado 
179224121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
179324121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
179424121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
179524121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
179624121865SAdrian Maldonado 
179724121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
179824121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
179924121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
180024121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
180124121865SAdrian Maldonado 
180201ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
180324121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
180424121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
180524121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
180624121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
180724121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
180824121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
180924121865SAdrian Maldonado 
181024121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
181124121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18129e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
181324121865SAdrian Maldonado 
181424121865SAdrian Maldonado   /* Free structures */
181524121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
181624121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
181724121865SAdrian Maldonado   PetscFunctionReturn(0);
18189e1d080bSHong Zhang }
18199e1d080bSHong Zhang 
18209e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
18219e1d080bSHong Zhang {
18229e1d080bSHong Zhang   PetscErrorCode ierr;
18239e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
18249e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
18259e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
18269e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
18279e1d080bSHong Zhang   Mat            Juser;
18289e1d080bSHong Zhang   PetscSection   sectionGlobal;
18299e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
18309e1d080bSHong Zhang   const PetscInt *edges,*cone;
18319e1d080bSHong Zhang   MPI_Comm       comm;
18329e1d080bSHong Zhang   MatType        mtype;
18339e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
18349e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
18359e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
18369e1d080bSHong Zhang 
18379e1d080bSHong Zhang   PetscFunctionBegin;
18389e1d080bSHong Zhang   mtype = dm->mattype;
18399e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
18409e1d080bSHong Zhang   if (isNest) {
18419e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
18429e1d080bSHong Zhang     PetscFunctionReturn(0);
18439e1d080bSHong Zhang   }
18449e1d080bSHong Zhang 
18459e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
1846a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
18479e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
1848bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
18491ad426b7SHong Zhang     PetscFunctionReturn(0);
18501ad426b7SHong Zhang   }
18511ad426b7SHong Zhang 
1852bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
1853e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
1854bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
1855bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
18562a945128SHong Zhang 
18572a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
18582a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
185989898e50SHong Zhang 
186089898e50SHong Zhang   /* (1) Set matrix preallocation */
186189898e50SHong Zhang   /*------------------------------*/
1862840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1863840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
1864840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
1865840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
1866840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
1867840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
1868840c2264SHong Zhang 
186989898e50SHong Zhang   /* Set preallocation for edges */
187089898e50SHong Zhang   /*-----------------------------*/
1871840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
1872840c2264SHong Zhang 
1873bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
1874840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
1875840c2264SHong Zhang     /* Get row indices */
1876840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
1877840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
1878840c2264SHong Zhang     if (nrows) {
1879840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
1880840c2264SHong Zhang 
18815cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
1882d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1883840c2264SHong Zhang       for (v=0; v<2; v++) {
1884840c2264SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
1885840c2264SHong Zhang 
18868675203cSHong Zhang         if (network->Je) {
1887840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
18888675203cSHong Zhang         } else Juser = NULL;
1889840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
18905cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1891840c2264SHong Zhang       }
1892840c2264SHong Zhang 
189389898e50SHong Zhang       /* Set preallocation for edge self */
1894840c2264SHong Zhang       cstart = rstart;
18958675203cSHong Zhang       if (network->Je) {
1896840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
18978675203cSHong Zhang       } else Juser = NULL;
18985cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1899840c2264SHong Zhang     }
1900840c2264SHong Zhang   }
1901840c2264SHong Zhang 
190289898e50SHong Zhang   /* Set preallocation for vertices */
190389898e50SHong Zhang   /*--------------------------------*/
1904840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
19058675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
1906840c2264SHong Zhang 
1907840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
1908840c2264SHong Zhang     /* Get row indices */
1909840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1910840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
1911840c2264SHong Zhang     if (!nrows) continue;
1912840c2264SHong Zhang 
1913bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1914bdcb62a2SHong Zhang     if (ghost) {
1915bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1916bdcb62a2SHong Zhang     } else {
1917bdcb62a2SHong Zhang       rows_v = rows;
1918bdcb62a2SHong Zhang     }
1919bdcb62a2SHong Zhang 
1920bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1921840c2264SHong Zhang 
1922840c2264SHong Zhang     /* Get supporting edges and connected vertices */
1923840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1924840c2264SHong Zhang 
1925840c2264SHong Zhang     for (e=0; e<nedges; e++) {
1926840c2264SHong Zhang       /* Supporting edges */
1927840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1928840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1929840c2264SHong Zhang 
19308675203cSHong Zhang       if (network->Jv) {
1931840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
19328675203cSHong Zhang       } else Juser = NULL;
1933bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1934840c2264SHong Zhang 
1935840c2264SHong Zhang       /* Connected vertices */
1936d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
1937840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
1938840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
1939840c2264SHong Zhang 
1940840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1941840c2264SHong Zhang 
19428675203cSHong Zhang       if (network->Jv) {
1943840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
19448675203cSHong Zhang       } else Juser = NULL;
1945e102a522SHong Zhang       if (ghost_vc||ghost) {
1946e102a522SHong Zhang         ghost2 = PETSC_TRUE;
1947e102a522SHong Zhang       } else {
1948e102a522SHong Zhang         ghost2 = PETSC_FALSE;
1949e102a522SHong Zhang       }
1950e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
1951840c2264SHong Zhang     }
1952840c2264SHong Zhang 
195389898e50SHong Zhang     /* Set preallocation for vertex self */
1954840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1955840c2264SHong Zhang     if (!ghost) {
1956840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
19578675203cSHong Zhang       if (network->Jv) {
1958840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
19598675203cSHong Zhang       } else Juser = NULL;
1960bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1961840c2264SHong Zhang     }
1962bdcb62a2SHong Zhang     if (ghost) {
1963bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1964bdcb62a2SHong Zhang     }
1965840c2264SHong Zhang   }
1966840c2264SHong Zhang 
1967840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
1968840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
19695cf7da58SHong Zhang 
19705cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
19715cf7da58SHong Zhang 
19725cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
1973840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
1974840c2264SHong Zhang 
1975840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
1976840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
1977840c2264SHong Zhang   for (j=0; j<localSize; j++) {
1978e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
1979e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
1980840c2264SHong Zhang   }
1981840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
1982840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
1983840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
1984840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
1985840c2264SHong Zhang 
19865cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
19875cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
19885cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
19895cf7da58SHong Zhang 
19905cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
19915cf7da58SHong Zhang 
199289898e50SHong Zhang   /* (2) Set matrix entries for edges */
199389898e50SHong Zhang   /*----------------------------------*/
19941ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
1995bfbc38dcSHong Zhang     /* Get row indices */
19961ad426b7SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
199717df6e9eSHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
19984b976069SHong Zhang     if (nrows) {
199917df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
20001ad426b7SHong Zhang 
2001bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
2002d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2003bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
2004bfbc38dcSHong Zhang         ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr);
2005883e35e8SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
20063e97b6e8SHong Zhang 
20078675203cSHong Zhang         if (network->Je) {
2008a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
20098675203cSHong Zhang         } else Juser = NULL;
2010a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2011bfbc38dcSHong Zhang       }
201217df6e9eSHong Zhang 
2013bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
20143e97b6e8SHong Zhang       cstart = rstart;
20158675203cSHong Zhang       if (network->Je) {
2016a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
20178675203cSHong Zhang       } else Juser = NULL;
2018a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
20191ad426b7SHong Zhang     }
20204b976069SHong Zhang   }
20211ad426b7SHong Zhang 
2022bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
202383b2e829SHong Zhang   /*---------------------------------*/
20241ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2025bfbc38dcSHong Zhang     /* Get row indices */
2026596e729fSHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
2027596e729fSHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
20284b976069SHong Zhang     if (!nrows) continue;
2029596e729fSHong Zhang 
2030bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2031bdcb62a2SHong Zhang     if (ghost) {
2032bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2033bdcb62a2SHong Zhang     } else {
2034bdcb62a2SHong Zhang       rows_v = rows;
2035bdcb62a2SHong Zhang     }
2036bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2037596e729fSHong Zhang 
2038bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2039596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2040596e729fSHong Zhang 
2041596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2042bfbc38dcSHong Zhang       /* Supporting edges */
2043596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
2044596e729fSHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
2045596e729fSHong Zhang 
20468675203cSHong Zhang       if (network->Jv) {
2047a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
20488675203cSHong Zhang       } else Juser = NULL;
2049bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2050596e729fSHong Zhang 
2051bfbc38dcSHong Zhang       /* Connected vertices */
2052d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
20532a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
20542a945128SHong Zhang 
205544aca652SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr);
205644aca652SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
2057a4e85ca8SHong Zhang 
20588675203cSHong Zhang       if (network->Jv) {
2059a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
20608675203cSHong Zhang       } else Juser = NULL;
2061bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2062596e729fSHong Zhang     }
2063596e729fSHong Zhang 
2064bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
20651ad426b7SHong Zhang     if (!ghost) {
2066596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
20678675203cSHong Zhang       if (network->Jv) {
2068a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
20698675203cSHong Zhang       } else Juser = NULL;
2070bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2071bdcb62a2SHong Zhang     }
2072bdcb62a2SHong Zhang     if (ghost) {
2073bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2074bdcb62a2SHong Zhang     }
20751ad426b7SHong Zhang   }
2076a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2077bdcb62a2SHong Zhang 
20781ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20791ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2080dd6f46cdSHong Zhang 
20815f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
20825f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20835f2c45f1SShri Abhyankar }
20845f2c45f1SShri Abhyankar 
20855f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
20865f2c45f1SShri Abhyankar {
20875f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20885f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20892727e31bSShri Abhyankar   PetscInt       j;
20905f2c45f1SShri Abhyankar 
20915f2c45f1SShri Abhyankar   PetscFunctionBegin;
20928415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
209383b2e829SHong Zhang   if (network->Je) {
209483b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
209583b2e829SHong Zhang   }
209683b2e829SHong Zhang   if (network->Jv) {
2097883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
209883b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
20991ad426b7SHong Zhang   }
210013c2a604SAdrian Maldonado 
210113c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
210213c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
210313c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2104f5427c60SHong Zhang   if (network->vltog) {
2105f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2106f5427c60SHong Zhang   }
210713c2a604SAdrian Maldonado   if (network->vertex.sf) {
210813c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
210913c2a604SAdrian Maldonado   }
211013c2a604SAdrian Maldonado   /* edge */
211113c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
211213c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
211313c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
211413c2a604SAdrian Maldonado   if (network->edge.sf) {
211513c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
211613c2a604SAdrian Maldonado   }
21175f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
21185f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
21195f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
212083b2e829SHong Zhang 
21212727e31bSShri Abhyankar   for(j=0; j<network->nsubnet; j++) {
21222727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
21232727e31bSShri Abhyankar   }
2124caf410d2SHong Zhang   ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr);
2125caf410d2SHong Zhang 
2126e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
21275f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
2128caf410d2SHong Zhang   ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
21295f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
21305f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21315f2c45f1SShri Abhyankar }
21325f2c45f1SShri Abhyankar 
21335f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
21345f2c45f1SShri Abhyankar {
21355f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21365f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
2137caf410d2SHong Zhang   PetscBool      iascii;
2138caf410d2SHong Zhang   PetscMPIInt    rank;
2139caf410d2SHong Zhang   PetscInt       p,nsubnet;
21405f2c45f1SShri Abhyankar 
21415f2c45f1SShri Abhyankar   PetscFunctionBegin;
2142caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2143caf410d2SHong Zhang   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
2144caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2145caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2146caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2147caf410d2SHong Zhang   if (iascii) {
2148caf410d2SHong Zhang     const PetscInt    *cone,*vtx,*edges;
2149caf410d2SHong Zhang     PetscInt          vfrom,vto,i,j,nv,ne;
2150caf410d2SHong Zhang 
2151caf410d2SHong Zhang     nsubnet = network->nsubnet - network->ncsubnet; /* num of subnetworks */
2152caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
2153caf410d2SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nsubnet: %D; nsubnetCouple: %D; nEdges: %D; nVertices: %D\n",rank,nsubnet,network->ncsubnet,network->nEdges,network->nVertices);CHKERRQ(ierr);
2154caf410d2SHong Zhang 
2155caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
2156caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2157caf410d2SHong Zhang       if (ne) {
2158caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2159caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2160caf410d2SHong Zhang           p = edges[j];
2161caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2162caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2163caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2164caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2165caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2166caf410d2SHong Zhang         }
2167caf410d2SHong Zhang       }
2168caf410d2SHong Zhang     }
2169caf410d2SHong Zhang     /* Coupling subnets */
2170caf410d2SHong Zhang     nsubnet = network->nsubnet;
2171caf410d2SHong Zhang     for (; i<nsubnet; i++) {
2172caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2173caf410d2SHong Zhang       if (ne) {
2174caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D (couple): nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2175caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2176caf410d2SHong Zhang           p = edges[j];
2177caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2178caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2179caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2180caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2181caf410d2SHong Zhang         }
2182caf410d2SHong Zhang       }
2183caf410d2SHong Zhang     }
2184caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2185caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2186caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
21875f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21885f2c45f1SShri Abhyankar }
21895f2c45f1SShri Abhyankar 
21905f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
21915f2c45f1SShri Abhyankar {
21925f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21935f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21945f2c45f1SShri Abhyankar 
21955f2c45f1SShri Abhyankar   PetscFunctionBegin;
21965f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
21975f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21985f2c45f1SShri Abhyankar }
21995f2c45f1SShri Abhyankar 
22005f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
22015f2c45f1SShri Abhyankar {
22025f2c45f1SShri Abhyankar   PetscErrorCode ierr;
22035f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
22045f2c45f1SShri Abhyankar 
22055f2c45f1SShri Abhyankar   PetscFunctionBegin;
22065f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
22075f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22085f2c45f1SShri Abhyankar }
22095f2c45f1SShri Abhyankar 
22105f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
22115f2c45f1SShri Abhyankar {
22125f2c45f1SShri Abhyankar   PetscErrorCode ierr;
22135f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
22145f2c45f1SShri Abhyankar 
22155f2c45f1SShri Abhyankar   PetscFunctionBegin;
22165f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
22175f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22185f2c45f1SShri Abhyankar }
22195f2c45f1SShri Abhyankar 
22205f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
22215f2c45f1SShri Abhyankar {
22225f2c45f1SShri Abhyankar   PetscErrorCode ierr;
22235f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
22245f2c45f1SShri Abhyankar 
22255f2c45f1SShri Abhyankar   PetscFunctionBegin;
22265f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
22275f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22285f2c45f1SShri Abhyankar }
222922bbedd7SHong Zhang 
223022bbedd7SHong Zhang /*@
2231b2aacc82SHong Zhang   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex globle index
223222bbedd7SHong Zhang 
223322bbedd7SHong Zhang   Not collective
223422bbedd7SHong Zhang 
223522bbedd7SHong Zhang   Input Parameters
223622bbedd7SHong Zhang + dm - the dm object
223722bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
223822bbedd7SHong Zhang 
223922bbedd7SHong Zhang   Output Parameters
224022bbedd7SHong Zhang +  vg  - global vertex ordering, start from 0
224122bbedd7SHong Zhang 
224222bbedd7SHong Zhang   Level: Advanced
224322bbedd7SHong Zhang 
224422bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
224522bbedd7SHong Zhang @*/
224622bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
224722bbedd7SHong Zhang {
224822bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
224922bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
225022bbedd7SHong Zhang 
225122bbedd7SHong Zhang   PetscFunctionBegin;
225222bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
225322bbedd7SHong Zhang   *vg = vltog[vloc];
225422bbedd7SHong Zhang   PetscFunctionReturn(0);
225522bbedd7SHong Zhang }
225622bbedd7SHong Zhang 
225722bbedd7SHong Zhang /*@
225822bbedd7SHong Zhang   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to globle map
225922bbedd7SHong Zhang 
226022bbedd7SHong Zhang   Collective
226122bbedd7SHong Zhang 
226222bbedd7SHong Zhang   Input Parameters:
226322bbedd7SHong Zhang + dm - the dm object
226422bbedd7SHong Zhang 
226522bbedd7SHong Zhang   Level: Advanced
226622bbedd7SHong Zhang 
226763029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
226822bbedd7SHong Zhang @*/
226922bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
227022bbedd7SHong Zhang {
227122bbedd7SHong Zhang   PetscErrorCode    ierr;
227222bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
227322bbedd7SHong Zhang   MPI_Comm          comm;
227463029d29SHong Zhang   PetscMPIInt       rank,size,*displs,*recvcounts,remoterank;
227522bbedd7SHong Zhang   PetscBool         ghost;
227663029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
227722bbedd7SHong Zhang   const PetscSFNode *iremote;
227822bbedd7SHong Zhang   PetscSF           vsf;
227963029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
228063029d29SHong Zhang   VecScatter        ctx;
228163029d29SHong Zhang   PetscScalar       *varr,val;
228263029d29SHong Zhang   const PetscScalar *varr_read;
228322bbedd7SHong Zhang 
228422bbedd7SHong Zhang   PetscFunctionBegin;
228522bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
228622bbedd7SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
228763029d29SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
228822bbedd7SHong Zhang 
228922bbedd7SHong Zhang   if (size == 1) {
229022bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
229122bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
229222bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
229322bbedd7SHong Zhang     network->vltog = vltog;
229422bbedd7SHong Zhang     PetscFunctionReturn(0);
229522bbedd7SHong Zhang   }
229622bbedd7SHong Zhang 
229722bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
229822bbedd7SHong Zhang   if (network->vltog) {
229922bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
230022bbedd7SHong Zhang   }
230122bbedd7SHong Zhang 
230222bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
230322bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
230422bbedd7SHong Zhang   vsf = network->vertex.sf;
230522bbedd7SHong Zhang 
230622bbedd7SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size+1,&displs,size,&recvcounts);CHKERRQ(ierr);
2307f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
230822bbedd7SHong Zhang 
230922bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
231022bbedd7SHong Zhang 
231122bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
231222bbedd7SHong Zhang   vrange[0] = 0;
231322bbedd7SHong Zhang   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRQ(ierr);
231467dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
231522bbedd7SHong Zhang 
231622bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
231722bbedd7SHong Zhang   network->vltog = vltog;
231822bbedd7SHong Zhang 
231963029d29SHong Zhang   /* Set vltog for non-ghost vertices */
232063029d29SHong Zhang   k = 0;
232122bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
232222bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
232363029d29SHong Zhang     if (ghost) continue;
232463029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
232522bbedd7SHong Zhang   }
2326f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
232763029d29SHong Zhang 
232863029d29SHong Zhang   /* Set vltog for ghost vertices */
232963029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
233063029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
233163029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
233263029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
233363029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
233463029d29SHong Zhang   for (i=0; i<nleaves; i++) {
233563029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
233663029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
233763029d29SHong Zhang   }
233863029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
233963029d29SHong Zhang 
234063029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
234163029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
234263029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
234363029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
234463029d29SHong Zhang 
234563029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
234663029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
234763029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
234863029d29SHong Zhang   for (i=0; i<N; i+=2) {
23492e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
235063029d29SHong Zhang     if (remoterank == rank) {
235163029d29SHong Zhang       k = i+1; /* row number */
23522e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
235363029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
235463029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
235563029d29SHong Zhang     }
235663029d29SHong Zhang   }
235763029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
235863029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
235963029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
236063029d29SHong Zhang 
236163029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
236263029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
236363029d29SHong Zhang   k = 0;
236463029d29SHong Zhang   for (i=0; i<nroots; i++) {
236563029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
236663029d29SHong Zhang     if (!ghost) continue;
23672e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
236863029d29SHong Zhang   }
236963029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
237063029d29SHong Zhang 
237163029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
237263029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
237363029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
237422bbedd7SHong Zhang   PetscFunctionReturn(0);
237522bbedd7SHong Zhang }
2376