1*4dfdc2d9SRichard Tran Mills /* 2*4dfdc2d9SRichard Tran Mills Defines basic operations for the MATSEQAIJSELL matrix class. 3*4dfdc2d9SRichard Tran Mills This class is derived from the MATAIJCLASS, but maintains a "shadow" copy 4*4dfdc2d9SRichard Tran Mills of the matrix stored in MATSEQSELL format, which is used as appropriate for 5*4dfdc2d9SRichard Tran Mills performing operations for which this format is more suitable. 6*4dfdc2d9SRichard Tran Mills */ 7*4dfdc2d9SRichard Tran Mills 8*4dfdc2d9SRichard Tran Mills #include <../src/mat/impls/aij/seq/aij.h> 9*4dfdc2d9SRichard Tran Mills 10*4dfdc2d9SRichard Tran Mills typedef struct { 11*4dfdc2d9SRichard Tran Mills Mat S; /* The SELL formatted "shadow" matrix. */ 12*4dfdc2d9SRichard Tran Mills PetscBool eager_shadow; 13*4dfdc2d9SRichard Tran Mills PetscObjectState state; /* State of the matrix when shadow matrix was last constructed. */ 14*4dfdc2d9SRichard Tran Mills } Mat_SeqAIJSELL; 15*4dfdc2d9SRichard Tran Mills 16*4dfdc2d9SRichard Tran Mills PETSC_INTERN PetscErrorCode MatConvert_SeqAIJSELL_SeqAIJ(Mat A,MatType type,MatReuse reuse,Mat *newmat) 17*4dfdc2d9SRichard Tran Mills { 18*4dfdc2d9SRichard Tran Mills /* This routine is only called to convert a MATAIJSELL to its base PETSc type, */ 19*4dfdc2d9SRichard Tran Mills /* so we will ignore 'MatType type'. */ 20*4dfdc2d9SRichard Tran Mills PetscErrorCode ierr; 21*4dfdc2d9SRichard Tran Mills Mat B = *newmat; 22*4dfdc2d9SRichard Tran Mills Mat_SeqAIJSELL *aijsell = (Mat_SeqAIJSELL*) A->spptr; 23*4dfdc2d9SRichard Tran Mills 24*4dfdc2d9SRichard Tran Mills PetscFunctionBegin; 25*4dfdc2d9SRichard Tran Mills if (reuse == MAT_INITIAL_MATRIX) { 26*4dfdc2d9SRichard Tran Mills ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr); 27*4dfdc2d9SRichard Tran Mills } 28*4dfdc2d9SRichard Tran Mills 29*4dfdc2d9SRichard Tran Mills /* Reset the original function pointers. */ 30*4dfdc2d9SRichard Tran Mills B->ops->duplicate = MatDuplicate_SeqAIJ; 31*4dfdc2d9SRichard Tran Mills B->ops->assemblyend = MatAssemblyEnd_SeqAIJ; 32*4dfdc2d9SRichard Tran Mills B->ops->destroy = MatDestroy_SeqAIJ; 33*4dfdc2d9SRichard Tran Mills B->ops->mult = MatMult_SeqAIJ; 34*4dfdc2d9SRichard Tran Mills B->ops->multtranspose = MatMultTranspose_SeqAIJ; 35*4dfdc2d9SRichard Tran Mills B->ops->multadd = MatMultAdd_SeqAIJ; 36*4dfdc2d9SRichard Tran Mills B->ops->multtransposeadd = MatMultTransposeAdd_SeqAIJ; 37*4dfdc2d9SRichard Tran Mills 38*4dfdc2d9SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaijsell_seqaij_C",NULL);CHKERRQ(ierr); 39*4dfdc2d9SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqdense_seqaijsell_C",NULL);CHKERRQ(ierr); 40*4dfdc2d9SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaijsell_C",NULL);CHKERRQ(ierr); 41*4dfdc2d9SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqdense_seqaijsell_C",NULL);CHKERRQ(ierr); 42*4dfdc2d9SRichard Tran Mills 43*4dfdc2d9SRichard Tran Mills if (reuse == MAT_INITIAL_MATRIX) aijsell = (Mat_SeqAIJSELL*)B->spptr; 44*4dfdc2d9SRichard Tran Mills 45*4dfdc2d9SRichard Tran Mills /* Clean up the Mat_SeqAIJSELL data structure. */ 46*4dfdc2d9SRichard Tran Mills if(aijsell->S) { 47*4dfdc2d9SRichard Tran Mills ierr = MatDestroy(&aijsell->S);CHKERRQ(ierr); 48*4dfdc2d9SRichard Tran Mills } 49*4dfdc2d9SRichard Tran Mills ierr = PetscFree(B->spptr);CHKERRQ(ierr); 50*4dfdc2d9SRichard Tran Mills 51*4dfdc2d9SRichard Tran Mills /* Change the type of B to MATSEQAIJ. */ 52*4dfdc2d9SRichard Tran Mills ierr = PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ);CHKERRQ(ierr); 53*4dfdc2d9SRichard Tran Mills 54*4dfdc2d9SRichard Tran Mills *newmat = B; 55*4dfdc2d9SRichard Tran Mills PetscFunctionReturn(0); 56*4dfdc2d9SRichard Tran Mills } 57*4dfdc2d9SRichard Tran Mills 58*4dfdc2d9SRichard Tran Mills PetscErrorCode MatDestroy_SeqAIJSELL(Mat A) 59*4dfdc2d9SRichard Tran Mills { 60*4dfdc2d9SRichard Tran Mills PetscErrorCode ierr; 61*4dfdc2d9SRichard Tran Mills Mat_SeqAIJSELL *aijsell = (Mat_SeqAIJSELL*) A->spptr; 62*4dfdc2d9SRichard Tran Mills 63*4dfdc2d9SRichard Tran Mills PetscFunctionBegin; 64*4dfdc2d9SRichard Tran Mills 65*4dfdc2d9SRichard Tran Mills /* If MatHeaderMerge() was used, then this SeqAIJSELL matrix will not have an 66*4dfdc2d9SRichard Tran Mills * spptr pointer. */ 67*4dfdc2d9SRichard Tran Mills if (aijsell) { 68*4dfdc2d9SRichard Tran Mills /* Clean up everything in the Mat_SeqAIJSELL data structure, then free A->spptr. */ 69*4dfdc2d9SRichard Tran Mills if (aijsell->S) { 70*4dfdc2d9SRichard Tran Mills ierr = MatDestroy(&aijsell->S);CHKERRQ(ierr); 71*4dfdc2d9SRichard Tran Mills } 72*4dfdc2d9SRichard Tran Mills ierr = PetscFree(A->spptr);CHKERRQ(ierr); 73*4dfdc2d9SRichard Tran Mills } 74*4dfdc2d9SRichard Tran Mills 75*4dfdc2d9SRichard Tran Mills /* Change the type of A back to SEQAIJ and use MatDestroy_SeqAIJ() 76*4dfdc2d9SRichard Tran Mills * to destroy everything that remains. */ 77*4dfdc2d9SRichard Tran Mills ierr = PetscObjectChangeTypeName((PetscObject)A, MATSEQAIJ);CHKERRQ(ierr); 78*4dfdc2d9SRichard Tran Mills /* Note that I don't call MatSetType(). I believe this is because that 79*4dfdc2d9SRichard Tran Mills * is only to be called when *building* a matrix. I could be wrong, but 80*4dfdc2d9SRichard Tran Mills * that is how things work for the SuperLU matrix class. */ 81*4dfdc2d9SRichard Tran Mills ierr = MatDestroy_SeqAIJ(A);CHKERRQ(ierr); 82*4dfdc2d9SRichard Tran Mills PetscFunctionReturn(0); 83*4dfdc2d9SRichard Tran Mills } 84*4dfdc2d9SRichard Tran Mills 85*4dfdc2d9SRichard Tran Mills PetscErrorCode MatDuplicate_SeqAIJSELL(Mat A, MatDuplicateOption op, Mat *M) 86*4dfdc2d9SRichard Tran Mills { 87*4dfdc2d9SRichard Tran Mills PetscErrorCode ierr; 88*4dfdc2d9SRichard Tran Mills Mat_SeqAIJSELL *aijsell; 89*4dfdc2d9SRichard Tran Mills Mat_SeqAIJSELL *aijsell_dest; 90*4dfdc2d9SRichard Tran Mills 91*4dfdc2d9SRichard Tran Mills PetscFunctionBegin; 92*4dfdc2d9SRichard Tran Mills ierr = MatDuplicate_SeqAIJ(A,op,M);CHKERRQ(ierr); 93*4dfdc2d9SRichard Tran Mills aijsell = (Mat_SeqAIJSELL*) A->spptr; 94*4dfdc2d9SRichard Tran Mills aijsell_dest = (Mat_SeqAIJSELL*) (*M)->spptr; 95*4dfdc2d9SRichard Tran Mills ierr = PetscMemcpy(aijsell_dest,aijsell,sizeof(Mat_SeqAIJSELL));CHKERRQ(ierr); 96*4dfdc2d9SRichard Tran Mills /* We don't duplicate the shadow matrix -- that will be constructed as needed. */ 97*4dfdc2d9SRichard Tran Mills aijsell_dest->S = NULL; 98*4dfdc2d9SRichard Tran Mills /* TODO: Have the shadow matrix be built now if eager_shadow is set to true. */ 99*4dfdc2d9SRichard Tran Mills PetscFunctionReturn(0); 100*4dfdc2d9SRichard Tran Mills } 101*4dfdc2d9SRichard Tran Mills 102*4dfdc2d9SRichard Tran Mills PetscErrorCode MatAssemblyEnd_SeqAIJSELL(Mat A, MatAssemblyType mode) 103*4dfdc2d9SRichard Tran Mills { 104*4dfdc2d9SRichard Tran Mills PetscErrorCode ierr; 105*4dfdc2d9SRichard Tran Mills Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 106*4dfdc2d9SRichard Tran Mills Mat_SeqAIJSELL *aijsell; 107*4dfdc2d9SRichard Tran Mills 108*4dfdc2d9SRichard Tran Mills PetscFunctionBegin; 109*4dfdc2d9SRichard Tran Mills if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0); 110*4dfdc2d9SRichard Tran Mills 111*4dfdc2d9SRichard Tran Mills /* I disable the use of the inode routines so that the AIJSELL ones will be 112*4dfdc2d9SRichard Tran Mills * used instead, but I wonder if it might make sense (and is feasible) to 113*4dfdc2d9SRichard Tran Mills * use some of them. */ 114*4dfdc2d9SRichard Tran Mills a->inode.use = PETSC_FALSE; 115*4dfdc2d9SRichard Tran Mills 116*4dfdc2d9SRichard Tran Mills /* Since a MATSEQAIJSELL matrix is really just a MATSEQAIJ with some 117*4dfdc2d9SRichard Tran Mills * extra information and some different methods, call the AssemblyEnd 118*4dfdc2d9SRichard Tran Mills * routine for a MATSEQAIJ. 119*4dfdc2d9SRichard Tran Mills * I'm not sure if this is the best way to do this, but it avoids 120*4dfdc2d9SRichard Tran Mills * a lot of code duplication. */ 121*4dfdc2d9SRichard Tran Mills 122*4dfdc2d9SRichard Tran Mills ierr = MatAssemblyEnd_SeqAIJ(A, mode);CHKERRQ(ierr); 123*4dfdc2d9SRichard Tran Mills 124*4dfdc2d9SRichard Tran Mills /* If the user has requested "eager" shadowing, create the SELL shadow matrix (if needed; the function checks). 125*4dfdc2d9SRichard Tran Mills * (The default is to take a "lazy" approach, deferring this until something like MatMult() is called.) */ 126*4dfdc2d9SRichard Tran Mills aijsell = (Mat_SeqAIJSELL*) A->spptr; 127*4dfdc2d9SRichard Tran Mills if (aijsell->eager_shadow) { 128*4dfdc2d9SRichard Tran Mills /* TODO: Construct the shadow matrix here. */ 129*4dfdc2d9SRichard Tran Mills } 130*4dfdc2d9SRichard Tran Mills 131*4dfdc2d9SRichard Tran Mills PetscFunctionReturn(0); 132*4dfdc2d9SRichard Tran Mills } 133*4dfdc2d9SRichard Tran Mills 134*4dfdc2d9SRichard Tran Mills /* MatConvert_SeqAIJ_SeqAIJSELL converts a SeqAIJ matrix into a 135*4dfdc2d9SRichard Tran Mills * SeqAIJSELL matrix. This routine is called by the MatCreate_SeqAIJSELL() 136*4dfdc2d9SRichard Tran Mills * routine, but can also be used to convert an assembled SeqAIJ matrix 137*4dfdc2d9SRichard Tran Mills * into a SeqAIJSELL one. */ 138*4dfdc2d9SRichard Tran Mills PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJSELL(Mat A,MatType type,MatReuse reuse,Mat *newmat) 139*4dfdc2d9SRichard Tran Mills { 140*4dfdc2d9SRichard Tran Mills PetscErrorCode ierr; 141*4dfdc2d9SRichard Tran Mills Mat B = *newmat; 142*4dfdc2d9SRichard Tran Mills Mat_SeqAIJ *b; 143*4dfdc2d9SRichard Tran Mills Mat_SeqAIJSELL *aijsell; 144*4dfdc2d9SRichard Tran Mills PetscBool set; 145*4dfdc2d9SRichard Tran Mills PetscBool sametype; 146*4dfdc2d9SRichard Tran Mills 147*4dfdc2d9SRichard Tran Mills PetscFunctionBegin; 148*4dfdc2d9SRichard Tran Mills if (reuse == MAT_INITIAL_MATRIX) { 149*4dfdc2d9SRichard Tran Mills ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr); 150*4dfdc2d9SRichard Tran Mills } 151*4dfdc2d9SRichard Tran Mills 152*4dfdc2d9SRichard Tran Mills ierr = PetscObjectTypeCompare((PetscObject)A,type,&sametype);CHKERRQ(ierr); 153*4dfdc2d9SRichard Tran Mills if (sametype) PetscFunctionReturn(0); 154*4dfdc2d9SRichard Tran Mills 155*4dfdc2d9SRichard Tran Mills ierr = PetscNewLog(B,&aijsell);CHKERRQ(ierr); 156*4dfdc2d9SRichard Tran Mills b = (Mat_SeqAIJ*) B->data; 157*4dfdc2d9SRichard Tran Mills B->spptr = (void*) aijsell; 158*4dfdc2d9SRichard Tran Mills 159*4dfdc2d9SRichard Tran Mills /* Disable use of the inode routines so that the AIJSELL ones will be used instead. 160*4dfdc2d9SRichard Tran Mills * This happens in MatAssemblyEnd_SeqAIJSELL as well, but the assembly end may not be called, so set it here, too. 161*4dfdc2d9SRichard Tran Mills * As noted elsewhere, I wonder if it might make sense and be feasible to use some of the inode routines. */ 162*4dfdc2d9SRichard Tran Mills b->inode.use = PETSC_FALSE; 163*4dfdc2d9SRichard Tran Mills 164*4dfdc2d9SRichard Tran Mills /* Set function pointers for methods that we inherit from AIJ but override. 165*4dfdc2d9SRichard Tran Mills * We also parse some command line options below, since those determine some of the methods we point to. */ 166*4dfdc2d9SRichard Tran Mills B->ops->duplicate = MatDuplicate_SeqAIJSELL; 167*4dfdc2d9SRichard Tran Mills B->ops->assemblyend = MatAssemblyEnd_SeqAIJSELL; 168*4dfdc2d9SRichard Tran Mills B->ops->destroy = MatDestroy_SeqAIJSELL; 169*4dfdc2d9SRichard Tran Mills 170*4dfdc2d9SRichard Tran Mills aijsell->S = NULL; 171*4dfdc2d9SRichard Tran Mills aijsell->eager_shadow = PETSC_FALSE; 172*4dfdc2d9SRichard Tran Mills 173*4dfdc2d9SRichard Tran Mills /* Parse command line options. */ 174*4dfdc2d9SRichard Tran Mills ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"AIJSELL Options","Mat");CHKERRQ(ierr); 175*4dfdc2d9SRichard Tran Mills ierr = PetscOptionsBool("-mat_aijsell_eager_shadow","Eager Shadowing","None",(PetscBool)aijsell->eager_shadow,(PetscBool*)&aijsell->eager_shadow,&set);CHKERRQ(ierr); 176*4dfdc2d9SRichard Tran Mills ierr = PetscOptionsEnd();CHKERRQ(ierr); 177*4dfdc2d9SRichard Tran Mills 178*4dfdc2d9SRichard Tran Mills /* If A has already been assembled and eager shadowing is specified, build the shadow matrix. */ 179*4dfdc2d9SRichard Tran Mills if (A->assembled) { 180*4dfdc2d9SRichard Tran Mills /* TODO: Have the shadow matrix for B be built now if eager_shadow is set to true. */ 181*4dfdc2d9SRichard Tran Mills } 182*4dfdc2d9SRichard Tran Mills 183*4dfdc2d9SRichard Tran Mills /* Commenting these out for now, as these functions are not yet implemented. 184*4dfdc2d9SRichard Tran Mills B->ops->mult = MatMult_SeqAIJSELL_SpMV2; 185*4dfdc2d9SRichard Tran Mills B->ops->multtranspose = MatMultTranspose_SeqAIJSELL_SpMV2; 186*4dfdc2d9SRichard Tran Mills B->ops->multadd = MatMultAdd_SeqAIJSELL_SpMV2; 187*4dfdc2d9SRichard Tran Mills B->ops->multtransposeadd = MatMultTransposeAdd_SeqAIJSELL_SpMV2; 188*4dfdc2d9SRichard Tran Mills */ 189*4dfdc2d9SRichard Tran Mills 190*4dfdc2d9SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaijsell_seqaij_C",MatConvert_SeqAIJSELL_SeqAIJ);CHKERRQ(ierr); 191*4dfdc2d9SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqdense_seqaijsell_C",MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr); 192*4dfdc2d9SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaijsell_C",MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr); 193*4dfdc2d9SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqdense_seqaijsell_C",MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr); 194*4dfdc2d9SRichard Tran Mills 195*4dfdc2d9SRichard Tran Mills ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJSELL);CHKERRQ(ierr); 196*4dfdc2d9SRichard Tran Mills *newmat = B; 197*4dfdc2d9SRichard Tran Mills PetscFunctionReturn(0); 198*4dfdc2d9SRichard Tran Mills } 199*4dfdc2d9SRichard Tran Mills 200*4dfdc2d9SRichard Tran Mills /*@C 201*4dfdc2d9SRichard Tran Mills MatCreateSeqAIJSELL - Creates a sparse matrix of type SEQAIJSELL. 202*4dfdc2d9SRichard Tran Mills This type inherits from AIJ and is largely identical, but keeps a "shadow" 203*4dfdc2d9SRichard Tran Mills copy of the matrix in SEQSELL format, which is used when performing 204*4dfdc2d9SRichard Tran Mills operations for which this format is more suitable. 205*4dfdc2d9SRichard Tran Mills 206*4dfdc2d9SRichard Tran Mills Collective on MPI_Comm 207*4dfdc2d9SRichard Tran Mills 208*4dfdc2d9SRichard Tran Mills Input Parameters: 209*4dfdc2d9SRichard Tran Mills + comm - MPI communicator, set to PETSC_COMM_SELF 210*4dfdc2d9SRichard Tran Mills . m - number of rows 211*4dfdc2d9SRichard Tran Mills . n - number of columns 212*4dfdc2d9SRichard Tran Mills . nz - number of nonzeros per row (same for all rows) 213*4dfdc2d9SRichard Tran Mills - nnz - array containing the number of nonzeros in the various rows 214*4dfdc2d9SRichard Tran Mills (possibly different for each row) or NULL 215*4dfdc2d9SRichard Tran Mills 216*4dfdc2d9SRichard Tran Mills Output Parameter: 217*4dfdc2d9SRichard Tran Mills . A - the matrix 218*4dfdc2d9SRichard Tran Mills 219*4dfdc2d9SRichard Tran Mills Options Database Keys: 220*4dfdc2d9SRichard Tran Mills . -mat_aijsell_eager_shadow - Construct shadow matrix upon matrix assembly; default is to take a "lazy" approach, performing this step the first time the matrix is applied 221*4dfdc2d9SRichard Tran Mills 222*4dfdc2d9SRichard Tran Mills Notes: 223*4dfdc2d9SRichard Tran Mills If nnz is given then nz is ignored 224*4dfdc2d9SRichard Tran Mills 225*4dfdc2d9SRichard Tran Mills Level: intermediate 226*4dfdc2d9SRichard Tran Mills 227*4dfdc2d9SRichard Tran Mills .keywords: matrix, sparse, parallel 228*4dfdc2d9SRichard Tran Mills 229*4dfdc2d9SRichard Tran Mills .seealso: MatCreate(), MatCreateMPIAIJSELL(), MatSetValues() 230*4dfdc2d9SRichard Tran Mills @*/ 231*4dfdc2d9SRichard Tran Mills PetscErrorCode MatCreateSeqAIJSELL(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A) 232*4dfdc2d9SRichard Tran Mills { 233*4dfdc2d9SRichard Tran Mills PetscErrorCode ierr; 234*4dfdc2d9SRichard Tran Mills 235*4dfdc2d9SRichard Tran Mills PetscFunctionBegin; 236*4dfdc2d9SRichard Tran Mills ierr = MatCreate(comm,A);CHKERRQ(ierr); 237*4dfdc2d9SRichard Tran Mills ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr); 238*4dfdc2d9SRichard Tran Mills ierr = MatSetType(*A,MATSEQAIJSELL);CHKERRQ(ierr); 239*4dfdc2d9SRichard Tran Mills ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr); 240*4dfdc2d9SRichard Tran Mills PetscFunctionReturn(0); 241*4dfdc2d9SRichard Tran Mills } 242*4dfdc2d9SRichard Tran Mills 243*4dfdc2d9SRichard Tran Mills PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJSELL(Mat A) 244*4dfdc2d9SRichard Tran Mills { 245*4dfdc2d9SRichard Tran Mills PetscErrorCode ierr; 246*4dfdc2d9SRichard Tran Mills 247*4dfdc2d9SRichard Tran Mills PetscFunctionBegin; 248*4dfdc2d9SRichard Tran Mills ierr = MatSetType(A,MATSEQAIJ);CHKERRQ(ierr); 249*4dfdc2d9SRichard Tran Mills ierr = MatConvert_SeqAIJ_SeqAIJSELL(A,MATSEQAIJSELL,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr); 250*4dfdc2d9SRichard Tran Mills PetscFunctionReturn(0); 251*4dfdc2d9SRichard Tran Mills } 252