15fa1c062SBarry Smith /*
21472f72bSBarry Smith Defines a matrix-vector product for the MATMPIAIJCRL matrix class.
31472f72bSBarry Smith This class is derived from the MATMPIAIJ class and retains the
45fa1c062SBarry Smith compressed row storage (aka Yale sparse matrix format) but augments
55fa1c062SBarry Smith it with a column oriented storage that is more efficient for
65fa1c062SBarry Smith matrix vector products on Vector machines.
75fa1c062SBarry Smith
85fa1c062SBarry Smith CRL stands for constant row length (that is the same number of columns
95fa1c062SBarry Smith is kept (padded with zeros) for each row of the sparse matrix.
101472f72bSBarry Smith
111472f72bSBarry Smith See src/mat/impls/aij/seq/crl/crl.c for the sequential version
125fa1c062SBarry Smith */
135fa1c062SBarry Smith
14c6db04a5SJed Brown #include <../src/mat/impls/aij/mpi/mpiaij.h>
15c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/crl/crl.h>
165fa1c062SBarry Smith
MatDestroy_MPIAIJCRL(Mat A)1766976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_MPIAIJCRL(Mat A)
18d71ae5a4SJacob Faibussowitsch {
195a11e1b2SBarry Smith Mat_AIJCRL *aijcrl = (Mat_AIJCRL *)A->spptr;
205fa1c062SBarry Smith
21362febeeSStefano Zampini PetscFunctionBegin;
22bf0cc555SLisandro Dalcin if (aijcrl) {
239566063dSJacob Faibussowitsch PetscCall(PetscFree2(aijcrl->acols, aijcrl->icols));
249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&aijcrl->fwork));
259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&aijcrl->xwork));
269566063dSJacob Faibussowitsch PetscCall(PetscFree(aijcrl->array));
27bf0cc555SLisandro Dalcin }
289566063dSJacob Faibussowitsch PetscCall(PetscFree(A->spptr));
295fa1c062SBarry Smith
309566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATMPIAIJ));
319566063dSJacob Faibussowitsch PetscCall(MatDestroy_MPIAIJ(A));
323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
335fa1c062SBarry Smith }
345fa1c062SBarry Smith
MatMPIAIJCRL_create_aijcrl(Mat A)3566976f2fSJacob Faibussowitsch static PetscErrorCode MatMPIAIJCRL_create_aijcrl(Mat A)
36d71ae5a4SJacob Faibussowitsch {
37*57508eceSPierre Jolivet Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data;
38f4f49eeaSPierre Jolivet Mat_SeqAIJ *Aij = (Mat_SeqAIJ *)a->A->data, *Bij = (Mat_SeqAIJ *)a->B->data;
395a11e1b2SBarry Smith Mat_AIJCRL *aijcrl = (Mat_AIJCRL *)A->spptr;
40d0f46423SBarry Smith PetscInt m = A->rmap->n; /* Number of rows in the matrix. */
41d0f46423SBarry Smith PetscInt nd = a->A->cmap->n; /* number of columns in diagonal portion */
421472f72bSBarry Smith PetscInt *aj = Aij->j, *bj = Bij->j; /* From the CSR representation; points to the beginning of each row. */
431472f72bSBarry Smith PetscInt i, j, rmax = 0, *icols, *ailen = Aij->ilen, *bilen = Bij->ilen;
446873f782SBarry Smith PetscScalar *aa = Aij->a, *ba = Bij->a, *acols, *array;
455fa1c062SBarry Smith
465fa1c062SBarry Smith PetscFunctionBegin;
471472f72bSBarry Smith /* determine the row with the most columns */
48ad540459SPierre Jolivet for (i = 0; i < m; i++) rmax = PetscMax(rmax, ailen[i] + bilen[i]);
495a11e1b2SBarry Smith aijcrl->nz = Aij->nz + Bij->nz;
505a11e1b2SBarry Smith aijcrl->m = A->rmap->n;
515a11e1b2SBarry Smith aijcrl->rmax = rmax;
522205254eSKarl Rupp
539566063dSJacob Faibussowitsch PetscCall(PetscFree2(aijcrl->acols, aijcrl->icols));
549566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(rmax * m, &aijcrl->acols, rmax * m, &aijcrl->icols));
555a11e1b2SBarry Smith acols = aijcrl->acols;
565a11e1b2SBarry Smith icols = aijcrl->icols;
575fa1c062SBarry Smith for (i = 0; i < m; i++) {
581472f72bSBarry Smith for (j = 0; j < ailen[i]; j++) {
595fa1c062SBarry Smith acols[j * m + i] = *aa++;
605fa1c062SBarry Smith icols[j * m + i] = *aj++;
615fa1c062SBarry Smith }
621472f72bSBarry Smith for (; j < ailen[i] + bilen[i]; j++) {
631472f72bSBarry Smith acols[j * m + i] = *ba++;
6411285404SBarry Smith icols[j * m + i] = nd + *bj++;
651472f72bSBarry Smith }
665fa1c062SBarry Smith for (; j < rmax; j++) { /* empty column entries */
675fa1c062SBarry Smith acols[j * m + i] = 0.0;
685fa1c062SBarry Smith icols[j * m + i] = (j) ? icols[(j - 1) * m + i] : 0; /* handle case where row is EMPTY */
695fa1c062SBarry Smith }
705fa1c062SBarry Smith }
718564c97fSStefano Zampini PetscCall(PetscInfo(A, "Percentage of 0's introduced for vectorized multiply %g\n", 1.0 - ((double)aijcrl->nz) / PetscMax((double)rmax * m, 1)));
721472f72bSBarry Smith
739566063dSJacob Faibussowitsch PetscCall(PetscFree(aijcrl->array));
749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(a->B->cmap->n + nd, &array));
75483e0693SBarry Smith /* xwork array is actually B->n+nd long, but we define xwork this length so can copy into it */
769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&aijcrl->xwork));
779566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), 1, nd, PETSC_DECIDE, array, &aijcrl->xwork));
789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&aijcrl->fwork));
799566063dSJacob Faibussowitsch PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, a->B->cmap->n, array + nd, &aijcrl->fwork));
802205254eSKarl Rupp
815a11e1b2SBarry Smith aijcrl->array = array;
825a11e1b2SBarry Smith aijcrl->xscat = a->Mvctx;
833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
845fa1c062SBarry Smith }
855fa1c062SBarry Smith
MatAssemblyEnd_MPIAIJCRL(Mat A,MatAssemblyType mode)8666976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_MPIAIJCRL(Mat A, MatAssemblyType mode)
87d71ae5a4SJacob Faibussowitsch {
881472f72bSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data;
89f4f49eeaSPierre Jolivet Mat_SeqAIJ *Aij = (Mat_SeqAIJ *)a->A->data, *Bij = (Mat_SeqAIJ *)a->A->data;
905fa1c062SBarry Smith
915fa1c062SBarry Smith PetscFunctionBegin;
921472f72bSBarry Smith Aij->inode.use = PETSC_FALSE;
931472f72bSBarry Smith Bij->inode.use = PETSC_FALSE;
942205254eSKarl Rupp
959566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd_MPIAIJ(A, mode));
963ba16761SJacob Faibussowitsch if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(PETSC_SUCCESS);
975fa1c062SBarry Smith
981472f72bSBarry Smith /* Now calculate the permutation and grouping information. */
999566063dSJacob Faibussowitsch PetscCall(MatMPIAIJCRL_create_aijcrl(A));
1003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1015fa1c062SBarry Smith }
1025fa1c062SBarry Smith
1035a11e1b2SBarry Smith extern PetscErrorCode MatMult_AIJCRL(Mat, Vec, Vec);
1045a11e1b2SBarry Smith extern PetscErrorCode MatDuplicate_AIJCRL(Mat, MatDuplicateOption, Mat *);
1055fa1c062SBarry Smith
1065a11e1b2SBarry Smith /* MatConvert_MPIAIJ_MPIAIJCRL converts a MPIAIJ matrix into a
1075a11e1b2SBarry Smith * MPIAIJCRL matrix. This routine is called by the MatCreate_MPIAIJCRL()
1081472f72bSBarry Smith * routine, but can also be used to convert an assembled MPIAIJ matrix
1095a11e1b2SBarry Smith * into a MPIAIJCRL one. */
110b2573a8aSBarry Smith
MatConvert_MPIAIJ_MPIAIJCRL(Mat A,MatType type,MatReuse reuse,Mat * newmat)111d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJCRL(Mat A, MatType type, MatReuse reuse, Mat *newmat)
112d71ae5a4SJacob Faibussowitsch {
1135fa1c062SBarry Smith Mat B = *newmat;
1145a11e1b2SBarry Smith Mat_AIJCRL *aijcrl;
1155fa1c062SBarry Smith
1165fa1c062SBarry Smith PetscFunctionBegin;
11748a46eb9SPierre Jolivet if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &B));
1185fa1c062SBarry Smith
1194dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&aijcrl));
1205a11e1b2SBarry Smith B->spptr = (void *)aijcrl;
1215fa1c062SBarry Smith
12217667f90SBarry Smith /* Set function pointers for methods that we inherit from AIJ but override. */
1235a11e1b2SBarry Smith B->ops->duplicate = MatDuplicate_AIJCRL;
1245a11e1b2SBarry Smith B->ops->assemblyend = MatAssemblyEnd_MPIAIJCRL;
1255a11e1b2SBarry Smith B->ops->destroy = MatDestroy_MPIAIJCRL;
1265a11e1b2SBarry Smith B->ops->mult = MatMult_AIJCRL;
1275fa1c062SBarry Smith
1285fa1c062SBarry Smith /* If A has already been assembled, compute the permutation. */
1291baa6e33SBarry Smith if (A->assembled) PetscCall(MatMPIAIJCRL_create_aijcrl(B));
1309566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATMPIAIJCRL));
1315fa1c062SBarry Smith *newmat = B;
1323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1335fa1c062SBarry Smith }
1345fa1c062SBarry Smith
1355fa1c062SBarry Smith /*@C
13611a5261eSBarry Smith MatCreateMPIAIJCRL - Creates a sparse matrix of type `MATMPIAIJCRL`.
1375fa1c062SBarry Smith
138d083f849SBarry Smith Collective
1395fa1c062SBarry Smith
1405fa1c062SBarry Smith Input Parameters:
14111a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
1425fa1c062SBarry Smith . m - number of rows
1435fa1c062SBarry Smith . n - number of columns
14420f4b53cSBarry Smith . nz - number of nonzeros per row (same for all rows), for the "diagonal" submatrix
14520f4b53cSBarry Smith . nnz - array containing the number of nonzeros in the various rows (possibly different for each row) or `NULL`, for the "diagonal" submatrix
14620f4b53cSBarry Smith . onz - number of nonzeros per row (same for all rows), for the "off-diagonal" submatrix
14720f4b53cSBarry Smith - onnz - array containing the number of nonzeros in the various rows (possibly different for each row) or `NULL`, for the "off-diagonal" submatrix
1485fa1c062SBarry Smith
1495fa1c062SBarry Smith Output Parameter:
1505fa1c062SBarry Smith . A - the matrix
1515fa1c062SBarry Smith
1522ef1f0ffSBarry Smith Level: intermediate
1532ef1f0ffSBarry Smith
1542920cce0SJacob Faibussowitsch Notes:
1552920cce0SJacob Faibussowitsch This type inherits from `MATAIJ`, but stores some additional information that is used to
1562920cce0SJacob Faibussowitsch allow better vectorization of the matrix-vector product. At the cost of increased storage,
1572920cce0SJacob Faibussowitsch the AIJ formatted matrix can be copied to a format in which pieces of the matrix are stored
1582920cce0SJacob Faibussowitsch in ELLPACK format, allowing the vectorized matrix multiply routine to use stride-1 memory
1592920cce0SJacob Faibussowitsch accesses.
1602920cce0SJacob Faibussowitsch
16120f4b53cSBarry Smith If `nnz` is given then `nz` is ignored
1625fa1c062SBarry Smith
1631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, [Sparse Matrix Creation](sec_matsparse), `MATAIJ`, `MATAIJSELL`, `MATAIJPERM`, `MATAIJMKL`, `MatCreate()`, `MatCreateMPIAIJPERM()`, `MatSetValues()`
1645fa1c062SBarry Smith @*/
MatCreateMPIAIJCRL(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],PetscInt onz,const PetscInt onnz[],Mat * A)165d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIAIJCRL(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], PetscInt onz, const PetscInt onnz[], Mat *A)
166d71ae5a4SJacob Faibussowitsch {
1675fa1c062SBarry Smith PetscFunctionBegin;
1689566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A));
1699566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, m, n));
1709566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATMPIAIJCRL));
1719566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation_MPIAIJ(*A, nz, (PetscInt *)nnz, onz, (PetscInt *)onnz));
1723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1735fa1c062SBarry Smith }
1745fa1c062SBarry Smith
MatCreate_MPIAIJCRL(Mat A)175d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_MPIAIJCRL(Mat A)
176d71ae5a4SJacob Faibussowitsch {
1775fa1c062SBarry Smith PetscFunctionBegin;
1789566063dSJacob Faibussowitsch PetscCall(MatSetType(A, MATMPIAIJ));
1799566063dSJacob Faibussowitsch PetscCall(MatConvert_MPIAIJ_MPIAIJCRL(A, MATMPIAIJCRL, MAT_INPLACE_MATRIX, &A));
1803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1815fa1c062SBarry Smith }
182