1af0996ceSBarry Smith #include <petsc/private/dmmbimpl.h> /*I "petscdmmoab.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/vecimpl.h> 3032b8ab6SVijay Mahadevan 4032b8ab6SVijay Mahadevan #include <petscdmmoab.h> 5da6192ceSVijay Mahadevan #include <MBTagConventions.hpp> 6b117cd09SVijay Mahadevan #include <moab/NestedRefine.hpp> 7032b8ab6SVijay Mahadevan 8a86ed394SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMMoab_Compute_NNZ_From_Connectivity(DM, PetscInt*, PetscInt*, PetscInt*, PetscInt*, PetscBool); 9032b8ab6SVijay Mahadevan 10304006b3SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMCreateMatrix_Moab(DM dm, Mat *J) 11032b8ab6SVijay Mahadevan { 12c2612ac9SVijay Mahadevan PetscInt innz = 0, ionz = 0, nlsiz; 13032b8ab6SVijay Mahadevan DM_Moab *dmmoab = (DM_Moab*)dm->data; 14da6192ceSVijay Mahadevan PetscInt *nnz = 0, *onz = 0; 15032b8ab6SVijay Mahadevan char *tmp = 0; 162494be97SVijay Mahadevan Mat A; 17baf0d1e0SVijay Mahadevan MatType mtype; 18032b8ab6SVijay Mahadevan 19032b8ab6SVijay Mahadevan PetscFunctionBegin; 20032b8ab6SVijay Mahadevan PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21032b8ab6SVijay Mahadevan PetscValidPointer(J, 3); 22032b8ab6SVijay Mahadevan 23db66d124SVijay Mahadevan /* next, need to allocate the non-zero arrays to enable pre-allocation */ 24baf0d1e0SVijay Mahadevan mtype = dm->mattype; 25*9566063dSJacob Faibussowitsch PetscCall(PetscStrstr(mtype, MATBAIJ, &tmp)); 2682dfd14aSVijay Mahadevan nlsiz = (tmp ? dmmoab->nloc : dmmoab->nloc * dmmoab->numFields); 27032b8ab6SVijay Mahadevan 28032b8ab6SVijay Mahadevan /* allocate the nnz, onz arrays based on block size and local nodes */ 29*9566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nlsiz, &nnz, nlsiz, &onz)); 30032b8ab6SVijay Mahadevan 31032b8ab6SVijay Mahadevan /* compute the nonzero pattern based on MOAB connectivity data for local elements */ 32*9566063dSJacob Faibussowitsch PetscCall(DMMoab_Compute_NNZ_From_Connectivity(dm, &innz, nnz, &ionz, onz, (tmp ? PETSC_TRUE : PETSC_FALSE))); 33032b8ab6SVijay Mahadevan 34da6192ceSVijay Mahadevan /* create the Matrix and set its type as specified by user */ 35*9566063dSJacob Faibussowitsch PetscCall(MatCreate((((PetscObject)dm)->comm), &A)); 36*9566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, dmmoab->nloc * dmmoab->numFields, dmmoab->nloc * dmmoab->numFields, PETSC_DETERMINE, PETSC_DETERMINE)); 37*9566063dSJacob Faibussowitsch PetscCall(MatSetType(A, mtype)); 38*9566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(A, dmmoab->bs)); 39*9566063dSJacob Faibussowitsch PetscCall(MatSetDM(A, dm)); /* set DM reference */ 40*9566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(A)); 41da6192ceSVijay Mahadevan 427a8be351SBarry Smith PetscCheck(dmmoab->ltog_map,(((PetscObject)dm)->comm), PETSC_ERR_ORDER, "Cannot create a DMMoab Mat without calling DMSetUp first."); 43*9566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A, dmmoab->ltog_map, dmmoab->ltog_map)); 44032b8ab6SVijay Mahadevan 45032b8ab6SVijay Mahadevan /* set preallocation based on different supported Mat types */ 46*9566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A, innz, nnz)); 47*9566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(A, innz, nnz, ionz, onz)); 48*9566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(A, dmmoab->bs, innz, nnz)); 49*9566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJSetPreallocation(A, dmmoab->bs, innz, nnz, ionz, onz)); 50032b8ab6SVijay Mahadevan 51da8c5b52SVijay Mahadevan /* clean up temporary memory */ 52*9566063dSJacob Faibussowitsch PetscCall(PetscFree2(nnz, onz)); 53da8c5b52SVijay Mahadevan 54da8c5b52SVijay Mahadevan /* set up internal matrix data-structures */ 55*9566063dSJacob Faibussowitsch PetscCall(MatSetUp(A)); 56da8c5b52SVijay Mahadevan 57e92d1c7cSVijay Mahadevan /* MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE); */ 589c368985SVijay Mahadevan 592494be97SVijay Mahadevan *J = A; 60032b8ab6SVijay Mahadevan PetscFunctionReturn(0); 61032b8ab6SVijay Mahadevan } 62032b8ab6SVijay Mahadevan 63a86ed394SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMMoab_Compute_NNZ_From_Connectivity(DM dm, PetscInt* innz, PetscInt* nnz, PetscInt* ionz, PetscInt* onz, PetscBool isbaij) 64032b8ab6SVijay Mahadevan { 65b117cd09SVijay Mahadevan PetscInt i, f, nloc, vpere, bs, n_nnz, n_onz, ivtx = 0; 66c2612ac9SVijay Mahadevan PetscInt ibs, jbs, inbsize, iobsize, nfields, nlsiz; 67032b8ab6SVijay Mahadevan DM_Moab *dmmoab = (DM_Moab*)dm->data; 689c368985SVijay Mahadevan moab::Range found; 699c368985SVijay Mahadevan std::vector<moab::EntityHandle> adjs, storage; 705905e1eaSVijay Mahadevan PetscBool isinterlaced; 71da6192ceSVijay Mahadevan moab::EntityHandle vtx; 72032b8ab6SVijay Mahadevan moab::ErrorCode merr; 73032b8ab6SVijay Mahadevan 74032b8ab6SVijay Mahadevan PetscFunctionBegin; 75032b8ab6SVijay Mahadevan bs = dmmoab->bs; 76032b8ab6SVijay Mahadevan nloc = dmmoab->nloc; 775905e1eaSVijay Mahadevan nfields = dmmoab->numFields; 7882dfd14aSVijay Mahadevan isinterlaced = (isbaij || bs == nfields ? PETSC_TRUE : PETSC_FALSE); 79c2612ac9SVijay Mahadevan nlsiz = (isinterlaced ? nloc : nloc * nfields); 80032b8ab6SVijay Mahadevan 81f6829af0SVijay Mahadevan /* loop over the locally owned vertices and figure out the NNZ pattern using connectivity information */ 8264e1c140SVijay Mahadevan for (moab::Range::const_iterator iter = dmmoab->vowned->begin(); iter != dmmoab->vowned->end(); iter++, ivtx++) { 83032b8ab6SVijay Mahadevan 84da6192ceSVijay Mahadevan vtx = *iter; 85da6192ceSVijay Mahadevan /* Get adjacency information for current vertex - i.e., all elements of dimension (dim) that connects 86da6192ceSVijay Mahadevan to the current vertex. We can then decipher if a vertex is ghosted or not and compute the 87da6192ceSVijay Mahadevan non-zero pattern accordingly. */ 8864e1c140SVijay Mahadevan adjs.clear(); 89e92d1c7cSVijay Mahadevan if (dmmoab->hlevel && (dmmoab->pcomm->size() == 1)) { 909c368985SVijay Mahadevan merr = dmmoab->hierarchy->get_adjacencies(vtx, dmmoab->dim, adjs); MBERRNM(merr); 919c368985SVijay Mahadevan } 929c368985SVijay Mahadevan else { 93e92d1c7cSVijay Mahadevan merr = dmmoab->mbiface->get_adjacencies(&vtx, 1, dmmoab->dim, true, adjs, moab::Interface::UNION); MBERRNM(merr); 949c368985SVijay Mahadevan } 950df6e276SVijay Mahadevan 96e427d9c9SVijay Mahadevan /* reset counters */ 97e427d9c9SVijay Mahadevan n_nnz = n_onz = 0; 98e427d9c9SVijay Mahadevan found.clear(); 99e427d9c9SVijay Mahadevan 10015de014fSVijay Mahadevan /* loop over vertices and update the number of connectivity */ 1019c368985SVijay Mahadevan for (unsigned jter = 0; jter < adjs.size(); ++jter) { 1020df6e276SVijay Mahadevan 10315de014fSVijay Mahadevan /* Get connectivity information in canonical ordering for the local element */ 1049c368985SVijay Mahadevan const moab::EntityHandle *connect; 1059c368985SVijay Mahadevan std::vector<moab::EntityHandle> cconnect; 1069c368985SVijay Mahadevan merr = dmmoab->mbiface->get_connectivity(adjs[jter], connect, vpere, false, &storage); MBERRNM(merr); 1070df6e276SVijay Mahadevan 108f6829af0SVijay Mahadevan /* loop over each element connected to the adjacent vertex and update as needed */ 10915de014fSVijay Mahadevan for (i = 0; i < vpere; ++i) { 11064e1c140SVijay Mahadevan /* find the truly user-expected layer of ghosted entities to decipher NNZ pattern */ 111f6829af0SVijay Mahadevan if (connect[i] == vtx || found.find(connect[i]) != found.end()) continue; /* make sure we don't double count shared vertices */ 11264e1c140SVijay Mahadevan if (dmmoab->vghost->find(connect[i]) != dmmoab->vghost->end()) n_onz++; /* update out-of-proc onz */ 113f6829af0SVijay Mahadevan else n_nnz++; /* else local vertex */ 11415de014fSVijay Mahadevan found.insert(connect[i]); 11515de014fSVijay Mahadevan } 11615de014fSVijay Mahadevan } 1179daf19fdSVijay Mahadevan storage.clear(); 11815de014fSVijay Mahadevan 11915de014fSVijay Mahadevan if (isbaij) { 12015de014fSVijay Mahadevan nnz[ivtx] = n_nnz; /* leave out self to avoid repeats -> node shared by multiple elements */ 1215905e1eaSVijay Mahadevan if (onz) { 1225905e1eaSVijay Mahadevan onz[ivtx] = n_onz; /* add ghost non-owned nodes */ 1235905e1eaSVijay Mahadevan } 12415de014fSVijay Mahadevan } 125f6829af0SVijay Mahadevan else { /* AIJ matrices */ 1265905e1eaSVijay Mahadevan if (!isinterlaced) { 1275905e1eaSVijay Mahadevan for (f = 0; f < nfields; f++) { 1285905e1eaSVijay Mahadevan nnz[f * nloc + ivtx] = n_nnz; /* leave out self to avoid repeats -> node shared by multiple elements */ 1295905e1eaSVijay Mahadevan if (onz) 1305905e1eaSVijay Mahadevan onz[f * nloc + ivtx] = n_onz; /* add ghost non-owned nodes */ 1315905e1eaSVijay Mahadevan } 1325905e1eaSVijay Mahadevan } 1335905e1eaSVijay Mahadevan else { 1345905e1eaSVijay Mahadevan for (f = 0; f < nfields; f++) { 1355905e1eaSVijay Mahadevan nnz[nfields * ivtx + f] = n_nnz; /* leave out self to avoid repeats -> node shared by multiple elements */ 1365905e1eaSVijay Mahadevan if (onz) 1375905e1eaSVijay Mahadevan onz[nfields * ivtx + f] = n_onz; /* add ghost non-owned nodes */ 1385905e1eaSVijay Mahadevan } 1390df6e276SVijay Mahadevan } 1400df6e276SVijay Mahadevan } 1410df6e276SVijay Mahadevan } 1420df6e276SVijay Mahadevan 143c2612ac9SVijay Mahadevan for (i = 0; i < nlsiz; i++) 1445905e1eaSVijay Mahadevan nnz[i] += 1; /* self count the node */ 1455905e1eaSVijay Mahadevan 14682dfd14aSVijay Mahadevan for (ivtx = 0; ivtx < nloc; ivtx++) { 1475905e1eaSVijay Mahadevan if (!isbaij) { 1485905e1eaSVijay Mahadevan for (ibs = 0; ibs < nfields; ibs++) { 14982dfd14aSVijay Mahadevan if (dmmoab->dfill) { /* first address the diagonal block */ 1505905e1eaSVijay Mahadevan /* just add up the ints -- easier/faster rather than branching based on "1" */ 1515905e1eaSVijay Mahadevan for (jbs = 0, inbsize = 0; jbs < nfields; jbs++) 1525905e1eaSVijay Mahadevan inbsize += dmmoab->dfill[ibs * nfields + jbs]; 1535905e1eaSVijay Mahadevan } 15482dfd14aSVijay Mahadevan else inbsize = nfields; /* dense coupling since user didn't specify the component fill explicitly */ 15582dfd14aSVijay Mahadevan if (isinterlaced) nnz[ivtx * nfields + ibs] *= inbsize; 15682dfd14aSVijay Mahadevan else nnz[ibs * nloc + ivtx] *= inbsize; 1575905e1eaSVijay Mahadevan 1585905e1eaSVijay Mahadevan if (onz) { 15982dfd14aSVijay Mahadevan if (dmmoab->ofill) { /* next address the off-diagonal block */ 1605905e1eaSVijay Mahadevan /* just add up the ints -- easier/faster rather than branching based on "1" */ 1615905e1eaSVijay Mahadevan for (jbs = 0, iobsize = 0; jbs < nfields; jbs++) 1625905e1eaSVijay Mahadevan iobsize += dmmoab->dfill[ibs * nfields + jbs]; 1635905e1eaSVijay Mahadevan } 16482dfd14aSVijay Mahadevan else iobsize = nfields; /* dense coupling since user didn't specify the component fill explicitly */ 16582dfd14aSVijay Mahadevan if (isinterlaced) onz[ivtx * nfields + ibs] *= iobsize; 16682dfd14aSVijay Mahadevan else onz[ibs * nloc + ivtx] *= iobsize; 1675905e1eaSVijay Mahadevan } 1685905e1eaSVijay Mahadevan } 1695905e1eaSVijay Mahadevan } 1705905e1eaSVijay Mahadevan else { 17182dfd14aSVijay Mahadevan /* check if we got overzealous in our nnz and onz computations */ 17282dfd14aSVijay Mahadevan nnz[ivtx] = (nnz[ivtx] > dmmoab->nloc ? dmmoab->nloc : nnz[ivtx]); 17382dfd14aSVijay Mahadevan if (onz) onz[ivtx] = (onz[ivtx] > dmmoab->nloc ? dmmoab->nloc : onz[ivtx]); 1745905e1eaSVijay Mahadevan } 1755905e1eaSVijay Mahadevan } 1765905e1eaSVijay Mahadevan /* update innz and ionz based on local maxima */ 1775905e1eaSVijay Mahadevan if (innz || ionz) { 1780df6e276SVijay Mahadevan if (innz) *innz = 0; 1790df6e276SVijay Mahadevan if (ionz) *ionz = 0; 180c2612ac9SVijay Mahadevan for (i = 0; i < nlsiz; i++) { 181da6192ceSVijay Mahadevan if (innz && (nnz[i] > *innz)) *innz = nnz[i]; 182da6192ceSVijay Mahadevan if ((ionz && onz) && (onz[i] > *ionz)) *ionz = onz[i]; 183032b8ab6SVijay Mahadevan } 1845905e1eaSVijay Mahadevan } 1850df6e276SVijay Mahadevan PetscFunctionReturn(0); 186032b8ab6SVijay Mahadevan } 187032b8ab6SVijay Mahadevan 1885905e1eaSVijay Mahadevan static PetscErrorCode DMMoabSetBlockFills_Private(PetscInt w, const PetscInt *fill, PetscInt **rfill) 1895905e1eaSVijay Mahadevan { 1905905e1eaSVijay Mahadevan PetscInt i, j, *ifill; 1915905e1eaSVijay Mahadevan 1925905e1eaSVijay Mahadevan PetscFunctionBegin; 1935905e1eaSVijay Mahadevan if (!fill) PetscFunctionReturn(0); 194*9566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(w * w, &ifill)); 1955905e1eaSVijay Mahadevan for (i = 0; i < w; i++) { 1965905e1eaSVijay Mahadevan for (j = 0; j < w; j++) 1975905e1eaSVijay Mahadevan ifill[i * w + j] = fill[i * w + j]; 1985905e1eaSVijay Mahadevan } 1995905e1eaSVijay Mahadevan 2005905e1eaSVijay Mahadevan *rfill = ifill; 2015905e1eaSVijay Mahadevan PetscFunctionReturn(0); 2025905e1eaSVijay Mahadevan } 2035905e1eaSVijay Mahadevan 204cab5ea25SPierre Jolivet /*@C 2055905e1eaSVijay Mahadevan DMMoabSetBlockFills - Sets the fill pattern in each block for a multi-component problem 2065905e1eaSVijay Mahadevan of the matrix returned by DMCreateMatrix(). 2075905e1eaSVijay Mahadevan 208d083f849SBarry Smith Logically Collective on da 2095905e1eaSVijay Mahadevan 210d8d19677SJose E. Roman Input Parameters: 2115905e1eaSVijay Mahadevan + dm - the DMMoab object 2125905e1eaSVijay Mahadevan . dfill - the fill pattern in the diagonal block (may be NULL, means use dense block) 2135905e1eaSVijay Mahadevan - ofill - the fill pattern in the off-diagonal blocks 2145905e1eaSVijay Mahadevan 2155905e1eaSVijay Mahadevan Level: developer 2165905e1eaSVijay Mahadevan 21795452b02SPatrick Sanan Notes: 21895452b02SPatrick Sanan This only makes sense when you are doing multicomponent problems but using the 2195905e1eaSVijay Mahadevan MPIAIJ matrix format 2205905e1eaSVijay Mahadevan 2215905e1eaSVijay Mahadevan The format for dfill and ofill is a 2 dimensional dof by dof matrix with 1 entries 2225905e1eaSVijay Mahadevan representing coupling and 0 entries for missing coupling. For example 2235905e1eaSVijay Mahadevan $ dfill[9] = {1, 0, 0, 2245905e1eaSVijay Mahadevan $ 1, 1, 0, 2255905e1eaSVijay Mahadevan $ 0, 1, 1} 2265905e1eaSVijay Mahadevan means that row 0 is coupled with only itself in the diagonal block, row 1 is coupled with 2275905e1eaSVijay Mahadevan itself and row 0 (in the diagonal block) and row 2 is coupled with itself and row 1 (in the 2285905e1eaSVijay Mahadevan diagonal block). 2295905e1eaSVijay Mahadevan 2305905e1eaSVijay Mahadevan DMDASetGetMatrix() allows you to provide general code for those more complicated nonzero patterns then 2315905e1eaSVijay Mahadevan can be represented in the dfill, ofill format 2325905e1eaSVijay Mahadevan 2335905e1eaSVijay Mahadevan Contributed by Glenn Hammond 2345905e1eaSVijay Mahadevan 2355905e1eaSVijay Mahadevan .seealso DMCreateMatrix(), DMDASetGetMatrix(), DMSetMatrixPreallocateOnly() 2365905e1eaSVijay Mahadevan 2375905e1eaSVijay Mahadevan @*/ 2385905e1eaSVijay Mahadevan PetscErrorCode DMMoabSetBlockFills(DM dm, const PetscInt *dfill, const PetscInt *ofill) 2395905e1eaSVijay Mahadevan { 2405905e1eaSVijay Mahadevan DM_Moab *dmmoab = (DM_Moab*)dm->data; 2415905e1eaSVijay Mahadevan 2425905e1eaSVijay Mahadevan PetscFunctionBegin; 2435905e1eaSVijay Mahadevan PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 244*9566063dSJacob Faibussowitsch PetscCall(DMMoabSetBlockFills_Private(dmmoab->numFields, dfill, &dmmoab->dfill)); 245*9566063dSJacob Faibussowitsch PetscCall(DMMoabSetBlockFills_Private(dmmoab->numFields, ofill, &dmmoab->ofill)); 2465905e1eaSVijay Mahadevan PetscFunctionReturn(0); 2475905e1eaSVijay Mahadevan } 248