Actual source code: aijtype.c

  1: #define PETSCMAT_DLL

 3:  #include src/mat/matimpl.h

  5: typedef struct {
  6:   PetscErrorCode (*MatConvert)(Mat, MatType,MatReuse,Mat*);
  7:   PetscErrorCode (*MatDestroy)(Mat);
  8: } Mat_AIJ;

 11: EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_AIJ(Mat, MatType,MatReuse,Mat *);
 12: EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_MPIAIJ_AIJ(Mat, MatType,MatReuse,Mat *);
 13: EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_AIJ_SeqAIJ(Mat, MatType,MatReuse,Mat *);
 14: EXTERN PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_AIJ_MPIAIJ(Mat, MatType,MatReuse,Mat *);

 20: PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_AIJ_SeqAIJ(Mat A, MatType type, MatReuse reuse,Mat *newmat)
 21: {
 23:   Mat            B=*newmat;
 24:   Mat_AIJ        *aij=(Mat_AIJ *)A->spptr;

 27:   if (reuse == MAT_INITIAL_MATRIX) {
 28:     MatDuplicate(A,MAT_COPY_VALUES, &B);
 29:   }

 31:   B->ops->convert = aij->MatConvert;
 32:   B->ops->destroy = aij->MatDestroy;

 34:   PetscFree(aij);

 36:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_aij_seqaij_C","",PETSC_NULL);
 37:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_aij_C","",PETSC_NULL);
 38:   PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);
 39:   *newmat = B;
 40:   return(0);
 41: }

 47: PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_AIJ_MPIAIJ(Mat A, MatType type, MatReuse reuse, Mat *newmat)
 48: {
 50:   Mat            B=*newmat;
 51:   Mat_AIJ        *aij=(Mat_AIJ *)A->spptr;

 54:   if (reuse == MAT_INITIAL_MATRIX) {
 55:     MatDuplicate(A,MAT_COPY_VALUES, &B);
 56:   }

 58:   B->ops->convert = aij->MatConvert;
 59:   B->ops->destroy = aij->MatDestroy;

 61:   PetscFree(aij);

 63:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_aij_mpiaij_C","",PETSC_NULL);
 64:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_aij_C","",PETSC_NULL);
 65:   PetscObjectChangeTypeName((PetscObject)B,MATMPIAIJ);
 66:   *newmat = B;
 67:   return(0);
 68: }

 73: PetscErrorCode MatDestroy_AIJ(Mat A)
 74: {
 75:   PetscMPIInt    size;

 79:   MPI_Comm_size(A->comm,&size);
 80:   if (size == 1) {
 81:     MatConvert_AIJ_SeqAIJ(A,MATSEQAIJ,MAT_REUSE_MATRIX,&A);
 82:   } else {
 83:     MatConvert_AIJ_MPIAIJ(A,MATMPIAIJ,MAT_REUSE_MATRIX,&A);
 84:   }
 85:   (*A->ops->destroy)(A);
 86:   return(0);
 87: }

 91: PetscErrorCode MatConvertFrom_AIJviaSeqAIJ(Mat A, MatType type,MatReuse reuse,Mat *newmat)
 92: {

 96:   MatConvert_AIJ_SeqAIJ(A,MATSEQAIJ,MAT_REUSE_MATRIX,&A);
 97:   MatConvert(A,type,reuse,newmat);
 98:   if (reuse == MAT_INITIAL_MATRIX) {
 99:     MatConvert_SeqAIJ_AIJ(A,MATAIJ,MAT_REUSE_MATRIX,&A);
100:   }
101:   return(0);
102: }

106: PetscErrorCode MatConvertFrom_AIJviaMPIAIJ(Mat A, MatType type,MatReuse reuse,Mat *newmat)
107: {

111:   MatConvert_AIJ_MPIAIJ(A,PETSC_NULL,MAT_REUSE_MATRIX,&A);
112:   MatConvert(A,type,reuse,newmat);
113:   if (reuse == MAT_INITIAL_MATRIX) {
114:     MatConvert_MPIAIJ_AIJ(A,MATAIJ,MAT_REUSE_MATRIX,&A);
115:   }
116:   return(0);
117: }

