xref: /petsc/src/dm/impls/network/network.c (revision 35cb6cd333087cc89d8d5031932d4f38af02614d)
1af0996ceSBarry Smith #include <petsc/private/dmnetworkimpl.h> /*I  "petscdmnetwork.h"  I*/
25f2c45f1SShri Abhyankar 
3e3b1a053SGetnet Betrie PetscLogEvent DMNetwork_LayoutSetUp;
4e3b1a053SGetnet Betrie PetscLogEvent DMNetwork_SetUpNetwork;
5e3b1a053SGetnet Betrie PetscLogEvent DMNetwork_Distribute;
6e3b1a053SGetnet Betrie 
754dfd506SHong Zhang /*
854dfd506SHong Zhang   Creates the component header and value objects for a network point
954dfd506SHong Zhang */
10d71ae5a4SJacob Faibussowitsch static PetscErrorCode SetUpNetworkHeaderComponentValue(DM dm, DMNetworkComponentHeader header, DMNetworkComponentValue cvalue)
11d71ae5a4SJacob Faibussowitsch {
1254dfd506SHong Zhang   PetscFunctionBegin;
1354dfd506SHong Zhang   /* Allocate arrays for component information */
149566063dSJacob Faibussowitsch   PetscCall(PetscCalloc5(header->maxcomps, &header->size, header->maxcomps, &header->key, header->maxcomps, &header->offset, header->maxcomps, &header->nvar, header->maxcomps, &header->offsetvarrel));
159566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(header->maxcomps, &cvalue->data));
1654dfd506SHong Zhang 
1754dfd506SHong 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.
1854dfd506SHong Zhang    If the data header struct changes then this header size calculation needs to be updated. */
1954dfd506SHong Zhang   header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5 * header->maxcomps * sizeof(PetscInt);
2054dfd506SHong Zhang   header->hsize /= sizeof(DMNetworkComponentGenericDataType);
2154dfd506SHong Zhang   PetscFunctionReturn(0);
2254dfd506SHong Zhang }
2354dfd506SHong Zhang 
24d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkInitializeHeaderComponentData(DM dm)
25d71ae5a4SJacob Faibussowitsch {
26daad07d3SAidan Hamilton   DM_Network *network = (DM_Network *)dm->data;
27daad07d3SAidan Hamilton   PetscInt    np, p, defaultnumcomp = DMNETWORK_MAX_COMP_AT_POINT_DEFAULT;
28daad07d3SAidan Hamilton 
29daad07d3SAidan Hamilton   PetscFunctionBegin;
30daad07d3SAidan Hamilton   np = network->cloneshared->pEnd - network->cloneshared->pStart;
31daad07d3SAidan Hamilton   if (network->header)
32daad07d3SAidan Hamilton     for (p = 0; p < np; p++) {
33daad07d3SAidan Hamilton       network->header[p].maxcomps = defaultnumcomp;
34daad07d3SAidan Hamilton       PetscCall(SetUpNetworkHeaderComponentValue(dm, &network->header[p], &network->cvalue[p]));
35daad07d3SAidan Hamilton     }
36daad07d3SAidan Hamilton 
37daad07d3SAidan Hamilton   PetscFunctionReturn(0);
38daad07d3SAidan Hamilton }
395f2c45f1SShri Abhyankar /*@
40556ed216SShri Abhyankar   DMNetworkGetPlex - Gets the Plex DM associated with this network DM
41556ed216SShri Abhyankar 
42556ed216SShri Abhyankar   Not collective
43556ed216SShri Abhyankar 
44556ed216SShri Abhyankar   Input Parameters:
452bf73ac6SHong Zhang . dm - the dm object
462bf73ac6SHong Zhang 
472bf73ac6SHong Zhang   Output Parameters:
482bf73ac6SHong Zhang . plexdm - the plex dm object
49556ed216SShri Abhyankar 
50556ed216SShri Abhyankar   Level: Advanced
51556ed216SShri Abhyankar 
52db781477SPatrick Sanan .seealso: `DMNetworkCreate()`
53556ed216SShri Abhyankar @*/
54d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetPlex(DM dm, DM *plexdm)
55d71ae5a4SJacob Faibussowitsch {
562bf73ac6SHong Zhang   DM_Network *network = (DM_Network *)dm->data;
57556ed216SShri Abhyankar 
58556ed216SShri Abhyankar   PetscFunctionBegin;
59556ed216SShri Abhyankar   *plexdm = network->plex;
60556ed216SShri Abhyankar   PetscFunctionReturn(0);
61556ed216SShri Abhyankar }
62556ed216SShri Abhyankar 
63556ed216SShri Abhyankar /*@
642bf73ac6SHong Zhang   DMNetworkGetNumSubNetworks - Gets the the number of subnetworks
6572c3e9f7SHong Zhang 
662bf73ac6SHong Zhang   Not collective
6772c3e9f7SHong Zhang 
68f899ff85SJose E. Roman   Input Parameter:
692bf73ac6SHong Zhang . dm - the dm object
702bf73ac6SHong Zhang 
712bf73ac6SHong Zhang   Output Parameters:
722bf73ac6SHong Zhang + nsubnet - local number of subnetworks
732bf73ac6SHong Zhang - Nsubnet - global number of subnetworks
7472c3e9f7SHong Zhang 
7597bb938eSShri Abhyankar   Level: beginner
7672c3e9f7SHong Zhang 
77db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `DMNetworkSetNumSubNetworks()`
7872c3e9f7SHong Zhang @*/
79d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetNumSubNetworks(DM dm, PetscInt *nsubnet, PetscInt *Nsubnet)
80d71ae5a4SJacob Faibussowitsch {
812bf73ac6SHong Zhang   DM_Network *network = (DM_Network *)dm->data;
8272c3e9f7SHong Zhang 
8372c3e9f7SHong Zhang   PetscFunctionBegin;
84daad07d3SAidan Hamilton   if (nsubnet) *nsubnet = network->cloneshared->nsubnet;
85daad07d3SAidan Hamilton   if (Nsubnet) *Nsubnet = network->cloneshared->Nsubnet;
8672c3e9f7SHong Zhang   PetscFunctionReturn(0);
8772c3e9f7SHong Zhang }
8872c3e9f7SHong Zhang 
8972c3e9f7SHong Zhang /*@
902bf73ac6SHong Zhang   DMNetworkSetNumSubNetworks - Sets the number of subnetworks
915f2c45f1SShri Abhyankar 
92d083f849SBarry Smith   Collective on dm
935f2c45f1SShri Abhyankar 
945f2c45f1SShri Abhyankar   Input Parameters:
955f2c45f1SShri Abhyankar + dm - the dm object
962bf73ac6SHong Zhang . nsubnet - local number of subnetworks
972bf73ac6SHong Zhang - Nsubnet - global number of subnetworks
985f2c45f1SShri Abhyankar 
9997bb938eSShri Abhyankar    Level: beginner
1001b266c99SBarry Smith 
101db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `DMNetworkGetNumSubNetworks()`
1025f2c45f1SShri Abhyankar @*/
103d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkSetNumSubNetworks(DM dm, PetscInt nsubnet, PetscInt Nsubnet)
104d71ae5a4SJacob Faibussowitsch {
1055f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
1065f2c45f1SShri Abhyankar 
1075f2c45f1SShri Abhyankar   PetscFunctionBegin;
108d5b43468SJose E. Roman   PetscCheck(network->cloneshared->Nsubnet == 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Network sizes already set, cannot resize the network");
1092bf73ac6SHong Zhang 
1105f2c45f1SShri Abhyankar   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1112bf73ac6SHong Zhang   PetscValidLogicalCollectiveInt(dm, nsubnet, 2);
1122bf73ac6SHong Zhang   PetscValidLogicalCollectiveInt(dm, Nsubnet, 3);
1137765340cSHong Zhang 
1142bf73ac6SHong Zhang   if (Nsubnet == PETSC_DECIDE) {
1155c6496baSHong Zhang     PetscCheck(nsubnet >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of local subnetworks %" PetscInt_FMT " cannot be less than 0", nsubnet);
1161c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&nsubnet, &Nsubnet, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
117caf410d2SHong Zhang   }
1185c6496baSHong Zhang   PetscCheck(Nsubnet >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Number of global subnetworks %" PetscInt_FMT " cannot be less than 1", Nsubnet);
119caf410d2SHong Zhang 
120daad07d3SAidan Hamilton   network->cloneshared->Nsubnet = Nsubnet;
121daad07d3SAidan Hamilton   network->cloneshared->nsubnet = 0; /* initial value; will be determind by DMNetworkAddSubnetwork() */
122daad07d3SAidan Hamilton   PetscCall(PetscCalloc1(Nsubnet, &network->cloneshared->subnet));
123caf410d2SHong Zhang 
1242bf73ac6SHong Zhang   /* num of shared vertices */
125daad07d3SAidan Hamilton   network->cloneshared->nsvtx = 0;
126daad07d3SAidan Hamilton   network->cloneshared->Nsvtx = 0;
1277765340cSHong Zhang   PetscFunctionReturn(0);
1287765340cSHong Zhang }
1297765340cSHong Zhang 
1305f2c45f1SShri Abhyankar /*@
1312bf73ac6SHong Zhang   DMNetworkAddSubnetwork - Add a subnetwork
1325f2c45f1SShri Abhyankar 
1332bf73ac6SHong Zhang   Collective on dm
1345f2c45f1SShri Abhyankar 
1355f2c45f1SShri Abhyankar   Input Parameters:
136e3e68989SHong Zhang + dm - the dm object
1372bf73ac6SHong Zhang . name - name of the subnetwork
1382bf73ac6SHong Zhang . ne - number of local edges of this subnetwork
1398d1cd658SBarry Smith - edgelist - list of edges for this subnetwork, this is a one dimensional array with pairs of entries being the two vertices (in global numbering of the vertices) of each edge,
1408d1cd658SBarry Smith $            [first vertex of first edge, second vertex of first edge, first vertex of second edge, second vertex of second edge, etc]
1412bf73ac6SHong Zhang 
1422bf73ac6SHong Zhang   Output Parameters:
1432bf73ac6SHong Zhang . netnum - global index of the subnetwork
1445f2c45f1SShri Abhyankar 
1455f2c45f1SShri Abhyankar   Notes:
1465f2c45f1SShri Abhyankar   There is no copy involved in this operation, only the pointer is referenced. The edgelist should
1472bf73ac6SHong Zhang   not be destroyed before the call to DMNetworkLayoutSetUp()
1485f2c45f1SShri Abhyankar 
1498d1cd658SBarry 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,
1508d1cd658SBarry Smith   each subnetwork topology needs to be set on a unique rank and the communicator size needs to be at least equal to the number of subnetworks.
151f11a936eSBarry Smith 
15297bb938eSShri Abhyankar   Level: beginner
1535f2c45f1SShri Abhyankar 
154e3e68989SHong Zhang   Example usage:
155f11a936eSBarry Smith   Consider the following networks:
156d5b43468SJose E. Roman   1) A single subnetwork:
157e3e68989SHong Zhang .vb
158f11a936eSBarry Smith  network 0:
159f11a936eSBarry Smith  rank[0]:
160f11a936eSBarry Smith    v0 --> v2; v1 --> v2
161f11a936eSBarry Smith  rank[1]:
162f11a936eSBarry Smith    v3 --> v5; v4 --> v5
163e3e68989SHong Zhang .ve
164e3e68989SHong Zhang 
165e3e68989SHong Zhang  The resulting input
166f11a936eSBarry Smith  network 0:
167f11a936eSBarry Smith  rank[0]:
168f11a936eSBarry Smith    ne = 2
169f11a936eSBarry Smith    edgelist = [0 2 | 1 2]
170f11a936eSBarry Smith  rank[1]:
171f11a936eSBarry Smith    ne = 2
172f11a936eSBarry Smith    edgelist = [3 5 | 4 5]
173f11a936eSBarry Smith 
174f11a936eSBarry Smith   2) Two subnetworks:
175f11a936eSBarry Smith .vb
176f11a936eSBarry Smith  subnetwork 0:
177f11a936eSBarry Smith  rank[0]:
178f11a936eSBarry Smith    v0 --> v2; v2 --> v1; v1 --> v3;
179f11a936eSBarry Smith  subnetwork 1:
180f11a936eSBarry Smith  rank[1]:
181f11a936eSBarry Smith    v0 --> v3; v3 --> v2; v2 --> v1;
182f11a936eSBarry Smith .ve
183f11a936eSBarry Smith 
184f11a936eSBarry Smith  The resulting input
185f11a936eSBarry Smith  subnetwork 0:
186f11a936eSBarry Smith  rank[0]:
187f11a936eSBarry Smith    ne = 3
188f11a936eSBarry Smith    edgelist = [0 2 | 2 1 | 1 3]
189f11a936eSBarry Smith  rank[1]:
190f11a936eSBarry Smith    ne = 0
191f11a936eSBarry Smith    edgelist = NULL
192f11a936eSBarry Smith 
193f11a936eSBarry Smith  subnetwork 1:
194f11a936eSBarry Smith  rank[0]:
195f11a936eSBarry Smith    ne = 0
196f11a936eSBarry Smith    edgelist = NULL
197f11a936eSBarry Smith  rank[1]:
198f11a936eSBarry Smith    edgelist = [0 3 | 3 2 | 2 1]
199e3e68989SHong Zhang 
200db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `DMNetworkSetNumSubnetworks()`
2015f2c45f1SShri Abhyankar @*/
202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkAddSubnetwork(DM dm, const char *name, PetscInt ne, PetscInt edgelist[], PetscInt *netnum)
203d71ae5a4SJacob Faibussowitsch {
2045f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
2055c6496baSHong Zhang   PetscInt    i, Nedge, j, Nvtx, nvtx, nvtx_min = -1, nvtx_max = 0;
206f11a936eSBarry Smith   PetscBT     table;
2075f2c45f1SShri Abhyankar 
2085f2c45f1SShri Abhyankar   PetscFunctionBegin;
209ad540459SPierre Jolivet   for (i = 0; i < ne; i++) PetscCheck(edgelist[2 * i] != edgelist[2 * i + 1], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " has the same vertex %" PetscInt_FMT " at each endpoint", i, edgelist[2 * i]);
210f11a936eSBarry Smith 
2115c6496baSHong Zhang   i = 0;
2125c6496baSHong Zhang   if (ne) nvtx_min = nvtx_max = edgelist[0];
2135c6496baSHong Zhang   for (j = 0; j < ne; j++) {
2145c6496baSHong Zhang     nvtx_min = PetscMin(nvtx_min, edgelist[i]);
2155c6496baSHong Zhang     nvtx_max = PetscMax(nvtx_max, edgelist[i]);
2165c6496baSHong Zhang     i++;
2175c6496baSHong Zhang     nvtx_min = PetscMin(nvtx_min, edgelist[i]);
2185c6496baSHong Zhang     nvtx_max = PetscMax(nvtx_max, edgelist[i]);
2195c6496baSHong Zhang     i++;
2205c6496baSHong Zhang   }
2215c6496baSHong Zhang   Nvtx = nvtx_max - nvtx_min + 1; /* approximated total local nvtx for this subnet */
2225c6496baSHong Zhang 
2235c6496baSHong Zhang   /* Get exact local nvtx for this subnet: counting local values between nvtx_min and nvtx_max */
2249566063dSJacob Faibussowitsch   PetscCall(PetscBTCreate(Nvtx, &table));
2259566063dSJacob Faibussowitsch   PetscCall(PetscBTMemzero(Nvtx, table));
226f11a936eSBarry Smith   i = 0;
227f11a936eSBarry Smith   for (j = 0; j < ne; j++) {
2289566063dSJacob Faibussowitsch     PetscCall(PetscBTSet(table, edgelist[i++] - nvtx_min));
2299566063dSJacob Faibussowitsch     PetscCall(PetscBTSet(table, edgelist[i++] - nvtx_min));
230f11a936eSBarry Smith   }
231f11a936eSBarry Smith   nvtx = 0;
232f11a936eSBarry Smith   for (j = 0; j < Nvtx; j++) {
233f11a936eSBarry Smith     if (PetscBTLookup(table, j)) nvtx++;
234f11a936eSBarry Smith   }
2355c6496baSHong Zhang 
2365c6496baSHong Zhang   /* Get global total Nvtx = max(edgelist[])+1 for this subnet */
2371c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&nvtx_max, &Nvtx, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
2385c6496baSHong Zhang   Nvtx++;
2399566063dSJacob Faibussowitsch   PetscCall(PetscBTDestroy(&table));
240f11a936eSBarry Smith 
241f11a936eSBarry Smith   /* Get global total Nedge for this subnet */
2421c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&ne, &Nedge, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
243f11a936eSBarry Smith 
244daad07d3SAidan Hamilton   i = network->cloneshared->nsubnet;
24548a46eb9SPierre Jolivet   if (name) PetscCall(PetscStrcpy(network->cloneshared->subnet[i].name, name));
246daad07d3SAidan Hamilton   network->cloneshared->subnet[i].nvtx     = nvtx; /* include ghost vertices */
247daad07d3SAidan Hamilton   network->cloneshared->subnet[i].nedge    = ne;
248daad07d3SAidan Hamilton   network->cloneshared->subnet[i].edgelist = edgelist;
249daad07d3SAidan Hamilton   network->cloneshared->subnet[i].Nvtx     = Nvtx;
250daad07d3SAidan Hamilton   network->cloneshared->subnet[i].Nedge    = Nedge;
2512bf73ac6SHong Zhang 
2522bf73ac6SHong Zhang   /* ----------------------------------------------------------
2532bf73ac6SHong Zhang    p=v or e;
2542bf73ac6SHong Zhang    subnet[0].pStart   = 0
2552bf73ac6SHong Zhang    subnet[i+1].pStart = subnet[i].pEnd = subnet[i].pStart + (nE[i] or NV[i])
2562bf73ac6SHong Zhang    ----------------------------------------------------------------------- */
2572bf73ac6SHong Zhang   /* GLOBAL subnet[].vStart and vEnd, used by DMNetworkLayoutSetUp() */
258daad07d3SAidan Hamilton   network->cloneshared->subnet[i].vStart = network->cloneshared->NVertices;
259daad07d3SAidan Hamilton   network->cloneshared->subnet[i].vEnd   = network->cloneshared->subnet[i].vStart + network->cloneshared->subnet[i].Nvtx; /* global vEnd of subnet[i] */
2602bf73ac6SHong Zhang 
261daad07d3SAidan Hamilton   network->cloneshared->nVertices += nvtx; /* include ghost vertices */
262daad07d3SAidan Hamilton   network->cloneshared->NVertices += network->cloneshared->subnet[i].Nvtx;
2632bf73ac6SHong Zhang 
2642bf73ac6SHong Zhang   /* LOCAL subnet[].eStart and eEnd, used by DMNetworkLayoutSetUp() */
265daad07d3SAidan Hamilton   network->cloneshared->subnet[i].eStart = network->cloneshared->nEdges;
266daad07d3SAidan Hamilton   network->cloneshared->subnet[i].eEnd   = network->cloneshared->subnet[i].eStart + ne;
267daad07d3SAidan Hamilton   network->cloneshared->nEdges += ne;
268daad07d3SAidan Hamilton   network->cloneshared->NEdges += network->cloneshared->subnet[i].Nedge;
2692bf73ac6SHong Zhang 
270daad07d3SAidan Hamilton   PetscCall(PetscStrcpy(network->cloneshared->subnet[i].name, name));
271daad07d3SAidan Hamilton   if (netnum) *netnum = network->cloneshared->nsubnet;
272daad07d3SAidan Hamilton   network->cloneshared->nsubnet++;
2732bf73ac6SHong Zhang   PetscFunctionReturn(0);
2742bf73ac6SHong Zhang }
2752bf73ac6SHong Zhang 
2765c6496baSHong Zhang /*@C
2775c6496baSHong Zhang   DMNetworkSharedVertexGetInfo - Get info of a shared vertex struct, see petsc/private/dmnetworkimpl.h
2782bf73ac6SHong Zhang 
2795c6496baSHong Zhang   Not collective
2805c6496baSHong Zhang 
2815c6496baSHong Zhang   Input Parameters:
2825c6496baSHong Zhang + dm - the DM object
2835c6496baSHong Zhang - v - vertex point
2845c6496baSHong Zhang 
2855c6496baSHong Zhang   Output Parameters:
2865c6496baSHong Zhang + gidx - global number of this shared vertex in the internal dmplex
2875c6496baSHong Zhang . n - number of subnetworks that share this vertex
2885c6496baSHong Zhang - sv - array of size n: sv[2*i,2*i+1]=(net[i], idx[i]), i=0,...,n-1
2895c6496baSHong Zhang 
2905c6496baSHong Zhang   Level: intermediate
2915c6496baSHong Zhang 
292db781477SPatrick Sanan .seealso: `DMNetworkGetSharedVertices()`
2935c6496baSHong Zhang @*/
294d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkSharedVertexGetInfo(DM dm, PetscInt v, PetscInt *gidx, PetscInt *n, const PetscInt **sv)
295d71ae5a4SJacob Faibussowitsch {
2965c6496baSHong Zhang   DM_Network *network = (DM_Network *)dm->data;
297daad07d3SAidan Hamilton   SVtx       *svtx    = network->cloneshared->svtx;
2985c6496baSHong Zhang   PetscInt    i, gidx_tmp;
2995c6496baSHong Zhang 
3005c6496baSHong Zhang   PetscFunctionBegin;
3019566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetGlobalVertexIndex(dm, v, &gidx_tmp));
302daad07d3SAidan Hamilton   PetscCall(PetscTableFind(network->cloneshared->svtable, gidx_tmp + 1, &i));
3035c6496baSHong Zhang   PetscCheck(i > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "input vertex is not a shared vertex");
3045c6496baSHong Zhang 
3055c6496baSHong Zhang   i--;
3065c6496baSHong Zhang   if (gidx) *gidx = gidx_tmp;
3075c6496baSHong Zhang   if (n) *n = svtx[i].n;
3085c6496baSHong Zhang   if (sv) *sv = svtx[i].sv;
3095c6496baSHong Zhang   PetscFunctionReturn(0);
3105c6496baSHong Zhang }
3115c6496baSHong Zhang 
3125c6496baSHong Zhang /*
3135c6496baSHong Zhang   VtxGetInfo - Get info of an input vertex=(net,idx)
3145c6496baSHong Zhang 
3155c6496baSHong Zhang   Input Parameters:
3165c6496baSHong Zhang + Nsvtx - global num of shared vertices
3175c6496baSHong Zhang . svtx - array of shared vertices (global)
3185c6496baSHong Zhang - (net,idx) - subnet number and local index for a vertex
3195c6496baSHong Zhang 
3205c6496baSHong Zhang   Output Parameters:
3215c6496baSHong Zhang + gidx - global index of (net,idx)
3225c6496baSHong Zhang . svtype - see petsc/private/dmnetworkimpl.h
3235c6496baSHong Zhang - svtx_idx - ordering in the svtx array
3245c6496baSHong Zhang */
325d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode VtxGetInfo(PetscInt Nsvtx, SVtx *svtx, PetscInt net, PetscInt idx, PetscInt *gidx, SVtxType *svtype, PetscInt *svtx_idx)
326d71ae5a4SJacob Faibussowitsch {
3275c6496baSHong Zhang   PetscInt i, j, *svto, g_idx;
3282bf73ac6SHong Zhang   SVtxType vtype;
3292bf73ac6SHong Zhang 
3302bf73ac6SHong Zhang   PetscFunctionBegin;
3312bf73ac6SHong Zhang   if (!Nsvtx) PetscFunctionReturn(0);
3322bf73ac6SHong Zhang 
3335c6496baSHong Zhang   g_idx = -1;
3342bf73ac6SHong Zhang   vtype = SVNONE;
3355c6496baSHong Zhang 
3362bf73ac6SHong Zhang   for (i = 0; i < Nsvtx; i++) {
3372bf73ac6SHong Zhang     if (net == svtx[i].sv[0] && idx == svtx[i].sv[1]) {
3385c6496baSHong Zhang       g_idx = svtx[i].gidx;
3392bf73ac6SHong Zhang       vtype = SVFROM;
3402bf73ac6SHong Zhang     } else { /* loop over svtx[i].n */
3412bf73ac6SHong Zhang       for (j = 1; j < svtx[i].n; j++) {
3422bf73ac6SHong Zhang         svto = svtx[i].sv + 2 * j;
3432bf73ac6SHong Zhang         if (net == svto[0] && idx == svto[1]) {
3442bf73ac6SHong Zhang           /* input vertex net.idx is a shared to_vertex, output its global index and its svtype */
3455c6496baSHong Zhang           g_idx = svtx[i].gidx; /* output gidx for to_vertex */
3462bf73ac6SHong Zhang           vtype = SVTO;
3472bf73ac6SHong Zhang         }
3482bf73ac6SHong Zhang       }
3492bf73ac6SHong Zhang     }
3502bf73ac6SHong Zhang     if (vtype != SVNONE) break;
3512bf73ac6SHong Zhang   }
3525c6496baSHong Zhang   if (gidx) *gidx = g_idx;
3532bf73ac6SHong Zhang   if (svtype) *svtype = vtype;
3542bf73ac6SHong Zhang   if (svtx_idx) *svtx_idx = i;
3552bf73ac6SHong Zhang   PetscFunctionReturn(0);
3562bf73ac6SHong Zhang }
3572bf73ac6SHong Zhang 
3582bf73ac6SHong Zhang /*
3595c6496baSHong Zhang   TableAddSVtx - Add a new shared vertice from sedgelist[k] to a ctable svta
3605c6496baSHong Zhang 
3615c6496baSHong Zhang   Input:  network, sedgelist, k, svta
3625c6496baSHong Zhang   Output: svta, tdata, ta2sv
3632bf73ac6SHong Zhang */
364d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode TableAddSVtx(DM_Network *network, PetscInt *sedgelist, PetscInt k, PetscTable svta, PetscInt *tdata, PetscInt *ta2sv)
365d71ae5a4SJacob Faibussowitsch {
3665c6496baSHong Zhang   PetscInt net, idx, gidx;
3672bf73ac6SHong Zhang 
3682bf73ac6SHong Zhang   PetscFunctionBegin;
3695c6496baSHong Zhang   net  = sedgelist[k];
3705c6496baSHong Zhang   idx  = sedgelist[k + 1];
371daad07d3SAidan Hamilton   gidx = network->cloneshared->subnet[net].vStart + idx;
3729566063dSJacob Faibussowitsch   PetscCall(PetscTableAdd(svta, gidx + 1, *tdata + 1, INSERT_VALUES));
3735c6496baSHong Zhang 
3745c6496baSHong Zhang   ta2sv[*tdata] = k; /* maps tdata to index of sedgelist */
3755c6496baSHong Zhang   (*tdata)++;
3762bf73ac6SHong Zhang   PetscFunctionReturn(0);
3772bf73ac6SHong Zhang }
3782bf73ac6SHong Zhang 
3792bf73ac6SHong Zhang /*
3805c6496baSHong Zhang   SharedVtxCreate - Create an array of global shared vertices. See SVtx and SVtxType in dmnetworkimpl.h
3812bf73ac6SHong Zhang 
3822bf73ac6SHong Zhang   Input:  dm, Nsedgelist, sedgelist
3832bf73ac6SHong Zhang 
3842bf73ac6SHong Zhang   Note: Output svtx is organized as
3852bf73ac6SHong Zhang         sv(net[0],idx[0]) --> sv(net[1],idx[1])
3862bf73ac6SHong Zhang                           --> sv(net[1],idx[1])
3872bf73ac6SHong Zhang                           ...
3882bf73ac6SHong Zhang                           --> sv(net[n-1],idx[n-1])
3892bf73ac6SHong Zhang         and net[0] < net[1] < ... < net[n-1]
3902bf73ac6SHong Zhang         where sv[0] has SVFROM type, sv[i], i>0, has SVTO type.
3912bf73ac6SHong Zhang  */
392d71ae5a4SJacob Faibussowitsch static PetscErrorCode SharedVtxCreate(DM dm, PetscInt Nsedgelist, PetscInt *sedgelist)
393d71ae5a4SJacob Faibussowitsch {
3945c6496baSHong Zhang   SVtx              *svtx = NULL;
3952bf73ac6SHong Zhang   PetscInt          *sv, k, j, nsv, *tdata, **ta2sv;
3962bf73ac6SHong Zhang   PetscTable        *svtas;
3977340ca2cSHong Zhang   PetscInt           gidx, net, idx, i, nta, ita, idx_from, idx_to, n, *net_tmp, *idx_tmp, *gidx_tmp;
3982bf73ac6SHong Zhang   DM_Network        *network = (DM_Network *)dm->data;
3992bf73ac6SHong Zhang   PetscTablePosition ppos;
4002bf73ac6SHong Zhang 
4012bf73ac6SHong Zhang   PetscFunctionBegin;
4025c6496baSHong Zhang   /* (1) Crete an array of ctables svtas to map (net,idx) -> gidx; a svtas[] for a shared/merged vertex */
4039566063dSJacob Faibussowitsch   PetscCall(PetscCalloc3(Nsedgelist, &svtas, Nsedgelist, &tdata, 2 * Nsedgelist, &ta2sv));
4042bf73ac6SHong Zhang 
4052bf73ac6SHong Zhang   k   = 0; /* sedgelist vertex counter j = 4*k */
4067340ca2cSHong Zhang   nta = 0; /* num of svta tables created = num of groups of shared vertices */
4072bf73ac6SHong Zhang 
4082bf73ac6SHong Zhang   /* for j=0 */
409daad07d3SAidan Hamilton   PetscCall(PetscTableCreate(2 * Nsedgelist, network->cloneshared->NVertices + 1, &svtas[nta]));
4109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2 * Nsedgelist, &ta2sv[nta]));
4112bf73ac6SHong Zhang 
4129566063dSJacob Faibussowitsch   PetscCall(TableAddSVtx(network, sedgelist, k, svtas[nta], &tdata[nta], ta2sv[nta]));
4139566063dSJacob Faibussowitsch   PetscCall(TableAddSVtx(network, sedgelist, k + 2, svtas[nta], &tdata[nta], ta2sv[nta]));
4149371c9d4SSatish Balay   nta++;
4159371c9d4SSatish Balay   k += 4;
4162bf73ac6SHong Zhang 
4175c6496baSHong Zhang   for (j = 1; j < Nsedgelist; j++) { /* j: sedgelist counter */
4182bf73ac6SHong Zhang     for (ita = 0; ita < nta; ita++) {
4192bf73ac6SHong Zhang       /* vfrom */
4209371c9d4SSatish Balay       net  = sedgelist[k];
4219371c9d4SSatish Balay       idx  = sedgelist[k + 1];
422daad07d3SAidan Hamilton       gidx = network->cloneshared->subnet[net].vStart + idx; /* global index of the vertex net.idx before merging shared vertices */
4239566063dSJacob Faibussowitsch       PetscCall(PetscTableFind(svtas[ita], gidx + 1, &idx_from));
4242bf73ac6SHong Zhang 
4252bf73ac6SHong Zhang       /* vto */
4269371c9d4SSatish Balay       net  = sedgelist[k + 2];
4279371c9d4SSatish Balay       idx  = sedgelist[k + 3];
428daad07d3SAidan Hamilton       gidx = network->cloneshared->subnet[net].vStart + idx;
4299566063dSJacob Faibussowitsch       PetscCall(PetscTableFind(svtas[ita], gidx + 1, &idx_to));
4302bf73ac6SHong Zhang 
4312bf73ac6SHong Zhang       if (idx_from || idx_to) { /* vfrom or vto is on table svtas[ita] */
4329371c9d4SSatish Balay         idx_from--;
4339371c9d4SSatish Balay         idx_to--;
4342bf73ac6SHong Zhang         if (idx_from < 0) { /* vto is on svtas[ita] */
4359566063dSJacob Faibussowitsch           PetscCall(TableAddSVtx(network, sedgelist, k, svtas[ita], &tdata[ita], ta2sv[ita]));
4362bf73ac6SHong Zhang           break;
4372bf73ac6SHong Zhang         } else if (idx_to < 0) {
4389566063dSJacob Faibussowitsch           PetscCall(TableAddSVtx(network, sedgelist, k + 2, svtas[ita], &tdata[ita], ta2sv[ita]));
4392bf73ac6SHong Zhang           break;
4402bf73ac6SHong Zhang         }
4412bf73ac6SHong Zhang       }
4422bf73ac6SHong Zhang     }
4432bf73ac6SHong Zhang 
4442bf73ac6SHong Zhang     if (ita == nta) {
445daad07d3SAidan Hamilton       PetscCall(PetscTableCreate(2 * Nsedgelist, network->cloneshared->NVertices + 1, &svtas[nta]));
4469566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(2 * Nsedgelist, &ta2sv[nta]));
4472bf73ac6SHong Zhang 
4489566063dSJacob Faibussowitsch       PetscCall(TableAddSVtx(network, sedgelist, k, svtas[nta], &tdata[nta], ta2sv[nta]));
4499566063dSJacob Faibussowitsch       PetscCall(TableAddSVtx(network, sedgelist, k + 2, svtas[nta], &tdata[nta], ta2sv[nta]));
4502bf73ac6SHong Zhang       nta++;
4512bf73ac6SHong Zhang     }
4522bf73ac6SHong Zhang     k += 4;
4532bf73ac6SHong Zhang   }
4542bf73ac6SHong Zhang 
4556aad120cSJose E. Roman   /* (2) Create svtable for query shared vertices using gidx */
456daad07d3SAidan Hamilton   PetscCall(PetscTableCreate(nta, network->cloneshared->NVertices + 1, &network->cloneshared->svtable));
4575c6496baSHong Zhang 
4585c6496baSHong Zhang   /* (3) Construct svtx from svtas
4597340ca2cSHong Zhang    svtx: array of SVtx: sv[0]=(net[0],idx[0]) to vertices sv[k], k=1,...,n-1. */
4609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nta, &svtx));
4612bf73ac6SHong Zhang   for (nsv = 0; nsv < nta; nsv++) {
4624f5c2772SJose E. Roman     /* for a single svtx, put shared vertices in ascending order of gidx */
4639566063dSJacob Faibussowitsch     PetscCall(PetscTableGetCount(svtas[nsv], &n));
4649566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(2 * n, &sv));
4657340ca2cSHong Zhang     PetscCall(PetscMalloc3(n, &gidx_tmp, n, &net_tmp, n, &idx_tmp));
4665c6496baSHong Zhang     svtx[nsv].sv   = sv;
4675c6496baSHong Zhang     svtx[nsv].n    = n;
468daad07d3SAidan Hamilton     svtx[nsv].gidx = network->cloneshared->NVertices; /* initialization */
4692bf73ac6SHong Zhang 
4709566063dSJacob Faibussowitsch     PetscCall(PetscTableGetHeadPosition(svtas[nsv], &ppos));
4714f5c2772SJose E. Roman     for (k = 0; k < n; k++) { /* gidx is sorted in ascending order */
4729566063dSJacob Faibussowitsch       PetscCall(PetscTableGetNext(svtas[nsv], &ppos, &gidx, &i));
4739371c9d4SSatish Balay       gidx--;
4749371c9d4SSatish Balay       i--;
4755c6496baSHong Zhang       j           = ta2sv[nsv][i];    /* maps i to index of sedgelist */
4767340ca2cSHong Zhang       net_tmp[k]  = sedgelist[j];     /* subnet number */
4777340ca2cSHong Zhang       idx_tmp[k]  = sedgelist[j + 1]; /* index on the subnet */
4787340ca2cSHong Zhang       gidx_tmp[k] = gidx;             /* gidx in un-merged dmnetwork */
4792bf73ac6SHong Zhang     }
4805c6496baSHong Zhang 
4817340ca2cSHong Zhang     /* current implementation requires sv[]=[net,idx] in ascending order of its gidx in un-merged dmnetwork */
4827340ca2cSHong Zhang     PetscCall(PetscSortIntWithArrayPair(n, gidx_tmp, net_tmp, idx_tmp));
4837340ca2cSHong Zhang     svtx[nsv].gidx = gidx_tmp[0]; /* = min(gidx) */
4847340ca2cSHong Zhang     for (k = 0; k < n; k++) {
4857340ca2cSHong Zhang       sv[2 * k]     = net_tmp[k];
4867340ca2cSHong Zhang       sv[2 * k + 1] = idx_tmp[k];
4877340ca2cSHong Zhang     }
4887340ca2cSHong Zhang     PetscCall(PetscFree3(gidx_tmp, net_tmp, idx_tmp));
4897340ca2cSHong Zhang 
4906aad120cSJose E. Roman     /* Setup svtable for query shared vertices */
491daad07d3SAidan Hamilton     PetscCall(PetscTableAdd(network->cloneshared->svtable, svtx[nsv].gidx + 1, nsv + 1, INSERT_VALUES));
4922bf73ac6SHong Zhang   }
4932bf73ac6SHong Zhang 
4942bf73ac6SHong Zhang   for (j = 0; j < nta; j++) {
4959566063dSJacob Faibussowitsch     PetscCall(PetscTableDestroy(&svtas[j]));
4969566063dSJacob Faibussowitsch     PetscCall(PetscFree(ta2sv[j]));
4972bf73ac6SHong Zhang   }
4989566063dSJacob Faibussowitsch   PetscCall(PetscFree3(svtas, tdata, ta2sv));
4992bf73ac6SHong Zhang 
500daad07d3SAidan Hamilton   network->cloneshared->Nsvtx = nta;
501daad07d3SAidan Hamilton   network->cloneshared->svtx  = svtx;
5022bf73ac6SHong Zhang   PetscFunctionReturn(0);
5032bf73ac6SHong Zhang }
5042bf73ac6SHong Zhang 
5055c6496baSHong Zhang /*
5065c6496baSHong Zhang   GetEdgelist_Coupling - Get an integrated edgelist for dmplex from user-provided subnet[].edgelist when subnets are coupled by shared vertices
5075c6496baSHong Zhang 
5085c6496baSHong Zhang   Input Parameters:
5095c6496baSHong Zhang . dm - the dmnetwork object
5105c6496baSHong Zhang 
5115c6496baSHong Zhang    Output Parameters:
5125c6496baSHong Zhang +  edges - the integrated edgelist for dmplex
5135c6496baSHong Zhang -  nmerged_ptr - num of vertices being merged
5145c6496baSHong Zhang */
515d71ae5a4SJacob Faibussowitsch static PetscErrorCode GetEdgelist_Coupling(DM dm, PetscInt *edges, PetscInt *nmerged_ptr)
516d71ae5a4SJacob Faibussowitsch {
5172bf73ac6SHong Zhang   MPI_Comm    comm;
5182bf73ac6SHong Zhang   PetscMPIInt size, rank, *recvcounts = NULL, *displs = NULL;
519eac198afSGetnet   DM_Network *network = (DM_Network *)dm->data;
520eac198afSGetnet   PetscInt    i, j, ctr, np;
521daad07d3SAidan Hamilton   PetscInt   *vidxlTog, Nsv, Nsubnet = network->cloneshared->Nsubnet;
522daad07d3SAidan Hamilton   PetscInt   *sedgelist = network->cloneshared->sedgelist;
5235c6496baSHong Zhang   PetscInt    net, idx, gidx, nmerged, *vrange, gidx_from, net_from, sv_idx;
5242bf73ac6SHong Zhang   SVtxType    svtype = SVNONE;
5255c6496baSHong Zhang   SVtx       *svtx;
5262bf73ac6SHong Zhang 
5272bf73ac6SHong Zhang   PetscFunctionBegin;
5289566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5299566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
5312bf73ac6SHong Zhang 
5325c6496baSHong Zhang   /* (1) Create global svtx[] from sedgelist */
5335c6496baSHong Zhang   /* --------------------------------------- */
534daad07d3SAidan Hamilton   PetscCall(SharedVtxCreate(dm, network->cloneshared->Nsvtx, sedgelist));
535daad07d3SAidan Hamilton   Nsv  = network->cloneshared->Nsvtx;
536daad07d3SAidan Hamilton   svtx = network->cloneshared->svtx;
5372bf73ac6SHong Zhang 
538d5b43468SJose E. Roman   /* (2) Merge shared vto vertices to their vfrom vertex with same global vertex index (gidx) */
5395c6496baSHong Zhang   /* --------------------------------------------------------------------------------------- */
5402bf73ac6SHong Zhang   /* (2.1) compute vrage[rank]: global index of 1st local vertex in proc[rank] */
541daad07d3SAidan Hamilton   PetscCall(PetscMalloc4(size + 1, &vrange, size, &displs, size, &recvcounts, network->cloneshared->nVertices, &vidxlTog));
5429371c9d4SSatish Balay   for (i = 0; i < size; i++) {
5439371c9d4SSatish Balay     displs[i]     = i;
5449371c9d4SSatish Balay     recvcounts[i] = 1;
5459371c9d4SSatish Balay   }
5462bf73ac6SHong Zhang 
5472bf73ac6SHong Zhang   vrange[0] = 0;
548daad07d3SAidan Hamilton   PetscCallMPI(MPI_Allgatherv(&network->cloneshared->nVertices, 1, MPIU_INT, vrange + 1, recvcounts, displs, MPIU_INT, comm));
5495c6496baSHong Zhang   for (i = 2; i < size + 1; i++) vrange[i] += vrange[i - 1];
5502bf73ac6SHong Zhang 
5512bf73ac6SHong Zhang   /* (2.2) Create vidxlTog: maps UN-MERGED local vertex index i to global index gidx (plex, excluding ghost vertices) */
5529371c9d4SSatish Balay   i                           = 0;
5539371c9d4SSatish Balay   gidx                        = 0;
5542bf73ac6SHong Zhang   nmerged                     = 0; /* local num of merged vertices */
555daad07d3SAidan Hamilton   network->cloneshared->nsvtx = 0; /* local num of SVtx structs, including ghosts */
5562bf73ac6SHong Zhang   for (net = 0; net < Nsubnet; net++) {
557daad07d3SAidan Hamilton     for (idx = 0; idx < network->cloneshared->subnet[net].Nvtx; idx++) { /* Note: global subnet[net].Nvtx */
5589566063dSJacob Faibussowitsch       PetscCall(VtxGetInfo(Nsv, svtx, net, idx, &gidx_from, &svtype, &sv_idx));
5592bf73ac6SHong Zhang       if (svtype == SVTO) {
560daad07d3SAidan Hamilton         if (network->cloneshared->subnet[net].nvtx) { /* this proc owns sv_to */
5615c6496baSHong Zhang           net_from = svtx[sv_idx].sv[0];              /* subnet number of its shared vertex */
562daad07d3SAidan Hamilton           if (network->cloneshared->subnet[net_from].nvtx == 0) {
5635c6496baSHong Zhang             /* this proc does not own v_from, thus a ghost local vertex */
564daad07d3SAidan Hamilton             network->cloneshared->nsvtx++;
5652bf73ac6SHong Zhang           }
5665c6496baSHong Zhang           vidxlTog[i++] = gidx_from; /* gidx before merging! Bug??? */
5675c6496baSHong Zhang           nmerged++;                 /* a shared vertex -- merged */
5682bf73ac6SHong Zhang         }
5692bf73ac6SHong Zhang       } else {
570daad07d3SAidan Hamilton         if (svtype == SVFROM && network->cloneshared->subnet[net].nvtx) {
5715c6496baSHong Zhang           /* this proc owns this v_from, a new local shared vertex */
572daad07d3SAidan Hamilton           network->cloneshared->nsvtx++;
5732bf73ac6SHong Zhang         }
574daad07d3SAidan Hamilton         if (network->cloneshared->subnet[net].nvtx) vidxlTog[i++] = gidx;
5752bf73ac6SHong Zhang         gidx++;
5762bf73ac6SHong Zhang       }
5772bf73ac6SHong Zhang     }
5782bf73ac6SHong Zhang   }
5792bf73ac6SHong Zhang #if defined(PETSC_USE_DEBUG)
580daad07d3SAidan Hamilton   PetscCheck(i == network->cloneshared->nVertices, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "%" PetscInt_FMT " != %" PetscInt_FMT " nVertices", i, network->cloneshared->nVertices);
5812bf73ac6SHong Zhang #endif
5822bf73ac6SHong Zhang 
5835c6496baSHong Zhang   /* (2.3) Shared vertices in the subnetworks are merged, update global NVertices: np = sum(local nmerged) */
5849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&nmerged, &np, 1, MPIU_INT, MPI_SUM, comm));
585daad07d3SAidan Hamilton   network->cloneshared->NVertices -= np;
5862bf73ac6SHong Zhang 
5872bf73ac6SHong Zhang   ctr = 0;
5882bf73ac6SHong Zhang   for (net = 0; net < Nsubnet; net++) {
589daad07d3SAidan Hamilton     for (j = 0; j < network->cloneshared->subnet[net].nedge; j++) {
5902bf73ac6SHong Zhang       /* vfrom: */
591daad07d3SAidan Hamilton       i              = network->cloneshared->subnet[net].edgelist[2 * j] + (network->cloneshared->subnet[net].vStart - vrange[rank]);
5922bf73ac6SHong Zhang       edges[2 * ctr] = vidxlTog[i];
5932bf73ac6SHong Zhang 
5942bf73ac6SHong Zhang       /* vto */
595daad07d3SAidan Hamilton       i                  = network->cloneshared->subnet[net].edgelist[2 * j + 1] + (network->cloneshared->subnet[net].vStart - vrange[rank]);
5962bf73ac6SHong Zhang       edges[2 * ctr + 1] = vidxlTog[i];
5972bf73ac6SHong Zhang       ctr++;
5982bf73ac6SHong Zhang     }
5992bf73ac6SHong Zhang   }
6009566063dSJacob Faibussowitsch   PetscCall(PetscFree4(vrange, displs, recvcounts, vidxlTog));
6019566063dSJacob Faibussowitsch   PetscCall(PetscFree(sedgelist)); /* created in DMNetworkAddSharedVertices() */
6022bf73ac6SHong Zhang 
603eac198afSGetnet   *nmerged_ptr = nmerged;
6045f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
6055f2c45f1SShri Abhyankar }
6065f2c45f1SShri Abhyankar 
607d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkInitializeNonTopological(DM dm)
608d71ae5a4SJacob Faibussowitsch {
609daad07d3SAidan Hamilton   DM_Network *network = (DM_Network *)dm->data;
610daad07d3SAidan Hamilton   PetscInt    p, pStart = network->cloneshared->pStart, pEnd = network->cloneshared->pEnd;
611daad07d3SAidan Hamilton   MPI_Comm    comm;
612daad07d3SAidan Hamilton 
613daad07d3SAidan Hamilton   PetscFunctionBegin;
614daad07d3SAidan Hamilton   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
615daad07d3SAidan Hamilton 
616daad07d3SAidan Hamilton   PetscCall(PetscSectionCreate(comm, &network->DataSection));
617daad07d3SAidan Hamilton   PetscCall(PetscSectionCreate(comm, &network->DofSection));
618daad07d3SAidan Hamilton   PetscCall(PetscSectionSetChart(network->DataSection, pStart, pEnd));
619daad07d3SAidan Hamilton   PetscCall(PetscSectionSetChart(network->DofSection, pStart, pEnd));
620daad07d3SAidan Hamilton 
621daad07d3SAidan Hamilton   PetscCall(DMNetworkInitializeHeaderComponentData(dm));
622daad07d3SAidan Hamilton 
623daad07d3SAidan Hamilton   for (p = 0; p < pEnd - pStart; p++) {
624daad07d3SAidan Hamilton     network->header[p].ndata           = 0;
625daad07d3SAidan Hamilton     network->header[p].offset[0]       = 0;
626daad07d3SAidan Hamilton     network->header[p].offsetvarrel[0] = 0;
627daad07d3SAidan Hamilton     PetscCall(PetscSectionAddDof(network->DataSection, p, network->header[p].hsize));
628daad07d3SAidan Hamilton   }
629daad07d3SAidan Hamilton   PetscFunctionReturn(0);
630daad07d3SAidan Hamilton }
631daad07d3SAidan Hamilton 
6325f2c45f1SShri Abhyankar /*@
6335f2c45f1SShri Abhyankar   DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network
6345f2c45f1SShri Abhyankar 
635eac198afSGetnet   Not Collective
6365f2c45f1SShri Abhyankar 
6377a7aea1fSJed Brown   Input Parameters:
638f11a936eSBarry Smith . dm - the dmnetwork object
6395f2c45f1SShri Abhyankar 
6405f2c45f1SShri Abhyankar   Notes:
6415f2c45f1SShri Abhyankar   This routine should be called after the network sizes and edgelists have been provided. It creates
6425f2c45f1SShri Abhyankar   the bare layout of the network and sets up the network to begin insertion of components.
6435f2c45f1SShri Abhyankar 
6445f2c45f1SShri Abhyankar   All the components should be registered before calling this routine.
6455f2c45f1SShri Abhyankar 
64697bb938eSShri Abhyankar   Level: beginner
6475f2c45f1SShri Abhyankar 
648db781477SPatrick Sanan .seealso: `DMNetworkSetNumSubNetworks()`, `DMNetworkAddSubnetwork()`
6495f2c45f1SShri Abhyankar @*/
650d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkLayoutSetUp(DM dm)
651d71ae5a4SJacob Faibussowitsch {
6525f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network *)dm->data;
653daad07d3SAidan Hamilton   PetscInt        i, j, ctr, Nsubnet = network->cloneshared->Nsubnet, np, *edges, *subnetvtx, *subnetedge, e, v, vfrom, vto, net, globaledgeoff;
654caf410d2SHong Zhang   const PetscInt *cone;
655caf410d2SHong Zhang   MPI_Comm        comm;
6565503a911SAidan Hamilton   PetscMPIInt     size;
657eac198afSGetnet   PetscSection    sectiong;
6585c6496baSHong Zhang   PetscInt        nmerged = 0;
6596500d4abSHong Zhang 
6606500d4abSHong Zhang   PetscFunctionBegin;
661e3b1a053SGetnet Betrie   PetscCall(PetscLogEventBegin(DMNetwork_LayoutSetUp, dm, 0, 0, 0));
662daad07d3SAidan Hamilton   PetscCheck(network->cloneshared->nsubnet == Nsubnet, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Must call DMNetworkAddSubnetwork() %" PetscInt_FMT " times", Nsubnet);
6632bf73ac6SHong Zhang 
664eac198afSGetnet   /* This implementation requires user input each subnet by a single processor when Nsubnet>1, thus subnet[net].nvtx=subnet[net].Nvtx when net>0 */
665eac198afSGetnet   for (net = 1; net < Nsubnet; net++) {
6669371c9d4SSatish Balay     if (network->cloneshared->subnet[net].nvtx)
6679371c9d4SSatish Balay       PetscCheck(network->cloneshared->subnet[net].nvtx == network->cloneshared->subnet[net].Nvtx, PETSC_COMM_SELF, PETSC_ERR_SUP, "subnetwork %" PetscInt_FMT " local num of vertices %" PetscInt_FMT " != %" PetscInt_FMT " global num", net,
6689371c9d4SSatish Balay                  network->cloneshared->subnet[net].nvtx, network->cloneshared->subnet[net].Nvtx);
669eac198afSGetnet   }
670eac198afSGetnet 
6719566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
6725503a911SAidan Hamilton   PetscCall(MPI_Comm_size(comm, &size));
6736500d4abSHong Zhang 
674f11a936eSBarry Smith   /* Create LOCAL edgelist in global vertex ordering for the network by concatenating local input edgelists of the subnetworks */
675daad07d3SAidan Hamilton   PetscCall(PetscCalloc1(2 * network->cloneshared->nEdges, &edges));
676eac198afSGetnet 
677daad07d3SAidan Hamilton   if (network->cloneshared->Nsvtx) { /* subnetworks are coupled via shared vertices */
6789566063dSJacob Faibussowitsch     PetscCall(GetEdgelist_Coupling(dm, edges, &nmerged));
679eac198afSGetnet   } else { /* subnetworks are not coupled */
6806aad120cSJose E. Roman     /* Create a 0-size svtable for query shared vertices */
681daad07d3SAidan Hamilton     PetscCall(PetscTableCreate(0, network->cloneshared->NVertices + 1, &network->cloneshared->svtable));
682caf410d2SHong Zhang     ctr = 0;
6832bf73ac6SHong Zhang     for (i = 0; i < Nsubnet; i++) {
684daad07d3SAidan Hamilton       for (j = 0; j < network->cloneshared->subnet[i].nedge; j++) {
685daad07d3SAidan Hamilton         edges[2 * ctr]     = network->cloneshared->subnet[i].vStart + network->cloneshared->subnet[i].edgelist[2 * j];
686daad07d3SAidan Hamilton         edges[2 * ctr + 1] = network->cloneshared->subnet[i].vStart + network->cloneshared->subnet[i].edgelist[2 * j + 1];
6876500d4abSHong Zhang         ctr++;
6886500d4abSHong Zhang       }
6896500d4abSHong Zhang     }
690eac198afSGetnet   }
6917765340cSHong Zhang 
6922bf73ac6SHong Zhang   /* Create network->plex; One dimensional network, numCorners=2 */
6939566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &network->plex));
6949566063dSJacob Faibussowitsch   PetscCall(DMSetType(network->plex, DMPLEX));
6959566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(network->plex, 1));
696eac198afSGetnet 
697daad07d3SAidan Hamilton   if (size == 1) PetscCall(DMPlexBuildFromCellList(network->plex, network->cloneshared->nEdges, PETSC_DECIDE, 2, edges));
698daad07d3SAidan Hamilton   else PetscCall(DMPlexBuildFromCellListParallel(network->plex, network->cloneshared->nEdges, PETSC_DECIDE, PETSC_DECIDE, 2, edges, NULL, NULL));
6996500d4abSHong Zhang 
700daad07d3SAidan Hamilton   PetscCall(DMPlexGetChart(network->plex, &network->cloneshared->pStart, &network->cloneshared->pEnd));
701daad07d3SAidan Hamilton   PetscCall(DMPlexGetHeightStratum(network->plex, 0, &network->cloneshared->eStart, &network->cloneshared->eEnd));
702daad07d3SAidan Hamilton   PetscCall(DMPlexGetHeightStratum(network->plex, 1, &network->cloneshared->vStart, &network->cloneshared->vEnd));
703daad07d3SAidan Hamilton   np = network->cloneshared->pEnd - network->cloneshared->pStart;
7049566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(np, &network->header, np, &network->cvalue));
705caf410d2SHong Zhang 
706f11a936eSBarry Smith   /* Create edge and vertex arrays for the subnetworks
707f11a936eSBarry Smith      This implementation assumes that DMNetwork reads
708f11a936eSBarry Smith      (1) a single subnetwork in parallel; or
709f11a936eSBarry Smith      (2) n subnetworks using n processors, one subnetwork/processor.
710f11a936eSBarry Smith   */
711daad07d3SAidan Hamilton   PetscCall(PetscCalloc2(network->cloneshared->nEdges, &subnetedge, network->cloneshared->nVertices + network->cloneshared->nsvtx, &subnetvtx)); /* Maps local edge/vertex to local subnetwork's edge/vertex */
712daad07d3SAidan Hamilton   network->cloneshared->subnetedge = subnetedge;
713daad07d3SAidan Hamilton   network->cloneshared->subnetvtx  = subnetvtx;
7145c6496baSHong Zhang   for (j = 0; j < Nsubnet; j++) {
715daad07d3SAidan Hamilton     network->cloneshared->subnet[j].edges = subnetedge;
716daad07d3SAidan Hamilton     subnetedge += network->cloneshared->subnet[j].nedge;
717f11a936eSBarry Smith 
718daad07d3SAidan Hamilton     network->cloneshared->subnet[j].vertices = subnetvtx;
719daad07d3SAidan Hamilton     subnetvtx += network->cloneshared->subnet[j].nvtx;
7206500d4abSHong Zhang   }
721daad07d3SAidan Hamilton   network->cloneshared->svertices = subnetvtx;
722caf410d2SHong Zhang 
723caf410d2SHong Zhang   /* Get edge ownership */
724daad07d3SAidan Hamilton   np = network->cloneshared->eEnd - network->cloneshared->eStart;
7255503a911SAidan Hamilton   PetscCallMPI(MPI_Scan(&np, &globaledgeoff, 1, MPIU_INT, MPI_SUM, comm));
7265503a911SAidan Hamilton   globaledgeoff -= np;
727caf410d2SHong Zhang 
728eac198afSGetnet   /* Setup local edge and vertex arrays for subnetworks */
7292bf73ac6SHong Zhang   e = 0;
7302bf73ac6SHong Zhang   for (i = 0; i < Nsubnet; i++) {
731f11a936eSBarry Smith     ctr = 0;
732daad07d3SAidan Hamilton     for (j = 0; j < network->cloneshared->subnet[i].nedge; j++) {
7332bf73ac6SHong Zhang       /* edge e */
7345503a911SAidan Hamilton       network->header[e].index                 = e + globaledgeoff; /* Global edge index */
7352bf73ac6SHong Zhang       network->header[e].subnetid              = i;
736daad07d3SAidan Hamilton       network->cloneshared->subnet[i].edges[j] = e;
7372bf73ac6SHong Zhang 
7382bf73ac6SHong Zhang       /* connected vertices */
7399566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(network->plex, e, &cone));
7402bf73ac6SHong Zhang 
7412bf73ac6SHong Zhang       /* vertex cone[0] */
742f11a936eSBarry Smith       v                           = cone[0];
743f11a936eSBarry Smith       network->header[v].index    = edges[2 * e]; /* Global vertex index */
744f11a936eSBarry Smith       network->header[v].subnetid = i;            /* Subnetwork id */
745f11a936eSBarry Smith       if (Nsubnet == 1) {
746daad07d3SAidan Hamilton         network->cloneshared->subnet[i].vertices[v - network->cloneshared->vStart] = v; /* user's subnet[].idx = petsc's v */
747f11a936eSBarry Smith       } else {
748daad07d3SAidan Hamilton         vfrom                                           = network->cloneshared->subnet[i].edgelist[2 * ctr]; /* =subnet[i].idx, Global index! */
749daad07d3SAidan Hamilton         network->cloneshared->subnet[i].vertices[vfrom] = v;                                                 /* user's subnet[].dix = petsc's v */
750f11a936eSBarry Smith       }
7512bf73ac6SHong Zhang 
7522bf73ac6SHong Zhang       /* vertex cone[1] */
753f11a936eSBarry Smith       v                           = cone[1];
754f11a936eSBarry Smith       network->header[v].index    = edges[2 * e + 1]; /* Global vertex index */
755f11a936eSBarry Smith       network->header[v].subnetid = i;                /* Subnetwork id */
756f11a936eSBarry Smith       if (Nsubnet == 1) {
757daad07d3SAidan Hamilton         network->cloneshared->subnet[i].vertices[v - network->cloneshared->vStart] = v; /* user's subnet[].idx = petsc's v */
758f11a936eSBarry Smith       } else {
759daad07d3SAidan Hamilton         vto                                           = network->cloneshared->subnet[i].edgelist[2 * ctr + 1]; /* =subnet[i].idx, Global index! */
760daad07d3SAidan Hamilton         network->cloneshared->subnet[i].vertices[vto] = v;                                                     /* user's subnet[].dix = petsc's v */
761f11a936eSBarry Smith       }
7622bf73ac6SHong Zhang 
7639371c9d4SSatish Balay       e++;
7649371c9d4SSatish Balay       ctr++;
7656500d4abSHong Zhang     }
7666500d4abSHong Zhang   }
7675503a911SAidan Hamilton   PetscCall(PetscFree(edges));
768caf410d2SHong Zhang 
769eac198afSGetnet   /* Set local vertex array for the subnetworks */
770eac198afSGetnet   j = 0;
771daad07d3SAidan Hamilton   for (v = network->cloneshared->vStart; v < network->cloneshared->vEnd; v++) {
772eac198afSGetnet     /* local shared vertex */
773daad07d3SAidan Hamilton     PetscCall(PetscTableFind(network->cloneshared->svtable, network->header[v].index + 1, &i));
774daad07d3SAidan Hamilton     if (i) network->cloneshared->svertices[j++] = v;
7756500d4abSHong Zhang   }
776eac198afSGetnet 
777eac198afSGetnet   /* Create a global section to be used by DMNetworkIsGhostVertex() which is a non-collective routine */
778eac198afSGetnet   /* see snes_tutorials_network-ex1_4 */
7799566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(network->plex, &sectiong));
780daad07d3SAidan Hamilton   /* Initialize non-topological data structures  */
781daad07d3SAidan Hamilton   PetscCall(DMNetworkInitializeNonTopological(dm));
782e3b1a053SGetnet Betrie   PetscCall(PetscLogEventEnd(DMNetwork_LayoutSetUp, dm, 0, 0, 0));
7835f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
7845f2c45f1SShri Abhyankar }
7855f2c45f1SShri Abhyankar 
78694ef8ddeSSatish Balay /*@C
7872bf73ac6SHong Zhang   DMNetworkGetSubnetwork - Returns the information about a requested subnetwork
7882bf73ac6SHong Zhang 
7892bf73ac6SHong Zhang   Not collective
7902727e31bSShri Abhyankar 
7917a7aea1fSJed Brown   Input Parameters:
792caf410d2SHong Zhang + dm - the DM object
7932bf73ac6SHong Zhang - netnum - the global index of the subnetwork
7942727e31bSShri Abhyankar 
7957a7aea1fSJed Brown   Output Parameters:
7962727e31bSShri Abhyankar + nv - number of vertices (local)
7972727e31bSShri Abhyankar . ne - number of edges (local)
7982bf73ac6SHong Zhang . vtx - local vertices of the subnetwork
7992bf73ac6SHong Zhang - edge - local edges of the subnetwork
8002727e31bSShri Abhyankar 
8012727e31bSShri Abhyankar   Notes:
8022727e31bSShri Abhyankar     Cannot call this routine before DMNetworkLayoutSetup()
8032727e31bSShri Abhyankar 
804eac198afSGetnet     The local vertices returned on each rank are determined by DMNetwork. The user does not have any control over what vertices are local.
805eac198afSGetnet 
80606dd6b0eSSatish Balay   Level: intermediate
80706dd6b0eSSatish Balay 
808db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `DMNetworkAddSubnetwork()`, `DMNetworkLayoutSetUp()`
8092727e31bSShri Abhyankar @*/
810d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetSubnetwork(DM dm, PetscInt netnum, PetscInt *nv, PetscInt *ne, const PetscInt **vtx, const PetscInt **edge)
811d71ae5a4SJacob Faibussowitsch {
812caf410d2SHong Zhang   DM_Network *network = (DM_Network *)dm->data;
8132727e31bSShri Abhyankar 
8142727e31bSShri Abhyankar   PetscFunctionBegin;
815daad07d3SAidan Hamilton   PetscCheck(netnum < network->cloneshared->Nsubnet, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Subnet index %" PetscInt_FMT " exceeds the num of subnets %" PetscInt_FMT, netnum, network->cloneshared->Nsubnet);
816daad07d3SAidan Hamilton   if (nv) *nv = network->cloneshared->subnet[netnum].nvtx;
817daad07d3SAidan Hamilton   if (ne) *ne = network->cloneshared->subnet[netnum].nedge;
818daad07d3SAidan Hamilton   if (vtx) *vtx = network->cloneshared->subnet[netnum].vertices;
819daad07d3SAidan Hamilton   if (edge) *edge = network->cloneshared->subnet[netnum].edges;
8202bf73ac6SHong Zhang   PetscFunctionReturn(0);
8212bf73ac6SHong Zhang }
8222bf73ac6SHong Zhang 
8232bf73ac6SHong Zhang /*@
8242bf73ac6SHong Zhang   DMNetworkAddSharedVertices - Add shared vertices that connect two given subnetworks
8252bf73ac6SHong Zhang 
8262bf73ac6SHong Zhang   Collective on dm
8272bf73ac6SHong Zhang 
8282bf73ac6SHong Zhang   Input Parameters:
8292bf73ac6SHong Zhang + dm - the dm object
8302bf73ac6SHong Zhang . anetnum - first subnetwork global numbering returned by DMNetworkAddSubnetwork()
8312bf73ac6SHong Zhang . bnetnum - second subnetwork global numbering returned by DMNetworkAddSubnetwork()
8322bf73ac6SHong Zhang . nsvtx - number of vertices that are shared by the two subnetworks
8332bf73ac6SHong Zhang . asvtx - vertex index in the first subnetwork
8342bf73ac6SHong Zhang - bsvtx - vertex index in the second subnetwork
8352bf73ac6SHong Zhang 
8362bf73ac6SHong Zhang   Level: beginner
8372bf73ac6SHong Zhang 
838db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `DMNetworkAddSubnetwork()`, `DMNetworkGetSharedVertices()`
8392bf73ac6SHong Zhang @*/
840d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkAddSharedVertices(DM dm, PetscInt anetnum, PetscInt bnetnum, PetscInt nsvtx, PetscInt asvtx[], PetscInt bsvtx[])
841d71ae5a4SJacob Faibussowitsch {
8422bf73ac6SHong Zhang   DM_Network *network = (DM_Network *)dm->data;
843daad07d3SAidan Hamilton   PetscInt    i, nsubnet = network->cloneshared->Nsubnet, *sedgelist, Nsvtx = network->cloneshared->Nsvtx;
8442bf73ac6SHong Zhang 
8452bf73ac6SHong Zhang   PetscFunctionBegin;
8465c6496baSHong Zhang   PetscCheck(anetnum != bnetnum, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Subnetworks must have different netnum");
8475c6496baSHong Zhang   PetscCheck(anetnum >= 0 && bnetnum >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "netnum cannot be negative");
8482bf73ac6SHong Zhang   if (!Nsvtx) {
8492bf73ac6SHong Zhang     /* allocate network->sedgelist to hold at most 2*nsubnet pairs of shared vertices */
850daad07d3SAidan Hamilton     PetscCall(PetscMalloc1(2 * 4 * nsubnet, &network->cloneshared->sedgelist));
8512bf73ac6SHong Zhang   }
8522bf73ac6SHong Zhang 
853daad07d3SAidan Hamilton   sedgelist = network->cloneshared->sedgelist;
8542bf73ac6SHong Zhang   for (i = 0; i < nsvtx; i++) {
8559371c9d4SSatish Balay     sedgelist[4 * Nsvtx]     = anetnum;
8569371c9d4SSatish Balay     sedgelist[4 * Nsvtx + 1] = asvtx[i];
8579371c9d4SSatish Balay     sedgelist[4 * Nsvtx + 2] = bnetnum;
8589371c9d4SSatish Balay     sedgelist[4 * Nsvtx + 3] = bsvtx[i];
8592bf73ac6SHong Zhang     Nsvtx++;
8602bf73ac6SHong Zhang   }
8615c6496baSHong Zhang   PetscCheck(Nsvtx <= 2 * nsubnet, PETSC_COMM_SELF, PETSC_ERR_SUP, "allocate more space for coupling edgelist");
862daad07d3SAidan Hamilton   network->cloneshared->Nsvtx = Nsvtx;
8632727e31bSShri Abhyankar   PetscFunctionReturn(0);
8642727e31bSShri Abhyankar }
8652727e31bSShri Abhyankar 
8662727e31bSShri Abhyankar /*@C
8672bf73ac6SHong Zhang   DMNetworkGetSharedVertices - Returns the info for the shared vertices
8682bf73ac6SHong Zhang 
8692bf73ac6SHong Zhang   Not collective
870caf410d2SHong Zhang 
871f899ff85SJose E. Roman   Input Parameter:
8722bf73ac6SHong Zhang . dm - the DM object
873caf410d2SHong Zhang 
8747a7aea1fSJed Brown   Output Parameters:
8752bf73ac6SHong Zhang + nsv - number of local shared vertices
8762bf73ac6SHong Zhang - svtx - local shared vertices
877caf410d2SHong Zhang 
878caf410d2SHong Zhang   Notes:
879caf410d2SHong Zhang   Cannot call this routine before DMNetworkLayoutSetup()
880caf410d2SHong Zhang 
881caf410d2SHong Zhang   Level: intermediate
882caf410d2SHong Zhang 
883db781477SPatrick Sanan .seealso: `DMNetworkGetSubnetwork()`, `DMNetworkLayoutSetUp()`, `DMNetworkAddSharedVertices()`
884caf410d2SHong Zhang @*/
885d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetSharedVertices(DM dm, PetscInt *nsv, const PetscInt **svtx)
886d71ae5a4SJacob Faibussowitsch {
887caf410d2SHong Zhang   DM_Network *net = (DM_Network *)dm->data;
888caf410d2SHong Zhang 
889caf410d2SHong Zhang   PetscFunctionBegin;
8905c6496baSHong Zhang   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
891daad07d3SAidan Hamilton   if (nsv) *nsv = net->cloneshared->nsvtx;
892daad07d3SAidan Hamilton   if (svtx) *svtx = net->cloneshared->svertices;
893caf410d2SHong Zhang   PetscFunctionReturn(0);
894caf410d2SHong Zhang }
895caf410d2SHong Zhang 
896caf410d2SHong Zhang /*@C
8975f2c45f1SShri Abhyankar   DMNetworkRegisterComponent - Registers the network component
8985f2c45f1SShri Abhyankar 
899d083f849SBarry Smith   Logically collective on dm
9005f2c45f1SShri Abhyankar 
9017a7aea1fSJed Brown   Input Parameters:
9025f2c45f1SShri Abhyankar + dm - the network object
9035f2c45f1SShri Abhyankar . name - the component name
9045f2c45f1SShri Abhyankar - size - the storage size in bytes for this component data
9055f2c45f1SShri Abhyankar 
9067a7aea1fSJed Brown    Output Parameters:
9075f2c45f1SShri Abhyankar .  key - an integer key that defines the component
9085f2c45f1SShri Abhyankar 
90987497f52SBarry Smith    Note:
91087497f52SBarry Smith    This routine should be called by all processors before calling `DMNetworkLayoutSetup()`.
9115f2c45f1SShri Abhyankar 
91297bb938eSShri Abhyankar    Level: beginner
9135f2c45f1SShri Abhyankar 
914db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `DMNetworkLayoutSetUp()`
9155f2c45f1SShri Abhyankar @*/
916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkRegisterComponent(DM dm, const char *name, size_t size, PetscInt *key)
917d71ae5a4SJacob Faibussowitsch {
9185f2c45f1SShri Abhyankar   DM_Network         *network   = (DM_Network *)dm->data;
91954dfd506SHong Zhang   DMNetworkComponent *component = NULL, *newcomponent = NULL;
9205f2c45f1SShri Abhyankar   PetscBool           flg = PETSC_FALSE;
9215f2c45f1SShri Abhyankar   PetscInt            i;
9225f2c45f1SShri Abhyankar 
9235f2c45f1SShri Abhyankar   PetscFunctionBegin;
92448a46eb9SPierre Jolivet   if (!network->component) PetscCall(PetscCalloc1(network->max_comps_registered, &network->component));
92554dfd506SHong Zhang 
9265f2c45f1SShri Abhyankar   for (i = 0; i < network->ncomponent; i++) {
9279566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(network->component[i].name, name, &flg));
9285f2c45f1SShri Abhyankar     if (flg) {
9295f2c45f1SShri Abhyankar       *key = i;
9305f2c45f1SShri Abhyankar       PetscFunctionReturn(0);
9315f2c45f1SShri Abhyankar     }
9326d64e262SShri Abhyankar   }
93354dfd506SHong Zhang 
93454dfd506SHong Zhang   if (network->ncomponent == network->max_comps_registered) {
93554dfd506SHong Zhang     /* Reached max allowed so resize component */
93654dfd506SHong Zhang     network->max_comps_registered += 2;
9379566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(network->max_comps_registered, &newcomponent));
93854dfd506SHong Zhang     /* Copy over the previous component info */
93954dfd506SHong Zhang     for (i = 0; i < network->ncomponent; i++) {
9409566063dSJacob Faibussowitsch       PetscCall(PetscStrcpy(newcomponent[i].name, network->component[i].name));
94154dfd506SHong Zhang       newcomponent[i].size = network->component[i].size;
9425f2c45f1SShri Abhyankar     }
94354dfd506SHong Zhang     /* Free old one */
9449566063dSJacob Faibussowitsch     PetscCall(PetscFree(network->component));
94554dfd506SHong Zhang     /* Update pointer */
94654dfd506SHong Zhang     network->component = newcomponent;
94754dfd506SHong Zhang   }
94854dfd506SHong Zhang 
94954dfd506SHong Zhang   component = &network->component[network->ncomponent];
9505f2c45f1SShri Abhyankar 
9519566063dSJacob Faibussowitsch   PetscCall(PetscStrcpy(component->name, name));
9525f2c45f1SShri Abhyankar   component->size = size / sizeof(DMNetworkComponentGenericDataType);
9535f2c45f1SShri Abhyankar   *key            = network->ncomponent;
9545f2c45f1SShri Abhyankar   network->ncomponent++;
9555f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9565f2c45f1SShri Abhyankar }
9575f2c45f1SShri Abhyankar 
9585f2c45f1SShri Abhyankar /*@
9592bf73ac6SHong Zhang   DMNetworkGetVertexRange - Get the bounds [start, end) for the local vertices
9605f2c45f1SShri Abhyankar 
9615f2c45f1SShri Abhyankar   Not Collective
9625f2c45f1SShri Abhyankar 
963f899ff85SJose E. Roman   Input Parameter:
9642bf73ac6SHong Zhang . dm - the DMNetwork object
9655f2c45f1SShri Abhyankar 
966fd292e60Sprj-   Output Parameters:
9672bf73ac6SHong Zhang + vStart - the first vertex point
9682bf73ac6SHong Zhang - vEnd - one beyond the last vertex point
9695f2c45f1SShri Abhyankar 
97097bb938eSShri Abhyankar   Level: beginner
9715f2c45f1SShri Abhyankar 
972db781477SPatrick Sanan .seealso: `DMNetworkGetEdgeRange()`
9735f2c45f1SShri Abhyankar @*/
974d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetVertexRange(DM dm, PetscInt *vStart, PetscInt *vEnd)
975d71ae5a4SJacob Faibussowitsch {
9765f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
9775f2c45f1SShri Abhyankar 
9785f2c45f1SShri Abhyankar   PetscFunctionBegin;
979daad07d3SAidan Hamilton   if (vStart) *vStart = network->cloneshared->vStart;
980daad07d3SAidan Hamilton   if (vEnd) *vEnd = network->cloneshared->vEnd;
9815f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
9825f2c45f1SShri Abhyankar }
9835f2c45f1SShri Abhyankar 
9845f2c45f1SShri Abhyankar /*@
9852bf73ac6SHong Zhang   DMNetworkGetEdgeRange - Get the bounds [start, end) for the local edges
9865f2c45f1SShri Abhyankar 
9875f2c45f1SShri Abhyankar   Not Collective
9885f2c45f1SShri Abhyankar 
989f899ff85SJose E. Roman   Input Parameter:
9902bf73ac6SHong Zhang . dm - the DMNetwork object
9915f2c45f1SShri Abhyankar 
992fd292e60Sprj-   Output Parameters:
9935f2c45f1SShri Abhyankar + eStart - The first edge point
9945f2c45f1SShri Abhyankar - eEnd - One beyond the last edge point
9955f2c45f1SShri Abhyankar 
99697bb938eSShri Abhyankar   Level: beginner
9975f2c45f1SShri Abhyankar 
998db781477SPatrick Sanan .seealso: `DMNetworkGetVertexRange()`
9995f2c45f1SShri Abhyankar @*/
1000d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetEdgeRange(DM dm, PetscInt *eStart, PetscInt *eEnd)
1001d71ae5a4SJacob Faibussowitsch {
10025f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
10035f2c45f1SShri Abhyankar 
10045f2c45f1SShri Abhyankar   PetscFunctionBegin;
10055c6496baSHong Zhang   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1006daad07d3SAidan Hamilton   if (eStart) *eStart = network->cloneshared->eStart;
1007daad07d3SAidan Hamilton   if (eEnd) *eEnd = network->cloneshared->eEnd;
10085f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
10095f2c45f1SShri Abhyankar }
10105f2c45f1SShri Abhyankar 
1011d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetIndex(DM dm, PetscInt p, PetscInt *index)
1012d71ae5a4SJacob Faibussowitsch {
10132bf73ac6SHong Zhang   DM_Network *network = (DM_Network *)dm->data;
10145c6496baSHong Zhang 
10155c6496baSHong Zhang   PetscFunctionBegin;
10165c6496baSHong Zhang   if (network->header) {
10175c6496baSHong Zhang     *index = network->header[p].index;
10185c6496baSHong Zhang   } else {
10192bf73ac6SHong Zhang     PetscInt                 offsetp;
10202bf73ac6SHong Zhang     DMNetworkComponentHeader header;
10212bf73ac6SHong Zhang 
10229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(network->DataSection, p, &offsetp));
10232bf73ac6SHong Zhang     header = (DMNetworkComponentHeader)(network->componentdataarray + offsetp);
10242bf73ac6SHong Zhang     *index = header->index;
10255c6496baSHong Zhang   }
10262bf73ac6SHong Zhang   PetscFunctionReturn(0);
10272bf73ac6SHong Zhang }
10282bf73ac6SHong Zhang 
1029d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetSubnetID(DM dm, PetscInt p, PetscInt *subnetid)
1030d71ae5a4SJacob Faibussowitsch {
1031daad07d3SAidan Hamilton   DM_Network *network = (DM_Network *)dm->data;
1032daad07d3SAidan Hamilton 
1033daad07d3SAidan Hamilton   PetscFunctionBegin;
1034daad07d3SAidan Hamilton   if (network->header) {
1035daad07d3SAidan Hamilton     *subnetid = network->header[p].subnetid;
1036daad07d3SAidan Hamilton   } else {
1037daad07d3SAidan Hamilton     PetscInt                 offsetp;
1038daad07d3SAidan Hamilton     DMNetworkComponentHeader header;
1039daad07d3SAidan Hamilton 
1040daad07d3SAidan Hamilton     PetscCall(PetscSectionGetOffset(network->DataSection, p, &offsetp));
1041daad07d3SAidan Hamilton     header    = (DMNetworkComponentHeader)(network->componentdataarray + offsetp);
1042daad07d3SAidan Hamilton     *subnetid = header->subnetid;
1043daad07d3SAidan Hamilton   }
1044daad07d3SAidan Hamilton   PetscFunctionReturn(0);
1045daad07d3SAidan Hamilton }
1046daad07d3SAidan Hamilton 
10477b6afd5bSHong Zhang /*@
10482bf73ac6SHong Zhang   DMNetworkGetGlobalEdgeIndex - Get the global numbering for the edge on the network
10497b6afd5bSHong Zhang 
10507b6afd5bSHong Zhang   Not Collective
10517b6afd5bSHong Zhang 
10527b6afd5bSHong Zhang   Input Parameters:
10537b6afd5bSHong Zhang + dm - DMNetwork object
1054e85e6aecSHong Zhang - p - edge point
10557b6afd5bSHong Zhang 
1056fd292e60Sprj-   Output Parameters:
10572bf73ac6SHong Zhang . index - the global numbering for the edge
10587b6afd5bSHong Zhang 
10597b6afd5bSHong Zhang   Level: intermediate
10607b6afd5bSHong Zhang 
1061db781477SPatrick Sanan .seealso: `DMNetworkGetGlobalVertexIndex()`
10627b6afd5bSHong Zhang @*/
1063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetGlobalEdgeIndex(DM dm, PetscInt p, PetscInt *index)
1064d71ae5a4SJacob Faibussowitsch {
10657b6afd5bSHong Zhang   PetscFunctionBegin;
10669566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetIndex(dm, p, index));
10677b6afd5bSHong Zhang   PetscFunctionReturn(0);
10687b6afd5bSHong Zhang }
10697b6afd5bSHong Zhang 
10705f2c45f1SShri Abhyankar /*@
10712bf73ac6SHong Zhang   DMNetworkGetGlobalVertexIndex - Get the global numbering for the vertex on the network
1072e85e6aecSHong Zhang 
1073e85e6aecSHong Zhang   Not Collective
1074e85e6aecSHong Zhang 
1075e85e6aecSHong Zhang   Input Parameters:
1076e85e6aecSHong Zhang + dm - DMNetwork object
1077e85e6aecSHong Zhang - p  - vertex point
1078e85e6aecSHong Zhang 
1079fd292e60Sprj-   Output Parameters:
10802bf73ac6SHong Zhang . index - the global numbering for the vertex
1081e85e6aecSHong Zhang 
1082e85e6aecSHong Zhang   Level: intermediate
1083e85e6aecSHong Zhang 
1084db781477SPatrick Sanan .seealso: `DMNetworkGetGlobalEdgeIndex()`, `DMNetworkGetLocalVertexIndex()`
1085e85e6aecSHong Zhang @*/
1086d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetGlobalVertexIndex(DM dm, PetscInt p, PetscInt *index)
1087d71ae5a4SJacob Faibussowitsch {
1088e85e6aecSHong Zhang   PetscFunctionBegin;
10899566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetIndex(dm, p, index));
10909988b915SShri Abhyankar   PetscFunctionReturn(0);
10919988b915SShri Abhyankar }
10929988b915SShri Abhyankar 
10939988b915SShri Abhyankar /*@
10945f2c45f1SShri Abhyankar   DMNetworkGetNumComponents - Get the number of components at a vertex/edge
10955f2c45f1SShri Abhyankar 
10965f2c45f1SShri Abhyankar   Not Collective
10975f2c45f1SShri Abhyankar 
10985f2c45f1SShri Abhyankar   Input Parameters:
10992bf73ac6SHong Zhang + dm - the DMNetwork object
1100a2b725a8SWilliam Gropp - p - vertex/edge point
11015f2c45f1SShri Abhyankar 
11025f2c45f1SShri Abhyankar   Output Parameters:
11035f2c45f1SShri Abhyankar . numcomponents - Number of components at the vertex/edge
11045f2c45f1SShri Abhyankar 
110597bb938eSShri Abhyankar   Level: beginner
11065f2c45f1SShri Abhyankar 
1107db781477SPatrick Sanan .seealso: `DMNetworkRegisterComponent()`, `DMNetworkAddComponent()`
11085f2c45f1SShri Abhyankar @*/
1109d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetNumComponents(DM dm, PetscInt p, PetscInt *numcomponents)
1110d71ae5a4SJacob Faibussowitsch {
11115f2c45f1SShri Abhyankar   PetscInt    offset;
11125f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
11135f2c45f1SShri Abhyankar 
11145f2c45f1SShri Abhyankar   PetscFunctionBegin;
11159566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->DataSection, p, &offset));
11165f2c45f1SShri Abhyankar   *numcomponents = ((DMNetworkComponentHeader)(network->componentdataarray + offset))->ndata;
11175f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
11185f2c45f1SShri Abhyankar }
11195f2c45f1SShri Abhyankar 
11205f2c45f1SShri Abhyankar /*@
11212bf73ac6SHong Zhang   DMNetworkGetLocalVecOffset - Get the offset for accessing the variables associated with a component at the given vertex/edge from the local vector
11225f2c45f1SShri Abhyankar 
11235f2c45f1SShri Abhyankar   Not Collective
11245f2c45f1SShri Abhyankar 
11255f2c45f1SShri Abhyankar   Input Parameters:
11262bf73ac6SHong Zhang + dm - the DMNetwork object
1127f2f58720SBarry Smith . p - the edge or vertex point
11282bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
11299988b915SShri Abhyankar 
11309988b915SShri Abhyankar   Output Parameters:
11312bf73ac6SHong Zhang . offset - the local offset
11329988b915SShri Abhyankar 
1133f2f58720SBarry Smith   Notes:
1134f2f58720SBarry Smith     These offsets can be passed to MatSetValuesLocal() for matrices obtained with DMCreateMatrix().
1135f2f58720SBarry Smith 
1136f2f58720SBarry Smith     For vectors obtained with DMCreateLocalVector() the offsets can be used with VecSetValues().
1137f2f58720SBarry Smith 
1138f2f58720SBarry Smith     For vectors obtained with DMCreateLocalVector() and the array obtained with VecGetArray(vec,&array) you can access or set
1139f2f58720SBarry Smith     the vector values with array[offset].
1140f2f58720SBarry Smith 
1141f2f58720SBarry Smith     For vectors obtained with DMCreateGlobalVector() the offsets can be used with VecSetValuesLocal().
1142f2f58720SBarry Smith 
11439988b915SShri Abhyankar   Level: intermediate
11449988b915SShri Abhyankar 
1145db781477SPatrick Sanan .seealso: `DMGetLocalVector()`, `DMNetworkGetComponent()`, `DMNetworkGetGlobalVecOffset()`, `DMCreateGlobalVector()`, `VecGetArray()`, `VecSetValuesLocal()`, `MatSetValuesLocal()`
11469988b915SShri Abhyankar @*/
1147d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetLocalVecOffset(DM dm, PetscInt p, PetscInt compnum, PetscInt *offset)
1148d71ae5a4SJacob Faibussowitsch {
11499988b915SShri Abhyankar   DM_Network              *network = (DM_Network *)dm->data;
11509988b915SShri Abhyankar   PetscInt                 offsetp, offsetd;
11519988b915SShri Abhyankar   DMNetworkComponentHeader header;
11529988b915SShri Abhyankar 
11539988b915SShri Abhyankar   PetscFunctionBegin;
11549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->plex->localSection, p, &offsetp));
11552bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
11562bf73ac6SHong Zhang     *offset = offsetp;
11572bf73ac6SHong Zhang     PetscFunctionReturn(0);
11582bf73ac6SHong Zhang   }
11592bf73ac6SHong Zhang 
11609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->DataSection, p, &offsetd));
11619988b915SShri Abhyankar   header  = (DMNetworkComponentHeader)(network->componentdataarray + offsetd);
11629988b915SShri Abhyankar   *offset = offsetp + header->offsetvarrel[compnum];
11639988b915SShri Abhyankar   PetscFunctionReturn(0);
11649988b915SShri Abhyankar }
11659988b915SShri Abhyankar 
11669988b915SShri Abhyankar /*@
11672bf73ac6SHong Zhang   DMNetworkGetGlobalVecOffset - Get the global offset for accessing the variables associated with a component for the given vertex/edge from the global vector
11689988b915SShri Abhyankar 
11699988b915SShri Abhyankar   Not Collective
11709988b915SShri Abhyankar 
11719988b915SShri Abhyankar   Input Parameters:
11722bf73ac6SHong Zhang + dm - the DMNetwork object
1173f2f58720SBarry Smith . p - the edge or vertex point
11742bf73ac6SHong Zhang - compnum - component number; use ALL_COMPONENTS if no specific component is requested
11759988b915SShri Abhyankar 
11769988b915SShri Abhyankar   Output Parameters:
11779988b915SShri Abhyankar . offsetg - the global offset
11789988b915SShri Abhyankar 
1179f2f58720SBarry Smith   Notes:
1180f2f58720SBarry Smith     These offsets can be passed to MatSetValues() for matrices obtained with DMCreateMatrix().
1181f2f58720SBarry Smith 
1182f2f58720SBarry Smith     For vectors obtained with DMCreateGlobalVector() the offsets can be used with VecSetValues().
1183f2f58720SBarry Smith 
1184f2f58720SBarry Smith     For vectors obtained with DMCreateGlobalVector() and the array obtained with VecGetArray(vec,&array) you can access or set
1185f2f58720SBarry Smith     the vector values with array[offset - rstart] where restart is obtained with VecGetOwnershipRange(v,&rstart,NULL);
1186f2f58720SBarry Smith 
11879988b915SShri Abhyankar   Level: intermediate
11889988b915SShri Abhyankar 
1189db781477SPatrick Sanan .seealso: `DMNetworkGetLocalVecOffset()`, `DMGetGlobalVector()`, `DMNetworkGetComponent()`, `DMCreateGlobalVector()`, `VecGetArray()`, `VecSetValues()`, `MatSetValues()`
11909988b915SShri Abhyankar @*/
1191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetGlobalVecOffset(DM dm, PetscInt p, PetscInt compnum, PetscInt *offsetg)
1192d71ae5a4SJacob Faibussowitsch {
11939988b915SShri Abhyankar   DM_Network              *network = (DM_Network *)dm->data;
11949988b915SShri Abhyankar   PetscInt                 offsetp, offsetd;
11959988b915SShri Abhyankar   DMNetworkComponentHeader header;
11969988b915SShri Abhyankar 
11979988b915SShri Abhyankar   PetscFunctionBegin;
11989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->plex->globalSection, p, &offsetp));
11992bf73ac6SHong Zhang   if (offsetp < 0) offsetp = -(offsetp + 1); /* Convert to actual global offset for ghost vertex */
12002bf73ac6SHong Zhang 
12012bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
12022bf73ac6SHong Zhang     *offsetg = offsetp;
12032bf73ac6SHong Zhang     PetscFunctionReturn(0);
12042bf73ac6SHong Zhang   }
12059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->DataSection, p, &offsetd));
12069988b915SShri Abhyankar   header   = (DMNetworkComponentHeader)(network->componentdataarray + offsetd);
12079988b915SShri Abhyankar   *offsetg = offsetp + header->offsetvarrel[compnum];
12089988b915SShri Abhyankar   PetscFunctionReturn(0);
12099988b915SShri Abhyankar }
12109988b915SShri Abhyankar 
12119988b915SShri Abhyankar /*@
12122bf73ac6SHong Zhang   DMNetworkGetEdgeOffset - Get the offset for accessing the variables associated with the given edge from the local subvector
121324121865SAdrian Maldonado 
121424121865SAdrian Maldonado   Not Collective
121524121865SAdrian Maldonado 
121624121865SAdrian Maldonado   Input Parameters:
12172bf73ac6SHong Zhang + dm - the DMNetwork object
121824121865SAdrian Maldonado - p - the edge point
121924121865SAdrian Maldonado 
122024121865SAdrian Maldonado   Output Parameters:
122124121865SAdrian Maldonado . offset - the offset
122224121865SAdrian Maldonado 
122324121865SAdrian Maldonado   Level: intermediate
122424121865SAdrian Maldonado 
1225db781477SPatrick Sanan .seealso: `DMNetworkGetLocalVecOffset()`, `DMGetLocalVector()`
122624121865SAdrian Maldonado @*/
1227d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetEdgeOffset(DM dm, PetscInt p, PetscInt *offset)
1228d71ae5a4SJacob Faibussowitsch {
122924121865SAdrian Maldonado   DM_Network *network = (DM_Network *)dm->data;
123024121865SAdrian Maldonado 
123124121865SAdrian Maldonado   PetscFunctionBegin;
12329566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->edge.DofSection, p, offset));
123324121865SAdrian Maldonado   PetscFunctionReturn(0);
123424121865SAdrian Maldonado }
123524121865SAdrian Maldonado 
123624121865SAdrian Maldonado /*@
12372bf73ac6SHong Zhang   DMNetworkGetVertexOffset - Get the offset for accessing the variables associated with the given vertex from the local subvector
123824121865SAdrian Maldonado 
123924121865SAdrian Maldonado   Not Collective
124024121865SAdrian Maldonado 
124124121865SAdrian Maldonado   Input Parameters:
12422bf73ac6SHong Zhang + dm - the DMNetwork object
124324121865SAdrian Maldonado - p - the vertex point
124424121865SAdrian Maldonado 
124524121865SAdrian Maldonado   Output Parameters:
124624121865SAdrian Maldonado . offset - the offset
124724121865SAdrian Maldonado 
124824121865SAdrian Maldonado   Level: intermediate
124924121865SAdrian Maldonado 
1250db781477SPatrick Sanan .seealso: `DMNetworkGetEdgeOffset()`, `DMGetLocalVector()`
125124121865SAdrian Maldonado @*/
1252d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetVertexOffset(DM dm, PetscInt p, PetscInt *offset)
1253d71ae5a4SJacob Faibussowitsch {
125424121865SAdrian Maldonado   DM_Network *network = (DM_Network *)dm->data;
125524121865SAdrian Maldonado 
125624121865SAdrian Maldonado   PetscFunctionBegin;
1257daad07d3SAidan Hamilton   p -= network->cloneshared->vStart;
12589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->vertex.DofSection, p, offset));
125924121865SAdrian Maldonado   PetscFunctionReturn(0);
126024121865SAdrian Maldonado }
12612bf73ac6SHong Zhang 
12625f2c45f1SShri Abhyankar /*@
12632bf73ac6SHong Zhang   DMNetworkAddComponent - Adds a network component and number of variables at the given point (vertex/edge)
12645f2c45f1SShri Abhyankar 
1265eac198afSGetnet   Collective on dm
12665f2c45f1SShri Abhyankar 
12675f2c45f1SShri Abhyankar   Input Parameters:
12684dc646bcSBarry Smith + dm - the DMNetwork
1269eac198afSGetnet . p - the vertex/edge point. These points are local indices provided by DMNetworkGetSubnetwork()
1270eac198afSGetnet . componentkey - component key returned while registering the component with DMNetworkRegisterComponent()
127124359064SBarry Smith . compvalue - pointer to the data structure for the component, or NULL if the component does not require data, this data is not copied so you cannot
127224359064SBarry Smith               free this space until after DMSetUp() is called.
1273eac198afSGetnet - nvar - number of variables for the component at the vertex/edge point, zero if the component does not introduce any degrees of freedom at the point
12745f2c45f1SShri Abhyankar 
1275eac198afSGetnet   Notes:
1276eac198afSGetnet     The owning rank and any other ranks that have this point as a ghost location must call this routine to add a component and number of variables in the same order at the given point.
1277eac198afSGetnet 
1278eac198afSGetnet     DMNetworkLayoutSetUp() must be called before this routine.
1279eac198afSGetnet 
1280eac198afSGetnet   Developer Notes:
1281eac198afSGetnet      The requirement that all the ranks with access to a vertex (as owner or as ghost) add all the components comes from a limitation of the underlying implementation based on DMPLEX.
128297bb938eSShri Abhyankar   Level: beginner
12835f2c45f1SShri Abhyankar 
1284db781477SPatrick Sanan .seealso: `DMNetworkGetComponent()`, `DMNetworkGetSubnetwork()`, `DMNetworkIsGhostVertex()`, `DMNetworkLayoutSetUp()`
12855f2c45f1SShri Abhyankar @*/
1286d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkAddComponent(DM dm, PetscInt p, PetscInt componentkey, void *compvalue, PetscInt nvar)
1287d71ae5a4SJacob Faibussowitsch {
12885f2c45f1SShri Abhyankar   DM_Network              *network   = (DM_Network *)dm->data;
12892bf73ac6SHong Zhang   DMNetworkComponent      *component = &network->component[componentkey];
129054dfd506SHong Zhang   DMNetworkComponentHeader header;
129154dfd506SHong Zhang   DMNetworkComponentValue  cvalue;
129254dfd506SHong Zhang   PetscInt                 compnum;
129354dfd506SHong Zhang   PetscInt                *compsize, *compkey, *compoffset, *compnvar, *compoffsetvarrel;
129454dfd506SHong Zhang   void                   **compdata;
12955f2c45f1SShri Abhyankar 
12965f2c45f1SShri Abhyankar   PetscFunctionBegin;
12975c6496baSHong Zhang   PetscCheck(componentkey >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "componentkey %" PetscInt_FMT " cannot be negative. Input a component key returned while registering the component with DMNetworkRegisterComponent()", componentkey);
1298daad07d3SAidan Hamilton   PetscCheck(network->componentsetup == PETSC_FALSE, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "The network has already finalized the components. No new components can be added.");
1299eac198afSGetnet   /* The owning rank and all ghost ranks add nvar */
13009566063dSJacob Faibussowitsch   PetscCall(PetscSectionAddDof(network->DofSection, p, nvar));
13012bf73ac6SHong Zhang 
1302eac198afSGetnet   /* The owning rank and all ghost ranks add a component, including compvalue=NULL */
130354dfd506SHong Zhang   header = &network->header[p];
130454dfd506SHong Zhang   cvalue = &network->cvalue[p];
130554dfd506SHong Zhang   if (header->ndata == header->maxcomps) {
1306f11a936eSBarry Smith     PetscInt additional_size;
1307f11a936eSBarry Smith 
130854dfd506SHong Zhang     /* Reached limit so resize header component arrays */
130954dfd506SHong Zhang     header->maxcomps += 2;
131054dfd506SHong Zhang 
131154dfd506SHong Zhang     /* Allocate arrays for component information and value */
13129566063dSJacob Faibussowitsch     PetscCall(PetscCalloc5(header->maxcomps, &compsize, header->maxcomps, &compkey, header->maxcomps, &compoffset, header->maxcomps, &compnvar, header->maxcomps, &compoffsetvarrel));
13139566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(header->maxcomps, &compdata));
131454dfd506SHong Zhang 
131554dfd506SHong Zhang     /* Recalculate header size */
131654dfd506SHong Zhang     header->hsize = sizeof(struct _p_DMNetworkComponentHeader) + 5 * header->maxcomps * sizeof(PetscInt);
131754dfd506SHong Zhang 
131854dfd506SHong Zhang     header->hsize /= sizeof(DMNetworkComponentGenericDataType);
131954dfd506SHong Zhang 
132054dfd506SHong Zhang     /* Copy over component info */
13219566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(compsize, header->size, header->ndata * sizeof(PetscInt)));
13229566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(compkey, header->key, header->ndata * sizeof(PetscInt)));
13239566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(compoffset, header->offset, header->ndata * sizeof(PetscInt)));
13249566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(compnvar, header->nvar, header->ndata * sizeof(PetscInt)));
13259566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(compoffsetvarrel, header->offsetvarrel, header->ndata * sizeof(PetscInt)));
132654dfd506SHong Zhang 
132754dfd506SHong Zhang     /* Copy over component data pointers */
13289566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(compdata, cvalue->data, header->ndata * sizeof(void *)));
132954dfd506SHong Zhang 
133054dfd506SHong Zhang     /* Free old arrays */
13319566063dSJacob Faibussowitsch     PetscCall(PetscFree5(header->size, header->key, header->offset, header->nvar, header->offsetvarrel));
13329566063dSJacob Faibussowitsch     PetscCall(PetscFree(cvalue->data));
133354dfd506SHong Zhang 
133454dfd506SHong Zhang     /* Update pointers */
133554dfd506SHong Zhang     header->size         = compsize;
133654dfd506SHong Zhang     header->key          = compkey;
133754dfd506SHong Zhang     header->offset       = compoffset;
133854dfd506SHong Zhang     header->nvar         = compnvar;
133954dfd506SHong Zhang     header->offsetvarrel = compoffsetvarrel;
134054dfd506SHong Zhang 
134154dfd506SHong Zhang     cvalue->data = compdata;
134254dfd506SHong Zhang 
134354dfd506SHong Zhang     /* Update DataSection Dofs */
134454dfd506SHong 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 */
1345f11a936eSBarry Smith     additional_size = (5 * (header->maxcomps - header->ndata) * sizeof(PetscInt)) / sizeof(DMNetworkComponentGenericDataType);
13469566063dSJacob Faibussowitsch     PetscCall(PetscSectionAddDof(network->DataSection, p, additional_size));
134754dfd506SHong Zhang   }
134854dfd506SHong Zhang   header = &network->header[p];
134954dfd506SHong Zhang   cvalue = &network->cvalue[p];
135054dfd506SHong Zhang 
135154dfd506SHong Zhang   compnum = header->ndata;
13522bf73ac6SHong Zhang 
13532bf73ac6SHong Zhang   header->size[compnum] = component->size;
13549566063dSJacob Faibussowitsch   PetscCall(PetscSectionAddDof(network->DataSection, p, component->size));
13552bf73ac6SHong Zhang   header->key[compnum] = componentkey;
13562bf73ac6SHong Zhang   if (compnum != 0) header->offset[compnum] = header->offset[compnum - 1] + header->size[compnum - 1];
13572bf73ac6SHong Zhang   cvalue->data[compnum] = (void *)compvalue;
13582bf73ac6SHong Zhang 
13592bf73ac6SHong Zhang   /* variables */
13602bf73ac6SHong Zhang   header->nvar[compnum] += nvar;
13612bf73ac6SHong Zhang   if (compnum != 0) header->offsetvarrel[compnum] = header->offsetvarrel[compnum - 1] + header->nvar[compnum - 1];
13622bf73ac6SHong Zhang 
13632bf73ac6SHong Zhang   header->ndata++;
13645f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
13655f2c45f1SShri Abhyankar }
13665f2c45f1SShri Abhyankar 
136727f51fceSHong Zhang /*@
13682bf73ac6SHong Zhang   DMNetworkGetComponent - Gets the component key, the component data, and the number of variables at a given network point
136927f51fceSHong Zhang 
137027f51fceSHong Zhang   Not Collective
137127f51fceSHong Zhang 
137227f51fceSHong Zhang   Input Parameters:
13732bf73ac6SHong Zhang + dm - the DMNetwork object
13742bf73ac6SHong Zhang . p - vertex/edge point
137599c90e12SSatish Balay - compnum - component number; use ALL_COMPONENTS if sum up all the components
137627f51fceSHong Zhang 
137727f51fceSHong Zhang   Output Parameters:
13782bf73ac6SHong Zhang + compkey - the key obtained when registering the component (use NULL if not required)
13792bf73ac6SHong Zhang . component - the component data (use NULL if not required)
13802bf73ac6SHong Zhang - nvar  - number of variables (use NULL if not required)
138127f51fceSHong Zhang 
138297bb938eSShri Abhyankar   Level: beginner
138327f51fceSHong Zhang 
1384db781477SPatrick Sanan .seealso: `DMNetworkAddComponent()`, `DMNetworkGetNumComponents()`
138527f51fceSHong Zhang @*/
1386d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetComponent(DM dm, PetscInt p, PetscInt compnum, PetscInt *compkey, void **component, PetscInt *nvar)
1387d71ae5a4SJacob Faibussowitsch {
138827f51fceSHong Zhang   DM_Network              *network = (DM_Network *)dm->data;
13892bf73ac6SHong Zhang   PetscInt                 offset  = 0;
13902bf73ac6SHong Zhang   DMNetworkComponentHeader header;
139127f51fceSHong Zhang 
139227f51fceSHong Zhang   PetscFunctionBegin;
13932bf73ac6SHong Zhang   if (compnum == ALL_COMPONENTS) {
13949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(network->DofSection, p, nvar));
139527f51fceSHong Zhang     PetscFunctionReturn(0);
139627f51fceSHong Zhang   }
139727f51fceSHong Zhang 
13989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->DataSection, p, &offset));
139942dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray + offset);
14005f2c45f1SShri Abhyankar 
14012bf73ac6SHong Zhang   if (compnum >= 0) {
14022bf73ac6SHong Zhang     if (compkey) *compkey = header->key[compnum];
14032bf73ac6SHong Zhang     if (component) {
140454dfd506SHong Zhang       offset += header->hsize + header->offset[compnum];
14052bf73ac6SHong Zhang       *component = network->componentdataarray + offset;
14062bf73ac6SHong Zhang     }
14072bf73ac6SHong Zhang   }
14085f2c45f1SShri Abhyankar 
14092bf73ac6SHong Zhang   if (nvar) *nvar = header->nvar[compnum];
141054dfd506SHong Zhang 
14115f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14125f2c45f1SShri Abhyankar }
14135f2c45f1SShri Abhyankar 
14142bf73ac6SHong Zhang /*
14152bf73ac6SHong Zhang  Sets up the array that holds the data for all components and its associated section.
14162bf73ac6SHong 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.
14172bf73ac6SHong Zhang */
1418d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkComponentSetUp(DM dm)
1419d71ae5a4SJacob Faibussowitsch {
14205f2c45f1SShri Abhyankar   DM_Network                        *network = (DM_Network *)dm->data;
1421f11a936eSBarry Smith   PetscInt                           arr_size, p, offset, offsetp, ncomp, i, *headerarr;
14225f2c45f1SShri Abhyankar   DMNetworkComponentHeader           header;
14235f2c45f1SShri Abhyankar   DMNetworkComponentValue            cvalue;
1424f11a936eSBarry Smith   DMNetworkComponentHeader           headerinfo;
14255f2c45f1SShri Abhyankar   DMNetworkComponentGenericDataType *componentdataarray;
14265f2c45f1SShri Abhyankar 
14275f2c45f1SShri Abhyankar   PetscFunctionBegin;
14289566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(network->DataSection));
14299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(network->DataSection, &arr_size));
1430f11a936eSBarry Smith   /* arr_size+1 fixes pipeline test of opensolaris-misc for src/dm/tests/ex10.c -- Do not know why */
14319566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(arr_size + 1, &network->componentdataarray));
14325f2c45f1SShri Abhyankar   componentdataarray = network->componentdataarray;
1433daad07d3SAidan Hamilton   for (p = network->cloneshared->pStart; p < network->cloneshared->pEnd; p++) {
14349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(network->DataSection, p, &offsetp));
14355f2c45f1SShri Abhyankar     /* Copy header */
14365f2c45f1SShri Abhyankar     header     = &network->header[p];
1437f11a936eSBarry Smith     headerinfo = (DMNetworkComponentHeader)(componentdataarray + offsetp);
14389566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(headerinfo, header, sizeof(struct _p_DMNetworkComponentHeader)));
1439f11a936eSBarry Smith     headerarr = (PetscInt *)(headerinfo + 1);
14409566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(headerarr, header->size, header->maxcomps * sizeof(PetscInt)));
1441aeb78aa7SBarry Smith     headerinfo->size = headerarr;
144254dfd506SHong Zhang     headerarr += header->maxcomps;
14439566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(headerarr, header->key, header->maxcomps * sizeof(PetscInt)));
1444aeb78aa7SBarry Smith     headerinfo->key = headerarr;
144554dfd506SHong Zhang     headerarr += header->maxcomps;
14469566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(headerarr, header->offset, header->maxcomps * sizeof(PetscInt)));
1447aeb78aa7SBarry Smith     headerinfo->offset = headerarr;
144854dfd506SHong Zhang     headerarr += header->maxcomps;
14499566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(headerarr, header->nvar, header->maxcomps * sizeof(PetscInt)));
1450aeb78aa7SBarry Smith     headerinfo->nvar = headerarr;
145154dfd506SHong Zhang     headerarr += header->maxcomps;
14529566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(headerarr, header->offsetvarrel, header->maxcomps * sizeof(PetscInt)));
1453aeb78aa7SBarry Smith     headerinfo->offsetvarrel = headerarr;
145454dfd506SHong Zhang 
14555f2c45f1SShri Abhyankar     /* Copy data */
14565f2c45f1SShri Abhyankar     cvalue = &network->cvalue[p];
14575f2c45f1SShri Abhyankar     ncomp  = header->ndata;
14582bf73ac6SHong Zhang 
14595f2c45f1SShri Abhyankar     for (i = 0; i < ncomp; i++) {
146054dfd506SHong Zhang       offset = offsetp + header->hsize + header->offset[i];
14619566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(componentdataarray + offset, cvalue->data[i], header->size[i] * sizeof(DMNetworkComponentGenericDataType)));
14625f2c45f1SShri Abhyankar     }
14635f2c45f1SShri Abhyankar   }
1464aeb78aa7SBarry Smith 
1465daad07d3SAidan Hamilton   for (i = network->cloneshared->pStart; i < network->cloneshared->pEnd; i++) {
1466aeb78aa7SBarry Smith     PetscCall(PetscFree5(network->header[i].size, network->header[i].key, network->header[i].offset, network->header[i].nvar, network->header[i].offsetvarrel));
1467aeb78aa7SBarry Smith     PetscCall(PetscFree(network->cvalue[i].data));
1468aeb78aa7SBarry Smith   }
1469aeb78aa7SBarry Smith   PetscCall(PetscFree2(network->header, network->cvalue));
14705f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14715f2c45f1SShri Abhyankar }
14725f2c45f1SShri Abhyankar 
14735f2c45f1SShri Abhyankar /* Sets up the section for dofs. This routine is called during DMSetUp() */
1474d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMNetworkVariablesSetUp(DM dm)
1475d71ae5a4SJacob Faibussowitsch {
14765f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
14775f2c45f1SShri Abhyankar 
14785f2c45f1SShri Abhyankar   PetscFunctionBegin;
14799566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(network->DofSection));
14805f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
14815f2c45f1SShri Abhyankar }
14825f2c45f1SShri Abhyankar 
148324121865SAdrian Maldonado /* Get a subsection from a range of points */
1484d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMNetworkGetSubSection_private(PetscSection main, PetscInt pstart, PetscInt pend, PetscSection *subsection)
1485d71ae5a4SJacob Faibussowitsch {
148624121865SAdrian Maldonado   PetscInt i, nvar;
148724121865SAdrian Maldonado 
148824121865SAdrian Maldonado   PetscFunctionBegin;
14899566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)main), subsection));
14909566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*subsection, 0, pend - pstart));
149124121865SAdrian Maldonado   for (i = pstart; i < pend; i++) {
14929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(main, i, &nvar));
14939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(*subsection, i - pstart, nvar));
149424121865SAdrian Maldonado   }
149524121865SAdrian Maldonado 
14969566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*subsection));
149724121865SAdrian Maldonado   PetscFunctionReturn(0);
149824121865SAdrian Maldonado }
149924121865SAdrian Maldonado 
150024121865SAdrian Maldonado /* Create a submap of points with a GlobalToLocal structure */
1501d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMNetworkSetSubMap_private(PetscInt pstart, PetscInt pend, ISLocalToGlobalMapping *map)
1502d71ae5a4SJacob Faibussowitsch {
150324121865SAdrian Maldonado   PetscInt i, *subpoints;
150424121865SAdrian Maldonado 
150524121865SAdrian Maldonado   PetscFunctionBegin;
150624121865SAdrian Maldonado   /* Create index sets to map from "points" to "subpoints" */
15079566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pend - pstart, &subpoints));
1508ad540459SPierre Jolivet   for (i = pstart; i < pend; i++) subpoints[i - pstart] = i;
15099566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD, 1, pend - pstart, subpoints, PETSC_COPY_VALUES, map));
15109566063dSJacob Faibussowitsch   PetscCall(PetscFree(subpoints));
151124121865SAdrian Maldonado   PetscFunctionReturn(0);
151224121865SAdrian Maldonado }
151324121865SAdrian Maldonado 
151424121865SAdrian Maldonado /*@
15152bf73ac6SHong Zhang   DMNetworkAssembleGraphStructures - Assembles vertex and edge data structures. Must be called after DMNetworkDistribute
151624121865SAdrian Maldonado 
15172bf73ac6SHong Zhang   Collective on dm
151824121865SAdrian Maldonado 
151924121865SAdrian Maldonado   Input Parameters:
15202bf73ac6SHong Zhang . dm - the DMNetworkObject
152124121865SAdrian Maldonado 
152224121865SAdrian Maldonado   Note: the routine will create alternative orderings for the vertices and edges. Assume global network points are:
152324121865SAdrian Maldonado 
152424121865SAdrian Maldonado   points = [0 1 2 3 4 5 6]
152524121865SAdrian Maldonado 
1526caf410d2SHong 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]).
152724121865SAdrian Maldonado 
152824121865SAdrian Maldonado   With this new ordering a local PetscSection, global PetscSection and PetscSF will be created specific to the subset.
152924121865SAdrian Maldonado 
153024121865SAdrian Maldonado   Level: intermediate
153124121865SAdrian Maldonado 
153224121865SAdrian Maldonado @*/
1533d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkAssembleGraphStructures(DM dm)
1534d71ae5a4SJacob Faibussowitsch {
153524121865SAdrian Maldonado   MPI_Comm    comm;
1536f11a936eSBarry Smith   PetscMPIInt size;
153724121865SAdrian Maldonado   DM_Network *network = (DM_Network *)dm->data;
153824121865SAdrian Maldonado 
1539eab1376dSHong Zhang   PetscFunctionBegin;
15409566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
15419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
154224121865SAdrian Maldonado 
154324121865SAdrian Maldonado   /* Create maps for vertices and edges */
1544daad07d3SAidan Hamilton   PetscCall(DMNetworkSetSubMap_private(network->cloneshared->vStart, network->cloneshared->vEnd, &network->vertex.mapping));
1545daad07d3SAidan Hamilton   PetscCall(DMNetworkSetSubMap_private(network->cloneshared->eStart, network->cloneshared->eEnd, &network->edge.mapping));
154624121865SAdrian Maldonado 
154724121865SAdrian Maldonado   /* Create local sub-sections */
1548daad07d3SAidan Hamilton   PetscCall(DMNetworkGetSubSection_private(network->DofSection, network->cloneshared->vStart, network->cloneshared->vEnd, &network->vertex.DofSection));
1549daad07d3SAidan Hamilton   PetscCall(DMNetworkGetSubSection_private(network->DofSection, network->cloneshared->eStart, network->cloneshared->eEnd, &network->edge.DofSection));
155024121865SAdrian Maldonado 
15519852e123SBarry Smith   if (size > 1) {
15529566063dSJacob Faibussowitsch     PetscCall(PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf));
155322bbedd7SHong Zhang 
15549566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(network->vertex.DofSection, network->vertex.sf, PETSC_FALSE, PETSC_FALSE, &network->vertex.GlobalDofSection));
15559566063dSJacob Faibussowitsch     PetscCall(PetscSFGetSubSF(network->plex->sf, network->edge.mapping, &network->edge.sf));
15569566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(network->edge.DofSection, network->edge.sf, PETSC_FALSE, PETSC_FALSE, &network->edge.GlobalDofSection));
155724121865SAdrian Maldonado   } else {
155824121865SAdrian Maldonado     /* create structures for vertex */
15599566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(network->vertex.DofSection, &network->vertex.GlobalDofSection));
156024121865SAdrian Maldonado     /* create structures for edge */
15619566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(network->edge.DofSection, &network->edge.GlobalDofSection));
156224121865SAdrian Maldonado   }
156324121865SAdrian Maldonado 
156424121865SAdrian Maldonado   /* Add viewers */
15659566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)network->edge.GlobalDofSection, "Global edge dof section"));
15669566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)network->vertex.GlobalDofSection, "Global vertex dof section"));
15679566063dSJacob Faibussowitsch   PetscCall(PetscSectionViewFromOptions(network->edge.GlobalDofSection, NULL, "-edge_global_section_view"));
15689566063dSJacob Faibussowitsch   PetscCall(PetscSectionViewFromOptions(network->vertex.GlobalDofSection, NULL, "-vertex_global_section_view"));
156924121865SAdrian Maldonado   PetscFunctionReturn(0);
157024121865SAdrian Maldonado }
15717b6afd5bSHong Zhang 
1572f11a936eSBarry Smith /*
15735c6496baSHong Zhang    Setup a lookup btable for the input v's owning subnetworks
15745c6496baSHong Zhang    - add all owing subnetworks that connect to this v to the btable
1575f11a936eSBarry Smith      vertex_subnetid = supportingedge_subnetid
1576f11a936eSBarry Smith */
1577d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode SetSubnetIdLookupBT(DM dm, PetscInt v, PetscInt Nsubnet, PetscBT btable)
1578d71ae5a4SJacob Faibussowitsch {
1579f11a936eSBarry Smith   PetscInt                 e, nedges, offset;
1580f11a936eSBarry Smith   const PetscInt          *edges;
1581f11a936eSBarry Smith   DM_Network              *newDMnetwork = (DM_Network *)dm->data;
1582f11a936eSBarry Smith   DMNetworkComponentHeader header;
1583f11a936eSBarry Smith 
1584f11a936eSBarry Smith   PetscFunctionBegin;
15859566063dSJacob Faibussowitsch   PetscCall(PetscBTMemzero(Nsubnet, btable));
15869566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetSupportingEdges(dm, v, &nedges, &edges));
1587f11a936eSBarry Smith   for (e = 0; e < nedges; e++) {
15889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(newDMnetwork->DataSection, edges[e], &offset));
1589f11a936eSBarry Smith     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray + offset);
15909566063dSJacob Faibussowitsch     PetscCall(PetscBTSet(btable, header->subnetid));
1591f11a936eSBarry Smith   }
1592f11a936eSBarry Smith   PetscFunctionReturn(0);
1593f11a936eSBarry Smith }
1594f11a936eSBarry Smith 
15955f2c45f1SShri Abhyankar /*@
15962bf73ac6SHong Zhang   DMNetworkDistribute - Distributes the network and moves associated component data
15975f2c45f1SShri Abhyankar 
15985f2c45f1SShri Abhyankar   Collective
15995f2c45f1SShri Abhyankar 
1600d8d19677SJose E. Roman   Input Parameters:
1601d3464fd4SAdrian Maldonado + DM - the DMNetwork object
16022bf73ac6SHong Zhang - overlap - the overlap of partitions, 0 is the default
16035f2c45f1SShri Abhyankar 
16045b3f975aSHong Zhang   Options Database Key:
16055b3f975aSHong Zhang + -dmnetwork_view - Calls DMView() at the conclusion of DMSetUp()
16065b3f975aSHong Zhang - -dmnetwork_view_distributed - Calls DMView() at the conclusion of DMNetworkDistribute()
16075b3f975aSHong Zhang 
16085f2c45f1SShri Abhyankar   Notes:
16098b171c8eSHong Zhang   Distributes the network with <overlap>-overlapping partitioning of the edges.
16105f2c45f1SShri Abhyankar 
16115f2c45f1SShri Abhyankar   Level: intermediate
16125f2c45f1SShri Abhyankar 
1613db781477SPatrick Sanan .seealso: `DMNetworkCreate()`
16145f2c45f1SShri Abhyankar @*/
1615d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkDistribute(DM *dm, PetscInt overlap)
1616d71ae5a4SJacob Faibussowitsch {
1617d3464fd4SAdrian Maldonado   MPI_Comm                 comm;
1618d3464fd4SAdrian Maldonado   PetscMPIInt              size;
1619d3464fd4SAdrian Maldonado   DM_Network              *oldDMnetwork = (DM_Network *)((*dm)->data);
1620d3464fd4SAdrian Maldonado   DM_Network              *newDMnetwork;
1621caf410d2SHong Zhang   PetscSF                  pointsf = NULL;
16225f2c45f1SShri Abhyankar   DM                       newDM;
1623f11a936eSBarry Smith   PetscInt                 j, e, v, offset, *subnetvtx, *subnetedge, Nsubnet, gidx, svtx_idx, nv;
16245c6496baSHong Zhang   PetscInt                 net, *sv;
1625f11a936eSBarry Smith   PetscBT                  btable;
162651ac5effSHong Zhang   PetscPartitioner         part;
1627b9c6e19dSShri Abhyankar   DMNetworkComponentHeader header;
16285f2c45f1SShri Abhyankar 
16295f2c45f1SShri Abhyankar   PetscFunctionBegin;
16305c6496baSHong Zhang   PetscValidPointer(dm, 1);
16315c6496baSHong Zhang   PetscValidHeaderSpecific(*dm, DM_CLASSID, 1);
16329566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)*dm, &comm));
16339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1634d3464fd4SAdrian Maldonado   if (size == 1) PetscFunctionReturn(0);
1635d3464fd4SAdrian Maldonado 
16365c6496baSHong Zhang   PetscCheck(!overlap, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "overlap %" PetscInt_FMT " != 0 is not supported yet", overlap);
16375b3f975aSHong Zhang 
16382bf73ac6SHong 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. */
1639e3b1a053SGetnet Betrie   PetscCall(PetscLogEventBegin(DMNetwork_Distribute, dm, 0, 0, 0));
16409566063dSJacob Faibussowitsch   PetscCall(DMNetworkCreate(PetscObjectComm((PetscObject)*dm), &newDM));
16415f2c45f1SShri Abhyankar   newDMnetwork                       = (DM_Network *)newDM->data;
164254dfd506SHong Zhang   newDMnetwork->max_comps_registered = oldDMnetwork->max_comps_registered;
16439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(newDMnetwork->max_comps_registered, &newDMnetwork->component));
164451ac5effSHong Zhang 
164551ac5effSHong Zhang   /* Enable runtime options for petscpartitioner */
16469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetPartitioner(oldDMnetwork->plex, &part));
16479566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(part));
164851ac5effSHong Zhang 
16492bf73ac6SHong Zhang   /* Distribute plex dm */
16509566063dSJacob Faibussowitsch   PetscCall(DMPlexDistribute(oldDMnetwork->plex, overlap, &pointsf, &newDMnetwork->plex));
165151ac5effSHong Zhang 
16525f2c45f1SShri Abhyankar   /* Distribute dof section */
16539566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &newDMnetwork->DofSection));
16549566063dSJacob Faibussowitsch   PetscCall(PetscSFDistributeSection(pointsf, oldDMnetwork->DofSection, NULL, newDMnetwork->DofSection));
165551ac5effSHong Zhang 
16565f2c45f1SShri Abhyankar   /* Distribute data and associated section */
16579566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &newDMnetwork->DataSection));
16589566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeData(newDMnetwork->plex, pointsf, oldDMnetwork->DataSection, MPIU_INT, (void *)oldDMnetwork->componentdataarray, newDMnetwork->DataSection, (void **)&newDMnetwork->componentdataarray));
165924121865SAdrian Maldonado 
1660daad07d3SAidan Hamilton   PetscCall(PetscSectionGetChart(newDMnetwork->DataSection, &newDMnetwork->cloneshared->pStart, &newDMnetwork->cloneshared->pEnd));
1661daad07d3SAidan Hamilton   PetscCall(DMPlexGetHeightStratum(newDMnetwork->plex, 0, &newDMnetwork->cloneshared->eStart, &newDMnetwork->cloneshared->eEnd));
1662daad07d3SAidan Hamilton   PetscCall(DMPlexGetHeightStratum(newDMnetwork->plex, 1, &newDMnetwork->cloneshared->vStart, &newDMnetwork->cloneshared->vEnd));
1663daad07d3SAidan Hamilton   newDMnetwork->cloneshared->nEdges    = newDMnetwork->cloneshared->eEnd - newDMnetwork->cloneshared->eStart;
1664daad07d3SAidan Hamilton   newDMnetwork->cloneshared->nVertices = newDMnetwork->cloneshared->vEnd - newDMnetwork->cloneshared->vStart;
1665daad07d3SAidan Hamilton   newDMnetwork->cloneshared->NVertices = oldDMnetwork->cloneshared->NVertices;
1666daad07d3SAidan Hamilton   newDMnetwork->cloneshared->NEdges    = oldDMnetwork->cloneshared->NEdges;
1667daad07d3SAidan Hamilton   newDMnetwork->cloneshared->svtable   = oldDMnetwork->cloneshared->svtable; /* global table! */
1668daad07d3SAidan Hamilton   oldDMnetwork->cloneshared->svtable   = NULL;
166924121865SAdrian Maldonado 
16701bb6d2a8SBarry Smith   /* Set Dof section as the section for dm */
16719566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(newDMnetwork->plex, newDMnetwork->DofSection));
16729566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(newDMnetwork->plex, &newDMnetwork->GlobalDofSection));
16735f2c45f1SShri Abhyankar 
1674b9c6e19dSShri Abhyankar   /* Setup subnetwork info in the newDM */
1675daad07d3SAidan Hamilton   newDMnetwork->cloneshared->Nsubnet = oldDMnetwork->cloneshared->Nsubnet;
1676daad07d3SAidan Hamilton   newDMnetwork->cloneshared->Nsvtx   = oldDMnetwork->cloneshared->Nsvtx;
1677daad07d3SAidan Hamilton   oldDMnetwork->cloneshared->Nsvtx   = 0;
1678daad07d3SAidan Hamilton   newDMnetwork->cloneshared->svtx    = oldDMnetwork->cloneshared->svtx; /* global vertices! */
1679daad07d3SAidan Hamilton   oldDMnetwork->cloneshared->svtx    = NULL;
1680daad07d3SAidan Hamilton   PetscCall(PetscCalloc1(newDMnetwork->cloneshared->Nsubnet, &newDMnetwork->cloneshared->subnet));
16812bf73ac6SHong Zhang 
16822bf73ac6SHong Zhang   /* Copy over the global number of vertices and edges in each subnetwork.
16832bf73ac6SHong Zhang      Note: these are calculated in DMNetworkLayoutSetUp()
1684b9c6e19dSShri Abhyankar   */
1685daad07d3SAidan Hamilton   Nsubnet = newDMnetwork->cloneshared->Nsubnet;
1686f11a936eSBarry Smith   for (j = 0; j < Nsubnet; j++) {
1687daad07d3SAidan Hamilton     newDMnetwork->cloneshared->subnet[j].Nvtx  = oldDMnetwork->cloneshared->subnet[j].Nvtx;
1688daad07d3SAidan Hamilton     newDMnetwork->cloneshared->subnet[j].Nedge = oldDMnetwork->cloneshared->subnet[j].Nedge;
1689b9c6e19dSShri Abhyankar   }
1690b9c6e19dSShri Abhyankar 
1691f11a936eSBarry Smith   /* Count local nedges for subnetworks */
1692daad07d3SAidan Hamilton   for (e = newDMnetwork->cloneshared->eStart; e < newDMnetwork->cloneshared->eEnd; e++) {
16939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(newDMnetwork->DataSection, e, &offset));
169454dfd506SHong Zhang     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray + offset);
16955c6496baSHong Zhang 
169654dfd506SHong Zhang     /* Update pointers */
169754dfd506SHong Zhang     header->size         = (PetscInt *)(header + 1);
169854dfd506SHong Zhang     header->key          = header->size + header->maxcomps;
169954dfd506SHong Zhang     header->offset       = header->key + header->maxcomps;
170054dfd506SHong Zhang     header->nvar         = header->offset + header->maxcomps;
170154dfd506SHong Zhang     header->offsetvarrel = header->nvar + header->maxcomps;
170254dfd506SHong Zhang 
1703daad07d3SAidan Hamilton     newDMnetwork->cloneshared->subnet[header->subnetid].nedge++;
1704b9c6e19dSShri Abhyankar   }
1705b9c6e19dSShri Abhyankar 
17065c6496baSHong Zhang   /* Setup a btable to keep track subnetworks owned by this process at a shared vertex */
170748a46eb9SPierre Jolivet   if (newDMnetwork->cloneshared->Nsvtx) PetscCall(PetscBTCreate(Nsubnet, &btable));
17085c6496baSHong Zhang 
17095c6496baSHong Zhang   /* Count local nvtx for subnetworks */
1710daad07d3SAidan Hamilton   for (v = newDMnetwork->cloneshared->vStart; v < newDMnetwork->cloneshared->vEnd; v++) {
17119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(newDMnetwork->DataSection, v, &offset));
17125f80ce2aSJacob Faibussowitsch     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray + offset);
17135c6496baSHong Zhang 
171454dfd506SHong Zhang     /* Update pointers */
171554dfd506SHong Zhang     header->size         = (PetscInt *)(header + 1);
171654dfd506SHong Zhang     header->key          = header->size + header->maxcomps;
171754dfd506SHong Zhang     header->offset       = header->key + header->maxcomps;
171854dfd506SHong Zhang     header->nvar         = header->offset + header->maxcomps;
171954dfd506SHong Zhang     header->offsetvarrel = header->nvar + header->maxcomps;
172054dfd506SHong Zhang 
17212bf73ac6SHong Zhang     /* shared vertices: use gidx=header->index to check if v is a shared vertex */
17222bf73ac6SHong Zhang     gidx = header->index;
1723daad07d3SAidan Hamilton     PetscCall(PetscTableFind(newDMnetwork->cloneshared->svtable, gidx + 1, &svtx_idx));
17242bf73ac6SHong Zhang     svtx_idx--;
17252bf73ac6SHong Zhang 
17262bf73ac6SHong Zhang     if (svtx_idx < 0) { /* not a shared vertex */
1727daad07d3SAidan Hamilton       newDMnetwork->cloneshared->subnet[header->subnetid].nvtx++;
17282bf73ac6SHong Zhang     } else { /* a shared vertex belongs to more than one subnetworks, it is being counted by multiple subnets */
17295c6496baSHong Zhang       /* Setup a lookup btable for this v's owning subnetworks */
17309566063dSJacob Faibussowitsch       PetscCall(SetSubnetIdLookupBT(newDM, v, Nsubnet, btable));
1731f11a936eSBarry Smith 
1732daad07d3SAidan Hamilton       for (j = 0; j < newDMnetwork->cloneshared->svtx[svtx_idx].n; j++) {
1733daad07d3SAidan Hamilton         sv  = newDMnetwork->cloneshared->svtx[svtx_idx].sv + 2 * j;
17345c6496baSHong Zhang         net = sv[0];
1735*35cb6cd3SPierre Jolivet         if (PetscBTLookup(btable, net)) newDMnetwork->cloneshared->subnet[net].nvtx++; /* sv is on net owned by this process */
17362bf73ac6SHong Zhang       }
17372bf73ac6SHong Zhang     }
1738b9c6e19dSShri Abhyankar   }
1739b9c6e19dSShri Abhyankar 
17402bf73ac6SHong Zhang   /* Get total local nvtx for subnetworks */
17412bf73ac6SHong Zhang   nv = 0;
1742daad07d3SAidan Hamilton   for (j = 0; j < Nsubnet; j++) nv += newDMnetwork->cloneshared->subnet[j].nvtx;
1743daad07d3SAidan Hamilton   nv += newDMnetwork->cloneshared->Nsvtx;
1744caf410d2SHong Zhang 
17452bf73ac6SHong Zhang   /* Now create the vertices and edge arrays for the subnetworks */
1746daad07d3SAidan Hamilton   PetscCall(PetscCalloc2(newDMnetwork->cloneshared->nEdges, &subnetedge, nv, &subnetvtx)); /* Maps local vertex to local subnetwork's vertex */
1747daad07d3SAidan Hamilton   newDMnetwork->cloneshared->subnetedge = subnetedge;
1748daad07d3SAidan Hamilton   newDMnetwork->cloneshared->subnetvtx  = subnetvtx;
1749daad07d3SAidan Hamilton   for (j = 0; j < newDMnetwork->cloneshared->Nsubnet; j++) {
1750daad07d3SAidan Hamilton     newDMnetwork->cloneshared->subnet[j].edges = subnetedge;
1751daad07d3SAidan Hamilton     subnetedge += newDMnetwork->cloneshared->subnet[j].nedge;
17522bf73ac6SHong Zhang 
1753daad07d3SAidan Hamilton     newDMnetwork->cloneshared->subnet[j].vertices = subnetvtx;
1754daad07d3SAidan Hamilton     subnetvtx += newDMnetwork->cloneshared->subnet[j].nvtx;
1755caf410d2SHong Zhang 
17562bf73ac6SHong 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. */
1757daad07d3SAidan Hamilton     newDMnetwork->cloneshared->subnet[j].nvtx = newDMnetwork->cloneshared->subnet[j].nedge = 0;
1758b9c6e19dSShri Abhyankar   }
1759daad07d3SAidan Hamilton   newDMnetwork->cloneshared->svertices = subnetvtx;
1760b9c6e19dSShri Abhyankar 
17612bf73ac6SHong Zhang   /* Set the edges and vertices in each subnetwork */
1762daad07d3SAidan Hamilton   for (e = newDMnetwork->cloneshared->eStart; e < newDMnetwork->cloneshared->eEnd; e++) {
17639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(newDMnetwork->DataSection, e, &offset));
17645f80ce2aSJacob Faibussowitsch     header                                                                                                                 = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray + offset);
1765daad07d3SAidan Hamilton     newDMnetwork->cloneshared->subnet[header->subnetid].edges[newDMnetwork->cloneshared->subnet[header->subnetid].nedge++] = e;
1766b9c6e19dSShri Abhyankar   }
1767b9c6e19dSShri Abhyankar 
17682bf73ac6SHong Zhang   nv = 0;
1769daad07d3SAidan Hamilton   for (v = newDMnetwork->cloneshared->vStart; v < newDMnetwork->cloneshared->vEnd; v++) {
17709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(newDMnetwork->DataSection, v, &offset));
17715f80ce2aSJacob Faibussowitsch     header = (DMNetworkComponentHeader)(newDMnetwork->componentdataarray + offset);
17722bf73ac6SHong Zhang 
17732bf73ac6SHong Zhang     /* coupling vertices: use gidx = header->index to check if v is a coupling vertex */
1774daad07d3SAidan Hamilton     PetscCall(PetscTableFind(newDMnetwork->cloneshared->svtable, header->index + 1, &svtx_idx));
17752bf73ac6SHong Zhang     svtx_idx--;
17762bf73ac6SHong Zhang     if (svtx_idx < 0) {
1777daad07d3SAidan Hamilton       newDMnetwork->cloneshared->subnet[header->subnetid].vertices[newDMnetwork->cloneshared->subnet[header->subnetid].nvtx++] = v;
17782bf73ac6SHong Zhang     } else { /* a shared vertex */
1779daad07d3SAidan Hamilton       newDMnetwork->cloneshared->svertices[nv++] = v;
17802bf73ac6SHong Zhang 
17815c6496baSHong Zhang       /* Setup a lookup btable for this v's owning subnetworks */
17829566063dSJacob Faibussowitsch       PetscCall(SetSubnetIdLookupBT(newDM, v, Nsubnet, btable));
1783f11a936eSBarry Smith 
1784daad07d3SAidan Hamilton       for (j = 0; j < newDMnetwork->cloneshared->svtx[svtx_idx].n; j++) {
1785daad07d3SAidan Hamilton         sv  = newDMnetwork->cloneshared->svtx[svtx_idx].sv + 2 * j;
17865c6496baSHong Zhang         net = sv[0];
17879371c9d4SSatish Balay         if (PetscBTLookup(btable, net)) newDMnetwork->cloneshared->subnet[net].vertices[newDMnetwork->cloneshared->subnet[net].nvtx++] = v;
1788b9c6e19dSShri Abhyankar       }
17892bf73ac6SHong Zhang     }
17902bf73ac6SHong Zhang   }
1791daad07d3SAidan Hamilton   newDMnetwork->cloneshared->nsvtx = nv; /* num of local shared vertices */
1792b9c6e19dSShri Abhyankar 
1793caf410d2SHong Zhang   newDM->setupcalled                          = (*dm)->setupcalled;
1794daad07d3SAidan Hamilton   newDMnetwork->cloneshared->distributecalled = PETSC_TRUE;
1795caf410d2SHong Zhang 
17962bf73ac6SHong Zhang   /* Free spaces */
17979566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&pointsf));
17989566063dSJacob Faibussowitsch   PetscCall(DMDestroy(dm));
179948a46eb9SPierre Jolivet   if (newDMnetwork->cloneshared->Nsvtx) PetscCall(PetscBTDestroy(&btable));
18002bf73ac6SHong Zhang 
18015b3f975aSHong Zhang   /* View distributed dmnetwork */
18029566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(newDM, NULL, "-dmnetwork_view_distributed"));
18035b3f975aSHong Zhang 
1804d3464fd4SAdrian Maldonado   *dm = newDM;
1805e3b1a053SGetnet Betrie   PetscCall(PetscLogEventEnd(DMNetwork_Distribute, dm, 0, 0, 0));
18065f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
18075f2c45f1SShri Abhyankar }
18085f2c45f1SShri Abhyankar 
180924121865SAdrian Maldonado /*@C
18102bf73ac6SHong Zhang   PetscSFGetSubSF - Returns an SF for a specific subset of points. Leaves are re-numbered to reflect the new ordering
18112bf73ac6SHong Zhang 
18122bf73ac6SHong Zhang  Collective
181324121865SAdrian Maldonado 
181424121865SAdrian Maldonado   Input Parameters:
18159dddd249SSatish Balay + mainSF - the original SF structure
181624121865SAdrian Maldonado - map - a ISLocalToGlobal mapping that contains the subset of points
181724121865SAdrian Maldonado 
181897bb3fdcSJose E. Roman   Output Parameter:
18199dddd249SSatish Balay . subSF - a subset of the mainSF for the desired subset.
1820ee300463SSatish Balay 
1821ee300463SSatish Balay   Level: intermediate
18227d928bffSSatish Balay @*/
1823d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFGetSubSF(PetscSF mainsf, ISLocalToGlobalMapping map, PetscSF *subSF)
1824d71ae5a4SJacob Faibussowitsch {
182524121865SAdrian Maldonado   PetscInt           nroots, nleaves, *ilocal_sub;
182624121865SAdrian Maldonado   PetscInt           i, *ilocal_map, nroots_sub, nleaves_sub = 0;
182724121865SAdrian Maldonado   PetscInt          *local_points, *remote_points;
182824121865SAdrian Maldonado   PetscSFNode       *iremote_sub;
182924121865SAdrian Maldonado   const PetscInt    *ilocal;
183024121865SAdrian Maldonado   const PetscSFNode *iremote;
183124121865SAdrian Maldonado 
183224121865SAdrian Maldonado   PetscFunctionBegin;
18339566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(mainsf, &nroots, &nleaves, &ilocal, &iremote));
183424121865SAdrian Maldonado 
183524121865SAdrian Maldonado   /* Look for leaves that pertain to the subset of points. Get the local ordering */
18369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nleaves, &ilocal_map));
18379566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(map, IS_GTOLM_MASK, nleaves, ilocal, NULL, ilocal_map));
183824121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
183924121865SAdrian Maldonado     if (ilocal_map[i] != -1) nleaves_sub += 1;
184024121865SAdrian Maldonado   }
184124121865SAdrian Maldonado   /* Re-number ilocal with subset numbering. Need information from roots */
18429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nroots, &local_points, nroots, &remote_points));
184324121865SAdrian Maldonado   for (i = 0; i < nroots; i++) local_points[i] = i;
18449566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(map, IS_GTOLM_MASK, nroots, local_points, NULL, local_points));
18459566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(mainsf, MPIU_INT, local_points, remote_points, MPI_REPLACE));
18469566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(mainsf, MPIU_INT, local_points, remote_points, MPI_REPLACE));
184724121865SAdrian Maldonado   /* Fill up graph using local (that is, local to the subset) numbering. */
18489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nleaves_sub, &ilocal_sub));
18499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nleaves_sub, &iremote_sub));
185024121865SAdrian Maldonado   nleaves_sub = 0;
185124121865SAdrian Maldonado   for (i = 0; i < nleaves; i++) {
185224121865SAdrian Maldonado     if (ilocal_map[i] != -1) {
185324121865SAdrian Maldonado       ilocal_sub[nleaves_sub]        = ilocal_map[i];
18544b70a8deSAdrian Maldonado       iremote_sub[nleaves_sub].rank  = iremote[i].rank;
185524121865SAdrian Maldonado       iremote_sub[nleaves_sub].index = remote_points[ilocal[i]];
185624121865SAdrian Maldonado       nleaves_sub += 1;
185724121865SAdrian Maldonado     }
185824121865SAdrian Maldonado   }
18599566063dSJacob Faibussowitsch   PetscCall(PetscFree2(local_points, remote_points));
18609566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(map, &nroots_sub));
186124121865SAdrian Maldonado 
186224121865SAdrian Maldonado   /* Create new subSF */
18639566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD, subSF));
18649566063dSJacob Faibussowitsch   PetscCall(PetscSFSetFromOptions(*subSF));
18659566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(*subSF, nroots_sub, nleaves_sub, ilocal_sub, PETSC_OWN_POINTER, iremote_sub, PETSC_COPY_VALUES));
18669566063dSJacob Faibussowitsch   PetscCall(PetscFree(ilocal_map));
18679566063dSJacob Faibussowitsch   PetscCall(PetscFree(iremote_sub));
186824121865SAdrian Maldonado   PetscFunctionReturn(0);
186924121865SAdrian Maldonado }
187024121865SAdrian Maldonado 
18715f2c45f1SShri Abhyankar /*@C
18725f2c45f1SShri Abhyankar   DMNetworkGetSupportingEdges - Return the supporting edges for this vertex point
18735f2c45f1SShri Abhyankar 
18745f2c45f1SShri Abhyankar   Not Collective
18755f2c45f1SShri Abhyankar 
18765f2c45f1SShri Abhyankar   Input Parameters:
18772bf73ac6SHong Zhang + dm - the DMNetwork object
18785f2c45f1SShri Abhyankar - p  - the vertex point
18795f2c45f1SShri Abhyankar 
1880fd292e60Sprj-   Output Parameters:
18815f2c45f1SShri Abhyankar + nedges - number of edges connected to this vertex point
18822bf73ac6SHong Zhang - edges  - list of edge points
18835f2c45f1SShri Abhyankar 
188497bb938eSShri Abhyankar   Level: beginner
18855f2c45f1SShri Abhyankar 
18865f2c45f1SShri Abhyankar   Fortran Notes:
18875f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
18885f2c45f1SShri Abhyankar   include petsc.h90 in your code.
18895f2c45f1SShri Abhyankar 
1890db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `DMNetworkGetConnectedVertices()`
18915f2c45f1SShri Abhyankar @*/
1892d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetSupportingEdges(DM dm, PetscInt vertex, PetscInt *nedges, const PetscInt *edges[])
1893d71ae5a4SJacob Faibussowitsch {
18945f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
18955f2c45f1SShri Abhyankar 
18965f2c45f1SShri Abhyankar   PetscFunctionBegin;
18979566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSize(network->plex, vertex, nedges));
18989566063dSJacob Faibussowitsch   if (edges) PetscCall(DMPlexGetSupport(network->plex, vertex, edges));
18995f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19005f2c45f1SShri Abhyankar }
19015f2c45f1SShri Abhyankar 
19025f2c45f1SShri Abhyankar /*@C
1903d842c372SHong Zhang   DMNetworkGetConnectedVertices - Return the connected vertices for this edge point
19045f2c45f1SShri Abhyankar 
19055f2c45f1SShri Abhyankar   Not Collective
19065f2c45f1SShri Abhyankar 
19075f2c45f1SShri Abhyankar   Input Parameters:
19082bf73ac6SHong Zhang + dm - the DMNetwork object
19095f2c45f1SShri Abhyankar - p - the edge point
19105f2c45f1SShri Abhyankar 
1911fd292e60Sprj-   Output Parameters:
19125f2c45f1SShri Abhyankar . vertices - vertices connected to this edge
19135f2c45f1SShri Abhyankar 
191497bb938eSShri Abhyankar   Level: beginner
19155f2c45f1SShri Abhyankar 
19165f2c45f1SShri Abhyankar   Fortran Notes:
19175f2c45f1SShri Abhyankar   Since it returns an array, this routine is only available in Fortran 90, and you must
19185f2c45f1SShri Abhyankar   include petsc.h90 in your code.
19195f2c45f1SShri Abhyankar 
1920db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `DMNetworkGetSupportingEdges()`
19215f2c45f1SShri Abhyankar @*/
1922d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetConnectedVertices(DM dm, PetscInt edge, const PetscInt *vertices[])
1923d71ae5a4SJacob Faibussowitsch {
19245f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
19255f2c45f1SShri Abhyankar 
19265f2c45f1SShri Abhyankar   PetscFunctionBegin;
19279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(network->plex, edge, vertices));
19285f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
19295f2c45f1SShri Abhyankar }
19305f2c45f1SShri Abhyankar 
19315f2c45f1SShri Abhyankar /*@
19322bf73ac6SHong Zhang   DMNetworkIsSharedVertex - Returns TRUE if the vertex is shared by subnetworks
19332bf73ac6SHong Zhang 
19342bf73ac6SHong Zhang   Not Collective
19352bf73ac6SHong Zhang 
19362bf73ac6SHong Zhang   Input Parameters:
19372bf73ac6SHong Zhang + dm - the DMNetwork object
19382bf73ac6SHong Zhang - p - the vertex point
19392bf73ac6SHong Zhang 
19402bf73ac6SHong Zhang   Output Parameter:
19412bf73ac6SHong Zhang . flag - TRUE if the vertex is shared by subnetworks
19422bf73ac6SHong Zhang 
19432bf73ac6SHong Zhang   Level: beginner
19442bf73ac6SHong Zhang 
1945db781477SPatrick Sanan .seealso: `DMNetworkAddSharedVertices()`, `DMNetworkIsGhostVertex()`
19462bf73ac6SHong Zhang @*/
1947d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkIsSharedVertex(DM dm, PetscInt p, PetscBool *flag)
1948d71ae5a4SJacob Faibussowitsch {
19492bf73ac6SHong Zhang   PetscInt i;
19502bf73ac6SHong Zhang 
19512bf73ac6SHong Zhang   PetscFunctionBegin;
19522bf73ac6SHong Zhang   *flag = PETSC_FALSE;
19532bf73ac6SHong Zhang 
19542bf73ac6SHong Zhang   if (dm->setupcalled) { /* DMNetworkGetGlobalVertexIndex() requires DMSetUp() be called */
19552bf73ac6SHong Zhang     DM_Network *network = (DM_Network *)dm->data;
19562bf73ac6SHong Zhang     PetscInt    gidx;
19579566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetGlobalVertexIndex(dm, p, &gidx));
1958daad07d3SAidan Hamilton     PetscCall(PetscTableFind(network->cloneshared->svtable, gidx + 1, &i));
19592bf73ac6SHong Zhang     if (i) *flag = PETSC_TRUE;
19602bf73ac6SHong Zhang   } else { /* would be removed? */
19612bf73ac6SHong Zhang     PetscInt        nv;
19622bf73ac6SHong Zhang     const PetscInt *vtx;
19639566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetSharedVertices(dm, &nv, &vtx));
19642bf73ac6SHong Zhang     for (i = 0; i < nv; i++) {
19652bf73ac6SHong Zhang       if (p == vtx[i]) {
19662bf73ac6SHong Zhang         *flag = PETSC_TRUE;
19672bf73ac6SHong Zhang         break;
19682bf73ac6SHong Zhang       }
19692bf73ac6SHong Zhang     }
19702bf73ac6SHong Zhang   }
19712bf73ac6SHong Zhang   PetscFunctionReturn(0);
19722bf73ac6SHong Zhang }
19732bf73ac6SHong Zhang 
19742bf73ac6SHong Zhang /*@
19755f2c45f1SShri Abhyankar   DMNetworkIsGhostVertex - Returns TRUE if the vertex is a ghost vertex
19765f2c45f1SShri Abhyankar 
19775f2c45f1SShri Abhyankar   Not Collective
19785f2c45f1SShri Abhyankar 
19795f2c45f1SShri Abhyankar   Input Parameters:
19802bf73ac6SHong Zhang + dm - the DMNetwork object
1981a2b725a8SWilliam Gropp - p - the vertex point
19825f2c45f1SShri Abhyankar 
19835f2c45f1SShri Abhyankar   Output Parameter:
19845f2c45f1SShri Abhyankar . isghost - TRUE if the vertex is a ghost point
19855f2c45f1SShri Abhyankar 
198697bb938eSShri Abhyankar   Level: beginner
19875f2c45f1SShri Abhyankar 
1988db781477SPatrick Sanan .seealso: `DMNetworkGetConnectedVertices()`, `DMNetworkGetVertexRange()`, `DMNetworkIsSharedVertex()`
19895f2c45f1SShri Abhyankar @*/
1990d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkIsGhostVertex(DM dm, PetscInt p, PetscBool *isghost)
1991d71ae5a4SJacob Faibussowitsch {
19925f2c45f1SShri Abhyankar   DM_Network  *network = (DM_Network *)dm->data;
19935f2c45f1SShri Abhyankar   PetscInt     offsetg;
19945f2c45f1SShri Abhyankar   PetscSection sectiong;
19955f2c45f1SShri Abhyankar 
19965f2c45f1SShri Abhyankar   PetscFunctionBegin;
19975f2c45f1SShri Abhyankar   *isghost = PETSC_FALSE;
19989566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(network->plex, &sectiong));
19999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(sectiong, p, &offsetg));
20005f2c45f1SShri Abhyankar   if (offsetg < 0) *isghost = PETSC_TRUE;
20015f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20025f2c45f1SShri Abhyankar }
20035f2c45f1SShri Abhyankar 
2004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Network(DM dm)
2005d71ae5a4SJacob Faibussowitsch {
20065f2c45f1SShri Abhyankar   PetscFunctionBegin;
2007e3b1a053SGetnet Betrie   PetscCall(PetscLogEventBegin(DMNetwork_SetUpNetwork, dm, 0, 0, 0));
2008daad07d3SAidan Hamilton   PetscCall(DMNetworkFinalizeComponents(dm));
20095b3f975aSHong Zhang   /* View dmnetwork */
20109566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-dmnetwork_view"));
2011e3b1a053SGetnet Betrie   PetscCall(PetscLogEventEnd(DMNetwork_SetUpNetwork, dm, 0, 0, 0));
20125f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
20135f2c45f1SShri Abhyankar }
20145f2c45f1SShri Abhyankar 
20151ad426b7SHong Zhang /*@
201617df6e9eSHong Zhang   DMNetworkHasJacobian - Sets global flag for using user's sub Jacobian matrices
20171ad426b7SHong Zhang       -- replaced by DMNetworkSetOption(network,userjacobian,PETSC_TURE)?
20181ad426b7SHong Zhang 
20191ad426b7SHong Zhang   Collective
20201ad426b7SHong Zhang 
20211ad426b7SHong Zhang   Input Parameters:
20222bf73ac6SHong Zhang + dm - the DMNetwork object
202383b2e829SHong Zhang . eflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for edges
202483b2e829SHong Zhang - vflg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE) if user provides Jacobian for vertices
20251ad426b7SHong Zhang 
20261ad426b7SHong Zhang  Level: intermediate
20271ad426b7SHong Zhang 
20281ad426b7SHong Zhang @*/
2029d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkHasJacobian(DM dm, PetscBool eflg, PetscBool vflg)
2030d71ae5a4SJacob Faibussowitsch {
20311ad426b7SHong Zhang   DM_Network *network   = (DM_Network *)dm->data;
2032daad07d3SAidan Hamilton   PetscInt    nVertices = network->cloneshared->nVertices;
20331ad426b7SHong Zhang 
20341ad426b7SHong Zhang   PetscFunctionBegin;
203583b2e829SHong Zhang   network->userEdgeJacobian   = eflg;
203683b2e829SHong Zhang   network->userVertexJacobian = vflg;
20378675203cSHong Zhang 
203848a46eb9SPierre Jolivet   if (eflg && !network->Je) PetscCall(PetscCalloc1(3 * network->cloneshared->nEdges, &network->Je));
20398675203cSHong Zhang 
204066b4e0ffSHong Zhang   if (vflg && !network->Jv && nVertices) {
2041daad07d3SAidan Hamilton     PetscInt        i, *vptr, nedges, vStart = network->cloneshared->vStart;
204266b4e0ffSHong Zhang     PetscInt        nedges_total;
20438675203cSHong Zhang     const PetscInt *edges;
20448675203cSHong Zhang 
20458675203cSHong Zhang     /* count nvertex_total */
20468675203cSHong Zhang     nedges_total = 0;
20479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nVertices + 1, &vptr));
20488675203cSHong Zhang 
20498675203cSHong Zhang     vptr[0] = 0;
20508675203cSHong Zhang     for (i = 0; i < nVertices; i++) {
20519566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetSupportingEdges(dm, i + vStart, &nedges, &edges));
20528675203cSHong Zhang       nedges_total += nedges;
20538675203cSHong Zhang       vptr[i + 1] = vptr[i] + 2 * nedges + 1;
20548675203cSHong Zhang     }
20558675203cSHong Zhang 
20569566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(2 * nedges_total + nVertices, &network->Jv));
20578675203cSHong Zhang     network->Jvptr = vptr;
20588675203cSHong Zhang   }
20591ad426b7SHong Zhang   PetscFunctionReturn(0);
20601ad426b7SHong Zhang }
20611ad426b7SHong Zhang 
20621ad426b7SHong Zhang /*@
206383b2e829SHong Zhang   DMNetworkEdgeSetMatrix - Sets user-provided Jacobian matrices for this edge to the network
206483b2e829SHong Zhang 
206583b2e829SHong Zhang   Not Collective
206683b2e829SHong Zhang 
206783b2e829SHong Zhang   Input Parameters:
20682bf73ac6SHong Zhang + dm - the DMNetwork object
206983b2e829SHong Zhang . p - the edge point
20703e97b6e8SHong Zhang - J - array (size = 3) of Jacobian submatrices for this edge point:
20713e97b6e8SHong Zhang         J[0]: this edge
2072d842c372SHong Zhang         J[1] and J[2]: connected vertices, obtained by calling DMNetworkGetConnectedVertices()
207383b2e829SHong Zhang 
207497bb938eSShri Abhyankar   Level: advanced
207583b2e829SHong Zhang 
2076db781477SPatrick Sanan .seealso: `DMNetworkVertexSetMatrix()`
207783b2e829SHong Zhang @*/
2078d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkEdgeSetMatrix(DM dm, PetscInt p, Mat J[])
2079d71ae5a4SJacob Faibussowitsch {
208083b2e829SHong Zhang   DM_Network *network = (DM_Network *)dm->data;
208183b2e829SHong Zhang 
208283b2e829SHong Zhang   PetscFunctionBegin;
20835c6496baSHong Zhang   PetscCheck(network->Je, PetscObjectComm((PetscObject)dm), PETSC_ERR_ORDER, "Must call DMNetworkHasJacobian() collectively before calling DMNetworkEdgeSetMatrix");
20848675203cSHong Zhang 
20858675203cSHong Zhang   if (J) {
2086883e35e8SHong Zhang     network->Je[3 * p]     = J[0];
2087883e35e8SHong Zhang     network->Je[3 * p + 1] = J[1];
2088883e35e8SHong Zhang     network->Je[3 * p + 2] = J[2];
20898675203cSHong Zhang   }
209083b2e829SHong Zhang   PetscFunctionReturn(0);
209183b2e829SHong Zhang }
209283b2e829SHong Zhang 
209383b2e829SHong Zhang /*@
209476ddfea5SHong Zhang   DMNetworkVertexSetMatrix - Sets user-provided Jacobian matrix for this vertex to the network
20951ad426b7SHong Zhang 
20961ad426b7SHong Zhang   Not Collective
20971ad426b7SHong Zhang 
20981ad426b7SHong Zhang   Input Parameters:
20991ad426b7SHong Zhang + dm - The DMNetwork object
21001ad426b7SHong Zhang . p - the vertex point
21013e97b6e8SHong Zhang - J - array of Jacobian (size = 2*(num of supporting edges) + 1) submatrices for this vertex point:
21023e97b6e8SHong Zhang         J[0]:       this vertex
21033e97b6e8SHong Zhang         J[1+2*i]:   i-th supporting edge
21043e97b6e8SHong Zhang         J[1+2*i+1]: i-th connected vertex
21051ad426b7SHong Zhang 
210697bb938eSShri Abhyankar   Level: advanced
21071ad426b7SHong Zhang 
2108db781477SPatrick Sanan .seealso: `DMNetworkEdgeSetMatrix()`
21091ad426b7SHong Zhang @*/
2110d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkVertexSetMatrix(DM dm, PetscInt p, Mat J[])
2111d71ae5a4SJacob Faibussowitsch {
21125f2c45f1SShri Abhyankar   DM_Network     *network = (DM_Network *)dm->data;
2113daad07d3SAidan Hamilton   PetscInt        i, *vptr, nedges, vStart = network->cloneshared->vStart;
2114883e35e8SHong Zhang   const PetscInt *edges;
21155f2c45f1SShri Abhyankar 
21165f2c45f1SShri Abhyankar   PetscFunctionBegin;
21175c6496baSHong Zhang   PetscCheck(network->Jv, PetscObjectComm((PetscObject)dm), PETSC_ERR_ORDER, "Must call DMNetworkHasJacobian() collectively before calling DMNetworkVertexSetMatrix");
2118883e35e8SHong Zhang 
21198675203cSHong Zhang   if (J) {
2120883e35e8SHong Zhang     vptr                          = network->Jvptr;
21213e97b6e8SHong Zhang     network->Jv[vptr[p - vStart]] = J[0]; /* Set Jacobian for this vertex */
21223e97b6e8SHong Zhang 
21233e97b6e8SHong Zhang     /* Set Jacobian for each supporting edge and connected vertex */
21249566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetSupportingEdges(dm, p, &nedges, &edges));
2125883e35e8SHong Zhang     for (i = 1; i <= 2 * nedges; i++) network->Jv[vptr[p - vStart] + i] = J[i];
21268675203cSHong Zhang   }
2127883e35e8SHong Zhang   PetscFunctionReturn(0);
2128883e35e8SHong Zhang }
2129883e35e8SHong Zhang 
2130d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode MatSetPreallocationDenseblock_private(PetscInt nrows, PetscInt *rows, PetscInt ncols, PetscBool ghost, Vec vdnz, Vec vonz)
2131d71ae5a4SJacob Faibussowitsch {
21325cf7da58SHong Zhang   PetscInt    j;
21335cf7da58SHong Zhang   PetscScalar val = (PetscScalar)ncols;
21345cf7da58SHong Zhang 
21355cf7da58SHong Zhang   PetscFunctionBegin;
21365cf7da58SHong Zhang   if (!ghost) {
213748a46eb9SPierre Jolivet     for (j = 0; j < nrows; j++) PetscCall(VecSetValues(vdnz, 1, &rows[j], &val, ADD_VALUES));
21385cf7da58SHong Zhang   } else {
213948a46eb9SPierre Jolivet     for (j = 0; j < nrows; j++) PetscCall(VecSetValues(vonz, 1, &rows[j], &val, ADD_VALUES));
21405cf7da58SHong Zhang   }
21415cf7da58SHong Zhang   PetscFunctionReturn(0);
21425cf7da58SHong Zhang }
21435cf7da58SHong Zhang 
2144d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode MatSetPreallocationUserblock_private(Mat Ju, PetscInt nrows, PetscInt *rows, PetscInt ncols, PetscBool ghost, Vec vdnz, Vec vonz)
2145d71ae5a4SJacob Faibussowitsch {
21465cf7da58SHong Zhang   PetscInt    j, ncols_u;
21475cf7da58SHong Zhang   PetscScalar val;
21485cf7da58SHong Zhang 
21495cf7da58SHong Zhang   PetscFunctionBegin;
21505cf7da58SHong Zhang   if (!ghost) {
21515cf7da58SHong Zhang     for (j = 0; j < nrows; j++) {
21529566063dSJacob Faibussowitsch       PetscCall(MatGetRow(Ju, j, &ncols_u, NULL, NULL));
21535cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
21549566063dSJacob Faibussowitsch       PetscCall(VecSetValues(vdnz, 1, &rows[j], &val, ADD_VALUES));
21559566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(Ju, j, &ncols_u, NULL, NULL));
21565cf7da58SHong Zhang     }
21575cf7da58SHong Zhang   } else {
21585cf7da58SHong Zhang     for (j = 0; j < nrows; j++) {
21599566063dSJacob Faibussowitsch       PetscCall(MatGetRow(Ju, j, &ncols_u, NULL, NULL));
21605cf7da58SHong Zhang       val = (PetscScalar)ncols_u;
21619566063dSJacob Faibussowitsch       PetscCall(VecSetValues(vonz, 1, &rows[j], &val, ADD_VALUES));
21629566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(Ju, j, &ncols_u, NULL, NULL));
21635cf7da58SHong Zhang     }
21645cf7da58SHong Zhang   }
21655cf7da58SHong Zhang   PetscFunctionReturn(0);
21665cf7da58SHong Zhang }
21675cf7da58SHong Zhang 
2168d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode MatSetPreallocationblock_private(Mat Ju, PetscInt nrows, PetscInt *rows, PetscInt ncols, PetscBool ghost, Vec vdnz, Vec vonz)
2169d71ae5a4SJacob Faibussowitsch {
21705cf7da58SHong Zhang   PetscFunctionBegin;
21715cf7da58SHong Zhang   if (Ju) {
21729566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationUserblock_private(Ju, nrows, rows, ncols, ghost, vdnz, vonz));
21735cf7da58SHong Zhang   } else {
21749566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationDenseblock_private(nrows, rows, ncols, ghost, vdnz, vonz));
21755cf7da58SHong Zhang   }
21765cf7da58SHong Zhang   PetscFunctionReturn(0);
21775cf7da58SHong Zhang }
21785cf7da58SHong Zhang 
2179d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode MatSetDenseblock_private(PetscInt nrows, PetscInt *rows, PetscInt ncols, PetscInt cstart, Mat *J)
2180d71ae5a4SJacob Faibussowitsch {
2181883e35e8SHong Zhang   PetscInt     j, *cols;
2182883e35e8SHong Zhang   PetscScalar *zeros;
2183883e35e8SHong Zhang 
2184883e35e8SHong Zhang   PetscFunctionBegin;
21859566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(ncols, &cols, nrows * ncols, &zeros));
2186883e35e8SHong Zhang   for (j = 0; j < ncols; j++) cols[j] = j + cstart;
21879566063dSJacob Faibussowitsch   PetscCall(MatSetValues(*J, nrows, rows, ncols, cols, zeros, INSERT_VALUES));
21889566063dSJacob Faibussowitsch   PetscCall(PetscFree2(cols, zeros));
21891ad426b7SHong Zhang   PetscFunctionReturn(0);
21901ad426b7SHong Zhang }
2191a4e85ca8SHong Zhang 
2192d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode MatSetUserblock_private(Mat Ju, PetscInt nrows, PetscInt *rows, PetscInt ncols, PetscInt cstart, Mat *J)
2193d71ae5a4SJacob Faibussowitsch {
21943e97b6e8SHong Zhang   PetscInt        j, M, N, row, col, ncols_u;
21953e97b6e8SHong Zhang   const PetscInt *cols;
21963e97b6e8SHong Zhang   PetscScalar     zero = 0.0;
21973e97b6e8SHong Zhang 
21983e97b6e8SHong Zhang   PetscFunctionBegin;
21999566063dSJacob Faibussowitsch   PetscCall(MatGetSize(Ju, &M, &N));
220063a3b9bcSJacob Faibussowitsch   PetscCheck(nrows == M && ncols == N, PetscObjectComm((PetscObject)Ju), PETSC_ERR_USER, "%" PetscInt_FMT " by %" PetscInt_FMT " must equal %" PetscInt_FMT " by %" PetscInt_FMT, nrows, ncols, M, N);
22013e97b6e8SHong Zhang 
22023e97b6e8SHong Zhang   for (row = 0; row < nrows; row++) {
22039566063dSJacob Faibussowitsch     PetscCall(MatGetRow(Ju, row, &ncols_u, &cols, NULL));
22043e97b6e8SHong Zhang     for (j = 0; j < ncols_u; j++) {
22053e97b6e8SHong Zhang       col = cols[j] + cstart;
22069566063dSJacob Faibussowitsch       PetscCall(MatSetValues(*J, 1, &rows[row], 1, &col, &zero, INSERT_VALUES));
22073e97b6e8SHong Zhang     }
22089566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow(Ju, row, &ncols_u, &cols, NULL));
22093e97b6e8SHong Zhang   }
22103e97b6e8SHong Zhang   PetscFunctionReturn(0);
22113e97b6e8SHong Zhang }
22121ad426b7SHong Zhang 
2213d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode MatSetblock_private(Mat Ju, PetscInt nrows, PetscInt *rows, PetscInt ncols, PetscInt cstart, Mat *J)
2214d71ae5a4SJacob Faibussowitsch {
2215a4e85ca8SHong Zhang   PetscFunctionBegin;
2216a4e85ca8SHong Zhang   if (Ju) {
22179566063dSJacob Faibussowitsch     PetscCall(MatSetUserblock_private(Ju, nrows, rows, ncols, cstart, J));
2218a4e85ca8SHong Zhang   } else {
22199566063dSJacob Faibussowitsch     PetscCall(MatSetDenseblock_private(nrows, rows, ncols, cstart, J));
2220a4e85ca8SHong Zhang   }
2221a4e85ca8SHong Zhang   PetscFunctionReturn(0);
2222a4e85ca8SHong Zhang }
2223a4e85ca8SHong Zhang 
222424121865SAdrian 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.
222524121865SAdrian Maldonado */
2226d71ae5a4SJacob Faibussowitsch PetscErrorCode CreateSubGlobalToLocalMapping_private(PetscSection globalsec, PetscSection localsec, ISLocalToGlobalMapping *ltog)
2227d71ae5a4SJacob Faibussowitsch {
222824121865SAdrian Maldonado   PetscInt  i, size, dof;
222924121865SAdrian Maldonado   PetscInt *glob2loc;
223024121865SAdrian Maldonado 
223124121865SAdrian Maldonado   PetscFunctionBegin;
22329566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(localsec, &size));
22339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &glob2loc));
223424121865SAdrian Maldonado 
223524121865SAdrian Maldonado   for (i = 0; i < size; i++) {
22369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalsec, i, &dof));
223724121865SAdrian Maldonado     dof         = (dof >= 0) ? dof : -(dof + 1);
223824121865SAdrian Maldonado     glob2loc[i] = dof;
223924121865SAdrian Maldonado   }
224024121865SAdrian Maldonado 
22419566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD, 1, size, glob2loc, PETSC_OWN_POINTER, ltog));
224224121865SAdrian Maldonado #if 0
22439566063dSJacob Faibussowitsch   PetscCall(PetscIntView(size,glob2loc,PETSC_VIEWER_STDOUT_WORLD));
224424121865SAdrian Maldonado #endif
224524121865SAdrian Maldonado   PetscFunctionReturn(0);
224624121865SAdrian Maldonado }
224724121865SAdrian Maldonado 
224801ad2aeeSHong Zhang #include <petsc/private/matimpl.h>
22499e1d080bSHong Zhang 
2250d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Network_Nest(DM dm, Mat *J)
2251d71ae5a4SJacob Faibussowitsch {
22521ad426b7SHong Zhang   DM_Network            *network = (DM_Network *)dm->data;
225324121865SAdrian Maldonado   PetscInt               eDof, vDof;
225424121865SAdrian Maldonado   Mat                    j11, j12, j21, j22, bA[2][2];
22559e1d080bSHong Zhang   MPI_Comm               comm;
225624121865SAdrian Maldonado   ISLocalToGlobalMapping eISMap, vISMap;
225724121865SAdrian Maldonado 
22589e1d080bSHong Zhang   PetscFunctionBegin;
22599566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
226024121865SAdrian Maldonado 
22619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(network->edge.GlobalDofSection, &eDof));
22629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(network->vertex.GlobalDofSection, &vDof));
226324121865SAdrian Maldonado 
22649566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &j11));
22659566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(j11, eDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE));
22669566063dSJacob Faibussowitsch   PetscCall(MatSetType(j11, MATMPIAIJ));
226724121865SAdrian Maldonado 
22689566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &j12));
22699566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(j12, eDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE));
22709566063dSJacob Faibussowitsch   PetscCall(MatSetType(j12, MATMPIAIJ));
227124121865SAdrian Maldonado 
22729566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &j21));
22739566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(j21, vDof, eDof, PETSC_DETERMINE, PETSC_DETERMINE));
22749566063dSJacob Faibussowitsch   PetscCall(MatSetType(j21, MATMPIAIJ));
227524121865SAdrian Maldonado 
22769566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &j22));
22779566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(j22, vDof, vDof, PETSC_DETERMINE, PETSC_DETERMINE));
22789566063dSJacob Faibussowitsch   PetscCall(MatSetType(j22, MATMPIAIJ));
227924121865SAdrian Maldonado 
22803f6a6bdaSHong Zhang   bA[0][0] = j11;
22813f6a6bdaSHong Zhang   bA[0][1] = j12;
22823f6a6bdaSHong Zhang   bA[1][0] = j21;
22833f6a6bdaSHong Zhang   bA[1][1] = j22;
228424121865SAdrian Maldonado 
22859566063dSJacob Faibussowitsch   PetscCall(CreateSubGlobalToLocalMapping_private(network->edge.GlobalDofSection, network->edge.DofSection, &eISMap));
22869566063dSJacob Faibussowitsch   PetscCall(CreateSubGlobalToLocalMapping_private(network->vertex.GlobalDofSection, network->vertex.DofSection, &vISMap));
228724121865SAdrian Maldonado 
22889566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(j11, eISMap, eISMap));
22899566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(j12, eISMap, vISMap));
22909566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(j21, vISMap, eISMap));
22919566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(j22, vISMap, vISMap));
229224121865SAdrian Maldonado 
22939566063dSJacob Faibussowitsch   PetscCall(MatSetUp(j11));
22949566063dSJacob Faibussowitsch   PetscCall(MatSetUp(j12));
22959566063dSJacob Faibussowitsch   PetscCall(MatSetUp(j21));
22969566063dSJacob Faibussowitsch   PetscCall(MatSetUp(j22));
229724121865SAdrian Maldonado 
22989566063dSJacob Faibussowitsch   PetscCall(MatCreateNest(comm, 2, NULL, 2, NULL, &bA[0][0], J));
22999566063dSJacob Faibussowitsch   PetscCall(MatSetUp(*J));
23009566063dSJacob Faibussowitsch   PetscCall(MatNestSetVecType(*J, VECNEST));
23019566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&j11));
23029566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&j12));
23039566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&j21));
23049566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&j22));
230524121865SAdrian Maldonado 
23069566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY));
23079566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY));
23089566063dSJacob Faibussowitsch   PetscCall(MatSetOption(*J, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
230924121865SAdrian Maldonado 
231024121865SAdrian Maldonado   /* Free structures */
23119566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&eISMap));
23129566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&vISMap));
231324121865SAdrian Maldonado   PetscFunctionReturn(0);
23149e1d080bSHong Zhang }
23159e1d080bSHong Zhang 
2316d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Network(DM dm, Mat *J)
2317d71ae5a4SJacob Faibussowitsch {
23189e1d080bSHong Zhang   DM_Network     *network = (DM_Network *)dm->data;
23199e1d080bSHong Zhang   PetscInt        eStart, eEnd, vStart, vEnd, rstart, nrows, *rows, localSize;
23209e1d080bSHong Zhang   PetscInt        cstart, ncols, j, e, v;
23219e1d080bSHong Zhang   PetscBool       ghost, ghost_vc, ghost2, isNest;
23229e1d080bSHong Zhang   Mat             Juser;
23239e1d080bSHong Zhang   PetscSection    sectionGlobal;
23249e1d080bSHong Zhang   PetscInt        nedges, *vptr = NULL, vc, *rows_v; /* suppress maybe-uninitialized warning */
23259e1d080bSHong Zhang   const PetscInt *edges, *cone;
23269e1d080bSHong Zhang   MPI_Comm        comm;
23279e1d080bSHong Zhang   MatType         mtype;
23289e1d080bSHong Zhang   Vec             vd_nz, vo_nz;
23299e1d080bSHong Zhang   PetscInt       *dnnz, *onnz;
23309e1d080bSHong Zhang   PetscScalar    *vdnz, *vonz;
23319e1d080bSHong Zhang 
23329e1d080bSHong Zhang   PetscFunctionBegin;
23339e1d080bSHong Zhang   mtype = dm->mattype;
23349566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATNEST, &isNest));
23359e1d080bSHong Zhang   if (isNest) {
23369566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix_Network_Nest(dm, J));
23379566063dSJacob Faibussowitsch     PetscCall(MatSetDM(*J, dm));
23389e1d080bSHong Zhang     PetscFunctionReturn(0);
23399e1d080bSHong Zhang   }
23409e1d080bSHong Zhang 
23419e1d080bSHong Zhang   if (!network->userEdgeJacobian && !network->userVertexJacobian) {
2342a4e85ca8SHong Zhang     /* user does not provide Jacobian blocks */
23439566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix_Plex(network->plex, J));
23449566063dSJacob Faibussowitsch     PetscCall(MatSetDM(*J, dm));
23451ad426b7SHong Zhang     PetscFunctionReturn(0);
23461ad426b7SHong Zhang   }
23471ad426b7SHong Zhang 
23489566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
23499566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(network->plex, &sectionGlobal));
23509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
23519566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
23522a945128SHong Zhang 
23539566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, MATAIJ));
23549566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
235589898e50SHong Zhang 
235689898e50SHong Zhang   /* (1) Set matrix preallocation */
235789898e50SHong Zhang   /*------------------------------*/
23589566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
23599566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, &vd_nz));
23609566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(vd_nz, localSize, PETSC_DECIDE));
23619566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(vd_nz));
23629566063dSJacob Faibussowitsch   PetscCall(VecSet(vd_nz, 0.0));
23639566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(vd_nz, &vo_nz));
2364840c2264SHong Zhang 
236589898e50SHong Zhang   /* Set preallocation for edges */
236689898e50SHong Zhang   /*-----------------------------*/
23679566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetEdgeRange(dm, &eStart, &eEnd));
2368840c2264SHong Zhang 
23699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(localSize, &rows));
2370840c2264SHong Zhang   for (e = eStart; e < eEnd; e++) {
2371840c2264SHong Zhang     /* Get row indices */
23729566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetGlobalVecOffset(dm, e, ALL_COMPONENTS, &rstart));
23739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(network->DofSection, e, &nrows));
2374840c2264SHong Zhang     if (nrows) {
2375840c2264SHong Zhang       for (j = 0; j < nrows; j++) rows[j] = j + rstart;
2376840c2264SHong Zhang 
2377a5b23f4aSJose E. Roman       /* Set preallocation for connected vertices */
23789566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetConnectedVertices(dm, e, &cone));
2379840c2264SHong Zhang       for (v = 0; v < 2; v++) {
23809566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(network->DofSection, cone[v], &ncols));
2381840c2264SHong Zhang 
23828675203cSHong Zhang         if (network->Je) {
2383840c2264SHong Zhang           Juser = network->Je[3 * e + 1 + v]; /* Jacobian(e,v) */
23848675203cSHong Zhang         } else Juser = NULL;
23859566063dSJacob Faibussowitsch         PetscCall(DMNetworkIsGhostVertex(dm, cone[v], &ghost));
23869566063dSJacob Faibussowitsch         PetscCall(MatSetPreallocationblock_private(Juser, nrows, rows, ncols, ghost, vd_nz, vo_nz));
2387840c2264SHong Zhang       }
2388840c2264SHong Zhang 
238989898e50SHong Zhang       /* Set preallocation for edge self */
2390840c2264SHong Zhang       cstart = rstart;
23918675203cSHong Zhang       if (network->Je) {
2392840c2264SHong Zhang         Juser = network->Je[3 * e]; /* Jacobian(e,e) */
23938675203cSHong Zhang       } else Juser = NULL;
23949566063dSJacob Faibussowitsch       PetscCall(MatSetPreallocationblock_private(Juser, nrows, rows, nrows, PETSC_FALSE, vd_nz, vo_nz));
2395840c2264SHong Zhang     }
2396840c2264SHong Zhang   }
2397840c2264SHong Zhang 
239889898e50SHong Zhang   /* Set preallocation for vertices */
239989898e50SHong Zhang   /*--------------------------------*/
24009566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetVertexRange(dm, &vStart, &vEnd));
24018675203cSHong Zhang   if (vEnd - vStart) vptr = network->Jvptr;
2402840c2264SHong Zhang 
2403840c2264SHong Zhang   for (v = vStart; v < vEnd; v++) {
2404840c2264SHong Zhang     /* Get row indices */
24059566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetGlobalVecOffset(dm, v, ALL_COMPONENTS, &rstart));
24069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(network->DofSection, v, &nrows));
2407840c2264SHong Zhang     if (!nrows) continue;
2408840c2264SHong Zhang 
24099566063dSJacob Faibussowitsch     PetscCall(DMNetworkIsGhostVertex(dm, v, &ghost));
2410bdcb62a2SHong Zhang     if (ghost) {
24119566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nrows, &rows_v));
2412bdcb62a2SHong Zhang     } else {
2413bdcb62a2SHong Zhang       rows_v = rows;
2414bdcb62a2SHong Zhang     }
2415bdcb62a2SHong Zhang 
2416bdcb62a2SHong Zhang     for (j = 0; j < nrows; j++) rows_v[j] = j + rstart;
2417840c2264SHong Zhang 
2418840c2264SHong Zhang     /* Get supporting edges and connected vertices */
24199566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetSupportingEdges(dm, v, &nedges, &edges));
2420840c2264SHong Zhang 
2421840c2264SHong Zhang     for (e = 0; e < nedges; e++) {
2422840c2264SHong Zhang       /* Supporting edges */
24239566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetGlobalVecOffset(dm, edges[e], ALL_COMPONENTS, &cstart));
24249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(network->DofSection, edges[e], &ncols));
2425840c2264SHong Zhang 
24268675203cSHong Zhang       if (network->Jv) {
2427840c2264SHong Zhang         Juser = network->Jv[vptr[v - vStart] + 2 * e + 1]; /* Jacobian(v,e) */
24288675203cSHong Zhang       } else Juser = NULL;
24299566063dSJacob Faibussowitsch       PetscCall(MatSetPreallocationblock_private(Juser, nrows, rows_v, ncols, ghost, vd_nz, vo_nz));
2430840c2264SHong Zhang 
2431840c2264SHong Zhang       /* Connected vertices */
24329566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetConnectedVertices(dm, edges[e], &cone));
2433840c2264SHong Zhang       vc = (v == cone[0]) ? cone[1] : cone[0];
24349566063dSJacob Faibussowitsch       PetscCall(DMNetworkIsGhostVertex(dm, vc, &ghost_vc));
2435840c2264SHong Zhang 
24369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(network->DofSection, vc, &ncols));
2437840c2264SHong Zhang 
24388675203cSHong Zhang       if (network->Jv) {
2439840c2264SHong Zhang         Juser = network->Jv[vptr[v - vStart] + 2 * e + 2]; /* Jacobian(v,vc) */
24408675203cSHong Zhang       } else Juser = NULL;
2441e102a522SHong Zhang       if (ghost_vc || ghost) {
2442e102a522SHong Zhang         ghost2 = PETSC_TRUE;
2443e102a522SHong Zhang       } else {
2444e102a522SHong Zhang         ghost2 = PETSC_FALSE;
2445e102a522SHong Zhang       }
24469566063dSJacob Faibussowitsch       PetscCall(MatSetPreallocationblock_private(Juser, nrows, rows_v, ncols, ghost2, vd_nz, vo_nz));
2447840c2264SHong Zhang     }
2448840c2264SHong Zhang 
244989898e50SHong Zhang     /* Set preallocation for vertex self */
24509566063dSJacob Faibussowitsch     PetscCall(DMNetworkIsGhostVertex(dm, v, &ghost));
2451840c2264SHong Zhang     if (!ghost) {
24529566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetGlobalVecOffset(dm, v, ALL_COMPONENTS, &cstart));
24538675203cSHong Zhang       if (network->Jv) {
2454840c2264SHong Zhang         Juser = network->Jv[vptr[v - vStart]]; /* Jacobian(v,v) */
24558675203cSHong Zhang       } else Juser = NULL;
24569566063dSJacob Faibussowitsch       PetscCall(MatSetPreallocationblock_private(Juser, nrows, rows_v, nrows, PETSC_FALSE, vd_nz, vo_nz));
2457840c2264SHong Zhang     }
24581baa6e33SBarry Smith     if (ghost) PetscCall(PetscFree(rows_v));
2459840c2264SHong Zhang   }
2460840c2264SHong Zhang 
24619566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(vd_nz));
24629566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(vo_nz));
24635cf7da58SHong Zhang 
24649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(localSize, &dnnz, localSize, &onnz));
24655cf7da58SHong Zhang 
24669566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(vd_nz));
24679566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(vo_nz));
2468840c2264SHong Zhang 
24699566063dSJacob Faibussowitsch   PetscCall(VecGetArray(vd_nz, &vdnz));
24709566063dSJacob Faibussowitsch   PetscCall(VecGetArray(vo_nz, &vonz));
2471840c2264SHong Zhang   for (j = 0; j < localSize; j++) {
2472e102a522SHong Zhang     dnnz[j] = (PetscInt)PetscRealPart(vdnz[j]);
2473e102a522SHong Zhang     onnz[j] = (PetscInt)PetscRealPart(vonz[j]);
2474840c2264SHong Zhang   }
24759566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(vd_nz, &vdnz));
24769566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(vo_nz, &vonz));
24779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vd_nz));
24789566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vo_nz));
2479840c2264SHong Zhang 
24809566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(*J, 0, dnnz));
24819566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(*J, 0, dnnz, 0, onnz));
24829566063dSJacob Faibussowitsch   PetscCall(MatSetOption(*J, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
24835cf7da58SHong Zhang 
24849566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnnz, onnz));
24855cf7da58SHong Zhang 
248689898e50SHong Zhang   /* (2) Set matrix entries for edges */
248789898e50SHong Zhang   /*----------------------------------*/
24881ad426b7SHong Zhang   for (e = eStart; e < eEnd; e++) {
2489bfbc38dcSHong Zhang     /* Get row indices */
24909566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetGlobalVecOffset(dm, e, ALL_COMPONENTS, &rstart));
24919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(network->DofSection, e, &nrows));
24924b976069SHong Zhang     if (nrows) {
249317df6e9eSHong Zhang       for (j = 0; j < nrows; j++) rows[j] = j + rstart;
24941ad426b7SHong Zhang 
2495a5b23f4aSJose E. Roman       /* Set matrix entries for connected vertices */
24969566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetConnectedVertices(dm, e, &cone));
2497bfbc38dcSHong Zhang       for (v = 0; v < 2; v++) {
24989566063dSJacob Faibussowitsch         PetscCall(DMNetworkGetGlobalVecOffset(dm, cone[v], ALL_COMPONENTS, &cstart));
24999566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(network->DofSection, cone[v], &ncols));
25003e97b6e8SHong Zhang 
25018675203cSHong Zhang         if (network->Je) {
2502a4e85ca8SHong Zhang           Juser = network->Je[3 * e + 1 + v]; /* Jacobian(e,v) */
25038675203cSHong Zhang         } else Juser = NULL;
25049566063dSJacob Faibussowitsch         PetscCall(MatSetblock_private(Juser, nrows, rows, ncols, cstart, J));
2505bfbc38dcSHong Zhang       }
250617df6e9eSHong Zhang 
2507bfbc38dcSHong Zhang       /* Set matrix entries for edge self */
25083e97b6e8SHong Zhang       cstart = rstart;
25098675203cSHong Zhang       if (network->Je) {
2510a4e85ca8SHong Zhang         Juser = network->Je[3 * e]; /* Jacobian(e,e) */
25118675203cSHong Zhang       } else Juser = NULL;
25129566063dSJacob Faibussowitsch       PetscCall(MatSetblock_private(Juser, nrows, rows, nrows, cstart, J));
25131ad426b7SHong Zhang     }
25144b976069SHong Zhang   }
25151ad426b7SHong Zhang 
2516bfbc38dcSHong Zhang   /* Set matrix entries for vertices */
251783b2e829SHong Zhang   /*---------------------------------*/
25181ad426b7SHong Zhang   for (v = vStart; v < vEnd; v++) {
2519bfbc38dcSHong Zhang     /* Get row indices */
25209566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetGlobalVecOffset(dm, v, ALL_COMPONENTS, &rstart));
25219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(network->DofSection, v, &nrows));
25224b976069SHong Zhang     if (!nrows) continue;
2523596e729fSHong Zhang 
25249566063dSJacob Faibussowitsch     PetscCall(DMNetworkIsGhostVertex(dm, v, &ghost));
2525bdcb62a2SHong Zhang     if (ghost) {
25269566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nrows, &rows_v));
2527bdcb62a2SHong Zhang     } else {
2528bdcb62a2SHong Zhang       rows_v = rows;
2529bdcb62a2SHong Zhang     }
2530bdcb62a2SHong Zhang     for (j = 0; j < nrows; j++) rows_v[j] = j + rstart;
2531596e729fSHong Zhang 
2532bfbc38dcSHong Zhang     /* Get supporting edges and connected vertices */
25339566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetSupportingEdges(dm, v, &nedges, &edges));
2534596e729fSHong Zhang 
2535596e729fSHong Zhang     for (e = 0; e < nedges; e++) {
2536bfbc38dcSHong Zhang       /* Supporting edges */
25379566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetGlobalVecOffset(dm, edges[e], ALL_COMPONENTS, &cstart));
25389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(network->DofSection, edges[e], &ncols));
2539596e729fSHong Zhang 
25408675203cSHong Zhang       if (network->Jv) {
2541a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v - vStart] + 2 * e + 1]; /* Jacobian(v,e) */
25428675203cSHong Zhang       } else Juser = NULL;
25439566063dSJacob Faibussowitsch       PetscCall(MatSetblock_private(Juser, nrows, rows_v, ncols, cstart, J));
2544596e729fSHong Zhang 
2545bfbc38dcSHong Zhang       /* Connected vertices */
25469566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetConnectedVertices(dm, edges[e], &cone));
25472a945128SHong Zhang       vc = (v == cone[0]) ? cone[1] : cone[0];
25482a945128SHong Zhang 
25499566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetGlobalVecOffset(dm, vc, ALL_COMPONENTS, &cstart));
25509566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(network->DofSection, vc, &ncols));
2551a4e85ca8SHong Zhang 
25528675203cSHong Zhang       if (network->Jv) {
2553a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v - vStart] + 2 * e + 2]; /* Jacobian(v,vc) */
25548675203cSHong Zhang       } else Juser = NULL;
25559566063dSJacob Faibussowitsch       PetscCall(MatSetblock_private(Juser, nrows, rows_v, ncols, cstart, J));
2556596e729fSHong Zhang     }
2557596e729fSHong Zhang 
2558bfbc38dcSHong Zhang     /* Set matrix entries for vertex self */
25591ad426b7SHong Zhang     if (!ghost) {
25609566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetGlobalVecOffset(dm, v, ALL_COMPONENTS, &cstart));
25618675203cSHong Zhang       if (network->Jv) {
2562a4e85ca8SHong Zhang         Juser = network->Jv[vptr[v - vStart]]; /* Jacobian(v,v) */
25638675203cSHong Zhang       } else Juser = NULL;
25649566063dSJacob Faibussowitsch       PetscCall(MatSetblock_private(Juser, nrows, rows_v, nrows, cstart, J));
2565bdcb62a2SHong Zhang     }
25661baa6e33SBarry Smith     if (ghost) PetscCall(PetscFree(rows_v));
25671ad426b7SHong Zhang   }
25689566063dSJacob Faibussowitsch   PetscCall(PetscFree(rows));
2569bdcb62a2SHong Zhang 
25709566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY));
25719566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY));
2572dd6f46cdSHong Zhang 
25739566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
25745f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
25755f2c45f1SShri Abhyankar }
25765f2c45f1SShri Abhyankar 
2577d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMNetworkDestroyComponentData(DM dm)
2578d71ae5a4SJacob Faibussowitsch {
2579daad07d3SAidan Hamilton   DM_Network *network = (DM_Network *)dm->data;
2580daad07d3SAidan Hamilton   PetscInt    j, np;
2581daad07d3SAidan Hamilton 
2582daad07d3SAidan Hamilton   PetscFunctionBegin;
2583daad07d3SAidan Hamilton   if (network->header) {
2584daad07d3SAidan Hamilton     np = network->cloneshared->pEnd - network->cloneshared->pStart;
2585daad07d3SAidan Hamilton     for (j = 0; j < np; j++) {
2586daad07d3SAidan Hamilton       PetscCall(PetscFree5(network->header[j].size, network->header[j].key, network->header[j].offset, network->header[j].nvar, network->header[j].offsetvarrel));
2587daad07d3SAidan Hamilton       PetscCall(PetscFree(network->cvalue[j].data));
2588daad07d3SAidan Hamilton     }
2589daad07d3SAidan Hamilton     PetscCall(PetscFree2(network->header, network->cvalue));
2590daad07d3SAidan Hamilton   }
2591daad07d3SAidan Hamilton   PetscFunctionReturn(0);
2592daad07d3SAidan Hamilton }
2593daad07d3SAidan Hamilton 
2594d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Network(DM dm)
2595d71ae5a4SJacob Faibussowitsch {
25965f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
2597aeb78aa7SBarry Smith   PetscInt    j;
25985f2c45f1SShri Abhyankar 
25995f2c45f1SShri Abhyankar   PetscFunctionBegin;
2600daad07d3SAidan Hamilton   /*
2601daad07d3SAidan Hamilton     Developers Note: Due to the mixed topological definition of DMNetwork and data defined ON the
2602daad07d3SAidan Hamilton     network like DofSection, DataSection, *componentdataarray, and friends, when cloning, we share
2603daad07d3SAidan Hamilton     only the true topological data, and make our own data ON the network. Thus refct only refers
2604daad07d3SAidan Hamilton     to the number of references to topological data, and data ON the network is always destroyed.
2605daad07d3SAidan Hamilton     It is understood this is atypical for a DM, but is very intentional.
2606daad07d3SAidan Hamilton   */
2607daad07d3SAidan Hamilton 
2608daad07d3SAidan Hamilton   /* Always destroy data ON the network */
26099566063dSJacob Faibussowitsch   PetscCall(PetscFree(network->Je));
261083b2e829SHong Zhang   if (network->Jv) {
26119566063dSJacob Faibussowitsch     PetscCall(PetscFree(network->Jvptr));
26129566063dSJacob Faibussowitsch     PetscCall(PetscFree(network->Jv));
26131ad426b7SHong Zhang   }
2614daad07d3SAidan Hamilton   PetscCall(PetscSectionDestroy(&network->DataSection));
2615daad07d3SAidan Hamilton   PetscCall(PetscSectionDestroy(&network->DofSection));
2616daad07d3SAidan Hamilton   PetscCall(PetscFree(network->component));
2617daad07d3SAidan Hamilton   PetscCall(PetscFree(network->componentdataarray));
2618daad07d3SAidan Hamilton   PetscCall(DMNetworkDestroyComponentData(dm));
261913c2a604SAdrian Maldonado 
2620daad07d3SAidan Hamilton   PetscCall(DMDestroy(&network->plex)); /* this is cloned in DMClone_Network, so safe to destroy */
2621daad07d3SAidan Hamilton 
2622daad07d3SAidan Hamilton   /*
2623daad07d3SAidan Hamilton   Developers Note: The DMNetworkVertexInfo and DMNetworkEdgeInfo data structures are completely
2624daad07d3SAidan Hamilton   destroyed as they are again a mix of topological data:
2625daad07d3SAidan Hamilton     ISLocalToGlobalMapping            mapping;
2626daad07d3SAidan Hamilton     PetscSF                           sf;
2627daad07d3SAidan Hamilton   and data ON the network
2628daad07d3SAidan Hamilton     PetscSection                      DofSection;
2629daad07d3SAidan Hamilton     PetscSection                      GlobalDofSection;
2630daad07d3SAidan Hamilton   And the only way to access them currently is through DMNetworkAssembleGraphStructures which assembles
2631daad07d3SAidan Hamilton   everything. So we must destroy everything and require DMNetworkAssembleGraphStructures is called again
2632daad07d3SAidan Hamilton   for any clone.
2633daad07d3SAidan Hamilton   */
26349566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&network->vertex.mapping));
26359566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&network->vertex.DofSection));
26369566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&network->vertex.GlobalDofSection));
26379566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&network->vertex.sf));
263813c2a604SAdrian Maldonado   /* edge */
26399566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&network->edge.mapping));
26409566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&network->edge.DofSection));
26419566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&network->edge.GlobalDofSection));
26429566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&network->edge.sf));
2643daad07d3SAidan Hamilton   /* Destroy the potentially cloneshared data */
2644daad07d3SAidan Hamilton   if (--network->cloneshared->refct <= 0) {
2645daad07d3SAidan Hamilton     /* Developer Note: I'm not sure if vltog can be reused or not, as I'm not sure what it's purpose is. I
2646daad07d3SAidan Hamilton      naively think it can be reused. */
2647daad07d3SAidan Hamilton     PetscCall(PetscFree(network->cloneshared->vltog));
2648daad07d3SAidan Hamilton     for (j = 0; j < network->cloneshared->Nsvtx; j++) PetscCall(PetscFree(network->cloneshared->svtx[j].sv));
2649daad07d3SAidan Hamilton     PetscCall(PetscFree(network->cloneshared->svtx));
2650daad07d3SAidan Hamilton     PetscCall(PetscFree2(network->cloneshared->subnetedge, network->cloneshared->subnetvtx));
2651daad07d3SAidan Hamilton     PetscCall(PetscTableDestroy(&network->cloneshared->svtable));
2652daad07d3SAidan Hamilton     PetscCall(PetscFree(network->cloneshared->subnet));
2653daad07d3SAidan Hamilton     PetscCall(PetscFree(network->cloneshared));
2654daad07d3SAidan Hamilton   }
2655daad07d3SAidan Hamilton   PetscCall(PetscFree(network)); /* Always freed as this structure is copied in a clone, not cloneshared */
26565f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
26575f2c45f1SShri Abhyankar }
26585f2c45f1SShri Abhyankar 
2659d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Network(DM dm, PetscViewer viewer)
2660d71ae5a4SJacob Faibussowitsch {
2661caf410d2SHong Zhang   PetscBool   iascii;
2662caf410d2SHong Zhang   PetscMPIInt rank;
26635f2c45f1SShri Abhyankar 
26645f2c45f1SShri Abhyankar   PetscFunctionBegin;
2665caf410d2SHong Zhang   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2666caf410d2SHong Zhang   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
26679566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
26689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
2669caf410d2SHong Zhang   if (iascii) {
2670caf410d2SHong Zhang     const PetscInt *cone, *vtx, *edges;
26715c6496baSHong Zhang     PetscInt        vfrom, vto, i, j, nv, ne, nsv, p, nsubnet;
26722bf73ac6SHong Zhang     DM_Network     *network = (DM_Network *)dm->data;
2673caf410d2SHong Zhang 
2674daad07d3SAidan Hamilton     nsubnet = network->cloneshared->Nsubnet; /* num of subnetworks */
2675dd400576SPatrick Sanan     if (rank == 0) {
26769371c9d4SSatish Balay       PetscCall(PetscPrintf(PETSC_COMM_SELF, "  NSubnets: %" PetscInt_FMT "; NEdges: %" PetscInt_FMT "; NVertices: %" PetscInt_FMT "; NSharedVertices: %" PetscInt_FMT ".\n", nsubnet, network->cloneshared->NEdges, network->cloneshared->NVertices,
26779371c9d4SSatish Balay                             network->cloneshared->Nsvtx));
26782bf73ac6SHong Zhang     }
26792bf73ac6SHong Zhang 
26809566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetSharedVertices(dm, &nsv, NULL));
26819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
2682daad07d3SAidan Hamilton     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  [%d] nEdges: %" PetscInt_FMT "; nVertices: %" PetscInt_FMT "; nSharedVertices: %" PetscInt_FMT "\n", rank, network->cloneshared->nEdges, network->cloneshared->nVertices, nsv));
2683caf410d2SHong Zhang 
2684caf410d2SHong Zhang     for (i = 0; i < nsubnet; i++) {
26859566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetSubnetwork(dm, i, &nv, &ne, &vtx, &edges));
2686caf410d2SHong Zhang       if (ne) {
26879566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "     Subnet %" PetscInt_FMT ": nEdges %" PetscInt_FMT ", nVertices(include shared vertices) %" PetscInt_FMT "\n", i, ne, nv));
2688caf410d2SHong Zhang         for (j = 0; j < ne; j++) {
2689caf410d2SHong Zhang           p = edges[j];
26909566063dSJacob Faibussowitsch           PetscCall(DMNetworkGetConnectedVertices(dm, p, &cone));
26919566063dSJacob Faibussowitsch           PetscCall(DMNetworkGetGlobalVertexIndex(dm, cone[0], &vfrom));
26929566063dSJacob Faibussowitsch           PetscCall(DMNetworkGetGlobalVertexIndex(dm, cone[1], &vto));
26939566063dSJacob Faibussowitsch           PetscCall(DMNetworkGetGlobalEdgeIndex(dm, edges[j], &p));
26949566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "       edge %" PetscInt_FMT ": %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", p, vfrom, vto));
2695caf410d2SHong Zhang         }
2696caf410d2SHong Zhang       }
2697caf410d2SHong Zhang     }
26982bf73ac6SHong Zhang 
26992bf73ac6SHong Zhang     /* Shared vertices */
27009566063dSJacob Faibussowitsch     PetscCall(DMNetworkGetSharedVertices(dm, NULL, &vtx));
27015c6496baSHong Zhang     if (nsv) {
27025c6496baSHong Zhang       PetscInt        gidx;
27032bf73ac6SHong Zhang       PetscBool       ghost;
27045c6496baSHong Zhang       const PetscInt *sv = NULL;
27055c6496baSHong Zhang 
27069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "     SharedVertices:\n"));
27075c6496baSHong Zhang       for (i = 0; i < nsv; i++) {
27089566063dSJacob Faibussowitsch         PetscCall(DMNetworkIsGhostVertex(dm, vtx[i], &ghost));
27092bf73ac6SHong Zhang         if (ghost) continue;
27102bf73ac6SHong Zhang 
27119566063dSJacob Faibussowitsch         PetscCall(DMNetworkSharedVertexGetInfo(dm, vtx[i], &gidx, &nv, &sv));
27129566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "       svtx %" PetscInt_FMT ": global index %" PetscInt_FMT ", subnet[%" PetscInt_FMT "].%" PetscInt_FMT " ---->\n", i, gidx, sv[0], sv[1]));
271348a46eb9SPierre Jolivet         for (j = 1; j < nv; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "                                           ----> subnet[%" PetscInt_FMT "].%" PetscInt_FMT "\n", sv[2 * j], sv[2 * j + 1]));
2714caf410d2SHong Zhang       }
2715caf410d2SHong Zhang     }
27169566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
27179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
27185c6496baSHong Zhang   } else PetscCheck(iascii, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name);
27195f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27205f2c45f1SShri Abhyankar }
27215f2c45f1SShri Abhyankar 
2722d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalBegin_Network(DM dm, Vec g, InsertMode mode, Vec l)
2723d71ae5a4SJacob Faibussowitsch {
27245f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
27255f2c45f1SShri Abhyankar 
27265f2c45f1SShri Abhyankar   PetscFunctionBegin;
27279566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(network->plex, g, mode, l));
27285f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27295f2c45f1SShri Abhyankar }
27305f2c45f1SShri Abhyankar 
2731d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalEnd_Network(DM dm, Vec g, InsertMode mode, Vec l)
2732d71ae5a4SJacob Faibussowitsch {
27335f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
27345f2c45f1SShri Abhyankar 
27355f2c45f1SShri Abhyankar   PetscFunctionBegin;
27369566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(network->plex, g, mode, l));
27375f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27385f2c45f1SShri Abhyankar }
27395f2c45f1SShri Abhyankar 
2740d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalBegin_Network(DM dm, Vec l, InsertMode mode, Vec g)
2741d71ae5a4SJacob Faibussowitsch {
27425f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
27435f2c45f1SShri Abhyankar 
27445f2c45f1SShri Abhyankar   PetscFunctionBegin;
27459566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(network->plex, l, mode, g));
27465f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27475f2c45f1SShri Abhyankar }
27485f2c45f1SShri Abhyankar 
2749d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalEnd_Network(DM dm, Vec l, InsertMode mode, Vec g)
2750d71ae5a4SJacob Faibussowitsch {
27515f2c45f1SShri Abhyankar   DM_Network *network = (DM_Network *)dm->data;
27525f2c45f1SShri Abhyankar 
27535f2c45f1SShri Abhyankar   PetscFunctionBegin;
27549566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(network->plex, l, mode, g));
27555f2c45f1SShri Abhyankar   PetscFunctionReturn(0);
27565f2c45f1SShri Abhyankar }
275722bbedd7SHong Zhang 
275822bbedd7SHong Zhang /*@
275964238763SRodolfo Oliveira   DMNetworkGetVertexLocalToGlobalOrdering - Get vertex global index
276022bbedd7SHong Zhang 
276122bbedd7SHong Zhang   Not collective
276222bbedd7SHong Zhang 
27637a7aea1fSJed Brown   Input Parameters:
276422bbedd7SHong Zhang + dm - the dm object
276522bbedd7SHong Zhang - vloc - local vertex ordering, start from 0
276622bbedd7SHong Zhang 
27677a7aea1fSJed Brown   Output Parameters:
2768f0fc11ceSJed Brown .  vg  - global vertex ordering, start from 0
276922bbedd7SHong Zhang 
277097bb938eSShri Abhyankar   Level: advanced
277122bbedd7SHong Zhang 
2772db781477SPatrick Sanan .seealso: `DMNetworkSetVertexLocalToGlobalOrdering()`
277322bbedd7SHong Zhang @*/
2774d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkGetVertexLocalToGlobalOrdering(DM dm, PetscInt vloc, PetscInt *vg)
2775d71ae5a4SJacob Faibussowitsch {
277622bbedd7SHong Zhang   DM_Network *network = (DM_Network *)dm->data;
2777daad07d3SAidan Hamilton   PetscInt   *vltog   = network->cloneshared->vltog;
277822bbedd7SHong Zhang 
277922bbedd7SHong Zhang   PetscFunctionBegin;
27805c6496baSHong Zhang   PetscCheck(vltog, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Must call DMNetworkSetVertexLocalToGlobalOrdering() first");
278122bbedd7SHong Zhang   *vg = vltog[vloc];
278222bbedd7SHong Zhang   PetscFunctionReturn(0);
278322bbedd7SHong Zhang }
278422bbedd7SHong Zhang 
278522bbedd7SHong Zhang /*@
278664238763SRodolfo Oliveira   DMNetworkSetVertexLocalToGlobalOrdering - Create and setup vertex local to global map
278722bbedd7SHong Zhang 
278822bbedd7SHong Zhang   Collective
278922bbedd7SHong Zhang 
279022bbedd7SHong Zhang   Input Parameters:
2791f0fc11ceSJed Brown . dm - the dm object
279222bbedd7SHong Zhang 
279397bb938eSShri Abhyankar   Level: advanced
279422bbedd7SHong Zhang 
2795db781477SPatrick Sanan .seealso: `DMNetworkGetGlobalVertexIndex()`
279622bbedd7SHong Zhang @*/
2797d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkSetVertexLocalToGlobalOrdering(DM dm)
2798d71ae5a4SJacob Faibussowitsch {
279922bbedd7SHong Zhang   DM_Network        *network = (DM_Network *)dm->data;
280022bbedd7SHong Zhang   MPI_Comm           comm;
28012bf73ac6SHong Zhang   PetscMPIInt        rank, size, *displs = NULL, *recvcounts = NULL, remoterank;
280222bbedd7SHong Zhang   PetscBool          ghost;
280363029d29SHong Zhang   PetscInt          *vltog, nroots, nleaves, i, *vrange, k, N, lidx;
280422bbedd7SHong Zhang   const PetscSFNode *iremote;
280522bbedd7SHong Zhang   PetscSF            vsf;
280663029d29SHong Zhang   Vec                Vleaves, Vleaves_seq;
280763029d29SHong Zhang   VecScatter         ctx;
280863029d29SHong Zhang   PetscScalar       *varr, val;
280963029d29SHong Zhang   const PetscScalar *varr_read;
281022bbedd7SHong Zhang 
281122bbedd7SHong Zhang   PetscFunctionBegin;
28129566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
28139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
28149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
281522bbedd7SHong Zhang 
281622bbedd7SHong Zhang   if (size == 1) {
2817daad07d3SAidan Hamilton     nroots = network->cloneshared->vEnd - network->cloneshared->vStart;
28189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nroots, &vltog));
281922bbedd7SHong Zhang     for (i = 0; i < nroots; i++) vltog[i] = i;
2820daad07d3SAidan Hamilton     network->cloneshared->vltog = vltog;
282122bbedd7SHong Zhang     PetscFunctionReturn(0);
282222bbedd7SHong Zhang   }
282322bbedd7SHong Zhang 
2824daad07d3SAidan Hamilton   PetscCheck(network->cloneshared->distributecalled, comm, PETSC_ERR_ARG_WRONGSTATE, "Must call DMNetworkDistribute() first");
2825daad07d3SAidan Hamilton   if (network->cloneshared->vltog) PetscCall(PetscFree(network->cloneshared->vltog));
282622bbedd7SHong Zhang 
2827daad07d3SAidan Hamilton   PetscCall(DMNetworkSetSubMap_private(network->cloneshared->vStart, network->cloneshared->vEnd, &network->vertex.mapping));
28289566063dSJacob Faibussowitsch   PetscCall(PetscSFGetSubSF(network->plex->sf, network->vertex.mapping, &network->vertex.sf));
282922bbedd7SHong Zhang   vsf = network->vertex.sf;
283022bbedd7SHong Zhang 
28319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(size + 1, &vrange, size, &displs, size, &recvcounts));
28329566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(vsf, &nroots, &nleaves, NULL, &iremote));
283322bbedd7SHong Zhang 
28349371c9d4SSatish Balay   for (i = 0; i < size; i++) {
28359371c9d4SSatish Balay     displs[i]     = i;
28369371c9d4SSatish Balay     recvcounts[i] = 1;
28379371c9d4SSatish Balay   }
283822bbedd7SHong Zhang 
283922bbedd7SHong Zhang   i         = nroots - nleaves; /* local number of vertices, excluding ghosts */
284022bbedd7SHong Zhang   vrange[0] = 0;
28419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgatherv(&i, 1, MPIU_INT, vrange + 1, recvcounts, displs, MPIU_INT, comm));
2842ad540459SPierre Jolivet   for (i = 2; i < size + 1; i++) vrange[i] += vrange[i - 1];
284322bbedd7SHong Zhang 
28449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nroots, &vltog));
2845daad07d3SAidan Hamilton   network->cloneshared->vltog = vltog;
284622bbedd7SHong Zhang 
284763029d29SHong Zhang   /* Set vltog for non-ghost vertices */
284863029d29SHong Zhang   k = 0;
284922bbedd7SHong Zhang   for (i = 0; i < nroots; i++) {
2850daad07d3SAidan Hamilton     PetscCall(DMNetworkIsGhostVertex(dm, i + network->cloneshared->vStart, &ghost));
285163029d29SHong Zhang     if (ghost) continue;
285263029d29SHong Zhang     vltog[i] = vrange[rank] + k++;
285322bbedd7SHong Zhang   }
28549566063dSJacob Faibussowitsch   PetscCall(PetscFree3(vrange, displs, recvcounts));
285563029d29SHong Zhang 
285663029d29SHong Zhang   /* Set vltog for ghost vertices */
285763029d29SHong Zhang   /* (a) create parallel Vleaves and sequential Vleaves_seq to convert local iremote[*].index to global index */
28589566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, &Vleaves));
28599566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(Vleaves, 2 * nleaves, PETSC_DETERMINE));
28609566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(Vleaves));
28619566063dSJacob Faibussowitsch   PetscCall(VecGetArray(Vleaves, &varr));
286263029d29SHong Zhang   for (i = 0; i < nleaves; i++) {
286363029d29SHong Zhang     varr[2 * i]     = (PetscScalar)(iremote[i].rank);  /* rank of remote process */
286463029d29SHong Zhang     varr[2 * i + 1] = (PetscScalar)(iremote[i].index); /* local index in remote process */
286563029d29SHong Zhang   }
28669566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(Vleaves, &varr));
286763029d29SHong Zhang 
286863029d29SHong Zhang   /* (b) scatter local info to remote processes via VecScatter() */
28699566063dSJacob Faibussowitsch   PetscCall(VecScatterCreateToAll(Vleaves, &ctx, &Vleaves_seq));
28709566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(ctx, Vleaves, Vleaves_seq, INSERT_VALUES, SCATTER_FORWARD));
28719566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(ctx, Vleaves, Vleaves_seq, INSERT_VALUES, SCATTER_FORWARD));
287263029d29SHong Zhang 
287363029d29SHong Zhang   /* (c) convert local indices to global indices in parallel vector Vleaves */
28749566063dSJacob Faibussowitsch   PetscCall(VecGetSize(Vleaves_seq, &N));
28759566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(Vleaves_seq, &varr_read));
287663029d29SHong Zhang   for (i = 0; i < N; i += 2) {
28772e4cff2eSHong Zhang     remoterank = (PetscMPIInt)PetscRealPart(varr_read[i]);
287863029d29SHong Zhang     if (remoterank == rank) {
287963029d29SHong Zhang       k    = i + 1; /* row number */
28802e4cff2eSHong Zhang       lidx = (PetscInt)PetscRealPart(varr_read[i + 1]);
288163029d29SHong Zhang       val  = (PetscScalar)vltog[lidx]; /* global index for non-ghost vertex computed above */
28829566063dSJacob Faibussowitsch       PetscCall(VecSetValues(Vleaves, 1, &k, &val, INSERT_VALUES));
288363029d29SHong Zhang     }
288463029d29SHong Zhang   }
28859566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(Vleaves_seq, &varr_read));
28869566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(Vleaves));
28879566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(Vleaves));
288863029d29SHong Zhang 
288963029d29SHong Zhang   /* (d) Set vltog for ghost vertices by copying local values of Vleaves */
28909566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(Vleaves, &varr_read));
289163029d29SHong Zhang   k = 0;
289263029d29SHong Zhang   for (i = 0; i < nroots; i++) {
2893daad07d3SAidan Hamilton     PetscCall(DMNetworkIsGhostVertex(dm, i + network->cloneshared->vStart, &ghost));
289463029d29SHong Zhang     if (!ghost) continue;
28959371c9d4SSatish Balay     vltog[i] = (PetscInt)PetscRealPart(varr_read[2 * k + 1]);
28969371c9d4SSatish Balay     k++;
289763029d29SHong Zhang   }
28989566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(Vleaves, &varr_read));
289963029d29SHong Zhang 
29009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Vleaves));
29019566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&Vleaves_seq));
29029566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
290322bbedd7SHong Zhang   PetscFunctionReturn(0);
290422bbedd7SHong Zhang }
290542dc13f1SHong Zhang 
2906d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMISAddSize_private(DM_Network *network, PetscInt p, PetscInt numkeys, PetscInt keys[], PetscInt blocksize[], PetscInt nselectedvar[], PetscInt *nidx)
2907d71ae5a4SJacob Faibussowitsch {
290842dc13f1SHong Zhang   PetscInt                 i, j, ncomps, nvar, key, offset = 0;
290942dc13f1SHong Zhang   DMNetworkComponentHeader header;
291042dc13f1SHong Zhang 
291142dc13f1SHong Zhang   PetscFunctionBegin;
29129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->DataSection, p, &offset));
291342dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray + offset))->ndata;
291442dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray + offset);
291542dc13f1SHong Zhang 
291642dc13f1SHong Zhang   for (i = 0; i < ncomps; i++) {
291742dc13f1SHong Zhang     key  = header->key[i];
291842dc13f1SHong Zhang     nvar = header->nvar[i];
291942dc13f1SHong Zhang     for (j = 0; j < numkeys; j++) {
292042dc13f1SHong Zhang       if (key == keys[j]) {
292142dc13f1SHong Zhang         if (!blocksize || blocksize[j] == -1) {
292242dc13f1SHong Zhang           *nidx += nvar;
292342dc13f1SHong Zhang         } else {
292442dc13f1SHong Zhang           *nidx += nselectedvar[j] * nvar / blocksize[j];
292542dc13f1SHong Zhang         }
292642dc13f1SHong Zhang       }
292742dc13f1SHong Zhang     }
292842dc13f1SHong Zhang   }
292942dc13f1SHong Zhang   PetscFunctionReturn(0);
293042dc13f1SHong Zhang }
293142dc13f1SHong Zhang 
2932d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMISComputeIdx_private(DM dm, PetscInt p, PetscInt numkeys, PetscInt keys[], PetscInt blocksize[], PetscInt nselectedvar[], PetscInt *selectedvar[], PetscInt *ii, PetscInt *idx)
2933d71ae5a4SJacob Faibussowitsch {
293442dc13f1SHong Zhang   PetscInt                 i, j, ncomps, nvar, key, offsetg, k, k1, offset = 0;
293542dc13f1SHong Zhang   DM_Network              *network = (DM_Network *)dm->data;
293642dc13f1SHong Zhang   DMNetworkComponentHeader header;
293742dc13f1SHong Zhang 
293842dc13f1SHong Zhang   PetscFunctionBegin;
29399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->DataSection, p, &offset));
294042dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray + offset))->ndata;
294142dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray + offset);
294242dc13f1SHong Zhang 
294342dc13f1SHong Zhang   for (i = 0; i < ncomps; i++) {
294442dc13f1SHong Zhang     key  = header->key[i];
294542dc13f1SHong Zhang     nvar = header->nvar[i];
294642dc13f1SHong Zhang     for (j = 0; j < numkeys; j++) {
294742dc13f1SHong Zhang       if (key != keys[j]) continue;
294842dc13f1SHong Zhang 
29499566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetGlobalVecOffset(dm, p, i, &offsetg));
295042dc13f1SHong Zhang       if (!blocksize || blocksize[j] == -1) {
295142dc13f1SHong Zhang         for (k = 0; k < nvar; k++) idx[(*ii)++] = offsetg + k;
295242dc13f1SHong Zhang       } else {
295342dc13f1SHong Zhang         for (k = 0; k < nvar; k += blocksize[j]) {
295442dc13f1SHong Zhang           for (k1 = 0; k1 < nselectedvar[j]; k1++) idx[(*ii)++] = offsetg + k + selectedvar[j][k1];
295542dc13f1SHong Zhang         }
295642dc13f1SHong Zhang       }
295742dc13f1SHong Zhang     }
295842dc13f1SHong Zhang   }
295942dc13f1SHong Zhang   PetscFunctionReturn(0);
296042dc13f1SHong Zhang }
296142dc13f1SHong Zhang 
296242dc13f1SHong Zhang /*@
296342dc13f1SHong Zhang   DMNetworkCreateIS - Create an index set object from the global vector of the network
296442dc13f1SHong Zhang 
296542dc13f1SHong Zhang   Collective
296642dc13f1SHong Zhang 
296742dc13f1SHong Zhang   Input Parameters:
296842dc13f1SHong Zhang + dm - DMNetwork object
296942dc13f1SHong Zhang . numkeys - number of keys
297042dc13f1SHong Zhang . keys - array of keys that define the components of the variables you wish to extract
297142dc13f1SHong Zhang . blocksize - block size of the variables associated to the component
297242dc13f1SHong Zhang . nselectedvar - number of variables in each block to select
297342dc13f1SHong Zhang - selectedvar - the offset into the block of each variable in each block to select
297442dc13f1SHong Zhang 
297542dc13f1SHong Zhang   Output Parameters:
297642dc13f1SHong Zhang . is - the index set
297742dc13f1SHong Zhang 
297842dc13f1SHong Zhang   Level: Advanced
297942dc13f1SHong Zhang 
298042dc13f1SHong Zhang   Notes:
298142dc13f1SHong 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.
298242dc13f1SHong Zhang 
2983db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `ISCreateGeneral()`, `DMNetworkCreateLocalIS()`
298442dc13f1SHong Zhang @*/
2985d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkCreateIS(DM dm, PetscInt numkeys, PetscInt keys[], PetscInt blocksize[], PetscInt nselectedvar[], PetscInt *selectedvar[], IS *is)
2986d71ae5a4SJacob Faibussowitsch {
298742dc13f1SHong Zhang   MPI_Comm    comm;
298842dc13f1SHong Zhang   DM_Network *network = (DM_Network *)dm->data;
298942dc13f1SHong Zhang   PetscInt    i, p, estart, eend, vstart, vend, nidx, *idx;
299042dc13f1SHong Zhang   PetscBool   ghost;
299142dc13f1SHong Zhang 
299242dc13f1SHong Zhang   PetscFunctionBegin;
29939566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
299442dc13f1SHong Zhang 
299542dc13f1SHong Zhang   /* Check input parameters */
299642dc13f1SHong Zhang   for (i = 0; i < numkeys; i++) {
299742dc13f1SHong Zhang     if (!blocksize || blocksize[i] == -1) continue;
299863a3b9bcSJacob Faibussowitsch     PetscCheck(nselectedvar[i] <= blocksize[i], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "number of selectedvariables %" PetscInt_FMT " cannot be larger than blocksize %" PetscInt_FMT, nselectedvar[i], blocksize[i]);
299942dc13f1SHong Zhang   }
300042dc13f1SHong Zhang 
30019566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetEdgeRange(dm, &estart, &eend));
30029566063dSJacob Faibussowitsch   PetscCall(DMNetworkGetVertexRange(dm, &vstart, &vend));
300342dc13f1SHong Zhang 
300442dc13f1SHong Zhang   /* Get local number of idx */
300542dc13f1SHong Zhang   nidx = 0;
300648a46eb9SPierre Jolivet   for (p = estart; p < eend; p++) PetscCall(DMISAddSize_private(network, p, numkeys, keys, blocksize, nselectedvar, &nidx));
300742dc13f1SHong Zhang   for (p = vstart; p < vend; p++) {
30089566063dSJacob Faibussowitsch     PetscCall(DMNetworkIsGhostVertex(dm, p, &ghost));
300942dc13f1SHong Zhang     if (ghost) continue;
30109566063dSJacob Faibussowitsch     PetscCall(DMISAddSize_private(network, p, numkeys, keys, blocksize, nselectedvar, &nidx));
301142dc13f1SHong Zhang   }
301242dc13f1SHong Zhang 
301342dc13f1SHong Zhang   /* Compute idx */
30149566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nidx, &idx));
301542dc13f1SHong Zhang   i = 0;
301648a46eb9SPierre Jolivet   for (p = estart; p < eend; p++) PetscCall(DMISComputeIdx_private(dm, p, numkeys, keys, blocksize, nselectedvar, selectedvar, &i, idx));
301742dc13f1SHong Zhang   for (p = vstart; p < vend; p++) {
30189566063dSJacob Faibussowitsch     PetscCall(DMNetworkIsGhostVertex(dm, p, &ghost));
301942dc13f1SHong Zhang     if (ghost) continue;
30209566063dSJacob Faibussowitsch     PetscCall(DMISComputeIdx_private(dm, p, numkeys, keys, blocksize, nselectedvar, selectedvar, &i, idx));
302142dc13f1SHong Zhang   }
302242dc13f1SHong Zhang 
302342dc13f1SHong Zhang   /* Create is */
30249566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm, nidx, idx, PETSC_COPY_VALUES, is));
30259566063dSJacob Faibussowitsch   PetscCall(PetscFree(idx));
302642dc13f1SHong Zhang   PetscFunctionReturn(0);
302742dc13f1SHong Zhang }
302842dc13f1SHong Zhang 
3029d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMISComputeLocalIdx_private(DM dm, PetscInt p, PetscInt numkeys, PetscInt keys[], PetscInt blocksize[], PetscInt nselectedvar[], PetscInt *selectedvar[], PetscInt *ii, PetscInt *idx)
3030d71ae5a4SJacob Faibussowitsch {
303142dc13f1SHong Zhang   PetscInt                 i, j, ncomps, nvar, key, offsetl, k, k1, offset = 0;
303242dc13f1SHong Zhang   DM_Network              *network = (DM_Network *)dm->data;
303342dc13f1SHong Zhang   DMNetworkComponentHeader header;
303442dc13f1SHong Zhang 
303542dc13f1SHong Zhang   PetscFunctionBegin;
30369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(network->DataSection, p, &offset));
303742dc13f1SHong Zhang   ncomps = ((DMNetworkComponentHeader)(network->componentdataarray + offset))->ndata;
303842dc13f1SHong Zhang   header = (DMNetworkComponentHeader)(network->componentdataarray + offset);
303942dc13f1SHong Zhang 
304042dc13f1SHong Zhang   for (i = 0; i < ncomps; i++) {
304142dc13f1SHong Zhang     key  = header->key[i];
304242dc13f1SHong Zhang     nvar = header->nvar[i];
304342dc13f1SHong Zhang     for (j = 0; j < numkeys; j++) {
304442dc13f1SHong Zhang       if (key != keys[j]) continue;
304542dc13f1SHong Zhang 
30469566063dSJacob Faibussowitsch       PetscCall(DMNetworkGetLocalVecOffset(dm, p, i, &offsetl));
304742dc13f1SHong Zhang       if (!blocksize || blocksize[j] == -1) {
304842dc13f1SHong Zhang         for (k = 0; k < nvar; k++) idx[(*ii)++] = offsetl + k;
304942dc13f1SHong Zhang       } else {
305042dc13f1SHong Zhang         for (k = 0; k < nvar; k += blocksize[j]) {
305142dc13f1SHong Zhang           for (k1 = 0; k1 < nselectedvar[j]; k1++) idx[(*ii)++] = offsetl + k + selectedvar[j][k1];
305242dc13f1SHong Zhang         }
305342dc13f1SHong Zhang       }
305442dc13f1SHong Zhang     }
305542dc13f1SHong Zhang   }
305642dc13f1SHong Zhang   PetscFunctionReturn(0);
305742dc13f1SHong Zhang }
305842dc13f1SHong Zhang 
305942dc13f1SHong Zhang /*@
306042dc13f1SHong Zhang   DMNetworkCreateLocalIS - Create an index set object from the local vector of the network
306142dc13f1SHong Zhang 
306242dc13f1SHong Zhang   Not collective
306342dc13f1SHong Zhang 
306442dc13f1SHong Zhang   Input Parameters:
306542dc13f1SHong Zhang + dm - DMNetwork object
306642dc13f1SHong Zhang . numkeys - number of keys
306742dc13f1SHong Zhang . keys - array of keys that define the components of the variables you wish to extract
306842dc13f1SHong Zhang . blocksize - block size of the variables associated to the component
306942dc13f1SHong Zhang . nselectedvar - number of variables in each block to select
307042dc13f1SHong Zhang - selectedvar - the offset into the block of each variable in each block to select
307142dc13f1SHong Zhang 
307242dc13f1SHong Zhang   Output Parameters:
307342dc13f1SHong Zhang . is - the index set
307442dc13f1SHong Zhang 
307542dc13f1SHong Zhang   Level: Advanced
307642dc13f1SHong Zhang 
307742dc13f1SHong Zhang   Notes:
307842dc13f1SHong 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.
307942dc13f1SHong Zhang 
3080db781477SPatrick Sanan .seealso: `DMNetworkCreate()`, `DMNetworkCreateIS`, `ISCreateGeneral()`
308142dc13f1SHong Zhang @*/
3082d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkCreateLocalIS(DM dm, PetscInt numkeys, PetscInt keys[], PetscInt blocksize[], PetscInt nselectedvar[], PetscInt *selectedvar[], IS *is)
3083d71ae5a4SJacob Faibussowitsch {
308442dc13f1SHong Zhang   DM_Network *network = (DM_Network *)dm->data;
308542dc13f1SHong Zhang   PetscInt    i, p, pstart, pend, nidx, *idx;
308642dc13f1SHong Zhang 
308742dc13f1SHong Zhang   PetscFunctionBegin;
308842dc13f1SHong Zhang   /* Check input parameters */
308942dc13f1SHong Zhang   for (i = 0; i < numkeys; i++) {
309042dc13f1SHong Zhang     if (!blocksize || blocksize[i] == -1) continue;
309163a3b9bcSJacob Faibussowitsch     PetscCheck(nselectedvar[i] <= blocksize[i], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "number of selectedvariables %" PetscInt_FMT " cannot be larger than blocksize %" PetscInt_FMT, nselectedvar[i], blocksize[i]);
309242dc13f1SHong Zhang   }
309342dc13f1SHong Zhang 
3094daad07d3SAidan Hamilton   pstart = network->cloneshared->pStart;
3095daad07d3SAidan Hamilton   pend   = network->cloneshared->pEnd;
309642dc13f1SHong Zhang 
309742dc13f1SHong Zhang   /* Get local number of idx */
309842dc13f1SHong Zhang   nidx = 0;
309948a46eb9SPierre Jolivet   for (p = pstart; p < pend; p++) PetscCall(DMISAddSize_private(network, p, numkeys, keys, blocksize, nselectedvar, &nidx));
310042dc13f1SHong Zhang 
310142dc13f1SHong Zhang   /* Compute local idx */
31029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nidx, &idx));
310342dc13f1SHong Zhang   i = 0;
310448a46eb9SPierre Jolivet   for (p = pstart; p < pend; p++) PetscCall(DMISComputeLocalIdx_private(dm, p, numkeys, keys, blocksize, nselectedvar, selectedvar, &i, idx));
310542dc13f1SHong Zhang 
310642dc13f1SHong Zhang   /* Create is */
31079566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nidx, idx, PETSC_COPY_VALUES, is));
31089566063dSJacob Faibussowitsch   PetscCall(PetscFree(idx));
310942dc13f1SHong Zhang   PetscFunctionReturn(0);
311042dc13f1SHong Zhang }
3111daad07d3SAidan Hamilton /*@
3112d5b43468SJose E. Roman   DMNetworkFinalizeComponents - Sets up internal data structures for the sections and components. It is called after registering new components and adding all components
3113daad07d3SAidan Hamilton   to the cloned network. After calling this subroutine, no new components can be added to the network.
3114daad07d3SAidan Hamilton 
3115daad07d3SAidan Hamilton   Collective
3116daad07d3SAidan Hamilton 
3117daad07d3SAidan Hamilton   Input Parameters:
3118daad07d3SAidan Hamilton . dm - the dmnetwork object
3119daad07d3SAidan Hamilton 
3120daad07d3SAidan Hamilton   Level: beginner
3121daad07d3SAidan Hamilton 
3122daad07d3SAidan Hamilton .seealso: `DMNetworkAddComponent()`, `DMNetworkRegisterComponent()`, `DMSetUp()`
3123daad07d3SAidan Hamilton @*/
3124d71ae5a4SJacob Faibussowitsch PetscErrorCode DMNetworkFinalizeComponents(DM dm)
3125d71ae5a4SJacob Faibussowitsch {
3126daad07d3SAidan Hamilton   DM_Network *network = (DM_Network *)dm->data;
3127daad07d3SAidan Hamilton 
3128daad07d3SAidan Hamilton   PetscFunctionBegin;
3129daad07d3SAidan Hamilton   if (network->componentsetup) PetscFunctionReturn(0);
3130daad07d3SAidan Hamilton   PetscCall(DMNetworkComponentSetUp(dm));
3131daad07d3SAidan Hamilton   PetscCall(DMNetworkVariablesSetUp(dm));
3132daad07d3SAidan Hamilton   PetscCall(DMSetLocalSection(network->plex, network->DofSection));
3133daad07d3SAidan Hamilton   PetscCall(DMGetGlobalSection(network->plex, &network->GlobalDofSection));
3134daad07d3SAidan Hamilton   network->componentsetup = PETSC_TRUE;
3135daad07d3SAidan Hamilton   PetscFunctionReturn(0);
3136daad07d3SAidan Hamilton }
3137