xref: /petsc/src/dm/impls/network/network.c (revision ffc4695bcb29f4b022f59a5fd6bc99fc280ff6d8)
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 
3597bb938eSShri Abhyankar   Level: beginner
3672c3e9f7SHong Zhang 
3772c3e9f7SHong Zhang .seealso: DMNetworkCreate()
3872c3e9f7SHong Zhang @*/
3972c3e9f7SHong Zhang PetscErrorCode DMNetworkGetSizes(DM netdm, PetscInt *Nsubnet, PetscInt *Ncsubnet)
4072c3e9f7SHong Zhang {
4172c3e9f7SHong Zhang   DM_Network *network = (DM_Network*) netdm->data;
4272c3e9f7SHong Zhang 
4372c3e9f7SHong Zhang   PetscFunctionBegin;
4472c3e9f7SHong Zhang   *Nsubnet = network->nsubnet;
4572c3e9f7SHong Zhang   *Ncsubnet = network->ncsubnet;
4672c3e9f7SHong Zhang   PetscFunctionReturn(0);
4772c3e9f7SHong Zhang }
4872c3e9f7SHong Zhang 
4972c3e9f7SHong Zhang /*@
50e2aaf10cSShri Abhyankar   DMNetworkSetSizes - Sets the number of subnetworks, local and global vertices and edges for each subnetwork.
515f2c45f1SShri Abhyankar 
52d083f849SBarry Smith   Collective on dm
535f2c45f1SShri Abhyankar 
545f2c45f1SShri Abhyankar   Input Parameters:
555f2c45f1SShri Abhyankar + dm - the dm object
56caf410d2SHong Zhang . Nsubnet - global number of subnetworks
57caf410d2SHong Zhang . nV - number of local vertices for each subnetwork
58caf410d2SHong Zhang . nE - number of local edges for each subnetwork
59caf410d2SHong Zhang . NsubnetCouple - global number of coupling subnetworks
60caf410d2SHong Zhang - nec - number of local edges for each coupling subnetwork
615f2c45f1SShri Abhyankar 
62caf410d2SHong Zhang    You cannot change the sizes once they have been set. nV, nE are arrays of length Nsubnet, and nec is array of length NsubnetCouple.
635f2c45f1SShri Abhyankar 
6497bb938eSShri Abhyankar    Level: beginner
651b266c99SBarry Smith 
661b266c99SBarry Smith .seealso: DMNetworkCreate()
675f2c45f1SShri Abhyankar @*/
68caf410d2SHong Zhang PetscErrorCode DMNetworkSetSizes(DM dm,PetscInt Nsubnet,PetscInt nV[], PetscInt nE[],PetscInt NsubnetCouple,PetscInt nec[])
695f2c45f1SShri Abhyankar {
705f2c45f1SShri Abhyankar   PetscErrorCode ierr;
715f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*) dm->data;
72e2aaf10cSShri Abhyankar   PetscInt       a[2],b[2],i;
735f2c45f1SShri Abhyankar 
745f2c45f1SShri Abhyankar   PetscFunctionBegin;
755f2c45f1SShri Abhyankar   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
76e2aaf10cSShri Abhyankar   if (Nsubnet <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subnetworks %D cannot be less than 1",Nsubnet);
777765340cSHong Zhang   if (NsubnetCouple < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of coupling subnetworks %D cannot be less than 0",NsubnetCouple);
787765340cSHong Zhang 
79caf410d2SHong Zhang   PetscValidLogicalCollectiveInt(dm,Nsubnet,2);
80caf410d2SHong Zhang   if (NsubnetCouple) PetscValidLogicalCollectiveInt(dm,NsubnetCouple,5);
817765340cSHong Zhang   if (network->nsubnet != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network");
827765340cSHong Zhang 
83caf410d2SHong Zhang   if (!nV || !nE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Local vertex size or edge size must be provided");
84f025b11dSHong Zhang 
85caf410d2SHong Zhang   network->nsubnet  = Nsubnet + NsubnetCouple;
86caf410d2SHong Zhang   network->ncsubnet = NsubnetCouple;
87caf410d2SHong Zhang   ierr = PetscCalloc1(Nsubnet+NsubnetCouple,&network->subnet);CHKERRQ(ierr);
88caf410d2SHong Zhang 
89caf410d2SHong Zhang   /* ----------------------------------------------------------
90caf410d2SHong Zhang    p=v or e; P=V or E
91caf410d2SHong Zhang    subnet[0].pStart   = 0
92caf410d2SHong Zhang    subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i])
93caf410d2SHong Zhang    ----------------------------------------------------------------------- */
94caf410d2SHong Zhang   for (i=0; i < Nsubnet; i++) {
95caf410d2SHong Zhang     /* Get global number of vertices and edges for subnet[i] */
96caf410d2SHong Zhang     a[0] = nV[i]; a[1] = nE[i]; /* local number of vertices (excluding ghost) and edges */
977765340cSHong Zhang     ierr = MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
98071fcb05SBarry Smith     network->subnet[i].Nvtx = b[0];
99071fcb05SBarry Smith     network->subnet[i].Nedge = b[1];
1007765340cSHong Zhang 
101caf410d2SHong Zhang     network->subnet[i].nvtx   = nV[i]; /* local nvtx, without ghost */
1027765340cSHong Zhang 
103caf410d2SHong Zhang     /* global subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */
104caf410d2SHong Zhang     network->subnet[i].vStart = network->NVertices;
1057765340cSHong Zhang     network->subnet[i].vEnd   = network->subnet[i].vStart + network->subnet[i].Nvtx;
106caf410d2SHong Zhang 
107caf410d2SHong Zhang     network->nVertices += nV[i];
1087765340cSHong Zhang     network->NVertices += network->subnet[i].Nvtx;
1097765340cSHong Zhang 
1107765340cSHong Zhang     network->subnet[i].nedge  = nE[i];
1117765340cSHong Zhang     network->subnet[i].eStart = network->nEdges;
112caf410d2SHong Zhang     network->subnet[i].eEnd   = network->subnet[i].eStart + nE[i];
113caf410d2SHong Zhang     network->nEdges += nE[i];
114caf410d2SHong Zhang     network->NEdges += network->subnet[i].Nedge;
115caf410d2SHong Zhang   }
116caf410d2SHong Zhang 
117caf410d2SHong Zhang   /* coupling subnetwork */
118caf410d2SHong Zhang   for (; i < Nsubnet+NsubnetCouple; i++) {
119caf410d2SHong Zhang     /* Get global number of coupling edges for subnet[i] */
120caf410d2SHong Zhang     ierr = MPIU_Allreduce(nec+(i-Nsubnet),&network->subnet[i].Nedge,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
121caf410d2SHong Zhang 
122caf410d2SHong Zhang     network->subnet[i].nvtx   = 0; /* We design coupling subnetwork such that it does not have its own vertices */
123caf410d2SHong Zhang     network->subnet[i].vStart = network->nVertices;
124caf410d2SHong Zhang     network->subnet[i].vEnd   = network->subnet[i].vStart;
125caf410d2SHong Zhang 
126caf410d2SHong Zhang     network->subnet[i].nedge  = nec[i-Nsubnet];
127caf410d2SHong Zhang     network->subnet[i].eStart = network->nEdges;
128caf410d2SHong Zhang     network->subnet[i].eEnd = network->subnet[i].eStart + nec[i-Nsubnet];
129caf410d2SHong Zhang     network->nEdges += nec[i-Nsubnet];
1307765340cSHong Zhang     network->NEdges += network->subnet[i].Nedge;
1317765340cSHong Zhang   }
1327765340cSHong Zhang   PetscFunctionReturn(0);
1337765340cSHong Zhang }
1347765340cSHong Zhang 
1355f2c45f1SShri Abhyankar /*@
1365f2c45f1SShri Abhyankar   DMNetworkSetEdgeList - Sets the list of local edges (vertex connectivity) for the network
1375f2c45f1SShri Abhyankar 
138d083f849SBarry Smith   Logically collective on dm
1395f2c45f1SShri Abhyankar 
1405f2c45f1SShri Abhyankar   Input Parameters:
141e3e68989SHong Zhang + dm - the dm object
142e3e68989SHong Zhang . edgelist - list of edges for each subnetwork
143e3e68989SHong Zhang - edgelistCouple - list of edges for each coupling subnetwork
1445f2c45f1SShri Abhyankar 
1455f2c45f1SShri Abhyankar   Notes:
1465f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1475f2c45f1SShri Abhyankar   not be destroyed before the call to DMNetworkLayoutSetUp
1485f2c45f1SShri Abhyankar 
14997bb938eSShri Abhyankar   Level: beginner
1505f2c45f1SShri Abhyankar 
151e3e68989SHong Zhang   Example usage:
152e3e68989SHong Zhang   Consider the following 2 separate networks and a coupling network:
153e3e68989SHong Zhang 
154e3e68989SHong Zhang .vb
155e3e68989SHong Zhang  network 0: v0 -> v1 -> v2 -> v3
156e3e68989SHong Zhang  network 1: v1 -> v2 -> v0
157e3e68989SHong Zhang  coupling network: network 1: v2 -> network 0: v0
158e3e68989SHong Zhang .ve
159e3e68989SHong Zhang 
160e3e68989SHong Zhang  The resulting input
161e3e68989SHong Zhang    edgelist[0] = [0 1 | 1 2 | 2 3];
162e3e68989SHong Zhang    edgelist[1] = [1 2 | 2 0]
163e3e68989SHong Zhang    edgelistCouple[0] = [(network)1 (v)2 (network)0 (v)0].
164e3e68989SHong Zhang 
1655f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkSetSizes
1665f2c45f1SShri Abhyankar @*/
1674e18019cSBarry Smith PetscErrorCode DMNetworkSetEdgeList(DM dm,PetscInt *edgelist[],PetscInt *edgelistCouple[])
1685f2c45f1SShri Abhyankar {
1695f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*) dm->data;
17072c3e9f7SHong Zhang   PetscInt   i;
1715f2c45f1SShri Abhyankar 
1725f2c45f1SShri Abhyankar   PetscFunctionBegin;
17372c3e9f7SHong Zhang   for (i=0; i < (network->nsubnet-network->ncsubnet); i++) network->subnet[i].edgelist = edgelist[i];
17472c3e9f7SHong Zhang   if (network->ncsubnet) {
17572c3e9f7SHong Zhang     PetscInt j = 0;
17672c3e9f7SHong Zhang     if (!edgelistCouple) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Must provide edgelist_couple");
17772c3e9f7SHong Zhang     while (i < network->nsubnet) network->subnet[i++].edgelist = edgelistCouple[j++];
178e3e68989SHong Zhang   }
1795f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
1805f2c45f1SShri Abhyankar }
1815f2c45f1SShri Abhyankar 
1825f2c45f1SShri Abhyankar /*@
1835f2c45f1SShri Abhyankar   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
1845f2c45f1SShri Abhyankar 
185d083f849SBarry Smith   Collective on dm
1865f2c45f1SShri Abhyankar 
1877a7aea1fSJed Brown   Input Parameters:
1885f2c45f1SShri Abhyankar . DM - the dmnetwork object
1895f2c45f1SShri Abhyankar 
1905f2c45f1SShri Abhyankar   Notes:
1915f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
1925f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
1935f2c45f1SShri Abhyankar 
1945f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
1955f2c45f1SShri Abhyankar 
19697bb938eSShri Abhyankar   Level: beginner
1975f2c45f1SShri Abhyankar 
1985f2c45f1SShri Abhyankar .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList
1995f2c45f1SShri Abhyankar @*/
2005f2c45f1SShri Abhyankar PetscErrorCode DMNetworkLayoutSetUp(DM dm)
2015f2c45f1SShri Abhyankar {
2025f2c45f1SShri Abhyankar   PetscErrorCode ierr;
2035f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
2048e71b177SVaclav Hapla   PetscInt       numCorners=2,dim = 1; /* One dimensional network */
205caf410d2SHong Zhang   PetscInt       i,j,ctr,nsubnet,*eowners,np,*edges,*subnetvtx,vStart;
206caf410d2SHong Zhang   PetscInt       k,netid,vid, *vidxlTog,*edgelist_couple=NULL;
207caf410d2SHong Zhang   const PetscInt *cone;
208caf410d2SHong Zhang   MPI_Comm       comm;
209caf410d2SHong Zhang   PetscMPIInt    size,rank;
2106500d4abSHong Zhang 
2116500d4abSHong Zhang   PetscFunctionBegin;
212caf410d2SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
213*ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
214*ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
2156500d4abSHong Zhang 
216caf410d2SHong Zhang   /* Create the local edgelist for the network by concatenating local input edgelists of the subnetworks */
2178e71b177SVaclav Hapla   ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr);
2187765340cSHong Zhang   nsubnet = network->nsubnet - network->ncsubnet;
219caf410d2SHong Zhang   ctr = 0;
2207765340cSHong Zhang   for (i=0; i < nsubnet; i++) {
2216500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
222ba38b151SHong Zhang       edges[2*ctr]   = network->subnet[i].vStart + network->subnet[i].edgelist[2*j];
223ba38b151SHong Zhang       edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1];
2246500d4abSHong Zhang       ctr++;
2256500d4abSHong Zhang     }
2266500d4abSHong Zhang   }
2277765340cSHong Zhang 
228caf410d2SHong Zhang   /* Append local coupling edgelists of the subnetworks */
2297765340cSHong Zhang   i       = nsubnet; /* netid of coupling subnet */
2307765340cSHong Zhang   nsubnet = network->nsubnet;
2317765340cSHong Zhang   while (i < nsubnet) {
232991cf414SHong Zhang     edgelist_couple = network->subnet[i].edgelist;
23372c3e9f7SHong Zhang 
2346500d4abSHong Zhang     k = 0;
2356500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
2366500d4abSHong Zhang       netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
237caf410d2SHong Zhang       edges[2*ctr] = network->subnet[netid].vStart + vid; k += 2;
2386500d4abSHong Zhang 
2396500d4abSHong Zhang       netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
240caf410d2SHong Zhang       edges[2*ctr+1] = network->subnet[netid].vStart + vid; k+=2;
2416500d4abSHong Zhang       ctr++;
2426500d4abSHong Zhang     }
2437765340cSHong Zhang     i++;
2447765340cSHong Zhang   }
245caf410d2SHong Zhang   /*
246caf410d2SHong Zhang   if (rank == 0) {
247caf410d2SHong Zhang     ierr = PetscPrintf(PETSC_COMM_SELF,"[%d] edgelist:\n",rank);
2486500d4abSHong Zhang     for (i=0; i < network->nEdges; i++) {
249caf410d2SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"[%D %D]",edges[2*i],edges[2*i+1]);CHKERRQ(ierr);
2506500d4abSHong Zhang       printf("\n");
2516500d4abSHong Zhang     }
252caf410d2SHong Zhang   }
253caf410d2SHong Zhang    */
2546500d4abSHong Zhang 
255caf410d2SHong Zhang   /* Create network->plex */
2568e71b177SVaclav Hapla   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
2578e71b177SVaclav Hapla   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
2588e71b177SVaclav Hapla   ierr = DMSetDimension(network->plex,dim);CHKERRQ(ierr);
259caf410d2SHong Zhang   if (size == 1) {
2605e488331SVaclav Hapla     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices,numCorners,edges);CHKERRQ(ierr);
261caf410d2SHong Zhang   } else {
26225b6865aSVaclav Hapla     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices,network->NVertices,numCorners,edges,NULL);CHKERRQ(ierr);
263acdb140fSBarry Smith   }
2646500d4abSHong Zhang 
2656500d4abSHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
2666500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
2676500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
268caf410d2SHong Zhang   vStart = network->vStart;
2696500d4abSHong Zhang 
270caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
271caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
2726500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
2736500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
2746500d4abSHong Zhang 
275caf410d2SHong Zhang   network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
276caf410d2SHong Zhang   np = network->pEnd - network->pStart;
277caf410d2SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
278caf410d2SHong Zhang 
279caf410d2SHong Zhang   /* Create vidxlTog: maps local vertex index to global index */
280caf410d2SHong Zhang   np = network->vEnd - vStart;
281caf410d2SHong Zhang   ierr = PetscMalloc2(np,&vidxlTog,size+1,&eowners);CHKERRQ(ierr);
282caf410d2SHong Zhang   ctr = 0;
283caf410d2SHong Zhang   for (i=network->eStart; i<network->eEnd; i++) {
284caf410d2SHong Zhang     ierr = DMNetworkGetConnectedVertices(dm,i,&cone);CHKERRQ(ierr);
285caf410d2SHong Zhang     vidxlTog[cone[0] - vStart] = edges[2*ctr];
286caf410d2SHong Zhang     vidxlTog[cone[1] - vStart] = edges[2*ctr+1];
287caf410d2SHong Zhang     ctr++;
288caf410d2SHong Zhang   }
2898e71b177SVaclav Hapla   ierr = PetscFree(edges);CHKERRQ(ierr);
290caf410d2SHong Zhang 
2916500d4abSHong Zhang   /* Create vertices and edges array for the subnetworks */
2926500d4abSHong Zhang   for (j=0; j < network->nsubnet; j++) {
2936500d4abSHong Zhang     ierr = PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);CHKERRQ(ierr);
294caf410d2SHong Zhang 
2956500d4abSHong Zhang     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
2966500d4abSHong Zhang        These get updated when the vertices and edges are added. */
297caf410d2SHong Zhang     network->subnet[j].nvtx  = 0;
298caf410d2SHong Zhang     network->subnet[j].nedge = 0;
2996500d4abSHong Zhang   }
300caf410d2SHong Zhang   ierr = PetscCalloc1(np,&network->subnetvtx);CHKERRQ(ierr);
3016500d4abSHong Zhang 
302caf410d2SHong Zhang 
303caf410d2SHong Zhang   /* Get edge ownership */
304caf410d2SHong Zhang   np = network->eEnd - network->eStart;
305*ffc4695bSBarry Smith   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr);
306caf410d2SHong Zhang   eowners[0] = 0;
307caf410d2SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
308caf410d2SHong Zhang 
309caf410d2SHong Zhang   i = 0; j = 0;
310caf410d2SHong Zhang   while (i < np) { /* local edges, including coupling edges */
311caf410d2SHong Zhang     network->header[i].index = i + eowners[rank];   /* Global edge index */
312caf410d2SHong Zhang 
313caf410d2SHong Zhang     if (j < network->nsubnet && i < network->subnet[j].eEnd) {
3146500d4abSHong Zhang       network->header[i].subnetid = j; /* Subnetwork id */
3156500d4abSHong Zhang       network->subnet[j].edges[network->subnet[j].nedge++] = i;
316caf410d2SHong Zhang 
317caf410d2SHong Zhang       network->header[i].ndata = 0;
318caf410d2SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
319caf410d2SHong Zhang       network->header[i].offset[0] = 0;
3209988b915SShri Abhyankar       network->header[i].offsetvarrel[0] = 0;
321caf410d2SHong Zhang       i++;
322caf410d2SHong Zhang     }
323caf410d2SHong Zhang     if (i >= network->subnet[j].eEnd) j++;
324caf410d2SHong Zhang   }
325caf410d2SHong Zhang 
326caf410d2SHong Zhang   /* Count network->subnet[*].nvtx */
327caf410d2SHong Zhang   for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */
328caf410d2SHong Zhang     k = vidxlTog[i-vStart];
329caf410d2SHong Zhang     for (j=0; j < network->nsubnet; j++) {
330caf410d2SHong Zhang       if (network->subnet[j].vStart <= k && k < network->subnet[j].vEnd) {
331caf410d2SHong Zhang         network->subnet[j].nvtx++;
3326500d4abSHong Zhang         break;
3336500d4abSHong Zhang       }
3346500d4abSHong Zhang     }
3356500d4abSHong Zhang   }
3366500d4abSHong Zhang 
337caf410d2SHong Zhang   /* Set network->subnet[*].vertices on array network->subnetvtx */
338caf410d2SHong Zhang   subnetvtx = network->subnetvtx;
3396500d4abSHong Zhang   for (j=0; j<network->nsubnet; j++) {
340caf410d2SHong Zhang     network->subnet[j].vertices = subnetvtx;
341caf410d2SHong Zhang     subnetvtx                  += network->subnet[j].nvtx;
342caf410d2SHong Zhang     network->subnet[j].nvtx = 0;
343caf410d2SHong Zhang   }
344caf410d2SHong Zhang 
345caf410d2SHong Zhang   /* Set vertex array for the subnetworks */
346caf410d2SHong Zhang   for (i=vStart; i<network->vEnd; i++) { /* local vertices, including ghosts */
347caf410d2SHong Zhang     network->header[i].index = vidxlTog[i-vStart]; /*  Global vertex index */
348caf410d2SHong Zhang 
349caf410d2SHong Zhang     k = vidxlTog[i-vStart];
350caf410d2SHong Zhang     for (j=0; j < network->nsubnet; j++) {
351caf410d2SHong Zhang       if (network->subnet[j].vStart <= k && k < network->subnet[j].vEnd) {
3526500d4abSHong Zhang         network->header[i].subnetid = j;
3536500d4abSHong Zhang         network->subnet[j].vertices[network->subnet[j].nvtx++] = i;
3546500d4abSHong Zhang         break;
3556500d4abSHong Zhang       }
3566500d4abSHong Zhang     }
357caf410d2SHong Zhang 
3586500d4abSHong Zhang     network->header[i].ndata = 0;
3596500d4abSHong Zhang     ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
360caf410d2SHong Zhang     network->header[i].offset[0] = 0;
3619988b915SShri Abhyankar     network->header[i].offsetvarrel[0] = 0;
3626500d4abSHong Zhang   }
3636500d4abSHong Zhang 
364caf410d2SHong Zhang   ierr = PetscFree2(vidxlTog,eowners);CHKERRQ(ierr);
3655f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
3665f2c45f1SShri Abhyankar }
3675f2c45f1SShri Abhyankar 
36894ef8ddeSSatish Balay /*@C
3692727e31bSShri Abhyankar   DMNetworkGetSubnetworkInfo - Returns the info for the subnetwork
3702727e31bSShri Abhyankar 
3717a7aea1fSJed Brown   Input Parameters:
372caf410d2SHong Zhang + dm - the DM object
3732727e31bSShri Abhyankar - id   - the ID (integer) of the subnetwork
3742727e31bSShri Abhyankar 
3757a7aea1fSJed Brown   Output Parameters:
3762727e31bSShri Abhyankar + nv    - number of vertices (local)
3772727e31bSShri Abhyankar . ne    - number of edges (local)
3782727e31bSShri Abhyankar . vtx   - local vertices for this subnetwork
379a2b725a8SWilliam Gropp - edge  - local edges for this subnetwork
3802727e31bSShri Abhyankar 
3812727e31bSShri Abhyankar   Notes:
3822727e31bSShri Abhyankar   Cannot call this routine before DMNetworkLayoutSetup()
3832727e31bSShri Abhyankar 
38406dd6b0eSSatish Balay   Level: intermediate
38506dd6b0eSSatish Balay 
3862727e31bSShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
3872727e31bSShri Abhyankar @*/
388caf410d2SHong Zhang PetscErrorCode DMNetworkGetSubnetworkInfo(DM dm,PetscInt id,PetscInt *nv, PetscInt *ne,const PetscInt **vtx, const PetscInt **edge)
3892727e31bSShri Abhyankar {
390caf410d2SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
3912727e31bSShri Abhyankar 
3922727e31bSShri Abhyankar   PetscFunctionBegin;
39372c3e9f7SHong 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);
3942727e31bSShri Abhyankar   *nv   = network->subnet[id].nvtx;
3952727e31bSShri Abhyankar   *ne   = network->subnet[id].nedge;
3962727e31bSShri Abhyankar   *vtx  = network->subnet[id].vertices;
3972727e31bSShri Abhyankar   *edge = network->subnet[id].edges;
3982727e31bSShri Abhyankar   PetscFunctionReturn(0);
3992727e31bSShri Abhyankar }
4002727e31bSShri Abhyankar 
4012727e31bSShri Abhyankar /*@C
402caf410d2SHong Zhang   DMNetworkGetSubnetworkCoupleInfo - Returns the info for the coupling subnetwork
403caf410d2SHong Zhang 
4047a7aea1fSJed Brown   Input Parameters:
405caf410d2SHong Zhang + dm - the DM object
406caf410d2SHong Zhang - id   - the ID (integer) of the coupling subnetwork
407caf410d2SHong Zhang 
4087a7aea1fSJed Brown   Output Parameters:
409caf410d2SHong Zhang + ne - number of edges (local)
410caf410d2SHong Zhang - edge  - local edges for this coupling subnetwork
411caf410d2SHong Zhang 
412caf410d2SHong Zhang   Notes:
413caf410d2SHong Zhang   Cannot call this routine before DMNetworkLayoutSetup()
414caf410d2SHong Zhang 
415caf410d2SHong Zhang   Level: intermediate
416caf410d2SHong Zhang 
417caf410d2SHong Zhang .seealso: DMNetworkGetSubnetworkInfo, DMNetworkLayoutSetUp, DMNetworkCreate
418caf410d2SHong Zhang @*/
419caf410d2SHong Zhang PetscErrorCode DMNetworkGetSubnetworkCoupleInfo(DM dm,PetscInt id,PetscInt *ne,const PetscInt **edge)
420caf410d2SHong Zhang {
421caf410d2SHong Zhang   DM_Network *net = (DM_Network*)dm->data;
42272c3e9f7SHong Zhang   PetscInt   id1;
423caf410d2SHong Zhang 
424caf410d2SHong Zhang   PetscFunctionBegin;
42572c3e9f7SHong Zhang   if (net->ncsubnet) {
42672c3e9f7SHong 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);
42772c3e9f7SHong Zhang 
42872c3e9f7SHong Zhang     id1   = id + net->nsubnet - net->ncsubnet;
429caf410d2SHong Zhang     *ne   = net->subnet[id1].nedge;
430caf410d2SHong Zhang     *edge = net->subnet[id1].edges;
43172c3e9f7SHong Zhang   } else {
43272c3e9f7SHong Zhang     *ne   = 0;
43372c3e9f7SHong Zhang     *edge = NULL;
43472c3e9f7SHong Zhang   }
435caf410d2SHong Zhang   PetscFunctionReturn(0);
436caf410d2SHong Zhang }
437caf410d2SHong Zhang 
438caf410d2SHong Zhang /*@C
4395f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
4405f2c45f1SShri Abhyankar 
441d083f849SBarry Smith   Logically collective on dm
4425f2c45f1SShri Abhyankar 
4437a7aea1fSJed Brown   Input Parameters:
4445f2c45f1SShri Abhyankar + dm   - the network object
4455f2c45f1SShri Abhyankar . name - the component name
4465f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
4475f2c45f1SShri Abhyankar 
4487a7aea1fSJed Brown    Output Parameters:
4495f2c45f1SShri Abhyankar .   key - an integer key that defines the component
4505f2c45f1SShri Abhyankar 
4515f2c45f1SShri Abhyankar    Notes
4525f2c45f1SShri Abhyankar    This routine should be called by all processors before calling DMNetworkLayoutSetup().
4535f2c45f1SShri Abhyankar 
45497bb938eSShri Abhyankar    Level: beginner
4555f2c45f1SShri Abhyankar 
4565f2c45f1SShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
4575f2c45f1SShri Abhyankar @*/
458caf410d2SHong Zhang PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key)
4595f2c45f1SShri Abhyankar {
4605f2c45f1SShri Abhyankar   PetscErrorCode        ierr;
4615f2c45f1SShri Abhyankar   DM_Network            *network = (DM_Network*) dm->data;
4625f2c45f1SShri Abhyankar   DMNetworkComponent    *component=&network->component[network->ncomponent];
4635f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
4645f2c45f1SShri Abhyankar   PetscInt              i;
4655f2c45f1SShri Abhyankar 
4665f2c45f1SShri Abhyankar   PetscFunctionBegin;
4675f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
4685f2c45f1SShri Abhyankar     ierr = PetscStrcmp(component->name,name,&flg);CHKERRQ(ierr);
4695f2c45f1SShri Abhyankar     if (flg) {
4705f2c45f1SShri Abhyankar       *key = i;
4715f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
4725f2c45f1SShri Abhyankar     }
4736d64e262SShri Abhyankar   }
4746d64e262SShri Abhyankar   if (network->ncomponent == MAX_COMPONENTS) {
4756d64e262SShri Abhyankar     SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components registered exceeds the max %D",MAX_COMPONENTS);
4765f2c45f1SShri Abhyankar   }
4775f2c45f1SShri Abhyankar 
4785f2c45f1SShri Abhyankar   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
4795f2c45f1SShri Abhyankar   component->size = size/sizeof(DMNetworkComponentGenericDataType);
4805f2c45f1SShri Abhyankar   *key = network->ncomponent;
4815f2c45f1SShri Abhyankar   network->ncomponent++;
4825f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
4835f2c45f1SShri Abhyankar }
4845f2c45f1SShri Abhyankar 
4855f2c45f1SShri Abhyankar /*@
4865f2c45f1SShri Abhyankar   DMNetworkGetVertexRange - Get the bounds [start, end) for the vertices.
4875f2c45f1SShri Abhyankar 
4885f2c45f1SShri Abhyankar   Not Collective
4895f2c45f1SShri Abhyankar 
4905f2c45f1SShri Abhyankar   Input Parameters:
491a2b725a8SWilliam Gropp . dm - The DMNetwork object
4925f2c45f1SShri Abhyankar 
493fd292e60Sprj-   Output Parameters:
4945f2c45f1SShri Abhyankar + vStart - The first vertex point
4955f2c45f1SShri Abhyankar - vEnd   - One beyond the last vertex point
4965f2c45f1SShri Abhyankar 
49797bb938eSShri Abhyankar   Level: beginner
4985f2c45f1SShri Abhyankar 
4995f2c45f1SShri Abhyankar .seealso: DMNetworkGetEdgeRange
5005f2c45f1SShri Abhyankar @*/
5015f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
5025f2c45f1SShri Abhyankar {
5035f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
5045f2c45f1SShri Abhyankar 
5055f2c45f1SShri Abhyankar   PetscFunctionBegin;
5065f2c45f1SShri Abhyankar   if (vStart) *vStart = network->vStart;
5075f2c45f1SShri Abhyankar   if (vEnd) *vEnd = network->vEnd;
5085f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5095f2c45f1SShri Abhyankar }
5105f2c45f1SShri Abhyankar 
5115f2c45f1SShri Abhyankar /*@
5125f2c45f1SShri Abhyankar   DMNetworkGetEdgeRange - Get the bounds [start, end) for the edges.
5135f2c45f1SShri Abhyankar 
5145f2c45f1SShri Abhyankar   Not Collective
5155f2c45f1SShri Abhyankar 
5165f2c45f1SShri Abhyankar   Input Parameters:
517a2b725a8SWilliam Gropp . dm - The DMNetwork object
5185f2c45f1SShri Abhyankar 
519fd292e60Sprj-   Output Parameters:
5205f2c45f1SShri Abhyankar + eStart - The first edge point
5215f2c45f1SShri Abhyankar - eEnd   - One beyond the last edge point
5225f2c45f1SShri Abhyankar 
52397bb938eSShri Abhyankar   Level: beginner
5245f2c45f1SShri Abhyankar 
5255f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange
5265f2c45f1SShri Abhyankar @*/
5275f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
5285f2c45f1SShri Abhyankar {
5295f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
5305f2c45f1SShri Abhyankar 
5315f2c45f1SShri Abhyankar   PetscFunctionBegin;
5325f2c45f1SShri Abhyankar   if (eStart) *eStart = network->eStart;
5335f2c45f1SShri Abhyankar   if (eEnd) *eEnd = network->eEnd;
5345f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5355f2c45f1SShri Abhyankar }
5365f2c45f1SShri Abhyankar 
5377b6afd5bSHong Zhang /*@
538e85e6aecSHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the user global numbering for the edge.
5397b6afd5bSHong Zhang 
5407b6afd5bSHong Zhang   Not Collective
5417b6afd5bSHong Zhang 
5427b6afd5bSHong Zhang   Input Parameters:
5437b6afd5bSHong Zhang + dm - DMNetwork object
544e85e6aecSHong Zhang - p  - edge point
5457b6afd5bSHong Zhang 
546fd292e60Sprj-   Output Parameters:
547e85e6aecSHong Zhang . index - user global numbering for the edge
5487b6afd5bSHong Zhang 
5497b6afd5bSHong Zhang   Level: intermediate
5507b6afd5bSHong Zhang 
551e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalVertexIndex
5527b6afd5bSHong Zhang @*/
553e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
5547b6afd5bSHong Zhang {
5557b6afd5bSHong Zhang   PetscErrorCode    ierr;
5567b6afd5bSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
5577b6afd5bSHong Zhang   PetscInt          offsetp;
5587b6afd5bSHong Zhang   DMNetworkComponentHeader header;
5597b6afd5bSHong Zhang 
5607b6afd5bSHong Zhang   PetscFunctionBegin;
561caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
5627b6afd5bSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
5637b6afd5bSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
564e85e6aecSHong Zhang   *index = header->index;
5657b6afd5bSHong Zhang   PetscFunctionReturn(0);
5667b6afd5bSHong Zhang }
5677b6afd5bSHong Zhang 
5685f2c45f1SShri Abhyankar /*@
569e85e6aecSHong Zhang   DMNetworkGetGlobalVertexIndex - Get the user global numbering for the vertex.
570e85e6aecSHong Zhang 
571e85e6aecSHong Zhang   Not Collective
572e85e6aecSHong Zhang 
573e85e6aecSHong Zhang   Input Parameters:
574e85e6aecSHong Zhang + dm - DMNetwork object
575e85e6aecSHong Zhang - p  - vertex point
576e85e6aecSHong Zhang 
577fd292e60Sprj-   Output Parameters:
578e85e6aecSHong Zhang . index - user global numbering for the vertex
579e85e6aecSHong Zhang 
580e85e6aecSHong Zhang   Level: intermediate
581e85e6aecSHong Zhang 
582e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalEdgeIndex
583e85e6aecSHong Zhang @*/
584e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
585e85e6aecSHong Zhang {
586e85e6aecSHong Zhang   PetscErrorCode    ierr;
587e85e6aecSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
588e85e6aecSHong Zhang   PetscInt          offsetp;
589e85e6aecSHong Zhang   DMNetworkComponentHeader header;
590e85e6aecSHong Zhang 
591e85e6aecSHong Zhang   PetscFunctionBegin;
592caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
593e85e6aecSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
594e85e6aecSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
595e85e6aecSHong Zhang   *index = header->index;
596e85e6aecSHong Zhang   PetscFunctionReturn(0);
597e85e6aecSHong Zhang }
598e85e6aecSHong Zhang 
599c3b11c7cSShri Abhyankar /*
600c3b11c7cSShri Abhyankar   DMNetworkGetComponentKeyOffset - Gets the type along with the offset for indexing the
601c3b11c7cSShri Abhyankar                                     component value from the component data array
602c3b11c7cSShri Abhyankar 
603c3b11c7cSShri Abhyankar   Not Collective
604c3b11c7cSShri Abhyankar 
605c3b11c7cSShri Abhyankar   Input Parameters:
606c3b11c7cSShri Abhyankar + dm      - The DMNetwork object
607c3b11c7cSShri Abhyankar . p       - vertex/edge point
608c3b11c7cSShri Abhyankar - compnum - component number
609c3b11c7cSShri Abhyankar 
610c3b11c7cSShri Abhyankar   Output Parameters:
611c3b11c7cSShri Abhyankar + compkey - the key obtained when registering the component
612c3b11c7cSShri Abhyankar - offset  - offset into the component data array associated with the vertex/edge point
613c3b11c7cSShri Abhyankar 
614c3b11c7cSShri Abhyankar   Notes:
615c3b11c7cSShri Abhyankar   Typical usage:
616c3b11c7cSShri Abhyankar 
617c3b11c7cSShri Abhyankar   DMNetworkGetComponentDataArray(dm, &arr);
618c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
619c3b11c7cSShri Abhyankar   Loop over vertices or edges
620c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
621c3b11c7cSShri Abhyankar     Loop over numcomps
622c3b11c7cSShri Abhyankar       DMNetworkGetComponentKeyOffset(dm,v,compnum,&key,&offset);
623c3b11c7cSShri Abhyankar       compdata = (UserCompDataType)(arr+offset);
624c3b11c7cSShri Abhyankar 
625c3b11c7cSShri Abhyankar   Level: intermediate
626c3b11c7cSShri Abhyankar 
627c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray,
628c3b11c7cSShri Abhyankar */
629c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponentKeyOffset(DM dm,PetscInt p, PetscInt compnum, PetscInt *compkey, PetscInt *offset)
630c3b11c7cSShri Abhyankar {
631c3b11c7cSShri Abhyankar   PetscErrorCode           ierr;
632c3b11c7cSShri Abhyankar   PetscInt                 offsetp;
633c3b11c7cSShri Abhyankar   DMNetworkComponentHeader header;
634c3b11c7cSShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
635c3b11c7cSShri Abhyankar 
636c3b11c7cSShri Abhyankar   PetscFunctionBegin;
637c3b11c7cSShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
638c3b11c7cSShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
639c3b11c7cSShri Abhyankar   if (compkey) *compkey = header->key[compnum];
640c3b11c7cSShri Abhyankar   if (offset) *offset  = offsetp+network->dataheadersize+header->offset[compnum];
641c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
642c3b11c7cSShri Abhyankar }
643c3b11c7cSShri Abhyankar 
644c3b11c7cSShri Abhyankar /*@
645c3b11c7cSShri Abhyankar   DMNetworkGetComponent - Returns the network component and its key
646c3b11c7cSShri Abhyankar 
647c3b11c7cSShri Abhyankar   Not Collective
648c3b11c7cSShri Abhyankar 
6497a7aea1fSJed Brown   Input Parameters:
650c3b11c7cSShri Abhyankar + dm - DMNetwork object
651c3b11c7cSShri Abhyankar . p  - edge or vertex point
652c3b11c7cSShri Abhyankar - compnum - component number
653c3b11c7cSShri Abhyankar 
654c3b11c7cSShri Abhyankar   Output Parameters:
655c3b11c7cSShri Abhyankar + compkey - the key set for this computing during registration
656c3b11c7cSShri Abhyankar - component - the component data
657c3b11c7cSShri Abhyankar 
658c3b11c7cSShri Abhyankar   Notes:
659c3b11c7cSShri Abhyankar   Typical usage:
660c3b11c7cSShri Abhyankar 
661c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
662c3b11c7cSShri Abhyankar   Loop over vertices or edges
663c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
664c3b11c7cSShri Abhyankar     Loop over numcomps
665c3b11c7cSShri Abhyankar       DMNetworkGetComponent(dm,v,compnum,&key,&component);
666c3b11c7cSShri Abhyankar 
66797bb938eSShri Abhyankar   Level: beginner
668c3b11c7cSShri Abhyankar 
669c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetVariableOffset
670c3b11c7cSShri Abhyankar @*/
671c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponent(DM dm, PetscInt p, PetscInt compnum, PetscInt *key, void **component)
672c3b11c7cSShri Abhyankar {
673c3b11c7cSShri Abhyankar   PetscErrorCode ierr;
674c3b11c7cSShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
675e108cb99SStefano Zampini   PetscInt       offsetd = 0;
676c3b11c7cSShri Abhyankar 
677c3b11c7cSShri Abhyankar   PetscFunctionBegin;
678c3b11c7cSShri Abhyankar   ierr = DMNetworkGetComponentKeyOffset(dm,p,compnum,key,&offsetd);CHKERRQ(ierr);
679c3b11c7cSShri Abhyankar   *component = network->componentdataarray+offsetd;
680c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
681c3b11c7cSShri Abhyankar }
682c3b11c7cSShri Abhyankar 
683e85e6aecSHong Zhang /*@
684325661f6SSatish Balay   DMNetworkAddComponent - Adds a network component at the given point (vertex/edge)
6855f2c45f1SShri Abhyankar 
6865f2c45f1SShri Abhyankar   Not Collective
6875f2c45f1SShri Abhyankar 
6885f2c45f1SShri Abhyankar   Input Parameters:
6895f2c45f1SShri Abhyankar + dm           - The DMNetwork object
6905f2c45f1SShri Abhyankar . p            - vertex/edge point
6915f2c45f1SShri Abhyankar . componentkey - component key returned while registering the component
6925f2c45f1SShri Abhyankar - compvalue    - pointer to the data structure for the component
6935f2c45f1SShri Abhyankar 
69497bb938eSShri Abhyankar   Level: beginner
6955f2c45f1SShri Abhyankar 
6965f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange, DMNetworkGetEdgeRange, DMNetworkRegisterComponent
6975f2c45f1SShri Abhyankar @*/
6985f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p,PetscInt componentkey,void* compvalue)
6995f2c45f1SShri Abhyankar {
7005f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
70143a39a44SBarry Smith   DMNetworkComponent       *component = &network->component[componentkey];
7025f2c45f1SShri Abhyankar   DMNetworkComponentHeader header = &network->header[p];
7035f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue = &network->cvalue[p];
7045f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
7055f2c45f1SShri Abhyankar 
7065f2c45f1SShri Abhyankar   PetscFunctionBegin;
707fa58f0a9SHong 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);
708fa58f0a9SHong Zhang 
70943a39a44SBarry Smith   header->size[header->ndata] = component->size;
71043a39a44SBarry Smith   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
7115f2c45f1SShri Abhyankar   header->key[header->ndata] = componentkey;
7125f2c45f1SShri Abhyankar   if (header->ndata != 0) header->offset[header->ndata] = header->offset[header->ndata-1] + header->size[header->ndata-1];
7139988b915SShri Abhyankar   header->nvar[header->ndata] = 0;
7145f2c45f1SShri Abhyankar 
7155f2c45f1SShri Abhyankar   cvalue->data[header->ndata] = (void*)compvalue;
7165f2c45f1SShri Abhyankar   header->ndata++;
7175f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7185f2c45f1SShri Abhyankar }
7195f2c45f1SShri Abhyankar 
7205f2c45f1SShri Abhyankar /*@
7219988b915SShri Abhyankar   DMNetworkSetComponentNumVariables - Sets the number of variables for a component
7229988b915SShri Abhyankar 
7239988b915SShri Abhyankar   Not Collective
7249988b915SShri Abhyankar 
7259988b915SShri Abhyankar   Input Parameters:
7269988b915SShri Abhyankar + dm           - The DMNetwork object
7279988b915SShri Abhyankar . p            - vertex/edge point
7289988b915SShri Abhyankar . compnum      - component number (First component added = 0, second = 1, ...)
7299988b915SShri Abhyankar - nvar         - number of variables for the component
7309988b915SShri Abhyankar 
73197bb938eSShri Abhyankar   Level: beginner
7329988b915SShri Abhyankar 
7339dacc45bSShrirang Abhyankar .seealso: DMNetworkAddComponent(), DMNetworkGetNumComponents(),DMNetworkRegisterComponent()
7349988b915SShri Abhyankar @*/
7359988b915SShri Abhyankar PetscErrorCode DMNetworkSetComponentNumVariables(DM dm, PetscInt p,PetscInt compnum,PetscInt nvar)
7369988b915SShri Abhyankar {
7379988b915SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
7389988b915SShri Abhyankar   DMNetworkComponentHeader header = &network->header[p];
7399988b915SShri Abhyankar   PetscErrorCode           ierr;
7409988b915SShri Abhyankar 
7419988b915SShri Abhyankar   PetscFunctionBegin;
7429988b915SShri Abhyankar   ierr = DMNetworkAddNumVariables(dm,p,nvar);CHKERRQ(ierr);
7439988b915SShri Abhyankar   header->nvar[compnum] = nvar;
7449988b915SShri Abhyankar   if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum-1] + header->nvar[compnum-1];
7459988b915SShri Abhyankar   PetscFunctionReturn(0);
7469988b915SShri Abhyankar }
7479988b915SShri Abhyankar 
7489988b915SShri Abhyankar /*@
7495f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
7505f2c45f1SShri Abhyankar 
7515f2c45f1SShri Abhyankar   Not Collective
7525f2c45f1SShri Abhyankar 
7535f2c45f1SShri Abhyankar   Input Parameters:
7545f2c45f1SShri Abhyankar + dm - The DMNetwork object
755a2b725a8SWilliam Gropp - p  - vertex/edge point
7565f2c45f1SShri Abhyankar 
7575f2c45f1SShri Abhyankar   Output Parameters:
7585f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
7595f2c45f1SShri Abhyankar 
76097bb938eSShri Abhyankar   Level: beginner
7615f2c45f1SShri Abhyankar 
7625f2c45f1SShri Abhyankar .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent
7635f2c45f1SShri Abhyankar @*/
7645f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
7655f2c45f1SShri Abhyankar {
7665f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7675f2c45f1SShri Abhyankar   PetscInt       offset;
7685f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7695f2c45f1SShri Abhyankar 
7705f2c45f1SShri Abhyankar   PetscFunctionBegin;
7715f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
7725f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
7735f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7745f2c45f1SShri Abhyankar }
7755f2c45f1SShri Abhyankar 
7765f2c45f1SShri Abhyankar /*@
7775f2c45f1SShri Abhyankar   DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector.
7785f2c45f1SShri Abhyankar 
7795f2c45f1SShri Abhyankar   Not Collective
7805f2c45f1SShri Abhyankar 
7815f2c45f1SShri Abhyankar   Input Parameters:
7825f2c45f1SShri Abhyankar + dm     - The DMNetwork object
7835f2c45f1SShri Abhyankar - p      - the edge/vertex point
7845f2c45f1SShri Abhyankar 
7855f2c45f1SShri Abhyankar   Output Parameters:
7865f2c45f1SShri Abhyankar . offset - the offset
7875f2c45f1SShri Abhyankar 
78897bb938eSShri Abhyankar   Level: beginner
7895f2c45f1SShri Abhyankar 
7905f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
7915f2c45f1SShri Abhyankar @*/
7925f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset)
7935f2c45f1SShri Abhyankar {
7945f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7955f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7965f2c45f1SShri Abhyankar 
7975f2c45f1SShri Abhyankar   PetscFunctionBegin;
7981bb6d2a8SBarry Smith   ierr = PetscSectionGetOffset(network->plex->localSection,p,offset);CHKERRQ(ierr);
7995f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8005f2c45f1SShri Abhyankar }
8015f2c45f1SShri Abhyankar 
8025f2c45f1SShri Abhyankar /*@
8035f2c45f1SShri Abhyankar   DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector.
8045f2c45f1SShri Abhyankar 
8055f2c45f1SShri Abhyankar   Not Collective
8065f2c45f1SShri Abhyankar 
8075f2c45f1SShri Abhyankar   Input Parameters:
8085f2c45f1SShri Abhyankar + dm      - The DMNetwork object
8095f2c45f1SShri Abhyankar - p       - the edge/vertex point
8105f2c45f1SShri Abhyankar 
8115f2c45f1SShri Abhyankar   Output Parameters:
8125f2c45f1SShri Abhyankar . offsetg - the offset
8135f2c45f1SShri Abhyankar 
81497bb938eSShri Abhyankar   Level: beginner
8155f2c45f1SShri Abhyankar 
8165f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableOffset, DMGetLocalVector
8175f2c45f1SShri Abhyankar @*/
8185f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg)
8195f2c45f1SShri Abhyankar {
8205f2c45f1SShri Abhyankar   PetscErrorCode ierr;
8215f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8225f2c45f1SShri Abhyankar 
8235f2c45f1SShri Abhyankar   PetscFunctionBegin;
8241bb6d2a8SBarry Smith   ierr = PetscSectionGetOffset(network->plex->globalSection,p,offsetg);CHKERRQ(ierr);
8256fefedf4SHong Zhang   if (*offsetg < 0) *offsetg = -(*offsetg + 1); /* Convert to actual global offset for ghost vertex */
8265f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8275f2c45f1SShri Abhyankar }
8285f2c45f1SShri Abhyankar 
82924121865SAdrian Maldonado /*@
8309988b915SShri Abhyankar   DMNetworkGetComponentVariableOffset - Get the offset for accessing the variable associated with a component for the given vertex/edge from the local vector.
8319988b915SShri Abhyankar 
8329988b915SShri Abhyankar   Not Collective
8339988b915SShri Abhyankar 
8349988b915SShri Abhyankar   Input Parameters:
8359988b915SShri Abhyankar + dm     - The DMNetwork object
8367d928bffSSatish Balay . p      - the edge/vertex point
8377d928bffSSatish Balay - compnum - component number
8389988b915SShri Abhyankar 
8399988b915SShri Abhyankar   Output Parameters:
8409988b915SShri Abhyankar . offset - the offset
8419988b915SShri Abhyankar 
8429988b915SShri Abhyankar   Level: intermediate
8439988b915SShri Abhyankar 
8449dacc45bSShrirang Abhyankar .seealso: DMNetworkGetVariableGlobalOffset(), DMGetLocalVector(), DMNetworkSetComponentNumVariables()
8459988b915SShri Abhyankar @*/
8469988b915SShri Abhyankar PetscErrorCode DMNetworkGetComponentVariableOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offset)
8479988b915SShri Abhyankar {
8489988b915SShri Abhyankar   PetscErrorCode ierr;
8499988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8509988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
8519988b915SShri Abhyankar   DMNetworkComponentHeader header;
8529988b915SShri Abhyankar 
8539988b915SShri Abhyankar   PetscFunctionBegin;
8549988b915SShri Abhyankar   ierr = DMNetworkGetVariableOffset(dm,p,&offsetp);CHKERRQ(ierr);
8559988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
8569988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
8579988b915SShri Abhyankar   *offset = offsetp + header->offsetvarrel[compnum];
8589988b915SShri Abhyankar   PetscFunctionReturn(0);
8599988b915SShri Abhyankar }
8609988b915SShri Abhyankar 
8619988b915SShri Abhyankar /*@
8629988b915SShri Abhyankar   DMNetworkGetComponentVariableGlobalOffset - Get the global offset for accessing the variable associated with a component for the given vertex/edge from the local vector.
8639988b915SShri Abhyankar 
8649988b915SShri Abhyankar   Not Collective
8659988b915SShri Abhyankar 
8669988b915SShri Abhyankar   Input Parameters:
8679988b915SShri Abhyankar + dm     - The DMNetwork object
8687d928bffSSatish Balay . p      - the edge/vertex point
8697d928bffSSatish Balay - compnum - component number
8709988b915SShri Abhyankar 
8719988b915SShri Abhyankar   Output Parameters:
8729988b915SShri Abhyankar . offsetg - the global offset
8739988b915SShri Abhyankar 
8749988b915SShri Abhyankar   Level: intermediate
8759988b915SShri Abhyankar 
8769dacc45bSShrirang Abhyankar .seealso: DMNetworkGetVariableGlobalOffset(), DMNetworkGetComponentVariableOffset(), DMGetLocalVector(), DMNetworkSetComponentNumVariables()
8779988b915SShri Abhyankar @*/
8789988b915SShri Abhyankar PetscErrorCode DMNetworkGetComponentVariableGlobalOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offsetg)
8799988b915SShri Abhyankar {
8809988b915SShri Abhyankar   PetscErrorCode ierr;
8819988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8829988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
8839988b915SShri Abhyankar   DMNetworkComponentHeader header;
8849988b915SShri Abhyankar 
8859988b915SShri Abhyankar   PetscFunctionBegin;
8869988b915SShri Abhyankar   ierr = DMNetworkGetVariableGlobalOffset(dm,p,&offsetp);CHKERRQ(ierr);
8879988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
8889988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
8899988b915SShri Abhyankar   *offsetg = offsetp + header->offsetvarrel[compnum];
8909988b915SShri Abhyankar   PetscFunctionReturn(0);
8919988b915SShri Abhyankar }
8929988b915SShri Abhyankar 
8939988b915SShri Abhyankar /*@
89424121865SAdrian Maldonado   DMNetworkGetEdgeOffset - Get the offset for accessing the variable associated with the given edge from the local subvector.
89524121865SAdrian Maldonado 
89624121865SAdrian Maldonado   Not Collective
89724121865SAdrian Maldonado 
89824121865SAdrian Maldonado   Input Parameters:
89924121865SAdrian Maldonado + dm     - The DMNetwork object
90024121865SAdrian Maldonado - p      - the edge point
90124121865SAdrian Maldonado 
90224121865SAdrian Maldonado   Output Parameters:
90324121865SAdrian Maldonado . offset - the offset
90424121865SAdrian Maldonado 
90524121865SAdrian Maldonado   Level: intermediate
90624121865SAdrian Maldonado 
90724121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
90824121865SAdrian Maldonado @*/
90924121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
91024121865SAdrian Maldonado {
91124121865SAdrian Maldonado   PetscErrorCode ierr;
91224121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
91324121865SAdrian Maldonado 
91424121865SAdrian Maldonado   PetscFunctionBegin;
91524121865SAdrian Maldonado 
91624121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
91724121865SAdrian Maldonado   PetscFunctionReturn(0);
91824121865SAdrian Maldonado }
91924121865SAdrian Maldonado 
92024121865SAdrian Maldonado /*@
92124121865SAdrian Maldonado   DMNetworkGetVertexOffset - Get the offset for accessing the variable associated with the given vertex from the local subvector.
92224121865SAdrian Maldonado 
92324121865SAdrian Maldonado   Not Collective
92424121865SAdrian Maldonado 
92524121865SAdrian Maldonado   Input Parameters:
92624121865SAdrian Maldonado + dm     - The DMNetwork object
92724121865SAdrian Maldonado - p      - the vertex point
92824121865SAdrian Maldonado 
92924121865SAdrian Maldonado   Output Parameters:
93024121865SAdrian Maldonado . offset - the offset
93124121865SAdrian Maldonado 
93224121865SAdrian Maldonado   Level: intermediate
93324121865SAdrian Maldonado 
93424121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
93524121865SAdrian Maldonado @*/
93624121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
93724121865SAdrian Maldonado {
93824121865SAdrian Maldonado   PetscErrorCode ierr;
93924121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
94024121865SAdrian Maldonado 
94124121865SAdrian Maldonado   PetscFunctionBegin;
94224121865SAdrian Maldonado 
94324121865SAdrian Maldonado   p -= network->vStart;
94424121865SAdrian Maldonado 
94524121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
94624121865SAdrian Maldonado   PetscFunctionReturn(0);
94724121865SAdrian Maldonado }
9485f2c45f1SShri Abhyankar /*@
9495f2c45f1SShri Abhyankar   DMNetworkAddNumVariables - Add number of variables associated with a given point.
9505f2c45f1SShri Abhyankar 
9515f2c45f1SShri Abhyankar   Not Collective
9525f2c45f1SShri Abhyankar 
9535f2c45f1SShri Abhyankar   Input Parameters:
9545f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
9555f2c45f1SShri Abhyankar . p    - the vertex/edge point
9565f2c45f1SShri Abhyankar - nvar - number of additional variables
9575f2c45f1SShri Abhyankar 
95897bb938eSShri Abhyankar   Level: beginner
9595f2c45f1SShri Abhyankar 
9605f2c45f1SShri Abhyankar .seealso: DMNetworkSetNumVariables
9615f2c45f1SShri Abhyankar @*/
9625f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar)
9635f2c45f1SShri Abhyankar {
9645f2c45f1SShri Abhyankar   PetscErrorCode ierr;
9655f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
9665f2c45f1SShri Abhyankar 
9675f2c45f1SShri Abhyankar   PetscFunctionBegin;
9685f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
9695f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9705f2c45f1SShri Abhyankar }
9715f2c45f1SShri Abhyankar 
97227f51fceSHong Zhang /*@
97327f51fceSHong Zhang   DMNetworkGetNumVariables - Gets number of variables for a vertex/edge point.
97427f51fceSHong Zhang 
97527f51fceSHong Zhang   Not Collective
97627f51fceSHong Zhang 
97727f51fceSHong Zhang   Input Parameters:
97827f51fceSHong Zhang + dm   - The DMNetworkObject
97927f51fceSHong Zhang - p    - the vertex/edge point
98027f51fceSHong Zhang 
98127f51fceSHong Zhang   Output Parameters:
98227f51fceSHong Zhang . nvar - number of variables
98327f51fceSHong Zhang 
98497bb938eSShri Abhyankar   Level: beginner
98527f51fceSHong Zhang 
98627f51fceSHong Zhang .seealso: DMNetworkAddNumVariables, DMNetworkSddNumVariables
98727f51fceSHong Zhang @*/
98827f51fceSHong Zhang PetscErrorCode DMNetworkGetNumVariables(DM dm,PetscInt p,PetscInt *nvar)
98927f51fceSHong Zhang {
99027f51fceSHong Zhang   PetscErrorCode ierr;
99127f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
99227f51fceSHong Zhang 
99327f51fceSHong Zhang   PetscFunctionBegin;
99427f51fceSHong Zhang   ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
99527f51fceSHong Zhang   PetscFunctionReturn(0);
99627f51fceSHong Zhang }
99727f51fceSHong Zhang 
9985f2c45f1SShri Abhyankar /*@
9995f2c45f1SShri Abhyankar   DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point.
10005f2c45f1SShri Abhyankar 
10015f2c45f1SShri Abhyankar   Not Collective
10025f2c45f1SShri Abhyankar 
10035f2c45f1SShri Abhyankar   Input Parameters:
10045f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
10055f2c45f1SShri Abhyankar . p    - the vertex/edge point
10065f2c45f1SShri Abhyankar - nvar - number of variables
10075f2c45f1SShri Abhyankar 
100897bb938eSShri Abhyankar   Level: beginner
10095f2c45f1SShri Abhyankar 
10105f2c45f1SShri Abhyankar .seealso: DMNetworkAddNumVariables
10115f2c45f1SShri Abhyankar @*/
10125f2c45f1SShri Abhyankar PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar)
10135f2c45f1SShri Abhyankar {
10145f2c45f1SShri Abhyankar   PetscErrorCode ierr;
10155f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10165f2c45f1SShri Abhyankar 
10175f2c45f1SShri Abhyankar   PetscFunctionBegin;
10185f2c45f1SShri Abhyankar   ierr = PetscSectionSetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
10195f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10205f2c45f1SShri Abhyankar }
10215f2c45f1SShri Abhyankar 
10225f2c45f1SShri Abhyankar /* Sets up the array that holds the data for all components and its associated section. This
10235f2c45f1SShri Abhyankar    function is called during DMSetUp() */
10245f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
10255f2c45f1SShri Abhyankar {
10265f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
10275f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
1028e53b5ba3SHong Zhang   PetscInt                 arr_size,p,offset,offsetp,ncomp,i;
10295f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
10305f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
10315f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
10325f2c45f1SShri Abhyankar 
10335f2c45f1SShri Abhyankar   PetscFunctionBegin;
10345f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
10355f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
103675b160a0SShri Abhyankar   ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
10375f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
10385f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
10395f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
10405f2c45f1SShri Abhyankar     /* Copy header */
10415f2c45f1SShri Abhyankar     header = &network->header[p];
1042302440fdSBarry Smith     ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
10435f2c45f1SShri Abhyankar     /* Copy data */
10445f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
10455f2c45f1SShri Abhyankar     ncomp = header->ndata;
10465f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
10475f2c45f1SShri Abhyankar       offset = offsetp + network->dataheadersize + header->offset[i];
1048302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
10495f2c45f1SShri Abhyankar     }
10505f2c45f1SShri Abhyankar   }
10515f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10525f2c45f1SShri Abhyankar }
10535f2c45f1SShri Abhyankar 
10545f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
10555f2c45f1SShri Abhyankar PetscErrorCode DMNetworkVariablesSetUp(DM dm)
10565f2c45f1SShri Abhyankar {
10575f2c45f1SShri Abhyankar   PetscErrorCode ierr;
10585f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10595f2c45f1SShri Abhyankar 
10605f2c45f1SShri Abhyankar   PetscFunctionBegin;
10615f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
10625f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10635f2c45f1SShri Abhyankar }
10645f2c45f1SShri Abhyankar 
106597bb938eSShri Abhyankar /*
10665f2c45f1SShri Abhyankar   DMNetworkGetComponentDataArray - Returns the component data array
10675f2c45f1SShri Abhyankar 
10685f2c45f1SShri Abhyankar   Not Collective
10695f2c45f1SShri Abhyankar 
10705f2c45f1SShri Abhyankar   Input Parameters:
10715f2c45f1SShri Abhyankar . dm - The DMNetwork Object
10725f2c45f1SShri Abhyankar 
10735f2c45f1SShri Abhyankar   Output Parameters:
10745f2c45f1SShri Abhyankar . componentdataarray - array that holds data for all components
10755f2c45f1SShri Abhyankar 
10765f2c45f1SShri Abhyankar   Level: intermediate
10775f2c45f1SShri Abhyankar 
1078a730d845SHong Zhang .seealso: DMNetworkGetComponentKeyOffset, DMNetworkGetNumComponents
107997bb938eSShri Abhyankar */
10805f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray)
10815f2c45f1SShri Abhyankar {
10825f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
10835f2c45f1SShri Abhyankar 
10845f2c45f1SShri Abhyankar   PetscFunctionBegin;
10855f2c45f1SShri Abhyankar   *componentdataarray = network->componentdataarray;
10865f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10875f2c45f1SShri Abhyankar }
10885f2c45f1SShri Abhyankar 
108924121865SAdrian Maldonado /* Get a subsection from a range of points */
109024121865SAdrian Maldonado PetscErrorCode DMNetworkGetSubSection_private(PetscSection master, PetscInt pstart, PetscInt pend,PetscSection *subsection)
109124121865SAdrian Maldonado {
109224121865SAdrian Maldonado   PetscErrorCode ierr;
109324121865SAdrian Maldonado   PetscInt       i, nvar;
109424121865SAdrian Maldonado 
109524121865SAdrian Maldonado   PetscFunctionBegin;
109624121865SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)master), subsection);CHKERRQ(ierr);
109724121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
109824121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
109924121865SAdrian Maldonado     ierr = PetscSectionGetDof(master,i,&nvar);CHKERRQ(ierr);
110024121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
110124121865SAdrian Maldonado   }
110224121865SAdrian Maldonado 
110324121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
110424121865SAdrian Maldonado   PetscFunctionReturn(0);
110524121865SAdrian Maldonado }
110624121865SAdrian Maldonado 
110724121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
110824121865SAdrian Maldonado PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
110924121865SAdrian Maldonado {
111024121865SAdrian Maldonado   PetscErrorCode ierr;
111124121865SAdrian Maldonado   PetscInt       i, *subpoints;
111224121865SAdrian Maldonado 
111324121865SAdrian Maldonado   PetscFunctionBegin;
111424121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
111524121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
111624121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
111724121865SAdrian Maldonado     subpoints[i - pstart] = i;
111824121865SAdrian Maldonado   }
1119459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
112024121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
112124121865SAdrian Maldonado   PetscFunctionReturn(0);
112224121865SAdrian Maldonado }
112324121865SAdrian Maldonado 
112424121865SAdrian Maldonado /*@
112524121865SAdrian Maldonado   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute.
112624121865SAdrian Maldonado 
112724121865SAdrian Maldonado   Collective
112824121865SAdrian Maldonado 
112924121865SAdrian Maldonado   Input Parameters:
113024121865SAdrian Maldonado . dm   - The DMNetworkObject
113124121865SAdrian Maldonado 
113224121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
113324121865SAdrian Maldonado 
113424121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
113524121865SAdrian Maldonado 
1136caf410d2SHong 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]).
113724121865SAdrian Maldonado 
113824121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
113924121865SAdrian Maldonado 
114024121865SAdrian Maldonado   Level: intermediate
114124121865SAdrian Maldonado 
114224121865SAdrian Maldonado @*/
114324121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
114424121865SAdrian Maldonado {
114524121865SAdrian Maldonado   PetscErrorCode ierr;
114624121865SAdrian Maldonado   MPI_Comm       comm;
11479852e123SBarry Smith   PetscMPIInt    rank, size;
114824121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
114924121865SAdrian Maldonado 
1150eab1376dSHong Zhang   PetscFunctionBegin;
115124121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1152*ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1153*ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
115424121865SAdrian Maldonado 
115524121865SAdrian Maldonado   /* Create maps for vertices and edges */
115624121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
115724121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
115824121865SAdrian Maldonado 
115924121865SAdrian Maldonado   /* Create local sub-sections */
116024121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
116124121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
116224121865SAdrian Maldonado 
11639852e123SBarry Smith   if (size > 1) {
116424121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
116522bbedd7SHong Zhang 
116624121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
116724121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
116824121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
116924121865SAdrian Maldonado   } else {
117024121865SAdrian Maldonado     /* create structures for vertex */
117124121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
117224121865SAdrian Maldonado     /* create structures for edge */
117324121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
117424121865SAdrian Maldonado   }
117524121865SAdrian Maldonado 
117624121865SAdrian Maldonado   /* Add viewers */
117724121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
117824121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
117924121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
118024121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
118124121865SAdrian Maldonado   PetscFunctionReturn(0);
118224121865SAdrian Maldonado }
11837b6afd5bSHong Zhang 
11845f2c45f1SShri Abhyankar /*@
11855f2c45f1SShri Abhyankar   DMNetworkDistribute - Distributes the network and moves associated component data.
11865f2c45f1SShri Abhyankar 
11875f2c45f1SShri Abhyankar   Collective
11885f2c45f1SShri Abhyankar 
11895f2c45f1SShri Abhyankar   Input Parameter:
1190d3464fd4SAdrian Maldonado + DM - the DMNetwork object
11915f2c45f1SShri Abhyankar - overlap - The overlap of partitions, 0 is the default
11925f2c45f1SShri Abhyankar 
11935f2c45f1SShri Abhyankar   Notes:
11948b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
11955f2c45f1SShri Abhyankar 
11965f2c45f1SShri Abhyankar   Level: intermediate
11975f2c45f1SShri Abhyankar 
11985f2c45f1SShri Abhyankar .seealso: DMNetworkCreate
11995f2c45f1SShri Abhyankar @*/
1200d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
12015f2c45f1SShri Abhyankar {
1202d3464fd4SAdrian Maldonado   MPI_Comm       comm;
12035f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1204d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1205d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1206d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1207caf410d2SHong Zhang   PetscSF        pointsf=NULL;
12085f2c45f1SShri Abhyankar   DM             newDM;
1209caf410d2SHong Zhang   PetscInt       j,e,v,offset,*subnetvtx;
121051ac5effSHong Zhang   PetscPartitioner         part;
1211b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
12125f2c45f1SShri Abhyankar 
12135f2c45f1SShri Abhyankar   PetscFunctionBegin;
1214d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1215*ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1216d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1217d3464fd4SAdrian Maldonado 
1218d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
12195f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
12205f2c45f1SShri Abhyankar   newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
122151ac5effSHong Zhang 
122251ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
122351ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
122451ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
122551ac5effSHong Zhang 
12265f2c45f1SShri Abhyankar   /* Distribute plex dm and dof section */
122780cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
122851ac5effSHong Zhang 
12295f2c45f1SShri Abhyankar   /* Distribute dof section */
1230d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DofSection);CHKERRQ(ierr);
12315f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
1232d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DataSection);CHKERRQ(ierr);
123351ac5effSHong Zhang 
12345f2c45f1SShri Abhyankar   /* Distribute data and associated section */
123531da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
123624121865SAdrian Maldonado 
12375f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
12385f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
12395f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
12405f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
12416fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
12426fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
12435f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
124424121865SAdrian Maldonado 
12451bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
124692fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1247e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
12485f2c45f1SShri Abhyankar 
1249b9c6e19dSShri Abhyankar   /* Set up subnetwork info in the newDM */
1250b9c6e19dSShri Abhyankar   newDMnetwork->nsubnet  = oldDMnetwork->nsubnet;
1251caf410d2SHong Zhang   newDMnetwork->ncsubnet = oldDMnetwork->ncsubnet;
1252b9c6e19dSShri Abhyankar   ierr = PetscCalloc1(newDMnetwork->nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
1253b9c6e19dSShri Abhyankar   /* Copy over the global number of vertices and edges in each subnetwork. Note that these are already
1254b9c6e19dSShri Abhyankar      calculated in DMNetworkLayoutSetUp()
1255b9c6e19dSShri Abhyankar   */
1256b9c6e19dSShri Abhyankar   for (j=0; j < newDMnetwork->nsubnet; j++) {
1257b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1258b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1259b9c6e19dSShri Abhyankar   }
1260b9c6e19dSShri Abhyankar 
1261b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1262b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1263b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1264b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1265b9c6e19dSShri Abhyankar   }
1266b9c6e19dSShri Abhyankar 
1267b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1268b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1269b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1270b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nvtx++;
1271b9c6e19dSShri Abhyankar   }
1272b9c6e19dSShri Abhyankar 
1273b9c6e19dSShri Abhyankar   /* Now create the vertices and edge arrays for the subnetworks */
1274caf410d2SHong Zhang   ierr = PetscCalloc1(newDMnetwork->vEnd-newDMnetwork->vStart,&newDMnetwork->subnetvtx);CHKERRQ(ierr);
1275caf410d2SHong Zhang   subnetvtx = newDMnetwork->subnetvtx;
1276caf410d2SHong Zhang 
1277b9c6e19dSShri Abhyankar   for (j=0; j<newDMnetwork->nsubnet; j++) {
1278b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr);
1279caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1280caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1281caf410d2SHong Zhang 
1282b9c6e19dSShri Abhyankar     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
1283b9c6e19dSShri Abhyankar        These get updated when the vertices and edges are added. */
1284b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1285b9c6e19dSShri Abhyankar   }
1286b9c6e19dSShri Abhyankar 
1287b9c6e19dSShri Abhyankar   /* Set the vertices and edges in each subnetwork */
1288b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1289b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1290b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1291b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1292b9c6e19dSShri Abhyankar   }
1293b9c6e19dSShri Abhyankar 
1294b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1295b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1296b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1297b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
1298b9c6e19dSShri Abhyankar   }
1299b9c6e19dSShri Abhyankar 
1300caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
130122bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1302caf410d2SHong Zhang 
130324121865SAdrian Maldonado   /* Destroy point SF */
130424121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
130524121865SAdrian Maldonado 
1306d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
1307d3464fd4SAdrian Maldonado   *dm  = newDM;
13085f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13095f2c45f1SShri Abhyankar }
13105f2c45f1SShri Abhyankar 
131124121865SAdrian Maldonado /*@C
131224121865SAdrian Maldonado   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering.
131324121865SAdrian Maldonado 
131424121865SAdrian Maldonado   Input Parameters:
131524121865SAdrian Maldonado + masterSF - the original SF structure
131624121865SAdrian Maldonado - map      - a ISLocalToGlobal mapping that contains the subset of points
131724121865SAdrian Maldonado 
131824121865SAdrian Maldonado   Output Parameters:
131924121865SAdrian Maldonado . subSF    - a subset of the masterSF for the desired subset.
1320ee300463SSatish Balay 
1321ee300463SSatish Balay   Level: intermediate
13227d928bffSSatish Balay @*/
132324121865SAdrian Maldonado PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) {
132424121865SAdrian Maldonado 
132524121865SAdrian Maldonado   PetscErrorCode        ierr;
132624121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
132724121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
132824121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
132924121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
133024121865SAdrian Maldonado   const PetscInt        *ilocal;
133124121865SAdrian Maldonado   const PetscSFNode     *iremote;
133224121865SAdrian Maldonado 
133324121865SAdrian Maldonado   PetscFunctionBegin;
133424121865SAdrian Maldonado   ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
133524121865SAdrian Maldonado 
133624121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
133724121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
133824121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
133924121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
134024121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
134124121865SAdrian Maldonado   }
134224121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
134324121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
134424121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
134524121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
134624121865SAdrian Maldonado   ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
134724121865SAdrian Maldonado   ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
134824121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
13494b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
13504b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
135124121865SAdrian Maldonado   nleaves_sub = 0;
135224121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
135324121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
135424121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
13554b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
135624121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
135724121865SAdrian Maldonado       nleaves_sub += 1;
135824121865SAdrian Maldonado     }
135924121865SAdrian Maldonado   }
136024121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
136124121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
136224121865SAdrian Maldonado 
136324121865SAdrian Maldonado   /* Create new subSF */
136424121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
136524121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
13664b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
136724121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
13684b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
136924121865SAdrian Maldonado   PetscFunctionReturn(0);
137024121865SAdrian Maldonado }
137124121865SAdrian Maldonado 
13725f2c45f1SShri Abhyankar /*@C
13735f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
13745f2c45f1SShri Abhyankar 
13755f2c45f1SShri Abhyankar   Not Collective
13765f2c45f1SShri Abhyankar 
13775f2c45f1SShri Abhyankar   Input Parameters:
13785f2c45f1SShri Abhyankar + dm - The DMNetwork object
13795f2c45f1SShri Abhyankar - p  - the vertex point
13805f2c45f1SShri Abhyankar 
1381fd292e60Sprj-   Output Parameters:
13825f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
13835f2c45f1SShri Abhyankar - edges  - List of edge points
13845f2c45f1SShri Abhyankar 
138597bb938eSShri Abhyankar   Level: beginner
13865f2c45f1SShri Abhyankar 
13875f2c45f1SShri Abhyankar   Fortran Notes:
13885f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
13895f2c45f1SShri Abhyankar   include petsc.h90 in your code.
13905f2c45f1SShri Abhyankar 
1391d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices
13925f2c45f1SShri Abhyankar @*/
13935f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
13945f2c45f1SShri Abhyankar {
13955f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13965f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
13975f2c45f1SShri Abhyankar 
13985f2c45f1SShri Abhyankar   PetscFunctionBegin;
13995f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
14005f2c45f1SShri Abhyankar   ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);
14015f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14025f2c45f1SShri Abhyankar }
14035f2c45f1SShri Abhyankar 
14045f2c45f1SShri Abhyankar /*@C
1405d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
14065f2c45f1SShri Abhyankar 
14075f2c45f1SShri Abhyankar   Not Collective
14085f2c45f1SShri Abhyankar 
14095f2c45f1SShri Abhyankar   Input Parameters:
14105f2c45f1SShri Abhyankar + dm - The DMNetwork object
14115f2c45f1SShri Abhyankar - p  - the edge point
14125f2c45f1SShri Abhyankar 
1413fd292e60Sprj-   Output Parameters:
14145f2c45f1SShri Abhyankar . vertices  - vertices connected to this edge
14155f2c45f1SShri Abhyankar 
141697bb938eSShri Abhyankar   Level: beginner
14175f2c45f1SShri Abhyankar 
14185f2c45f1SShri Abhyankar   Fortran Notes:
14195f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
14205f2c45f1SShri Abhyankar   include petsc.h90 in your code.
14215f2c45f1SShri Abhyankar 
14225f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
14235f2c45f1SShri Abhyankar @*/
1424d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
14255f2c45f1SShri Abhyankar {
14265f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14275f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14285f2c45f1SShri Abhyankar 
14295f2c45f1SShri Abhyankar   PetscFunctionBegin;
14305f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
14315f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14325f2c45f1SShri Abhyankar }
14335f2c45f1SShri Abhyankar 
14345f2c45f1SShri Abhyankar /*@
14355f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
14365f2c45f1SShri Abhyankar 
14375f2c45f1SShri Abhyankar   Not Collective
14385f2c45f1SShri Abhyankar 
14395f2c45f1SShri Abhyankar   Input Parameters:
14405f2c45f1SShri Abhyankar + dm - The DMNetwork object
1441a2b725a8SWilliam Gropp - p  - the vertex point
14425f2c45f1SShri Abhyankar 
14435f2c45f1SShri Abhyankar   Output Parameter:
14445f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
14455f2c45f1SShri Abhyankar 
144697bb938eSShri Abhyankar   Level: beginner
14475f2c45f1SShri Abhyankar 
1448d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange
14495f2c45f1SShri Abhyankar @*/
14505f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
14515f2c45f1SShri Abhyankar {
14525f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14535f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14545f2c45f1SShri Abhyankar   PetscInt       offsetg;
14555f2c45f1SShri Abhyankar   PetscSection   sectiong;
14565f2c45f1SShri Abhyankar 
14575f2c45f1SShri Abhyankar   PetscFunctionBegin;
1458caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
14595f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
1460e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
14615f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
14625f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
14635f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14645f2c45f1SShri Abhyankar }
14655f2c45f1SShri Abhyankar 
14665f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
14675f2c45f1SShri Abhyankar {
14685f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14695f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
14705f2c45f1SShri Abhyankar 
14715f2c45f1SShri Abhyankar   PetscFunctionBegin;
14725f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
14735f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
14745f2c45f1SShri Abhyankar 
147592fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
1476e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
14779e1d080bSHong Zhang 
14789e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
14799e1d080bSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr);
14805f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14815f2c45f1SShri Abhyankar }
14825f2c45f1SShri Abhyankar 
14831ad426b7SHong Zhang /*@
148417df6e9eSHong Zhang     DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
14851ad426b7SHong Zhang                             -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
14861ad426b7SHong Zhang 
14871ad426b7SHong Zhang     Collective
14881ad426b7SHong Zhang 
14891ad426b7SHong Zhang     Input Parameters:
149083b2e829SHong Zhang +   dm - The DMNetwork object
149183b2e829SHong Zhang .   eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
149283b2e829SHong Zhang -   vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
14931ad426b7SHong Zhang 
14941ad426b7SHong Zhang     Level: intermediate
14951ad426b7SHong Zhang 
14961ad426b7SHong Zhang @*/
149783b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
14981ad426b7SHong Zhang {
14991ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
15008675203cSHong Zhang   PetscErrorCode ierr;
150166b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
15021ad426b7SHong Zhang 
15031ad426b7SHong Zhang   PetscFunctionBegin;
150483b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
150583b2e829SHong Zhang   network->userVertexJacobian = vflg;
15068675203cSHong Zhang 
15078675203cSHong Zhang   if (eflg && !network->Je) {
15088675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
15098675203cSHong Zhang   }
15108675203cSHong Zhang 
151166b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
15128675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
151366b4e0ffSHong Zhang     PetscInt       nedges_total;
15148675203cSHong Zhang     const PetscInt *edges;
15158675203cSHong Zhang 
15168675203cSHong Zhang     /* count nvertex_total */
15178675203cSHong Zhang     nedges_total = 0;
15188675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
15198675203cSHong Zhang 
15208675203cSHong Zhang     vptr[0] = 0;
15218675203cSHong Zhang     for (i=0; i<nVertices; i++) {
15228675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
15238675203cSHong Zhang       nedges_total += nedges;
15248675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
15258675203cSHong Zhang     }
15268675203cSHong Zhang 
15278675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
15288675203cSHong Zhang     network->Jvptr = vptr;
15298675203cSHong Zhang   }
15301ad426b7SHong Zhang   PetscFunctionReturn(0);
15311ad426b7SHong Zhang }
15321ad426b7SHong Zhang 
15331ad426b7SHong Zhang /*@
153483b2e829SHong Zhang     DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
153583b2e829SHong Zhang 
153683b2e829SHong Zhang     Not Collective
153783b2e829SHong Zhang 
153883b2e829SHong Zhang     Input Parameters:
153983b2e829SHong Zhang +   dm - The DMNetwork object
154083b2e829SHong Zhang .   p  - the edge point
15413e97b6e8SHong Zhang -   J - array (size = 3) of Jacobian submatrices for this edge point:
15423e97b6e8SHong Zhang         J[0]: this edge
1543d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
154483b2e829SHong Zhang 
154597bb938eSShri Abhyankar     Level: advanced
154683b2e829SHong Zhang 
154783b2e829SHong Zhang .seealso: DMNetworkVertexSetMatrix
154883b2e829SHong Zhang @*/
154983b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
155083b2e829SHong Zhang {
155183b2e829SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
155283b2e829SHong Zhang 
155383b2e829SHong Zhang   PetscFunctionBegin;
15548675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
15558675203cSHong Zhang 
15568675203cSHong Zhang   if (J) {
1557883e35e8SHong Zhang     network->Je[3*p]   = J[0];
1558883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
1559883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
15608675203cSHong Zhang   }
156183b2e829SHong Zhang   PetscFunctionReturn(0);
156283b2e829SHong Zhang }
156383b2e829SHong Zhang 
156483b2e829SHong Zhang /*@
156576ddfea5SHong Zhang     DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
15661ad426b7SHong Zhang 
15671ad426b7SHong Zhang     Not Collective
15681ad426b7SHong Zhang 
15691ad426b7SHong Zhang     Input Parameters:
15701ad426b7SHong Zhang +   dm - The DMNetwork object
15711ad426b7SHong Zhang .   p  - the vertex point
15723e97b6e8SHong Zhang -   J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
15733e97b6e8SHong Zhang         J[0]:       this vertex
15743e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
15753e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
15761ad426b7SHong Zhang 
157797bb938eSShri Abhyankar     Level: advanced
15781ad426b7SHong Zhang 
157983b2e829SHong Zhang .seealso: DMNetworkEdgeSetMatrix
15801ad426b7SHong Zhang @*/
1581883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
15825f2c45f1SShri Abhyankar {
15835f2c45f1SShri Abhyankar   PetscErrorCode ierr;
15845f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
15858675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
1586883e35e8SHong Zhang   const PetscInt *edges;
15875f2c45f1SShri Abhyankar 
15885f2c45f1SShri Abhyankar   PetscFunctionBegin;
15898675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1590883e35e8SHong Zhang 
15918675203cSHong Zhang   if (J) {
1592883e35e8SHong Zhang     vptr = network->Jvptr;
15933e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
15943e97b6e8SHong Zhang 
15953e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
1596883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
1597883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
15988675203cSHong Zhang   }
1599883e35e8SHong Zhang   PetscFunctionReturn(0);
1600883e35e8SHong Zhang }
1601883e35e8SHong Zhang 
1602e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16035cf7da58SHong Zhang {
16045cf7da58SHong Zhang   PetscErrorCode ierr;
16055cf7da58SHong Zhang   PetscInt       j;
16065cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
16075cf7da58SHong Zhang 
16085cf7da58SHong Zhang   PetscFunctionBegin;
16095cf7da58SHong Zhang   if (!ghost) {
16105cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16115cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16125cf7da58SHong Zhang     }
16135cf7da58SHong Zhang   } else {
16145cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16155cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16165cf7da58SHong Zhang     }
16175cf7da58SHong Zhang   }
16185cf7da58SHong Zhang   PetscFunctionReturn(0);
16195cf7da58SHong Zhang }
16205cf7da58SHong Zhang 
1621e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16225cf7da58SHong Zhang {
16235cf7da58SHong Zhang   PetscErrorCode ierr;
16245cf7da58SHong Zhang   PetscInt       j,ncols_u;
16255cf7da58SHong Zhang   PetscScalar    val;
16265cf7da58SHong Zhang 
16275cf7da58SHong Zhang   PetscFunctionBegin;
16285cf7da58SHong Zhang   if (!ghost) {
16295cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16305cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16315cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
16325cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16335cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16345cf7da58SHong Zhang     }
16355cf7da58SHong Zhang   } else {
16365cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16375cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16385cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
16395cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16405cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16415cf7da58SHong Zhang     }
16425cf7da58SHong Zhang   }
16435cf7da58SHong Zhang   PetscFunctionReturn(0);
16445cf7da58SHong Zhang }
16455cf7da58SHong Zhang 
1646e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16475cf7da58SHong Zhang {
16485cf7da58SHong Zhang   PetscErrorCode ierr;
16495cf7da58SHong Zhang 
16505cf7da58SHong Zhang   PetscFunctionBegin;
16515cf7da58SHong Zhang   if (Ju) {
16525cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
16535cf7da58SHong Zhang   } else {
16545cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
16555cf7da58SHong Zhang   }
16565cf7da58SHong Zhang   PetscFunctionReturn(0);
16575cf7da58SHong Zhang }
16585cf7da58SHong Zhang 
1659e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1660883e35e8SHong Zhang {
1661883e35e8SHong Zhang   PetscErrorCode ierr;
1662883e35e8SHong Zhang   PetscInt       j,*cols;
1663883e35e8SHong Zhang   PetscScalar    *zeros;
1664883e35e8SHong Zhang 
1665883e35e8SHong Zhang   PetscFunctionBegin;
1666883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
1667883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
1668883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
1669883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
16701ad426b7SHong Zhang   PetscFunctionReturn(0);
16711ad426b7SHong Zhang }
1672a4e85ca8SHong Zhang 
1673e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
16743e97b6e8SHong Zhang {
16753e97b6e8SHong Zhang   PetscErrorCode ierr;
16763e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
16773e97b6e8SHong Zhang   const PetscInt *cols;
16783e97b6e8SHong Zhang   PetscScalar    zero=0.0;
16793e97b6e8SHong Zhang 
16803e97b6e8SHong Zhang   PetscFunctionBegin;
16813e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
16823e97b6e8SHong 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);
16833e97b6e8SHong Zhang 
16843e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
16853e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
16863e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
16873e97b6e8SHong Zhang       col = cols[j] + cstart;
16883e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
16893e97b6e8SHong Zhang     }
16903e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
16913e97b6e8SHong Zhang   }
16923e97b6e8SHong Zhang   PetscFunctionReturn(0);
16933e97b6e8SHong Zhang }
16941ad426b7SHong Zhang 
1695e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1696a4e85ca8SHong Zhang {
1697a4e85ca8SHong Zhang   PetscErrorCode ierr;
1698f4431b8cSHong Zhang 
1699a4e85ca8SHong Zhang   PetscFunctionBegin;
1700a4e85ca8SHong Zhang   if (Ju) {
1701a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1702a4e85ca8SHong Zhang   } else {
1703a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1704a4e85ca8SHong Zhang   }
1705a4e85ca8SHong Zhang   PetscFunctionReturn(0);
1706a4e85ca8SHong Zhang }
1707a4e85ca8SHong Zhang 
170824121865SAdrian 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.
170924121865SAdrian Maldonado */
171024121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
171124121865SAdrian Maldonado {
171224121865SAdrian Maldonado   PetscErrorCode ierr;
171324121865SAdrian Maldonado   PetscInt       i,size,dof;
171424121865SAdrian Maldonado   PetscInt       *glob2loc;
171524121865SAdrian Maldonado 
171624121865SAdrian Maldonado   PetscFunctionBegin;
171724121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
171824121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
171924121865SAdrian Maldonado 
172024121865SAdrian Maldonado   for (i = 0; i < size; i++) {
172124121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
172224121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
172324121865SAdrian Maldonado     glob2loc[i] = dof;
172424121865SAdrian Maldonado   }
172524121865SAdrian Maldonado 
172624121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
172724121865SAdrian Maldonado #if 0
172824121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
172924121865SAdrian Maldonado #endif
173024121865SAdrian Maldonado   PetscFunctionReturn(0);
173124121865SAdrian Maldonado }
173224121865SAdrian Maldonado 
173301ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
17349e1d080bSHong Zhang 
17359e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
17361ad426b7SHong Zhang {
17371ad426b7SHong Zhang   PetscErrorCode ierr;
17381ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
17399e1d080bSHong Zhang   PetscMPIInt    rank, size;
174024121865SAdrian Maldonado   PetscInt       eDof,vDof;
174124121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
17429e1d080bSHong Zhang   MPI_Comm       comm;
174324121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
174424121865SAdrian Maldonado 
17459e1d080bSHong Zhang   PetscFunctionBegin;
174624121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1747*ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
1748*ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
174924121865SAdrian Maldonado 
175024121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
175124121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
175224121865SAdrian Maldonado 
175301ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
175424121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
175524121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
175624121865SAdrian Maldonado 
175701ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
175824121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
175924121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
176024121865SAdrian Maldonado 
176101ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
176224121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
176324121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
176424121865SAdrian Maldonado 
176501ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
176624121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
176724121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
176824121865SAdrian Maldonado 
17693f6a6bdaSHong Zhang   bA[0][0] = j11;
17703f6a6bdaSHong Zhang   bA[0][1] = j12;
17713f6a6bdaSHong Zhang   bA[1][0] = j21;
17723f6a6bdaSHong Zhang   bA[1][1] = j22;
177324121865SAdrian Maldonado 
177424121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
177524121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
177624121865SAdrian Maldonado 
177724121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
177824121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
177924121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
178024121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
178124121865SAdrian Maldonado 
178224121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
178324121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
178424121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
178524121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
178624121865SAdrian Maldonado 
178701ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
178824121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
178924121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
179024121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
179124121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
179224121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
179324121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
179424121865SAdrian Maldonado 
179524121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179624121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17979e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
179824121865SAdrian Maldonado 
179924121865SAdrian Maldonado   /* Free structures */
180024121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
180124121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
180224121865SAdrian Maldonado   PetscFunctionReturn(0);
18039e1d080bSHong Zhang }
18049e1d080bSHong Zhang 
18059e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
18069e1d080bSHong Zhang {
18079e1d080bSHong Zhang   PetscErrorCode ierr;
18089e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
18099e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
18109e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
18119e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
18129e1d080bSHong Zhang   Mat            Juser;
18139e1d080bSHong Zhang   PetscSection   sectionGlobal;
18149e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
18159e1d080bSHong Zhang   const PetscInt *edges,*cone;
18169e1d080bSHong Zhang   MPI_Comm       comm;
18179e1d080bSHong Zhang   MatType        mtype;
18189e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
18199e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
18209e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
18219e1d080bSHong Zhang 
18229e1d080bSHong Zhang   PetscFunctionBegin;
18239e1d080bSHong Zhang   mtype = dm->mattype;
18249e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
18259e1d080bSHong Zhang   if (isNest) {
18269e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
1827c6b011d8SStefano Zampini     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
18289e1d080bSHong Zhang     PetscFunctionReturn(0);
18299e1d080bSHong Zhang   }
18309e1d080bSHong Zhang 
18319e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
1832a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
18339e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
1834bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
18351ad426b7SHong Zhang     PetscFunctionReturn(0);
18361ad426b7SHong Zhang   }
18371ad426b7SHong Zhang 
1838bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
1839e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
1840bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
1841bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
18422a945128SHong Zhang 
18432a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
18442a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
184589898e50SHong Zhang 
184689898e50SHong Zhang   /* (1) Set matrix preallocation */
184789898e50SHong Zhang   /*------------------------------*/
1848840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1849840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
1850840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
1851840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
1852840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
1853840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
1854840c2264SHong Zhang 
185589898e50SHong Zhang   /* Set preallocation for edges */
185689898e50SHong Zhang   /*-----------------------------*/
1857840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
1858840c2264SHong Zhang 
1859bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
1860840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
1861840c2264SHong Zhang     /* Get row indices */
1862840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
1863840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
1864840c2264SHong Zhang     if (nrows) {
1865840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
1866840c2264SHong Zhang 
18675cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
1868d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1869840c2264SHong Zhang       for (v=0; v<2; v++) {
1870840c2264SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
1871840c2264SHong Zhang 
18728675203cSHong Zhang         if (network->Je) {
1873840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
18748675203cSHong Zhang         } else Juser = NULL;
1875840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
18765cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1877840c2264SHong Zhang       }
1878840c2264SHong Zhang 
187989898e50SHong Zhang       /* Set preallocation for edge self */
1880840c2264SHong Zhang       cstart = rstart;
18818675203cSHong Zhang       if (network->Je) {
1882840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
18838675203cSHong Zhang       } else Juser = NULL;
18845cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1885840c2264SHong Zhang     }
1886840c2264SHong Zhang   }
1887840c2264SHong Zhang 
188889898e50SHong Zhang   /* Set preallocation for vertices */
188989898e50SHong Zhang   /*--------------------------------*/
1890840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
18918675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
1892840c2264SHong Zhang 
1893840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
1894840c2264SHong Zhang     /* Get row indices */
1895840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1896840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
1897840c2264SHong Zhang     if (!nrows) continue;
1898840c2264SHong Zhang 
1899bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1900bdcb62a2SHong Zhang     if (ghost) {
1901bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1902bdcb62a2SHong Zhang     } else {
1903bdcb62a2SHong Zhang       rows_v = rows;
1904bdcb62a2SHong Zhang     }
1905bdcb62a2SHong Zhang 
1906bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1907840c2264SHong Zhang 
1908840c2264SHong Zhang     /* Get supporting edges and connected vertices */
1909840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1910840c2264SHong Zhang 
1911840c2264SHong Zhang     for (e=0; e<nedges; e++) {
1912840c2264SHong Zhang       /* Supporting edges */
1913840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1914840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1915840c2264SHong Zhang 
19168675203cSHong Zhang       if (network->Jv) {
1917840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
19188675203cSHong Zhang       } else Juser = NULL;
1919bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1920840c2264SHong Zhang 
1921840c2264SHong Zhang       /* Connected vertices */
1922d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
1923840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
1924840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
1925840c2264SHong Zhang 
1926840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1927840c2264SHong Zhang 
19288675203cSHong Zhang       if (network->Jv) {
1929840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
19308675203cSHong Zhang       } else Juser = NULL;
1931e102a522SHong Zhang       if (ghost_vc||ghost) {
1932e102a522SHong Zhang         ghost2 = PETSC_TRUE;
1933e102a522SHong Zhang       } else {
1934e102a522SHong Zhang         ghost2 = PETSC_FALSE;
1935e102a522SHong Zhang       }
1936e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
1937840c2264SHong Zhang     }
1938840c2264SHong Zhang 
193989898e50SHong Zhang     /* Set preallocation for vertex self */
1940840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1941840c2264SHong Zhang     if (!ghost) {
1942840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
19438675203cSHong Zhang       if (network->Jv) {
1944840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
19458675203cSHong Zhang       } else Juser = NULL;
1946bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1947840c2264SHong Zhang     }
1948bdcb62a2SHong Zhang     if (ghost) {
1949bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1950bdcb62a2SHong Zhang     }
1951840c2264SHong Zhang   }
1952840c2264SHong Zhang 
1953840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
1954840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
19555cf7da58SHong Zhang 
19565cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
19575cf7da58SHong Zhang 
19585cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
1959840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
1960840c2264SHong Zhang 
1961840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
1962840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
1963840c2264SHong Zhang   for (j=0; j<localSize; j++) {
1964e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
1965e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
1966840c2264SHong Zhang   }
1967840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
1968840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
1969840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
1970840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
1971840c2264SHong Zhang 
19725cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
19735cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
19745cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
19755cf7da58SHong Zhang 
19765cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
19775cf7da58SHong Zhang 
197889898e50SHong Zhang   /* (2) Set matrix entries for edges */
197989898e50SHong Zhang   /*----------------------------------*/
19801ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
1981bfbc38dcSHong Zhang     /* Get row indices */
19821ad426b7SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
198317df6e9eSHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
19844b976069SHong Zhang     if (nrows) {
198517df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
19861ad426b7SHong Zhang 
1987bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
1988d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1989bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
1990bfbc38dcSHong Zhang         ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr);
1991883e35e8SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
19923e97b6e8SHong Zhang 
19938675203cSHong Zhang         if (network->Je) {
1994a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
19958675203cSHong Zhang         } else Juser = NULL;
1996a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1997bfbc38dcSHong Zhang       }
199817df6e9eSHong Zhang 
1999bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
20003e97b6e8SHong Zhang       cstart = rstart;
20018675203cSHong Zhang       if (network->Je) {
2002a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
20038675203cSHong Zhang       } else Juser = NULL;
2004a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
20051ad426b7SHong Zhang     }
20064b976069SHong Zhang   }
20071ad426b7SHong Zhang 
2008bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
200983b2e829SHong Zhang   /*---------------------------------*/
20101ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2011bfbc38dcSHong Zhang     /* Get row indices */
2012596e729fSHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
2013596e729fSHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
20144b976069SHong Zhang     if (!nrows) continue;
2015596e729fSHong Zhang 
2016bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2017bdcb62a2SHong Zhang     if (ghost) {
2018bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2019bdcb62a2SHong Zhang     } else {
2020bdcb62a2SHong Zhang       rows_v = rows;
2021bdcb62a2SHong Zhang     }
2022bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2023596e729fSHong Zhang 
2024bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2025596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2026596e729fSHong Zhang 
2027596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2028bfbc38dcSHong Zhang       /* Supporting edges */
2029596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
2030596e729fSHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
2031596e729fSHong Zhang 
20328675203cSHong Zhang       if (network->Jv) {
2033a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
20348675203cSHong Zhang       } else Juser = NULL;
2035bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2036596e729fSHong Zhang 
2037bfbc38dcSHong Zhang       /* Connected vertices */
2038d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
20392a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
20402a945128SHong Zhang 
204144aca652SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr);
204244aca652SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
2043a4e85ca8SHong Zhang 
20448675203cSHong Zhang       if (network->Jv) {
2045a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
20468675203cSHong Zhang       } else Juser = NULL;
2047bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2048596e729fSHong Zhang     }
2049596e729fSHong Zhang 
2050bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
20511ad426b7SHong Zhang     if (!ghost) {
2052596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
20538675203cSHong Zhang       if (network->Jv) {
2054a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
20558675203cSHong Zhang       } else Juser = NULL;
2056bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2057bdcb62a2SHong Zhang     }
2058bdcb62a2SHong Zhang     if (ghost) {
2059bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2060bdcb62a2SHong Zhang     }
20611ad426b7SHong Zhang   }
2062a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2063bdcb62a2SHong Zhang 
20641ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20651ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2066dd6f46cdSHong Zhang 
20675f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
20685f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20695f2c45f1SShri Abhyankar }
20705f2c45f1SShri Abhyankar 
20715f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
20725f2c45f1SShri Abhyankar {
20735f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20745f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20752727e31bSShri Abhyankar   PetscInt       j;
20765f2c45f1SShri Abhyankar 
20775f2c45f1SShri Abhyankar   PetscFunctionBegin;
20788415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
207983b2e829SHong Zhang   if (network->Je) {
208083b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
208183b2e829SHong Zhang   }
208283b2e829SHong Zhang   if (network->Jv) {
2083883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
208483b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
20851ad426b7SHong Zhang   }
208613c2a604SAdrian Maldonado 
208713c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
208813c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
208913c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2090f5427c60SHong Zhang   if (network->vltog) {
2091f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2092f5427c60SHong Zhang   }
209313c2a604SAdrian Maldonado   if (network->vertex.sf) {
209413c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
209513c2a604SAdrian Maldonado   }
209613c2a604SAdrian Maldonado   /* edge */
209713c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
209813c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
209913c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
210013c2a604SAdrian Maldonado   if (network->edge.sf) {
210113c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
210213c2a604SAdrian Maldonado   }
21035f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
21045f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
21055f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
210683b2e829SHong Zhang 
21072727e31bSShri Abhyankar   for (j=0; j<network->nsubnet; j++) {
21082727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
21092727e31bSShri Abhyankar   }
2110caf410d2SHong Zhang   ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr);
2111caf410d2SHong Zhang 
2112e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
21135f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
2114caf410d2SHong Zhang   ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
21155f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
21165f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21175f2c45f1SShri Abhyankar }
21185f2c45f1SShri Abhyankar 
21195f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
21205f2c45f1SShri Abhyankar {
21215f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21225f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
2123caf410d2SHong Zhang   PetscBool      iascii;
2124caf410d2SHong Zhang   PetscMPIInt    rank;
2125caf410d2SHong Zhang   PetscInt       p,nsubnet;
21265f2c45f1SShri Abhyankar 
21275f2c45f1SShri Abhyankar   PetscFunctionBegin;
2128caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2129*ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
2130caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2131caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2132caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2133caf410d2SHong Zhang   if (iascii) {
2134caf410d2SHong Zhang     const PetscInt    *cone,*vtx,*edges;
2135caf410d2SHong Zhang     PetscInt          vfrom,vto,i,j,nv,ne;
2136caf410d2SHong Zhang 
2137caf410d2SHong Zhang     nsubnet = network->nsubnet - network->ncsubnet; /* num of subnetworks */
2138caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
2139caf410d2SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nsubnet: %D; nsubnetCouple: %D; nEdges: %D; nVertices: %D\n",rank,nsubnet,network->ncsubnet,network->nEdges,network->nVertices);CHKERRQ(ierr);
2140caf410d2SHong Zhang 
2141caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
2142caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2143caf410d2SHong Zhang       if (ne) {
2144caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2145caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2146caf410d2SHong Zhang           p = edges[j];
2147caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2148caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2149caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2150caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2151caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2152caf410d2SHong Zhang         }
2153caf410d2SHong Zhang       }
2154caf410d2SHong Zhang     }
2155caf410d2SHong Zhang     /* Coupling subnets */
2156caf410d2SHong Zhang     nsubnet = network->nsubnet;
2157caf410d2SHong Zhang     for (; i<nsubnet; i++) {
2158caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2159caf410d2SHong Zhang       if (ne) {
2160caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D (couple): nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2161caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2162caf410d2SHong Zhang           p = edges[j];
2163caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2164caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2165caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2166d5c9c0c4SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2167caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2168caf410d2SHong Zhang         }
2169caf410d2SHong Zhang       }
2170caf410d2SHong Zhang     }
2171caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2172caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2173caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
21745f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21755f2c45f1SShri Abhyankar }
21765f2c45f1SShri Abhyankar 
21775f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
21785f2c45f1SShri Abhyankar {
21795f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21805f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21815f2c45f1SShri Abhyankar 
21825f2c45f1SShri Abhyankar   PetscFunctionBegin;
21835f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
21845f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21855f2c45f1SShri Abhyankar }
21865f2c45f1SShri Abhyankar 
21875f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
21885f2c45f1SShri Abhyankar {
21895f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21905f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21915f2c45f1SShri Abhyankar 
21925f2c45f1SShri Abhyankar   PetscFunctionBegin;
21935f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
21945f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21955f2c45f1SShri Abhyankar }
21965f2c45f1SShri Abhyankar 
21975f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
21985f2c45f1SShri Abhyankar {
21995f2c45f1SShri Abhyankar   PetscErrorCode ierr;
22005f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
22015f2c45f1SShri Abhyankar 
22025f2c45f1SShri Abhyankar   PetscFunctionBegin;
22035f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
22045f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22055f2c45f1SShri Abhyankar }
22065f2c45f1SShri Abhyankar 
22075f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
22085f2c45f1SShri Abhyankar {
22095f2c45f1SShri Abhyankar   PetscErrorCode ierr;
22105f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
22115f2c45f1SShri Abhyankar 
22125f2c45f1SShri Abhyankar   PetscFunctionBegin;
22135f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
22145f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22155f2c45f1SShri Abhyankar }
221622bbedd7SHong Zhang 
221722bbedd7SHong Zhang /*@
221864238763SRodolfo Oliveira   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index
221922bbedd7SHong Zhang 
222022bbedd7SHong Zhang   Not collective
222122bbedd7SHong Zhang 
22227a7aea1fSJed Brown   Input Parameters:
222322bbedd7SHong Zhang + dm - the dm object
222422bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
222522bbedd7SHong Zhang 
22267a7aea1fSJed Brown   Output Parameters:
2227f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
222822bbedd7SHong Zhang 
222997bb938eSShri Abhyankar   Level: advanced
223022bbedd7SHong Zhang 
223122bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
223222bbedd7SHong Zhang @*/
223322bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
223422bbedd7SHong Zhang {
223522bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
223622bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
223722bbedd7SHong Zhang 
223822bbedd7SHong Zhang   PetscFunctionBegin;
223922bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
224022bbedd7SHong Zhang   *vg = vltog[vloc];
224122bbedd7SHong Zhang   PetscFunctionReturn(0);
224222bbedd7SHong Zhang }
224322bbedd7SHong Zhang 
224422bbedd7SHong Zhang /*@
224564238763SRodolfo Oliveira   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map
224622bbedd7SHong Zhang 
224722bbedd7SHong Zhang   Collective
224822bbedd7SHong Zhang 
224922bbedd7SHong Zhang   Input Parameters:
2250f0fc11ceSJed Brown . dm - the dm object
225122bbedd7SHong Zhang 
225297bb938eSShri Abhyankar   Level: advanced
225322bbedd7SHong Zhang 
225463029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
225522bbedd7SHong Zhang @*/
225622bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
225722bbedd7SHong Zhang {
225822bbedd7SHong Zhang   PetscErrorCode    ierr;
225922bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
226022bbedd7SHong Zhang   MPI_Comm          comm;
226163029d29SHong Zhang   PetscMPIInt       rank,size,*displs,*recvcounts,remoterank;
226222bbedd7SHong Zhang   PetscBool         ghost;
226363029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
226422bbedd7SHong Zhang   const PetscSFNode *iremote;
226522bbedd7SHong Zhang   PetscSF           vsf;
226663029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
226763029d29SHong Zhang   VecScatter        ctx;
226863029d29SHong Zhang   PetscScalar       *varr,val;
226963029d29SHong Zhang   const PetscScalar *varr_read;
227022bbedd7SHong Zhang 
227122bbedd7SHong Zhang   PetscFunctionBegin;
227222bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2273*ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
2274*ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
227522bbedd7SHong Zhang 
227622bbedd7SHong Zhang   if (size == 1) {
227722bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
227822bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
227922bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
228022bbedd7SHong Zhang     network->vltog = vltog;
228122bbedd7SHong Zhang     PetscFunctionReturn(0);
228222bbedd7SHong Zhang   }
228322bbedd7SHong Zhang 
228422bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
228522bbedd7SHong Zhang   if (network->vltog) {
228622bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
228722bbedd7SHong Zhang   }
228822bbedd7SHong Zhang 
228922bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
229022bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
229122bbedd7SHong Zhang   vsf = network->vertex.sf;
229222bbedd7SHong Zhang 
229322bbedd7SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size+1,&displs,size,&recvcounts);CHKERRQ(ierr);
2294f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
229522bbedd7SHong Zhang 
229622bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
229722bbedd7SHong Zhang 
229822bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
229922bbedd7SHong Zhang   vrange[0] = 0;
2300*ffc4695bSBarry Smith   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
230167dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
230222bbedd7SHong Zhang 
230322bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
230422bbedd7SHong Zhang   network->vltog = vltog;
230522bbedd7SHong Zhang 
230663029d29SHong Zhang   /* Set vltog for non-ghost vertices */
230763029d29SHong Zhang   k = 0;
230822bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
230922bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
231063029d29SHong Zhang     if (ghost) continue;
231163029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
231222bbedd7SHong Zhang   }
2313f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
231463029d29SHong Zhang 
231563029d29SHong Zhang   /* Set vltog for ghost vertices */
231663029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
231763029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
231863029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
231963029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
232063029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
232163029d29SHong Zhang   for (i=0; i<nleaves; i++) {
232263029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
232363029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
232463029d29SHong Zhang   }
232563029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
232663029d29SHong Zhang 
232763029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
232863029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
232963029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
233063029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
233163029d29SHong Zhang 
233263029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
233363029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
233463029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
233563029d29SHong Zhang   for (i=0; i<N; i+=2) {
23362e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
233763029d29SHong Zhang     if (remoterank == rank) {
233863029d29SHong Zhang       k = i+1; /* row number */
23392e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
234063029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
234163029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
234263029d29SHong Zhang     }
234363029d29SHong Zhang   }
234463029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
234563029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
234663029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
234763029d29SHong Zhang 
234863029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
234963029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
235063029d29SHong Zhang   k = 0;
235163029d29SHong Zhang   for (i=0; i<nroots; i++) {
235263029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
235363029d29SHong Zhang     if (!ghost) continue;
23542e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
235563029d29SHong Zhang   }
235663029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
235763029d29SHong Zhang 
235863029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
235963029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
236063029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
236122bbedd7SHong Zhang   PetscFunctionReturn(0);
236222bbedd7SHong Zhang }
2363