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,¤t_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