xref: /petsc/src/dm/impls/network/network.c (revision 8e71b177f4c538fc06c0847ff35010cf9fd15769)
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;
204*8e71b177SVaclav 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);
213caf410d2SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
214caf410d2SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
2156500d4abSHong Zhang 
216caf410d2SHong Zhang   /* Create the local edgelist for the network by concatenating local input edgelists of the subnetworks */
217*8e71b177SVaclav 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 */
256*8e71b177SVaclav Hapla   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
257*8e71b177SVaclav Hapla   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
258*8e71b177SVaclav Hapla   ierr = DMSetDimension(network->plex,dim);CHKERRQ(ierr);
259caf410d2SHong Zhang   if (size == 1) {
260*8e71b177SVaclav Hapla     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices,numCorners,edges,PETSC_FALSE);CHKERRQ(ierr);
261caf410d2SHong Zhang   } else {
262*8e71b177SVaclav Hapla     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices,numCorners,edges,PETSC_FALSE,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   }
289*8e71b177SVaclav 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;
305caf410d2SHong Zhang   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRQ(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);
115224121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
11539852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(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);
1215d3464fd4SAdrian Maldonado   ierr = MPI_Comm_size(comm, &size);CHKERRQ(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.
13207d928bffSSatish Balay @*/
132124121865SAdrian Maldonado PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) {
132224121865SAdrian Maldonado 
132324121865SAdrian Maldonado   PetscErrorCode        ierr;
132424121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
132524121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
132624121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
132724121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
132824121865SAdrian Maldonado   const PetscInt        *ilocal;
132924121865SAdrian Maldonado   const PetscSFNode     *iremote;
133024121865SAdrian Maldonado 
133124121865SAdrian Maldonado   PetscFunctionBegin;
133224121865SAdrian Maldonado   ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
133324121865SAdrian Maldonado 
133424121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
133524121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
133624121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
133724121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
133824121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
133924121865SAdrian Maldonado   }
134024121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
134124121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
134224121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
134324121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
134424121865SAdrian Maldonado   ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
134524121865SAdrian Maldonado   ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
134624121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
13474b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
13484b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
134924121865SAdrian Maldonado   nleaves_sub = 0;
135024121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
135124121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
135224121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
13534b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
135424121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
135524121865SAdrian Maldonado       nleaves_sub += 1;
135624121865SAdrian Maldonado     }
135724121865SAdrian Maldonado   }
135824121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
135924121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
136024121865SAdrian Maldonado 
136124121865SAdrian Maldonado   /* Create new subSF */
136224121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
136324121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
13644b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
136524121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
13664b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
136724121865SAdrian Maldonado   PetscFunctionReturn(0);
136824121865SAdrian Maldonado }
136924121865SAdrian Maldonado 
13705f2c45f1SShri Abhyankar /*@C
13715f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
13725f2c45f1SShri Abhyankar 
13735f2c45f1SShri Abhyankar   Not Collective
13745f2c45f1SShri Abhyankar 
13755f2c45f1SShri Abhyankar   Input Parameters:
13765f2c45f1SShri Abhyankar + dm - The DMNetwork object
13775f2c45f1SShri Abhyankar - p  - the vertex point
13785f2c45f1SShri Abhyankar 
1379fd292e60Sprj-   Output Parameters:
13805f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
13815f2c45f1SShri Abhyankar - edges  - List of edge points
13825f2c45f1SShri Abhyankar 
138397bb938eSShri Abhyankar   Level: beginner
13845f2c45f1SShri Abhyankar 
13855f2c45f1SShri Abhyankar   Fortran Notes:
13865f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
13875f2c45f1SShri Abhyankar   include petsc.h90 in your code.
13885f2c45f1SShri Abhyankar 
1389d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices
13905f2c45f1SShri Abhyankar @*/
13915f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
13925f2c45f1SShri Abhyankar {
13935f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13945f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
13955f2c45f1SShri Abhyankar 
13965f2c45f1SShri Abhyankar   PetscFunctionBegin;
13975f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
13985f2c45f1SShri Abhyankar   ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);
13995f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14005f2c45f1SShri Abhyankar }
14015f2c45f1SShri Abhyankar 
14025f2c45f1SShri Abhyankar /*@C
1403d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
14045f2c45f1SShri Abhyankar 
14055f2c45f1SShri Abhyankar   Not Collective
14065f2c45f1SShri Abhyankar 
14075f2c45f1SShri Abhyankar   Input Parameters:
14085f2c45f1SShri Abhyankar + dm - The DMNetwork object
14095f2c45f1SShri Abhyankar - p  - the edge point
14105f2c45f1SShri Abhyankar 
1411fd292e60Sprj-   Output Parameters:
14125f2c45f1SShri Abhyankar . vertices  - vertices connected to this edge
14135f2c45f1SShri Abhyankar 
141497bb938eSShri Abhyankar   Level: beginner
14155f2c45f1SShri Abhyankar 
14165f2c45f1SShri Abhyankar   Fortran Notes:
14175f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
14185f2c45f1SShri Abhyankar   include petsc.h90 in your code.
14195f2c45f1SShri Abhyankar 
14205f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
14215f2c45f1SShri Abhyankar @*/
1422d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
14235f2c45f1SShri Abhyankar {
14245f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14255f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14265f2c45f1SShri Abhyankar 
14275f2c45f1SShri Abhyankar   PetscFunctionBegin;
14285f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
14295f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14305f2c45f1SShri Abhyankar }
14315f2c45f1SShri Abhyankar 
14325f2c45f1SShri Abhyankar /*@
14335f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
14345f2c45f1SShri Abhyankar 
14355f2c45f1SShri Abhyankar   Not Collective
14365f2c45f1SShri Abhyankar 
14375f2c45f1SShri Abhyankar   Input Parameters:
14385f2c45f1SShri Abhyankar + dm - The DMNetwork object
1439a2b725a8SWilliam Gropp - p  - the vertex point
14405f2c45f1SShri Abhyankar 
14415f2c45f1SShri Abhyankar   Output Parameter:
14425f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
14435f2c45f1SShri Abhyankar 
144497bb938eSShri Abhyankar   Level: beginner
14455f2c45f1SShri Abhyankar 
1446d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange
14475f2c45f1SShri Abhyankar @*/
14485f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
14495f2c45f1SShri Abhyankar {
14505f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14515f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14525f2c45f1SShri Abhyankar   PetscInt       offsetg;
14535f2c45f1SShri Abhyankar   PetscSection   sectiong;
14545f2c45f1SShri Abhyankar 
14555f2c45f1SShri Abhyankar   PetscFunctionBegin;
1456caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
14575f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
1458e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
14595f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
14605f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
14615f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14625f2c45f1SShri Abhyankar }
14635f2c45f1SShri Abhyankar 
14645f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
14655f2c45f1SShri Abhyankar {
14665f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14675f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
14685f2c45f1SShri Abhyankar 
14695f2c45f1SShri Abhyankar   PetscFunctionBegin;
14705f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
14715f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
14725f2c45f1SShri Abhyankar 
147392fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
1474e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
14759e1d080bSHong Zhang 
14769e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
14779e1d080bSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dm_view");CHKERRQ(ierr);
14785f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14795f2c45f1SShri Abhyankar }
14805f2c45f1SShri Abhyankar 
14811ad426b7SHong Zhang /*@
148217df6e9eSHong Zhang     DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
14831ad426b7SHong Zhang                             -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
14841ad426b7SHong Zhang 
14851ad426b7SHong Zhang     Collective
14861ad426b7SHong Zhang 
14871ad426b7SHong Zhang     Input Parameters:
148883b2e829SHong Zhang +   dm - The DMNetwork object
148983b2e829SHong Zhang .   eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
149083b2e829SHong Zhang -   vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
14911ad426b7SHong Zhang 
14921ad426b7SHong Zhang     Level: intermediate
14931ad426b7SHong Zhang 
14941ad426b7SHong Zhang @*/
149583b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
14961ad426b7SHong Zhang {
14971ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
14988675203cSHong Zhang   PetscErrorCode ierr;
149966b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
15001ad426b7SHong Zhang 
15011ad426b7SHong Zhang   PetscFunctionBegin;
150283b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
150383b2e829SHong Zhang   network->userVertexJacobian = vflg;
15048675203cSHong Zhang 
15058675203cSHong Zhang   if (eflg && !network->Je) {
15068675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
15078675203cSHong Zhang   }
15088675203cSHong Zhang 
150966b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
15108675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
151166b4e0ffSHong Zhang     PetscInt       nedges_total;
15128675203cSHong Zhang     const PetscInt *edges;
15138675203cSHong Zhang 
15148675203cSHong Zhang     /* count nvertex_total */
15158675203cSHong Zhang     nedges_total = 0;
15168675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
15178675203cSHong Zhang 
15188675203cSHong Zhang     vptr[0] = 0;
15198675203cSHong Zhang     for (i=0; i<nVertices; i++) {
15208675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
15218675203cSHong Zhang       nedges_total += nedges;
15228675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
15238675203cSHong Zhang     }
15248675203cSHong Zhang 
15258675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
15268675203cSHong Zhang     network->Jvptr = vptr;
15278675203cSHong Zhang   }
15281ad426b7SHong Zhang   PetscFunctionReturn(0);
15291ad426b7SHong Zhang }
15301ad426b7SHong Zhang 
15311ad426b7SHong Zhang /*@
153283b2e829SHong Zhang     DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
153383b2e829SHong Zhang 
153483b2e829SHong Zhang     Not Collective
153583b2e829SHong Zhang 
153683b2e829SHong Zhang     Input Parameters:
153783b2e829SHong Zhang +   dm - The DMNetwork object
153883b2e829SHong Zhang .   p  - the edge point
15393e97b6e8SHong Zhang -   J - array (size = 3) of Jacobian submatrices for this edge point:
15403e97b6e8SHong Zhang         J[0]: this edge
1541d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
154283b2e829SHong Zhang 
154397bb938eSShri Abhyankar     Level: advanced
154483b2e829SHong Zhang 
154583b2e829SHong Zhang .seealso: DMNetworkVertexSetMatrix
154683b2e829SHong Zhang @*/
154783b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
154883b2e829SHong Zhang {
154983b2e829SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
155083b2e829SHong Zhang 
155183b2e829SHong Zhang   PetscFunctionBegin;
15528675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
15538675203cSHong Zhang 
15548675203cSHong Zhang   if (J) {
1555883e35e8SHong Zhang     network->Je[3*p]   = J[0];
1556883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
1557883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
15588675203cSHong Zhang   }
155983b2e829SHong Zhang   PetscFunctionReturn(0);
156083b2e829SHong Zhang }
156183b2e829SHong Zhang 
156283b2e829SHong Zhang /*@
156376ddfea5SHong Zhang     DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
15641ad426b7SHong Zhang 
15651ad426b7SHong Zhang     Not Collective
15661ad426b7SHong Zhang 
15671ad426b7SHong Zhang     Input Parameters:
15681ad426b7SHong Zhang +   dm - The DMNetwork object
15691ad426b7SHong Zhang .   p  - the vertex point
15703e97b6e8SHong Zhang -   J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
15713e97b6e8SHong Zhang         J[0]:       this vertex
15723e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
15733e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
15741ad426b7SHong Zhang 
157597bb938eSShri Abhyankar     Level: advanced
15761ad426b7SHong Zhang 
157783b2e829SHong Zhang .seealso: DMNetworkEdgeSetMatrix
15781ad426b7SHong Zhang @*/
1579883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
15805f2c45f1SShri Abhyankar {
15815f2c45f1SShri Abhyankar   PetscErrorCode ierr;
15825f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
15838675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
1584883e35e8SHong Zhang   const PetscInt *edges;
15855f2c45f1SShri Abhyankar 
15865f2c45f1SShri Abhyankar   PetscFunctionBegin;
15878675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1588883e35e8SHong Zhang 
15898675203cSHong Zhang   if (J) {
1590883e35e8SHong Zhang     vptr = network->Jvptr;
15913e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
15923e97b6e8SHong Zhang 
15933e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
1594883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
1595883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
15968675203cSHong Zhang   }
1597883e35e8SHong Zhang   PetscFunctionReturn(0);
1598883e35e8SHong Zhang }
1599883e35e8SHong Zhang 
1600e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16015cf7da58SHong Zhang {
16025cf7da58SHong Zhang   PetscErrorCode ierr;
16035cf7da58SHong Zhang   PetscInt       j;
16045cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
16055cf7da58SHong Zhang 
16065cf7da58SHong Zhang   PetscFunctionBegin;
16075cf7da58SHong Zhang   if (!ghost) {
16085cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16095cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16105cf7da58SHong Zhang     }
16115cf7da58SHong Zhang   } else {
16125cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16135cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16145cf7da58SHong Zhang     }
16155cf7da58SHong Zhang   }
16165cf7da58SHong Zhang   PetscFunctionReturn(0);
16175cf7da58SHong Zhang }
16185cf7da58SHong Zhang 
1619e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16205cf7da58SHong Zhang {
16215cf7da58SHong Zhang   PetscErrorCode ierr;
16225cf7da58SHong Zhang   PetscInt       j,ncols_u;
16235cf7da58SHong Zhang   PetscScalar    val;
16245cf7da58SHong Zhang 
16255cf7da58SHong Zhang   PetscFunctionBegin;
16265cf7da58SHong Zhang   if (!ghost) {
16275cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16285cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16295cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
16305cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16315cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16325cf7da58SHong Zhang     }
16335cf7da58SHong Zhang   } else {
16345cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
16355cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16365cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
16375cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
16385cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
16395cf7da58SHong Zhang     }
16405cf7da58SHong Zhang   }
16415cf7da58SHong Zhang   PetscFunctionReturn(0);
16425cf7da58SHong Zhang }
16435cf7da58SHong Zhang 
1644e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
16455cf7da58SHong Zhang {
16465cf7da58SHong Zhang   PetscErrorCode ierr;
16475cf7da58SHong Zhang 
16485cf7da58SHong Zhang   PetscFunctionBegin;
16495cf7da58SHong Zhang   if (Ju) {
16505cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
16515cf7da58SHong Zhang   } else {
16525cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
16535cf7da58SHong Zhang   }
16545cf7da58SHong Zhang   PetscFunctionReturn(0);
16555cf7da58SHong Zhang }
16565cf7da58SHong Zhang 
1657e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1658883e35e8SHong Zhang {
1659883e35e8SHong Zhang   PetscErrorCode ierr;
1660883e35e8SHong Zhang   PetscInt       j,*cols;
1661883e35e8SHong Zhang   PetscScalar    *zeros;
1662883e35e8SHong Zhang 
1663883e35e8SHong Zhang   PetscFunctionBegin;
1664883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
1665883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
1666883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
1667883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
16681ad426b7SHong Zhang   PetscFunctionReturn(0);
16691ad426b7SHong Zhang }
1670a4e85ca8SHong Zhang 
1671e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
16723e97b6e8SHong Zhang {
16733e97b6e8SHong Zhang   PetscErrorCode ierr;
16743e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
16753e97b6e8SHong Zhang   const PetscInt *cols;
16763e97b6e8SHong Zhang   PetscScalar    zero=0.0;
16773e97b6e8SHong Zhang 
16783e97b6e8SHong Zhang   PetscFunctionBegin;
16793e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
16803e97b6e8SHong 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);
16813e97b6e8SHong Zhang 
16823e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
16833e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
16843e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
16853e97b6e8SHong Zhang       col = cols[j] + cstart;
16863e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
16873e97b6e8SHong Zhang     }
16883e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
16893e97b6e8SHong Zhang   }
16903e97b6e8SHong Zhang   PetscFunctionReturn(0);
16913e97b6e8SHong Zhang }
16921ad426b7SHong Zhang 
1693e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1694a4e85ca8SHong Zhang {
1695a4e85ca8SHong Zhang   PetscErrorCode ierr;
1696f4431b8cSHong Zhang 
1697a4e85ca8SHong Zhang   PetscFunctionBegin;
1698a4e85ca8SHong Zhang   if (Ju) {
1699a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1700a4e85ca8SHong Zhang   } else {
1701a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1702a4e85ca8SHong Zhang   }
1703a4e85ca8SHong Zhang   PetscFunctionReturn(0);
1704a4e85ca8SHong Zhang }
1705a4e85ca8SHong Zhang 
170624121865SAdrian 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.
170724121865SAdrian Maldonado */
170824121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
170924121865SAdrian Maldonado {
171024121865SAdrian Maldonado   PetscErrorCode ierr;
171124121865SAdrian Maldonado   PetscInt       i,size,dof;
171224121865SAdrian Maldonado   PetscInt       *glob2loc;
171324121865SAdrian Maldonado 
171424121865SAdrian Maldonado   PetscFunctionBegin;
171524121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
171624121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
171724121865SAdrian Maldonado 
171824121865SAdrian Maldonado   for (i = 0; i < size; i++) {
171924121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
172024121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
172124121865SAdrian Maldonado     glob2loc[i] = dof;
172224121865SAdrian Maldonado   }
172324121865SAdrian Maldonado 
172424121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
172524121865SAdrian Maldonado #if 0
172624121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
172724121865SAdrian Maldonado #endif
172824121865SAdrian Maldonado   PetscFunctionReturn(0);
172924121865SAdrian Maldonado }
173024121865SAdrian Maldonado 
173101ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
17329e1d080bSHong Zhang 
17339e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
17341ad426b7SHong Zhang {
17351ad426b7SHong Zhang   PetscErrorCode ierr;
17361ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
17379e1d080bSHong Zhang   PetscMPIInt    rank, size;
173824121865SAdrian Maldonado   PetscInt       eDof,vDof;
173924121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
17409e1d080bSHong Zhang   MPI_Comm       comm;
174124121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
174224121865SAdrian Maldonado 
17439e1d080bSHong Zhang   PetscFunctionBegin;
174424121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
174524121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
174624121865SAdrian Maldonado   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
174724121865SAdrian Maldonado 
174824121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
174924121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
175024121865SAdrian Maldonado 
175101ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
175224121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
175324121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
175424121865SAdrian Maldonado 
175501ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
175624121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
175724121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
175824121865SAdrian Maldonado 
175901ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
176024121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
176124121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
176224121865SAdrian Maldonado 
176301ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
176424121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
176524121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
176624121865SAdrian Maldonado 
17673f6a6bdaSHong Zhang   bA[0][0] = j11;
17683f6a6bdaSHong Zhang   bA[0][1] = j12;
17693f6a6bdaSHong Zhang   bA[1][0] = j21;
17703f6a6bdaSHong Zhang   bA[1][1] = j22;
177124121865SAdrian Maldonado 
177224121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
177324121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
177424121865SAdrian Maldonado 
177524121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
177624121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
177724121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
177824121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
177924121865SAdrian Maldonado 
178024121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
178124121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
178224121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
178324121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
178424121865SAdrian Maldonado 
178501ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
178624121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
178724121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
178824121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
178924121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
179024121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
179124121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
179224121865SAdrian Maldonado 
179324121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179424121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17959e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
179624121865SAdrian Maldonado 
179724121865SAdrian Maldonado   /* Free structures */
179824121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
179924121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
180024121865SAdrian Maldonado   PetscFunctionReturn(0);
18019e1d080bSHong Zhang }
18029e1d080bSHong Zhang 
18039e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
18049e1d080bSHong Zhang {
18059e1d080bSHong Zhang   PetscErrorCode ierr;
18069e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
18079e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
18089e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
18099e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
18109e1d080bSHong Zhang   Mat            Juser;
18119e1d080bSHong Zhang   PetscSection   sectionGlobal;
18129e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
18139e1d080bSHong Zhang   const PetscInt *edges,*cone;
18149e1d080bSHong Zhang   MPI_Comm       comm;
18159e1d080bSHong Zhang   MatType        mtype;
18169e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
18179e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
18189e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
18199e1d080bSHong Zhang 
18209e1d080bSHong Zhang   PetscFunctionBegin;
18219e1d080bSHong Zhang   mtype = dm->mattype;
18229e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
18239e1d080bSHong Zhang   if (isNest) {
18249e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
1825c6b011d8SStefano Zampini     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
18269e1d080bSHong Zhang     PetscFunctionReturn(0);
18279e1d080bSHong Zhang   }
18289e1d080bSHong Zhang 
18299e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
1830a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
18319e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
1832bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
18331ad426b7SHong Zhang     PetscFunctionReturn(0);
18341ad426b7SHong Zhang   }
18351ad426b7SHong Zhang 
1836bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
1837e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
1838bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
1839bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
18402a945128SHong Zhang 
18412a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
18422a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
184389898e50SHong Zhang 
184489898e50SHong Zhang   /* (1) Set matrix preallocation */
184589898e50SHong Zhang   /*------------------------------*/
1846840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1847840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
1848840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
1849840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
1850840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
1851840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
1852840c2264SHong Zhang 
185389898e50SHong Zhang   /* Set preallocation for edges */
185489898e50SHong Zhang   /*-----------------------------*/
1855840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
1856840c2264SHong Zhang 
1857bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
1858840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
1859840c2264SHong Zhang     /* Get row indices */
1860840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
1861840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
1862840c2264SHong Zhang     if (nrows) {
1863840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
1864840c2264SHong Zhang 
18655cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
1866d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1867840c2264SHong Zhang       for (v=0; v<2; v++) {
1868840c2264SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
1869840c2264SHong Zhang 
18708675203cSHong Zhang         if (network->Je) {
1871840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
18728675203cSHong Zhang         } else Juser = NULL;
1873840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
18745cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1875840c2264SHong Zhang       }
1876840c2264SHong Zhang 
187789898e50SHong Zhang       /* Set preallocation for edge self */
1878840c2264SHong Zhang       cstart = rstart;
18798675203cSHong Zhang       if (network->Je) {
1880840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
18818675203cSHong Zhang       } else Juser = NULL;
18825cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1883840c2264SHong Zhang     }
1884840c2264SHong Zhang   }
1885840c2264SHong Zhang 
188689898e50SHong Zhang   /* Set preallocation for vertices */
188789898e50SHong Zhang   /*--------------------------------*/
1888840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
18898675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
1890840c2264SHong Zhang 
1891840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
1892840c2264SHong Zhang     /* Get row indices */
1893840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1894840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
1895840c2264SHong Zhang     if (!nrows) continue;
1896840c2264SHong Zhang 
1897bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1898bdcb62a2SHong Zhang     if (ghost) {
1899bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1900bdcb62a2SHong Zhang     } else {
1901bdcb62a2SHong Zhang       rows_v = rows;
1902bdcb62a2SHong Zhang     }
1903bdcb62a2SHong Zhang 
1904bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1905840c2264SHong Zhang 
1906840c2264SHong Zhang     /* Get supporting edges and connected vertices */
1907840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1908840c2264SHong Zhang 
1909840c2264SHong Zhang     for (e=0; e<nedges; e++) {
1910840c2264SHong Zhang       /* Supporting edges */
1911840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1912840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1913840c2264SHong Zhang 
19148675203cSHong Zhang       if (network->Jv) {
1915840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
19168675203cSHong Zhang       } else Juser = NULL;
1917bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1918840c2264SHong Zhang 
1919840c2264SHong Zhang       /* Connected vertices */
1920d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
1921840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
1922840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
1923840c2264SHong Zhang 
1924840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1925840c2264SHong Zhang 
19268675203cSHong Zhang       if (network->Jv) {
1927840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
19288675203cSHong Zhang       } else Juser = NULL;
1929e102a522SHong Zhang       if (ghost_vc||ghost) {
1930e102a522SHong Zhang         ghost2 = PETSC_TRUE;
1931e102a522SHong Zhang       } else {
1932e102a522SHong Zhang         ghost2 = PETSC_FALSE;
1933e102a522SHong Zhang       }
1934e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
1935840c2264SHong Zhang     }
1936840c2264SHong Zhang 
193789898e50SHong Zhang     /* Set preallocation for vertex self */
1938840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1939840c2264SHong Zhang     if (!ghost) {
1940840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
19418675203cSHong Zhang       if (network->Jv) {
1942840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
19438675203cSHong Zhang       } else Juser = NULL;
1944bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1945840c2264SHong Zhang     }
1946bdcb62a2SHong Zhang     if (ghost) {
1947bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1948bdcb62a2SHong Zhang     }
1949840c2264SHong Zhang   }
1950840c2264SHong Zhang 
1951840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
1952840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
19535cf7da58SHong Zhang 
19545cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
19555cf7da58SHong Zhang 
19565cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
1957840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
1958840c2264SHong Zhang 
1959840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
1960840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
1961840c2264SHong Zhang   for (j=0; j<localSize; j++) {
1962e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
1963e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
1964840c2264SHong Zhang   }
1965840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
1966840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
1967840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
1968840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
1969840c2264SHong Zhang 
19705cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
19715cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
19725cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
19735cf7da58SHong Zhang 
19745cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
19755cf7da58SHong Zhang 
197689898e50SHong Zhang   /* (2) Set matrix entries for edges */
197789898e50SHong Zhang   /*----------------------------------*/
19781ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
1979bfbc38dcSHong Zhang     /* Get row indices */
19801ad426b7SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
198117df6e9eSHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
19824b976069SHong Zhang     if (nrows) {
198317df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
19841ad426b7SHong Zhang 
1985bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
1986d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1987bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
1988bfbc38dcSHong Zhang         ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr);
1989883e35e8SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
19903e97b6e8SHong Zhang 
19918675203cSHong Zhang         if (network->Je) {
1992a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
19938675203cSHong Zhang         } else Juser = NULL;
1994a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1995bfbc38dcSHong Zhang       }
199617df6e9eSHong Zhang 
1997bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
19983e97b6e8SHong Zhang       cstart = rstart;
19998675203cSHong Zhang       if (network->Je) {
2000a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
20018675203cSHong Zhang       } else Juser = NULL;
2002a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
20031ad426b7SHong Zhang     }
20044b976069SHong Zhang   }
20051ad426b7SHong Zhang 
2006bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
200783b2e829SHong Zhang   /*---------------------------------*/
20081ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2009bfbc38dcSHong Zhang     /* Get row indices */
2010596e729fSHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
2011596e729fSHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
20124b976069SHong Zhang     if (!nrows) continue;
2013596e729fSHong Zhang 
2014bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2015bdcb62a2SHong Zhang     if (ghost) {
2016bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2017bdcb62a2SHong Zhang     } else {
2018bdcb62a2SHong Zhang       rows_v = rows;
2019bdcb62a2SHong Zhang     }
2020bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2021596e729fSHong Zhang 
2022bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2023596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2024596e729fSHong Zhang 
2025596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2026bfbc38dcSHong Zhang       /* Supporting edges */
2027596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
2028596e729fSHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
2029596e729fSHong Zhang 
20308675203cSHong Zhang       if (network->Jv) {
2031a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
20328675203cSHong Zhang       } else Juser = NULL;
2033bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2034596e729fSHong Zhang 
2035bfbc38dcSHong Zhang       /* Connected vertices */
2036d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
20372a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
20382a945128SHong Zhang 
203944aca652SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr);
204044aca652SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
2041a4e85ca8SHong Zhang 
20428675203cSHong Zhang       if (network->Jv) {
2043a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
20448675203cSHong Zhang       } else Juser = NULL;
2045bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2046596e729fSHong Zhang     }
2047596e729fSHong Zhang 
2048bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
20491ad426b7SHong Zhang     if (!ghost) {
2050596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
20518675203cSHong Zhang       if (network->Jv) {
2052a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
20538675203cSHong Zhang       } else Juser = NULL;
2054bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2055bdcb62a2SHong Zhang     }
2056bdcb62a2SHong Zhang     if (ghost) {
2057bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2058bdcb62a2SHong Zhang     }
20591ad426b7SHong Zhang   }
2060a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2061bdcb62a2SHong Zhang 
20621ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20631ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2064dd6f46cdSHong Zhang 
20655f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
20665f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20675f2c45f1SShri Abhyankar }
20685f2c45f1SShri Abhyankar 
20695f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
20705f2c45f1SShri Abhyankar {
20715f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20725f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20732727e31bSShri Abhyankar   PetscInt       j;
20745f2c45f1SShri Abhyankar 
20755f2c45f1SShri Abhyankar   PetscFunctionBegin;
20768415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
207783b2e829SHong Zhang   if (network->Je) {
207883b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
207983b2e829SHong Zhang   }
208083b2e829SHong Zhang   if (network->Jv) {
2081883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
208283b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
20831ad426b7SHong Zhang   }
208413c2a604SAdrian Maldonado 
208513c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
208613c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
208713c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2088f5427c60SHong Zhang   if (network->vltog) {
2089f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2090f5427c60SHong Zhang   }
209113c2a604SAdrian Maldonado   if (network->vertex.sf) {
209213c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
209313c2a604SAdrian Maldonado   }
209413c2a604SAdrian Maldonado   /* edge */
209513c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
209613c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
209713c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
209813c2a604SAdrian Maldonado   if (network->edge.sf) {
209913c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
210013c2a604SAdrian Maldonado   }
21015f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
21025f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
21035f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
210483b2e829SHong Zhang 
21052727e31bSShri Abhyankar   for(j=0; j<network->nsubnet; j++) {
21062727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
21072727e31bSShri Abhyankar   }
2108caf410d2SHong Zhang   ierr = PetscFree(network->subnetvtx);CHKERRQ(ierr);
2109caf410d2SHong Zhang 
2110e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
21115f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
2112caf410d2SHong Zhang   ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
21135f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
21145f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21155f2c45f1SShri Abhyankar }
21165f2c45f1SShri Abhyankar 
21175f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
21185f2c45f1SShri Abhyankar {
21195f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21205f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
2121caf410d2SHong Zhang   PetscBool      iascii;
2122caf410d2SHong Zhang   PetscMPIInt    rank;
2123caf410d2SHong Zhang   PetscInt       p,nsubnet;
21245f2c45f1SShri Abhyankar 
21255f2c45f1SShri Abhyankar   PetscFunctionBegin;
2126caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2127caf410d2SHong Zhang   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
2128caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2129caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2130caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2131caf410d2SHong Zhang   if (iascii) {
2132caf410d2SHong Zhang     const PetscInt    *cone,*vtx,*edges;
2133caf410d2SHong Zhang     PetscInt          vfrom,vto,i,j,nv,ne;
2134caf410d2SHong Zhang 
2135caf410d2SHong Zhang     nsubnet = network->nsubnet - network->ncsubnet; /* num of subnetworks */
2136caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
2137caf410d2SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nsubnet: %D; nsubnetCouple: %D; nEdges: %D; nVertices: %D\n",rank,nsubnet,network->ncsubnet,network->nEdges,network->nVertices);CHKERRQ(ierr);
2138caf410d2SHong Zhang 
2139caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
2140caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2141caf410d2SHong Zhang       if (ne) {
2142caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2143caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2144caf410d2SHong Zhang           p = edges[j];
2145caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2146caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2147caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2148caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2149caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2150caf410d2SHong Zhang         }
2151caf410d2SHong Zhang       }
2152caf410d2SHong Zhang     }
2153caf410d2SHong Zhang     /* Coupling subnets */
2154caf410d2SHong Zhang     nsubnet = network->nsubnet;
2155caf410d2SHong Zhang     for (; i<nsubnet; i++) {
2156caf410d2SHong Zhang       ierr = DMNetworkGetSubnetworkInfo(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2157caf410d2SHong Zhang       if (ne) {
2158caf410d2SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D (couple): nEdges %D, nVertices %D\n",i,ne,nv);CHKERRQ(ierr);
2159caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2160caf410d2SHong Zhang           p = edges[j];
2161caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2162caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2163caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2164d5c9c0c4SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2165caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2166caf410d2SHong Zhang         }
2167caf410d2SHong Zhang       }
2168caf410d2SHong Zhang     }
2169caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2170caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2171caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
21725f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21735f2c45f1SShri Abhyankar }
21745f2c45f1SShri Abhyankar 
21755f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
21765f2c45f1SShri Abhyankar {
21775f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21785f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21795f2c45f1SShri Abhyankar 
21805f2c45f1SShri Abhyankar   PetscFunctionBegin;
21815f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
21825f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21835f2c45f1SShri Abhyankar }
21845f2c45f1SShri Abhyankar 
21855f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
21865f2c45f1SShri Abhyankar {
21875f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21885f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21895f2c45f1SShri Abhyankar 
21905f2c45f1SShri Abhyankar   PetscFunctionBegin;
21915f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
21925f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
21935f2c45f1SShri Abhyankar }
21945f2c45f1SShri Abhyankar 
21955f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
21965f2c45f1SShri Abhyankar {
21975f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21985f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
21995f2c45f1SShri Abhyankar 
22005f2c45f1SShri Abhyankar   PetscFunctionBegin;
22015f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
22025f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22035f2c45f1SShri Abhyankar }
22045f2c45f1SShri Abhyankar 
22055f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
22065f2c45f1SShri Abhyankar {
22075f2c45f1SShri Abhyankar   PetscErrorCode ierr;
22085f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
22095f2c45f1SShri Abhyankar 
22105f2c45f1SShri Abhyankar   PetscFunctionBegin;
22115f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
22125f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
22135f2c45f1SShri Abhyankar }
221422bbedd7SHong Zhang 
221522bbedd7SHong Zhang /*@
221664238763SRodolfo Oliveira   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index
221722bbedd7SHong Zhang 
221822bbedd7SHong Zhang   Not collective
221922bbedd7SHong Zhang 
22207a7aea1fSJed Brown   Input Parameters:
222122bbedd7SHong Zhang + dm - the dm object
222222bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
222322bbedd7SHong Zhang 
22247a7aea1fSJed Brown   Output Parameters:
2225f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
222622bbedd7SHong Zhang 
222797bb938eSShri Abhyankar   Level: advanced
222822bbedd7SHong Zhang 
222922bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
223022bbedd7SHong Zhang @*/
223122bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
223222bbedd7SHong Zhang {
223322bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
223422bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
223522bbedd7SHong Zhang 
223622bbedd7SHong Zhang   PetscFunctionBegin;
223722bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
223822bbedd7SHong Zhang   *vg = vltog[vloc];
223922bbedd7SHong Zhang   PetscFunctionReturn(0);
224022bbedd7SHong Zhang }
224122bbedd7SHong Zhang 
224222bbedd7SHong Zhang /*@
224364238763SRodolfo Oliveira   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map
224422bbedd7SHong Zhang 
224522bbedd7SHong Zhang   Collective
224622bbedd7SHong Zhang 
224722bbedd7SHong Zhang   Input Parameters:
2248f0fc11ceSJed Brown . dm - the dm object
224922bbedd7SHong Zhang 
225097bb938eSShri Abhyankar   Level: advanced
225122bbedd7SHong Zhang 
225263029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
225322bbedd7SHong Zhang @*/
225422bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
225522bbedd7SHong Zhang {
225622bbedd7SHong Zhang   PetscErrorCode    ierr;
225722bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
225822bbedd7SHong Zhang   MPI_Comm          comm;
225963029d29SHong Zhang   PetscMPIInt       rank,size,*displs,*recvcounts,remoterank;
226022bbedd7SHong Zhang   PetscBool         ghost;
226163029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
226222bbedd7SHong Zhang   const PetscSFNode *iremote;
226322bbedd7SHong Zhang   PetscSF           vsf;
226463029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
226563029d29SHong Zhang   VecScatter        ctx;
226663029d29SHong Zhang   PetscScalar       *varr,val;
226763029d29SHong Zhang   const PetscScalar *varr_read;
226822bbedd7SHong Zhang 
226922bbedd7SHong Zhang   PetscFunctionBegin;
227022bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
227122bbedd7SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
227263029d29SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
227322bbedd7SHong Zhang 
227422bbedd7SHong Zhang   if (size == 1) {
227522bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
227622bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
227722bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
227822bbedd7SHong Zhang     network->vltog = vltog;
227922bbedd7SHong Zhang     PetscFunctionReturn(0);
228022bbedd7SHong Zhang   }
228122bbedd7SHong Zhang 
228222bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
228322bbedd7SHong Zhang   if (network->vltog) {
228422bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
228522bbedd7SHong Zhang   }
228622bbedd7SHong Zhang 
228722bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
228822bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
228922bbedd7SHong Zhang   vsf = network->vertex.sf;
229022bbedd7SHong Zhang 
229122bbedd7SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size+1,&displs,size,&recvcounts);CHKERRQ(ierr);
2292f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
229322bbedd7SHong Zhang 
229422bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
229522bbedd7SHong Zhang 
229622bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
229722bbedd7SHong Zhang   vrange[0] = 0;
229822bbedd7SHong Zhang   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRQ(ierr);
229967dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
230022bbedd7SHong Zhang 
230122bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
230222bbedd7SHong Zhang   network->vltog = vltog;
230322bbedd7SHong Zhang 
230463029d29SHong Zhang   /* Set vltog for non-ghost vertices */
230563029d29SHong Zhang   k = 0;
230622bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
230722bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
230863029d29SHong Zhang     if (ghost) continue;
230963029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
231022bbedd7SHong Zhang   }
2311f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
231263029d29SHong Zhang 
231363029d29SHong Zhang   /* Set vltog for ghost vertices */
231463029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
231563029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
231663029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
231763029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
231863029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
231963029d29SHong Zhang   for (i=0; i<nleaves; i++) {
232063029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
232163029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
232263029d29SHong Zhang   }
232363029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
232463029d29SHong Zhang 
232563029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
232663029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
232763029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232863029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232963029d29SHong Zhang 
233063029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
233163029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
233263029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
233363029d29SHong Zhang   for (i=0; i<N; i+=2) {
23342e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
233563029d29SHong Zhang     if (remoterank == rank) {
233663029d29SHong Zhang       k = i+1; /* row number */
23372e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
233863029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
233963029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
234063029d29SHong Zhang     }
234163029d29SHong Zhang   }
234263029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
234363029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
234463029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
234563029d29SHong Zhang 
234663029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
234763029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
234863029d29SHong Zhang   k = 0;
234963029d29SHong Zhang   for (i=0; i<nroots; i++) {
235063029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
235163029d29SHong Zhang     if (!ghost) continue;
23522e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
235363029d29SHong Zhang   }
235463029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
235563029d29SHong Zhang 
235663029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
235763029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
235863029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
235922bbedd7SHong Zhang   PetscFunctionReturn(0);
236022bbedd7SHong Zhang }
2361