xref: /petsc/src/mat/impls/aij/mpi/crl/mcrl.c (revision 362febeeeb69b91ebadcb4b2dc0a22cb6dfc4097)
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 {
205fa1c062SBarry Smith   PetscErrorCode ierr;
215a11e1b2SBarry Smith   Mat_AIJCRL     *aijcrl = (Mat_AIJCRL*) A->spptr;
225fa1c062SBarry Smith 
23*362febeeSStefano Zampini   PetscFunctionBegin;
24bf0cc555SLisandro Dalcin   if (aijcrl) {
255a11e1b2SBarry Smith     ierr = PetscFree2(aijcrl->acols,aijcrl->icols);CHKERRQ(ierr);
266bf464f9SBarry Smith     ierr = VecDestroy(&aijcrl->fwork);CHKERRQ(ierr);
276bf464f9SBarry Smith     ierr = VecDestroy(&aijcrl->xwork);CHKERRQ(ierr);
285a11e1b2SBarry Smith     ierr = PetscFree(aijcrl->array);CHKERRQ(ierr);
29bf0cc555SLisandro Dalcin   }
30c31cb41cSBarry Smith   ierr = PetscFree(A->spptr);CHKERRQ(ierr);
315fa1c062SBarry Smith 
321472f72bSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A, MATMPIAIJ);CHKERRQ(ierr);
334723c594SBarry Smith   ierr = MatDestroy_MPIAIJ(A);CHKERRQ(ierr);
345fa1c062SBarry Smith   PetscFunctionReturn(0);
355fa1c062SBarry Smith }
365fa1c062SBarry Smith 
3796b95a6bSBarry Smith PetscErrorCode MatMPIAIJCRL_create_aijcrl(Mat A)
385fa1c062SBarry Smith {
391472f72bSBarry Smith   Mat_MPIAIJ     *a      = (Mat_MPIAIJ*)(A)->data;
4011285404SBarry Smith   Mat_SeqAIJ     *Aij    = (Mat_SeqAIJ*)(a->A->data), *Bij = (Mat_SeqAIJ*)(a->B->data);
415a11e1b2SBarry Smith   Mat_AIJCRL     *aijcrl = (Mat_AIJCRL*) A->spptr;
42d0f46423SBarry Smith   PetscInt       m       = A->rmap->n; /* Number of rows in the matrix. */
43d0f46423SBarry Smith   PetscInt       nd      = a->A->cmap->n; /* number of columns in diagonal portion */
441472f72bSBarry Smith   PetscInt       *aj     = Aij->j,*bj = Bij->j; /* From the CSR representation; points to the beginning  of each row. */
451472f72bSBarry Smith   PetscInt       i, j,rmax = 0,*icols, *ailen = Aij->ilen, *bilen = Bij->ilen;
466873f782SBarry Smith   PetscScalar    *aa = Aij->a,*ba = Bij->a,*acols,*array;
475fa1c062SBarry Smith   PetscErrorCode ierr;
485fa1c062SBarry Smith 
495fa1c062SBarry Smith   PetscFunctionBegin;
501472f72bSBarry Smith   /* determine the row with the most columns */
511472f72bSBarry Smith   for (i=0; i<m; i++) {
521472f72bSBarry Smith     rmax = PetscMax(rmax,ailen[i]+bilen[i]);
531472f72bSBarry Smith   }
545a11e1b2SBarry Smith   aijcrl->nz   = Aij->nz+Bij->nz;
555a11e1b2SBarry Smith   aijcrl->m    = A->rmap->n;
565a11e1b2SBarry Smith   aijcrl->rmax = rmax;
572205254eSKarl Rupp 
585a11e1b2SBarry Smith   ierr  = PetscFree2(aijcrl->acols,aijcrl->icols);CHKERRQ(ierr);
59dcca6d9dSJed Brown   ierr  = PetscMalloc2(rmax*m,&aijcrl->acols,rmax*m,&aijcrl->icols);CHKERRQ(ierr);
605a11e1b2SBarry Smith   acols = aijcrl->acols;
615a11e1b2SBarry Smith   icols = aijcrl->icols;
625fa1c062SBarry Smith   for (i=0; i<m; i++) {
631472f72bSBarry Smith     for (j=0; j<ailen[i]; j++) {
645fa1c062SBarry Smith       acols[j*m+i] = *aa++;
655fa1c062SBarry Smith       icols[j*m+i] = *aj++;
665fa1c062SBarry Smith     }
671472f72bSBarry Smith     for (; j<ailen[i]+bilen[i]; j++) {
681472f72bSBarry Smith       acols[j*m+i] = *ba++;
6911285404SBarry Smith       icols[j*m+i] = nd + *bj++;
701472f72bSBarry Smith     }
715fa1c062SBarry Smith     for (; j<rmax; j++) { /* empty column entries */
725fa1c062SBarry Smith       acols[j*m+i] = 0.0;
735fa1c062SBarry Smith       icols[j*m+i] = (j) ? icols[(j-1)*m+i] : 0;  /* handle case where row is EMPTY */
745fa1c062SBarry Smith     }
755fa1c062SBarry Smith   }
76a2ea699eSBarry Smith   ierr = PetscInfo1(A,"Percentage of 0's introduced for vectorized multiply %g\n",1.0-((double)(aijcrl->nz))/((double)(rmax*m)));CHKERRQ(ierr);
771472f72bSBarry Smith 
785a11e1b2SBarry Smith   ierr = PetscFree(aijcrl->array);CHKERRQ(ierr);
79854ce69bSBarry Smith   ierr = PetscMalloc1(a->B->cmap->n+nd,&array);CHKERRQ(ierr);
80483e0693SBarry Smith   /* xwork array is actually B->n+nd long, but we define xwork this length so can copy into it */
816bf464f9SBarry Smith   ierr = VecDestroy(&aijcrl->xwork);CHKERRQ(ierr);
82ce94432eSBarry Smith   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,nd,PETSC_DECIDE,array,&aijcrl->xwork);CHKERRQ(ierr);
836bf464f9SBarry Smith   ierr = VecDestroy(&aijcrl->fwork);CHKERRQ(ierr);
84778a2246SBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,a->B->cmap->n,array+nd,&aijcrl->fwork);CHKERRQ(ierr);
852205254eSKarl Rupp 
865a11e1b2SBarry Smith   aijcrl->array = array;
875a11e1b2SBarry Smith   aijcrl->xscat = a->Mvctx;
885fa1c062SBarry Smith   PetscFunctionReturn(0);
895fa1c062SBarry Smith }
905fa1c062SBarry Smith 
915a11e1b2SBarry Smith PetscErrorCode MatAssemblyEnd_MPIAIJCRL(Mat A, MatAssemblyType mode)
925fa1c062SBarry Smith {
935fa1c062SBarry Smith   PetscErrorCode ierr;
941472f72bSBarry Smith   Mat_MPIAIJ     *a   = (Mat_MPIAIJ*)A->data;
951472f72bSBarry Smith   Mat_SeqAIJ     *Aij = (Mat_SeqAIJ*)(a->A->data), *Bij = (Mat_SeqAIJ*)(a->A->data);
965fa1c062SBarry Smith 
975fa1c062SBarry Smith   PetscFunctionBegin;
981472f72bSBarry Smith   Aij->inode.use = PETSC_FALSE;
991472f72bSBarry Smith   Bij->inode.use = PETSC_FALSE;
1002205254eSKarl Rupp 
1014723c594SBarry Smith   ierr = MatAssemblyEnd_MPIAIJ(A,mode);CHKERRQ(ierr);
1024723c594SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1035fa1c062SBarry Smith 
1041472f72bSBarry Smith   /* Now calculate the permutation and grouping information. */
10596b95a6bSBarry Smith   ierr = MatMPIAIJCRL_create_aijcrl(A);CHKERRQ(ierr);
1065fa1c062SBarry Smith   PetscFunctionReturn(0);
1075fa1c062SBarry Smith }
1085fa1c062SBarry Smith 
1095a11e1b2SBarry Smith extern PetscErrorCode MatMult_AIJCRL(Mat,Vec,Vec);
1105a11e1b2SBarry Smith extern PetscErrorCode MatDuplicate_AIJCRL(Mat,MatDuplicateOption,Mat*);
1115fa1c062SBarry Smith 
1125a11e1b2SBarry Smith /* MatConvert_MPIAIJ_MPIAIJCRL converts a MPIAIJ matrix into a
1135a11e1b2SBarry Smith  * MPIAIJCRL matrix.  This routine is called by the MatCreate_MPIAIJCRL()
1141472f72bSBarry Smith  * routine, but can also be used to convert an assembled MPIAIJ matrix
1155a11e1b2SBarry Smith  * into a MPIAIJCRL one. */
116b2573a8aSBarry Smith 
117cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJCRL(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1185fa1c062SBarry Smith {
1195fa1c062SBarry Smith   PetscErrorCode ierr;
1205fa1c062SBarry Smith   Mat            B = *newmat;
1215a11e1b2SBarry Smith   Mat_AIJCRL     *aijcrl;
1225fa1c062SBarry Smith 
1235fa1c062SBarry Smith   PetscFunctionBegin;
1245fa1c062SBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
1255fa1c062SBarry Smith     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
1265fa1c062SBarry Smith   }
1275fa1c062SBarry Smith 
128b00a9115SJed Brown   ierr     = PetscNewLog(B,&aijcrl);CHKERRQ(ierr);
1295a11e1b2SBarry Smith   B->spptr = (void*) aijcrl;
1305fa1c062SBarry Smith 
13117667f90SBarry Smith   /* Set function pointers for methods that we inherit from AIJ but override. */
1325a11e1b2SBarry Smith   B->ops->duplicate   = MatDuplicate_AIJCRL;
1335a11e1b2SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_MPIAIJCRL;
1345a11e1b2SBarry Smith   B->ops->destroy     = MatDestroy_MPIAIJCRL;
1355a11e1b2SBarry Smith   B->ops->mult        = MatMult_AIJCRL;
1365fa1c062SBarry Smith 
1375fa1c062SBarry Smith   /* If A has already been assembled, compute the permutation. */
1384eeb8337SBarry Smith   if (A->assembled) {
13996b95a6bSBarry Smith     ierr = MatMPIAIJCRL_create_aijcrl(B);CHKERRQ(ierr);
1405fa1c062SBarry Smith   }
1415a11e1b2SBarry Smith   ierr    = PetscObjectChangeTypeName((PetscObject)B,MATMPIAIJCRL);CHKERRQ(ierr);
1425fa1c062SBarry Smith   *newmat = B;
1435fa1c062SBarry Smith   PetscFunctionReturn(0);
1445fa1c062SBarry Smith }
1455fa1c062SBarry Smith 
1465fa1c062SBarry Smith /*@C
1475a11e1b2SBarry Smith    MatCreateMPIAIJCRL - Creates a sparse matrix of type MPIAIJCRL.
1485fa1c062SBarry Smith    This type inherits from AIJ, but stores some additional
1495fa1c062SBarry Smith    information that is used to allow better vectorization of
1505fa1c062SBarry Smith    the matrix-vector product. At the cost of increased storage, the AIJ formatted
1515fa1c062SBarry Smith    matrix can be copied to a format in which pieces of the matrix are
1525fa1c062SBarry Smith    stored in ELLPACK format, allowing the vectorized matrix multiply
1535fa1c062SBarry Smith    routine to use stride-1 memory accesses.  As with the AIJ type, it is
1545fa1c062SBarry Smith    important to preallocate matrix storage in order to get good assembly
1555fa1c062SBarry Smith    performance.
1565fa1c062SBarry Smith 
157d083f849SBarry Smith    Collective
1585fa1c062SBarry Smith 
1595fa1c062SBarry Smith    Input Parameters:
1605fa1c062SBarry Smith +  comm - MPI communicator, set to PETSC_COMM_SELF
1615fa1c062SBarry Smith .  m - number of rows
1625fa1c062SBarry Smith .  n - number of columns
1635fa1c062SBarry Smith .  nz - number of nonzeros per row (same for all rows)
1645fa1c062SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
1650298fd71SBarry Smith          (possibly different for each row) or NULL
1665fa1c062SBarry Smith 
1675fa1c062SBarry Smith    Output Parameter:
1685fa1c062SBarry Smith .  A - the matrix
1695fa1c062SBarry Smith 
1705fa1c062SBarry Smith    Notes:
1715fa1c062SBarry Smith    If nnz is given then nz is ignored
1725fa1c062SBarry Smith 
1735fa1c062SBarry Smith    Level: intermediate
1745fa1c062SBarry Smith 
1755a11e1b2SBarry Smith .seealso: MatCreate(), MatCreateMPIAIJPERM(), MatSetValues()
1765fa1c062SBarry Smith @*/
1777087cfbeSBarry Smith PetscErrorCode  MatCreateMPIAIJCRL(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],PetscInt onz,const PetscInt onnz[],Mat *A)
1785fa1c062SBarry Smith {
1795fa1c062SBarry Smith   PetscErrorCode ierr;
1805fa1c062SBarry Smith 
1815fa1c062SBarry Smith   PetscFunctionBegin;
1825fa1c062SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1835fa1c062SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
1845a11e1b2SBarry Smith   ierr = MatSetType(*A,MATMPIAIJCRL);CHKERRQ(ierr);
1851472f72bSBarry Smith   ierr = MatMPIAIJSetPreallocation_MPIAIJ(*A,nz,(PetscInt*)nnz,onz,(PetscInt*)onnz);CHKERRQ(ierr);
1865fa1c062SBarry Smith   PetscFunctionReturn(0);
1875fa1c062SBarry Smith }
1885fa1c062SBarry Smith 
1898cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_MPIAIJCRL(Mat A)
1905fa1c062SBarry Smith {
1915fa1c062SBarry Smith   PetscErrorCode ierr;
1925fa1c062SBarry Smith 
1935fa1c062SBarry Smith   PetscFunctionBegin;
1941472f72bSBarry Smith   ierr = MatSetType(A,MATMPIAIJ);CHKERRQ(ierr);
195511c6705SHong Zhang   ierr = MatConvert_MPIAIJ_MPIAIJCRL(A,MATMPIAIJCRL,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
1965fa1c062SBarry Smith   PetscFunctionReturn(0);
1975fa1c062SBarry Smith }
1985fa1c062SBarry Smith 
199