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, §iong)); 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, §iong)); 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, §ionGlobal)); 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