1eb9c0419SKris Buschelman /* 29af31e4aSHong Zhang Defines projective product routines where A is a AIJ matrix 3eb9c0419SKris Buschelman C = P^T * A * P 4eb9c0419SKris Buschelman */ 5eb9c0419SKris Buschelman 6231952e2SKris Buschelman #include "src/mat/impls/aij/seq/aij.h" /*I "petscmat.h" I*/ 7eb9c0419SKris Buschelman #include "src/mat/utils/freespace.h" 89af31e4aSHong Zhang #include "src/mat/impls/aij/mpi/mpiaij.h" 9eb9c0419SKris Buschelman 10eb9c0419SKris Buschelman #undef __FUNCT__ 119af31e4aSHong Zhang #define __FUNCT__ "MatPtAP" 124d3841fdSKris Buschelman /*@ 139af31e4aSHong Zhang MatPtAP - Creates the matrix projection C = P^T * A * P 144d3841fdSKris Buschelman 154d3841fdSKris Buschelman Collective on Mat 164d3841fdSKris Buschelman 174d3841fdSKris Buschelman Input Parameters: 184d3841fdSKris Buschelman + A - the matrix 19f747e1aeSHong Zhang . P - the projection matrix 20f747e1aeSHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 21f747e1aeSHong Zhang - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)) 224d3841fdSKris Buschelman 234d3841fdSKris Buschelman Output Parameters: 244d3841fdSKris Buschelman . C - the product matrix 254d3841fdSKris Buschelman 264d3841fdSKris Buschelman Notes: 274d3841fdSKris Buschelman C will be created and must be destroyed by the user with MatDestroy(). 284d3841fdSKris Buschelman 294d3841fdSKris Buschelman This routine is currently only implemented for pairs of SeqAIJ matrices and classes 304d3841fdSKris Buschelman which inherit from SeqAIJ. C will be of type MATSEQAIJ. 314d3841fdSKris Buschelman 324d3841fdSKris Buschelman Level: intermediate 334d3841fdSKris Buschelman 349af31e4aSHong Zhang .seealso: MatPtAPSymbolic(),MatPtAPNumeric(),MatMatMult() 354d3841fdSKris Buschelman @*/ 36dfbe8321SBarry Smith PetscErrorCode MatPtAP(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) { 37dfbe8321SBarry Smith PetscErrorCode ierr; 38534c1384SKris Buschelman PetscErrorCode (*fA)(Mat,Mat,MatReuse,PetscReal,Mat *); 39534c1384SKris Buschelman PetscErrorCode (*fP)(Mat,Mat,MatReuse,PetscReal,Mat *); 40eb9c0419SKris Buschelman 41eb9c0419SKris Buschelman PetscFunctionBegin; 429af31e4aSHong Zhang PetscValidHeaderSpecific(A,MAT_COOKIE,1); 439af31e4aSHong Zhang PetscValidType(A,1); 449af31e4aSHong Zhang MatPreallocated(A); 459af31e4aSHong Zhang if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 469af31e4aSHong Zhang if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 479af31e4aSHong Zhang PetscValidHeaderSpecific(P,MAT_COOKIE,2); 489af31e4aSHong Zhang PetscValidType(P,2); 499af31e4aSHong Zhang MatPreallocated(P); 509af31e4aSHong Zhang if (!P->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 519af31e4aSHong Zhang if (P->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 529af31e4aSHong Zhang PetscValidPointer(C,3); 53534c1384SKris Buschelman 549af31e4aSHong Zhang if (P->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",P->M,A->N); 55eb9c0419SKris Buschelman 569af31e4aSHong Zhang if (fill <=0.0) SETERRQ1(PETSC_ERR_ARG_SIZ,"fill=%g must be > 0.0",fill); 57eb9c0419SKris Buschelman 58534c1384SKris Buschelman /* For now, we do not dispatch based on the type of A and P */ 59534c1384SKris Buschelman /* When implementations like _SeqAIJ_MAIJ exist, attack the multiple dispatch problem. */ 60534c1384SKris Buschelman fA = A->ops->ptap; 61534c1384SKris Buschelman if (!fA) SETERRQ1(PETSC_ERR_SUP,"MatPtAP not supported for A of type %s",A->type_name); 62534c1384SKris Buschelman fP = P->ops->ptap; 63534c1384SKris Buschelman if (!fP) SETERRQ1(PETSC_ERR_SUP,"MatPtAP not supported for P of type %s",P->type_name); 64534c1384SKris Buschelman if (fP!=fA) SETERRQ2(PETSC_ERR_ARG_INCOMP,"MatPtAP requires A, %s, to be compatible with P, %s",A->type_name,P->type_name); 65534c1384SKris Buschelman 669af31e4aSHong Zhang ierr = PetscLogEventBegin(MAT_PtAP,A,P,0,0);CHKERRQ(ierr); 67534c1384SKris Buschelman ierr = (*fA)(A,P,scall,fill,C);CHKERRQ(ierr); 689af31e4aSHong Zhang ierr = PetscLogEventEnd(MAT_PtAP,A,P,0,0);CHKERRQ(ierr); 69eb9c0419SKris Buschelman PetscFunctionReturn(0); 70eb9c0419SKris Buschelman } 71eb9c0419SKris Buschelman 720e36024fSHong Zhang EXTERN PetscErrorCode MatPtAP_SeqAIJ_SeqAIJ_ReducedPt(Mat,Mat,MatReuse,PetscReal,int,int,Mat*); 730e36024fSHong Zhang EXTERN PetscErrorCode MatPtAPSymbolic_SeqAIJ_SeqAIJ_ReducedPt(Mat,Mat,PetscReal,int,int,Mat*); 740e36024fSHong Zhang EXTERN PetscErrorCode MatPtAPNumeric_SeqAIJ_SeqAIJ_ReducedPt(Mat,Mat,int,int,Mat); 75b90dcfe3SHong Zhang 76eb9c0419SKris Buschelman #undef __FUNCT__ 77ff134f7aSHong Zhang #define __FUNCT__ "MatPtAP_MPIAIJ_MPIAIJ" 78ff134f7aSHong Zhang PetscErrorCode MatPtAP_MPIAIJ_MPIAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) 79ff134f7aSHong Zhang { 80ff134f7aSHong Zhang PetscErrorCode ierr; 81b90dcfe3SHong Zhang 82b90dcfe3SHong Zhang PetscFunctionBegin; 83b90dcfe3SHong Zhang if (scall == MAT_INITIAL_MATRIX){ 84b90dcfe3SHong Zhang ierr = MatPtAPSymbolic_MPIAIJ_MPIAIJ(A,P,fill,C);CHKERRQ(ierr);/* numeric product is computed as well */ 85b90dcfe3SHong Zhang } else if (scall == MAT_REUSE_MATRIX){ 86b90dcfe3SHong Zhang ierr = MatPtAPNumeric_MPIAIJ_MPIAIJ(A,P,*C);CHKERRQ(ierr); 87b90dcfe3SHong Zhang } else { 88b90dcfe3SHong Zhang SETERRQ1(PETSC_ERR_ARG_WRONG,"Invalid MatReuse %d",scall); 89b90dcfe3SHong Zhang } 90b90dcfe3SHong Zhang PetscFunctionReturn(0); 91b90dcfe3SHong Zhang } 92b90dcfe3SHong Zhang 93b90dcfe3SHong Zhang #undef __FUNCT__ 94b90dcfe3SHong Zhang #define __FUNCT__ "MatMatMultSymbolic_MPIAIJ_MPIAIJ" 95b90dcfe3SHong Zhang PetscErrorCode MatPtAPSymbolic_MPIAIJ_MPIAIJ(Mat A,Mat P,PetscReal fill,Mat *C) 96b90dcfe3SHong Zhang { 97b90dcfe3SHong Zhang PetscErrorCode ierr; 9825616d81SHong Zhang Mat P_seq,A_loc,C_seq; 990e36024fSHong Zhang int prstart,prend,m=P->m; 10025616d81SHong Zhang IS isrowp,iscolp; 101ff134f7aSHong Zhang 102ff134f7aSHong Zhang PetscFunctionBegin; 10325616d81SHong Zhang /* get P_seq = submatrix of P by taking rows of P that equal to nonzero col of A */ 104b90dcfe3SHong Zhang ierr = MatGetBrowsOfAcols(A,P,MAT_INITIAL_MATRIX,&isrowp,&iscolp,&prstart,&P_seq);CHKERRQ(ierr); 10525616d81SHong Zhang ierr = ISDestroy(iscolp);CHKERRQ(ierr); 106ff134f7aSHong Zhang 10725616d81SHong Zhang /* get A_loc = submatrix of A by taking all local rows of A */ 108b90dcfe3SHong Zhang ierr = MatGetLocalMat(A,MAT_INITIAL_MATRIX,PETSC_NULL,&isrowp,&A_loc);CHKERRQ(ierr); 10925616d81SHong Zhang ierr = ISDestroy(isrowp);CHKERRQ(ierr); 1100e36024fSHong Zhang 11125616d81SHong Zhang /* compute C_seq = P_loc^T * A_loc * P_seq */ 112ff134f7aSHong Zhang prend = prstart + m; 113b90dcfe3SHong Zhang ierr = MatPtAP_SeqAIJ_SeqAIJ_ReducedPt(A_loc,P_seq,MAT_INITIAL_MATRIX,fill,prstart,prend,&C_seq);CHKERRQ(ierr); 11425616d81SHong Zhang ierr = MatDestroy(P_seq);CHKERRQ(ierr); 11525616d81SHong Zhang ierr = MatDestroy(A_loc);CHKERRQ(ierr); 116b90dcfe3SHong Zhang 117b90dcfe3SHong Zhang /* add C_seq into mpi C */ 118b90dcfe3SHong Zhang ierr = MatMerge_SeqsToMPI(A->comm,C_seq,P->n,P->n,MAT_INITIAL_MATRIX,C);CHKERRQ(ierr); 119b90dcfe3SHong Zhang 120ff134f7aSHong Zhang PetscFunctionReturn(0); 121ff134f7aSHong Zhang } 122ff134f7aSHong Zhang 123ff134f7aSHong Zhang #undef __FUNCT__ 124ff134f7aSHong Zhang #define __FUNCT__ "MatMatMultSymbolic_MPIAIJ_MPIAIJ" 125b90dcfe3SHong Zhang PetscErrorCode MatPtAPNumeric_MPIAIJ_MPIAIJ(Mat A,Mat P,Mat C) 126ff134f7aSHong Zhang { 127b90dcfe3SHong Zhang PetscErrorCode ierr; 128b90dcfe3SHong Zhang Mat P_seq,A_loc,C_seq; 129b90dcfe3SHong Zhang int prstart,prend,m=P->m; 130b90dcfe3SHong Zhang IS isrowp,iscolp; 131671beff6SHong Zhang Mat_Merge_SeqsToMPI *merge; 132671beff6SHong Zhang PetscObjectContainer container; 133ff134f7aSHong Zhang 134ff134f7aSHong Zhang PetscFunctionBegin; 135671beff6SHong Zhang ierr = PetscObjectQuery((PetscObject)C,"MatMergeSeqsToMPI",(PetscObject *)&container);CHKERRQ(ierr); 136671beff6SHong Zhang if (container) { 137*7f79fd58SMatthew Knepley ierr = PetscObjectContainerGetPointer(container,(void **)&merge);CHKERRQ(ierr); 138*7f79fd58SMatthew Knepley } else { 139*7f79fd58SMatthew Knepley SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "Matrix C does not posses and object container"); 140671beff6SHong Zhang } 141671beff6SHong Zhang 142b90dcfe3SHong Zhang /* get P_seq = submatrix of P by taking rows of P that equal to nonzero col of A */ 143b90dcfe3SHong Zhang ierr = MatGetBrowsOfAcols(A,P,MAT_INITIAL_MATRIX,&isrowp,&iscolp,&prstart,&P_seq);CHKERRQ(ierr); 144b90dcfe3SHong Zhang ierr = ISDestroy(iscolp);CHKERRQ(ierr); 145ff134f7aSHong Zhang 146b90dcfe3SHong Zhang /* get A_loc = submatrix of A by taking all local rows of A */ 147b90dcfe3SHong Zhang ierr = MatGetLocalMat(A,MAT_INITIAL_MATRIX,PETSC_NULL,&isrowp,&A_loc);CHKERRQ(ierr); 148b90dcfe3SHong Zhang ierr = ISDestroy(isrowp);CHKERRQ(ierr); 149ff134f7aSHong Zhang 150b90dcfe3SHong Zhang /* compute C_seq = P_loc^T * A_loc * P_seq */ 151b90dcfe3SHong Zhang prend = prstart + m; 152b90dcfe3SHong Zhang C_seq = merge->C_seq; 153b90dcfe3SHong Zhang ierr = MatPtAP_SeqAIJ_SeqAIJ_ReducedPt(A_loc,P_seq,MAT_REUSE_MATRIX,1.0,prstart,prend,&C_seq);CHKERRQ(ierr); 154b90dcfe3SHong Zhang ierr = MatDestroy(P_seq);CHKERRQ(ierr); 155b90dcfe3SHong Zhang ierr = MatDestroy(A_loc);CHKERRQ(ierr); 156b90dcfe3SHong Zhang 157b90dcfe3SHong Zhang /* add C_seq into mpi C */ 158b90dcfe3SHong Zhang ierr = MatMerge_SeqsToMPI(A->comm,C_seq,P->n,P->n,MAT_REUSE_MATRIX,&C);CHKERRQ(ierr); 159b90dcfe3SHong Zhang 160ff134f7aSHong Zhang PetscFunctionReturn(0); 161ff134f7aSHong Zhang } 162ff134f7aSHong Zhang 163ff134f7aSHong Zhang #undef __FUNCT__ 1649af31e4aSHong Zhang #define __FUNCT__ "MatPtAP_SeqAIJ_SeqAIJ" 165dfbe8321SBarry Smith PetscErrorCode MatPtAP_SeqAIJ_SeqAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) 1669af31e4aSHong Zhang { 167dfbe8321SBarry Smith PetscErrorCode ierr; 1689af31e4aSHong Zhang PetscFunctionBegin; 1699af31e4aSHong Zhang if (scall == MAT_INITIAL_MATRIX){ 170d20bfe6fSHong Zhang ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 1719af31e4aSHong Zhang ierr = MatPtAPSymbolic_SeqAIJ_SeqAIJ(A,P,fill,C);CHKERRQ(ierr); 172d20bfe6fSHong Zhang ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 1739af31e4aSHong Zhang } 174d20bfe6fSHong Zhang ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 1759af31e4aSHong Zhang ierr = MatPtAPNumeric_SeqAIJ_SeqAIJ(A,P,*C);CHKERRQ(ierr); 176d20bfe6fSHong Zhang ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 1779af31e4aSHong Zhang PetscFunctionReturn(0); 1789af31e4aSHong Zhang } 1799af31e4aSHong Zhang 1809af31e4aSHong Zhang #undef __FUNCT__ 1819af31e4aSHong Zhang #define __FUNCT__ "MatPtAPSymbolic" 1826849ba73SBarry Smith /* 1839af31e4aSHong Zhang MatPtAPSymbolic - Creates the (i,j) structure of the matrix projection C = P^T * A * P 1844d3841fdSKris Buschelman 1854d3841fdSKris Buschelman Collective on Mat 1864d3841fdSKris Buschelman 1874d3841fdSKris Buschelman Input Parameters: 1884d3841fdSKris Buschelman + A - the matrix 1894d3841fdSKris Buschelman - P - the projection matrix 1904d3841fdSKris Buschelman 1914d3841fdSKris Buschelman Output Parameters: 1924d3841fdSKris Buschelman . C - the (i,j) structure of the product matrix 1934d3841fdSKris Buschelman 1944d3841fdSKris Buschelman Notes: 1954d3841fdSKris Buschelman C will be created and must be destroyed by the user with MatDestroy(). 1964d3841fdSKris Buschelman 1974d3841fdSKris Buschelman This routine is currently only implemented for pairs of SeqAIJ matrices and classes 1984d3841fdSKris Buschelman which inherit from SeqAIJ. C will be of type MATSEQAIJ. The product is computed using 1999af31e4aSHong Zhang this (i,j) structure by calling MatPtAPNumeric(). 2004d3841fdSKris Buschelman 2014d3841fdSKris Buschelman Level: intermediate 2024d3841fdSKris Buschelman 2039af31e4aSHong Zhang .seealso: MatPtAP(),MatPtAPNumeric(),MatMatMultSymbolic() 2046849ba73SBarry Smith */ 205dfbe8321SBarry Smith PetscErrorCode MatPtAPSymbolic(Mat A,Mat P,PetscReal fill,Mat *C) { 206dfbe8321SBarry Smith PetscErrorCode ierr; 207534c1384SKris Buschelman PetscErrorCode (*fA)(Mat,Mat,PetscReal,Mat*); 208534c1384SKris Buschelman PetscErrorCode (*fP)(Mat,Mat,PetscReal,Mat*); 209eb9c0419SKris Buschelman 210eb9c0419SKris Buschelman PetscFunctionBegin; 211eb9c0419SKris Buschelman 2124482741eSBarry Smith PetscValidHeaderSpecific(A,MAT_COOKIE,1); 213c9780b6fSBarry Smith PetscValidType(A,1); 214eb9c0419SKris Buschelman MatPreallocated(A); 215eb9c0419SKris Buschelman if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 216eb9c0419SKris Buschelman if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 217eb9c0419SKris Buschelman 2184482741eSBarry Smith PetscValidHeaderSpecific(P,MAT_COOKIE,2); 219c9780b6fSBarry Smith PetscValidType(P,2); 220eb9c0419SKris Buschelman MatPreallocated(P); 221eb9c0419SKris Buschelman if (!P->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 222eb9c0419SKris Buschelman if (P->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 223eb9c0419SKris Buschelman 2244482741eSBarry Smith PetscValidPointer(C,3); 2254482741eSBarry Smith 226eb9c0419SKris Buschelman if (P->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",P->M,A->N); 227eb9c0419SKris Buschelman if (A->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %d != %d",A->M,A->N); 228eb9c0419SKris Buschelman 229534c1384SKris Buschelman /* For now, we do not dispatch based on the type of A and P */ 230534c1384SKris Buschelman /* When implementations like _SeqAIJ_MAIJ exist, attack the multiple dispatch problem. */ 231534c1384SKris Buschelman fA = A->ops->ptapsymbolic; 232534c1384SKris Buschelman if (!fA) SETERRQ1(PETSC_ERR_SUP,"MatPtAPSymbolic not supported for A of type %s",A->type_name); 233534c1384SKris Buschelman fP = P->ops->ptapsymbolic; 234534c1384SKris Buschelman if (!fP) SETERRQ1(PETSC_ERR_SUP,"MatPtAPSymbolic not supported for P of type %s",P->type_name); 235534c1384SKris Buschelman if (fP!=fA) SETERRQ2(PETSC_ERR_ARG_INCOMP,"MatPtAPSymbolic requires A, %s, to be compatible with P, %s",A->type_name,P->type_name); 2364d3841fdSKris Buschelman 237534c1384SKris Buschelman ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 238534c1384SKris Buschelman ierr = (*fA)(A,P,fill,C);CHKERRQ(ierr); 239534c1384SKris Buschelman ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 240eb9c0419SKris Buschelman 241eb9c0419SKris Buschelman PetscFunctionReturn(0); 242eb9c0419SKris Buschelman } 243eb9c0419SKris Buschelman 244f747e1aeSHong Zhang typedef struct { 245f747e1aeSHong Zhang Mat symAP; 246f747e1aeSHong Zhang } Mat_PtAPstruct; 247f747e1aeSHong Zhang 24878a80504SBarry Smith EXTERN PetscErrorCode MatDestroy_SeqAIJ(Mat); 24978a80504SBarry Smith 250f747e1aeSHong Zhang #undef __FUNCT__ 251f747e1aeSHong Zhang #define __FUNCT__ "MatDestroy_SeqAIJ_PtAP" 252f4a850bbSBarry Smith PetscErrorCode MatDestroy_SeqAIJ_PtAP(Mat A) 253f747e1aeSHong Zhang { 254f4a850bbSBarry Smith PetscErrorCode ierr; 255f747e1aeSHong Zhang Mat_PtAPstruct *ptap=(Mat_PtAPstruct*)A->spptr; 256f747e1aeSHong Zhang 257f747e1aeSHong Zhang PetscFunctionBegin; 258f747e1aeSHong Zhang ierr = MatDestroy(ptap->symAP);CHKERRQ(ierr); 259f747e1aeSHong Zhang ierr = PetscFree(ptap);CHKERRQ(ierr); 26078a80504SBarry Smith ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr); 261f747e1aeSHong Zhang PetscFunctionReturn(0); 262f747e1aeSHong Zhang } 263f747e1aeSHong Zhang 264eb9c0419SKris Buschelman #undef __FUNCT__ 2659af31e4aSHong Zhang #define __FUNCT__ "MatPtAPSymbolic_SeqAIJ_SeqAIJ" 266dfbe8321SBarry Smith PetscErrorCode MatPtAPSymbolic_SeqAIJ_SeqAIJ(Mat A,Mat P,PetscReal fill,Mat *C) { 267dfbe8321SBarry Smith PetscErrorCode ierr; 268d20bfe6fSHong Zhang FreeSpaceList free_space=PETSC_NULL,current_space=PETSC_NULL; 269d20bfe6fSHong Zhang Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*p=(Mat_SeqAIJ*)P->data,*c; 270d20bfe6fSHong Zhang int *pti,*ptj,*ptJ,*ai=a->i,*aj=a->j,*ajj,*pi=p->i,*pj=p->j,*pjj; 271d20bfe6fSHong Zhang int *ci,*cj,*denserow,*sparserow,*ptadenserow,*ptasparserow,*ptaj; 272d20bfe6fSHong Zhang int an=A->N,am=A->M,pn=P->N,pm=P->M; 273d20bfe6fSHong Zhang int i,j,k,ptnzi,arow,anzj,ptanzi,prow,pnzj,cnzi; 274d20bfe6fSHong Zhang MatScalar *ca; 275eb9c0419SKris Buschelman 276eb9c0419SKris Buschelman PetscFunctionBegin; 277d20bfe6fSHong Zhang /* Get ij structure of P^T */ 278eb9c0419SKris Buschelman ierr = MatGetSymbolicTranspose_SeqAIJ(P,&pti,&ptj);CHKERRQ(ierr); 279d20bfe6fSHong Zhang ptJ=ptj; 280eb9c0419SKris Buschelman 281d20bfe6fSHong Zhang /* Allocate ci array, arrays for fill computation and */ 282d20bfe6fSHong Zhang /* free space for accumulating nonzero column info */ 283d20bfe6fSHong Zhang ierr = PetscMalloc((pn+1)*sizeof(int),&ci);CHKERRQ(ierr); 284d20bfe6fSHong Zhang ci[0] = 0; 285eb9c0419SKris Buschelman 286d20bfe6fSHong Zhang ierr = PetscMalloc((2*pn+2*an+1)*sizeof(int),&ptadenserow);CHKERRQ(ierr); 287d20bfe6fSHong Zhang ierr = PetscMemzero(ptadenserow,(2*pn+2*an+1)*sizeof(int));CHKERRQ(ierr); 288d20bfe6fSHong Zhang ptasparserow = ptadenserow + an; 289d20bfe6fSHong Zhang denserow = ptasparserow + an; 290d20bfe6fSHong Zhang sparserow = denserow + pn; 291eb9c0419SKris Buschelman 292d20bfe6fSHong Zhang /* Set initial free space to be nnz(A) scaled by aspect ratio of P. */ 293d20bfe6fSHong Zhang /* This should be reasonable if sparsity of PtAP is similar to that of A. */ 294d20bfe6fSHong Zhang ierr = GetMoreSpace((ai[am]/pm)*pn,&free_space); 295d20bfe6fSHong Zhang current_space = free_space; 296d20bfe6fSHong Zhang 297d20bfe6fSHong Zhang /* Determine symbolic info for each row of C: */ 298d20bfe6fSHong Zhang for (i=0;i<pn;i++) { 299d20bfe6fSHong Zhang ptnzi = pti[i+1] - pti[i]; 300d20bfe6fSHong Zhang ptanzi = 0; 301d20bfe6fSHong Zhang /* Determine symbolic row of PtA: */ 302d20bfe6fSHong Zhang for (j=0;j<ptnzi;j++) { 303d20bfe6fSHong Zhang arow = *ptJ++; 304d20bfe6fSHong Zhang anzj = ai[arow+1] - ai[arow]; 305d20bfe6fSHong Zhang ajj = aj + ai[arow]; 306d20bfe6fSHong Zhang for (k=0;k<anzj;k++) { 307d20bfe6fSHong Zhang if (!ptadenserow[ajj[k]]) { 308d20bfe6fSHong Zhang ptadenserow[ajj[k]] = -1; 309d20bfe6fSHong Zhang ptasparserow[ptanzi++] = ajj[k]; 310d20bfe6fSHong Zhang } 311d20bfe6fSHong Zhang } 312d20bfe6fSHong Zhang } 313d20bfe6fSHong Zhang /* Using symbolic info for row of PtA, determine symbolic info for row of C: */ 314d20bfe6fSHong Zhang ptaj = ptasparserow; 315d20bfe6fSHong Zhang cnzi = 0; 316d20bfe6fSHong Zhang for (j=0;j<ptanzi;j++) { 317d20bfe6fSHong Zhang prow = *ptaj++; 318d20bfe6fSHong Zhang pnzj = pi[prow+1] - pi[prow]; 319d20bfe6fSHong Zhang pjj = pj + pi[prow]; 320d20bfe6fSHong Zhang for (k=0;k<pnzj;k++) { 321d20bfe6fSHong Zhang if (!denserow[pjj[k]]) { 322d20bfe6fSHong Zhang denserow[pjj[k]] = -1; 323d20bfe6fSHong Zhang sparserow[cnzi++] = pjj[k]; 324d20bfe6fSHong Zhang } 325d20bfe6fSHong Zhang } 326d20bfe6fSHong Zhang } 327d20bfe6fSHong Zhang 328d20bfe6fSHong Zhang /* sort sparserow */ 329d20bfe6fSHong Zhang ierr = PetscSortInt(cnzi,sparserow);CHKERRQ(ierr); 330d20bfe6fSHong Zhang 331d20bfe6fSHong Zhang /* If free space is not available, make more free space */ 332d20bfe6fSHong Zhang /* Double the amount of total space in the list */ 333d20bfe6fSHong Zhang if (current_space->local_remaining<cnzi) { 334d20bfe6fSHong Zhang ierr = GetMoreSpace(current_space->total_array_size,¤t_space);CHKERRQ(ierr); 335d20bfe6fSHong Zhang } 336d20bfe6fSHong Zhang 337d20bfe6fSHong Zhang /* Copy data into free space, and zero out denserows */ 338d20bfe6fSHong Zhang ierr = PetscMemcpy(current_space->array,sparserow,cnzi*sizeof(int));CHKERRQ(ierr); 339d20bfe6fSHong Zhang current_space->array += cnzi; 340d20bfe6fSHong Zhang current_space->local_used += cnzi; 341d20bfe6fSHong Zhang current_space->local_remaining -= cnzi; 342d20bfe6fSHong Zhang 343d20bfe6fSHong Zhang for (j=0;j<ptanzi;j++) { 344d20bfe6fSHong Zhang ptadenserow[ptasparserow[j]] = 0; 345d20bfe6fSHong Zhang } 346d20bfe6fSHong Zhang for (j=0;j<cnzi;j++) { 347d20bfe6fSHong Zhang denserow[sparserow[j]] = 0; 348d20bfe6fSHong Zhang } 349d20bfe6fSHong Zhang /* Aside: Perhaps we should save the pta info for the numerical factorization. */ 350d20bfe6fSHong Zhang /* For now, we will recompute what is needed. */ 351d20bfe6fSHong Zhang ci[i+1] = ci[i] + cnzi; 352d20bfe6fSHong Zhang } 353d20bfe6fSHong Zhang /* nnz is now stored in ci[ptm], column indices are in the list of free space */ 354d20bfe6fSHong Zhang /* Allocate space for cj, initialize cj, and */ 355d20bfe6fSHong Zhang /* destroy list of free space and other temporary array(s) */ 356d20bfe6fSHong Zhang ierr = PetscMalloc((ci[pn]+1)*sizeof(int),&cj);CHKERRQ(ierr); 357d20bfe6fSHong Zhang ierr = MakeSpaceContiguous(&free_space,cj);CHKERRQ(ierr); 358d20bfe6fSHong Zhang ierr = PetscFree(ptadenserow);CHKERRQ(ierr); 359d20bfe6fSHong Zhang 360d20bfe6fSHong Zhang /* Allocate space for ca */ 361d20bfe6fSHong Zhang ierr = PetscMalloc((ci[pn]+1)*sizeof(MatScalar),&ca);CHKERRQ(ierr); 362d20bfe6fSHong Zhang ierr = PetscMemzero(ca,(ci[pn]+1)*sizeof(MatScalar));CHKERRQ(ierr); 363d20bfe6fSHong Zhang 364d20bfe6fSHong Zhang /* put together the new matrix */ 365d20bfe6fSHong Zhang ierr = MatCreateSeqAIJWithArrays(A->comm,pn,pn,ci,cj,ca,C);CHKERRQ(ierr); 366d20bfe6fSHong Zhang 367d20bfe6fSHong Zhang /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 368d20bfe6fSHong Zhang /* Since these are PETSc arrays, change flags to free them as necessary. */ 369d20bfe6fSHong Zhang c = (Mat_SeqAIJ *)((*C)->data); 370d20bfe6fSHong Zhang c->freedata = PETSC_TRUE; 371d20bfe6fSHong Zhang c->nonew = 0; 372d20bfe6fSHong Zhang 373d20bfe6fSHong Zhang /* Clean up. */ 374d20bfe6fSHong Zhang ierr = MatRestoreSymbolicTranspose_SeqAIJ(P,&pti,&ptj);CHKERRQ(ierr); 375eb9c0419SKris Buschelman 376eb9c0419SKris Buschelman PetscFunctionReturn(0); 377eb9c0419SKris Buschelman } 378eb9c0419SKris Buschelman 3793985e5eaSKris Buschelman #include "src/mat/impls/maij/maij.h" 3803985e5eaSKris Buschelman EXTERN_C_BEGIN 3813985e5eaSKris Buschelman #undef __FUNCT__ 3829af31e4aSHong Zhang #define __FUNCT__ "MatPtAPSymbolic_SeqAIJ_SeqMAIJ" 383dfbe8321SBarry Smith PetscErrorCode MatPtAPSymbolic_SeqAIJ_SeqMAIJ(Mat A,Mat PP,Mat *C) { 3845c66b693SKris Buschelman /* This routine requires testing -- I don't think it works. */ 385dfbe8321SBarry Smith PetscErrorCode ierr; 3863985e5eaSKris Buschelman FreeSpaceList free_space=PETSC_NULL,current_space=PETSC_NULL; 3873985e5eaSKris Buschelman Mat_SeqMAIJ *pp=(Mat_SeqMAIJ*)PP->data; 3883985e5eaSKris Buschelman Mat P=pp->AIJ; 3893985e5eaSKris Buschelman Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*p=(Mat_SeqAIJ*)P->data,*c; 3903985e5eaSKris Buschelman int *pti,*ptj,*ptJ,*ai=a->i,*aj=a->j,*ajj,*pi=p->i,*pj=p->j,*pjj; 3913985e5eaSKris Buschelman int *ci,*cj,*denserow,*sparserow,*ptadenserow,*ptasparserow,*ptaj; 3923985e5eaSKris Buschelman int an=A->N,am=A->M,pn=P->N,pm=P->M,ppdof=pp->dof; 393fe05a634SKris Buschelman int i,j,k,dof,pdof,ptnzi,arow,anzj,ptanzi,prow,pnzj,cnzi; 3943985e5eaSKris Buschelman MatScalar *ca; 3953985e5eaSKris Buschelman 3963985e5eaSKris Buschelman PetscFunctionBegin; 3973985e5eaSKris Buschelman /* Start timer */ 3989af31e4aSHong Zhang ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,PP,0,0);CHKERRQ(ierr); 3993985e5eaSKris Buschelman 4003985e5eaSKris Buschelman /* Get ij structure of P^T */ 4013985e5eaSKris Buschelman ierr = MatGetSymbolicTranspose_SeqAIJ(P,&pti,&ptj);CHKERRQ(ierr); 4023985e5eaSKris Buschelman 4033985e5eaSKris Buschelman /* Allocate ci array, arrays for fill computation and */ 4043985e5eaSKris Buschelman /* free space for accumulating nonzero column info */ 4053985e5eaSKris Buschelman ierr = PetscMalloc((pn+1)*sizeof(int),&ci);CHKERRQ(ierr); 4063985e5eaSKris Buschelman ci[0] = 0; 4073985e5eaSKris Buschelman 4083985e5eaSKris Buschelman ierr = PetscMalloc((2*pn+2*an+1)*sizeof(int),&ptadenserow);CHKERRQ(ierr); 4093985e5eaSKris Buschelman ierr = PetscMemzero(ptadenserow,(2*pn+2*an+1)*sizeof(int));CHKERRQ(ierr); 4103985e5eaSKris Buschelman ptasparserow = ptadenserow + an; 4113985e5eaSKris Buschelman denserow = ptasparserow + an; 4123985e5eaSKris Buschelman sparserow = denserow + pn; 4133985e5eaSKris Buschelman 4143985e5eaSKris Buschelman /* Set initial free space to be nnz(A) scaled by aspect ratio of P. */ 4153985e5eaSKris Buschelman /* This should be reasonable if sparsity of PtAP is similar to that of A. */ 4163985e5eaSKris Buschelman ierr = GetMoreSpace((ai[am]/pm)*pn,&free_space); 4173985e5eaSKris Buschelman current_space = free_space; 4183985e5eaSKris Buschelman 4193985e5eaSKris Buschelman /* Determine symbolic info for each row of C: */ 4203985e5eaSKris Buschelman for (i=0;i<pn/ppdof;i++) { 4213985e5eaSKris Buschelman ptnzi = pti[i+1] - pti[i]; 4223985e5eaSKris Buschelman ptanzi = 0; 4233985e5eaSKris Buschelman ptJ = ptj + pti[i]; 4243985e5eaSKris Buschelman for (dof=0;dof<ppdof;dof++) { 4253985e5eaSKris Buschelman /* Determine symbolic row of PtA: */ 4263985e5eaSKris Buschelman for (j=0;j<ptnzi;j++) { 4273985e5eaSKris Buschelman arow = ptJ[j] + dof; 4283985e5eaSKris Buschelman anzj = ai[arow+1] - ai[arow]; 4293985e5eaSKris Buschelman ajj = aj + ai[arow]; 4303985e5eaSKris Buschelman for (k=0;k<anzj;k++) { 4313985e5eaSKris Buschelman if (!ptadenserow[ajj[k]]) { 4323985e5eaSKris Buschelman ptadenserow[ajj[k]] = -1; 4333985e5eaSKris Buschelman ptasparserow[ptanzi++] = ajj[k]; 4343985e5eaSKris Buschelman } 4353985e5eaSKris Buschelman } 4363985e5eaSKris Buschelman } 4373985e5eaSKris Buschelman /* Using symbolic info for row of PtA, determine symbolic info for row of C: */ 4383985e5eaSKris Buschelman ptaj = ptasparserow; 4393985e5eaSKris Buschelman cnzi = 0; 4403985e5eaSKris Buschelman for (j=0;j<ptanzi;j++) { 441fe05a634SKris Buschelman pdof = *ptaj%dof; 4423985e5eaSKris Buschelman prow = (*ptaj++)/dof; 4433985e5eaSKris Buschelman pnzj = pi[prow+1] - pi[prow]; 4443985e5eaSKris Buschelman pjj = pj + pi[prow]; 4453985e5eaSKris Buschelman for (k=0;k<pnzj;k++) { 446fe05a634SKris Buschelman if (!denserow[pjj[k]+pdof]) { 447fe05a634SKris Buschelman denserow[pjj[k]+pdof] = -1; 448fe05a634SKris Buschelman sparserow[cnzi++] = pjj[k]+pdof; 4493985e5eaSKris Buschelman } 4503985e5eaSKris Buschelman } 4513985e5eaSKris Buschelman } 4523985e5eaSKris Buschelman 4533985e5eaSKris Buschelman /* sort sparserow */ 4543985e5eaSKris Buschelman ierr = PetscSortInt(cnzi,sparserow);CHKERRQ(ierr); 4553985e5eaSKris Buschelman 4563985e5eaSKris Buschelman /* If free space is not available, make more free space */ 4573985e5eaSKris Buschelman /* Double the amount of total space in the list */ 4583985e5eaSKris Buschelman if (current_space->local_remaining<cnzi) { 4593985e5eaSKris Buschelman ierr = GetMoreSpace(current_space->total_array_size,¤t_space);CHKERRQ(ierr); 4603985e5eaSKris Buschelman } 4613985e5eaSKris Buschelman 4623985e5eaSKris Buschelman /* Copy data into free space, and zero out denserows */ 4633985e5eaSKris Buschelman ierr = PetscMemcpy(current_space->array,sparserow,cnzi*sizeof(int));CHKERRQ(ierr); 4643985e5eaSKris Buschelman current_space->array += cnzi; 4653985e5eaSKris Buschelman current_space->local_used += cnzi; 4663985e5eaSKris Buschelman current_space->local_remaining -= cnzi; 4673985e5eaSKris Buschelman 4683985e5eaSKris Buschelman for (j=0;j<ptanzi;j++) { 4693985e5eaSKris Buschelman ptadenserow[ptasparserow[j]] = 0; 4703985e5eaSKris Buschelman } 4713985e5eaSKris Buschelman for (j=0;j<cnzi;j++) { 4723985e5eaSKris Buschelman denserow[sparserow[j]] = 0; 4733985e5eaSKris Buschelman } 4743985e5eaSKris Buschelman /* Aside: Perhaps we should save the pta info for the numerical factorization. */ 4753985e5eaSKris Buschelman /* For now, we will recompute what is needed. */ 4763985e5eaSKris Buschelman ci[i+1+dof] = ci[i+dof] + cnzi; 4773985e5eaSKris Buschelman } 4783985e5eaSKris Buschelman } 4793985e5eaSKris Buschelman /* nnz is now stored in ci[ptm], column indices are in the list of free space */ 4803985e5eaSKris Buschelman /* Allocate space for cj, initialize cj, and */ 4813985e5eaSKris Buschelman /* destroy list of free space and other temporary array(s) */ 4823985e5eaSKris Buschelman ierr = PetscMalloc((ci[pn]+1)*sizeof(int),&cj);CHKERRQ(ierr); 4833985e5eaSKris Buschelman ierr = MakeSpaceContiguous(&free_space,cj);CHKERRQ(ierr); 4843985e5eaSKris Buschelman ierr = PetscFree(ptadenserow);CHKERRQ(ierr); 4853985e5eaSKris Buschelman 4863985e5eaSKris Buschelman /* Allocate space for ca */ 4873985e5eaSKris Buschelman ierr = PetscMalloc((ci[pn]+1)*sizeof(MatScalar),&ca);CHKERRQ(ierr); 4883985e5eaSKris Buschelman ierr = PetscMemzero(ca,(ci[pn]+1)*sizeof(MatScalar));CHKERRQ(ierr); 4893985e5eaSKris Buschelman 4903985e5eaSKris Buschelman /* put together the new matrix */ 4913985e5eaSKris Buschelman ierr = MatCreateSeqAIJWithArrays(A->comm,pn,pn,ci,cj,ca,C);CHKERRQ(ierr); 4923985e5eaSKris Buschelman 4933985e5eaSKris Buschelman /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 4943985e5eaSKris Buschelman /* Since these are PETSc arrays, change flags to free them as necessary. */ 4953985e5eaSKris Buschelman c = (Mat_SeqAIJ *)((*C)->data); 4963985e5eaSKris Buschelman c->freedata = PETSC_TRUE; 4973985e5eaSKris Buschelman c->nonew = 0; 4983985e5eaSKris Buschelman 4993985e5eaSKris Buschelman /* Clean up. */ 5003985e5eaSKris Buschelman ierr = MatRestoreSymbolicTranspose_SeqAIJ(P,&pti,&ptj);CHKERRQ(ierr); 5013985e5eaSKris Buschelman 5029af31e4aSHong Zhang ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,PP,0,0);CHKERRQ(ierr); 5033985e5eaSKris Buschelman PetscFunctionReturn(0); 5043985e5eaSKris Buschelman } 5053985e5eaSKris Buschelman EXTERN_C_END 5063985e5eaSKris Buschelman 507eb9c0419SKris Buschelman #undef __FUNCT__ 5089af31e4aSHong Zhang #define __FUNCT__ "MatPtAPNumeric" 5096849ba73SBarry Smith /* 5109af31e4aSHong Zhang MatPtAPNumeric - Computes the matrix projection C = P^T * A * P 5114d3841fdSKris Buschelman 5124d3841fdSKris Buschelman Collective on Mat 5134d3841fdSKris Buschelman 5144d3841fdSKris Buschelman Input Parameters: 5154d3841fdSKris Buschelman + A - the matrix 5164d3841fdSKris Buschelman - P - the projection matrix 5174d3841fdSKris Buschelman 5184d3841fdSKris Buschelman Output Parameters: 5194d3841fdSKris Buschelman . C - the product matrix 5204d3841fdSKris Buschelman 5214d3841fdSKris Buschelman Notes: 5229af31e4aSHong Zhang C must have been created by calling MatPtAPSymbolic and must be destroyed by 5234d3841fdSKris Buschelman the user using MatDeatroy(). 5244d3841fdSKris Buschelman 525170ef064SHong Zhang This routine is currently only implemented for pairs of AIJ matrices and classes 526170ef064SHong Zhang which inherit from AIJ. C will be of type MATAIJ. 5274d3841fdSKris Buschelman 5284d3841fdSKris Buschelman Level: intermediate 5294d3841fdSKris Buschelman 5309af31e4aSHong Zhang .seealso: MatPtAP(),MatPtAPSymbolic(),MatMatMultNumeric() 5316849ba73SBarry Smith */ 532dfbe8321SBarry Smith PetscErrorCode MatPtAPNumeric(Mat A,Mat P,Mat C) { 533dfbe8321SBarry Smith PetscErrorCode ierr; 534534c1384SKris Buschelman PetscErrorCode (*fA)(Mat,Mat,Mat); 535534c1384SKris Buschelman PetscErrorCode (*fP)(Mat,Mat,Mat); 536eb9c0419SKris Buschelman 537eb9c0419SKris Buschelman PetscFunctionBegin; 538eb9c0419SKris Buschelman 5394482741eSBarry Smith PetscValidHeaderSpecific(A,MAT_COOKIE,1); 540c9780b6fSBarry Smith PetscValidType(A,1); 541eb9c0419SKris Buschelman MatPreallocated(A); 542eb9c0419SKris Buschelman if (!A->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 543eb9c0419SKris Buschelman if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 544eb9c0419SKris Buschelman 5454482741eSBarry Smith PetscValidHeaderSpecific(P,MAT_COOKIE,2); 546c9780b6fSBarry Smith PetscValidType(P,2); 547eb9c0419SKris Buschelman MatPreallocated(P); 548eb9c0419SKris Buschelman if (!P->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 549eb9c0419SKris Buschelman if (P->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 550eb9c0419SKris Buschelman 5514482741eSBarry Smith PetscValidHeaderSpecific(C,MAT_COOKIE,3); 552c9780b6fSBarry Smith PetscValidType(C,3); 553eb9c0419SKris Buschelman MatPreallocated(C); 554eb9c0419SKris Buschelman if (!C->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 555eb9c0419SKris Buschelman if (C->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); 556eb9c0419SKris Buschelman 557eb9c0419SKris Buschelman if (P->N!=C->M) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",P->N,C->M); 558eb9c0419SKris Buschelman if (P->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",P->M,A->N); 559eb9c0419SKris Buschelman if (A->M!=A->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix 'A' must be square, %d != %d",A->M,A->N); 560eb9c0419SKris Buschelman if (P->N!=C->N) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",P->N,C->N); 561eb9c0419SKris Buschelman 562534c1384SKris Buschelman /* For now, we do not dispatch based on the type of A and P */ 563534c1384SKris Buschelman /* When implementations like _SeqAIJ_MAIJ exist, attack the multiple dispatch problem. */ 564534c1384SKris Buschelman fA = A->ops->ptapnumeric; 565534c1384SKris Buschelman if (!fA) SETERRQ1(PETSC_ERR_SUP,"MatPtAPNumeric not supported for A of type %s",A->type_name); 566534c1384SKris Buschelman fP = P->ops->ptapnumeric; 567534c1384SKris Buschelman if (!fP) SETERRQ1(PETSC_ERR_SUP,"MatPtAPNumeric not supported for P of type %s",P->type_name); 568534c1384SKris Buschelman if (fP!=fA) SETERRQ2(PETSC_ERR_ARG_INCOMP,"MatPtAPNumeric requires A, %s, to be compatible with P, %s",A->type_name,P->type_name); 5694d3841fdSKris Buschelman 570534c1384SKris Buschelman ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 571534c1384SKris Buschelman ierr = (*fA)(A,P,C);CHKERRQ(ierr); 572534c1384SKris Buschelman ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 573eb9c0419SKris Buschelman 574eb9c0419SKris Buschelman PetscFunctionReturn(0); 575eb9c0419SKris Buschelman } 576eb9c0419SKris Buschelman 577eb9c0419SKris Buschelman #undef __FUNCT__ 5789af31e4aSHong Zhang #define __FUNCT__ "MatPtAPNumeric_SeqAIJ_SeqAIJ" 579dfbe8321SBarry Smith PetscErrorCode MatPtAPNumeric_SeqAIJ_SeqAIJ(Mat A,Mat P,Mat C) 580dfbe8321SBarry Smith { 581dfbe8321SBarry Smith PetscErrorCode ierr; 582d20bfe6fSHong Zhang int flops=0; 583d20bfe6fSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 584d20bfe6fSHong Zhang Mat_SeqAIJ *p = (Mat_SeqAIJ *) P->data; 585d20bfe6fSHong Zhang Mat_SeqAIJ *c = (Mat_SeqAIJ *) C->data; 586d20bfe6fSHong Zhang int *ai=a->i,*aj=a->j,*apj,*apjdense,*pi=p->i,*pj=p->j,*pJ=p->j,*pjj; 587d20bfe6fSHong Zhang int *ci=c->i,*cj=c->j,*cjj; 588d20bfe6fSHong Zhang int am=A->M,cn=C->N,cm=C->M; 589d20bfe6fSHong Zhang int i,j,k,anzi,pnzi,apnzj,nextap,pnzj,prow,crow; 590d20bfe6fSHong Zhang MatScalar *aa=a->a,*apa,*pa=p->a,*pA=p->a,*paj,*ca=c->a,*caj; 591eb9c0419SKris Buschelman 592eb9c0419SKris Buschelman PetscFunctionBegin; 593d20bfe6fSHong Zhang /* Allocate temporary array for storage of one row of A*P */ 594d20bfe6fSHong Zhang ierr = PetscMalloc(cn*(sizeof(MatScalar)+2*sizeof(int)),&apa);CHKERRQ(ierr); 595d20bfe6fSHong Zhang ierr = PetscMemzero(apa,cn*(sizeof(MatScalar)+2*sizeof(int)));CHKERRQ(ierr); 596eb9c0419SKris Buschelman 597d20bfe6fSHong Zhang apj = (int *)(apa + cn); 598d20bfe6fSHong Zhang apjdense = apj + cn; 599d20bfe6fSHong Zhang 600d20bfe6fSHong Zhang /* Clear old values in C */ 601d20bfe6fSHong Zhang ierr = PetscMemzero(ca,ci[cm]*sizeof(MatScalar));CHKERRQ(ierr); 602d20bfe6fSHong Zhang 603d20bfe6fSHong Zhang for (i=0;i<am;i++) { 604d20bfe6fSHong Zhang /* Form sparse row of A*P */ 605d20bfe6fSHong Zhang anzi = ai[i+1] - ai[i]; 606d20bfe6fSHong Zhang apnzj = 0; 607d20bfe6fSHong Zhang for (j=0;j<anzi;j++) { 608d20bfe6fSHong Zhang prow = *aj++; 609d20bfe6fSHong Zhang pnzj = pi[prow+1] - pi[prow]; 610d20bfe6fSHong Zhang pjj = pj + pi[prow]; 611d20bfe6fSHong Zhang paj = pa + pi[prow]; 612d20bfe6fSHong Zhang for (k=0;k<pnzj;k++) { 613d20bfe6fSHong Zhang if (!apjdense[pjj[k]]) { 614d20bfe6fSHong Zhang apjdense[pjj[k]] = -1; 615d20bfe6fSHong Zhang apj[apnzj++] = pjj[k]; 616d20bfe6fSHong Zhang } 617d20bfe6fSHong Zhang apa[pjj[k]] += (*aa)*paj[k]; 618d20bfe6fSHong Zhang } 619d20bfe6fSHong Zhang flops += 2*pnzj; 620d20bfe6fSHong Zhang aa++; 621d20bfe6fSHong Zhang } 622d20bfe6fSHong Zhang 623d20bfe6fSHong Zhang /* Sort the j index array for quick sparse axpy. */ 624d20bfe6fSHong Zhang ierr = PetscSortInt(apnzj,apj);CHKERRQ(ierr); 625d20bfe6fSHong Zhang 626d20bfe6fSHong Zhang /* Compute P^T*A*P using outer product (P^T)[:,j]*(A*P)[j,:]. */ 627d20bfe6fSHong Zhang pnzi = pi[i+1] - pi[i]; 628d20bfe6fSHong Zhang for (j=0;j<pnzi;j++) { 629d20bfe6fSHong Zhang nextap = 0; 630d20bfe6fSHong Zhang crow = *pJ++; 631d20bfe6fSHong Zhang cjj = cj + ci[crow]; 632d20bfe6fSHong Zhang caj = ca + ci[crow]; 633d20bfe6fSHong Zhang /* Perform sparse axpy operation. Note cjj includes apj. */ 634d20bfe6fSHong Zhang for (k=0;nextap<apnzj;k++) { 635d20bfe6fSHong Zhang if (cjj[k]==apj[nextap]) { 636d20bfe6fSHong Zhang caj[k] += (*pA)*apa[apj[nextap++]]; 637d20bfe6fSHong Zhang } 638d20bfe6fSHong Zhang } 639d20bfe6fSHong Zhang flops += 2*apnzj; 640d20bfe6fSHong Zhang pA++; 641d20bfe6fSHong Zhang } 642d20bfe6fSHong Zhang 643d20bfe6fSHong Zhang /* Zero the current row info for A*P */ 644d20bfe6fSHong Zhang for (j=0;j<apnzj;j++) { 645d20bfe6fSHong Zhang apa[apj[j]] = 0.; 646d20bfe6fSHong Zhang apjdense[apj[j]] = 0; 647d20bfe6fSHong Zhang } 648d20bfe6fSHong Zhang } 649d20bfe6fSHong Zhang 650d20bfe6fSHong Zhang /* Assemble the final matrix and clean up */ 651d20bfe6fSHong Zhang ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 652d20bfe6fSHong Zhang ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 653d20bfe6fSHong Zhang ierr = PetscFree(apa);CHKERRQ(ierr); 654d20bfe6fSHong Zhang ierr = PetscLogFlops(flops);CHKERRQ(ierr); 655d20bfe6fSHong Zhang 656eb9c0419SKris Buschelman PetscFunctionReturn(0); 657eb9c0419SKris Buschelman } 6580e36024fSHong Zhang 6590e36024fSHong Zhang /* Compute C = P[rstart:rend,:]^T * A * P of seqaij matrices - used by MatPtAP_MPIAIJ_MPIAIJ() */ 6600e36024fSHong Zhang 6610e36024fSHong Zhang #undef __FUNCT__ 6620e36024fSHong Zhang #define __FUNCT__ "MatPtAPNumeric_SeqAIJ_SeqAIJ_ReducedPt" 663*7f79fd58SMatthew Knepley /*@C 664e9b43d0fSSatish Balay MatPtAPNumeric_SeqAIJ_SeqAIJ_ReducedPt - Creates C = P[rstart:rend,:]^T * A * P of seqaij matrices, 665b90dcfe3SHong Zhang used by MatPtAP_MPIAIJ_MPIAIJ() 666b90dcfe3SHong Zhang 667b90dcfe3SHong Zhang Collective on Mat 668b90dcfe3SHong Zhang 669b90dcfe3SHong Zhang Input Parameters: 670b90dcfe3SHong Zhang + A - the matrix in seqaij format 671b90dcfe3SHong Zhang . P - the projection matrix in seqaij format 672b90dcfe3SHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 673b90dcfe3SHong Zhang . fill - expected fill (not being used when scall==MAT_REUSE_MATRIX) 674b90dcfe3SHong Zhang . prstart, prend - the starting and ending-1-th row of the matrix P to be used for transpose 675b90dcfe3SHong Zhang 676b90dcfe3SHong Zhang Output Parameters: 677b90dcfe3SHong Zhang . C - the product matrix in seqaij format 678b90dcfe3SHong Zhang 679b90dcfe3SHong Zhang Level: developer 680b90dcfe3SHong Zhang 681b90dcfe3SHong Zhang .seealso: MatPtAPSymbolic(),MatPtAPNumeric(),MatMatMult() 682b90dcfe3SHong Zhang @*/ 6830e36024fSHong Zhang PetscErrorCode MatPtAPNumeric_SeqAIJ_SeqAIJ_ReducedPt(Mat A,Mat P,int prstart,int prend,Mat C) 6840e36024fSHong Zhang { 6850e36024fSHong Zhang PetscErrorCode ierr; 6860e36024fSHong Zhang int flops=0; 6870e36024fSHong Zhang Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; 6880e36024fSHong Zhang Mat_SeqAIJ *p = (Mat_SeqAIJ *) P->data; 6890e36024fSHong Zhang Mat_SeqAIJ *c = (Mat_SeqAIJ *) C->data; 69020d4747cSHong Zhang int *ai=a->i,*aj=a->j,*apj,*apjdense; 69120d4747cSHong Zhang int *pi=p->i,*pj=p->j,*pJ=p->j+pi[prstart],*pjj; 6920e36024fSHong Zhang int *ci=c->i,*cj=c->j,*cjj; 6930e36024fSHong Zhang int am=A->M,cn=C->N,cm=C->M; 6940e36024fSHong Zhang int i,j,k,anzi,pnzi,apnzj,nextap,pnzj,prow,crow; 6950e36024fSHong Zhang MatScalar *aa=a->a,*apa,*pa=p->a,*pA=p->a,*paj,*ca=c->a,*caj; 6960e36024fSHong Zhang 6970e36024fSHong Zhang PetscFunctionBegin; 6980e36024fSHong Zhang pA=p->a+pi[prstart]; 6990e36024fSHong Zhang /* Allocate temporary array for storage of one row of A*P */ 7000e36024fSHong Zhang ierr = PetscMalloc(cn*(sizeof(MatScalar)+2*sizeof(int)),&apa);CHKERRQ(ierr); 7010e36024fSHong Zhang ierr = PetscMemzero(apa,cn*(sizeof(MatScalar)+2*sizeof(int)));CHKERRQ(ierr); 7020e36024fSHong Zhang 7030e36024fSHong Zhang apj = (int *)(apa + cn); 7040e36024fSHong Zhang apjdense = apj + cn; 7050e36024fSHong Zhang 7060e36024fSHong Zhang /* Clear old values in C */ 7070e36024fSHong Zhang ierr = PetscMemzero(ca,ci[cm]*sizeof(MatScalar));CHKERRQ(ierr); 7080e36024fSHong Zhang 7090e36024fSHong Zhang for (i=0;i<am;i++) { 7100e36024fSHong Zhang /* Form sparse row of A*P */ 7110e36024fSHong Zhang anzi = ai[i+1] - ai[i]; 7120e36024fSHong Zhang apnzj = 0; 7130e36024fSHong Zhang for (j=0;j<anzi;j++) { 7140e36024fSHong Zhang prow = *aj++; 7150e36024fSHong Zhang pnzj = pi[prow+1] - pi[prow]; 7160e36024fSHong Zhang pjj = pj + pi[prow]; 7170e36024fSHong Zhang paj = pa + pi[prow]; 7180e36024fSHong Zhang for (k=0;k<pnzj;k++) { 7190e36024fSHong Zhang if (!apjdense[pjj[k]]) { 7200e36024fSHong Zhang apjdense[pjj[k]] = -1; 7210e36024fSHong Zhang apj[apnzj++] = pjj[k]; 7220e36024fSHong Zhang } 7230e36024fSHong Zhang apa[pjj[k]] += (*aa)*paj[k]; 7240e36024fSHong Zhang } 7250e36024fSHong Zhang flops += 2*pnzj; 7260e36024fSHong Zhang aa++; 7270e36024fSHong Zhang } 7280e36024fSHong Zhang 7290e36024fSHong Zhang /* Sort the j index array for quick sparse axpy. */ 7300e36024fSHong Zhang ierr = PetscSortInt(apnzj,apj);CHKERRQ(ierr); 7310e36024fSHong Zhang 7320e36024fSHong Zhang /* Compute P[[prstart:prend,:]^T*A*P using outer product (P^T)[:,j+prstart]*(A*P)[j,:]. */ 7330e36024fSHong Zhang pnzi = pi[i+1+prstart] - pi[i+prstart]; 7340e36024fSHong Zhang for (j=0;j<pnzi;j++) { 7350e36024fSHong Zhang nextap = 0; 7360e36024fSHong Zhang crow = *pJ++; 7370e36024fSHong Zhang cjj = cj + ci[crow]; 7380e36024fSHong Zhang caj = ca + ci[crow]; 7390e36024fSHong Zhang /* Perform sparse axpy operation. Note cjj includes apj. */ 7400e36024fSHong Zhang for (k=0;nextap<apnzj;k++) { 7410e36024fSHong Zhang if (cjj[k]==apj[nextap]) { 7420e36024fSHong Zhang caj[k] += (*pA)*apa[apj[nextap++]]; 7430e36024fSHong Zhang } 7440e36024fSHong Zhang } 7450e36024fSHong Zhang flops += 2*apnzj; 7460e36024fSHong Zhang pA++; 7470e36024fSHong Zhang } 7480e36024fSHong Zhang 7490e36024fSHong Zhang /* Zero the current row info for A*P */ 7500e36024fSHong Zhang for (j=0;j<apnzj;j++) { 7510e36024fSHong Zhang apa[apj[j]] = 0.; 7520e36024fSHong Zhang apjdense[apj[j]] = 0; 7530e36024fSHong Zhang } 7540e36024fSHong Zhang } 7550e36024fSHong Zhang 7560e36024fSHong Zhang /* Assemble the final matrix and clean up */ 7570e36024fSHong Zhang ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 7580e36024fSHong Zhang ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 7590e36024fSHong Zhang ierr = PetscFree(apa);CHKERRQ(ierr); 7600e36024fSHong Zhang ierr = PetscLogFlops(flops);CHKERRQ(ierr); 7610e36024fSHong Zhang 7620e36024fSHong Zhang PetscFunctionReturn(0); 7630e36024fSHong Zhang } 7640e36024fSHong Zhang 7650e36024fSHong Zhang #undef __FUNCT__ 7660e36024fSHong Zhang #define __FUNCT__ "MatPtAPSymbolic_SeqAIJ_SeqAIJ_ReducedPt" 7670e36024fSHong Zhang PetscErrorCode MatPtAPSymbolic_SeqAIJ_SeqAIJ_ReducedPt(Mat A,Mat P,PetscReal fill,int prstart,int prend,Mat *C) { 7680e36024fSHong Zhang PetscErrorCode ierr; 7690e36024fSHong Zhang FreeSpaceList free_space=PETSC_NULL,current_space=PETSC_NULL; 7700e36024fSHong Zhang Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*p=(Mat_SeqAIJ*)P->data,*c; 7710e36024fSHong Zhang int *pti,*ptj,*ptJ,*ai=a->i,*aj=a->j,*ajj,*pi=p->i,*pj=p->j,*pjj; 7720e36024fSHong Zhang int *ci,*cj,*denserow,*sparserow,*ptadenserow,*ptasparserow,*ptaj; 7730e36024fSHong Zhang int an=A->N,am=A->M,pn=P->N,pm=P->M; 7740e36024fSHong Zhang int i,j,k,ptnzi,arow,anzj,ptanzi,prow,pnzj,cnzi; 7750e36024fSHong Zhang MatScalar *ca; 7760e36024fSHong Zhang Mat *psub,P_sub; 7770e36024fSHong Zhang IS isrow,iscol; 7780e36024fSHong Zhang int m = prend - prstart; 7790b89d903Svictorle 7800b89d903Svictorle PetscFunctionBegin; 7810b89d903Svictorle /* Get ij structure of P[rstart:rend,:]^T */ 7820e36024fSHong Zhang ierr = ISCreateStride(PETSC_COMM_SELF,m,prstart,1,&isrow);CHKERRQ(ierr); 7830e36024fSHong Zhang ierr = ISCreateStride(PETSC_COMM_SELF,P->n,0,1,&iscol);CHKERRQ(ierr); 7840e36024fSHong Zhang ierr = MatGetSubMatrices(P,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&psub);CHKERRQ(ierr); 7850e36024fSHong Zhang ierr = ISDestroy(isrow);CHKERRQ(ierr); 7860e36024fSHong Zhang ierr = ISDestroy(iscol);CHKERRQ(ierr); 7870e36024fSHong Zhang P_sub = psub[0]; 7880e36024fSHong Zhang ierr = MatGetSymbolicTranspose_SeqAIJ(P_sub,&pti,&ptj);CHKERRQ(ierr); 7890e36024fSHong Zhang ierr = MatDestroyMatrices(1,&psub);CHKERRQ(ierr); 7900e36024fSHong Zhang ptJ=ptj; 7910e36024fSHong Zhang 7920e36024fSHong Zhang /* Allocate ci array, arrays for fill computation and */ 7930e36024fSHong Zhang /* free space for accumulating nonzero column info */ 7940e36024fSHong Zhang ierr = PetscMalloc((pn+1)*sizeof(int),&ci);CHKERRQ(ierr); 7950e36024fSHong Zhang ci[0] = 0; 7960e36024fSHong Zhang 7970e36024fSHong Zhang ierr = PetscMalloc((2*pn+2*an+1)*sizeof(int),&ptadenserow);CHKERRQ(ierr); 7980e36024fSHong Zhang ierr = PetscMemzero(ptadenserow,(2*pn+2*an+1)*sizeof(int));CHKERRQ(ierr); 7990e36024fSHong Zhang ptasparserow = ptadenserow + an; 8000e36024fSHong Zhang denserow = ptasparserow + an; 8010e36024fSHong Zhang sparserow = denserow + pn; 8020e36024fSHong Zhang 8030e36024fSHong Zhang /* Set initial free space to be nnz(A) scaled by aspect ratio of P. */ 8040e36024fSHong Zhang /* This should be reasonable if sparsity of PtAP is similar to that of A. */ 805b90dcfe3SHong Zhang ierr = GetMoreSpace((int)(fill*ai[am]/pm)*pn,&free_space); 8060e36024fSHong Zhang current_space = free_space; 8070e36024fSHong Zhang 8080e36024fSHong Zhang /* Determine symbolic info for each row of C: */ 8090e36024fSHong Zhang for (i=0;i<pn;i++) { 8100e36024fSHong Zhang ptnzi = pti[i+1] - pti[i]; 8110e36024fSHong Zhang ptanzi = 0; 8120e36024fSHong Zhang /* Determine symbolic row of PtA_reduced: */ 8130e36024fSHong Zhang for (j=0;j<ptnzi;j++) { 8140e36024fSHong Zhang arow = *ptJ++; 8150e36024fSHong Zhang anzj = ai[arow+1] - ai[arow]; 8160e36024fSHong Zhang ajj = aj + ai[arow]; 8170e36024fSHong Zhang for (k=0;k<anzj;k++) { 8180e36024fSHong Zhang if (!ptadenserow[ajj[k]]) { 8190e36024fSHong Zhang ptadenserow[ajj[k]] = -1; 8200e36024fSHong Zhang ptasparserow[ptanzi++] = ajj[k]; 8210e36024fSHong Zhang } 8220e36024fSHong Zhang } 8230e36024fSHong Zhang } 8240e36024fSHong Zhang /* Using symbolic info for row of PtA, determine symbolic info for row of C: */ 8250e36024fSHong Zhang ptaj = ptasparserow; 8260e36024fSHong Zhang cnzi = 0; 8270e36024fSHong Zhang for (j=0;j<ptanzi;j++) { 8280e36024fSHong Zhang prow = *ptaj++; 8290e36024fSHong Zhang pnzj = pi[prow+1] - pi[prow]; 8300e36024fSHong Zhang pjj = pj + pi[prow]; 8310e36024fSHong Zhang for (k=0;k<pnzj;k++) { 8320e36024fSHong Zhang if (!denserow[pjj[k]]) { 8330e36024fSHong Zhang denserow[pjj[k]] = -1; 8340e36024fSHong Zhang sparserow[cnzi++] = pjj[k]; 8350e36024fSHong Zhang } 8360e36024fSHong Zhang } 8370e36024fSHong Zhang } 8380e36024fSHong Zhang 8390e36024fSHong Zhang /* sort sparserow */ 8400e36024fSHong Zhang ierr = PetscSortInt(cnzi,sparserow);CHKERRQ(ierr); 8410e36024fSHong Zhang 8420e36024fSHong Zhang /* If free space is not available, make more free space */ 8430e36024fSHong Zhang /* Double the amount of total space in the list */ 8440e36024fSHong Zhang if (current_space->local_remaining<cnzi) { 8450e36024fSHong Zhang ierr = GetMoreSpace(current_space->total_array_size,¤t_space);CHKERRQ(ierr); 8460e36024fSHong Zhang } 8470e36024fSHong Zhang 8480e36024fSHong Zhang /* Copy data into free space, and zero out denserows */ 8490e36024fSHong Zhang ierr = PetscMemcpy(current_space->array,sparserow,cnzi*sizeof(int));CHKERRQ(ierr); 8500e36024fSHong Zhang current_space->array += cnzi; 8510e36024fSHong Zhang current_space->local_used += cnzi; 8520e36024fSHong Zhang current_space->local_remaining -= cnzi; 8530e36024fSHong Zhang 8540e36024fSHong Zhang for (j=0;j<ptanzi;j++) { 8550e36024fSHong Zhang ptadenserow[ptasparserow[j]] = 0; 8560e36024fSHong Zhang } 8570e36024fSHong Zhang for (j=0;j<cnzi;j++) { 8580e36024fSHong Zhang denserow[sparserow[j]] = 0; 8590e36024fSHong Zhang } 8600e36024fSHong Zhang /* Aside: Perhaps we should save the pta info for the numerical factorization. */ 8610e36024fSHong Zhang /* For now, we will recompute what is needed. */ 8620e36024fSHong Zhang ci[i+1] = ci[i] + cnzi; 8630e36024fSHong Zhang } 8640e36024fSHong Zhang /* nnz is now stored in ci[ptm], column indices are in the list of free space */ 8650e36024fSHong Zhang /* Allocate space for cj, initialize cj, and */ 8660e36024fSHong Zhang /* destroy list of free space and other temporary array(s) */ 8670e36024fSHong Zhang ierr = PetscMalloc((ci[pn]+1)*sizeof(int),&cj);CHKERRQ(ierr); 8680e36024fSHong Zhang ierr = MakeSpaceContiguous(&free_space,cj);CHKERRQ(ierr); 8690e36024fSHong Zhang ierr = PetscFree(ptadenserow);CHKERRQ(ierr); 8700e36024fSHong Zhang 8710e36024fSHong Zhang /* Allocate space for ca */ 8720e36024fSHong Zhang ierr = PetscMalloc((ci[pn]+1)*sizeof(MatScalar),&ca);CHKERRQ(ierr); 8730e36024fSHong Zhang ierr = PetscMemzero(ca,(ci[pn]+1)*sizeof(MatScalar));CHKERRQ(ierr); 8740e36024fSHong Zhang 8750e36024fSHong Zhang /* put together the new matrix */ 8760e36024fSHong Zhang ierr = MatCreateSeqAIJWithArrays(A->comm,pn,pn,ci,cj,ca,C);CHKERRQ(ierr); 8770e36024fSHong Zhang 8780e36024fSHong Zhang /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 8790e36024fSHong Zhang /* Since these are PETSc arrays, change flags to free them as necessary. */ 8800e36024fSHong Zhang c = (Mat_SeqAIJ *)((*C)->data); 8810e36024fSHong Zhang c->freedata = PETSC_TRUE; 8820e36024fSHong Zhang c->nonew = 0; 8830e36024fSHong Zhang 8840e36024fSHong Zhang /* Clean up. */ 8850e36024fSHong Zhang ierr = MatRestoreSymbolicTranspose_SeqAIJ(P,&pti,&ptj);CHKERRQ(ierr); 8860e36024fSHong Zhang 8870e36024fSHong Zhang PetscFunctionReturn(0); 8880e36024fSHong Zhang } 8890e36024fSHong Zhang 8900e36024fSHong Zhang #undef __FUNCT__ 8910e36024fSHong Zhang #define __FUNCT__ "MatPtAP_SeqAIJ_SeqAIJ_ReducedPt" 8920e36024fSHong Zhang PetscErrorCode MatPtAP_SeqAIJ_SeqAIJ_ReducedPt(Mat A,Mat P,MatReuse scall,PetscReal fill,int prstart,int prend,Mat *C) 8930e36024fSHong Zhang { 8940e36024fSHong Zhang PetscErrorCode ierr; 8950e36024fSHong Zhang PetscFunctionBegin; 8960e36024fSHong Zhang if (A->m != prend-prstart) SETERRQ2(PETSC_ERR_ARG_SIZ,"Matrix dimensions are incompatible, %d != %d",A->m,prend-prstart); 8970e36024fSHong Zhang if (prend-prstart > P->m) SETERRQ2(PETSC_ERR_ARG_SIZ," prend-prstart %d cannot be larger than P->m %d",prend-prstart,P->m); 8980e36024fSHong Zhang if (scall == MAT_INITIAL_MATRIX){ 8990e36024fSHong Zhang ierr = MatPtAPSymbolic_SeqAIJ_SeqAIJ_ReducedPt(A,P,fill,prstart,prend,C);CHKERRQ(ierr); 9000e36024fSHong Zhang } 9010e36024fSHong Zhang 9020e36024fSHong Zhang ierr = MatPtAPNumeric_SeqAIJ_SeqAIJ_ReducedPt(A,P,prstart,prend,*C);CHKERRQ(ierr); 9030e36024fSHong Zhang 9040e36024fSHong Zhang PetscFunctionReturn(0); 9050e36024fSHong Zhang } 9060e36024fSHong Zhang 907