xref: /petsc/src/dm/impls/moab/dmmbmat.cxx (revision da8c5b52c7dbc42c6b360272cd190500ea2375bd)
1032b8ab6SVijay Mahadevan #include <petsc-private/dmmbimpl.h> /*I  "petscdm.h"   I*/
2032b8ab6SVijay Mahadevan #include <petsc-private/vecimpl.h> /*I  "petscdm.h"   I*/
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);
8*da8c5b52SVijay Mahadevan static PetscErrorCode DMMoab_MatFillMatrixEntries_Private(DM,Mat);
9032b8ab6SVijay Mahadevan 
10032b8ab6SVijay Mahadevan #undef __FUNCT__
11032b8ab6SVijay Mahadevan #define __FUNCT__ "DMCreateMatrix_Moab"
12032b8ab6SVijay Mahadevan PetscErrorCode DMCreateMatrix_Moab(DM dm, MatType mtype,Mat *J)
13032b8ab6SVijay Mahadevan {
14032b8ab6SVijay Mahadevan   PetscErrorCode  ierr;
15da6192ceSVijay Mahadevan   ISLocalToGlobalMapping ltogb;
16da6192ceSVijay Mahadevan   PetscInt        innz,ionz,nlsiz;
17032b8ab6SVijay Mahadevan   DM_Moab         *dmmoab=(DM_Moab*)dm->data;
18da6192ceSVijay Mahadevan   PetscInt        *nnz=0,*onz=0;
19032b8ab6SVijay Mahadevan   char            *tmp=0;
20032b8ab6SVijay Mahadevan   moab::ErrorCode merr;
21032b8ab6SVijay Mahadevan 
22032b8ab6SVijay Mahadevan   PetscFunctionBegin;
23032b8ab6SVijay Mahadevan   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
24032b8ab6SVijay Mahadevan   PetscValidPointer(J,3);
25032b8ab6SVijay Mahadevan 
26db66d124SVijay Mahadevan   /* create the Matrix and set its type as specified by user */
27032b8ab6SVijay Mahadevan   ierr = MatCreate(dmmoab->pcomm->comm(), J);CHKERRQ(ierr);
28032b8ab6SVijay Mahadevan   ierr = MatSetSizes(*J, nloc, nloc, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
29032b8ab6SVijay Mahadevan   ierr = MatSetType(*J, mtype);CHKERRQ(ierr);
30032b8ab6SVijay Mahadevan   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
31032b8ab6SVijay Mahadevan 
32db66d124SVijay Mahadevan   /* next, need to allocate the non-zero arrays to enable pre-allocation */
33032b8ab6SVijay Mahadevan   ierr = MatGetType(*J, &mltype);CHKERRQ(ierr); /* in case user overrode the default type from command-line, re-check the type */
34032b8ab6SVijay Mahadevan   ierr = PetscStrstr(mltype, "baij", &tmp);CHKERRQ(ierr);
35032b8ab6SVijay Mahadevan   nsize = (tmp ? dmmoab->nloc:dmmoab->nloc*dmmoab->bs);
36032b8ab6SVijay Mahadevan 
37032b8ab6SVijay Mahadevan   /* allocate the nnz, onz arrays based on block size and local nodes */
38da6192ceSVijay Mahadevan   ierr = PetscMalloc((nlsiz)*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
39da6192ceSVijay Mahadevan   ierr = PetscMemzero(nnz,sizeof(PetscInt)*(nlsiz));CHKERRQ(ierr);
40da6192ceSVijay Mahadevan   ierr = PetscMalloc(nlsiz*sizeof(PetscInt),&onz);CHKERRQ(ierr);
41da6192ceSVijay Mahadevan   ierr = PetscMemzero(onz,sizeof(PetscInt)*nlsiz);CHKERRQ(ierr);
42032b8ab6SVijay Mahadevan 
43032b8ab6SVijay Mahadevan   /* compute the nonzero pattern based on MOAB connectivity data for local elements */
44032b8ab6SVijay Mahadevan   ierr = DMMoab_Compute_NNZ_From_Connectivity(dm,&innz,nnz,&ionz,onz,(tmp?PETSC_TRUE:PETSC_FALSE));CHKERRQ(ierr);
45032b8ab6SVijay Mahadevan 
46da6192ceSVijay Mahadevan   /* create the Matrix and set its type as specified by user */
47da6192ceSVijay Mahadevan   ierr = MatCreate(dmmoab->pcomm->comm(), J);CHKERRQ(ierr);
48addae81cSVijay Mahadevan   ierr = MatSetSizes(*J, dmmoab->nloc*dmmoab->numFields, dmmoab->nloc*dmmoab->numFields, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
49032b8ab6SVijay Mahadevan   ierr = MatSetBlockSize(*J, dmmoab->bs);CHKERRQ(ierr);
50da6192ceSVijay Mahadevan   ierr = MatSetType(*J, mtype);CHKERRQ(ierr);
51da6192ceSVijay Mahadevan   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
52da6192ceSVijay Mahadevan 
53da6192ceSVijay Mahadevan   if (!dmmoab->ltog_map) SETERRQ(dmmoab->pcomm->comm(), PETSC_ERR_ORDER, "Cannot create a DMMoab Mat without calling DMSetUp first.");
54da6192ceSVijay Mahadevan   ierr = MatSetLocalToGlobalMapping(*J,dmmoab->ltog_map,dmmoab->ltog_map);CHKERRQ(ierr);
55da6192ceSVijay Mahadevan   ierr = ISLocalToGlobalMappingBlock(dmmoab->ltog_map,dmmoab->bs,&ltogb);
56da6192ceSVijay Mahadevan   ierr = MatSetLocalToGlobalMappingBlock(*J,ltogb,ltogb);CHKERRQ(ierr);
57da6192ceSVijay Mahadevan   ierr = ISLocalToGlobalMappingDestroy(&ltogb);CHKERRQ(ierr);
58032b8ab6SVijay Mahadevan 
59032b8ab6SVijay Mahadevan   /* set preallocation based on different supported Mat types */
60e23c60ebSVijay Mahadevan   ierr = MatSeqAIJSetPreallocation(*J, innz, nnz);CHKERRQ(ierr);
61e23c60ebSVijay Mahadevan   ierr = MatMPIAIJSetPreallocation(*J, innz, nnz, ionz, onz);CHKERRQ(ierr);
62032b8ab6SVijay Mahadevan   ierr = MatSeqBAIJSetPreallocation(*J, dmmoab->bs, innz, nnz);CHKERRQ(ierr);
63032b8ab6SVijay Mahadevan   ierr = MatMPIBAIJSetPreallocation(*J, dmmoab->bs, innz, nnz, ionz, onz);CHKERRQ(ierr);
64032b8ab6SVijay Mahadevan 
65*da8c5b52SVijay Mahadevan   /* clean up temporary memory */
66032b8ab6SVijay Mahadevan   ierr = PetscFree(nnz);CHKERRQ(ierr);
67032b8ab6SVijay Mahadevan   ierr = PetscFree(onz);CHKERRQ(ierr);
68*da8c5b52SVijay Mahadevan 
69*da8c5b52SVijay Mahadevan   /* set up internal matrix data-structures */
70*da8c5b52SVijay Mahadevan   ierr = MatSetUp(*J);CHKERRQ(ierr);
71*da8c5b52SVijay Mahadevan 
72*da8c5b52SVijay Mahadevan   /* set DM reference */
73*da8c5b52SVijay Mahadevan   ierr = MatSetDM(*J, dm);CHKERRQ(ierr);
74*da8c5b52SVijay Mahadevan 
75*da8c5b52SVijay Mahadevan   /* set the correct NNZ pattern by setting matrix entries - make the matrix ready to use */
76*da8c5b52SVijay Mahadevan   ierr = DMMoab_MatFillMatrixEntries_Private(dm,*J);CHKERRQ(ierr);
77032b8ab6SVijay Mahadevan   PetscFunctionReturn(0);
78032b8ab6SVijay Mahadevan }
79032b8ab6SVijay Mahadevan 
80032b8ab6SVijay Mahadevan 
81032b8ab6SVijay Mahadevan #undef __FUNCT__
82032b8ab6SVijay Mahadevan #define __FUNCT__ "DMMoab_Compute_NNZ_From_Connectivity"
83032b8ab6SVijay Mahadevan PetscErrorCode DMMoab_Compute_NNZ_From_Connectivity(DM dm,PetscInt* innz,PetscInt* nnz,PetscInt* ionz,PetscInt* onz,PetscBool isbaij)
84032b8ab6SVijay Mahadevan {
85da6192ceSVijay Mahadevan   PetscInt        i,f,nloc,vpere,bs,nsize,ivtx,n_nnz,n_onz;
86032b8ab6SVijay Mahadevan   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
87032b8ab6SVijay Mahadevan   const moab::EntityHandle *connect;
88da6192ceSVijay Mahadevan   moab::Range     adjs,found,allvlocal,allvghost;
89da6192ceSVijay Mahadevan   moab::Range::iterator iter,jter;
90da6192ceSVijay Mahadevan   std::vector<moab::EntityHandle> storage;
91da6192ceSVijay Mahadevan   moab::EntityHandle vtx;
92032b8ab6SVijay Mahadevan   moab::ErrorCode merr;
93032b8ab6SVijay Mahadevan 
94032b8ab6SVijay Mahadevan   PetscFunctionBegin;
95032b8ab6SVijay Mahadevan   bs = dmmoab->bs;
96032b8ab6SVijay Mahadevan   nloc = dmmoab->nloc;
97032b8ab6SVijay Mahadevan   nsize = (isbaij ? nloc:nloc*bs);
98032b8ab6SVijay Mahadevan 
99da6192ceSVijay Mahadevan   /* find the truly user-expected layer of ghosted entities to decipher NNZ pattern */
100da6192ceSVijay Mahadevan   merr = dmmoab->mbiface->get_entities_by_type(dmmoab->fileset,moab::MBVERTEX,allvlocal,true);MBERRNM(merr);
101da6192ceSVijay Mahadevan   merr = dmmoab->pcomm->filter_pstatus(allvlocal,PSTATUS_NOT_OWNED,PSTATUS_NOT,-1,&adjs);MBERRNM(merr);
102da6192ceSVijay Mahadevan   allvghost = moab::subtract(allvlocal, adjs);
103032b8ab6SVijay Mahadevan 
104032b8ab6SVijay Mahadevan   /* loop over vertices and update the number of connectivity */
105032b8ab6SVijay Mahadevan   for (j=0;j<vpere;j++) {
106032b8ab6SVijay Mahadevan 
107da6192ceSVijay Mahadevan     vtx = *iter;
108da6192ceSVijay Mahadevan     adjs.clear();
109da6192ceSVijay Mahadevan     /* Get adjacency information for current vertex - i.e., all elements of dimension (dim) that connects
110da6192ceSVijay Mahadevan        to the current vertex. We can then decipher if a vertex is ghosted or not and compute the
111da6192ceSVijay Mahadevan        non-zero pattern accordingly. */
112da6192ceSVijay Mahadevan     merr = dmmoab->mbiface->get_adjacencies(&vtx,1,dmmoab->dim,false,adjs,moab::Interface::INTERSECT);
1130df6e276SVijay Mahadevan 
11415de014fSVijay Mahadevan     /* loop over vertices and update the number of connectivity */
11515de014fSVijay Mahadevan     for(jter = adjs.begin(); jter != adjs.end(); jter++) {
1160df6e276SVijay Mahadevan 
11715de014fSVijay Mahadevan       /* Get connectivity information in canonical ordering for the local element */
11815de014fSVijay Mahadevan       merr = dmmoab->mbiface->get_connectivity(*jter,connect,vpere,false,&storage);MBERRNM(merr);
1190df6e276SVijay Mahadevan 
12015de014fSVijay Mahadevan       for (i=0; i<vpere; ++i) {
12115de014fSVijay Mahadevan         if (connect[i] == vtx || found.find(connect[i]) != found.end()) continue;
122da6192ceSVijay Mahadevan         if (allvghost.find(connect[i]) != allvghost.end()) n_onz++;
12315de014fSVijay Mahadevan         else n_nnz++;
12415de014fSVijay Mahadevan         found.insert(connect[i]);
12515de014fSVijay Mahadevan       }
12615de014fSVijay Mahadevan     }
12715de014fSVijay Mahadevan 
12815de014fSVijay Mahadevan     if (isbaij) {
12915de014fSVijay Mahadevan       nnz[ivtx]=n_nnz;      /* leave out self to avoid repeats -> node shared by multiple elements */
13015de014fSVijay Mahadevan       if (onz) onz[ivtx]=n_onz;  /* add ghost non-owned nodes */
13115de014fSVijay Mahadevan     }
13215de014fSVijay Mahadevan     else {
133addae81cSVijay Mahadevan       for (f=0;f<dmmoab->numFields;f++) {
134addae81cSVijay Mahadevan         nnz[dmmoab->numFields*ivtx+f]=n_nnz;      /* leave out self to avoid repeats -> node shared by multiple elements */
135addae81cSVijay Mahadevan         if (onz) onz[dmmoab->numFields*ivtx+f]=n_onz;  /* add ghost non-owned nodes */
1360df6e276SVijay Mahadevan       }
1370df6e276SVijay Mahadevan     }
1380df6e276SVijay Mahadevan   }
1390df6e276SVijay Mahadevan 
1400df6e276SVijay Mahadevan   if (innz) *innz=0;
1410df6e276SVijay Mahadevan   if (ionz) *ionz=0;
1420df6e276SVijay Mahadevan   for (i=0;i<nsize;i++) {
1430df6e276SVijay Mahadevan     nnz[i]+=1;  /* self count the node */
144da6192ceSVijay Mahadevan     /* check if we got overzealous */
145da6192ceSVijay Mahadevan     nnz[i]=(nnz[i]>dmmoab->nloc ? dmmoab->nloc:nnz[i]);
146032b8ab6SVijay Mahadevan     if (!isbaij) {
1470df6e276SVijay Mahadevan       nnz[i]*=bs;
1480df6e276SVijay Mahadevan       onz[i]*=bs;
149032b8ab6SVijay Mahadevan     }
150*da8c5b52SVijay Mahadevan     PetscInfo3(dm, "Vertex ID: %D \t NNZ = %D \t ONZ = %D.\n",i,nnz[i],onz[i]);
1510df6e276SVijay Mahadevan 
152da6192ceSVijay Mahadevan     if (innz && (nnz[i]>*innz)) *innz=nnz[i];
153da6192ceSVijay Mahadevan     if ((ionz && onz) && (onz[i]>*ionz)) *ionz=onz[i];
154032b8ab6SVijay Mahadevan   }
1550df6e276SVijay Mahadevan   PetscFunctionReturn(0);
156032b8ab6SVijay Mahadevan }
157032b8ab6SVijay Mahadevan 
158*da8c5b52SVijay Mahadevan 
159*da8c5b52SVijay Mahadevan #undef __FUNCT__
160*da8c5b52SVijay Mahadevan #define __FUNCT__ "DMMoab_MatFillMatrixEntries_Private"
161*da8c5b52SVijay Mahadevan PetscErrorCode DMMoab_MatFillMatrixEntries_Private(DM dm, Mat A)
162*da8c5b52SVijay Mahadevan {
163*da8c5b52SVijay Mahadevan   DM_Moab                   *dmmoab = (DM_Moab*)dm->data;
164*da8c5b52SVijay Mahadevan   PetscInt                  nconn = 0,prev_nconn = 0;
165*da8c5b52SVijay Mahadevan   const moab::EntityHandle  *connect;
166*da8c5b52SVijay Mahadevan   PetscScalar               *locala=NULL;
167*da8c5b52SVijay Mahadevan   PetscInt                  *dof_indices=NULL;
168*da8c5b52SVijay Mahadevan   PetscErrorCode            ierr;
169*da8c5b52SVijay Mahadevan 
170*da8c5b52SVijay Mahadevan   PetscFunctionBegin;
171*da8c5b52SVijay Mahadevan   /* loop over local elements */
172*da8c5b52SVijay Mahadevan   for(moab::Range::iterator iter = dmmoab->elocal->begin(); iter != dmmoab->elocal->end(); iter++) {
173*da8c5b52SVijay Mahadevan     const moab::EntityHandle ehandle = *iter;
174*da8c5b52SVijay Mahadevan 
175*da8c5b52SVijay Mahadevan     /* Get connectivity information: */
176*da8c5b52SVijay Mahadevan     ierr = DMMoabGetElementConnectivity(dm, ehandle, &nconn, &connect);CHKERRQ(ierr);
177*da8c5b52SVijay Mahadevan 
178*da8c5b52SVijay Mahadevan     /* if we have mixed elements or arrays have not been initialized - Allocate now */
179*da8c5b52SVijay Mahadevan     if (prev_nconn != nconn) {
180*da8c5b52SVijay Mahadevan       if (locala) {
181*da8c5b52SVijay Mahadevan         ierr = PetscFree(locala);CHKERRQ(ierr);
182*da8c5b52SVijay Mahadevan         ierr = PetscFree(dof_indices);CHKERRQ(ierr);
183*da8c5b52SVijay Mahadevan       }
184*da8c5b52SVijay Mahadevan       ierr = PetscMalloc(sizeof(PetscScalar)*nconn*nconn*dmmoab->numFields*dmmoab->numFields,&locala);CHKERRQ(ierr);
185*da8c5b52SVijay Mahadevan       ierr = PetscMemzero(locala,sizeof(PetscScalar)*nconn*nconn*dmmoab->numFields*dmmoab->numFields);CHKERRQ(ierr);
186*da8c5b52SVijay Mahadevan       ierr = PetscMalloc(sizeof(PetscInt)*nconn,&dof_indices);CHKERRQ(ierr);
187*da8c5b52SVijay Mahadevan       PetscInfo2(dm, "Allocating new memory and zeroing out for locala. [Prev: %d,  Curr-size: %d].\n",prev_nconn*prev_nconn*dmmoab->numFields*dmmoab->numFields,nconn*nconn*dmmoab->numFields*dmmoab->numFields);
188*da8c5b52SVijay Mahadevan       prev_nconn=nconn;
189*da8c5b52SVijay Mahadevan     }
190*da8c5b52SVijay Mahadevan 
191*da8c5b52SVijay Mahadevan     /* get the global DOF number to appropriately set the element contribution in the RHS vector */
192*da8c5b52SVijay Mahadevan     ierr = DMMoabGetDofsBlockedLocal(dm, nconn, connect, dof_indices);CHKERRQ(ierr);
193*da8c5b52SVijay Mahadevan 
194*da8c5b52SVijay Mahadevan     /* set the values directly into appropriate locations. Can alternately use VecSetValues */
195*da8c5b52SVijay Mahadevan     ierr = MatSetValuesBlockedLocal(A, nconn, dof_indices, nconn, dof_indices, locala, INSERT_VALUES);CHKERRQ(ierr);
196*da8c5b52SVijay Mahadevan   }
197*da8c5b52SVijay Mahadevan 
198*da8c5b52SVijay Mahadevan   /* clean up memory */
199*da8c5b52SVijay Mahadevan   ierr = PetscFree(locala);CHKERRQ(ierr);
200*da8c5b52SVijay Mahadevan   ierr = PetscFree(dof_indices);CHKERRQ(ierr);
201*da8c5b52SVijay Mahadevan 
202*da8c5b52SVijay Mahadevan   /* finish assembly */
203*da8c5b52SVijay Mahadevan   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
204*da8c5b52SVijay Mahadevan   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
205*da8c5b52SVijay Mahadevan   PetscFunctionReturn(0);
206*da8c5b52SVijay Mahadevan }
207*da8c5b52SVijay Mahadevan 
208