xref: /petsc/src/dm/impls/moab/dmmbmat.cxx (revision e92d1c7cd0078e3a0fee96009c329e484288a4cc)
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 #undef __FUNCT__
11304006b3SVijay Mahadevan #define __FUNCT__ "DMCreateMatrix_Moab"
12304006b3SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMCreateMatrix_Moab(DM dm, Mat *J)
13032b8ab6SVijay Mahadevan {
14032b8ab6SVijay Mahadevan   PetscErrorCode  ierr;
15c2612ac9SVijay Mahadevan   PetscInt        innz = 0, ionz = 0, nlsiz;
16032b8ab6SVijay Mahadevan   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
17da6192ceSVijay Mahadevan   PetscInt        *nnz = 0, *onz = 0;
18032b8ab6SVijay Mahadevan   char            *tmp = 0;
192494be97SVijay Mahadevan   Mat             A;
20baf0d1e0SVijay Mahadevan   MatType         mtype;
21032b8ab6SVijay Mahadevan 
22032b8ab6SVijay Mahadevan   PetscFunctionBegin;
23032b8ab6SVijay Mahadevan   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24032b8ab6SVijay Mahadevan   PetscValidPointer(J, 3);
25032b8ab6SVijay Mahadevan 
26db66d124SVijay Mahadevan   /* next, need to allocate the non-zero arrays to enable pre-allocation */
27baf0d1e0SVijay Mahadevan   mtype = dm->mattype;
28baf0d1e0SVijay Mahadevan   ierr = PetscStrstr(mtype, "baij", &tmp);CHKERRQ(ierr);
2982dfd14aSVijay Mahadevan   nlsiz = (tmp ? dmmoab->nloc : dmmoab->nloc * dmmoab->numFields);
30032b8ab6SVijay Mahadevan 
31032b8ab6SVijay Mahadevan   /* allocate the nnz, onz arrays based on block size and local nodes */
327ae5e5b6SVijay Mahadevan   ierr = PetscCalloc2(nlsiz, &nnz, nlsiz, &onz);CHKERRQ(ierr);
33032b8ab6SVijay Mahadevan 
34032b8ab6SVijay Mahadevan   /* compute the nonzero pattern based on MOAB connectivity data for local elements */
35032b8ab6SVijay Mahadevan   ierr = DMMoab_Compute_NNZ_From_Connectivity(dm, &innz, nnz, &ionz, onz, (tmp ? PETSC_TRUE : PETSC_FALSE));CHKERRQ(ierr);
36032b8ab6SVijay Mahadevan 
37da6192ceSVijay Mahadevan   /* create the Matrix and set its type as specified by user */
389daf19fdSVijay Mahadevan   ierr = MatCreate((((PetscObject)dm)->comm), &A);CHKERRQ(ierr);
392494be97SVijay Mahadevan   ierr = MatSetSizes(A, dmmoab->nloc * dmmoab->numFields, dmmoab->nloc * dmmoab->numFields, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
402494be97SVijay Mahadevan   ierr = MatSetType(A, mtype);CHKERRQ(ierr);
412494be97SVijay Mahadevan   ierr = MatSetBlockSize(A, dmmoab->bs);CHKERRQ(ierr);
422494be97SVijay Mahadevan   ierr = MatSetDM(A, dm);CHKERRQ(ierr); /* set DM reference */
432494be97SVijay Mahadevan   ierr = MatSetFromOptions(A);CHKERRQ(ierr);
44da6192ceSVijay Mahadevan 
459daf19fdSVijay Mahadevan   if (!dmmoab->ltog_map) SETERRQ((((PetscObject)dm)->comm), PETSC_ERR_ORDER, "Cannot create a DMMoab Mat without calling DMSetUp first.");
462494be97SVijay Mahadevan   ierr = MatSetLocalToGlobalMapping(A, dmmoab->ltog_map, dmmoab->ltog_map);CHKERRQ(ierr);
47032b8ab6SVijay Mahadevan 
48032b8ab6SVijay Mahadevan   /* set preallocation based on different supported Mat types */
492494be97SVijay Mahadevan   ierr = MatSeqAIJSetPreallocation(A, innz, nnz);CHKERRQ(ierr);
502494be97SVijay Mahadevan   ierr = MatMPIAIJSetPreallocation(A, innz, nnz, ionz, onz);CHKERRQ(ierr);
512494be97SVijay Mahadevan   ierr = MatSeqBAIJSetPreallocation(A, dmmoab->bs, innz, nnz);CHKERRQ(ierr);
522494be97SVijay Mahadevan   ierr = MatMPIBAIJSetPreallocation(A, dmmoab->bs, innz, nnz, ionz, onz);CHKERRQ(ierr);
53032b8ab6SVijay Mahadevan 
54da8c5b52SVijay Mahadevan   /* clean up temporary memory */
557ae5e5b6SVijay Mahadevan   ierr = PetscFree2(nnz, onz);CHKERRQ(ierr);
56da8c5b52SVijay Mahadevan 
57da8c5b52SVijay Mahadevan   /* set up internal matrix data-structures */
582494be97SVijay Mahadevan   ierr = MatSetUp(A);CHKERRQ(ierr);
59da8c5b52SVijay Mahadevan 
60*e92d1c7cSVijay Mahadevan   /* MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE); */
619c368985SVijay Mahadevan 
622494be97SVijay Mahadevan   *J = A;
63032b8ab6SVijay Mahadevan   PetscFunctionReturn(0);
64032b8ab6SVijay Mahadevan }
65032b8ab6SVijay Mahadevan 
66032b8ab6SVijay Mahadevan 
6763d025dbSVijay Mahadevan #undef __FUNCT__
6863d025dbSVijay Mahadevan #define __FUNCT__ "DMMoab_Compute_NNZ_From_Connectivity"
69a86ed394SVijay Mahadevan PETSC_EXTERN PetscErrorCode DMMoab_Compute_NNZ_From_Connectivity(DM dm, PetscInt* innz, PetscInt* nnz, PetscInt* ionz, PetscInt* onz, PetscBool isbaij)
70032b8ab6SVijay Mahadevan {
71b117cd09SVijay Mahadevan   PetscInt        i, f, nloc, vpere, bs, n_nnz, n_onz, ivtx = 0;
72c2612ac9SVijay Mahadevan   PetscInt        ibs, jbs, inbsize, iobsize, nfields, nlsiz;
73032b8ab6SVijay Mahadevan   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
749c368985SVijay Mahadevan   moab::Range     found;
759c368985SVijay Mahadevan   std::vector<moab::EntityHandle> adjs, storage;
765905e1eaSVijay Mahadevan   PetscBool isinterlaced;
77da6192ceSVijay Mahadevan   moab::EntityHandle vtx;
78032b8ab6SVijay Mahadevan   moab::ErrorCode merr;
79032b8ab6SVijay Mahadevan 
80032b8ab6SVijay Mahadevan   PetscFunctionBegin;
81032b8ab6SVijay Mahadevan   bs = dmmoab->bs;
82032b8ab6SVijay Mahadevan   nloc = dmmoab->nloc;
835905e1eaSVijay Mahadevan   nfields = dmmoab->numFields;
8482dfd14aSVijay Mahadevan   isinterlaced = (isbaij || bs == nfields ? PETSC_TRUE : PETSC_FALSE);
85c2612ac9SVijay Mahadevan   nlsiz = (isinterlaced ? nloc : nloc * nfields);
86032b8ab6SVijay Mahadevan 
87f6829af0SVijay Mahadevan   /* loop over the locally owned vertices and figure out the NNZ pattern using connectivity information */
8864e1c140SVijay Mahadevan   for (moab::Range::const_iterator iter = dmmoab->vowned->begin(); iter != dmmoab->vowned->end(); iter++, ivtx++) {
89032b8ab6SVijay Mahadevan 
90da6192ceSVijay Mahadevan     vtx = *iter;
91da6192ceSVijay Mahadevan     /* Get adjacency information for current vertex - i.e., all elements of dimension (dim) that connects
92da6192ceSVijay Mahadevan        to the current vertex. We can then decipher if a vertex is ghosted or not and compute the
93da6192ceSVijay Mahadevan        non-zero pattern accordingly. */
9464e1c140SVijay Mahadevan     adjs.clear();
95*e92d1c7cSVijay Mahadevan     if (dmmoab->hlevel && (dmmoab->pcomm->size() == 1)) {
969c368985SVijay Mahadevan       merr = dmmoab->hierarchy->get_adjacencies(vtx, dmmoab->dim, adjs); MBERRNM(merr);
979c368985SVijay Mahadevan     }
989c368985SVijay Mahadevan     else {
99*e92d1c7cSVijay Mahadevan       merr = dmmoab->mbiface->get_adjacencies(&vtx, 1, dmmoab->dim, true, adjs, moab::Interface::UNION); MBERRNM(merr);
1009c368985SVijay Mahadevan     }
1010df6e276SVijay Mahadevan 
102e427d9c9SVijay Mahadevan     /* reset counters */
103e427d9c9SVijay Mahadevan     n_nnz = n_onz = 0;
104e427d9c9SVijay Mahadevan     found.clear();
105e427d9c9SVijay Mahadevan 
10615de014fSVijay Mahadevan     /* loop over vertices and update the number of connectivity */
1079c368985SVijay Mahadevan     for (unsigned jter = 0; jter < adjs.size(); ++jter) {
1080df6e276SVijay Mahadevan 
10915de014fSVijay Mahadevan       /* Get connectivity information in canonical ordering for the local element */
1109c368985SVijay Mahadevan       const moab::EntityHandle *connect;
1119c368985SVijay Mahadevan       std::vector<moab::EntityHandle> cconnect;
1129c368985SVijay Mahadevan       merr = dmmoab->mbiface->get_connectivity(adjs[jter], connect, vpere, false, &storage); MBERRNM(merr);
1130df6e276SVijay Mahadevan 
114f6829af0SVijay Mahadevan       /* loop over each element connected to the adjacent vertex and update as needed */
11515de014fSVijay Mahadevan       for (i = 0; i < vpere; ++i) {
11664e1c140SVijay Mahadevan         /* find the truly user-expected layer of ghosted entities to decipher NNZ pattern */
117f6829af0SVijay Mahadevan         if (connect[i] == vtx || found.find(connect[i]) != found.end()) continue; /* make sure we don't double count shared vertices */
11864e1c140SVijay Mahadevan         if (dmmoab->vghost->find(connect[i]) != dmmoab->vghost->end()) n_onz++; /* update out-of-proc onz */
119f6829af0SVijay Mahadevan         else n_nnz++; /* else local vertex */
12015de014fSVijay Mahadevan         found.insert(connect[i]);
12115de014fSVijay Mahadevan       }
12215de014fSVijay Mahadevan     }
1239daf19fdSVijay Mahadevan     storage.clear();
12415de014fSVijay Mahadevan 
12515de014fSVijay Mahadevan     if (isbaij) {
12615de014fSVijay Mahadevan       nnz[ivtx] = n_nnz;  /* leave out self to avoid repeats -> node shared by multiple elements */
1275905e1eaSVijay Mahadevan       if (onz) {
1285905e1eaSVijay Mahadevan         onz[ivtx] = n_onz; /* add ghost non-owned nodes */
1295905e1eaSVijay Mahadevan       }
13015de014fSVijay Mahadevan     }
131f6829af0SVijay Mahadevan     else { /* AIJ matrices */
1325905e1eaSVijay Mahadevan       if (!isinterlaced) {
1335905e1eaSVijay Mahadevan         for (f = 0; f < nfields; f++) {
1345905e1eaSVijay Mahadevan           nnz[f * nloc + ivtx] = n_nnz; /* leave out self to avoid repeats -> node shared by multiple elements */
1355905e1eaSVijay Mahadevan           if (onz)
1365905e1eaSVijay Mahadevan             onz[f * nloc + ivtx] = n_onz; /* add ghost non-owned nodes */
1375905e1eaSVijay Mahadevan         }
1385905e1eaSVijay Mahadevan       }
1395905e1eaSVijay Mahadevan       else {
1405905e1eaSVijay Mahadevan         for (f = 0; f < nfields; f++) {
1415905e1eaSVijay Mahadevan           nnz[nfields * ivtx + f] = n_nnz; /* leave out self to avoid repeats -> node shared by multiple elements */
1425905e1eaSVijay Mahadevan           if (onz)
1435905e1eaSVijay Mahadevan             onz[nfields * ivtx + f] = n_onz; /* add ghost non-owned nodes */
1445905e1eaSVijay Mahadevan         }
1450df6e276SVijay Mahadevan       }
1460df6e276SVijay Mahadevan     }
1470df6e276SVijay Mahadevan   }
1480df6e276SVijay Mahadevan 
149c2612ac9SVijay Mahadevan   for (i = 0; i < nlsiz; i++)
1505905e1eaSVijay Mahadevan     nnz[i] += 1; /* self count the node */
1515905e1eaSVijay Mahadevan 
15282dfd14aSVijay Mahadevan   for (ivtx = 0; ivtx < nloc; ivtx++) {
1535905e1eaSVijay Mahadevan     if (!isbaij) {
1545905e1eaSVijay Mahadevan       for (ibs = 0; ibs < nfields; ibs++) {
15582dfd14aSVijay Mahadevan         if (dmmoab->dfill) {  /* first address the diagonal block */
1565905e1eaSVijay Mahadevan           /* just add up the ints -- easier/faster rather than branching based on "1" */
1575905e1eaSVijay Mahadevan           for (jbs = 0, inbsize = 0; jbs < nfields; jbs++)
1585905e1eaSVijay Mahadevan             inbsize += dmmoab->dfill[ibs * nfields + jbs];
1595905e1eaSVijay Mahadevan         }
16082dfd14aSVijay Mahadevan         else inbsize = nfields; /* dense coupling since user didn't specify the component fill explicitly */
16182dfd14aSVijay Mahadevan         if (isinterlaced) nnz[ivtx * nfields + ibs] *= inbsize;
16282dfd14aSVijay Mahadevan         else nnz[ibs * nloc + ivtx] *= inbsize;
1635905e1eaSVijay Mahadevan 
1645905e1eaSVijay Mahadevan         if (onz) {
16582dfd14aSVijay Mahadevan           if (dmmoab->ofill) {  /* next address the off-diagonal block */
1665905e1eaSVijay Mahadevan             /* just add up the ints -- easier/faster rather than branching based on "1" */
1675905e1eaSVijay Mahadevan             for (jbs = 0, iobsize = 0; jbs < nfields; jbs++)
1685905e1eaSVijay Mahadevan               iobsize += dmmoab->dfill[ibs * nfields + jbs];
1695905e1eaSVijay Mahadevan           }
17082dfd14aSVijay Mahadevan           else iobsize = nfields; /* dense coupling since user didn't specify the component fill explicitly */
17182dfd14aSVijay Mahadevan           if (isinterlaced) onz[ivtx * nfields + ibs] *= iobsize;
17282dfd14aSVijay Mahadevan           else onz[ibs * nloc + ivtx] *= iobsize;
1735905e1eaSVijay Mahadevan         }
1745905e1eaSVijay Mahadevan       }
1755905e1eaSVijay Mahadevan     }
1765905e1eaSVijay Mahadevan     else {
17782dfd14aSVijay Mahadevan       /* check if we got overzealous in our nnz and onz computations */
17882dfd14aSVijay Mahadevan       nnz[ivtx] = (nnz[ivtx] > dmmoab->nloc ? dmmoab->nloc : nnz[ivtx]);
17982dfd14aSVijay Mahadevan       if (onz) onz[ivtx] = (onz[ivtx] > dmmoab->nloc ? dmmoab->nloc : onz[ivtx]);
1805905e1eaSVijay Mahadevan     }
1815905e1eaSVijay Mahadevan   }
1825905e1eaSVijay Mahadevan   /* update innz and ionz based on local maxima */
1835905e1eaSVijay Mahadevan   if (innz || ionz) {
1840df6e276SVijay Mahadevan     if (innz) *innz = 0;
1850df6e276SVijay Mahadevan     if (ionz) *ionz = 0;
1869daf19fdSVijay Mahadevan     if (isbaij) {
187c2612ac9SVijay Mahadevan       for (i = 0; i < nlsiz; i++) {
188da6192ceSVijay Mahadevan         if (innz && (nnz[i] > *innz)) *innz = nnz[i];
189da6192ceSVijay Mahadevan         if ((ionz && onz) && (onz[i] > *ionz)) *ionz = onz[i];
190032b8ab6SVijay Mahadevan       }
1915905e1eaSVijay Mahadevan     }
1929daf19fdSVijay Mahadevan     else {
1939daf19fdSVijay Mahadevan       for (i = 0; i < nlsiz * nfields; i++) {
1949daf19fdSVijay Mahadevan         if (innz && (nnz[i] > *innz)) *innz = nnz[i];
1959daf19fdSVijay Mahadevan         if ((ionz && onz) && (onz[i] > *ionz)) *ionz = onz[i];
1969daf19fdSVijay Mahadevan       }
1979daf19fdSVijay Mahadevan     }
1989daf19fdSVijay Mahadevan   }
1990df6e276SVijay Mahadevan   PetscFunctionReturn(0);
200032b8ab6SVijay Mahadevan }
201032b8ab6SVijay Mahadevan 
202da8c5b52SVijay Mahadevan 
20363d025dbSVijay Mahadevan #undef __FUNCT__
20463d025dbSVijay Mahadevan #define __FUNCT__ "DMMoabSetBlockFills_Private"
2055905e1eaSVijay Mahadevan static PetscErrorCode DMMoabSetBlockFills_Private(PetscInt w, const PetscInt *fill, PetscInt **rfill)
2065905e1eaSVijay Mahadevan {
2075905e1eaSVijay Mahadevan   PetscErrorCode ierr;
2085905e1eaSVijay Mahadevan   PetscInt       i, j, *ifill;
2095905e1eaSVijay Mahadevan 
2105905e1eaSVijay Mahadevan   PetscFunctionBegin;
2115905e1eaSVijay Mahadevan   if (!fill) PetscFunctionReturn(0);
2125905e1eaSVijay Mahadevan   ierr  = PetscMalloc1(w * w, &ifill);CHKERRQ(ierr);
2135905e1eaSVijay Mahadevan   for (i = 0; i < w; i++) {
2145905e1eaSVijay Mahadevan     for (j = 0; j < w; j++)
2155905e1eaSVijay Mahadevan       ifill[i * w + j] = fill[i * w + j];
2165905e1eaSVijay Mahadevan   }
2175905e1eaSVijay Mahadevan 
2185905e1eaSVijay Mahadevan   *rfill = ifill;
2195905e1eaSVijay Mahadevan   PetscFunctionReturn(0);
2205905e1eaSVijay Mahadevan }
2215905e1eaSVijay Mahadevan 
2225905e1eaSVijay Mahadevan 
2235905e1eaSVijay Mahadevan /*@
2245905e1eaSVijay Mahadevan     DMMoabSetBlockFills - Sets the fill pattern in each block for a multi-component problem
2255905e1eaSVijay Mahadevan     of the matrix returned by DMCreateMatrix().
2265905e1eaSVijay Mahadevan 
2275905e1eaSVijay Mahadevan     Logically Collective on DMDA
2285905e1eaSVijay Mahadevan 
2295905e1eaSVijay Mahadevan     Input Parameter:
2305905e1eaSVijay Mahadevan +   dm - the DMMoab object
2315905e1eaSVijay Mahadevan .   dfill - the fill pattern in the diagonal block (may be NULL, means use dense block)
2325905e1eaSVijay Mahadevan -   ofill - the fill pattern in the off-diagonal blocks
2335905e1eaSVijay Mahadevan 
2345905e1eaSVijay Mahadevan     Level: developer
2355905e1eaSVijay Mahadevan 
2365905e1eaSVijay Mahadevan     Notes: This only makes sense when you are doing multicomponent problems but using the
2375905e1eaSVijay Mahadevan        MPIAIJ matrix format
2385905e1eaSVijay Mahadevan 
2395905e1eaSVijay Mahadevan            The format for dfill and ofill is a 2 dimensional dof by dof matrix with 1 entries
2405905e1eaSVijay Mahadevan        representing coupling and 0 entries for missing coupling. For example
2415905e1eaSVijay Mahadevan $             dfill[9] = {1, 0, 0,
2425905e1eaSVijay Mahadevan $                         1, 1, 0,
2435905e1eaSVijay Mahadevan $                         0, 1, 1}
2445905e1eaSVijay Mahadevan        means that row 0 is coupled with only itself in the diagonal block, row 1 is coupled with
2455905e1eaSVijay Mahadevan        itself and row 0 (in the diagonal block) and row 2 is coupled with itself and row 1 (in the
2465905e1eaSVijay Mahadevan        diagonal block).
2475905e1eaSVijay Mahadevan 
2485905e1eaSVijay Mahadevan      DMDASetGetMatrix() allows you to provide general code for those more complicated nonzero patterns then
2495905e1eaSVijay Mahadevan      can be represented in the dfill, ofill format
2505905e1eaSVijay Mahadevan 
2515905e1eaSVijay Mahadevan    Contributed by Glenn Hammond
2525905e1eaSVijay Mahadevan 
2535905e1eaSVijay Mahadevan .seealso DMCreateMatrix(), DMDASetGetMatrix(), DMSetMatrixPreallocateOnly()
2545905e1eaSVijay Mahadevan 
2555905e1eaSVijay Mahadevan @*/
2565905e1eaSVijay Mahadevan PetscErrorCode  DMMoabSetBlockFills(DM dm, const PetscInt *dfill, const PetscInt *ofill)
2575905e1eaSVijay Mahadevan {
2585905e1eaSVijay Mahadevan   DM_Moab       *dmmoab = (DM_Moab*)dm->data;
2595905e1eaSVijay Mahadevan   PetscErrorCode ierr;
2605905e1eaSVijay Mahadevan 
2615905e1eaSVijay Mahadevan   PetscFunctionBegin;
2625905e1eaSVijay Mahadevan   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2635905e1eaSVijay Mahadevan   ierr = DMMoabSetBlockFills_Private(dmmoab->numFields, dfill, &dmmoab->dfill);CHKERRQ(ierr);
2645905e1eaSVijay Mahadevan   ierr = DMMoabSetBlockFills_Private(dmmoab->numFields, ofill, &dmmoab->ofill);CHKERRQ(ierr);
2655905e1eaSVijay Mahadevan   PetscFunctionReturn(0);
2665905e1eaSVijay Mahadevan }
267