xref: /petsc/src/dm/impls/network/network.c (revision d8d19677bbccf95218448bee62e6b87f4513e133)
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 
5172c3e9f7SHong Zhang   Input Parameters:
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
1232bf73ac6SHong Zhang - edgelist - list of edges for this subnetwork
1242bf73ac6SHong Zhang 
1252bf73ac6SHong Zhang   Output Parameters:
1262bf73ac6SHong Zhang . netnum - global index of the subnetwork
1275f2c45f1SShri Abhyankar 
1285f2c45f1SShri Abhyankar   Notes:
1295f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1302bf73ac6SHong Zhang   not be destroyed before the call to DMNetworkLayoutSetUp()
1315f2c45f1SShri Abhyankar 
132f11a936eSBarry 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, 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.
133f11a936eSBarry Smith 
13497bb938eSShri Abhyankar   Level: beginner
1355f2c45f1SShri Abhyankar 
136e3e68989SHong Zhang   Example usage:
137f11a936eSBarry Smith   Consider the following networks:
138f11a936eSBarry Smith   1) A sigle subnetwork:
139e3e68989SHong Zhang .vb
140f11a936eSBarry Smith  network 0:
141f11a936eSBarry Smith  rank[0]:
142f11a936eSBarry Smith    v0 --> v2; v1 --> v2
143f11a936eSBarry Smith  rank[1]:
144f11a936eSBarry Smith    v3 --> v5; v4 --> v5
145e3e68989SHong Zhang .ve
146e3e68989SHong Zhang 
147e3e68989SHong Zhang  The resulting input
148f11a936eSBarry Smith  network 0:
149f11a936eSBarry Smith  rank[0]:
150f11a936eSBarry Smith    ne = 2
151f11a936eSBarry Smith    edgelist = [0 2 | 1 2]
152f11a936eSBarry Smith  rank[1]:
153f11a936eSBarry Smith    ne = 2
154f11a936eSBarry Smith    edgelist = [3 5 | 4 5]
155f11a936eSBarry Smith 
156f11a936eSBarry Smith   2) Two subnetworks:
157f11a936eSBarry Smith .vb
158f11a936eSBarry Smith  subnetwork 0:
159f11a936eSBarry Smith  rank[0]:
160f11a936eSBarry Smith    v0 --> v2; v2 --> v1; v1 --> v3;
161f11a936eSBarry Smith  subnetwork 1:
162f11a936eSBarry Smith  rank[1]:
163f11a936eSBarry Smith    v0 --> v3; v3 --> v2; v2 --> v1;
164f11a936eSBarry Smith .ve
165f11a936eSBarry Smith 
166f11a936eSBarry Smith  The resulting input
167f11a936eSBarry Smith  subnetwork 0:
168f11a936eSBarry Smith  rank[0]:
169f11a936eSBarry Smith    ne = 3
170f11a936eSBarry Smith    edgelist = [0 2 | 2 1 | 1 3]
171f11a936eSBarry Smith  rank[1]:
172f11a936eSBarry Smith    ne = 0
173f11a936eSBarry Smith    edgelist = NULL
174f11a936eSBarry Smith 
175f11a936eSBarry Smith  subnetwork 1:
176f11a936eSBarry Smith  rank[0]:
177f11a936eSBarry Smith    ne = 0
178f11a936eSBarry Smith    edgelist = NULL
179f11a936eSBarry Smith  rank[1]:
180f11a936eSBarry Smith    edgelist = [0 3 | 3 2 | 2 1]
181e3e68989SHong Zhang 
1822bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkSetNumSubnetworks()
1835f2c45f1SShri Abhyankar @*/
184f11a936eSBarry Smith PetscErrorCode DMNetworkAddSubnetwork(DM dm,const char* name,PetscInt ne,PetscInt edgelist[],PetscInt *netnum)
1855f2c45f1SShri Abhyankar {
1862bf73ac6SHong Zhang   PetscErrorCode ierr;
1875f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
188f11a936eSBarry Smith   PetscInt       i,Nedge,j,Nvtx,nvtx;
189f11a936eSBarry Smith   PetscBT        table;
1905f2c45f1SShri Abhyankar 
1915f2c45f1SShri Abhyankar   PetscFunctionBegin;
192f11a936eSBarry Smith   /* Get global total Nvtx = max(edgelist[])+1 for this subnet */
193f11a936eSBarry Smith   nvtx = -1; i = 0;
194f11a936eSBarry Smith   for (j=0; j<ne; j++) {
195f11a936eSBarry Smith     nvtx = PetscMax(nvtx, edgelist[i]); i++;
196f11a936eSBarry Smith     nvtx = PetscMax(nvtx, edgelist[i]); i++;
197f11a936eSBarry Smith   }
198f11a936eSBarry Smith   nvtx++;
199f11a936eSBarry Smith   ierr = MPIU_Allreduce(&nvtx,&Nvtx,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
200f11a936eSBarry Smith 
201f11a936eSBarry Smith   /* Get local nvtx for this subnet */
202f11a936eSBarry Smith   ierr = PetscBTCreate(Nvtx,&table);CHKERRQ(ierr);
203f11a936eSBarry Smith   ierr = PetscBTMemzero(Nvtx,table);CHKERRQ(ierr);
204f11a936eSBarry Smith   i = 0;
205f11a936eSBarry Smith   for (j=0; j<ne; j++) {
206f11a936eSBarry Smith     ierr = PetscBTSet(table,edgelist[i]);CHKERRQ(ierr);
207f11a936eSBarry Smith     i++;
208f11a936eSBarry Smith     ierr = PetscBTSet(table,edgelist[i]);CHKERRQ(ierr);
209f11a936eSBarry Smith     i++;
210f11a936eSBarry Smith   }
211f11a936eSBarry Smith   nvtx = 0;
212f11a936eSBarry Smith   for (j=0; j<Nvtx; j++) {
213f11a936eSBarry Smith     if (PetscBTLookup(table,j)) nvtx++;
214f11a936eSBarry Smith   }
215f11a936eSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
216f11a936eSBarry Smith 
217f11a936eSBarry Smith   /* Get global total Nedge for this subnet */
218f11a936eSBarry Smith   ierr = MPIU_Allreduce(&ne,&Nedge,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
219f11a936eSBarry Smith 
220f11a936eSBarry Smith   i = network->nsubnet;
2212bf73ac6SHong Zhang   if (name) {
2222bf73ac6SHong Zhang     ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr);
223e3e68989SHong Zhang   }
224f11a936eSBarry Smith   network->subnet[i].nvtx     = nvtx; /* include ghost vertices */
2252bf73ac6SHong Zhang   network->subnet[i].nedge    = ne;
2262bf73ac6SHong Zhang   network->subnet[i].edgelist = edgelist;
227f11a936eSBarry Smith   network->subnet[i].Nvtx     = Nvtx;
228f11a936eSBarry Smith   network->subnet[i].Nedge    = Nedge;
2292bf73ac6SHong Zhang 
2302bf73ac6SHong Zhang   /* ----------------------------------------------------------
2312bf73ac6SHong Zhang    p=v or e;
2322bf73ac6SHong Zhang    subnet[0].pStart   = 0
2332bf73ac6SHong Zhang    subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i])
2342bf73ac6SHong Zhang    ----------------------------------------------------------------------- */
2352bf73ac6SHong Zhang   /* GLOBAL subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */
2362bf73ac6SHong Zhang   network->subnet[i].vStart = network->NVertices;
2372bf73ac6SHong Zhang   network->subnet[i].vEnd   = network->subnet[i].vStart + network->subnet[i].Nvtx; /* global vEnd of subnet[i] */
2382bf73ac6SHong Zhang 
239f11a936eSBarry Smith   network->nVertices += nvtx; /* include ghost vertices */
2402bf73ac6SHong Zhang   network->NVertices += network->subnet[i].Nvtx;
2412bf73ac6SHong Zhang 
2422bf73ac6SHong Zhang   /* LOCAL subnet[].eStart and eEnd, used by DMNetworkLayoutSetUp() */
2432bf73ac6SHong Zhang   network->subnet[i].eStart = network->nEdges;
2442bf73ac6SHong Zhang   network->subnet[i].eEnd   = network->subnet[i].eStart + ne;
2452bf73ac6SHong Zhang   network->nEdges += ne;
2462bf73ac6SHong Zhang   network->NEdges += network->subnet[i].Nedge;
2472bf73ac6SHong Zhang 
2482bf73ac6SHong Zhang   ierr = PetscStrcpy(network->subnet[i].name,name);CHKERRQ(ierr);
2492bf73ac6SHong Zhang   if (netnum) *netnum = network->nsubnet;
2502bf73ac6SHong Zhang   network->nsubnet++;
2512bf73ac6SHong Zhang   PetscFunctionReturn(0);
2522bf73ac6SHong Zhang }
2532bf73ac6SHong Zhang 
2542bf73ac6SHong Zhang /*
2552bf73ac6SHong Zhang   SetUp a single svtx struct. See SVtx defined in dmnetworkimpl.h
2562bf73ac6SHong Zhang   Set gidx and type if input v=(net,idx) is a from_vertex;
2572bf73ac6SHong Zhang   Get gid, type and index in the svtx array if input v=(net,idx) is a to_vertex.
2582bf73ac6SHong Zhang 
2592bf73ac6SHong Zhang   Input:  Nsvtx, svtx, net, idx, gidx
2602bf73ac6SHong Zhang   Output: gidx, svtype, svtx_idx
2612bf73ac6SHong Zhang  */
2622bf73ac6SHong Zhang static PetscErrorCode SVtxSetUp(PetscInt Nsvtx,SVtx *svtx,PetscInt net,PetscInt idx,PetscInt *gidx,SVtxType *svtype,PetscInt *svtx_idx)
2632bf73ac6SHong Zhang {
2642bf73ac6SHong Zhang   PetscInt i,j,*svto;
2652bf73ac6SHong Zhang   SVtxType vtype;
2662bf73ac6SHong Zhang 
2672bf73ac6SHong Zhang   PetscFunctionBegin;
2682bf73ac6SHong Zhang   if (!Nsvtx) PetscFunctionReturn(0);
2692bf73ac6SHong Zhang 
2702bf73ac6SHong Zhang   vtype = SVNONE;
2712bf73ac6SHong Zhang   for (i=0; i<Nsvtx; i++) {
2722bf73ac6SHong Zhang     if (net == svtx[i].sv[0] && idx == svtx[i].sv[1]) {
2732bf73ac6SHong Zhang       /* (1) input vertex net.idx is a shared from_vertex, set its global index and output its svtype */
2742bf73ac6SHong Zhang       svtx[i].gidx = *gidx; /* set gidx */
2752bf73ac6SHong Zhang       vtype        = SVFROM;
2762bf73ac6SHong Zhang     } else { /* loop over svtx[i].n */
2772bf73ac6SHong Zhang       for (j=1; j<svtx[i].n; j++) {
2782bf73ac6SHong Zhang         svto = svtx[i].sv + 2*j;
2792bf73ac6SHong Zhang         if (net == svto[0] && idx == svto[1]) {
2802bf73ac6SHong Zhang           /* input vertex net.idx is a shared to_vertex, output its global index and its svtype */
2812bf73ac6SHong Zhang           *gidx = svtx[i].gidx; /* output gidx for to_vertex */
2822bf73ac6SHong Zhang           vtype = SVTO;
2832bf73ac6SHong Zhang         }
2842bf73ac6SHong Zhang       }
2852bf73ac6SHong Zhang     }
2862bf73ac6SHong Zhang     if (vtype != SVNONE) break;
2872bf73ac6SHong Zhang   }
2882bf73ac6SHong Zhang   if (svtype)   *svtype   = vtype;
2892bf73ac6SHong Zhang   if (svtx_idx) *svtx_idx = i;
2902bf73ac6SHong Zhang   PetscFunctionReturn(0);
2912bf73ac6SHong Zhang }
2922bf73ac6SHong Zhang 
2932bf73ac6SHong Zhang /*
2942bf73ac6SHong Zhang  Add a new shared vertex sv=(net,idx) to table svtas[ita]
2952bf73ac6SHong Zhang */
2962bf73ac6SHong Zhang static PetscErrorCode TableAddSVtx(PetscTable *svtas,PetscInt ita,PetscInt* tdata,PetscInt *sv_wk,PetscInt *ii,PetscInt *sedgelist,PetscInt k,DM_Network *network,PetscInt **ta2sv)
2972bf73ac6SHong Zhang {
2982bf73ac6SHong Zhang   PetscInt       net,idx,gidx,i=*ii;
2992bf73ac6SHong Zhang   PetscErrorCode ierr;
3002bf73ac6SHong Zhang 
3012bf73ac6SHong Zhang   PetscFunctionBegin;
3022bf73ac6SHong Zhang   net = sv_wk[2*i]   = sedgelist[k];
3032bf73ac6SHong Zhang   idx = sv_wk[2*i+1] = sedgelist[k+1];
3042bf73ac6SHong Zhang   gidx = network->subnet[net].vStart + idx;
3052bf73ac6SHong Zhang   ierr = PetscTableAdd(svtas[ita],gidx+1,tdata[ita]+1,INSERT_VALUES);CHKERRQ(ierr);
3062bf73ac6SHong Zhang   *(ta2sv[ita] + tdata[ita]) = i; /* maps tdata to index of sv_wk; sv_wk keeps (net,idx) info */
3072bf73ac6SHong Zhang   tdata[ita]++; (*ii)++;
3082bf73ac6SHong Zhang   PetscFunctionReturn(0);
3092bf73ac6SHong Zhang }
3102bf73ac6SHong Zhang 
3112bf73ac6SHong Zhang /*
3122bf73ac6SHong Zhang   Create an array of shared vertices. See SVtx and SVtxType in dmnetworkimpl.h
3132bf73ac6SHong Zhang 
3142bf73ac6SHong Zhang   Input:  dm, Nsedgelist, sedgelist
3152bf73ac6SHong Zhang   Output: Nsvtx,svtx
3162bf73ac6SHong Zhang 
3172bf73ac6SHong Zhang   Note: Output svtx is organized as
3182bf73ac6SHong Zhang         sv(net[0],idx[0]) --> sv(net[1],idx[1])
3192bf73ac6SHong Zhang                           --> sv(net[1],idx[1])
3202bf73ac6SHong Zhang                           ...
3212bf73ac6SHong Zhang                           --> sv(net[n-1],idx[n-1])
3222bf73ac6SHong Zhang         and net[0] < net[1] < ... < net[n-1]
3232bf73ac6SHong Zhang         where sv[0] has SVFROM type, sv[i], i>0, has SVTO type.
3242bf73ac6SHong Zhang  */
3252bf73ac6SHong Zhang static PetscErrorCode SVtxCreate(DM dm,PetscInt Nsedgelist,PetscInt *sedgelist,PetscInt *Nsvtx,SVtx **svtx)
3262bf73ac6SHong Zhang {
3272bf73ac6SHong Zhang   PetscErrorCode ierr;
3282bf73ac6SHong Zhang   SVtx           *sedges = NULL;
3292bf73ac6SHong Zhang   PetscInt       *sv,k,j,nsv,*tdata,**ta2sv;
3302bf73ac6SHong Zhang   PetscTable     *svtas;
3312bf73ac6SHong Zhang   PetscInt       gidx,net,idx,i,nta,ita,idx_from,idx_to,n,*sv_wk;
3322bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
3332bf73ac6SHong Zhang   PetscTablePosition ppos;
3342bf73ac6SHong Zhang 
3352bf73ac6SHong Zhang   PetscFunctionBegin;
3362bf73ac6SHong Zhang   /* (1) Crete ctables svtas */
3372bf73ac6SHong Zhang   ierr = PetscCalloc4(Nsedgelist,&svtas,Nsedgelist,&tdata,4*Nsedgelist,&sv_wk,2*Nsedgelist,&ta2sv);CHKERRQ(ierr);
3382bf73ac6SHong Zhang 
3392bf73ac6SHong Zhang   j   = 0;   /* sedgelist counter */
3402bf73ac6SHong Zhang   k   = 0;   /* sedgelist vertex counter j = 4*k */
3412bf73ac6SHong Zhang   i   = 0;   /* sv_wk (vertices added to the ctables) counter */
3422bf73ac6SHong Zhang   nta = 0;   /* num of sv tables created */
3432bf73ac6SHong Zhang 
3442bf73ac6SHong Zhang   /* for j=0 */
3452bf73ac6SHong Zhang   ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr);
3462bf73ac6SHong Zhang   ierr = PetscMalloc1(2*Nsedgelist,&ta2sv[nta]);CHKERRQ(ierr);
3472bf73ac6SHong Zhang 
3482bf73ac6SHong Zhang   ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
3492bf73ac6SHong Zhang   ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
3502bf73ac6SHong Zhang   nta++; k += 4;
3512bf73ac6SHong Zhang 
3522bf73ac6SHong Zhang   for (j = 1; j < Nsedgelist; j++) {
3532bf73ac6SHong Zhang     for (ita = 0; ita < nta; ita++) {
3542bf73ac6SHong Zhang       /* vfrom */
3552bf73ac6SHong Zhang       net = sedgelist[k]; idx = sedgelist[k+1];
3562bf73ac6SHong Zhang       gidx = network->subnet[net].vStart + idx; /* global index of the vertex net.idx before merging shared vertices */
3572bf73ac6SHong Zhang       ierr = PetscTableFind(svtas[ita],gidx+1,&idx_from);CHKERRQ(ierr);
3582bf73ac6SHong Zhang 
3592bf73ac6SHong Zhang       /* vto */
3602bf73ac6SHong Zhang       net = sedgelist[k+2]; idx = sedgelist[k+3];
3612bf73ac6SHong Zhang       gidx = network->subnet[net].vStart + idx;
3622bf73ac6SHong Zhang       ierr = PetscTableFind(svtas[ita],gidx+1,&idx_to);CHKERRQ(ierr);
3632bf73ac6SHong Zhang 
3642bf73ac6SHong Zhang       if (idx_from || idx_to) { /* vfrom or vto is on table svtas[ita] */
3652bf73ac6SHong Zhang         idx_from--; idx_to--;
3662bf73ac6SHong Zhang         if (idx_from < 0) { /* vto is on svtas[ita] */
3672bf73ac6SHong Zhang           ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
3682bf73ac6SHong Zhang           break;
3692bf73ac6SHong Zhang         } else if (idx_to < 0) {
3702bf73ac6SHong Zhang           ierr = TableAddSVtx(svtas,ita,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
3712bf73ac6SHong Zhang           break;
3722bf73ac6SHong Zhang         }
3732bf73ac6SHong Zhang       }
3742bf73ac6SHong Zhang     }
3752bf73ac6SHong Zhang 
3762bf73ac6SHong Zhang     if (ita == nta) {
3772bf73ac6SHong Zhang       ierr = PetscTableCreate(2*Nsedgelist,network->NVertices+1,&svtas[nta]);CHKERRQ(ierr);
3782bf73ac6SHong Zhang       ierr = PetscMalloc1(2*Nsedgelist, &ta2sv[nta]);CHKERRQ(ierr);
3792bf73ac6SHong Zhang 
3802bf73ac6SHong Zhang       ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k,network,ta2sv);CHKERRQ(ierr);
3812bf73ac6SHong Zhang       ierr = TableAddSVtx(svtas,nta,tdata,sv_wk,&i,sedgelist,k+2,network,ta2sv);CHKERRQ(ierr);
3822bf73ac6SHong Zhang       nta++;
3832bf73ac6SHong Zhang     }
3842bf73ac6SHong Zhang     k += 4;
3852bf73ac6SHong Zhang   }
3862bf73ac6SHong Zhang 
3872bf73ac6SHong Zhang   /* (2) Construct sedges from ctable
3882bf73ac6SHong Zhang      sedges: edges connect vertex sv[0]=(net[0],idx[0]) to vertices sv[k], k=1,...,n-1;
3894f5c2772SJose E. Roman      net[k], k=0, ...,n-1, are in ascending order */
3902bf73ac6SHong Zhang   ierr = PetscMalloc1(nta,&sedges);CHKERRQ(ierr);
3912bf73ac6SHong Zhang   for (nsv = 0; nsv < nta; nsv++) {
3924f5c2772SJose E. Roman     /* for a single svtx, put shared vertices in ascending order of gidx */
3934f5c2772SJose E. Roman     ierr = PetscTableGetCount(svtas[nsv],&n);CHKERRQ(ierr);
3942bf73ac6SHong Zhang     ierr = PetscCalloc1(2*n,&sv);CHKERRQ(ierr);
3952bf73ac6SHong Zhang     sedges[nsv].sv   = sv;
3962bf73ac6SHong Zhang     sedges[nsv].n    = n;
3972bf73ac6SHong Zhang     sedges[nsv].gidx = -1; /* initialization */
3982bf73ac6SHong Zhang 
3992bf73ac6SHong Zhang     ierr = PetscTableGetHeadPosition(svtas[nsv],&ppos);CHKERRQ(ierr);
4004f5c2772SJose E. Roman     for (k=0; k<n; k++) { /* gidx is sorted in ascending order */
4012bf73ac6SHong Zhang       ierr = PetscTableGetNext(svtas[nsv],&ppos,&gidx,&i);CHKERRQ(ierr);
4022bf73ac6SHong Zhang       gidx--; i--;
4032bf73ac6SHong Zhang 
4042bf73ac6SHong Zhang       j = ta2sv[nsv][i]; /* maps i to index of sv_wk */
4052bf73ac6SHong Zhang       sv[2*k]   = sv_wk[2*j];
4062bf73ac6SHong Zhang       sv[2*k+1] = sv_wk[2*j + 1];
4072bf73ac6SHong Zhang     }
4082bf73ac6SHong Zhang   }
4092bf73ac6SHong Zhang 
4102bf73ac6SHong Zhang   for (j=0; j<nta; j++) {
4112bf73ac6SHong Zhang     ierr = PetscTableDestroy(&svtas[j]);CHKERRQ(ierr);
4122bf73ac6SHong Zhang     ierr = PetscFree(ta2sv[j]);CHKERRQ(ierr);
4132bf73ac6SHong Zhang   }
4142bf73ac6SHong Zhang   ierr = PetscFree4(svtas,tdata,sv_wk,ta2sv);CHKERRQ(ierr);
4152bf73ac6SHong Zhang 
4162bf73ac6SHong Zhang   *Nsvtx = nta;
4172bf73ac6SHong Zhang   *svtx  = sedges;
4182bf73ac6SHong Zhang   PetscFunctionReturn(0);
4192bf73ac6SHong Zhang }
4202bf73ac6SHong Zhang 
4212bf73ac6SHong Zhang static PetscErrorCode DMNetworkLayoutSetUp_Coupling(DM dm)
4222bf73ac6SHong Zhang {
4232bf73ac6SHong Zhang   PetscErrorCode ierr;
4242bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
425f11a936eSBarry Smith   PetscInt       i,j,ctr,np,*edges,*subnetvtx,*subnetedge,vStart;
4262bf73ac6SHong Zhang   PetscInt       k,*vidxlTog,Nsv=0,Nsubnet=network->Nsubnet;
4272bf73ac6SHong Zhang   PetscInt       *sedgelist=network->sedgelist;
4282bf73ac6SHong Zhang   const PetscInt *cone;
4292bf73ac6SHong Zhang   MPI_Comm       comm;
4302bf73ac6SHong Zhang   PetscMPIInt    size,rank,*recvcounts=NULL,*displs=NULL;
4312bf73ac6SHong Zhang   PetscInt       net,idx,gidx,nmerged,e,v,vfrom,vto,*vrange,*eowners,gidx_from,net_from,sv_idx;
4322bf73ac6SHong Zhang   SVtxType       svtype = SVNONE;
4332bf73ac6SHong Zhang   SVtx           *svtx=NULL;
4342bf73ac6SHong Zhang   PetscSection   sectiong;
4352bf73ac6SHong Zhang 
4362bf73ac6SHong Zhang   PetscFunctionBegin;
4372bf73ac6SHong Zhang   /* This implementation requires user input each subnet by a single processor, thus subnet[net].nvtx=subnet[net].Nvtx */
4382bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
4392bf73ac6SHong 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);
4402bf73ac6SHong Zhang   }
4412bf73ac6SHong Zhang 
4422bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
44355b25c41SPierre Jolivet   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
44455b25c41SPierre Jolivet   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
4452bf73ac6SHong Zhang 
4462bf73ac6SHong Zhang   /* (1) Create svtx[] from sedgelist */
4472bf73ac6SHong Zhang   /* -------------------------------- */
4482bf73ac6SHong Zhang   /* Nsv: global number of SVtx; svtx: shared vertices, see SVtx in dmnetworkimpl.h */
4492bf73ac6SHong Zhang   ierr = SVtxCreate(dm,network->Nsvtx,sedgelist,&Nsv,&svtx);CHKERRQ(ierr);
4502bf73ac6SHong Zhang 
4512bf73ac6SHong Zhang   /* (2) Setup svtx; Shared vto vertices are merged to their vfrom vertex with same global vetex index (gidx) */
4522bf73ac6SHong Zhang   /* -------------------------------------------------------------------------------------------------------- */
4532bf73ac6SHong Zhang   /* (2.1) compute vrage[rank]: global index of 1st local vertex in proc[rank] */
4542bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
4552bf73ac6SHong Zhang   for (i=0; i<size; i++) {displs[i] = i; recvcounts[i] = 1;}
4562bf73ac6SHong Zhang 
4572bf73ac6SHong Zhang   vrange[0] = 0;
4582bf73ac6SHong Zhang   ierr = MPI_Allgatherv(&network->nVertices,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
4592bf73ac6SHong Zhang   for (i=2; i<size+1; i++) {
4602bf73ac6SHong Zhang     vrange[i] += vrange[i-1];
4612bf73ac6SHong Zhang   }
4622bf73ac6SHong Zhang 
4632bf73ac6SHong Zhang   /* (2.2) Create vidxlTog: maps UN-MERGED local vertex index i to global index gidx (plex, excluding ghost vertices) */
4642bf73ac6SHong Zhang   ierr = PetscMalloc1(network->nVertices,&vidxlTog);CHKERRQ(ierr);
4652bf73ac6SHong Zhang   i = 0; gidx = 0;
4662bf73ac6SHong Zhang   nmerged = 0; /* local num of merged vertices */
4672bf73ac6SHong Zhang   network->nsvtx = 0;
4682bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
4692bf73ac6SHong Zhang     for (idx=0; idx<network->subnet[net].Nvtx; idx++) {
4702bf73ac6SHong Zhang       gidx_from = gidx;
4712bf73ac6SHong Zhang       sv_idx    = -1;
4722bf73ac6SHong Zhang 
4732bf73ac6SHong Zhang       ierr = SVtxSetUp(Nsv,svtx,net,idx,&gidx_from,&svtype,&sv_idx);CHKERRQ(ierr);
4742bf73ac6SHong Zhang       if (svtype == SVTO) {
4752bf73ac6SHong Zhang         if (network->subnet[net].nvtx) {/* this proc owns sv_to */
4762bf73ac6SHong Zhang           net_from = svtx[sv_idx].sv[0]; /* subnet num of its shared vertex */
4772bf73ac6SHong Zhang           if (network->subnet[net_from].nvtx == 0) {
4782bf73ac6SHong Zhang             /* this proc does not own v_from, thus a new local coupling vertex */
4792bf73ac6SHong Zhang             network->nsvtx++;
4802bf73ac6SHong Zhang           }
4812bf73ac6SHong Zhang           vidxlTog[i++] = gidx_from;
4822bf73ac6SHong Zhang           nmerged++; /* a coupling vertex -- merged */
4832bf73ac6SHong Zhang         }
4842bf73ac6SHong Zhang       } else {
4852bf73ac6SHong Zhang         if (svtype == SVFROM) {
4862bf73ac6SHong Zhang           if (network->subnet[net].nvtx) {
4872bf73ac6SHong Zhang             /* this proc owns this v_from, a new local coupling vertex */
4882bf73ac6SHong Zhang             network->nsvtx++;
4892bf73ac6SHong Zhang           }
4902bf73ac6SHong Zhang         }
4912bf73ac6SHong Zhang         if (network->subnet[net].nvtx) vidxlTog[i++] = gidx;
4922bf73ac6SHong Zhang         gidx++;
4932bf73ac6SHong Zhang       }
4942bf73ac6SHong Zhang     }
4952bf73ac6SHong Zhang   }
4962bf73ac6SHong Zhang #if defined(PETSC_USE_DEBUG)
4972bf73ac6SHong Zhang   if (i != network->nVertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"%D != %D nVertices",i,network->nVertices);
4982bf73ac6SHong Zhang #endif
4992bf73ac6SHong Zhang 
5002bf73ac6SHong Zhang   /* (2.3) Setup svtable for querry shared vertices */
5012bf73ac6SHong Zhang   for (v=0; v<Nsv; v++) {
5022bf73ac6SHong Zhang     gidx = svtx[v].gidx;
5032bf73ac6SHong Zhang     ierr = PetscTableAdd(network->svtable,gidx+1,v+1,INSERT_VALUES);CHKERRQ(ierr);
5042bf73ac6SHong Zhang   }
5052bf73ac6SHong Zhang 
5062bf73ac6SHong Zhang   /* (2.4) Shared vertices in the subnetworks are merged, update global NVertices: np = sum(local nmerged) */
5072bf73ac6SHong Zhang   ierr = MPI_Allreduce(&nmerged,&np,1,MPIU_INT,MPI_SUM,comm);CHKERRMPI(ierr);
5082bf73ac6SHong Zhang   network->NVertices -= np;
5092bf73ac6SHong Zhang 
5102bf73ac6SHong Zhang   ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr);
5112bf73ac6SHong Zhang 
5122bf73ac6SHong Zhang   ctr = 0;
5132bf73ac6SHong Zhang   for (net=0; net<Nsubnet; net++) {
5142bf73ac6SHong Zhang     for (j = 0; j < network->subnet[net].nedge; j++) {
5152bf73ac6SHong Zhang       /* vfrom: */
5162bf73ac6SHong Zhang       i = network->subnet[net].edgelist[2*j] + (network->subnet[net].vStart - vrange[rank]);
5172bf73ac6SHong Zhang       edges[2*ctr] = vidxlTog[i];
5182bf73ac6SHong Zhang 
5192bf73ac6SHong Zhang       /* vto */
5202bf73ac6SHong Zhang       i = network->subnet[net].edgelist[2*j+1] + (network->subnet[net].vStart - vrange[rank]);
5212bf73ac6SHong Zhang       edges[2*ctr+1] = vidxlTog[i];
5222bf73ac6SHong Zhang       ctr++;
5232bf73ac6SHong Zhang     }
5242bf73ac6SHong Zhang   }
5252bf73ac6SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
5262bf73ac6SHong Zhang   ierr = PetscFree(vidxlTog);CHKERRQ(ierr);
5272bf73ac6SHong Zhang 
5282bf73ac6SHong Zhang   /* (3) Create network->plex */
5292bf73ac6SHong Zhang   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
5302bf73ac6SHong Zhang   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
5312bf73ac6SHong Zhang   ierr = DMSetDimension(network->plex,1);CHKERRQ(ierr);
5322bf73ac6SHong Zhang   if (size == 1) {
5332bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices-nmerged,2,edges);CHKERRQ(ierr);
5342bf73ac6SHong Zhang   } else {
5352bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices-nmerged,PETSC_DECIDE,2,edges,NULL);CHKERRQ(ierr);
5362bf73ac6SHong Zhang   }
5372bf73ac6SHong Zhang 
5382bf73ac6SHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
5392bf73ac6SHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
5402bf73ac6SHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
5412bf73ac6SHong Zhang   vStart = network->vStart;
5422bf73ac6SHong Zhang 
5432bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
5442bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
5452bf73ac6SHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
5462bf73ac6SHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
5472bf73ac6SHong Zhang 
5482bf73ac6SHong Zhang   np = network->pEnd - network->pStart;
5492bf73ac6SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
55054dfd506SHong Zhang   for (i=0; i<np; i++) {
55154dfd506SHong Zhang     network->header[i].maxcomps = 1;
55254dfd506SHong Zhang     ierr = SetUpNetworkHeaderComponentValue(dm,&network->header[i],&network->cvalue[i]);CHKERRQ(ierr);
55354dfd506SHong Zhang   }
5542bf73ac6SHong Zhang 
555f11a936eSBarry Smith   /* (4) Create edge and vertex arrays for the subnetworks */
556f11a936eSBarry Smith   ierr = PetscCalloc2(network->nEdges,&subnetedge,network->nVertices+network->nsvtx,&subnetvtx);CHKERRQ(ierr); /* Maps local edge/vertex to local subnetwork's edge/vertex */
557f11a936eSBarry Smith   network->subnetedge = subnetedge;
558f11a936eSBarry Smith   network->subnetvtx  = subnetvtx;
5592bf73ac6SHong Zhang   for (j=0; j < Nsubnet; j++) {
560f11a936eSBarry Smith     network->subnet[j].edges = subnetedge;
561f11a936eSBarry Smith     subnetedge              += network->subnet[j].nedge;
562f11a936eSBarry Smith 
5632bf73ac6SHong Zhang     network->subnet[j].vertices = subnetvtx;
5642bf73ac6SHong Zhang     subnetvtx                  += network->subnet[j].nvtx;
5652bf73ac6SHong Zhang   }
5662bf73ac6SHong Zhang   network->svertices = subnetvtx;
5672bf73ac6SHong Zhang 
5682bf73ac6SHong Zhang   /* Get edge ownership */
569f11a936eSBarry Smith   ierr = PetscMalloc1(size+1,&eowners);CHKERRQ(ierr);
5702bf73ac6SHong Zhang   np = network->eEnd - network->eStart; /* num of local edges */
5712bf73ac6SHong Zhang   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr);
5722bf73ac6SHong Zhang   eowners[0] = 0;
5732bf73ac6SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
5742bf73ac6SHong Zhang 
575f11a936eSBarry Smith   /* Setup edge and vertex arrays for subnetworks */
5762bf73ac6SHong Zhang   e = 0;
5772bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
578f11a936eSBarry Smith     ctr = 0;
5792bf73ac6SHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
5802bf73ac6SHong Zhang       /* edge e */
5812bf73ac6SHong Zhang       network->header[e].index    = e + eowners[rank]; /* Global edge index */
5822bf73ac6SHong Zhang       network->header[e].subnetid = i;                 /* Subnetwork id */
5832bf73ac6SHong Zhang       network->subnet[i].edges[j] = e;
5842bf73ac6SHong Zhang       network->header[e].ndata           = 0;
5852bf73ac6SHong Zhang       network->header[e].offset[0]       = 0;
5862bf73ac6SHong Zhang       network->header[e].offsetvarrel[0] = 0;
58754dfd506SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,e,network->header[e].hsize);CHKERRQ(ierr);
5882bf73ac6SHong Zhang 
5892bf73ac6SHong Zhang       /* connected vertices */
5902bf73ac6SHong Zhang       ierr = DMPlexGetCone(network->plex,e,&cone);CHKERRQ(ierr);
5912bf73ac6SHong Zhang 
5922bf73ac6SHong Zhang       /* vertex cone[0] */
593f11a936eSBarry Smith       v = cone[0];
594f11a936eSBarry Smith       network->header[v].index    = edges[2*e];   /* Global vertex index */
595f11a936eSBarry Smith       network->header[v].subnetid = i;            /* Subnetwork id */
596f11a936eSBarry Smith       vfrom = network->subnet[i].edgelist[2*ctr];
597f11a936eSBarry Smith       network->subnet[i].vertices[vfrom] = v;     /* user's subnet[].dix = petsc's v */
5982bf73ac6SHong Zhang 
5992bf73ac6SHong Zhang       /* vertex cone[1] */
600f11a936eSBarry Smith       v = cone[1];
601f11a936eSBarry Smith       network->header[v].index    = edges[2*e+1]; /* Global vertex index */
602f11a936eSBarry Smith       network->header[v].subnetid = i;
603f11a936eSBarry Smith       vto = network->subnet[i].edgelist[2*ctr+1];
604f11a936eSBarry Smith       network->subnet[i].vertices[vto]= v;
6052bf73ac6SHong Zhang 
606f11a936eSBarry Smith       e++; ctr++;
6072bf73ac6SHong Zhang     }
6082bf73ac6SHong Zhang   }
609f11a936eSBarry Smith   ierr = PetscFree(eowners);CHKERRQ(ierr);
610f11a936eSBarry Smith   ierr = PetscFree(edges);CHKERRQ(ierr);
6112bf73ac6SHong Zhang 
6122bf73ac6SHong Zhang   /* Set vertex array for the subnetworks */
6132bf73ac6SHong Zhang   k = 0;
6142bf73ac6SHong Zhang   for (v=vStart; v<network->vEnd; v++) { /* local vertices, including ghosts */
6152bf73ac6SHong Zhang     network->header[v].ndata           = 0;
6162bf73ac6SHong Zhang     network->header[v].offset[0]       = 0;
6172bf73ac6SHong Zhang     network->header[v].offsetvarrel[0] = 0;
61854dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,v,network->header[v].hsize);CHKERRQ(ierr);
6192bf73ac6SHong Zhang 
6202bf73ac6SHong Zhang     /* shared vertex */
621f11a936eSBarry Smith     ierr = PetscTableFind(network->svtable,network->header[v].index+1,&i);CHKERRQ(ierr);
6222bf73ac6SHong Zhang     if (i) network->svertices[k++] = v;
6232bf73ac6SHong Zhang   }
6242bf73ac6SHong Zhang #if defined(PETSC_USE_DEBUG)
6252bf73ac6SHong Zhang   if (k != network->nsvtx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"k %D != %D nsvtx",k,network->nsvtx);
6262bf73ac6SHong Zhang #endif
6272bf73ac6SHong Zhang 
6282bf73ac6SHong Zhang   network->svtx  = svtx;
6292bf73ac6SHong Zhang   network->Nsvtx = Nsv;
6302bf73ac6SHong Zhang   ierr = PetscFree(sedgelist);CHKERRQ(ierr);
6312bf73ac6SHong Zhang 
6322bf73ac6SHong Zhang   /* Create a global section to be used by DMNetworkIsGhostVertex() which is a non-collective routine */
633f11a936eSBarry Smith   /* see snes_tutorials_network-ex1_4 */
6342bf73ac6SHong Zhang   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
6355f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
6365f2c45f1SShri Abhyankar }
6375f2c45f1SShri Abhyankar 
6385f2c45f1SShri Abhyankar /*@
6395f2c45f1SShri Abhyankar   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
6405f2c45f1SShri Abhyankar 
641d083f849SBarry Smith   Collective on dm
6425f2c45f1SShri Abhyankar 
6437a7aea1fSJed Brown   Input Parameters:
644f11a936eSBarry Smith . dm - the dmnetwork object
6455f2c45f1SShri Abhyankar 
6465f2c45f1SShri Abhyankar   Notes:
6475f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
6485f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
6495f2c45f1SShri Abhyankar 
6505f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
6515f2c45f1SShri Abhyankar 
65297bb938eSShri Abhyankar   Level: beginner
6535f2c45f1SShri Abhyankar 
6542bf73ac6SHong Zhang .seealso: DMNetworkSetNumSubNetworks(), DMNetworkAddSubnetwork()
6555f2c45f1SShri Abhyankar @*/
6565f2c45f1SShri Abhyankar PetscErrorCode DMNetworkLayoutSetUp(DM dm)
6575f2c45f1SShri Abhyankar {
6585f2c45f1SShri Abhyankar   PetscErrorCode ierr;
6595f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
660f11a936eSBarry Smith   PetscInt       i,j,ctr,Nsubnet=network->Nsubnet,*eowners,np,*edges,*subnetvtx,*subnetedge,e,v,vfrom,vto;
661caf410d2SHong Zhang   const PetscInt *cone;
662caf410d2SHong Zhang   MPI_Comm       comm;
663caf410d2SHong Zhang   PetscMPIInt    size,rank;
6646500d4abSHong Zhang 
6656500d4abSHong Zhang   PetscFunctionBegin;
6662bf73ac6SHong Zhang   if (network->nsubnet != network->Nsubnet) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Must call DMNetworkAddSubnetwork() %D times",network->Nsubnet);
6672bf73ac6SHong Zhang 
6682bf73ac6SHong Zhang   /* Create svtable for querry shared vertices */
6692bf73ac6SHong Zhang   ierr = PetscTableCreate(network->Nsvtx,network->NVertices+1,&network->svtable);CHKERRQ(ierr);
6702bf73ac6SHong Zhang 
6712bf73ac6SHong Zhang   if (network->Nsvtx) {
6722bf73ac6SHong Zhang     ierr = DMNetworkLayoutSetUp_Coupling(dm);CHKERRQ(ierr);
6732bf73ac6SHong Zhang     PetscFunctionReturn(0);
6742bf73ac6SHong Zhang   }
6752bf73ac6SHong Zhang 
676caf410d2SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
677ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
678ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
6796500d4abSHong Zhang 
680f11a936eSBarry Smith   /* Create LOCAL edgelist in global vertex ordering for the network by concatenating local input edgelists of the subnetworks */
6818e71b177SVaclav Hapla   ierr = PetscCalloc1(2*network->nEdges,&edges);CHKERRQ(ierr);
682caf410d2SHong Zhang   ctr = 0;
6832bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
6846500d4abSHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
685ba38b151SHong Zhang       edges[2*ctr]   = network->subnet[i].vStart + network->subnet[i].edgelist[2*j];
686ba38b151SHong Zhang       edges[2*ctr+1] = network->subnet[i].vStart + network->subnet[i].edgelist[2*j+1];
6876500d4abSHong Zhang       ctr++;
6886500d4abSHong Zhang     }
6896500d4abSHong Zhang   }
6907765340cSHong Zhang 
6912bf73ac6SHong Zhang   /* Create network->plex; One dimensional network, numCorners=2 */
6928e71b177SVaclav Hapla   ierr = DMCreate(comm,&network->plex);CHKERRQ(ierr);
6938e71b177SVaclav Hapla   ierr = DMSetType(network->plex,DMPLEX);CHKERRQ(ierr);
6942bf73ac6SHong Zhang   ierr = DMSetDimension(network->plex,1);CHKERRQ(ierr);
695caf410d2SHong Zhang   if (size == 1) {
6962bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellList(network->plex,network->nEdges,network->nVertices,2,edges);CHKERRQ(ierr);
697caf410d2SHong Zhang   } else {
6982bf73ac6SHong Zhang     ierr = DMPlexBuildFromCellListParallel(network->plex,network->nEdges,network->nVertices,PETSC_DECIDE,2,edges,NULL);CHKERRQ(ierr);
699acdb140fSBarry Smith   }
7006500d4abSHong Zhang 
7016500d4abSHong Zhang   ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr);
7026500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr);
7036500d4abSHong Zhang   ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr);
7046500d4abSHong Zhang 
705caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DataSection);CHKERRQ(ierr);
706caf410d2SHong Zhang   ierr = PetscSectionCreate(comm,&network->DofSection);CHKERRQ(ierr);
7076500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr);
7086500d4abSHong Zhang   ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr);
7096500d4abSHong Zhang 
710caf410d2SHong Zhang   np = network->pEnd - network->pStart;
711caf410d2SHong Zhang   ierr = PetscCalloc2(np,&network->header,np,&network->cvalue);CHKERRQ(ierr);
71254dfd506SHong Zhang   for (i=0; i < np; i++) {
71354dfd506SHong Zhang     network->header[i].maxcomps = 1;
71454dfd506SHong Zhang     ierr = SetUpNetworkHeaderComponentValue(dm,&network->header[i],&network->cvalue[i]);CHKERRQ(ierr);
71554dfd506SHong Zhang   }
716caf410d2SHong Zhang 
717f11a936eSBarry Smith   /* Create edge and vertex arrays for the subnetworks
718f11a936eSBarry Smith      This implementation assumes that DMNetwork reads
719f11a936eSBarry Smith      (1) a single subnetwork in parallel; or
720f11a936eSBarry Smith      (2) n subnetworks using n processors, one subnetwork/processor.
721f11a936eSBarry Smith    */
722f11a936eSBarry Smith   ierr = PetscCalloc2(network->nEdges,&subnetedge,network->nVertices,&subnetvtx);CHKERRQ(ierr); /* Maps local edge/vertex to local subnetwork's edge/vertex */
723f11a936eSBarry Smith 
724f11a936eSBarry Smith   network->subnetedge = subnetedge;
725f11a936eSBarry Smith   network->subnetvtx  = subnetvtx;
7262bf73ac6SHong Zhang   for (j=0; j < network->Nsubnet; j++) {
727f11a936eSBarry Smith     network->subnet[j].edges = subnetedge;
728f11a936eSBarry Smith     subnetedge              += network->subnet[j].nedge;
729f11a936eSBarry Smith 
730f11a936eSBarry Smith     network->subnet[j].vertices = subnetvtx;
731f11a936eSBarry Smith     subnetvtx                  += network->subnet[j].nvtx;
7326500d4abSHong Zhang   }
733caf410d2SHong Zhang 
734caf410d2SHong Zhang   /* Get edge ownership */
7352bf73ac6SHong Zhang   ierr = PetscMalloc1(size+1,&eowners);CHKERRQ(ierr);
736caf410d2SHong Zhang   np = network->eEnd - network->eStart;
737ffc4695bSBarry Smith   ierr = MPI_Allgather(&np,1,MPIU_INT,eowners+1,1,MPIU_INT,comm);CHKERRMPI(ierr);
738caf410d2SHong Zhang   eowners[0] = 0;
739caf410d2SHong Zhang   for (i=2; i<=size; i++) eowners[i] += eowners[i-1];
740caf410d2SHong Zhang 
7412bf73ac6SHong Zhang   /* Setup edge and vertex arrays for subnetworks */
7422bf73ac6SHong Zhang   e = 0;
7432bf73ac6SHong Zhang   for (i=0; i < Nsubnet; i++) {
744f11a936eSBarry Smith     ctr = 0;
7452bf73ac6SHong Zhang     for (j = 0; j < network->subnet[i].nedge; j++) {
7462bf73ac6SHong Zhang       /* edge e */
7472bf73ac6SHong Zhang       network->header[e].index    = e + eowners[rank];   /* Global edge index */
7482bf73ac6SHong Zhang       network->header[e].subnetid = i;
7492bf73ac6SHong Zhang       network->subnet[i].edges[j] = e;
750caf410d2SHong Zhang 
7512bf73ac6SHong Zhang       network->header[e].ndata           = 0;
7522bf73ac6SHong Zhang       network->header[e].offset[0]       = 0;
7532bf73ac6SHong Zhang       network->header[e].offsetvarrel[0] = 0;
75454dfd506SHong Zhang       ierr = PetscSectionAddDof(network->DataSection,e,network->header[e].hsize);CHKERRQ(ierr);
7552bf73ac6SHong Zhang 
7562bf73ac6SHong Zhang       /* connected vertices */
7572bf73ac6SHong Zhang       ierr = DMPlexGetCone(network->plex,e,&cone);CHKERRQ(ierr);
7582bf73ac6SHong Zhang 
7592bf73ac6SHong Zhang       /* vertex cone[0] */
760f11a936eSBarry Smith       v = cone[0];
761f11a936eSBarry Smith       network->header[v].index     = edges[2*e];  /* Global vertex index */
762f11a936eSBarry Smith       network->header[v].subnetid  = i;           /* Subnetwork id */
763f11a936eSBarry Smith       if (Nsubnet == 1) {
764f11a936eSBarry Smith         network->subnet[i].vertices[v - network->vStart] = v; /* user's subnet[].idx = petsc's v */
765f11a936eSBarry Smith       } else {
766f11a936eSBarry Smith         vfrom = network->subnet[i].edgelist[2*ctr];     /* =subnet[i].idx, Global index! */
767f11a936eSBarry Smith         network->subnet[i].vertices[vfrom] = v; /* user's subnet[].dix = petsc's v */
768f11a936eSBarry Smith       }
7692bf73ac6SHong Zhang 
7702bf73ac6SHong Zhang       /* vertex cone[1] */
771f11a936eSBarry Smith       v = cone[1];
772f11a936eSBarry Smith       network->header[v].index    = edges[2*e+1];   /* Global vertex index */
773f11a936eSBarry Smith       network->header[v].subnetid = i;              /* Subnetwork id */
774f11a936eSBarry Smith       if (Nsubnet == 1) {
775f11a936eSBarry Smith         network->subnet[i].vertices[v - network->vStart] = v; /* user's subnet[].idx = petsc's v */
776f11a936eSBarry Smith       } else {
777f11a936eSBarry Smith         vto = network->subnet[i].edgelist[2*ctr+1];     /* =subnet[i].idx, Global index! */
778f11a936eSBarry Smith         network->subnet[i].vertices[vto] = v; /* user's subnet[].dix = petsc's v */
779f11a936eSBarry Smith       }
7802bf73ac6SHong Zhang 
781f11a936eSBarry Smith       e++; ctr++;
7826500d4abSHong Zhang     }
7836500d4abSHong Zhang   }
7842bf73ac6SHong Zhang   ierr = PetscFree(eowners);CHKERRQ(ierr);
785f11a936eSBarry Smith   ierr = PetscFree(edges);CHKERRQ(ierr); /* local edge list with global idx used by DMPlexBuildFromCellList() */
786caf410d2SHong Zhang 
7872bf73ac6SHong Zhang   for (v = network->vStart; v < network->vEnd; v++) {
7882bf73ac6SHong Zhang     network->header[v].ndata           = 0;
7892bf73ac6SHong Zhang     network->header[v].offset[0]       = 0;
7902bf73ac6SHong Zhang     network->header[v].offsetvarrel[0] = 0;
79154dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,v,network->header[e].hsize);CHKERRQ(ierr);
7926500d4abSHong Zhang   }
7935f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7945f2c45f1SShri Abhyankar }
7955f2c45f1SShri Abhyankar 
79694ef8ddeSSatish Balay /*@C
7972bf73ac6SHong Zhang   DMNetworkGetSubnetwork - Returns the information about a requested subnetwork
7982bf73ac6SHong Zhang 
7992bf73ac6SHong Zhang   Not collective
8002727e31bSShri Abhyankar 
8017a7aea1fSJed Brown   Input Parameters:
802caf410d2SHong Zhang + dm - the DM object
8032bf73ac6SHong Zhang - netnum - the global index of the subnetwork
8042727e31bSShri Abhyankar 
8057a7aea1fSJed Brown   Output Parameters:
8062727e31bSShri Abhyankar + nv - number of vertices (local)
8072727e31bSShri Abhyankar . ne - number of edges (local)
8082bf73ac6SHong Zhang . vtx - local vertices of the subnetwork
8092bf73ac6SHong Zhang - edge - local edges of the subnetwork
8102727e31bSShri Abhyankar 
8112727e31bSShri Abhyankar   Notes:
8122727e31bSShri Abhyankar   Cannot call this routine before DMNetworkLayoutSetup()
8132727e31bSShri Abhyankar 
81406dd6b0eSSatish Balay   Level: intermediate
81506dd6b0eSSatish Balay 
8162bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkLayoutSetUp()
8172727e31bSShri Abhyankar @*/
8182bf73ac6SHong Zhang PetscErrorCode DMNetworkGetSubnetwork(DM dm,PetscInt netnum,PetscInt *nv,PetscInt *ne,const PetscInt **vtx,const PetscInt **edge)
8192727e31bSShri Abhyankar {
820caf410d2SHong Zhang   DM_Network *network = (DM_Network*)dm->data;
8212727e31bSShri Abhyankar 
8222727e31bSShri Abhyankar   PetscFunctionBegin;
8232bf73ac6SHong 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);
8242bf73ac6SHong Zhang   if (nv) *nv     = network->subnet[netnum].nvtx;
8252bf73ac6SHong Zhang   if (ne) *ne     = network->subnet[netnum].nedge;
8262bf73ac6SHong Zhang   if (vtx) *vtx   = network->subnet[netnum].vertices;
8272bf73ac6SHong Zhang   if (edge) *edge = network->subnet[netnum].edges;
8282bf73ac6SHong Zhang   PetscFunctionReturn(0);
8292bf73ac6SHong Zhang }
8302bf73ac6SHong Zhang 
8312bf73ac6SHong Zhang /*@
8322bf73ac6SHong Zhang   DMNetworkAddSharedVertices - Add shared vertices that connect two given subnetworks
8332bf73ac6SHong Zhang 
8342bf73ac6SHong Zhang   Collective on dm
8352bf73ac6SHong Zhang 
8362bf73ac6SHong Zhang   Input Parameters:
8372bf73ac6SHong Zhang + dm - the dm object
8382bf73ac6SHong Zhang . anetnum - first subnetwork global numbering returned by DMNetworkAddSubnetwork()
8392bf73ac6SHong Zhang . bnetnum - second subnetwork global numbering returned by DMNetworkAddSubnetwork()
8402bf73ac6SHong Zhang . nsvtx - number of vertices that are shared by the two subnetworks
8412bf73ac6SHong Zhang . asvtx - vertex index in the first subnetwork
8422bf73ac6SHong Zhang - bsvtx - vertex index in the second subnetwork
8432bf73ac6SHong Zhang 
8442bf73ac6SHong Zhang   Level: beginner
8452bf73ac6SHong Zhang 
8462bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkAddSubnetwork(), DMNetworkGetSharedVertices()
8472bf73ac6SHong Zhang @*/
8482bf73ac6SHong Zhang PetscErrorCode DMNetworkAddSharedVertices(DM dm,PetscInt anetnum,PetscInt bnetnum,PetscInt nsvtx,PetscInt asvtx[],PetscInt bsvtx[])
8492bf73ac6SHong Zhang {
8502bf73ac6SHong Zhang   PetscErrorCode ierr;
8512bf73ac6SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
8522bf73ac6SHong Zhang   PetscInt       i,nsubnet = network->Nsubnet,*sedgelist,Nsvtx=network->Nsvtx;
8532bf73ac6SHong Zhang 
8542bf73ac6SHong Zhang   PetscFunctionBegin;
8552bf73ac6SHong Zhang   if (anetnum == bnetnum) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Subnetworks must have different netnum");
8562bf73ac6SHong Zhang   if (anetnum < 0 || bnetnum < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"netnum cannot be negative");
8572bf73ac6SHong Zhang   if (!Nsvtx) {
8582bf73ac6SHong Zhang     /* allocate network->sedgelist to hold at most 2*nsubnet pairs of shared vertices */
8592bf73ac6SHong Zhang     ierr = PetscMalloc1(2*4*nsubnet,&network->sedgelist);CHKERRQ(ierr);
8602bf73ac6SHong Zhang   }
8612bf73ac6SHong Zhang 
8622bf73ac6SHong Zhang   sedgelist = network->sedgelist;
8632bf73ac6SHong Zhang   for (i=0; i<nsvtx; i++) {
8642bf73ac6SHong Zhang     sedgelist[4*Nsvtx]   = anetnum; sedgelist[4*Nsvtx+1] = asvtx[i];
8652bf73ac6SHong Zhang     sedgelist[4*Nsvtx+2] = bnetnum; sedgelist[4*Nsvtx+3] = bsvtx[i];
8662bf73ac6SHong Zhang     Nsvtx++;
8672bf73ac6SHong Zhang   }
8682bf73ac6SHong Zhang   if (Nsvtx > 2*nsubnet) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"allocate more space for coupling edgelist");
8692bf73ac6SHong Zhang   network->Nsvtx = Nsvtx;
8702727e31bSShri Abhyankar   PetscFunctionReturn(0);
8712727e31bSShri Abhyankar }
8722727e31bSShri Abhyankar 
8732727e31bSShri Abhyankar /*@C
8742bf73ac6SHong Zhang   DMNetworkGetSharedVertices - Returns the info for the shared vertices
8752bf73ac6SHong Zhang 
8762bf73ac6SHong Zhang   Not collective
877caf410d2SHong Zhang 
8787a7aea1fSJed Brown   Input Parameters:
8792bf73ac6SHong Zhang . dm - the DM object
880caf410d2SHong Zhang 
8817a7aea1fSJed Brown   Output Parameters:
8822bf73ac6SHong Zhang + nsv - number of local shared vertices
8832bf73ac6SHong Zhang - svtx - local shared vertices
884caf410d2SHong Zhang 
885caf410d2SHong Zhang   Notes:
886caf410d2SHong Zhang   Cannot call this routine before DMNetworkLayoutSetup()
887caf410d2SHong Zhang 
888caf410d2SHong Zhang   Level: intermediate
889caf410d2SHong Zhang 
8902bf73ac6SHong Zhang .seealso: DMNetworkGetSubnetwork(), DMNetworkLayoutSetUp(), DMNetworkAddSharedVertices()
891caf410d2SHong Zhang @*/
8922bf73ac6SHong Zhang PetscErrorCode DMNetworkGetSharedVertices(DM dm,PetscInt *nsv,const PetscInt **svtx)
893caf410d2SHong Zhang {
894caf410d2SHong Zhang   DM_Network *net = (DM_Network*)dm->data;
895caf410d2SHong Zhang 
896caf410d2SHong Zhang   PetscFunctionBegin;
8972bf73ac6SHong Zhang   if (net->Nsvtx) {
8982bf73ac6SHong Zhang     *nsv  = net->nsvtx;
8992bf73ac6SHong Zhang     *svtx = net->svertices;
90072c3e9f7SHong Zhang   } else {
9012bf73ac6SHong Zhang     *nsv  = 0;
9022bf73ac6SHong Zhang     *svtx = NULL;
90372c3e9f7SHong Zhang   }
904caf410d2SHong Zhang   PetscFunctionReturn(0);
905caf410d2SHong Zhang }
906caf410d2SHong Zhang 
907caf410d2SHong Zhang /*@C
9085f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
9095f2c45f1SShri Abhyankar 
910d083f849SBarry Smith   Logically collective on dm
9115f2c45f1SShri Abhyankar 
9127a7aea1fSJed Brown   Input Parameters:
9135f2c45f1SShri Abhyankar + dm - the network object
9145f2c45f1SShri Abhyankar . name - the component name
9155f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
9165f2c45f1SShri Abhyankar 
9177a7aea1fSJed Brown    Output Parameters:
9185f2c45f1SShri Abhyankar .  key - an integer key that defines the component
9195f2c45f1SShri Abhyankar 
9205f2c45f1SShri Abhyankar    Notes
9215f2c45f1SShri Abhyankar    This routine should be called by all processors before calling DMNetworkLayoutSetup().
9225f2c45f1SShri Abhyankar 
92397bb938eSShri Abhyankar    Level: beginner
9245f2c45f1SShri Abhyankar 
9252bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkLayoutSetUp()
9265f2c45f1SShri Abhyankar @*/
927caf410d2SHong Zhang PetscErrorCode DMNetworkRegisterComponent(DM dm,const char *name,size_t size,PetscInt *key)
9285f2c45f1SShri Abhyankar {
9295f2c45f1SShri Abhyankar   PetscErrorCode        ierr;
9305f2c45f1SShri Abhyankar   DM_Network            *network = (DM_Network*) dm->data;
93154dfd506SHong Zhang   DMNetworkComponent    *component=NULL,*newcomponent=NULL;
9325f2c45f1SShri Abhyankar   PetscBool             flg=PETSC_FALSE;
9335f2c45f1SShri Abhyankar   PetscInt              i;
9345f2c45f1SShri Abhyankar 
9355f2c45f1SShri Abhyankar   PetscFunctionBegin;
93654dfd506SHong Zhang   if (!network->component) {
93754dfd506SHong Zhang     ierr = PetscCalloc1(network->max_comps_registered,&network->component);CHKERRQ(ierr);
93854dfd506SHong Zhang   }
93954dfd506SHong Zhang 
9405f2c45f1SShri Abhyankar   for (i=0; i < network->ncomponent; i++) {
94154dfd506SHong Zhang     ierr = PetscStrcmp(network->component[i].name,name,&flg);CHKERRQ(ierr);
9425f2c45f1SShri Abhyankar     if (flg) {
9435f2c45f1SShri Abhyankar       *key = i;
9445f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
9455f2c45f1SShri Abhyankar     }
9466d64e262SShri Abhyankar   }
94754dfd506SHong Zhang 
94854dfd506SHong Zhang   if (network->ncomponent == network->max_comps_registered) {
94954dfd506SHong Zhang     /* Reached max allowed so resize component */
95054dfd506SHong Zhang     network->max_comps_registered += 2;
95154dfd506SHong Zhang     ierr = PetscCalloc1(network->max_comps_registered,&newcomponent);CHKERRQ(ierr);
95254dfd506SHong Zhang     /* Copy over the previous component info */
95354dfd506SHong Zhang     for (i=0; i < network->ncomponent; i++) {
95454dfd506SHong Zhang       ierr = PetscStrcpy(newcomponent[i].name,network->component[i].name);CHKERRQ(ierr);
95554dfd506SHong Zhang       newcomponent[i].size = network->component[i].size;
9565f2c45f1SShri Abhyankar     }
95754dfd506SHong Zhang     /* Free old one */
95854dfd506SHong Zhang     ierr = PetscFree(network->component);CHKERRQ(ierr);
95954dfd506SHong Zhang     /* Update pointer */
96054dfd506SHong Zhang     network->component = newcomponent;
96154dfd506SHong Zhang   }
96254dfd506SHong Zhang 
96354dfd506SHong Zhang   component = &network->component[network->ncomponent];
9645f2c45f1SShri Abhyankar 
9655f2c45f1SShri Abhyankar   ierr = PetscStrcpy(component->name,name);CHKERRQ(ierr);
9665f2c45f1SShri Abhyankar   component->size = size/sizeof(DMNetworkComponentGenericDataType);
9675f2c45f1SShri Abhyankar   *key = network->ncomponent;
9685f2c45f1SShri Abhyankar   network->ncomponent++;
9695f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9705f2c45f1SShri Abhyankar }
9715f2c45f1SShri Abhyankar 
9725f2c45f1SShri Abhyankar /*@
9732bf73ac6SHong Zhang   DMNetworkGetVertexRange - Get the bounds [start, end) for the local vertices
9745f2c45f1SShri Abhyankar 
9755f2c45f1SShri Abhyankar   Not Collective
9765f2c45f1SShri Abhyankar 
9775f2c45f1SShri Abhyankar   Input Parameters:
9782bf73ac6SHong Zhang . dm - the DMNetwork object
9795f2c45f1SShri Abhyankar 
980fd292e60Sprj-   Output Parameters:
9812bf73ac6SHong Zhang + vStart - the first vertex point
9822bf73ac6SHong Zhang - vEnd - one beyond the last vertex point
9835f2c45f1SShri Abhyankar 
98497bb938eSShri Abhyankar   Level: beginner
9855f2c45f1SShri Abhyankar 
9862bf73ac6SHong Zhang .seealso: DMNetworkGetEdgeRange()
9875f2c45f1SShri Abhyankar @*/
9885f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetVertexRange(DM dm,PetscInt *vStart,PetscInt *vEnd)
9895f2c45f1SShri Abhyankar {
9905f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*)dm->data;
9915f2c45f1SShri Abhyankar 
9925f2c45f1SShri Abhyankar   PetscFunctionBegin;
9935f2c45f1SShri Abhyankar   if (vStart) *vStart = network->vStart;
9945f2c45f1SShri Abhyankar   if (vEnd) *vEnd = network->vEnd;
9955f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9965f2c45f1SShri Abhyankar }
9975f2c45f1SShri Abhyankar 
9985f2c45f1SShri Abhyankar /*@
9992bf73ac6SHong Zhang   DMNetworkGetEdgeRange - Get the bounds [start, end) for the local edges
10005f2c45f1SShri Abhyankar 
10015f2c45f1SShri Abhyankar   Not Collective
10025f2c45f1SShri Abhyankar 
10035f2c45f1SShri Abhyankar   Input Parameters:
10042bf73ac6SHong Zhang . dm - the DMNetwork object
10055f2c45f1SShri Abhyankar 
1006fd292e60Sprj-   Output Parameters:
10075f2c45f1SShri Abhyankar + eStart - The first edge point
10085f2c45f1SShri Abhyankar - eEnd - One beyond the last edge point
10095f2c45f1SShri Abhyankar 
101097bb938eSShri Abhyankar   Level: beginner
10115f2c45f1SShri Abhyankar 
10122bf73ac6SHong Zhang .seealso: DMNetworkGetVertexRange()
10135f2c45f1SShri Abhyankar @*/
10145f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetEdgeRange(DM dm,PetscInt *eStart,PetscInt *eEnd)
10155f2c45f1SShri Abhyankar {
10165f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network*)dm->data;
10175f2c45f1SShri Abhyankar 
10185f2c45f1SShri Abhyankar   PetscFunctionBegin;
10195f2c45f1SShri Abhyankar   if (eStart) *eStart = network->eStart;
10205f2c45f1SShri Abhyankar   if (eEnd) *eEnd = network->eEnd;
10215f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10225f2c45f1SShri Abhyankar }
10235f2c45f1SShri Abhyankar 
10242bf73ac6SHong Zhang static PetscErrorCode DMNetworkGetIndex(DM dm,PetscInt p,PetscInt *index)
10252bf73ac6SHong Zhang {
10262bf73ac6SHong Zhang   PetscErrorCode    ierr;
10272bf73ac6SHong Zhang   DM_Network        *network = (DM_Network*)dm->data;
10282bf73ac6SHong Zhang   PetscInt          offsetp;
10292bf73ac6SHong Zhang   DMNetworkComponentHeader header;
10302bf73ac6SHong Zhang 
10312bf73ac6SHong Zhang   PetscFunctionBegin;
10322bf73ac6SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
10332bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
10342bf73ac6SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetp);
10352bf73ac6SHong Zhang   *index = header->index;
10362bf73ac6SHong Zhang   PetscFunctionReturn(0);
10372bf73ac6SHong Zhang }
10382bf73ac6SHong Zhang 
10397b6afd5bSHong Zhang /*@
10402bf73ac6SHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the global numbering for the edge on the network
10417b6afd5bSHong Zhang 
10427b6afd5bSHong Zhang   Not Collective
10437b6afd5bSHong Zhang 
10447b6afd5bSHong Zhang   Input Parameters:
10457b6afd5bSHong Zhang + dm - DMNetwork object
1046e85e6aecSHong Zhang - p - edge point
10477b6afd5bSHong Zhang 
1048fd292e60Sprj-   Output Parameters:
10492bf73ac6SHong Zhang . index - the global numbering for the edge
10507b6afd5bSHong Zhang 
10517b6afd5bSHong Zhang   Level: intermediate
10527b6afd5bSHong Zhang 
10532bf73ac6SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
10547b6afd5bSHong Zhang @*/
1055e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm,PetscInt p,PetscInt *index)
10567b6afd5bSHong Zhang {
10577b6afd5bSHong Zhang   PetscErrorCode ierr;
10587b6afd5bSHong Zhang 
10597b6afd5bSHong Zhang   PetscFunctionBegin;
10602bf73ac6SHong Zhang   ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr);
10617b6afd5bSHong Zhang   PetscFunctionReturn(0);
10627b6afd5bSHong Zhang }
10637b6afd5bSHong Zhang 
10645f2c45f1SShri Abhyankar /*@
10652bf73ac6SHong Zhang   DMNetworkGetGlobalVertexIndex - Get the global numbering for the vertex on the network
1066e85e6aecSHong Zhang 
1067e85e6aecSHong Zhang   Not Collective
1068e85e6aecSHong Zhang 
1069e85e6aecSHong Zhang   Input Parameters:
1070e85e6aecSHong Zhang + dm - DMNetwork object
1071e85e6aecSHong Zhang - p  - vertex point
1072e85e6aecSHong Zhang 
1073fd292e60Sprj-   Output Parameters:
10742bf73ac6SHong Zhang . index - the global numbering for the vertex
1075e85e6aecSHong Zhang 
1076e85e6aecSHong Zhang   Level: intermediate
1077e85e6aecSHong Zhang 
10782bf73ac6SHong Zhang .seealso: DMNetworkGetGlobalEdgeIndex()
1079e85e6aecSHong Zhang @*/
1080e85e6aecSHong Zhang PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm,PetscInt p,PetscInt *index)
1081e85e6aecSHong Zhang {
1082e85e6aecSHong Zhang   PetscErrorCode ierr;
1083e85e6aecSHong Zhang 
1084e85e6aecSHong Zhang   PetscFunctionBegin;
10852bf73ac6SHong Zhang   ierr = DMNetworkGetIndex(dm,p,index);CHKERRQ(ierr);
10869988b915SShri Abhyankar   PetscFunctionReturn(0);
10879988b915SShri Abhyankar }
10889988b915SShri Abhyankar 
10899988b915SShri Abhyankar /*@
10905f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
10915f2c45f1SShri Abhyankar 
10925f2c45f1SShri Abhyankar   Not Collective
10935f2c45f1SShri Abhyankar 
10945f2c45f1SShri Abhyankar   Input Parameters:
10952bf73ac6SHong Zhang + dm - the DMNetwork object
1096a2b725a8SWilliam Gropp - p - vertex/edge point
10975f2c45f1SShri Abhyankar 
10985f2c45f1SShri Abhyankar   Output Parameters:
10995f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
11005f2c45f1SShri Abhyankar 
110197bb938eSShri Abhyankar   Level: beginner
11025f2c45f1SShri Abhyankar 
11032bf73ac6SHong Zhang .seealso: DMNetworkRegisterComponent(), DMNetworkAddComponent()
11045f2c45f1SShri Abhyankar @*/
11055f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetNumComponents(DM dm,PetscInt p,PetscInt *numcomponents)
11065f2c45f1SShri Abhyankar {
11075f2c45f1SShri Abhyankar   PetscErrorCode ierr;
11085f2c45f1SShri Abhyankar   PetscInt       offset;
11095f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11105f2c45f1SShri Abhyankar 
11115f2c45f1SShri Abhyankar   PetscFunctionBegin;
11125f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
11135f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
11145f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
11155f2c45f1SShri Abhyankar }
11165f2c45f1SShri Abhyankar 
11175f2c45f1SShri Abhyankar /*@
11182bf73ac6SHong Zhang   DMNetworkGetLocalVecOffset - Get the offset for accessing the variables associated with a component at the given vertex/edge from the local vector
11195f2c45f1SShri Abhyankar 
11205f2c45f1SShri Abhyankar   Not Collective
11215f2c45f1SShri Abhyankar 
11225f2c45f1SShri Abhyankar   Input Parameters:
11232bf73ac6SHong Zhang + dm - the DMNetwork object
11247d928bffSSatish Balay . p - the edge/vertex point
11252bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
11269988b915SShri Abhyankar 
11279988b915SShri Abhyankar   Output Parameters:
11282bf73ac6SHong Zhang . offset - the local offset
11299988b915SShri Abhyankar 
11309988b915SShri Abhyankar   Level: intermediate
11319988b915SShri Abhyankar 
11322bf73ac6SHong Zhang .seealso: DMGetLocalVector(), DMNetworkGetComponent(), DMNetworkGetGlobalVecOffset()
11339988b915SShri Abhyankar @*/
11342bf73ac6SHong Zhang PetscErrorCode DMNetworkGetLocalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offset)
11359988b915SShri Abhyankar {
11369988b915SShri Abhyankar   PetscErrorCode ierr;
11379988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11389988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
11399988b915SShri Abhyankar   DMNetworkComponentHeader header;
11409988b915SShri Abhyankar 
11419988b915SShri Abhyankar   PetscFunctionBegin;
11422bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->localSection,p,&offsetp);CHKERRQ(ierr);
11432bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
11442bf73ac6SHong Zhang     *offset = offsetp;
11452bf73ac6SHong Zhang     PetscFunctionReturn(0);
11462bf73ac6SHong Zhang   }
11472bf73ac6SHong Zhang 
11489988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
11499988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
11509988b915SShri Abhyankar   *offset = offsetp + header->offsetvarrel[compnum];
11519988b915SShri Abhyankar   PetscFunctionReturn(0);
11529988b915SShri Abhyankar }
11539988b915SShri Abhyankar 
11549988b915SShri Abhyankar /*@
11552bf73ac6SHong Zhang   DMNetworkGetGlobalVecOffset - Get the global offset for accessing the variables associated with a component for the given vertex/edge from the global vector
11569988b915SShri Abhyankar 
11579988b915SShri Abhyankar   Not Collective
11589988b915SShri Abhyankar 
11599988b915SShri Abhyankar   Input Parameters:
11602bf73ac6SHong Zhang + dm - the DMNetwork object
11617d928bffSSatish Balay . p - the edge/vertex point
11622bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
11639988b915SShri Abhyankar 
11649988b915SShri Abhyankar   Output Parameters:
11659988b915SShri Abhyankar . offsetg - the global offset
11669988b915SShri Abhyankar 
11679988b915SShri Abhyankar   Level: intermediate
11689988b915SShri Abhyankar 
11692bf73ac6SHong Zhang .seealso: DMNetworkGetLocalVecOffset(), DMGetGlobalVector(), DMNetworkGetComponent()
11709988b915SShri Abhyankar @*/
11712bf73ac6SHong Zhang PetscErrorCode DMNetworkGetGlobalVecOffset(DM dm,PetscInt p,PetscInt compnum,PetscInt *offsetg)
11729988b915SShri Abhyankar {
11739988b915SShri Abhyankar   PetscErrorCode ierr;
11749988b915SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
11759988b915SShri Abhyankar   PetscInt       offsetp,offsetd;
11769988b915SShri Abhyankar   DMNetworkComponentHeader header;
11779988b915SShri Abhyankar 
11789988b915SShri Abhyankar   PetscFunctionBegin;
11792bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->plex->globalSection,p,&offsetp);CHKERRQ(ierr);
11802bf73ac6SHong Zhang   if (offsetp < 0) offsetp = -(offsetp + 1); /* Convert to actual global offset for ghost vertex */
11812bf73ac6SHong Zhang 
11822bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
11832bf73ac6SHong Zhang     *offsetg = offsetp;
11842bf73ac6SHong Zhang     PetscFunctionReturn(0);
11852bf73ac6SHong Zhang   }
11869988b915SShri Abhyankar   ierr = PetscSectionGetOffset(network->DataSection,p,&offsetd);CHKERRQ(ierr);
11879988b915SShri Abhyankar   header = (DMNetworkComponentHeader)(network->componentdataarray+offsetd);
11889988b915SShri Abhyankar   *offsetg = offsetp + header->offsetvarrel[compnum];
11899988b915SShri Abhyankar   PetscFunctionReturn(0);
11909988b915SShri Abhyankar }
11919988b915SShri Abhyankar 
11929988b915SShri Abhyankar /*@
11932bf73ac6SHong Zhang   DMNetworkGetEdgeOffset - Get the offset for accessing the variables associated with the given edge from the local subvector
119424121865SAdrian Maldonado 
119524121865SAdrian Maldonado   Not Collective
119624121865SAdrian Maldonado 
119724121865SAdrian Maldonado   Input Parameters:
11982bf73ac6SHong Zhang + dm - the DMNetwork object
119924121865SAdrian Maldonado - p - the edge point
120024121865SAdrian Maldonado 
120124121865SAdrian Maldonado   Output Parameters:
120224121865SAdrian Maldonado . offset - the offset
120324121865SAdrian Maldonado 
120424121865SAdrian Maldonado   Level: intermediate
120524121865SAdrian Maldonado 
12062bf73ac6SHong Zhang .seealso: DMNetworkGetLocalVecOffset(), DMGetLocalVector()
120724121865SAdrian Maldonado @*/
120824121865SAdrian Maldonado PetscErrorCode DMNetworkGetEdgeOffset(DM dm,PetscInt p,PetscInt *offset)
120924121865SAdrian Maldonado {
121024121865SAdrian Maldonado   PetscErrorCode ierr;
121124121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
121224121865SAdrian Maldonado 
121324121865SAdrian Maldonado   PetscFunctionBegin;
121424121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->edge.DofSection,p,offset);CHKERRQ(ierr);
121524121865SAdrian Maldonado   PetscFunctionReturn(0);
121624121865SAdrian Maldonado }
121724121865SAdrian Maldonado 
121824121865SAdrian Maldonado /*@
12192bf73ac6SHong Zhang   DMNetworkGetVertexOffset - Get the offset for accessing the variables associated with the given vertex from the local subvector
122024121865SAdrian Maldonado 
122124121865SAdrian Maldonado   Not Collective
122224121865SAdrian Maldonado 
122324121865SAdrian Maldonado   Input Parameters:
12242bf73ac6SHong Zhang + dm - the DMNetwork object
122524121865SAdrian Maldonado - p - the vertex point
122624121865SAdrian Maldonado 
122724121865SAdrian Maldonado   Output Parameters:
122824121865SAdrian Maldonado . offset - the offset
122924121865SAdrian Maldonado 
123024121865SAdrian Maldonado   Level: intermediate
123124121865SAdrian Maldonado 
12322bf73ac6SHong Zhang .seealso: DMNetworkGetEdgeOffset(), DMGetLocalVector()
123324121865SAdrian Maldonado @*/
123424121865SAdrian Maldonado PetscErrorCode DMNetworkGetVertexOffset(DM dm,PetscInt p,PetscInt *offset)
123524121865SAdrian Maldonado {
123624121865SAdrian Maldonado   PetscErrorCode ierr;
123724121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
123824121865SAdrian Maldonado 
123924121865SAdrian Maldonado   PetscFunctionBegin;
124024121865SAdrian Maldonado   p -= network->vStart;
124124121865SAdrian Maldonado   ierr = PetscSectionGetOffset(network->vertex.DofSection,p,offset);CHKERRQ(ierr);
124224121865SAdrian Maldonado   PetscFunctionReturn(0);
124324121865SAdrian Maldonado }
12442bf73ac6SHong Zhang 
12455f2c45f1SShri Abhyankar /*@
12462bf73ac6SHong Zhang   DMNetworkAddComponent - Adds a network component and number of variables at the given point (vertex/edge)
12475f2c45f1SShri Abhyankar 
12485f2c45f1SShri Abhyankar   Not Collective
12495f2c45f1SShri Abhyankar 
12505f2c45f1SShri Abhyankar   Input Parameters:
12514dc646bcSBarry Smith + dm - the DMNetwork
12525f2c45f1SShri Abhyankar . p - the vertex/edge point
12532bf73ac6SHong Zhang . componentkey - component key returned while registering the component; ignored if compvalue=NULL
12542bf73ac6SHong Zhang . compvalue - pointer to the data structure for the component, or NULL if not required.
12552bf73ac6SHong Zhang - nvar - number of variables for the component at the vertex/edge point
12565f2c45f1SShri Abhyankar 
125797bb938eSShri Abhyankar   Level: beginner
12585f2c45f1SShri Abhyankar 
12592bf73ac6SHong Zhang .seealso: DMNetworkGetComponent()
12605f2c45f1SShri Abhyankar @*/
12612bf73ac6SHong Zhang PetscErrorCode DMNetworkAddComponent(DM dm,PetscInt p,PetscInt componentkey,void* compvalue,PetscInt nvar)
12625f2c45f1SShri Abhyankar {
12635f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
12645f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
12652bf73ac6SHong Zhang   DMNetworkComponent       *component = &network->component[componentkey];
126654dfd506SHong Zhang   DMNetworkComponentHeader header;
126754dfd506SHong Zhang   DMNetworkComponentValue  cvalue;
12682bf73ac6SHong Zhang   PetscBool                sharedv=PETSC_FALSE;
126954dfd506SHong Zhang   PetscInt                 compnum;
127054dfd506SHong Zhang   PetscInt                 *compsize,*compkey,*compoffset,*compnvar,*compoffsetvarrel;
127154dfd506SHong Zhang   void*                    *compdata;
12725f2c45f1SShri Abhyankar 
12735f2c45f1SShri Abhyankar   PetscFunctionBegin;
12745f2c45f1SShri Abhyankar   ierr = PetscSectionAddDof(network->DofSection,p,nvar);CHKERRQ(ierr);
12752bf73ac6SHong Zhang   if (!compvalue) PetscFunctionReturn(0);
12762bf73ac6SHong Zhang 
12772bf73ac6SHong Zhang   ierr = DMNetworkIsSharedVertex(dm,p,&sharedv);CHKERRQ(ierr);
12782bf73ac6SHong Zhang   if (sharedv) {
12792bf73ac6SHong Zhang     PetscBool ghost;
12802bf73ac6SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
12812bf73ac6SHong Zhang     if (ghost) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Adding a component at a leaf(ghost) shared vertex is not supported");
12822bf73ac6SHong Zhang   }
12832bf73ac6SHong Zhang 
128454dfd506SHong Zhang   header = &network->header[p];
128554dfd506SHong Zhang   cvalue = &network->cvalue[p];
128654dfd506SHong Zhang   if (header->ndata == header->maxcomps) {
1287f11a936eSBarry Smith     PetscInt additional_size;
1288f11a936eSBarry Smith 
128954dfd506SHong Zhang     /* Reached limit so resize header component arrays */
129054dfd506SHong Zhang     header->maxcomps += 2;
129154dfd506SHong Zhang 
129254dfd506SHong Zhang     /* Allocate arrays for component information and value */
129354dfd506SHong Zhang     ierr = PetscCalloc5(header->maxcomps,&compsize,header->maxcomps,&compkey,header->maxcomps,&compoffset,header->maxcomps,&compnvar,header->maxcomps,&compoffsetvarrel);CHKERRQ(ierr);
129454dfd506SHong Zhang     ierr = PetscMalloc1(header->maxcomps,&compdata);CHKERRQ(ierr);
129554dfd506SHong Zhang 
129654dfd506SHong Zhang     /* Recalculate header size */
129754dfd506SHong Zhang     header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5*header->maxcomps*sizeof(PetscInt);
129854dfd506SHong Zhang 
129954dfd506SHong Zhang     header->hsize /= sizeof(DMNetworkComponentGenericDataType);
130054dfd506SHong Zhang 
130154dfd506SHong Zhang     /* Copy over component info */
130254dfd506SHong Zhang     ierr = PetscMemcpy(compsize,header->size,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
130354dfd506SHong Zhang     ierr = PetscMemcpy(compkey,header->key,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
130454dfd506SHong Zhang     ierr = PetscMemcpy(compoffset,header->offset,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
130554dfd506SHong Zhang     ierr = PetscMemcpy(compnvar,header->nvar,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
130654dfd506SHong Zhang     ierr = PetscMemcpy(compoffsetvarrel,header->offsetvarrel,header->ndata*sizeof(PetscInt));CHKERRQ(ierr);
130754dfd506SHong Zhang 
130854dfd506SHong Zhang     /* Copy over component data pointers */
130954dfd506SHong Zhang     ierr = PetscMemcpy(compdata,cvalue->data,header->ndata*sizeof(void*));CHKERRQ(ierr);
131054dfd506SHong Zhang 
131154dfd506SHong Zhang     /* Free old arrays */
131254dfd506SHong Zhang     ierr = PetscFree5(header->size,header->key,header->offset,header->nvar,header->offsetvarrel);CHKERRQ(ierr);
131354dfd506SHong Zhang     ierr = PetscFree(cvalue->data);CHKERRQ(ierr);
131454dfd506SHong Zhang 
131554dfd506SHong Zhang     /* Update pointers */
131654dfd506SHong Zhang     header->size = compsize;
131754dfd506SHong Zhang     header->key  = compkey;
131854dfd506SHong Zhang     header->offset = compoffset;
131954dfd506SHong Zhang     header->nvar = compnvar;
132054dfd506SHong Zhang     header->offsetvarrel = compoffsetvarrel;
132154dfd506SHong Zhang 
132254dfd506SHong Zhang     cvalue->data = compdata;
132354dfd506SHong Zhang 
132454dfd506SHong Zhang     /* Update DataSection Dofs */
132554dfd506SHong 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 */
1326f11a936eSBarry Smith     additional_size = (5*(header->maxcomps - header->ndata)*sizeof(PetscInt))/sizeof(DMNetworkComponentGenericDataType);
132754dfd506SHong Zhang     ierr = PetscSectionAddDof(network->DataSection,p,additional_size);CHKERRQ(ierr);
132854dfd506SHong Zhang   }
132954dfd506SHong Zhang   header = &network->header[p];
133054dfd506SHong Zhang   cvalue = &network->cvalue[p];
133154dfd506SHong Zhang 
133254dfd506SHong Zhang   compnum = header->ndata;
13332bf73ac6SHong Zhang 
13342bf73ac6SHong Zhang   header->size[compnum] = component->size;
13352bf73ac6SHong Zhang   ierr = PetscSectionAddDof(network->DataSection,p,component->size);CHKERRQ(ierr);
13362bf73ac6SHong Zhang   header->key[compnum] = componentkey;
13372bf73ac6SHong Zhang   if (compnum != 0) header->offset[compnum] = header->offset[compnum-1] + header->size[compnum-1];
13382bf73ac6SHong Zhang   cvalue->data[compnum] = (void*)compvalue;
13392bf73ac6SHong Zhang 
13402bf73ac6SHong Zhang   /* variables */
13412bf73ac6SHong Zhang   header->nvar[compnum] += nvar;
13422bf73ac6SHong Zhang   if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum-1] + header->nvar[compnum-1];
13432bf73ac6SHong Zhang 
13442bf73ac6SHong Zhang   header->ndata++;
13455f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13465f2c45f1SShri Abhyankar }
13475f2c45f1SShri Abhyankar 
134827f51fceSHong Zhang /*@
13492bf73ac6SHong Zhang   DMNetworkGetComponent - Gets the component key, the component data, and the number of variables at a given network point
135027f51fceSHong Zhang 
135127f51fceSHong Zhang   Not Collective
135227f51fceSHong Zhang 
135327f51fceSHong Zhang   Input Parameters:
13542bf73ac6SHong Zhang + dm - the DMNetwork object
13552bf73ac6SHong Zhang . p - vertex/edge point
135699c90e12SSatish Balay - compnum - component number; use ALL_COMPONENTS if sum up all the components
135727f51fceSHong Zhang 
135827f51fceSHong Zhang   Output Parameters:
13592bf73ac6SHong Zhang + compkey - the key obtained when registering the component (use NULL if not required)
13602bf73ac6SHong Zhang . component - the component data (use NULL if not required)
13612bf73ac6SHong Zhang - nvar  - number of variables (use NULL if not required)
136227f51fceSHong Zhang 
136397bb938eSShri Abhyankar   Level: beginner
136427f51fceSHong Zhang 
13652bf73ac6SHong Zhang .seealso: DMNetworkAddComponent(), DMNetworkGetNumComponents()
136627f51fceSHong Zhang @*/
13672bf73ac6SHong Zhang PetscErrorCode DMNetworkGetComponent(DM dm,PetscInt p,PetscInt compnum,PetscInt *compkey,void **component,PetscInt *nvar)
136827f51fceSHong Zhang {
136927f51fceSHong Zhang   PetscErrorCode ierr;
137027f51fceSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
13712bf73ac6SHong Zhang   PetscInt       offset = 0;
13722bf73ac6SHong Zhang   DMNetworkComponentHeader header;
137327f51fceSHong Zhang 
137427f51fceSHong Zhang   PetscFunctionBegin;
13752bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
137627f51fceSHong Zhang     ierr = PetscSectionGetDof(network->DofSection,p,nvar);CHKERRQ(ierr);
137727f51fceSHong Zhang     PetscFunctionReturn(0);
137827f51fceSHong Zhang   }
137927f51fceSHong Zhang 
13802bf73ac6SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
138142dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
13825f2c45f1SShri Abhyankar 
13832bf73ac6SHong Zhang   if (compnum >= 0) {
13842bf73ac6SHong Zhang     if (compkey) *compkey = header->key[compnum];
13852bf73ac6SHong Zhang     if (component) {
138654dfd506SHong Zhang       offset += header->hsize+header->offset[compnum];
13872bf73ac6SHong Zhang       *component = network->componentdataarray+offset;
13882bf73ac6SHong Zhang     }
13892bf73ac6SHong Zhang   }
13905f2c45f1SShri Abhyankar 
13912bf73ac6SHong Zhang   if (nvar) *nvar = header->nvar[compnum];
139254dfd506SHong Zhang 
13935f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13945f2c45f1SShri Abhyankar }
13955f2c45f1SShri Abhyankar 
13962bf73ac6SHong Zhang /*
13972bf73ac6SHong Zhang  Sets up the array that holds the data for all components and its associated section.
13982bf73ac6SHong 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.
13992bf73ac6SHong Zhang */
14005f2c45f1SShri Abhyankar PetscErrorCode DMNetworkComponentSetUp(DM dm)
14015f2c45f1SShri Abhyankar {
14025f2c45f1SShri Abhyankar   PetscErrorCode           ierr;
14035f2c45f1SShri Abhyankar   DM_Network               *network = (DM_Network*)dm->data;
1404f11a936eSBarry Smith   PetscInt                 arr_size,p,offset,offsetp,ncomp,i,*headerarr;
14055f2c45f1SShri Abhyankar   DMNetworkComponentHeader header;
14065f2c45f1SShri Abhyankar   DMNetworkComponentValue  cvalue;
1407f11a936eSBarry Smith   DMNetworkComponentHeader headerinfo;
14085f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
14095f2c45f1SShri Abhyankar 
14105f2c45f1SShri Abhyankar   PetscFunctionBegin;
14115f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DataSection);CHKERRQ(ierr);
14125f2c45f1SShri Abhyankar   ierr = PetscSectionGetStorageSize(network->DataSection,&arr_size);CHKERRQ(ierr);
1413f11a936eSBarry Smith   /* arr_size+1 fixes pipeline test of opensolaris-misc for src/dm/tests/ex10.c -- Do not know why */
1414f11a936eSBarry Smith   ierr = PetscCalloc1(arr_size+1,&network->componentdataarray);CHKERRQ(ierr);
14155f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
14165f2c45f1SShri Abhyankar   for (p = network->pStart; p < network->pEnd; p++) {
14175f2c45f1SShri Abhyankar     ierr = PetscSectionGetOffset(network->DataSection,p,&offsetp);CHKERRQ(ierr);
14185f2c45f1SShri Abhyankar     /* Copy header */
14195f2c45f1SShri Abhyankar     header = &network->header[p];
1420f11a936eSBarry Smith     headerinfo = (DMNetworkComponentHeader)(componentdataarray+offsetp);
142154dfd506SHong Zhang     ierr = PetscMemcpy(headerinfo,header,sizeof(struct _p_DMNetworkComponentHeader));CHKERRQ(ierr);
1422f11a936eSBarry Smith     headerarr = (PetscInt*)(headerinfo+1);
142354dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->size,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
142454dfd506SHong Zhang     headerarr += header->maxcomps;
142554dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->key,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
142654dfd506SHong Zhang     headerarr += header->maxcomps;
142754dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offset,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
142854dfd506SHong Zhang     headerarr += header->maxcomps;
142954dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->nvar,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
143054dfd506SHong Zhang     headerarr += header->maxcomps;
143154dfd506SHong Zhang     ierr = PetscMemcpy(headerarr,header->offsetvarrel,header->maxcomps*sizeof(PetscInt));CHKERRQ(ierr);
143254dfd506SHong Zhang 
14335f2c45f1SShri Abhyankar     /* Copy data */
14345f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
14355f2c45f1SShri Abhyankar     ncomp  = header->ndata;
14362bf73ac6SHong Zhang 
14375f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
143854dfd506SHong Zhang       offset = offsetp + header->hsize + header->offset[i];
1439302440fdSBarry Smith       ierr = PetscMemcpy(componentdataarray+offset,cvalue->data[i],header->size[i]*sizeof(DMNetworkComponentGenericDataType));CHKERRQ(ierr);
14405f2c45f1SShri Abhyankar     }
14415f2c45f1SShri Abhyankar   }
14425f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14435f2c45f1SShri Abhyankar }
14445f2c45f1SShri Abhyankar 
14455f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
14462bf73ac6SHong Zhang static PetscErrorCode DMNetworkVariablesSetUp(DM dm)
14475f2c45f1SShri Abhyankar {
14485f2c45f1SShri Abhyankar   PetscErrorCode ierr;
14495f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
14502bf73ac6SHong Zhang   MPI_Comm       comm;
14512bf73ac6SHong Zhang   PetscMPIInt    size;
14525f2c45f1SShri Abhyankar 
14535f2c45f1SShri Abhyankar   PetscFunctionBegin;
14542bf73ac6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
14552bf73ac6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
14562bf73ac6SHong Zhang 
14572bf73ac6SHong Zhang   if (size > 1) { /* Sync nvar at shared vertices for all processes */
14582bf73ac6SHong Zhang     PetscSF           sf = network->plex->sf;
14592bf73ac6SHong Zhang     PetscInt          *local_nvar, *remote_nvar,nroots,nleaves,p=-1,i,nsv;
14602bf73ac6SHong Zhang     const PetscInt    *svtx;
14612bf73ac6SHong Zhang     PetscBool         ghost;
14622bf73ac6SHong Zhang     /*
14632bf73ac6SHong Zhang      PetscMPIInt       rank;
14642bf73ac6SHong Zhang      const PetscInt    *ilocal;
14652bf73ac6SHong Zhang      const PetscSFNode *iremote;
14662bf73ac6SHong Zhang      ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
14672bf73ac6SHong Zhang      ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
14682bf73ac6SHong Zhang     */
14692bf73ac6SHong Zhang     ierr = PetscSFGetGraph(sf,&nroots,&nleaves,NULL,NULL);CHKERRQ(ierr);
14702bf73ac6SHong Zhang     ierr = PetscCalloc2(nroots,&local_nvar,nroots,&remote_nvar);CHKERRQ(ierr);
14712bf73ac6SHong Zhang 
14722bf73ac6SHong Zhang     /* Leaves copy user's nvar to local_nvar */
14732bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nsv,&svtx);CHKERRQ(ierr);
14742bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
14752bf73ac6SHong Zhang       p = svtx[i];
14762bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
14772bf73ac6SHong Zhang       if (!ghost) continue;
14782bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
14792bf73ac6SHong Zhang       /* printf("[%d] Before SFReduce: leaf local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
14802bf73ac6SHong Zhang     }
14812bf73ac6SHong Zhang 
14822bf73ac6SHong Zhang     /* Leaves add local_nvar to root remote_nvar */
14832bf73ac6SHong Zhang     ierr = PetscSFReduceBegin(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
14842bf73ac6SHong Zhang     ierr = PetscSFReduceEnd(sf, MPIU_INT, local_nvar, remote_nvar, MPI_SUM);CHKERRQ(ierr);
14852bf73ac6SHong Zhang     /* printf("[%d] remote_nvar[%d] = %d\n",rank,p,remote_nvar[p]); */
14862bf73ac6SHong Zhang 
14872bf73ac6SHong Zhang     /* Update roots' local_nvar */
14882bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
14892bf73ac6SHong Zhang       p = svtx[i];
14902bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
14912bf73ac6SHong Zhang       if (ghost) continue;
14922bf73ac6SHong Zhang 
14932bf73ac6SHong Zhang       ierr = PetscSectionAddDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
14942bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,p,&local_nvar[p]);CHKERRQ(ierr);
14952bf73ac6SHong Zhang       /* printf("[%d]  After SFReduce: root local_nvar[%d] = %d\n",rank,p,local_nvar[p]); */
14962bf73ac6SHong Zhang     }
14972bf73ac6SHong Zhang 
14982bf73ac6SHong Zhang     /* Roots Bcast nvar to leaves */
1499ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
1500ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(sf, MPIU_INT, local_nvar, remote_nvar,MPI_REPLACE);CHKERRQ(ierr);
15012bf73ac6SHong Zhang 
15022bf73ac6SHong Zhang     /* Leaves reset receved/remote nvar to dm */
15032bf73ac6SHong Zhang     for (i=0; i<nsv; i++) {
15042bf73ac6SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
15052bf73ac6SHong Zhang       if (!ghost) continue;
15062bf73ac6SHong Zhang       p = svtx[i];
15072bf73ac6SHong Zhang       /* printf("[%d] leaf reset nvar %d at p= %d \n",rank,remote_nvar[p],p); */
15082bf73ac6SHong Zhang       /* DMNetworkSetNumVariables(dm,p,remote_nvar[p]) */
15092bf73ac6SHong Zhang       ierr = PetscSectionSetDof(network->DofSection,p,remote_nvar[p]);CHKERRQ(ierr);
15102bf73ac6SHong Zhang     }
15112bf73ac6SHong Zhang 
15122bf73ac6SHong Zhang     ierr = PetscFree2(local_nvar,remote_nvar);CHKERRQ(ierr);
15132bf73ac6SHong Zhang   }
15142bf73ac6SHong Zhang 
15155f2c45f1SShri Abhyankar   ierr = PetscSectionSetUp(network->DofSection);CHKERRQ(ierr);
15165f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
15175f2c45f1SShri Abhyankar }
15185f2c45f1SShri Abhyankar 
151924121865SAdrian Maldonado /* Get a subsection from a range of points */
15209dddd249SSatish Balay static PetscErrorCode DMNetworkGetSubSection_private(PetscSection main,PetscInt pstart,PetscInt pend,PetscSection *subsection)
152124121865SAdrian Maldonado {
152224121865SAdrian Maldonado   PetscErrorCode ierr;
152324121865SAdrian Maldonado   PetscInt       i, nvar;
152424121865SAdrian Maldonado 
152524121865SAdrian Maldonado   PetscFunctionBegin;
15269dddd249SSatish Balay   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)main), subsection);CHKERRQ(ierr);
152724121865SAdrian Maldonado   ierr = PetscSectionSetChart(*subsection, 0, pend - pstart);CHKERRQ(ierr);
152824121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
15299dddd249SSatish Balay     ierr = PetscSectionGetDof(main,i,&nvar);CHKERRQ(ierr);
153024121865SAdrian Maldonado     ierr = PetscSectionSetDof(*subsection, i - pstart, nvar);CHKERRQ(ierr);
153124121865SAdrian Maldonado   }
153224121865SAdrian Maldonado 
153324121865SAdrian Maldonado   ierr = PetscSectionSetUp(*subsection);CHKERRQ(ierr);
153424121865SAdrian Maldonado   PetscFunctionReturn(0);
153524121865SAdrian Maldonado }
153624121865SAdrian Maldonado 
153724121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
15382bf73ac6SHong Zhang static PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
153924121865SAdrian Maldonado {
154024121865SAdrian Maldonado   PetscErrorCode ierr;
154124121865SAdrian Maldonado   PetscInt       i, *subpoints;
154224121865SAdrian Maldonado 
154324121865SAdrian Maldonado   PetscFunctionBegin;
154424121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
154524121865SAdrian Maldonado   ierr = PetscMalloc1(pend - pstart, &subpoints);CHKERRQ(ierr);
154624121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
154724121865SAdrian Maldonado     subpoints[i - pstart] = i;
154824121865SAdrian Maldonado   }
1549459726d8SSatish Balay   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,pend-pstart,subpoints,PETSC_COPY_VALUES,map);CHKERRQ(ierr);
155024121865SAdrian Maldonado   ierr = PetscFree(subpoints);CHKERRQ(ierr);
155124121865SAdrian Maldonado   PetscFunctionReturn(0);
155224121865SAdrian Maldonado }
155324121865SAdrian Maldonado 
155424121865SAdrian Maldonado /*@
15552bf73ac6SHong Zhang   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute
155624121865SAdrian Maldonado 
15572bf73ac6SHong Zhang   Collective on dm
155824121865SAdrian Maldonado 
155924121865SAdrian Maldonado   Input Parameters:
15602bf73ac6SHong Zhang . dm - the DMNetworkObject
156124121865SAdrian Maldonado 
156224121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
156324121865SAdrian Maldonado 
156424121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
156524121865SAdrian Maldonado 
1566caf410d2SHong 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]).
156724121865SAdrian Maldonado 
156824121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
156924121865SAdrian Maldonado 
157024121865SAdrian Maldonado   Level: intermediate
157124121865SAdrian Maldonado 
157224121865SAdrian Maldonado @*/
157324121865SAdrian Maldonado PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
157424121865SAdrian Maldonado {
157524121865SAdrian Maldonado   PetscErrorCode ierr;
157624121865SAdrian Maldonado   MPI_Comm       comm;
1577f11a936eSBarry Smith   PetscMPIInt    size;
157824121865SAdrian Maldonado   DM_Network     *network = (DM_Network*)dm->data;
157924121865SAdrian Maldonado 
1580eab1376dSHong Zhang   PetscFunctionBegin;
158124121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1582ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
158324121865SAdrian Maldonado 
158424121865SAdrian Maldonado   /* Create maps for vertices and edges */
158524121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
158624121865SAdrian Maldonado   ierr = DMNetworkSetSubMap_private(network->eStart,network->eEnd,&network->edge.mapping);CHKERRQ(ierr);
158724121865SAdrian Maldonado 
158824121865SAdrian Maldonado   /* Create local sub-sections */
158924121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->vStart,network->vEnd,&network->vertex.DofSection);CHKERRQ(ierr);
159024121865SAdrian Maldonado   ierr = DMNetworkGetSubSection_private(network->DofSection,network->eStart,network->eEnd,&network->edge.DofSection);CHKERRQ(ierr);
159124121865SAdrian Maldonado 
15929852e123SBarry Smith   if (size > 1) {
159324121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
159422bbedd7SHong Zhang 
159524121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection);CHKERRQ(ierr);
159624121865SAdrian Maldonado     ierr = PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf);CHKERRQ(ierr);
159724121865SAdrian Maldonado     ierr = PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection);CHKERRQ(ierr);
159824121865SAdrian Maldonado   } else {
159924121865SAdrian Maldonado     /* create structures for vertex */
160024121865SAdrian Maldonado     ierr = PetscSectionClone(network->vertex.DofSection,&network->vertex.GlobalDofSection);CHKERRQ(ierr);
160124121865SAdrian Maldonado     /* create structures for edge */
160224121865SAdrian Maldonado     ierr = PetscSectionClone(network->edge.DofSection,&network->edge.GlobalDofSection);CHKERRQ(ierr);
160324121865SAdrian Maldonado   }
160424121865SAdrian Maldonado 
160524121865SAdrian Maldonado   /* Add viewers */
160624121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->edge.GlobalDofSection,"Global edge dof section");CHKERRQ(ierr);
160724121865SAdrian Maldonado   ierr = PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection,"Global vertex dof section");CHKERRQ(ierr);
160824121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view");CHKERRQ(ierr);
160924121865SAdrian Maldonado   ierr = PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view");CHKERRQ(ierr);
161024121865SAdrian Maldonado   PetscFunctionReturn(0);
161124121865SAdrian Maldonado }
16127b6afd5bSHong Zhang 
1613f11a936eSBarry Smith /*
1614f11a936eSBarry Smith    Add all subnetid for the input vertex v in this process to the btable
1615f11a936eSBarry Smith    vertex_subnetid = supportingedge_subnetid
1616f11a936eSBarry Smith */
1617f11a936eSBarry Smith PETSC_STATIC_INLINE PetscErrorCode SetSubnetIdLookupBT(DM dm,PetscInt v,PetscInt Nsubnet,PetscBT btable)
1618f11a936eSBarry Smith {
1619f11a936eSBarry Smith   PetscErrorCode ierr;
1620f11a936eSBarry Smith   PetscInt       e,nedges,offset;
1621f11a936eSBarry Smith   const PetscInt *edges;
1622f11a936eSBarry Smith   DM_Network     *newDMnetwork = (DM_Network*)dm->data;
1623f11a936eSBarry Smith   DMNetworkComponentHeader header;
1624f11a936eSBarry Smith 
1625f11a936eSBarry Smith   PetscFunctionBegin;
1626f11a936eSBarry Smith   ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
1627f11a936eSBarry Smith   ierr = PetscBTMemzero(Nsubnet,btable);CHKERRQ(ierr);
1628f11a936eSBarry Smith   for (e=0; e<nedges; e++) {
1629f11a936eSBarry Smith     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,edges[e],&offset);CHKERRQ(ierr);
1630f11a936eSBarry Smith     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
1631f11a936eSBarry Smith     ierr = PetscBTSet(btable,header->subnetid);CHKERRQ(ierr);
1632f11a936eSBarry Smith   }
1633f11a936eSBarry Smith   PetscFunctionReturn(0);
1634f11a936eSBarry Smith }
1635f11a936eSBarry Smith 
16365f2c45f1SShri Abhyankar /*@
16372bf73ac6SHong Zhang   DMNetworkDistribute - Distributes the network and moves associated component data
16385f2c45f1SShri Abhyankar 
16395f2c45f1SShri Abhyankar   Collective
16405f2c45f1SShri Abhyankar 
1641*d8d19677SJose E. Roman   Input Parameters:
1642d3464fd4SAdrian Maldonado + DM - the DMNetwork object
16432bf73ac6SHong Zhang - overlap - the overlap of partitions, 0 is the default
16445f2c45f1SShri Abhyankar 
16455b3f975aSHong Zhang   Options Database Key:
16465b3f975aSHong Zhang + -dmnetwork_view - Calls DMView() at the conclusion of DMSetUp()
16475b3f975aSHong Zhang - -dmnetwork_view_distributed - Calls DMView() at the conclusion of DMNetworkDistribute()
16485b3f975aSHong Zhang 
16495f2c45f1SShri Abhyankar   Notes:
16508b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
16515f2c45f1SShri Abhyankar 
16525f2c45f1SShri Abhyankar   Level: intermediate
16535f2c45f1SShri Abhyankar 
16542bf73ac6SHong Zhang .seealso: DMNetworkCreate()
16555f2c45f1SShri Abhyankar @*/
1656d3464fd4SAdrian Maldonado PetscErrorCode DMNetworkDistribute(DM *dm,PetscInt overlap)
16575f2c45f1SShri Abhyankar {
1658d3464fd4SAdrian Maldonado   MPI_Comm       comm;
16595f2c45f1SShri Abhyankar   PetscErrorCode ierr;
1660d3464fd4SAdrian Maldonado   PetscMPIInt    size;
1661d3464fd4SAdrian Maldonado   DM_Network     *oldDMnetwork = (DM_Network*)((*dm)->data);
1662d3464fd4SAdrian Maldonado   DM_Network     *newDMnetwork;
1663caf410d2SHong Zhang   PetscSF        pointsf=NULL;
16645f2c45f1SShri Abhyankar   DM             newDM;
1665f11a936eSBarry Smith   PetscInt       j,e,v,offset,*subnetvtx,*subnetedge,Nsubnet,gidx,svtx_idx,nv;
16662bf73ac6SHong Zhang   PetscInt       to_net,from_net,*svto;
1667f11a936eSBarry Smith   PetscBT        btable;
166851ac5effSHong Zhang   PetscPartitioner         part;
1669b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
16705f2c45f1SShri Abhyankar 
16715f2c45f1SShri Abhyankar   PetscFunctionBegin;
1672d3464fd4SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)*dm,&comm);CHKERRQ(ierr);
1673ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1674d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1675d3464fd4SAdrian Maldonado 
16765b3f975aSHong Zhang   if (overlap) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"overlap %D != 0 is not supported yet",overlap);
16775b3f975aSHong Zhang 
16782bf73ac6SHong 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. */
1679d3464fd4SAdrian Maldonado   ierr = DMNetworkCreate(PetscObjectComm((PetscObject)*dm),&newDM);CHKERRQ(ierr);
16805f2c45f1SShri Abhyankar   newDMnetwork = (DM_Network*)newDM->data;
168154dfd506SHong Zhang   newDMnetwork->max_comps_registered = oldDMnetwork->max_comps_registered;
168254dfd506SHong Zhang   ierr = PetscMalloc1(newDMnetwork->max_comps_registered,&newDMnetwork->component);CHKERRQ(ierr);
168351ac5effSHong Zhang 
168451ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
168551ac5effSHong Zhang   ierr = DMPlexGetPartitioner(oldDMnetwork->plex,&part);CHKERRQ(ierr);
168651ac5effSHong Zhang   ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
168751ac5effSHong Zhang 
16882bf73ac6SHong Zhang   /* Distribute plex dm */
168980cf41d5SMatthew G. Knepley   ierr = DMPlexDistribute(oldDMnetwork->plex,overlap,&pointsf,&newDMnetwork->plex);CHKERRQ(ierr);
169051ac5effSHong Zhang 
16915f2c45f1SShri Abhyankar   /* Distribute dof section */
16922bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DofSection);CHKERRQ(ierr);
16935f2c45f1SShri Abhyankar   ierr = PetscSFDistributeSection(pointsf,oldDMnetwork->DofSection,NULL,newDMnetwork->DofSection);CHKERRQ(ierr);
169451ac5effSHong Zhang 
16955f2c45f1SShri Abhyankar   /* Distribute data and associated section */
16962bf73ac6SHong Zhang   ierr = PetscSectionCreate(comm,&newDMnetwork->DataSection);CHKERRQ(ierr);
169731da1fc8SHong Zhang   ierr = DMPlexDistributeData(newDMnetwork->plex,pointsf,oldDMnetwork->DataSection,MPIU_INT,(void*)oldDMnetwork->componentdataarray,newDMnetwork->DataSection,(void**)&newDMnetwork->componentdataarray);CHKERRQ(ierr);
169824121865SAdrian Maldonado 
16995f2c45f1SShri Abhyankar   ierr = PetscSectionGetChart(newDMnetwork->DataSection,&newDMnetwork->pStart,&newDMnetwork->pEnd);CHKERRQ(ierr);
17005f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,0, &newDMnetwork->eStart,&newDMnetwork->eEnd);CHKERRQ(ierr);
17015f2c45f1SShri Abhyankar   ierr = DMPlexGetHeightStratum(newDMnetwork->plex,1,&newDMnetwork->vStart,&newDMnetwork->vEnd);CHKERRQ(ierr);
17025f2c45f1SShri Abhyankar   newDMnetwork->nEdges    = newDMnetwork->eEnd - newDMnetwork->eStart;
17036fefedf4SHong Zhang   newDMnetwork->nVertices = newDMnetwork->vEnd - newDMnetwork->vStart;
17046fefedf4SHong Zhang   newDMnetwork->NVertices = oldDMnetwork->NVertices;
17055f2c45f1SShri Abhyankar   newDMnetwork->NEdges    = oldDMnetwork->NEdges;
1706f11a936eSBarry Smith   newDMnetwork->svtable   = oldDMnetwork->svtable; /* global table! */
17072bf73ac6SHong Zhang   oldDMnetwork->svtable   = NULL;
170824121865SAdrian Maldonado 
17091bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
171092fd8e1eSJed Brown   ierr = DMSetLocalSection(newDMnetwork->plex,newDMnetwork->DofSection);CHKERRQ(ierr);
1711e87a4003SBarry Smith   ierr = DMGetGlobalSection(newDMnetwork->plex,&newDMnetwork->GlobalDofSection);CHKERRQ(ierr);
17125f2c45f1SShri Abhyankar 
1713b9c6e19dSShri Abhyankar   /* Setup subnetwork info in the newDM */
17142bf73ac6SHong Zhang   newDMnetwork->Nsubnet = oldDMnetwork->Nsubnet;
17152bf73ac6SHong Zhang   newDMnetwork->Nsvtx   = oldDMnetwork->Nsvtx;
17162bf73ac6SHong Zhang   oldDMnetwork->Nsvtx   = 0;
17172bf73ac6SHong Zhang   newDMnetwork->svtx    = oldDMnetwork->svtx; /* global vertices! */
17182bf73ac6SHong Zhang   oldDMnetwork->svtx    = NULL;
17192bf73ac6SHong Zhang   ierr = PetscCalloc1(newDMnetwork->Nsubnet,&newDMnetwork->subnet);CHKERRQ(ierr);
17202bf73ac6SHong Zhang 
17212bf73ac6SHong Zhang   /* Copy over the global number of vertices and edges in each subnetwork.
17222bf73ac6SHong Zhang      Note: these are calculated in DMNetworkLayoutSetUp()
1723b9c6e19dSShri Abhyankar   */
1724f11a936eSBarry Smith   Nsubnet = newDMnetwork->Nsubnet;
1725f11a936eSBarry Smith   for (j = 0; j < Nsubnet; j++) {
1726b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nvtx  = oldDMnetwork->subnet[j].Nvtx;
1727b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].Nedge = oldDMnetwork->subnet[j].Nedge;
1728b9c6e19dSShri Abhyankar   }
1729b9c6e19dSShri Abhyankar 
1730f11a936eSBarry Smith   /* Count local nedges for subnetworks */
1731b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1732b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
173354dfd506SHong Zhang     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);
173454dfd506SHong Zhang     /* Update pointers */
173554dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
173654dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
173754dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
173854dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
173954dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
174054dfd506SHong Zhang 
1741b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].nedge++;
1742b9c6e19dSShri Abhyankar   }
1743b9c6e19dSShri Abhyankar 
1744f11a936eSBarry Smith   /* Count local nvtx for subnetworks */
1745f11a936eSBarry Smith   ierr = PetscBTCreate(Nsubnet,&btable);CHKERRQ(ierr);
1746b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1747b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1748b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
174954dfd506SHong Zhang     /* Update pointers */
175054dfd506SHong Zhang     header->size          = (PetscInt*)(header + 1);
175154dfd506SHong Zhang     header->key           = header->size   + header->maxcomps;
175254dfd506SHong Zhang     header->offset        = header->key    + header->maxcomps;
175354dfd506SHong Zhang     header->nvar          = header->offset + header->maxcomps;
175454dfd506SHong Zhang     header->offsetvarrel  = header->nvar   + header->maxcomps;
175554dfd506SHong Zhang 
17562bf73ac6SHong Zhang     /* shared vertices: use gidx=header->index to check if v is a shared vertex */
17572bf73ac6SHong Zhang     gidx = header->index;
17582bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
17592bf73ac6SHong Zhang     svtx_idx--;
17602bf73ac6SHong Zhang 
17612bf73ac6SHong Zhang     if (svtx_idx < 0) { /* not a shared vertex */
1762b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].nvtx++;
17632bf73ac6SHong Zhang     } else { /* a shared vertex belongs to more than one subnetworks, it is being counted by multiple subnets */
1764f11a936eSBarry Smith       ierr = SetSubnetIdLookupBT(newDM,v,Nsubnet,btable);CHKERRQ(ierr);
1765f11a936eSBarry Smith 
17662bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
1767f11a936eSBarry Smith       if (PetscBTLookup(btable,from_net)) newDMnetwork->subnet[from_net].nvtx++; /* sv is on from_net */
1768f11a936eSBarry Smith 
17692bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
17702bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
17712bf73ac6SHong Zhang         to_net = svto[0];
1772f11a936eSBarry Smith         if (PetscBTLookup(btable,to_net)) newDMnetwork->subnet[to_net].nvtx++; /* sv is on to_net */
17732bf73ac6SHong Zhang       }
17742bf73ac6SHong Zhang     }
1775b9c6e19dSShri Abhyankar   }
1776b9c6e19dSShri Abhyankar 
17772bf73ac6SHong Zhang   /* Get total local nvtx for subnetworks */
17782bf73ac6SHong Zhang   nv = 0;
1779f11a936eSBarry Smith   for (j=0; j<Nsubnet; j++) nv += newDMnetwork->subnet[j].nvtx;
17802bf73ac6SHong Zhang   nv += newDMnetwork->Nsvtx;
1781caf410d2SHong Zhang 
17822bf73ac6SHong Zhang   /* Now create the vertices and edge arrays for the subnetworks */
1783f11a936eSBarry Smith   ierr = PetscCalloc2(newDMnetwork->nEdges,&subnetedge,nv,&subnetvtx);CHKERRQ(ierr); /* Maps local vertex to local subnetwork's vertex */
1784f11a936eSBarry Smith   newDMnetwork->subnetedge = subnetedge;
17852bf73ac6SHong Zhang   newDMnetwork->subnetvtx  = subnetvtx;
1786f11a936eSBarry Smith   for (j=0; j < newDMnetwork->Nsubnet; j++) {
1787f11a936eSBarry Smith     newDMnetwork->subnet[j].edges = subnetedge;
1788f11a936eSBarry Smith     subnetedge                   += newDMnetwork->subnet[j].nedge;
17892bf73ac6SHong Zhang 
1790caf410d2SHong Zhang     newDMnetwork->subnet[j].vertices = subnetvtx;
1791caf410d2SHong Zhang     subnetvtx                       += newDMnetwork->subnet[j].nvtx;
1792caf410d2SHong Zhang 
17932bf73ac6SHong 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. */
1794b9c6e19dSShri Abhyankar     newDMnetwork->subnet[j].nvtx = newDMnetwork->subnet[j].nedge = 0;
1795b9c6e19dSShri Abhyankar   }
17962bf73ac6SHong Zhang   newDMnetwork->svertices = subnetvtx;
1797b9c6e19dSShri Abhyankar 
17982bf73ac6SHong Zhang   /* Set the edges and vertices in each subnetwork */
1799b9c6e19dSShri Abhyankar   for (e = newDMnetwork->eStart; e < newDMnetwork->eEnd; e++) {
1800b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,e,&offset);CHKERRQ(ierr);
1801b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
1802b9c6e19dSShri Abhyankar     newDMnetwork->subnet[header->subnetid].edges[newDMnetwork->subnet[header->subnetid].nedge++] = e;
1803b9c6e19dSShri Abhyankar   }
1804b9c6e19dSShri Abhyankar 
18052bf73ac6SHong Zhang   nv = 0;
1806b9c6e19dSShri Abhyankar   for (v = newDMnetwork->vStart; v < newDMnetwork->vEnd; v++) {
1807b9c6e19dSShri Abhyankar     ierr = PetscSectionGetOffset(newDMnetwork->DataSection,v,&offset);CHKERRQ(ierr);
1808b9c6e19dSShri Abhyankar     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray+offset);CHKERRQ(ierr);
18092bf73ac6SHong Zhang 
18102bf73ac6SHong Zhang     /* coupling vertices: use gidx = header->index to check if v is a coupling vertex */
18112bf73ac6SHong Zhang     ierr = PetscTableFind(newDMnetwork->svtable,header->index+1,&svtx_idx);CHKERRQ(ierr);
18122bf73ac6SHong Zhang     svtx_idx--;
18132bf73ac6SHong Zhang     if (svtx_idx < 0) {
1814b9c6e19dSShri Abhyankar       newDMnetwork->subnet[header->subnetid].vertices[newDMnetwork->subnet[header->subnetid].nvtx++] = v;
18152bf73ac6SHong Zhang     } else { /* a shared vertex */
18162bf73ac6SHong Zhang       newDMnetwork->svertices[nv++] = v;
18172bf73ac6SHong Zhang 
1818f11a936eSBarry Smith       /* add all subnetid for this shared vertex in this process to btable */
1819f11a936eSBarry Smith       ierr = SetSubnetIdLookupBT(newDM,v,Nsubnet,btable);CHKERRQ(ierr);
1820f11a936eSBarry Smith 
18212bf73ac6SHong Zhang       from_net = newDMnetwork->svtx[svtx_idx].sv[0];
1822f11a936eSBarry Smith       if (PetscBTLookup(btable,from_net))
18232bf73ac6SHong Zhang         newDMnetwork->subnet[from_net].vertices[newDMnetwork->subnet[from_net].nvtx++] = v;
18242bf73ac6SHong Zhang 
18252bf73ac6SHong Zhang       for (j=1; j<newDMnetwork->svtx[svtx_idx].n; j++) {
18262bf73ac6SHong Zhang         svto   = newDMnetwork->svtx[svtx_idx].sv + 2*j;
18272bf73ac6SHong Zhang         to_net = svto[0];
1828f11a936eSBarry Smith         if (PetscBTLookup(btable,to_net))
18292bf73ac6SHong Zhang           newDMnetwork->subnet[to_net].vertices[newDMnetwork->subnet[to_net].nvtx++] = v;
1830b9c6e19dSShri Abhyankar       }
18312bf73ac6SHong Zhang     }
18322bf73ac6SHong Zhang   }
18332bf73ac6SHong Zhang   newDMnetwork->nsvtx = nv;   /* num of local shared vertices */
1834b9c6e19dSShri Abhyankar 
1835caf410d2SHong Zhang   newDM->setupcalled = (*dm)->setupcalled;
183622bbedd7SHong Zhang   newDMnetwork->distributecalled = PETSC_TRUE;
1837caf410d2SHong Zhang 
18382bf73ac6SHong Zhang   /* Free spaces */
183924121865SAdrian Maldonado   ierr = PetscSFDestroy(&pointsf);CHKERRQ(ierr);
1840d3464fd4SAdrian Maldonado   ierr = DMDestroy(dm);CHKERRQ(ierr);
1841f11a936eSBarry Smith   ierr = PetscBTDestroy(&btable);CHKERRQ(ierr);
18422bf73ac6SHong Zhang 
18435b3f975aSHong Zhang   /* View distributed dmnetwork */
18445b3f975aSHong Zhang   ierr = DMViewFromOptions(newDM,NULL,"-dmnetwork_view_distributed");CHKERRQ(ierr);
18455b3f975aSHong Zhang 
1846d3464fd4SAdrian Maldonado   *dm  = newDM;
18475f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18485f2c45f1SShri Abhyankar }
18495f2c45f1SShri Abhyankar 
185024121865SAdrian Maldonado /*@C
18512bf73ac6SHong Zhang   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering
18522bf73ac6SHong Zhang 
18532bf73ac6SHong Zhang  Collective
185424121865SAdrian Maldonado 
185524121865SAdrian Maldonado   Input Parameters:
18569dddd249SSatish Balay + mainSF - the original SF structure
185724121865SAdrian Maldonado - map - a ISLocalToGlobal mapping that contains the subset of points
185824121865SAdrian Maldonado 
185924121865SAdrian Maldonado   Output Parameters:
18609dddd249SSatish Balay . subSF - a subset of the mainSF for the desired subset.
1861ee300463SSatish Balay 
1862ee300463SSatish Balay   Level: intermediate
18637d928bffSSatish Balay @*/
18649dddd249SSatish Balay PetscErrorCode PetscSFGetSubSF(PetscSF mainsf,ISLocalToGlobalMapping map,PetscSF *subSF)
18652bf73ac6SHong Zhang {
186624121865SAdrian Maldonado   PetscErrorCode        ierr;
186724121865SAdrian Maldonado   PetscInt              nroots, nleaves, *ilocal_sub;
186824121865SAdrian Maldonado   PetscInt              i, *ilocal_map, nroots_sub, nleaves_sub = 0;
186924121865SAdrian Maldonado   PetscInt              *local_points, *remote_points;
187024121865SAdrian Maldonado   PetscSFNode           *iremote_sub;
187124121865SAdrian Maldonado   const PetscInt        *ilocal;
187224121865SAdrian Maldonado   const PetscSFNode     *iremote;
187324121865SAdrian Maldonado 
187424121865SAdrian Maldonado   PetscFunctionBegin;
18759dddd249SSatish Balay   ierr = PetscSFGetGraph(mainsf,&nroots,&nleaves,&ilocal,&iremote);CHKERRQ(ierr);
187624121865SAdrian Maldonado 
187724121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
187824121865SAdrian Maldonado   ierr = PetscMalloc1(nleaves,&ilocal_map);CHKERRQ(ierr);
187924121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nleaves,ilocal,NULL,ilocal_map);CHKERRQ(ierr);
188024121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
188124121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
188224121865SAdrian Maldonado   }
188324121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
188424121865SAdrian Maldonado   ierr = PetscMalloc2(nroots,&local_points,nroots,&remote_points);CHKERRQ(ierr);
188524121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
188624121865SAdrian Maldonado   ierr = ISGlobalToLocalMappingApply(map,IS_GTOLM_MASK,nroots,local_points,NULL,local_points);CHKERRQ(ierr);
1887ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
1888ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(mainsf, MPIU_INT, local_points, remote_points,MPI_REPLACE);CHKERRQ(ierr);
188924121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
18904b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&ilocal_sub);CHKERRQ(ierr);
18914b70a8deSAdrian Maldonado   ierr = PetscMalloc1(nleaves_sub,&iremote_sub);CHKERRQ(ierr);
189224121865SAdrian Maldonado   nleaves_sub = 0;
189324121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
189424121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
189524121865SAdrian Maldonado       ilocal_sub[nleaves_sub] = ilocal_map[i];
18964b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank = iremote[i].rank;
189724121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
189824121865SAdrian Maldonado       nleaves_sub += 1;
189924121865SAdrian Maldonado     }
190024121865SAdrian Maldonado   }
190124121865SAdrian Maldonado   ierr = PetscFree2(local_points,remote_points);CHKERRQ(ierr);
190224121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingGetSize(map,&nroots_sub);CHKERRQ(ierr);
190324121865SAdrian Maldonado 
190424121865SAdrian Maldonado   /* Create new subSF */
190524121865SAdrian Maldonado   ierr = PetscSFCreate(PETSC_COMM_WORLD,subSF);CHKERRQ(ierr);
190624121865SAdrian Maldonado   ierr = PetscSFSetFromOptions(*subSF);CHKERRQ(ierr);
19074b70a8deSAdrian Maldonado   ierr = PetscSFSetGraph(*subSF,nroots_sub,nleaves_sub,ilocal_sub,PETSC_OWN_POINTER,iremote_sub,PETSC_COPY_VALUES);CHKERRQ(ierr);
190824121865SAdrian Maldonado   ierr = PetscFree(ilocal_map);CHKERRQ(ierr);
19094b70a8deSAdrian Maldonado   ierr = PetscFree(iremote_sub);CHKERRQ(ierr);
191024121865SAdrian Maldonado   PetscFunctionReturn(0);
191124121865SAdrian Maldonado }
191224121865SAdrian Maldonado 
19135f2c45f1SShri Abhyankar /*@C
19145f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
19155f2c45f1SShri Abhyankar 
19165f2c45f1SShri Abhyankar   Not Collective
19175f2c45f1SShri Abhyankar 
19185f2c45f1SShri Abhyankar   Input Parameters:
19192bf73ac6SHong Zhang + dm - the DMNetwork object
19205f2c45f1SShri Abhyankar - p  - the vertex point
19215f2c45f1SShri Abhyankar 
1922fd292e60Sprj-   Output Parameters:
19235f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
19242bf73ac6SHong Zhang - edges  - list of edge points
19255f2c45f1SShri Abhyankar 
192697bb938eSShri Abhyankar   Level: beginner
19275f2c45f1SShri Abhyankar 
19285f2c45f1SShri Abhyankar   Fortran Notes:
19295f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
19305f2c45f1SShri Abhyankar   include petsc.h90 in your code.
19315f2c45f1SShri Abhyankar 
19322bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetConnectedVertices()
19335f2c45f1SShri Abhyankar @*/
19345f2c45f1SShri Abhyankar PetscErrorCode DMNetworkGetSupportingEdges(DM dm,PetscInt vertex,PetscInt *nedges,const PetscInt *edges[])
19355f2c45f1SShri Abhyankar {
19365f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19375f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19385f2c45f1SShri Abhyankar 
19395f2c45f1SShri Abhyankar   PetscFunctionBegin;
19405f2c45f1SShri Abhyankar   ierr = DMPlexGetSupportSize(network->plex,vertex,nedges);CHKERRQ(ierr);
1941a9b4a83eSHong Zhang   if (edges) {ierr = DMPlexGetSupport(network->plex,vertex,edges);CHKERRQ(ierr);}
19425f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19435f2c45f1SShri Abhyankar }
19445f2c45f1SShri Abhyankar 
19455f2c45f1SShri Abhyankar /*@C
1946d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
19475f2c45f1SShri Abhyankar 
19485f2c45f1SShri Abhyankar   Not Collective
19495f2c45f1SShri Abhyankar 
19505f2c45f1SShri Abhyankar   Input Parameters:
19512bf73ac6SHong Zhang + dm - the DMNetwork object
19525f2c45f1SShri Abhyankar - p - the edge point
19535f2c45f1SShri Abhyankar 
1954fd292e60Sprj-   Output Parameters:
19555f2c45f1SShri Abhyankar . vertices - vertices connected to this edge
19565f2c45f1SShri Abhyankar 
195797bb938eSShri Abhyankar   Level: beginner
19585f2c45f1SShri Abhyankar 
19595f2c45f1SShri Abhyankar   Fortran Notes:
19605f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
19615f2c45f1SShri Abhyankar   include petsc.h90 in your code.
19625f2c45f1SShri Abhyankar 
19632bf73ac6SHong Zhang .seealso: DMNetworkCreate(), DMNetworkGetSupportingEdges()
19645f2c45f1SShri Abhyankar @*/
1965d842c372SHong Zhang PetscErrorCode DMNetworkGetConnectedVertices(DM dm,PetscInt edge,const PetscInt *vertices[])
19665f2c45f1SShri Abhyankar {
19675f2c45f1SShri Abhyankar   PetscErrorCode ierr;
19685f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
19695f2c45f1SShri Abhyankar 
19705f2c45f1SShri Abhyankar   PetscFunctionBegin;
19715f2c45f1SShri Abhyankar   ierr = DMPlexGetCone(network->plex,edge,vertices);CHKERRQ(ierr);
19725f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19735f2c45f1SShri Abhyankar }
19745f2c45f1SShri Abhyankar 
19755f2c45f1SShri Abhyankar /*@
19762bf73ac6SHong Zhang   DMNetworkIsSharedVertex - Returns TRUE if the vertex is shared by subnetworks
19772bf73ac6SHong Zhang 
19782bf73ac6SHong Zhang   Not Collective
19792bf73ac6SHong Zhang 
19802bf73ac6SHong Zhang   Input Parameters:
19812bf73ac6SHong Zhang + dm - the DMNetwork object
19822bf73ac6SHong Zhang - p - the vertex point
19832bf73ac6SHong Zhang 
19842bf73ac6SHong Zhang   Output Parameter:
19852bf73ac6SHong Zhang . flag - TRUE if the vertex is shared by subnetworks
19862bf73ac6SHong Zhang 
19872bf73ac6SHong Zhang   Level: beginner
19882bf73ac6SHong Zhang 
19892bf73ac6SHong Zhang .seealso: DMNetworkAddSharedVertices(), DMNetworkIsGhostVertex()
19902bf73ac6SHong Zhang @*/
19912bf73ac6SHong Zhang PetscErrorCode DMNetworkIsSharedVertex(DM dm,PetscInt p,PetscBool *flag)
19922bf73ac6SHong Zhang {
19932bf73ac6SHong Zhang   PetscErrorCode ierr;
19942bf73ac6SHong Zhang   PetscInt       i;
19952bf73ac6SHong Zhang 
19962bf73ac6SHong Zhang   PetscFunctionBegin;
19972bf73ac6SHong Zhang   *flag = PETSC_FALSE;
19982bf73ac6SHong Zhang 
19992bf73ac6SHong Zhang   if (dm->setupcalled) { /* DMNetworkGetGlobalVertexIndex() requires DMSetUp() be called */
20002bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
20012bf73ac6SHong Zhang     PetscInt       gidx;
20022bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVertexIndex(dm,p,&gidx);CHKERRQ(ierr);
20032bf73ac6SHong Zhang     ierr = PetscTableFind(network->svtable,gidx+1,&i);CHKERRQ(ierr);
20042bf73ac6SHong Zhang     if (i) *flag = PETSC_TRUE;
20052bf73ac6SHong Zhang   } else { /* would be removed? */
20062bf73ac6SHong Zhang     PetscInt       nv;
20072bf73ac6SHong Zhang     const PetscInt *vtx;
20082bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&nv,&vtx);CHKERRQ(ierr);
20092bf73ac6SHong Zhang     for (i=0; i<nv; i++) {
20102bf73ac6SHong Zhang       if (p == vtx[i]) {
20112bf73ac6SHong Zhang         *flag = PETSC_TRUE;
20122bf73ac6SHong Zhang         break;
20132bf73ac6SHong Zhang       }
20142bf73ac6SHong Zhang     }
20152bf73ac6SHong Zhang   }
20162bf73ac6SHong Zhang   PetscFunctionReturn(0);
20172bf73ac6SHong Zhang }
20182bf73ac6SHong Zhang 
20192bf73ac6SHong Zhang /*@
20205f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
20215f2c45f1SShri Abhyankar 
20225f2c45f1SShri Abhyankar   Not Collective
20235f2c45f1SShri Abhyankar 
20245f2c45f1SShri Abhyankar   Input Parameters:
20252bf73ac6SHong Zhang + dm - the DMNetwork object
2026a2b725a8SWilliam Gropp - p - the vertex point
20275f2c45f1SShri Abhyankar 
20285f2c45f1SShri Abhyankar   Output Parameter:
20295f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
20305f2c45f1SShri Abhyankar 
203197bb938eSShri Abhyankar   Level: beginner
20325f2c45f1SShri Abhyankar 
20332bf73ac6SHong Zhang .seealso: DMNetworkGetConnectedVertices(), DMNetworkGetVertexRange(), DMNetworkIsSharedVertex()
20345f2c45f1SShri Abhyankar @*/
20355f2c45f1SShri Abhyankar PetscErrorCode DMNetworkIsGhostVertex(DM dm,PetscInt p,PetscBool *isghost)
20365f2c45f1SShri Abhyankar {
20375f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20385f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
20395f2c45f1SShri Abhyankar   PetscInt       offsetg;
20405f2c45f1SShri Abhyankar   PetscSection   sectiong;
20415f2c45f1SShri Abhyankar 
20425f2c45f1SShri Abhyankar   PetscFunctionBegin;
20435f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
2044e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectiong);CHKERRQ(ierr);
20455f2c45f1SShri Abhyankar   ierr = PetscSectionGetOffset(sectiong,p,&offsetg);CHKERRQ(ierr);
20465f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
20475f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20485f2c45f1SShri Abhyankar }
20495f2c45f1SShri Abhyankar 
20505f2c45f1SShri Abhyankar PetscErrorCode DMSetUp_Network(DM dm)
20515f2c45f1SShri Abhyankar {
20525f2c45f1SShri Abhyankar   PetscErrorCode ierr;
20535f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
20545f2c45f1SShri Abhyankar 
20555f2c45f1SShri Abhyankar   PetscFunctionBegin;
20565f2c45f1SShri Abhyankar   ierr = DMNetworkComponentSetUp(dm);CHKERRQ(ierr);
20575f2c45f1SShri Abhyankar   ierr = DMNetworkVariablesSetUp(dm);CHKERRQ(ierr);
20585f2c45f1SShri Abhyankar 
205992fd8e1eSJed Brown   ierr = DMSetLocalSection(network->plex,network->DofSection);CHKERRQ(ierr);
2060e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&network->GlobalDofSection);CHKERRQ(ierr);
20619e1d080bSHong Zhang 
20629e1d080bSHong Zhang   dm->setupcalled = PETSC_TRUE;
20635b3f975aSHong Zhang 
20645b3f975aSHong Zhang   /* View dmnetwork */
20655b3f975aSHong Zhang   ierr = DMViewFromOptions(dm,NULL,"-dmnetwork_view");CHKERRQ(ierr);
20665f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20675f2c45f1SShri Abhyankar }
20685f2c45f1SShri Abhyankar 
20691ad426b7SHong Zhang /*@
207017df6e9eSHong Zhang   DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
20711ad426b7SHong Zhang       -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
20721ad426b7SHong Zhang 
20731ad426b7SHong Zhang   Collective
20741ad426b7SHong Zhang 
20751ad426b7SHong Zhang   Input Parameters:
20762bf73ac6SHong Zhang + dm - the DMNetwork object
207783b2e829SHong Zhang . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
207883b2e829SHong Zhang - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
20791ad426b7SHong Zhang 
20801ad426b7SHong Zhang  Level: intermediate
20811ad426b7SHong Zhang 
20821ad426b7SHong Zhang @*/
208383b2e829SHong Zhang PetscErrorCode DMNetworkHasJacobian(DM dm,PetscBool eflg,PetscBool vflg)
20841ad426b7SHong Zhang {
20851ad426b7SHong Zhang   DM_Network     *network=(DM_Network*)dm->data;
20868675203cSHong Zhang   PetscErrorCode ierr;
208766b4e0ffSHong Zhang   PetscInt       nVertices = network->nVertices;
20881ad426b7SHong Zhang 
20891ad426b7SHong Zhang   PetscFunctionBegin;
209083b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
209183b2e829SHong Zhang   network->userVertexJacobian = vflg;
20928675203cSHong Zhang 
20938675203cSHong Zhang   if (eflg && !network->Je) {
20948675203cSHong Zhang     ierr = PetscCalloc1(3*network->nEdges,&network->Je);CHKERRQ(ierr);
20958675203cSHong Zhang   }
20968675203cSHong Zhang 
209766b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
20988675203cSHong Zhang     PetscInt       i,*vptr,nedges,vStart=network->vStart;
209966b4e0ffSHong Zhang     PetscInt       nedges_total;
21008675203cSHong Zhang     const PetscInt *edges;
21018675203cSHong Zhang 
21028675203cSHong Zhang     /* count nvertex_total */
21038675203cSHong Zhang     nedges_total = 0;
21048675203cSHong Zhang     ierr = PetscMalloc1(nVertices+1,&vptr);CHKERRQ(ierr);
21058675203cSHong Zhang 
21068675203cSHong Zhang     vptr[0] = 0;
21078675203cSHong Zhang     for (i=0; i<nVertices; i++) {
21088675203cSHong Zhang       ierr = DMNetworkGetSupportingEdges(dm,i+vStart,&nedges,&edges);CHKERRQ(ierr);
21098675203cSHong Zhang       nedges_total += nedges;
21108675203cSHong Zhang       vptr[i+1] = vptr[i] + 2*nedges + 1;
21118675203cSHong Zhang     }
21128675203cSHong Zhang 
21138675203cSHong Zhang     ierr = PetscCalloc1(2*nedges_total+nVertices,&network->Jv);CHKERRQ(ierr);
21148675203cSHong Zhang     network->Jvptr = vptr;
21158675203cSHong Zhang   }
21161ad426b7SHong Zhang   PetscFunctionReturn(0);
21171ad426b7SHong Zhang }
21181ad426b7SHong Zhang 
21191ad426b7SHong Zhang /*@
212083b2e829SHong Zhang   DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
212183b2e829SHong Zhang 
212283b2e829SHong Zhang   Not Collective
212383b2e829SHong Zhang 
212483b2e829SHong Zhang   Input Parameters:
21252bf73ac6SHong Zhang + dm - the DMNetwork object
212683b2e829SHong Zhang . p - the edge point
21273e97b6e8SHong Zhang - J - array (size = 3) of Jacobian submatrices for this edge point:
21283e97b6e8SHong Zhang         J[0]: this edge
2129d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
213083b2e829SHong Zhang 
213197bb938eSShri Abhyankar   Level: advanced
213283b2e829SHong Zhang 
21332bf73ac6SHong Zhang .seealso: DMNetworkVertexSetMatrix()
213483b2e829SHong Zhang @*/
213583b2e829SHong Zhang PetscErrorCode DMNetworkEdgeSetMatrix(DM dm,PetscInt p,Mat J[])
213683b2e829SHong Zhang {
213783b2e829SHong Zhang   DM_Network *network=(DM_Network*)dm->data;
213883b2e829SHong Zhang 
213983b2e829SHong Zhang   PetscFunctionBegin;
21408675203cSHong Zhang   if (!network->Je) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
21418675203cSHong Zhang 
21428675203cSHong Zhang   if (J) {
2143883e35e8SHong Zhang     network->Je[3*p]   = J[0];
2144883e35e8SHong Zhang     network->Je[3*p+1] = J[1];
2145883e35e8SHong Zhang     network->Je[3*p+2] = J[2];
21468675203cSHong Zhang   }
214783b2e829SHong Zhang   PetscFunctionReturn(0);
214883b2e829SHong Zhang }
214983b2e829SHong Zhang 
215083b2e829SHong Zhang /*@
215176ddfea5SHong Zhang   DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
21521ad426b7SHong Zhang 
21531ad426b7SHong Zhang   Not Collective
21541ad426b7SHong Zhang 
21551ad426b7SHong Zhang   Input Parameters:
21561ad426b7SHong Zhang + dm - The DMNetwork object
21571ad426b7SHong Zhang . p - the vertex point
21583e97b6e8SHong Zhang - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
21593e97b6e8SHong Zhang         J[0]:       this vertex
21603e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
21613e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
21621ad426b7SHong Zhang 
216397bb938eSShri Abhyankar   Level: advanced
21641ad426b7SHong Zhang 
21652bf73ac6SHong Zhang .seealso: DMNetworkEdgeSetMatrix()
21661ad426b7SHong Zhang @*/
2167883e35e8SHong Zhang PetscErrorCode DMNetworkVertexSetMatrix(DM dm,PetscInt p,Mat J[])
21685f2c45f1SShri Abhyankar {
21695f2c45f1SShri Abhyankar   PetscErrorCode ierr;
21705f2c45f1SShri Abhyankar   DM_Network     *network=(DM_Network*)dm->data;
21718675203cSHong Zhang   PetscInt       i,*vptr,nedges,vStart=network->vStart;
2172883e35e8SHong Zhang   const PetscInt *edges;
21735f2c45f1SShri Abhyankar 
21745f2c45f1SShri Abhyankar   PetscFunctionBegin;
21758675203cSHong Zhang   if (!network->Jv) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ORDER,"Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
2176883e35e8SHong Zhang 
21778675203cSHong Zhang   if (J) {
2178883e35e8SHong Zhang     vptr = network->Jvptr;
21793e97b6e8SHong Zhang     network->Jv[vptr[p-vStart]] = J[0]; /* Set Jacobian for this vertex */
21803e97b6e8SHong Zhang 
21813e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
2182883e35e8SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,p,&nedges,&edges);CHKERRQ(ierr);
2183883e35e8SHong Zhang     for (i=1; i<=2*nedges; i++) network->Jv[vptr[p-vStart]+i] = J[i];
21848675203cSHong Zhang   }
2185883e35e8SHong Zhang   PetscFunctionReturn(0);
2186883e35e8SHong Zhang }
2187883e35e8SHong Zhang 
2188e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
21895cf7da58SHong Zhang {
21905cf7da58SHong Zhang   PetscErrorCode ierr;
21915cf7da58SHong Zhang   PetscInt       j;
21925cf7da58SHong Zhang   PetscScalar    val=(PetscScalar)ncols;
21935cf7da58SHong Zhang 
21945cf7da58SHong Zhang   PetscFunctionBegin;
21955cf7da58SHong Zhang   if (!ghost) {
21965cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
21975cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
21985cf7da58SHong Zhang     }
21995cf7da58SHong Zhang   } else {
22005cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22015cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22025cf7da58SHong Zhang     }
22035cf7da58SHong Zhang   }
22045cf7da58SHong Zhang   PetscFunctionReturn(0);
22055cf7da58SHong Zhang }
22065cf7da58SHong Zhang 
2207e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
22085cf7da58SHong Zhang {
22095cf7da58SHong Zhang   PetscErrorCode ierr;
22105cf7da58SHong Zhang   PetscInt       j,ncols_u;
22115cf7da58SHong Zhang   PetscScalar    val;
22125cf7da58SHong Zhang 
22135cf7da58SHong Zhang   PetscFunctionBegin;
22145cf7da58SHong Zhang   if (!ghost) {
22155cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22165cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22175cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
22185cf7da58SHong Zhang       ierr = VecSetValues(vdnz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22195cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22205cf7da58SHong Zhang     }
22215cf7da58SHong Zhang   } else {
22225cf7da58SHong Zhang     for (j=0; j<nrows; j++) {
22235cf7da58SHong Zhang       ierr = MatGetRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22245cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
22255cf7da58SHong Zhang       ierr = VecSetValues(vonz,1,&rows[j],&val,ADD_VALUES);CHKERRQ(ierr);
22265cf7da58SHong Zhang       ierr = MatRestoreRow(Ju,j,&ncols_u,NULL,NULL);CHKERRQ(ierr);
22275cf7da58SHong Zhang     }
22285cf7da58SHong Zhang   }
22295cf7da58SHong Zhang   PetscFunctionReturn(0);
22305cf7da58SHong Zhang }
22315cf7da58SHong Zhang 
2232e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetPreallocationblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscBool ghost,Vec vdnz,Vec vonz)
22335cf7da58SHong Zhang {
22345cf7da58SHong Zhang   PetscErrorCode ierr;
22355cf7da58SHong Zhang 
22365cf7da58SHong Zhang   PetscFunctionBegin;
22375cf7da58SHong Zhang   if (Ju) {
22385cf7da58SHong Zhang     ierr = MatSetPreallocationUserblock_private(Ju,nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
22395cf7da58SHong Zhang   } else {
22405cf7da58SHong Zhang     ierr = MatSetPreallocationDenseblock_private(nrows,rows,ncols,ghost,vdnz,vonz);CHKERRQ(ierr);
22415cf7da58SHong Zhang   }
22425cf7da58SHong Zhang   PetscFunctionReturn(0);
22435cf7da58SHong Zhang }
22445cf7da58SHong Zhang 
2245e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetDenseblock_private(PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2246883e35e8SHong Zhang {
2247883e35e8SHong Zhang   PetscErrorCode ierr;
2248883e35e8SHong Zhang   PetscInt       j,*cols;
2249883e35e8SHong Zhang   PetscScalar    *zeros;
2250883e35e8SHong Zhang 
2251883e35e8SHong Zhang   PetscFunctionBegin;
2252883e35e8SHong Zhang   ierr = PetscCalloc2(ncols,&cols,nrows*ncols,&zeros);CHKERRQ(ierr);
2253883e35e8SHong Zhang   for (j=0; j<ncols; j++) cols[j] = j+ cstart;
2254883e35e8SHong Zhang   ierr = MatSetValues(*J,nrows,rows,ncols,cols,zeros,INSERT_VALUES);CHKERRQ(ierr);
2255883e35e8SHong Zhang   ierr = PetscFree2(cols,zeros);CHKERRQ(ierr);
22561ad426b7SHong Zhang   PetscFunctionReturn(0);
22571ad426b7SHong Zhang }
2258a4e85ca8SHong Zhang 
2259e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetUserblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
22603e97b6e8SHong Zhang {
22613e97b6e8SHong Zhang   PetscErrorCode ierr;
22623e97b6e8SHong Zhang   PetscInt       j,M,N,row,col,ncols_u;
22633e97b6e8SHong Zhang   const PetscInt *cols;
22643e97b6e8SHong Zhang   PetscScalar    zero=0.0;
22653e97b6e8SHong Zhang 
22663e97b6e8SHong Zhang   PetscFunctionBegin;
22673e97b6e8SHong Zhang   ierr = MatGetSize(Ju,&M,&N);CHKERRQ(ierr);
22683e97b6e8SHong 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);
22693e97b6e8SHong Zhang 
22703e97b6e8SHong Zhang   for (row=0; row<nrows; row++) {
22713e97b6e8SHong Zhang     ierr = MatGetRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
22723e97b6e8SHong Zhang     for (j=0; j<ncols_u; j++) {
22733e97b6e8SHong Zhang       col = cols[j] + cstart;
22743e97b6e8SHong Zhang       ierr = MatSetValues(*J,1,&rows[row],1,&col,&zero,INSERT_VALUES);CHKERRQ(ierr);
22753e97b6e8SHong Zhang     }
22763e97b6e8SHong Zhang     ierr = MatRestoreRow(Ju,row,&ncols_u,&cols,NULL);CHKERRQ(ierr);
22773e97b6e8SHong Zhang   }
22783e97b6e8SHong Zhang   PetscFunctionReturn(0);
22793e97b6e8SHong Zhang }
22801ad426b7SHong Zhang 
2281e0f69777SHong Zhang PETSC_STATIC_INLINE PetscErrorCode MatSetblock_private(Mat Ju,PetscInt nrows,PetscInt *rows,PetscInt ncols,PetscInt cstart,Mat *J)
2282a4e85ca8SHong Zhang {
2283a4e85ca8SHong Zhang   PetscErrorCode ierr;
2284f4431b8cSHong Zhang 
2285a4e85ca8SHong Zhang   PetscFunctionBegin;
2286a4e85ca8SHong Zhang   if (Ju) {
2287a4e85ca8SHong Zhang     ierr = MatSetUserblock_private(Ju,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2288a4e85ca8SHong Zhang   } else {
2289a4e85ca8SHong Zhang     ierr = MatSetDenseblock_private(nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2290a4e85ca8SHong Zhang   }
2291a4e85ca8SHong Zhang   PetscFunctionReturn(0);
2292a4e85ca8SHong Zhang }
2293a4e85ca8SHong Zhang 
229424121865SAdrian 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.
229524121865SAdrian Maldonado */
229624121865SAdrian Maldonado PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
229724121865SAdrian Maldonado {
229824121865SAdrian Maldonado   PetscErrorCode ierr;
229924121865SAdrian Maldonado   PetscInt       i,size,dof;
230024121865SAdrian Maldonado   PetscInt       *glob2loc;
230124121865SAdrian Maldonado 
230224121865SAdrian Maldonado   PetscFunctionBegin;
230324121865SAdrian Maldonado   ierr = PetscSectionGetStorageSize(localsec,&size);CHKERRQ(ierr);
230424121865SAdrian Maldonado   ierr = PetscMalloc1(size,&glob2loc);CHKERRQ(ierr);
230524121865SAdrian Maldonado 
230624121865SAdrian Maldonado   for (i = 0; i < size; i++) {
230724121865SAdrian Maldonado     ierr = PetscSectionGetOffset(globalsec,i,&dof);CHKERRQ(ierr);
230824121865SAdrian Maldonado     dof = (dof >= 0) ? dof : -(dof + 1);
230924121865SAdrian Maldonado     glob2loc[i] = dof;
231024121865SAdrian Maldonado   }
231124121865SAdrian Maldonado 
231224121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD,1,size,glob2loc,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr);
231324121865SAdrian Maldonado #if 0
231424121865SAdrian Maldonado   ierr = PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
231524121865SAdrian Maldonado #endif
231624121865SAdrian Maldonado   PetscFunctionReturn(0);
231724121865SAdrian Maldonado }
231824121865SAdrian Maldonado 
231901ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
23209e1d080bSHong Zhang 
23219e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network_Nest(DM dm,Mat *J)
23221ad426b7SHong Zhang {
23231ad426b7SHong Zhang   PetscErrorCode ierr;
23241ad426b7SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
232524121865SAdrian Maldonado   PetscInt       eDof,vDof;
232624121865SAdrian Maldonado   Mat            j11,j12,j21,j22,bA[2][2];
23279e1d080bSHong Zhang   MPI_Comm       comm;
232824121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap,vISMap;
232924121865SAdrian Maldonado 
23309e1d080bSHong Zhang   PetscFunctionBegin;
233124121865SAdrian Maldonado   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
233224121865SAdrian Maldonado 
233324121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection,&eDof);CHKERRQ(ierr);
233424121865SAdrian Maldonado   ierr = PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection,&vDof);CHKERRQ(ierr);
233524121865SAdrian Maldonado 
233601ad2aeeSHong Zhang   ierr = MatCreate(comm, &j11);CHKERRQ(ierr);
233724121865SAdrian Maldonado   ierr = MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
233824121865SAdrian Maldonado   ierr = MatSetType(j11, MATMPIAIJ);CHKERRQ(ierr);
233924121865SAdrian Maldonado 
234001ad2aeeSHong Zhang   ierr = MatCreate(comm, &j12);CHKERRQ(ierr);
234124121865SAdrian Maldonado   ierr = MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE ,PETSC_DETERMINE);CHKERRQ(ierr);
234224121865SAdrian Maldonado   ierr = MatSetType(j12, MATMPIAIJ);CHKERRQ(ierr);
234324121865SAdrian Maldonado 
234401ad2aeeSHong Zhang   ierr = MatCreate(comm, &j21);CHKERRQ(ierr);
234524121865SAdrian Maldonado   ierr = MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
234624121865SAdrian Maldonado   ierr = MatSetType(j21, MATMPIAIJ);CHKERRQ(ierr);
234724121865SAdrian Maldonado 
234801ad2aeeSHong Zhang   ierr = MatCreate(comm, &j22);CHKERRQ(ierr);
234924121865SAdrian Maldonado   ierr = MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
235024121865SAdrian Maldonado   ierr = MatSetType(j22, MATMPIAIJ);CHKERRQ(ierr);
235124121865SAdrian Maldonado 
23523f6a6bdaSHong Zhang   bA[0][0] = j11;
23533f6a6bdaSHong Zhang   bA[0][1] = j12;
23543f6a6bdaSHong Zhang   bA[1][0] = j21;
23553f6a6bdaSHong Zhang   bA[1][1] = j22;
235624121865SAdrian Maldonado 
235724121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection,network->edge.DofSection,&eISMap);CHKERRQ(ierr);
235824121865SAdrian Maldonado   ierr = CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection,network->vertex.DofSection,&vISMap);CHKERRQ(ierr);
235924121865SAdrian Maldonado 
236024121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j11,eISMap,eISMap);CHKERRQ(ierr);
236124121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j12,eISMap,vISMap);CHKERRQ(ierr);
236224121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j21,vISMap,eISMap);CHKERRQ(ierr);
236324121865SAdrian Maldonado   ierr = MatSetLocalToGlobalMapping(j22,vISMap,vISMap);CHKERRQ(ierr);
236424121865SAdrian Maldonado 
236524121865SAdrian Maldonado   ierr = MatSetUp(j11);CHKERRQ(ierr);
236624121865SAdrian Maldonado   ierr = MatSetUp(j12);CHKERRQ(ierr);
236724121865SAdrian Maldonado   ierr = MatSetUp(j21);CHKERRQ(ierr);
236824121865SAdrian Maldonado   ierr = MatSetUp(j22);CHKERRQ(ierr);
236924121865SAdrian Maldonado 
237001ad2aeeSHong Zhang   ierr = MatCreateNest(comm,2,NULL,2,NULL,&bA[0][0],J);CHKERRQ(ierr);
237124121865SAdrian Maldonado   ierr = MatSetUp(*J);CHKERRQ(ierr);
237224121865SAdrian Maldonado   ierr = MatNestSetVecType(*J,VECNEST);CHKERRQ(ierr);
237324121865SAdrian Maldonado   ierr = MatDestroy(&j11);CHKERRQ(ierr);
237424121865SAdrian Maldonado   ierr = MatDestroy(&j12);CHKERRQ(ierr);
237524121865SAdrian Maldonado   ierr = MatDestroy(&j21);CHKERRQ(ierr);
237624121865SAdrian Maldonado   ierr = MatDestroy(&j22);CHKERRQ(ierr);
237724121865SAdrian Maldonado 
237824121865SAdrian Maldonado   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
237924121865SAdrian Maldonado   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23809e1d080bSHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
238124121865SAdrian Maldonado 
238224121865SAdrian Maldonado   /* Free structures */
238324121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&eISMap);CHKERRQ(ierr);
238424121865SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&vISMap);CHKERRQ(ierr);
238524121865SAdrian Maldonado   PetscFunctionReturn(0);
23869e1d080bSHong Zhang }
23879e1d080bSHong Zhang 
23889e1d080bSHong Zhang PetscErrorCode DMCreateMatrix_Network(DM dm,Mat *J)
23899e1d080bSHong Zhang {
23909e1d080bSHong Zhang   PetscErrorCode ierr;
23919e1d080bSHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
23929e1d080bSHong Zhang   PetscInt       eStart,eEnd,vStart,vEnd,rstart,nrows,*rows,localSize;
23939e1d080bSHong Zhang   PetscInt       cstart,ncols,j,e,v;
23949e1d080bSHong Zhang   PetscBool      ghost,ghost_vc,ghost2,isNest;
23959e1d080bSHong Zhang   Mat            Juser;
23969e1d080bSHong Zhang   PetscSection   sectionGlobal;
23979e1d080bSHong Zhang   PetscInt       nedges,*vptr=NULL,vc,*rows_v; /* suppress maybe-uninitialized warning */
23989e1d080bSHong Zhang   const PetscInt *edges,*cone;
23999e1d080bSHong Zhang   MPI_Comm       comm;
24009e1d080bSHong Zhang   MatType        mtype;
24019e1d080bSHong Zhang   Vec            vd_nz,vo_nz;
24029e1d080bSHong Zhang   PetscInt       *dnnz,*onnz;
24039e1d080bSHong Zhang   PetscScalar    *vdnz,*vonz;
24049e1d080bSHong Zhang 
24059e1d080bSHong Zhang   PetscFunctionBegin;
24069e1d080bSHong Zhang   mtype = dm->mattype;
24079e1d080bSHong Zhang   ierr = PetscStrcmp(mtype,MATNEST,&isNest);CHKERRQ(ierr);
24089e1d080bSHong Zhang   if (isNest) {
24099e1d080bSHong Zhang     ierr = DMCreateMatrix_Network_Nest(dm,J);CHKERRQ(ierr);
2410c6b011d8SStefano Zampini     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
24119e1d080bSHong Zhang     PetscFunctionReturn(0);
24129e1d080bSHong Zhang   }
24139e1d080bSHong Zhang 
24149e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
2415a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
24169e1d080bSHong Zhang     ierr = DMCreateMatrix_Plex(network->plex,J);CHKERRQ(ierr);
2417bfbc38dcSHong Zhang     ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
24181ad426b7SHong Zhang     PetscFunctionReturn(0);
24191ad426b7SHong Zhang   }
24201ad426b7SHong Zhang 
2421bfbc38dcSHong Zhang   ierr = MatCreate(PetscObjectComm((PetscObject)dm),J);CHKERRQ(ierr);
2422e87a4003SBarry Smith   ierr = DMGetGlobalSection(network->plex,&sectionGlobal);CHKERRQ(ierr);
2423bfbc38dcSHong Zhang   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal,&localSize);CHKERRQ(ierr);
2424bfbc38dcSHong Zhang   ierr = MatSetSizes(*J,localSize,localSize,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
24252a945128SHong Zhang 
24262a945128SHong Zhang   ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr);
24272a945128SHong Zhang   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
242889898e50SHong Zhang 
242989898e50SHong Zhang   /* (1) Set matrix preallocation */
243089898e50SHong Zhang   /*------------------------------*/
2431840c2264SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2432840c2264SHong Zhang   ierr = VecCreate(comm,&vd_nz);CHKERRQ(ierr);
2433840c2264SHong Zhang   ierr = VecSetSizes(vd_nz,localSize,PETSC_DECIDE);CHKERRQ(ierr);
2434840c2264SHong Zhang   ierr = VecSetFromOptions(vd_nz);CHKERRQ(ierr);
2435840c2264SHong Zhang   ierr = VecSet(vd_nz,0.0);CHKERRQ(ierr);
2436840c2264SHong Zhang   ierr = VecDuplicate(vd_nz,&vo_nz);CHKERRQ(ierr);
2437840c2264SHong Zhang 
243889898e50SHong Zhang   /* Set preallocation for edges */
243989898e50SHong Zhang   /*-----------------------------*/
2440840c2264SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&eStart,&eEnd);CHKERRQ(ierr);
2441840c2264SHong Zhang 
2442bdcb62a2SHong Zhang   ierr = PetscMalloc1(localSize,&rows);CHKERRQ(ierr);
2443840c2264SHong Zhang   for (e=eStart; e<eEnd; e++) {
2444840c2264SHong Zhang     /* Get row indices */
24452bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
24462bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
2447840c2264SHong Zhang     if (nrows) {
2448840c2264SHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
2449840c2264SHong Zhang 
2450a5b23f4aSJose E. Roman       /* Set preallocation for connected vertices */
2451d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2452840c2264SHong Zhang       for (v=0; v<2; v++) {
24532bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
2454840c2264SHong Zhang 
24558675203cSHong Zhang         if (network->Je) {
2456840c2264SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
24578675203cSHong Zhang         } else Juser = NULL;
2458840c2264SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,cone[v],&ghost);CHKERRQ(ierr);
24595cf7da58SHong Zhang         ierr = MatSetPreallocationblock_private(Juser,nrows,rows,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2460840c2264SHong Zhang       }
2461840c2264SHong Zhang 
246289898e50SHong Zhang       /* Set preallocation for edge self */
2463840c2264SHong Zhang       cstart = rstart;
24648675203cSHong Zhang       if (network->Je) {
2465840c2264SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
24668675203cSHong Zhang       } else Juser = NULL;
24675cf7da58SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2468840c2264SHong Zhang     }
2469840c2264SHong Zhang   }
2470840c2264SHong Zhang 
247189898e50SHong Zhang   /* Set preallocation for vertices */
247289898e50SHong Zhang   /*--------------------------------*/
2473840c2264SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vStart,&vEnd);CHKERRQ(ierr);
24748675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
2475840c2264SHong Zhang 
2476840c2264SHong Zhang   for (v=vStart; v<vEnd; v++) {
2477840c2264SHong Zhang     /* Get row indices */
24782bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
24792bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
2480840c2264SHong Zhang     if (!nrows) continue;
2481840c2264SHong Zhang 
2482bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2483bdcb62a2SHong Zhang     if (ghost) {
2484bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2485bdcb62a2SHong Zhang     } else {
2486bdcb62a2SHong Zhang       rows_v = rows;
2487bdcb62a2SHong Zhang     }
2488bdcb62a2SHong Zhang 
2489bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2490840c2264SHong Zhang 
2491840c2264SHong Zhang     /* Get supporting edges and connected vertices */
2492840c2264SHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2493840c2264SHong Zhang 
2494840c2264SHong Zhang     for (e=0; e<nedges; e++) {
2495840c2264SHong Zhang       /* Supporting edges */
24962bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
24972bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2498840c2264SHong Zhang 
24998675203cSHong Zhang       if (network->Jv) {
2500840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
25018675203cSHong Zhang       } else Juser = NULL;
2502bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost,vd_nz,vo_nz);CHKERRQ(ierr);
2503840c2264SHong Zhang 
2504840c2264SHong Zhang       /* Connected vertices */
2505d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
2506840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
2507840c2264SHong Zhang       ierr = DMNetworkIsGhostVertex(dm,vc,&ghost_vc);CHKERRQ(ierr);
2508840c2264SHong Zhang 
25092bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2510840c2264SHong Zhang 
25118675203cSHong Zhang       if (network->Jv) {
2512840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
25138675203cSHong Zhang       } else Juser = NULL;
2514e102a522SHong Zhang       if (ghost_vc||ghost) {
2515e102a522SHong Zhang         ghost2 = PETSC_TRUE;
2516e102a522SHong Zhang       } else {
2517e102a522SHong Zhang         ghost2 = PETSC_FALSE;
2518e102a522SHong Zhang       }
2519e102a522SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,ncols,ghost2,vd_nz,vo_nz);CHKERRQ(ierr);
2520840c2264SHong Zhang     }
2521840c2264SHong Zhang 
252289898e50SHong Zhang     /* Set preallocation for vertex self */
2523840c2264SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2524840c2264SHong Zhang     if (!ghost) {
25252bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25268675203cSHong Zhang       if (network->Jv) {
2527840c2264SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
25288675203cSHong Zhang       } else Juser = NULL;
2529bdcb62a2SHong Zhang       ierr = MatSetPreallocationblock_private(Juser,nrows,rows_v,nrows,PETSC_FALSE,vd_nz,vo_nz);CHKERRQ(ierr);
2530840c2264SHong Zhang     }
2531bdcb62a2SHong Zhang     if (ghost) {
2532bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2533bdcb62a2SHong Zhang     }
2534840c2264SHong Zhang   }
2535840c2264SHong Zhang 
2536840c2264SHong Zhang   ierr = VecAssemblyBegin(vd_nz);CHKERRQ(ierr);
2537840c2264SHong Zhang   ierr = VecAssemblyBegin(vo_nz);CHKERRQ(ierr);
25385cf7da58SHong Zhang 
25395cf7da58SHong Zhang   ierr = PetscMalloc2(localSize,&dnnz,localSize,&onnz);CHKERRQ(ierr);
25405cf7da58SHong Zhang 
25415cf7da58SHong Zhang   ierr = VecAssemblyEnd(vd_nz);CHKERRQ(ierr);
2542840c2264SHong Zhang   ierr = VecAssemblyEnd(vo_nz);CHKERRQ(ierr);
2543840c2264SHong Zhang 
2544840c2264SHong Zhang   ierr = VecGetArray(vd_nz,&vdnz);CHKERRQ(ierr);
2545840c2264SHong Zhang   ierr = VecGetArray(vo_nz,&vonz);CHKERRQ(ierr);
2546840c2264SHong Zhang   for (j=0; j<localSize; j++) {
2547e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
2548e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
2549840c2264SHong Zhang   }
2550840c2264SHong Zhang   ierr = VecRestoreArray(vd_nz,&vdnz);CHKERRQ(ierr);
2551840c2264SHong Zhang   ierr = VecRestoreArray(vo_nz,&vonz);CHKERRQ(ierr);
2552840c2264SHong Zhang   ierr = VecDestroy(&vd_nz);CHKERRQ(ierr);
2553840c2264SHong Zhang   ierr = VecDestroy(&vo_nz);CHKERRQ(ierr);
2554840c2264SHong Zhang 
25555cf7da58SHong Zhang   ierr = MatSeqAIJSetPreallocation(*J,0,dnnz);CHKERRQ(ierr);
25565cf7da58SHong Zhang   ierr = MatMPIAIJSetPreallocation(*J,0,dnnz,0,onnz);CHKERRQ(ierr);
25575cf7da58SHong Zhang   ierr = MatSetOption(*J,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
25585cf7da58SHong Zhang 
25595cf7da58SHong Zhang   ierr = PetscFree2(dnnz,onnz);CHKERRQ(ierr);
25605cf7da58SHong Zhang 
256189898e50SHong Zhang   /* (2) Set matrix entries for edges */
256289898e50SHong Zhang   /*----------------------------------*/
25631ad426b7SHong Zhang   for (e=eStart; e<eEnd; e++) {
2564bfbc38dcSHong Zhang     /* Get row indices */
25652bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,e,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
25662bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,e,&nrows);CHKERRQ(ierr);
25674b976069SHong Zhang     if (nrows) {
256817df6e9eSHong Zhang       for (j=0; j<nrows; j++) rows[j] = j + rstart;
25691ad426b7SHong Zhang 
2570a5b23f4aSJose E. Roman       /* Set matrix entries for connected vertices */
2571d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,e,&cone);CHKERRQ(ierr);
2572bfbc38dcSHong Zhang       for (v=0; v<2; v++) {
25732bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVecOffset(dm,cone[v],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
25742bf73ac6SHong Zhang         ierr = PetscSectionGetDof(network->DofSection,cone[v],&ncols);CHKERRQ(ierr);
25753e97b6e8SHong Zhang 
25768675203cSHong Zhang         if (network->Je) {
2577a4e85ca8SHong Zhang           Juser = network->Je[3*e+1+v]; /* Jacobian(e,v) */
25788675203cSHong Zhang         } else Juser = NULL;
2579a4e85ca8SHong Zhang         ierr = MatSetblock_private(Juser,nrows,rows,ncols,cstart,J);CHKERRQ(ierr);
2580bfbc38dcSHong Zhang       }
258117df6e9eSHong Zhang 
2582bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
25833e97b6e8SHong Zhang       cstart = rstart;
25848675203cSHong Zhang       if (network->Je) {
2585a4e85ca8SHong Zhang         Juser = network->Je[3*e]; /* Jacobian(e,e) */
25868675203cSHong Zhang       } else Juser = NULL;
2587a4e85ca8SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows,nrows,cstart,J);CHKERRQ(ierr);
25881ad426b7SHong Zhang     }
25894b976069SHong Zhang   }
25901ad426b7SHong Zhang 
2591bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
259283b2e829SHong Zhang   /*---------------------------------*/
25931ad426b7SHong Zhang   for (v=vStart; v<vEnd; v++) {
2594bfbc38dcSHong Zhang     /* Get row indices */
25952bf73ac6SHong Zhang     ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&rstart);CHKERRQ(ierr);
25962bf73ac6SHong Zhang     ierr = PetscSectionGetDof(network->DofSection,v,&nrows);CHKERRQ(ierr);
25974b976069SHong Zhang     if (!nrows) continue;
2598596e729fSHong Zhang 
2599bdcb62a2SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,v,&ghost);CHKERRQ(ierr);
2600bdcb62a2SHong Zhang     if (ghost) {
2601bdcb62a2SHong Zhang       ierr = PetscMalloc1(nrows,&rows_v);CHKERRQ(ierr);
2602bdcb62a2SHong Zhang     } else {
2603bdcb62a2SHong Zhang       rows_v = rows;
2604bdcb62a2SHong Zhang     }
2605bdcb62a2SHong Zhang     for (j=0; j<nrows; j++) rows_v[j] = j + rstart;
2606596e729fSHong Zhang 
2607bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
2608596e729fSHong Zhang     ierr = DMNetworkGetSupportingEdges(dm,v,&nedges,&edges);CHKERRQ(ierr);
2609596e729fSHong Zhang 
2610596e729fSHong Zhang     for (e=0; e<nedges; e++) {
2611bfbc38dcSHong Zhang       /* Supporting edges */
26122bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,edges[e],ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
26132bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,edges[e],&ncols);CHKERRQ(ierr);
2614596e729fSHong Zhang 
26158675203cSHong Zhang       if (network->Jv) {
2616a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+1]; /* Jacobian(v,e) */
26178675203cSHong Zhang       } else Juser = NULL;
2618bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2619596e729fSHong Zhang 
2620bfbc38dcSHong Zhang       /* Connected vertices */
2621d842c372SHong Zhang       ierr = DMNetworkGetConnectedVertices(dm,edges[e],&cone);CHKERRQ(ierr);
26222a945128SHong Zhang       vc = (v == cone[0]) ? cone[1]:cone[0];
26232a945128SHong Zhang 
26242bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,vc,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
26252bf73ac6SHong Zhang       ierr = PetscSectionGetDof(network->DofSection,vc,&ncols);CHKERRQ(ierr);
2626a4e85ca8SHong Zhang 
26278675203cSHong Zhang       if (network->Jv) {
2628a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]+2*e+2]; /* Jacobian(v,vc) */
26298675203cSHong Zhang       } else Juser = NULL;
2630bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,ncols,cstart,J);CHKERRQ(ierr);
2631596e729fSHong Zhang     }
2632596e729fSHong Zhang 
2633bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
26341ad426b7SHong Zhang     if (!ghost) {
26352bf73ac6SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,v,ALL_COMPONENTS,&cstart);CHKERRQ(ierr);
26368675203cSHong Zhang       if (network->Jv) {
2637a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v-vStart]]; /* Jacobian(v,v) */
26388675203cSHong Zhang       } else Juser = NULL;
2639bdcb62a2SHong Zhang       ierr = MatSetblock_private(Juser,nrows,rows_v,nrows,cstart,J);CHKERRQ(ierr);
2640bdcb62a2SHong Zhang     }
2641bdcb62a2SHong Zhang     if (ghost) {
2642bdcb62a2SHong Zhang       ierr = PetscFree(rows_v);CHKERRQ(ierr);
2643bdcb62a2SHong Zhang     }
26441ad426b7SHong Zhang   }
2645a4e85ca8SHong Zhang   ierr = PetscFree(rows);CHKERRQ(ierr);
2646bdcb62a2SHong Zhang 
26471ad426b7SHong Zhang   ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
26481ad426b7SHong Zhang   ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2649dd6f46cdSHong Zhang 
26505f2c45f1SShri Abhyankar   ierr = MatSetDM(*J,dm);CHKERRQ(ierr);
26515f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26525f2c45f1SShri Abhyankar }
26535f2c45f1SShri Abhyankar 
26545f2c45f1SShri Abhyankar PetscErrorCode DMDestroy_Network(DM dm)
26555f2c45f1SShri Abhyankar {
26565f2c45f1SShri Abhyankar   PetscErrorCode ierr;
26575f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
265854dfd506SHong Zhang   PetscInt       j,np;
26595f2c45f1SShri Abhyankar 
26605f2c45f1SShri Abhyankar   PetscFunctionBegin;
26618415c774SShri Abhyankar   if (--network->refct > 0) PetscFunctionReturn(0);
266283b2e829SHong Zhang   if (network->Je) {
266383b2e829SHong Zhang     ierr = PetscFree(network->Je);CHKERRQ(ierr);
266483b2e829SHong Zhang   }
266583b2e829SHong Zhang   if (network->Jv) {
2666883e35e8SHong Zhang     ierr = PetscFree(network->Jvptr);CHKERRQ(ierr);
266783b2e829SHong Zhang     ierr = PetscFree(network->Jv);CHKERRQ(ierr);
26681ad426b7SHong Zhang   }
266913c2a604SAdrian Maldonado 
267013c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->vertex.mapping);CHKERRQ(ierr);
267113c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.DofSection);CHKERRQ(ierr);
267213c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->vertex.GlobalDofSection);CHKERRQ(ierr);
2673f5427c60SHong Zhang   if (network->vltog) {
2674f5427c60SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
2675f5427c60SHong Zhang   }
267613c2a604SAdrian Maldonado   if (network->vertex.sf) {
267713c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->vertex.sf);CHKERRQ(ierr);
267813c2a604SAdrian Maldonado   }
267913c2a604SAdrian Maldonado   /* edge */
268013c2a604SAdrian Maldonado   ierr = ISLocalToGlobalMappingDestroy(&network->edge.mapping);CHKERRQ(ierr);
268113c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.DofSection);CHKERRQ(ierr);
268213c2a604SAdrian Maldonado   ierr = PetscSectionDestroy(&network->edge.GlobalDofSection);CHKERRQ(ierr);
268313c2a604SAdrian Maldonado   if (network->edge.sf) {
268413c2a604SAdrian Maldonado     ierr = PetscSFDestroy(&network->edge.sf);CHKERRQ(ierr);
268513c2a604SAdrian Maldonado   }
26865f2c45f1SShri Abhyankar   ierr = DMDestroy(&network->plex);CHKERRQ(ierr);
26875f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DataSection);CHKERRQ(ierr);
26885f2c45f1SShri Abhyankar   ierr = PetscSectionDestroy(&network->DofSection);CHKERRQ(ierr);
268983b2e829SHong Zhang 
26902bf73ac6SHong Zhang   for (j=0; j<network->Nsvtx; j++) {
26912bf73ac6SHong Zhang     ierr = PetscFree(network->svtx[j].sv);CHKERRQ(ierr);
26922bf73ac6SHong Zhang   }
26932bf73ac6SHong Zhang   if (network->svtx) {ierr = PetscFree(network->svtx);CHKERRQ(ierr);}
2694f11a936eSBarry Smith   ierr = PetscFree2(network->subnetedge,network->subnetvtx);CHKERRQ(ierr);
2695caf410d2SHong Zhang 
26962bf73ac6SHong Zhang   ierr = PetscTableDestroy(&network->svtable);CHKERRQ(ierr);
2697e2aaf10cSShri Abhyankar   ierr = PetscFree(network->subnet);CHKERRQ(ierr);
269854dfd506SHong Zhang   ierr = PetscFree(network->component);CHKERRQ(ierr);
26995f2c45f1SShri Abhyankar   ierr = PetscFree(network->componentdataarray);CHKERRQ(ierr);
270054dfd506SHong Zhang 
270154dfd506SHong Zhang   if (network->header) {
270254dfd506SHong Zhang     np = network->pEnd - network->pStart;
270354dfd506SHong Zhang     for (j=0; j < np; j++) {
270454dfd506SHong 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);
270554dfd506SHong Zhang       ierr = PetscFree(network->cvalue[j].data);CHKERRQ(ierr);
270654dfd506SHong Zhang     }
2707caf410d2SHong Zhang     ierr = PetscFree2(network->header,network->cvalue);CHKERRQ(ierr);
270854dfd506SHong Zhang   }
27095f2c45f1SShri Abhyankar   ierr = PetscFree(network);CHKERRQ(ierr);
27105f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27115f2c45f1SShri Abhyankar }
27125f2c45f1SShri Abhyankar 
27135f2c45f1SShri Abhyankar PetscErrorCode DMView_Network(DM dm,PetscViewer viewer)
27145f2c45f1SShri Abhyankar {
27155f2c45f1SShri Abhyankar   PetscErrorCode ierr;
2716caf410d2SHong Zhang   PetscBool      iascii;
2717caf410d2SHong Zhang   PetscMPIInt    rank;
27185f2c45f1SShri Abhyankar 
27195f2c45f1SShri Abhyankar   PetscFunctionBegin;
2720caf410d2SHong Zhang   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE,"Must call DMSetUp() first");
2721ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
2722caf410d2SHong Zhang   PetscValidHeaderSpecific(dm,DM_CLASSID, 1);
2723caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2724caf410d2SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2725caf410d2SHong Zhang   if (iascii) {
2726caf410d2SHong Zhang     const PetscInt *cone,*vtx,*edges;
27272bf73ac6SHong Zhang     PetscInt       vfrom,vto,i,j,nv,ne,ncv,p,nsubnet;
27282bf73ac6SHong Zhang     DM_Network     *network = (DM_Network*)dm->data;
2729caf410d2SHong Zhang 
27302bf73ac6SHong Zhang     nsubnet = network->Nsubnet; /* num of subnetworks */
27312bf73ac6SHong Zhang     if (!rank) {
27322bf73ac6SHong Zhang       ierr = PetscPrintf(PETSC_COMM_SELF,"  NSubnets: %D; NEdges: %D; NVertices: %D; NSharedVertices: %D.\n",nsubnet,network->NEdges,network->NVertices,network->Nsvtx);CHKERRQ(ierr);
27332bf73ac6SHong Zhang     }
27342bf73ac6SHong Zhang 
27352bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
2736caf410d2SHong Zhang     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
27372bf73ac6SHong Zhang     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nEdges: %D; nVertices: %D; nSharedVertices: %D\n",rank,network->nEdges,network->nVertices,ncv);CHKERRQ(ierr);
2738caf410d2SHong Zhang 
2739caf410d2SHong Zhang     for (i=0; i<nsubnet; i++) {
27402bf73ac6SHong Zhang       ierr = DMNetworkGetSubnetwork(dm,i,&nv,&ne,&vtx,&edges);CHKERRQ(ierr);
2741caf410d2SHong Zhang       if (ne) {
27422bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %D: nEdges %D, nVertices(include shared vertices) %D\n",i,ne,nv);CHKERRQ(ierr);
2743caf410d2SHong Zhang         for (j=0; j<ne; j++) {
2744caf410d2SHong Zhang           p = edges[j];
2745caf410d2SHong Zhang           ierr = DMNetworkGetConnectedVertices(dm,p,&cone);CHKERRQ(ierr);
2746caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[0],&vfrom);CHKERRQ(ierr);
2747caf410d2SHong Zhang           ierr = DMNetworkGetGlobalVertexIndex(dm,cone[1],&vto);CHKERRQ(ierr);
2748caf410d2SHong Zhang           ierr = DMNetworkGetGlobalEdgeIndex(dm,edges[j],&p);CHKERRQ(ierr);
2749caf410d2SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       edge %D: %D ----> %D\n",p,vfrom,vto);CHKERRQ(ierr);
2750caf410d2SHong Zhang         }
2751caf410d2SHong Zhang       }
2752caf410d2SHong Zhang     }
27532bf73ac6SHong Zhang 
27542bf73ac6SHong Zhang     /* Shared vertices */
27552bf73ac6SHong Zhang     ierr = DMNetworkGetSharedVertices(dm,&ncv,&vtx);CHKERRQ(ierr);
27562bf73ac6SHong Zhang     if (ncv) {
27572bf73ac6SHong Zhang       SVtx       *svtx = network->svtx;
27582bf73ac6SHong Zhang       PetscInt    gidx,svtx_idx,nvto,vfrom_net,vfrom_idx,*svto;
27592bf73ac6SHong Zhang       PetscBool   ghost;
27602bf73ac6SHong Zhang       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "     SharedVertices:\n");CHKERRQ(ierr);
27612bf73ac6SHong Zhang       for (i=0; i<ncv; i++) {
27622bf73ac6SHong Zhang         ierr = DMNetworkIsGhostVertex(dm,vtx[i],&ghost);CHKERRQ(ierr);
27632bf73ac6SHong Zhang         if (ghost) continue;
27642bf73ac6SHong Zhang 
27652bf73ac6SHong Zhang         ierr = DMNetworkGetGlobalVertexIndex(dm,vtx[i],&gidx);CHKERRQ(ierr);
27662bf73ac6SHong Zhang         ierr = PetscTableFind(network->svtable,gidx+1,&svtx_idx);CHKERRQ(ierr);
27672bf73ac6SHong Zhang         svtx_idx--;
27682bf73ac6SHong Zhang         nvto = svtx[svtx_idx].n;
27692bf73ac6SHong Zhang 
27702bf73ac6SHong Zhang         vfrom_net = svtx[svtx_idx].sv[0];
27712bf73ac6SHong Zhang         vfrom_idx = svtx[svtx_idx].sv[1];
27722bf73ac6SHong Zhang         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "       svtx %D: global index %D, subnet[%D].%D ---->\n",i,gidx,vfrom_net,vfrom_idx);CHKERRQ(ierr);
27732bf73ac6SHong Zhang         for (j=1; j<nvto; j++) {
27742bf73ac6SHong Zhang           svto = svtx[svtx_idx].sv + 2*j;
27752bf73ac6SHong Zhang           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "                                           ----> subnet[%D].%D\n",svto[0],svto[1]);CHKERRQ(ierr);
2776caf410d2SHong Zhang         }
2777caf410d2SHong Zhang       }
2778caf410d2SHong Zhang     }
2779caf410d2SHong Zhang     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2780caf410d2SHong Zhang     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
2781caf410d2SHong Zhang   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
27825f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27835f2c45f1SShri Abhyankar }
27845f2c45f1SShri Abhyankar 
27855f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
27865f2c45f1SShri Abhyankar {
27875f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27885f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27895f2c45f1SShri Abhyankar 
27905f2c45f1SShri Abhyankar   PetscFunctionBegin;
27915f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalBegin(network->plex,g,mode,l);CHKERRQ(ierr);
27925f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27935f2c45f1SShri Abhyankar }
27945f2c45f1SShri Abhyankar 
27955f2c45f1SShri Abhyankar PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
27965f2c45f1SShri Abhyankar {
27975f2c45f1SShri Abhyankar   PetscErrorCode ierr;
27985f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
27995f2c45f1SShri Abhyankar 
28005f2c45f1SShri Abhyankar   PetscFunctionBegin;
28015f2c45f1SShri Abhyankar   ierr = DMGlobalToLocalEnd(network->plex,g,mode,l);CHKERRQ(ierr);
28025f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28035f2c45f1SShri Abhyankar }
28045f2c45f1SShri Abhyankar 
28055f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
28065f2c45f1SShri Abhyankar {
28075f2c45f1SShri Abhyankar   PetscErrorCode ierr;
28085f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
28095f2c45f1SShri Abhyankar 
28105f2c45f1SShri Abhyankar   PetscFunctionBegin;
28115f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalBegin(network->plex,l,mode,g);CHKERRQ(ierr);
28125f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28135f2c45f1SShri Abhyankar }
28145f2c45f1SShri Abhyankar 
28155f2c45f1SShri Abhyankar PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
28165f2c45f1SShri Abhyankar {
28175f2c45f1SShri Abhyankar   PetscErrorCode ierr;
28185f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network*)dm->data;
28195f2c45f1SShri Abhyankar 
28205f2c45f1SShri Abhyankar   PetscFunctionBegin;
28215f2c45f1SShri Abhyankar   ierr = DMLocalToGlobalEnd(network->plex,l,mode,g);CHKERRQ(ierr);
28225f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
28235f2c45f1SShri Abhyankar }
282422bbedd7SHong Zhang 
282522bbedd7SHong Zhang /*@
282664238763SRodolfo Oliveira   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index
282722bbedd7SHong Zhang 
282822bbedd7SHong Zhang   Not collective
282922bbedd7SHong Zhang 
28307a7aea1fSJed Brown   Input Parameters:
283122bbedd7SHong Zhang + dm - the dm object
283222bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
283322bbedd7SHong Zhang 
28347a7aea1fSJed Brown   Output Parameters:
2835f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
283622bbedd7SHong Zhang 
283797bb938eSShri Abhyankar   Level: advanced
283822bbedd7SHong Zhang 
283922bbedd7SHong Zhang .seealso: DMNetworkSetVertexLocalToGlobalOrdering()
284022bbedd7SHong Zhang @*/
284122bbedd7SHong Zhang PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm,PetscInt vloc,PetscInt *vg)
284222bbedd7SHong Zhang {
284322bbedd7SHong Zhang   DM_Network  *network = (DM_Network*)dm->data;
284422bbedd7SHong Zhang   PetscInt    *vltog = network->vltog;
284522bbedd7SHong Zhang 
284622bbedd7SHong Zhang   PetscFunctionBegin;
284722bbedd7SHong Zhang   if (!vltog) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
284822bbedd7SHong Zhang   *vg = vltog[vloc];
284922bbedd7SHong Zhang   PetscFunctionReturn(0);
285022bbedd7SHong Zhang }
285122bbedd7SHong Zhang 
285222bbedd7SHong Zhang /*@
285364238763SRodolfo Oliveira   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map
285422bbedd7SHong Zhang 
285522bbedd7SHong Zhang   Collective
285622bbedd7SHong Zhang 
285722bbedd7SHong Zhang   Input Parameters:
2858f0fc11ceSJed Brown . dm - the dm object
285922bbedd7SHong Zhang 
286097bb938eSShri Abhyankar   Level: advanced
286122bbedd7SHong Zhang 
286263029d29SHong Zhang .seealso: DMNetworkGetGlobalVertexIndex()
286322bbedd7SHong Zhang @*/
286422bbedd7SHong Zhang PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
286522bbedd7SHong Zhang {
286622bbedd7SHong Zhang   PetscErrorCode    ierr;
286722bbedd7SHong Zhang   DM_Network        *network=(DM_Network*)dm->data;
286822bbedd7SHong Zhang   MPI_Comm          comm;
28692bf73ac6SHong Zhang   PetscMPIInt       rank,size,*displs=NULL,*recvcounts=NULL,remoterank;
287022bbedd7SHong Zhang   PetscBool         ghost;
287163029d29SHong Zhang   PetscInt          *vltog,nroots,nleaves,i,*vrange,k,N,lidx;
287222bbedd7SHong Zhang   const PetscSFNode *iremote;
287322bbedd7SHong Zhang   PetscSF           vsf;
287463029d29SHong Zhang   Vec               Vleaves,Vleaves_seq;
287563029d29SHong Zhang   VecScatter        ctx;
287663029d29SHong Zhang   PetscScalar       *varr,val;
287763029d29SHong Zhang   const PetscScalar *varr_read;
287822bbedd7SHong Zhang 
287922bbedd7SHong Zhang   PetscFunctionBegin;
288022bbedd7SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2881ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
2882ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
288322bbedd7SHong Zhang 
288422bbedd7SHong Zhang   if (size == 1) {
288522bbedd7SHong Zhang     nroots = network->vEnd - network->vStart;
288622bbedd7SHong Zhang     ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
288722bbedd7SHong Zhang     for (i=0; i<nroots; i++) vltog[i] = i;
288822bbedd7SHong Zhang     network->vltog = vltog;
288922bbedd7SHong Zhang     PetscFunctionReturn(0);
289022bbedd7SHong Zhang   }
289122bbedd7SHong Zhang 
289222bbedd7SHong Zhang   if (!network->distributecalled) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE,"Must call DMNetworkDistribute() first");
289322bbedd7SHong Zhang   if (network->vltog) {
289422bbedd7SHong Zhang     ierr = PetscFree(network->vltog);CHKERRQ(ierr);
289522bbedd7SHong Zhang   }
289622bbedd7SHong Zhang 
289722bbedd7SHong Zhang   ierr = DMNetworkSetSubMap_private(network->vStart,network->vEnd,&network->vertex.mapping);CHKERRQ(ierr);
289822bbedd7SHong Zhang   ierr = PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf);CHKERRQ(ierr);
289922bbedd7SHong Zhang   vsf = network->vertex.sf;
290022bbedd7SHong Zhang 
29012bf73ac6SHong Zhang   ierr = PetscMalloc3(size+1,&vrange,size,&displs,size,&recvcounts);CHKERRQ(ierr);
2902f5427c60SHong Zhang   ierr = PetscSFGetGraph(vsf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
290322bbedd7SHong Zhang 
290422bbedd7SHong Zhang   for (i=0; i<size; i++) { displs[i] = i; recvcounts[i] = 1;}
290522bbedd7SHong Zhang 
290622bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
290722bbedd7SHong Zhang   vrange[0] = 0;
2908ffc4695bSBarry Smith   ierr = MPI_Allgatherv(&i,1,MPIU_INT,vrange+1,recvcounts,displs,MPIU_INT,comm);CHKERRMPI(ierr);
290967dd800bSHong Zhang   for (i=2; i<size+1; i++) {vrange[i] += vrange[i-1];}
291022bbedd7SHong Zhang 
291122bbedd7SHong Zhang   ierr = PetscMalloc1(nroots, &vltog);CHKERRQ(ierr);
291222bbedd7SHong Zhang   network->vltog = vltog;
291322bbedd7SHong Zhang 
291463029d29SHong Zhang   /* Set vltog for non-ghost vertices */
291563029d29SHong Zhang   k = 0;
291622bbedd7SHong Zhang   for (i=0; i<nroots; i++) {
291722bbedd7SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
291863029d29SHong Zhang     if (ghost) continue;
291963029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
292022bbedd7SHong Zhang   }
2921f5427c60SHong Zhang   ierr = PetscFree3(vrange,displs,recvcounts);CHKERRQ(ierr);
292263029d29SHong Zhang 
292363029d29SHong Zhang   /* Set vltog for ghost vertices */
292463029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
292563029d29SHong Zhang   ierr = VecCreate(comm,&Vleaves);CHKERRQ(ierr);
292663029d29SHong Zhang   ierr = VecSetSizes(Vleaves,2*nleaves,PETSC_DETERMINE);CHKERRQ(ierr);
292763029d29SHong Zhang   ierr = VecSetFromOptions(Vleaves);CHKERRQ(ierr);
292863029d29SHong Zhang   ierr = VecGetArray(Vleaves,&varr);CHKERRQ(ierr);
292963029d29SHong Zhang   for (i=0; i<nleaves; i++) {
293063029d29SHong Zhang     varr[2*i]   = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
293163029d29SHong Zhang     varr[2*i+1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
293263029d29SHong Zhang   }
293363029d29SHong Zhang   ierr = VecRestoreArray(Vleaves,&varr);CHKERRQ(ierr);
293463029d29SHong Zhang 
293563029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
293663029d29SHong Zhang   ierr = VecScatterCreateToAll(Vleaves,&ctx,&Vleaves_seq);CHKERRQ(ierr);
293763029d29SHong Zhang   ierr = VecScatterBegin(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
293863029d29SHong Zhang   ierr = VecScatterEnd(ctx,Vleaves,Vleaves_seq,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
293963029d29SHong Zhang 
294063029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
294163029d29SHong Zhang   ierr = VecGetSize(Vleaves_seq,&N);CHKERRQ(ierr);
294263029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
294363029d29SHong Zhang   for (i=0; i<N; i+=2) {
29442e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
294563029d29SHong Zhang     if (remoterank == rank) {
294663029d29SHong Zhang       k = i+1; /* row number */
29472e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i+1]);
294863029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
294963029d29SHong Zhang       ierr = VecSetValues(Vleaves,1,&k,&val,INSERT_VALUES);CHKERRQ(ierr);
295063029d29SHong Zhang     }
295163029d29SHong Zhang   }
295263029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves_seq,&varr_read);CHKERRQ(ierr);
295363029d29SHong Zhang   ierr = VecAssemblyBegin(Vleaves);CHKERRQ(ierr);
295463029d29SHong Zhang   ierr = VecAssemblyEnd(Vleaves);CHKERRQ(ierr);
295563029d29SHong Zhang 
295663029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
295763029d29SHong Zhang   ierr = VecGetArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
295863029d29SHong Zhang   k = 0;
295963029d29SHong Zhang   for (i=0; i<nroots; i++) {
296063029d29SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,i+network->vStart,&ghost);CHKERRQ(ierr);
296163029d29SHong Zhang     if (!ghost) continue;
29622e4cff2eSHong Zhang     vltog[i] = (PetscInt)PetscRealPart(varr_read[2*k+1]); k++;
296363029d29SHong Zhang   }
296463029d29SHong Zhang   ierr = VecRestoreArrayRead(Vleaves,&varr_read);CHKERRQ(ierr);
296563029d29SHong Zhang 
296663029d29SHong Zhang   ierr = VecDestroy(&Vleaves);CHKERRQ(ierr);
296763029d29SHong Zhang   ierr = VecDestroy(&Vleaves_seq);CHKERRQ(ierr);
296863029d29SHong Zhang   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
296922bbedd7SHong Zhang   PetscFunctionReturn(0);
297022bbedd7SHong Zhang }
297142dc13f1SHong Zhang 
297242dc13f1SHong Zhang PETSC_STATIC_INLINE PetscErrorCode DMISAddSize_private(DM_Network *network,PetscInt p,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *nidx)
297342dc13f1SHong Zhang {
297442dc13f1SHong Zhang   PetscErrorCode           ierr;
297542dc13f1SHong Zhang   PetscInt                 i,j,ncomps,nvar,key,offset=0;
297642dc13f1SHong Zhang   DMNetworkComponentHeader header;
297742dc13f1SHong Zhang 
297842dc13f1SHong Zhang   PetscFunctionBegin;
297942dc13f1SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
298042dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
298142dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
298242dc13f1SHong Zhang 
298342dc13f1SHong Zhang   for (i=0; i<ncomps; i++) {
298442dc13f1SHong Zhang     key  = header->key[i];
298542dc13f1SHong Zhang     nvar = header->nvar[i];
298642dc13f1SHong Zhang     for (j=0; j<numkeys; j++) {
298742dc13f1SHong Zhang       if (key == keys[j]) {
298842dc13f1SHong Zhang         if (!blocksize || blocksize[j] == -1) {
298942dc13f1SHong Zhang           *nidx += nvar;
299042dc13f1SHong Zhang         } else {
299142dc13f1SHong Zhang           *nidx += nselectedvar[j]*nvar/blocksize[j];
299242dc13f1SHong Zhang         }
299342dc13f1SHong Zhang       }
299442dc13f1SHong Zhang     }
299542dc13f1SHong Zhang   }
299642dc13f1SHong Zhang   PetscFunctionReturn(0);
299742dc13f1SHong Zhang }
299842dc13f1SHong Zhang 
299942dc13f1SHong 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)
300042dc13f1SHong Zhang {
300142dc13f1SHong Zhang   PetscErrorCode           ierr;
300242dc13f1SHong Zhang   PetscInt                 i,j,ncomps,nvar,key,offsetg,k,k1,offset=0;
300342dc13f1SHong Zhang   DM_Network               *network = (DM_Network*)dm->data;
300442dc13f1SHong Zhang   DMNetworkComponentHeader header;
300542dc13f1SHong Zhang 
300642dc13f1SHong Zhang   PetscFunctionBegin;
300742dc13f1SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
300842dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
300942dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
301042dc13f1SHong Zhang 
301142dc13f1SHong Zhang   for (i=0; i<ncomps; i++) {
301242dc13f1SHong Zhang     key  = header->key[i];
301342dc13f1SHong Zhang     nvar = header->nvar[i];
301442dc13f1SHong Zhang     for (j=0; j<numkeys; j++) {
301542dc13f1SHong Zhang       if (key != keys[j]) continue;
301642dc13f1SHong Zhang 
301742dc13f1SHong Zhang       ierr = DMNetworkGetGlobalVecOffset(dm,p,i,&offsetg);CHKERRQ(ierr);
301842dc13f1SHong Zhang       if (!blocksize || blocksize[j] == -1) {
301942dc13f1SHong Zhang         for (k=0; k<nvar; k++) idx[(*ii)++] = offsetg + k;
302042dc13f1SHong Zhang       } else {
302142dc13f1SHong Zhang         for (k=0; k<nvar; k+=blocksize[j]) {
302242dc13f1SHong Zhang           for (k1=0; k1<nselectedvar[j]; k1++) idx[(*ii)++] = offsetg + k + selectedvar[j][k1];
302342dc13f1SHong Zhang         }
302442dc13f1SHong Zhang       }
302542dc13f1SHong Zhang     }
302642dc13f1SHong Zhang   }
302742dc13f1SHong Zhang   PetscFunctionReturn(0);
302842dc13f1SHong Zhang }
302942dc13f1SHong Zhang 
303042dc13f1SHong Zhang /*@
303142dc13f1SHong Zhang   DMNetworkCreateIS - Create an index set object from the global vector of the network
303242dc13f1SHong Zhang 
303342dc13f1SHong Zhang   Collective
303442dc13f1SHong Zhang 
303542dc13f1SHong Zhang   Input Parameters:
303642dc13f1SHong Zhang + dm - DMNetwork object
303742dc13f1SHong Zhang . numkeys - number of keys
303842dc13f1SHong Zhang . keys - array of keys that define the components of the variables you wish to extract
303942dc13f1SHong Zhang . blocksize - block size of the variables associated to the component
304042dc13f1SHong Zhang . nselectedvar - number of variables in each block to select
304142dc13f1SHong Zhang - selectedvar - the offset into the block of each variable in each block to select
304242dc13f1SHong Zhang 
304342dc13f1SHong Zhang   Output Parameters:
304442dc13f1SHong Zhang . is - the index set
304542dc13f1SHong Zhang 
304642dc13f1SHong Zhang   Level: Advanced
304742dc13f1SHong Zhang 
304842dc13f1SHong Zhang   Notes:
304942dc13f1SHong 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.
305042dc13f1SHong Zhang 
305142dc13f1SHong Zhang .seealso: DMNetworkCreate(), ISCreateGeneral(), DMNetworkCreateLocalIS()
305242dc13f1SHong Zhang @*/
305342dc13f1SHong Zhang PetscErrorCode DMNetworkCreateIS(DM dm,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],IS *is)
305442dc13f1SHong Zhang {
305542dc13f1SHong Zhang   PetscErrorCode ierr;
305642dc13f1SHong Zhang   MPI_Comm       comm;
305742dc13f1SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
305842dc13f1SHong Zhang   PetscInt       i,p,estart,eend,vstart,vend,nidx,*idx;
305942dc13f1SHong Zhang   PetscBool      ghost;
306042dc13f1SHong Zhang 
306142dc13f1SHong Zhang   PetscFunctionBegin;
306242dc13f1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
306342dc13f1SHong Zhang 
306442dc13f1SHong Zhang   /* Check input parameters */
306542dc13f1SHong Zhang   for (i=0; i<numkeys; i++) {
306642dc13f1SHong Zhang     if (!blocksize || blocksize[i] == -1) continue;
306742dc13f1SHong 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]);
306842dc13f1SHong Zhang   }
306942dc13f1SHong Zhang 
307042dc13f1SHong Zhang   ierr = DMNetworkGetEdgeRange(dm,&estart,&eend);CHKERRQ(ierr);
307142dc13f1SHong Zhang   ierr = DMNetworkGetVertexRange(dm,&vstart,&vend);CHKERRQ(ierr);
307242dc13f1SHong Zhang 
307342dc13f1SHong Zhang   /* Get local number of idx */
307442dc13f1SHong Zhang   nidx = 0;
307542dc13f1SHong Zhang   for (p=estart; p<eend; p++) {
307642dc13f1SHong Zhang     ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr);
307742dc13f1SHong Zhang   }
307842dc13f1SHong Zhang   for (p=vstart; p<vend; p++) {
307942dc13f1SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
308042dc13f1SHong Zhang     if (ghost) continue;
308142dc13f1SHong Zhang     ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr);
308242dc13f1SHong Zhang   }
308342dc13f1SHong Zhang 
308442dc13f1SHong Zhang   /* Compute idx */
308542dc13f1SHong Zhang   ierr = PetscMalloc1(nidx,&idx);CHKERRQ(ierr);
308642dc13f1SHong Zhang   i = 0;
308742dc13f1SHong Zhang   for (p=estart; p<eend; p++) {
308842dc13f1SHong Zhang     ierr = DMISComputeIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr);
308942dc13f1SHong Zhang   }
309042dc13f1SHong Zhang   for (p=vstart; p<vend; p++) {
309142dc13f1SHong Zhang     ierr = DMNetworkIsGhostVertex(dm,p,&ghost);CHKERRQ(ierr);
309242dc13f1SHong Zhang     if (ghost) continue;
309342dc13f1SHong Zhang     ierr = DMISComputeIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr);
309442dc13f1SHong Zhang   }
309542dc13f1SHong Zhang 
309642dc13f1SHong Zhang   /* Create is */
309742dc13f1SHong Zhang   ierr = ISCreateGeneral(comm,nidx,idx,PETSC_COPY_VALUES,is);CHKERRQ(ierr);
309842dc13f1SHong Zhang   ierr = PetscFree(idx);CHKERRQ(ierr);
309942dc13f1SHong Zhang   PetscFunctionReturn(0);
310042dc13f1SHong Zhang }
310142dc13f1SHong Zhang 
310242dc13f1SHong 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)
310342dc13f1SHong Zhang {
310442dc13f1SHong Zhang   PetscErrorCode           ierr;
310542dc13f1SHong Zhang   PetscInt                 i,j,ncomps,nvar,key,offsetl,k,k1,offset=0;
310642dc13f1SHong Zhang   DM_Network               *network = (DM_Network*)dm->data;
310742dc13f1SHong Zhang   DMNetworkComponentHeader header;
310842dc13f1SHong Zhang 
310942dc13f1SHong Zhang   PetscFunctionBegin;
311042dc13f1SHong Zhang   ierr = PetscSectionGetOffset(network->DataSection,p,&offset);CHKERRQ(ierr);
311142dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray+offset))->ndata;
311242dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray+offset);
311342dc13f1SHong Zhang 
311442dc13f1SHong Zhang   for (i=0; i<ncomps; i++) {
311542dc13f1SHong Zhang     key  = header->key[i];
311642dc13f1SHong Zhang     nvar = header->nvar[i];
311742dc13f1SHong Zhang     for (j=0; j<numkeys; j++) {
311842dc13f1SHong Zhang       if (key != keys[j]) continue;
311942dc13f1SHong Zhang 
312042dc13f1SHong Zhang       ierr = DMNetworkGetLocalVecOffset(dm,p,i,&offsetl);CHKERRQ(ierr);
312142dc13f1SHong Zhang       if (!blocksize || blocksize[j] == -1) {
312242dc13f1SHong Zhang         for (k=0; k<nvar; k++) idx[(*ii)++] = offsetl + k;
312342dc13f1SHong Zhang       } else {
312442dc13f1SHong Zhang         for (k=0; k<nvar; k+=blocksize[j]) {
312542dc13f1SHong Zhang           for (k1=0; k1<nselectedvar[j]; k1++) idx[(*ii)++] = offsetl + k + selectedvar[j][k1];
312642dc13f1SHong Zhang         }
312742dc13f1SHong Zhang       }
312842dc13f1SHong Zhang     }
312942dc13f1SHong Zhang   }
313042dc13f1SHong Zhang   PetscFunctionReturn(0);
313142dc13f1SHong Zhang }
313242dc13f1SHong Zhang 
313342dc13f1SHong Zhang /*@
313442dc13f1SHong Zhang   DMNetworkCreateLocalIS - Create an index set object from the local vector of the network
313542dc13f1SHong Zhang 
313642dc13f1SHong Zhang   Not collective
313742dc13f1SHong Zhang 
313842dc13f1SHong Zhang   Input Parameters:
313942dc13f1SHong Zhang + dm - DMNetwork object
314042dc13f1SHong Zhang . numkeys - number of keys
314142dc13f1SHong Zhang . keys - array of keys that define the components of the variables you wish to extract
314242dc13f1SHong Zhang . blocksize - block size of the variables associated to the component
314342dc13f1SHong Zhang . nselectedvar - number of variables in each block to select
314442dc13f1SHong Zhang - selectedvar - the offset into the block of each variable in each block to select
314542dc13f1SHong Zhang 
314642dc13f1SHong Zhang   Output Parameters:
314742dc13f1SHong Zhang . is - the index set
314842dc13f1SHong Zhang 
314942dc13f1SHong Zhang   Level: Advanced
315042dc13f1SHong Zhang 
315142dc13f1SHong Zhang   Notes:
315242dc13f1SHong 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.
315342dc13f1SHong Zhang 
315442dc13f1SHong Zhang .seealso: DMNetworkCreate(), DMNetworkCreateIS, ISCreateGeneral()
315542dc13f1SHong Zhang @*/
315642dc13f1SHong Zhang PetscErrorCode DMNetworkCreateLocalIS(DM dm,PetscInt numkeys,PetscInt keys[],PetscInt blocksize[],PetscInt nselectedvar[],PetscInt *selectedvar[],IS *is)
315742dc13f1SHong Zhang {
315842dc13f1SHong Zhang   PetscErrorCode ierr;
315942dc13f1SHong Zhang   DM_Network     *network = (DM_Network*)dm->data;
316042dc13f1SHong Zhang   PetscInt       i,p,pstart,pend,nidx,*idx;
316142dc13f1SHong Zhang 
316242dc13f1SHong Zhang   PetscFunctionBegin;
316342dc13f1SHong Zhang   /* Check input parameters */
316442dc13f1SHong Zhang   for (i=0; i<numkeys; i++) {
316542dc13f1SHong Zhang     if (!blocksize || blocksize[i] == -1) continue;
316642dc13f1SHong 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]);
316742dc13f1SHong Zhang   }
316842dc13f1SHong Zhang 
316942dc13f1SHong Zhang   pstart = network->pStart;
317042dc13f1SHong Zhang   pend   = network->pEnd;
317142dc13f1SHong Zhang 
317242dc13f1SHong Zhang   /* Get local number of idx */
317342dc13f1SHong Zhang   nidx = 0;
317442dc13f1SHong Zhang   for (p=pstart; p<pend; p++) {
317542dc13f1SHong Zhang     ierr = DMISAddSize_private(network,p,numkeys,keys,blocksize,nselectedvar,&nidx);CHKERRQ(ierr);
317642dc13f1SHong Zhang   }
317742dc13f1SHong Zhang 
317842dc13f1SHong Zhang   /* Compute local idx */
317942dc13f1SHong Zhang   ierr = PetscMalloc1(nidx,&idx);CHKERRQ(ierr);
318042dc13f1SHong Zhang   i = 0;
318142dc13f1SHong Zhang   for (p=pstart; p<pend; p++) {
318242dc13f1SHong Zhang     ierr = DMISComputeLocalIdx_private(dm,p,numkeys,keys,blocksize,nselectedvar,selectedvar,&i,idx);CHKERRQ(ierr);
318342dc13f1SHong Zhang   }
318442dc13f1SHong Zhang 
318542dc13f1SHong Zhang   /* Create is */
318642dc13f1SHong Zhang   ierr = ISCreateGeneral(PETSC_COMM_SELF,nidx,idx,PETSC_COPY_VALUES,is);CHKERRQ(ierr);
318742dc13f1SHong Zhang   ierr = PetscFree(idx);CHKERRQ(ierr);
318842dc13f1SHong Zhang   PetscFunctionReturn(0);
318942dc13f1SHong Zhang }
3190