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