xref: /petsc/src/dm/impls/moab/dmmbmat.cxx (revision c2612ac9e8581f2d6950da21aa6b78984bc822a9)
1b8ecf6d3SVijay Mahadevan #include <petsc-private/dmmbimpl.h> /*I  "petscdmmoab.h"   I*/
2b8ecf6d3SVijay Mahadevan #include <petsc-private/vecimpl.h>
3032b8ab6SVijay Mahadevan 
4032b8ab6SVijay Mahadevan #include <petscdmmoab.h>
5da6192ceSVijay Mahadevan #include <MBTagConventions.hpp>
6032b8ab6SVijay Mahadevan 
7032b8ab6SVijay Mahadevan static PetscErrorCode DMMoab_Compute_NNZ_From_Connectivity(DM,PetscInt*,PetscInt*,PetscInt*,PetscInt*,PetscBool);
8032b8ab6SVijay Mahadevan 
9032b8ab6SVijay Mahadevan #undef __FUNCT__
10032b8ab6SVijay Mahadevan #define __FUNCT__ "DMCreateMatrix_Moab"
11baf0d1e0SVijay Mahadevan PetscErrorCode DMCreateMatrix_Moab(DM dm,Mat *J)
12032b8ab6SVijay Mahadevan {
13032b8ab6SVijay Mahadevan   PetscErrorCode  ierr;
14*c2612ac9SVijay Mahadevan   PetscInt        innz=0,ionz=0,nlsiz;
15032b8ab6SVijay Mahadevan   DM_Moab         *dmmoab=(DM_Moab*)dm->data;
16da6192ceSVijay Mahadevan   PetscInt        *nnz=0,*onz=0;
17032b8ab6SVijay Mahadevan   char            *tmp=0;
182494be97SVijay Mahadevan   Mat             A;
19baf0d1e0SVijay Mahadevan   MatType         mtype;
20032b8ab6SVijay Mahadevan 
21032b8ab6SVijay Mahadevan   PetscFunctionBegin;
22032b8ab6SVijay Mahadevan   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
23032b8ab6SVijay Mahadevan   PetscValidPointer(J,3);
24032b8ab6SVijay Mahadevan 
25db66d124SVijay Mahadevan   /* next, need to allocate the non-zero arrays to enable pre-allocation */
26baf0d1e0SVijay Mahadevan   mtype = dm->mattype;
27baf0d1e0SVijay Mahadevan   ierr = PetscStrstr(mtype, "baij", &tmp);CHKERRQ(ierr);
2882dfd14aSVijay Mahadevan   nlsiz = (tmp ? dmmoab->nloc:dmmoab->nloc*dmmoab->numFields);
29032b8ab6SVijay Mahadevan 
30032b8ab6SVijay Mahadevan   /* allocate the nnz, onz arrays based on block size and local nodes */
31da6192ceSVijay Mahadevan   ierr = PetscMalloc((nlsiz)*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
32da6192ceSVijay Mahadevan   ierr = PetscMemzero(nnz,sizeof(PetscInt)*(nlsiz));CHKERRQ(ierr);
33da6192ceSVijay Mahadevan   ierr = PetscMalloc(nlsiz*sizeof(PetscInt),&onz);CHKERRQ(ierr);
34da6192ceSVijay Mahadevan   ierr = PetscMemzero(onz,sizeof(PetscInt)*nlsiz);CHKERRQ(ierr);
35032b8ab6SVijay Mahadevan 
36032b8ab6SVijay Mahadevan   /* compute the nonzero pattern based on MOAB connectivity data for local elements */
37032b8ab6SVijay Mahadevan   ierr = DMMoab_Compute_NNZ_From_Connectivity(dm,&innz,nnz,&ionz,onz,(tmp?PETSC_TRUE:PETSC_FALSE));CHKERRQ(ierr);
38032b8ab6SVijay Mahadevan 
39da6192ceSVijay Mahadevan   /* create the Matrix and set its type as specified by user */
402494be97SVijay Mahadevan   ierr = MatCreate(dmmoab->pcomm->comm(), &A);CHKERRQ(ierr);
412494be97SVijay Mahadevan   ierr = MatSetSizes(A, dmmoab->nloc*dmmoab->numFields, dmmoab->nloc*dmmoab->numFields, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
422494be97SVijay Mahadevan   ierr = MatSetType(A, mtype);CHKERRQ(ierr);
432494be97SVijay Mahadevan   ierr = MatSetBlockSize(A, dmmoab->bs);CHKERRQ(ierr);
442494be97SVijay Mahadevan   ierr = MatSetDM(A, dm);CHKERRQ(ierr);  /* set DM reference */
452494be97SVijay Mahadevan   ierr = MatSetFromOptions(A);CHKERRQ(ierr);
46da6192ceSVijay Mahadevan 
47da6192ceSVijay Mahadevan   if (!dmmoab->ltog_map) SETERRQ(dmmoab->pcomm->comm(), PETSC_ERR_ORDER, "Cannot create a DMMoab Mat without calling DMSetUp first.");
482494be97SVijay Mahadevan   ierr = MatSetLocalToGlobalMapping(A,dmmoab->ltog_map,dmmoab->ltog_map);CHKERRQ(ierr);
49032b8ab6SVijay Mahadevan 
50032b8ab6SVijay Mahadevan   /* set preallocation based on different supported Mat types */
512494be97SVijay Mahadevan   ierr = MatSeqAIJSetPreallocation(A, innz, nnz);CHKERRQ(ierr);
522494be97SVijay Mahadevan   ierr = MatMPIAIJSetPreallocation(A, innz, nnz, ionz, onz);CHKERRQ(ierr);
532494be97SVijay Mahadevan   ierr = MatSeqBAIJSetPreallocation(A, dmmoab->bs, innz, nnz);CHKERRQ(ierr);
542494be97SVijay Mahadevan   ierr = MatMPIBAIJSetPreallocation(A, dmmoab->bs, innz, nnz, ionz, onz);CHKERRQ(ierr);
55032b8ab6SVijay Mahadevan 
56da8c5b52SVijay Mahadevan   /* clean up temporary memory */
57032b8ab6SVijay Mahadevan   ierr = PetscFree(nnz);CHKERRQ(ierr);
58032b8ab6SVijay Mahadevan   ierr = PetscFree(onz);CHKERRQ(ierr);
59da8c5b52SVijay Mahadevan 
60da8c5b52SVijay Mahadevan   /* set up internal matrix data-structures */
612494be97SVijay Mahadevan   ierr = MatSetUp(A);CHKERRQ(ierr);
62da8c5b52SVijay Mahadevan 
632494be97SVijay Mahadevan   *J = A;
64032b8ab6SVijay Mahadevan   PetscFunctionReturn(0);
65032b8ab6SVijay Mahadevan }
66032b8ab6SVijay Mahadevan 
67032b8ab6SVijay Mahadevan 
68032b8ab6SVijay Mahadevan #undef __FUNCT__
69032b8ab6SVijay Mahadevan #define __FUNCT__ "DMMoab_Compute_NNZ_From_Connectivity"
70032b8ab6SVijay Mahadevan PetscErrorCode DMMoab_Compute_NNZ_From_Connectivity(DM dm,PetscInt* innz,PetscInt* nnz,PetscInt* ionz,PetscInt* onz,PetscBool isbaij)
71032b8ab6SVijay Mahadevan {
725905e1eaSVijay Mahadevan   PetscInt        i,f,nloc,vpere,bs,ivtx,n_nnz,n_onz;
73*c2612ac9SVijay Mahadevan   PetscInt        ibs,jbs,inbsize,iobsize,nfields,nlsiz;
74032b8ab6SVijay Mahadevan   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
75032b8ab6SVijay Mahadevan   const moab::EntityHandle *connect;
76da6192ceSVijay Mahadevan   moab::Range     adjs,found,allvlocal,allvghost;
77da6192ceSVijay Mahadevan   moab::Range::iterator iter,jter;
78da6192ceSVijay Mahadevan   std::vector<moab::EntityHandle> storage;
795905e1eaSVijay Mahadevan   PetscBool isinterlaced;
80da6192ceSVijay Mahadevan   moab::EntityHandle vtx;
81032b8ab6SVijay Mahadevan   moab::ErrorCode merr;
82032b8ab6SVijay Mahadevan 
83032b8ab6SVijay Mahadevan   PetscFunctionBegin;
84032b8ab6SVijay Mahadevan   bs = dmmoab->bs;
85032b8ab6SVijay Mahadevan   nloc = dmmoab->nloc;
865905e1eaSVijay Mahadevan   nfields = dmmoab->numFields;
8782dfd14aSVijay Mahadevan   isinterlaced=(isbaij || bs==nfields ? PETSC_TRUE : PETSC_FALSE);
88*c2612ac9SVijay Mahadevan   nlsiz = (isinterlaced ? nloc:nloc*nfields);
89032b8ab6SVijay Mahadevan 
90da6192ceSVijay Mahadevan   /* find the truly user-expected layer of ghosted entities to decipher NNZ pattern */
91da6192ceSVijay Mahadevan   merr = dmmoab->mbiface->get_entities_by_type(dmmoab->fileset,moab::MBVERTEX,allvlocal,true);MBERRNM(merr);
92da6192ceSVijay Mahadevan   merr = dmmoab->pcomm->filter_pstatus(allvlocal,PSTATUS_NOT_OWNED,PSTATUS_NOT,-1,&adjs);MBERRNM(merr);
93da6192ceSVijay Mahadevan   allvghost = moab::subtract(allvlocal, adjs);
94032b8ab6SVijay Mahadevan 
95f6829af0SVijay Mahadevan   /* loop over the locally owned vertices and figure out the NNZ pattern using connectivity information */
96e427d9c9SVijay Mahadevan   for(iter = dmmoab->vowned->begin(),ivtx=0; iter != dmmoab->vowned->end(); iter++,ivtx++) {
97032b8ab6SVijay Mahadevan 
98da6192ceSVijay Mahadevan     vtx = *iter;
99da6192ceSVijay Mahadevan     adjs.clear();
100da6192ceSVijay Mahadevan     /* Get adjacency information for current vertex - i.e., all elements of dimension (dim) that connects
101da6192ceSVijay Mahadevan        to the current vertex. We can then decipher if a vertex is ghosted or not and compute the
102da6192ceSVijay Mahadevan        non-zero pattern accordingly. */
103da6192ceSVijay Mahadevan     merr = dmmoab->mbiface->get_adjacencies(&vtx,1,dmmoab->dim,false,adjs,moab::Interface::INTERSECT);
1040df6e276SVijay Mahadevan 
105e427d9c9SVijay Mahadevan     /* reset counters */
106e427d9c9SVijay Mahadevan     n_nnz=n_onz=0;
107e427d9c9SVijay Mahadevan     found.clear();
108e427d9c9SVijay Mahadevan 
10915de014fSVijay Mahadevan     /* loop over vertices and update the number of connectivity */
11015de014fSVijay Mahadevan     for(jter = adjs.begin(); jter != adjs.end(); jter++) {
1110df6e276SVijay Mahadevan 
11215de014fSVijay Mahadevan       /* Get connectivity information in canonical ordering for the local element */
11315de014fSVijay Mahadevan       merr = dmmoab->mbiface->get_connectivity(*jter,connect,vpere,false,&storage);MBERRNM(merr);
1140df6e276SVijay Mahadevan 
115f6829af0SVijay Mahadevan       /* loop over each element connected to the adjacent vertex and update as needed */
11615de014fSVijay Mahadevan       for (i=0; i<vpere; ++i) {
117f6829af0SVijay Mahadevan         if (connect[i] == vtx || found.find(connect[i]) != found.end()) continue; /* make sure we don't double count shared vertices */
118f6829af0SVijay Mahadevan         if (allvghost.find(connect[i]) != allvghost.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     }
12315de014fSVijay Mahadevan 
12415de014fSVijay Mahadevan     if (isbaij) {
12515de014fSVijay Mahadevan       nnz[ivtx]=n_nnz;    /* leave out self to avoid repeats -> node shared by multiple elements */
1265905e1eaSVijay Mahadevan       if (onz) {
1275905e1eaSVijay Mahadevan         onz[ivtx]=n_onz;  /* add ghost non-owned nodes */
1285905e1eaSVijay Mahadevan       }
12915de014fSVijay Mahadevan     }
130f6829af0SVijay Mahadevan     else { /* AIJ matrices */
1315905e1eaSVijay Mahadevan       if (!isinterlaced) {
1325905e1eaSVijay Mahadevan         for (f=0;f<nfields;f++) {
1335905e1eaSVijay Mahadevan           nnz[f*nloc+ivtx]=n_nnz;    /* leave out self to avoid repeats -> node shared by multiple elements */
1345905e1eaSVijay Mahadevan           if (onz)
1355905e1eaSVijay Mahadevan             onz[f*nloc+ivtx]=n_onz;  /* add ghost non-owned nodes */
1365905e1eaSVijay Mahadevan         }
1375905e1eaSVijay Mahadevan       }
1385905e1eaSVijay Mahadevan       else {
1395905e1eaSVijay Mahadevan         for (f=0;f<nfields;f++) {
1405905e1eaSVijay Mahadevan           nnz[nfields*ivtx+f]=n_nnz;    /* leave out self to avoid repeats -> node shared by multiple elements */
1415905e1eaSVijay Mahadevan           if (onz)
1425905e1eaSVijay Mahadevan             onz[nfields*ivtx+f]=n_onz;  /* add ghost non-owned nodes */
1435905e1eaSVijay Mahadevan         }
1440df6e276SVijay Mahadevan       }
1450df6e276SVijay Mahadevan     }
1460df6e276SVijay Mahadevan   }
1470df6e276SVijay Mahadevan 
148*c2612ac9SVijay Mahadevan   for (i=0;i<nlsiz;i++)
1495905e1eaSVijay Mahadevan     nnz[i]+=1;  /* self count the node */
1505905e1eaSVijay Mahadevan 
15182dfd14aSVijay Mahadevan   for (ivtx=0;ivtx<nloc;ivtx++) {
1525905e1eaSVijay Mahadevan     if (!isbaij) {
1535905e1eaSVijay Mahadevan       for (ibs=0; ibs<nfields; ibs++) {
15482dfd14aSVijay Mahadevan         if (dmmoab->dfill) {  /* first address the diagonal block */
1555905e1eaSVijay Mahadevan           /* just add up the ints -- easier/faster rather than branching based on "1" */
1565905e1eaSVijay Mahadevan           for (jbs=0,inbsize=0; jbs<nfields; jbs++)
1575905e1eaSVijay Mahadevan             inbsize += dmmoab->dfill[ibs*nfields+jbs];
1585905e1eaSVijay Mahadevan         }
15982dfd14aSVijay Mahadevan         else inbsize=nfields; /* dense coupling since user didn't specify the component fill explicitly */
16082dfd14aSVijay Mahadevan         if (isinterlaced) nnz[ivtx*nfields+ibs]*=inbsize;
16182dfd14aSVijay Mahadevan         else nnz[ibs*nloc+ivtx]*=inbsize;
1625905e1eaSVijay Mahadevan 
1635905e1eaSVijay Mahadevan         if (onz) {
16482dfd14aSVijay Mahadevan           if (dmmoab->ofill) {  /* next address the off-diagonal block */
1655905e1eaSVijay Mahadevan             /* just add up the ints -- easier/faster rather than branching based on "1" */
1665905e1eaSVijay Mahadevan             for (jbs=0,iobsize=0; jbs<nfields; jbs++)
1675905e1eaSVijay Mahadevan               iobsize += dmmoab->dfill[ibs*nfields+jbs];
1685905e1eaSVijay Mahadevan           }
16982dfd14aSVijay Mahadevan           else iobsize=nfields; /* dense coupling since user didn't specify the component fill explicitly */
17082dfd14aSVijay Mahadevan           if (isinterlaced) onz[ivtx*nfields+ibs]*=iobsize;
17182dfd14aSVijay Mahadevan           else onz[ibs*nloc+ivtx]*=iobsize;
1725905e1eaSVijay Mahadevan         }
1735905e1eaSVijay Mahadevan       }
1745905e1eaSVijay Mahadevan     }
1755905e1eaSVijay Mahadevan     else {
17682dfd14aSVijay Mahadevan       /* check if we got overzealous in our nnz and onz computations */
17782dfd14aSVijay Mahadevan       nnz[ivtx]=(nnz[ivtx]>dmmoab->nloc?dmmoab->nloc:nnz[ivtx]);
17882dfd14aSVijay Mahadevan       if (onz) onz[ivtx]=(onz[ivtx]>dmmoab->nloc?dmmoab->nloc:onz[ivtx]);
1795905e1eaSVijay Mahadevan     }
1805905e1eaSVijay Mahadevan   }
1815905e1eaSVijay Mahadevan   /* update innz and ionz based on local maxima */
1825905e1eaSVijay Mahadevan   if (innz || ionz) {
1830df6e276SVijay Mahadevan     if (innz) *innz=0;
1840df6e276SVijay Mahadevan     if (ionz) *ionz=0;
185*c2612ac9SVijay Mahadevan     for (i=0;i<nlsiz;i++) {
186da6192ceSVijay Mahadevan       if (innz && (nnz[i]>*innz)) *innz=nnz[i];
187da6192ceSVijay Mahadevan       if ((ionz && onz) && (onz[i]>*ionz)) *ionz=onz[i];
188032b8ab6SVijay Mahadevan     }
1895905e1eaSVijay Mahadevan   }
1900df6e276SVijay Mahadevan   PetscFunctionReturn(0);
191032b8ab6SVijay Mahadevan }
192032b8ab6SVijay Mahadevan 
193da8c5b52SVijay Mahadevan 
194da8c5b52SVijay Mahadevan #undef __FUNCT__
1955905e1eaSVijay Mahadevan #define __FUNCT__ "DMMoabSetBlockFills_Private"
1965905e1eaSVijay Mahadevan static PetscErrorCode DMMoabSetBlockFills_Private(PetscInt w,const PetscInt *fill,PetscInt **rfill)
1975905e1eaSVijay Mahadevan {
1985905e1eaSVijay Mahadevan   PetscErrorCode ierr;
1995905e1eaSVijay Mahadevan   PetscInt       i,j,*ifill;
2005905e1eaSVijay Mahadevan 
2015905e1eaSVijay Mahadevan   PetscFunctionBegin;
2025905e1eaSVijay Mahadevan   if (!fill) PetscFunctionReturn(0);
2035905e1eaSVijay Mahadevan   ierr  = PetscMalloc1(w*w,&ifill);CHKERRQ(ierr);
2045905e1eaSVijay Mahadevan   for (i=0;i<w;i++) {
2055905e1eaSVijay Mahadevan     for (j=0; j<w; j++)
2065905e1eaSVijay Mahadevan       ifill[i*w+j]=fill[i*w+j];
2075905e1eaSVijay Mahadevan   }
2085905e1eaSVijay Mahadevan 
2095905e1eaSVijay Mahadevan   *rfill = ifill;
2105905e1eaSVijay Mahadevan   PetscFunctionReturn(0);
2115905e1eaSVijay Mahadevan }
2125905e1eaSVijay Mahadevan 
2135905e1eaSVijay Mahadevan 
2145905e1eaSVijay Mahadevan #undef __FUNCT__
2155905e1eaSVijay Mahadevan #define __FUNCT__ "DMMoabSetBlockFills"
2165905e1eaSVijay Mahadevan /*@
2175905e1eaSVijay Mahadevan     DMMoabSetBlockFills - Sets the fill pattern in each block for a multi-component problem
2185905e1eaSVijay Mahadevan     of the matrix returned by DMCreateMatrix().
2195905e1eaSVijay Mahadevan 
2205905e1eaSVijay Mahadevan     Logically Collective on DMDA
2215905e1eaSVijay Mahadevan 
2225905e1eaSVijay Mahadevan     Input Parameter:
2235905e1eaSVijay Mahadevan +   dm - the DMMoab object
2245905e1eaSVijay Mahadevan .   dfill - the fill pattern in the diagonal block (may be NULL, means use dense block)
2255905e1eaSVijay Mahadevan -   ofill - the fill pattern in the off-diagonal blocks
2265905e1eaSVijay Mahadevan 
2275905e1eaSVijay Mahadevan     Level: developer
2285905e1eaSVijay Mahadevan 
2295905e1eaSVijay Mahadevan     Notes: This only makes sense when you are doing multicomponent problems but using the
2305905e1eaSVijay Mahadevan        MPIAIJ matrix format
2315905e1eaSVijay Mahadevan 
2325905e1eaSVijay Mahadevan            The format for dfill and ofill is a 2 dimensional dof by dof matrix with 1 entries
2335905e1eaSVijay Mahadevan        representing coupling and 0 entries for missing coupling. For example
2345905e1eaSVijay Mahadevan $             dfill[9] = {1, 0, 0,
2355905e1eaSVijay Mahadevan $                         1, 1, 0,
2365905e1eaSVijay Mahadevan $                         0, 1, 1}
2375905e1eaSVijay Mahadevan        means that row 0 is coupled with only itself in the diagonal block, row 1 is coupled with
2385905e1eaSVijay Mahadevan        itself and row 0 (in the diagonal block) and row 2 is coupled with itself and row 1 (in the
2395905e1eaSVijay Mahadevan        diagonal block).
2405905e1eaSVijay Mahadevan 
2415905e1eaSVijay Mahadevan      DMDASetGetMatrix() allows you to provide general code for those more complicated nonzero patterns then
2425905e1eaSVijay Mahadevan      can be represented in the dfill, ofill format
2435905e1eaSVijay Mahadevan 
2445905e1eaSVijay Mahadevan    Contributed by Glenn Hammond
2455905e1eaSVijay Mahadevan 
2465905e1eaSVijay Mahadevan .seealso DMCreateMatrix(), DMDASetGetMatrix(), DMSetMatrixPreallocateOnly()
2475905e1eaSVijay Mahadevan 
2485905e1eaSVijay Mahadevan @*/
2495905e1eaSVijay Mahadevan PetscErrorCode  DMMoabSetBlockFills(DM dm,const PetscInt *dfill,const PetscInt *ofill)
2505905e1eaSVijay Mahadevan {
2515905e1eaSVijay Mahadevan   DM_Moab       *dmmoab=(DM_Moab*)dm->data;
2525905e1eaSVijay Mahadevan   PetscErrorCode ierr;
2535905e1eaSVijay Mahadevan 
2545905e1eaSVijay Mahadevan   PetscFunctionBegin;
2555905e1eaSVijay Mahadevan   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2565905e1eaSVijay Mahadevan   ierr = DMMoabSetBlockFills_Private(dmmoab->numFields,dfill,&dmmoab->dfill);CHKERRQ(ierr);
2575905e1eaSVijay Mahadevan   ierr = DMMoabSetBlockFills_Private(dmmoab->numFields,ofill,&dmmoab->ofill);CHKERRQ(ierr);
2585905e1eaSVijay Mahadevan   PetscFunctionReturn(0);
2595905e1eaSVijay Mahadevan }
260