xref: /petsc/src/mat/impls/aij/mpi/crl/mcrl.c (revision 1472f72bf2626bdee7ece57716cd133d1b2bac50)
15fa1c062SBarry Smith #define PETSCMAT_DLL
25fa1c062SBarry Smith 
35fa1c062SBarry Smith /*
4*1472f72bSBarry Smith   Defines a matrix-vector product for the MATMPIAIJCRL matrix class.
5*1472f72bSBarry 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.
12*1472f72bSBarry Smith 
13*1472f72bSBarry Smith    See src/mat/impls/aij/seq/crl/crl.c for the sequential version
145fa1c062SBarry Smith */
155fa1c062SBarry Smith 
16*1472f72bSBarry Smith #include "src/mat/impls/aij/mpi/mpiaij.h"
17*1472f72bSBarry Smith #include "src/mat/impls/aij/seq/crl/crl.h"
185fa1c062SBarry Smith 
195fa1c062SBarry Smith #undef __FUNCT__
20*1472f72bSBarry Smith #define __FUNCT__ "MatDestroy_MPICRL"
21*1472f72bSBarry Smith PetscErrorCode MatDestroy_MPICRL(Mat A)
225fa1c062SBarry Smith {
235fa1c062SBarry Smith   PetscErrorCode ierr;
24*1472f72bSBarry Smith   Mat_CRL        *crl = (Mat_CRL *) A->spptr;
255fa1c062SBarry Smith 
26*1472f72bSBarry Smith   /* We are going to convert A back into a MPIAIJ matrix, since we are
27*1472f72bSBarry 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
30*1472f72bSBarry Smith    * their MPIAIJ versions. */
31*1472f72bSBarry Smith   A->ops->assemblyend = crl->AssemblyEnd;
32*1472f72bSBarry Smith   A->ops->destroy     = crl->MatDestroy;
33*1472f72bSBarry Smith   A->ops->duplicate   = crl->MatDuplicate;
345fa1c062SBarry Smith 
35*1472f72bSBarry 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   }
39*1472f72bSBarry Smith   /* Free the Mat_CRL struct itself. */
405fa1c062SBarry Smith   ierr = PetscFree(crl);CHKERRQ(ierr);
415fa1c062SBarry Smith 
42*1472f72bSBarry Smith   /* Change the type of A back to MPIAIJ and use MatDestroy_MPIAIJ()
435fa1c062SBarry Smith    * to destroy everything that remains. */
44*1472f72bSBarry Smith   ierr = PetscObjectChangeTypeName( (PetscObject)A, MATMPIAIJ);CHKERRQ(ierr);
455fa1c062SBarry Smith   /* Note that I don't call MatSetType().  I believe this is because that
465fa1c062SBarry Smith    * is only to be called when *building* a matrix. */
475fa1c062SBarry Smith   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
485fa1c062SBarry Smith   PetscFunctionReturn(0);
495fa1c062SBarry Smith }
505fa1c062SBarry Smith 
515fa1c062SBarry Smith #undef __FUNCT__
52*1472f72bSBarry Smith #define __FUNCT__ "MPICRL_create_crl"
53*1472f72bSBarry Smith PetscErrorCode MPICRL_create_crl(Mat A)
545fa1c062SBarry Smith {
55*1472f72bSBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ *)(A)->data;
56*1472f72bSBarry Smith   Mat_SeqAIJ     *Aij = (Mat_SeqAIJ*)(a->A->data), *Bij = (Mat_SeqAIJ*)(a->A->data);
57*1472f72bSBarry Smith   Mat_CRL        *crl = (Mat_CRL*) A->spptr;
585fa1c062SBarry Smith   PetscInt       m = A->m;  /* Number of rows in the matrix. */
59*1472f72bSBarry Smith   PetscInt       *aj = Aij->j,*bj = Bij->j;  /* From the CSR representation; points to the beginning  of each row. */
60*1472f72bSBarry Smith   PetscInt       i, j,rmax = 0,*icols, *ailen = Aij->ilen, *bilen = Bij->ilen;
61*1472f72bSBarry Smith   PetscScalar    *aa = Aij->a,*ba = Bij->a,*acols;
625fa1c062SBarry Smith   PetscErrorCode ierr;
635fa1c062SBarry Smith 
645fa1c062SBarry Smith   PetscFunctionBegin;
65*1472f72bSBarry Smith   /* determine the row with the most columns */
66*1472f72bSBarry Smith   for (i=0; i<m; i++) {
67*1472f72bSBarry Smith     rmax = PetscMax(rmax,ailen[i]+bilen[i]);
68*1472f72bSBarry Smith   }
69*1472f72bSBarry Smith   crl->nz   = Aij->nz+Bij->nz;
70*1472f72bSBarry Smith   crl->m    = A->m;
71*1472f72bSBarry Smith   crl->rmax = rmax;
725fa1c062SBarry Smith   ierr  = PetscMalloc2(rmax*m,PetscScalar,&crl->acols,rmax*m,PetscInt,&crl->icols);CHKERRQ(ierr);
735fa1c062SBarry Smith   acols = crl->acols;
745fa1c062SBarry Smith   icols = crl->icols;
755fa1c062SBarry Smith   for (i=0; i<m; i++) {
76*1472f72bSBarry Smith     for (j=0; j<ailen[i]; j++) {
775fa1c062SBarry Smith       acols[j*m+i] = *aa++;
785fa1c062SBarry Smith       icols[j*m+i] = *aj++;
795fa1c062SBarry Smith     }
80*1472f72bSBarry Smith     for (;j<ailen[i]+bilen[i]; j++) {
81*1472f72bSBarry Smith       acols[j*m+i] = *ba++;
82*1472f72bSBarry Smith       icols[j*m+i] = *bj++;
83*1472f72bSBarry Smith     }
845fa1c062SBarry Smith     for (;j<rmax; j++) { /* empty column entries */
855fa1c062SBarry Smith       acols[j*m+i] = 0.0;
865fa1c062SBarry Smith       icols[j*m+i] = (j) ? icols[(j-1)*m+i] : 0;  /* handle case where row is EMPTY */
875fa1c062SBarry Smith     }
885fa1c062SBarry Smith   }
89*1472f72bSBarry Smith   ierr = PetscLogInfo((A,"MPICRL_create_crl: Percentage of 0's introduced for vectorized multiply %g\n",1.0-((double)(Bij->nz + Bij->nz))/((double)(rmax*m))));
90*1472f72bSBarry Smith 
91*1472f72bSBarry Smith   ierr = VecCreateSeqWithArray(A->comm,Aij->rmax,array,&crl->xwork);CHKERRQ(ierr);
92*1472f72bSBarry Smith 
935fa1c062SBarry Smith   PetscFunctionReturn(0);
945fa1c062SBarry Smith }
955fa1c062SBarry Smith 
965fa1c062SBarry Smith #undef __FUNCT__
97*1472f72bSBarry Smith #define __FUNCT__ "MatAssemblyEnd_MPICRL"
98*1472f72bSBarry Smith PetscErrorCode MatAssemblyEnd_MPICRL(Mat A, MatAssemblyType mode)
995fa1c062SBarry Smith {
1005fa1c062SBarry Smith   PetscErrorCode ierr;
101*1472f72bSBarry Smith   Mat_CRL        *crl = (Mat_CRL*) A->spptr;
102*1472f72bSBarry Smith   Mat_MPIAIJ     *a = (Mat_MPIAIJ*)A->data;
103*1472f72bSBarry Smith   Mat_SeqAIJ     *Aij = (Mat_SeqAIJ*)(a->A->data), *Bij = (Mat_SeqAIJ*)(a->A->data);
1045fa1c062SBarry Smith 
1055fa1c062SBarry Smith   PetscFunctionBegin;
106*1472f72bSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1075fa1c062SBarry Smith 
108*1472f72bSBarry Smith   /* Since a MATMPICRL matrix is really just a MATMPIAIJ with some
109*1472f72bSBarry Smith    * extra information, call the AssemblyEnd routine for a MATMPIAIJ.
110*1472f72bSBarry Smith    * I'm not sure if this is the best way to do this, but it avoids
111*1472f72bSBarry Smith    * a lot of code duplication.
112*1472f72bSBarry Smith    * I also note that currently MATMPICRL doesn't know anything about
113*1472f72bSBarry Smith    * the Mat_CompressedRow data structure that MPIAIJ now uses when there
114*1472f72bSBarry Smith    * are many zero rows.  If the MPIAIJ assembly end routine decides to use
115*1472f72bSBarry Smith    * this, this may break things.  (Don't know... haven't looked at it.) */
116*1472f72bSBarry Smith   Aij->inode.use = PETSC_FALSE;
117*1472f72bSBarry Smith   Bij->inode.use = PETSC_FALSE;
118*1472f72bSBarry Smith   (*crl->AssemblyEnd)(A, mode);
1195fa1c062SBarry Smith 
120*1472f72bSBarry Smith   /* Now calculate the permutation and grouping information. */
121*1472f72bSBarry Smith   ierr = MPICRL_create_crl(A);CHKERRQ(ierr);
1225fa1c062SBarry Smith   PetscFunctionReturn(0);
1235fa1c062SBarry Smith }
1245fa1c062SBarry Smith 
125*1472f72bSBarry Smith extern PetscErrorCode MatMult_CRL(Mat,Vec,Vec);
126*1472f72bSBarry Smith extern PetscErrorCode MatDuplicate_CRL(Mat,MatDuplicateOption,Mat*);
1275fa1c062SBarry Smith 
128*1472f72bSBarry Smith /* MatConvert_MPIAIJ_MPICRL converts a MPIAIJ matrix into a
129*1472f72bSBarry Smith  * MPICRL matrix.  This routine is called by the MatCreate_MPICRL()
130*1472f72bSBarry Smith  * routine, but can also be used to convert an assembled MPIAIJ matrix
131*1472f72bSBarry Smith  * into a MPICRL one. */
1325fa1c062SBarry Smith EXTERN_C_BEGIN
1335fa1c062SBarry Smith #undef __FUNCT__
134*1472f72bSBarry Smith #define __FUNCT__ "MatConvert_MPIAIJ_MPICRL"
135*1472f72bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_MPIAIJ_MPICRL(Mat A,MatType type,MatReuse reuse,Mat *newmat)
1365fa1c062SBarry Smith {
137*1472f72bSBarry Smith   /* This routine is only called to convert to MATMPICRL
138*1472f72bSBarry Smith    * from MATMPIAIJ, so we can ignore 'MatType Type'. */
1395fa1c062SBarry Smith   PetscErrorCode ierr;
1405fa1c062SBarry Smith   Mat            B = *newmat;
141*1472f72bSBarry Smith   Mat_CRL        *crl;
1425fa1c062SBarry Smith 
1435fa1c062SBarry Smith   PetscFunctionBegin;
1445fa1c062SBarry Smith   if (reuse == MAT_INITIAL_MATRIX) {
1455fa1c062SBarry Smith     ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
1465fa1c062SBarry Smith   }
1475fa1c062SBarry Smith 
148*1472f72bSBarry Smith   ierr = PetscNew(Mat_CRL,&crl);CHKERRQ(ierr);
1495fa1c062SBarry Smith   B->spptr = (void *) crl;
1505fa1c062SBarry Smith 
151*1472f72bSBarry Smith   /* Save a pointer to the original MPIAIJ assembly end routine, because we
1525fa1c062SBarry Smith    * will want to use it later in the CRL assembly end routine.
153*1472f72bSBarry Smith    * Also, save a pointer to the original MPIAIJ Destroy routine, because we
1545fa1c062SBarry Smith    * will want to use it in the CRL destroy routine. */
155*1472f72bSBarry Smith   crl->AssemblyEnd  = A->ops->assemblyend;
156*1472f72bSBarry Smith   crl->MatDestroy   = A->ops->destroy;
157*1472f72bSBarry Smith   crl->MatDuplicate = A->ops->duplicate;
1585fa1c062SBarry Smith 
1595fa1c062SBarry Smith   /* Set function pointers for methods that we inherit from AIJ but
1605fa1c062SBarry Smith    * override. */
161*1472f72bSBarry Smith   B->ops->duplicate   = MatDuplicate_CRL;
162*1472f72bSBarry Smith   B->ops->assemblyend = MatAssemblyEnd_MPICRL;
163*1472f72bSBarry Smith   B->ops->destroy     = MatDestroy_MPICRL;
164*1472f72bSBarry Smith   B->ops->mult        = MatMult_CRL;
1655fa1c062SBarry Smith 
1665fa1c062SBarry Smith   /* If A has already been assembled, compute the permutation. */
1675fa1c062SBarry Smith   if (A->assembled == PETSC_TRUE) {
168*1472f72bSBarry Smith     ierr = MPICRL_create_crl(B);CHKERRQ(ierr);
1695fa1c062SBarry Smith   }
170*1472f72bSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATMPICRL);CHKERRQ(ierr);
1715fa1c062SBarry Smith   *newmat = B;
1725fa1c062SBarry Smith   PetscFunctionReturn(0);
1735fa1c062SBarry Smith }
1745fa1c062SBarry Smith EXTERN_C_END
1755fa1c062SBarry Smith 
1765fa1c062SBarry Smith 
1775fa1c062SBarry Smith #undef __FUNCT__
178*1472f72bSBarry Smith #define __FUNCT__ "MatCreateMPICRL"
1795fa1c062SBarry Smith /*@C
180*1472f72bSBarry Smith    MatCreateMPICRL - Creates a sparse matrix of type MPICRL.
1815fa1c062SBarry Smith    This type inherits from AIJ, but stores some additional
1825fa1c062SBarry Smith    information that is used to allow better vectorization of
1835fa1c062SBarry Smith    the matrix-vector product. At the cost of increased storage, the AIJ formatted
1845fa1c062SBarry Smith    matrix can be copied to a format in which pieces of the matrix are
1855fa1c062SBarry Smith    stored in ELLPACK format, allowing the vectorized matrix multiply
1865fa1c062SBarry Smith    routine to use stride-1 memory accesses.  As with the AIJ type, it is
1875fa1c062SBarry Smith    important to preallocate matrix storage in order to get good assembly
1885fa1c062SBarry Smith    performance.
1895fa1c062SBarry Smith 
1905fa1c062SBarry Smith    Collective on MPI_Comm
1915fa1c062SBarry Smith 
1925fa1c062SBarry Smith    Input Parameters:
1935fa1c062SBarry Smith +  comm - MPI communicator, set to PETSC_COMM_SELF
1945fa1c062SBarry Smith .  m - number of rows
1955fa1c062SBarry Smith .  n - number of columns
1965fa1c062SBarry Smith .  nz - number of nonzeros per row (same for all rows)
1975fa1c062SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
1985fa1c062SBarry Smith          (possibly different for each row) or PETSC_NULL
1995fa1c062SBarry Smith 
2005fa1c062SBarry Smith    Output Parameter:
2015fa1c062SBarry Smith .  A - the matrix
2025fa1c062SBarry Smith 
2035fa1c062SBarry Smith    Notes:
2045fa1c062SBarry Smith    If nnz is given then nz is ignored
2055fa1c062SBarry Smith 
2065fa1c062SBarry Smith    Level: intermediate
2075fa1c062SBarry Smith 
2085fa1c062SBarry Smith .keywords: matrix, cray, sparse, parallel
2095fa1c062SBarry Smith 
2105fa1c062SBarry Smith .seealso: MatCreate(), MatCreateMPICSRPERM(), MatSetValues()
2115fa1c062SBarry Smith @*/
212*1472f72bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreateMPICRL(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],PetscInt onz,const PetscInt onnz[],Mat *A)
2135fa1c062SBarry Smith {
2145fa1c062SBarry Smith   PetscErrorCode ierr;
2155fa1c062SBarry Smith 
2165fa1c062SBarry Smith   PetscFunctionBegin;
2175fa1c062SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2185fa1c062SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
219*1472f72bSBarry Smith   ierr = MatSetType(*A,MATMPICRL);CHKERRQ(ierr);
220*1472f72bSBarry Smith   ierr = MatMPIAIJSetPreallocation_MPIAIJ(*A,nz,(PetscInt*)nnz,onz,(PetscInt*)onnz);CHKERRQ(ierr);
2215fa1c062SBarry Smith   PetscFunctionReturn(0);
2225fa1c062SBarry Smith }
2235fa1c062SBarry Smith 
2245fa1c062SBarry Smith 
2255fa1c062SBarry Smith EXTERN_C_BEGIN
2265fa1c062SBarry Smith #undef __FUNCT__
227*1472f72bSBarry Smith #define __FUNCT__ "MatCreate_MPICRL"
228*1472f72bSBarry Smith PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_MPICRL(Mat A)
2295fa1c062SBarry Smith {
2305fa1c062SBarry Smith   PetscErrorCode ierr;
2315fa1c062SBarry Smith 
2325fa1c062SBarry Smith   PetscFunctionBegin;
233*1472f72bSBarry Smith   /* Change the type name before calling MatSetType() to force proper construction of MPIAIJ
234*1472f72bSBarry Smith      and MATMPICRL types. */
235*1472f72bSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATMPICRL);CHKERRQ(ierr);
236*1472f72bSBarry Smith   ierr = MatSetType(A,MATMPIAIJ);CHKERRQ(ierr);
237*1472f72bSBarry Smith   ierr = MatConvert_MPIAIJ_MPICRL(A,MATMPICRL,MAT_REUSE_MATRIX,&A);CHKERRQ(ierr);
2385fa1c062SBarry Smith   PetscFunctionReturn(0);
2395fa1c062SBarry Smith }
2405fa1c062SBarry Smith EXTERN_C_END
2415fa1c062SBarry Smith 
242