xref: /petsc/src/mat/impls/aij/mpi/crl/mcrl.c (revision 899cda47322a0d0eb8e2428039961ef470104e3e)
15fa1c062SBarry Smith #define PETSCMAT_DLL
25fa1c062SBarry Smith 
35fa1c062SBarry Smith /*
41472f72bSBarry Smith   Defines a matrix-vector product for the MATMPIAIJCRL matrix class.
51472f72bSBarry Smith   This class is derived from the MATMPIAIJ class and retains the
65fa1c062SBarry Smith   compressed row storage (aka Yale sparse matrix format) but augments
75fa1c062SBarry Smith   it with a column oriented storage that is more efficient for
85fa1c062SBarry Smith   matrix vector products on Vector machines.
95fa1c062SBarry Smith 
105fa1c062SBarry Smith   CRL stands for constant row length (that is the same number of columns
115fa1c062SBarry Smith   is kept (padded with zeros) for each row of the sparse matrix.
121472f72bSBarry Smith 
131472f72bSBarry Smith    See src/mat/impls/aij/seq/crl/crl.c for the sequential version
145fa1c062SBarry Smith */
155fa1c062SBarry Smith 
161472f72bSBarry Smith #include "src/mat/impls/aij/mpi/mpiaij.h"
171472f72bSBarry Smith #include "src/mat/impls/aij/seq/crl/crl.h"
185fa1c062SBarry Smith 
195fa1c062SBarry Smith #undef __FUNCT__
201472f72bSBarry Smith #define __FUNCT__ "MatDestroy_MPICRL"
211472f72bSBarry Smith PetscErrorCode MatDestroy_MPICRL(Mat A)
225fa1c062SBarry Smith {
235fa1c062SBarry Smith   PetscErrorCode ierr;
241472f72bSBarry Smith   Mat_CRL        *crl = (Mat_CRL *) A->spptr;
255fa1c062SBarry Smith 
261472f72bSBarry Smith   /* We are going to convert A back into a MPIAIJ matrix, since we are
271472f72bSBarry Smith    * eventually going to use MatDestroy_MPIAIJ() to destroy everything
285fa1c062SBarry Smith    * that is not specific to CRL.
295fa1c062SBarry Smith    * In preparation for this, reset the operations pointers in A to
301472f72bSBarry Smith    * their MPIAIJ versions. */
311472f72bSBarry Smith   A->ops->assemblyend = crl->AssemblyEnd;
321472f72bSBarry Smith   A->ops->destroy     = crl->MatDestroy;
331472f72bSBarry Smith   A->ops->duplicate   = crl->MatDuplicate;
345fa1c062SBarry Smith 
351472f72bSBarry Smith   /* Free everything in the Mat_CRL data structure. */
365fa1c062SBarry Smith   if (crl->icols) {
375fa1c062SBarry Smith     ierr = PetscFree2(crl->acols,crl->icols);CHKERRQ(ierr);
385fa1c062SBarry Smith   }
399222b4acSBarry Smith   if (crl->fwork) {
409222b4acSBarry Smith     ierr = VecDestroy(crl->fwork);CHKERRQ(ierr);
419222b4acSBarry Smith   }
429222b4acSBarry Smith   if (crl->xwork) {
439222b4acSBarry Smith     ierr = VecDestroy(crl->xwork);CHKERRQ(ierr);
449222b4acSBarry Smith   }
459222b4acSBarry Smith   if (crl->array) {
469222b4acSBarry Smith     ierr = PetscFree(crl->array);CHKERRQ(ierr);
479222b4acSBarry Smith   }
481472f72bSBarry Smith   /* Free the Mat_CRL struct itself. */
495fa1c062SBarry Smith   ierr = PetscFree(crl);CHKERRQ(ierr);
505fa1c062SBarry Smith 
511472f72bSBarry Smith   /* Change the type of A back to MPIAIJ and use MatDestroy_MPIAIJ()
525fa1c062SBarry Smith    * to destroy everything that remains. */
531472f72bSBarry Smith   ierr = PetscObjectChangeTypeName( (PetscObject)A, MATMPIAIJ);CHKERRQ(ierr);
545fa1c062SBarry Smith   /* Note that I don't call MatSetType().  I believe this is because that
555fa1c062SBarry Smith    * is only to be called when *building* a matrix. */
565fa1c062SBarry Smith   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
575fa1c062SBarry Smith   PetscFunctionReturn(0);
585fa1c062SBarry Smith }
595fa1c062SBarry Smith 
605fa1c062SBarry Smith #undef __FUNCT__
611472f72bSBarry Smith #define __FUNCT__ "MPICRL_create_crl"
621472f72bSBarry Smith PetscErrorCode MPICRL_create_crl(Mat A)
635fa1c062SBarry Smith {
641472f72bSBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ *)(A)->data;
6511285404SBarry Smith   Mat_SeqAIJ     *Aij = (Mat_SeqAIJ*)(a->A->data), *Bij = (Mat_SeqAIJ*)(a->B->data);
661472f72bSBarry Smith   Mat_CRL        *crl = (Mat_CRL*) A->spptr;
67*899cda47SBarry Smith   PetscInt       m = A->rmap.n;  /* Number of rows in the matrix. */
68*899cda47SBarry Smith   PetscInt       nd = a->A->cmap.n; /* number of columns in diagonal portion */
691472f72bSBarry Smith   PetscInt       *aj = Aij->j,*bj = Bij->j;  /* From the CSR representation; points to the beginning  of each row. */
701472f72bSBarry Smith   PetscInt       i, j,rmax = 0,*icols, *ailen = Aij->ilen, *bilen = Bij->ilen;
716873f782SBarry Smith   PetscScalar    *aa = Aij->a,*ba = Bij->a,*acols,*array;
725fa1c062SBarry Smith   PetscErrorCode ierr;
735fa1c062SBarry Smith 
745fa1c062SBarry Smith   PetscFunctionBegin;
751472f72bSBarry Smith   /* determine the row with the most columns */
761472f72bSBarry Smith   for (i=0; i<m; i++) {
771472f72bSBarry Smith     rmax = PetscMax(rmax,ailen[i]+bilen[i]);
781472f72bSBarry Smith   }
791472f72bSBarry Smith   crl->nz   = Aij->nz+Bij->nz;
80*899cda47SBarry Smith   crl->m    = A->rmap.n;
811472f72bSBarry Smith   crl->rmax = rmax;
825fa1c062SBarry Smith   ierr  = PetscMalloc2(rmax*m,PetscScalar,&crl->acols,rmax*m,PetscInt,&crl->icols);CHKERRQ(ierr);
835fa1c062SBarry Smith   acols = crl->acols;
845fa1c062SBarry Smith   icols = crl->icols;
855fa1c062SBarry Smith   for (i=0; i<m; i++) {
861472f72bSBarry Smith     for (j=0; j<ailen[i]; j++) {
875fa1c062SBarry Smith       acols[j*m+i] = *aa++;
885fa1c062SBarry Smith       icols[j*m+i] = *aj++;
895fa1c062SBarry Smith     }
901472f72bSBarry Smith     for (;j<ailen[i]+bilen[i]; j++) {
911472f72bSBarry Smith       acols[j*m+i] = *ba++;
9211285404SBarry Smith       icols[j*m+i] = nd + *bj++;
931472f72bSBarry Smith     }
945fa1c062SBarry Smith     for (;j<rmax; j++) { /* empty column entries */
955fa1c062SBarry Smith       acols[j*m+i] = 0.0;
965fa1c062SBarry Smith       icols[j*m+i] = (j) ? icols[(j-1)*m+i] : 0;  /* handle case where row is EMPTY */
975fa1c062SBarry Smith     }
985fa1c062SBarry Smith   }
99ae15b995SBarry Smith   ierr = PetscInfo1(A,"Percentage of 0's introduced for vectorized multiply %g\n",1.0-((double)(crl->nz))/((double)(rmax*m)));
1001472f72bSBarry Smith 
101*899cda47SBarry Smith   ierr = PetscMalloc((a->B->cmap.n+nd)*sizeof(PetscScalar),&array);CHKERRQ(ierr);
102483e0693SBarry Smith   /* xwork array is actually B->n+nd long, but we define xwork this length so can copy into it */
10311285404SBarry Smith   ierr = VecCreateMPIWithArray(A->comm,nd,PETSC_DECIDE,array,&crl->xwork);CHKERRQ(ierr);
104*899cda47SBarry Smith   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,a->B->cmap.n,array+nd,&crl->fwork);CHKERRQ(ierr);
1059222b4acSBarry Smith   crl->array = array;
10611285404SBarry Smith   crl->xscat = a->Mvctx;
1075fa1c062SBarry Smith   PetscFunctionReturn(0);
1085fa1c062SBarry Smith }
1095fa1c062SBarry Smith 
1105fa1c062SBarry Smith #undef __FUNCT__
1111472f72bSBarry Smith #define __FUNCT__ "MatAssemblyEnd_MPICRL"
1121472f72bSBarry Smith PetscErrorCode MatAssemblyEnd_MPICRL(Mat A, MatAssemblyType mode)
1135fa1c062SBarry Smith {
1145fa1c062SBarry Smith   PetscErrorCode ierr;
1151472f72bSBarry Smith   Mat_CRL        *crl = (Mat_CRL*) A->spptr;
1161472f72bSBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
1171472f72bSBarry Smith   Mat_SeqAIJ     *Aij = (Mat_SeqAIJ*)(a->A->data), *Bij = (Mat_SeqAIJ*)(a->A->data);
1185fa1c062SBarry Smith 
1195fa1c062SBarry Smith   PetscFunctionBegin;
1201472f72bSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1215fa1c062SBarry Smith 
1221472f72bSBarry Smith   /* Since a MATMPICRL matrix is really just a MATMPIAIJ with some
1231472f72bSBarry Smith    * extra information, call the AssemblyEnd routine for a MATMPIAIJ.
1241472f72bSBarry Smith    * I'm not sure if this is the best way to do this, but it avoids
1251472f72bSBarry Smith    * a lot of code duplication.
1261472f72bSBarry Smith    * I also note that currently MATMPICRL doesn't know anything about
1271472f72bSBarry Smith    * the Mat_CompressedRow data structure that MPIAIJ now uses when there
1281472f72bSBarry Smith    * are many zero rows.  If the MPIAIJ assembly end routine decides to use
1291472f72bSBarry Smith    * this, this may break things.  (Don't know... haven't looked at it.) */
1301472f72bSBarry Smith   Aij->inode.use = PETSC_FALSE;
1311472f72bSBarry Smith   Bij->inode.use = PETSC_FALSE;
1321472f72bSBarry Smith   (*crl->AssemblyEnd)(A, mode);
1335fa1c062SBarry Smith 
1341472f72bSBarry Smith   /* Now calculate the permutation and grouping information. */
1351472f72bSBarry Smith   ierr = MPICRL_create_crl(A);CHKERRQ(ierr);
1365fa1c062SBarry Smith   PetscFunctionReturn(0);
1375fa1c062SBarry Smith }
1385fa1c062SBarry Smith 
1391472f72bSBarry Smith extern PetscErrorCode MatMult_CRL(Mat,Vec,Vec);
1401472f72bSBarry Smith extern PetscErrorCode MatDuplicate_CRL(Mat,MatDuplicateOption,Mat*);
1415fa1c062SBarry Smith 
1421472f72bSBarry Smith /* MatConvert_MPIAIJ_MPICRL converts a MPIAIJ matrix into a
1431472f72bSBarry Smith  * MPICRL matrix.  This routine is called by the MatCreate_MPICRL()
1441472f72bSBarry Smith  * routine, but can also be used to convert an assembled MPIAIJ matrix
1451472f72bSBarry Smith  * into a MPICRL one. */
1465fa1c062SBarry Smith EXTERN_C_BEGIN
1475fa1c062SBarry Smith #undef __FUNCT__
1481472f72bSBarry Smith #define __FUNCT__ "MatConvert_MPIAIJ_MPICRL"
1491472f72bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_MPIAIJ_MPICRL(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1505fa1c062SBarry Smith {
1511472f72bSBarry Smith   /* This routine is only called to convert to MATMPICRL
1521472f72bSBarry Smith    * from MATMPIAIJ, so we can ignore 'MatType Type'. */
1535fa1c062SBarry Smith   PetscErrorCode ierr;
1545fa1c062SBarry Smith   Mat            B = *newmat;
1551472f72bSBarry Smith   Mat_CRL        *crl;
1565fa1c062SBarry Smith 
1575fa1c062SBarry Smith   PetscFunctionBegin;
1585fa1c062SBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
1595fa1c062SBarry Smith     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
1605fa1c062SBarry Smith   }
1615fa1c062SBarry Smith 
1621472f72bSBarry Smith   ierr = PetscNew(Mat_CRL,&crl);CHKERRQ(ierr);
1635fa1c062SBarry Smith   B->spptr = (void *) crl;
1645fa1c062SBarry Smith 
1651472f72bSBarry Smith   /* Save a pointer to the original MPIAIJ assembly end routine, because we
1665fa1c062SBarry Smith    * will want to use it later in the CRL assembly end routine.
1671472f72bSBarry Smith    * Also, save a pointer to the original MPIAIJ Destroy routine, because we
1685fa1c062SBarry Smith    * will want to use it in the CRL destroy routine. */
1691472f72bSBarry Smith   crl->AssemblyEnd  = A->ops->assemblyend;
1701472f72bSBarry Smith   crl->MatDestroy   = A->ops->destroy;
1711472f72bSBarry Smith   crl->MatDuplicate = A->ops->duplicate;
1725fa1c062SBarry Smith 
1735fa1c062SBarry Smith   /* Set function pointers for methods that we inherit from AIJ but
1745fa1c062SBarry Smith    * override. */
1751472f72bSBarry Smith   B->ops->duplicate   = MatDuplicate_CRL;
1761472f72bSBarry Smith   B->ops->assemblyend = MatAssemblyEnd_MPICRL;
1771472f72bSBarry Smith   B->ops->destroy     = MatDestroy_MPICRL;
1781472f72bSBarry Smith   B->ops->mult        = MatMult_CRL;
1795fa1c062SBarry Smith 
1805fa1c062SBarry Smith   /* If A has already been assembled, compute the permutation. */
1815fa1c062SBarry Smith   if (A->assembled == PETSC_TRUE) {
1821472f72bSBarry Smith     ierr = MPICRL_create_crl(B);CHKERRQ(ierr);
1835fa1c062SBarry Smith   }
1841472f72bSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATMPICRL);CHKERRQ(ierr);
1855fa1c062SBarry Smith   *newmat = B;
1865fa1c062SBarry Smith   PetscFunctionReturn(0);
1875fa1c062SBarry Smith }
1885fa1c062SBarry Smith EXTERN_C_END
1895fa1c062SBarry Smith 
1905fa1c062SBarry Smith 
1915fa1c062SBarry Smith #undef __FUNCT__
1921472f72bSBarry Smith #define __FUNCT__ "MatCreateMPICRL"
1935fa1c062SBarry Smith /*@C
1941472f72bSBarry Smith    MatCreateMPICRL - Creates a sparse matrix of type MPICRL.
1955fa1c062SBarry Smith    This type inherits from AIJ, but stores some additional
1965fa1c062SBarry Smith    information that is used to allow better vectorization of
1975fa1c062SBarry Smith    the matrix-vector product. At the cost of increased storage, the AIJ formatted
1985fa1c062SBarry Smith    matrix can be copied to a format in which pieces of the matrix are
1995fa1c062SBarry Smith    stored in ELLPACK format, allowing the vectorized matrix multiply
2005fa1c062SBarry Smith    routine to use stride-1 memory accesses.  As with the AIJ type, it is
2015fa1c062SBarry Smith    important to preallocate matrix storage in order to get good assembly
2025fa1c062SBarry Smith    performance.
2035fa1c062SBarry Smith 
2045fa1c062SBarry Smith    Collective on MPI_Comm
2055fa1c062SBarry Smith 
2065fa1c062SBarry Smith    Input Parameters:
2075fa1c062SBarry Smith +  comm - MPI communicator, set to PETSC_COMM_SELF
2085fa1c062SBarry Smith .  m - number of rows
2095fa1c062SBarry Smith .  n - number of columns
2105fa1c062SBarry Smith .  nz - number of nonzeros per row (same for all rows)
2115fa1c062SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
2125fa1c062SBarry Smith          (possibly different for each row) or PETSC_NULL
2135fa1c062SBarry Smith 
2145fa1c062SBarry Smith    Output Parameter:
2155fa1c062SBarry Smith .  A - the matrix
2165fa1c062SBarry Smith 
2175fa1c062SBarry Smith    Notes:
2185fa1c062SBarry Smith    If nnz is given then nz is ignored
2195fa1c062SBarry Smith 
2205fa1c062SBarry Smith    Level: intermediate
2215fa1c062SBarry Smith 
2225fa1c062SBarry Smith .keywords: matrix, cray, sparse, parallel
2235fa1c062SBarry Smith 
2245fa1c062SBarry Smith .seealso: MatCreate(), MatCreateMPICSRPERM(), MatSetValues()
2255fa1c062SBarry Smith @*/
2261472f72bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreateMPICRL(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],PetscInt onz,const PetscInt onnz[],Mat *A)
2275fa1c062SBarry Smith {
2285fa1c062SBarry Smith   PetscErrorCode ierr;
2295fa1c062SBarry Smith 
2305fa1c062SBarry Smith   PetscFunctionBegin;
2315fa1c062SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2325fa1c062SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
2331472f72bSBarry Smith   ierr = MatSetType(*A,MATMPICRL);CHKERRQ(ierr);
2341472f72bSBarry Smith   ierr = MatMPIAIJSetPreallocation_MPIAIJ(*A,nz,(PetscInt*)nnz,onz,(PetscInt*)onnz);CHKERRQ(ierr);
2355fa1c062SBarry Smith   PetscFunctionReturn(0);
2365fa1c062SBarry Smith }
2375fa1c062SBarry Smith 
2385fa1c062SBarry Smith 
2395fa1c062SBarry Smith EXTERN_C_BEGIN
2405fa1c062SBarry Smith #undef __FUNCT__
2411472f72bSBarry Smith #define __FUNCT__ "MatCreate_MPICRL"
2421472f72bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_MPICRL(Mat A)
2435fa1c062SBarry Smith {
2445fa1c062SBarry Smith   PetscErrorCode ierr;
2455fa1c062SBarry Smith 
2465fa1c062SBarry Smith   PetscFunctionBegin;
2471472f72bSBarry Smith   /* Change the type name before calling MatSetType() to force proper construction of MPIAIJ
2481472f72bSBarry Smith      and MATMPICRL types. */
2491472f72bSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATMPICRL);CHKERRQ(ierr);
2501472f72bSBarry Smith   ierr = MatSetType(A,MATMPIAIJ);CHKERRQ(ierr);
2511472f72bSBarry Smith   ierr = MatConvert_MPIAIJ_MPICRL(A,MATMPICRL,MAT_REUSE_MATRIX,&A);CHKERRQ(ierr);
2525fa1c062SBarry Smith   PetscFunctionReturn(0);
2535fa1c062SBarry Smith }
2545fa1c062SBarry Smith EXTERN_C_END
2555fa1c062SBarry Smith 
256