/*$Id: matmatmult.c,v 1.15 2001/09/07 20:04:44 buschelm Exp $*/ /* Defines matrix-matrix product routines for pairs of SeqAIJ matrices C = A * B C = P * A * P^T */ #include "src/mat/impls/aij/seq/aij.h" #include "src/mat/utils/freespace.h" static int logkey_matmatmult = 0; static int logkey_matmatmult_symbolic = 0; static int logkey_matmatmult_numeric = 0; static int logkey_matapplypapt = 0; static int logkey_matapplypapt_symbolic = 0; static int logkey_matapplypapt_numeric = 0; /* MatMatMult_Symbolic_SeqAIJ_SeqAIJ - Forms the symbolic product of two SeqAIJ matrices C = A * B; Note: C is assumed to be uncreated. If this is not the case, Destroy C before calling this routine. */ #undef __FUNCT__ #define __FUNCT__ "MatMatMult_Symbolic_SeqAIJ_SeqAIJ" int MatMatMult_Symbolic_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat *C) { int ierr; FreeSpaceList free_space=PETSC_NULL,current_space=PETSC_NULL; Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*b=(Mat_SeqAIJ*)B->data,*c; int aishift=a->indexshift,bishift=b->indexshift; int *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj; int *ci,*cj,*denserow,*sparserow; int an=A->N,am=A->M,bn=B->N,bm=B->M; int i,j,k,anzi,brow,bnzj,cnzi; MatScalar *ca; PetscFunctionBegin; /* some error checking which could be moved into interface layer */ if (aishift || bishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); if (an!=bm) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",an,bm); /* Set up timers */ if (!logkey_matmatmult_symbolic) { ierr = PetscLogEventRegister(&logkey_matmatmult_symbolic,"MatMatMult_Symbolic",MAT_COOKIE);CHKERRQ(ierr); } ierr = PetscLogEventBegin(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr); /* Set up */ /* Allocate ci array, arrays for fill computation and */ /* free space for accumulating nonzero column info */ ierr = PetscMalloc(((am+1)+1)*sizeof(int),&ci);CHKERRQ(ierr); ci[0] = 0; ierr = PetscMalloc((2*bn+1)*sizeof(int),&denserow);CHKERRQ(ierr); ierr = PetscMemzero(denserow,(2*bn+1)*sizeof(int));CHKERRQ(ierr); sparserow = denserow + bn; /* Initial FreeSpace size is nnz(B)=bi[bm] */ ierr = GetMoreSpace(bi[bm],&free_space);CHKERRQ(ierr); current_space = free_space; /* Determine symbolic info for each row of the product: */ for (i=0;ilocal_remainingtotal_array_size,¤t_space);CHKERRQ(ierr); } /* Copy data into free space, and zero out denserow */ ierr = PetscMemcpy(current_space->array,sparserow,cnzi*sizeof(int));CHKERRQ(ierr); current_space->array += cnzi; current_space->local_used += cnzi; current_space->local_remaining -= cnzi; for (j=0;jcomm,am,bn,ci,cj,ca,C);CHKERRQ(ierr); /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ /* These are PETSc arrays, so change flags so arrays can be deleted by PETSc */ c = (Mat_SeqAIJ *)((*C)->data); c->freedata = PETSC_TRUE; c->nonew = 0; ierr = PetscLogEventEnd(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); } /* MatMatMult_Numeric_SeqAIJ_SeqAIJ - Forms the numeric product of two SeqAIJ matrices C=A*B; Note: C must have been created by calling MatMatMult_Symbolic_SeqAIJ_SeqAIJ. */ #undef __FUNCT__ #define __FUNCT__ "MatMatMult_Numeric_SeqAIJ_SeqAIJ" int MatMatMult_Numeric_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat C) { int ierr,flops=0; Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data; int aishift=a->indexshift,bishift=b->indexshift,cishift=c->indexshift; int *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj,*ci=c->i,*cj=c->j; int an=A->N,am=A->M,bn=B->N,bm=B->M,cn=C->N,cm=C->M; int i,j,k,anzi,bnzi,cnzi,brow; MatScalar *aa=a->a,*ba=b->a,*baj,*ca=c->a,*temp; PetscFunctionBegin; /* This error checking should be unnecessary if the symbolic was performed */ if (aishift || bishift || cishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); if (am!=cm) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",am,cm); if (an!=bm) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",an,bm); if (bn!=cn) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",bn,cn); /* Set up timers */ if (!logkey_matmatmult_numeric) { ierr = PetscLogEventRegister(&logkey_matmatmult_numeric,"MatMatMult_Numeric",MAT_COOKIE);CHKERRQ(ierr); } ierr = PetscLogEventBegin(logkey_matmatmult_numeric,A,B,C,0);CHKERRQ(ierr); /* Allocate temp accumulation space to avoid searching for nonzero columns in C */ ierr = PetscMalloc((cn+1)*sizeof(MatScalar),&temp);CHKERRQ(ierr); ierr = PetscMemzero(temp,cn*sizeof(MatScalar));CHKERRQ(ierr); /* Traverse A row-wise. */ /* Build the ith row in C by summing over nonzero columns in A, */ /* the rows of B corresponding to nonzeros of A. */ for (i=0;idata,*p=(Mat_SeqAIJ*)P->data,*c; int aishift=a->indexshift,pishift=p->indexshift; int *ai=a->i,*aj=a->j,*ajj,*pi=p->i,*pj=p->j,*pti,*ptj,*ptjj; int *ci,*cj,*paj,*padenserow,*pasparserow,*denserow,*sparserow; int an=A->N,am=A->M,pn=P->N,pm=P->M; int i,j,k,pnzi,arow,anzj,panzi,ptrow,ptnzj,cnzi; MatScalar *ca; PetscFunctionBegin; /* some error checking which could be moved into interface layer */ if (aishift || pishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); if (pn!=am) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pn,am); if (am!=an) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %d != %d",am, an); /* Set up timers */ if (!logkey_matapplypapt_symbolic) { ierr = PetscLogEventRegister(&logkey_matapplypapt_symbolic,"MatApplyPAPt_Symbolic",MAT_COOKIE);CHKERRQ(ierr); } ierr = PetscLogEventBegin(logkey_matapplypapt_symbolic,A,P,0,0);CHKERRQ(ierr); /* Create ij structure of P^T */ ierr = MatGetSymbolicTranspose_SeqAIJ(P,&pti,&ptj);CHKERRQ(ierr); /* Allocate ci array, arrays for fill computation and */ /* free space for accumulating nonzero column info */ ierr = PetscMalloc(((pm+1)*1)*sizeof(int),&ci);CHKERRQ(ierr); ci[0] = 0; ierr = PetscMalloc((2*an+2*pm+1)*sizeof(int),&padenserow);CHKERRQ(ierr); ierr = PetscMemzero(padenserow,(2*an+2*pm+1)*sizeof(int));CHKERRQ(ierr); pasparserow = padenserow + an; denserow = pasparserow + an; sparserow = denserow + pm; /* Set initial free space to be nnz(A) scaled by aspect ratio of Pt. */ /* This should be reasonable if sparsity of PAPt is similar to that of A. */ ierr = GetMoreSpace((ai[am]/pn)*pm,&free_space); current_space = free_space; /* Determine fill for each row of C: */ for (i=0;ilocal_remainingtotal_array_size,¤t_space);CHKERRQ(ierr); } /* Copy data into free space, and zero out dense row */ ierr = PetscMemcpy(current_space->array,sparserow,cnzi*sizeof(int));CHKERRQ(ierr); current_space->array += cnzi; current_space->local_used += cnzi; current_space->local_remaining -= cnzi; for (j=0;jcomm,pm,pm,ci,cj,ca,C);CHKERRQ(ierr); /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ /* Since these are PETSc arrays, change flags to free them as necessary. */ c = (Mat_SeqAIJ *)((*C)->data); c->freedata = PETSC_TRUE; c->nonew = 0; /* Clean up. */ ierr = MatRestoreSymbolicTranspose_SeqAIJ(P,&pti,&ptj);CHKERRQ(ierr); ierr = PetscLogEventEnd(logkey_matapplypapt_symbolic,A,P,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); } /* MatApplyPAPt_Numeric_SeqAIJ - Forms the numeric product of two SeqAIJ matrices C = P * A * P^T; Note: C must have been created by calling MatApplyPAPt_Symbolic_SeqAIJ. */ #undef __FUNCT__ #define __FUNCT__ "MatApplyPAPt_Numeric_SeqAIJ_SeqAIJ" int MatApplyPAPt_Numeric_SeqAIJ_SeqAIJ(Mat A,Mat P,Mat C) { int ierr,flops=0; Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; Mat_SeqAIJ *p = (Mat_SeqAIJ *) P->data; Mat_SeqAIJ *c = (Mat_SeqAIJ *) C->data; int aishift=a->indexshift,pishift=p->indexshift,cishift=c->indexshift; int *ai=a->i,*aj=a->j,*ajj,*pi=p->i,*pj=p->j,*pjj=p->j,*paj,*pajdense,*ptj; int *ci=c->i,*cj=c->j; int an=A->N,am=A->M,pn=P->N,pm=P->M,cn=C->N,cm=C->M; int i,j,k,k1,k2,pnzi,anzj,panzj,arow,ptcol,ptnzj,cnzi; MatScalar *aa=a->a,*pa=p->a,*pta=p->a,*ptaj,*paa,*aaj,*ca=c->a,sum; PetscFunctionBegin; /* This error checking should be unnecessary if the symbolic was performed */ if (aishift || pishift || cishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); if (pm!=cm) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pm,cm); if (pn!=am) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pn,am); if (am!=an) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %d != %d",am, an); if (pm!=cn) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pm, cn); /* Set up timers */ if (!logkey_matapplypapt_numeric) { ierr = PetscLogEventRegister(&logkey_matapplypapt_numeric,"MatApplyPAPt_Numeric",MAT_COOKIE);CHKERRQ(ierr); } ierr = PetscLogEventBegin(logkey_matapplypapt_numeric,A,P,C,0);CHKERRQ(ierr); ierr = PetscMalloc(an*(sizeof(MatScalar)+2*sizeof(int)),&paa);CHKERRQ(ierr); ierr = PetscMemzero(paa,an*(sizeof(MatScalar)+2*sizeof(int)));CHKERRQ(ierr); ierr = PetscMemzero(ca,ci[cm]*sizeof(MatScalar));CHKERRQ(ierr); paj = (int *)(paa + an); pajdense = paj + an; for (i=0;i ptj[k2]) */ { k2++; } } *ca++ = sum; } /* Zero the current row info for P*A */ for (j=0;j