xref: /petsc/src/dm/impls/moab/dmmbmat.cxx (revision 1baa6e3354bfe224b33a0c158f482508792a8a6e)
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;
259566063dSJacob 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 */
299566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(nlsiz, &nnz, nlsiz, &onz));
30032b8ab6SVijay Mahadevan 
31032b8ab6SVijay Mahadevan   /* compute the nonzero pattern based on MOAB connectivity data for local elements */
329566063dSJacob 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 */
359566063dSJacob Faibussowitsch   PetscCall(MatCreate((((PetscObject)dm)->comm), &A));
369566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(A, dmmoab->nloc * dmmoab->numFields, dmmoab->nloc * dmmoab->numFields, PETSC_DETERMINE, PETSC_DETERMINE));
379566063dSJacob Faibussowitsch   PetscCall(MatSetType(A, mtype));
389566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(A, dmmoab->bs));
399566063dSJacob Faibussowitsch   PetscCall(MatSetDM(A, dm)); /* set DM reference */
409566063dSJacob 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.");
439566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(A, dmmoab->ltog_map, dmmoab->ltog_map));
44032b8ab6SVijay Mahadevan 
45032b8ab6SVijay Mahadevan   /* set preallocation based on different supported Mat types */
469566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(A, innz, nnz));
479566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(A, innz, nnz, ionz, onz));
489566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(A, dmmoab->bs, innz, nnz));
499566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(A, dmmoab->bs, innz, nnz, ionz, onz));
50032b8ab6SVijay Mahadevan 
51da8c5b52SVijay Mahadevan   /* clean up temporary memory */
529566063dSJacob Faibussowitsch   PetscCall(PetscFree2(nnz, onz));
53da8c5b52SVijay Mahadevan 
54da8c5b52SVijay Mahadevan   /* set up internal matrix data-structures */
559566063dSJacob 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);
91*1baa6e33SBarry Smith     } else {
92e92d1c7cSVijay Mahadevan       merr = dmmoab->mbiface->get_adjacencies(&vtx, 1, dmmoab->dim, true, adjs, moab::Interface::UNION); MBERRNM(merr);
939c368985SVijay Mahadevan     }
940df6e276SVijay Mahadevan 
95e427d9c9SVijay Mahadevan     /* reset counters */
96e427d9c9SVijay Mahadevan     n_nnz = n_onz = 0;
97e427d9c9SVijay Mahadevan     found.clear();
98e427d9c9SVijay Mahadevan 
9915de014fSVijay Mahadevan     /* loop over vertices and update the number of connectivity */
1009c368985SVijay Mahadevan     for (unsigned jter = 0; jter < adjs.size(); ++jter) {
1010df6e276SVijay Mahadevan 
10215de014fSVijay Mahadevan       /* Get connectivity information in canonical ordering for the local element */
1039c368985SVijay Mahadevan       const moab::EntityHandle *connect;
1049c368985SVijay Mahadevan       std::vector<moab::EntityHandle> cconnect;
1059c368985SVijay Mahadevan       merr = dmmoab->mbiface->get_connectivity(adjs[jter], connect, vpere, false, &storage); MBERRNM(merr);
1060df6e276SVijay Mahadevan 
107f6829af0SVijay Mahadevan       /* loop over each element connected to the adjacent vertex and update as needed */
10815de014fSVijay Mahadevan       for (i = 0; i < vpere; ++i) {
10964e1c140SVijay Mahadevan         /* find the truly user-expected layer of ghosted entities to decipher NNZ pattern */
110f6829af0SVijay Mahadevan         if (connect[i] == vtx || found.find(connect[i]) != found.end()) continue; /* make sure we don't double count shared vertices */
11164e1c140SVijay Mahadevan         if (dmmoab->vghost->find(connect[i]) != dmmoab->vghost->end()) n_onz++; /* update out-of-proc onz */
112f6829af0SVijay Mahadevan         else n_nnz++; /* else local vertex */
11315de014fSVijay Mahadevan         found.insert(connect[i]);
11415de014fSVijay Mahadevan       }
11515de014fSVijay Mahadevan     }
1169daf19fdSVijay Mahadevan     storage.clear();
11715de014fSVijay Mahadevan 
11815de014fSVijay Mahadevan     if (isbaij) {
11915de014fSVijay Mahadevan       nnz[ivtx] = n_nnz;  /* leave out self to avoid repeats -> node shared by multiple elements */
1205905e1eaSVijay Mahadevan       if (onz) {
1215905e1eaSVijay Mahadevan         onz[ivtx] = n_onz; /* add ghost non-owned nodes */
1225905e1eaSVijay Mahadevan       }
123*1baa6e33SBarry Smith     } else { /* AIJ matrices */
1245905e1eaSVijay Mahadevan       if (!isinterlaced) {
1255905e1eaSVijay Mahadevan         for (f = 0; f < nfields; f++) {
1265905e1eaSVijay Mahadevan           nnz[f * nloc + ivtx] = n_nnz; /* leave out self to avoid repeats -> node shared by multiple elements */
1275905e1eaSVijay Mahadevan           if (onz)
1285905e1eaSVijay Mahadevan             onz[f * nloc + ivtx] = n_onz; /* add ghost non-owned nodes */
1295905e1eaSVijay Mahadevan         }
130*1baa6e33SBarry Smith       } else {
1315905e1eaSVijay Mahadevan         for (f = 0; f < nfields; f++) {
1325905e1eaSVijay Mahadevan           nnz[nfields * ivtx + f] = n_nnz; /* leave out self to avoid repeats -> node shared by multiple elements */
1335905e1eaSVijay Mahadevan           if (onz)
1345905e1eaSVijay Mahadevan             onz[nfields * ivtx + f] = n_onz; /* add ghost non-owned nodes */
1355905e1eaSVijay Mahadevan         }
1360df6e276SVijay Mahadevan       }
1370df6e276SVijay Mahadevan     }
1380df6e276SVijay Mahadevan   }
1390df6e276SVijay Mahadevan 
140c2612ac9SVijay Mahadevan   for (i = 0; i < nlsiz; i++)
1415905e1eaSVijay Mahadevan     nnz[i] += 1; /* self count the node */
1425905e1eaSVijay Mahadevan 
14382dfd14aSVijay Mahadevan   for (ivtx = 0; ivtx < nloc; ivtx++) {
1445905e1eaSVijay Mahadevan     if (!isbaij) {
1455905e1eaSVijay Mahadevan       for (ibs = 0; ibs < nfields; ibs++) {
14682dfd14aSVijay Mahadevan         if (dmmoab->dfill) {  /* first address the diagonal block */
1475905e1eaSVijay Mahadevan           /* just add up the ints -- easier/faster rather than branching based on "1" */
1485905e1eaSVijay Mahadevan           for (jbs = 0, inbsize = 0; jbs < nfields; jbs++)
1495905e1eaSVijay Mahadevan             inbsize += dmmoab->dfill[ibs * nfields + jbs];
1505905e1eaSVijay Mahadevan         }
15182dfd14aSVijay Mahadevan         else inbsize = nfields; /* dense coupling since user didn't specify the component fill explicitly */
15282dfd14aSVijay Mahadevan         if (isinterlaced) nnz[ivtx * nfields + ibs] *= inbsize;
15382dfd14aSVijay Mahadevan         else nnz[ibs * nloc + ivtx] *= inbsize;
1545905e1eaSVijay Mahadevan 
1555905e1eaSVijay Mahadevan         if (onz) {
15682dfd14aSVijay Mahadevan           if (dmmoab->ofill) {  /* next address the off-diagonal block */
1575905e1eaSVijay Mahadevan             /* just add up the ints -- easier/faster rather than branching based on "1" */
1585905e1eaSVijay Mahadevan             for (jbs = 0, iobsize = 0; jbs < nfields; jbs++)
1595905e1eaSVijay Mahadevan               iobsize += dmmoab->dfill[ibs * nfields + jbs];
1605905e1eaSVijay Mahadevan           }
16182dfd14aSVijay Mahadevan           else iobsize = nfields; /* dense coupling since user didn't specify the component fill explicitly */
16282dfd14aSVijay Mahadevan           if (isinterlaced) onz[ivtx * nfields + ibs] *= iobsize;
16382dfd14aSVijay Mahadevan           else onz[ibs * nloc + ivtx] *= iobsize;
1645905e1eaSVijay Mahadevan         }
1655905e1eaSVijay Mahadevan       }
166*1baa6e33SBarry Smith     } else {
16782dfd14aSVijay Mahadevan       /* check if we got overzealous in our nnz and onz computations */
16882dfd14aSVijay Mahadevan       nnz[ivtx] = (nnz[ivtx] > dmmoab->nloc ? dmmoab->nloc : nnz[ivtx]);
16982dfd14aSVijay Mahadevan       if (onz) onz[ivtx] = (onz[ivtx] > dmmoab->nloc ? dmmoab->nloc : onz[ivtx]);
1705905e1eaSVijay Mahadevan     }
1715905e1eaSVijay Mahadevan   }
1725905e1eaSVijay Mahadevan   /* update innz and ionz based on local maxima */
1735905e1eaSVijay Mahadevan   if (innz || ionz) {
1740df6e276SVijay Mahadevan     if (innz) *innz = 0;
1750df6e276SVijay Mahadevan     if (ionz) *ionz = 0;
176c2612ac9SVijay Mahadevan     for (i = 0; i < nlsiz; i++) {
177da6192ceSVijay Mahadevan       if (innz && (nnz[i] > *innz)) *innz = nnz[i];
178da6192ceSVijay Mahadevan       if ((ionz && onz) && (onz[i] > *ionz)) *ionz = onz[i];
179032b8ab6SVijay Mahadevan     }
1805905e1eaSVijay Mahadevan   }
1810df6e276SVijay Mahadevan   PetscFunctionReturn(0);
182032b8ab6SVijay Mahadevan }
183032b8ab6SVijay Mahadevan 
1845905e1eaSVijay Mahadevan static PetscErrorCode DMMoabSetBlockFills_Private(PetscInt w, const PetscInt *fill, PetscInt **rfill)
1855905e1eaSVijay Mahadevan {
1865905e1eaSVijay Mahadevan   PetscInt       i, j, *ifill;
1875905e1eaSVijay Mahadevan 
1885905e1eaSVijay Mahadevan   PetscFunctionBegin;
1895905e1eaSVijay Mahadevan   if (!fill) PetscFunctionReturn(0);
1909566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(w * w, &ifill));
1915905e1eaSVijay Mahadevan   for (i = 0; i < w; i++) {
1925905e1eaSVijay Mahadevan     for (j = 0; j < w; j++)
1935905e1eaSVijay Mahadevan       ifill[i * w + j] = fill[i * w + j];
1945905e1eaSVijay Mahadevan   }
1955905e1eaSVijay Mahadevan 
1965905e1eaSVijay Mahadevan   *rfill = ifill;
1975905e1eaSVijay Mahadevan   PetscFunctionReturn(0);
1985905e1eaSVijay Mahadevan }
1995905e1eaSVijay Mahadevan 
200cab5ea25SPierre Jolivet /*@C
2015905e1eaSVijay Mahadevan     DMMoabSetBlockFills - Sets the fill pattern in each block for a multi-component problem
2025905e1eaSVijay Mahadevan     of the matrix returned by DMCreateMatrix().
2035905e1eaSVijay Mahadevan 
204d083f849SBarry Smith     Logically Collective on da
2055905e1eaSVijay Mahadevan 
206d8d19677SJose E. Roman     Input Parameters:
2075905e1eaSVijay Mahadevan +   dm - the DMMoab object
2085905e1eaSVijay Mahadevan .   dfill - the fill pattern in the diagonal block (may be NULL, means use dense block)
2095905e1eaSVijay Mahadevan -   ofill - the fill pattern in the off-diagonal blocks
2105905e1eaSVijay Mahadevan 
2115905e1eaSVijay Mahadevan     Level: developer
2125905e1eaSVijay Mahadevan 
21395452b02SPatrick Sanan     Notes:
21495452b02SPatrick Sanan     This only makes sense when you are doing multicomponent problems but using the
2155905e1eaSVijay Mahadevan        MPIAIJ matrix format
2165905e1eaSVijay Mahadevan 
2175905e1eaSVijay Mahadevan            The format for dfill and ofill is a 2 dimensional dof by dof matrix with 1 entries
2185905e1eaSVijay Mahadevan        representing coupling and 0 entries for missing coupling. For example
2195905e1eaSVijay Mahadevan $             dfill[9] = {1, 0, 0,
2205905e1eaSVijay Mahadevan $                         1, 1, 0,
2215905e1eaSVijay Mahadevan $                         0, 1, 1}
2225905e1eaSVijay Mahadevan        means that row 0 is coupled with only itself in the diagonal block, row 1 is coupled with
2235905e1eaSVijay Mahadevan        itself and row 0 (in the diagonal block) and row 2 is coupled with itself and row 1 (in the
2245905e1eaSVijay Mahadevan        diagonal block).
2255905e1eaSVijay Mahadevan 
2265905e1eaSVijay Mahadevan      DMDASetGetMatrix() allows you to provide general code for those more complicated nonzero patterns then
2275905e1eaSVijay Mahadevan      can be represented in the dfill, ofill format
2285905e1eaSVijay Mahadevan 
2295905e1eaSVijay Mahadevan    Contributed by Glenn Hammond
2305905e1eaSVijay Mahadevan 
231db781477SPatrick Sanan .seealso `DMCreateMatrix()`, `DMDASetGetMatrix()`, `DMSetMatrixPreallocateOnly()`
2325905e1eaSVijay Mahadevan 
2335905e1eaSVijay Mahadevan @*/
2345905e1eaSVijay Mahadevan PetscErrorCode  DMMoabSetBlockFills(DM dm, const PetscInt *dfill, const PetscInt *ofill)
2355905e1eaSVijay Mahadevan {
2365905e1eaSVijay Mahadevan   DM_Moab       *dmmoab = (DM_Moab*)dm->data;
2375905e1eaSVijay Mahadevan 
2385905e1eaSVijay Mahadevan   PetscFunctionBegin;
2395905e1eaSVijay Mahadevan   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2409566063dSJacob Faibussowitsch   PetscCall(DMMoabSetBlockFills_Private(dmmoab->numFields, dfill, &dmmoab->dfill));
2419566063dSJacob Faibussowitsch   PetscCall(DMMoabSetBlockFills_Private(dmmoab->numFields, ofill, &dmmoab->ofill));
2425905e1eaSVijay Mahadevan   PetscFunctionReturn(0);
2435905e1eaSVijay Mahadevan }
244