xref: /petsc/src/dm/impls/network/network.c (revision 8d1cd658de3d7755d52a210745df00bed3eff48b)
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
123*8d1cd658SBarry 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,
124*8d1cd658SBarry 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 
133*8d1cd658SBarry 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,
134*8d1cd658SBarry 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;
194*8d1cd658SBarry Smith   for (i=0; i<ne; i++) {
195*8d1cd658SBarry 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]);
196*8d1cd658SBarry 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 
10832bf73ac6SHong Zhang .seealso: DMNetworkGetGlobalEdgeIndex()
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
11297d928bffSSatish Balay . p - the edge/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 
11359988b915SShri Abhyankar   Level: intermediate
11369988b915SShri Abhyankar 
11372bf73ac6SHong Zhang .seealso: DMGetLocalVector(), DMNetworkGetComponent(), DMNetworkGetGlobalVecOffset()
11389988b915SShri Abhyankar @*/
11392bf73ac6SHong Zhang PetscErrorCode DMNetworkGetLocalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offset)
11409988b915SShri Abhyankar {
11419988b915SShri Abhyankar   PetscErrorCode ierr;
11429988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11439988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
11449988b915SShri Abhyankar   DMNetworkComponentHeader header;
11459988b915SShri Abhyankar 
11469988b915SShri Abhyankar   PetscFunctionBegin;
11472bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->localSection,p,&offsetp);CHKERRQ(ierr);
11482bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
11492bf73ac6SHong Zhang     *offset = offsetp;
11502bf73ac6SHong Zhang     PetscFunctionReturn(0);
11512bf73ac6SHong Zhang   }
11522bf73ac6SHong Zhang 
11539988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
11549988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
11559988b915SShri Abhyankar   *offset = offsetp + header->offsetvarrel[compnum];
11569988b915SShri Abhyankar   PetscFunctionReturn(0);
11579988b915SShri Abhyankar }
11589988b915SShri Abhyankar 
11599988b915SShri Abhyankar /*@
11602bf73ac6SHong Zhang   DMNetworkGetGlobalVecOffset - Get the global offset for accessing the variables associated with a component for the given vertex/edge from the global vector
11619988b915SShri Abhyankar 
11629988b915SShri Abhyankar   Not Collective
11639988b915SShri Abhyankar 
11649988b915SShri Abhyankar   Input Parameters:
11652bf73ac6SHong Zhang + dm - the DMNetwork object
11667d928bffSSatish Balay . p - the edge/vertex point
11672bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
11689988b915SShri Abhyankar 
11699988b915SShri Abhyankar   Output Parameters:
11709988b915SShri Abhyankar . offsetg - the global offset
11719988b915SShri Abhyankar 
11729988b915SShri Abhyankar   Level: intermediate
11739988b915SShri Abhyankar 
11742bf73ac6SHong Zhang .seealso: DMNetworkGetLocalVecOffset(), DMGetGlobalVector(), DMNetworkGetComponent()
11759988b915SShri Abhyankar @*/
11762bf73ac6SHong Zhang PetscErrorCode DMNetworkGetGlobalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offsetg)
11779988b915SShri Abhyankar {
11789988b915SShri Abhyankar   PetscErrorCode ierr;
11799988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11809988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
11819988b915SShri Abhyankar   DMNetworkComponentHeader header;
11829988b915SShri Abhyankar 
11839988b915SShri Abhyankar   PetscFunctionBegin;
11842bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->globalSection,p,&offsetp);CHKERRQ(ierr);
11852bf73ac6SHong Zhang   if (offsetp < 0) offsetp = -(offsetp + 1); /* Convert to actual global offset for ghost vertex */
11862bf73ac6SHong Zhang 
11872bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
11882bf73ac6SHong Zhang     *offsetg = offsetp;
11892bf73ac6SHong Zhang     PetscFunctionReturn(0);
11902bf73ac6SHong Zhang   }
11919988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
11929988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
11939988b915SShri Abhyankar   *offsetg = offsetp + header->offsetvarrel[compnum];
11949988b915SShri Abhyankar   PetscFunctionReturn(0);
11959988b915SShri Abhyankar }
11969988b915SShri Abhyankar 
11979988b915SShri Abhyankar /*@
11982bf73ac6SHong Zhang   DMNetworkGetEdgeOffset - Get the offset for accessing the variables associated with the given edge from the local subvector
119924121865SAdrian Maldonado 
120024121865SAdrian Maldonado   Not Collective
120124121865SAdrian Maldonado 
120224121865SAdrian Maldonado   Input Parameters:
12032bf73ac6SHong Zhang + dm - the DMNetwork object
120424121865SAdrian Maldonado - p - the edge point
120524121865SAdrian Maldonado 
120624121865SAdrian Maldonado   Output Parameters:
120724121865SAdrian Maldonado . offset - the offset
120824121865SAdrian Maldonado 
120924121865SAdrian Maldonado   Level: intermediate
121024121865SAdrian Maldonado 
12112bf73ac6SHong Zhang .seealso: DMNetworkGetLocalVecOffset(), DMGetLocalVector()
121224121865SAdrian Maldonado @*/
121324121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
121424121865SAdrian Maldonado {
121524121865SAdrian Maldonado   PetscErrorCode ierr;
121624121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
121724121865SAdrian Maldonado 
121824121865SAdrian Maldonado   PetscFunctionBegin;
121924121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
122024121865SAdrian Maldonado   PetscFunctionReturn(0);
122124121865SAdrian Maldonado }
122224121865SAdrian Maldonado 
122324121865SAdrian Maldonado /*@
12242bf73ac6SHong Zhang   DMNetworkGetVertexOffset - Get the offset for accessing the variables associated with the given vertex from the local subvector
122524121865SAdrian Maldonado 
122624121865SAdrian Maldonado   Not Collective
122724121865SAdrian Maldonado 
122824121865SAdrian Maldonado   Input Parameters:
12292bf73ac6SHong Zhang + dm - the DMNetwork object
123024121865SAdrian Maldonado - p - the vertex point
123124121865SAdrian Maldonado 
123224121865SAdrian Maldonado   Output Parameters:
123324121865SAdrian Maldonado . offset - the offset
123424121865SAdrian Maldonado 
123524121865SAdrian Maldonado   Level: intermediate
123624121865SAdrian Maldonado 
12372bf73ac6SHong Zhang .seealso: DMNetworkGetEdgeOffset(), DMGetLocalVector()
123824121865SAdrian Maldonado @*/
123924121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
124024121865SAdrian Maldonado {
124124121865SAdrian Maldonado   PetscErrorCode ierr;
124224121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
124324121865SAdrian Maldonado 
124424121865SAdrian Maldonado   PetscFunctionBegin;
124524121865SAdrian Maldonado   p -= network->vStart;
124624121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
124724121865SAdrian Maldonado   PetscFunctionReturn(0);
124824121865SAdrian Maldonado }
12492bf73ac6SHong Zhang 
12505f2c45f1SShri Abhyankar /*@
12512bf73ac6SHong Zhang   DMNetworkAddComponent - Adds a network component and number of variables at the given point (vertex/edge)
12525f2c45f1SShri Abhyankar 
12535f2c45f1SShri Abhyankar   Not Collective
12545f2c45f1SShri Abhyankar 
12555f2c45f1SShri Abhyankar   Input Parameters:
12564dc646bcSBarry Smith + dm - the DMNetwork
12575f2c45f1SShri Abhyankar . p - the vertex/edge point
12582bf73ac6SHong Zhang . componentkey - component key returned while registering the component; ignored if compvalue=NULL
12592bf73ac6SHong Zhang . compvalue - pointer to the data structure for the component, or NULL if not required.
12602bf73ac6SHong Zhang - nvar - number of variables for the component at the vertex/edge point
12615f2c45f1SShri Abhyankar 
126297bb938eSShri Abhyankar   Level: beginner
12635f2c45f1SShri Abhyankar 
12642bf73ac6SHong Zhang .seealso: DMNetworkGetComponent()
12655f2c45f1SShri Abhyankar @*/
12662bf73ac6SHong Zhang PetscErrorCode DMNetworkAddComponent(DM dm,PetscInt p,PetscInt componentkey,void* compvalue,PetscInt nvar)
12675f2c45f1SShri Abhyankar {
12685f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
12695f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
12702bf73ac6SHong Zhang   DMNetworkComponent       *component = &network->component[componentkey];
127154dfd506SHong Zhang   DMNetworkComponentHeader header;
127254dfd506SHong Zhang   DMNetworkComponentValue  cvalue;
12732bf73ac6SHong Zhang   PetscBool                sharedv=PETSC_FALSE;
127454dfd506SHong Zhang   PetscInt                 compnum;
127554dfd506SHong Zhang   PetscInt                 *compsize,*compkey,*compoffset,*compnvar,*compoffsetvarrel;
127654dfd506SHong Zhang   void*                    *compdata;
12775f2c45f1SShri Abhyankar 
12785f2c45f1SShri Abhyankar   PetscFunctionBegin;
12795f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
12802bf73ac6SHong Zhang   if (!compvalue) PetscFunctionReturn(0);
12812bf73ac6SHong Zhang 
12822bf73ac6SHong Zhang   ierr = DMNetworkIsSharedVertex(dm,p,&sharedv);CHKERRQ(ierr);
12832bf73ac6SHong Zhang   if (sharedv) {
12842bf73ac6SHong Zhang     PetscBool ghost;
12852bf73ac6SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
12862bf73ac6SHong Zhang     if (ghost) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adding a component at a leaf(ghost) shared vertex is not supported");
12872bf73ac6SHong Zhang   }
12882bf73ac6SHong Zhang 
128954dfd506SHong Zhang   header = &network->header[p];
129054dfd506SHong Zhang   cvalue = &network->cvalue[p];
129154dfd506SHong Zhang   if (header->ndata == header->maxcomps) {
1292f11a936eSBarry Smith     PetscInt additional_size;
1293f11a936eSBarry Smith 
129454dfd506SHong Zhang     /* Reached limit so resize header component arrays */
129554dfd506SHong Zhang     header->maxcomps += 2;
129654dfd506SHong Zhang 
129754dfd506SHong Zhang     /* Allocate arrays for component information and value */
129854dfd506SHong Zhang     ierr = PetscCalloc5(header->maxcomps,&compsize,header->maxcomps,&compkey,header->maxcomps,&compoffset,header->maxcomps,&compnvar,header->maxcomps,&compoffsetvarrel);CHKERRQ(ierr);
129954dfd506SHong Zhang     ierr = PetscMalloc1(header->maxcomps,&compdata);CHKERRQ(ierr);
130054dfd506SHong Zhang 
130154dfd506SHong Zhang     /* Recalculate header size */
130254dfd506SHong Zhang     header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt);
130354dfd506SHong Zhang 
130454dfd506SHong Zhang     header->hsize /= sizeof(DMNetworkComponentGenericDataType);
130554dfd506SHong Zhang 
130654dfd506SHong Zhang     /* Copy over component info */
130754dfd506SHong Zhang     ierr = PetscMemcpy(compsize,header->size,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
130854dfd506SHong Zhang     ierr = PetscMemcpy(compkey,header->key,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
130954dfd506SHong Zhang     ierr = PetscMemcpy(compoffset,header->offset,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
131054dfd506SHong Zhang     ierr = PetscMemcpy(compnvar,header->nvar,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
131154dfd506SHong Zhang     ierr = PetscMemcpy(compoffsetvarrel,header->offsetvarrel,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
131254dfd506SHong Zhang 
131354dfd506SHong Zhang     /* Copy over component data pointers */
131454dfd506SHong Zhang     ierr = PetscMemcpy(compdata,cvalue->data,header->ndata*sizeof(void*));CHKERRQ(ierr);
131554dfd506SHong Zhang 
131654dfd506SHong Zhang     /* Free old arrays */
131754dfd506SHong Zhang     ierr = PetscFree5(header->size,header->key,header->offset,header->nvar,header->offsetvarrel);CHKERRQ(ierr);
131854dfd506SHong Zhang     ierr = PetscFree(cvalue->data);CHKERRQ(ierr);
131954dfd506SHong Zhang 
132054dfd506SHong Zhang     /* Update pointers */
132154dfd506SHong Zhang     header->size = compsize;
132254dfd506SHong Zhang     header->key  = compkey;
132354dfd506SHong Zhang     header->offset = compoffset;
132454dfd506SHong Zhang     header->nvar = compnvar;
132554dfd506SHong Zhang     header->offsetvarrel = compoffsetvarrel;
132654dfd506SHong Zhang 
132754dfd506SHong Zhang     cvalue->data = compdata;
132854dfd506SHong Zhang 
132954dfd506SHong Zhang     /* Update DataSection Dofs */
133054dfd506SHong 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 */
1331f11a936eSBarry Smith     additional_size = (5*(header->maxcomps - header->ndata)*sizeof(PetscInt))/sizeof(DMNetworkComponentGenericDataType);
133254dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,p,additional_size);CHKERRQ(ierr);
133354dfd506SHong Zhang   }
133454dfd506SHong Zhang   header = &network->header[p];
133554dfd506SHong Zhang   cvalue = &network->cvalue[p];
133654dfd506SHong Zhang 
133754dfd506SHong Zhang   compnum = header->ndata;
13382bf73ac6SHong Zhang 
13392bf73ac6SHong Zhang   header->size[compnum] = component->size;
13402bf73ac6SHong Zhang   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
13412bf73ac6SHong Zhang   header->key[compnum] = componentkey;
13422bf73ac6SHong Zhang   if (compnum != 0) header->offset[compnum] = header->offset[compnum-1] + header->size[compnum-1];
13432bf73ac6SHong Zhang   cvalue->data[compnum] = (void*)compvalue;
13442bf73ac6SHong Zhang 
13452bf73ac6SHong Zhang   /* variables */
13462bf73ac6SHong Zhang   header->nvar[compnum] += nvar;
13472bf73ac6SHong Zhang   if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum-1] + header->nvar[compnum-1];
13482bf73ac6SHong Zhang 
13492bf73ac6SHong Zhang   header->ndata++;
13505f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13515f2c45f1SShri Abhyankar }
13525f2c45f1SShri Abhyankar 
135327f51fceSHong Zhang /*@
13542bf73ac6SHong Zhang   DMNetworkGetComponent - Gets the component key, the component data, and the number of variables at a given network point
135527f51fceSHong Zhang 
135627f51fceSHong Zhang   Not Collective
135727f51fceSHong Zhang 
135827f51fceSHong Zhang   Input Parameters:
13592bf73ac6SHong Zhang + dm - the DMNetwork object
13602bf73ac6SHong Zhang . p - vertex/edge point
136199c90e12SSatish Balay - compnum - component number; use ALL_COMPONENTS if sum up all the components
136227f51fceSHong Zhang 
136327f51fceSHong Zhang   Output Parameters:
13642bf73ac6SHong Zhang + compkey - the key obtained when registering the component (use NULL if not required)
13652bf73ac6SHong Zhang . component - the component data (use NULL if not required)
13662bf73ac6SHong Zhang - nvar  - number of variables (use NULL if not required)
136727f51fceSHong Zhang 
136897bb938eSShri Abhyankar   Level: beginner
136927f51fceSHong Zhang 
13702bf73ac6SHong Zhang .seealso: DMNetworkAddComponent(), DMNetworkGetNumComponents()
137127f51fceSHong Zhang @*/
13722bf73ac6SHong Zhang PetscErrorCode DMNetworkGetComponent(DM dm,PetscInt p,PetscInt compnum,PetscInt *compkey,void **component,PetscInt *nvar)
137327f51fceSHong Zhang {
137427f51fceSHong Zhang   PetscErrorCode ierr;
137527f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
13762bf73ac6SHong Zhang   PetscInt       offset = 0;
13772bf73ac6SHong Zhang   DMNetworkComponentHeader header;
137827f51fceSHong Zhang 
137927f51fceSHong Zhang   PetscFunctionBegin;
13802bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
138127f51fceSHong Zhang     ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
138227f51fceSHong Zhang     PetscFunctionReturn(0);
138327f51fceSHong Zhang   }
138427f51fceSHong Zhang 
13852bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
138642dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
13875f2c45f1SShri Abhyankar 
13882bf73ac6SHong Zhang   if (compnum >= 0) {
13892bf73ac6SHong Zhang     if (compkey) *compkey = header->key[compnum];
13902bf73ac6SHong Zhang     if (component) {
139154dfd506SHong Zhang       offset += header->hsize+header->offset[compnum];
13922bf73ac6SHong Zhang       *component = network->componentdataarray+offset;
13932bf73ac6SHong Zhang     }
13942bf73ac6SHong Zhang   }
13955f2c45f1SShri Abhyankar 
13962bf73ac6SHong Zhang   if (nvar) *nvar = header->nvar[compnum];
139754dfd506SHong Zhang 
13985f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13995f2c45f1SShri Abhyankar }
14005f2c45f1SShri Abhyankar 
14012bf73ac6SHong Zhang /*
14022bf73ac6SHong Zhang  Sets up the array that holds the data for all components and its associated section.
14032bf73ac6SHong 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.
14042bf73ac6SHong Zhang */
14055f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
14065f2c45f1SShri Abhyankar {
14075f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
14085f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
1409f11a936eSBarry Smith   PetscInt                 arr_size,p,offset,offsetp,ncomp,i,*headerarr;
14105f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
14115f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
1412f11a936eSBarry Smith   DMNetworkComponentHeader headerinfo;
14135f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
14145f2c45f1SShri Abhyankar 
14155f2c45f1SShri Abhyankar   PetscFunctionBegin;
14165f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
14175f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
1418f11a936eSBarry Smith   /* arr_size+1 fixes pipeline test of opensolaris-misc for src/dm/tests/ex10.c -- Do not know why */
1419f11a936eSBarry Smith   ierr = PetscCalloc1(arr_size+1,&network->componentdataarray);CHKERRQ(ierr);
14205f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
14215f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
14225f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
14235f2c45f1SShri Abhyankar     /* Copy header */
14245f2c45f1SShri Abhyankar     header = &network->header[p];
1425f11a936eSBarry Smith     headerinfo = (DMNetworkComponentHeader)(componentdataarray+offsetp);
142654dfd506SHong Zhang     ierr = PetscMemcpy(headerinfo,header,sizeof(struct _p_DMNetworkComponentHeader));CHKERRQ(ierr);
1427f11a936eSBarry Smith     headerarr = (PetscInt*)(headerinfo+1);
142854dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->size,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
142954dfd506SHong Zhang     headerarr += header->maxcomps;
143054dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->key,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
143154dfd506SHong Zhang     headerarr += header->maxcomps;
143254dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offset,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
143354dfd506SHong Zhang     headerarr += header->maxcomps;
143454dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->nvar,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
143554dfd506SHong Zhang     headerarr += header->maxcomps;
143654dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offsetvarrel,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
143754dfd506SHong Zhang 
14385f2c45f1SShri Abhyankar     /* Copy data */
14395f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
14405f2c45f1SShri Abhyankar     ncomp  = header->ndata;
14412bf73ac6SHong Zhang 
14425f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
144354dfd506SHong Zhang       offset = offsetp + header->hsize + header->offset[i];
1444302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
14455f2c45f1SShri Abhyankar     }
14465f2c45f1SShri Abhyankar   }
14475f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14485f2c45f1SShri Abhyankar }
14495f2c45f1SShri Abhyankar 
14505f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
14512bf73ac6SHong Zhang static PetscErrorCode DMNetworkVariablesSetUp(DM dm)
14525f2c45f1SShri Abhyankar {
14535f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14545f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14552bf73ac6SHong Zhang   MPI_Comm       comm;
14562bf73ac6SHong Zhang   PetscMPIInt    size;
14575f2c45f1SShri Abhyankar 
14585f2c45f1SShri Abhyankar   PetscFunctionBegin;
14592bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
14602bf73ac6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
14612bf73ac6SHong Zhang 
14622bf73ac6SHong Zhang   if (size > 1) { /* Sync nvar at shared vertices for all processes */
14632bf73ac6SHong Zhang     PetscSF           sf = network->plex->sf;
14642bf73ac6SHong Zhang     PetscInt          *local_nvar, *remote_nvar,nroots,nleaves,p=-1,i,nsv;
14652bf73ac6SHong Zhang     const PetscInt    *svtx;
14662bf73ac6SHong Zhang     PetscBool         ghost;
14672bf73ac6SHong Zhang     /*
14682bf73ac6SHong Zhang      PetscMPIInt       rank;
14692bf73ac6SHong Zhang      const PetscInt    *ilocal;
14702bf73ac6SHong Zhang      const PetscSFNode *iremote;
14712bf73ac6SHong Zhang      ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
14722bf73ac6SHong Zhang      ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
14732bf73ac6SHong Zhang     */
14742bf73ac6SHong Zhang     ierr = PetscSFGetGraph(sf,&nroots,&nleaves,NULL,NULL);CHKERRQ(ierr);
14752bf73ac6SHong Zhang     ierr = PetscCalloc2(nroots,&local_nvar,nroots,&remote_nvar);CHKERRQ(ierr);
14762bf73ac6SHong Zhang 
14772bf73ac6SHong Zhang     /* Leaves copy user's nvar to local_nvar */
14782bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nsv,&svtx);CHKERRQ(ierr);
14792bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
14802bf73ac6SHong Zhang       p = svtx[i];
14812bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
14822bf73ac6SHong Zhang       if (!ghost) continue;
14832bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
14842bf73ac6SHong Zhang       /* printf("[%d] Before SFReduce: leaf local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
14852bf73ac6SHong Zhang     }
14862bf73ac6SHong Zhang 
14872bf73ac6SHong Zhang     /* Leaves add local_nvar to root remote_nvar */
14882bf73ac6SHong Zhang     ierr = PetscSFReduceBegin(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
14892bf73ac6SHong Zhang     ierr = PetscSFReduceEnd(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
14902bf73ac6SHong Zhang     /* printf("[%d] remote_nvar[%d] = %d\n",rank,p,remote_nvar[p]); */
14912bf73ac6SHong Zhang 
14922bf73ac6SHong Zhang     /* Update roots' local_nvar */
14932bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
14942bf73ac6SHong Zhang       p = svtx[i];
14952bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
14962bf73ac6SHong Zhang       if (ghost) continue;
14972bf73ac6SHong Zhang 
14982bf73ac6SHong Zhang       ierr = PetscSectionAddDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
14992bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
15002bf73ac6SHong Zhang       /* printf("[%d]  After SFReduce: root local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
15012bf73ac6SHong Zhang     }
15022bf73ac6SHong Zhang 
15032bf73ac6SHong Zhang     /* Roots Bcast nvar to leaves */
1504ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
1505ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
15062bf73ac6SHong Zhang 
15072bf73ac6SHong Zhang     /* Leaves reset receved/remote nvar to dm */
15082bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
15092bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
15102bf73ac6SHong Zhang       if (!ghost) continue;
15112bf73ac6SHong Zhang       p = svtx[i];
15122bf73ac6SHong Zhang       /* printf("[%d] leaf reset nvar %d at p= %d \n",rank,remote_nvar[p],p); */
15132bf73ac6SHong Zhang       /* DMNetworkSetNumVariables(dm,p,remote_nvar[p]) */
15142bf73ac6SHong Zhang       ierr = PetscSectionSetDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
15152bf73ac6SHong Zhang     }
15162bf73ac6SHong Zhang 
15172bf73ac6SHong Zhang     ierr = PetscFree2(local_nvar,remote_nvar);CHKERRQ(ierr);
15182bf73ac6SHong Zhang   }
15192bf73ac6SHong Zhang 
15205f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
15215f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
15225f2c45f1SShri Abhyankar }
15235f2c45f1SShri Abhyankar 
152424121865SAdrian Maldonado /* Get a subsection from a range of points */
15259dddd249SSatish Balay static PetscErrorCode DMNetworkGetSubSection_private(PetscSection main,PetscInt pstart,PetscInt pend,PetscSection *subsection)
152624121865SAdrian Maldonado {
152724121865SAdrian Maldonado   PetscErrorCode ierr;
152824121865SAdrian Maldonado   PetscInt       i, nvar;
152924121865SAdrian Maldonado 
153024121865SAdrian Maldonado   PetscFunctionBegin;
15319dddd249SSatish Balay   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)main), subsection);CHKERRQ(ierr);
153224121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
153324121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
15349dddd249SSatish Balay     ierr = PetscSectionGetDof(main,i,&nvar);CHKERRQ(ierr);
153524121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
153624121865SAdrian Maldonado   }
153724121865SAdrian Maldonado 
153824121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
153924121865SAdrian Maldonado   PetscFunctionReturn(0);
154024121865SAdrian Maldonado }
154124121865SAdrian Maldonado 
154224121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
15432bf73ac6SHong Zhang static PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
154424121865SAdrian Maldonado {
154524121865SAdrian Maldonado   PetscErrorCode ierr;
154624121865SAdrian Maldonado   PetscInt       i, *subpoints;
154724121865SAdrian Maldonado 
154824121865SAdrian Maldonado   PetscFunctionBegin;
154924121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
155024121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
155124121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
155224121865SAdrian Maldonado     subpoints[i - pstart] = i;
155324121865SAdrian Maldonado   }
1554459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
155524121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
155624121865SAdrian Maldonado   PetscFunctionReturn(0);
155724121865SAdrian Maldonado }
155824121865SAdrian Maldonado 
155924121865SAdrian Maldonado /*@
15602bf73ac6SHong Zhang   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute
156124121865SAdrian Maldonado 
15622bf73ac6SHong Zhang   Collective on dm
156324121865SAdrian Maldonado 
156424121865SAdrian Maldonado   Input Parameters:
15652bf73ac6SHong Zhang . dm - the DMNetworkObject
156624121865SAdrian Maldonado 
156724121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
156824121865SAdrian Maldonado 
156924121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
157024121865SAdrian Maldonado 
1571caf410d2SHong 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]).
157224121865SAdrian Maldonado 
157324121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
157424121865SAdrian Maldonado 
157524121865SAdrian Maldonado   Level: intermediate
157624121865SAdrian Maldonado 
157724121865SAdrian Maldonado @*/
157824121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
157924121865SAdrian Maldonado {
158024121865SAdrian Maldonado   PetscErrorCode ierr;
158124121865SAdrian Maldonado   MPI_Comm       comm;
1582f11a936eSBarry Smith   PetscMPIInt    size;
158324121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
158424121865SAdrian Maldonado 
1585eab1376dSHong Zhang   PetscFunctionBegin;
158624121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1587ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
158824121865SAdrian Maldonado 
158924121865SAdrian Maldonado   /* Create maps for vertices and edges */
159024121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
159124121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
159224121865SAdrian Maldonado 
159324121865SAdrian Maldonado   /* Create local sub-sections */
159424121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
159524121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
159624121865SAdrian Maldonado 
15979852e123SBarry Smith   if (size > 1) {
159824121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
159922bbedd7SHong Zhang 
160024121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
160124121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
160224121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
160324121865SAdrian Maldonado   } else {
160424121865SAdrian Maldonado     /* create structures for vertex */
160524121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
160624121865SAdrian Maldonado     /* create structures for edge */
160724121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
160824121865SAdrian Maldonado   }
160924121865SAdrian Maldonado 
161024121865SAdrian Maldonado   /* Add viewers */
161124121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
161224121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
161324121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
161424121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
161524121865SAdrian Maldonado   PetscFunctionReturn(0);
161624121865SAdrian Maldonado }
16177b6afd5bSHong Zhang 
1618f11a936eSBarry Smith /*
1619f11a936eSBarry Smith    Add all subnetid for the input vertex v in this process to the btable
1620f11a936eSBarry Smith    vertex_subnetid = supportingedge_subnetid
1621f11a936eSBarry Smith */
1622f11a936eSBarry Smith PETSC_STATIC_INLINE PetscErrorCode SetSubnetIdLookupBT(DM dm,PetscInt v,PetscInt Nsubnet,PetscBT btable)
1623f11a936eSBarry Smith {
1624f11a936eSBarry Smith   PetscErrorCode ierr;
1625f11a936eSBarry Smith   PetscInt       e,nedges,offset;
1626f11a936eSBarry Smith   const PetscInt *edges;
1627f11a936eSBarry Smith   DM_Network     *newDMnetwork = (DM_Network*)dm->data;
1628f11a936eSBarry Smith   DMNetworkComponentHeader header;
1629f11a936eSBarry Smith 
1630f11a936eSBarry Smith   PetscFunctionBegin;
1631f11a936eSBarry Smith   ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1632f11a936eSBarry Smith   ierr = PetscBTMemzero(Nsubnet,btable);CHKERRQ(ierr);
1633f11a936eSBarry Smith   for (e=0; e<nedges; e++) {
1634f11a936eSBarry Smith     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,edges[e],&offset);CHKERRQ(ierr);
1635f11a936eSBarry Smith     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
1636f11a936eSBarry Smith     ierr = PetscBTSet(btable,header->subnetid);CHKERRQ(ierr);
1637f11a936eSBarry Smith   }
1638f11a936eSBarry Smith   PetscFunctionReturn(0);
1639f11a936eSBarry Smith }
1640f11a936eSBarry Smith 
16415f2c45f1SShri Abhyankar /*@
16422bf73ac6SHong Zhang   DMNetworkDistribute - Distributes the network and moves associated component data
16435f2c45f1SShri Abhyankar 
16445f2c45f1SShri Abhyankar   Collective
16455f2c45f1SShri Abhyankar 
1646d8d19677SJose E. Roman   Input Parameters:
1647d3464fd4SAdrian Maldonado + DM - the DMNetwork object
16482bf73ac6SHong Zhang - overlap - the overlap of partitions, 0 is the default
16495f2c45f1SShri Abhyankar 
16505b3f975aSHong Zhang   Options Database Key:
16515b3f975aSHong Zhang + -dmnetwork_view - Calls DMView() at the conclusion of DMSetUp()
16525b3f975aSHong Zhang - -dmnetwork_view_distributed - Calls DMView() at the conclusion of DMNetworkDistribute()
16535b3f975aSHong Zhang 
16545f2c45f1SShri Abhyankar   Notes:
16558b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
16565f2c45f1SShri Abhyankar 
16575f2c45f1SShri Abhyankar   Level: intermediate
16585f2c45f1SShri Abhyankar 
16592bf73ac6SHong Zhang .seealso: DMNetworkCreate()
16605f2c45f1SShri Abhyankar @*/
1661d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
16625f2c45f1SShri Abhyankar {
1663d3464fd4SAdrian Maldonado   MPI_Comm       comm;
16645f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1665d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1666d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1667d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1668caf410d2SHong Zhang   PetscSF        pointsf=NULL;
16695f2c45f1SShri Abhyankar   DM             newDM;
1670f11a936eSBarry Smith   PetscInt       j,e,v,offset,*subnetvtx,*subnetedge,Nsubnet,gidx,svtx_idx,nv;
16712bf73ac6SHong Zhang   PetscInt       to_net,from_net,*svto;
1672f11a936eSBarry Smith   PetscBT        btable;
167351ac5effSHong Zhang   PetscPartitioner         part;
1674b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
16755f2c45f1SShri Abhyankar 
16765f2c45f1SShri Abhyankar   PetscFunctionBegin;
1677d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1678ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1679d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1680d3464fd4SAdrian Maldonado 
16815b3f975aSHong Zhang   if (overlap) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"overlap %D != 0 is not supported yet",overlap);
16825b3f975aSHong Zhang 
16832bf73ac6SHong 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. */
1684d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
16855f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
168654dfd506SHong Zhang   newDMnetwork->max_comps_registered = oldDMnetwork->max_comps_registered;
168754dfd506SHong Zhang   ierr = PetscMalloc1(newDMnetwork->max_comps_registered,&newDMnetwork->component);CHKERRQ(ierr);
168851ac5effSHong Zhang 
168951ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
169051ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
169151ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
169251ac5effSHong Zhang 
16932bf73ac6SHong Zhang   /* Distribute plex dm */
169480cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
169551ac5effSHong Zhang 
16965f2c45f1SShri Abhyankar   /* Distribute dof section */
16972bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DofSection);CHKERRQ(ierr);
16985f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
169951ac5effSHong Zhang 
17005f2c45f1SShri Abhyankar   /* Distribute data and associated section */
17012bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DataSection);CHKERRQ(ierr);
170231da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
170324121865SAdrian Maldonado 
17045f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
17055f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
17065f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
17075f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
17086fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
17096fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
17105f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
1711f11a936eSBarry Smith   newDMnetwork->svtable   = oldDMnetwork->svtable; /* global table! */
17122bf73ac6SHong Zhang   oldDMnetwork->svtable   = NULL;
171324121865SAdrian Maldonado 
17141bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
171592fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1716e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
17175f2c45f1SShri Abhyankar 
1718b9c6e19dSShri Abhyankar   /* Setup subnetwork info in the newDM */
17192bf73ac6SHong Zhang   newDMnetwork->Nsubnet = oldDMnetwork->Nsubnet;
17202bf73ac6SHong Zhang   newDMnetwork->Nsvtx   = oldDMnetwork->Nsvtx;
17212bf73ac6SHong Zhang   oldDMnetwork->Nsvtx   = 0;
17222bf73ac6SHong Zhang   newDMnetwork->svtx    = oldDMnetwork->svtx; /* global vertices! */
17232bf73ac6SHong Zhang   oldDMnetwork->svtx    = NULL;
17242bf73ac6SHong Zhang   ierr = PetscCalloc1(newDMnetwork->Nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
17252bf73ac6SHong Zhang 
17262bf73ac6SHong Zhang   /* Copy over the global number of vertices and edges in each subnetwork.
17272bf73ac6SHong Zhang      Note: these are calculated in DMNetworkLayoutSetUp()
1728b9c6e19dSShri Abhyankar   */
1729f11a936eSBarry Smith   Nsubnet = newDMnetwork->Nsubnet;
1730f11a936eSBarry Smith   for (j = 0; j < Nsubnet; j++) {
1731b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1732b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1733b9c6e19dSShri Abhyankar   }
1734b9c6e19dSShri Abhyankar 
1735f11a936eSBarry Smith   /* Count local nedges for subnetworks */
1736b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1737b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
173854dfd506SHong Zhang     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
173954dfd506SHong Zhang     /* Update pointers */
174054dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
174154dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
174254dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
174354dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
174454dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
174554dfd506SHong Zhang 
1746b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1747b9c6e19dSShri Abhyankar   }
1748b9c6e19dSShri Abhyankar 
1749f11a936eSBarry Smith   /* Count local nvtx for subnetworks */
1750f11a936eSBarry Smith   ierr = PetscBTCreate(Nsubnet,&btable);CHKERRQ(ierr);
1751b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1752b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1753b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
175454dfd506SHong Zhang     /* Update pointers */
175554dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
175654dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
175754dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
175854dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
175954dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
176054dfd506SHong Zhang 
17612bf73ac6SHong Zhang     /* shared vertices: use gidx=header->index to check if v is a shared vertex */
17622bf73ac6SHong Zhang     gidx = header->index;
17632bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
17642bf73ac6SHong Zhang     svtx_idx--;
17652bf73ac6SHong Zhang 
17662bf73ac6SHong Zhang     if (svtx_idx < 0) { /* not a shared vertex */
1767b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].nvtx++;
17682bf73ac6SHong Zhang     } else { /* a shared vertex belongs to more than one subnetworks, it is being counted by multiple subnets */
1769f11a936eSBarry Smith       ierr = SetSubnetIdLookupBT(newDM,v,Nsubnet,btable);CHKERRQ(ierr);
1770f11a936eSBarry Smith 
17712bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
1772f11a936eSBarry Smith       if (PetscBTLookup(btable,from_net)) newDMnetwork->subnet[from_net].nvtx++; /* sv is on from_net */
1773f11a936eSBarry Smith 
17742bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
17752bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
17762bf73ac6SHong Zhang         to_net = svto[0];
1777f11a936eSBarry Smith         if (PetscBTLookup(btable,to_net)) newDMnetwork->subnet[to_net].nvtx++; /* sv is on to_net */
17782bf73ac6SHong Zhang       }
17792bf73ac6SHong Zhang     }
1780b9c6e19dSShri Abhyankar   }
1781b9c6e19dSShri Abhyankar 
17822bf73ac6SHong Zhang   /* Get total local nvtx for subnetworks */
17832bf73ac6SHong Zhang   nv = 0;
1784f11a936eSBarry Smith   for (j=0; j<Nsubnet; j++) nv += newDMnetwork->subnet[j].nvtx;
17852bf73ac6SHong Zhang   nv += newDMnetwork->Nsvtx;
1786caf410d2SHong Zhang 
17872bf73ac6SHong Zhang   /* Now create the vertices and edge arrays for the subnetworks */
1788f11a936eSBarry Smith   ierr = PetscCalloc2(newDMnetwork->nEdges,&subnetedge,nv,&subnetvtx);CHKERRQ(ierr); /* Maps local vertex to local subnetwork's vertex */
1789f11a936eSBarry Smith   newDMnetwork->subnetedge = subnetedge;
17902bf73ac6SHong Zhang   newDMnetwork->subnetvtx  = subnetvtx;
1791f11a936eSBarry Smith   for (j=0; j < newDMnetwork->Nsubnet; j++) {
1792f11a936eSBarry Smith     newDMnetwork->subnet[j].edges = subnetedge;
1793f11a936eSBarry Smith     subnetedge                   += newDMnetwork->subnet[j].nedge;
17942bf73ac6SHong Zhang 
1795caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1796caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1797caf410d2SHong Zhang 
17982bf73ac6SHong 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. */
1799b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1800b9c6e19dSShri Abhyankar   }
18012bf73ac6SHong Zhang   newDMnetwork->svertices = subnetvtx;
1802b9c6e19dSShri Abhyankar 
18032bf73ac6SHong Zhang   /* Set the edges and vertices in each subnetwork */
1804b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1805b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1806b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1807b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1808b9c6e19dSShri Abhyankar   }
1809b9c6e19dSShri Abhyankar 
18102bf73ac6SHong Zhang   nv = 0;
1811b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1812b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1813b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
18142bf73ac6SHong Zhang 
18152bf73ac6SHong Zhang     /* coupling vertices: use gidx = header->index to check if v is a coupling vertex */
18162bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,header->index+1,&svtx_idx);CHKERRQ(ierr);
18172bf73ac6SHong Zhang     svtx_idx--;
18182bf73ac6SHong Zhang     if (svtx_idx < 0) {
1819b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
18202bf73ac6SHong Zhang     } else { /* a shared vertex */
18212bf73ac6SHong Zhang       newDMnetwork->svertices[nv++] = v;
18222bf73ac6SHong Zhang 
1823f11a936eSBarry Smith       /* add all subnetid for this shared vertex in this process to btable */
1824f11a936eSBarry Smith       ierr = SetSubnetIdLookupBT(newDM,v,Nsubnet,btable);CHKERRQ(ierr);
1825f11a936eSBarry Smith 
18262bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
1827f11a936eSBarry Smith       if (PetscBTLookup(btable,from_net))
18282bf73ac6SHong Zhang         newDMnetwork->subnet[from_net].vertices[newDMnetwork->subnet[from_net].nvtx++] = v;
18292bf73ac6SHong Zhang 
18302bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
18312bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
18322bf73ac6SHong Zhang         to_net = svto[0];
1833f11a936eSBarry Smith         if (PetscBTLookup(btable,to_net))
18342bf73ac6SHong Zhang           newDMnetwork->subnet[to_net].vertices[newDMnetwork->subnet[to_net].nvtx++] = v;
1835b9c6e19dSShri Abhyankar       }
18362bf73ac6SHong Zhang     }
18372bf73ac6SHong Zhang   }
18382bf73ac6SHong Zhang   newDMnetwork->nsvtx = nv;   /* num of local shared vertices */
1839b9c6e19dSShri Abhyankar 
1840caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
184122bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1842caf410d2SHong Zhang 
18432bf73ac6SHong Zhang   /* Free spaces */
184424121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
1845d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
1846f11a936eSBarry Smith   ierr = PetscBTDestroy(&btable);CHKERRQ(ierr);
18472bf73ac6SHong Zhang 
18485b3f975aSHong Zhang   /* View distributed dmnetwork */
18495b3f975aSHong Zhang   ierr = DMViewFromOptions(newDM,NULL,"-dmnetwork_view_distributed");CHKERRQ(ierr);
18505b3f975aSHong Zhang 
1851d3464fd4SAdrian Maldonado   *dm  = newDM;
18525f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18535f2c45f1SShri Abhyankar }
18545f2c45f1SShri Abhyankar 
185524121865SAdrian Maldonado /*@C
18562bf73ac6SHong Zhang   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering
18572bf73ac6SHong Zhang 
18582bf73ac6SHong Zhang  Collective
185924121865SAdrian Maldonado 
186024121865SAdrian Maldonado   Input Parameters:
18619dddd249SSatish Balay + mainSF - the original SF structure
186224121865SAdrian Maldonado - map - a ISLocalToGlobal mapping that contains the subset of points
186324121865SAdrian Maldonado 
186497bb3fdcSJose E. Roman   Output Parameter:
18659dddd249SSatish Balay . subSF - a subset of the mainSF for the desired subset.
1866ee300463SSatish Balay 
1867ee300463SSatish Balay   Level: intermediate
18687d928bffSSatish Balay @*/
18699dddd249SSatish Balay PetscErrorCode PetscSFGetSubSF(PetscSF mainsf,ISLocalToGlobalMapping map,PetscSF *subSF)
18702bf73ac6SHong Zhang {
187124121865SAdrian Maldonado   PetscErrorCode        ierr;
187224121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
187324121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
187424121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
187524121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
187624121865SAdrian Maldonado   const PetscInt        *ilocal;
187724121865SAdrian Maldonado   const PetscSFNode     *iremote;
187824121865SAdrian Maldonado 
187924121865SAdrian Maldonado   PetscFunctionBegin;
18809dddd249SSatish Balay   ierr = PetscSFGetGraph(mainsf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
188124121865SAdrian Maldonado 
188224121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
188324121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
188424121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
188524121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
188624121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
188724121865SAdrian Maldonado   }
188824121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
188924121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
189024121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
189124121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
1892ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
1893ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
189424121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
18954b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
18964b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
189724121865SAdrian Maldonado   nleaves_sub = 0;
189824121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
189924121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
190024121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
19014b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
190224121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
190324121865SAdrian Maldonado       nleaves_sub += 1;
190424121865SAdrian Maldonado     }
190524121865SAdrian Maldonado   }
190624121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
190724121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
190824121865SAdrian Maldonado 
190924121865SAdrian Maldonado   /* Create new subSF */
191024121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
191124121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
19124b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
191324121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
19144b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
191524121865SAdrian Maldonado   PetscFunctionReturn(0);
191624121865SAdrian Maldonado }
191724121865SAdrian Maldonado 
19185f2c45f1SShri Abhyankar /*@C
19195f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
19205f2c45f1SShri Abhyankar 
19215f2c45f1SShri Abhyankar   Not Collective
19225f2c45f1SShri Abhyankar 
19235f2c45f1SShri Abhyankar   Input Parameters:
19242bf73ac6SHong Zhang + dm - the DMNetwork object
19255f2c45f1SShri Abhyankar - p  - the vertex point
19265f2c45f1SShri Abhyankar 
1927fd292e60Sprj-   Output Parameters:
19285f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
19292bf73ac6SHong Zhang - edges  - list of edge points
19305f2c45f1SShri Abhyankar 
193197bb938eSShri Abhyankar   Level: beginner
19325f2c45f1SShri Abhyankar 
19335f2c45f1SShri Abhyankar   Fortran Notes:
19345f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
19355f2c45f1SShri Abhyankar   include petsc.h90 in your code.
19365f2c45f1SShri Abhyankar 
19372bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetConnectedVertices()
19385f2c45f1SShri Abhyankar @*/
19395f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
19405f2c45f1SShri Abhyankar {
19415f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19425f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19435f2c45f1SShri Abhyankar 
19445f2c45f1SShri Abhyankar   PetscFunctionBegin;
19455f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
1946a9b4a83eSHong Zhang   if (edges) {ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);}
19475f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19485f2c45f1SShri Abhyankar }
19495f2c45f1SShri Abhyankar 
19505f2c45f1SShri Abhyankar /*@C
1951d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
19525f2c45f1SShri Abhyankar 
19535f2c45f1SShri Abhyankar   Not Collective
19545f2c45f1SShri Abhyankar 
19555f2c45f1SShri Abhyankar   Input Parameters:
19562bf73ac6SHong Zhang + dm - the DMNetwork object
19575f2c45f1SShri Abhyankar - p - the edge point
19585f2c45f1SShri Abhyankar 
1959fd292e60Sprj-   Output Parameters:
19605f2c45f1SShri Abhyankar . vertices - vertices connected to this edge
19615f2c45f1SShri Abhyankar 
196297bb938eSShri Abhyankar   Level: beginner
19635f2c45f1SShri Abhyankar 
19645f2c45f1SShri Abhyankar   Fortran Notes:
19655f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
19665f2c45f1SShri Abhyankar   include petsc.h90 in your code.
19675f2c45f1SShri Abhyankar 
19682bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetSupportingEdges()
19695f2c45f1SShri Abhyankar @*/
1970d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
19715f2c45f1SShri Abhyankar {
19725f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19735f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19745f2c45f1SShri Abhyankar 
19755f2c45f1SShri Abhyankar   PetscFunctionBegin;
19765f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
19775f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19785f2c45f1SShri Abhyankar }
19795f2c45f1SShri Abhyankar 
19805f2c45f1SShri Abhyankar /*@
19812bf73ac6SHong Zhang   DMNetworkIsSharedVertex - Returns TRUE if the vertex is shared by subnetworks
19822bf73ac6SHong Zhang 
19832bf73ac6SHong Zhang   Not Collective
19842bf73ac6SHong Zhang 
19852bf73ac6SHong Zhang   Input Parameters:
19862bf73ac6SHong Zhang + dm - the DMNetwork object
19872bf73ac6SHong Zhang - p - the vertex point
19882bf73ac6SHong Zhang 
19892bf73ac6SHong Zhang   Output Parameter:
19902bf73ac6SHong Zhang . flag - TRUE if the vertex is shared by subnetworks
19912bf73ac6SHong Zhang 
19922bf73ac6SHong Zhang   Level: beginner
19932bf73ac6SHong Zhang 
19942bf73ac6SHong Zhang .seealso: DMNetworkAddSharedVertices(), DMNetworkIsGhostVertex()
19952bf73ac6SHong Zhang @*/
19962bf73ac6SHong Zhang PetscErrorCode DMNetworkIsSharedVertex(DM dm,PetscInt p,PetscBool *flag)
19972bf73ac6SHong Zhang {
19982bf73ac6SHong Zhang   PetscErrorCode ierr;
19992bf73ac6SHong Zhang   PetscInt       i;
20002bf73ac6SHong Zhang 
20012bf73ac6SHong Zhang   PetscFunctionBegin;
20022bf73ac6SHong Zhang   *flag = PETSC_FALSE;
20032bf73ac6SHong Zhang 
20042bf73ac6SHong Zhang   if (dm->setupcalled) { /* DMNetworkGetGlobalVertexIndex() requires DMSetUp() be called */
20052bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
20062bf73ac6SHong Zhang     PetscInt       gidx;
20072bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVertexIndex(dm,p,&gidx);CHKERRQ(ierr);
20082bf73ac6SHong Zhang     ierr = PetscTableFind(network->svtable,gidx+1,&i);CHKERRQ(ierr);
20092bf73ac6SHong Zhang     if (i) *flag = PETSC_TRUE;
20102bf73ac6SHong Zhang   } else { /* would be removed? */
20112bf73ac6SHong Zhang     PetscInt       nv;
20122bf73ac6SHong Zhang     const PetscInt *vtx;
20132bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nv,&vtx);CHKERRQ(ierr);
20142bf73ac6SHong Zhang     for (i=0; i<nv; i++) {
20152bf73ac6SHong Zhang       if (p == vtx[i]) {
20162bf73ac6SHong Zhang         *flag = PETSC_TRUE;
20172bf73ac6SHong Zhang         break;
20182bf73ac6SHong Zhang       }
20192bf73ac6SHong Zhang     }
20202bf73ac6SHong Zhang   }
20212bf73ac6SHong Zhang   PetscFunctionReturn(0);
20222bf73ac6SHong Zhang }
20232bf73ac6SHong Zhang 
20242bf73ac6SHong Zhang /*@
20255f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
20265f2c45f1SShri Abhyankar 
20275f2c45f1SShri Abhyankar   Not Collective
20285f2c45f1SShri Abhyankar 
20295f2c45f1SShri Abhyankar   Input Parameters:
20302bf73ac6SHong Zhang + dm - the DMNetwork object
2031a2b725a8SWilliam Gropp - p - the vertex point
20325f2c45f1SShri Abhyankar 
20335f2c45f1SShri Abhyankar   Output Parameter:
20345f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
20355f2c45f1SShri Abhyankar 
203697bb938eSShri Abhyankar   Level: beginner
20375f2c45f1SShri Abhyankar 
20382bf73ac6SHong Zhang .seealso: DMNetworkGetConnectedVertices(), DMNetworkGetVertexRange(), DMNetworkIsSharedVertex()
20395f2c45f1SShri Abhyankar @*/
20405f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
20415f2c45f1SShri Abhyankar {
20425f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20435f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20445f2c45f1SShri Abhyankar   PetscInt       offsetg;
20455f2c45f1SShri Abhyankar   PetscSection   sectiong;
20465f2c45f1SShri Abhyankar 
20475f2c45f1SShri Abhyankar   PetscFunctionBegin;
20485f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
2049e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
20505f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
20515f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
20525f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20535f2c45f1SShri Abhyankar }
20545f2c45f1SShri Abhyankar 
20555f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
20565f2c45f1SShri Abhyankar {
20575f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20585f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
20595f2c45f1SShri Abhyankar 
20605f2c45f1SShri Abhyankar   PetscFunctionBegin;
20615f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
20625f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
20635f2c45f1SShri Abhyankar 
206492fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
2065e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
20669e1d080bSHong Zhang 
20679e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
20685b3f975aSHong Zhang 
20695b3f975aSHong Zhang   /* View dmnetwork */
20705b3f975aSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dmnetwork_view");CHKERRQ(ierr);
20715f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20725f2c45f1SShri Abhyankar }
20735f2c45f1SShri Abhyankar 
20741ad426b7SHong Zhang /*@
207517df6e9eSHong Zhang   DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
20761ad426b7SHong Zhang       -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
20771ad426b7SHong Zhang 
20781ad426b7SHong Zhang   Collective
20791ad426b7SHong Zhang 
20801ad426b7SHong Zhang   Input Parameters:
20812bf73ac6SHong Zhang + dm - the DMNetwork object
208283b2e829SHong Zhang . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
208383b2e829SHong Zhang - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
20841ad426b7SHong Zhang 
20851ad426b7SHong Zhang  Level: intermediate
20861ad426b7SHong Zhang 
20871ad426b7SHong Zhang @*/
208883b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
20891ad426b7SHong Zhang {
20901ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
20918675203cSHong Zhang   PetscErrorCode ierr;
209266b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
20931ad426b7SHong Zhang 
20941ad426b7SHong Zhang   PetscFunctionBegin;
209583b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
209683b2e829SHong Zhang   network->userVertexJacobian = vflg;
20978675203cSHong Zhang 
20988675203cSHong Zhang   if (eflg && !network->Je) {
20998675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
21008675203cSHong Zhang   }
21018675203cSHong Zhang 
210266b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
21038675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
210466b4e0ffSHong Zhang     PetscInt       nedges_total;
21058675203cSHong Zhang     const PetscInt *edges;
21068675203cSHong Zhang 
21078675203cSHong Zhang     /* count nvertex_total */
21088675203cSHong Zhang     nedges_total = 0;
21098675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
21108675203cSHong Zhang 
21118675203cSHong Zhang     vptr[0] = 0;
21128675203cSHong Zhang     for (i=0; i<nVertices; i++) {
21138675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
21148675203cSHong Zhang       nedges_total += nedges;
21158675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
21168675203cSHong Zhang     }
21178675203cSHong Zhang 
21188675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
21198675203cSHong Zhang     network->Jvptr = vptr;
21208675203cSHong Zhang   }
21211ad426b7SHong Zhang   PetscFunctionReturn(0);
21221ad426b7SHong Zhang }
21231ad426b7SHong Zhang 
21241ad426b7SHong Zhang /*@
212583b2e829SHong Zhang   DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
212683b2e829SHong Zhang 
212783b2e829SHong Zhang   Not Collective
212883b2e829SHong Zhang 
212983b2e829SHong Zhang   Input Parameters:
21302bf73ac6SHong Zhang + dm - the DMNetwork object
213183b2e829SHong Zhang . p - the edge point
21323e97b6e8SHong Zhang - J - array (size = 3) of Jacobian submatrices for this edge point:
21333e97b6e8SHong Zhang         J[0]: this edge
2134d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
213583b2e829SHong Zhang 
213697bb938eSShri Abhyankar   Level: advanced
213783b2e829SHong Zhang 
21382bf73ac6SHong Zhang .seealso: DMNetworkVertexSetMatrix()
213983b2e829SHong Zhang @*/
214083b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
214183b2e829SHong Zhang {
214283b2e829SHong Zhang   DM_Network *network=(DM_Network*)dm->data;
214383b2e829SHong Zhang 
214483b2e829SHong Zhang   PetscFunctionBegin;
21458675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
21468675203cSHong Zhang 
21478675203cSHong Zhang   if (J) {
2148883e35e8SHong Zhang     network->Je[3*p]   = J[0];
2149883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
2150883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
21518675203cSHong Zhang   }
215283b2e829SHong Zhang   PetscFunctionReturn(0);
215383b2e829SHong Zhang }
215483b2e829SHong Zhang 
215583b2e829SHong Zhang /*@
215676ddfea5SHong Zhang   DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
21571ad426b7SHong Zhang 
21581ad426b7SHong Zhang   Not Collective
21591ad426b7SHong Zhang 
21601ad426b7SHong Zhang   Input Parameters:
21611ad426b7SHong Zhang + dm - The DMNetwork object
21621ad426b7SHong Zhang . p - the vertex point
21633e97b6e8SHong Zhang - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
21643e97b6e8SHong Zhang         J[0]:       this vertex
21653e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
21663e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
21671ad426b7SHong Zhang 
216897bb938eSShri Abhyankar   Level: advanced
21691ad426b7SHong Zhang 
21702bf73ac6SHong Zhang .seealso: DMNetworkEdgeSetMatrix()
21711ad426b7SHong Zhang @*/
2172883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
21735f2c45f1SShri Abhyankar {
21745f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21755f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
21768675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
2177883e35e8SHong Zhang   const PetscInt *edges;
21785f2c45f1SShri Abhyankar 
21795f2c45f1SShri Abhyankar   PetscFunctionBegin;
21808675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
2181883e35e8SHong Zhang 
21828675203cSHong Zhang   if (J) {
2183883e35e8SHong Zhang     vptr = network->Jvptr;
21843e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
21853e97b6e8SHong Zhang 
21863e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
2187883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
2188883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
21898675203cSHong Zhang   }
2190883e35e8SHong Zhang   PetscFunctionReturn(0);
2191883e35e8SHong Zhang }
2192883e35e8SHong Zhang 
2193e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
21945cf7da58SHong Zhang {
21955cf7da58SHong Zhang   PetscErrorCode ierr;
21965cf7da58SHong Zhang   PetscInt       j;
21975cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
21985cf7da58SHong Zhang 
21995cf7da58SHong Zhang   PetscFunctionBegin;
22005cf7da58SHong Zhang   if (!ghost) {
22015cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22025cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22035cf7da58SHong Zhang     }
22045cf7da58SHong Zhang   } else {
22055cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22065cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22075cf7da58SHong Zhang     }
22085cf7da58SHong Zhang   }
22095cf7da58SHong Zhang   PetscFunctionReturn(0);
22105cf7da58SHong Zhang }
22115cf7da58SHong Zhang 
2212e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
22135cf7da58SHong Zhang {
22145cf7da58SHong Zhang   PetscErrorCode ierr;
22155cf7da58SHong Zhang   PetscInt       j,ncols_u;
22165cf7da58SHong Zhang   PetscScalar    val;
22175cf7da58SHong Zhang 
22185cf7da58SHong Zhang   PetscFunctionBegin;
22195cf7da58SHong Zhang   if (!ghost) {
22205cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22215cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22225cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
22235cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22245cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22255cf7da58SHong Zhang     }
22265cf7da58SHong Zhang   } else {
22275cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22285cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22295cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
22305cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22315cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22325cf7da58SHong Zhang     }
22335cf7da58SHong Zhang   }
22345cf7da58SHong Zhang   PetscFunctionReturn(0);
22355cf7da58SHong Zhang }
22365cf7da58SHong Zhang 
2237e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
22385cf7da58SHong Zhang {
22395cf7da58SHong Zhang   PetscErrorCode ierr;
22405cf7da58SHong Zhang 
22415cf7da58SHong Zhang   PetscFunctionBegin;
22425cf7da58SHong Zhang   if (Ju) {
22435cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
22445cf7da58SHong Zhang   } else {
22455cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
22465cf7da58SHong Zhang   }
22475cf7da58SHong Zhang   PetscFunctionReturn(0);
22485cf7da58SHong Zhang }
22495cf7da58SHong Zhang 
2250e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2251883e35e8SHong Zhang {
2252883e35e8SHong Zhang   PetscErrorCode ierr;
2253883e35e8SHong Zhang   PetscInt       j,*cols;
2254883e35e8SHong Zhang   PetscScalar    *zeros;
2255883e35e8SHong Zhang 
2256883e35e8SHong Zhang   PetscFunctionBegin;
2257883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
2258883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
2259883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
2260883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
22611ad426b7SHong Zhang   PetscFunctionReturn(0);
22621ad426b7SHong Zhang }
2263a4e85ca8SHong Zhang 
2264e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
22653e97b6e8SHong Zhang {
22663e97b6e8SHong Zhang   PetscErrorCode ierr;
22673e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
22683e97b6e8SHong Zhang   const PetscInt *cols;
22693e97b6e8SHong Zhang   PetscScalar    zero=0.0;
22703e97b6e8SHong Zhang 
22713e97b6e8SHong Zhang   PetscFunctionBegin;
22723e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
22733e97b6e8SHong 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);
22743e97b6e8SHong Zhang 
22753e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
22763e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
22773e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
22783e97b6e8SHong Zhang       col = cols[j] + cstart;
22793e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
22803e97b6e8SHong Zhang     }
22813e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
22823e97b6e8SHong Zhang   }
22833e97b6e8SHong Zhang   PetscFunctionReturn(0);
22843e97b6e8SHong Zhang }
22851ad426b7SHong Zhang 
2286e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2287a4e85ca8SHong Zhang {
2288a4e85ca8SHong Zhang   PetscErrorCode ierr;
2289f4431b8cSHong Zhang 
2290a4e85ca8SHong Zhang   PetscFunctionBegin;
2291a4e85ca8SHong Zhang   if (Ju) {
2292a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2293a4e85ca8SHong Zhang   } else {
2294a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2295a4e85ca8SHong Zhang   }
2296a4e85ca8SHong Zhang   PetscFunctionReturn(0);
2297a4e85ca8SHong Zhang }
2298a4e85ca8SHong Zhang 
229924121865SAdrian 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.
230024121865SAdrian Maldonado */
230124121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
230224121865SAdrian Maldonado {
230324121865SAdrian Maldonado   PetscErrorCode ierr;
230424121865SAdrian Maldonado   PetscInt       i,size,dof;
230524121865SAdrian Maldonado   PetscInt       *glob2loc;
230624121865SAdrian Maldonado 
230724121865SAdrian Maldonado   PetscFunctionBegin;
230824121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
230924121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
231024121865SAdrian Maldonado 
231124121865SAdrian Maldonado   for (i = 0; i < size; i++) {
231224121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
231324121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
231424121865SAdrian Maldonado     glob2loc[i] = dof;
231524121865SAdrian Maldonado   }
231624121865SAdrian Maldonado 
231724121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
231824121865SAdrian Maldonado #if 0
231924121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
232024121865SAdrian Maldonado #endif
232124121865SAdrian Maldonado   PetscFunctionReturn(0);
232224121865SAdrian Maldonado }
232324121865SAdrian Maldonado 
232401ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
23259e1d080bSHong Zhang 
23269e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
23271ad426b7SHong Zhang {
23281ad426b7SHong Zhang   PetscErrorCode ierr;
23291ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
233024121865SAdrian Maldonado   PetscInt       eDof,vDof;
233124121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
23329e1d080bSHong Zhang   MPI_Comm       comm;
233324121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
233424121865SAdrian Maldonado 
23359e1d080bSHong Zhang   PetscFunctionBegin;
233624121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
233724121865SAdrian Maldonado 
233824121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
233924121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
234024121865SAdrian Maldonado 
234101ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
234224121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
234324121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
234424121865SAdrian Maldonado 
234501ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
234624121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
234724121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
234824121865SAdrian Maldonado 
234901ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
235024121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
235124121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
235224121865SAdrian Maldonado 
235301ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
235424121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
235524121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
235624121865SAdrian Maldonado 
23573f6a6bdaSHong Zhang   bA[0][0] = j11;
23583f6a6bdaSHong Zhang   bA[0][1] = j12;
23593f6a6bdaSHong Zhang   bA[1][0] = j21;
23603f6a6bdaSHong Zhang   bA[1][1] = j22;
236124121865SAdrian Maldonado 
236224121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
236324121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
236424121865SAdrian Maldonado 
236524121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
236624121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
236724121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
236824121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
236924121865SAdrian Maldonado 
237024121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
237124121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
237224121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
237324121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
237424121865SAdrian Maldonado 
237501ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
237624121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
237724121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
237824121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
237924121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
238024121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
238124121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
238224121865SAdrian Maldonado 
238324121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
238424121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23859e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
238624121865SAdrian Maldonado 
238724121865SAdrian Maldonado   /* Free structures */
238824121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
238924121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
239024121865SAdrian Maldonado   PetscFunctionReturn(0);
23919e1d080bSHong Zhang }
23929e1d080bSHong Zhang 
23939e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
23949e1d080bSHong Zhang {
23959e1d080bSHong Zhang   PetscErrorCode ierr;
23969e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
23979e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
23989e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
23999e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
24009e1d080bSHong Zhang   Mat            Juser;
24019e1d080bSHong Zhang   PetscSection   sectionGlobal;
24029e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
24039e1d080bSHong Zhang   const PetscInt *edges,*cone;
24049e1d080bSHong Zhang   MPI_Comm       comm;
24059e1d080bSHong Zhang   MatType        mtype;
24069e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
24079e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
24089e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
24099e1d080bSHong Zhang 
24109e1d080bSHong Zhang   PetscFunctionBegin;
24119e1d080bSHong Zhang   mtype = dm->mattype;
24129e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
24139e1d080bSHong Zhang   if (isNest) {
24149e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
2415c6b011d8SStefano Zampini     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
24169e1d080bSHong Zhang     PetscFunctionReturn(0);
24179e1d080bSHong Zhang   }
24189e1d080bSHong Zhang 
24199e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
2420a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
24219e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
2422bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
24231ad426b7SHong Zhang     PetscFunctionReturn(0);
24241ad426b7SHong Zhang   }
24251ad426b7SHong Zhang 
2426bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
2427e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
2428bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
2429bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
24302a945128SHong Zhang 
24312a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
24322a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
243389898e50SHong Zhang 
243489898e50SHong Zhang   /* (1) Set matrix preallocation */
243589898e50SHong Zhang   /*------------------------------*/
2436840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2437840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
2438840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
2439840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
2440840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
2441840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
2442840c2264SHong Zhang 
244389898e50SHong Zhang   /* Set preallocation for edges */
244489898e50SHong Zhang   /*-----------------------------*/
2445840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
2446840c2264SHong Zhang 
2447bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
2448840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
2449840c2264SHong Zhang     /* Get row indices */
24502bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
24512bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
2452840c2264SHong Zhang     if (nrows) {
2453840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
2454840c2264SHong Zhang 
2455a5b23f4aSJose E. Roman       /* Set preallocation for connected vertices */
2456d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2457840c2264SHong Zhang       for (v=0; v<2; v++) {
24582bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
2459840c2264SHong Zhang 
24608675203cSHong Zhang         if (network->Je) {
2461840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
24628675203cSHong Zhang         } else Juser = NULL;
2463840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
24645cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2465840c2264SHong Zhang       }
2466840c2264SHong Zhang 
246789898e50SHong Zhang       /* Set preallocation for edge self */
2468840c2264SHong Zhang       cstart = rstart;
24698675203cSHong Zhang       if (network->Je) {
2470840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
24718675203cSHong Zhang       } else Juser = NULL;
24725cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2473840c2264SHong Zhang     }
2474840c2264SHong Zhang   }
2475840c2264SHong Zhang 
247689898e50SHong Zhang   /* Set preallocation for vertices */
247789898e50SHong Zhang   /*--------------------------------*/
2478840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
24798675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
2480840c2264SHong Zhang 
2481840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
2482840c2264SHong Zhang     /* Get row indices */
24832bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
24842bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
2485840c2264SHong Zhang     if (!nrows) continue;
2486840c2264SHong Zhang 
2487bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2488bdcb62a2SHong Zhang     if (ghost) {
2489bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2490bdcb62a2SHong Zhang     } else {
2491bdcb62a2SHong Zhang       rows_v = rows;
2492bdcb62a2SHong Zhang     }
2493bdcb62a2SHong Zhang 
2494bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2495840c2264SHong Zhang 
2496840c2264SHong Zhang     /* Get supporting edges and connected vertices */
2497840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2498840c2264SHong Zhang 
2499840c2264SHong Zhang     for (e=0; e<nedges; e++) {
2500840c2264SHong Zhang       /* Supporting edges */
25012bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25022bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2503840c2264SHong Zhang 
25048675203cSHong Zhang       if (network->Jv) {
2505840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
25068675203cSHong Zhang       } else Juser = NULL;
2507bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2508840c2264SHong Zhang 
2509840c2264SHong Zhang       /* Connected vertices */
2510d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
2511840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
2512840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
2513840c2264SHong Zhang 
25142bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2515840c2264SHong Zhang 
25168675203cSHong Zhang       if (network->Jv) {
2517840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
25188675203cSHong Zhang       } else Juser = NULL;
2519e102a522SHong Zhang       if (ghost_vc||ghost) {
2520e102a522SHong Zhang         ghost2 = PETSC_TRUE;
2521e102a522SHong Zhang       } else {
2522e102a522SHong Zhang         ghost2 = PETSC_FALSE;
2523e102a522SHong Zhang       }
2524e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
2525840c2264SHong Zhang     }
2526840c2264SHong Zhang 
252789898e50SHong Zhang     /* Set preallocation for vertex self */
2528840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2529840c2264SHong Zhang     if (!ghost) {
25302bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25318675203cSHong Zhang       if (network->Jv) {
2532840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
25338675203cSHong Zhang       } else Juser = NULL;
2534bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2535840c2264SHong Zhang     }
2536bdcb62a2SHong Zhang     if (ghost) {
2537bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2538bdcb62a2SHong Zhang     }
2539840c2264SHong Zhang   }
2540840c2264SHong Zhang 
2541840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
2542840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
25435cf7da58SHong Zhang 
25445cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
25455cf7da58SHong Zhang 
25465cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
2547840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
2548840c2264SHong Zhang 
2549840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
2550840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
2551840c2264SHong Zhang   for (j=0; j<localSize; j++) {
2552e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
2553e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
2554840c2264SHong Zhang   }
2555840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
2556840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
2557840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
2558840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
2559840c2264SHong Zhang 
25605cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
25615cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
25625cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
25635cf7da58SHong Zhang 
25645cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
25655cf7da58SHong Zhang 
256689898e50SHong Zhang   /* (2) Set matrix entries for edges */
256789898e50SHong Zhang   /*----------------------------------*/
25681ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
2569bfbc38dcSHong Zhang     /* Get row indices */
25702bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
25712bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
25724b976069SHong Zhang     if (nrows) {
257317df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
25741ad426b7SHong Zhang 
2575a5b23f4aSJose E. Roman       /* Set matrix entries for connected vertices */
2576d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2577bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
25782bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVecOffset(dm,cone[v],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25792bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
25803e97b6e8SHong Zhang 
25818675203cSHong Zhang         if (network->Je) {
2582a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
25838675203cSHong Zhang         } else Juser = NULL;
2584a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2585bfbc38dcSHong Zhang       }
258617df6e9eSHong Zhang 
2587bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
25883e97b6e8SHong Zhang       cstart = rstart;
25898675203cSHong Zhang       if (network->Je) {
2590a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
25918675203cSHong Zhang       } else Juser = NULL;
2592a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
25931ad426b7SHong Zhang     }
25944b976069SHong Zhang   }
25951ad426b7SHong Zhang 
2596bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
259783b2e829SHong Zhang   /*---------------------------------*/
25981ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2599bfbc38dcSHong Zhang     /* Get row indices */
26002bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
26012bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
26024b976069SHong Zhang     if (!nrows) continue;
2603596e729fSHong Zhang 
2604bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2605bdcb62a2SHong Zhang     if (ghost) {
2606bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2607bdcb62a2SHong Zhang     } else {
2608bdcb62a2SHong Zhang       rows_v = rows;
2609bdcb62a2SHong Zhang     }
2610bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2611596e729fSHong Zhang 
2612bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2613596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2614596e729fSHong Zhang 
2615596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2616bfbc38dcSHong Zhang       /* Supporting edges */
26172bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
26182bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2619596e729fSHong Zhang 
26208675203cSHong Zhang       if (network->Jv) {
2621a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
26228675203cSHong Zhang       } else Juser = NULL;
2623bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2624596e729fSHong Zhang 
2625bfbc38dcSHong Zhang       /* Connected vertices */
2626d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
26272a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
26282a945128SHong Zhang 
26292bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,vc,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
26302bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2631a4e85ca8SHong Zhang 
26328675203cSHong Zhang       if (network->Jv) {
2633a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
26348675203cSHong Zhang       } else Juser = NULL;
2635bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2636596e729fSHong Zhang     }
2637596e729fSHong Zhang 
2638bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
26391ad426b7SHong Zhang     if (!ghost) {
26402bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
26418675203cSHong Zhang       if (network->Jv) {
2642a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
26438675203cSHong Zhang       } else Juser = NULL;
2644bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2645bdcb62a2SHong Zhang     }
2646bdcb62a2SHong Zhang     if (ghost) {
2647bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2648bdcb62a2SHong Zhang     }
26491ad426b7SHong Zhang   }
2650a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2651bdcb62a2SHong Zhang 
26521ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
26531ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2654dd6f46cdSHong Zhang 
26555f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
26565f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26575f2c45f1SShri Abhyankar }
26585f2c45f1SShri Abhyankar 
26595f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
26605f2c45f1SShri Abhyankar {
26615f2c45f1SShri Abhyankar   PetscErrorCode ierr;
26625f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
266354dfd506SHong Zhang   PetscInt       j,np;
26645f2c45f1SShri Abhyankar 
26655f2c45f1SShri Abhyankar   PetscFunctionBegin;
26668415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
266783b2e829SHong Zhang   if (network->Je) {
266883b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
266983b2e829SHong Zhang   }
267083b2e829SHong Zhang   if (network->Jv) {
2671883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
267283b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
26731ad426b7SHong Zhang   }
267413c2a604SAdrian Maldonado 
267513c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
267613c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
267713c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2678f5427c60SHong Zhang   if (network->vltog) {
2679f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2680f5427c60SHong Zhang   }
268113c2a604SAdrian Maldonado   if (network->vertex.sf) {
268213c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
268313c2a604SAdrian Maldonado   }
268413c2a604SAdrian Maldonado   /* edge */
268513c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
268613c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
268713c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
268813c2a604SAdrian Maldonado   if (network->edge.sf) {
268913c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
269013c2a604SAdrian Maldonado   }
26915f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
26925f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
26935f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
269483b2e829SHong Zhang 
26952bf73ac6SHong Zhang   for (j=0; j<network->Nsvtx; j++) {
26962bf73ac6SHong Zhang     ierr = PetscFree(network->svtx[j].sv);CHKERRQ(ierr);
26972bf73ac6SHong Zhang   }
26982bf73ac6SHong Zhang   if (network->svtx) {ierr = PetscFree(network->svtx);CHKERRQ(ierr);}
2699f11a936eSBarry Smith   ierr = PetscFree2(network->subnetedge,network->subnetvtx);CHKERRQ(ierr);
2700caf410d2SHong Zhang 
27012bf73ac6SHong Zhang   ierr = PetscTableDestroy(&network->svtable);CHKERRQ(ierr);
2702e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
270354dfd506SHong Zhang   ierr = PetscFree(network->component);CHKERRQ(ierr);
27045f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
270554dfd506SHong Zhang 
270654dfd506SHong Zhang   if (network->header) {
270754dfd506SHong Zhang     np = network->pEnd - network->pStart;
270854dfd506SHong Zhang     for (j=0; j < np; j++) {
270954dfd506SHong 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);
271054dfd506SHong Zhang       ierr = PetscFree(network->cvalue[j].data);CHKERRQ(ierr);
271154dfd506SHong Zhang     }
2712caf410d2SHong Zhang     ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
271354dfd506SHong Zhang   }
27145f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
27155f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27165f2c45f1SShri Abhyankar }
27175f2c45f1SShri Abhyankar 
27185f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
27195f2c45f1SShri Abhyankar {
27205f2c45f1SShri Abhyankar   PetscErrorCode ierr;
2721caf410d2SHong Zhang   PetscBool      iascii;
2722caf410d2SHong Zhang   PetscMPIInt    rank;
27235f2c45f1SShri Abhyankar 
27245f2c45f1SShri Abhyankar   PetscFunctionBegin;
2725caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2726ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
2727caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2728caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2729caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2730caf410d2SHong Zhang   if (iascii) {
2731caf410d2SHong Zhang     const PetscInt *cone,*vtx,*edges;
27322bf73ac6SHong Zhang     PetscInt       vfrom,vto,i,j,nv,ne,ncv,p,nsubnet;
27332bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
2734caf410d2SHong Zhang 
27352bf73ac6SHong Zhang     nsubnet = network->Nsubnet; /* num of subnetworks */
2736dd400576SPatrick Sanan     if (rank == 0) {
27372bf73ac6SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  NSubnets: %D; NEdges: %D; NVertices: %D; NSharedVertices: %D.\n",nsubnet,network->NEdges,network->NVertices,network->Nsvtx);CHKERRQ(ierr);
27382bf73ac6SHong Zhang     }
27392bf73ac6SHong Zhang 
27402bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
2741caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
27422bf73ac6SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nEdges: %D; nVertices: %D; nSharedVertices: %D\n",rank,network->nEdges,network->nVertices,ncv);CHKERRQ(ierr);
2743caf410d2SHong Zhang 
2744caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
27452bf73ac6SHong Zhang       ierr = DMNetworkGetSubnetwork(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2746caf410d2SHong Zhang       if (ne) {
27472bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices(include shared vertices) %D\n",i,ne,nv);CHKERRQ(ierr);
2748caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2749caf410d2SHong Zhang           p = edges[j];
2750caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2751caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2752caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2753caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2754caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D ----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2755caf410d2SHong Zhang         }
2756caf410d2SHong Zhang       }
2757caf410d2SHong Zhang     }
27582bf73ac6SHong Zhang 
27592bf73ac6SHong Zhang     /* Shared vertices */
27602bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
27612bf73ac6SHong Zhang     if (ncv) {
27622bf73ac6SHong Zhang       SVtx       *svtx = network->svtx;
27632bf73ac6SHong Zhang       PetscInt    gidx,svtx_idx,nvto,vfrom_net,vfrom_idx,*svto;
27642bf73ac6SHong Zhang       PetscBool   ghost;
27652bf73ac6SHong Zhang       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     SharedVertices:\n");CHKERRQ(ierr);
27662bf73ac6SHong Zhang       for (i=0; i<ncv; i++) {
27672bf73ac6SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,vtx[i],&ghost);CHKERRQ(ierr);
27682bf73ac6SHong Zhang         if (ghost) continue;
27692bf73ac6SHong Zhang 
27702bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVertexIndex(dm,vtx[i],&gidx);CHKERRQ(ierr);
27712bf73ac6SHong Zhang         ierr = PetscTableFind(network->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
27722bf73ac6SHong Zhang         svtx_idx--;
27732bf73ac6SHong Zhang         nvto = svtx[svtx_idx].n;
27742bf73ac6SHong Zhang 
27752bf73ac6SHong Zhang         vfrom_net = svtx[svtx_idx].sv[0];
27762bf73ac6SHong Zhang         vfrom_idx = svtx[svtx_idx].sv[1];
27772bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       svtx %D: global index %D, subnet[%D].%D ---->\n",i,gidx,vfrom_net,vfrom_idx);CHKERRQ(ierr);
27782bf73ac6SHong Zhang         for (j=1; j<nvto; j++) {
27792bf73ac6SHong Zhang           svto = svtx[svtx_idx].sv + 2*j;
27802bf73ac6SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "                                           ----> subnet[%D].%D\n",svto[0],svto[1]);CHKERRQ(ierr);
2781caf410d2SHong Zhang         }
2782caf410d2SHong Zhang       }
2783caf410d2SHong Zhang     }
2784caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2785caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2786caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
27875f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27885f2c45f1SShri Abhyankar }
27895f2c45f1SShri Abhyankar 
27905f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
27915f2c45f1SShri Abhyankar {
27925f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27935f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27945f2c45f1SShri Abhyankar 
27955f2c45f1SShri Abhyankar   PetscFunctionBegin;
27965f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
27975f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27985f2c45f1SShri Abhyankar }
27995f2c45f1SShri Abhyankar 
28005f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
28015f2c45f1SShri Abhyankar {
28025f2c45f1SShri Abhyankar   PetscErrorCode ierr;
28035f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
28045f2c45f1SShri Abhyankar 
28055f2c45f1SShri Abhyankar   PetscFunctionBegin;
28065f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
28075f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28085f2c45f1SShri Abhyankar }
28095f2c45f1SShri Abhyankar 
28105f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
28115f2c45f1SShri Abhyankar {
28125f2c45f1SShri Abhyankar   PetscErrorCode ierr;
28135f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
28145f2c45f1SShri Abhyankar 
28155f2c45f1SShri Abhyankar   PetscFunctionBegin;
28165f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
28175f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28185f2c45f1SShri Abhyankar }
28195f2c45f1SShri Abhyankar 
28205f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
28215f2c45f1SShri Abhyankar {
28225f2c45f1SShri Abhyankar   PetscErrorCode ierr;
28235f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
28245f2c45f1SShri Abhyankar 
28255f2c45f1SShri Abhyankar   PetscFunctionBegin;
28265f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
28275f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28285f2c45f1SShri Abhyankar }
282922bbedd7SHong Zhang 
283022bbedd7SHong Zhang /*@
283164238763SRodolfo Oliveira   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index
283222bbedd7SHong Zhang 
283322bbedd7SHong Zhang   Not collective
283422bbedd7SHong Zhang 
28357a7aea1fSJed Brown   Input Parameters:
283622bbedd7SHong Zhang + dm - the dm object
283722bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
283822bbedd7SHong Zhang 
28397a7aea1fSJed Brown   Output Parameters:
2840f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
284122bbedd7SHong Zhang 
284297bb938eSShri Abhyankar   Level: advanced
284322bbedd7SHong Zhang 
284422bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
284522bbedd7SHong Zhang @*/
284622bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
284722bbedd7SHong Zhang {
284822bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
284922bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
285022bbedd7SHong Zhang 
285122bbedd7SHong Zhang   PetscFunctionBegin;
285222bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
285322bbedd7SHong Zhang   *vg = vltog[vloc];
285422bbedd7SHong Zhang   PetscFunctionReturn(0);
285522bbedd7SHong Zhang }
285622bbedd7SHong Zhang 
285722bbedd7SHong Zhang /*@
285864238763SRodolfo Oliveira   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map
285922bbedd7SHong Zhang 
286022bbedd7SHong Zhang   Collective
286122bbedd7SHong Zhang 
286222bbedd7SHong Zhang   Input Parameters:
2863f0fc11ceSJed Brown . dm - the dm object
286422bbedd7SHong Zhang 
286597bb938eSShri Abhyankar   Level: advanced
286622bbedd7SHong Zhang 
286763029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
286822bbedd7SHong Zhang @*/
286922bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
287022bbedd7SHong Zhang {
287122bbedd7SHong Zhang   PetscErrorCode    ierr;
287222bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
287322bbedd7SHong Zhang   MPI_Comm          comm;
28742bf73ac6SHong Zhang   PetscMPIInt       rank,size,*displs=NULL,*recvcounts=NULL,remoterank;
287522bbedd7SHong Zhang   PetscBool         ghost;
287663029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
287722bbedd7SHong Zhang   const PetscSFNode *iremote;
287822bbedd7SHong Zhang   PetscSF           vsf;
287963029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
288063029d29SHong Zhang   VecScatter        ctx;
288163029d29SHong Zhang   PetscScalar       *varr,val;
288263029d29SHong Zhang   const PetscScalar *varr_read;
288322bbedd7SHong Zhang 
288422bbedd7SHong Zhang   PetscFunctionBegin;
288522bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2886ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
2887ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
288822bbedd7SHong Zhang 
288922bbedd7SHong Zhang   if (size == 1) {
289022bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
289122bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
289222bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
289322bbedd7SHong Zhang     network->vltog = vltog;
289422bbedd7SHong Zhang     PetscFunctionReturn(0);
289522bbedd7SHong Zhang   }
289622bbedd7SHong Zhang 
289722bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
289822bbedd7SHong Zhang   if (network->vltog) {
289922bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
290022bbedd7SHong Zhang   }
290122bbedd7SHong Zhang 
290222bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
290322bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
290422bbedd7SHong Zhang   vsf = network->vertex.sf;
290522bbedd7SHong Zhang 
29062bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
2907f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
290822bbedd7SHong Zhang 
290922bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
291022bbedd7SHong Zhang 
291122bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
291222bbedd7SHong Zhang   vrange[0] = 0;
2913ffc4695bSBarry Smith   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
291467dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
291522bbedd7SHong Zhang 
291622bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
291722bbedd7SHong Zhang   network->vltog = vltog;
291822bbedd7SHong Zhang 
291963029d29SHong Zhang   /* Set vltog for non-ghost vertices */
292063029d29SHong Zhang   k = 0;
292122bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
292222bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
292363029d29SHong Zhang     if (ghost) continue;
292463029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
292522bbedd7SHong Zhang   }
2926f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
292763029d29SHong Zhang 
292863029d29SHong Zhang   /* Set vltog for ghost vertices */
292963029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
293063029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
293163029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
293263029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
293363029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
293463029d29SHong Zhang   for (i=0; i<nleaves; i++) {
293563029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
293663029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
293763029d29SHong Zhang   }
293863029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
293963029d29SHong Zhang 
294063029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
294163029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
294263029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
294363029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
294463029d29SHong Zhang 
294563029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
294663029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
294763029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
294863029d29SHong Zhang   for (i=0; i<N; i+=2) {
29492e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
295063029d29SHong Zhang     if (remoterank == rank) {
295163029d29SHong Zhang       k = i+1; /* row number */
29522e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
295363029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
295463029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
295563029d29SHong Zhang     }
295663029d29SHong Zhang   }
295763029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
295863029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
295963029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
296063029d29SHong Zhang 
296163029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
296263029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
296363029d29SHong Zhang   k = 0;
296463029d29SHong Zhang   for (i=0; i<nroots; i++) {
296563029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
296663029d29SHong Zhang     if (!ghost) continue;
29672e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
296863029d29SHong Zhang   }
296963029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
297063029d29SHong Zhang 
297163029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
297263029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
297363029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
297422bbedd7SHong Zhang   PetscFunctionReturn(0);
297522bbedd7SHong Zhang }
297642dc13f1SHong Zhang 
297742dc13f1SHong Zhang PETSC_STATIC_INLINE PetscErrorCode DMISAddSize_private(DM_Network *network,PetscInt p,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *nidx)
297842dc13f1SHong Zhang {
297942dc13f1SHong Zhang   PetscErrorCode           ierr;
298042dc13f1SHong Zhang   PetscInt                 i,j,ncomps,nvar,key,offset=0;
298142dc13f1SHong Zhang   DMNetworkComponentHeader header;
298242dc13f1SHong Zhang 
298342dc13f1SHong Zhang   PetscFunctionBegin;
298442dc13f1SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
298542dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
298642dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
298742dc13f1SHong Zhang 
298842dc13f1SHong Zhang   for (i=0; i<ncomps; i++) {
298942dc13f1SHong Zhang     key  = header->key[i];
299042dc13f1SHong Zhang     nvar = header->nvar[i];
299142dc13f1SHong Zhang     for (j=0; j<numkeys; j++) {
299242dc13f1SHong Zhang       if (key == keys[j]) {
299342dc13f1SHong Zhang         if (!blocksize || blocksize[j] == -1) {
299442dc13f1SHong Zhang           *nidx += nvar;
299542dc13f1SHong Zhang         } else {
299642dc13f1SHong Zhang           *nidx += nselectedvar[j]*nvar/blocksize[j];
299742dc13f1SHong Zhang         }
299842dc13f1SHong Zhang       }
299942dc13f1SHong Zhang     }
300042dc13f1SHong Zhang   }
300142dc13f1SHong Zhang   PetscFunctionReturn(0);
300242dc13f1SHong Zhang }
300342dc13f1SHong Zhang 
300442dc13f1SHong 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)
300542dc13f1SHong Zhang {
300642dc13f1SHong Zhang   PetscErrorCode           ierr;
300742dc13f1SHong Zhang   PetscInt                 i,j,ncomps,nvar,key,offsetg,k,k1,offset=0;
300842dc13f1SHong Zhang   DM_Network               *network = (DM_Network*)dm->data;
300942dc13f1SHong Zhang   DMNetworkComponentHeader header;
301042dc13f1SHong Zhang 
301142dc13f1SHong Zhang   PetscFunctionBegin;
301242dc13f1SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
301342dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
301442dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
301542dc13f1SHong Zhang 
301642dc13f1SHong Zhang   for (i=0; i<ncomps; i++) {
301742dc13f1SHong Zhang     key  = header->key[i];
301842dc13f1SHong Zhang     nvar = header->nvar[i];
301942dc13f1SHong Zhang     for (j=0; j<numkeys; j++) {
302042dc13f1SHong Zhang       if (key != keys[j]) continue;
302142dc13f1SHong Zhang 
302242dc13f1SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,p,i,&offsetg);CHKERRQ(ierr);
302342dc13f1SHong Zhang       if (!blocksize || blocksize[j] == -1) {
302442dc13f1SHong Zhang         for (k=0; k<nvar; k++) idx[(*ii)++] = offsetg + k;
302542dc13f1SHong Zhang       } else {
302642dc13f1SHong Zhang         for (k=0; k<nvar; k+=blocksize[j]) {
302742dc13f1SHong Zhang           for (k1=0; k1<nselectedvar[j]; k1++) idx[(*ii)++] = offsetg + k + selectedvar[j][k1];
302842dc13f1SHong Zhang         }
302942dc13f1SHong Zhang       }
303042dc13f1SHong Zhang     }
303142dc13f1SHong Zhang   }
303242dc13f1SHong Zhang   PetscFunctionReturn(0);
303342dc13f1SHong Zhang }
303442dc13f1SHong Zhang 
303542dc13f1SHong Zhang /*@
303642dc13f1SHong Zhang   DMNetworkCreateIS - Create an index set object from the global vector of the network
303742dc13f1SHong Zhang 
303842dc13f1SHong Zhang   Collective
303942dc13f1SHong Zhang 
304042dc13f1SHong Zhang   Input Parameters:
304142dc13f1SHong Zhang + dm - DMNetwork object
304242dc13f1SHong Zhang . numkeys - number of keys
304342dc13f1SHong Zhang . keys - array of keys that define the components of the variables you wish to extract
304442dc13f1SHong Zhang . blocksize - block size of the variables associated to the component
304542dc13f1SHong Zhang . nselectedvar - number of variables in each block to select
304642dc13f1SHong Zhang - selectedvar - the offset into the block of each variable in each block to select
304742dc13f1SHong Zhang 
304842dc13f1SHong Zhang   Output Parameters:
304942dc13f1SHong Zhang . is - the index set
305042dc13f1SHong Zhang 
305142dc13f1SHong Zhang   Level: Advanced
305242dc13f1SHong Zhang 
305342dc13f1SHong Zhang   Notes:
305442dc13f1SHong 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.
305542dc13f1SHong Zhang 
305642dc13f1SHong Zhang .seealso: DMNetworkCreate(), ISCreateGeneral(), DMNetworkCreateLocalIS()
305742dc13f1SHong Zhang @*/
305842dc13f1SHong Zhang PetscErrorCode DMNetworkCreateIS(DM dm,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],IS *is)
305942dc13f1SHong Zhang {
306042dc13f1SHong Zhang   PetscErrorCode ierr;
306142dc13f1SHong Zhang   MPI_Comm       comm;
306242dc13f1SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
306342dc13f1SHong Zhang   PetscInt       i,p,estart,eend,vstart,vend,nidx,*idx;
306442dc13f1SHong Zhang   PetscBool      ghost;
306542dc13f1SHong Zhang 
306642dc13f1SHong Zhang   PetscFunctionBegin;
306742dc13f1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
306842dc13f1SHong Zhang 
306942dc13f1SHong Zhang   /* Check input parameters */
307042dc13f1SHong Zhang   for (i=0; i<numkeys; i++) {
307142dc13f1SHong Zhang     if (!blocksize || blocksize[i] == -1) continue;
307242dc13f1SHong 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]);
307342dc13f1SHong Zhang   }
307442dc13f1SHong Zhang 
307542dc13f1SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&estart,&eend);CHKERRQ(ierr);
307642dc13f1SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vstart,&vend);CHKERRQ(ierr);
307742dc13f1SHong Zhang 
307842dc13f1SHong Zhang   /* Get local number of idx */
307942dc13f1SHong Zhang   nidx = 0;
308042dc13f1SHong Zhang   for (p=estart; p<eend; p++) {
308142dc13f1SHong Zhang     ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr);
308242dc13f1SHong Zhang   }
308342dc13f1SHong Zhang   for (p=vstart; p<vend; p++) {
308442dc13f1SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
308542dc13f1SHong Zhang     if (ghost) continue;
308642dc13f1SHong Zhang     ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr);
308742dc13f1SHong Zhang   }
308842dc13f1SHong Zhang 
308942dc13f1SHong Zhang   /* Compute idx */
309042dc13f1SHong Zhang   ierr = PetscMalloc1(nidx,&idx);CHKERRQ(ierr);
309142dc13f1SHong Zhang   i = 0;
309242dc13f1SHong Zhang   for (p=estart; p<eend; p++) {
309342dc13f1SHong Zhang     ierr = DMISComputeIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr);
309442dc13f1SHong Zhang   }
309542dc13f1SHong Zhang   for (p=vstart; p<vend; p++) {
309642dc13f1SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
309742dc13f1SHong Zhang     if (ghost) continue;
309842dc13f1SHong Zhang     ierr = DMISComputeIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr);
309942dc13f1SHong Zhang   }
310042dc13f1SHong Zhang 
310142dc13f1SHong Zhang   /* Create is */
310242dc13f1SHong Zhang   ierr = ISCreateGeneral(comm,nidx,idx,PETSC_COPY_VALUES,is);CHKERRQ(ierr);
310342dc13f1SHong Zhang   ierr = PetscFree(idx);CHKERRQ(ierr);
310442dc13f1SHong Zhang   PetscFunctionReturn(0);
310542dc13f1SHong Zhang }
310642dc13f1SHong Zhang 
310742dc13f1SHong 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)
310842dc13f1SHong Zhang {
310942dc13f1SHong Zhang   PetscErrorCode           ierr;
311042dc13f1SHong Zhang   PetscInt                 i,j,ncomps,nvar,key,offsetl,k,k1,offset=0;
311142dc13f1SHong Zhang   DM_Network               *network = (DM_Network*)dm->data;
311242dc13f1SHong Zhang   DMNetworkComponentHeader header;
311342dc13f1SHong Zhang 
311442dc13f1SHong Zhang   PetscFunctionBegin;
311542dc13f1SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
311642dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
311742dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
311842dc13f1SHong Zhang 
311942dc13f1SHong Zhang   for (i=0; i<ncomps; i++) {
312042dc13f1SHong Zhang     key  = header->key[i];
312142dc13f1SHong Zhang     nvar = header->nvar[i];
312242dc13f1SHong Zhang     for (j=0; j<numkeys; j++) {
312342dc13f1SHong Zhang       if (key != keys[j]) continue;
312442dc13f1SHong Zhang 
312542dc13f1SHong Zhang       ierr = DMNetworkGetLocalVecOffset(dm,p,i,&offsetl);CHKERRQ(ierr);
312642dc13f1SHong Zhang       if (!blocksize || blocksize[j] == -1) {
312742dc13f1SHong Zhang         for (k=0; k<nvar; k++) idx[(*ii)++] = offsetl + k;
312842dc13f1SHong Zhang       } else {
312942dc13f1SHong Zhang         for (k=0; k<nvar; k+=blocksize[j]) {
313042dc13f1SHong Zhang           for (k1=0; k1<nselectedvar[j]; k1++) idx[(*ii)++] = offsetl + k + selectedvar[j][k1];
313142dc13f1SHong Zhang         }
313242dc13f1SHong Zhang       }
313342dc13f1SHong Zhang     }
313442dc13f1SHong Zhang   }
313542dc13f1SHong Zhang   PetscFunctionReturn(0);
313642dc13f1SHong Zhang }
313742dc13f1SHong Zhang 
313842dc13f1SHong Zhang /*@
313942dc13f1SHong Zhang   DMNetworkCreateLocalIS - Create an index set object from the local vector of the network
314042dc13f1SHong Zhang 
314142dc13f1SHong Zhang   Not collective
314242dc13f1SHong Zhang 
314342dc13f1SHong Zhang   Input Parameters:
314442dc13f1SHong Zhang + dm - DMNetwork object
314542dc13f1SHong Zhang . numkeys - number of keys
314642dc13f1SHong Zhang . keys - array of keys that define the components of the variables you wish to extract
314742dc13f1SHong Zhang . blocksize - block size of the variables associated to the component
314842dc13f1SHong Zhang . nselectedvar - number of variables in each block to select
314942dc13f1SHong Zhang - selectedvar - the offset into the block of each variable in each block to select
315042dc13f1SHong Zhang 
315142dc13f1SHong Zhang   Output Parameters:
315242dc13f1SHong Zhang . is - the index set
315342dc13f1SHong Zhang 
315442dc13f1SHong Zhang   Level: Advanced
315542dc13f1SHong Zhang 
315642dc13f1SHong Zhang   Notes:
315742dc13f1SHong 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.
315842dc13f1SHong Zhang 
315942dc13f1SHong Zhang .seealso: DMNetworkCreate(), DMNetworkCreateIS, ISCreateGeneral()
316042dc13f1SHong Zhang @*/
316142dc13f1SHong Zhang PetscErrorCode DMNetworkCreateLocalIS(DM dm,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],IS *is)
316242dc13f1SHong Zhang {
316342dc13f1SHong Zhang   PetscErrorCode ierr;
316442dc13f1SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
316542dc13f1SHong Zhang   PetscInt       i,p,pstart,pend,nidx,*idx;
316642dc13f1SHong Zhang 
316742dc13f1SHong Zhang   PetscFunctionBegin;
316842dc13f1SHong Zhang   /* Check input parameters */
316942dc13f1SHong Zhang   for (i=0; i<numkeys; i++) {
317042dc13f1SHong Zhang     if (!blocksize || blocksize[i] == -1) continue;
317142dc13f1SHong 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]);
317242dc13f1SHong Zhang   }
317342dc13f1SHong Zhang 
317442dc13f1SHong Zhang   pstart = network->pStart;
317542dc13f1SHong Zhang   pend   = network->pEnd;
317642dc13f1SHong Zhang 
317742dc13f1SHong Zhang   /* Get local number of idx */
317842dc13f1SHong Zhang   nidx = 0;
317942dc13f1SHong Zhang   for (p=pstart; p<pend; p++) {
318042dc13f1SHong Zhang     ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr);
318142dc13f1SHong Zhang   }
318242dc13f1SHong Zhang 
318342dc13f1SHong Zhang   /* Compute local idx */
318442dc13f1SHong Zhang   ierr = PetscMalloc1(nidx,&idx);CHKERRQ(ierr);
318542dc13f1SHong Zhang   i = 0;
318642dc13f1SHong Zhang   for (p=pstart; p<pend; p++) {
318742dc13f1SHong Zhang     ierr = DMISComputeLocalIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr);
318842dc13f1SHong Zhang   }
318942dc13f1SHong Zhang 
319042dc13f1SHong Zhang   /* Create is */
319142dc13f1SHong Zhang   ierr = ISCreateGeneral(PETSC_COMM_SELF,nidx,idx,PETSC_COPY_VALUES,is);CHKERRQ(ierr);
319242dc13f1SHong Zhang   ierr = PetscFree(idx);CHKERRQ(ierr);
319342dc13f1SHong Zhang   PetscFunctionReturn(0);
319442dc13f1SHong Zhang }
3195