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