xref: /petsc/src/dm/impls/network/network.c (revision f2f587200c6a9182f0d00447142a2e6d14a773ff)
1af0996ceSBarry Smith #include <petsc/private/dmnetworkimpl.h>  /*I  "petscdmnetwork.h"  I*/
25f2c45f1SShri Abhyankar 
354dfd506SHong Zhang /*
454dfd506SHong Zhang   Creates the component header and value objects for a network point
554dfd506SHong Zhang */
654dfd506SHong Zhang static PetscErrorCode SetUpNetworkHeaderComponentValue(DM dm,DMNetworkComponentHeader header,DMNetworkComponentValue cvalue)
754dfd506SHong Zhang {
854dfd506SHong Zhang   PetscErrorCode ierr;
954dfd506SHong Zhang 
1054dfd506SHong Zhang   PetscFunctionBegin;
1154dfd506SHong Zhang   /* Allocate arrays for component information */
1254dfd506SHong Zhang   ierr = PetscCalloc5(header->maxcomps,&header->size,header->maxcomps,&header->key,header->maxcomps,&header->offset,header->maxcomps,&header->nvar,header->maxcomps,&header->offsetvarrel);CHKERRQ(ierr);
1354dfd506SHong Zhang   ierr = PetscCalloc1(header->maxcomps,&cvalue->data);CHKERRQ(ierr);
1454dfd506SHong Zhang 
1554dfd506SHong Zhang   /* The size of the header is the size of struct _p_DMNetworkComponentHeader. Since the struct contains PetscInt pointers we cannot use sizeof(struct). So, we need to explicitly calculate the size.
1654dfd506SHong Zhang    If the data header struct changes then this header size calculation needs to be updated. */
1754dfd506SHong Zhang   header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt);
1854dfd506SHong Zhang   header->hsize /= sizeof(DMNetworkComponentGenericDataType);
1954dfd506SHong Zhang   PetscFunctionReturn(0);
2054dfd506SHong Zhang }
2154dfd506SHong Zhang 
225f2c45f1SShri Abhyankar /*@
23556ed216SShri Abhyankar   DMNetworkGetPlex - Gets the Plex DM associated with this network DM
24556ed216SShri Abhyankar 
25556ed216SShri Abhyankar   Not collective
26556ed216SShri Abhyankar 
27556ed216SShri Abhyankar   Input Parameters:
282bf73ac6SHong Zhang . dm - the dm object
292bf73ac6SHong Zhang 
302bf73ac6SHong Zhang   Output Parameters:
312bf73ac6SHong Zhang . plexdm - the plex dm object
32556ed216SShri Abhyankar 
33556ed216SShri Abhyankar   Level: Advanced
34556ed216SShri Abhyankar 
35556ed216SShri Abhyankar .seealso: DMNetworkCreate()
36556ed216SShri Abhyankar @*/
372bf73ac6SHong Zhang PetscErrorCode DMNetworkGetPlex(DM dm,DM *plexdm)
38556ed216SShri Abhyankar {
392bf73ac6SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
40556ed216SShri Abhyankar 
41556ed216SShri Abhyankar   PetscFunctionBegin;
42556ed216SShri Abhyankar   *plexdm = network->plex;
43556ed216SShri Abhyankar   PetscFunctionReturn(0);
44556ed216SShri Abhyankar }
45556ed216SShri Abhyankar 
46556ed216SShri Abhyankar /*@
472bf73ac6SHong Zhang   DMNetworkGetNumSubNetworks - Gets the the number of subnetworks
4872c3e9f7SHong Zhang 
492bf73ac6SHong Zhang   Not collective
5072c3e9f7SHong Zhang 
51f899ff85SJose E. Roman   Input Parameter:
522bf73ac6SHong Zhang . dm - the dm object
532bf73ac6SHong Zhang 
542bf73ac6SHong Zhang   Output Parameters:
552bf73ac6SHong Zhang + nsubnet - local number of subnetworks
562bf73ac6SHong Zhang - Nsubnet - global number of subnetworks
5772c3e9f7SHong Zhang 
5897bb938eSShri Abhyankar   Level: beginner
5972c3e9f7SHong Zhang 
602bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkSetNumSubNetworks()
6172c3e9f7SHong Zhang @*/
622bf73ac6SHong Zhang PetscErrorCode DMNetworkGetNumSubNetworks(DM dm,PetscInt *nsubnet,PetscInt *Nsubnet)
6372c3e9f7SHong Zhang {
642bf73ac6SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
6572c3e9f7SHong Zhang 
6672c3e9f7SHong Zhang   PetscFunctionBegin;
672bf73ac6SHong Zhang   if (nsubnet) *nsubnet = network->nsubnet;
682bf73ac6SHong Zhang   if (Nsubnet) *Nsubnet = network->Nsubnet;
6972c3e9f7SHong Zhang   PetscFunctionReturn(0);
7072c3e9f7SHong Zhang }
7172c3e9f7SHong Zhang 
7272c3e9f7SHong Zhang /*@
732bf73ac6SHong Zhang   DMNetworkSetNumSubNetworks - Sets the number of subnetworks
745f2c45f1SShri Abhyankar 
75d083f849SBarry Smith   Collective on dm
765f2c45f1SShri Abhyankar 
775f2c45f1SShri Abhyankar   Input Parameters:
785f2c45f1SShri Abhyankar + dm - the dm object
792bf73ac6SHong Zhang . nsubnet - local number of subnetworks
802bf73ac6SHong Zhang - Nsubnet - global number of subnetworks
815f2c45f1SShri Abhyankar 
8297bb938eSShri Abhyankar    Level: beginner
831b266c99SBarry Smith 
842bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetNumSubNetworks()
855f2c45f1SShri Abhyankar @*/
862bf73ac6SHong Zhang PetscErrorCode DMNetworkSetNumSubNetworks(DM dm,PetscInt nsubnet,PetscInt Nsubnet)
875f2c45f1SShri Abhyankar {
885f2c45f1SShri Abhyankar   PetscErrorCode ierr;
895f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
905f2c45f1SShri Abhyankar 
915f2c45f1SShri Abhyankar   PetscFunctionBegin;
922bf73ac6SHong Zhang   if (network->Nsubnet != 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Network sizes alread set, cannot resize the network");
932bf73ac6SHong Zhang 
945f2c45f1SShri Abhyankar   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
952bf73ac6SHong Zhang   PetscValidLogicalCollectiveInt(dm,nsubnet,2);
962bf73ac6SHong Zhang   PetscValidLogicalCollectiveInt(dm,Nsubnet,3);
977765340cSHong Zhang 
982bf73ac6SHong Zhang   if (Nsubnet == PETSC_DECIDE) {
992bf73ac6SHong Zhang     if (nsubnet < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of local subnetworks %D cannot be less than 0",nsubnet);
100820f2d46SBarry Smith     ierr = MPIU_Allreduce(&nsubnet,&Nsubnet,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
101caf410d2SHong Zhang   }
1022bf73ac6SHong Zhang   if (Nsubnet < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Number of global subnetworks %D cannot be less than 1",Nsubnet);
103caf410d2SHong Zhang 
1042bf73ac6SHong Zhang   network->Nsubnet  = Nsubnet;
1052bf73ac6SHong Zhang   network->nsubnet  = 0;       /* initia value; will be determind by DMNetworkAddSubnetwork() */
1062bf73ac6SHong Zhang   ierr = PetscCalloc1(Nsubnet,&network->subnet);CHKERRQ(ierr);
107caf410d2SHong Zhang 
1082bf73ac6SHong Zhang   /* num of shared vertices */
1092bf73ac6SHong Zhang   network->nsvtx = 0;
1102bf73ac6SHong Zhang   network->Nsvtx = 0;
1117765340cSHong Zhang   PetscFunctionReturn(0);
1127765340cSHong Zhang }
1137765340cSHong Zhang 
1145f2c45f1SShri Abhyankar /*@
1152bf73ac6SHong Zhang   DMNetworkAddSubnetwork - Add a subnetwork
1165f2c45f1SShri Abhyankar 
1172bf73ac6SHong Zhang   Collective on dm
1185f2c45f1SShri Abhyankar 
1195f2c45f1SShri Abhyankar   Input Parameters:
120e3e68989SHong Zhang + dm - the dm object
1212bf73ac6SHong Zhang . name - name of the subnetwork
1222bf73ac6SHong Zhang . ne - number of local edges of this subnetwork
1238d1cd658SBarry Smith - edgelist - list of edges for this subnetwork, this is a one dimensional array with pairs of entries being the two vertices (in global numbering of the vertices) of each edge,
1248d1cd658SBarry Smith $            [first vertex of first edge, second vertex of first edge, first vertex of second edge, second vertex of second edge, etc]
1252bf73ac6SHong Zhang 
1262bf73ac6SHong Zhang   Output Parameters:
1272bf73ac6SHong Zhang . netnum - global index of the subnetwork
1285f2c45f1SShri Abhyankar 
1295f2c45f1SShri Abhyankar   Notes:
1305f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1312bf73ac6SHong Zhang   not be destroyed before the call to DMNetworkLayoutSetUp()
1325f2c45f1SShri Abhyankar 
1338d1cd658SBarry Smith   A network can comprise of a single subnetwork OR multiple subnetworks. For a single subnetwork, the subnetwork can be read either in serial or parallel. For a multiple subnetworks,
1348d1cd658SBarry Smith   each subnetwork topology needs to be set on a unique rank and the communicator size needs to be at least equal to the number of subnetworks.
135f11a936eSBarry Smith 
13697bb938eSShri Abhyankar   Level: beginner
1375f2c45f1SShri Abhyankar 
138e3e68989SHong Zhang   Example usage:
139f11a936eSBarry Smith   Consider the following networks:
140f11a936eSBarry Smith   1) A sigle subnetwork:
141e3e68989SHong Zhang .vb
142f11a936eSBarry Smith  network 0:
143f11a936eSBarry Smith  rank[0]:
144f11a936eSBarry Smith    v0 --> v2; v1 --> v2
145f11a936eSBarry Smith  rank[1]:
146f11a936eSBarry Smith    v3 --> v5; v4 --> v5
147e3e68989SHong Zhang .ve
148e3e68989SHong Zhang 
149e3e68989SHong Zhang  The resulting input
150f11a936eSBarry Smith  network 0:
151f11a936eSBarry Smith  rank[0]:
152f11a936eSBarry Smith    ne = 2
153f11a936eSBarry Smith    edgelist = [0 2 | 1 2]
154f11a936eSBarry Smith  rank[1]:
155f11a936eSBarry Smith    ne = 2
156f11a936eSBarry Smith    edgelist = [3 5 | 4 5]
157f11a936eSBarry Smith 
158f11a936eSBarry Smith   2) Two subnetworks:
159f11a936eSBarry Smith .vb
160f11a936eSBarry Smith  subnetwork 0:
161f11a936eSBarry Smith  rank[0]:
162f11a936eSBarry Smith    v0 --> v2; v2 --> v1; v1 --> v3;
163f11a936eSBarry Smith  subnetwork 1:
164f11a936eSBarry Smith  rank[1]:
165f11a936eSBarry Smith    v0 --> v3; v3 --> v2; v2 --> v1;
166f11a936eSBarry Smith .ve
167f11a936eSBarry Smith 
168f11a936eSBarry Smith  The resulting input
169f11a936eSBarry Smith  subnetwork 0:
170f11a936eSBarry Smith  rank[0]:
171f11a936eSBarry Smith    ne = 3
172f11a936eSBarry Smith    edgelist = [0 2 | 2 1 | 1 3]
173f11a936eSBarry Smith  rank[1]:
174f11a936eSBarry Smith    ne = 0
175f11a936eSBarry Smith    edgelist = NULL
176f11a936eSBarry Smith 
177f11a936eSBarry Smith  subnetwork 1:
178f11a936eSBarry Smith  rank[0]:
179f11a936eSBarry Smith    ne = 0
180f11a936eSBarry Smith    edgelist = NULL
181f11a936eSBarry Smith  rank[1]:
182f11a936eSBarry Smith    edgelist = [0 3 | 3 2 | 2 1]
183e3e68989SHong Zhang 
1842bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkSetNumSubnetworks()
1855f2c45f1SShri Abhyankar @*/
186f11a936eSBarry Smith PetscErrorCode DMNetworkAddSubnetwork(DM dm,const char* name,PetscInt ne,PetscInt edgelist[],PetscInt *netnum)
1875f2c45f1SShri Abhyankar {
1882bf73ac6SHong Zhang   PetscErrorCode ierr;
1895f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
190f11a936eSBarry Smith   PetscInt       i,Nedge,j,Nvtx,nvtx;
191f11a936eSBarry Smith   PetscBT        table;
1925f2c45f1SShri Abhyankar 
1935f2c45f1SShri Abhyankar   PetscFunctionBegin;
1948d1cd658SBarry Smith   for (i=0; i<ne; i++) {
1958d1cd658SBarry Smith     if (edgelist[2*i] == edgelist[2*i+1]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Edge %D has the same vertex %D at each endpoint",i,edgelist[2*i]);
1968d1cd658SBarry Smith   }
197f11a936eSBarry Smith   /* Get global total Nvtx = max(edgelist[])+1 for this subnet */
198f11a936eSBarry Smith   nvtx = -1; i = 0;
199f11a936eSBarry Smith   for (j=0; j<ne; j++) {
200f11a936eSBarry Smith     nvtx = PetscMax(nvtx, edgelist[i]); i++;
201f11a936eSBarry Smith     nvtx = PetscMax(nvtx, edgelist[i]); i++;
202f11a936eSBarry Smith   }
203f11a936eSBarry Smith   nvtx++;
204f11a936eSBarry Smith   ierr = MPIU_Allreduce(&nvtx,&Nvtx,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
205f11a936eSBarry Smith 
206f11a936eSBarry Smith   /* Get local nvtx for this subnet */
207f11a936eSBarry Smith   ierr = PetscBTCreate(Nvtx,&table);CHKERRQ(ierr);
208f11a936eSBarry Smith   ierr = PetscBTMemzero(Nvtx,table);CHKERRQ(ierr);
209f11a936eSBarry Smith   i = 0;
210f11a936eSBarry Smith   for (j=0; j<ne; j++) {
211f11a936eSBarry Smith     ierr = PetscBTSet(table,edgelist[i]);CHKERRQ(ierr);
212f11a936eSBarry Smith     i++;
213f11a936eSBarry Smith     ierr = PetscBTSet(table,edgelist[i]);CHKERRQ(ierr);
214f11a936eSBarry Smith     i++;
215f11a936eSBarry Smith   }
216f11a936eSBarry Smith   nvtx = 0;
217f11a936eSBarry Smith   for (j=0; j<Nvtx; j++) {
218f11a936eSBarry Smith     if (PetscBTLookup(table,j)) nvtx++;
219f11a936eSBarry Smith   }
220f11a936eSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
221f11a936eSBarry Smith 
222f11a936eSBarry Smith   /* Get global total Nedge for this subnet */
223f11a936eSBarry Smith   ierr = MPIU_Allreduce(&ne,&Nedge,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
224f11a936eSBarry Smith 
225f11a936eSBarry Smith   i = network->nsubnet;
2262bf73ac6SHong Zhang   if (name) {
2272bf73ac6SHong Zhang     ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr);
228e3e68989SHong Zhang   }
229f11a936eSBarry Smith   network->subnet[i].nvtx     = nvtx; /* include ghost vertices */
2302bf73ac6SHong Zhang   network->subnet[i].nedge    = ne;
2312bf73ac6SHong Zhang   network->subnet[i].edgelist = edgelist;
232f11a936eSBarry Smith   network->subnet[i].Nvtx     = Nvtx;
233f11a936eSBarry Smith   network->subnet[i].Nedge    = Nedge;
2342bf73ac6SHong Zhang 
2352bf73ac6SHong Zhang   /* ----------------------------------------------------------
2362bf73ac6SHong Zhang    p=v or e;
2372bf73ac6SHong Zhang    subnet[0].pStart   = 0
2382bf73ac6SHong Zhang    subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i])
2392bf73ac6SHong Zhang    ----------------------------------------------------------------------- */
2402bf73ac6SHong Zhang   /* GLOBAL subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */
2412bf73ac6SHong Zhang   network->subnet[i].vStart = network->NVertices;
2422bf73ac6SHong Zhang   network->subnet[i].vEnd   = network->subnet[i].vStart + network->subnet[i].Nvtx; /* global vEnd of subnet[i] */
2432bf73ac6SHong Zhang 
244f11a936eSBarry Smith   network->nVertices += nvtx; /* include ghost vertices */
2452bf73ac6SHong Zhang   network->NVertices += network->subnet[i].Nvtx;
2462bf73ac6SHong Zhang 
2472bf73ac6SHong Zhang   /* LOCAL subnet[].eStart and eEnd, used by DMNetworkLayoutSetUp() */
2482bf73ac6SHong Zhang   network->subnet[i].eStart = network->nEdges;
2492bf73ac6SHong Zhang   network->subnet[i].eEnd   = network->subnet[i].eStart + ne;
2502bf73ac6SHong Zhang   network->nEdges += ne;
2512bf73ac6SHong Zhang   network->NEdges += network->subnet[i].Nedge;
2522bf73ac6SHong Zhang 
2532bf73ac6SHong Zhang   ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr);
2542bf73ac6SHong Zhang   if (netnum) *netnum = network->nsubnet;
2552bf73ac6SHong Zhang   network->nsubnet++;
2562bf73ac6SHong Zhang   PetscFunctionReturn(0);
2572bf73ac6SHong Zhang }
2582bf73ac6SHong Zhang 
2592bf73ac6SHong Zhang /*
2602bf73ac6SHong Zhang   SetUp a single svtx struct. See SVtx defined in dmnetworkimpl.h
2612bf73ac6SHong Zhang   Set gidx and type if input v=(net,idx) is a from_vertex;
2622bf73ac6SHong Zhang   Get gid, type and index in the svtx array if input v=(net,idx) is a to_vertex.
2632bf73ac6SHong Zhang 
2642bf73ac6SHong Zhang   Input:  Nsvtx, svtx, net, idx, gidx
2652bf73ac6SHong Zhang   Output: gidx, svtype, svtx_idx
2662bf73ac6SHong Zhang  */
2672bf73ac6SHong Zhang static PetscErrorCode SVtxSetUp(PetscInt Nsvtx,SVtx *svtx,PetscInt net,PetscInt idx,PetscInt *gidx,SVtxType *svtype,PetscInt *svtx_idx)
2682bf73ac6SHong Zhang {
2692bf73ac6SHong Zhang   PetscInt i,j,*svto;
2702bf73ac6SHong Zhang   SVtxType vtype;
2712bf73ac6SHong Zhang 
2722bf73ac6SHong Zhang   PetscFunctionBegin;
2732bf73ac6SHong Zhang   if (!Nsvtx) PetscFunctionReturn(0);
2742bf73ac6SHong Zhang 
2752bf73ac6SHong Zhang   vtype = SVNONE;
2762bf73ac6SHong Zhang   for (i=0; i<Nsvtx; i++) {
2772bf73ac6SHong Zhang     if (net == svtx[i].sv[0] && idx == svtx[i].sv[1]) {
2782bf73ac6SHong Zhang       /* (1) input vertex net.idx is a shared from_vertex, set its global index and output its svtype */
2792bf73ac6SHong Zhang       svtx[i].gidx = *gidx; /* set gidx */
2802bf73ac6SHong Zhang       vtype        = SVFROM;
2812bf73ac6SHong Zhang     } else { /* loop over svtx[i].n */
2822bf73ac6SHong Zhang       for (j=1; j<svtx[i].n; j++) {
2832bf73ac6SHong Zhang         svto = svtx[i].sv + 2*j;
2842bf73ac6SHong Zhang         if (net == svto[0] && idx == svto[1]) {
2852bf73ac6SHong Zhang           /* input vertex net.idx is a shared to_vertex, output its global index and its svtype */
2862bf73ac6SHong Zhang           *gidx = svtx[i].gidx; /* output gidx for to_vertex */
2872bf73ac6SHong Zhang           vtype = SVTO;
2882bf73ac6SHong Zhang         }
2892bf73ac6SHong Zhang       }
2902bf73ac6SHong Zhang     }
2912bf73ac6SHong Zhang     if (vtype != SVNONE) break;
2922bf73ac6SHong Zhang   }
2932bf73ac6SHong Zhang   if (svtype)   *svtype   = vtype;
2942bf73ac6SHong Zhang   if (svtx_idx) *svtx_idx = i;
2952bf73ac6SHong Zhang   PetscFunctionReturn(0);
2962bf73ac6SHong Zhang }
2972bf73ac6SHong Zhang 
2982bf73ac6SHong Zhang /*
2992bf73ac6SHong Zhang  Add a new shared vertex sv=(net,idx) to table svtas[ita]
3002bf73ac6SHong Zhang */
3012bf73ac6SHong Zhang static PetscErrorCode TableAddSVtx(PetscTable *svtas,PetscInt ita,PetscInt* tdata,PetscInt *sv_wk,PetscInt *ii,PetscInt *sedgelist,PetscInt k,DM_Network *network,PetscInt **ta2sv)
3022bf73ac6SHong Zhang {
3032bf73ac6SHong Zhang   PetscInt       net,idx,gidx,i=*ii;
3042bf73ac6SHong Zhang   PetscErrorCode ierr;
3052bf73ac6SHong Zhang 
3062bf73ac6SHong Zhang   PetscFunctionBegin;
3072bf73ac6SHong Zhang   net = sv_wk[2*i]   = sedgelist[k];
3082bf73ac6SHong Zhang   idx = sv_wk[2*i+1] = sedgelist[k+1];
3092bf73ac6SHong Zhang   gidx = network->subnet[net].vStart + idx;
3102bf73ac6SHong Zhang   ierr = PetscTableAdd(svtas[ita],gidx+1,tdata[ita]+1,INSERT_VALUES);CHKERRQ(ierr);
3112bf73ac6SHong Zhang   *(ta2sv[ita] + tdata[ita]) = i; /* maps tdata to index of sv_wk; sv_wk keeps (net,idx) info */
3122bf73ac6SHong Zhang   tdata[ita]++; (*ii)++;
3132bf73ac6SHong Zhang   PetscFunctionReturn(0);
3142bf73ac6SHong Zhang }
3152bf73ac6SHong Zhang 
3162bf73ac6SHong Zhang /*
3172bf73ac6SHong Zhang   Create an array of shared vertices. See SVtx and SVtxType in dmnetworkimpl.h
3182bf73ac6SHong Zhang 
3192bf73ac6SHong Zhang   Input:  dm, Nsedgelist, sedgelist
3202bf73ac6SHong Zhang   Output: Nsvtx,svtx
3212bf73ac6SHong Zhang 
3222bf73ac6SHong Zhang   Note: Output svtx is organized as
3232bf73ac6SHong Zhang         sv(net[0],idx[0]) --> sv(net[1],idx[1])
3242bf73ac6SHong Zhang                           --> sv(net[1],idx[1])
3252bf73ac6SHong Zhang                           ...
3262bf73ac6SHong Zhang                           --> sv(net[n-1],idx[n-1])
3272bf73ac6SHong Zhang         and net[0] < net[1] < ... < net[n-1]
3282bf73ac6SHong Zhang         where sv[0] has SVFROM type, sv[i], i>0, has SVTO type.
3292bf73ac6SHong Zhang  */
3302bf73ac6SHong Zhang static PetscErrorCode SVtxCreate(DM dm,PetscInt Nsedgelist,PetscInt *sedgelist,PetscInt *Nsvtx,SVtx **svtx)
3312bf73ac6SHong Zhang {
3322bf73ac6SHong Zhang   PetscErrorCode ierr;
3332bf73ac6SHong Zhang   SVtx           *sedges = NULL;
3342bf73ac6SHong Zhang   PetscInt       *sv,k,j,nsv,*tdata,**ta2sv;
3352bf73ac6SHong Zhang   PetscTable     *svtas;
3362bf73ac6SHong Zhang   PetscInt       gidx,net,idx,i,nta,ita,idx_from,idx_to,n,*sv_wk;
3372bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
3382bf73ac6SHong Zhang   PetscTablePosition ppos;
3392bf73ac6SHong Zhang 
3402bf73ac6SHong Zhang   PetscFunctionBegin;
3412bf73ac6SHong Zhang   /* (1) Crete ctables svtas */
3422bf73ac6SHong Zhang   ierr = PetscCalloc4(Nsedgelist,&svtas,Nsedgelist,&tdata,4*Nsedgelist,&sv_wk,2*Nsedgelist,&ta2sv);CHKERRQ(ierr);
3432bf73ac6SHong Zhang 
3442bf73ac6SHong Zhang   j   = 0;   /* sedgelist counter */
3452bf73ac6SHong Zhang   k   = 0;   /* sedgelist vertex counter j = 4*k */
3462bf73ac6SHong Zhang   i   = 0;   /* sv_wk (vertices added to the ctables) counter */
3472bf73ac6SHong Zhang   nta = 0;   /* num of sv tables created */
3482bf73ac6SHong Zhang 
3492bf73ac6SHong Zhang   /* for j=0 */
3502bf73ac6SHong Zhang   ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr);
3512bf73ac6SHong Zhang   ierr = PetscMalloc1(2*Nsedgelist,&ta2sv[nta]);CHKERRQ(ierr);
3522bf73ac6SHong Zhang 
3532bf73ac6SHong Zhang   ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
3542bf73ac6SHong Zhang   ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
3552bf73ac6SHong Zhang   nta++; k += 4;
3562bf73ac6SHong Zhang 
3572bf73ac6SHong Zhang   for (j = 1; j < Nsedgelist; j++) {
3582bf73ac6SHong Zhang     for (ita = 0; ita < nta; ita++) {
3592bf73ac6SHong Zhang       /* vfrom */
3602bf73ac6SHong Zhang       net = sedgelist[k]; idx = sedgelist[k+1];
3612bf73ac6SHong Zhang       gidx = network->subnet[net].vStart + idx; /* global index of the vertex net.idx before merging shared vertices */
3622bf73ac6SHong Zhang       ierr = PetscTableFind(svtas[ita],gidx+1,&idx_from);CHKERRQ(ierr);
3632bf73ac6SHong Zhang 
3642bf73ac6SHong Zhang       /* vto */
3652bf73ac6SHong Zhang       net = sedgelist[k+2]; idx = sedgelist[k+3];
3662bf73ac6SHong Zhang       gidx = network->subnet[net].vStart + idx;
3672bf73ac6SHong Zhang       ierr = PetscTableFind(svtas[ita],gidx+1,&idx_to);CHKERRQ(ierr);
3682bf73ac6SHong Zhang 
3692bf73ac6SHong Zhang       if (idx_from || idx_to) { /* vfrom or vto is on table svtas[ita] */
3702bf73ac6SHong Zhang         idx_from--; idx_to--;
3712bf73ac6SHong Zhang         if (idx_from < 0) { /* vto is on svtas[ita] */
3722bf73ac6SHong Zhang           ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
3732bf73ac6SHong Zhang           break;
3742bf73ac6SHong Zhang         } else if (idx_to < 0) {
3752bf73ac6SHong Zhang           ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
3762bf73ac6SHong Zhang           break;
3772bf73ac6SHong Zhang         }
3782bf73ac6SHong Zhang       }
3792bf73ac6SHong Zhang     }
3802bf73ac6SHong Zhang 
3812bf73ac6SHong Zhang     if (ita == nta) {
3822bf73ac6SHong Zhang       ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr);
3832bf73ac6SHong Zhang       ierr = PetscMalloc1(2*Nsedgelist, &ta2sv[nta]);CHKERRQ(ierr);
3842bf73ac6SHong Zhang 
3852bf73ac6SHong Zhang       ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
3862bf73ac6SHong Zhang       ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
3872bf73ac6SHong Zhang       nta++;
3882bf73ac6SHong Zhang     }
3892bf73ac6SHong Zhang     k += 4;
3902bf73ac6SHong Zhang   }
3912bf73ac6SHong Zhang 
3922bf73ac6SHong Zhang   /* (2) Construct sedges from ctable
3932bf73ac6SHong Zhang      sedges: edges connect vertex sv[0]=(net[0],idx[0]) to vertices sv[k], k=1,...,n-1;
3944f5c2772SJose E. Roman      net[k], k=0, ...,n-1, are in ascending order */
3952bf73ac6SHong Zhang   ierr = PetscMalloc1(nta,&sedges);CHKERRQ(ierr);
3962bf73ac6SHong Zhang   for (nsv = 0; nsv < nta; nsv++) {
3974f5c2772SJose E. Roman     /* for a single svtx, put shared vertices in ascending order of gidx */
3984f5c2772SJose E. Roman     ierr = PetscTableGetCount(svtas[nsv],&n);CHKERRQ(ierr);
3992bf73ac6SHong Zhang     ierr = PetscCalloc1(2*n,&sv);CHKERRQ(ierr);
4002bf73ac6SHong Zhang     sedges[nsv].sv   = sv;
4012bf73ac6SHong Zhang     sedges[nsv].n    = n;
4022bf73ac6SHong Zhang     sedges[nsv].gidx = -1; /* initialization */
4032bf73ac6SHong Zhang 
4042bf73ac6SHong Zhang     ierr = PetscTableGetHeadPosition(svtas[nsv],&ppos);CHKERRQ(ierr);
4054f5c2772SJose E. Roman     for (k=0; k<n; k++) { /* gidx is sorted in ascending order */
4062bf73ac6SHong Zhang       ierr = PetscTableGetNext(svtas[nsv],&ppos,&gidx,&i);CHKERRQ(ierr);
4072bf73ac6SHong Zhang       gidx--; i--;
4082bf73ac6SHong Zhang 
4092bf73ac6SHong Zhang       j = ta2sv[nsv][i]; /* maps i to index of sv_wk */
4102bf73ac6SHong Zhang       sv[2*k]   = sv_wk[2*j];
4112bf73ac6SHong Zhang       sv[2*k+1] = sv_wk[2*j + 1];
4122bf73ac6SHong Zhang     }
4132bf73ac6SHong Zhang   }
4142bf73ac6SHong Zhang 
4152bf73ac6SHong Zhang   for (j=0; j<nta; j++) {
4162bf73ac6SHong Zhang     ierr = PetscTableDestroy(&svtas[j]);CHKERRQ(ierr);
4172bf73ac6SHong Zhang     ierr = PetscFree(ta2sv[j]);CHKERRQ(ierr);
4182bf73ac6SHong Zhang   }
4192bf73ac6SHong Zhang   ierr = PetscFree4(svtas,tdata,sv_wk,ta2sv);CHKERRQ(ierr);
4202bf73ac6SHong Zhang 
4212bf73ac6SHong Zhang   *Nsvtx = nta;
4222bf73ac6SHong Zhang   *svtx  = sedges;
4232bf73ac6SHong Zhang   PetscFunctionReturn(0);
4242bf73ac6SHong Zhang }
4252bf73ac6SHong Zhang 
4262bf73ac6SHong Zhang static PetscErrorCode DMNetworkLayoutSetUp_Coupling(DM dm)
4272bf73ac6SHong Zhang {
4282bf73ac6SHong Zhang   PetscErrorCode ierr;
4292bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
430f11a936eSBarry Smith   PetscInt       i,j,ctr,np,*edges,*subnetvtx,*subnetedge,vStart;
4312bf73ac6SHong Zhang   PetscInt       k,*vidxlTog,Nsv=0,Nsubnet=network->Nsubnet;
4322bf73ac6SHong Zhang   PetscInt       *sedgelist=network->sedgelist;
4332bf73ac6SHong Zhang   const PetscInt *cone;
4342bf73ac6SHong Zhang   MPI_Comm       comm;
4352bf73ac6SHong Zhang   PetscMPIInt    size,rank,*recvcounts=NULL,*displs=NULL;
4362bf73ac6SHong Zhang   PetscInt       net,idx,gidx,nmerged,e,v,vfrom,vto,*vrange,*eowners,gidx_from,net_from,sv_idx;
4372bf73ac6SHong Zhang   SVtxType       svtype = SVNONE;
4382bf73ac6SHong Zhang   SVtx           *svtx=NULL;
4392bf73ac6SHong Zhang   PetscSection   sectiong;
4402bf73ac6SHong Zhang 
4412bf73ac6SHong Zhang   PetscFunctionBegin;
4422bf73ac6SHong Zhang   /* This implementation requires user input each subnet by a single processor, thus subnet[net].nvtx=subnet[net].Nvtx */
4432bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
4442bf73ac6SHong Zhang     if (network->subnet[net].nvtx && network->subnet[net].nvtx != network->subnet[net].Nvtx) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"subnetwork %D local num of vertices %D != %D global num",net,network->subnet[net].nvtx,network->subnet[net].Nvtx);
4452bf73ac6SHong Zhang   }
4462bf73ac6SHong Zhang 
4472bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
44855b25c41SPierre Jolivet   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
44955b25c41SPierre Jolivet   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
4502bf73ac6SHong Zhang 
4512bf73ac6SHong Zhang   /* (1) Create svtx[] from sedgelist */
4522bf73ac6SHong Zhang   /* -------------------------------- */
4532bf73ac6SHong Zhang   /* Nsv: global number of SVtx; svtx: shared vertices, see SVtx in dmnetworkimpl.h */
4542bf73ac6SHong Zhang   ierr = SVtxCreate(dm,network->Nsvtx,sedgelist,&Nsv,&svtx);CHKERRQ(ierr);
4552bf73ac6SHong Zhang 
4562bf73ac6SHong Zhang   /* (2) Setup svtx; Shared vto vertices are merged to their vfrom vertex with same global vetex index (gidx) */
4572bf73ac6SHong Zhang   /* -------------------------------------------------------------------------------------------------------- */
4582bf73ac6SHong Zhang   /* (2.1) compute vrage[rank]: global index of 1st local vertex in proc[rank] */
4592bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
4602bf73ac6SHong Zhang   for (i=0; i<size; i++) {displs[i] = i; recvcounts[i] = 1;}
4612bf73ac6SHong Zhang 
4622bf73ac6SHong Zhang   vrange[0] = 0;
4632bf73ac6SHong Zhang   ierr = MPI_Allgatherv(&network->nVertices,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
4642bf73ac6SHong Zhang   for (i=2; i<size+1; i++) {
4652bf73ac6SHong Zhang     vrange[i] += vrange[i-1];
4662bf73ac6SHong Zhang   }
4672bf73ac6SHong Zhang 
4682bf73ac6SHong Zhang   /* (2.2) Create vidxlTog: maps UN-MERGED local vertex index i to global index gidx (plex, excluding ghost vertices) */
4692bf73ac6SHong Zhang   ierr = PetscMalloc1(network->nVertices,&vidxlTog);CHKERRQ(ierr);
4702bf73ac6SHong Zhang   i = 0; gidx = 0;
4712bf73ac6SHong Zhang   nmerged = 0; /* local num of merged vertices */
4722bf73ac6SHong Zhang   network->nsvtx = 0;
4732bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
4742bf73ac6SHong Zhang     for (idx=0; idx<network->subnet[net].Nvtx; idx++) {
4752bf73ac6SHong Zhang       gidx_from = gidx;
4762bf73ac6SHong Zhang       sv_idx    = -1;
4772bf73ac6SHong Zhang 
4782bf73ac6SHong Zhang       ierr = SVtxSetUp(Nsv,svtx,net,idx,&gidx_from,&svtype,&sv_idx);CHKERRQ(ierr);
4792bf73ac6SHong Zhang       if (svtype == SVTO) {
4802bf73ac6SHong Zhang         if (network->subnet[net].nvtx) {/* this proc owns sv_to */
4812bf73ac6SHong Zhang           net_from = svtx[sv_idx].sv[0]; /* subnet num of its shared vertex */
4822bf73ac6SHong Zhang           if (network->subnet[net_from].nvtx == 0) {
4832bf73ac6SHong Zhang             /* this proc does not own v_from, thus a new local coupling vertex */
4842bf73ac6SHong Zhang             network->nsvtx++;
4852bf73ac6SHong Zhang           }
4862bf73ac6SHong Zhang           vidxlTog[i++] = gidx_from;
4872bf73ac6SHong Zhang           nmerged++; /* a coupling vertex -- merged */
4882bf73ac6SHong Zhang         }
4892bf73ac6SHong Zhang       } else {
4902bf73ac6SHong Zhang         if (svtype == SVFROM) {
4912bf73ac6SHong Zhang           if (network->subnet[net].nvtx) {
4922bf73ac6SHong Zhang             /* this proc owns this v_from, a new local coupling vertex */
4932bf73ac6SHong Zhang             network->nsvtx++;
4942bf73ac6SHong Zhang           }
4952bf73ac6SHong Zhang         }
4962bf73ac6SHong Zhang         if (network->subnet[net].nvtx) vidxlTog[i++] = gidx;
4972bf73ac6SHong Zhang         gidx++;
4982bf73ac6SHong Zhang       }
4992bf73ac6SHong Zhang     }
5002bf73ac6SHong Zhang   }
5012bf73ac6SHong Zhang #if defined(PETSC_USE_DEBUG)
5022bf73ac6SHong Zhang   if (i != network->nVertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"%D != %D nVertices",i,network->nVertices);
5032bf73ac6SHong Zhang #endif
5042bf73ac6SHong Zhang 
5052bf73ac6SHong Zhang   /* (2.3) Setup svtable for querry shared vertices */
5062bf73ac6SHong Zhang   for (v=0; v<Nsv; v++) {
5072bf73ac6SHong Zhang     gidx = svtx[v].gidx;
5082bf73ac6SHong Zhang     ierr = PetscTableAdd(network->svtable,gidx+1,v+1,INSERT_VALUES);CHKERRQ(ierr);
5092bf73ac6SHong Zhang   }
5102bf73ac6SHong Zhang 
5112bf73ac6SHong Zhang   /* (2.4) Shared vertices in the subnetworks are merged, update global NVertices: np = sum(local nmerged) */
5122bf73ac6SHong Zhang   ierr = MPI_Allreduce(&nmerged,&np,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
5132bf73ac6SHong Zhang   network->NVertices -= np;
5142bf73ac6SHong Zhang 
5152bf73ac6SHong Zhang   ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr);
5162bf73ac6SHong Zhang 
5172bf73ac6SHong Zhang   ctr = 0;
5182bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
5192bf73ac6SHong Zhang     for (j = 0; j < network->subnet[net].nedge; j++) {
5202bf73ac6SHong Zhang       /* vfrom: */
5212bf73ac6SHong Zhang       i = network->subnet[net].edgelist[2*j] + (network->subnet[net].vStart - vrange[rank]);
5222bf73ac6SHong Zhang       edges[2*ctr] = vidxlTog[i];
5232bf73ac6SHong Zhang 
5242bf73ac6SHong Zhang       /* vto */
5252bf73ac6SHong Zhang       i = network->subnet[net].edgelist[2*j+1] + (network->subnet[net].vStart - vrange[rank]);
5262bf73ac6SHong Zhang       edges[2*ctr+1] = vidxlTog[i];
5272bf73ac6SHong Zhang       ctr++;
5282bf73ac6SHong Zhang     }
5292bf73ac6SHong Zhang   }
5302bf73ac6SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
5312bf73ac6SHong Zhang   ierr = PetscFree(vidxlTog);CHKERRQ(ierr);
5322bf73ac6SHong Zhang 
5332bf73ac6SHong Zhang   /* (3) Create network->plex */
5342bf73ac6SHong Zhang   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
5352bf73ac6SHong Zhang   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
5362bf73ac6SHong Zhang   ierr = DMSetDimension(network->plex,1);CHKERRQ(ierr);
5372bf73ac6SHong Zhang   if (size == 1) {
5382bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices-nmerged,2,edges);CHKERRQ(ierr);
5392bf73ac6SHong Zhang   } else {
5402bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices-nmerged,PETSC_DECIDE,2,edges,NULL);CHKERRQ(ierr);
5412bf73ac6SHong Zhang   }
5422bf73ac6SHong Zhang 
5432bf73ac6SHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
5442bf73ac6SHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
5452bf73ac6SHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
5462bf73ac6SHong Zhang   vStart = network->vStart;
5472bf73ac6SHong Zhang 
5482bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
5492bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
5502bf73ac6SHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
5512bf73ac6SHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
5522bf73ac6SHong Zhang 
5532bf73ac6SHong Zhang   np = network->pEnd - network->pStart;
5542bf73ac6SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
55554dfd506SHong Zhang   for (i=0; i<np; i++) {
55654dfd506SHong Zhang     network->header[i].maxcomps = 1;
55754dfd506SHong Zhang     ierr = SetUpNetworkHeaderComponentValue(dm,&network->header[i],&network->cvalue[i]);CHKERRQ(ierr);
55854dfd506SHong Zhang   }
5592bf73ac6SHong Zhang 
560f11a936eSBarry Smith   /* (4) Create edge and vertex arrays for the subnetworks */
561f11a936eSBarry Smith   ierr = PetscCalloc2(network->nEdges,&subnetedge,network->nVertices+network->nsvtx,&subnetvtx);CHKERRQ(ierr); /* Maps local edge/vertex to local subnetwork's edge/vertex */
562f11a936eSBarry Smith   network->subnetedge = subnetedge;
563f11a936eSBarry Smith   network->subnetvtx  = subnetvtx;
5642bf73ac6SHong Zhang   for (j=0; j < Nsubnet; j++) {
565f11a936eSBarry Smith     network->subnet[j].edges = subnetedge;
566f11a936eSBarry Smith     subnetedge              += network->subnet[j].nedge;
567f11a936eSBarry Smith 
5682bf73ac6SHong Zhang     network->subnet[j].vertices = subnetvtx;
5692bf73ac6SHong Zhang     subnetvtx                  += network->subnet[j].nvtx;
5702bf73ac6SHong Zhang   }
5712bf73ac6SHong Zhang   network->svertices = subnetvtx;
5722bf73ac6SHong Zhang 
5732bf73ac6SHong Zhang   /* Get edge ownership */
574f11a936eSBarry Smith   ierr = PetscMalloc1(size+1,&eowners);CHKERRQ(ierr);
5752bf73ac6SHong Zhang   np = network->eEnd - network->eStart; /* num of local edges */
5762bf73ac6SHong Zhang   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr);
5772bf73ac6SHong Zhang   eowners[0] = 0;
5782bf73ac6SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
5792bf73ac6SHong Zhang 
580f11a936eSBarry Smith   /* Setup edge and vertex arrays for subnetworks */
5812bf73ac6SHong Zhang   e = 0;
5822bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
583f11a936eSBarry Smith     ctr = 0;
5842bf73ac6SHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
5852bf73ac6SHong Zhang       /* edge e */
5862bf73ac6SHong Zhang       network->header[e].index    = e + eowners[rank]; /* Global edge index */
5872bf73ac6SHong Zhang       network->header[e].subnetid = i;                 /* Subnetwork id */
5882bf73ac6SHong Zhang       network->subnet[i].edges[j] = e;
5892bf73ac6SHong Zhang       network->header[e].ndata           = 0;
5902bf73ac6SHong Zhang       network->header[e].offset[0]       = 0;
5912bf73ac6SHong Zhang       network->header[e].offsetvarrel[0] = 0;
59254dfd506SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,e,network->header[e].hsize);CHKERRQ(ierr);
5932bf73ac6SHong Zhang 
5942bf73ac6SHong Zhang       /* connected vertices */
5952bf73ac6SHong Zhang       ierr = DMPlexGetCone(network->plex,e,&cone);CHKERRQ(ierr);
5962bf73ac6SHong Zhang 
5972bf73ac6SHong Zhang       /* vertex cone[0] */
598f11a936eSBarry Smith       v = cone[0];
599f11a936eSBarry Smith       network->header[v].index    = edges[2*e];   /* Global vertex index */
600f11a936eSBarry Smith       network->header[v].subnetid = i;            /* Subnetwork id */
601f11a936eSBarry Smith       vfrom = network->subnet[i].edgelist[2*ctr];
602f11a936eSBarry Smith       network->subnet[i].vertices[vfrom] = v;     /* user's subnet[].dix = petsc's v */
6032bf73ac6SHong Zhang 
6042bf73ac6SHong Zhang       /* vertex cone[1] */
605f11a936eSBarry Smith       v = cone[1];
606f11a936eSBarry Smith       network->header[v].index    = edges[2*e+1]; /* Global vertex index */
607f11a936eSBarry Smith       network->header[v].subnetid = i;
608f11a936eSBarry Smith       vto = network->subnet[i].edgelist[2*ctr+1];
609f11a936eSBarry Smith       network->subnet[i].vertices[vto]= v;
6102bf73ac6SHong Zhang 
611f11a936eSBarry Smith       e++; ctr++;
6122bf73ac6SHong Zhang     }
6132bf73ac6SHong Zhang   }
614f11a936eSBarry Smith   ierr = PetscFree(eowners);CHKERRQ(ierr);
615f11a936eSBarry Smith   ierr = PetscFree(edges);CHKERRQ(ierr);
6162bf73ac6SHong Zhang 
6172bf73ac6SHong Zhang   /* Set vertex array for the subnetworks */
6182bf73ac6SHong Zhang   k = 0;
6192bf73ac6SHong Zhang   for (v=vStart; v<network->vEnd; v++) { /* local vertices, including ghosts */
6202bf73ac6SHong Zhang     network->header[v].ndata           = 0;
6212bf73ac6SHong Zhang     network->header[v].offset[0]       = 0;
6222bf73ac6SHong Zhang     network->header[v].offsetvarrel[0] = 0;
62354dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,v,network->header[v].hsize);CHKERRQ(ierr);
6242bf73ac6SHong Zhang 
6252bf73ac6SHong Zhang     /* shared vertex */
626f11a936eSBarry Smith     ierr = PetscTableFind(network->svtable,network->header[v].index+1,&i);CHKERRQ(ierr);
6272bf73ac6SHong Zhang     if (i) network->svertices[k++] = v;
6282bf73ac6SHong Zhang   }
6292bf73ac6SHong Zhang #if defined(PETSC_USE_DEBUG)
6302bf73ac6SHong Zhang   if (k != network->nsvtx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"k %D != %D nsvtx",k,network->nsvtx);
6312bf73ac6SHong Zhang #endif
6322bf73ac6SHong Zhang 
6332bf73ac6SHong Zhang   network->svtx  = svtx;
6342bf73ac6SHong Zhang   network->Nsvtx = Nsv;
6352bf73ac6SHong Zhang   ierr = PetscFree(sedgelist);CHKERRQ(ierr);
6362bf73ac6SHong Zhang 
6372bf73ac6SHong Zhang   /* Create a global section to be used by DMNetworkIsGhostVertex() which is a non-collective routine */
638f11a936eSBarry Smith   /* see snes_tutorials_network-ex1_4 */
6392bf73ac6SHong Zhang   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
6405f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
6415f2c45f1SShri Abhyankar }
6425f2c45f1SShri Abhyankar 
6435f2c45f1SShri Abhyankar /*@
6445f2c45f1SShri Abhyankar   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
6455f2c45f1SShri Abhyankar 
646d083f849SBarry Smith   Collective on dm
6475f2c45f1SShri Abhyankar 
6487a7aea1fSJed Brown   Input Parameters:
649f11a936eSBarry Smith . dm - the dmnetwork object
6505f2c45f1SShri Abhyankar 
6515f2c45f1SShri Abhyankar   Notes:
6525f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
6535f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
6545f2c45f1SShri Abhyankar 
6555f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
6565f2c45f1SShri Abhyankar 
65797bb938eSShri Abhyankar   Level: beginner
6585f2c45f1SShri Abhyankar 
6592bf73ac6SHong Zhang .seealso: DMNetworkSetNumSubNetworks(), DMNetworkAddSubnetwork()
6605f2c45f1SShri Abhyankar @*/
6615f2c45f1SShri Abhyankar PetscErrorCode DMNetworkLayoutSetUp(DM dm)
6625f2c45f1SShri Abhyankar {
6635f2c45f1SShri Abhyankar   PetscErrorCode ierr;
6645f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
665f11a936eSBarry Smith   PetscInt       i,j,ctr,Nsubnet=network->Nsubnet,*eowners,np,*edges,*subnetvtx,*subnetedge,e,v,vfrom,vto;
666caf410d2SHong Zhang   const PetscInt *cone;
667caf410d2SHong Zhang   MPI_Comm       comm;
668caf410d2SHong Zhang   PetscMPIInt    size,rank;
6696500d4abSHong Zhang 
6706500d4abSHong Zhang   PetscFunctionBegin;
6712bf73ac6SHong Zhang   if (network->nsubnet != network->Nsubnet) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Must call DMNetworkAddSubnetwork() %D times",network->Nsubnet);
6722bf73ac6SHong Zhang 
6732bf73ac6SHong Zhang   /* Create svtable for querry shared vertices */
6742bf73ac6SHong Zhang   ierr = PetscTableCreate(network->Nsvtx,network->NVertices+1,&network->svtable);CHKERRQ(ierr);
6752bf73ac6SHong Zhang 
6762bf73ac6SHong Zhang   if (network->Nsvtx) {
6772bf73ac6SHong Zhang     ierr = DMNetworkLayoutSetUp_Coupling(dm);CHKERRQ(ierr);
6782bf73ac6SHong Zhang     PetscFunctionReturn(0);
6792bf73ac6SHong Zhang   }
6802bf73ac6SHong Zhang 
681caf410d2SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
682ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
683ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
6846500d4abSHong Zhang 
685f11a936eSBarry Smith   /* Create LOCAL edgelist in global vertex ordering for the network by concatenating local input edgelists of the subnetworks */
6868e71b177SVaclav Hapla   ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr);
687caf410d2SHong Zhang   ctr = 0;
6882bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
6896500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
690ba38b151SHong Zhang       edges[2*ctr]   = network->subnet[i].vStart + network->subnet[i].edgelist[2*j];
691ba38b151SHong Zhang       edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1];
6926500d4abSHong Zhang       ctr++;
6936500d4abSHong Zhang     }
6946500d4abSHong Zhang   }
6957765340cSHong Zhang 
6962bf73ac6SHong Zhang   /* Create network->plex; One dimensional network, numCorners=2 */
6978e71b177SVaclav Hapla   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
6988e71b177SVaclav Hapla   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
6992bf73ac6SHong Zhang   ierr = DMSetDimension(network->plex,1);CHKERRQ(ierr);
700caf410d2SHong Zhang   if (size == 1) {
7012bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices,2,edges);CHKERRQ(ierr);
702caf410d2SHong Zhang   } else {
7032bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices,PETSC_DECIDE,2,edges,NULL);CHKERRQ(ierr);
704acdb140fSBarry Smith   }
7056500d4abSHong Zhang 
7066500d4abSHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
7076500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
7086500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
7096500d4abSHong Zhang 
710caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
711caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
7126500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
7136500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
7146500d4abSHong Zhang 
715caf410d2SHong Zhang   np = network->pEnd - network->pStart;
716caf410d2SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
71754dfd506SHong Zhang   for (i=0; i < np; i++) {
71854dfd506SHong Zhang     network->header[i].maxcomps = 1;
71954dfd506SHong Zhang     ierr = SetUpNetworkHeaderComponentValue(dm,&network->header[i],&network->cvalue[i]);CHKERRQ(ierr);
72054dfd506SHong Zhang   }
721caf410d2SHong Zhang 
722f11a936eSBarry Smith   /* Create edge and vertex arrays for the subnetworks
723f11a936eSBarry Smith      This implementation assumes that DMNetwork reads
724f11a936eSBarry Smith      (1) a single subnetwork in parallel; or
725f11a936eSBarry Smith      (2) n subnetworks using n processors, one subnetwork/processor.
726f11a936eSBarry Smith    */
727f11a936eSBarry Smith   ierr = PetscCalloc2(network->nEdges,&subnetedge,network->nVertices,&subnetvtx);CHKERRQ(ierr); /* Maps local edge/vertex to local subnetwork's edge/vertex */
728f11a936eSBarry Smith 
729f11a936eSBarry Smith   network->subnetedge = subnetedge;
730f11a936eSBarry Smith   network->subnetvtx  = subnetvtx;
7312bf73ac6SHong Zhang   for (j=0; j < network->Nsubnet; j++) {
732f11a936eSBarry Smith     network->subnet[j].edges = subnetedge;
733f11a936eSBarry Smith     subnetedge              += network->subnet[j].nedge;
734f11a936eSBarry Smith 
735f11a936eSBarry Smith     network->subnet[j].vertices = subnetvtx;
736f11a936eSBarry Smith     subnetvtx                  += network->subnet[j].nvtx;
7376500d4abSHong Zhang   }
738caf410d2SHong Zhang 
739caf410d2SHong Zhang   /* Get edge ownership */
7402bf73ac6SHong Zhang   ierr = PetscMalloc1(size+1,&eowners);CHKERRQ(ierr);
741caf410d2SHong Zhang   np = network->eEnd - network->eStart;
742ffc4695bSBarry Smith   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr);
743caf410d2SHong Zhang   eowners[0] = 0;
744caf410d2SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
745caf410d2SHong Zhang 
7462bf73ac6SHong Zhang   /* Setup edge and vertex arrays for subnetworks */
7472bf73ac6SHong Zhang   e = 0;
7482bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
749f11a936eSBarry Smith     ctr = 0;
7502bf73ac6SHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
7512bf73ac6SHong Zhang       /* edge e */
7522bf73ac6SHong Zhang       network->header[e].index    = e + eowners[rank];   /* Global edge index */
7532bf73ac6SHong Zhang       network->header[e].subnetid = i;
7542bf73ac6SHong Zhang       network->subnet[i].edges[j] = e;
755caf410d2SHong Zhang 
7562bf73ac6SHong Zhang       network->header[e].ndata           = 0;
7572bf73ac6SHong Zhang       network->header[e].offset[0]       = 0;
7582bf73ac6SHong Zhang       network->header[e].offsetvarrel[0] = 0;
75954dfd506SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,e,network->header[e].hsize);CHKERRQ(ierr);
7602bf73ac6SHong Zhang 
7612bf73ac6SHong Zhang       /* connected vertices */
7622bf73ac6SHong Zhang       ierr = DMPlexGetCone(network->plex,e,&cone);CHKERRQ(ierr);
7632bf73ac6SHong Zhang 
7642bf73ac6SHong Zhang       /* vertex cone[0] */
765f11a936eSBarry Smith       v = cone[0];
766f11a936eSBarry Smith       network->header[v].index     = edges[2*e];  /* Global vertex index */
767f11a936eSBarry Smith       network->header[v].subnetid  = i;           /* Subnetwork id */
768f11a936eSBarry Smith       if (Nsubnet == 1) {
769f11a936eSBarry Smith         network->subnet[i].vertices[v - network->vStart] = v; /* user's subnet[].idx = petsc's v */
770f11a936eSBarry Smith       } else {
771f11a936eSBarry Smith         vfrom = network->subnet[i].edgelist[2*ctr];     /* =subnet[i].idx, Global index! */
772f11a936eSBarry Smith         network->subnet[i].vertices[vfrom] = v; /* user's subnet[].dix = petsc's v */
773f11a936eSBarry Smith       }
7742bf73ac6SHong Zhang 
7752bf73ac6SHong Zhang       /* vertex cone[1] */
776f11a936eSBarry Smith       v = cone[1];
777f11a936eSBarry Smith       network->header[v].index    = edges[2*e+1];   /* Global vertex index */
778f11a936eSBarry Smith       network->header[v].subnetid = i;              /* Subnetwork id */
779f11a936eSBarry Smith       if (Nsubnet == 1) {
780f11a936eSBarry Smith         network->subnet[i].vertices[v - network->vStart] = v; /* user's subnet[].idx = petsc's v */
781f11a936eSBarry Smith       } else {
782f11a936eSBarry Smith         vto = network->subnet[i].edgelist[2*ctr+1];     /* =subnet[i].idx, Global index! */
783f11a936eSBarry Smith         network->subnet[i].vertices[vto] = v; /* user's subnet[].dix = petsc's v */
784f11a936eSBarry Smith       }
7852bf73ac6SHong Zhang 
786f11a936eSBarry Smith       e++; ctr++;
7876500d4abSHong Zhang     }
7886500d4abSHong Zhang   }
7892bf73ac6SHong Zhang   ierr = PetscFree(eowners);CHKERRQ(ierr);
790f11a936eSBarry Smith   ierr = PetscFree(edges);CHKERRQ(ierr); /* local edge list with global idx used by DMPlexBuildFromCellList() */
791caf410d2SHong Zhang 
7922bf73ac6SHong Zhang   for (v = network->vStart; v < network->vEnd; v++) {
7932bf73ac6SHong Zhang     network->header[v].ndata           = 0;
7942bf73ac6SHong Zhang     network->header[v].offset[0]       = 0;
7952bf73ac6SHong Zhang     network->header[v].offsetvarrel[0] = 0;
79654dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,v,network->header[e].hsize);CHKERRQ(ierr);
7976500d4abSHong Zhang   }
7985f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7995f2c45f1SShri Abhyankar }
8005f2c45f1SShri Abhyankar 
80194ef8ddeSSatish Balay /*@C
8022bf73ac6SHong Zhang   DMNetworkGetSubnetwork - Returns the information about a requested subnetwork
8032bf73ac6SHong Zhang 
8042bf73ac6SHong Zhang   Not collective
8052727e31bSShri Abhyankar 
8067a7aea1fSJed Brown   Input Parameters:
807caf410d2SHong Zhang + dm - the DM object
8082bf73ac6SHong Zhang - netnum - the global index of the subnetwork
8092727e31bSShri Abhyankar 
8107a7aea1fSJed Brown   Output Parameters:
8112727e31bSShri Abhyankar + nv - number of vertices (local)
8122727e31bSShri Abhyankar . ne - number of edges (local)
8132bf73ac6SHong Zhang . vtx - local vertices of the subnetwork
8142bf73ac6SHong Zhang - edge - local edges of the subnetwork
8152727e31bSShri Abhyankar 
8162727e31bSShri Abhyankar   Notes:
8172727e31bSShri Abhyankar   Cannot call this routine before DMNetworkLayoutSetup()
8182727e31bSShri Abhyankar 
81906dd6b0eSSatish Balay   Level: intermediate
82006dd6b0eSSatish Balay 
8212bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkLayoutSetUp()
8222727e31bSShri Abhyankar @*/
8232bf73ac6SHong Zhang PetscErrorCode DMNetworkGetSubnetwork(DM dm,PetscInt netnum,PetscInt *nv,PetscInt *ne,const PetscInt **vtx,const PetscInt **edge)
8242727e31bSShri Abhyankar {
825caf410d2SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
8262727e31bSShri Abhyankar 
8272727e31bSShri Abhyankar   PetscFunctionBegin;
8282bf73ac6SHong Zhang   if (netnum >= network->Nsubnet) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Subnet index %D exceeds the num of subnets %D",netnum,network->Nsubnet);
8292bf73ac6SHong Zhang   if (nv) *nv     = network->subnet[netnum].nvtx;
8302bf73ac6SHong Zhang   if (ne) *ne     = network->subnet[netnum].nedge;
8312bf73ac6SHong Zhang   if (vtx) *vtx   = network->subnet[netnum].vertices;
8322bf73ac6SHong Zhang   if (edge) *edge = network->subnet[netnum].edges;
8332bf73ac6SHong Zhang   PetscFunctionReturn(0);
8342bf73ac6SHong Zhang }
8352bf73ac6SHong Zhang 
8362bf73ac6SHong Zhang /*@
8372bf73ac6SHong Zhang   DMNetworkAddSharedVertices - Add shared vertices that connect two given subnetworks
8382bf73ac6SHong Zhang 
8392bf73ac6SHong Zhang   Collective on dm
8402bf73ac6SHong Zhang 
8412bf73ac6SHong Zhang   Input Parameters:
8422bf73ac6SHong Zhang + dm - the dm object
8432bf73ac6SHong Zhang . anetnum - first subnetwork global numbering returned by DMNetworkAddSubnetwork()
8442bf73ac6SHong Zhang . bnetnum - second subnetwork global numbering returned by DMNetworkAddSubnetwork()
8452bf73ac6SHong Zhang . nsvtx - number of vertices that are shared by the two subnetworks
8462bf73ac6SHong Zhang . asvtx - vertex index in the first subnetwork
8472bf73ac6SHong Zhang - bsvtx - vertex index in the second subnetwork
8482bf73ac6SHong Zhang 
8492bf73ac6SHong Zhang   Level: beginner
8502bf73ac6SHong Zhang 
8512bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkGetSharedVertices()
8522bf73ac6SHong Zhang @*/
8532bf73ac6SHong Zhang PetscErrorCode DMNetworkAddSharedVertices(DM dm,PetscInt anetnum,PetscInt bnetnum,PetscInt nsvtx,PetscInt asvtx[],PetscInt bsvtx[])
8542bf73ac6SHong Zhang {
8552bf73ac6SHong Zhang   PetscErrorCode ierr;
8562bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
8572bf73ac6SHong Zhang   PetscInt       i,nsubnet = network->Nsubnet,*sedgelist,Nsvtx=network->Nsvtx;
8582bf73ac6SHong Zhang 
8592bf73ac6SHong Zhang   PetscFunctionBegin;
8602bf73ac6SHong Zhang   if (anetnum == bnetnum) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Subnetworks must have different netnum");
8612bf73ac6SHong Zhang   if (anetnum < 0 || bnetnum < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"netnum cannot be negative");
8622bf73ac6SHong Zhang   if (!Nsvtx) {
8632bf73ac6SHong Zhang     /* allocate network->sedgelist to hold at most 2*nsubnet pairs of shared vertices */
8642bf73ac6SHong Zhang     ierr = PetscMalloc1(2*4*nsubnet,&network->sedgelist);CHKERRQ(ierr);
8652bf73ac6SHong Zhang   }
8662bf73ac6SHong Zhang 
8672bf73ac6SHong Zhang   sedgelist = network->sedgelist;
8682bf73ac6SHong Zhang   for (i=0; i<nsvtx; i++) {
8692bf73ac6SHong Zhang     sedgelist[4*Nsvtx]   = anetnum; sedgelist[4*Nsvtx+1] = asvtx[i];
8702bf73ac6SHong Zhang     sedgelist[4*Nsvtx+2] = bnetnum; sedgelist[4*Nsvtx+3] = bsvtx[i];
8712bf73ac6SHong Zhang     Nsvtx++;
8722bf73ac6SHong Zhang   }
8732bf73ac6SHong Zhang   if (Nsvtx > 2*nsubnet) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"allocate more space for coupling edgelist");
8742bf73ac6SHong Zhang   network->Nsvtx = Nsvtx;
8752727e31bSShri Abhyankar   PetscFunctionReturn(0);
8762727e31bSShri Abhyankar }
8772727e31bSShri Abhyankar 
8782727e31bSShri Abhyankar /*@C
8792bf73ac6SHong Zhang   DMNetworkGetSharedVertices - Returns the info for the shared vertices
8802bf73ac6SHong Zhang 
8812bf73ac6SHong Zhang   Not collective
882caf410d2SHong Zhang 
883f899ff85SJose E. Roman   Input Parameter:
8842bf73ac6SHong Zhang . dm - the DM object
885caf410d2SHong Zhang 
8867a7aea1fSJed Brown   Output Parameters:
8872bf73ac6SHong Zhang + nsv - number of local shared vertices
8882bf73ac6SHong Zhang - svtx - local shared vertices
889caf410d2SHong Zhang 
890caf410d2SHong Zhang   Notes:
891caf410d2SHong Zhang   Cannot call this routine before DMNetworkLayoutSetup()
892caf410d2SHong Zhang 
893caf410d2SHong Zhang   Level: intermediate
894caf410d2SHong Zhang 
8952bf73ac6SHong Zhang .seealso: DMNetworkGetSubnetwork(), DMNetworkLayoutSetUp(), DMNetworkAddSharedVertices()
896caf410d2SHong Zhang @*/
8972bf73ac6SHong Zhang PetscErrorCode DMNetworkGetSharedVertices(DM dm,PetscInt *nsv,const PetscInt **svtx)
898caf410d2SHong Zhang {
899caf410d2SHong Zhang   DM_Network *net = (DM_Network*)dm->data;
900caf410d2SHong Zhang 
901caf410d2SHong Zhang   PetscFunctionBegin;
9022bf73ac6SHong Zhang   if (net->Nsvtx) {
9032bf73ac6SHong Zhang     *nsv  = net->nsvtx;
9042bf73ac6SHong Zhang     *svtx = net->svertices;
90572c3e9f7SHong Zhang   } else {
9062bf73ac6SHong Zhang     *nsv  = 0;
9072bf73ac6SHong Zhang     *svtx = NULL;
90872c3e9f7SHong Zhang   }
909caf410d2SHong Zhang   PetscFunctionReturn(0);
910caf410d2SHong Zhang }
911caf410d2SHong Zhang 
912caf410d2SHong Zhang /*@C
9135f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
9145f2c45f1SShri Abhyankar 
915d083f849SBarry Smith   Logically collective on dm
9165f2c45f1SShri Abhyankar 
9177a7aea1fSJed Brown   Input Parameters:
9185f2c45f1SShri Abhyankar + dm - the network object
9195f2c45f1SShri Abhyankar . name - the component name
9205f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
9215f2c45f1SShri Abhyankar 
9227a7aea1fSJed Brown    Output Parameters:
9235f2c45f1SShri Abhyankar .  key - an integer key that defines the component
9245f2c45f1SShri Abhyankar 
9255f2c45f1SShri Abhyankar    Notes
9265f2c45f1SShri Abhyankar    This routine should be called by all processors before calling DMNetworkLayoutSetup().
9275f2c45f1SShri Abhyankar 
92897bb938eSShri Abhyankar    Level: beginner
9295f2c45f1SShri Abhyankar 
9302bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkLayoutSetUp()
9315f2c45f1SShri Abhyankar @*/
932caf410d2SHong Zhang PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key)
9335f2c45f1SShri Abhyankar {
9345f2c45f1SShri Abhyankar   PetscErrorCode        ierr;
9355f2c45f1SShri Abhyankar   DM_Network            *network = (DM_Network*) dm->data;
93654dfd506SHong Zhang   DMNetworkComponent    *component=NULL,*newcomponent=NULL;
9375f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
9385f2c45f1SShri Abhyankar   PetscInt              i;
9395f2c45f1SShri Abhyankar 
9405f2c45f1SShri Abhyankar   PetscFunctionBegin;
94154dfd506SHong Zhang   if (!network->component) {
94254dfd506SHong Zhang     ierr = PetscCalloc1(network->max_comps_registered,&network->component);CHKERRQ(ierr);
94354dfd506SHong Zhang   }
94454dfd506SHong Zhang 
9455f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
94654dfd506SHong Zhang     ierr = PetscStrcmp(network->component[i].name,name,&flg);CHKERRQ(ierr);
9475f2c45f1SShri Abhyankar     if (flg) {
9485f2c45f1SShri Abhyankar       *key = i;
9495f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
9505f2c45f1SShri Abhyankar     }
9516d64e262SShri Abhyankar   }
95254dfd506SHong Zhang 
95354dfd506SHong Zhang   if (network->ncomponent == network->max_comps_registered) {
95454dfd506SHong Zhang     /* Reached max allowed so resize component */
95554dfd506SHong Zhang     network->max_comps_registered += 2;
95654dfd506SHong Zhang     ierr = PetscCalloc1(network->max_comps_registered,&newcomponent);CHKERRQ(ierr);
95754dfd506SHong Zhang     /* Copy over the previous component info */
95854dfd506SHong Zhang     for (i=0; i < network->ncomponent; i++) {
95954dfd506SHong Zhang       ierr = PetscStrcpy(newcomponent[i].name,network->component[i].name);CHKERRQ(ierr);
96054dfd506SHong Zhang       newcomponent[i].size = network->component[i].size;
9615f2c45f1SShri Abhyankar     }
96254dfd506SHong Zhang     /* Free old one */
96354dfd506SHong Zhang     ierr = PetscFree(network->component);CHKERRQ(ierr);
96454dfd506SHong Zhang     /* Update pointer */
96554dfd506SHong Zhang     network->component = newcomponent;
96654dfd506SHong Zhang   }
96754dfd506SHong Zhang 
96854dfd506SHong Zhang   component = &network->component[network->ncomponent];
9695f2c45f1SShri Abhyankar 
9705f2c45f1SShri Abhyankar   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
9715f2c45f1SShri Abhyankar   component->size = size/sizeof(DMNetworkComponentGenericDataType);
9725f2c45f1SShri Abhyankar   *key = network->ncomponent;
9735f2c45f1SShri Abhyankar   network->ncomponent++;
9745f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9755f2c45f1SShri Abhyankar }
9765f2c45f1SShri Abhyankar 
9775f2c45f1SShri Abhyankar /*@
9782bf73ac6SHong Zhang   DMNetworkGetVertexRange - Get the bounds [start, end) for the local vertices
9795f2c45f1SShri Abhyankar 
9805f2c45f1SShri Abhyankar   Not Collective
9815f2c45f1SShri Abhyankar 
982f899ff85SJose E. Roman   Input Parameter:
9832bf73ac6SHong Zhang . dm - the DMNetwork object
9845f2c45f1SShri Abhyankar 
985fd292e60Sprj-   Output Parameters:
9862bf73ac6SHong Zhang + vStart - the first vertex point
9872bf73ac6SHong Zhang - vEnd - one beyond the last vertex point
9885f2c45f1SShri Abhyankar 
98997bb938eSShri Abhyankar   Level: beginner
9905f2c45f1SShri Abhyankar 
9912bf73ac6SHong Zhang .seealso: DMNetworkGetEdgeRange()
9925f2c45f1SShri Abhyankar @*/
9935f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
9945f2c45f1SShri Abhyankar {
9955f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*)dm->data;
9965f2c45f1SShri Abhyankar 
9975f2c45f1SShri Abhyankar   PetscFunctionBegin;
9985f2c45f1SShri Abhyankar   if (vStart) *vStart = network->vStart;
9995f2c45f1SShri Abhyankar   if (vEnd) *vEnd = network->vEnd;
10005f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10015f2c45f1SShri Abhyankar }
10025f2c45f1SShri Abhyankar 
10035f2c45f1SShri Abhyankar /*@
10042bf73ac6SHong Zhang   DMNetworkGetEdgeRange - Get the bounds [start, end) for the local edges
10055f2c45f1SShri Abhyankar 
10065f2c45f1SShri Abhyankar   Not Collective
10075f2c45f1SShri Abhyankar 
1008f899ff85SJose E. Roman   Input Parameter:
10092bf73ac6SHong Zhang . dm - the DMNetwork object
10105f2c45f1SShri Abhyankar 
1011fd292e60Sprj-   Output Parameters:
10125f2c45f1SShri Abhyankar + eStart - The first edge point
10135f2c45f1SShri Abhyankar - eEnd - One beyond the last edge point
10145f2c45f1SShri Abhyankar 
101597bb938eSShri Abhyankar   Level: beginner
10165f2c45f1SShri Abhyankar 
10172bf73ac6SHong Zhang .seealso: DMNetworkGetVertexRange()
10185f2c45f1SShri Abhyankar @*/
10195f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
10205f2c45f1SShri Abhyankar {
10215f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*)dm->data;
10225f2c45f1SShri Abhyankar 
10235f2c45f1SShri Abhyankar   PetscFunctionBegin;
10245f2c45f1SShri Abhyankar   if (eStart) *eStart = network->eStart;
10255f2c45f1SShri Abhyankar   if (eEnd) *eEnd = network->eEnd;
10265f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10275f2c45f1SShri Abhyankar }
10285f2c45f1SShri Abhyankar 
10292bf73ac6SHong Zhang static PetscErrorCode DMNetworkGetIndex(DM dm,PetscInt p,PetscInt *index)
10302bf73ac6SHong Zhang {
10312bf73ac6SHong Zhang   PetscErrorCode    ierr;
10322bf73ac6SHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
10332bf73ac6SHong Zhang   PetscInt          offsetp;
10342bf73ac6SHong Zhang   DMNetworkComponentHeader header;
10352bf73ac6SHong Zhang 
10362bf73ac6SHong Zhang   PetscFunctionBegin;
10372bf73ac6SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
10382bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
10392bf73ac6SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
10402bf73ac6SHong Zhang   *index = header->index;
10412bf73ac6SHong Zhang   PetscFunctionReturn(0);
10422bf73ac6SHong Zhang }
10432bf73ac6SHong Zhang 
10447b6afd5bSHong Zhang /*@
10452bf73ac6SHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the global numbering for the edge on the network
10467b6afd5bSHong Zhang 
10477b6afd5bSHong Zhang   Not Collective
10487b6afd5bSHong Zhang 
10497b6afd5bSHong Zhang   Input Parameters:
10507b6afd5bSHong Zhang + dm - DMNetwork object
1051e85e6aecSHong Zhang - p - edge point
10527b6afd5bSHong Zhang 
1053fd292e60Sprj-   Output Parameters:
10542bf73ac6SHong Zhang . index - the global numbering for the edge
10557b6afd5bSHong Zhang 
10567b6afd5bSHong Zhang   Level: intermediate
10577b6afd5bSHong Zhang 
10582bf73ac6SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
10597b6afd5bSHong Zhang @*/
1060e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
10617b6afd5bSHong Zhang {
10627b6afd5bSHong Zhang   PetscErrorCode ierr;
10637b6afd5bSHong Zhang 
10647b6afd5bSHong Zhang   PetscFunctionBegin;
10652bf73ac6SHong Zhang   ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr);
10667b6afd5bSHong Zhang   PetscFunctionReturn(0);
10677b6afd5bSHong Zhang }
10687b6afd5bSHong Zhang 
10695f2c45f1SShri Abhyankar /*@
10702bf73ac6SHong Zhang   DMNetworkGetGlobalVertexIndex - Get the global numbering for the vertex on the network
1071e85e6aecSHong Zhang 
1072e85e6aecSHong Zhang   Not Collective
1073e85e6aecSHong Zhang 
1074e85e6aecSHong Zhang   Input Parameters:
1075e85e6aecSHong Zhang + dm - DMNetwork object
1076e85e6aecSHong Zhang - p  - vertex point
1077e85e6aecSHong Zhang 
1078fd292e60Sprj-   Output Parameters:
10792bf73ac6SHong Zhang . index - the global numbering for the vertex
1080e85e6aecSHong Zhang 
1081e85e6aecSHong Zhang   Level: intermediate
1082e85e6aecSHong Zhang 
1083*f2f58720SBarry Smith .seealso: DMNetworkGetGlobalEdgeIndex(), DMNetworkGetLocalVertexIndex()
1084e85e6aecSHong Zhang @*/
1085e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
1086e85e6aecSHong Zhang {
1087e85e6aecSHong Zhang   PetscErrorCode ierr;
1088e85e6aecSHong Zhang 
1089e85e6aecSHong Zhang   PetscFunctionBegin;
10902bf73ac6SHong Zhang   ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr);
10919988b915SShri Abhyankar   PetscFunctionReturn(0);
10929988b915SShri Abhyankar }
10939988b915SShri Abhyankar 
10949988b915SShri Abhyankar /*@
10955f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
10965f2c45f1SShri Abhyankar 
10975f2c45f1SShri Abhyankar   Not Collective
10985f2c45f1SShri Abhyankar 
10995f2c45f1SShri Abhyankar   Input Parameters:
11002bf73ac6SHong Zhang + dm - the DMNetwork object
1101a2b725a8SWilliam Gropp - p - vertex/edge point
11025f2c45f1SShri Abhyankar 
11035f2c45f1SShri Abhyankar   Output Parameters:
11045f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
11055f2c45f1SShri Abhyankar 
110697bb938eSShri Abhyankar   Level: beginner
11075f2c45f1SShri Abhyankar 
11082bf73ac6SHong Zhang .seealso: DMNetworkRegisterComponent(), DMNetworkAddComponent()
11095f2c45f1SShri Abhyankar @*/
11105f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
11115f2c45f1SShri Abhyankar {
11125f2c45f1SShri Abhyankar   PetscErrorCode ierr;
11135f2c45f1SShri Abhyankar   PetscInt       offset;
11145f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11155f2c45f1SShri Abhyankar 
11165f2c45f1SShri Abhyankar   PetscFunctionBegin;
11175f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
11185f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
11195f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
11205f2c45f1SShri Abhyankar }
11215f2c45f1SShri Abhyankar 
11225f2c45f1SShri Abhyankar /*@
11232bf73ac6SHong Zhang   DMNetworkGetLocalVecOffset - Get the offset for accessing the variables associated with a component at the given vertex/edge from the local vector
11245f2c45f1SShri Abhyankar 
11255f2c45f1SShri Abhyankar   Not Collective
11265f2c45f1SShri Abhyankar 
11275f2c45f1SShri Abhyankar   Input Parameters:
11282bf73ac6SHong Zhang + dm - the DMNetwork object
1129*f2f58720SBarry Smith . p - the edge or vertex point
11302bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
11319988b915SShri Abhyankar 
11329988b915SShri Abhyankar   Output Parameters:
11332bf73ac6SHong Zhang . offset - the local offset
11349988b915SShri Abhyankar 
1135*f2f58720SBarry Smith   Notes:
1136*f2f58720SBarry Smith     These offsets can be passed to MatSetValuesLocal() for matrices obtained with DMCreateMatrix().
1137*f2f58720SBarry Smith 
1138*f2f58720SBarry Smith     For vectors obtained with DMCreateLocalVector() the offsets can be used with VecSetValues().
1139*f2f58720SBarry Smith 
1140*f2f58720SBarry Smith     For vectors obtained with DMCreateLocalVector() and the array obtained with VecGetArray(vec,&array) you can access or set
1141*f2f58720SBarry Smith     the vector values with array[offset].
1142*f2f58720SBarry Smith 
1143*f2f58720SBarry Smith     For vectors obtained with DMCreateGlobalVector() the offsets can be used with VecSetValuesLocal().
1144*f2f58720SBarry Smith 
11459988b915SShri Abhyankar   Level: intermediate
11469988b915SShri Abhyankar 
1147*f2f58720SBarry Smith .seealso: DMGetLocalVector(), DMNetworkGetComponent(), DMNetworkGetGlobalVecOffset(), DMCreateGlobalVector(), VecGetArray(), VecSetValuesLocal(), MatSetValuesLocal()
11489988b915SShri Abhyankar @*/
11492bf73ac6SHong Zhang PetscErrorCode DMNetworkGetLocalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offset)
11509988b915SShri Abhyankar {
11519988b915SShri Abhyankar   PetscErrorCode ierr;
11529988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11539988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
11549988b915SShri Abhyankar   DMNetworkComponentHeader header;
11559988b915SShri Abhyankar 
11569988b915SShri Abhyankar   PetscFunctionBegin;
11572bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->localSection,p,&offsetp);CHKERRQ(ierr);
11582bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
11592bf73ac6SHong Zhang     *offset = offsetp;
11602bf73ac6SHong Zhang     PetscFunctionReturn(0);
11612bf73ac6SHong Zhang   }
11622bf73ac6SHong Zhang 
11639988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
11649988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
11659988b915SShri Abhyankar   *offset = offsetp + header->offsetvarrel[compnum];
11669988b915SShri Abhyankar   PetscFunctionReturn(0);
11679988b915SShri Abhyankar }
11689988b915SShri Abhyankar 
11699988b915SShri Abhyankar /*@
11702bf73ac6SHong Zhang   DMNetworkGetGlobalVecOffset - Get the global offset for accessing the variables associated with a component for the given vertex/edge from the global vector
11719988b915SShri Abhyankar 
11729988b915SShri Abhyankar   Not Collective
11739988b915SShri Abhyankar 
11749988b915SShri Abhyankar   Input Parameters:
11752bf73ac6SHong Zhang + dm - the DMNetwork object
1176*f2f58720SBarry Smith . p - the edge or vertex point
11772bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
11789988b915SShri Abhyankar 
11799988b915SShri Abhyankar   Output Parameters:
11809988b915SShri Abhyankar . offsetg - the global offset
11819988b915SShri Abhyankar 
1182*f2f58720SBarry Smith   Notes:
1183*f2f58720SBarry Smith     These offsets can be passed to MatSetValues() for matrices obtained with DMCreateMatrix().
1184*f2f58720SBarry Smith 
1185*f2f58720SBarry Smith     For vectors obtained with DMCreateGlobalVector() the offsets can be used with VecSetValues().
1186*f2f58720SBarry Smith 
1187*f2f58720SBarry Smith     For vectors obtained with DMCreateGlobalVector() and the array obtained with VecGetArray(vec,&array) you can access or set
1188*f2f58720SBarry Smith     the vector values with array[offset - rstart] where restart is obtained with VecGetOwnershipRange(v,&rstart,NULL);
1189*f2f58720SBarry Smith 
11909988b915SShri Abhyankar   Level: intermediate
11919988b915SShri Abhyankar 
1192*f2f58720SBarry Smith .seealso: DMNetworkGetLocalVecOffset(), DMGetGlobalVector(), DMNetworkGetComponent(), DMCreateGlobalVector(), VecGetArray(), VecSetValues(), MatSetValues()
11939988b915SShri Abhyankar @*/
11942bf73ac6SHong Zhang PetscErrorCode DMNetworkGetGlobalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offsetg)
11959988b915SShri Abhyankar {
11969988b915SShri Abhyankar   PetscErrorCode ierr;
11979988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11989988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
11999988b915SShri Abhyankar   DMNetworkComponentHeader header;
12009988b915SShri Abhyankar 
12019988b915SShri Abhyankar   PetscFunctionBegin;
12022bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->globalSection,p,&offsetp);CHKERRQ(ierr);
12032bf73ac6SHong Zhang   if (offsetp < 0) offsetp = -(offsetp + 1); /* Convert to actual global offset for ghost vertex */
12042bf73ac6SHong Zhang 
12052bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
12062bf73ac6SHong Zhang     *offsetg = offsetp;
12072bf73ac6SHong Zhang     PetscFunctionReturn(0);
12082bf73ac6SHong Zhang   }
12099988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
12109988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
12119988b915SShri Abhyankar   *offsetg = offsetp + header->offsetvarrel[compnum];
12129988b915SShri Abhyankar   PetscFunctionReturn(0);
12139988b915SShri Abhyankar }
12149988b915SShri Abhyankar 
12159988b915SShri Abhyankar /*@
12162bf73ac6SHong Zhang   DMNetworkGetEdgeOffset - Get the offset for accessing the variables associated with the given edge from the local subvector
121724121865SAdrian Maldonado 
121824121865SAdrian Maldonado   Not Collective
121924121865SAdrian Maldonado 
122024121865SAdrian Maldonado   Input Parameters:
12212bf73ac6SHong Zhang + dm - the DMNetwork object
122224121865SAdrian Maldonado - p - the edge point
122324121865SAdrian Maldonado 
122424121865SAdrian Maldonado   Output Parameters:
122524121865SAdrian Maldonado . offset - the offset
122624121865SAdrian Maldonado 
122724121865SAdrian Maldonado   Level: intermediate
122824121865SAdrian Maldonado 
12292bf73ac6SHong Zhang .seealso: DMNetworkGetLocalVecOffset(), DMGetLocalVector()
123024121865SAdrian Maldonado @*/
123124121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
123224121865SAdrian Maldonado {
123324121865SAdrian Maldonado   PetscErrorCode ierr;
123424121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
123524121865SAdrian Maldonado 
123624121865SAdrian Maldonado   PetscFunctionBegin;
123724121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
123824121865SAdrian Maldonado   PetscFunctionReturn(0);
123924121865SAdrian Maldonado }
124024121865SAdrian Maldonado 
124124121865SAdrian Maldonado /*@
12422bf73ac6SHong Zhang   DMNetworkGetVertexOffset - Get the offset for accessing the variables associated with the given vertex from the local subvector
124324121865SAdrian Maldonado 
124424121865SAdrian Maldonado   Not Collective
124524121865SAdrian Maldonado 
124624121865SAdrian Maldonado   Input Parameters:
12472bf73ac6SHong Zhang + dm - the DMNetwork object
124824121865SAdrian Maldonado - p - the vertex point
124924121865SAdrian Maldonado 
125024121865SAdrian Maldonado   Output Parameters:
125124121865SAdrian Maldonado . offset - the offset
125224121865SAdrian Maldonado 
125324121865SAdrian Maldonado   Level: intermediate
125424121865SAdrian Maldonado 
12552bf73ac6SHong Zhang .seealso: DMNetworkGetEdgeOffset(), DMGetLocalVector()
125624121865SAdrian Maldonado @*/
125724121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
125824121865SAdrian Maldonado {
125924121865SAdrian Maldonado   PetscErrorCode ierr;
126024121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
126124121865SAdrian Maldonado 
126224121865SAdrian Maldonado   PetscFunctionBegin;
126324121865SAdrian Maldonado   p -= network->vStart;
126424121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
126524121865SAdrian Maldonado   PetscFunctionReturn(0);
126624121865SAdrian Maldonado }
12672bf73ac6SHong Zhang 
12685f2c45f1SShri Abhyankar /*@
12692bf73ac6SHong Zhang   DMNetworkAddComponent - Adds a network component and number of variables at the given point (vertex/edge)
12705f2c45f1SShri Abhyankar 
12715f2c45f1SShri Abhyankar   Not Collective
12725f2c45f1SShri Abhyankar 
12735f2c45f1SShri Abhyankar   Input Parameters:
12744dc646bcSBarry Smith + dm - the DMNetwork
12755f2c45f1SShri Abhyankar . p - the vertex/edge point
12762bf73ac6SHong Zhang . componentkey - component key returned while registering the component; ignored if compvalue=NULL
12772bf73ac6SHong Zhang . compvalue - pointer to the data structure for the component, or NULL if not required.
12782bf73ac6SHong Zhang - nvar - number of variables for the component at the vertex/edge point
12795f2c45f1SShri Abhyankar 
128097bb938eSShri Abhyankar   Level: beginner
12815f2c45f1SShri Abhyankar 
12822bf73ac6SHong Zhang .seealso: DMNetworkGetComponent()
12835f2c45f1SShri Abhyankar @*/
12842bf73ac6SHong Zhang PetscErrorCode DMNetworkAddComponent(DM dm,PetscInt p,PetscInt componentkey,void* compvalue,PetscInt nvar)
12855f2c45f1SShri Abhyankar {
12865f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
12875f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
12882bf73ac6SHong Zhang   DMNetworkComponent       *component = &network->component[componentkey];
128954dfd506SHong Zhang   DMNetworkComponentHeader header;
129054dfd506SHong Zhang   DMNetworkComponentValue  cvalue;
12912bf73ac6SHong Zhang   PetscBool                sharedv=PETSC_FALSE;
129254dfd506SHong Zhang   PetscInt                 compnum;
129354dfd506SHong Zhang   PetscInt                 *compsize,*compkey,*compoffset,*compnvar,*compoffsetvarrel;
129454dfd506SHong Zhang   void*                    *compdata;
12955f2c45f1SShri Abhyankar 
12965f2c45f1SShri Abhyankar   PetscFunctionBegin;
12975f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
12982bf73ac6SHong Zhang   if (!compvalue) PetscFunctionReturn(0);
12992bf73ac6SHong Zhang 
13002bf73ac6SHong Zhang   ierr = DMNetworkIsSharedVertex(dm,p,&sharedv);CHKERRQ(ierr);
13012bf73ac6SHong Zhang   if (sharedv) {
13022bf73ac6SHong Zhang     PetscBool ghost;
13032bf73ac6SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
13042bf73ac6SHong Zhang     if (ghost) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adding a component at a leaf(ghost) shared vertex is not supported");
13052bf73ac6SHong Zhang   }
13062bf73ac6SHong Zhang 
130754dfd506SHong Zhang   header = &network->header[p];
130854dfd506SHong Zhang   cvalue = &network->cvalue[p];
130954dfd506SHong Zhang   if (header->ndata == header->maxcomps) {
1310f11a936eSBarry Smith     PetscInt additional_size;
1311f11a936eSBarry Smith 
131254dfd506SHong Zhang     /* Reached limit so resize header component arrays */
131354dfd506SHong Zhang     header->maxcomps += 2;
131454dfd506SHong Zhang 
131554dfd506SHong Zhang     /* Allocate arrays for component information and value */
131654dfd506SHong Zhang     ierr = PetscCalloc5(header->maxcomps,&compsize,header->maxcomps,&compkey,header->maxcomps,&compoffset,header->maxcomps,&compnvar,header->maxcomps,&compoffsetvarrel);CHKERRQ(ierr);
131754dfd506SHong Zhang     ierr = PetscMalloc1(header->maxcomps,&compdata);CHKERRQ(ierr);
131854dfd506SHong Zhang 
131954dfd506SHong Zhang     /* Recalculate header size */
132054dfd506SHong Zhang     header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt);
132154dfd506SHong Zhang 
132254dfd506SHong Zhang     header->hsize /= sizeof(DMNetworkComponentGenericDataType);
132354dfd506SHong Zhang 
132454dfd506SHong Zhang     /* Copy over component info */
132554dfd506SHong Zhang     ierr = PetscMemcpy(compsize,header->size,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
132654dfd506SHong Zhang     ierr = PetscMemcpy(compkey,header->key,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
132754dfd506SHong Zhang     ierr = PetscMemcpy(compoffset,header->offset,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
132854dfd506SHong Zhang     ierr = PetscMemcpy(compnvar,header->nvar,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
132954dfd506SHong Zhang     ierr = PetscMemcpy(compoffsetvarrel,header->offsetvarrel,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
133054dfd506SHong Zhang 
133154dfd506SHong Zhang     /* Copy over component data pointers */
133254dfd506SHong Zhang     ierr = PetscMemcpy(compdata,cvalue->data,header->ndata*sizeof(void*));CHKERRQ(ierr);
133354dfd506SHong Zhang 
133454dfd506SHong Zhang     /* Free old arrays */
133554dfd506SHong Zhang     ierr = PetscFree5(header->size,header->key,header->offset,header->nvar,header->offsetvarrel);CHKERRQ(ierr);
133654dfd506SHong Zhang     ierr = PetscFree(cvalue->data);CHKERRQ(ierr);
133754dfd506SHong Zhang 
133854dfd506SHong Zhang     /* Update pointers */
133954dfd506SHong Zhang     header->size = compsize;
134054dfd506SHong Zhang     header->key  = compkey;
134154dfd506SHong Zhang     header->offset = compoffset;
134254dfd506SHong Zhang     header->nvar = compnvar;
134354dfd506SHong Zhang     header->offsetvarrel = compoffsetvarrel;
134454dfd506SHong Zhang 
134554dfd506SHong Zhang     cvalue->data = compdata;
134654dfd506SHong Zhang 
134754dfd506SHong Zhang     /* Update DataSection Dofs */
134854dfd506SHong Zhang     /* The dofs for datasection point p equals sizeof the header (i.e. header->hsize) + sizes of the components added at point p. With the resizing of the header, we need to update the dofs for point p. Hence, we add the extra size added for the header */
1349f11a936eSBarry Smith     additional_size = (5*(header->maxcomps - header->ndata)*sizeof(PetscInt))/sizeof(DMNetworkComponentGenericDataType);
135054dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,p,additional_size);CHKERRQ(ierr);
135154dfd506SHong Zhang   }
135254dfd506SHong Zhang   header = &network->header[p];
135354dfd506SHong Zhang   cvalue = &network->cvalue[p];
135454dfd506SHong Zhang 
135554dfd506SHong Zhang   compnum = header->ndata;
13562bf73ac6SHong Zhang 
13572bf73ac6SHong Zhang   header->size[compnum] = component->size;
13582bf73ac6SHong Zhang   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
13592bf73ac6SHong Zhang   header->key[compnum] = componentkey;
13602bf73ac6SHong Zhang   if (compnum != 0) header->offset[compnum] = header->offset[compnum-1] + header->size[compnum-1];
13612bf73ac6SHong Zhang   cvalue->data[compnum] = (void*)compvalue;
13622bf73ac6SHong Zhang 
13632bf73ac6SHong Zhang   /* variables */
13642bf73ac6SHong Zhang   header->nvar[compnum] += nvar;
13652bf73ac6SHong Zhang   if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum-1] + header->nvar[compnum-1];
13662bf73ac6SHong Zhang 
13672bf73ac6SHong Zhang   header->ndata++;
13685f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13695f2c45f1SShri Abhyankar }
13705f2c45f1SShri Abhyankar 
137127f51fceSHong Zhang /*@
13722bf73ac6SHong Zhang   DMNetworkGetComponent - Gets the component key, the component data, and the number of variables at a given network point
137327f51fceSHong Zhang 
137427f51fceSHong Zhang   Not Collective
137527f51fceSHong Zhang 
137627f51fceSHong Zhang   Input Parameters:
13772bf73ac6SHong Zhang + dm - the DMNetwork object
13782bf73ac6SHong Zhang . p - vertex/edge point
137999c90e12SSatish Balay - compnum - component number; use ALL_COMPONENTS if sum up all the components
138027f51fceSHong Zhang 
138127f51fceSHong Zhang   Output Parameters:
13822bf73ac6SHong Zhang + compkey - the key obtained when registering the component (use NULL if not required)
13832bf73ac6SHong Zhang . component - the component data (use NULL if not required)
13842bf73ac6SHong Zhang - nvar  - number of variables (use NULL if not required)
138527f51fceSHong Zhang 
138697bb938eSShri Abhyankar   Level: beginner
138727f51fceSHong Zhang 
13882bf73ac6SHong Zhang .seealso: DMNetworkAddComponent(), DMNetworkGetNumComponents()
138927f51fceSHong Zhang @*/
13902bf73ac6SHong Zhang PetscErrorCode DMNetworkGetComponent(DM dm,PetscInt p,PetscInt compnum,PetscInt *compkey,void **component,PetscInt *nvar)
139127f51fceSHong Zhang {
139227f51fceSHong Zhang   PetscErrorCode ierr;
139327f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
13942bf73ac6SHong Zhang   PetscInt       offset = 0;
13952bf73ac6SHong Zhang   DMNetworkComponentHeader header;
139627f51fceSHong Zhang 
139727f51fceSHong Zhang   PetscFunctionBegin;
13982bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
139927f51fceSHong Zhang     ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
140027f51fceSHong Zhang     PetscFunctionReturn(0);
140127f51fceSHong Zhang   }
140227f51fceSHong Zhang 
14032bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
140442dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
14055f2c45f1SShri Abhyankar 
14062bf73ac6SHong Zhang   if (compnum >= 0) {
14072bf73ac6SHong Zhang     if (compkey) *compkey = header->key[compnum];
14082bf73ac6SHong Zhang     if (component) {
140954dfd506SHong Zhang       offset += header->hsize+header->offset[compnum];
14102bf73ac6SHong Zhang       *component = network->componentdataarray+offset;
14112bf73ac6SHong Zhang     }
14122bf73ac6SHong Zhang   }
14135f2c45f1SShri Abhyankar 
14142bf73ac6SHong Zhang   if (nvar) *nvar = header->nvar[compnum];
141554dfd506SHong Zhang 
14165f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14175f2c45f1SShri Abhyankar }
14185f2c45f1SShri Abhyankar 
14192bf73ac6SHong Zhang /*
14202bf73ac6SHong Zhang  Sets up the array that holds the data for all components and its associated section.
14212bf73ac6SHong Zhang  It copies the data for all components in a contiguous array called componentdataarray. The component data is stored pointwise with an additional header (metadata) stored for each point. The header has metadata information such as number of components at each point, number of variables for each component, offsets for the components data, etc.
14222bf73ac6SHong Zhang */
14235f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
14245f2c45f1SShri Abhyankar {
14255f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
14265f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
1427f11a936eSBarry Smith   PetscInt                 arr_size,p,offset,offsetp,ncomp,i,*headerarr;
14285f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
14295f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
1430f11a936eSBarry Smith   DMNetworkComponentHeader headerinfo;
14315f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
14325f2c45f1SShri Abhyankar 
14335f2c45f1SShri Abhyankar   PetscFunctionBegin;
14345f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
14355f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
1436f11a936eSBarry Smith   /* arr_size+1 fixes pipeline test of opensolaris-misc for src/dm/tests/ex10.c -- Do not know why */
1437f11a936eSBarry Smith   ierr = PetscCalloc1(arr_size+1,&network->componentdataarray);CHKERRQ(ierr);
14385f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
14395f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
14405f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
14415f2c45f1SShri Abhyankar     /* Copy header */
14425f2c45f1SShri Abhyankar     header = &network->header[p];
1443f11a936eSBarry Smith     headerinfo = (DMNetworkComponentHeader)(componentdataarray+offsetp);
144454dfd506SHong Zhang     ierr = PetscMemcpy(headerinfo,header,sizeof(struct _p_DMNetworkComponentHeader));CHKERRQ(ierr);
1445f11a936eSBarry Smith     headerarr = (PetscInt*)(headerinfo+1);
144654dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->size,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
144754dfd506SHong Zhang     headerarr += header->maxcomps;
144854dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->key,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
144954dfd506SHong Zhang     headerarr += header->maxcomps;
145054dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offset,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
145154dfd506SHong Zhang     headerarr += header->maxcomps;
145254dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->nvar,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
145354dfd506SHong Zhang     headerarr += header->maxcomps;
145454dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offsetvarrel,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
145554dfd506SHong Zhang 
14565f2c45f1SShri Abhyankar     /* Copy data */
14575f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
14585f2c45f1SShri Abhyankar     ncomp  = header->ndata;
14592bf73ac6SHong Zhang 
14605f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
146154dfd506SHong Zhang       offset = offsetp + header->hsize + header->offset[i];
1462302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
14635f2c45f1SShri Abhyankar     }
14645f2c45f1SShri Abhyankar   }
14655f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14665f2c45f1SShri Abhyankar }
14675f2c45f1SShri Abhyankar 
14685f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
14692bf73ac6SHong Zhang static PetscErrorCode DMNetworkVariablesSetUp(DM dm)
14705f2c45f1SShri Abhyankar {
14715f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14725f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14732bf73ac6SHong Zhang   MPI_Comm       comm;
14742bf73ac6SHong Zhang   PetscMPIInt    size;
14755f2c45f1SShri Abhyankar 
14765f2c45f1SShri Abhyankar   PetscFunctionBegin;
14772bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
14782bf73ac6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
14792bf73ac6SHong Zhang 
14802bf73ac6SHong Zhang   if (size > 1) { /* Sync nvar at shared vertices for all processes */
14812bf73ac6SHong Zhang     PetscSF           sf = network->plex->sf;
14822bf73ac6SHong Zhang     PetscInt          *local_nvar, *remote_nvar,nroots,nleaves,p=-1,i,nsv;
14832bf73ac6SHong Zhang     const PetscInt    *svtx;
14842bf73ac6SHong Zhang     PetscBool         ghost;
14852bf73ac6SHong Zhang     /*
14862bf73ac6SHong Zhang      PetscMPIInt       rank;
14872bf73ac6SHong Zhang      const PetscInt    *ilocal;
14882bf73ac6SHong Zhang      const PetscSFNode *iremote;
14892bf73ac6SHong Zhang      ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
14902bf73ac6SHong Zhang      ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
14912bf73ac6SHong Zhang     */
14922bf73ac6SHong Zhang     ierr = PetscSFGetGraph(sf,&nroots,&nleaves,NULL,NULL);CHKERRQ(ierr);
14932bf73ac6SHong Zhang     ierr = PetscCalloc2(nroots,&local_nvar,nroots,&remote_nvar);CHKERRQ(ierr);
14942bf73ac6SHong Zhang 
14952bf73ac6SHong Zhang     /* Leaves copy user's nvar to local_nvar */
14962bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nsv,&svtx);CHKERRQ(ierr);
14972bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
14982bf73ac6SHong Zhang       p = svtx[i];
14992bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
15002bf73ac6SHong Zhang       if (!ghost) continue;
15012bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
15022bf73ac6SHong Zhang       /* printf("[%d] Before SFReduce: leaf local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
15032bf73ac6SHong Zhang     }
15042bf73ac6SHong Zhang 
15052bf73ac6SHong Zhang     /* Leaves add local_nvar to root remote_nvar */
15062bf73ac6SHong Zhang     ierr = PetscSFReduceBegin(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
15072bf73ac6SHong Zhang     ierr = PetscSFReduceEnd(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
15082bf73ac6SHong Zhang     /* printf("[%d] remote_nvar[%d] = %d\n",rank,p,remote_nvar[p]); */
15092bf73ac6SHong Zhang 
15102bf73ac6SHong Zhang     /* Update roots' local_nvar */
15112bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
15122bf73ac6SHong Zhang       p = svtx[i];
15132bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
15142bf73ac6SHong Zhang       if (ghost) continue;
15152bf73ac6SHong Zhang 
15162bf73ac6SHong Zhang       ierr = PetscSectionAddDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
15172bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
15182bf73ac6SHong Zhang       /* printf("[%d]  After SFReduce: root local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
15192bf73ac6SHong Zhang     }
15202bf73ac6SHong Zhang 
15212bf73ac6SHong Zhang     /* Roots Bcast nvar to leaves */
1522ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
1523ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
15242bf73ac6SHong Zhang 
15252bf73ac6SHong Zhang     /* Leaves reset receved/remote nvar to dm */
15262bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
15272bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
15282bf73ac6SHong Zhang       if (!ghost) continue;
15292bf73ac6SHong Zhang       p = svtx[i];
15302bf73ac6SHong Zhang       /* printf("[%d] leaf reset nvar %d at p= %d \n",rank,remote_nvar[p],p); */
15312bf73ac6SHong Zhang       /* DMNetworkSetNumVariables(dm,p,remote_nvar[p]) */
15322bf73ac6SHong Zhang       ierr = PetscSectionSetDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
15332bf73ac6SHong Zhang     }
15342bf73ac6SHong Zhang 
15352bf73ac6SHong Zhang     ierr = PetscFree2(local_nvar,remote_nvar);CHKERRQ(ierr);
15362bf73ac6SHong Zhang   }
15372bf73ac6SHong Zhang 
15385f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
15395f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
15405f2c45f1SShri Abhyankar }
15415f2c45f1SShri Abhyankar 
154224121865SAdrian Maldonado /* Get a subsection from a range of points */
15439dddd249SSatish Balay static PetscErrorCode DMNetworkGetSubSection_private(PetscSection main,PetscInt pstart,PetscInt pend,PetscSection *subsection)
154424121865SAdrian Maldonado {
154524121865SAdrian Maldonado   PetscErrorCode ierr;
154624121865SAdrian Maldonado   PetscInt       i, nvar;
154724121865SAdrian Maldonado 
154824121865SAdrian Maldonado   PetscFunctionBegin;
15499dddd249SSatish Balay   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)main), subsection);CHKERRQ(ierr);
155024121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
155124121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
15529dddd249SSatish Balay     ierr = PetscSectionGetDof(main,i,&nvar);CHKERRQ(ierr);
155324121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
155424121865SAdrian Maldonado   }
155524121865SAdrian Maldonado 
155624121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
155724121865SAdrian Maldonado   PetscFunctionReturn(0);
155824121865SAdrian Maldonado }
155924121865SAdrian Maldonado 
156024121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
15612bf73ac6SHong Zhang static PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
156224121865SAdrian Maldonado {
156324121865SAdrian Maldonado   PetscErrorCode ierr;
156424121865SAdrian Maldonado   PetscInt       i, *subpoints;
156524121865SAdrian Maldonado 
156624121865SAdrian Maldonado   PetscFunctionBegin;
156724121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
156824121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
156924121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
157024121865SAdrian Maldonado     subpoints[i - pstart] = i;
157124121865SAdrian Maldonado   }
1572459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
157324121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
157424121865SAdrian Maldonado   PetscFunctionReturn(0);
157524121865SAdrian Maldonado }
157624121865SAdrian Maldonado 
157724121865SAdrian Maldonado /*@
15782bf73ac6SHong Zhang   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute
157924121865SAdrian Maldonado 
15802bf73ac6SHong Zhang   Collective on dm
158124121865SAdrian Maldonado 
158224121865SAdrian Maldonado   Input Parameters:
15832bf73ac6SHong Zhang . dm - the DMNetworkObject
158424121865SAdrian Maldonado 
158524121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
158624121865SAdrian Maldonado 
158724121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
158824121865SAdrian Maldonado 
1589caf410d2SHong Zhang   where edges = [0,1,2,3] and vertices = [4,5,6]. The new orderings will be specific to the subset (i.e vertices = [0,1,2] <- [4,5,6]).
159024121865SAdrian Maldonado 
159124121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
159224121865SAdrian Maldonado 
159324121865SAdrian Maldonado   Level: intermediate
159424121865SAdrian Maldonado 
159524121865SAdrian Maldonado @*/
159624121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
159724121865SAdrian Maldonado {
159824121865SAdrian Maldonado   PetscErrorCode ierr;
159924121865SAdrian Maldonado   MPI_Comm       comm;
1600f11a936eSBarry Smith   PetscMPIInt    size;
160124121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
160224121865SAdrian Maldonado 
1603eab1376dSHong Zhang   PetscFunctionBegin;
160424121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1605ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
160624121865SAdrian Maldonado 
160724121865SAdrian Maldonado   /* Create maps for vertices and edges */
160824121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
160924121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
161024121865SAdrian Maldonado 
161124121865SAdrian Maldonado   /* Create local sub-sections */
161224121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
161324121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
161424121865SAdrian Maldonado 
16159852e123SBarry Smith   if (size > 1) {
161624121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
161722bbedd7SHong Zhang 
161824121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
161924121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
162024121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
162124121865SAdrian Maldonado   } else {
162224121865SAdrian Maldonado     /* create structures for vertex */
162324121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
162424121865SAdrian Maldonado     /* create structures for edge */
162524121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
162624121865SAdrian Maldonado   }
162724121865SAdrian Maldonado 
162824121865SAdrian Maldonado   /* Add viewers */
162924121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
163024121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
163124121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
163224121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
163324121865SAdrian Maldonado   PetscFunctionReturn(0);
163424121865SAdrian Maldonado }
16357b6afd5bSHong Zhang 
1636f11a936eSBarry Smith /*
1637f11a936eSBarry Smith    Add all subnetid for the input vertex v in this process to the btable
1638f11a936eSBarry Smith    vertex_subnetid = supportingedge_subnetid
1639f11a936eSBarry Smith */
1640f11a936eSBarry Smith PETSC_STATIC_INLINE PetscErrorCode SetSubnetIdLookupBT(DM dm,PetscInt v,PetscInt Nsubnet,PetscBT btable)
1641f11a936eSBarry Smith {
1642f11a936eSBarry Smith   PetscErrorCode ierr;
1643f11a936eSBarry Smith   PetscInt       e,nedges,offset;
1644f11a936eSBarry Smith   const PetscInt *edges;
1645f11a936eSBarry Smith   DM_Network     *newDMnetwork = (DM_Network*)dm->data;
1646f11a936eSBarry Smith   DMNetworkComponentHeader header;
1647f11a936eSBarry Smith 
1648f11a936eSBarry Smith   PetscFunctionBegin;
1649f11a936eSBarry Smith   ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1650f11a936eSBarry Smith   ierr = PetscBTMemzero(Nsubnet,btable);CHKERRQ(ierr);
1651f11a936eSBarry Smith   for (e=0; e<nedges; e++) {
1652f11a936eSBarry Smith     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,edges[e],&offset);CHKERRQ(ierr);
1653f11a936eSBarry Smith     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
1654f11a936eSBarry Smith     ierr = PetscBTSet(btable,header->subnetid);CHKERRQ(ierr);
1655f11a936eSBarry Smith   }
1656f11a936eSBarry Smith   PetscFunctionReturn(0);
1657f11a936eSBarry Smith }
1658f11a936eSBarry Smith 
16595f2c45f1SShri Abhyankar /*@
16602bf73ac6SHong Zhang   DMNetworkDistribute - Distributes the network and moves associated component data
16615f2c45f1SShri Abhyankar 
16625f2c45f1SShri Abhyankar   Collective
16635f2c45f1SShri Abhyankar 
1664d8d19677SJose E. Roman   Input Parameters:
1665d3464fd4SAdrian Maldonado + DM - the DMNetwork object
16662bf73ac6SHong Zhang - overlap - the overlap of partitions, 0 is the default
16675f2c45f1SShri Abhyankar 
16685b3f975aSHong Zhang   Options Database Key:
16695b3f975aSHong Zhang + -dmnetwork_view - Calls DMView() at the conclusion of DMSetUp()
16705b3f975aSHong Zhang - -dmnetwork_view_distributed - Calls DMView() at the conclusion of DMNetworkDistribute()
16715b3f975aSHong Zhang 
16725f2c45f1SShri Abhyankar   Notes:
16738b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
16745f2c45f1SShri Abhyankar 
16755f2c45f1SShri Abhyankar   Level: intermediate
16765f2c45f1SShri Abhyankar 
16772bf73ac6SHong Zhang .seealso: DMNetworkCreate()
16785f2c45f1SShri Abhyankar @*/
1679d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
16805f2c45f1SShri Abhyankar {
1681d3464fd4SAdrian Maldonado   MPI_Comm       comm;
16825f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1683d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1684d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1685d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1686caf410d2SHong Zhang   PetscSF        pointsf=NULL;
16875f2c45f1SShri Abhyankar   DM             newDM;
1688f11a936eSBarry Smith   PetscInt       j,e,v,offset,*subnetvtx,*subnetedge,Nsubnet,gidx,svtx_idx,nv;
16892bf73ac6SHong Zhang   PetscInt       to_net,from_net,*svto;
1690f11a936eSBarry Smith   PetscBT        btable;
169151ac5effSHong Zhang   PetscPartitioner         part;
1692b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
16935f2c45f1SShri Abhyankar 
16945f2c45f1SShri Abhyankar   PetscFunctionBegin;
1695d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1696ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1697d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1698d3464fd4SAdrian Maldonado 
16995b3f975aSHong Zhang   if (overlap) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"overlap %D != 0 is not supported yet",overlap);
17005b3f975aSHong Zhang 
17012bf73ac6SHong Zhang   /* This routine moves the component data to the appropriate processors. It makes use of the DataSection and the componentdataarray to move the component data to appropriate processors and returns a new DataSection and new componentdataarray. */
1702d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
17035f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
170454dfd506SHong Zhang   newDMnetwork->max_comps_registered = oldDMnetwork->max_comps_registered;
170554dfd506SHong Zhang   ierr = PetscMalloc1(newDMnetwork->max_comps_registered,&newDMnetwork->component);CHKERRQ(ierr);
170651ac5effSHong Zhang 
170751ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
170851ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
170951ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
171051ac5effSHong Zhang 
17112bf73ac6SHong Zhang   /* Distribute plex dm */
171280cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
171351ac5effSHong Zhang 
17145f2c45f1SShri Abhyankar   /* Distribute dof section */
17152bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DofSection);CHKERRQ(ierr);
17165f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
171751ac5effSHong Zhang 
17185f2c45f1SShri Abhyankar   /* Distribute data and associated section */
17192bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DataSection);CHKERRQ(ierr);
172031da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
172124121865SAdrian Maldonado 
17225f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
17235f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
17245f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
17255f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
17266fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
17276fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
17285f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
1729f11a936eSBarry Smith   newDMnetwork->svtable   = oldDMnetwork->svtable; /* global table! */
17302bf73ac6SHong Zhang   oldDMnetwork->svtable   = NULL;
173124121865SAdrian Maldonado 
17321bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
173392fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1734e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
17355f2c45f1SShri Abhyankar 
1736b9c6e19dSShri Abhyankar   /* Setup subnetwork info in the newDM */
17372bf73ac6SHong Zhang   newDMnetwork->Nsubnet = oldDMnetwork->Nsubnet;
17382bf73ac6SHong Zhang   newDMnetwork->Nsvtx   = oldDMnetwork->Nsvtx;
17392bf73ac6SHong Zhang   oldDMnetwork->Nsvtx   = 0;
17402bf73ac6SHong Zhang   newDMnetwork->svtx    = oldDMnetwork->svtx; /* global vertices! */
17412bf73ac6SHong Zhang   oldDMnetwork->svtx    = NULL;
17422bf73ac6SHong Zhang   ierr = PetscCalloc1(newDMnetwork->Nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
17432bf73ac6SHong Zhang 
17442bf73ac6SHong Zhang   /* Copy over the global number of vertices and edges in each subnetwork.
17452bf73ac6SHong Zhang      Note: these are calculated in DMNetworkLayoutSetUp()
1746b9c6e19dSShri Abhyankar   */
1747f11a936eSBarry Smith   Nsubnet = newDMnetwork->Nsubnet;
1748f11a936eSBarry Smith   for (j = 0; j < Nsubnet; j++) {
1749b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1750b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1751b9c6e19dSShri Abhyankar   }
1752b9c6e19dSShri Abhyankar 
1753f11a936eSBarry Smith   /* Count local nedges for subnetworks */
1754b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1755b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
175654dfd506SHong Zhang     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
175754dfd506SHong Zhang     /* Update pointers */
175854dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
175954dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
176054dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
176154dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
176254dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
176354dfd506SHong Zhang 
1764b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1765b9c6e19dSShri Abhyankar   }
1766b9c6e19dSShri Abhyankar 
1767f11a936eSBarry Smith   /* Count local nvtx for subnetworks */
1768f11a936eSBarry Smith   ierr = PetscBTCreate(Nsubnet,&btable);CHKERRQ(ierr);
1769b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1770b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1771b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
177254dfd506SHong Zhang     /* Update pointers */
177354dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
177454dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
177554dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
177654dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
177754dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
177854dfd506SHong Zhang 
17792bf73ac6SHong Zhang     /* shared vertices: use gidx=header->index to check if v is a shared vertex */
17802bf73ac6SHong Zhang     gidx = header->index;
17812bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
17822bf73ac6SHong Zhang     svtx_idx--;
17832bf73ac6SHong Zhang 
17842bf73ac6SHong Zhang     if (svtx_idx < 0) { /* not a shared vertex */
1785b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].nvtx++;
17862bf73ac6SHong Zhang     } else { /* a shared vertex belongs to more than one subnetworks, it is being counted by multiple subnets */
1787f11a936eSBarry Smith       ierr = SetSubnetIdLookupBT(newDM,v,Nsubnet,btable);CHKERRQ(ierr);
1788f11a936eSBarry Smith 
17892bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
1790f11a936eSBarry Smith       if (PetscBTLookup(btable,from_net)) newDMnetwork->subnet[from_net].nvtx++; /* sv is on from_net */
1791f11a936eSBarry Smith 
17922bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
17932bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
17942bf73ac6SHong Zhang         to_net = svto[0];
1795f11a936eSBarry Smith         if (PetscBTLookup(btable,to_net)) newDMnetwork->subnet[to_net].nvtx++; /* sv is on to_net */
17962bf73ac6SHong Zhang       }
17972bf73ac6SHong Zhang     }
1798b9c6e19dSShri Abhyankar   }
1799b9c6e19dSShri Abhyankar 
18002bf73ac6SHong Zhang   /* Get total local nvtx for subnetworks */
18012bf73ac6SHong Zhang   nv = 0;
1802f11a936eSBarry Smith   for (j=0; j<Nsubnet; j++) nv += newDMnetwork->subnet[j].nvtx;
18032bf73ac6SHong Zhang   nv += newDMnetwork->Nsvtx;
1804caf410d2SHong Zhang 
18052bf73ac6SHong Zhang   /* Now create the vertices and edge arrays for the subnetworks */
1806f11a936eSBarry Smith   ierr = PetscCalloc2(newDMnetwork->nEdges,&subnetedge,nv,&subnetvtx);CHKERRQ(ierr); /* Maps local vertex to local subnetwork's vertex */
1807f11a936eSBarry Smith   newDMnetwork->subnetedge = subnetedge;
18082bf73ac6SHong Zhang   newDMnetwork->subnetvtx  = subnetvtx;
1809f11a936eSBarry Smith   for (j=0; j < newDMnetwork->Nsubnet; j++) {
1810f11a936eSBarry Smith     newDMnetwork->subnet[j].edges = subnetedge;
1811f11a936eSBarry Smith     subnetedge                   += newDMnetwork->subnet[j].nedge;
18122bf73ac6SHong Zhang 
1813caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1814caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1815caf410d2SHong Zhang 
18162bf73ac6SHong Zhang     /* Temporarily setting nvtx and nedge to 0 so we can use them as counters in the below for loop. These get updated when the vertices and edges are added. */
1817b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1818b9c6e19dSShri Abhyankar   }
18192bf73ac6SHong Zhang   newDMnetwork->svertices = subnetvtx;
1820b9c6e19dSShri Abhyankar 
18212bf73ac6SHong Zhang   /* Set the edges and vertices in each subnetwork */
1822b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1823b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1824b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1825b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1826b9c6e19dSShri Abhyankar   }
1827b9c6e19dSShri Abhyankar 
18282bf73ac6SHong Zhang   nv = 0;
1829b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1830b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1831b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
18322bf73ac6SHong Zhang 
18332bf73ac6SHong Zhang     /* coupling vertices: use gidx = header->index to check if v is a coupling vertex */
18342bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,header->index+1,&svtx_idx);CHKERRQ(ierr);
18352bf73ac6SHong Zhang     svtx_idx--;
18362bf73ac6SHong Zhang     if (svtx_idx < 0) {
1837b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
18382bf73ac6SHong Zhang     } else { /* a shared vertex */
18392bf73ac6SHong Zhang       newDMnetwork->svertices[nv++] = v;
18402bf73ac6SHong Zhang 
1841f11a936eSBarry Smith       /* add all subnetid for this shared vertex in this process to btable */
1842f11a936eSBarry Smith       ierr = SetSubnetIdLookupBT(newDM,v,Nsubnet,btable);CHKERRQ(ierr);
1843f11a936eSBarry Smith 
18442bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
1845f11a936eSBarry Smith       if (PetscBTLookup(btable,from_net))
18462bf73ac6SHong Zhang         newDMnetwork->subnet[from_net].vertices[newDMnetwork->subnet[from_net].nvtx++] = v;
18472bf73ac6SHong Zhang 
18482bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
18492bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
18502bf73ac6SHong Zhang         to_net = svto[0];
1851f11a936eSBarry Smith         if (PetscBTLookup(btable,to_net))
18522bf73ac6SHong Zhang           newDMnetwork->subnet[to_net].vertices[newDMnetwork->subnet[to_net].nvtx++] = v;
1853b9c6e19dSShri Abhyankar       }
18542bf73ac6SHong Zhang     }
18552bf73ac6SHong Zhang   }
18562bf73ac6SHong Zhang   newDMnetwork->nsvtx = nv;   /* num of local shared vertices */
1857b9c6e19dSShri Abhyankar 
1858caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
185922bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1860caf410d2SHong Zhang 
18612bf73ac6SHong Zhang   /* Free spaces */
186224121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
1863d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
1864f11a936eSBarry Smith   ierr = PetscBTDestroy(&btable);CHKERRQ(ierr);
18652bf73ac6SHong Zhang 
18665b3f975aSHong Zhang   /* View distributed dmnetwork */
18675b3f975aSHong Zhang   ierr = DMViewFromOptions(newDM,NULL,"-dmnetwork_view_distributed");CHKERRQ(ierr);
18685b3f975aSHong Zhang 
1869d3464fd4SAdrian Maldonado   *dm  = newDM;
18705f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18715f2c45f1SShri Abhyankar }
18725f2c45f1SShri Abhyankar 
187324121865SAdrian Maldonado /*@C
18742bf73ac6SHong Zhang   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering
18752bf73ac6SHong Zhang 
18762bf73ac6SHong Zhang  Collective
187724121865SAdrian Maldonado 
187824121865SAdrian Maldonado   Input Parameters:
18799dddd249SSatish Balay + mainSF - the original SF structure
188024121865SAdrian Maldonado - map - a ISLocalToGlobal mapping that contains the subset of points
188124121865SAdrian Maldonado 
188297bb3fdcSJose E. Roman   Output Parameter:
18839dddd249SSatish Balay . subSF - a subset of the mainSF for the desired subset.
1884ee300463SSatish Balay 
1885ee300463SSatish Balay   Level: intermediate
18867d928bffSSatish Balay @*/
18879dddd249SSatish Balay PetscErrorCode PetscSFGetSubSF(PetscSF mainsf,ISLocalToGlobalMapping map,PetscSF *subSF)
18882bf73ac6SHong Zhang {
188924121865SAdrian Maldonado   PetscErrorCode        ierr;
189024121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
189124121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
189224121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
189324121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
189424121865SAdrian Maldonado   const PetscInt        *ilocal;
189524121865SAdrian Maldonado   const PetscSFNode     *iremote;
189624121865SAdrian Maldonado 
189724121865SAdrian Maldonado   PetscFunctionBegin;
18989dddd249SSatish Balay   ierr = PetscSFGetGraph(mainsf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
189924121865SAdrian Maldonado 
190024121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
190124121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
190224121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
190324121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
190424121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
190524121865SAdrian Maldonado   }
190624121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
190724121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
190824121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
190924121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
1910ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
1911ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
191224121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
19134b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
19144b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
191524121865SAdrian Maldonado   nleaves_sub = 0;
191624121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
191724121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
191824121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
19194b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
192024121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
192124121865SAdrian Maldonado       nleaves_sub += 1;
192224121865SAdrian Maldonado     }
192324121865SAdrian Maldonado   }
192424121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
192524121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
192624121865SAdrian Maldonado 
192724121865SAdrian Maldonado   /* Create new subSF */
192824121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
192924121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
19304b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
193124121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
19324b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
193324121865SAdrian Maldonado   PetscFunctionReturn(0);
193424121865SAdrian Maldonado }
193524121865SAdrian Maldonado 
19365f2c45f1SShri Abhyankar /*@C
19375f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
19385f2c45f1SShri Abhyankar 
19395f2c45f1SShri Abhyankar   Not Collective
19405f2c45f1SShri Abhyankar 
19415f2c45f1SShri Abhyankar   Input Parameters:
19422bf73ac6SHong Zhang + dm - the DMNetwork object
19435f2c45f1SShri Abhyankar - p  - the vertex point
19445f2c45f1SShri Abhyankar 
1945fd292e60Sprj-   Output Parameters:
19465f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
19472bf73ac6SHong Zhang - edges  - list of edge points
19485f2c45f1SShri Abhyankar 
194997bb938eSShri Abhyankar   Level: beginner
19505f2c45f1SShri Abhyankar 
19515f2c45f1SShri Abhyankar   Fortran Notes:
19525f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
19535f2c45f1SShri Abhyankar   include petsc.h90 in your code.
19545f2c45f1SShri Abhyankar 
19552bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetConnectedVertices()
19565f2c45f1SShri Abhyankar @*/
19575f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
19585f2c45f1SShri Abhyankar {
19595f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19605f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19615f2c45f1SShri Abhyankar 
19625f2c45f1SShri Abhyankar   PetscFunctionBegin;
19635f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
1964a9b4a83eSHong Zhang   if (edges) {ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);}
19655f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19665f2c45f1SShri Abhyankar }
19675f2c45f1SShri Abhyankar 
19685f2c45f1SShri Abhyankar /*@C
1969d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
19705f2c45f1SShri Abhyankar 
19715f2c45f1SShri Abhyankar   Not Collective
19725f2c45f1SShri Abhyankar 
19735f2c45f1SShri Abhyankar   Input Parameters:
19742bf73ac6SHong Zhang + dm - the DMNetwork object
19755f2c45f1SShri Abhyankar - p - the edge point
19765f2c45f1SShri Abhyankar 
1977fd292e60Sprj-   Output Parameters:
19785f2c45f1SShri Abhyankar . vertices - vertices connected to this edge
19795f2c45f1SShri Abhyankar 
198097bb938eSShri Abhyankar   Level: beginner
19815f2c45f1SShri Abhyankar 
19825f2c45f1SShri Abhyankar   Fortran Notes:
19835f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
19845f2c45f1SShri Abhyankar   include petsc.h90 in your code.
19855f2c45f1SShri Abhyankar 
19862bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetSupportingEdges()
19875f2c45f1SShri Abhyankar @*/
1988d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
19895f2c45f1SShri Abhyankar {
19905f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19915f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19925f2c45f1SShri Abhyankar 
19935f2c45f1SShri Abhyankar   PetscFunctionBegin;
19945f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
19955f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19965f2c45f1SShri Abhyankar }
19975f2c45f1SShri Abhyankar 
19985f2c45f1SShri Abhyankar /*@
19992bf73ac6SHong Zhang   DMNetworkIsSharedVertex - Returns TRUE if the vertex is shared by subnetworks
20002bf73ac6SHong Zhang 
20012bf73ac6SHong Zhang   Not Collective
20022bf73ac6SHong Zhang 
20032bf73ac6SHong Zhang   Input Parameters:
20042bf73ac6SHong Zhang + dm - the DMNetwork object
20052bf73ac6SHong Zhang - p - the vertex point
20062bf73ac6SHong Zhang 
20072bf73ac6SHong Zhang   Output Parameter:
20082bf73ac6SHong Zhang . flag - TRUE if the vertex is shared by subnetworks
20092bf73ac6SHong Zhang 
20102bf73ac6SHong Zhang   Level: beginner
20112bf73ac6SHong Zhang 
20122bf73ac6SHong Zhang .seealso: DMNetworkAddSharedVertices(), DMNetworkIsGhostVertex()
20132bf73ac6SHong Zhang @*/
20142bf73ac6SHong Zhang PetscErrorCode DMNetworkIsSharedVertex(DM dm,PetscInt p,PetscBool *flag)
20152bf73ac6SHong Zhang {
20162bf73ac6SHong Zhang   PetscErrorCode ierr;
20172bf73ac6SHong Zhang   PetscInt       i;
20182bf73ac6SHong Zhang 
20192bf73ac6SHong Zhang   PetscFunctionBegin;
20202bf73ac6SHong Zhang   *flag = PETSC_FALSE;
20212bf73ac6SHong Zhang 
20222bf73ac6SHong Zhang   if (dm->setupcalled) { /* DMNetworkGetGlobalVertexIndex() requires DMSetUp() be called */
20232bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
20242bf73ac6SHong Zhang     PetscInt       gidx;
20252bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVertexIndex(dm,p,&gidx);CHKERRQ(ierr);
20262bf73ac6SHong Zhang     ierr = PetscTableFind(network->svtable,gidx+1,&i);CHKERRQ(ierr);
20272bf73ac6SHong Zhang     if (i) *flag = PETSC_TRUE;
20282bf73ac6SHong Zhang   } else { /* would be removed? */
20292bf73ac6SHong Zhang     PetscInt       nv;
20302bf73ac6SHong Zhang     const PetscInt *vtx;
20312bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nv,&vtx);CHKERRQ(ierr);
20322bf73ac6SHong Zhang     for (i=0; i<nv; i++) {
20332bf73ac6SHong Zhang       if (p == vtx[i]) {
20342bf73ac6SHong Zhang         *flag = PETSC_TRUE;
20352bf73ac6SHong Zhang         break;
20362bf73ac6SHong Zhang       }
20372bf73ac6SHong Zhang     }
20382bf73ac6SHong Zhang   }
20392bf73ac6SHong Zhang   PetscFunctionReturn(0);
20402bf73ac6SHong Zhang }
20412bf73ac6SHong Zhang 
20422bf73ac6SHong Zhang /*@
20435f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
20445f2c45f1SShri Abhyankar 
20455f2c45f1SShri Abhyankar   Not Collective
20465f2c45f1SShri Abhyankar 
20475f2c45f1SShri Abhyankar   Input Parameters:
20482bf73ac6SHong Zhang + dm - the DMNetwork object
2049a2b725a8SWilliam Gropp - p - the vertex point
20505f2c45f1SShri Abhyankar 
20515f2c45f1SShri Abhyankar   Output Parameter:
20525f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
20535f2c45f1SShri Abhyankar 
205497bb938eSShri Abhyankar   Level: beginner
20555f2c45f1SShri Abhyankar 
20562bf73ac6SHong Zhang .seealso: DMNetworkGetConnectedVertices(), DMNetworkGetVertexRange(), DMNetworkIsSharedVertex()
20575f2c45f1SShri Abhyankar @*/
20585f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
20595f2c45f1SShri Abhyankar {
20605f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20615f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20625f2c45f1SShri Abhyankar   PetscInt       offsetg;
20635f2c45f1SShri Abhyankar   PetscSection   sectiong;
20645f2c45f1SShri Abhyankar 
20655f2c45f1SShri Abhyankar   PetscFunctionBegin;
20665f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
2067e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
20685f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
20695f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
20705f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20715f2c45f1SShri Abhyankar }
20725f2c45f1SShri Abhyankar 
20735f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
20745f2c45f1SShri Abhyankar {
20755f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20765f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
20775f2c45f1SShri Abhyankar 
20785f2c45f1SShri Abhyankar   PetscFunctionBegin;
20795f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
20805f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
20815f2c45f1SShri Abhyankar 
208292fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
2083e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
20849e1d080bSHong Zhang 
20859e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
20865b3f975aSHong Zhang 
20875b3f975aSHong Zhang   /* View dmnetwork */
20885b3f975aSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dmnetwork_view");CHKERRQ(ierr);
20895f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20905f2c45f1SShri Abhyankar }
20915f2c45f1SShri Abhyankar 
20921ad426b7SHong Zhang /*@
209317df6e9eSHong Zhang   DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
20941ad426b7SHong Zhang       -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
20951ad426b7SHong Zhang 
20961ad426b7SHong Zhang   Collective
20971ad426b7SHong Zhang 
20981ad426b7SHong Zhang   Input Parameters:
20992bf73ac6SHong Zhang + dm - the DMNetwork object
210083b2e829SHong Zhang . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
210183b2e829SHong Zhang - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
21021ad426b7SHong Zhang 
21031ad426b7SHong Zhang  Level: intermediate
21041ad426b7SHong Zhang 
21051ad426b7SHong Zhang @*/
210683b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
21071ad426b7SHong Zhang {
21081ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
21098675203cSHong Zhang   PetscErrorCode ierr;
211066b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
21111ad426b7SHong Zhang 
21121ad426b7SHong Zhang   PetscFunctionBegin;
211383b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
211483b2e829SHong Zhang   network->userVertexJacobian = vflg;
21158675203cSHong Zhang 
21168675203cSHong Zhang   if (eflg && !network->Je) {
21178675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
21188675203cSHong Zhang   }
21198675203cSHong Zhang 
212066b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
21218675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
212266b4e0ffSHong Zhang     PetscInt       nedges_total;
21238675203cSHong Zhang     const PetscInt *edges;
21248675203cSHong Zhang 
21258675203cSHong Zhang     /* count nvertex_total */
21268675203cSHong Zhang     nedges_total = 0;
21278675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
21288675203cSHong Zhang 
21298675203cSHong Zhang     vptr[0] = 0;
21308675203cSHong Zhang     for (i=0; i<nVertices; i++) {
21318675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
21328675203cSHong Zhang       nedges_total += nedges;
21338675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
21348675203cSHong Zhang     }
21358675203cSHong Zhang 
21368675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
21378675203cSHong Zhang     network->Jvptr = vptr;
21388675203cSHong Zhang   }
21391ad426b7SHong Zhang   PetscFunctionReturn(0);
21401ad426b7SHong Zhang }
21411ad426b7SHong Zhang 
21421ad426b7SHong Zhang /*@
214383b2e829SHong Zhang   DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
214483b2e829SHong Zhang 
214583b2e829SHong Zhang   Not Collective
214683b2e829SHong Zhang 
214783b2e829SHong Zhang   Input Parameters:
21482bf73ac6SHong Zhang + dm - the DMNetwork object
214983b2e829SHong Zhang . p - the edge point
21503e97b6e8SHong Zhang - J - array (size = 3) of Jacobian submatrices for this edge point:
21513e97b6e8SHong Zhang         J[0]: this edge
2152d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
215383b2e829SHong Zhang 
215497bb938eSShri Abhyankar   Level: advanced
215583b2e829SHong Zhang 
21562bf73ac6SHong Zhang .seealso: DMNetworkVertexSetMatrix()
215783b2e829SHong Zhang @*/
215883b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
215983b2e829SHong Zhang {
216083b2e829SHong Zhang   DM_Network *network=(DM_Network*)dm->data;
216183b2e829SHong Zhang 
216283b2e829SHong Zhang   PetscFunctionBegin;
21638675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
21648675203cSHong Zhang 
21658675203cSHong Zhang   if (J) {
2166883e35e8SHong Zhang     network->Je[3*p]   = J[0];
2167883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
2168883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
21698675203cSHong Zhang   }
217083b2e829SHong Zhang   PetscFunctionReturn(0);
217183b2e829SHong Zhang }
217283b2e829SHong Zhang 
217383b2e829SHong Zhang /*@
217476ddfea5SHong Zhang   DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
21751ad426b7SHong Zhang 
21761ad426b7SHong Zhang   Not Collective
21771ad426b7SHong Zhang 
21781ad426b7SHong Zhang   Input Parameters:
21791ad426b7SHong Zhang + dm - The DMNetwork object
21801ad426b7SHong Zhang . p - the vertex point
21813e97b6e8SHong Zhang - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
21823e97b6e8SHong Zhang         J[0]:       this vertex
21833e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
21843e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
21851ad426b7SHong Zhang 
218697bb938eSShri Abhyankar   Level: advanced
21871ad426b7SHong Zhang 
21882bf73ac6SHong Zhang .seealso: DMNetworkEdgeSetMatrix()
21891ad426b7SHong Zhang @*/
2190883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
21915f2c45f1SShri Abhyankar {
21925f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21935f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
21948675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
2195883e35e8SHong Zhang   const PetscInt *edges;
21965f2c45f1SShri Abhyankar 
21975f2c45f1SShri Abhyankar   PetscFunctionBegin;
21988675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
2199883e35e8SHong Zhang 
22008675203cSHong Zhang   if (J) {
2201883e35e8SHong Zhang     vptr = network->Jvptr;
22023e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
22033e97b6e8SHong Zhang 
22043e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
2205883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
2206883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
22078675203cSHong Zhang   }
2208883e35e8SHong Zhang   PetscFunctionReturn(0);
2209883e35e8SHong Zhang }
2210883e35e8SHong Zhang 
2211e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
22125cf7da58SHong Zhang {
22135cf7da58SHong Zhang   PetscErrorCode ierr;
22145cf7da58SHong Zhang   PetscInt       j;
22155cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
22165cf7da58SHong Zhang 
22175cf7da58SHong Zhang   PetscFunctionBegin;
22185cf7da58SHong Zhang   if (!ghost) {
22195cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22205cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22215cf7da58SHong Zhang     }
22225cf7da58SHong Zhang   } else {
22235cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22245cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22255cf7da58SHong Zhang     }
22265cf7da58SHong Zhang   }
22275cf7da58SHong Zhang   PetscFunctionReturn(0);
22285cf7da58SHong Zhang }
22295cf7da58SHong Zhang 
2230e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
22315cf7da58SHong Zhang {
22325cf7da58SHong Zhang   PetscErrorCode ierr;
22335cf7da58SHong Zhang   PetscInt       j,ncols_u;
22345cf7da58SHong Zhang   PetscScalar    val;
22355cf7da58SHong Zhang 
22365cf7da58SHong Zhang   PetscFunctionBegin;
22375cf7da58SHong Zhang   if (!ghost) {
22385cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22395cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22405cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
22415cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22425cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22435cf7da58SHong Zhang     }
22445cf7da58SHong Zhang   } else {
22455cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22465cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22475cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
22485cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22495cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22505cf7da58SHong Zhang     }
22515cf7da58SHong Zhang   }
22525cf7da58SHong Zhang   PetscFunctionReturn(0);
22535cf7da58SHong Zhang }
22545cf7da58SHong Zhang 
2255e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
22565cf7da58SHong Zhang {
22575cf7da58SHong Zhang   PetscErrorCode ierr;
22585cf7da58SHong Zhang 
22595cf7da58SHong Zhang   PetscFunctionBegin;
22605cf7da58SHong Zhang   if (Ju) {
22615cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
22625cf7da58SHong Zhang   } else {
22635cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
22645cf7da58SHong Zhang   }
22655cf7da58SHong Zhang   PetscFunctionReturn(0);
22665cf7da58SHong Zhang }
22675cf7da58SHong Zhang 
2268e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2269883e35e8SHong Zhang {
2270883e35e8SHong Zhang   PetscErrorCode ierr;
2271883e35e8SHong Zhang   PetscInt       j,*cols;
2272883e35e8SHong Zhang   PetscScalar    *zeros;
2273883e35e8SHong Zhang 
2274883e35e8SHong Zhang   PetscFunctionBegin;
2275883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
2276883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
2277883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
2278883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
22791ad426b7SHong Zhang   PetscFunctionReturn(0);
22801ad426b7SHong Zhang }
2281a4e85ca8SHong Zhang 
2282e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
22833e97b6e8SHong Zhang {
22843e97b6e8SHong Zhang   PetscErrorCode ierr;
22853e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
22863e97b6e8SHong Zhang   const PetscInt *cols;
22873e97b6e8SHong Zhang   PetscScalar    zero=0.0;
22883e97b6e8SHong Zhang 
22893e97b6e8SHong Zhang   PetscFunctionBegin;
22903e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
22913e97b6e8SHong 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);
22923e97b6e8SHong Zhang 
22933e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
22943e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
22953e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
22963e97b6e8SHong Zhang       col = cols[j] + cstart;
22973e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
22983e97b6e8SHong Zhang     }
22993e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
23003e97b6e8SHong Zhang   }
23013e97b6e8SHong Zhang   PetscFunctionReturn(0);
23023e97b6e8SHong Zhang }
23031ad426b7SHong Zhang 
2304e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2305a4e85ca8SHong Zhang {
2306a4e85ca8SHong Zhang   PetscErrorCode ierr;
2307f4431b8cSHong Zhang 
2308a4e85ca8SHong Zhang   PetscFunctionBegin;
2309a4e85ca8SHong Zhang   if (Ju) {
2310a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2311a4e85ca8SHong Zhang   } else {
2312a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2313a4e85ca8SHong Zhang   }
2314a4e85ca8SHong Zhang   PetscFunctionReturn(0);
2315a4e85ca8SHong Zhang }
2316a4e85ca8SHong Zhang 
231724121865SAdrian 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.
231824121865SAdrian Maldonado */
231924121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
232024121865SAdrian Maldonado {
232124121865SAdrian Maldonado   PetscErrorCode ierr;
232224121865SAdrian Maldonado   PetscInt       i,size,dof;
232324121865SAdrian Maldonado   PetscInt       *glob2loc;
232424121865SAdrian Maldonado 
232524121865SAdrian Maldonado   PetscFunctionBegin;
232624121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
232724121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
232824121865SAdrian Maldonado 
232924121865SAdrian Maldonado   for (i = 0; i < size; i++) {
233024121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
233124121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
233224121865SAdrian Maldonado     glob2loc[i] = dof;
233324121865SAdrian Maldonado   }
233424121865SAdrian Maldonado 
233524121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
233624121865SAdrian Maldonado #if 0
233724121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
233824121865SAdrian Maldonado #endif
233924121865SAdrian Maldonado   PetscFunctionReturn(0);
234024121865SAdrian Maldonado }
234124121865SAdrian Maldonado 
234201ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
23439e1d080bSHong Zhang 
23449e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
23451ad426b7SHong Zhang {
23461ad426b7SHong Zhang   PetscErrorCode ierr;
23471ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
234824121865SAdrian Maldonado   PetscInt       eDof,vDof;
234924121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
23509e1d080bSHong Zhang   MPI_Comm       comm;
235124121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
235224121865SAdrian Maldonado 
23539e1d080bSHong Zhang   PetscFunctionBegin;
235424121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
235524121865SAdrian Maldonado 
235624121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
235724121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
235824121865SAdrian Maldonado 
235901ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
236024121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
236124121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
236224121865SAdrian Maldonado 
236301ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
236424121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
236524121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
236624121865SAdrian Maldonado 
236701ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
236824121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
236924121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
237024121865SAdrian Maldonado 
237101ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
237224121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
237324121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
237424121865SAdrian Maldonado 
23753f6a6bdaSHong Zhang   bA[0][0] = j11;
23763f6a6bdaSHong Zhang   bA[0][1] = j12;
23773f6a6bdaSHong Zhang   bA[1][0] = j21;
23783f6a6bdaSHong Zhang   bA[1][1] = j22;
237924121865SAdrian Maldonado 
238024121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
238124121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
238224121865SAdrian Maldonado 
238324121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
238424121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
238524121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
238624121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
238724121865SAdrian Maldonado 
238824121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
238924121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
239024121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
239124121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
239224121865SAdrian Maldonado 
239301ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
239424121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
239524121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
239624121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
239724121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
239824121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
239924121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
240024121865SAdrian Maldonado 
240124121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
240224121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24039e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
240424121865SAdrian Maldonado 
240524121865SAdrian Maldonado   /* Free structures */
240624121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
240724121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
240824121865SAdrian Maldonado   PetscFunctionReturn(0);
24099e1d080bSHong Zhang }
24109e1d080bSHong Zhang 
24119e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
24129e1d080bSHong Zhang {
24139e1d080bSHong Zhang   PetscErrorCode ierr;
24149e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
24159e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
24169e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
24179e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
24189e1d080bSHong Zhang   Mat            Juser;
24199e1d080bSHong Zhang   PetscSection   sectionGlobal;
24209e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
24219e1d080bSHong Zhang   const PetscInt *edges,*cone;
24229e1d080bSHong Zhang   MPI_Comm       comm;
24239e1d080bSHong Zhang   MatType        mtype;
24249e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
24259e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
24269e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
24279e1d080bSHong Zhang 
24289e1d080bSHong Zhang   PetscFunctionBegin;
24299e1d080bSHong Zhang   mtype = dm->mattype;
24309e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
24319e1d080bSHong Zhang   if (isNest) {
24329e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
2433c6b011d8SStefano Zampini     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
24349e1d080bSHong Zhang     PetscFunctionReturn(0);
24359e1d080bSHong Zhang   }
24369e1d080bSHong Zhang 
24379e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
2438a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
24399e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
2440bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
24411ad426b7SHong Zhang     PetscFunctionReturn(0);
24421ad426b7SHong Zhang   }
24431ad426b7SHong Zhang 
2444bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
2445e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
2446bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
2447bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
24482a945128SHong Zhang 
24492a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
24502a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
245189898e50SHong Zhang 
245289898e50SHong Zhang   /* (1) Set matrix preallocation */
245389898e50SHong Zhang   /*------------------------------*/
2454840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2455840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
2456840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
2457840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
2458840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
2459840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
2460840c2264SHong Zhang 
246189898e50SHong Zhang   /* Set preallocation for edges */
246289898e50SHong Zhang   /*-----------------------------*/
2463840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
2464840c2264SHong Zhang 
2465bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
2466840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
2467840c2264SHong Zhang     /* Get row indices */
24682bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
24692bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
2470840c2264SHong Zhang     if (nrows) {
2471840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
2472840c2264SHong Zhang 
2473a5b23f4aSJose E. Roman       /* Set preallocation for connected vertices */
2474d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2475840c2264SHong Zhang       for (v=0; v<2; v++) {
24762bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
2477840c2264SHong Zhang 
24788675203cSHong Zhang         if (network->Je) {
2479840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
24808675203cSHong Zhang         } else Juser = NULL;
2481840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
24825cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2483840c2264SHong Zhang       }
2484840c2264SHong Zhang 
248589898e50SHong Zhang       /* Set preallocation for edge self */
2486840c2264SHong Zhang       cstart = rstart;
24878675203cSHong Zhang       if (network->Je) {
2488840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
24898675203cSHong Zhang       } else Juser = NULL;
24905cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2491840c2264SHong Zhang     }
2492840c2264SHong Zhang   }
2493840c2264SHong Zhang 
249489898e50SHong Zhang   /* Set preallocation for vertices */
249589898e50SHong Zhang   /*--------------------------------*/
2496840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
24978675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
2498840c2264SHong Zhang 
2499840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
2500840c2264SHong Zhang     /* Get row indices */
25012bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
25022bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
2503840c2264SHong Zhang     if (!nrows) continue;
2504840c2264SHong Zhang 
2505bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2506bdcb62a2SHong Zhang     if (ghost) {
2507bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2508bdcb62a2SHong Zhang     } else {
2509bdcb62a2SHong Zhang       rows_v = rows;
2510bdcb62a2SHong Zhang     }
2511bdcb62a2SHong Zhang 
2512bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2513840c2264SHong Zhang 
2514840c2264SHong Zhang     /* Get supporting edges and connected vertices */
2515840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2516840c2264SHong Zhang 
2517840c2264SHong Zhang     for (e=0; e<nedges; e++) {
2518840c2264SHong Zhang       /* Supporting edges */
25192bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25202bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2521840c2264SHong Zhang 
25228675203cSHong Zhang       if (network->Jv) {
2523840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
25248675203cSHong Zhang       } else Juser = NULL;
2525bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2526840c2264SHong Zhang 
2527840c2264SHong Zhang       /* Connected vertices */
2528d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
2529840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
2530840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
2531840c2264SHong Zhang 
25322bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2533840c2264SHong Zhang 
25348675203cSHong Zhang       if (network->Jv) {
2535840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
25368675203cSHong Zhang       } else Juser = NULL;
2537e102a522SHong Zhang       if (ghost_vc||ghost) {
2538e102a522SHong Zhang         ghost2 = PETSC_TRUE;
2539e102a522SHong Zhang       } else {
2540e102a522SHong Zhang         ghost2 = PETSC_FALSE;
2541e102a522SHong Zhang       }
2542e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
2543840c2264SHong Zhang     }
2544840c2264SHong Zhang 
254589898e50SHong Zhang     /* Set preallocation for vertex self */
2546840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2547840c2264SHong Zhang     if (!ghost) {
25482bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25498675203cSHong Zhang       if (network->Jv) {
2550840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
25518675203cSHong Zhang       } else Juser = NULL;
2552bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2553840c2264SHong Zhang     }
2554bdcb62a2SHong Zhang     if (ghost) {
2555bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2556bdcb62a2SHong Zhang     }
2557840c2264SHong Zhang   }
2558840c2264SHong Zhang 
2559840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
2560840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
25615cf7da58SHong Zhang 
25625cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
25635cf7da58SHong Zhang 
25645cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
2565840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
2566840c2264SHong Zhang 
2567840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
2568840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
2569840c2264SHong Zhang   for (j=0; j<localSize; j++) {
2570e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
2571e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
2572840c2264SHong Zhang   }
2573840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
2574840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
2575840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
2576840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
2577840c2264SHong Zhang 
25785cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
25795cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
25805cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
25815cf7da58SHong Zhang 
25825cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
25835cf7da58SHong Zhang 
258489898e50SHong Zhang   /* (2) Set matrix entries for edges */
258589898e50SHong Zhang   /*----------------------------------*/
25861ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
2587bfbc38dcSHong Zhang     /* Get row indices */
25882bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
25892bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
25904b976069SHong Zhang     if (nrows) {
259117df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
25921ad426b7SHong Zhang 
2593a5b23f4aSJose E. Roman       /* Set matrix entries for connected vertices */
2594d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2595bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
25962bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVecOffset(dm,cone[v],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25972bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
25983e97b6e8SHong Zhang 
25998675203cSHong Zhang         if (network->Je) {
2600a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
26018675203cSHong Zhang         } else Juser = NULL;
2602a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2603bfbc38dcSHong Zhang       }
260417df6e9eSHong Zhang 
2605bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
26063e97b6e8SHong Zhang       cstart = rstart;
26078675203cSHong Zhang       if (network->Je) {
2608a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
26098675203cSHong Zhang       } else Juser = NULL;
2610a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
26111ad426b7SHong Zhang     }
26124b976069SHong Zhang   }
26131ad426b7SHong Zhang 
2614bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
261583b2e829SHong Zhang   /*---------------------------------*/
26161ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2617bfbc38dcSHong Zhang     /* Get row indices */
26182bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
26192bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
26204b976069SHong Zhang     if (!nrows) continue;
2621596e729fSHong Zhang 
2622bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2623bdcb62a2SHong Zhang     if (ghost) {
2624bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2625bdcb62a2SHong Zhang     } else {
2626bdcb62a2SHong Zhang       rows_v = rows;
2627bdcb62a2SHong Zhang     }
2628bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2629596e729fSHong Zhang 
2630bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2631596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2632596e729fSHong Zhang 
2633596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2634bfbc38dcSHong Zhang       /* Supporting edges */
26352bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
26362bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2637596e729fSHong Zhang 
26388675203cSHong Zhang       if (network->Jv) {
2639a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
26408675203cSHong Zhang       } else Juser = NULL;
2641bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2642596e729fSHong Zhang 
2643bfbc38dcSHong Zhang       /* Connected vertices */
2644d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
26452a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
26462a945128SHong Zhang 
26472bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,vc,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
26482bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2649a4e85ca8SHong Zhang 
26508675203cSHong Zhang       if (network->Jv) {
2651a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
26528675203cSHong Zhang       } else Juser = NULL;
2653bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2654596e729fSHong Zhang     }
2655596e729fSHong Zhang 
2656bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
26571ad426b7SHong Zhang     if (!ghost) {
26582bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
26598675203cSHong Zhang       if (network->Jv) {
2660a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
26618675203cSHong Zhang       } else Juser = NULL;
2662bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2663bdcb62a2SHong Zhang     }
2664bdcb62a2SHong Zhang     if (ghost) {
2665bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2666bdcb62a2SHong Zhang     }
26671ad426b7SHong Zhang   }
2668a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2669bdcb62a2SHong Zhang 
26701ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
26711ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2672dd6f46cdSHong Zhang 
26735f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
26745f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26755f2c45f1SShri Abhyankar }
26765f2c45f1SShri Abhyankar 
26775f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
26785f2c45f1SShri Abhyankar {
26795f2c45f1SShri Abhyankar   PetscErrorCode ierr;
26805f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
268154dfd506SHong Zhang   PetscInt       j,np;
26825f2c45f1SShri Abhyankar 
26835f2c45f1SShri Abhyankar   PetscFunctionBegin;
26848415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
268583b2e829SHong Zhang   if (network->Je) {
268683b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
268783b2e829SHong Zhang   }
268883b2e829SHong Zhang   if (network->Jv) {
2689883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
269083b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
26911ad426b7SHong Zhang   }
269213c2a604SAdrian Maldonado 
269313c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
269413c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
269513c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2696f5427c60SHong Zhang   if (network->vltog) {
2697f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2698f5427c60SHong Zhang   }
269913c2a604SAdrian Maldonado   if (network->vertex.sf) {
270013c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
270113c2a604SAdrian Maldonado   }
270213c2a604SAdrian Maldonado   /* edge */
270313c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
270413c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
270513c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
270613c2a604SAdrian Maldonado   if (network->edge.sf) {
270713c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
270813c2a604SAdrian Maldonado   }
27095f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
27105f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
27115f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
271283b2e829SHong Zhang 
27132bf73ac6SHong Zhang   for (j=0; j<network->Nsvtx; j++) {
27142bf73ac6SHong Zhang     ierr = PetscFree(network->svtx[j].sv);CHKERRQ(ierr);
27152bf73ac6SHong Zhang   }
27162bf73ac6SHong Zhang   if (network->svtx) {ierr = PetscFree(network->svtx);CHKERRQ(ierr);}
2717f11a936eSBarry Smith   ierr = PetscFree2(network->subnetedge,network->subnetvtx);CHKERRQ(ierr);
2718caf410d2SHong Zhang 
27192bf73ac6SHong Zhang   ierr = PetscTableDestroy(&network->svtable);CHKERRQ(ierr);
2720e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
272154dfd506SHong Zhang   ierr = PetscFree(network->component);CHKERRQ(ierr);
27225f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
272354dfd506SHong Zhang 
272454dfd506SHong Zhang   if (network->header) {
272554dfd506SHong Zhang     np = network->pEnd - network->pStart;
272654dfd506SHong Zhang     for (j=0; j < np; j++) {
272754dfd506SHong Zhang       ierr = PetscFree5(network->header[j].size,network->header[j].key,network->header[j].offset,network->header[j].nvar,network->header[j].offsetvarrel);CHKERRQ(ierr);
272854dfd506SHong Zhang       ierr = PetscFree(network->cvalue[j].data);CHKERRQ(ierr);
272954dfd506SHong Zhang     }
2730caf410d2SHong Zhang     ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
273154dfd506SHong Zhang   }
27325f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
27335f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27345f2c45f1SShri Abhyankar }
27355f2c45f1SShri Abhyankar 
27365f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
27375f2c45f1SShri Abhyankar {
27385f2c45f1SShri Abhyankar   PetscErrorCode ierr;
2739caf410d2SHong Zhang   PetscBool      iascii;
2740caf410d2SHong Zhang   PetscMPIInt    rank;
27415f2c45f1SShri Abhyankar 
27425f2c45f1SShri Abhyankar   PetscFunctionBegin;
2743caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2744ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
2745caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2746caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2747caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2748caf410d2SHong Zhang   if (iascii) {
2749caf410d2SHong Zhang     const PetscInt *cone,*vtx,*edges;
27502bf73ac6SHong Zhang     PetscInt       vfrom,vto,i,j,nv,ne,ncv,p,nsubnet;
27512bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
2752caf410d2SHong Zhang 
27532bf73ac6SHong Zhang     nsubnet = network->Nsubnet; /* num of subnetworks */
2754dd400576SPatrick Sanan     if (rank == 0) {
27552bf73ac6SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  NSubnets: %D; NEdges: %D; NVertices: %D; NSharedVertices: %D.\n",nsubnet,network->NEdges,network->NVertices,network->Nsvtx);CHKERRQ(ierr);
27562bf73ac6SHong Zhang     }
27572bf73ac6SHong Zhang 
27582bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
2759caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
27602bf73ac6SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nEdges: %D; nVertices: %D; nSharedVertices: %D\n",rank,network->nEdges,network->nVertices,ncv);CHKERRQ(ierr);
2761caf410d2SHong Zhang 
2762caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
27632bf73ac6SHong Zhang       ierr = DMNetworkGetSubnetwork(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2764caf410d2SHong Zhang       if (ne) {
27652bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices(include shared vertices) %D\n",i,ne,nv);CHKERRQ(ierr);
2766caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2767caf410d2SHong Zhang           p = edges[j];
2768caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2769caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2770caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2771caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2772caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D ----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2773caf410d2SHong Zhang         }
2774caf410d2SHong Zhang       }
2775caf410d2SHong Zhang     }
27762bf73ac6SHong Zhang 
27772bf73ac6SHong Zhang     /* Shared vertices */
27782bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
27792bf73ac6SHong Zhang     if (ncv) {
27802bf73ac6SHong Zhang       SVtx       *svtx = network->svtx;
27812bf73ac6SHong Zhang       PetscInt    gidx,svtx_idx,nvto,vfrom_net,vfrom_idx,*svto;
27822bf73ac6SHong Zhang       PetscBool   ghost;
27832bf73ac6SHong Zhang       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     SharedVertices:\n");CHKERRQ(ierr);
27842bf73ac6SHong Zhang       for (i=0; i<ncv; i++) {
27852bf73ac6SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,vtx[i],&ghost);CHKERRQ(ierr);
27862bf73ac6SHong Zhang         if (ghost) continue;
27872bf73ac6SHong Zhang 
27882bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVertexIndex(dm,vtx[i],&gidx);CHKERRQ(ierr);
27892bf73ac6SHong Zhang         ierr = PetscTableFind(network->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
27902bf73ac6SHong Zhang         svtx_idx--;
27912bf73ac6SHong Zhang         nvto = svtx[svtx_idx].n;
27922bf73ac6SHong Zhang 
27932bf73ac6SHong Zhang         vfrom_net = svtx[svtx_idx].sv[0];
27942bf73ac6SHong Zhang         vfrom_idx = svtx[svtx_idx].sv[1];
27952bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       svtx %D: global index %D, subnet[%D].%D ---->\n",i,gidx,vfrom_net,vfrom_idx);CHKERRQ(ierr);
27962bf73ac6SHong Zhang         for (j=1; j<nvto; j++) {
27972bf73ac6SHong Zhang           svto = svtx[svtx_idx].sv + 2*j;
27982bf73ac6SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "                                           ----> subnet[%D].%D\n",svto[0],svto[1]);CHKERRQ(ierr);
2799caf410d2SHong Zhang         }
2800caf410d2SHong Zhang       }
2801caf410d2SHong Zhang     }
2802caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2803caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2804caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
28055f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28065f2c45f1SShri Abhyankar }
28075f2c45f1SShri Abhyankar 
28085f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
28095f2c45f1SShri Abhyankar {
28105f2c45f1SShri Abhyankar   PetscErrorCode ierr;
28115f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
28125f2c45f1SShri Abhyankar 
28135f2c45f1SShri Abhyankar   PetscFunctionBegin;
28145f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
28155f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28165f2c45f1SShri Abhyankar }
28175f2c45f1SShri Abhyankar 
28185f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
28195f2c45f1SShri Abhyankar {
28205f2c45f1SShri Abhyankar   PetscErrorCode ierr;
28215f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
28225f2c45f1SShri Abhyankar 
28235f2c45f1SShri Abhyankar   PetscFunctionBegin;
28245f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
28255f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28265f2c45f1SShri Abhyankar }
28275f2c45f1SShri Abhyankar 
28285f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
28295f2c45f1SShri Abhyankar {
28305f2c45f1SShri Abhyankar   PetscErrorCode ierr;
28315f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
28325f2c45f1SShri Abhyankar 
28335f2c45f1SShri Abhyankar   PetscFunctionBegin;
28345f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
28355f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28365f2c45f1SShri Abhyankar }
28375f2c45f1SShri Abhyankar 
28385f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
28395f2c45f1SShri Abhyankar {
28405f2c45f1SShri Abhyankar   PetscErrorCode ierr;
28415f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
28425f2c45f1SShri Abhyankar 
28435f2c45f1SShri Abhyankar   PetscFunctionBegin;
28445f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
28455f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28465f2c45f1SShri Abhyankar }
284722bbedd7SHong Zhang 
284822bbedd7SHong Zhang /*@
284964238763SRodolfo Oliveira   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index
285022bbedd7SHong Zhang 
285122bbedd7SHong Zhang   Not collective
285222bbedd7SHong Zhang 
28537a7aea1fSJed Brown   Input Parameters:
285422bbedd7SHong Zhang + dm - the dm object
285522bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
285622bbedd7SHong Zhang 
28577a7aea1fSJed Brown   Output Parameters:
2858f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
285922bbedd7SHong Zhang 
286097bb938eSShri Abhyankar   Level: advanced
286122bbedd7SHong Zhang 
286222bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
286322bbedd7SHong Zhang @*/
286422bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
286522bbedd7SHong Zhang {
286622bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
286722bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
286822bbedd7SHong Zhang 
286922bbedd7SHong Zhang   PetscFunctionBegin;
287022bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
287122bbedd7SHong Zhang   *vg = vltog[vloc];
287222bbedd7SHong Zhang   PetscFunctionReturn(0);
287322bbedd7SHong Zhang }
287422bbedd7SHong Zhang 
287522bbedd7SHong Zhang /*@
287664238763SRodolfo Oliveira   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map
287722bbedd7SHong Zhang 
287822bbedd7SHong Zhang   Collective
287922bbedd7SHong Zhang 
288022bbedd7SHong Zhang   Input Parameters:
2881f0fc11ceSJed Brown . dm - the dm object
288222bbedd7SHong Zhang 
288397bb938eSShri Abhyankar   Level: advanced
288422bbedd7SHong Zhang 
288563029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
288622bbedd7SHong Zhang @*/
288722bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
288822bbedd7SHong Zhang {
288922bbedd7SHong Zhang   PetscErrorCode    ierr;
289022bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
289122bbedd7SHong Zhang   MPI_Comm          comm;
28922bf73ac6SHong Zhang   PetscMPIInt       rank,size,*displs=NULL,*recvcounts=NULL,remoterank;
289322bbedd7SHong Zhang   PetscBool         ghost;
289463029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
289522bbedd7SHong Zhang   const PetscSFNode *iremote;
289622bbedd7SHong Zhang   PetscSF           vsf;
289763029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
289863029d29SHong Zhang   VecScatter        ctx;
289963029d29SHong Zhang   PetscScalar       *varr,val;
290063029d29SHong Zhang   const PetscScalar *varr_read;
290122bbedd7SHong Zhang 
290222bbedd7SHong Zhang   PetscFunctionBegin;
290322bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2904ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
2905ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
290622bbedd7SHong Zhang 
290722bbedd7SHong Zhang   if (size == 1) {
290822bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
290922bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
291022bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
291122bbedd7SHong Zhang     network->vltog = vltog;
291222bbedd7SHong Zhang     PetscFunctionReturn(0);
291322bbedd7SHong Zhang   }
291422bbedd7SHong Zhang 
291522bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
291622bbedd7SHong Zhang   if (network->vltog) {
291722bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
291822bbedd7SHong Zhang   }
291922bbedd7SHong Zhang 
292022bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
292122bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
292222bbedd7SHong Zhang   vsf = network->vertex.sf;
292322bbedd7SHong Zhang 
29242bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
2925f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
292622bbedd7SHong Zhang 
292722bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
292822bbedd7SHong Zhang 
292922bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
293022bbedd7SHong Zhang   vrange[0] = 0;
2931ffc4695bSBarry Smith   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
293267dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
293322bbedd7SHong Zhang 
293422bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
293522bbedd7SHong Zhang   network->vltog = vltog;
293622bbedd7SHong Zhang 
293763029d29SHong Zhang   /* Set vltog for non-ghost vertices */
293863029d29SHong Zhang   k = 0;
293922bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
294022bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
294163029d29SHong Zhang     if (ghost) continue;
294263029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
294322bbedd7SHong Zhang   }
2944f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
294563029d29SHong Zhang 
294663029d29SHong Zhang   /* Set vltog for ghost vertices */
294763029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
294863029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
294963029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
295063029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
295163029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
295263029d29SHong Zhang   for (i=0; i<nleaves; i++) {
295363029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
295463029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
295563029d29SHong Zhang   }
295663029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
295763029d29SHong Zhang 
295863029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
295963029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
296063029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
296163029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
296263029d29SHong Zhang 
296363029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
296463029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
296563029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
296663029d29SHong Zhang   for (i=0; i<N; i+=2) {
29672e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
296863029d29SHong Zhang     if (remoterank == rank) {
296963029d29SHong Zhang       k = i+1; /* row number */
29702e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
297163029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
297263029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
297363029d29SHong Zhang     }
297463029d29SHong Zhang   }
297563029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
297663029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
297763029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
297863029d29SHong Zhang 
297963029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
298063029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
298163029d29SHong Zhang   k = 0;
298263029d29SHong Zhang   for (i=0; i<nroots; i++) {
298363029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
298463029d29SHong Zhang     if (!ghost) continue;
29852e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
298663029d29SHong Zhang   }
298763029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
298863029d29SHong Zhang 
298963029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
299063029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
299163029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
299222bbedd7SHong Zhang   PetscFunctionReturn(0);
299322bbedd7SHong Zhang }
299442dc13f1SHong Zhang 
299542dc13f1SHong Zhang PETSC_STATIC_INLINE PetscErrorCode DMISAddSize_private(DM_Network *network,PetscInt p,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *nidx)
299642dc13f1SHong Zhang {
299742dc13f1SHong Zhang   PetscErrorCode           ierr;
299842dc13f1SHong Zhang   PetscInt                 i,j,ncomps,nvar,key,offset=0;
299942dc13f1SHong Zhang   DMNetworkComponentHeader header;
300042dc13f1SHong Zhang 
300142dc13f1SHong Zhang   PetscFunctionBegin;
300242dc13f1SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
300342dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
300442dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
300542dc13f1SHong Zhang 
300642dc13f1SHong Zhang   for (i=0; i<ncomps; i++) {
300742dc13f1SHong Zhang     key  = header->key[i];
300842dc13f1SHong Zhang     nvar = header->nvar[i];
300942dc13f1SHong Zhang     for (j=0; j<numkeys; j++) {
301042dc13f1SHong Zhang       if (key == keys[j]) {
301142dc13f1SHong Zhang         if (!blocksize || blocksize[j] == -1) {
301242dc13f1SHong Zhang           *nidx += nvar;
301342dc13f1SHong Zhang         } else {
301442dc13f1SHong Zhang           *nidx += nselectedvar[j]*nvar/blocksize[j];
301542dc13f1SHong Zhang         }
301642dc13f1SHong Zhang       }
301742dc13f1SHong Zhang     }
301842dc13f1SHong Zhang   }
301942dc13f1SHong Zhang   PetscFunctionReturn(0);
302042dc13f1SHong Zhang }
302142dc13f1SHong Zhang 
302242dc13f1SHong Zhang PETSC_STATIC_INLINE PetscErrorCode DMISComputeIdx_private(DM dm,PetscInt p,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],PetscInt *ii,PetscInt *idx)
302342dc13f1SHong Zhang {
302442dc13f1SHong Zhang   PetscErrorCode           ierr;
302542dc13f1SHong Zhang   PetscInt                 i,j,ncomps,nvar,key,offsetg,k,k1,offset=0;
302642dc13f1SHong Zhang   DM_Network               *network = (DM_Network*)dm->data;
302742dc13f1SHong Zhang   DMNetworkComponentHeader header;
302842dc13f1SHong Zhang 
302942dc13f1SHong Zhang   PetscFunctionBegin;
303042dc13f1SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
303142dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
303242dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
303342dc13f1SHong Zhang 
303442dc13f1SHong Zhang   for (i=0; i<ncomps; i++) {
303542dc13f1SHong Zhang     key  = header->key[i];
303642dc13f1SHong Zhang     nvar = header->nvar[i];
303742dc13f1SHong Zhang     for (j=0; j<numkeys; j++) {
303842dc13f1SHong Zhang       if (key != keys[j]) continue;
303942dc13f1SHong Zhang 
304042dc13f1SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,p,i,&offsetg);CHKERRQ(ierr);
304142dc13f1SHong Zhang       if (!blocksize || blocksize[j] == -1) {
304242dc13f1SHong Zhang         for (k=0; k<nvar; k++) idx[(*ii)++] = offsetg + k;
304342dc13f1SHong Zhang       } else {
304442dc13f1SHong Zhang         for (k=0; k<nvar; k+=blocksize[j]) {
304542dc13f1SHong Zhang           for (k1=0; k1<nselectedvar[j]; k1++) idx[(*ii)++] = offsetg + k + selectedvar[j][k1];
304642dc13f1SHong Zhang         }
304742dc13f1SHong Zhang       }
304842dc13f1SHong Zhang     }
304942dc13f1SHong Zhang   }
305042dc13f1SHong Zhang   PetscFunctionReturn(0);
305142dc13f1SHong Zhang }
305242dc13f1SHong Zhang 
305342dc13f1SHong Zhang /*@
305442dc13f1SHong Zhang   DMNetworkCreateIS - Create an index set object from the global vector of the network
305542dc13f1SHong Zhang 
305642dc13f1SHong Zhang   Collective
305742dc13f1SHong Zhang 
305842dc13f1SHong Zhang   Input Parameters:
305942dc13f1SHong Zhang + dm - DMNetwork object
306042dc13f1SHong Zhang . numkeys - number of keys
306142dc13f1SHong Zhang . keys - array of keys that define the components of the variables you wish to extract
306242dc13f1SHong Zhang . blocksize - block size of the variables associated to the component
306342dc13f1SHong Zhang . nselectedvar - number of variables in each block to select
306442dc13f1SHong Zhang - selectedvar - the offset into the block of each variable in each block to select
306542dc13f1SHong Zhang 
306642dc13f1SHong Zhang   Output Parameters:
306742dc13f1SHong Zhang . is - the index set
306842dc13f1SHong Zhang 
306942dc13f1SHong Zhang   Level: Advanced
307042dc13f1SHong Zhang 
307142dc13f1SHong Zhang   Notes:
307242dc13f1SHong Zhang     Use blocksize[i] of -1 to indicate select all the variables of the i-th component, for which nselectvar[i] and selectedvar[i] are ignored. Use NULL, NULL, NULL to indicate for all selected components one wishes to obtain all the values of that component. For example, DMNetworkCreateIS(dm,1,&key,NULL,NULL,NULL,&is) will return an is that extracts all the variables for the 0-th component.
307342dc13f1SHong Zhang 
307442dc13f1SHong Zhang .seealso: DMNetworkCreate(), ISCreateGeneral(), DMNetworkCreateLocalIS()
307542dc13f1SHong Zhang @*/
307642dc13f1SHong Zhang PetscErrorCode DMNetworkCreateIS(DM dm,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],IS *is)
307742dc13f1SHong Zhang {
307842dc13f1SHong Zhang   PetscErrorCode ierr;
307942dc13f1SHong Zhang   MPI_Comm       comm;
308042dc13f1SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
308142dc13f1SHong Zhang   PetscInt       i,p,estart,eend,vstart,vend,nidx,*idx;
308242dc13f1SHong Zhang   PetscBool      ghost;
308342dc13f1SHong Zhang 
308442dc13f1SHong Zhang   PetscFunctionBegin;
308542dc13f1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
308642dc13f1SHong Zhang 
308742dc13f1SHong Zhang   /* Check input parameters */
308842dc13f1SHong Zhang   for (i=0; i<numkeys; i++) {
308942dc13f1SHong Zhang     if (!blocksize || blocksize[i] == -1) continue;
309042dc13f1SHong Zhang     if (nselectedvar[i] > blocksize[i]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"number of selectedvariables %D cannot be larger than blocksize %D",nselectedvar[i],blocksize[i]);
309142dc13f1SHong Zhang   }
309242dc13f1SHong Zhang 
309342dc13f1SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&estart,&eend);CHKERRQ(ierr);
309442dc13f1SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vstart,&vend);CHKERRQ(ierr);
309542dc13f1SHong Zhang 
309642dc13f1SHong Zhang   /* Get local number of idx */
309742dc13f1SHong Zhang   nidx = 0;
309842dc13f1SHong Zhang   for (p=estart; p<eend; p++) {
309942dc13f1SHong Zhang     ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr);
310042dc13f1SHong Zhang   }
310142dc13f1SHong Zhang   for (p=vstart; p<vend; p++) {
310242dc13f1SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
310342dc13f1SHong Zhang     if (ghost) continue;
310442dc13f1SHong Zhang     ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr);
310542dc13f1SHong Zhang   }
310642dc13f1SHong Zhang 
310742dc13f1SHong Zhang   /* Compute idx */
310842dc13f1SHong Zhang   ierr = PetscMalloc1(nidx,&idx);CHKERRQ(ierr);
310942dc13f1SHong Zhang   i = 0;
311042dc13f1SHong Zhang   for (p=estart; p<eend; p++) {
311142dc13f1SHong Zhang     ierr = DMISComputeIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr);
311242dc13f1SHong Zhang   }
311342dc13f1SHong Zhang   for (p=vstart; p<vend; p++) {
311442dc13f1SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
311542dc13f1SHong Zhang     if (ghost) continue;
311642dc13f1SHong Zhang     ierr = DMISComputeIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr);
311742dc13f1SHong Zhang   }
311842dc13f1SHong Zhang 
311942dc13f1SHong Zhang   /* Create is */
312042dc13f1SHong Zhang   ierr = ISCreateGeneral(comm,nidx,idx,PETSC_COPY_VALUES,is);CHKERRQ(ierr);
312142dc13f1SHong Zhang   ierr = PetscFree(idx);CHKERRQ(ierr);
312242dc13f1SHong Zhang   PetscFunctionReturn(0);
312342dc13f1SHong Zhang }
312442dc13f1SHong Zhang 
312542dc13f1SHong Zhang PETSC_STATIC_INLINE PetscErrorCode DMISComputeLocalIdx_private(DM dm,PetscInt p,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],PetscInt *ii,PetscInt *idx)
312642dc13f1SHong Zhang {
312742dc13f1SHong Zhang   PetscErrorCode           ierr;
312842dc13f1SHong Zhang   PetscInt                 i,j,ncomps,nvar,key,offsetl,k,k1,offset=0;
312942dc13f1SHong Zhang   DM_Network               *network = (DM_Network*)dm->data;
313042dc13f1SHong Zhang   DMNetworkComponentHeader header;
313142dc13f1SHong Zhang 
313242dc13f1SHong Zhang   PetscFunctionBegin;
313342dc13f1SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
313442dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
313542dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
313642dc13f1SHong Zhang 
313742dc13f1SHong Zhang   for (i=0; i<ncomps; i++) {
313842dc13f1SHong Zhang     key  = header->key[i];
313942dc13f1SHong Zhang     nvar = header->nvar[i];
314042dc13f1SHong Zhang     for (j=0; j<numkeys; j++) {
314142dc13f1SHong Zhang       if (key != keys[j]) continue;
314242dc13f1SHong Zhang 
314342dc13f1SHong Zhang       ierr = DMNetworkGetLocalVecOffset(dm,p,i,&offsetl);CHKERRQ(ierr);
314442dc13f1SHong Zhang       if (!blocksize || blocksize[j] == -1) {
314542dc13f1SHong Zhang         for (k=0; k<nvar; k++) idx[(*ii)++] = offsetl + k;
314642dc13f1SHong Zhang       } else {
314742dc13f1SHong Zhang         for (k=0; k<nvar; k+=blocksize[j]) {
314842dc13f1SHong Zhang           for (k1=0; k1<nselectedvar[j]; k1++) idx[(*ii)++] = offsetl + k + selectedvar[j][k1];
314942dc13f1SHong Zhang         }
315042dc13f1SHong Zhang       }
315142dc13f1SHong Zhang     }
315242dc13f1SHong Zhang   }
315342dc13f1SHong Zhang   PetscFunctionReturn(0);
315442dc13f1SHong Zhang }
315542dc13f1SHong Zhang 
315642dc13f1SHong Zhang /*@
315742dc13f1SHong Zhang   DMNetworkCreateLocalIS - Create an index set object from the local vector of the network
315842dc13f1SHong Zhang 
315942dc13f1SHong Zhang   Not collective
316042dc13f1SHong Zhang 
316142dc13f1SHong Zhang   Input Parameters:
316242dc13f1SHong Zhang + dm - DMNetwork object
316342dc13f1SHong Zhang . numkeys - number of keys
316442dc13f1SHong Zhang . keys - array of keys that define the components of the variables you wish to extract
316542dc13f1SHong Zhang . blocksize - block size of the variables associated to the component
316642dc13f1SHong Zhang . nselectedvar - number of variables in each block to select
316742dc13f1SHong Zhang - selectedvar - the offset into the block of each variable in each block to select
316842dc13f1SHong Zhang 
316942dc13f1SHong Zhang   Output Parameters:
317042dc13f1SHong Zhang . is - the index set
317142dc13f1SHong Zhang 
317242dc13f1SHong Zhang   Level: Advanced
317342dc13f1SHong Zhang 
317442dc13f1SHong Zhang   Notes:
317542dc13f1SHong Zhang     Use blocksize[i] of -1 to indicate select all the variables of the i-th component, for which nselectvar[i] and selectedvar[i] are ignored. Use NULL, NULL, NULL to indicate for all selected components one wishes to obtain all the values of that component. For example, DMNetworkCreateLocalIS(dm,1,&key,NULL,NULL,NULL,&is) will return an is that extracts all the variables for the 0-th component.
317642dc13f1SHong Zhang 
317742dc13f1SHong Zhang .seealso: DMNetworkCreate(), DMNetworkCreateIS, ISCreateGeneral()
317842dc13f1SHong Zhang @*/
317942dc13f1SHong Zhang PetscErrorCode DMNetworkCreateLocalIS(DM dm,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],IS *is)
318042dc13f1SHong Zhang {
318142dc13f1SHong Zhang   PetscErrorCode ierr;
318242dc13f1SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
318342dc13f1SHong Zhang   PetscInt       i,p,pstart,pend,nidx,*idx;
318442dc13f1SHong Zhang 
318542dc13f1SHong Zhang   PetscFunctionBegin;
318642dc13f1SHong Zhang   /* Check input parameters */
318742dc13f1SHong Zhang   for (i=0; i<numkeys; i++) {
318842dc13f1SHong Zhang     if (!blocksize || blocksize[i] == -1) continue;
318942dc13f1SHong Zhang     if (nselectedvar[i] > blocksize[i]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"number of selectedvariables %D cannot be larger than blocksize %D",nselectedvar[i],blocksize[i]);
319042dc13f1SHong Zhang   }
319142dc13f1SHong Zhang 
319242dc13f1SHong Zhang   pstart = network->pStart;
319342dc13f1SHong Zhang   pend   = network->pEnd;
319442dc13f1SHong Zhang 
319542dc13f1SHong Zhang   /* Get local number of idx */
319642dc13f1SHong Zhang   nidx = 0;
319742dc13f1SHong Zhang   for (p=pstart; p<pend; p++) {
319842dc13f1SHong Zhang     ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr);
319942dc13f1SHong Zhang   }
320042dc13f1SHong Zhang 
320142dc13f1SHong Zhang   /* Compute local idx */
320242dc13f1SHong Zhang   ierr = PetscMalloc1(nidx,&idx);CHKERRQ(ierr);
320342dc13f1SHong Zhang   i = 0;
320442dc13f1SHong Zhang   for (p=pstart; p<pend; p++) {
320542dc13f1SHong Zhang     ierr = DMISComputeLocalIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr);
320642dc13f1SHong Zhang   }
320742dc13f1SHong Zhang 
320842dc13f1SHong Zhang   /* Create is */
320942dc13f1SHong Zhang   ierr = ISCreateGeneral(PETSC_COMM_SELF,nidx,idx,PETSC_COPY_VALUES,is);CHKERRQ(ierr);
321042dc13f1SHong Zhang   ierr = PetscFree(idx);CHKERRQ(ierr);
321142dc13f1SHong Zhang   PetscFunctionReturn(0);
321242dc13f1SHong Zhang }
3213