1d50806bdSBarry Smith /*$Id: matmatmult.c,v 1.15 2001/09/07 20:04:44 buschelm Exp $*/ 2d50806bdSBarry Smith /* 3*2c9ce0e5SKris Buschelman Defines matrix-matrix product routines for pairs of SeqAIJ matrices 4d50806bdSBarry Smith C = A * B 594e3eecaSKris Buschelman C = P^T * A * P 694e3eecaSKris Buschelman C = P * A * P^T 7d50806bdSBarry Smith */ 8d50806bdSBarry Smith 9d50806bdSBarry Smith #include "src/mat/impls/aij/seq/aij.h" 10d50806bdSBarry Smith 112216b3a4SKris Buschelman static int logkey_matmatmult = 0; 122216b3a4SKris Buschelman static int logkey_matmatmult_symbolic = 0; 132216b3a4SKris Buschelman static int logkey_matmatmult_numeric = 0; 142216b3a4SKris Buschelman 1594e3eecaSKris Buschelman static int logkey_matgetsymtranspose = 0; 1694e3eecaSKris Buschelman static int logkey_mattranspose = 0; 1794e3eecaSKris Buschelman 182216b3a4SKris Buschelman static int logkey_matapplyptap = 0; 192216b3a4SKris Buschelman static int logkey_matapplyptap_symbolic = 0; 202216b3a4SKris Buschelman static int logkey_matapplyptap_numeric = 0; 212216b3a4SKris Buschelman 2294e3eecaSKris Buschelman static int logkey_matapplypapt = 0; 2394e3eecaSKris Buschelman static int logkey_matapplypapt_symbolic = 0; 2494e3eecaSKris Buschelman static int logkey_matapplypapt_numeric = 0; 2594e3eecaSKris Buschelman 26d50806bdSBarry Smith typedef struct _Space *FreeSpaceList; 27d50806bdSBarry Smith typedef struct _Space { 28d50806bdSBarry Smith FreeSpaceList more_space; 29d50806bdSBarry Smith int *array; 30d50806bdSBarry Smith int *array_head; 31d50806bdSBarry Smith int total_array_size; 32d50806bdSBarry Smith int local_used; 33d50806bdSBarry Smith int local_remaining; 34d50806bdSBarry Smith } FreeSpace; 35d50806bdSBarry Smith 36d50806bdSBarry Smith #undef __FUNCT__ 37d50806bdSBarry Smith #define __FUNCT__ "GetMoreSpace" 382216b3a4SKris Buschelman int GetMoreSpace(int size,FreeSpaceList *list) { 39d50806bdSBarry Smith FreeSpaceList a; 40d50806bdSBarry Smith int ierr; 41d50806bdSBarry Smith 42d50806bdSBarry Smith PetscFunctionBegin; 43d50806bdSBarry Smith ierr = PetscMalloc(sizeof(FreeSpace),&a);CHKERRQ(ierr); 44d50806bdSBarry Smith ierr = PetscMalloc(size*sizeof(int),&(a->array_head));CHKERRQ(ierr); 45d50806bdSBarry Smith a->array = a->array_head; 46d50806bdSBarry Smith a->local_remaining = size; 47d50806bdSBarry Smith a->local_used = 0; 48d50806bdSBarry Smith a->total_array_size = 0; 49d50806bdSBarry Smith a->more_space = NULL; 50d50806bdSBarry Smith 51d50806bdSBarry Smith if (*list) { 52d50806bdSBarry Smith (*list)->more_space = a; 53d50806bdSBarry Smith a->total_array_size = (*list)->total_array_size; 54d50806bdSBarry Smith } 55d50806bdSBarry Smith 56d50806bdSBarry Smith a->total_array_size += size; 57d50806bdSBarry Smith *list = a; 58d50806bdSBarry Smith PetscFunctionReturn(0); 59d50806bdSBarry Smith } 60d50806bdSBarry Smith 61d50806bdSBarry Smith #undef __FUNCT__ 62d50806bdSBarry Smith #define __FUNCT__ "MakeSpaceContiguous" 63d50806bdSBarry Smith int MakeSpaceContiguous(int *space,FreeSpaceList *head) { 64d50806bdSBarry Smith FreeSpaceList a; 65d50806bdSBarry Smith int ierr; 66d50806bdSBarry Smith 67d50806bdSBarry Smith PetscFunctionBegin; 68d50806bdSBarry Smith while ((*head)!=NULL) { 69d50806bdSBarry Smith a = (*head)->more_space; 70d50806bdSBarry Smith ierr = PetscMemcpy(space,(*head)->array_head,((*head)->local_used)*sizeof(int));CHKERRQ(ierr); 71d50806bdSBarry Smith space += (*head)->local_used; 72d50806bdSBarry Smith ierr = PetscFree((*head)->array_head);CHKERRQ(ierr); 73d50806bdSBarry Smith ierr = PetscFree(*head);CHKERRQ(ierr); 74d50806bdSBarry Smith *head = a; 75d50806bdSBarry Smith } 76d50806bdSBarry Smith PetscFunctionReturn(0); 77d50806bdSBarry Smith } 78d50806bdSBarry Smith 79d50806bdSBarry Smith /* 8094e3eecaSKris Buschelman MatMatMult_Symbolic_SeqAIJ_SeqAIJ - Forms the symbolic product of two SeqAIJ matrices 81d50806bdSBarry Smith C = A * B; 82d50806bdSBarry Smith 8394e3eecaSKris Buschelman Note: C is assumed to be uncreated. 84d50806bdSBarry Smith If this is not the case, Destroy C before calling this routine. 85d50806bdSBarry Smith */ 86d50806bdSBarry Smith #undef __FUNCT__ 8794e3eecaSKris Buschelman #define __FUNCT__ "MatMatMult_Symbolic_SeqAIJ_SeqAIJ" 8894e3eecaSKris Buschelman int MatMatMult_Symbolic_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat *C) 89d50806bdSBarry Smith { 90d50806bdSBarry Smith int ierr; 91d50806bdSBarry Smith FreeSpaceList free_space=PETSC_NULL,current_space=PETSC_NULL; 92d50806bdSBarry Smith Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*b=(Mat_SeqAIJ*)B->data,*c; 93d50806bdSBarry Smith int aishift=a->indexshift,bishift=b->indexshift; 94d50806bdSBarry Smith int *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj; 9594e3eecaSKris Buschelman int *ci,*cj,*denserow,*sparserow; 96d50806bdSBarry Smith int an=A->N,am=A->M,bn=B->N,bm=B->M; 97d50806bdSBarry Smith int i,j,k,anzi,brow,bnzj,cnzi; 98d50806bdSBarry Smith MatScalar *ca; 99d50806bdSBarry Smith 100d50806bdSBarry Smith PetscFunctionBegin; 101d50806bdSBarry Smith /* some error checking which could be moved into interface layer */ 102d50806bdSBarry Smith if (aishift || bishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 103d50806bdSBarry Smith if (an!=bm) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",an,bm); 104d50806bdSBarry Smith 10594e3eecaSKris Buschelman /* Set up timers */ 106d50806bdSBarry Smith if (!logkey_matmatmult_symbolic) { 107d50806bdSBarry Smith ierr = PetscLogEventRegister(&logkey_matmatmult_symbolic,"MatMatMult_Symbolic",MAT_COOKIE);CHKERRQ(ierr); 108d50806bdSBarry Smith } 109d50806bdSBarry Smith ierr = PetscLogEventBegin(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr); 110d50806bdSBarry Smith 111d50806bdSBarry Smith /* Set up */ 112d50806bdSBarry Smith /* Allocate ci array, arrays for fill computation and */ 113d50806bdSBarry Smith /* free space for accumulating nonzero column info */ 114d50806bdSBarry Smith ierr = PetscMalloc(((am+1)+1)*sizeof(int),&ci);CHKERRQ(ierr); 115d50806bdSBarry Smith ci[0] = 0; 116d50806bdSBarry Smith 11794e3eecaSKris Buschelman ierr = PetscMalloc((2*bn+1)*sizeof(int),&denserow);CHKERRQ(ierr); 11894e3eecaSKris Buschelman ierr = PetscMemzero(denserow,(2*bn+1)*sizeof(int));CHKERRQ(ierr); 11994e3eecaSKris Buschelman sparserow = denserow + bn; 120d50806bdSBarry Smith 121d50806bdSBarry Smith /* Initial FreeSpace size is nnz(B)=bi[bm] */ 122d50806bdSBarry Smith ierr = GetMoreSpace(bi[bm],&free_space);CHKERRQ(ierr); 123d50806bdSBarry Smith current_space = free_space; 124d50806bdSBarry Smith 12594e3eecaSKris Buschelman /* Determine symbolic info for each row of the product: */ 126d50806bdSBarry Smith for (i=0;i<am;i++) { 127d50806bdSBarry Smith anzi = ai[i+1] - ai[i]; 128d50806bdSBarry Smith cnzi = 0; 129d50806bdSBarry Smith for (j=0;j<anzi;j++) { 130d50806bdSBarry Smith brow = *aj++; 131d50806bdSBarry Smith bnzj = bi[brow+1] - bi[brow]; 132d50806bdSBarry Smith bjj = bj + bi[brow]; 133d50806bdSBarry Smith for (k=0;k<bnzj;k++) { 134d50806bdSBarry Smith /* If column is not marked, mark it in compressed and uncompressed locations. */ 135d50806bdSBarry Smith /* For simplicity, leave uncompressed row unsorted until finished with row, */ 136d50806bdSBarry Smith /* and increment nonzero count for this row. */ 13794e3eecaSKris Buschelman if (!denserow[bjj[k]]) { 13894e3eecaSKris Buschelman denserow[bjj[k]] = -1; 13994e3eecaSKris Buschelman sparserow[cnzi++] = bjj[k]; 140d50806bdSBarry Smith } 141d50806bdSBarry Smith } 142d50806bdSBarry Smith } 143d50806bdSBarry Smith 14494e3eecaSKris Buschelman /* sort sparserow */ 14594e3eecaSKris Buschelman ierr = PetscSortInt(cnzi,sparserow);CHKERRQ(ierr); 146d50806bdSBarry Smith 147d50806bdSBarry Smith /* If free space is not available, make more free space */ 148d50806bdSBarry Smith /* Double the amount of total space in the list */ 149d50806bdSBarry Smith if (current_space->local_remaining<cnzi) { 150d50806bdSBarry Smith ierr = GetMoreSpace(current_space->total_array_size,¤t_space);CHKERRQ(ierr); 151d50806bdSBarry Smith } 152d50806bdSBarry Smith 15394e3eecaSKris Buschelman /* Copy data into free space, and zero out denserow */ 15494e3eecaSKris Buschelman ierr = PetscMemcpy(current_space->array,sparserow,cnzi*sizeof(int));CHKERRQ(ierr); 155d50806bdSBarry Smith current_space->array += cnzi; 156d50806bdSBarry Smith current_space->local_used += cnzi; 157d50806bdSBarry Smith current_space->local_remaining -= cnzi; 158d50806bdSBarry Smith for (j=0;j<cnzi;j++) { 15994e3eecaSKris Buschelman denserow[sparserow[j]] = 0; 160d50806bdSBarry Smith } 161d50806bdSBarry Smith ci[i+1] = ci[i] + cnzi; 162d50806bdSBarry Smith } 163d50806bdSBarry Smith 16494e3eecaSKris Buschelman /* Column indices are in the list of free space */ 165d50806bdSBarry Smith /* Allocate space for cj, initialize cj, and */ 166d50806bdSBarry Smith /* destroy list of free space and other temporary array(s) */ 167d50806bdSBarry Smith ierr = PetscMalloc((ci[am]+1)*sizeof(int),&cj);CHKERRQ(ierr); 168d50806bdSBarry Smith ierr = MakeSpaceContiguous(cj,&free_space);CHKERRQ(ierr); 16994e3eecaSKris Buschelman ierr = PetscFree(denserow);CHKERRQ(ierr); 170d50806bdSBarry Smith 171d50806bdSBarry Smith /* Allocate space for ca */ 172d50806bdSBarry Smith ierr = PetscMalloc((ci[am]+1)*sizeof(MatScalar),&ca);CHKERRQ(ierr); 173d50806bdSBarry Smith ierr = PetscMemzero(ca,(ci[am]+1)*sizeof(MatScalar));CHKERRQ(ierr); 174d50806bdSBarry Smith 175d50806bdSBarry Smith /* put together the new matrix */ 176d50806bdSBarry Smith ierr = MatCreateSeqAIJWithArrays(A->comm,am,bn,ci,cj,ca,C);CHKERRQ(ierr); 177d50806bdSBarry Smith 178d50806bdSBarry Smith /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 179d50806bdSBarry Smith /* These are PETSc arrays, so change flags so arrays can be deleted by PETSc */ 180d50806bdSBarry Smith c = (Mat_SeqAIJ *)((*C)->data); 181d50806bdSBarry Smith c->freedata = PETSC_TRUE; 182d50806bdSBarry Smith c->nonew = 0; 183d50806bdSBarry Smith 184d50806bdSBarry Smith ierr = PetscLogEventEnd(logkey_matmatmult_symbolic,A,B,0,0);CHKERRQ(ierr); 185d50806bdSBarry Smith PetscFunctionReturn(0); 186d50806bdSBarry Smith } 187d50806bdSBarry Smith 188d50806bdSBarry Smith /* 18994e3eecaSKris Buschelman MatMatMult_Numeric_SeqAIJ_SeqAIJ - Forms the numeric product of two SeqAIJ matrices 190d50806bdSBarry Smith C=A*B; 19194e3eecaSKris Buschelman Note: C must have been created by calling MatMatMult_Symbolic_SeqAIJ_SeqAIJ. 192d50806bdSBarry Smith */ 193d50806bdSBarry Smith #undef __FUNCT__ 19494e3eecaSKris Buschelman #define __FUNCT__ "MatMatMult_Numeric_SeqAIJ_SeqAIJ" 19594e3eecaSKris Buschelman int MatMatMult_Numeric_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat C) 196d50806bdSBarry Smith { 19794e3eecaSKris Buschelman int ierr,flops=0; 198d50806bdSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data; 199d50806bdSBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ *)B->data; 200d50806bdSBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ *)C->data; 201d50806bdSBarry Smith int aishift=a->indexshift,bishift=b->indexshift,cishift=c->indexshift; 202d50806bdSBarry Smith int *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*bjj,*ci=c->i,*cj=c->j; 203d50806bdSBarry Smith int an=A->N,am=A->M,bn=B->N,bm=B->M,cn=C->N,cm=C->M; 20494e3eecaSKris Buschelman int i,j,k,anzi,bnzi,cnzi,brow; 205d50806bdSBarry Smith MatScalar *aa=a->a,*ba=b->a,*baj,*ca=c->a,*temp; 206d50806bdSBarry Smith 207d50806bdSBarry Smith PetscFunctionBegin; 208d50806bdSBarry Smith 209d50806bdSBarry Smith /* This error checking should be unnecessary if the symbolic was performed */ 210d50806bdSBarry Smith if (aishift || bishift || cishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 211d50806bdSBarry Smith if (am!=cm) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",am,cm); 212d50806bdSBarry Smith if (an!=bm) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",an,bm); 213d50806bdSBarry Smith if (bn!=cn) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",bn,cn); 214d50806bdSBarry Smith 21594e3eecaSKris Buschelman /* Set up timers */ 216d50806bdSBarry Smith if (!logkey_matmatmult_numeric) { 217d50806bdSBarry Smith ierr = PetscLogEventRegister(&logkey_matmatmult_numeric,"MatMatMult_Numeric",MAT_COOKIE);CHKERRQ(ierr); 218d50806bdSBarry Smith } 219d50806bdSBarry Smith ierr = PetscLogEventBegin(logkey_matmatmult_numeric,A,B,C,0);CHKERRQ(ierr); 22094e3eecaSKris Buschelman 221d50806bdSBarry Smith /* Allocate temp accumulation space to avoid searching for nonzero columns in C */ 222d50806bdSBarry Smith ierr = PetscMalloc((cn+1)*sizeof(MatScalar),&temp);CHKERRQ(ierr); 223d50806bdSBarry Smith ierr = PetscMemzero(temp,cn*sizeof(MatScalar));CHKERRQ(ierr); 224d50806bdSBarry Smith /* Traverse A row-wise. */ 225d50806bdSBarry Smith /* Build the ith row in C by summing over nonzero columns in A, */ 226d50806bdSBarry Smith /* the rows of B corresponding to nonzeros of A. */ 227d50806bdSBarry Smith for (i=0;i<am;i++) { 228d50806bdSBarry Smith anzi = ai[i+1] - ai[i]; 229d50806bdSBarry Smith for (j=0;j<anzi;j++) { 230d50806bdSBarry Smith brow = *aj++; 231d50806bdSBarry Smith bnzi = bi[brow+1] - bi[brow]; 232d50806bdSBarry Smith bjj = bj + bi[brow]; 233d50806bdSBarry Smith baj = ba + bi[brow]; 234d50806bdSBarry Smith for (k=0;k<bnzi;k++) { 235d50806bdSBarry Smith temp[bjj[k]] += (*aa)*baj[k]; 236d50806bdSBarry Smith } 237d50806bdSBarry Smith flops += 2*bnzi; 238d50806bdSBarry Smith aa++; 239d50806bdSBarry Smith } 240d50806bdSBarry Smith /* Store row back into C, and re-zero temp */ 241d50806bdSBarry Smith cnzi = ci[i+1] - ci[i]; 242d50806bdSBarry Smith for (j=0;j<cnzi;j++) { 243d50806bdSBarry Smith ca[j] = temp[cj[j]]; 244d50806bdSBarry Smith temp[cj[j]] = 0.0; 245d50806bdSBarry Smith } 246d50806bdSBarry Smith ca += cnzi; 247d50806bdSBarry Smith cj += cnzi; 248d50806bdSBarry Smith } 249716bacf3SKris Buschelman ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 250716bacf3SKris Buschelman ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 251716bacf3SKris Buschelman 252d50806bdSBarry Smith /* Free temp */ 253d50806bdSBarry Smith ierr = PetscFree(temp);CHKERRQ(ierr); 254d50806bdSBarry Smith ierr = PetscLogFlops(flops);CHKERRQ(ierr); 255d50806bdSBarry Smith ierr = PetscLogEventEnd(logkey_matmatmult_numeric,A,B,C,0);CHKERRQ(ierr); 256d50806bdSBarry Smith PetscFunctionReturn(0); 257d50806bdSBarry Smith } 258d50806bdSBarry Smith 259d50806bdSBarry Smith #undef __FUNCT__ 260d50806bdSBarry Smith #define __FUNCT__ "MatMatMult_SeqAIJ_SeqAIJ" 261d50806bdSBarry Smith int MatMatMult_SeqAIJ_SeqAIJ(Mat A,Mat B,Mat *C) { 262d50806bdSBarry Smith int ierr; 263d50806bdSBarry Smith 264d50806bdSBarry Smith PetscFunctionBegin; 2652216b3a4SKris Buschelman if (!logkey_matmatmult) { 2662216b3a4SKris Buschelman ierr = PetscLogEventRegister(&logkey_matmatmult,"MatMatMult",MAT_COOKIE);CHKERRQ(ierr); 2672216b3a4SKris Buschelman } 2682216b3a4SKris Buschelman ierr = PetscLogEventBegin(logkey_matmatmult,A,B,0,0);CHKERRQ(ierr); 26994e3eecaSKris Buschelman ierr = MatMatMult_Symbolic_SeqAIJ_SeqAIJ(A,B,C);CHKERRQ(ierr); 27094e3eecaSKris Buschelman ierr = MatMatMult_Numeric_SeqAIJ_SeqAIJ(A,B,*C);CHKERRQ(ierr); 2712216b3a4SKris Buschelman ierr = PetscLogEventEnd(logkey_matmatmult,A,B,0,0);CHKERRQ(ierr); 272d50806bdSBarry Smith PetscFunctionReturn(0); 273d50806bdSBarry Smith } 274d50806bdSBarry Smith 275d50806bdSBarry Smith #undef __FUNCT__ 27694e3eecaSKris Buschelman #define __FUNCT__ "MatGetSymbolicTranspose_SeqIJ" 27794e3eecaSKris Buschelman int MatGetSymbolicTranspose_SeqAIJ(Mat A,int *Ati[],int *Atj[]) { 27894e3eecaSKris Buschelman int ierr,i,j,anzj; 27994e3eecaSKris Buschelman Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data; 28094e3eecaSKris Buschelman int aishift = a->indexshift,an=A->N,am=A->M; 28194e3eecaSKris Buschelman int *ati,*atj,*atfill,*ai=a->i,*aj=a->j; 28294e3eecaSKris Buschelman 28394e3eecaSKris Buschelman PetscFunctionBegin; 28494e3eecaSKris Buschelman 28594e3eecaSKris Buschelman ierr = PetscLogInfo(A,"Getting Symbolic Transpose.\n");CHKERRQ(ierr); 28694e3eecaSKris Buschelman if (aishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 28794e3eecaSKris Buschelman 28894e3eecaSKris Buschelman /* Set up timers */ 28994e3eecaSKris Buschelman if (!logkey_matgetsymtranspose) { 29094e3eecaSKris Buschelman ierr = PetscLogEventRegister(&logkey_matgetsymtranspose,"MatGetSymbolicTranspose",MAT_COOKIE);CHKERRQ(ierr); 29194e3eecaSKris Buschelman } 29294e3eecaSKris Buschelman ierr = PetscLogEventBegin(logkey_matgetsymtranspose,A,0,0,0);CHKERRQ(ierr); 29394e3eecaSKris Buschelman 29494e3eecaSKris Buschelman /* Allocate space for symbolic transpose info and work array */ 29594e3eecaSKris Buschelman ierr = PetscMalloc((an+1)*sizeof(int),&ati);CHKERRQ(ierr); 29694e3eecaSKris Buschelman ierr = PetscMalloc(ai[am]*sizeof(int),&atj);CHKERRQ(ierr); 29794e3eecaSKris Buschelman ierr = PetscMalloc(an*sizeof(int),&atfill);CHKERRQ(ierr); 29894e3eecaSKris Buschelman ierr = PetscMemzero(ati,(an+1)*sizeof(int));CHKERRQ(ierr); 29994e3eecaSKris Buschelman 30094e3eecaSKris Buschelman /* Walk through aj and count ## of non-zeros in each row of A^T. */ 30194e3eecaSKris Buschelman /* Note: offset by 1 for fast conversion into csr format. */ 30294e3eecaSKris Buschelman for (i=0;i<ai[am];i++) { 30394e3eecaSKris Buschelman ati[aj[i]+1] += 1; 30494e3eecaSKris Buschelman } 30594e3eecaSKris Buschelman /* Form ati for csr format of A^T. */ 30694e3eecaSKris Buschelman for (i=0;i<an;i++) { 30794e3eecaSKris Buschelman ati[i+1] += ati[i]; 30894e3eecaSKris Buschelman } 30994e3eecaSKris Buschelman 31094e3eecaSKris Buschelman /* Copy ati into atfill so we have locations of the next free space in atj */ 31194e3eecaSKris Buschelman ierr = PetscMemcpy(atfill,ati,an*sizeof(int));CHKERRQ(ierr); 31294e3eecaSKris Buschelman 31394e3eecaSKris Buschelman /* Walk through A row-wise and mark nonzero entries of A^T. */ 31494e3eecaSKris Buschelman for (i=0;i<am;i++) { 31594e3eecaSKris Buschelman anzj = ai[i+1] - ai[i]; 31694e3eecaSKris Buschelman for (j=0;j<anzj;j++) { 31794e3eecaSKris Buschelman atj[atfill[*aj]] = i; 31894e3eecaSKris Buschelman atfill[*aj++] += 1; 31994e3eecaSKris Buschelman } 32094e3eecaSKris Buschelman } 32194e3eecaSKris Buschelman 32294e3eecaSKris Buschelman /* Clean up temporary space and complete requests. */ 32394e3eecaSKris Buschelman ierr = PetscFree(atfill);CHKERRQ(ierr); 32494e3eecaSKris Buschelman *Ati = ati; 32594e3eecaSKris Buschelman *Atj = atj; 32694e3eecaSKris Buschelman 32794e3eecaSKris Buschelman ierr = PetscLogEventEnd(logkey_matgetsymtranspose,A,0,0,0);CHKERRQ(ierr); 32894e3eecaSKris Buschelman PetscFunctionReturn(0); 32994e3eecaSKris Buschelman } 33094e3eecaSKris Buschelman 33194e3eecaSKris Buschelman extern int MatTranspose_SeqAIJ(Mat A,Mat *B); 33294e3eecaSKris Buschelman 33394e3eecaSKris Buschelman #undef __FUNCT__ 33494e3eecaSKris Buschelman #define __FUNCT__ "MatTranspose_SeqIJ_FAST" 33594e3eecaSKris Buschelman int MatTranspose_SeqAIJ_FAST(Mat A,Mat *B) { 33694e3eecaSKris Buschelman int ierr,i,j,anzj; 33794e3eecaSKris Buschelman Mat At; 33894e3eecaSKris Buschelman Mat_SeqAIJ *a=(Mat_SeqAIJ *)A->data,*at; 33994e3eecaSKris Buschelman int aishift = a->indexshift,an=A->N,am=A->M; 34094e3eecaSKris Buschelman int *ati,*atj,*atfill,*ai=a->i,*aj=a->j; 34194e3eecaSKris Buschelman MatScalar *ata,*aa=a->a; 34294e3eecaSKris Buschelman PetscFunctionBegin; 34394e3eecaSKris Buschelman 34494e3eecaSKris Buschelman if (aishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 34594e3eecaSKris Buschelman 34694e3eecaSKris Buschelman /* Set up timers */ 34794e3eecaSKris Buschelman if (!logkey_mattranspose) { 34894e3eecaSKris Buschelman ierr = PetscLogEventRegister(&logkey_mattranspose,"MatTranspose_SeqAIJ_FAST",MAT_COOKIE);CHKERRQ(ierr); 34994e3eecaSKris Buschelman } 35094e3eecaSKris Buschelman ierr = PetscLogEventBegin(logkey_mattranspose,A,0,0,0);CHKERRQ(ierr); 35194e3eecaSKris Buschelman 35294e3eecaSKris Buschelman /* Allocate space for symbolic transpose info and work array */ 35394e3eecaSKris Buschelman ierr = PetscMalloc((an+1)*sizeof(int),&ati);CHKERRQ(ierr); 35494e3eecaSKris Buschelman ierr = PetscMalloc(ai[am]*sizeof(int),&atj);CHKERRQ(ierr); 35594e3eecaSKris Buschelman ierr = PetscMalloc(ai[am]*sizeof(MatScalar),&ata);CHKERRQ(ierr); 35694e3eecaSKris Buschelman ierr = PetscMalloc(an*sizeof(int),&atfill);CHKERRQ(ierr); 35794e3eecaSKris Buschelman ierr = PetscMemzero(ati,(an+1)*sizeof(int));CHKERRQ(ierr); 35894e3eecaSKris Buschelman /* Walk through aj and count ## of non-zeros in each row of A^T. */ 35994e3eecaSKris Buschelman /* Note: offset by 1 for fast conversion into csr format. */ 36094e3eecaSKris Buschelman for (i=0;i<ai[am];i++) { 36194e3eecaSKris Buschelman ati[aj[i]+1] += 1; 36294e3eecaSKris Buschelman } 36394e3eecaSKris Buschelman /* Form ati for csr format of A^T. */ 36494e3eecaSKris Buschelman for (i=0;i<an;i++) { 36594e3eecaSKris Buschelman ati[i+1] += ati[i]; 36694e3eecaSKris Buschelman } 36794e3eecaSKris Buschelman 36894e3eecaSKris Buschelman /* Copy ati into atfill so we have locations of the next free space in atj */ 36994e3eecaSKris Buschelman ierr = PetscMemcpy(atfill,ati,an*sizeof(int));CHKERRQ(ierr); 37094e3eecaSKris Buschelman 37194e3eecaSKris Buschelman /* Walk through A row-wise and mark nonzero entries of A^T. */ 37294e3eecaSKris Buschelman for (i=0;i<am;i++) { 37394e3eecaSKris Buschelman anzj = ai[i+1] - ai[i]; 37494e3eecaSKris Buschelman for (j=0;j<anzj;j++) { 37594e3eecaSKris Buschelman atj[atfill[*aj]] = i; 37694e3eecaSKris Buschelman ata[atfill[*aj]] = *aa++; 37794e3eecaSKris Buschelman atfill[*aj++] += 1; 37894e3eecaSKris Buschelman } 37994e3eecaSKris Buschelman } 38094e3eecaSKris Buschelman 38194e3eecaSKris Buschelman /* Clean up temporary space and complete requests. */ 38294e3eecaSKris Buschelman ierr = PetscFree(atfill);CHKERRQ(ierr); 38394e3eecaSKris Buschelman ierr = MatCreateSeqAIJWithArrays(A->comm,an,am,ati,atj,ata,&At);CHKERRQ(ierr); 38494e3eecaSKris Buschelman at = (Mat_SeqAIJ *)(At->data); 38594e3eecaSKris Buschelman at->freedata = PETSC_TRUE; 38694e3eecaSKris Buschelman at->nonew = 0; 38794e3eecaSKris Buschelman if (B) { 38894e3eecaSKris Buschelman *B = At; 38994e3eecaSKris Buschelman } else { 39094e3eecaSKris Buschelman ierr = MatHeaderCopy(A,At); 39194e3eecaSKris Buschelman } 39294e3eecaSKris Buschelman ierr = PetscLogEventEnd(logkey_mattranspose,A,0,0,0);CHKERRQ(ierr); 39394e3eecaSKris Buschelman PetscFunctionReturn(0); 39494e3eecaSKris Buschelman } 39594e3eecaSKris Buschelman 39694e3eecaSKris Buschelman #undef __FUNCT__ 39794e3eecaSKris Buschelman #define __FUNCT__ "MatRestoreSymbolicTranspose" 39894e3eecaSKris Buschelman int MatRestoreSymbolicTranspose(Mat A,int *ati[],int *atj[]) { 39994e3eecaSKris Buschelman int ierr; 40094e3eecaSKris Buschelman 40194e3eecaSKris Buschelman PetscFunctionBegin; 40294e3eecaSKris Buschelman ierr = PetscLogInfo(A,"Restoring Symbolic Transpose.\n");CHKERRQ(ierr); 40394e3eecaSKris Buschelman ierr = PetscFree(*ati);CHKERRQ(ierr); 40494e3eecaSKris Buschelman ati = PETSC_NULL; 40594e3eecaSKris Buschelman ierr = PetscFree(*atj);CHKERRQ(ierr); 40694e3eecaSKris Buschelman atj = PETSC_NULL; 40794e3eecaSKris Buschelman PetscFunctionReturn(0); 40894e3eecaSKris Buschelman } 40994e3eecaSKris Buschelman 41094e3eecaSKris Buschelman /* 41194e3eecaSKris Buschelman MatApplyPtAP_Symbolic_SeqAIJ - Forms the symbolic product of two SeqAIJ matrices 41294e3eecaSKris Buschelman C = P^T * A * P; 41394e3eecaSKris Buschelman 41494e3eecaSKris Buschelman Note: C is assumed to be uncreated. 41594e3eecaSKris Buschelman If this is not the case, Destroy C before calling this routine. 41694e3eecaSKris Buschelman */ 41794e3eecaSKris Buschelman #undef __FUNCT__ 41894e3eecaSKris Buschelman #define __FUNCT__ "MatApplyPtAP_Symbolic_SeqAIJ" 41994e3eecaSKris Buschelman int MatApplyPtAP_Symbolic_SeqAIJ(Mat A,Mat P,Mat *C) { 420d50806bdSBarry Smith int ierr; 421d50806bdSBarry Smith FreeSpaceList free_space=PETSC_NULL,current_space=PETSC_NULL; 422d50806bdSBarry Smith Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*p=(Mat_SeqAIJ*)P->data,*c; 423d50806bdSBarry Smith int aishift=a->indexshift,pishift=p->indexshift; 42494e3eecaSKris Buschelman int *pti,*ptj,*ptJ,*ai=a->i,*aj=a->j,*ajj,*pi=p->i,*pj=p->j,*pjj; 42594e3eecaSKris Buschelman int *ci,*cj,*denserow,*sparserow,*ptadenserow,*ptasparserow,*ptaj; 426d50806bdSBarry Smith int an=A->N,am=A->M,pn=P->N,pm=P->M; 427d50806bdSBarry Smith int i,j,k,ptnzi,arow,anzj,ptanzi,prow,pnzj,cnzi; 428d50806bdSBarry Smith MatScalar *ca; 429d50806bdSBarry Smith 430d50806bdSBarry Smith PetscFunctionBegin; 431d50806bdSBarry Smith 432d50806bdSBarry Smith /* some error checking which could be moved into interface layer */ 433d50806bdSBarry Smith if (aishift || pishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 434d50806bdSBarry Smith if (pm!=an) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pm,an); 435d50806bdSBarry Smith if (am!=an) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %d != %d",am, an); 436d50806bdSBarry Smith 43794e3eecaSKris Buschelman /* Set up timers */ 438d50806bdSBarry Smith if (!logkey_matapplyptap_symbolic) { 439d50806bdSBarry Smith ierr = PetscLogEventRegister(&logkey_matapplyptap_symbolic,"MatApplyPtAP_Symbolic",MAT_COOKIE);CHKERRQ(ierr); 440d50806bdSBarry Smith } 441d50806bdSBarry Smith ierr = PetscLogEventBegin(logkey_matapplyptap_symbolic,A,P,0,0);CHKERRQ(ierr); 442d50806bdSBarry Smith 44394e3eecaSKris Buschelman /* Get ij structure of P^T */ 44494e3eecaSKris Buschelman ierr = MatGetSymbolicTranspose_SeqAIJ(P,&pti,&ptj);CHKERRQ(ierr); 44594e3eecaSKris Buschelman ptJ=ptj; 446d50806bdSBarry Smith 447d50806bdSBarry Smith /* Allocate ci array, arrays for fill computation and */ 448d50806bdSBarry Smith /* free space for accumulating nonzero column info */ 449d50806bdSBarry Smith ierr = PetscMalloc(((pn+1)*1)*sizeof(int),&ci);CHKERRQ(ierr); 450d50806bdSBarry Smith ci[0] = 0; 451d50806bdSBarry Smith 45294e3eecaSKris Buschelman ierr = PetscMalloc((2*pn+2*an+1)*sizeof(int),&ptadenserow);CHKERRQ(ierr); 45394e3eecaSKris Buschelman ierr = PetscMemzero(ptadenserow,(2*pn+2*an+1)*sizeof(int));CHKERRQ(ierr); 45494e3eecaSKris Buschelman ptasparserow = ptadenserow + an; 45594e3eecaSKris Buschelman denserow = ptasparserow + an; 45694e3eecaSKris Buschelman sparserow = denserow + pn; 457d50806bdSBarry Smith 458d50806bdSBarry Smith /* Set initial free space to be nnz(A) scaled by aspect ratio of P. */ 45994e3eecaSKris Buschelman /* This should be reasonable if sparsity of PtAP is similar to that of A. */ 460716bacf3SKris Buschelman ierr = GetMoreSpace((ai[am]/pm)*pn,&free_space); 461d50806bdSBarry Smith current_space = free_space; 462d50806bdSBarry Smith 46394e3eecaSKris Buschelman /* Determine symbolic info for each row of C: */ 464d50806bdSBarry Smith for (i=0;i<pn;i++) { 465d50806bdSBarry Smith ptnzi = pti[i+1] - pti[i]; 466d50806bdSBarry Smith ptanzi = 0; 46794e3eecaSKris Buschelman /* Determine symbolic row of PtA: */ 468d50806bdSBarry Smith for (j=0;j<ptnzi;j++) { 46994e3eecaSKris Buschelman arow = *ptJ++; 470d50806bdSBarry Smith anzj = ai[arow+1] - ai[arow]; 471d50806bdSBarry Smith ajj = aj + ai[arow]; 472d50806bdSBarry Smith for (k=0;k<anzj;k++) { 47394e3eecaSKris Buschelman if (!ptadenserow[ajj[k]]) { 47494e3eecaSKris Buschelman ptadenserow[ajj[k]] = -1; 47594e3eecaSKris Buschelman ptasparserow[ptanzi++] = ajj[k]; 476d50806bdSBarry Smith } 477d50806bdSBarry Smith } 478d50806bdSBarry Smith } 47994e3eecaSKris Buschelman /* Using symbolic info for row of PtA, determine symbolic info for row of C: */ 48094e3eecaSKris Buschelman ptaj = ptasparserow; 481d50806bdSBarry Smith cnzi = 0; 482d50806bdSBarry Smith for (j=0;j<ptanzi;j++) { 483d50806bdSBarry Smith prow = *ptaj++; 484d50806bdSBarry Smith pnzj = pi[prow+1] - pi[prow]; 485d50806bdSBarry Smith pjj = pj + pi[prow]; 486d50806bdSBarry Smith for (k=0;k<pnzj;k++) { 48794e3eecaSKris Buschelman if (!denserow[pjj[k]]) { 48894e3eecaSKris Buschelman denserow[pjj[k]] = -1; 48994e3eecaSKris Buschelman sparserow[cnzi++] = pjj[k]; 490d50806bdSBarry Smith } 491d50806bdSBarry Smith } 492d50806bdSBarry Smith } 493d50806bdSBarry Smith 49494e3eecaSKris Buschelman /* sort sparserow */ 49594e3eecaSKris Buschelman ierr = PetscSortInt(cnzi,sparserow);CHKERRQ(ierr); 496d50806bdSBarry Smith 497d50806bdSBarry Smith /* If free space is not available, make more free space */ 498d50806bdSBarry Smith /* Double the amount of total space in the list */ 499d50806bdSBarry Smith if (current_space->local_remaining<cnzi) { 500d50806bdSBarry Smith ierr = GetMoreSpace(current_space->total_array_size,¤t_space);CHKERRQ(ierr); 501d50806bdSBarry Smith } 502d50806bdSBarry Smith 50394e3eecaSKris Buschelman /* Copy data into free space, and zero out denserows */ 50494e3eecaSKris Buschelman ierr = PetscMemcpy(current_space->array,sparserow,cnzi*sizeof(int));CHKERRQ(ierr); 505d50806bdSBarry Smith current_space->array += cnzi; 506d50806bdSBarry Smith current_space->local_used += cnzi; 507d50806bdSBarry Smith current_space->local_remaining -= cnzi; 508d50806bdSBarry Smith 509d50806bdSBarry Smith for (j=0;j<ptanzi;j++) { 51094e3eecaSKris Buschelman ptadenserow[ptasparserow[j]] = 0; 511d50806bdSBarry Smith } 512d50806bdSBarry Smith for (j=0;j<cnzi;j++) { 51394e3eecaSKris Buschelman denserow[sparserow[j]] = 0; 514d50806bdSBarry Smith } 515d50806bdSBarry Smith /* Aside: Perhaps we should save the pta info for the numerical factorization. */ 516d50806bdSBarry Smith /* For now, we will recompute what is needed. */ 517d50806bdSBarry Smith ci[i+1] = ci[i] + cnzi; 518d50806bdSBarry Smith } 519d50806bdSBarry Smith /* nnz is now stored in ci[ptm], column indices are in the list of free space */ 520d50806bdSBarry Smith /* Allocate space for cj, initialize cj, and */ 521d50806bdSBarry Smith /* destroy list of free space and other temporary array(s) */ 522d50806bdSBarry Smith ierr = PetscMalloc((ci[pn]+1)*sizeof(int),&cj);CHKERRQ(ierr); 523d50806bdSBarry Smith ierr = MakeSpaceContiguous(cj,&free_space);CHKERRQ(ierr); 52494e3eecaSKris Buschelman ierr = PetscFree(ptadenserow);CHKERRQ(ierr); 525d50806bdSBarry Smith 526d50806bdSBarry Smith /* Allocate space for ca */ 527d50806bdSBarry Smith ierr = PetscMalloc((ci[pn]+1)*sizeof(MatScalar),&ca);CHKERRQ(ierr); 528d50806bdSBarry Smith ierr = PetscMemzero(ca,(ci[pn]+1)*sizeof(MatScalar));CHKERRQ(ierr); 529d50806bdSBarry Smith 530d50806bdSBarry Smith /* put together the new matrix */ 531d50806bdSBarry Smith ierr = MatCreateSeqAIJWithArrays(A->comm,pn,pn,ci,cj,ca,C);CHKERRQ(ierr); 532d50806bdSBarry Smith 533d50806bdSBarry Smith /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 534d50806bdSBarry Smith /* Since these are PETSc arrays, change flags to free them as necessary. */ 535d50806bdSBarry Smith c = (Mat_SeqAIJ *)((*C)->data); 536d50806bdSBarry Smith c->freedata = PETSC_TRUE; 537d50806bdSBarry Smith c->nonew = 0; 538d50806bdSBarry Smith 539d50806bdSBarry Smith /* Clean up. */ 54094e3eecaSKris Buschelman ierr = MatRestoreSymbolicTranspose(P,&pti,&ptj);CHKERRQ(ierr); 541d50806bdSBarry Smith 542d50806bdSBarry Smith ierr = PetscLogEventEnd(logkey_matapplyptap_symbolic,A,P,0,0);CHKERRQ(ierr); 543d50806bdSBarry Smith PetscFunctionReturn(0); 544d50806bdSBarry Smith } 545d50806bdSBarry Smith 54694e3eecaSKris Buschelman /* 54794e3eecaSKris Buschelman MatApplyPtAP_Numeric_SeqAIJ - Forms the numeric product of two SeqAIJ matrices 54894e3eecaSKris Buschelman C = P^T * A * P; 54994e3eecaSKris Buschelman Note: C must have been created by calling MatApplyPtAP_Symbolic_SeqAIJ. 55094e3eecaSKris Buschelman */ 551d50806bdSBarry Smith #undef __FUNCT__ 55294e3eecaSKris Buschelman #define __FUNCT__ "MatApplyPtAP_Numeric_SeqAIJ" 55394e3eecaSKris Buschelman int MatApplyPtAP_Numeric_SeqAIJ(Mat A,Mat P,Mat C) { 55494e3eecaSKris Buschelman int ierr,flops=0; 555d50806bdSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 556d50806bdSBarry Smith Mat_SeqAIJ *p = (Mat_SeqAIJ *) P->data; 557d50806bdSBarry Smith Mat_SeqAIJ *c = (Mat_SeqAIJ *) C->data; 558d50806bdSBarry Smith int aishift=a->indexshift,pishift=p->indexshift,cishift=c->indexshift; 559716bacf3SKris Buschelman int *ai=a->i,*aj=a->j,*apj,*apjdense,*pi=p->i,*pj=p->j,*pJ=p->j,*pjj; 560716bacf3SKris Buschelman int *ci=c->i,*cj=c->j,*cjj; 561d50806bdSBarry Smith int an=A->N,am=A->M,pn=P->N,pm=P->M,cn=C->N,cm=C->M; 56294e3eecaSKris Buschelman int i,j,k,anzi,pnzi,apnzj,nextap,pnzj,cnzj,prow,crow; 563d50806bdSBarry Smith MatScalar *aa=a->a,*apa,*pa=p->a,*pA=p->a,*paj,*ca=c->a,*caj; 564d50806bdSBarry Smith 565d50806bdSBarry Smith PetscFunctionBegin; 566d50806bdSBarry Smith 567d50806bdSBarry Smith /* This error checking should be unnecessary if the symbolic was performed */ 568d50806bdSBarry Smith if (aishift || pishift || cishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 569d50806bdSBarry Smith if (pn!=cm) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pn,cm); 570d50806bdSBarry Smith if (pm!=an) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pm,an); 571d50806bdSBarry Smith if (am!=an) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %d != %d",am, an); 572d50806bdSBarry Smith if (pn!=cn) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pn, cn); 573d50806bdSBarry Smith 57494e3eecaSKris Buschelman /* Set up timers */ 575d50806bdSBarry Smith if (!logkey_matapplyptap_numeric) { 576d50806bdSBarry Smith ierr = PetscLogEventRegister(&logkey_matapplyptap_numeric,"MatApplyPtAP_Numeric",MAT_COOKIE);CHKERRQ(ierr); 577d50806bdSBarry Smith } 578d50806bdSBarry Smith ierr = PetscLogEventBegin(logkey_matapplyptap_numeric,A,P,C,0);CHKERRQ(ierr); 579d50806bdSBarry Smith 580716bacf3SKris Buschelman ierr = PetscMalloc(cn*(sizeof(MatScalar)+2*sizeof(int)),&apa);CHKERRQ(ierr); 581716bacf3SKris Buschelman ierr = PetscMemzero(apa,cn*(sizeof(MatScalar)+2*sizeof(int)));CHKERRQ(ierr); 582d50806bdSBarry Smith ierr = PetscMemzero(ca,ci[cm]*sizeof(MatScalar));CHKERRQ(ierr); 583d50806bdSBarry Smith 584716bacf3SKris Buschelman apj = (int *)(apa + cn); 585716bacf3SKris Buschelman apjdense = apj + cn; 586716bacf3SKris Buschelman 587d50806bdSBarry Smith for (i=0;i<am;i++) { 588d50806bdSBarry Smith /* Form sparse row of A*P */ 589d50806bdSBarry Smith anzi = ai[i+1] - ai[i]; 590d50806bdSBarry Smith apnzj = 0; 591d50806bdSBarry Smith for (j=0;j<anzi;j++) { 592d50806bdSBarry Smith prow = *aj++; 593d50806bdSBarry Smith pnzj = pi[prow+1] - pi[prow]; 594d50806bdSBarry Smith pjj = pj + pi[prow]; 595d50806bdSBarry Smith paj = pa + pi[prow]; 596d50806bdSBarry Smith for (k=0;k<pnzj;k++) { 597716bacf3SKris Buschelman if (!apjdense[pjj[k]]) { 598716bacf3SKris Buschelman apjdense[pjj[k]] = -1; 599d50806bdSBarry Smith apj[apnzj++] = pjj[k]; 600d50806bdSBarry Smith } 601d50806bdSBarry Smith apa[pjj[k]] += (*aa)*paj[k]; 602d50806bdSBarry Smith } 603d50806bdSBarry Smith flops += 2*pnzj; 604d50806bdSBarry Smith aa++; 605d50806bdSBarry Smith } 606d50806bdSBarry Smith 607d50806bdSBarry Smith /* Sort the j index array for quick sparse axpy. */ 608d50806bdSBarry Smith ierr = PetscSortInt(apnzj,apj);CHKERRQ(ierr); 609d50806bdSBarry Smith 610d50806bdSBarry Smith /* Compute P^T*A*P using outer product (P^T)[:,j]*(A*P)[j,:]. */ 611d50806bdSBarry Smith pnzi = pi[i+1] - pi[i]; 612d50806bdSBarry Smith for (j=0;j<pnzi;j++) { 61394e3eecaSKris Buschelman nextap = 0; 614d50806bdSBarry Smith crow = *pJ++; 615d50806bdSBarry Smith cnzj = ci[crow+1] - ci[crow]; 616d50806bdSBarry Smith cjj = cj + ci[crow]; 617d50806bdSBarry Smith caj = ca + ci[crow]; 61894e3eecaSKris Buschelman /* Perform sparse axpy operation. Note cjj includes apj. */ 619716bacf3SKris Buschelman for (k=0;nextap<apnzj;k++) { 620d50806bdSBarry Smith if (cjj[k]==apj[nextap]) { 621d50806bdSBarry Smith caj[k] += (*pA)*apa[apj[nextap++]]; 622d50806bdSBarry Smith } 623d50806bdSBarry Smith } 624d50806bdSBarry Smith flops += 2*apnzj; 625d50806bdSBarry Smith pA++; 626d50806bdSBarry Smith } 627d50806bdSBarry Smith 628716bacf3SKris Buschelman /* Zero the current row info for A*P */ 629d50806bdSBarry Smith for (j=0;j<apnzj;j++) { 630d50806bdSBarry Smith apa[apj[j]] = 0.; 631716bacf3SKris Buschelman apjdense[apj[j]] = 0; 632d50806bdSBarry Smith } 633d50806bdSBarry Smith } 6342216b3a4SKris Buschelman 6352216b3a4SKris Buschelman /* Assemble the final matrix and clean up */ 6362216b3a4SKris Buschelman ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 6372216b3a4SKris Buschelman ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 638d50806bdSBarry Smith ierr = PetscFree(apa);CHKERRQ(ierr); 639d50806bdSBarry Smith ierr = PetscLogFlops(flops);CHKERRQ(ierr); 640d50806bdSBarry Smith ierr = PetscLogEventEnd(logkey_matapplyptap_numeric,A,P,C,0);CHKERRQ(ierr); 6412216b3a4SKris Buschelman 642d50806bdSBarry Smith PetscFunctionReturn(0); 643d50806bdSBarry Smith } 644d50806bdSBarry Smith 64594e3eecaSKris Buschelman 646d50806bdSBarry Smith #undef __FUNCT__ 647d50806bdSBarry Smith #define __FUNCT__ "MatApplyPtAP_SeqAIJ" 648d50806bdSBarry Smith int MatApplyPtAP_SeqAIJ(Mat A,Mat P,Mat *C) { 649d50806bdSBarry Smith int ierr; 650d50806bdSBarry Smith 651d50806bdSBarry Smith PetscFunctionBegin; 652716bacf3SKris Buschelman if (!logkey_matapplyptap) { 653716bacf3SKris Buschelman ierr = PetscLogEventRegister(&logkey_matapplyptap,"MatApplyPtAP",MAT_COOKIE);CHKERRQ(ierr); 654716bacf3SKris Buschelman } 6552216b3a4SKris Buschelman ierr = PetscLogEventBegin(logkey_matapplyptap,A,P,0,0);CHKERRQ(ierr); 65694e3eecaSKris Buschelman 65794e3eecaSKris Buschelman ierr = MatApplyPtAP_Symbolic_SeqAIJ(A,P,C);CHKERRQ(ierr); 65894e3eecaSKris Buschelman ierr = MatApplyPtAP_Numeric_SeqAIJ(A,P,*C);CHKERRQ(ierr); 65994e3eecaSKris Buschelman 6602216b3a4SKris Buschelman ierr = PetscLogEventEnd(logkey_matapplyptap,A,P,0,0);CHKERRQ(ierr); 661d50806bdSBarry Smith PetscFunctionReturn(0); 662d50806bdSBarry Smith } 66394e3eecaSKris Buschelman 66494e3eecaSKris Buschelman /* 66594e3eecaSKris Buschelman MatApplyPAPt_Symbolic_SeqAIJ - Forms the symbolic product of two SeqAIJ matrices 66694e3eecaSKris Buschelman C = P * A * P^T; 66794e3eecaSKris Buschelman 66894e3eecaSKris Buschelman Note: C is assumed to be uncreated. 66994e3eecaSKris Buschelman If this is not the case, Destroy C before calling this routine. 67094e3eecaSKris Buschelman */ 67194e3eecaSKris Buschelman #undef __FUNCT__ 67294e3eecaSKris Buschelman #define __FUNCT__ "MatApplyPAPt_Symbolic_SeqAIJ" 67394e3eecaSKris Buschelman int MatApplyPAPt_Symbolic_SeqAIJ(Mat A,Mat P,Mat *C) { 67494e3eecaSKris Buschelman /* Note: This code is virtually identical to that of MatApplyPtAP_SeqAIJ_Symbolic */ 67594e3eecaSKris Buschelman /* and MatMatMult_SeqAIJ_SeqAIJ_Symbolic. Perhaps they could be merged nicely. */ 67694e3eecaSKris Buschelman int ierr; 67794e3eecaSKris Buschelman FreeSpaceList free_space=PETSC_NULL,current_space=PETSC_NULL; 67894e3eecaSKris Buschelman Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*p=(Mat_SeqAIJ*)P->data,*c; 67994e3eecaSKris Buschelman int aishift=a->indexshift,pishift=p->indexshift; 68094e3eecaSKris Buschelman int *ai=a->i,*aj=a->j,*ajj,*pi=p->i,*pj=p->j,*pti,*ptj,*ptjj; 68194e3eecaSKris Buschelman int *ci,*cj,*paj,*padenserow,*pasparserow,*denserow,*sparserow; 68294e3eecaSKris Buschelman int an=A->N,am=A->M,pn=P->N,pm=P->M; 68394e3eecaSKris Buschelman int i,j,k,pnzi,arow,anzj,panzi,ptrow,ptnzj,cnzi; 68494e3eecaSKris Buschelman MatScalar *ca; 68594e3eecaSKris Buschelman 68694e3eecaSKris Buschelman PetscFunctionBegin; 68794e3eecaSKris Buschelman 68894e3eecaSKris Buschelman /* some error checking which could be moved into interface layer */ 68994e3eecaSKris Buschelman if (aishift || pishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 69094e3eecaSKris Buschelman if (pn!=am) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pn,am); 69194e3eecaSKris Buschelman if (am!=an) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %d != %d",am, an); 69294e3eecaSKris Buschelman 69394e3eecaSKris Buschelman /* Set up timers */ 69494e3eecaSKris Buschelman if (!logkey_matapplypapt_symbolic) { 69594e3eecaSKris Buschelman ierr = PetscLogEventRegister(&logkey_matapplypapt_symbolic,"MatApplyPAPt_Symbolic",MAT_COOKIE);CHKERRQ(ierr); 69694e3eecaSKris Buschelman } 69794e3eecaSKris Buschelman ierr = PetscLogEventBegin(logkey_matapplypapt_symbolic,A,P,0,0);CHKERRQ(ierr); 69894e3eecaSKris Buschelman 69994e3eecaSKris Buschelman /* Create ij structure of P^T */ 70094e3eecaSKris Buschelman ierr = MatGetSymbolicTranspose_SeqAIJ(P,&pti,&ptj);CHKERRQ(ierr); 70194e3eecaSKris Buschelman 70294e3eecaSKris Buschelman /* Allocate ci array, arrays for fill computation and */ 70394e3eecaSKris Buschelman /* free space for accumulating nonzero column info */ 70494e3eecaSKris Buschelman ierr = PetscMalloc(((pm+1)*1)*sizeof(int),&ci);CHKERRQ(ierr); 70594e3eecaSKris Buschelman ci[0] = 0; 70694e3eecaSKris Buschelman 70794e3eecaSKris Buschelman ierr = PetscMalloc((2*an+2*pm+1)*sizeof(int),&padenserow);CHKERRQ(ierr); 70894e3eecaSKris Buschelman ierr = PetscMemzero(padenserow,(2*an+2*pm+1)*sizeof(int));CHKERRQ(ierr); 70994e3eecaSKris Buschelman pasparserow = padenserow + an; 71094e3eecaSKris Buschelman denserow = pasparserow + an; 71194e3eecaSKris Buschelman sparserow = denserow + pm; 71294e3eecaSKris Buschelman 71394e3eecaSKris Buschelman /* Set initial free space to be nnz(A) scaled by aspect ratio of Pt. */ 71494e3eecaSKris Buschelman /* This should be reasonable if sparsity of PAPt is similar to that of A. */ 71594e3eecaSKris Buschelman ierr = GetMoreSpace((ai[am]/pn)*pm,&free_space); 71694e3eecaSKris Buschelman current_space = free_space; 71794e3eecaSKris Buschelman 71894e3eecaSKris Buschelman /* Determine fill for each row of C: */ 71994e3eecaSKris Buschelman for (i=0;i<pm;i++) { 72094e3eecaSKris Buschelman pnzi = pi[i+1] - pi[i]; 72194e3eecaSKris Buschelman panzi = 0; 72294e3eecaSKris Buschelman /* Get symbolic sparse row of PA: */ 72394e3eecaSKris Buschelman for (j=0;j<pnzi;j++) { 72494e3eecaSKris Buschelman arow = *pj++; 72594e3eecaSKris Buschelman anzj = ai[arow+1] - ai[arow]; 72694e3eecaSKris Buschelman ajj = aj + ai[arow]; 72794e3eecaSKris Buschelman for (k=0;k<anzj;k++) { 72894e3eecaSKris Buschelman if (!padenserow[ajj[k]]) { 72994e3eecaSKris Buschelman padenserow[ajj[k]] = -1; 73094e3eecaSKris Buschelman pasparserow[panzi++] = ajj[k]; 73194e3eecaSKris Buschelman } 73294e3eecaSKris Buschelman } 73394e3eecaSKris Buschelman } 73494e3eecaSKris Buschelman /* Using symbolic row of PA, determine symbolic row of C: */ 73594e3eecaSKris Buschelman paj = pasparserow; 73694e3eecaSKris Buschelman cnzi = 0; 73794e3eecaSKris Buschelman for (j=0;j<panzi;j++) { 73894e3eecaSKris Buschelman ptrow = *paj++; 73994e3eecaSKris Buschelman ptnzj = pti[ptrow+1] - pti[ptrow]; 74094e3eecaSKris Buschelman ptjj = ptj + pti[ptrow]; 74194e3eecaSKris Buschelman for (k=0;k<ptnzj;k++) { 74294e3eecaSKris Buschelman if (!denserow[ptjj[k]]) { 74394e3eecaSKris Buschelman denserow[ptjj[k]] = -1; 74494e3eecaSKris Buschelman sparserow[cnzi++] = ptjj[k]; 74594e3eecaSKris Buschelman } 74694e3eecaSKris Buschelman } 74794e3eecaSKris Buschelman } 74894e3eecaSKris Buschelman 74994e3eecaSKris Buschelman /* sort sparse representation */ 75094e3eecaSKris Buschelman ierr = PetscSortInt(cnzi,sparserow);CHKERRQ(ierr); 75194e3eecaSKris Buschelman 75294e3eecaSKris Buschelman /* If free space is not available, make more free space */ 75394e3eecaSKris Buschelman /* Double the amount of total space in the list */ 75494e3eecaSKris Buschelman if (current_space->local_remaining<cnzi) { 75594e3eecaSKris Buschelman ierr = GetMoreSpace(current_space->total_array_size,¤t_space);CHKERRQ(ierr); 75694e3eecaSKris Buschelman } 75794e3eecaSKris Buschelman 75894e3eecaSKris Buschelman /* Copy data into free space, and zero out dense row */ 75994e3eecaSKris Buschelman ierr = PetscMemcpy(current_space->array,sparserow,cnzi*sizeof(int));CHKERRQ(ierr); 76094e3eecaSKris Buschelman current_space->array += cnzi; 76194e3eecaSKris Buschelman current_space->local_used += cnzi; 76294e3eecaSKris Buschelman current_space->local_remaining -= cnzi; 76394e3eecaSKris Buschelman 76494e3eecaSKris Buschelman for (j=0;j<panzi;j++) { 76594e3eecaSKris Buschelman padenserow[pasparserow[j]] = 0; 76694e3eecaSKris Buschelman } 76794e3eecaSKris Buschelman for (j=0;j<cnzi;j++) { 76894e3eecaSKris Buschelman denserow[sparserow[j]] = 0; 76994e3eecaSKris Buschelman } 77094e3eecaSKris Buschelman ci[i+1] = ci[i] + cnzi; 77194e3eecaSKris Buschelman } 77294e3eecaSKris Buschelman /* column indices are in the list of free space */ 77394e3eecaSKris Buschelman /* Allocate space for cj, initialize cj, and */ 77494e3eecaSKris Buschelman /* destroy list of free space and other temporary array(s) */ 77594e3eecaSKris Buschelman ierr = PetscMalloc((ci[pm]+1)*sizeof(int),&cj);CHKERRQ(ierr); 77694e3eecaSKris Buschelman ierr = MakeSpaceContiguous(cj,&free_space);CHKERRQ(ierr); 77794e3eecaSKris Buschelman ierr = PetscFree(padenserow);CHKERRQ(ierr); 77894e3eecaSKris Buschelman 77994e3eecaSKris Buschelman /* Allocate space for ca */ 78094e3eecaSKris Buschelman ierr = PetscMalloc((ci[pm]+1)*sizeof(MatScalar),&ca);CHKERRQ(ierr); 78194e3eecaSKris Buschelman ierr = PetscMemzero(ca,(ci[pm]+1)*sizeof(MatScalar));CHKERRQ(ierr); 78294e3eecaSKris Buschelman 78394e3eecaSKris Buschelman /* put together the new matrix */ 78494e3eecaSKris Buschelman ierr = MatCreateSeqAIJWithArrays(A->comm,pm,pm,ci,cj,ca,C);CHKERRQ(ierr); 78594e3eecaSKris Buschelman 78694e3eecaSKris Buschelman /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 78794e3eecaSKris Buschelman /* Since these are PETSc arrays, change flags to free them as necessary. */ 78894e3eecaSKris Buschelman c = (Mat_SeqAIJ *)((*C)->data); 78994e3eecaSKris Buschelman c->freedata = PETSC_TRUE; 79094e3eecaSKris Buschelman c->nonew = 0; 79194e3eecaSKris Buschelman 79294e3eecaSKris Buschelman /* Clean up. */ 79394e3eecaSKris Buschelman ierr = MatRestoreSymbolicTranspose(P,&pti,&ptj);CHKERRQ(ierr); 79494e3eecaSKris Buschelman 79594e3eecaSKris Buschelman ierr = PetscLogEventEnd(logkey_matapplypapt_symbolic,A,P,0,0);CHKERRQ(ierr); 79694e3eecaSKris Buschelman PetscFunctionReturn(0); 79794e3eecaSKris Buschelman } 79894e3eecaSKris Buschelman 79994e3eecaSKris Buschelman /* 80094e3eecaSKris Buschelman MatApplyPAPt_Numeric_SeqAIJ - Forms the numeric product of two SeqAIJ matrices 80194e3eecaSKris Buschelman C = P * A * P^T; 80294e3eecaSKris Buschelman Note: C must have been created by calling MatApplyPAPt_Symbolic_SeqAIJ. 80394e3eecaSKris Buschelman */ 80494e3eecaSKris Buschelman #undef __FUNCT__ 80594e3eecaSKris Buschelman #define __FUNCT__ "MatApplyPAPt_Numeric_SeqAIJ" 80694e3eecaSKris Buschelman int MatApplyPAPt_Numeric_SeqAIJ(Mat A,Mat P,Mat C) { 80794e3eecaSKris Buschelman int ierr,flops=0; 80894e3eecaSKris Buschelman Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 80994e3eecaSKris Buschelman Mat_SeqAIJ *p = (Mat_SeqAIJ *) P->data; 81094e3eecaSKris Buschelman Mat_SeqAIJ *c = (Mat_SeqAIJ *) C->data; 81194e3eecaSKris Buschelman int aishift=a->indexshift,pishift=p->indexshift,cishift=c->indexshift; 81294e3eecaSKris Buschelman int *ai=a->i,*aj=a->j,*ajj,*pi=p->i,*pj=p->j,*pjj=p->j,*paj,*pajdense,*ptj; 81394e3eecaSKris Buschelman int *ci=c->i,*cj=c->j; 81494e3eecaSKris Buschelman int an=A->N,am=A->M,pn=P->N,pm=P->M,cn=C->N,cm=C->M; 81594e3eecaSKris Buschelman int i,j,k,k1,k2,pnzi,anzj,panzj,arow,ptcol,ptnzj,cnzi; 81694e3eecaSKris Buschelman MatScalar *aa=a->a,*pa=p->a,*pta=p->a,*ptaj,*paa,*aaj,*ca=c->a,sum; 81794e3eecaSKris Buschelman 81894e3eecaSKris Buschelman PetscFunctionBegin; 81994e3eecaSKris Buschelman 82094e3eecaSKris Buschelman /* This error checking should be unnecessary if the symbolic was performed */ 82194e3eecaSKris Buschelman if (aishift || pishift || cishift) SETERRQ(PETSC_ERR_SUP,"Shifted matrix indices are not supported."); 82294e3eecaSKris Buschelman if (pm!=cm) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pm,cm); 82394e3eecaSKris Buschelman if (pn!=am) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pn,am); 82494e3eecaSKris Buschelman if (am!=an) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %d != %d",am, an); 82594e3eecaSKris Buschelman if (pm!=cn) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",pm, cn); 82694e3eecaSKris Buschelman 82794e3eecaSKris Buschelman /* Set up timers */ 82894e3eecaSKris Buschelman if (!logkey_matapplypapt_numeric) { 82994e3eecaSKris Buschelman ierr = PetscLogEventRegister(&logkey_matapplypapt_numeric,"MatApplyPAPt_Numeric",MAT_COOKIE);CHKERRQ(ierr); 83094e3eecaSKris Buschelman } 83194e3eecaSKris Buschelman ierr = PetscLogEventBegin(logkey_matapplypapt_numeric,A,P,C,0);CHKERRQ(ierr); 83294e3eecaSKris Buschelman 83394e3eecaSKris Buschelman ierr = PetscMalloc(an*(sizeof(MatScalar)+2*sizeof(int)),&paa);CHKERRQ(ierr); 83494e3eecaSKris Buschelman ierr = PetscMemzero(paa,an*(sizeof(MatScalar)+2*sizeof(int)));CHKERRQ(ierr); 83594e3eecaSKris Buschelman ierr = PetscMemzero(ca,ci[cm]*sizeof(MatScalar));CHKERRQ(ierr); 83694e3eecaSKris Buschelman 83794e3eecaSKris Buschelman paj = (int *)(paa + an); 83894e3eecaSKris Buschelman pajdense = paj + an; 83994e3eecaSKris Buschelman 84094e3eecaSKris Buschelman for (i=0;i<pm;i++) { 84194e3eecaSKris Buschelman /* Form sparse row of P*A */ 84294e3eecaSKris Buschelman pnzi = pi[i+1] - pi[i]; 84394e3eecaSKris Buschelman panzj = 0; 84494e3eecaSKris Buschelman for (j=0;j<pnzi;j++) { 84594e3eecaSKris Buschelman arow = *pj++; 84694e3eecaSKris Buschelman anzj = ai[arow+1] - ai[arow]; 84794e3eecaSKris Buschelman ajj = aj + ai[arow]; 84894e3eecaSKris Buschelman aaj = aa + ai[arow]; 84994e3eecaSKris Buschelman for (k=0;k<anzj;k++) { 85094e3eecaSKris Buschelman if (!pajdense[ajj[k]]) { 85194e3eecaSKris Buschelman pajdense[ajj[k]] = -1; 85294e3eecaSKris Buschelman paj[panzj++] = ajj[k]; 85394e3eecaSKris Buschelman } 85494e3eecaSKris Buschelman paa[ajj[k]] += (*pa)*aaj[k]; 85594e3eecaSKris Buschelman } 85694e3eecaSKris Buschelman flops += 2*anzj; 85794e3eecaSKris Buschelman pa++; 85894e3eecaSKris Buschelman } 85994e3eecaSKris Buschelman 86094e3eecaSKris Buschelman /* Sort the j index array for quick sparse axpy. */ 86194e3eecaSKris Buschelman ierr = PetscSortInt(panzj,paj);CHKERRQ(ierr); 86294e3eecaSKris Buschelman 86394e3eecaSKris Buschelman /* Compute P*A*P^T using sparse inner products. */ 86494e3eecaSKris Buschelman /* Take advantage of pre-computed (i,j) of C for locations of non-zeros. */ 86594e3eecaSKris Buschelman cnzi = ci[i+1] - ci[i]; 86694e3eecaSKris Buschelman for (j=0;j<cnzi;j++) { 86794e3eecaSKris Buschelman /* Form sparse inner product of current row of P*A with (*cj++) col of P^T. */ 86894e3eecaSKris Buschelman ptcol = *cj++; 86994e3eecaSKris Buschelman ptnzj = pi[ptcol+1] - pi[ptcol]; 87094e3eecaSKris Buschelman ptj = pjj + pi[ptcol]; 87194e3eecaSKris Buschelman ptaj = pta + pi[ptcol]; 87294e3eecaSKris Buschelman sum = 0.; 87394e3eecaSKris Buschelman k1 = 0; 87494e3eecaSKris Buschelman k2 = 0; 87594e3eecaSKris Buschelman while ((k1<panzj) && (k2<ptnzj)) { 87694e3eecaSKris Buschelman if (paj[k1]==ptj[k2]) { 87794e3eecaSKris Buschelman sum += paa[paj[k1++]]*pta[k2++]; 87894e3eecaSKris Buschelman } else if (paj[k1] < ptj[k2]) { 87994e3eecaSKris Buschelman k1++; 88094e3eecaSKris Buschelman } else /* if (paj[k1] > ptj[k2]) */ { 88194e3eecaSKris Buschelman k2++; 88294e3eecaSKris Buschelman } 88394e3eecaSKris Buschelman } 88494e3eecaSKris Buschelman *ca++ = sum; 88594e3eecaSKris Buschelman } 88694e3eecaSKris Buschelman 88794e3eecaSKris Buschelman /* Zero the current row info for P*A */ 88894e3eecaSKris Buschelman for (j=0;j<panzj;j++) { 88994e3eecaSKris Buschelman paa[paj[j]] = 0.; 89094e3eecaSKris Buschelman pajdense[paj[j]] = 0; 89194e3eecaSKris Buschelman } 89294e3eecaSKris Buschelman } 89394e3eecaSKris Buschelman 89494e3eecaSKris Buschelman ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 89594e3eecaSKris Buschelman ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 89694e3eecaSKris Buschelman ierr = PetscLogFlops(flops);CHKERRQ(ierr); 89794e3eecaSKris Buschelman ierr = PetscLogEventEnd(logkey_matapplypapt_numeric,A,P,C,0);CHKERRQ(ierr); 89894e3eecaSKris Buschelman PetscFunctionReturn(0); 89994e3eecaSKris Buschelman } 90094e3eecaSKris Buschelman 90194e3eecaSKris Buschelman #undef __FUNCT__ 90294e3eecaSKris Buschelman #define __FUNCT__ "MatApplyPAPt_SeqAIJ" 90394e3eecaSKris Buschelman int MatApplyPAPt_SeqAIJ(Mat A,Mat P,Mat *C) { 90494e3eecaSKris Buschelman int ierr; 90594e3eecaSKris Buschelman 90694e3eecaSKris Buschelman PetscFunctionBegin; 90794e3eecaSKris Buschelman if (!logkey_matapplypapt) { 90894e3eecaSKris Buschelman ierr = PetscLogEventRegister(&logkey_matapplypapt,"MatApplyPAPt",MAT_COOKIE);CHKERRQ(ierr); 90994e3eecaSKris Buschelman } 91094e3eecaSKris Buschelman ierr = PetscLogEventBegin(logkey_matapplypapt,A,P,0,0);CHKERRQ(ierr); 91194e3eecaSKris Buschelman ierr = MatApplyPAPt_Symbolic_SeqAIJ(A,P,C);CHKERRQ(ierr); 91294e3eecaSKris Buschelman ierr = MatApplyPAPt_Numeric_SeqAIJ(A,P,*C);CHKERRQ(ierr); 91394e3eecaSKris Buschelman ierr = PetscLogEventEnd(logkey_matapplypapt,A,P,0,0);CHKERRQ(ierr); 91494e3eecaSKris Buschelman PetscFunctionReturn(0); 91594e3eecaSKris Buschelman } 916