xref: /petsc/src/mat/impls/aij/mpi/crl/mcrl.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
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 
189371c9d4SSatish Balay PetscErrorCode MatDestroy_MPIAIJCRL(Mat A) {
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));
325fa1c062SBarry Smith   PetscFunctionReturn(0);
335fa1c062SBarry Smith }
345fa1c062SBarry Smith 
359371c9d4SSatish Balay PetscErrorCode MatMPIAIJCRL_create_aijcrl(Mat A) {
361472f72bSBarry Smith   Mat_MPIAIJ  *a   = (Mat_MPIAIJ *)(A)->data;
3711285404SBarry Smith   Mat_SeqAIJ  *Aij = (Mat_SeqAIJ *)(a->A->data), *Bij = (Mat_SeqAIJ *)(a->B->data);
385a11e1b2SBarry Smith   Mat_AIJCRL  *aijcrl = (Mat_AIJCRL *)A->spptr;
39d0f46423SBarry Smith   PetscInt     m      = A->rmap->n;       /* Number of rows in the matrix. */
40d0f46423SBarry Smith   PetscInt     nd     = a->A->cmap->n;    /* number of columns in diagonal portion */
411472f72bSBarry Smith   PetscInt    *aj = Aij->j, *bj = Bij->j; /* From the CSR representation; points to the beginning  of each row. */
421472f72bSBarry Smith   PetscInt     i, j, rmax = 0, *icols, *ailen = Aij->ilen, *bilen = Bij->ilen;
436873f782SBarry Smith   PetscScalar *aa = Aij->a, *ba = Bij->a, *acols, *array;
445fa1c062SBarry Smith 
455fa1c062SBarry Smith   PetscFunctionBegin;
461472f72bSBarry Smith   /* determine the row with the most columns */
47ad540459SPierre Jolivet   for (i = 0; i < m; i++) rmax = PetscMax(rmax, ailen[i] + bilen[i]);
485a11e1b2SBarry Smith   aijcrl->nz   = Aij->nz + Bij->nz;
495a11e1b2SBarry Smith   aijcrl->m    = A->rmap->n;
505a11e1b2SBarry Smith   aijcrl->rmax = rmax;
512205254eSKarl Rupp 
529566063dSJacob Faibussowitsch   PetscCall(PetscFree2(aijcrl->acols, aijcrl->icols));
539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(rmax * m, &aijcrl->acols, rmax * m, &aijcrl->icols));
545a11e1b2SBarry Smith   acols = aijcrl->acols;
555a11e1b2SBarry Smith   icols = aijcrl->icols;
565fa1c062SBarry Smith   for (i = 0; i < m; i++) {
571472f72bSBarry Smith     for (j = 0; j < ailen[i]; j++) {
585fa1c062SBarry Smith       acols[j * m + i] = *aa++;
595fa1c062SBarry Smith       icols[j * m + i] = *aj++;
605fa1c062SBarry Smith     }
611472f72bSBarry Smith     for (; j < ailen[i] + bilen[i]; j++) {
621472f72bSBarry Smith       acols[j * m + i] = *ba++;
6311285404SBarry Smith       icols[j * m + i] = nd + *bj++;
641472f72bSBarry Smith     }
655fa1c062SBarry Smith     for (; j < rmax; j++) { /* empty column entries */
665fa1c062SBarry Smith       acols[j * m + i] = 0.0;
675fa1c062SBarry Smith       icols[j * m + i] = (j) ? icols[(j - 1) * m + i] : 0; /* handle case where row is EMPTY */
685fa1c062SBarry Smith     }
695fa1c062SBarry Smith   }
709566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A, "Percentage of 0's introduced for vectorized multiply %g\n", 1.0 - ((double)(aijcrl->nz)) / ((double)(rmax * m))));
711472f72bSBarry Smith 
729566063dSJacob Faibussowitsch   PetscCall(PetscFree(aijcrl->array));
739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(a->B->cmap->n + nd, &array));
74483e0693SBarry Smith   /* xwork array is actually B->n+nd long, but we define xwork this length so can copy into it */
759566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&aijcrl->xwork));
769566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), 1, nd, PETSC_DECIDE, array, &aijcrl->xwork));
779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&aijcrl->fwork));
789566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, 1, a->B->cmap->n, array + nd, &aijcrl->fwork));
792205254eSKarl Rupp 
805a11e1b2SBarry Smith   aijcrl->array = array;
815a11e1b2SBarry Smith   aijcrl->xscat = a->Mvctx;
825fa1c062SBarry Smith   PetscFunctionReturn(0);
835fa1c062SBarry Smith }
845fa1c062SBarry Smith 
859371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_MPIAIJCRL(Mat A, MatAssemblyType mode) {
861472f72bSBarry Smith   Mat_MPIAIJ *a   = (Mat_MPIAIJ *)A->data;
871472f72bSBarry Smith   Mat_SeqAIJ *Aij = (Mat_SeqAIJ *)(a->A->data), *Bij = (Mat_SeqAIJ *)(a->A->data);
885fa1c062SBarry Smith 
895fa1c062SBarry Smith   PetscFunctionBegin;
901472f72bSBarry Smith   Aij->inode.use = PETSC_FALSE;
911472f72bSBarry Smith   Bij->inode.use = PETSC_FALSE;
922205254eSKarl Rupp 
939566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_MPIAIJ(A, mode));
944723c594SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
955fa1c062SBarry Smith 
961472f72bSBarry Smith   /* Now calculate the permutation and grouping information. */
979566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJCRL_create_aijcrl(A));
985fa1c062SBarry Smith   PetscFunctionReturn(0);
995fa1c062SBarry Smith }
1005fa1c062SBarry Smith 
1015a11e1b2SBarry Smith extern PetscErrorCode MatMult_AIJCRL(Mat, Vec, Vec);
1025a11e1b2SBarry Smith extern PetscErrorCode MatDuplicate_AIJCRL(Mat, MatDuplicateOption, Mat *);
1035fa1c062SBarry Smith 
1045a11e1b2SBarry Smith /* MatConvert_MPIAIJ_MPIAIJCRL converts a MPIAIJ matrix into a
1055a11e1b2SBarry Smith  * MPIAIJCRL matrix.  This routine is called by the MatCreate_MPIAIJCRL()
1061472f72bSBarry Smith  * routine, but can also be used to convert an assembled MPIAIJ matrix
1075a11e1b2SBarry Smith  * into a MPIAIJCRL one. */
108b2573a8aSBarry Smith 
1099371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJCRL(Mat A, MatType type, MatReuse reuse, Mat *newmat) {
1105fa1c062SBarry Smith   Mat         B = *newmat;
1115a11e1b2SBarry Smith   Mat_AIJCRL *aijcrl;
1125fa1c062SBarry Smith 
1135fa1c062SBarry Smith   PetscFunctionBegin;
11448a46eb9SPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &B));
1155fa1c062SBarry Smith 
116*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&aijcrl));
1175a11e1b2SBarry Smith   B->spptr = (void *)aijcrl;
1185fa1c062SBarry Smith 
11917667f90SBarry Smith   /* Set function pointers for methods that we inherit from AIJ but override. */
1205a11e1b2SBarry Smith   B->ops->duplicate   = MatDuplicate_AIJCRL;
1215a11e1b2SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_MPIAIJCRL;
1225a11e1b2SBarry Smith   B->ops->destroy     = MatDestroy_MPIAIJCRL;
1235a11e1b2SBarry Smith   B->ops->mult        = MatMult_AIJCRL;
1245fa1c062SBarry Smith 
1255fa1c062SBarry Smith   /* If A has already been assembled, compute the permutation. */
1261baa6e33SBarry Smith   if (A->assembled) PetscCall(MatMPIAIJCRL_create_aijcrl(B));
1279566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATMPIAIJCRL));
1285fa1c062SBarry Smith   *newmat = B;
1295fa1c062SBarry Smith   PetscFunctionReturn(0);
1305fa1c062SBarry Smith }
1315fa1c062SBarry Smith 
1325fa1c062SBarry Smith /*@C
13311a5261eSBarry Smith    MatCreateMPIAIJCRL - Creates a sparse matrix of type `MATMPIAIJCRL`.
13411a5261eSBarry Smith    This type inherits from `MATAIJ`, but stores some additional
1355fa1c062SBarry Smith    information that is used to allow better vectorization of
1365fa1c062SBarry Smith    the matrix-vector product. At the cost of increased storage, the AIJ formatted
1375fa1c062SBarry Smith    matrix can be copied to a format in which pieces of the matrix are
1385fa1c062SBarry Smith    stored in ELLPACK format, allowing the vectorized matrix multiply
1395fa1c062SBarry Smith    routine to use stride-1 memory accesses.  As with the AIJ type, it is
1405fa1c062SBarry Smith    important to preallocate matrix storage in order to get good assembly
1415fa1c062SBarry Smith    performance.
1425fa1c062SBarry Smith 
143d083f849SBarry Smith    Collective
1445fa1c062SBarry Smith 
1455fa1c062SBarry Smith    Input Parameters:
14611a5261eSBarry Smith +  comm - MPI communicator, set to `PETSC_COMM_SELF`
1475fa1c062SBarry Smith .  m - number of rows
1485fa1c062SBarry Smith .  n - number of columns
1495fa1c062SBarry Smith .  nz - number of nonzeros per row (same for all rows)
1505fa1c062SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
1510298fd71SBarry Smith          (possibly different for each row) or NULL
1525fa1c062SBarry Smith 
1535fa1c062SBarry Smith    Output Parameter:
1545fa1c062SBarry Smith .  A - the matrix
1555fa1c062SBarry Smith 
15611a5261eSBarry Smith    Note:
1575fa1c062SBarry Smith    If nnz is given then nz is ignored
1585fa1c062SBarry Smith 
1595fa1c062SBarry Smith    Level: intermediate
1605fa1c062SBarry Smith 
16160161072SBarry Smith .seealso: [Sparse Matrix Creation](sec_matsparse), `MATAIJ`, `MATAIJSELL`, `MATAIJPERM`, `MATAIJMKL`, `MatCreate()`, `MatCreateMPIAIJPERM()`, `MatSetValues()`
1625fa1c062SBarry Smith @*/
1639371c9d4SSatish Balay PetscErrorCode MatCreateMPIAIJCRL(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], PetscInt onz, const PetscInt onnz[], Mat *A) {
1645fa1c062SBarry Smith   PetscFunctionBegin;
1659566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
1669566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
1679566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATMPIAIJCRL));
1689566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation_MPIAIJ(*A, nz, (PetscInt *)nnz, onz, (PetscInt *)onnz));
1695fa1c062SBarry Smith   PetscFunctionReturn(0);
1705fa1c062SBarry Smith }
1715fa1c062SBarry Smith 
1729371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_MPIAIJCRL(Mat A) {
1735fa1c062SBarry Smith   PetscFunctionBegin;
1749566063dSJacob Faibussowitsch   PetscCall(MatSetType(A, MATMPIAIJ));
1759566063dSJacob Faibussowitsch   PetscCall(MatConvert_MPIAIJ_MPIAIJCRL(A, MATMPIAIJCRL, MAT_INPLACE_MATRIX, &A));
1765fa1c062SBarry Smith   PetscFunctionReturn(0);
1775fa1c062SBarry Smith }
178