xref: /petsc/src/mat/impls/aij/mpi/crl/mcrl.c (revision 1baa6e3354bfe224b33a0c158f482508792a8a6e)
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 
185a11e1b2SBarry Smith PetscErrorCode MatDestroy_MPIAIJCRL(Mat A)
195fa1c062SBarry Smith {
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));
335fa1c062SBarry Smith   PetscFunctionReturn(0);
345fa1c062SBarry Smith }
355fa1c062SBarry Smith 
3696b95a6bSBarry Smith PetscErrorCode MatMPIAIJCRL_create_aijcrl(Mat A)
375fa1c062SBarry Smith {
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 */
491472f72bSBarry Smith   for (i=0; i<m; i++) {
501472f72bSBarry Smith     rmax = PetscMax(rmax,ailen[i]+bilen[i]);
511472f72bSBarry Smith   }
525a11e1b2SBarry Smith   aijcrl->nz   = Aij->nz+Bij->nz;
535a11e1b2SBarry Smith   aijcrl->m    = A->rmap->n;
545a11e1b2SBarry Smith   aijcrl->rmax = rmax;
552205254eSKarl Rupp 
569566063dSJacob Faibussowitsch   PetscCall(PetscFree2(aijcrl->acols,aijcrl->icols));
579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(rmax*m,&aijcrl->acols,rmax*m,&aijcrl->icols));
585a11e1b2SBarry Smith   acols = aijcrl->acols;
595a11e1b2SBarry Smith   icols = aijcrl->icols;
605fa1c062SBarry Smith   for (i=0; i<m; i++) {
611472f72bSBarry Smith     for (j=0; j<ailen[i]; j++) {
625fa1c062SBarry Smith       acols[j*m+i] = *aa++;
635fa1c062SBarry Smith       icols[j*m+i] = *aj++;
645fa1c062SBarry Smith     }
651472f72bSBarry Smith     for (; j<ailen[i]+bilen[i]; j++) {
661472f72bSBarry Smith       acols[j*m+i] = *ba++;
6711285404SBarry Smith       icols[j*m+i] = nd + *bj++;
681472f72bSBarry Smith     }
695fa1c062SBarry Smith     for (; j<rmax; j++) { /* empty column entries */
705fa1c062SBarry Smith       acols[j*m+i] = 0.0;
715fa1c062SBarry Smith       icols[j*m+i] = (j) ? icols[(j-1)*m+i] : 0;  /* handle case where row is EMPTY */
725fa1c062SBarry Smith     }
735fa1c062SBarry Smith   }
749566063dSJacob Faibussowitsch   PetscCall(PetscInfo(A,"Percentage of 0's introduced for vectorized multiply %g\n",1.0-((double)(aijcrl->nz))/((double)(rmax*m))));
751472f72bSBarry Smith 
769566063dSJacob Faibussowitsch   PetscCall(PetscFree(aijcrl->array));
779566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(a->B->cmap->n+nd,&array));
78483e0693SBarry Smith   /* xwork array is actually B->n+nd long, but we define xwork this length so can copy into it */
799566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&aijcrl->xwork));
809566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,nd,PETSC_DECIDE,array,&aijcrl->xwork));
819566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&aijcrl->fwork));
829566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->B->cmap->n,array+nd,&aijcrl->fwork));
832205254eSKarl Rupp 
845a11e1b2SBarry Smith   aijcrl->array = array;
855a11e1b2SBarry Smith   aijcrl->xscat = a->Mvctx;
865fa1c062SBarry Smith   PetscFunctionReturn(0);
875fa1c062SBarry Smith }
885fa1c062SBarry Smith 
895a11e1b2SBarry Smith PetscErrorCode MatAssemblyEnd_MPIAIJCRL(Mat A, MatAssemblyType mode)
905fa1c062SBarry Smith {
911472f72bSBarry Smith   Mat_MPIAIJ     *a   = (Mat_MPIAIJ*)A->data;
921472f72bSBarry Smith   Mat_SeqAIJ     *Aij = (Mat_SeqAIJ*)(a->A->data), *Bij = (Mat_SeqAIJ*)(a->A->data);
935fa1c062SBarry Smith 
945fa1c062SBarry Smith   PetscFunctionBegin;
951472f72bSBarry Smith   Aij->inode.use = PETSC_FALSE;
961472f72bSBarry Smith   Bij->inode.use = PETSC_FALSE;
972205254eSKarl Rupp 
989566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_MPIAIJ(A,mode));
994723c594SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1005fa1c062SBarry Smith 
1011472f72bSBarry Smith   /* Now calculate the permutation and grouping information. */
1029566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJCRL_create_aijcrl(A));
1035fa1c062SBarry Smith   PetscFunctionReturn(0);
1045fa1c062SBarry Smith }
1055fa1c062SBarry Smith 
1065a11e1b2SBarry Smith extern PetscErrorCode MatMult_AIJCRL(Mat,Vec,Vec);
1075a11e1b2SBarry Smith extern PetscErrorCode MatDuplicate_AIJCRL(Mat,MatDuplicateOption,Mat*);
1085fa1c062SBarry Smith 
1095a11e1b2SBarry Smith /* MatConvert_MPIAIJ_MPIAIJCRL converts a MPIAIJ matrix into a
1105a11e1b2SBarry Smith  * MPIAIJCRL matrix.  This routine is called by the MatCreate_MPIAIJCRL()
1111472f72bSBarry Smith  * routine, but can also be used to convert an assembled MPIAIJ matrix
1125a11e1b2SBarry Smith  * into a MPIAIJCRL one. */
113b2573a8aSBarry Smith 
114cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJCRL(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1155fa1c062SBarry Smith {
1165fa1c062SBarry Smith   Mat            B = *newmat;
1175a11e1b2SBarry Smith   Mat_AIJCRL     *aijcrl;
1185fa1c062SBarry Smith 
1195fa1c062SBarry Smith   PetscFunctionBegin;
1205fa1c062SBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
1219566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&B));
1225fa1c062SBarry Smith   }
1235fa1c062SBarry Smith 
1249566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&aijcrl));
1255a11e1b2SBarry Smith   B->spptr = (void*) aijcrl;
1265fa1c062SBarry Smith 
12717667f90SBarry Smith   /* Set function pointers for methods that we inherit from AIJ but override. */
1285a11e1b2SBarry Smith   B->ops->duplicate   = MatDuplicate_AIJCRL;
1295a11e1b2SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_MPIAIJCRL;
1305a11e1b2SBarry Smith   B->ops->destroy     = MatDestroy_MPIAIJCRL;
1315a11e1b2SBarry Smith   B->ops->mult        = MatMult_AIJCRL;
1325fa1c062SBarry Smith 
1335fa1c062SBarry Smith   /* If A has already been assembled, compute the permutation. */
134*1baa6e33SBarry Smith   if (A->assembled) PetscCall(MatMPIAIJCRL_create_aijcrl(B));
1359566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATMPIAIJCRL));
1365fa1c062SBarry Smith   *newmat = B;
1375fa1c062SBarry Smith   PetscFunctionReturn(0);
1385fa1c062SBarry Smith }
1395fa1c062SBarry Smith 
1405fa1c062SBarry Smith /*@C
1415a11e1b2SBarry Smith    MatCreateMPIAIJCRL - Creates a sparse matrix of type MPIAIJCRL.
1425fa1c062SBarry Smith    This type inherits from AIJ, but stores some additional
1435fa1c062SBarry Smith    information that is used to allow better vectorization of
1445fa1c062SBarry Smith    the matrix-vector product. At the cost of increased storage, the AIJ formatted
1455fa1c062SBarry Smith    matrix can be copied to a format in which pieces of the matrix are
1465fa1c062SBarry Smith    stored in ELLPACK format, allowing the vectorized matrix multiply
1475fa1c062SBarry Smith    routine to use stride-1 memory accesses.  As with the AIJ type, it is
1485fa1c062SBarry Smith    important to preallocate matrix storage in order to get good assembly
1495fa1c062SBarry Smith    performance.
1505fa1c062SBarry Smith 
151d083f849SBarry Smith    Collective
1525fa1c062SBarry Smith 
1535fa1c062SBarry Smith    Input Parameters:
1545fa1c062SBarry Smith +  comm - MPI communicator, set to PETSC_COMM_SELF
1555fa1c062SBarry Smith .  m - number of rows
1565fa1c062SBarry Smith .  n - number of columns
1575fa1c062SBarry Smith .  nz - number of nonzeros per row (same for all rows)
1585fa1c062SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
1590298fd71SBarry Smith          (possibly different for each row) or NULL
1605fa1c062SBarry Smith 
1615fa1c062SBarry Smith    Output Parameter:
1625fa1c062SBarry Smith .  A - the matrix
1635fa1c062SBarry Smith 
1645fa1c062SBarry Smith    Notes:
1655fa1c062SBarry Smith    If nnz is given then nz is ignored
1665fa1c062SBarry Smith 
1675fa1c062SBarry Smith    Level: intermediate
1685fa1c062SBarry Smith 
169db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateMPIAIJPERM()`, `MatSetValues()`
1705fa1c062SBarry Smith @*/
1717087cfbeSBarry Smith PetscErrorCode  MatCreateMPIAIJCRL(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],PetscInt onz,const PetscInt onnz[],Mat *A)
1725fa1c062SBarry Smith {
1735fa1c062SBarry Smith   PetscFunctionBegin;
1749566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,A));
1759566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A,m,n,m,n));
1769566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A,MATMPIAIJCRL));
1779566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation_MPIAIJ(*A,nz,(PetscInt*)nnz,onz,(PetscInt*)onnz));
1785fa1c062SBarry Smith   PetscFunctionReturn(0);
1795fa1c062SBarry Smith }
1805fa1c062SBarry Smith 
1818cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_MPIAIJCRL(Mat A)
1825fa1c062SBarry Smith {
1835fa1c062SBarry Smith   PetscFunctionBegin;
1849566063dSJacob Faibussowitsch   PetscCall(MatSetType(A,MATMPIAIJ));
1859566063dSJacob Faibussowitsch   PetscCall(MatConvert_MPIAIJ_MPIAIJCRL(A,MATMPIAIJCRL,MAT_INPLACE_MATRIX,&A));
1865fa1c062SBarry Smith   PetscFunctionReturn(0);
1875fa1c062SBarry Smith }
188