xref: /petsc/src/mat/impls/aij/seq/matmatmult.c (revision c9780b6f0ebe9a8148f0ae06999feae3eb835510)
1d50806bdSBarry Smith /*$Id: matmatmult.c,v 1.15 2001/09/07 20:04:44 buschelm Exp $*/
2d50806bdSBarry Smith /*
32c9ce0e5SKris Buschelman   Defines matrix-matrix product routines for pairs of SeqAIJ matrices
4d50806bdSBarry Smith           C = A * B
5d50806bdSBarry Smith */
6d50806bdSBarry Smith 
7c1f4806aSKris Buschelman #include "src/mat/impls/aij/seq/aij.h" /*I "petscmat.h" I*/
870f19b1fSKris Buschelman #include "src/mat/utils/freespace.h"
9d50806bdSBarry Smith 
102216b3a4SKris Buschelman static int logkey_matmatmult          = 0;
112216b3a4SKris Buschelman static int logkey_matmatmult_symbolic = 0;
122216b3a4SKris Buschelman static int logkey_matmatmult_numeric  = 0;
132216b3a4SKris Buschelman 
14c1f4806aSKris Buschelman #undef __FUNCT__
15c1f4806aSKris Buschelman #define __FUNCT__ "MatMatMult"
165c66b693SKris Buschelman /*@
175c66b693SKris Buschelman    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
1894e3eecaSKris Buschelman 
195c66b693SKris Buschelman    Collective on Mat
20d50806bdSBarry Smith 
215c66b693SKris Buschelman    Input Parameters:
225c66b693SKris Buschelman +  A - the left matrix
235c66b693SKris Buschelman -  B - the right matrix
245c66b693SKris Buschelman 
255c66b693SKris Buschelman    Output Parameters:
265c66b693SKris Buschelman .  C - the product matrix
275c66b693SKris Buschelman 
285c66b693SKris Buschelman    Notes:
295c66b693SKris Buschelman    C will be created and must be destroyed by the user with MatDestroy().
305c66b693SKris Buschelman 
315c66b693SKris Buschelman    This routine is currently only implemented for pairs of SeqAIJ matrices.
325c66b693SKris Buschelman 
335c66b693SKris Buschelman    Level: intermediate
345c66b693SKris Buschelman 
355c66b693SKris Buschelman .seealso: MatMatMultSymbolic(),MatMatMultNumeric()
365c66b693SKris Buschelman @*/
375c66b693SKris Buschelman int MatMatMult(Mat A,Mat B, Mat *C) {
385c66b693SKris Buschelman   /* Perhaps this "interface" routine should be moved into the interface directory.*/
395c66b693SKris Buschelman   /* To facilitate implementations with varying types, QueryFunction is used.*/
405c66b693SKris Buschelman   /* It is assumed that implementations will be composed as "MatMatMult_<type of A><type of B>". */
41d50806bdSBarry Smith   int  ierr;
425c66b693SKris Buschelman   char funct[80];
435c66b693SKris Buschelman   int  (*mult)(Mat,Mat,Mat*);
44d50806bdSBarry Smith 
45d50806bdSBarry Smith   PetscFunctionBegin;
464482741eSBarry Smith   PetscValidHeaderSpecific(A,MAT_COOKIE,1);
47*c9780b6fSBarry Smith   PetscValidType(A,1);
485c66b693SKris Buschelman   MatPreallocated(A);
495c66b693SKris Buschelman   if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
505c66b693SKris Buschelman   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
51d50806bdSBarry Smith 
524482741eSBarry Smith   PetscValidHeaderSpecific(B,MAT_COOKIE,2);
53*c9780b6fSBarry Smith   PetscValidType(B,2);
545c66b693SKris Buschelman   MatPreallocated(B);
555c66b693SKris Buschelman   if (!B->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
565c66b693SKris Buschelman   if (B->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
57d50806bdSBarry Smith 
584482741eSBarry Smith   PetscValidPointer(C,3);
594482741eSBarry Smith 
605c66b693SKris Buschelman   if (B->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->M,A->N);
61d50806bdSBarry Smith 
625c66b693SKris Buschelman   ierr = PetscStrcpy(funct,"MatMatMult_");CHKERRQ(ierr);
635c66b693SKris Buschelman   ierr = PetscStrcat(funct,A->type_name);CHKERRQ(ierr);
645c66b693SKris Buschelman   ierr = PetscStrcat(funct,B->type_name);CHKERRQ(ierr);
655c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,funct,(PetscVoidFunction)&mult);CHKERRQ(ierr);
664482741eSBarry Smith   if (!mult) SETERRQ2(PETSC_ERR_SUP,"C=A*B not implemented for A of type %s and B of type %s",
675c66b693SKris Buschelman                          A->type_name,B->type_name);
685c66b693SKris Buschelman   ierr = (*mult)(A,B,C);CHKERRQ(ierr);
69d50806bdSBarry Smith   PetscFunctionReturn(0);
70d50806bdSBarry Smith }
715c66b693SKris Buschelman 
725c66b693SKris Buschelman #undef __FUNCT__
735c66b693SKris Buschelman #define __FUNCT__ "MatMatMult_SeqAIJ_SeqAIJ"
745c66b693SKris Buschelman int MatMatMult_SeqAIJ_SeqAIJ(Mat A,Mat B, Mat *C) {
755c66b693SKris Buschelman   int ierr;
765c66b693SKris Buschelman   char symfunct[80],numfunct[80],types[80];
775c66b693SKris Buschelman   int (*symbolic)(Mat,Mat,Mat*),(*numeric)(Mat,Mat,Mat);
785c66b693SKris Buschelman 
795c66b693SKris Buschelman   PetscFunctionBegin;
805c66b693SKris Buschelman   ierr = PetscStrcpy(types,A->type_name);CHKERRQ(ierr);
815c66b693SKris Buschelman   ierr = PetscStrcat(types,B->type_name);CHKERRQ(ierr);
825c66b693SKris Buschelman   ierr = PetscStrcpy(symfunct,"MatMatMultSymbolic_");CHKERRQ(ierr);
835c66b693SKris Buschelman   ierr = PetscStrcat(symfunct,types);CHKERRQ(ierr);
845c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,symfunct,(PetscVoidFunction)&symbolic);CHKERRQ(ierr);
855c66b693SKris Buschelman   if (!symbolic) SETERRQ2(PETSC_ERR_SUP,
865c66b693SKris Buschelman                          "C=A*B not implemented for A of type %s and B of type %s",
875c66b693SKris Buschelman                          A->type_name,B->type_name);
885c66b693SKris Buschelman   ierr = PetscStrcpy(numfunct,"MatMatMultNumeric_");CHKERRQ(ierr);
895c66b693SKris Buschelman   ierr = PetscStrcat(numfunct,types);CHKERRQ(ierr);
905c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,numfunct,(PetscVoidFunction)&numeric);CHKERRQ(ierr);
915c66b693SKris Buschelman   if (!numeric) SETERRQ2(PETSC_ERR_SUP,
925c66b693SKris Buschelman                          "C=A*B not implemented for A of type %s and B of type %s",
935c66b693SKris Buschelman                          A->type_name,B->type_name);
945c66b693SKris Buschelman   ierr = PetscLogEventBegin(logkey_matmatmult,A,B,0,0);CHKERRQ(ierr);
955c66b693SKris Buschelman   ierr = (*symbolic)(A,B,C);CHKERRQ(ierr);
965c66b693SKris Buschelman   ierr = (*numeric)(A,B,*C);CHKERRQ(ierr);
975c66b693SKris Buschelman   ierr = PetscLogEventEnd(logkey_matmatmult,A,B,0,0);CHKERRQ(ierr);
985c66b693SKris Buschelman   PetscFunctionReturn(0);
995c66b693SKris Buschelman }
1005c66b693SKris Buschelman 
101c1f4806aSKris Buschelman #undef __FUNCT__
102c1f4806aSKris Buschelman #define __FUNCT__ "MatMatMultSymbolic"
1035c66b693SKris Buschelman /*@
1045c66b693SKris Buschelman    MatMatMultSymbolic - Performs construction, preallocation, and computes the ij structure
1055c66b693SKris Buschelman    of the matrix-matrix product C=A*B.  Call this routine before calling MatMatMultNumeric().
1065c66b693SKris Buschelman 
1075c66b693SKris Buschelman    Collective on Mat
1085c66b693SKris Buschelman 
1095c66b693SKris Buschelman    Input Parameters:
1105c66b693SKris Buschelman +  A - the left matrix
1115c66b693SKris Buschelman -  B - the right matrix
1125c66b693SKris Buschelman 
1135c66b693SKris Buschelman    Output Parameters:
1145c66b693SKris Buschelman .  C - the matrix containing the ij structure of product matrix
1155c66b693SKris Buschelman 
1165c66b693SKris Buschelman    Notes:
1175c66b693SKris Buschelman    C will be created and must be destroyed by the user with MatDestroy().
1185c66b693SKris Buschelman 
1195c66b693SKris Buschelman    This routine is currently only implemented for SeqAIJ type matrices.
1205c66b693SKris Buschelman 
1215c66b693SKris Buschelman    Level: intermediate
1225c66b693SKris Buschelman 
1235c66b693SKris Buschelman .seealso: MatMatMult(),MatMatMultNumeric()
1245c66b693SKris Buschelman @*/
1255c66b693SKris Buschelman int MatMatMultSymbolic(Mat A,Mat B,Mat *C) {
1265c66b693SKris Buschelman   /* Perhaps this "interface" routine should be moved into the interface directory.*/
1275c66b693SKris Buschelman   /* To facilitate implementations with varying types, QueryFunction is used.*/
1285c66b693SKris Buschelman   /* It is assumed that implementations will be composed as "MatMatMultSymbolic_<type of A><type of B>". */
1295c66b693SKris Buschelman   int  ierr;
1305c66b693SKris Buschelman   char funct[80];
1315c66b693SKris Buschelman   int  (*symbolic)(Mat,Mat,Mat *);
1325c66b693SKris Buschelman 
1335c66b693SKris Buschelman   PetscFunctionBegin;
1344482741eSBarry Smith   PetscValidHeaderSpecific(A,MAT_COOKIE,1);
135*c9780b6fSBarry Smith   PetscValidType(A,1);
1365c66b693SKris Buschelman   MatPreallocated(A);
1375c66b693SKris Buschelman   if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
1385c66b693SKris Buschelman   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1395c66b693SKris Buschelman 
1404482741eSBarry Smith   PetscValidHeaderSpecific(B,MAT_COOKIE,2);
141*c9780b6fSBarry Smith   PetscValidType(B,2);
1425c66b693SKris Buschelman   MatPreallocated(B);
1435c66b693SKris Buschelman   if (!B->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
1445c66b693SKris Buschelman   if (B->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1454482741eSBarry Smith   PetscValidPointer(C,3);
1464482741eSBarry Smith 
1475c66b693SKris Buschelman 
1485c66b693SKris Buschelman   if (B->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->M,A->N);
1495c66b693SKris Buschelman 
1505c66b693SKris Buschelman   ierr = PetscStrcpy(funct,"MatMatMultSymbolic_");CHKERRQ(ierr);
1515c66b693SKris Buschelman   ierr = PetscStrcat(funct,A->type_name);CHKERRQ(ierr);
1525c66b693SKris Buschelman   ierr = PetscStrcat(funct,B->type_name);CHKERRQ(ierr);
1535c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,funct,(PetscVoidFunction)&symbolic);CHKERRQ(ierr);
1545c66b693SKris Buschelman   if (!symbolic) SETERRQ2(PETSC_ERR_SUP,
1555c66b693SKris Buschelman                          "C=A*B not implemented for A of type %s and B of type %s",
1565c66b693SKris Buschelman                          A->type_name,B->type_name);
1575c66b693SKris Buschelman   ierr = (*symbolic)(A,B,C);CHKERRQ(ierr);
1585c66b693SKris Buschelman 
1595c66b693SKris Buschelman   PetscFunctionReturn(0);
1605c66b693SKris Buschelman }
16158c24d83SHong Zhang 
16258c24d83SHong Zhang #undef __FUNCT__
16358c24d83SHong Zhang #define __FUNCT__ "MatMatMult_Symbolic_SeqAIJ_SeqAIJ"
16458c24d83SHong Zhang int MatMatMult_Symbolic_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat *C)
16558c24d83SHong Zhang {
16658c24d83SHong Zhang   int            ierr;
16758c24d83SHong Zhang   FreeSpaceList  free_space=PETSC_NULL,current_space=PETSC_NULL;
16858c24d83SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b=(Mat_SeqAIJ*)B->data,*c;
16958c24d83SHong Zhang   int            *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj;
17058c24d83SHong Zhang   int            *ci,*cj,*lnk,idx0,idx,bcol;
1715c66b693SKris Buschelman   int            am=A->M,bn=B->N,bm=B->M;
17258c24d83SHong Zhang   int            i,j,k,anzi,brow,bnzj,cnzi;
17358c24d83SHong Zhang   MatScalar      *ca;
17458c24d83SHong Zhang 
17558c24d83SHong Zhang   PetscFunctionBegin;
1765c66b693SKris Buschelman   /* Start timers */
17758c24d83SHong Zhang   ierr = PetscLogEventBegin(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr);
17858c24d83SHong Zhang 
17958c24d83SHong Zhang   /* Set up */
18058c24d83SHong Zhang   /* Allocate ci array, arrays for fill computation and */
18158c24d83SHong Zhang   /* free space for accumulating nonzero column info */
18258c24d83SHong Zhang   ierr = PetscMalloc(((am+1)+1)*sizeof(int),&ci);CHKERRQ(ierr);
18358c24d83SHong Zhang   ci[0] = 0;
18458c24d83SHong Zhang 
18558c24d83SHong Zhang   ierr = PetscMalloc((bn+1)*sizeof(int),&lnk);CHKERRQ(ierr);
18658c24d83SHong Zhang   for (i=0; i<bn; i++) lnk[i] = -1;
18758c24d83SHong Zhang 
18858c24d83SHong Zhang   /* Initial FreeSpace size is nnz(B)=4*bi[bm] */
18958c24d83SHong Zhang   ierr = GetMoreSpace(4*bi[bm],&free_space);CHKERRQ(ierr);
19058c24d83SHong Zhang   current_space = free_space;
19158c24d83SHong Zhang 
19258c24d83SHong Zhang   /* Determine symbolic info for each row of the product: */
19358c24d83SHong Zhang   for (i=0;i<am;i++) {
19458c24d83SHong Zhang     anzi = ai[i+1] - ai[i];
19558c24d83SHong Zhang     cnzi = 0;
19658c24d83SHong Zhang     lnk[bn] = bn;
19758c24d83SHong Zhang     for (j=0;j<anzi;j++) {
19858c24d83SHong Zhang       brow = *aj++;
19958c24d83SHong Zhang       bnzj = bi[brow+1] - bi[brow];
20058c24d83SHong Zhang       bjj  = bj + bi[brow];
20158c24d83SHong Zhang       idx  = bn;
20258c24d83SHong Zhang       for (k=0;k<bnzj;k++) {
20358c24d83SHong Zhang         bcol = bjj[k];
20458c24d83SHong Zhang         if (lnk[bcol] == -1) { /* new col */
20558c24d83SHong Zhang           if (k>0) idx = bjj[k-1];
20658c24d83SHong Zhang           do {
20758c24d83SHong Zhang             idx0 = idx;
20858c24d83SHong Zhang             idx  = lnk[idx0];
20958c24d83SHong Zhang           } while (bcol > idx);
21058c24d83SHong Zhang           lnk[idx0] = bcol;
21158c24d83SHong Zhang           lnk[bcol] = idx;
21258c24d83SHong Zhang           cnzi++;
21358c24d83SHong Zhang         }
21458c24d83SHong Zhang       }
21558c24d83SHong Zhang     }
21658c24d83SHong Zhang 
21758c24d83SHong Zhang     /* If free space is not available, make more free space */
21858c24d83SHong Zhang     /* Double the amount of total space in the list */
21958c24d83SHong Zhang     if (current_space->local_remaining<cnzi) {
22058c24d83SHong Zhang       printf("...%d -th row, double space ...\n",i);
22158c24d83SHong Zhang       ierr = GetMoreSpace(current_space->total_array_size,&current_space);CHKERRQ(ierr);
22258c24d83SHong Zhang     }
22358c24d83SHong Zhang 
22458c24d83SHong Zhang     /* Copy data into free space, and zero out denserow and lnk */
22558c24d83SHong Zhang     idx = bn;
22658c24d83SHong Zhang     for (j=0; j<cnzi; j++){
22758c24d83SHong Zhang       idx0 = idx;
22858c24d83SHong Zhang       idx  = lnk[idx0];
22958c24d83SHong Zhang       *current_space->array++ = idx;
23058c24d83SHong Zhang       lnk[idx0] = -1;
23158c24d83SHong Zhang     }
23258c24d83SHong Zhang     lnk[idx] = -1;
23358c24d83SHong Zhang 
23458c24d83SHong Zhang     current_space->local_used      += cnzi;
23558c24d83SHong Zhang     current_space->local_remaining -= cnzi;
23658c24d83SHong Zhang 
23758c24d83SHong Zhang     ci[i+1] = ci[i] + cnzi;
23858c24d83SHong Zhang   }
23958c24d83SHong Zhang 
24058c24d83SHong Zhang   /* Column indices are in the list of free space */
24158c24d83SHong Zhang   /* Allocate space for cj, initialize cj, and */
24258c24d83SHong Zhang   /* destroy list of free space and other temporary array(s) */
24358c24d83SHong Zhang   ierr = PetscMalloc((ci[am]+1)*sizeof(int),&cj);CHKERRQ(ierr);
24458c24d83SHong Zhang   ierr = MakeSpaceContiguous(&free_space,cj);CHKERRQ(ierr);
24558c24d83SHong Zhang   ierr = PetscFree(lnk);CHKERRQ(ierr);
24658c24d83SHong Zhang 
24758c24d83SHong Zhang   /* Allocate space for ca */
24858c24d83SHong Zhang   ierr = PetscMalloc((ci[am]+1)*sizeof(MatScalar),&ca);CHKERRQ(ierr);
24958c24d83SHong Zhang   ierr = PetscMemzero(ca,(ci[am]+1)*sizeof(MatScalar));CHKERRQ(ierr);
25058c24d83SHong Zhang 
25158c24d83SHong Zhang   /* put together the new matrix */
25258c24d83SHong Zhang   ierr = MatCreateSeqAIJWithArrays(A->comm,am,bn,ci,cj,ca,C);CHKERRQ(ierr);
25358c24d83SHong Zhang 
25458c24d83SHong Zhang   /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */
25558c24d83SHong Zhang   /* These are PETSc arrays, so change flags so arrays can be deleted by PETSc */
25658c24d83SHong Zhang   c = (Mat_SeqAIJ *)((*C)->data);
25758c24d83SHong Zhang   c->freedata = PETSC_TRUE;
25858c24d83SHong Zhang   c->nonew    = 0;
25958c24d83SHong Zhang 
26058c24d83SHong Zhang   ierr = PetscLogEventEnd(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr);
26158c24d83SHong Zhang   PetscFunctionReturn(0);
26258c24d83SHong Zhang }
263d50806bdSBarry Smith 
264c1f4806aSKris Buschelman #undef __FUNCT__
265c1f4806aSKris Buschelman #define __FUNCT__ "MatMatMultNumeric"
2665c66b693SKris Buschelman /*@
2675c66b693SKris Buschelman    MatMatMultNumeric - Performs the numeric matrix-matrix product.
2685c66b693SKris Buschelman    Call this routine after first calling MatMatMultSymbolic().
2695c66b693SKris Buschelman 
2705c66b693SKris Buschelman    Collective on Mat
2715c66b693SKris Buschelman 
2725c66b693SKris Buschelman    Input Parameters:
2735c66b693SKris Buschelman +  A - the left matrix
2745c66b693SKris Buschelman -  B - the right matrix
2755c66b693SKris Buschelman 
2765c66b693SKris Buschelman    Output Parameters:
2775c66b693SKris Buschelman .  C - the product matrix, whose ij structure was defined from MatMatMultSymbolic().
2785c66b693SKris Buschelman 
2795c66b693SKris Buschelman    Notes:
2805c66b693SKris Buschelman    C must have been created with MatMatMultSymbolic.
2815c66b693SKris Buschelman 
2825c66b693SKris Buschelman    This routine is currently only implemented for SeqAIJ type matrices.
2835c66b693SKris Buschelman 
2845c66b693SKris Buschelman    Level: intermediate
2855c66b693SKris Buschelman 
2865c66b693SKris Buschelman .seealso: MatMatMult(),MatMatMultSymbolic()
2875c66b693SKris Buschelman @*/
2885c66b693SKris Buschelman int MatMatMultNumeric(Mat A,Mat B,Mat C){
2895c66b693SKris Buschelman   /* Perhaps this "interface" routine should be moved into the interface directory.*/
2905c66b693SKris Buschelman   /* To facilitate implementations with varying types, QueryFunction is used.*/
2915c66b693SKris Buschelman   /* It is assumed that implementations will be composed as "MatMatMultNumeric_<type of A><type of B>". */
2925c66b693SKris Buschelman   int ierr;
2935c66b693SKris Buschelman   char funct[80];
2945c66b693SKris Buschelman   int (*numeric)(Mat,Mat,Mat);
2955c66b693SKris Buschelman 
2965c66b693SKris Buschelman   PetscFunctionBegin;
2975c66b693SKris Buschelman 
2984482741eSBarry Smith   PetscValidHeaderSpecific(A,MAT_COOKIE,1);
299*c9780b6fSBarry Smith   PetscValidType(A,1);
3005c66b693SKris Buschelman   MatPreallocated(A);
3015c66b693SKris Buschelman   if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3025c66b693SKris Buschelman   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3035c66b693SKris Buschelman 
3044482741eSBarry Smith   PetscValidHeaderSpecific(B,MAT_COOKIE,2);
305*c9780b6fSBarry Smith   PetscValidType(B,2);
3065c66b693SKris Buschelman   MatPreallocated(B);
3075c66b693SKris Buschelman   if (!B->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3085c66b693SKris Buschelman   if (B->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3095c66b693SKris Buschelman 
3104482741eSBarry Smith   PetscValidHeaderSpecific(C,MAT_COOKIE,3);
311*c9780b6fSBarry Smith   PetscValidType(C,3);
3125c66b693SKris Buschelman   MatPreallocated(C);
3135c66b693SKris Buschelman   if (!C->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3145c66b693SKris Buschelman   if (C->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3155c66b693SKris Buschelman 
3165c66b693SKris Buschelman   if (B->N!=C->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->N,C->N);
3175c66b693SKris Buschelman   if (B->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->M,A->N);
3185c66b693SKris Buschelman   if (A->M!=C->M) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",A->M,C->M);
3195c66b693SKris Buschelman 
3205c66b693SKris Buschelman   /* Query A for ApplyPtAP implementation based on types of P */
3215c66b693SKris Buschelman   ierr = PetscStrcpy(funct,"MatMatMultNumeric_");CHKERRQ(ierr);
3225c66b693SKris Buschelman   ierr = PetscStrcat(funct,A->type_name);CHKERRQ(ierr);
3235c66b693SKris Buschelman   ierr = PetscStrcat(funct,B->type_name);CHKERRQ(ierr);
3245c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,funct,(PetscVoidFunction)&numeric);CHKERRQ(ierr);
3255c66b693SKris Buschelman   if (!numeric) SETERRQ2(PETSC_ERR_SUP,
3265c66b693SKris Buschelman                          "C=A*B not implemented for A of type %s and B of type %s",
3275c66b693SKris Buschelman                          A->type_name,B->type_name);
3285c66b693SKris Buschelman   ierr = (*numeric)(A,B,C);CHKERRQ(ierr);
3295c66b693SKris Buschelman 
3305c66b693SKris Buschelman   PetscFunctionReturn(0);
3315c66b693SKris Buschelman }
3325c66b693SKris Buschelman 
333d50806bdSBarry Smith #undef __FUNCT__
33494e3eecaSKris Buschelman #define __FUNCT__ "MatMatMult_Numeric_SeqAIJ_SeqAIJ"
33594e3eecaSKris Buschelman int MatMatMult_Numeric_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat C)
336d50806bdSBarry Smith {
33794e3eecaSKris Buschelman   int        ierr,flops=0;
338d50806bdSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
339d50806bdSBarry Smith   Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data;
340d50806bdSBarry Smith   Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data;
341d50806bdSBarry Smith   int        *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj,*ci=c->i,*cj=c->j;
3425c66b693SKris Buschelman   int        am=A->M,cn=C->N;
34394e3eecaSKris Buschelman   int        i,j,k,anzi,bnzi,cnzi,brow;
344d50806bdSBarry Smith   MatScalar  *aa=a->a,*ba=b->a,*baj,*ca=c->a,*temp;
345d50806bdSBarry Smith 
346d50806bdSBarry Smith   PetscFunctionBegin;
347d50806bdSBarry Smith 
3485c66b693SKris Buschelman   /* Start timers */
349d50806bdSBarry Smith   ierr = PetscLogEventBegin(logkey_matmatmult_numeric,A,B,C,0);CHKERRQ(ierr);
35094e3eecaSKris Buschelman 
351d50806bdSBarry Smith   /* Allocate temp accumulation space to avoid searching for nonzero columns in C */
352d50806bdSBarry Smith   ierr = PetscMalloc((cn+1)*sizeof(MatScalar),&temp);CHKERRQ(ierr);
353d50806bdSBarry Smith   ierr = PetscMemzero(temp,cn*sizeof(MatScalar));CHKERRQ(ierr);
354d50806bdSBarry Smith   /* Traverse A row-wise. */
355d50806bdSBarry Smith   /* Build the ith row in C by summing over nonzero columns in A, */
356d50806bdSBarry Smith   /* the rows of B corresponding to nonzeros of A. */
357d50806bdSBarry Smith   for (i=0;i<am;i++) {
358d50806bdSBarry Smith     anzi = ai[i+1] - ai[i];
359d50806bdSBarry Smith     for (j=0;j<anzi;j++) {
360d50806bdSBarry Smith       brow = *aj++;
361d50806bdSBarry Smith       bnzi = bi[brow+1] - bi[brow];
362d50806bdSBarry Smith       bjj  = bj + bi[brow];
363d50806bdSBarry Smith       baj  = ba + bi[brow];
364d50806bdSBarry Smith       for (k=0;k<bnzi;k++) {
365d50806bdSBarry Smith         temp[bjj[k]] += (*aa)*baj[k];
366d50806bdSBarry Smith       }
367d50806bdSBarry Smith       flops += 2*bnzi;
368d50806bdSBarry Smith       aa++;
369d50806bdSBarry Smith     }
370d50806bdSBarry Smith     /* Store row back into C, and re-zero temp */
371d50806bdSBarry Smith     cnzi = ci[i+1] - ci[i];
372d50806bdSBarry Smith     for (j=0;j<cnzi;j++) {
373d50806bdSBarry Smith       ca[j] = temp[cj[j]];
374d50806bdSBarry Smith       temp[cj[j]] = 0.0;
375d50806bdSBarry Smith     }
376d50806bdSBarry Smith     ca += cnzi;
377d50806bdSBarry Smith     cj += cnzi;
378d50806bdSBarry Smith   }
379716bacf3SKris Buschelman   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
380716bacf3SKris Buschelman   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
381716bacf3SKris Buschelman 
382d50806bdSBarry Smith   /* Free temp */
383d50806bdSBarry Smith   ierr = PetscFree(temp);CHKERRQ(ierr);
384d50806bdSBarry Smith   ierr = PetscLogFlops(flops);CHKERRQ(ierr);
385d50806bdSBarry Smith   ierr = PetscLogEventEnd(logkey_matmatmult_numeric,A,B,C,0);CHKERRQ(ierr);
386d50806bdSBarry Smith   PetscFunctionReturn(0);
387d50806bdSBarry Smith }
388d50806bdSBarry Smith 
389d50806bdSBarry Smith #undef __FUNCT__
3905c66b693SKris Buschelman #define __FUNCT__ "RegisterMatMatMultRoutines_Private"
3915c66b693SKris Buschelman int RegisterMatMatMultRoutines_Private(Mat A) {
392d50806bdSBarry Smith   int ierr;
393d50806bdSBarry Smith 
394d50806bdSBarry Smith   PetscFunctionBegin;
3952216b3a4SKris Buschelman   if (!logkey_matmatmult) {
3962216b3a4SKris Buschelman     ierr = PetscLogEventRegister(&logkey_matmatmult,"MatMatMult",MAT_COOKIE);CHKERRQ(ierr);
3972216b3a4SKris Buschelman   }
3985c66b693SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatMatMult_seqaijseqaij",
3995c66b693SKris Buschelman                                            "MatMatMult_SeqAIJ_SeqAIJ",
4005c66b693SKris Buschelman                                            MatMatMult_SeqAIJ_SeqAIJ);CHKERRQ(ierr);
4015c66b693SKris Buschelman   if (!logkey_matmatmult_symbolic) {
4025c66b693SKris Buschelman     ierr = PetscLogEventRegister(&logkey_matmatmult_symbolic,"MatMatMult_Symbolic",MAT_COOKIE);CHKERRQ(ierr);
403d50806bdSBarry Smith   }
4045c66b693SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatMatMultSymbolic_seqaijseqaij",
4055c66b693SKris Buschelman                                            "MatMatMult_Symbolic_SeqAIJ_SeqAIJ",
4065c66b693SKris Buschelman                                            MatMatMult_Symbolic_SeqAIJ_SeqAIJ);CHKERRQ(ierr);
4075c66b693SKris Buschelman   if (!logkey_matmatmult_numeric) {
4085c66b693SKris Buschelman     ierr = PetscLogEventRegister(&logkey_matmatmult_numeric,"MatMatMult_Numeric",MAT_COOKIE);CHKERRQ(ierr);
40994e3eecaSKris Buschelman   }
4105c66b693SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatMatMultNumeric_seqaijseqaij",
4115c66b693SKris Buschelman                                            "MatMatMult_Numeric_SeqAIJ_SeqAIJ",
4125c66b693SKris Buschelman                                            MatMatMult_Numeric_SeqAIJ_SeqAIJ);CHKERRQ(ierr);
41394e3eecaSKris Buschelman   PetscFunctionReturn(0);
41494e3eecaSKris Buschelman }
415