xref: /petsc/src/dm/impls/network/network.c (revision 9ad3091ec00a22ef64b5e90f9c247318c1a47045)
1af0996ceSBarry Smith #include <petsc/private/dmnetworkimpl.h>  /*I  "petscdmnetwork.h"  I*/
25f2c45f1SShri Abhyankar #include <petscdmplex.h>
35f2c45f1SShri Abhyankar #include <petscsf.h>
45f2c45f1SShri Abhyankar 
55f2c45f1SShri Abhyankar /*@
6556ed216SShri Abhyankar   DMNetworkGetPlex - Gets the Plex DM associated with this network DM
7556ed216SShri Abhyankar 
8556ed216SShri Abhyankar   Not collective
9556ed216SShri Abhyankar 
10556ed216SShri Abhyankar   Input Parameters:
11556ed216SShri Abhyankar + netdm - the dm object
12556ed216SShri Abhyankar - plexmdm - the plex dm object
13556ed216SShri Abhyankar 
14556ed216SShri Abhyankar   Level: Advanced
15556ed216SShri Abhyankar 
16556ed216SShri Abhyankar .seealso: DMNetworkCreate()
17556ed216SShri Abhyankar @*/
18556ed216SShri Abhyankar PetscErrorCode DMNetworkGetPlex(DM netdm, DM *plexdm)
19556ed216SShri Abhyankar {
20556ed216SShri Abhyankar   DM_Network *network = (DM_Network*) netdm->data;
21556ed216SShri Abhyankar 
22556ed216SShri Abhyankar   PetscFunctionBegin;
23556ed216SShri Abhyankar   *plexdm = network->plex;
24556ed216SShri Abhyankar   PetscFunctionReturn(0);
25556ed216SShri Abhyankar }
26556ed216SShri Abhyankar 
27556ed216SShri Abhyankar /*@
28e2aaf10cSShri Abhyankar   DMNetworkSetSizes - Sets the number of subnetworks, local and global vertices and edges for each subnetwork.
295f2c45f1SShri Abhyankar 
305f2c45f1SShri Abhyankar   Collective on DM
315f2c45f1SShri Abhyankar 
325f2c45f1SShri Abhyankar   Input Parameters:
335f2c45f1SShri Abhyankar + dm - the dm object
34e2aaf10cSShri Abhyankar . Nsubnet - number of subnetworks
35f025b11dSHong Zhang . NsubnetCouple - number of coupling subnetworks
36f025b11dSHong Zhang . nV - number of local vertices for each subnetwork and coupling subnetwork
37f025b11dSHong Zhang . nE - number of local edges for each subnetwork and coupling subnetwork
38f025b11dSHong Zhang . NV - number of global vertices (or PETSC_DETERMINE) for each subnetwork and coupling subnetwork
39f025b11dSHong Zhang - NE - number of global edges (or PETSC_DETERMINE) for each subnetwork and coupling subnetwork
405f2c45f1SShri Abhyankar 
415f2c45f1SShri Abhyankar    Notes
425f2c45f1SShri Abhyankar    If one processor calls this with NV (NE) of PETSC_DECIDE then all processors must, otherwise the prgram will hang.
435f2c45f1SShri Abhyankar 
44f025b11dSHong Zhang    You cannot change the sizes once they have been set. nV, nE, NV and NE are arrays of length Nsubnet+NsubnetCouple.
455f2c45f1SShri Abhyankar 
461b266c99SBarry Smith    Level: intermediate
471b266c99SBarry Smith 
481b266c99SBarry Smith .seealso: DMNetworkCreate()
495f2c45f1SShri Abhyankar @*/
50f025b11dSHong Zhang PetscErrorCode DMNetworkSetSizes(DM dm,PetscInt Nsubnet,PetscInt NsubnetCouple,PetscInt nV[], PetscInt nE[], PetscInt NV[], PetscInt NE[])
515f2c45f1SShri Abhyankar {
525f2c45f1SShri Abhyankar   PetscErrorCode ierr;
535f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*) dm->data;
54e2aaf10cSShri Abhyankar   PetscInt       a[2],b[2],i;
555f2c45f1SShri Abhyankar 
565f2c45f1SShri Abhyankar   PetscFunctionBegin;
575f2c45f1SShri Abhyankar   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
58e2aaf10cSShri Abhyankar   if (Nsubnet <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subnetworks %D cannot be less than 1",Nsubnet);
597765340cSHong Zhang   if (NsubnetCouple < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of coupling subnetworks %D cannot be less than 0",NsubnetCouple);
607765340cSHong Zhang 
617765340cSHong Zhang   if (Nsubnet > 0) PetscValidLogicalCollectiveInt(dm,Nsubnet,2);
627765340cSHong Zhang   if (network->nsubnet != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network");
637765340cSHong Zhang 
647765340cSHong Zhang   network->nsubnet  = Nsubnet + NsubnetCouple;
657765340cSHong Zhang   Nsubnet          += NsubnetCouple;
667765340cSHong Zhang   network->ncsubnet = NsubnetCouple;
677765340cSHong Zhang   ierr = PetscCalloc1(Nsubnet,&network->subnet);CHKERRQ(ierr);
687765340cSHong Zhang   for(i=0; i < Nsubnet; i++) {
69f025b11dSHong Zhang     if (NV) {
707765340cSHong Zhang       if (NV[i] > 0) PetscValidLogicalCollectiveInt(dm,NV[i],6);
717765340cSHong Zhang       if (NV[i] > 0 && nV[i] > NV[i]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Subnetwork %D: Local vertex size %D cannot be larger than global vertex size %D",i,nV[i],NV[i]);
72f025b11dSHong Zhang     }
73f025b11dSHong Zhang     if (NE) {
74f025b11dSHong Zhang       if (NE[i] > 0) PetscValidLogicalCollectiveInt(dm,NE[i],7);
757765340cSHong Zhang       if (NE[i] > 0 && nE[i] > NE[i]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Subnetwork %D: Local edge size %D cannot be larger than global edge size %D",i,nE[i],NE[i]);
76f025b11dSHong Zhang     }
77f025b11dSHong Zhang 
787765340cSHong Zhang     a[0] = nV[i]; a[1] = nE[i];
797765340cSHong Zhang     ierr = MPIU_Allreduce(a,b,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
807765340cSHong Zhang     network->subnet[i].Nvtx = b[0]; network->subnet[i].Nedge = b[1];
817765340cSHong Zhang 
827765340cSHong Zhang     network->subnet[i].id = i;
837765340cSHong Zhang 
847765340cSHong Zhang     network->subnet[i].nvtx = nV[i];
857765340cSHong Zhang     network->subnet[i].vStart = network->nVertices;
867765340cSHong Zhang     network->subnet[i].vEnd   = network->subnet[i].vStart + network->subnet[i].Nvtx;
877765340cSHong Zhang     network->nVertices += network->subnet[i].nvtx;
887765340cSHong Zhang     network->NVertices += network->subnet[i].Nvtx;
897765340cSHong Zhang 
907765340cSHong Zhang     network->subnet[i].nedge = nE[i];
917765340cSHong Zhang     network->subnet[i].eStart = network->nEdges;
927765340cSHong Zhang     network->subnet[i].eEnd = network->subnet[i].eStart + network->subnet[i].Nedge;
937765340cSHong Zhang     network->nEdges += network->subnet[i].nedge;
947765340cSHong Zhang     network->NEdges += network->subnet[i].Nedge;
957765340cSHong Zhang   }
967765340cSHong Zhang   PetscFunctionReturn(0);
977765340cSHong Zhang }
987765340cSHong Zhang 
995f2c45f1SShri Abhyankar /*@
1005f2c45f1SShri Abhyankar   DMNetworkSetEdgeList - Sets the list of local edges (vertex connectivity) for the network
1015f2c45f1SShri Abhyankar 
1025f2c45f1SShri Abhyankar   Logically collective on DM
1035f2c45f1SShri Abhyankar 
1045f2c45f1SShri Abhyankar   Input Parameters:
105e3e68989SHong Zhang + dm - the dm object
106e3e68989SHong Zhang . edgelist - list of edges for each subnetwork
107e3e68989SHong Zhang - edgelistCouple - list of edges for each coupling subnetwork
1085f2c45f1SShri Abhyankar 
1095f2c45f1SShri Abhyankar   Notes:
1105f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1115f2c45f1SShri Abhyankar   not be destroyed before the call to DMNetworkLayoutSetUp
1125f2c45f1SShri Abhyankar 
1135f2c45f1SShri Abhyankar   Level: intermediate
1145f2c45f1SShri Abhyankar 
115e3e68989SHong Zhang   Example usage:
116e3e68989SHong Zhang   Consider the following 2 separate networks and a coupling network:
117e3e68989SHong Zhang 
118e3e68989SHong Zhang .vb
119e3e68989SHong Zhang  network 0: v0 -> v1 -> v2 -> v3
120e3e68989SHong Zhang  network 1: v1 -> v2 -> v0
121e3e68989SHong Zhang  coupling network: network 1: v2 -> network 0: v0
122e3e68989SHong Zhang .ve
123e3e68989SHong Zhang 
124e3e68989SHong Zhang  The resulting input
125e3e68989SHong Zhang    edgelist[0] = [0 1 | 1 2 | 2 3];
126e3e68989SHong Zhang    edgelist[1] = [1 2 | 2 0]
127e3e68989SHong Zhang    edgelistCouple[0] = [(network)1 (v)2 (network)0 (v)0].
128e3e68989SHong Zhang 
1295f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkSetSizes
1305f2c45f1SShri Abhyankar @*/
131e3e68989SHong Zhang PetscErrorCode DMNetworkSetEdgeList(DM dm,int *edgelist[],int *edgelistCouple[])
1325f2c45f1SShri Abhyankar {
1335f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*) dm->data;
134e3e68989SHong Zhang   PetscInt   i,nsubnet,ncsubnet=network->ncsubnet;
1355f2c45f1SShri Abhyankar 
1365f2c45f1SShri Abhyankar   PetscFunctionBegin;
137e3e68989SHong Zhang   nsubnet = network->nsubnet - ncsubnet;
138e3e68989SHong Zhang   for(i=0; i < nsubnet; i++) {
139e2aaf10cSShri Abhyankar     network->subnet[i].edgelist = edgelist[i];
140e2aaf10cSShri Abhyankar   }
141e3e68989SHong Zhang   if (edgelistCouple) {
142e3e68989SHong Zhang     PetscInt j;
143e3e68989SHong Zhang     j = 0;
144e3e68989SHong Zhang     nsubnet = network->nsubnet;
145e3e68989SHong Zhang     while (i < nsubnet) network->subnet[i++].edgelist = edgelistCouple[j++];
146e3e68989SHong Zhang   }
1475f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
1485f2c45f1SShri Abhyankar }
1495f2c45f1SShri Abhyankar 
1505f2c45f1SShri Abhyankar /*@
1515f2c45f1SShri Abhyankar   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
1525f2c45f1SShri Abhyankar 
1535f2c45f1SShri Abhyankar   Collective on DM
1545f2c45f1SShri Abhyankar 
1555f2c45f1SShri Abhyankar   Input Parameters
1565f2c45f1SShri Abhyankar . DM - the dmnetwork object
1575f2c45f1SShri Abhyankar 
1585f2c45f1SShri Abhyankar   Notes:
1595f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
1605f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
1615f2c45f1SShri Abhyankar 
1625f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
1635f2c45f1SShri Abhyankar 
1645f2c45f1SShri Abhyankar   Level: intermediate
1655f2c45f1SShri Abhyankar 
1665f2c45f1SShri Abhyankar .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList
1675f2c45f1SShri Abhyankar @*/
1685f2c45f1SShri Abhyankar PetscErrorCode DMNetworkLayoutSetUp(DM dm)
1695f2c45f1SShri Abhyankar {
1705f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1715f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
1725f2c45f1SShri Abhyankar   PetscInt       dim = 1; /* One dimensional network */
173991cf414SHong Zhang   PetscInt       numCorners=2,spacedim=2;
1746500d4abSHong Zhang   double         *vertexcoords=NULL;
1757765340cSHong Zhang   PetscInt       i,j,ndata,ctr=0,nsubnet;
176*9ad3091eSHong Zhang   PetscInt       k,netid,vid;
177*9ad3091eSHong Zhang   int            *edgelist_couple=NULL;
1786500d4abSHong Zhang 
1796500d4abSHong Zhang   PetscFunctionBegin;
1806500d4abSHong Zhang   if (network->nVertices) {
1816500d4abSHong Zhang     ierr = PetscCalloc1(numCorners*network->nVertices,&vertexcoords);CHKERRQ(ierr);
1826500d4abSHong Zhang   }
1836500d4abSHong Zhang 
1846500d4abSHong Zhang   /* Create the edgelist for the network by concatenating edgelists of the subnetworks */
1857765340cSHong Zhang   nsubnet = network->nsubnet - network->ncsubnet;
1866500d4abSHong Zhang   ierr = PetscCalloc1(2*network->nEdges,&network->edges);CHKERRQ(ierr);
1877765340cSHong Zhang   for (i=0; i < nsubnet; i++) {
1886500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
1896500d4abSHong Zhang       network->edges[2*ctr] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j];
1906500d4abSHong Zhang       network->edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1];
1916500d4abSHong Zhang       ctr++;
1926500d4abSHong Zhang     }
1936500d4abSHong Zhang   }
1947765340cSHong Zhang 
1957765340cSHong Zhang   i       = nsubnet; /* netid of coupling subnet */
1967765340cSHong Zhang   nsubnet = network->nsubnet;
1977765340cSHong Zhang   while (i < nsubnet) {
198991cf414SHong Zhang     edgelist_couple = network->subnet[i].edgelist;
1996500d4abSHong Zhang     k = 0;
2006500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
2016500d4abSHong Zhang       netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
2026500d4abSHong Zhang       network->edges[2*ctr] = network->subnet[netid].vStart + vid; k += 2;
2036500d4abSHong Zhang 
2046500d4abSHong Zhang       netid = edgelist_couple[k]; vid = edgelist_couple[k+1];
205991cf414SHong Zhang       network->edges[2*ctr+1] = network->subnet[netid].vStart + vid; k+=2;
2066500d4abSHong Zhang       ctr++;
2076500d4abSHong Zhang     }
2087765340cSHong Zhang     i++;
2097765340cSHong Zhang   }
2106500d4abSHong Zhang 
21134bd1bf5SHong Zhang #if 0
2126500d4abSHong Zhang   for(i=0; i < network->nEdges; i++) {
2136500d4abSHong Zhang     ierr = PetscPrintf(PETSC_COMM_SELF,"[%D %D]",network->edges[2*i],network->edges[2*i+1]);CHKERRQ(ierr);
2146500d4abSHong Zhang     printf("\n");
2156500d4abSHong Zhang   }
2166500d4abSHong Zhang #endif
2176500d4abSHong Zhang 
2186500d4abSHong Zhang   ierr = DMPlexCreateFromCellList(PetscObjectComm((PetscObject)dm),dim,network->nEdges,network->nVertices,numCorners,PETSC_FALSE,network->edges,spacedim,vertexcoords,&network->plex);CHKERRQ(ierr);
2196500d4abSHong Zhang   if (network->nVertices) {
2206500d4abSHong Zhang     ierr = PetscFree(vertexcoords);CHKERRQ(ierr);
2216500d4abSHong Zhang   }
2226500d4abSHong Zhang   ierr = PetscFree(network->edges);CHKERRQ(ierr);
2236500d4abSHong Zhang 
2246500d4abSHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
2256500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
2266500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
2276500d4abSHong Zhang 
2286500d4abSHong Zhang   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DataSection);CHKERRQ(ierr);
2296500d4abSHong Zhang   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DofSection);CHKERRQ(ierr);
2306500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
2316500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
2326500d4abSHong Zhang 
2336500d4abSHong Zhang   /* Create vertices and edges array for the subnetworks */
2346500d4abSHong Zhang   for (j=0; j < network->nsubnet; j++) {
2356500d4abSHong Zhang     ierr = PetscCalloc1(network->subnet[j].nedge,&network->subnet[j].edges);CHKERRQ(ierr);
2366500d4abSHong Zhang     ierr = PetscCalloc1(network->subnet[j].nvtx,&network->subnet[j].vertices);CHKERRQ(ierr);
2376500d4abSHong Zhang     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
2386500d4abSHong Zhang        These get updated when the vertices and edges are added. */
2396500d4abSHong Zhang     network->subnet[j].nvtx = network->subnet[j].nedge = 0;
2406500d4abSHong Zhang   }
2416500d4abSHong Zhang 
2426500d4abSHong Zhang   network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
2436500d4abSHong Zhang   ierr = PetscCalloc1(network->pEnd-network->pStart,&network->header);CHKERRQ(ierr);
2446500d4abSHong Zhang   for (i=network->eStart; i < network->eEnd; i++) {
2456500d4abSHong Zhang     network->header[i].index = i;   /* Global edge number */
2466500d4abSHong Zhang     for (j=0; j < network->nsubnet; j++) {
2476500d4abSHong Zhang       if((network->subnet[j].eStart <= i) && (i < network->subnet[j].eEnd)) {
2486500d4abSHong Zhang 	network->header[i].subnetid = j; /* Subnetwork id */
2496500d4abSHong Zhang 	network->subnet[j].edges[network->subnet[j].nedge++] = i;
2506500d4abSHong Zhang 	break;
2516500d4abSHong Zhang       }
2526500d4abSHong Zhang     }
2536500d4abSHong Zhang     network->header[i].ndata = 0;
2546500d4abSHong Zhang     ndata = network->header[i].ndata;
2556500d4abSHong Zhang     ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
2566500d4abSHong Zhang     network->header[i].offset[ndata] = 0;
2576500d4abSHong Zhang   }
2586500d4abSHong Zhang 
2596500d4abSHong Zhang   for(i=network->vStart; i < network->vEnd; i++) {
2606500d4abSHong Zhang     network->header[i].index = i - network->vStart;
2616500d4abSHong Zhang     for (j=0; j < network->nsubnet; j++) {
2626500d4abSHong Zhang       if ((network->subnet[j].vStart <= i-network->vStart) && (i-network->vStart < network->subnet[j].vEnd)) {
2636500d4abSHong Zhang 	network->header[i].subnetid = j;
2646500d4abSHong Zhang 	network->subnet[j].vertices[network->subnet[j].nvtx++] = i;
2656500d4abSHong Zhang 	break;
2666500d4abSHong Zhang       }
2676500d4abSHong Zhang     }
2686500d4abSHong Zhang     network->header[i].ndata = 0;
2696500d4abSHong Zhang     ndata = network->header[i].ndata;
2706500d4abSHong Zhang     ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr);
2716500d4abSHong Zhang     network->header[i].offset[ndata] = 0;
2726500d4abSHong Zhang   }
2736500d4abSHong Zhang 
2746500d4abSHong Zhang   ierr = PetscMalloc1(network->pEnd-network->pStart,&network->cvalue);CHKERRQ(ierr);
2755f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
2765f2c45f1SShri Abhyankar }
2775f2c45f1SShri Abhyankar 
27894ef8ddeSSatish Balay /*@C
2792727e31bSShri Abhyankar   DMNetworkGetSubnetworkInfo - Returns the info for the subnetwork
2802727e31bSShri Abhyankar 
2812727e31bSShri Abhyankar   Input Parameters
2822727e31bSShri Abhyankar + dm   - the number object
2832727e31bSShri Abhyankar - id   - the ID (integer) of the subnetwork
2842727e31bSShri Abhyankar 
2852727e31bSShri Abhyankar   Output Parameters
2862727e31bSShri Abhyankar + nv    - number of vertices (local)
2872727e31bSShri Abhyankar . ne    - number of edges (local)
2882727e31bSShri Abhyankar . vtx   - local vertices for this subnetwork
2892727e31bSShri Abhyankar . edge  - local edges for this subnetwork
2902727e31bSShri Abhyankar 
2912727e31bSShri Abhyankar   Notes:
2922727e31bSShri Abhyankar   Cannot call this routine before DMNetworkLayoutSetup()
2932727e31bSShri Abhyankar 
2942727e31bSShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
2952727e31bSShri Abhyankar @*/
2962727e31bSShri Abhyankar PetscErrorCode DMNetworkGetSubnetworkInfo(DM netdm,PetscInt id,PetscInt *nv, PetscInt *ne,const PetscInt **vtx, const PetscInt **edge)
2972727e31bSShri Abhyankar {
2982727e31bSShri Abhyankar   DM_Network     *network = (DM_Network*) netdm->data;
2992727e31bSShri Abhyankar 
3002727e31bSShri Abhyankar   PetscFunctionBegin;
3012727e31bSShri Abhyankar   *nv = network->subnet[id].nvtx;
3022727e31bSShri Abhyankar   *ne = network->subnet[id].nedge;
3032727e31bSShri Abhyankar   *vtx = network->subnet[id].vertices;
3042727e31bSShri Abhyankar   *edge = network->subnet[id].edges;
3052727e31bSShri Abhyankar   PetscFunctionReturn(0);
3062727e31bSShri Abhyankar }
3072727e31bSShri Abhyankar 
3082727e31bSShri Abhyankar /*@C
3095f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
3105f2c45f1SShri Abhyankar 
3115f2c45f1SShri Abhyankar   Logically collective on DM
3125f2c45f1SShri Abhyankar 
3135f2c45f1SShri Abhyankar   Input Parameters
3145f2c45f1SShri Abhyankar + dm   - the network object
3155f2c45f1SShri Abhyankar . name - the component name
3165f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
3175f2c45f1SShri Abhyankar 
3185f2c45f1SShri Abhyankar    Output Parameters
3195f2c45f1SShri Abhyankar .   key - an integer key that defines the component
3205f2c45f1SShri Abhyankar 
3215f2c45f1SShri Abhyankar    Notes
3225f2c45f1SShri Abhyankar    This routine should be called by all processors before calling DMNetworkLayoutSetup().
3235f2c45f1SShri Abhyankar 
3245f2c45f1SShri Abhyankar    Level: intermediate
3255f2c45f1SShri Abhyankar 
3265f2c45f1SShri Abhyankar .seealso: DMNetworkLayoutSetUp, DMNetworkCreate
3275f2c45f1SShri Abhyankar @*/
3285f2c45f1SShri Abhyankar PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,PetscInt size,PetscInt *key)
3295f2c45f1SShri Abhyankar {
3305f2c45f1SShri Abhyankar   PetscErrorCode        ierr;
3315f2c45f1SShri Abhyankar   DM_Network            *network = (DM_Network*) dm->data;
3325f2c45f1SShri Abhyankar   DMNetworkComponent    *component=&network->component[network->ncomponent];
3335f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
3345f2c45f1SShri Abhyankar   PetscInt              i;
3355f2c45f1SShri Abhyankar 
3365f2c45f1SShri Abhyankar   PetscFunctionBegin;
3375f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
3385f2c45f1SShri Abhyankar     ierr = PetscStrcmp(component->name,name,&flg);CHKERRQ(ierr);
3395f2c45f1SShri Abhyankar     if (flg) {
3405f2c45f1SShri Abhyankar       *key = i;
3415f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
3425f2c45f1SShri Abhyankar     }
3436d64e262SShri Abhyankar   }
3446d64e262SShri Abhyankar   if(network->ncomponent == MAX_COMPONENTS) {
3456d64e262SShri Abhyankar     SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Number of components registered exceeds the max %D",MAX_COMPONENTS);
3465f2c45f1SShri Abhyankar   }
3475f2c45f1SShri Abhyankar 
3485f2c45f1SShri Abhyankar   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
3495f2c45f1SShri Abhyankar   component->size = size/sizeof(DMNetworkComponentGenericDataType);
3505f2c45f1SShri Abhyankar   *key = network->ncomponent;
3515f2c45f1SShri Abhyankar   network->ncomponent++;
3525f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
3535f2c45f1SShri Abhyankar }
3545f2c45f1SShri Abhyankar 
3555f2c45f1SShri Abhyankar /*@
3565f2c45f1SShri Abhyankar   DMNetworkGetVertexRange - Get the bounds [start, end) for the vertices.
3575f2c45f1SShri Abhyankar 
3585f2c45f1SShri Abhyankar   Not Collective
3595f2c45f1SShri Abhyankar 
3605f2c45f1SShri Abhyankar   Input Parameters:
3615f2c45f1SShri Abhyankar + dm - The DMNetwork object
3625f2c45f1SShri Abhyankar 
3635f2c45f1SShri Abhyankar   Output Paramters:
3645f2c45f1SShri Abhyankar + vStart - The first vertex point
3655f2c45f1SShri Abhyankar - vEnd   - One beyond the last vertex point
3665f2c45f1SShri Abhyankar 
3675f2c45f1SShri Abhyankar   Level: intermediate
3685f2c45f1SShri Abhyankar 
3695f2c45f1SShri Abhyankar .seealso: DMNetworkGetEdgeRange
3705f2c45f1SShri Abhyankar @*/
3715f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
3725f2c45f1SShri Abhyankar {
3735f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
3745f2c45f1SShri Abhyankar 
3755f2c45f1SShri Abhyankar   PetscFunctionBegin;
3765f2c45f1SShri Abhyankar   if (vStart) *vStart = network->vStart;
3775f2c45f1SShri Abhyankar   if (vEnd) *vEnd = network->vEnd;
3785f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
3795f2c45f1SShri Abhyankar }
3805f2c45f1SShri Abhyankar 
3815f2c45f1SShri Abhyankar /*@
3825f2c45f1SShri Abhyankar   DMNetworkGetEdgeRange - Get the bounds [start, end) for the edges.
3835f2c45f1SShri Abhyankar 
3845f2c45f1SShri Abhyankar   Not Collective
3855f2c45f1SShri Abhyankar 
3865f2c45f1SShri Abhyankar   Input Parameters:
3875f2c45f1SShri Abhyankar + dm - The DMNetwork object
3885f2c45f1SShri Abhyankar 
3895f2c45f1SShri Abhyankar   Output Paramters:
3905f2c45f1SShri Abhyankar + eStart - The first edge point
3915f2c45f1SShri Abhyankar - eEnd   - One beyond the last edge point
3925f2c45f1SShri Abhyankar 
3935f2c45f1SShri Abhyankar   Level: intermediate
3945f2c45f1SShri Abhyankar 
3955f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange
3965f2c45f1SShri Abhyankar @*/
3975f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
3985f2c45f1SShri Abhyankar {
3995f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
4005f2c45f1SShri Abhyankar 
4015f2c45f1SShri Abhyankar   PetscFunctionBegin;
4025f2c45f1SShri Abhyankar   if (eStart) *eStart = network->eStart;
4035f2c45f1SShri Abhyankar   if (eEnd) *eEnd = network->eEnd;
4045f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
4055f2c45f1SShri Abhyankar }
4065f2c45f1SShri Abhyankar 
4077b6afd5bSHong Zhang /*@
408e85e6aecSHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the user global numbering for the edge.
4097b6afd5bSHong Zhang 
4107b6afd5bSHong Zhang   Not Collective
4117b6afd5bSHong Zhang 
4127b6afd5bSHong Zhang   Input Parameters:
4137b6afd5bSHong Zhang + dm - DMNetwork object
414e85e6aecSHong Zhang - p  - edge point
4157b6afd5bSHong Zhang 
4167b6afd5bSHong Zhang   Output Paramters:
417e85e6aecSHong Zhang . index - user global numbering for the edge
4187b6afd5bSHong Zhang 
4197b6afd5bSHong Zhang   Level: intermediate
4207b6afd5bSHong Zhang 
421e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalVertexIndex
4227b6afd5bSHong Zhang @*/
423e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
4247b6afd5bSHong Zhang {
4257b6afd5bSHong Zhang   PetscErrorCode    ierr;
4267b6afd5bSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
4277b6afd5bSHong Zhang   PetscInt          offsetp;
4287b6afd5bSHong Zhang   DMNetworkComponentHeader header;
4297b6afd5bSHong Zhang 
4307b6afd5bSHong Zhang   PetscFunctionBegin;
4317b6afd5bSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
4327b6afd5bSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
433e85e6aecSHong Zhang   *index = header->index;
4347b6afd5bSHong Zhang   PetscFunctionReturn(0);
4357b6afd5bSHong Zhang }
4367b6afd5bSHong Zhang 
4375f2c45f1SShri Abhyankar /*@
438e85e6aecSHong Zhang   DMNetworkGetGlobalVertexIndex - Get the user global numbering for the vertex.
439e85e6aecSHong Zhang 
440e85e6aecSHong Zhang   Not Collective
441e85e6aecSHong Zhang 
442e85e6aecSHong Zhang   Input Parameters:
443e85e6aecSHong Zhang + dm - DMNetwork object
444e85e6aecSHong Zhang - p  - vertex point
445e85e6aecSHong Zhang 
446e85e6aecSHong Zhang   Output Paramters:
447e85e6aecSHong Zhang . index - user global numbering for the vertex
448e85e6aecSHong Zhang 
449e85e6aecSHong Zhang   Level: intermediate
450e85e6aecSHong Zhang 
451e85e6aecSHong Zhang .seealso: DMNetworkGetGlobalEdgeIndex
452e85e6aecSHong Zhang @*/
453e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
454e85e6aecSHong Zhang {
455e85e6aecSHong Zhang   PetscErrorCode    ierr;
456e85e6aecSHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
457e85e6aecSHong Zhang   PetscInt          offsetp;
458e85e6aecSHong Zhang   DMNetworkComponentHeader header;
459e85e6aecSHong Zhang 
460e85e6aecSHong Zhang   PetscFunctionBegin;
461e85e6aecSHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
462e85e6aecSHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
463e85e6aecSHong Zhang   *index = header->index;
464e85e6aecSHong Zhang   PetscFunctionReturn(0);
465e85e6aecSHong Zhang }
466e85e6aecSHong Zhang 
467c3b11c7cSShri Abhyankar /*
468c3b11c7cSShri Abhyankar   DMNetworkGetComponentKeyOffset - Gets the type along with the offset for indexing the
469c3b11c7cSShri Abhyankar                                     component value from the component data array
470c3b11c7cSShri Abhyankar 
471c3b11c7cSShri Abhyankar   Not Collective
472c3b11c7cSShri Abhyankar 
473c3b11c7cSShri Abhyankar   Input Parameters:
474c3b11c7cSShri Abhyankar + dm      - The DMNetwork object
475c3b11c7cSShri Abhyankar . p       - vertex/edge point
476c3b11c7cSShri Abhyankar - compnum - component number
477c3b11c7cSShri Abhyankar 
478c3b11c7cSShri Abhyankar   Output Parameters:
479c3b11c7cSShri Abhyankar + compkey - the key obtained when registering the component
480c3b11c7cSShri Abhyankar - offset  - offset into the component data array associated with the vertex/edge point
481c3b11c7cSShri Abhyankar 
482c3b11c7cSShri Abhyankar   Notes:
483c3b11c7cSShri Abhyankar   Typical usage:
484c3b11c7cSShri Abhyankar 
485c3b11c7cSShri Abhyankar   DMNetworkGetComponentDataArray(dm, &arr);
486c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
487c3b11c7cSShri Abhyankar   Loop over vertices or edges
488c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
489c3b11c7cSShri Abhyankar     Loop over numcomps
490c3b11c7cSShri Abhyankar       DMNetworkGetComponentKeyOffset(dm,v,compnum,&key,&offset);
491c3b11c7cSShri Abhyankar       compdata = (UserCompDataType)(arr+offset);
492c3b11c7cSShri Abhyankar 
493c3b11c7cSShri Abhyankar   Level: intermediate
494c3b11c7cSShri Abhyankar 
495c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetComponentDataArray,
496c3b11c7cSShri Abhyankar */
497c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponentKeyOffset(DM dm,PetscInt p, PetscInt compnum, PetscInt *compkey, PetscInt *offset)
498c3b11c7cSShri Abhyankar {
499c3b11c7cSShri Abhyankar   PetscErrorCode           ierr;
500c3b11c7cSShri Abhyankar   PetscInt                 offsetp;
501c3b11c7cSShri Abhyankar   DMNetworkComponentHeader header;
502c3b11c7cSShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
503c3b11c7cSShri Abhyankar 
504c3b11c7cSShri Abhyankar   PetscFunctionBegin;
505c3b11c7cSShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
506c3b11c7cSShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
507c3b11c7cSShri Abhyankar   if (compkey) *compkey = header->key[compnum];
508c3b11c7cSShri Abhyankar   if (offset) *offset  = offsetp+network->dataheadersize+header->offset[compnum];
509c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
510c3b11c7cSShri Abhyankar }
511c3b11c7cSShri Abhyankar 
512c3b11c7cSShri Abhyankar /*@
513c3b11c7cSShri Abhyankar   DMNetworkGetComponent - Returns the network component and its key
514c3b11c7cSShri Abhyankar 
515c3b11c7cSShri Abhyankar   Not Collective
516c3b11c7cSShri Abhyankar 
517c3b11c7cSShri Abhyankar   Input Parameters
518c3b11c7cSShri Abhyankar + dm - DMNetwork object
519c3b11c7cSShri Abhyankar . p  - edge or vertex point
520c3b11c7cSShri Abhyankar - compnum - component number
521c3b11c7cSShri Abhyankar 
522c3b11c7cSShri Abhyankar   Output Parameters:
523c3b11c7cSShri Abhyankar + compkey - the key set for this computing during registration
524c3b11c7cSShri Abhyankar - component - the component data
525c3b11c7cSShri Abhyankar 
526c3b11c7cSShri Abhyankar   Notes:
527c3b11c7cSShri Abhyankar   Typical usage:
528c3b11c7cSShri Abhyankar 
529c3b11c7cSShri Abhyankar   DMNetworkGetVertex/EdgeRange(dm,&Start,&End);
530c3b11c7cSShri Abhyankar   Loop over vertices or edges
531c3b11c7cSShri Abhyankar     DMNetworkGetNumComponents(dm,v,&numcomps);
532c3b11c7cSShri Abhyankar     Loop over numcomps
533c3b11c7cSShri Abhyankar       DMNetworkGetComponent(dm,v,compnum,&key,&component);
534c3b11c7cSShri Abhyankar 
535c3b11c7cSShri Abhyankar   Level: intermediate
536c3b11c7cSShri Abhyankar 
537c3b11c7cSShri Abhyankar .seealso: DMNetworkGetNumComponents, DMNetworkGetVariableOffset
538c3b11c7cSShri Abhyankar @*/
539c3b11c7cSShri Abhyankar PetscErrorCode DMNetworkGetComponent(DM dm, PetscInt p, PetscInt compnum, PetscInt *key, void **component)
540c3b11c7cSShri Abhyankar {
541c3b11c7cSShri Abhyankar   PetscErrorCode ierr;
542c3b11c7cSShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
543c3b11c7cSShri Abhyankar   PetscInt       offsetd;
544c3b11c7cSShri Abhyankar 
545c3b11c7cSShri Abhyankar   PetscFunctionBegin;
546c3b11c7cSShri Abhyankar 
547c3b11c7cSShri Abhyankar   ierr = DMNetworkGetComponentKeyOffset(dm,p,compnum,key,&offsetd);CHKERRQ(ierr);
548c3b11c7cSShri Abhyankar   *component = network->componentdataarray+offsetd;
549c3b11c7cSShri Abhyankar 
550c3b11c7cSShri Abhyankar   PetscFunctionReturn(0);
551c3b11c7cSShri Abhyankar }
552c3b11c7cSShri Abhyankar 
553e85e6aecSHong Zhang /*@
554325661f6SSatish Balay   DMNetworkAddComponent - Adds a network component at the given point (vertex/edge)
5555f2c45f1SShri Abhyankar 
5565f2c45f1SShri Abhyankar   Not Collective
5575f2c45f1SShri Abhyankar 
5585f2c45f1SShri Abhyankar   Input Parameters:
5595f2c45f1SShri Abhyankar + dm           - The DMNetwork object
5605f2c45f1SShri Abhyankar . p            - vertex/edge point
5615f2c45f1SShri Abhyankar . componentkey - component key returned while registering the component
5625f2c45f1SShri Abhyankar - compvalue    - pointer to the data structure for the component
5635f2c45f1SShri Abhyankar 
5645f2c45f1SShri Abhyankar   Level: intermediate
5655f2c45f1SShri Abhyankar 
5665f2c45f1SShri Abhyankar .seealso: DMNetworkGetVertexRange, DMNetworkGetEdgeRange, DMNetworkRegisterComponent
5675f2c45f1SShri Abhyankar @*/
5685f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p,PetscInt componentkey,void* compvalue)
5695f2c45f1SShri Abhyankar {
5705f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
57143a39a44SBarry Smith   DMNetworkComponent       *component = &network->component[componentkey];
5725f2c45f1SShri Abhyankar   DMNetworkComponentHeader header = &network->header[p];
5735f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue = &network->cvalue[p];
5745f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
5755f2c45f1SShri Abhyankar 
5765f2c45f1SShri Abhyankar   PetscFunctionBegin;
577fa58f0a9SHong 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);
578fa58f0a9SHong Zhang 
57943a39a44SBarry Smith   header->size[header->ndata] = component->size;
58043a39a44SBarry Smith   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
5815f2c45f1SShri Abhyankar   header->key[header->ndata] = componentkey;
5825f2c45f1SShri Abhyankar   if (header->ndata != 0) header->offset[header->ndata] = header->offset[header->ndata-1] + header->size[header->ndata-1];
5835f2c45f1SShri Abhyankar 
5845f2c45f1SShri Abhyankar   cvalue->data[header->ndata] = (void*)compvalue;
5855f2c45f1SShri Abhyankar   header->ndata++;
5865f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
5875f2c45f1SShri Abhyankar }
5885f2c45f1SShri Abhyankar 
5895f2c45f1SShri Abhyankar /*@
5905f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
5915f2c45f1SShri Abhyankar 
5925f2c45f1SShri Abhyankar   Not Collective
5935f2c45f1SShri Abhyankar 
5945f2c45f1SShri Abhyankar   Input Parameters:
5955f2c45f1SShri Abhyankar + dm - The DMNetwork object
5965f2c45f1SShri Abhyankar . p  - vertex/edge point
5975f2c45f1SShri Abhyankar 
5985f2c45f1SShri Abhyankar   Output Parameters:
5995f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
6005f2c45f1SShri Abhyankar 
6015f2c45f1SShri Abhyankar   Level: intermediate
6025f2c45f1SShri Abhyankar 
6035f2c45f1SShri Abhyankar .seealso: DMNetworkRegisterComponent, DMNetworkAddComponent
6045f2c45f1SShri Abhyankar @*/
6055f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
6065f2c45f1SShri Abhyankar {
6075f2c45f1SShri Abhyankar   PetscErrorCode ierr;
6085f2c45f1SShri Abhyankar   PetscInt       offset;
6095f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
6105f2c45f1SShri Abhyankar 
6115f2c45f1SShri Abhyankar   PetscFunctionBegin;
6125f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
6135f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
6145f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
6155f2c45f1SShri Abhyankar }
6165f2c45f1SShri Abhyankar 
6175f2c45f1SShri Abhyankar /*@
6185f2c45f1SShri Abhyankar   DMNetworkGetVariableOffset - Get the offset for accessing the variable associated with the given vertex/edge from the local vector.
6195f2c45f1SShri Abhyankar 
6205f2c45f1SShri Abhyankar   Not Collective
6215f2c45f1SShri Abhyankar 
6225f2c45f1SShri Abhyankar   Input Parameters:
6235f2c45f1SShri Abhyankar + dm     - The DMNetwork object
6245f2c45f1SShri Abhyankar - p      - the edge/vertex point
6255f2c45f1SShri Abhyankar 
6265f2c45f1SShri Abhyankar   Output Parameters:
6275f2c45f1SShri Abhyankar . offset - the offset
6285f2c45f1SShri Abhyankar 
6295f2c45f1SShri Abhyankar   Level: intermediate
6305f2c45f1SShri Abhyankar 
6315f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
6325f2c45f1SShri Abhyankar @*/
6335f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableOffset(DM dm,PetscInt p,PetscInt *offset)
6345f2c45f1SShri Abhyankar {
6355f2c45f1SShri Abhyankar   PetscErrorCode ierr;
6365f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
6375f2c45f1SShri Abhyankar 
6385f2c45f1SShri Abhyankar   PetscFunctionBegin;
6395f78ed8bSShri Abhyankar   ierr = PetscSectionGetOffset(network->plex->defaultSection,p,offset);CHKERRQ(ierr);
6405f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
6415f2c45f1SShri Abhyankar }
6425f2c45f1SShri Abhyankar 
6435f2c45f1SShri Abhyankar /*@
6445f2c45f1SShri Abhyankar   DMNetworkGetVariableGlobalOffset - Get the global offset for the variable associated with the given vertex/edge from the global vector.
6455f2c45f1SShri Abhyankar 
6465f2c45f1SShri Abhyankar   Not Collective
6475f2c45f1SShri Abhyankar 
6485f2c45f1SShri Abhyankar   Input Parameters:
6495f2c45f1SShri Abhyankar + dm      - The DMNetwork object
6505f2c45f1SShri Abhyankar - p       - the edge/vertex point
6515f2c45f1SShri Abhyankar 
6525f2c45f1SShri Abhyankar   Output Parameters:
6535f2c45f1SShri Abhyankar . offsetg - the offset
6545f2c45f1SShri Abhyankar 
6555f2c45f1SShri Abhyankar   Level: intermediate
6565f2c45f1SShri Abhyankar 
6575f2c45f1SShri Abhyankar .seealso: DMNetworkGetVariableOffset, DMGetLocalVector
6585f2c45f1SShri Abhyankar @*/
6595f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVariableGlobalOffset(DM dm,PetscInt p,PetscInt *offsetg)
6605f2c45f1SShri Abhyankar {
6615f2c45f1SShri Abhyankar   PetscErrorCode ierr;
6625f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
6635f2c45f1SShri Abhyankar 
6645f2c45f1SShri Abhyankar   PetscFunctionBegin;
6655f78ed8bSShri Abhyankar   ierr = PetscSectionGetOffset(network->plex->defaultGlobalSection,p,offsetg);CHKERRQ(ierr);
6666fefedf4SHong Zhang   if (*offsetg < 0) *offsetg = -(*offsetg + 1); /* Convert to actual global offset for ghost vertex */
6675f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
6685f2c45f1SShri Abhyankar }
6695f2c45f1SShri Abhyankar 
67024121865SAdrian Maldonado /*@
67124121865SAdrian Maldonado   DMNetworkGetEdgeOffset - Get the offset for accessing the variable associated with the given edge from the local subvector.
67224121865SAdrian Maldonado 
67324121865SAdrian Maldonado   Not Collective
67424121865SAdrian Maldonado 
67524121865SAdrian Maldonado   Input Parameters:
67624121865SAdrian Maldonado + dm     - The DMNetwork object
67724121865SAdrian Maldonado - p      - the edge point
67824121865SAdrian Maldonado 
67924121865SAdrian Maldonado   Output Parameters:
68024121865SAdrian Maldonado . offset - the offset
68124121865SAdrian Maldonado 
68224121865SAdrian Maldonado   Level: intermediate
68324121865SAdrian Maldonado 
68424121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
68524121865SAdrian Maldonado @*/
68624121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
68724121865SAdrian Maldonado {
68824121865SAdrian Maldonado   PetscErrorCode ierr;
68924121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
69024121865SAdrian Maldonado 
69124121865SAdrian Maldonado   PetscFunctionBegin;
69224121865SAdrian Maldonado 
69324121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
69424121865SAdrian Maldonado   PetscFunctionReturn(0);
69524121865SAdrian Maldonado }
69624121865SAdrian Maldonado 
69724121865SAdrian Maldonado /*@
69824121865SAdrian Maldonado   DMNetworkGetVertexOffset - Get the offset for accessing the variable associated with the given vertex from the local subvector.
69924121865SAdrian Maldonado 
70024121865SAdrian Maldonado   Not Collective
70124121865SAdrian Maldonado 
70224121865SAdrian Maldonado   Input Parameters:
70324121865SAdrian Maldonado + dm     - The DMNetwork object
70424121865SAdrian Maldonado - p      - the vertex point
70524121865SAdrian Maldonado 
70624121865SAdrian Maldonado   Output Parameters:
70724121865SAdrian Maldonado . offset - the offset
70824121865SAdrian Maldonado 
70924121865SAdrian Maldonado   Level: intermediate
71024121865SAdrian Maldonado 
71124121865SAdrian Maldonado .seealso: DMNetworkGetVariableGlobalOffset, DMGetLocalVector
71224121865SAdrian Maldonado @*/
71324121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
71424121865SAdrian Maldonado {
71524121865SAdrian Maldonado   PetscErrorCode ierr;
71624121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
71724121865SAdrian Maldonado 
71824121865SAdrian Maldonado   PetscFunctionBegin;
71924121865SAdrian Maldonado 
72024121865SAdrian Maldonado   p -= network->vStart;
72124121865SAdrian Maldonado 
72224121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
72324121865SAdrian Maldonado   PetscFunctionReturn(0);
72424121865SAdrian Maldonado }
7255f2c45f1SShri Abhyankar /*@
7265f2c45f1SShri Abhyankar   DMNetworkAddNumVariables - Add number of variables associated with a given point.
7275f2c45f1SShri Abhyankar 
7285f2c45f1SShri Abhyankar   Not Collective
7295f2c45f1SShri Abhyankar 
7305f2c45f1SShri Abhyankar   Input Parameters:
7315f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
7325f2c45f1SShri Abhyankar . p    - the vertex/edge point
7335f2c45f1SShri Abhyankar - nvar - number of additional variables
7345f2c45f1SShri Abhyankar 
7355f2c45f1SShri Abhyankar   Level: intermediate
7365f2c45f1SShri Abhyankar 
7375f2c45f1SShri Abhyankar .seealso: DMNetworkSetNumVariables
7385f2c45f1SShri Abhyankar @*/
7395f2c45f1SShri Abhyankar PetscErrorCode DMNetworkAddNumVariables(DM dm,PetscInt p,PetscInt nvar)
7405f2c45f1SShri Abhyankar {
7415f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7425f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7435f2c45f1SShri Abhyankar 
7445f2c45f1SShri Abhyankar   PetscFunctionBegin;
7455f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
7465f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7475f2c45f1SShri Abhyankar }
7485f2c45f1SShri Abhyankar 
74927f51fceSHong Zhang /*@
75027f51fceSHong Zhang   DMNetworkGetNumVariables - Gets number of variables for a vertex/edge point.
75127f51fceSHong Zhang 
75227f51fceSHong Zhang   Not Collective
75327f51fceSHong Zhang 
75427f51fceSHong Zhang   Input Parameters:
75527f51fceSHong Zhang + dm   - The DMNetworkObject
75627f51fceSHong Zhang - p    - the vertex/edge point
75727f51fceSHong Zhang 
75827f51fceSHong Zhang   Output Parameters:
75927f51fceSHong Zhang . nvar - number of variables
76027f51fceSHong Zhang 
76127f51fceSHong Zhang   Level: intermediate
76227f51fceSHong Zhang 
76327f51fceSHong Zhang .seealso: DMNetworkAddNumVariables, DMNetworkSddNumVariables
76427f51fceSHong Zhang @*/
76527f51fceSHong Zhang PetscErrorCode DMNetworkGetNumVariables(DM dm,PetscInt p,PetscInt *nvar)
76627f51fceSHong Zhang {
76727f51fceSHong Zhang   PetscErrorCode ierr;
76827f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
76927f51fceSHong Zhang 
77027f51fceSHong Zhang   PetscFunctionBegin;
77127f51fceSHong Zhang   ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
77227f51fceSHong Zhang   PetscFunctionReturn(0);
77327f51fceSHong Zhang }
77427f51fceSHong Zhang 
7755f2c45f1SShri Abhyankar /*@
7765f2c45f1SShri Abhyankar   DMNetworkSetNumVariables - Sets number of variables for a vertex/edge point.
7775f2c45f1SShri Abhyankar 
7785f2c45f1SShri Abhyankar   Not Collective
7795f2c45f1SShri Abhyankar 
7805f2c45f1SShri Abhyankar   Input Parameters:
7815f2c45f1SShri Abhyankar + dm   - The DMNetworkObject
7825f2c45f1SShri Abhyankar . p    - the vertex/edge point
7835f2c45f1SShri Abhyankar - nvar - number of variables
7845f2c45f1SShri Abhyankar 
7855f2c45f1SShri Abhyankar   Level: intermediate
7865f2c45f1SShri Abhyankar 
7875f2c45f1SShri Abhyankar .seealso: DMNetworkAddNumVariables
7885f2c45f1SShri Abhyankar @*/
7895f2c45f1SShri Abhyankar PetscErrorCode DMNetworkSetNumVariables(DM dm,PetscInt p,PetscInt nvar)
7905f2c45f1SShri Abhyankar {
7915f2c45f1SShri Abhyankar   PetscErrorCode ierr;
7925f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
7935f2c45f1SShri Abhyankar 
7945f2c45f1SShri Abhyankar   PetscFunctionBegin;
7955f2c45f1SShri Abhyankar   ierr = PetscSectionSetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
7965f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7975f2c45f1SShri Abhyankar }
7985f2c45f1SShri Abhyankar 
7995f2c45f1SShri Abhyankar /* Sets up the array that holds the data for all components and its associated section. This
8005f2c45f1SShri Abhyankar    function is called during DMSetUp() */
8015f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
8025f2c45f1SShri Abhyankar {
8035f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
8045f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
805e53b5ba3SHong Zhang   PetscInt                 arr_size,p,offset,offsetp,ncomp,i;
8065f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
8075f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
8085f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
8095f2c45f1SShri Abhyankar 
8105f2c45f1SShri Abhyankar   PetscFunctionBegin;
8115f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
8125f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
81375b160a0SShri Abhyankar   ierr = PetscMalloc1(arr_size,&network->componentdataarray);CHKERRQ(ierr);
8145f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
8155f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
8165f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
8175f2c45f1SShri Abhyankar     /* Copy header */
8185f2c45f1SShri Abhyankar     header = &network->header[p];
819302440fdSBarry Smith     ierr = PetscMemcpy(componentdataarray+offsetp,header,network->dataheadersize*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
8205f2c45f1SShri Abhyankar     /* Copy data */
8215f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
8225f2c45f1SShri Abhyankar     ncomp = header->ndata;
8235f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
8245f2c45f1SShri Abhyankar       offset = offsetp + network->dataheadersize + header->offset[i];
825302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
8265f2c45f1SShri Abhyankar     }
8275f2c45f1SShri Abhyankar   }
8285f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8295f2c45f1SShri Abhyankar }
8305f2c45f1SShri Abhyankar 
8315f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
8325f2c45f1SShri Abhyankar PetscErrorCode DMNetworkVariablesSetUp(DM dm)
8335f2c45f1SShri Abhyankar {
8345f2c45f1SShri Abhyankar   PetscErrorCode ierr;
8355f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8365f2c45f1SShri Abhyankar 
8375f2c45f1SShri Abhyankar   PetscFunctionBegin;
8385f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
8395f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8405f2c45f1SShri Abhyankar }
8415f2c45f1SShri Abhyankar 
8425f2c45f1SShri Abhyankar /*@C
8435f2c45f1SShri Abhyankar   DMNetworkGetComponentDataArray - Returns the component data array
8445f2c45f1SShri Abhyankar 
8455f2c45f1SShri Abhyankar   Not Collective
8465f2c45f1SShri Abhyankar 
8475f2c45f1SShri Abhyankar   Input Parameters:
8485f2c45f1SShri Abhyankar . dm - The DMNetwork Object
8495f2c45f1SShri Abhyankar 
8505f2c45f1SShri Abhyankar   Output Parameters:
8515f2c45f1SShri Abhyankar . componentdataarray - array that holds data for all components
8525f2c45f1SShri Abhyankar 
8535f2c45f1SShri Abhyankar   Level: intermediate
8545f2c45f1SShri Abhyankar 
855a730d845SHong Zhang .seealso: DMNetworkGetComponentKeyOffset, DMNetworkGetNumComponents
8565f2c45f1SShri Abhyankar @*/
8575f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetComponentDataArray(DM dm,DMNetworkComponentGenericDataType **componentdataarray)
8585f2c45f1SShri Abhyankar {
8595f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
8605f2c45f1SShri Abhyankar 
8615f2c45f1SShri Abhyankar   PetscFunctionBegin;
8625f2c45f1SShri Abhyankar   *componentdataarray = network->componentdataarray;
8635f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
8645f2c45f1SShri Abhyankar }
8655f2c45f1SShri Abhyankar 
86624121865SAdrian Maldonado /* Get a subsection from a range of points */
86724121865SAdrian Maldonado PetscErrorCode DMNetworkGetSubSection_private(PetscSection master, PetscInt pstart, PetscInt pend,PetscSection *subsection)
86824121865SAdrian Maldonado {
86924121865SAdrian Maldonado   PetscErrorCode ierr;
87024121865SAdrian Maldonado   PetscInt       i, nvar;
87124121865SAdrian Maldonado 
87224121865SAdrian Maldonado   PetscFunctionBegin;
87324121865SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)master), subsection);CHKERRQ(ierr);
87424121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
87524121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
87624121865SAdrian Maldonado     ierr = PetscSectionGetDof(master,i,&nvar);CHKERRQ(ierr);
87724121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
87824121865SAdrian Maldonado   }
87924121865SAdrian Maldonado 
88024121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
88124121865SAdrian Maldonado   PetscFunctionReturn(0);
88224121865SAdrian Maldonado }
88324121865SAdrian Maldonado 
88424121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
88524121865SAdrian Maldonado PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
88624121865SAdrian Maldonado {
88724121865SAdrian Maldonado   PetscErrorCode ierr;
88824121865SAdrian Maldonado   PetscInt       i, *subpoints;
88924121865SAdrian Maldonado 
89024121865SAdrian Maldonado   PetscFunctionBegin;
89124121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
89224121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
89324121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
89424121865SAdrian Maldonado     subpoints[i - pstart] = i;
89524121865SAdrian Maldonado   }
896459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
89724121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
89824121865SAdrian Maldonado   PetscFunctionReturn(0);
89924121865SAdrian Maldonado }
90024121865SAdrian Maldonado 
90124121865SAdrian Maldonado /*@
90224121865SAdrian Maldonado   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute.
90324121865SAdrian Maldonado 
90424121865SAdrian Maldonado   Collective
90524121865SAdrian Maldonado 
90624121865SAdrian Maldonado   Input Parameters:
90724121865SAdrian Maldonado . dm   - The DMNetworkObject
90824121865SAdrian Maldonado 
90924121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
91024121865SAdrian Maldonado 
91124121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
91224121865SAdrian Maldonado 
91324121865SAdrian Maldonado   where edges = [0, 3] and vertices = [4, 6]. The new orderings will be specific to the subset (i.e vertices = [0, 2]).
91424121865SAdrian Maldonado 
91524121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
91624121865SAdrian Maldonado 
91724121865SAdrian Maldonado   Level: intermediate
91824121865SAdrian Maldonado 
91924121865SAdrian Maldonado @*/
92024121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
92124121865SAdrian Maldonado {
92224121865SAdrian Maldonado   PetscErrorCode ierr;
92324121865SAdrian Maldonado   MPI_Comm       comm;
9249852e123SBarry Smith   PetscMPIInt    rank, size;
92524121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
92624121865SAdrian Maldonado 
927eab1376dSHong Zhang   PetscFunctionBegin;
92824121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
92924121865SAdrian Maldonado   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
9309852e123SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
93124121865SAdrian Maldonado 
93224121865SAdrian Maldonado   /* Create maps for vertices and edges */
93324121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
93424121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
93524121865SAdrian Maldonado 
93624121865SAdrian Maldonado   /* Create local sub-sections */
93724121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
93824121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
93924121865SAdrian Maldonado 
9409852e123SBarry Smith   if (size > 1) {
94124121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
94224121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
94324121865SAdrian Maldonado   ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
94424121865SAdrian Maldonado   ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
94524121865SAdrian Maldonado   } else {
94624121865SAdrian Maldonado   /* create structures for vertex */
94724121865SAdrian Maldonado   ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
94824121865SAdrian Maldonado   /* create structures for edge */
94924121865SAdrian Maldonado   ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
95024121865SAdrian Maldonado   }
95124121865SAdrian Maldonado 
95224121865SAdrian Maldonado 
95324121865SAdrian Maldonado   /* Add viewers */
95424121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
95524121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
95624121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
95724121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
95824121865SAdrian Maldonado 
95924121865SAdrian Maldonado   PetscFunctionReturn(0);
96024121865SAdrian Maldonado }
9617b6afd5bSHong Zhang 
9625f2c45f1SShri Abhyankar /*@
9635f2c45f1SShri Abhyankar   DMNetworkDistribute - Distributes the network and moves associated component data.
9645f2c45f1SShri Abhyankar 
9655f2c45f1SShri Abhyankar   Collective
9665f2c45f1SShri Abhyankar 
9675f2c45f1SShri Abhyankar   Input Parameter:
968d3464fd4SAdrian Maldonado + DM - the DMNetwork object
9695f2c45f1SShri Abhyankar - overlap - The overlap of partitions, 0 is the default
9705f2c45f1SShri Abhyankar 
9715f2c45f1SShri Abhyankar   Notes:
9728b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
9735f2c45f1SShri Abhyankar 
9745f2c45f1SShri Abhyankar   Level: intermediate
9755f2c45f1SShri Abhyankar 
9765f2c45f1SShri Abhyankar .seealso: DMNetworkCreate
9775f2c45f1SShri Abhyankar @*/
978d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
9795f2c45f1SShri Abhyankar {
980d3464fd4SAdrian Maldonado   MPI_Comm       comm;
9815f2c45f1SShri Abhyankar   PetscErrorCode ierr;
982d3464fd4SAdrian Maldonado   PetscMPIInt    size;
983d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
984d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
9855f2c45f1SShri Abhyankar   PetscSF        pointsf;
9865f2c45f1SShri Abhyankar   DM             newDM;
98751ac5effSHong Zhang   PetscPartitioner part;
988b9c6e19dSShri Abhyankar   PetscInt         j,e,v,offset;
989b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
9905f2c45f1SShri Abhyankar 
9915f2c45f1SShri Abhyankar   PetscFunctionBegin;
992d3464fd4SAdrian Maldonado 
993d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
994d3464fd4SAdrian Maldonado   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
995d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
996d3464fd4SAdrian Maldonado 
997d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
9985f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
9995f2c45f1SShri Abhyankar   newDMnetwork->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType);
100051ac5effSHong Zhang 
100151ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
100251ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
100351ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
100451ac5effSHong Zhang 
10055f2c45f1SShri Abhyankar   /* Distribute plex dm and dof section */
100680cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
100751ac5effSHong Zhang 
10085f2c45f1SShri Abhyankar   /* Distribute dof section */
1009d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DofSection);CHKERRQ(ierr);
10105f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
1011d3464fd4SAdrian Maldonado   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)*dm),&newDMnetwork->DataSection);CHKERRQ(ierr);
101251ac5effSHong Zhang 
10135f2c45f1SShri Abhyankar   /* Distribute data and associated section */
101431da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
101524121865SAdrian Maldonado 
10165f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
10175f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
10185f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
10195f2c45f1SShri Abhyankar   newDMnetwork->nEdges = newDMnetwork->eEnd - newDMnetwork->eStart;
10206fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
10216fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
10225f2c45f1SShri Abhyankar   newDMnetwork->NEdges = oldDMnetwork->NEdges;
102324121865SAdrian Maldonado 
10245f2c45f1SShri Abhyankar   /* Set Dof section as the default section for dm */
10255f2c45f1SShri Abhyankar   ierr = DMSetDefaultSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
10265f2c45f1SShri Abhyankar   ierr = DMGetDefaultGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
10275f2c45f1SShri Abhyankar 
1028b9c6e19dSShri Abhyankar   /* Set up subnetwork info in the newDM */
1029b9c6e19dSShri Abhyankar   newDMnetwork->nsubnet = oldDMnetwork->nsubnet;
1030b9c6e19dSShri Abhyankar   ierr = PetscCalloc1(newDMnetwork->nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
1031b9c6e19dSShri Abhyankar   /* Copy over the global number of vertices and edges in each subnetwork. Note that these are already
1032b9c6e19dSShri Abhyankar      calculated in DMNetworkLayoutSetUp()
1033b9c6e19dSShri Abhyankar   */
1034b9c6e19dSShri Abhyankar   for(j=0; j < newDMnetwork->nsubnet; j++) {
1035b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx = oldDMnetwork->subnet[j].Nvtx;
1036b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1037b9c6e19dSShri Abhyankar   }
1038b9c6e19dSShri Abhyankar 
1039b9c6e19dSShri Abhyankar   for(e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1040b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1041b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1042b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1043b9c6e19dSShri Abhyankar   }
1044b9c6e19dSShri Abhyankar 
1045b9c6e19dSShri Abhyankar   for(v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1046b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1047b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1048b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nvtx++;
1049b9c6e19dSShri Abhyankar   }
1050b9c6e19dSShri Abhyankar 
1051b9c6e19dSShri Abhyankar   /* Now create the vertices and edge arrays for the subnetworks */
1052b9c6e19dSShri Abhyankar   for(j=0; j < newDMnetwork->nsubnet; j++) {
1053b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nedge,&newDMnetwork->subnet[j].edges);CHKERRQ(ierr);
1054b9c6e19dSShri Abhyankar     ierr = PetscCalloc1(newDMnetwork->subnet[j].nvtx,&newDMnetwork->subnet[j].vertices);CHKERRQ(ierr);
1055b9c6e19dSShri Abhyankar     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop.
1056b9c6e19dSShri Abhyankar        These get updated when the vertices and edges are added. */
1057b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1058b9c6e19dSShri Abhyankar   }
1059b9c6e19dSShri Abhyankar 
1060b9c6e19dSShri Abhyankar   /* Set the vertices and edges in each subnetwork */
1061b9c6e19dSShri Abhyankar   for(e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++ ) {
1062b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1063b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1064b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++]  = e;
1065b9c6e19dSShri Abhyankar   }
1066b9c6e19dSShri Abhyankar 
1067b9c6e19dSShri Abhyankar   for(v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++ ) {
1068b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1069b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1070b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++]  = v;
1071b9c6e19dSShri Abhyankar   }
1072b9c6e19dSShri Abhyankar 
107324121865SAdrian Maldonado   /* Destroy point SF */
107424121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
107524121865SAdrian Maldonado 
1076d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
1077d3464fd4SAdrian Maldonado   *dm  = newDM;
10785f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10795f2c45f1SShri Abhyankar }
10805f2c45f1SShri Abhyankar 
108124121865SAdrian Maldonado /*@C
108224121865SAdrian Maldonado   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering.
108324121865SAdrian Maldonado 
108424121865SAdrian Maldonado   Input Parameters:
108524121865SAdrian Maldonado + masterSF - the original SF structure
108624121865SAdrian Maldonado - map      - a ISLocalToGlobal mapping that contains the subset of points
108724121865SAdrian Maldonado 
108824121865SAdrian Maldonado   Output Parameters:
108924121865SAdrian Maldonado . subSF    - a subset of the masterSF for the desired subset.
109024121865SAdrian Maldonado */
109124121865SAdrian Maldonado 
109224121865SAdrian Maldonado PetscErrorCode PetscSFGetSubSF(PetscSF mastersf, ISLocalToGlobalMapping map, PetscSF *subSF) {
109324121865SAdrian Maldonado 
109424121865SAdrian Maldonado   PetscErrorCode        ierr;
109524121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
109624121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
109724121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
109824121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
109924121865SAdrian Maldonado   const PetscInt        *ilocal;
110024121865SAdrian Maldonado   const PetscSFNode     *iremote;
110124121865SAdrian Maldonado 
110224121865SAdrian Maldonado   PetscFunctionBegin;
110324121865SAdrian Maldonado   ierr = PetscSFGetGraph(mastersf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
110424121865SAdrian Maldonado 
110524121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
110624121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
110724121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
110824121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
110924121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
111024121865SAdrian Maldonado   }
111124121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
111224121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
111324121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
111424121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
111524121865SAdrian Maldonado   ierr = PetscSFBcastBegin(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
111624121865SAdrian Maldonado   ierr = PetscSFBcastEnd(mastersf, MPIU_INT, local_points, remote_points);CHKERRQ(ierr);
111724121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
11184b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
11194b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
112024121865SAdrian Maldonado   nleaves_sub = 0;
112124121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
112224121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
112324121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
11244b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
112524121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
112624121865SAdrian Maldonado       nleaves_sub += 1;
112724121865SAdrian Maldonado     }
112824121865SAdrian Maldonado   }
112924121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
113024121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
113124121865SAdrian Maldonado 
113224121865SAdrian Maldonado   /* Create new subSF */
113324121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
113424121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
11354b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
113624121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
11374b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
113824121865SAdrian Maldonado   PetscFunctionReturn(0);
113924121865SAdrian Maldonado }
114024121865SAdrian Maldonado 
11415f2c45f1SShri Abhyankar /*@C
11425f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
11435f2c45f1SShri Abhyankar 
11445f2c45f1SShri Abhyankar   Not Collective
11455f2c45f1SShri Abhyankar 
11465f2c45f1SShri Abhyankar   Input Parameters:
11475f2c45f1SShri Abhyankar + dm - The DMNetwork object
11485f2c45f1SShri Abhyankar - p  - the vertex point
11495f2c45f1SShri Abhyankar 
11505f2c45f1SShri Abhyankar   Output Paramters:
11515f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
11525f2c45f1SShri Abhyankar - edges  - List of edge points
11535f2c45f1SShri Abhyankar 
11545f2c45f1SShri Abhyankar   Level: intermediate
11555f2c45f1SShri Abhyankar 
11565f2c45f1SShri Abhyankar   Fortran Notes:
11575f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
11585f2c45f1SShri Abhyankar   include petsc.h90 in your code.
11595f2c45f1SShri Abhyankar 
1160d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices
11615f2c45f1SShri Abhyankar @*/
11625f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
11635f2c45f1SShri Abhyankar {
11645f2c45f1SShri Abhyankar   PetscErrorCode ierr;
11655f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11665f2c45f1SShri Abhyankar 
11675f2c45f1SShri Abhyankar   PetscFunctionBegin;
11685f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
11695f2c45f1SShri Abhyankar   ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);
11705f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
11715f2c45f1SShri Abhyankar }
11725f2c45f1SShri Abhyankar 
11735f2c45f1SShri Abhyankar /*@C
1174d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
11755f2c45f1SShri Abhyankar 
11765f2c45f1SShri Abhyankar   Not Collective
11775f2c45f1SShri Abhyankar 
11785f2c45f1SShri Abhyankar   Input Parameters:
11795f2c45f1SShri Abhyankar + dm - The DMNetwork object
11805f2c45f1SShri Abhyankar - p  - the edge point
11815f2c45f1SShri Abhyankar 
11825f2c45f1SShri Abhyankar   Output Paramters:
11835f2c45f1SShri Abhyankar . vertices  - vertices connected to this edge
11845f2c45f1SShri Abhyankar 
11855f2c45f1SShri Abhyankar   Level: intermediate
11865f2c45f1SShri Abhyankar 
11875f2c45f1SShri Abhyankar   Fortran Notes:
11885f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
11895f2c45f1SShri Abhyankar   include petsc.h90 in your code.
11905f2c45f1SShri Abhyankar 
11915f2c45f1SShri Abhyankar .seealso: DMNetworkCreate, DMNetworkGetSupportingEdges
11925f2c45f1SShri Abhyankar @*/
1193d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
11945f2c45f1SShri Abhyankar {
11955f2c45f1SShri Abhyankar   PetscErrorCode ierr;
11965f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11975f2c45f1SShri Abhyankar 
11985f2c45f1SShri Abhyankar   PetscFunctionBegin;
11995f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
12005f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
12015f2c45f1SShri Abhyankar }
12025f2c45f1SShri Abhyankar 
12035f2c45f1SShri Abhyankar /*@
12045f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
12055f2c45f1SShri Abhyankar 
12065f2c45f1SShri Abhyankar   Not Collective
12075f2c45f1SShri Abhyankar 
12085f2c45f1SShri Abhyankar   Input Parameters:
12095f2c45f1SShri Abhyankar + dm - The DMNetwork object
12105f2c45f1SShri Abhyankar . p  - the vertex point
12115f2c45f1SShri Abhyankar 
12125f2c45f1SShri Abhyankar   Output Parameter:
12135f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
12145f2c45f1SShri Abhyankar 
12155f2c45f1SShri Abhyankar   Level: intermediate
12165f2c45f1SShri Abhyankar 
1217d842c372SHong Zhang .seealso: DMNetworkCreate, DMNetworkGetConnectedVertices, DMNetworkGetVertexRange
12185f2c45f1SShri Abhyankar @*/
12195f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
12205f2c45f1SShri Abhyankar {
12215f2c45f1SShri Abhyankar   PetscErrorCode ierr;
12225f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
12235f2c45f1SShri Abhyankar   PetscInt       offsetg;
12245f2c45f1SShri Abhyankar   PetscSection   sectiong;
12255f2c45f1SShri Abhyankar 
12265f2c45f1SShri Abhyankar   PetscFunctionBegin;
12275f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
12285f2c45f1SShri Abhyankar   ierr = DMGetDefaultGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
12295f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
12305f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
12315f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
12325f2c45f1SShri Abhyankar }
12335f2c45f1SShri Abhyankar 
12345f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
12355f2c45f1SShri Abhyankar {
12365f2c45f1SShri Abhyankar   PetscErrorCode ierr;
12375f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
12385f2c45f1SShri Abhyankar 
12395f2c45f1SShri Abhyankar   PetscFunctionBegin;
12405f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
12415f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
12425f2c45f1SShri Abhyankar 
12435f2c45f1SShri Abhyankar   ierr = DMSetDefaultSection(network->plex,network->DofSection);CHKERRQ(ierr);
12445f2c45f1SShri Abhyankar   ierr = DMGetDefaultGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
12455f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
12465f2c45f1SShri Abhyankar }
12475f2c45f1SShri Abhyankar 
12481ad426b7SHong Zhang /*@
124917df6e9eSHong Zhang     DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
12501ad426b7SHong Zhang                             -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
12511ad426b7SHong Zhang 
12521ad426b7SHong Zhang     Collective
12531ad426b7SHong Zhang 
12541ad426b7SHong Zhang     Input Parameters:
125583b2e829SHong Zhang +   dm - The DMNetwork object
125683b2e829SHong Zhang .   eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
125783b2e829SHong Zhang -   vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
12581ad426b7SHong Zhang 
12591ad426b7SHong Zhang     Level: intermediate
12601ad426b7SHong Zhang 
12611ad426b7SHong Zhang @*/
126283b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
12631ad426b7SHong Zhang {
12641ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
12658675203cSHong Zhang   PetscErrorCode ierr;
12661ad426b7SHong Zhang 
12671ad426b7SHong Zhang   PetscFunctionBegin;
126883b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
126983b2e829SHong Zhang   network->userVertexJacobian = vflg;
12708675203cSHong Zhang 
12718675203cSHong Zhang   if (eflg && !network->Je) {
12728675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
12738675203cSHong Zhang   }
12748675203cSHong Zhang 
12758675203cSHong Zhang   if (vflg && !network->Jv) {
12768675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
12778675203cSHong Zhang     PetscInt       nVertices = network->nVertices,nedges_total;
12788675203cSHong Zhang     const PetscInt *edges;
12798675203cSHong Zhang 
12808675203cSHong Zhang     /* count nvertex_total */
12818675203cSHong Zhang     nedges_total = 0;
12828675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
12838675203cSHong Zhang 
12848675203cSHong Zhang     vptr[0] = 0;
12858675203cSHong Zhang     for (i=0; i<nVertices; i++) {
12868675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
12878675203cSHong Zhang       nedges_total += nedges;
12888675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
12898675203cSHong Zhang     }
12908675203cSHong Zhang 
12918675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
12928675203cSHong Zhang     network->Jvptr = vptr;
12938675203cSHong Zhang   }
12941ad426b7SHong Zhang   PetscFunctionReturn(0);
12951ad426b7SHong Zhang }
12961ad426b7SHong Zhang 
12971ad426b7SHong Zhang /*@
129883b2e829SHong Zhang     DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
129983b2e829SHong Zhang 
130083b2e829SHong Zhang     Not Collective
130183b2e829SHong Zhang 
130283b2e829SHong Zhang     Input Parameters:
130383b2e829SHong Zhang +   dm - The DMNetwork object
130483b2e829SHong Zhang .   p  - the edge point
13053e97b6e8SHong Zhang -   J - array (size = 3) of Jacobian submatrices for this edge point:
13063e97b6e8SHong Zhang         J[0]: this edge
1307d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
130883b2e829SHong Zhang 
130983b2e829SHong Zhang     Level: intermediate
131083b2e829SHong Zhang 
131183b2e829SHong Zhang .seealso: DMNetworkVertexSetMatrix
131283b2e829SHong Zhang @*/
131383b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
131483b2e829SHong Zhang {
131583b2e829SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
131683b2e829SHong Zhang 
131783b2e829SHong Zhang   PetscFunctionBegin;
13188675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
13198675203cSHong Zhang 
13208675203cSHong Zhang   if (J) {
1321883e35e8SHong Zhang     network->Je[3*p]   = J[0];
1322883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
1323883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
13248675203cSHong Zhang   }
132583b2e829SHong Zhang   PetscFunctionReturn(0);
132683b2e829SHong Zhang }
132783b2e829SHong Zhang 
132883b2e829SHong Zhang /*@
132976ddfea5SHong Zhang     DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
13301ad426b7SHong Zhang 
13311ad426b7SHong Zhang     Not Collective
13321ad426b7SHong Zhang 
13331ad426b7SHong Zhang     Input Parameters:
13341ad426b7SHong Zhang +   dm - The DMNetwork object
13351ad426b7SHong Zhang .   p  - the vertex point
13363e97b6e8SHong Zhang -   J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
13373e97b6e8SHong Zhang         J[0]:       this vertex
13383e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
13393e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
13401ad426b7SHong Zhang 
13411ad426b7SHong Zhang     Level: intermediate
13421ad426b7SHong Zhang 
134383b2e829SHong Zhang .seealso: DMNetworkEdgeSetMatrix
13441ad426b7SHong Zhang @*/
1345883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
13465f2c45f1SShri Abhyankar {
13475f2c45f1SShri Abhyankar   PetscErrorCode ierr;
13485f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
13498675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
1350883e35e8SHong Zhang   const PetscInt *edges;
13515f2c45f1SShri Abhyankar 
13525f2c45f1SShri Abhyankar   PetscFunctionBegin;
13538675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
1354883e35e8SHong Zhang 
13558675203cSHong Zhang   if (J) {
1356883e35e8SHong Zhang     vptr = network->Jvptr;
13573e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
13583e97b6e8SHong Zhang 
13593e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
1360883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
1361883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
13628675203cSHong Zhang   }
1363883e35e8SHong Zhang   PetscFunctionReturn(0);
1364883e35e8SHong Zhang }
1365883e35e8SHong Zhang 
1366e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
13675cf7da58SHong Zhang {
13685cf7da58SHong Zhang   PetscErrorCode ierr;
13695cf7da58SHong Zhang   PetscInt       j;
13705cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
13715cf7da58SHong Zhang 
13725cf7da58SHong Zhang   PetscFunctionBegin;
13735cf7da58SHong Zhang   if (!ghost) {
13745cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
13755cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
13765cf7da58SHong Zhang     }
13775cf7da58SHong Zhang   } else {
13785cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
13795cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
13805cf7da58SHong Zhang     }
13815cf7da58SHong Zhang   }
13825cf7da58SHong Zhang   PetscFunctionReturn(0);
13835cf7da58SHong Zhang }
13845cf7da58SHong Zhang 
1385e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
13865cf7da58SHong Zhang {
13875cf7da58SHong Zhang   PetscErrorCode ierr;
13885cf7da58SHong Zhang   PetscInt       j,ncols_u;
13895cf7da58SHong Zhang   PetscScalar    val;
13905cf7da58SHong Zhang 
13915cf7da58SHong Zhang   PetscFunctionBegin;
13925cf7da58SHong Zhang   if (!ghost) {
13935cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
13945cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
13955cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
13965cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
13975cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
13985cf7da58SHong Zhang     }
13995cf7da58SHong Zhang   } else {
14005cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
14015cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
14025cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
14035cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
14045cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
14055cf7da58SHong Zhang     }
14065cf7da58SHong Zhang   }
14075cf7da58SHong Zhang   PetscFunctionReturn(0);
14085cf7da58SHong Zhang }
14095cf7da58SHong Zhang 
1410e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
14115cf7da58SHong Zhang {
14125cf7da58SHong Zhang   PetscErrorCode ierr;
14135cf7da58SHong Zhang 
14145cf7da58SHong Zhang   PetscFunctionBegin;
14155cf7da58SHong Zhang   if (Ju) {
14165cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
14175cf7da58SHong Zhang   } else {
14185cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
14195cf7da58SHong Zhang   }
14205cf7da58SHong Zhang   PetscFunctionReturn(0);
14215cf7da58SHong Zhang }
14225cf7da58SHong Zhang 
1423e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1424883e35e8SHong Zhang {
1425883e35e8SHong Zhang   PetscErrorCode ierr;
1426883e35e8SHong Zhang   PetscInt       j,*cols;
1427883e35e8SHong Zhang   PetscScalar    *zeros;
1428883e35e8SHong Zhang 
1429883e35e8SHong Zhang   PetscFunctionBegin;
1430883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
1431883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
1432883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
1433883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
14341ad426b7SHong Zhang   PetscFunctionReturn(0);
14351ad426b7SHong Zhang }
1436a4e85ca8SHong Zhang 
1437e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
14383e97b6e8SHong Zhang {
14393e97b6e8SHong Zhang   PetscErrorCode ierr;
14403e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
14413e97b6e8SHong Zhang   const PetscInt *cols;
14423e97b6e8SHong Zhang   PetscScalar    zero=0.0;
14433e97b6e8SHong Zhang 
14443e97b6e8SHong Zhang   PetscFunctionBegin;
14453e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
14463e97b6e8SHong 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);
14473e97b6e8SHong Zhang 
14483e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
14493e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
14503e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
14513e97b6e8SHong Zhang       col = cols[j] + cstart;
14523e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
14533e97b6e8SHong Zhang     }
14543e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
14553e97b6e8SHong Zhang   }
14563e97b6e8SHong Zhang   PetscFunctionReturn(0);
14573e97b6e8SHong Zhang }
14581ad426b7SHong Zhang 
1459e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
1460a4e85ca8SHong Zhang {
1461a4e85ca8SHong Zhang   PetscErrorCode ierr;
1462f4431b8cSHong Zhang 
1463a4e85ca8SHong Zhang   PetscFunctionBegin;
1464a4e85ca8SHong Zhang   if (Ju) {
1465a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1466a4e85ca8SHong Zhang   } else {
1467a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1468a4e85ca8SHong Zhang   }
1469a4e85ca8SHong Zhang   PetscFunctionReturn(0);
1470a4e85ca8SHong Zhang }
1471a4e85ca8SHong Zhang 
147224121865SAdrian 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.
147324121865SAdrian Maldonado */
147424121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
147524121865SAdrian Maldonado {
147624121865SAdrian Maldonado   PetscErrorCode ierr;
147724121865SAdrian Maldonado   PetscInt       i, size, dof;
147824121865SAdrian Maldonado   PetscInt       *glob2loc;
147924121865SAdrian Maldonado 
148024121865SAdrian Maldonado   PetscFunctionBegin;
148124121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
148224121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
148324121865SAdrian Maldonado 
148424121865SAdrian Maldonado   for (i = 0; i < size; i++) {
148524121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
148624121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
148724121865SAdrian Maldonado     glob2loc[i] = dof;
148824121865SAdrian Maldonado   }
148924121865SAdrian Maldonado 
149024121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
149124121865SAdrian Maldonado #if 0
149224121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
149324121865SAdrian Maldonado #endif
149424121865SAdrian Maldonado   PetscFunctionReturn(0);
149524121865SAdrian Maldonado }
149624121865SAdrian Maldonado 
149701ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
14981ad426b7SHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
14991ad426b7SHong Zhang {
15001ad426b7SHong Zhang   PetscErrorCode ierr;
150124121865SAdrian Maldonado   PetscMPIInt    rank, size;
15021ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
1503a4e85ca8SHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
1504840c2264SHong Zhang   PetscInt       cstart,ncols,j,e,v;
150524121865SAdrian Maldonado   PetscBool      ghost,ghost_vc,ghost2,isNest;
1506a4e85ca8SHong Zhang   Mat            Juser;
1507bfbc38dcSHong Zhang   PetscSection   sectionGlobal;
1508447d78afSSatish Balay   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
1509a4e85ca8SHong Zhang   const PetscInt *edges,*cone;
15105cf7da58SHong Zhang   MPI_Comm       comm;
151124121865SAdrian Maldonado   MatType        mtype;
15125cf7da58SHong Zhang   Vec            vd_nz,vo_nz;
15135cf7da58SHong Zhang   PetscInt       *dnnz,*onnz;
15145cf7da58SHong Zhang   PetscScalar    *vdnz,*vonz;
15151ad426b7SHong Zhang 
15161ad426b7SHong Zhang   PetscFunctionBegin;
151724121865SAdrian Maldonado   mtype = dm->mattype;
151824121865SAdrian Maldonado   ierr = PetscStrcmp(mtype, MATNEST, &isNest);CHKERRQ(ierr);
151924121865SAdrian Maldonado 
152024121865SAdrian Maldonado   if (isNest) {
15210731d606SHong Zhang     /* ierr = DMCreateMatrix_Network_Nest(); */
152224121865SAdrian Maldonado     PetscInt   eDof, vDof;
152324121865SAdrian Maldonado     Mat        j11, j12, j21, j22, bA[2][2];
152424121865SAdrian Maldonado     ISLocalToGlobalMapping eISMap, vISMap;
152524121865SAdrian Maldonado 
152624121865SAdrian Maldonado     ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
152724121865SAdrian Maldonado     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
152824121865SAdrian Maldonado     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
152924121865SAdrian Maldonado 
153024121865SAdrian Maldonado     ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
153124121865SAdrian Maldonado     ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
153224121865SAdrian Maldonado 
153301ad2aeeSHong Zhang     ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
153424121865SAdrian Maldonado     ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
153524121865SAdrian Maldonado     ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
153624121865SAdrian Maldonado 
153701ad2aeeSHong Zhang     ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
153824121865SAdrian Maldonado     ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
153924121865SAdrian Maldonado     ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
154024121865SAdrian Maldonado 
154101ad2aeeSHong Zhang     ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
154224121865SAdrian Maldonado     ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
154324121865SAdrian Maldonado     ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
154424121865SAdrian Maldonado 
154501ad2aeeSHong Zhang     ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
154624121865SAdrian Maldonado     ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
154724121865SAdrian Maldonado     ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
154824121865SAdrian Maldonado 
15493f6a6bdaSHong Zhang     bA[0][0] = j11;
15503f6a6bdaSHong Zhang     bA[0][1] = j12;
15513f6a6bdaSHong Zhang     bA[1][0] = j21;
15523f6a6bdaSHong Zhang     bA[1][1] = j22;
155324121865SAdrian Maldonado 
155424121865SAdrian Maldonado     ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
155524121865SAdrian Maldonado     ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
155624121865SAdrian Maldonado 
155724121865SAdrian Maldonado     ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
155824121865SAdrian Maldonado     ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
155924121865SAdrian Maldonado     ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
156024121865SAdrian Maldonado     ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
156124121865SAdrian Maldonado 
156224121865SAdrian Maldonado     ierr = MatSetUp(j11);CHKERRQ(ierr);
156324121865SAdrian Maldonado     ierr = MatSetUp(j12);CHKERRQ(ierr);
156424121865SAdrian Maldonado     ierr = MatSetUp(j21);CHKERRQ(ierr);
156524121865SAdrian Maldonado     ierr = MatSetUp(j22);CHKERRQ(ierr);
156624121865SAdrian Maldonado 
156701ad2aeeSHong Zhang     ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
156824121865SAdrian Maldonado     ierr = MatSetUp(*J);CHKERRQ(ierr);
156924121865SAdrian Maldonado     ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
157024121865SAdrian Maldonado     ierr = MatDestroy(&j11);CHKERRQ(ierr);
157124121865SAdrian Maldonado     ierr = MatDestroy(&j12);CHKERRQ(ierr);
157224121865SAdrian Maldonado     ierr = MatDestroy(&j21);CHKERRQ(ierr);
157324121865SAdrian Maldonado     ierr = MatDestroy(&j22);CHKERRQ(ierr);
157424121865SAdrian Maldonado 
157524121865SAdrian Maldonado     ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
157624121865SAdrian Maldonado     ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
157724121865SAdrian Maldonado 
157824121865SAdrian Maldonado     /* Free structures */
157924121865SAdrian Maldonado     ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
158024121865SAdrian Maldonado     ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
158124121865SAdrian Maldonado 
158224121865SAdrian Maldonado     PetscFunctionReturn(0);
158324121865SAdrian Maldonado   } else if (!network->userEdgeJacobian && !network->userVertexJacobian) {
1584a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
1585bfbc38dcSHong Zhang     ierr = DMCreateMatrix(network->plex,J);CHKERRQ(ierr);
1586bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
15871ad426b7SHong Zhang     PetscFunctionReturn(0);
15881ad426b7SHong Zhang   }
15891ad426b7SHong Zhang 
1590bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
15912a945128SHong Zhang   ierr = DMGetDefaultGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
1592bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
1593bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
15942a945128SHong Zhang 
15952a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
15962a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
159789898e50SHong Zhang 
159889898e50SHong Zhang   /* (1) Set matrix preallocation */
159989898e50SHong Zhang   /*------------------------------*/
1600840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1601840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
1602840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
1603840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
1604840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
1605840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
1606840c2264SHong Zhang 
160789898e50SHong Zhang   /* Set preallocation for edges */
160889898e50SHong Zhang   /*-----------------------------*/
1609840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
1610840c2264SHong Zhang 
1611bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
1612840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
1613840c2264SHong Zhang     /* Get row indices */
1614840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
1615840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
1616840c2264SHong Zhang     if (nrows) {
1617840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
1618840c2264SHong Zhang 
16195cf7da58SHong Zhang       /* Set preallocation for conntected vertices */
1620d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1621840c2264SHong Zhang       for (v=0; v<2; v++) {
1622840c2264SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
1623840c2264SHong Zhang 
16248675203cSHong Zhang         if (network->Je) {
1625840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
16268675203cSHong Zhang         } else Juser = NULL;
1627840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
16285cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1629840c2264SHong Zhang       }
1630840c2264SHong Zhang 
163189898e50SHong Zhang       /* Set preallocation for edge self */
1632840c2264SHong Zhang       cstart = rstart;
16338675203cSHong Zhang       if (network->Je) {
1634840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
16358675203cSHong Zhang       } else Juser = NULL;
16365cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1637840c2264SHong Zhang     }
1638840c2264SHong Zhang   }
1639840c2264SHong Zhang 
164089898e50SHong Zhang   /* Set preallocation for vertices */
164189898e50SHong Zhang   /*--------------------------------*/
1642840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
16438675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
1644840c2264SHong Zhang 
1645840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
1646840c2264SHong Zhang     /* Get row indices */
1647840c2264SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1648840c2264SHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
1649840c2264SHong Zhang     if (!nrows) continue;
1650840c2264SHong Zhang 
1651bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1652bdcb62a2SHong Zhang     if (ghost) {
1653bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1654bdcb62a2SHong Zhang     } else {
1655bdcb62a2SHong Zhang       rows_v = rows;
1656bdcb62a2SHong Zhang     }
1657bdcb62a2SHong Zhang 
1658bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1659840c2264SHong Zhang 
1660840c2264SHong Zhang     /* Get supporting edges and connected vertices */
1661840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1662840c2264SHong Zhang 
1663840c2264SHong Zhang     for (e=0; e<nedges; e++) {
1664840c2264SHong Zhang       /* Supporting edges */
1665840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1666840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1667840c2264SHong Zhang 
16688675203cSHong Zhang       if (network->Jv) {
1669840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
16708675203cSHong Zhang       } else Juser = NULL;
1671bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
1672840c2264SHong Zhang 
1673840c2264SHong Zhang       /* Connected vertices */
1674d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
1675840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
1676840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
1677840c2264SHong Zhang 
1678840c2264SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1679840c2264SHong Zhang 
16808675203cSHong Zhang       if (network->Jv) {
1681840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
16828675203cSHong Zhang       } else Juser = NULL;
1683e102a522SHong Zhang       if (ghost_vc||ghost) {
1684e102a522SHong Zhang         ghost2 = PETSC_TRUE;
1685e102a522SHong Zhang       } else {
1686e102a522SHong Zhang         ghost2 = PETSC_FALSE;
1687e102a522SHong Zhang       }
1688e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
1689840c2264SHong Zhang     }
1690840c2264SHong Zhang 
169189898e50SHong Zhang     /* Set preallocation for vertex self */
1692840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1693840c2264SHong Zhang     if (!ghost) {
1694840c2264SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
16958675203cSHong Zhang       if (network->Jv) {
1696840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
16978675203cSHong Zhang       } else Juser = NULL;
1698bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
1699840c2264SHong Zhang     }
1700bdcb62a2SHong Zhang     if (ghost) {
1701bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1702bdcb62a2SHong Zhang     }
1703840c2264SHong Zhang   }
1704840c2264SHong Zhang 
1705840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
1706840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
17075cf7da58SHong Zhang 
17085cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
17095cf7da58SHong Zhang 
17105cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
1711840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
1712840c2264SHong Zhang 
1713840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
1714840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
1715840c2264SHong Zhang   for (j=0; j<localSize; j++) {
1716e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
1717e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
1718840c2264SHong Zhang   }
1719840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
1720840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
1721840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
1722840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
1723840c2264SHong Zhang 
17245cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
17255cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
17265cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
17275cf7da58SHong Zhang 
17285cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
17295cf7da58SHong Zhang 
173089898e50SHong Zhang   /* (2) Set matrix entries for edges */
173189898e50SHong Zhang   /*----------------------------------*/
17321ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
1733bfbc38dcSHong Zhang     /* Get row indices */
17341ad426b7SHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,e,&rstart);CHKERRQ(ierr);
173517df6e9eSHong Zhang     ierr = DMNetworkGetNumVariables(dm,e,&nrows);CHKERRQ(ierr);
17364b976069SHong Zhang     if (nrows) {
173717df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
17381ad426b7SHong Zhang 
1739bfbc38dcSHong Zhang       /* Set matrix entries for conntected vertices */
1740d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
1741bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
1742bfbc38dcSHong Zhang         ierr = DMNetworkGetVariableGlobalOffset(dm,cone[v],&cstart);CHKERRQ(ierr);
1743883e35e8SHong Zhang         ierr = DMNetworkGetNumVariables(dm,cone[v],&ncols);CHKERRQ(ierr);
17443e97b6e8SHong Zhang 
17458675203cSHong Zhang         if (network->Je) {
1746a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
17478675203cSHong Zhang         } else Juser = NULL;
1748a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
1749bfbc38dcSHong Zhang       }
175017df6e9eSHong Zhang 
1751bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
17523e97b6e8SHong Zhang       cstart = rstart;
17538675203cSHong Zhang       if (network->Je) {
1754a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
17558675203cSHong Zhang       } else Juser = NULL;
1756a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
17571ad426b7SHong Zhang     }
17584b976069SHong Zhang   }
17591ad426b7SHong Zhang 
1760bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
176183b2e829SHong Zhang   /*---------------------------------*/
17621ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
1763bfbc38dcSHong Zhang     /* Get row indices */
1764596e729fSHong Zhang     ierr = DMNetworkGetVariableGlobalOffset(dm,v,&rstart);CHKERRQ(ierr);
1765596e729fSHong Zhang     ierr = DMNetworkGetNumVariables(dm,v,&nrows);CHKERRQ(ierr);
17664b976069SHong Zhang     if (!nrows) continue;
1767596e729fSHong Zhang 
1768bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
1769bdcb62a2SHong Zhang     if (ghost) {
1770bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
1771bdcb62a2SHong Zhang     } else {
1772bdcb62a2SHong Zhang       rows_v = rows;
1773bdcb62a2SHong Zhang     }
1774bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
1775596e729fSHong Zhang 
1776bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
1777596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1778596e729fSHong Zhang 
1779596e729fSHong Zhang     for (e=0; e<nedges; e++) {
1780bfbc38dcSHong Zhang       /* Supporting edges */
1781596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,edges[e],&cstart);CHKERRQ(ierr);
1782596e729fSHong Zhang       ierr = DMNetworkGetNumVariables(dm,edges[e],&ncols);CHKERRQ(ierr);
1783596e729fSHong Zhang 
17848675203cSHong Zhang       if (network->Jv) {
1785a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
17868675203cSHong Zhang       } else Juser = NULL;
1787bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
1788596e729fSHong Zhang 
1789bfbc38dcSHong Zhang       /* Connected vertices */
1790d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
17912a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
17922a945128SHong Zhang 
179344aca652SHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,vc,&cstart);CHKERRQ(ierr);
179444aca652SHong Zhang       ierr = DMNetworkGetNumVariables(dm,vc,&ncols);CHKERRQ(ierr);
1795a4e85ca8SHong Zhang 
17968675203cSHong Zhang       if (network->Jv) {
1797a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
17988675203cSHong Zhang       } else Juser = NULL;
1799bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
1800596e729fSHong Zhang     }
1801596e729fSHong Zhang 
1802bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
18031ad426b7SHong Zhang     if (!ghost) {
1804596e729fSHong Zhang       ierr = DMNetworkGetVariableGlobalOffset(dm,v,&cstart);CHKERRQ(ierr);
18058675203cSHong Zhang       if (network->Jv) {
1806a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
18078675203cSHong Zhang       } else Juser = NULL;
1808bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
1809bdcb62a2SHong Zhang     }
1810bdcb62a2SHong Zhang     if (ghost) {
1811bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
1812bdcb62a2SHong Zhang     }
18131ad426b7SHong Zhang   }
1814a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
1815bdcb62a2SHong Zhang 
18161ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
18171ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1818dd6f46cdSHong Zhang 
18195f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
18205f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18215f2c45f1SShri Abhyankar }
18225f2c45f1SShri Abhyankar 
18235f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
18245f2c45f1SShri Abhyankar {
18255f2c45f1SShri Abhyankar   PetscErrorCode ierr;
18265f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
18272727e31bSShri Abhyankar   PetscInt       j;
18285f2c45f1SShri Abhyankar 
18295f2c45f1SShri Abhyankar   PetscFunctionBegin;
18308415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
183183b2e829SHong Zhang   if (network->Je) {
183283b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
183383b2e829SHong Zhang   }
183483b2e829SHong Zhang   if (network->Jv) {
1835883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
183683b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
18371ad426b7SHong Zhang   }
183813c2a604SAdrian Maldonado 
183913c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
184013c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
184113c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
184213c2a604SAdrian Maldonado   if (network->vertex.sf) {
184313c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
184413c2a604SAdrian Maldonado   }
184513c2a604SAdrian Maldonado   /* edge */
184613c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
184713c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
184813c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
184913c2a604SAdrian Maldonado   if (network->edge.sf) {
185013c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
185113c2a604SAdrian Maldonado   }
18525f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
18535f2c45f1SShri Abhyankar   network->edges = NULL;
18545f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
18555f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
185683b2e829SHong Zhang 
18572727e31bSShri Abhyankar   for(j=0; j < network->nsubnet; j++) {
18582727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].edges);CHKERRQ(ierr);
18592727e31bSShri Abhyankar     ierr = PetscFree(network->subnet[j].vertices);CHKERRQ(ierr);
18602727e31bSShri Abhyankar   }
1861e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
18625f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
18635f2c45f1SShri Abhyankar   ierr = PetscFree(network->cvalue);CHKERRQ(ierr);
18645f2c45f1SShri Abhyankar   ierr = PetscFree(network->header);CHKERRQ(ierr);
18655f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
18665f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18675f2c45f1SShri Abhyankar }
18685f2c45f1SShri Abhyankar 
18695f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
18705f2c45f1SShri Abhyankar {
18715f2c45f1SShri Abhyankar   PetscErrorCode ierr;
18725f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
18735f2c45f1SShri Abhyankar 
18745f2c45f1SShri Abhyankar   PetscFunctionBegin;
18755f2c45f1SShri Abhyankar   ierr = DMView(network->plex,viewer);CHKERRQ(ierr);
18765f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18775f2c45f1SShri Abhyankar }
18785f2c45f1SShri Abhyankar 
18795f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
18805f2c45f1SShri Abhyankar {
18815f2c45f1SShri Abhyankar   PetscErrorCode ierr;
18825f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
18835f2c45f1SShri Abhyankar 
18845f2c45f1SShri Abhyankar   PetscFunctionBegin;
18855f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
18865f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18875f2c45f1SShri Abhyankar }
18885f2c45f1SShri Abhyankar 
18895f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
18905f2c45f1SShri Abhyankar {
18915f2c45f1SShri Abhyankar   PetscErrorCode ierr;
18925f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
18935f2c45f1SShri Abhyankar 
18945f2c45f1SShri Abhyankar   PetscFunctionBegin;
18955f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
18965f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18975f2c45f1SShri Abhyankar }
18985f2c45f1SShri Abhyankar 
18995f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
19005f2c45f1SShri Abhyankar {
19015f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19025f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19035f2c45f1SShri Abhyankar 
19045f2c45f1SShri Abhyankar   PetscFunctionBegin;
19055f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
19065f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19075f2c45f1SShri Abhyankar }
19085f2c45f1SShri Abhyankar 
19095f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
19105f2c45f1SShri Abhyankar {
19115f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19125f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19135f2c45f1SShri Abhyankar 
19145f2c45f1SShri Abhyankar   PetscFunctionBegin;
19155f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
19165f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19175f2c45f1SShri Abhyankar }
1918