122: PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_AIJ(Mat A, MatType type,MatReuse reuse,Mat *newmat)
123: {
125:   Mat            B=*newmat;
126:   Mat_AIJ        *aij;

129:   if (reuse == MAT_INITIAL_MATRIX) {
130:     MatDuplicate(A,MAT_COPY_VALUES, &B);
131:   }
132: 
133:   PetscNew(Mat_AIJ,&aij);
134:   aij->MatConvert = A->ops->convert;
135:   aij->MatDestroy = A->ops->destroy;

137:   B->spptr        = (void *)aij;
138:   B->ops->convert = MatConvertFrom_AIJviaSeqAIJ;
139:   B->ops->destroy = MatDestroy_AIJ;

141:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_aij_seqaij_C",
142:                                     "MatConvert_AIJ_SeqAIJ",MatConvert_AIJ_SeqAIJ);
143:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_aij_C",
144:                                     "MatConvert_SeqAIJ_AIJ",MatConvert_SeqAIJ_AIJ);
145:   PetscObjectChangeTypeName((PetscObject)B,MATAIJ);
146:   *newmat = B;
147:   return(0);
148: }

154: PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_MPIAIJ_AIJ(Mat A, MatType type,MatReuse reuse,Mat *newmat)
155: {
157:   Mat            B=*newmat;
158:   Mat_AIJ        *aij;

161:   if (reuse == MAT_INITIAL_MATRIX) {
162:     MatDuplicate(A,MAT_COPY_VALUES, &B);
163:   }

165:   PetscNew(Mat_AIJ,&aij);
166:   aij->MatConvert = A->ops->convert;
167:   aij->MatDestroy = A->ops->destroy;

169:   B->spptr        = (void *)aij;
170:   B->ops->convert = MatConvertFrom_AIJviaMPIAIJ;
171:   B->ops->destroy = MatDestroy_AIJ;

173:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_aij_mpiaij_C",
174:                                     "MatConvert_AIJ_MPIAIJ",
175:                                     (void (*)(void))MatConvert_AIJ_MPIAIJ);
176:   PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_aij_C",
177:                                     "MatConvert_MPIAIJ_AIJ",
178:                                     (void (*)(void))MatConvert_MPIAIJ_AIJ);
179:   PetscObjectChangeTypeName((PetscObject)B,MATAIJ);
180:   *newmat = B;
181:   return(0);
182: }

188: PetscErrorCode PETSCMAT_DLLEXPORT MatConvertTo_AIJ(Mat A, MatType type,MatReuse reuse,Mat *newmat)
189: {
190:   /*
191:     This method is to be registered using MatConvertRegisterDynamic.  Perhaps a better mechanism would be to
192:     add a second MatConvert function pointer (one for "from" -- which we already have, and a second for "to").
193:     We should maintain the current registry list as well in order to provide a measure of backwards compatibility
194:     if indeed we make this change.
195:   */
197:   PetscMPIInt    size;
198:   Mat            B=*newmat;

201:   MPI_Comm_size(A->comm,&size);
202:   if (size == 1) {
203:     MatConvert(A,MATSEQAIJ,reuse,&B);
204:     MatConvert_SeqAIJ_AIJ(B,MATAIJ,MAT_REUSE_MATRIX,&B);
205:   } else {
206:     MatConvert(A,MATMPIAIJ,reuse,&B);
207:     MatConvert_MPIAIJ_AIJ(B,MATAIJ,MAT_REUSE_MATRIX,&B);
208:   }
209:   *newmat = B;
210:   return(0);
211: }

214: /*MC
215:    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.

217:    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
218:    and MATMPIAIJ otherwise.  As a result, for single process communicators, 
219:   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported 
220:   for communicators controlling multiple processes.  It is recommended that you call both of
221:   the above preallocation routines for simplicity.

223:    Options Database Keys:
224: . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()

226:   Level: beginner

228: .seealso: MatCreateMPIAIJ,MATSEQAIJ,MATMPIAIJ
229: M*/

234: PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_AIJ(Mat A)
235: {
237:   PetscMPIInt    size;

240:   PetscObjectChangeTypeName((PetscObject)A,MATAIJ);
241:   MPI_Comm_size(A->comm,&size);
242:   if (size == 1) {
243:     MatSetType(A,MATSEQAIJ);
244:     MatConvert_SeqAIJ_AIJ(A,MATAIJ,MAT_REUSE_MATRIX,&A);
245:   } else {
246:     MatSetType(A,MATMPIAIJ);
247:     MatConvert_MPIAIJ_AIJ(A,MATAIJ,MAT_REUSE_MATRIX,&A);
248:   }
249:   return(0);
250: }