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`. 1385fa1c062SBarry Smith 139d083f849SBarry Smith Collective 1405fa1c062SBarry Smith 1415fa1c062SBarry Smith Input Parameters: 14211a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF` 1435fa1c062SBarry Smith . m - number of rows 1445fa1c062SBarry Smith . n - number of columns 14520f4b53cSBarry Smith . nz - number of nonzeros per row (same for all rows), for the "diagonal" submatrix 14620f4b53cSBarry Smith . nnz - array containing the number of nonzeros in the various rows (possibly different for each row) or `NULL`, for the "diagonal" submatrix 14720f4b53cSBarry Smith . onz - number of nonzeros per row (same for all rows), for the "off-diagonal" submatrix 14820f4b53cSBarry Smith - onnz - array containing the number of nonzeros in the various rows (possibly different for each row) or `NULL`, for the "off-diagonal" submatrix 1495fa1c062SBarry Smith 1505fa1c062SBarry Smith Output Parameter: 1515fa1c062SBarry Smith . A - the matrix 1525fa1c062SBarry Smith 1532ef1f0ffSBarry Smith Level: intermediate 1542ef1f0ffSBarry Smith 155*2920cce0SJacob Faibussowitsch Notes: 156*2920cce0SJacob Faibussowitsch This type inherits from `MATAIJ`, but stores some additional information that is used to 157*2920cce0SJacob Faibussowitsch allow better vectorization of the matrix-vector product. At the cost of increased storage, 158*2920cce0SJacob Faibussowitsch the AIJ formatted matrix can be copied to a format in which pieces of the matrix are stored 159*2920cce0SJacob Faibussowitsch in ELLPACK format, allowing the vectorized matrix multiply routine to use stride-1 memory 160*2920cce0SJacob Faibussowitsch accesses. 161*2920cce0SJacob Faibussowitsch 16220f4b53cSBarry Smith If `nnz` is given then `nz` is ignored 1635fa1c062SBarry Smith 1641cc06b55SBarry Smith .seealso: [](ch_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