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,<ogb); 56da6192ceSVijay Mahadevan ierr = MatSetLocalToGlobalMappingBlock(*J,ltogb,ltogb);CHKERRQ(ierr); 57da6192ceSVijay Mahadevan ierr = ISLocalToGlobalMappingDestroy(<ogb);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