xref: /petsc/src/mat/impls/aij/seq/matmatmult.c (revision c1f4806a4f47b1e31166d4cb6a1640e11d32eebf)
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 
7*c1f4806aSKris 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 
14*c1f4806aSKris Buschelman #undef __FUNCT__
15*c1f4806aSKris 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;
465c66b693SKris Buschelman   PetscValidPointer(C);
47d50806bdSBarry Smith 
485c66b693SKris Buschelman   PetscValidHeaderSpecific(A,MAT_COOKIE);
495c66b693SKris Buschelman   PetscValidType(A);
505c66b693SKris Buschelman   MatPreallocated(A);
515c66b693SKris Buschelman   if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
525c66b693SKris Buschelman   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
53d50806bdSBarry Smith 
545c66b693SKris Buschelman   PetscValidHeaderSpecific(B,MAT_COOKIE);
555c66b693SKris Buschelman   PetscValidType(B);
565c66b693SKris Buschelman   MatPreallocated(B);
575c66b693SKris Buschelman   if (!B->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
585c66b693SKris Buschelman   if (B->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
59d50806bdSBarry 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);
665c66b693SKris Buschelman   if (!mult) SETERRQ2(PETSC_ERR_SUP,
675c66b693SKris Buschelman                          "C=A*B not implemented for A of type %s and B of type %s",
685c66b693SKris Buschelman                          A->type_name,B->type_name);
695c66b693SKris Buschelman   ierr = (*mult)(A,B,C);CHKERRQ(ierr);
70d50806bdSBarry Smith   PetscFunctionReturn(0);
71d50806bdSBarry Smith }
725c66b693SKris Buschelman 
735c66b693SKris Buschelman #undef __FUNCT__
745c66b693SKris Buschelman #define __FUNCT__ "MatMatMult_SeqAIJ_SeqAIJ"
755c66b693SKris Buschelman int MatMatMult_SeqAIJ_SeqAIJ(Mat A,Mat B, Mat *C) {
765c66b693SKris Buschelman   int ierr;
775c66b693SKris Buschelman   char symfunct[80],numfunct[80],types[80];
785c66b693SKris Buschelman   int (*symbolic)(Mat,Mat,Mat*),(*numeric)(Mat,Mat,Mat);
795c66b693SKris Buschelman 
805c66b693SKris Buschelman   PetscFunctionBegin;
815c66b693SKris Buschelman   ierr = PetscStrcpy(types,A->type_name);CHKERRQ(ierr);
825c66b693SKris Buschelman   ierr = PetscStrcat(types,B->type_name);CHKERRQ(ierr);
835c66b693SKris Buschelman   ierr = PetscStrcpy(symfunct,"MatMatMultSymbolic_");CHKERRQ(ierr);
845c66b693SKris Buschelman   ierr = PetscStrcat(symfunct,types);CHKERRQ(ierr);
855c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,symfunct,(PetscVoidFunction)&symbolic);CHKERRQ(ierr);
865c66b693SKris Buschelman   if (!symbolic) SETERRQ2(PETSC_ERR_SUP,
875c66b693SKris Buschelman                          "C=A*B not implemented for A of type %s and B of type %s",
885c66b693SKris Buschelman                          A->type_name,B->type_name);
895c66b693SKris Buschelman   ierr = PetscStrcpy(numfunct,"MatMatMultNumeric_");CHKERRQ(ierr);
905c66b693SKris Buschelman   ierr = PetscStrcat(numfunct,types);CHKERRQ(ierr);
915c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,numfunct,(PetscVoidFunction)&numeric);CHKERRQ(ierr);
925c66b693SKris Buschelman   if (!numeric) SETERRQ2(PETSC_ERR_SUP,
935c66b693SKris Buschelman                          "C=A*B not implemented for A of type %s and B of type %s",
945c66b693SKris Buschelman                          A->type_name,B->type_name);
955c66b693SKris Buschelman   ierr = PetscLogEventBegin(logkey_matmatmult,A,B,0,0);CHKERRQ(ierr);
965c66b693SKris Buschelman   ierr = (*symbolic)(A,B,C);CHKERRQ(ierr);
975c66b693SKris Buschelman   ierr = (*numeric)(A,B,*C);CHKERRQ(ierr);
985c66b693SKris Buschelman   ierr = PetscLogEventEnd(logkey_matmatmult,A,B,0,0);CHKERRQ(ierr);
995c66b693SKris Buschelman   PetscFunctionReturn(0);
1005c66b693SKris Buschelman }
1015c66b693SKris Buschelman 
102*c1f4806aSKris Buschelman #undef __FUNCT__
103*c1f4806aSKris Buschelman #define __FUNCT__ "MatMatMultSymbolic"
1045c66b693SKris Buschelman /*@
1055c66b693SKris Buschelman    MatMatMultSymbolic - Performs construction, preallocation, and computes the ij structure
1065c66b693SKris Buschelman    of the matrix-matrix product C=A*B.  Call this routine before calling MatMatMultNumeric().
1075c66b693SKris Buschelman 
1085c66b693SKris Buschelman    Collective on Mat
1095c66b693SKris Buschelman 
1105c66b693SKris Buschelman    Input Parameters:
1115c66b693SKris Buschelman +  A - the left matrix
1125c66b693SKris Buschelman -  B - the right matrix
1135c66b693SKris Buschelman 
1145c66b693SKris Buschelman    Output Parameters:
1155c66b693SKris Buschelman .  C - the matrix containing the ij structure of product matrix
1165c66b693SKris Buschelman 
1175c66b693SKris Buschelman    Notes:
1185c66b693SKris Buschelman    C will be created and must be destroyed by the user with MatDestroy().
1195c66b693SKris Buschelman 
1205c66b693SKris Buschelman    This routine is currently only implemented for SeqAIJ type matrices.
1215c66b693SKris Buschelman 
1225c66b693SKris Buschelman    Level: intermediate
1235c66b693SKris Buschelman 
1245c66b693SKris Buschelman .seealso: MatMatMult(),MatMatMultNumeric()
1255c66b693SKris Buschelman @*/
1265c66b693SKris Buschelman int MatMatMultSymbolic(Mat A,Mat B,Mat *C) {
1275c66b693SKris Buschelman   /* Perhaps this "interface" routine should be moved into the interface directory.*/
1285c66b693SKris Buschelman   /* To facilitate implementations with varying types, QueryFunction is used.*/
1295c66b693SKris Buschelman   /* It is assumed that implementations will be composed as "MatMatMultSymbolic_<type of A><type of B>". */
1305c66b693SKris Buschelman   int ierr;
1315c66b693SKris Buschelman   char funct[80];
1325c66b693SKris Buschelman   int (*symbolic)(Mat,Mat,Mat *);
1335c66b693SKris Buschelman 
1345c66b693SKris Buschelman   PetscFunctionBegin;
1355c66b693SKris Buschelman   PetscValidPointer(C);
1365c66b693SKris Buschelman 
1375c66b693SKris Buschelman   PetscValidHeaderSpecific(A,MAT_COOKIE);
1385c66b693SKris Buschelman   PetscValidType(A);
1395c66b693SKris Buschelman   MatPreallocated(A);
1405c66b693SKris Buschelman   if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
1415c66b693SKris Buschelman   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1425c66b693SKris Buschelman 
1435c66b693SKris Buschelman   PetscValidHeaderSpecific(B,MAT_COOKIE);
1445c66b693SKris Buschelman   PetscValidType(B);
1455c66b693SKris Buschelman   MatPreallocated(B);
1465c66b693SKris Buschelman   if (!B->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
1475c66b693SKris Buschelman   if (B->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1485c66b693SKris Buschelman 
1495c66b693SKris Buschelman   if (B->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->M,A->N);
1505c66b693SKris Buschelman 
1515c66b693SKris Buschelman   ierr = PetscStrcpy(funct,"MatMatMultSymbolic_");CHKERRQ(ierr);
1525c66b693SKris Buschelman   ierr = PetscStrcat(funct,A->type_name);CHKERRQ(ierr);
1535c66b693SKris Buschelman   ierr = PetscStrcat(funct,B->type_name);CHKERRQ(ierr);
1545c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,funct,(PetscVoidFunction)&symbolic);CHKERRQ(ierr);
1555c66b693SKris Buschelman   if (!symbolic) SETERRQ2(PETSC_ERR_SUP,
1565c66b693SKris Buschelman                          "C=A*B not implemented for A of type %s and B of type %s",
1575c66b693SKris Buschelman                          A->type_name,B->type_name);
1585c66b693SKris Buschelman   ierr = (*symbolic)(A,B,C);CHKERRQ(ierr);
1595c66b693SKris Buschelman 
1605c66b693SKris Buschelman   PetscFunctionReturn(0);
1615c66b693SKris Buschelman }
16258c24d83SHong Zhang 
16358c24d83SHong Zhang #undef __FUNCT__
16458c24d83SHong Zhang #define __FUNCT__ "MatMatMult_Symbolic_SeqAIJ_SeqAIJ"
16558c24d83SHong Zhang int MatMatMult_Symbolic_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat *C)
16658c24d83SHong Zhang {
16758c24d83SHong Zhang   int            ierr;
16858c24d83SHong Zhang   FreeSpaceList  free_space=PETSC_NULL,current_space=PETSC_NULL;
16958c24d83SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b=(Mat_SeqAIJ*)B->data,*c;
17058c24d83SHong Zhang   int            *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj;
17158c24d83SHong Zhang   int            *ci,*cj,*lnk,idx0,idx,bcol;
1725c66b693SKris Buschelman   int            am=A->M,bn=B->N,bm=B->M;
17358c24d83SHong Zhang   int            i,j,k,anzi,brow,bnzj,cnzi;
17458c24d83SHong Zhang   MatScalar      *ca;
17558c24d83SHong Zhang 
17658c24d83SHong Zhang   PetscFunctionBegin;
1775c66b693SKris Buschelman   /* Start timers */
17858c24d83SHong Zhang   ierr = PetscLogEventBegin(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr);
17958c24d83SHong Zhang 
18058c24d83SHong Zhang   /* Set up */
18158c24d83SHong Zhang   /* Allocate ci array, arrays for fill computation and */
18258c24d83SHong Zhang   /* free space for accumulating nonzero column info */
18358c24d83SHong Zhang   ierr = PetscMalloc(((am+1)+1)*sizeof(int),&ci);CHKERRQ(ierr);
18458c24d83SHong Zhang   ci[0] = 0;
18558c24d83SHong Zhang 
18658c24d83SHong Zhang   ierr = PetscMalloc((bn+1)*sizeof(int),&lnk);CHKERRQ(ierr);
18758c24d83SHong Zhang   for (i=0; i<bn; i++) lnk[i] = -1;
18858c24d83SHong Zhang 
18958c24d83SHong Zhang   /* Initial FreeSpace size is nnz(B)=4*bi[bm] */
19058c24d83SHong Zhang   ierr = GetMoreSpace(4*bi[bm],&free_space);CHKERRQ(ierr);
19158c24d83SHong Zhang   current_space = free_space;
19258c24d83SHong Zhang 
19358c24d83SHong Zhang   /* Determine symbolic info for each row of the product: */
19458c24d83SHong Zhang   for (i=0;i<am;i++) {
19558c24d83SHong Zhang     anzi = ai[i+1] - ai[i];
19658c24d83SHong Zhang     cnzi = 0;
19758c24d83SHong Zhang     lnk[bn] = bn;
19858c24d83SHong Zhang     for (j=0;j<anzi;j++) {
19958c24d83SHong Zhang       brow = *aj++;
20058c24d83SHong Zhang       bnzj = bi[brow+1] - bi[brow];
20158c24d83SHong Zhang       bjj  = bj + bi[brow];
20258c24d83SHong Zhang       idx  = bn;
20358c24d83SHong Zhang       for (k=0;k<bnzj;k++) {
20458c24d83SHong Zhang         bcol = bjj[k];
20558c24d83SHong Zhang         if (lnk[bcol] == -1) { /* new col */
20658c24d83SHong Zhang           if (k>0) idx = bjj[k-1];
20758c24d83SHong Zhang           do {
20858c24d83SHong Zhang             idx0 = idx;
20958c24d83SHong Zhang             idx  = lnk[idx0];
21058c24d83SHong Zhang           } while (bcol > idx);
21158c24d83SHong Zhang           lnk[idx0] = bcol;
21258c24d83SHong Zhang           lnk[bcol] = idx;
21358c24d83SHong Zhang           cnzi++;
21458c24d83SHong Zhang         }
21558c24d83SHong Zhang       }
21658c24d83SHong Zhang     }
21758c24d83SHong Zhang 
21858c24d83SHong Zhang     /* If free space is not available, make more free space */
21958c24d83SHong Zhang     /* Double the amount of total space in the list */
22058c24d83SHong Zhang     if (current_space->local_remaining<cnzi) {
22158c24d83SHong Zhang       printf("...%d -th row, double space ...\n",i);
22258c24d83SHong Zhang       ierr = GetMoreSpace(current_space->total_array_size,&current_space);CHKERRQ(ierr);
22358c24d83SHong Zhang     }
22458c24d83SHong Zhang 
22558c24d83SHong Zhang     /* Copy data into free space, and zero out denserow and lnk */
22658c24d83SHong Zhang     idx = bn;
22758c24d83SHong Zhang     for (j=0; j<cnzi; j++){
22858c24d83SHong Zhang       idx0 = idx;
22958c24d83SHong Zhang       idx  = lnk[idx0];
23058c24d83SHong Zhang       *current_space->array++ = idx;
23158c24d83SHong Zhang       lnk[idx0] = -1;
23258c24d83SHong Zhang     }
23358c24d83SHong Zhang     lnk[idx] = -1;
23458c24d83SHong Zhang 
23558c24d83SHong Zhang     current_space->local_used      += cnzi;
23658c24d83SHong Zhang     current_space->local_remaining -= cnzi;
23758c24d83SHong Zhang 
23858c24d83SHong Zhang     ci[i+1] = ci[i] + cnzi;
23958c24d83SHong Zhang   }
24058c24d83SHong Zhang 
24158c24d83SHong Zhang   /* Column indices are in the list of free space */
24258c24d83SHong Zhang   /* Allocate space for cj, initialize cj, and */
24358c24d83SHong Zhang   /* destroy list of free space and other temporary array(s) */
24458c24d83SHong Zhang   ierr = PetscMalloc((ci[am]+1)*sizeof(int),&cj);CHKERRQ(ierr);
24558c24d83SHong Zhang   ierr = MakeSpaceContiguous(&free_space,cj);CHKERRQ(ierr);
24658c24d83SHong Zhang   ierr = PetscFree(lnk);CHKERRQ(ierr);
24758c24d83SHong Zhang 
24858c24d83SHong Zhang   /* Allocate space for ca */
24958c24d83SHong Zhang   ierr = PetscMalloc((ci[am]+1)*sizeof(MatScalar),&ca);CHKERRQ(ierr);
25058c24d83SHong Zhang   ierr = PetscMemzero(ca,(ci[am]+1)*sizeof(MatScalar));CHKERRQ(ierr);
25158c24d83SHong Zhang 
25258c24d83SHong Zhang   /* put together the new matrix */
25358c24d83SHong Zhang   ierr = MatCreateSeqAIJWithArrays(A->comm,am,bn,ci,cj,ca,C);CHKERRQ(ierr);
25458c24d83SHong Zhang 
25558c24d83SHong Zhang   /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */
25658c24d83SHong Zhang   /* These are PETSc arrays, so change flags so arrays can be deleted by PETSc */
25758c24d83SHong Zhang   c = (Mat_SeqAIJ *)((*C)->data);
25858c24d83SHong Zhang   c->freedata = PETSC_TRUE;
25958c24d83SHong Zhang   c->nonew    = 0;
26058c24d83SHong Zhang 
26158c24d83SHong Zhang   ierr = PetscLogEventEnd(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr);
26258c24d83SHong Zhang   PetscFunctionReturn(0);
26358c24d83SHong Zhang }
264d50806bdSBarry Smith 
265*c1f4806aSKris Buschelman #undef __FUNCT__
266*c1f4806aSKris Buschelman #define __FUNCT__ "MatMatMultNumeric"
2675c66b693SKris Buschelman /*@
2685c66b693SKris Buschelman    MatMatMultNumeric - Performs the numeric matrix-matrix product.
2695c66b693SKris Buschelman    Call this routine after first calling MatMatMultSymbolic().
2705c66b693SKris Buschelman 
2715c66b693SKris Buschelman    Collective on Mat
2725c66b693SKris Buschelman 
2735c66b693SKris Buschelman    Input Parameters:
2745c66b693SKris Buschelman +  A - the left matrix
2755c66b693SKris Buschelman -  B - the right matrix
2765c66b693SKris Buschelman 
2775c66b693SKris Buschelman    Output Parameters:
2785c66b693SKris Buschelman .  C - the product matrix, whose ij structure was defined from MatMatMultSymbolic().
2795c66b693SKris Buschelman 
2805c66b693SKris Buschelman    Notes:
2815c66b693SKris Buschelman    C must have been created with MatMatMultSymbolic.
2825c66b693SKris Buschelman 
2835c66b693SKris Buschelman    This routine is currently only implemented for SeqAIJ type matrices.
2845c66b693SKris Buschelman 
2855c66b693SKris Buschelman    Level: intermediate
2865c66b693SKris Buschelman 
2875c66b693SKris Buschelman .seealso: MatMatMult(),MatMatMultSymbolic()
2885c66b693SKris Buschelman @*/
2895c66b693SKris Buschelman int MatMatMultNumeric(Mat A,Mat B,Mat C){
2905c66b693SKris Buschelman   /* Perhaps this "interface" routine should be moved into the interface directory.*/
2915c66b693SKris Buschelman   /* To facilitate implementations with varying types, QueryFunction is used.*/
2925c66b693SKris Buschelman   /* It is assumed that implementations will be composed as "MatMatMultNumeric_<type of A><type of B>". */
2935c66b693SKris Buschelman   int ierr;
2945c66b693SKris Buschelman   char funct[80];
2955c66b693SKris Buschelman   int (*numeric)(Mat,Mat,Mat);
2965c66b693SKris Buschelman 
2975c66b693SKris Buschelman   PetscFunctionBegin;
2985c66b693SKris Buschelman 
2995c66b693SKris Buschelman   PetscValidHeaderSpecific(A,MAT_COOKIE);
3005c66b693SKris Buschelman   PetscValidType(A);
3015c66b693SKris Buschelman   MatPreallocated(A);
3025c66b693SKris Buschelman   if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3035c66b693SKris Buschelman   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3045c66b693SKris Buschelman 
3055c66b693SKris Buschelman   PetscValidHeaderSpecific(B,MAT_COOKIE);
3065c66b693SKris Buschelman   PetscValidType(B);
3075c66b693SKris Buschelman   MatPreallocated(B);
3085c66b693SKris Buschelman   if (!B->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3095c66b693SKris Buschelman   if (B->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3105c66b693SKris Buschelman 
3115c66b693SKris Buschelman   PetscValidHeaderSpecific(C,MAT_COOKIE);
3125c66b693SKris Buschelman   PetscValidType(C);
3135c66b693SKris Buschelman   MatPreallocated(C);
3145c66b693SKris Buschelman   if (!C->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3155c66b693SKris Buschelman   if (C->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3165c66b693SKris Buschelman 
3175c66b693SKris Buschelman   if (B->N!=C->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->N,C->N);
3185c66b693SKris Buschelman   if (B->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->M,A->N);
3195c66b693SKris Buschelman   if (A->M!=C->M) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",A->M,C->M);
3205c66b693SKris Buschelman 
3215c66b693SKris Buschelman   /* Query A for ApplyPtAP implementation based on types of P */
3225c66b693SKris Buschelman   ierr = PetscStrcpy(funct,"MatMatMultNumeric_");CHKERRQ(ierr);
3235c66b693SKris Buschelman   ierr = PetscStrcat(funct,A->type_name);CHKERRQ(ierr);
3245c66b693SKris Buschelman   ierr = PetscStrcat(funct,B->type_name);CHKERRQ(ierr);
3255c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,funct,(PetscVoidFunction)&numeric);CHKERRQ(ierr);
3265c66b693SKris Buschelman   if (!numeric) SETERRQ2(PETSC_ERR_SUP,
3275c66b693SKris Buschelman                          "C=A*B not implemented for A of type %s and B of type %s",
3285c66b693SKris Buschelman                          A->type_name,B->type_name);
3295c66b693SKris Buschelman   ierr = (*numeric)(A,B,C);CHKERRQ(ierr);
3305c66b693SKris Buschelman 
3315c66b693SKris Buschelman   PetscFunctionReturn(0);
3325c66b693SKris Buschelman }
3335c66b693SKris Buschelman 
334d50806bdSBarry Smith #undef __FUNCT__
33594e3eecaSKris Buschelman #define __FUNCT__ "MatMatMult_Numeric_SeqAIJ_SeqAIJ"
33694e3eecaSKris Buschelman int MatMatMult_Numeric_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat C)
337d50806bdSBarry Smith {
33894e3eecaSKris Buschelman   int        ierr,flops=0;
339d50806bdSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
340d50806bdSBarry Smith   Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data;
341d50806bdSBarry Smith   Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data;
342d50806bdSBarry Smith   int        *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj,*ci=c->i,*cj=c->j;
3435c66b693SKris Buschelman   int        am=A->M,cn=C->N;
34494e3eecaSKris Buschelman   int        i,j,k,anzi,bnzi,cnzi,brow;
345d50806bdSBarry Smith   MatScalar  *aa=a->a,*ba=b->a,*baj,*ca=c->a,*temp;
346d50806bdSBarry Smith 
347d50806bdSBarry Smith   PetscFunctionBegin;
348d50806bdSBarry Smith 
3495c66b693SKris Buschelman   /* Start timers */
350d50806bdSBarry Smith   ierr = PetscLogEventBegin(logkey_matmatmult_numeric,A,B,C,0);CHKERRQ(ierr);
35194e3eecaSKris Buschelman 
352d50806bdSBarry Smith   /* Allocate temp accumulation space to avoid searching for nonzero columns in C */
353d50806bdSBarry Smith   ierr = PetscMalloc((cn+1)*sizeof(MatScalar),&temp);CHKERRQ(ierr);
354d50806bdSBarry Smith   ierr = PetscMemzero(temp,cn*sizeof(MatScalar));CHKERRQ(ierr);
355d50806bdSBarry Smith   /* Traverse A row-wise. */
356d50806bdSBarry Smith   /* Build the ith row in C by summing over nonzero columns in A, */
357d50806bdSBarry Smith   /* the rows of B corresponding to nonzeros of A. */
358d50806bdSBarry Smith   for (i=0;i<am;i++) {
359d50806bdSBarry Smith     anzi = ai[i+1] - ai[i];
360d50806bdSBarry Smith     for (j=0;j<anzi;j++) {
361d50806bdSBarry Smith       brow = *aj++;
362d50806bdSBarry Smith       bnzi = bi[brow+1] - bi[brow];
363d50806bdSBarry Smith       bjj  = bj + bi[brow];
364d50806bdSBarry Smith       baj  = ba + bi[brow];
365d50806bdSBarry Smith       for (k=0;k<bnzi;k++) {
366d50806bdSBarry Smith         temp[bjj[k]] += (*aa)*baj[k];
367d50806bdSBarry Smith       }
368d50806bdSBarry Smith       flops += 2*bnzi;
369d50806bdSBarry Smith       aa++;
370d50806bdSBarry Smith     }
371d50806bdSBarry Smith     /* Store row back into C, and re-zero temp */
372d50806bdSBarry Smith     cnzi = ci[i+1] - ci[i];
373d50806bdSBarry Smith     for (j=0;j<cnzi;j++) {
374d50806bdSBarry Smith       ca[j] = temp[cj[j]];
375d50806bdSBarry Smith       temp[cj[j]] = 0.0;
376d50806bdSBarry Smith     }
377d50806bdSBarry Smith     ca += cnzi;
378d50806bdSBarry Smith     cj += cnzi;
379d50806bdSBarry Smith   }
380716bacf3SKris Buschelman   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
381716bacf3SKris Buschelman   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
382716bacf3SKris Buschelman 
383d50806bdSBarry Smith   /* Free temp */
384d50806bdSBarry Smith   ierr = PetscFree(temp);CHKERRQ(ierr);
385d50806bdSBarry Smith   ierr = PetscLogFlops(flops);CHKERRQ(ierr);
386d50806bdSBarry Smith   ierr = PetscLogEventEnd(logkey_matmatmult_numeric,A,B,C,0);CHKERRQ(ierr);
387d50806bdSBarry Smith   PetscFunctionReturn(0);
388d50806bdSBarry Smith }
389d50806bdSBarry Smith 
390d50806bdSBarry Smith #undef __FUNCT__
3915c66b693SKris Buschelman #define __FUNCT__ "RegisterMatMatMultRoutines_Private"
3925c66b693SKris Buschelman int RegisterMatMatMultRoutines_Private(Mat A) {
393d50806bdSBarry Smith   int ierr;
394d50806bdSBarry Smith 
395d50806bdSBarry Smith   PetscFunctionBegin;
3962216b3a4SKris Buschelman   if (!logkey_matmatmult) {
3972216b3a4SKris Buschelman     ierr = PetscLogEventRegister(&logkey_matmatmult,"MatMatMult",MAT_COOKIE);CHKERRQ(ierr);
3982216b3a4SKris Buschelman   }
3995c66b693SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatMatMult_seqaijseqaij",
4005c66b693SKris Buschelman                                            "MatMatMult_SeqAIJ_SeqAIJ",
4015c66b693SKris Buschelman                                            MatMatMult_SeqAIJ_SeqAIJ);CHKERRQ(ierr);
4025c66b693SKris Buschelman   if (!logkey_matmatmult_symbolic) {
4035c66b693SKris Buschelman     ierr = PetscLogEventRegister(&logkey_matmatmult_symbolic,"MatMatMult_Symbolic",MAT_COOKIE);CHKERRQ(ierr);
404d50806bdSBarry Smith   }
4055c66b693SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatMatMultSymbolic_seqaijseqaij",
4065c66b693SKris Buschelman                                            "MatMatMult_Symbolic_SeqAIJ_SeqAIJ",
4075c66b693SKris Buschelman                                            MatMatMult_Symbolic_SeqAIJ_SeqAIJ);CHKERRQ(ierr);
4085c66b693SKris Buschelman   if (!logkey_matmatmult_numeric) {
4095c66b693SKris Buschelman     ierr = PetscLogEventRegister(&logkey_matmatmult_numeric,"MatMatMult_Numeric",MAT_COOKIE);CHKERRQ(ierr);
41094e3eecaSKris Buschelman   }
4115c66b693SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatMatMultNumeric_seqaijseqaij",
4125c66b693SKris Buschelman                                            "MatMatMult_Numeric_SeqAIJ_SeqAIJ",
4135c66b693SKris Buschelman                                            MatMatMult_Numeric_SeqAIJ_SeqAIJ);CHKERRQ(ierr);
41494e3eecaSKris Buschelman   PetscFunctionReturn(0);
41594e3eecaSKris Buschelman }
416