15fa1c062SBarry Smith 25fa1c062SBarry Smith /* 31472f72bSBarry Smith Defines a matrix-vector product for the MATMPIAIJCRL matrix class. 41472f72bSBarry Smith This class is derived from the MATMPIAIJ class and retains the 55fa1c062SBarry Smith compressed row storage (aka Yale sparse matrix format) but augments 65fa1c062SBarry Smith it with a column oriented storage that is more efficient for 75fa1c062SBarry Smith matrix vector products on Vector machines. 85fa1c062SBarry Smith 95fa1c062SBarry Smith CRL stands for constant row length (that is the same number of columns 105fa1c062SBarry Smith is kept (padded with zeros) for each row of the sparse matrix. 111472f72bSBarry Smith 121472f72bSBarry Smith See src/mat/impls/aij/seq/crl/crl.c for the sequential version 135fa1c062SBarry Smith */ 145fa1c062SBarry Smith 15c6db04a5SJed Brown #include <../src/mat/impls/aij/mpi/mpiaij.h> 16c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/crl/crl.h> 175fa1c062SBarry Smith 18d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_MPIAIJCRL(Mat A) 19d71ae5a4SJacob Faibussowitsch { 205a11e1b2SBarry Smith Mat_AIJCRL *aijcrl = (Mat_AIJCRL *)A->spptr; 215fa1c062SBarry Smith 22362febeeSStefano Zampini PetscFunctionBegin; 23bf0cc555SLisandro Dalcin if (aijcrl) { 249566063dSJacob Faibussowitsch PetscCall(PetscFree2(aijcrl->acols, aijcrl->icols)); 259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&aijcrl->fwork)); 269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&aijcrl->xwork)); 279566063dSJacob Faibussowitsch PetscCall(PetscFree(aijcrl->array)); 28bf0cc555SLisandro Dalcin } 299566063dSJacob Faibussowitsch PetscCall(PetscFree(A->spptr)); 305fa1c062SBarry Smith 319566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATMPIAIJ)); 329566063dSJacob Faibussowitsch PetscCall(MatDestroy_MPIAIJ(A)); 333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 345fa1c062SBarry Smith } 355fa1c062SBarry Smith 36d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPIAIJCRL_create_aijcrl(Mat A) 37d71ae5a4SJacob Faibussowitsch { 381472f72bSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ *)(A)->data; 3911285404SBarry Smith Mat_SeqAIJ *Aij = (Mat_SeqAIJ *)(a->A->data), *Bij = (Mat_SeqAIJ *)(a->B->data); 405a11e1b2SBarry Smith Mat_AIJCRL *aijcrl = (Mat_AIJCRL *)A->spptr; 41d0f46423SBarry Smith PetscInt m = A->rmap->n; /* Number of rows in the matrix. */ 42d0f46423SBarry Smith PetscInt nd = a->A->cmap->n; /* number of columns in diagonal portion */ 431472f72bSBarry Smith PetscInt *aj = Aij->j, *bj = Bij->j; /* From the CSR representation; points to the beginning of each row. */ 441472f72bSBarry Smith PetscInt i, j, rmax = 0, *icols, *ailen = Aij->ilen, *bilen = Bij->ilen; 456873f782SBarry Smith PetscScalar *aa = Aij->a, *ba = Bij->a, *acols, *array; 465fa1c062SBarry Smith 475fa1c062SBarry Smith PetscFunctionBegin; 481472f72bSBarry Smith /* determine the row with the most columns */ 49ad540459SPierre Jolivet for (i = 0; i < m; i++) rmax = PetscMax(rmax, ailen[i] + bilen[i]); 505a11e1b2SBarry Smith aijcrl->nz = Aij->nz + Bij->nz; 515a11e1b2SBarry Smith aijcrl->m = A->rmap->n; 525a11e1b2SBarry Smith aijcrl->rmax = rmax; 532205254eSKarl Rupp 549566063dSJacob Faibussowitsch PetscCall(PetscFree2(aijcrl->acols, aijcrl->icols)); 559566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(rmax * m, &aijcrl->acols, rmax * m, &aijcrl->icols)); 565a11e1b2SBarry Smith acols = aijcrl->acols; 575a11e1b2SBarry Smith icols = aijcrl->icols; 585fa1c062SBarry Smith for (i = 0; i < m; i++) { 591472f72bSBarry Smith for (j = 0; j < ailen[i]; j++) { 605fa1c062SBarry Smith acols[j * m + i] = *aa++; 615fa1c062SBarry Smith icols[j * m + i] = *aj++; 625fa1c062SBarry Smith } 631472f72bSBarry Smith for (; j < ailen[i] + bilen[i]; j++) { 641472f72bSBarry Smith acols[j * m + i] = *ba++; 6511285404SBarry Smith icols[j * m + i] = nd + *bj++; 661472f72bSBarry Smith } 675fa1c062SBarry Smith for (; j < rmax; j++) { /* empty column entries */ 685fa1c062SBarry Smith acols[j * m + i] = 0.0; 695fa1c062SBarry Smith icols[j * m + i] = (j) ? icols[(j - 1) * m + i] : 0; /* handle case where row is EMPTY */ 705fa1c062SBarry Smith } 715fa1c062SBarry Smith } 729566063dSJacob Faibussowitsch PetscCall(PetscInfo(A, "Percentage of 0's introduced for vectorized multiply %g\n", 1.0 - ((double)(aijcrl->nz)) / ((double)(rmax * m)))); 731472f72bSBarry Smith 749566063dSJacob Faibussowitsch PetscCall(PetscFree(aijcrl->array)); 759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(a->B->cmap->n + nd, &array)); 76483e0693SBarry Smith /* xwork array is actually B->n+nd long, but we define xwork this length so can copy into it */ 779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&aijcrl->xwork)); 789566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), 1, nd, PETSC_DECIDE, array, &aijcrl->xwork)); 799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&aijcrl->fwork)); 809566063dSJacob Faibussowitsch PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, a->B->cmap->n, array + nd, &aijcrl->fwork)); 812205254eSKarl Rupp 825a11e1b2SBarry Smith aijcrl->array = array; 835a11e1b2SBarry Smith aijcrl->xscat = a->Mvctx; 843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 855fa1c062SBarry Smith } 865fa1c062SBarry Smith 87d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_MPIAIJCRL(Mat A, MatAssemblyType mode) 88d71ae5a4SJacob Faibussowitsch { 891472f72bSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data; 901472f72bSBarry Smith Mat_SeqAIJ *Aij = (Mat_SeqAIJ *)(a->A->data), *Bij = (Mat_SeqAIJ *)(a->A->data); 915fa1c062SBarry Smith 925fa1c062SBarry Smith PetscFunctionBegin; 931472f72bSBarry Smith Aij->inode.use = PETSC_FALSE; 941472f72bSBarry Smith Bij->inode.use = PETSC_FALSE; 952205254eSKarl Rupp 969566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_MPIAIJ(A, mode)); 973ba16761SJacob Faibussowitsch if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(PETSC_SUCCESS); 985fa1c062SBarry Smith 991472f72bSBarry Smith /* Now calculate the permutation and grouping information. */ 1009566063dSJacob Faibussowitsch PetscCall(MatMPIAIJCRL_create_aijcrl(A)); 1013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1025fa1c062SBarry Smith } 1035fa1c062SBarry Smith 1045a11e1b2SBarry Smith extern PetscErrorCode MatMult_AIJCRL(Mat, Vec, Vec); 1055a11e1b2SBarry Smith extern PetscErrorCode MatDuplicate_AIJCRL(Mat, MatDuplicateOption, Mat *); 1065fa1c062SBarry Smith 1075a11e1b2SBarry Smith /* MatConvert_MPIAIJ_MPIAIJCRL converts a MPIAIJ matrix into a 1085a11e1b2SBarry Smith * MPIAIJCRL matrix. This routine is called by the MatCreate_MPIAIJCRL() 1091472f72bSBarry Smith * routine, but can also be used to convert an assembled MPIAIJ matrix 1105a11e1b2SBarry Smith * into a MPIAIJCRL one. */ 111b2573a8aSBarry Smith 112d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJCRL(Mat A, MatType type, MatReuse reuse, Mat *newmat) 113d71ae5a4SJacob Faibussowitsch { 1145fa1c062SBarry Smith Mat B = *newmat; 1155a11e1b2SBarry Smith Mat_AIJCRL *aijcrl; 1165fa1c062SBarry Smith 1175fa1c062SBarry Smith PetscFunctionBegin; 11848a46eb9SPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &B)); 1195fa1c062SBarry Smith 1204dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&aijcrl)); 1215a11e1b2SBarry Smith B->spptr = (void *)aijcrl; 1225fa1c062SBarry Smith 12317667f90SBarry Smith /* Set function pointers for methods that we inherit from AIJ but override. */ 1245a11e1b2SBarry Smith B->ops->duplicate = MatDuplicate_AIJCRL; 1255a11e1b2SBarry Smith B->ops->assemblyend = MatAssemblyEnd_MPIAIJCRL; 1265a11e1b2SBarry Smith B->ops->destroy = MatDestroy_MPIAIJCRL; 1275a11e1b2SBarry Smith B->ops->mult = MatMult_AIJCRL; 1285fa1c062SBarry Smith 1295fa1c062SBarry Smith /* If A has already been assembled, compute the permutation. */ 1301baa6e33SBarry Smith if (A->assembled) PetscCall(MatMPIAIJCRL_create_aijcrl(B)); 1319566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATMPIAIJCRL)); 1325fa1c062SBarry Smith *newmat = B; 1333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1345fa1c062SBarry Smith } 1355fa1c062SBarry Smith 1365fa1c062SBarry Smith /*@C 13711a5261eSBarry Smith MatCreateMPIAIJCRL - Creates a sparse matrix of type `MATMPIAIJCRL`. 13811a5261eSBarry Smith This type inherits from `MATAIJ`, but stores some additional 1395fa1c062SBarry Smith information that is used to allow better vectorization of 1405fa1c062SBarry Smith the matrix-vector product. At the cost of increased storage, the AIJ formatted 1415fa1c062SBarry Smith matrix can be copied to a format in which pieces of the matrix are 1425fa1c062SBarry Smith stored in ELLPACK format, allowing the vectorized matrix multiply 143*20f4b53cSBarry Smith routine to use stride-1 memory accesses. 1445fa1c062SBarry Smith 145d083f849SBarry Smith Collective 1465fa1c062SBarry Smith 1475fa1c062SBarry Smith Input Parameters: 14811a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 1495fa1c062SBarry Smith . m - number of rows 1505fa1c062SBarry Smith . n - number of columns 151*20f4b53cSBarry Smith . nz - number of nonzeros per row (same for all rows), for the "diagonal" submatrix 152*20f4b53cSBarry Smith . nnz - array containing the number of nonzeros in the various rows (possibly different for each row) or `NULL`, for the "diagonal" submatrix 153*20f4b53cSBarry Smith . onz - number of nonzeros per row (same for all rows), for the "off-diagonal" submatrix 154*20f4b53cSBarry Smith - onnz - array containing the number of nonzeros in the various rows (possibly different for each row) or `NULL`, for the "off-diagonal" submatrix 1555fa1c062SBarry Smith 1565fa1c062SBarry Smith Output Parameter: 1575fa1c062SBarry Smith . A - the matrix 1585fa1c062SBarry Smith 1592ef1f0ffSBarry Smith Level: intermediate 1602ef1f0ffSBarry Smith 16111a5261eSBarry Smith Note: 162*20f4b53cSBarry Smith If `nnz` is given then `nz` is ignored 1635fa1c062SBarry Smith 1642ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, [Sparse Matrix Creation](sec_matsparse), `MATAIJ`, `MATAIJSELL`, `MATAIJPERM`, `MATAIJMKL`, `MatCreate()`, `MatCreateMPIAIJPERM()`, `MatSetValues()` 1655fa1c062SBarry Smith @*/ 166d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIAIJCRL(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], PetscInt onz, const PetscInt onnz[], Mat *A) 167d71ae5a4SJacob Faibussowitsch { 1685fa1c062SBarry Smith PetscFunctionBegin; 1699566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 1709566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n)); 1719566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATMPIAIJCRL)); 1729566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation_MPIAIJ(*A, nz, (PetscInt *)nnz, onz, (PetscInt *)onnz)); 1733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1745fa1c062SBarry Smith } 1755fa1c062SBarry Smith 176d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_MPIAIJCRL(Mat A) 177d71ae5a4SJacob Faibussowitsch { 1785fa1c062SBarry Smith PetscFunctionBegin; 1799566063dSJacob Faibussowitsch PetscCall(MatSetType(A, MATMPIAIJ)); 1809566063dSJacob Faibussowitsch PetscCall(MatConvert_MPIAIJ_MPIAIJCRL(A, MATMPIAIJCRL, MAT_INPLACE_MATRIX, &A)); 1813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1825fa1c062SBarry Smith } 183