xref: /petsc/src/mat/impls/aij/mpi/crl/mcrl.c (revision 1cc06b555e92f8ec64db10330b8bbd830e5bc876)
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
14320f4b53cSBarry 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
15120f4b53cSBarry Smith .  nz - number of nonzeros per row (same for all rows), for the "diagonal" submatrix
15220f4b53cSBarry Smith .  nnz - array containing the number of nonzeros in the various rows (possibly different for each row) or `NULL`, for the "diagonal" submatrix
15320f4b53cSBarry Smith .  onz - number of nonzeros per row (same for all rows), for the "off-diagonal" submatrix
15420f4b53cSBarry 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:
16220f4b53cSBarry Smith    If `nnz` is given then `nz` is ignored
1635fa1c062SBarry Smith 
164*1cc06b55SBarry 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