xref: /petsc/src/mat/impls/aij/seq/matmatmult.c (revision 4d3841fd6aab5bbfbc7d95cf7b2a91f823f98fbd)
1d50806bdSBarry Smith /*
22c9ce0e5SKris Buschelman   Defines matrix-matrix product routines for pairs of SeqAIJ matrices
3d50806bdSBarry Smith           C = A * B
4d50806bdSBarry Smith */
5d50806bdSBarry Smith 
6c1f4806aSKris Buschelman #include "src/mat/impls/aij/seq/aij.h" /*I "petscmat.h" I*/
770f19b1fSKris Buschelman #include "src/mat/utils/freespace.h"
8d50806bdSBarry Smith 
92216b3a4SKris Buschelman static int logkey_matmatmult          = 0;
102216b3a4SKris Buschelman static int logkey_matmatmult_symbolic = 0;
112216b3a4SKris Buschelman static int logkey_matmatmult_numeric  = 0;
122216b3a4SKris Buschelman 
13c1f4806aSKris Buschelman #undef __FUNCT__
14c1f4806aSKris Buschelman #define __FUNCT__ "MatMatMult"
155c66b693SKris Buschelman /*@
165c66b693SKris Buschelman    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
1794e3eecaSKris Buschelman 
185c66b693SKris Buschelman    Collective on Mat
19d50806bdSBarry Smith 
205c66b693SKris Buschelman    Input Parameters:
215c66b693SKris Buschelman +  A - the left matrix
225c66b693SKris Buschelman -  B - the right matrix
235c66b693SKris Buschelman 
245c66b693SKris Buschelman    Output Parameters:
255c66b693SKris Buschelman .  C - the product matrix
265c66b693SKris Buschelman 
275c66b693SKris Buschelman    Notes:
285c66b693SKris Buschelman    C will be created and must be destroyed by the user with MatDestroy().
295c66b693SKris Buschelman 
30*4d3841fdSKris Buschelman    This routine is currently only implemented for pairs of SeqAIJ matrices and classes
31*4d3841fdSKris Buschelman    which inherit from SeqAIJ.  C will be of type MATSEQAIJ.
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);
47c9780b6fSBarry 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);
53c9780b6fSBarry 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 
62*4d3841fdSKris Buschelman   /* Currently only _seqaijseqaij is implemented, so just query for it in A and B. */
63*4d3841fdSKris Buschelman   /* When other implementations exist, attack the multiple dispatch problem. */
64*4d3841fdSKris Buschelman   ierr = PetscStrcpy(funct,"MatMatMult_seqaijseqaij");CHKERRQ(ierr);
65*4d3841fdSKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)B,funct,(PetscVoidFunction)&mult);CHKERRQ(ierr);
66*4d3841fdSKris Buschelman   if (!mult) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for B of type %s",B->type_name);
675c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,funct,(PetscVoidFunction)&mult);CHKERRQ(ierr);
68*4d3841fdSKris Buschelman   if (!mult) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for A of type %s",A->type_name);
69*4d3841fdSKris Buschelman 
705c66b693SKris Buschelman   ierr = (*mult)(A,B,C);CHKERRQ(ierr);
71d50806bdSBarry Smith   PetscFunctionReturn(0);
72d50806bdSBarry Smith }
735c66b693SKris Buschelman 
745c66b693SKris Buschelman #undef __FUNCT__
755c66b693SKris Buschelman #define __FUNCT__ "MatMatMult_SeqAIJ_SeqAIJ"
765c66b693SKris Buschelman int MatMatMult_SeqAIJ_SeqAIJ(Mat A,Mat B, Mat *C) {
775c66b693SKris Buschelman   int ierr;
78*4d3841fdSKris Buschelman   char symfunct[80],numfunct[80];
795c66b693SKris Buschelman   int (*symbolic)(Mat,Mat,Mat*),(*numeric)(Mat,Mat,Mat);
805c66b693SKris Buschelman 
815c66b693SKris Buschelman   PetscFunctionBegin;
82*4d3841fdSKris Buschelman 
83*4d3841fdSKris Buschelman   /* Currently only _seqaijseqaij is implemented, so just query for it in A and B. */
84*4d3841fdSKris Buschelman   /* When other implementations exist, attack the multiple dispatch problem. */
85*4d3841fdSKris Buschelman   ierr = PetscStrcpy(symfunct,"MatMatMultSymbolic_seqaijseqaij");CHKERRQ(ierr);
86*4d3841fdSKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)B,symfunct,(PetscVoidFunction)&symbolic);CHKERRQ(ierr);
87*4d3841fdSKris Buschelman   if (!symbolic) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for B of type %s",B->type_name);
885c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,symfunct,(PetscVoidFunction)&symbolic);CHKERRQ(ierr);
89*4d3841fdSKris Buschelman   if (!symbolic) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for A of type %s",A->type_name);
90*4d3841fdSKris Buschelman 
91*4d3841fdSKris Buschelman   ierr = PetscStrcpy(numfunct,"MatMatMultNumeric_seqaijseqaij");CHKERRQ(ierr);
925c66b693SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,numfunct,(PetscVoidFunction)&numeric);CHKERRQ(ierr);
93*4d3841fdSKris Buschelman   if (!numeric) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for A of type %s",A->type_name);
94*4d3841fdSKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)B,numfunct,(PetscVoidFunction)&numeric);CHKERRQ(ierr);
95*4d3841fdSKris Buschelman   if (!numeric) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for B of type %s",B->type_name);
96*4d3841fdSKris Buschelman 
975c66b693SKris Buschelman   ierr = PetscLogEventBegin(logkey_matmatmult,A,B,0,0);CHKERRQ(ierr);
985c66b693SKris Buschelman   ierr = (*symbolic)(A,B,C);CHKERRQ(ierr);
995c66b693SKris Buschelman   ierr = (*numeric)(A,B,*C);CHKERRQ(ierr);
1005c66b693SKris Buschelman   ierr = PetscLogEventEnd(logkey_matmatmult,A,B,0,0);CHKERRQ(ierr);
1015c66b693SKris Buschelman   PetscFunctionReturn(0);
1025c66b693SKris Buschelman }
1035c66b693SKris Buschelman 
104c1f4806aSKris Buschelman #undef __FUNCT__
105c1f4806aSKris Buschelman #define __FUNCT__ "MatMatMultSymbolic"
1065c66b693SKris Buschelman /*@
1075c66b693SKris Buschelman    MatMatMultSymbolic - Performs construction, preallocation, and computes the ij structure
1085c66b693SKris Buschelman    of the matrix-matrix product C=A*B.  Call this routine before calling MatMatMultNumeric().
1095c66b693SKris Buschelman 
1105c66b693SKris Buschelman    Collective on Mat
1115c66b693SKris Buschelman 
1125c66b693SKris Buschelman    Input Parameters:
1135c66b693SKris Buschelman +  A - the left matrix
1145c66b693SKris Buschelman -  B - the right matrix
1155c66b693SKris Buschelman 
1165c66b693SKris Buschelman    Output Parameters:
1175c66b693SKris Buschelman .  C - the matrix containing the ij structure of product matrix
1185c66b693SKris Buschelman 
1195c66b693SKris Buschelman    Notes:
120*4d3841fdSKris Buschelman    C will be created as a MATSEQAIJ matrix and must be destroyed by the user with MatDestroy().
1215c66b693SKris Buschelman 
122*4d3841fdSKris Buschelman    This routine is currently only implemented for SeqAIJ matrices and classes which inherit from SeqAIJ.
1235c66b693SKris Buschelman 
1245c66b693SKris Buschelman    Level: intermediate
1255c66b693SKris Buschelman 
1265c66b693SKris Buschelman .seealso: MatMatMult(),MatMatMultNumeric()
1275c66b693SKris Buschelman @*/
1285c66b693SKris Buschelman int MatMatMultSymbolic(Mat A,Mat B,Mat *C) {
1295c66b693SKris Buschelman   /* Perhaps this "interface" routine should be moved into the interface directory.*/
1305c66b693SKris Buschelman   /* To facilitate implementations with varying types, QueryFunction is used.*/
1315c66b693SKris Buschelman   /* It is assumed that implementations will be composed as "MatMatMultSymbolic_<type of A><type of B>". */
1325c66b693SKris Buschelman   int  ierr;
133*4d3841fdSKris Buschelman   char symfunct[80];
1345c66b693SKris Buschelman   int  (*symbolic)(Mat,Mat,Mat *);
1355c66b693SKris Buschelman 
1365c66b693SKris Buschelman   PetscFunctionBegin;
1374482741eSBarry Smith   PetscValidHeaderSpecific(A,MAT_COOKIE,1);
138c9780b6fSBarry Smith   PetscValidType(A,1);
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 
1434482741eSBarry Smith   PetscValidHeaderSpecific(B,MAT_COOKIE,2);
144c9780b6fSBarry Smith   PetscValidType(B,2);
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");
1484482741eSBarry Smith   PetscValidPointer(C,3);
1494482741eSBarry Smith 
1505c66b693SKris Buschelman 
1515c66b693SKris Buschelman   if (B->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->M,A->N);
1525c66b693SKris Buschelman 
153*4d3841fdSKris Buschelman   /* Currently only _seqaijseqaij is implemented, so just query for it in A and B. */
154*4d3841fdSKris Buschelman   /* When other implementations exist, attack the multiple dispatch problem. */
155*4d3841fdSKris Buschelman   ierr = PetscStrcpy(symfunct,"MatMatMultSymbolic_seqaijseqaij");CHKERRQ(ierr);
156*4d3841fdSKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)B,symfunct,(PetscVoidFunction)&symbolic);CHKERRQ(ierr);
157*4d3841fdSKris Buschelman   if (!symbolic) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for B of type %s",B->type_name);
158*4d3841fdSKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,symfunct,(PetscVoidFunction)&symbolic);CHKERRQ(ierr);
159*4d3841fdSKris Buschelman   if (!symbolic) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for A of type %s",A->type_name);
1605c66b693SKris Buschelman   ierr = (*symbolic)(A,B,C);CHKERRQ(ierr);
1615c66b693SKris Buschelman 
1625c66b693SKris Buschelman   PetscFunctionReturn(0);
1635c66b693SKris Buschelman }
16458c24d83SHong Zhang 
16558c24d83SHong Zhang #undef __FUNCT__
16658c24d83SHong Zhang #define __FUNCT__ "MatMatMult_Symbolic_SeqAIJ_SeqAIJ"
16758c24d83SHong Zhang int MatMatMult_Symbolic_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat *C)
16858c24d83SHong Zhang {
16958c24d83SHong Zhang   int            ierr;
17058c24d83SHong Zhang   FreeSpaceList  free_space=PETSC_NULL,current_space=PETSC_NULL;
17158c24d83SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b=(Mat_SeqAIJ*)B->data,*c;
17258c24d83SHong Zhang   int            *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj;
17358c24d83SHong Zhang   int            *ci,*cj,*lnk,idx0,idx,bcol;
1745c66b693SKris Buschelman   int            am=A->M,bn=B->N,bm=B->M;
17558c24d83SHong Zhang   int            i,j,k,anzi,brow,bnzj,cnzi;
17658c24d83SHong Zhang   MatScalar      *ca;
17758c24d83SHong Zhang 
17858c24d83SHong Zhang   PetscFunctionBegin;
1795c66b693SKris Buschelman   /* Start timers */
18058c24d83SHong Zhang   ierr = PetscLogEventBegin(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr);
18158c24d83SHong Zhang 
18258c24d83SHong Zhang   /* Set up */
18358c24d83SHong Zhang   /* Allocate ci array, arrays for fill computation and */
18458c24d83SHong Zhang   /* free space for accumulating nonzero column info */
18558c24d83SHong Zhang   ierr = PetscMalloc(((am+1)+1)*sizeof(int),&ci);CHKERRQ(ierr);
18658c24d83SHong Zhang   ci[0] = 0;
18758c24d83SHong Zhang 
18858c24d83SHong Zhang   ierr = PetscMalloc((bn+1)*sizeof(int),&lnk);CHKERRQ(ierr);
18958c24d83SHong Zhang   for (i=0; i<bn; i++) lnk[i] = -1;
19058c24d83SHong Zhang 
19158c24d83SHong Zhang   /* Initial FreeSpace size is nnz(B)=4*bi[bm] */
19258c24d83SHong Zhang   ierr = GetMoreSpace(4*bi[bm],&free_space);CHKERRQ(ierr);
19358c24d83SHong Zhang   current_space = free_space;
19458c24d83SHong Zhang 
19558c24d83SHong Zhang   /* Determine symbolic info for each row of the product: */
19658c24d83SHong Zhang   for (i=0;i<am;i++) {
19758c24d83SHong Zhang     anzi = ai[i+1] - ai[i];
19858c24d83SHong Zhang     cnzi = 0;
19958c24d83SHong Zhang     lnk[bn] = bn;
20058c24d83SHong Zhang     for (j=0;j<anzi;j++) {
20158c24d83SHong Zhang       brow = *aj++;
20258c24d83SHong Zhang       bnzj = bi[brow+1] - bi[brow];
20358c24d83SHong Zhang       bjj  = bj + bi[brow];
20458c24d83SHong Zhang       idx  = bn;
20558c24d83SHong Zhang       for (k=0;k<bnzj;k++) {
20658c24d83SHong Zhang         bcol = bjj[k];
20758c24d83SHong Zhang         if (lnk[bcol] == -1) { /* new col */
20858c24d83SHong Zhang           if (k>0) idx = bjj[k-1];
20958c24d83SHong Zhang           do {
21058c24d83SHong Zhang             idx0 = idx;
21158c24d83SHong Zhang             idx  = lnk[idx0];
21258c24d83SHong Zhang           } while (bcol > idx);
21358c24d83SHong Zhang           lnk[idx0] = bcol;
21458c24d83SHong Zhang           lnk[bcol] = idx;
21558c24d83SHong Zhang           cnzi++;
21658c24d83SHong Zhang         }
21758c24d83SHong Zhang       }
21858c24d83SHong Zhang     }
21958c24d83SHong Zhang 
22058c24d83SHong Zhang     /* If free space is not available, make more free space */
22158c24d83SHong Zhang     /* Double the amount of total space in the list */
22258c24d83SHong Zhang     if (current_space->local_remaining<cnzi) {
22358c24d83SHong Zhang       printf("...%d -th row, double space ...\n",i);
22458c24d83SHong Zhang       ierr = GetMoreSpace(current_space->total_array_size,&current_space);CHKERRQ(ierr);
22558c24d83SHong Zhang     }
22658c24d83SHong Zhang 
22758c24d83SHong Zhang     /* Copy data into free space, and zero out denserow and lnk */
22858c24d83SHong Zhang     idx = bn;
22958c24d83SHong Zhang     for (j=0; j<cnzi; j++){
23058c24d83SHong Zhang       idx0 = idx;
23158c24d83SHong Zhang       idx  = lnk[idx0];
23258c24d83SHong Zhang       *current_space->array++ = idx;
23358c24d83SHong Zhang       lnk[idx0] = -1;
23458c24d83SHong Zhang     }
23558c24d83SHong Zhang     lnk[idx] = -1;
23658c24d83SHong Zhang 
23758c24d83SHong Zhang     current_space->local_used      += cnzi;
23858c24d83SHong Zhang     current_space->local_remaining -= cnzi;
23958c24d83SHong Zhang 
24058c24d83SHong Zhang     ci[i+1] = ci[i] + cnzi;
24158c24d83SHong Zhang   }
24258c24d83SHong Zhang 
24358c24d83SHong Zhang   /* Column indices are in the list of free space */
24458c24d83SHong Zhang   /* Allocate space for cj, initialize cj, and */
24558c24d83SHong Zhang   /* destroy list of free space and other temporary array(s) */
24658c24d83SHong Zhang   ierr = PetscMalloc((ci[am]+1)*sizeof(int),&cj);CHKERRQ(ierr);
24758c24d83SHong Zhang   ierr = MakeSpaceContiguous(&free_space,cj);CHKERRQ(ierr);
24858c24d83SHong Zhang   ierr = PetscFree(lnk);CHKERRQ(ierr);
24958c24d83SHong Zhang 
25058c24d83SHong Zhang   /* Allocate space for ca */
25158c24d83SHong Zhang   ierr = PetscMalloc((ci[am]+1)*sizeof(MatScalar),&ca);CHKERRQ(ierr);
25258c24d83SHong Zhang   ierr = PetscMemzero(ca,(ci[am]+1)*sizeof(MatScalar));CHKERRQ(ierr);
25358c24d83SHong Zhang 
25458c24d83SHong Zhang   /* put together the new matrix */
25558c24d83SHong Zhang   ierr = MatCreateSeqAIJWithArrays(A->comm,am,bn,ci,cj,ca,C);CHKERRQ(ierr);
25658c24d83SHong Zhang 
25758c24d83SHong Zhang   /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */
25858c24d83SHong Zhang   /* These are PETSc arrays, so change flags so arrays can be deleted by PETSc */
25958c24d83SHong Zhang   c = (Mat_SeqAIJ *)((*C)->data);
26058c24d83SHong Zhang   c->freedata = PETSC_TRUE;
26158c24d83SHong Zhang   c->nonew    = 0;
26258c24d83SHong Zhang 
26358c24d83SHong Zhang   ierr = PetscLogEventEnd(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr);
26458c24d83SHong Zhang   PetscFunctionReturn(0);
26558c24d83SHong Zhang }
266d50806bdSBarry Smith 
267c1f4806aSKris Buschelman #undef __FUNCT__
268c1f4806aSKris Buschelman #define __FUNCT__ "MatMatMultNumeric"
2695c66b693SKris Buschelman /*@
2705c66b693SKris Buschelman    MatMatMultNumeric - Performs the numeric matrix-matrix product.
2715c66b693SKris Buschelman    Call this routine after first calling MatMatMultSymbolic().
2725c66b693SKris Buschelman 
2735c66b693SKris Buschelman    Collective on Mat
2745c66b693SKris Buschelman 
2755c66b693SKris Buschelman    Input Parameters:
2765c66b693SKris Buschelman +  A - the left matrix
2775c66b693SKris Buschelman -  B - the right matrix
2785c66b693SKris Buschelman 
2795c66b693SKris Buschelman    Output Parameters:
2805c66b693SKris Buschelman .  C - the product matrix, whose ij structure was defined from MatMatMultSymbolic().
2815c66b693SKris Buschelman 
2825c66b693SKris Buschelman    Notes:
2835c66b693SKris Buschelman    C must have been created with MatMatMultSymbolic.
2845c66b693SKris Buschelman 
2855c66b693SKris Buschelman    This routine is currently only implemented for SeqAIJ type matrices.
2865c66b693SKris Buschelman 
2875c66b693SKris Buschelman    Level: intermediate
2885c66b693SKris Buschelman 
2895c66b693SKris Buschelman .seealso: MatMatMult(),MatMatMultSymbolic()
2905c66b693SKris Buschelman @*/
2915c66b693SKris Buschelman int MatMatMultNumeric(Mat A,Mat B,Mat C){
2925c66b693SKris Buschelman   /* Perhaps this "interface" routine should be moved into the interface directory.*/
2935c66b693SKris Buschelman   /* To facilitate implementations with varying types, QueryFunction is used.*/
2945c66b693SKris Buschelman   /* It is assumed that implementations will be composed as "MatMatMultNumeric_<type of A><type of B>". */
2955c66b693SKris Buschelman   int ierr;
296*4d3841fdSKris Buschelman   char numfunct[80];
2975c66b693SKris Buschelman   int (*numeric)(Mat,Mat,Mat);
2985c66b693SKris Buschelman 
2995c66b693SKris Buschelman   PetscFunctionBegin;
3005c66b693SKris Buschelman 
3014482741eSBarry Smith   PetscValidHeaderSpecific(A,MAT_COOKIE,1);
302c9780b6fSBarry Smith   PetscValidType(A,1);
3035c66b693SKris Buschelman   MatPreallocated(A);
3045c66b693SKris Buschelman   if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3055c66b693SKris Buschelman   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3065c66b693SKris Buschelman 
3074482741eSBarry Smith   PetscValidHeaderSpecific(B,MAT_COOKIE,2);
308c9780b6fSBarry Smith   PetscValidType(B,2);
3095c66b693SKris Buschelman   MatPreallocated(B);
3105c66b693SKris Buschelman   if (!B->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3115c66b693SKris Buschelman   if (B->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3125c66b693SKris Buschelman 
3134482741eSBarry Smith   PetscValidHeaderSpecific(C,MAT_COOKIE,3);
314c9780b6fSBarry Smith   PetscValidType(C,3);
3155c66b693SKris Buschelman   MatPreallocated(C);
3165c66b693SKris Buschelman   if (!C->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3175c66b693SKris Buschelman   if (C->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3185c66b693SKris Buschelman 
3195c66b693SKris Buschelman   if (B->N!=C->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->N,C->N);
3205c66b693SKris Buschelman   if (B->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",B->M,A->N);
3215c66b693SKris Buschelman   if (A->M!=C->M) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",A->M,C->M);
3225c66b693SKris Buschelman 
323*4d3841fdSKris Buschelman   /* Currently only _seqaijseqaij is implemented, so just query for it in A and B. */
324*4d3841fdSKris Buschelman   /* When other implementations exist, attack the multiple dispatch problem. */
325*4d3841fdSKris Buschelman   ierr = PetscStrcpy(numfunct,"MatMatMultNumeric_seqaijseqaij");CHKERRQ(ierr);
326*4d3841fdSKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)A,numfunct,(PetscVoidFunction)&numeric);CHKERRQ(ierr);
327*4d3841fdSKris Buschelman   if (!numeric) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for A of type %s",A->type_name);
328*4d3841fdSKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)B,numfunct,(PetscVoidFunction)&numeric);CHKERRQ(ierr);
329*4d3841fdSKris Buschelman   if (!numeric) SETERRQ1(PETSC_ERR_SUP,"C=A*B not implemented for B of type %s",B->type_name);
330*4d3841fdSKris Buschelman 
3315c66b693SKris Buschelman   ierr = (*numeric)(A,B,C);CHKERRQ(ierr);
3325c66b693SKris Buschelman 
3335c66b693SKris Buschelman   PetscFunctionReturn(0);
3345c66b693SKris Buschelman }
3355c66b693SKris Buschelman 
336d50806bdSBarry Smith #undef __FUNCT__
33794e3eecaSKris Buschelman #define __FUNCT__ "MatMatMult_Numeric_SeqAIJ_SeqAIJ"
33894e3eecaSKris Buschelman int MatMatMult_Numeric_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat C)
339d50806bdSBarry Smith {
34094e3eecaSKris Buschelman   int        ierr,flops=0;
341d50806bdSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
342d50806bdSBarry Smith   Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data;
343d50806bdSBarry Smith   Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data;
344d50806bdSBarry Smith   int        *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj,*ci=c->i,*cj=c->j;
3455c66b693SKris Buschelman   int        am=A->M,cn=C->N;
34694e3eecaSKris Buschelman   int        i,j,k,anzi,bnzi,cnzi,brow;
347d50806bdSBarry Smith   MatScalar  *aa=a->a,*ba=b->a,*baj,*ca=c->a,*temp;
348d50806bdSBarry Smith 
349d50806bdSBarry Smith   PetscFunctionBegin;
350d50806bdSBarry Smith 
3515c66b693SKris Buschelman   /* Start timers */
352d50806bdSBarry Smith   ierr = PetscLogEventBegin(logkey_matmatmult_numeric,A,B,C,0);CHKERRQ(ierr);
35394e3eecaSKris Buschelman 
354d50806bdSBarry Smith   /* Allocate temp accumulation space to avoid searching for nonzero columns in C */
355d50806bdSBarry Smith   ierr = PetscMalloc((cn+1)*sizeof(MatScalar),&temp);CHKERRQ(ierr);
356d50806bdSBarry Smith   ierr = PetscMemzero(temp,cn*sizeof(MatScalar));CHKERRQ(ierr);
357d50806bdSBarry Smith   /* Traverse A row-wise. */
358d50806bdSBarry Smith   /* Build the ith row in C by summing over nonzero columns in A, */
359d50806bdSBarry Smith   /* the rows of B corresponding to nonzeros of A. */
360d50806bdSBarry Smith   for (i=0;i<am;i++) {
361d50806bdSBarry Smith     anzi = ai[i+1] - ai[i];
362d50806bdSBarry Smith     for (j=0;j<anzi;j++) {
363d50806bdSBarry Smith       brow = *aj++;
364d50806bdSBarry Smith       bnzi = bi[brow+1] - bi[brow];
365d50806bdSBarry Smith       bjj  = bj + bi[brow];
366d50806bdSBarry Smith       baj  = ba + bi[brow];
367d50806bdSBarry Smith       for (k=0;k<bnzi;k++) {
368d50806bdSBarry Smith         temp[bjj[k]] += (*aa)*baj[k];
369d50806bdSBarry Smith       }
370d50806bdSBarry Smith       flops += 2*bnzi;
371d50806bdSBarry Smith       aa++;
372d50806bdSBarry Smith     }
373d50806bdSBarry Smith     /* Store row back into C, and re-zero temp */
374d50806bdSBarry Smith     cnzi = ci[i+1] - ci[i];
375d50806bdSBarry Smith     for (j=0;j<cnzi;j++) {
376d50806bdSBarry Smith       ca[j] = temp[cj[j]];
377d50806bdSBarry Smith       temp[cj[j]] = 0.0;
378d50806bdSBarry Smith     }
379d50806bdSBarry Smith     ca += cnzi;
380d50806bdSBarry Smith     cj += cnzi;
381d50806bdSBarry Smith   }
382716bacf3SKris Buschelman   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
383716bacf3SKris Buschelman   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
384716bacf3SKris Buschelman 
385d50806bdSBarry Smith   /* Free temp */
386d50806bdSBarry Smith   ierr = PetscFree(temp);CHKERRQ(ierr);
387d50806bdSBarry Smith   ierr = PetscLogFlops(flops);CHKERRQ(ierr);
388d50806bdSBarry Smith   ierr = PetscLogEventEnd(logkey_matmatmult_numeric,A,B,C,0);CHKERRQ(ierr);
389d50806bdSBarry Smith   PetscFunctionReturn(0);
390d50806bdSBarry Smith }
391d50806bdSBarry Smith 
392d50806bdSBarry Smith #undef __FUNCT__
3935c66b693SKris Buschelman #define __FUNCT__ "RegisterMatMatMultRoutines_Private"
3945c66b693SKris Buschelman int RegisterMatMatMultRoutines_Private(Mat A) {
395d50806bdSBarry Smith   int ierr;
396d50806bdSBarry Smith 
397d50806bdSBarry Smith   PetscFunctionBegin;
3982216b3a4SKris Buschelman   if (!logkey_matmatmult) {
3992216b3a4SKris Buschelman     ierr = PetscLogEventRegister(&logkey_matmatmult,"MatMatMult",MAT_COOKIE);CHKERRQ(ierr);
4002216b3a4SKris Buschelman   }
4015c66b693SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatMatMult_seqaijseqaij",
4025c66b693SKris Buschelman                                            "MatMatMult_SeqAIJ_SeqAIJ",
4035c66b693SKris Buschelman                                            MatMatMult_SeqAIJ_SeqAIJ);CHKERRQ(ierr);
4045c66b693SKris Buschelman   if (!logkey_matmatmult_symbolic) {
4055c66b693SKris Buschelman     ierr = PetscLogEventRegister(&logkey_matmatmult_symbolic,"MatMatMult_Symbolic",MAT_COOKIE);CHKERRQ(ierr);
406d50806bdSBarry Smith   }
4075c66b693SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatMatMultSymbolic_seqaijseqaij",
4085c66b693SKris Buschelman                                            "MatMatMult_Symbolic_SeqAIJ_SeqAIJ",
4095c66b693SKris Buschelman                                            MatMatMult_Symbolic_SeqAIJ_SeqAIJ);CHKERRQ(ierr);
4105c66b693SKris Buschelman   if (!logkey_matmatmult_numeric) {
4115c66b693SKris Buschelman     ierr = PetscLogEventRegister(&logkey_matmatmult_numeric,"MatMatMult_Numeric",MAT_COOKIE);CHKERRQ(ierr);
41294e3eecaSKris Buschelman   }
4135c66b693SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatMatMultNumeric_seqaijseqaij",
4145c66b693SKris Buschelman                                            "MatMatMult_Numeric_SeqAIJ_SeqAIJ",
4155c66b693SKris Buschelman                                            MatMatMult_Numeric_SeqAIJ_SeqAIJ);CHKERRQ(ierr);
41694e3eecaSKris Buschelman   PetscFunctionReturn(0);
41794e3eecaSKris Buschelman }
418