xref: /petsc/src/mat/impls/aij/seq/aijsell/aijsell.c (revision 2e956fe4fc852fabc23b437482e1fb7b77fddb0d)
14dfdc2d9SRichard Tran Mills /*
24dfdc2d9SRichard Tran Mills   Defines basic operations for the MATSEQAIJSELL matrix class.
34dfdc2d9SRichard Tran Mills   This class is derived from the MATAIJCLASS, but maintains a "shadow" copy
44dfdc2d9SRichard Tran Mills   of the matrix stored in MATSEQSELL format, which is used as appropriate for
54dfdc2d9SRichard Tran Mills   performing operations for which this format is more suitable.
64dfdc2d9SRichard Tran Mills */
74dfdc2d9SRichard Tran Mills 
84dfdc2d9SRichard Tran Mills #include <../src/mat/impls/aij/seq/aij.h>
9b0e5de86SRichard Tran Mills #include <../src/mat/impls/sell/seq/sell.h>
104dfdc2d9SRichard Tran Mills 
114dfdc2d9SRichard Tran Mills typedef struct {
124dfdc2d9SRichard Tran Mills   Mat              S; /* The SELL formatted "shadow" matrix. */
134dfdc2d9SRichard Tran Mills   PetscBool        eager_shadow;
144dfdc2d9SRichard Tran Mills   PetscObjectState state; /* State of the matrix when shadow matrix was last constructed. */
154dfdc2d9SRichard Tran Mills } Mat_SeqAIJSELL;
164dfdc2d9SRichard Tran Mills 
174dfdc2d9SRichard Tran Mills PETSC_INTERN PetscErrorCode MatConvert_SeqAIJSELL_SeqAIJ(Mat A,MatType type,MatReuse reuse,Mat *newmat)
184dfdc2d9SRichard Tran Mills {
194dfdc2d9SRichard Tran Mills   /* This routine is only called to convert a MATAIJSELL to its base PETSc type, */
204dfdc2d9SRichard Tran Mills   /* so we will ignore 'MatType type'. */
214dfdc2d9SRichard Tran Mills   Mat            B        = *newmat;
224dfdc2d9SRichard Tran Mills   Mat_SeqAIJSELL *aijsell = (Mat_SeqAIJSELL*) A->spptr;
234dfdc2d9SRichard Tran Mills 
244dfdc2d9SRichard Tran Mills   PetscFunctionBegin;
254dfdc2d9SRichard Tran Mills   if (reuse == MAT_INITIAL_MATRIX) {
269566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&B));
274dfdc2d9SRichard Tran Mills   }
284dfdc2d9SRichard Tran Mills 
294dfdc2d9SRichard Tran Mills   /* Reset the original function pointers. */
304dfdc2d9SRichard Tran Mills   B->ops->duplicate        = MatDuplicate_SeqAIJ;
314dfdc2d9SRichard Tran Mills   B->ops->assemblyend      = MatAssemblyEnd_SeqAIJ;
324dfdc2d9SRichard Tran Mills   B->ops->destroy          = MatDestroy_SeqAIJ;
334dfdc2d9SRichard Tran Mills   B->ops->mult             = MatMult_SeqAIJ;
344dfdc2d9SRichard Tran Mills   B->ops->multtranspose    = MatMultTranspose_SeqAIJ;
354dfdc2d9SRichard Tran Mills   B->ops->multadd          = MatMultAdd_SeqAIJ;
364dfdc2d9SRichard Tran Mills   B->ops->multtransposeadd = MatMultTransposeAdd_SeqAIJ;
37af22a668SRichard Tran Mills   B->ops->sor              = MatSOR_SeqAIJ;
384dfdc2d9SRichard Tran Mills 
399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaijsell_seqaij_C",NULL));
404dfdc2d9SRichard Tran Mills 
414dfdc2d9SRichard Tran Mills   if (reuse == MAT_INITIAL_MATRIX) aijsell = (Mat_SeqAIJSELL*)B->spptr;
424dfdc2d9SRichard Tran Mills 
438cde19baSRichard Tran Mills   /* Clean up the Mat_SeqAIJSELL data structure.
448cde19baSRichard Tran Mills    * Note that MatDestroy() simply returns if passed a NULL value, so it's OK to call even if the shadow matrix was never constructed. */
459566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&aijsell->S));
469566063dSJacob Faibussowitsch   PetscCall(PetscFree(B->spptr));
474dfdc2d9SRichard Tran Mills 
484dfdc2d9SRichard Tran Mills   /* Change the type of B to MATSEQAIJ. */
499566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQAIJ));
504dfdc2d9SRichard Tran Mills 
514dfdc2d9SRichard Tran Mills   *newmat = B;
524dfdc2d9SRichard Tran Mills   PetscFunctionReturn(0);
534dfdc2d9SRichard Tran Mills }
544dfdc2d9SRichard Tran Mills 
554dfdc2d9SRichard Tran Mills PetscErrorCode MatDestroy_SeqAIJSELL(Mat A)
564dfdc2d9SRichard Tran Mills {
574dfdc2d9SRichard Tran Mills   Mat_SeqAIJSELL  *aijsell = (Mat_SeqAIJSELL*) A->spptr;
584dfdc2d9SRichard Tran Mills 
594dfdc2d9SRichard Tran Mills   PetscFunctionBegin;
604dfdc2d9SRichard Tran Mills 
614dfdc2d9SRichard Tran Mills   /* If MatHeaderMerge() was used, then this SeqAIJSELL matrix will not have an
624dfdc2d9SRichard Tran Mills    * spptr pointer. */
634dfdc2d9SRichard Tran Mills   if (aijsell) {
644dfdc2d9SRichard Tran Mills     /* Clean up everything in the Mat_SeqAIJSELL data structure, then free A->spptr. */
659566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&aijsell->S));
669566063dSJacob Faibussowitsch     PetscCall(PetscFree(A->spptr));
674dfdc2d9SRichard Tran Mills   }
684dfdc2d9SRichard Tran Mills 
694dfdc2d9SRichard Tran Mills   /* Change the type of A back to SEQAIJ and use MatDestroy_SeqAIJ()
704dfdc2d9SRichard Tran Mills    * to destroy everything that remains. */
719566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATSEQAIJ));
724dfdc2d9SRichard Tran Mills   /* Note that I don't call MatSetType().  I believe this is because that
734dfdc2d9SRichard Tran Mills    * is only to be called when *building* a matrix.  I could be wrong, but
744dfdc2d9SRichard Tran Mills    * that is how things work for the SuperLU matrix class. */
75*2e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaijsell_seqaij_C",NULL));
769566063dSJacob Faibussowitsch   PetscCall(MatDestroy_SeqAIJ(A));
774dfdc2d9SRichard Tran Mills   PetscFunctionReturn(0);
784dfdc2d9SRichard Tran Mills }
794dfdc2d9SRichard Tran Mills 
80a2a1850bSRichard Tran Mills /* Build or update the shadow matrix if and only if needed.
81a2a1850bSRichard Tran Mills  * We track the ObjectState to determine when this needs to be done. */
82b0e5de86SRichard Tran Mills PETSC_INTERN PetscErrorCode MatSeqAIJSELL_build_shadow(Mat A)
83b0e5de86SRichard Tran Mills {
84b0e5de86SRichard Tran Mills   Mat_SeqAIJSELL   *aijsell = (Mat_SeqAIJSELL*) A->spptr;
85a2a1850bSRichard Tran Mills   PetscObjectState state;
86b0e5de86SRichard Tran Mills 
87b0e5de86SRichard Tran Mills   PetscFunctionBegin;
889566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)A,&state));
89a2a1850bSRichard Tran Mills   if (aijsell->S && aijsell->state == state) {
90a2a1850bSRichard Tran Mills     /* The existing shadow matrix is up-to-date, so simply exit. */
91a2a1850bSRichard Tran Mills     PetscFunctionReturn(0);
92a2a1850bSRichard Tran Mills   }
93a2a1850bSRichard Tran Mills 
949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_Convert,A,0,0,0));
95b0e5de86SRichard Tran Mills   if (aijsell->S) {
969566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqAIJ_SeqSELL(A,MATSEQSELL,MAT_REUSE_MATRIX,&aijsell->S));
97b0e5de86SRichard Tran Mills   } else {
989566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqAIJ_SeqSELL(A,MATSEQSELL,MAT_INITIAL_MATRIX,&aijsell->S));
99b0e5de86SRichard Tran Mills   }
1009566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(MAT_Convert,A,0,0,0));
101b0e5de86SRichard Tran Mills 
102b0e5de86SRichard Tran Mills   /* Record the ObjectState so that we can tell when the shadow matrix needs updating */
1039566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)A,&aijsell->state));
104b0e5de86SRichard Tran Mills 
105b0e5de86SRichard Tran Mills   PetscFunctionReturn(0);
106b0e5de86SRichard Tran Mills }
107b0e5de86SRichard Tran Mills 
1084dfdc2d9SRichard Tran Mills PetscErrorCode MatDuplicate_SeqAIJSELL(Mat A, MatDuplicateOption op, Mat *M)
1094dfdc2d9SRichard Tran Mills {
1104dfdc2d9SRichard Tran Mills   Mat_SeqAIJSELL *aijsell;
1114dfdc2d9SRichard Tran Mills   Mat_SeqAIJSELL *aijsell_dest;
1124dfdc2d9SRichard Tran Mills 
1134dfdc2d9SRichard Tran Mills   PetscFunctionBegin;
1149566063dSJacob Faibussowitsch   PetscCall(MatDuplicate_SeqAIJ(A,op,M));
1154dfdc2d9SRichard Tran Mills   aijsell      = (Mat_SeqAIJSELL*) A->spptr;
1164dfdc2d9SRichard Tran Mills   aijsell_dest = (Mat_SeqAIJSELL*) (*M)->spptr;
1179566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(aijsell_dest,aijsell,1));
1184dfdc2d9SRichard Tran Mills   /* We don't duplicate the shadow matrix -- that will be constructed as needed. */
1194dfdc2d9SRichard Tran Mills   aijsell_dest->S = NULL;
12063663694SRichard Tran Mills   if (aijsell->eager_shadow) {
1219566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSELL_build_shadow(A));
12263663694SRichard Tran Mills   }
1234dfdc2d9SRichard Tran Mills   PetscFunctionReturn(0);
1244dfdc2d9SRichard Tran Mills }
1254dfdc2d9SRichard Tran Mills 
1264dfdc2d9SRichard Tran Mills PetscErrorCode MatAssemblyEnd_SeqAIJSELL(Mat A, MatAssemblyType mode)
1274dfdc2d9SRichard Tran Mills {
1284dfdc2d9SRichard Tran Mills   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
1298cde19baSRichard Tran Mills   Mat_SeqAIJSELL  *aijsell = (Mat_SeqAIJSELL*)A->spptr;
1304dfdc2d9SRichard Tran Mills 
1314dfdc2d9SRichard Tran Mills   PetscFunctionBegin;
1324dfdc2d9SRichard Tran Mills   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1334dfdc2d9SRichard Tran Mills 
1344dfdc2d9SRichard Tran Mills   /* I disable the use of the inode routines so that the AIJSELL ones will be
1354dfdc2d9SRichard Tran Mills    * used instead, but I wonder if it might make sense (and is feasible) to
1364dfdc2d9SRichard Tran Mills    * use some of them. */
1374dfdc2d9SRichard Tran Mills   a->inode.use = PETSC_FALSE;
1384dfdc2d9SRichard Tran Mills 
1394dfdc2d9SRichard Tran Mills   /* Since a MATSEQAIJSELL matrix is really just a MATSEQAIJ with some
1404dfdc2d9SRichard Tran Mills    * extra information and some different methods, call the AssemblyEnd
1414dfdc2d9SRichard Tran Mills    * routine for a MATSEQAIJ.
1424dfdc2d9SRichard Tran Mills    * I'm not sure if this is the best way to do this, but it avoids
1434dfdc2d9SRichard Tran Mills    * a lot of code duplication. */
1444dfdc2d9SRichard Tran Mills 
1459566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd_SeqAIJ(A, mode));
1464dfdc2d9SRichard Tran Mills 
1474dfdc2d9SRichard Tran Mills   /* If the user has requested "eager" shadowing, create the SELL shadow matrix (if needed; the function checks).
1484dfdc2d9SRichard Tran Mills    * (The default is to take a "lazy" approach, deferring this until something like MatMult() is called.) */
1494dfdc2d9SRichard Tran Mills   if (aijsell->eager_shadow) {
1509566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSELL_build_shadow(A));
1514dfdc2d9SRichard Tran Mills   }
1524dfdc2d9SRichard Tran Mills 
1534dfdc2d9SRichard Tran Mills   PetscFunctionReturn(0);
1544dfdc2d9SRichard Tran Mills }
1554dfdc2d9SRichard Tran Mills 
156b0e5de86SRichard Tran Mills PetscErrorCode MatMult_SeqAIJSELL(Mat A,Vec xx,Vec yy)
157b0e5de86SRichard Tran Mills {
158b0e5de86SRichard Tran Mills   Mat_SeqAIJSELL    *aijsell = (Mat_SeqAIJSELL*)A->spptr;
159b0e5de86SRichard Tran Mills 
160b0e5de86SRichard Tran Mills   PetscFunctionBegin;
1619566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSELL_build_shadow(A));
1629566063dSJacob Faibussowitsch   PetscCall(MatMult_SeqSELL(aijsell->S,xx,yy));
163b0e5de86SRichard Tran Mills   PetscFunctionReturn(0);
164b0e5de86SRichard Tran Mills }
165b0e5de86SRichard Tran Mills 
1664da9d7bdSRichard Tran Mills PetscErrorCode MatMultTranspose_SeqAIJSELL(Mat A,Vec xx,Vec yy)
1674da9d7bdSRichard Tran Mills {
1684da9d7bdSRichard Tran Mills   Mat_SeqAIJSELL    *aijsell=(Mat_SeqAIJSELL*)A->spptr;
1694da9d7bdSRichard Tran Mills 
1704da9d7bdSRichard Tran Mills   PetscFunctionBegin;
1719566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSELL_build_shadow(A));
1729566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose_SeqSELL(aijsell->S,xx,yy));
1734da9d7bdSRichard Tran Mills   PetscFunctionReturn(0);
1744da9d7bdSRichard Tran Mills }
1754da9d7bdSRichard Tran Mills 
1764da9d7bdSRichard Tran Mills PetscErrorCode MatMultAdd_SeqAIJSELL(Mat A,Vec xx,Vec yy,Vec zz)
1774da9d7bdSRichard Tran Mills {
1784da9d7bdSRichard Tran Mills   Mat_SeqAIJSELL    *aijsell=(Mat_SeqAIJSELL*)A->spptr;
1794da9d7bdSRichard Tran Mills 
1804da9d7bdSRichard Tran Mills   PetscFunctionBegin;
1819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSELL_build_shadow(A));
1829566063dSJacob Faibussowitsch   PetscCall(MatMultAdd_SeqSELL(aijsell->S,xx,yy,zz));
1834da9d7bdSRichard Tran Mills   PetscFunctionReturn(0);
1844da9d7bdSRichard Tran Mills }
1854da9d7bdSRichard Tran Mills 
1864da9d7bdSRichard Tran Mills PetscErrorCode MatMultTransposeAdd_SeqAIJSELL(Mat A,Vec xx,Vec yy,Vec zz)
1874da9d7bdSRichard Tran Mills {
1884da9d7bdSRichard Tran Mills   Mat_SeqAIJSELL    *aijsell=(Mat_SeqAIJSELL*)A->spptr;
1894da9d7bdSRichard Tran Mills 
1904da9d7bdSRichard Tran Mills   PetscFunctionBegin;
1919566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSELL_build_shadow(A));
1929566063dSJacob Faibussowitsch   PetscCall(MatMultTransposeAdd_SeqSELL(aijsell->S,xx,yy,zz));
1934da9d7bdSRichard Tran Mills   PetscFunctionReturn(0);
1944da9d7bdSRichard Tran Mills }
1954da9d7bdSRichard Tran Mills 
196af22a668SRichard Tran Mills PetscErrorCode MatSOR_SeqAIJSELL(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
197af22a668SRichard Tran Mills {
198af22a668SRichard Tran Mills   Mat_SeqAIJSELL    *aijsell=(Mat_SeqAIJSELL*)A->spptr;
199af22a668SRichard Tran Mills 
200af22a668SRichard Tran Mills   PetscFunctionBegin;
2019566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSELL_build_shadow(A));
2029566063dSJacob Faibussowitsch   PetscCall(MatSOR_SeqSELL(aijsell->S,bb,omega,flag,fshift,its,lits,xx));
203af22a668SRichard Tran Mills   PetscFunctionReturn(0);
204af22a668SRichard Tran Mills }
205af22a668SRichard Tran Mills 
2064dfdc2d9SRichard Tran Mills /* MatConvert_SeqAIJ_SeqAIJSELL converts a SeqAIJ matrix into a
2074dfdc2d9SRichard Tran Mills  * SeqAIJSELL matrix.  This routine is called by the MatCreate_SeqAIJSELL()
2084dfdc2d9SRichard Tran Mills  * routine, but can also be used to convert an assembled SeqAIJ matrix
2094dfdc2d9SRichard Tran Mills  * into a SeqAIJSELL one. */
2104dfdc2d9SRichard Tran Mills PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJSELL(Mat A,MatType type,MatReuse reuse,Mat *newmat)
2114dfdc2d9SRichard Tran Mills {
2124dfdc2d9SRichard Tran Mills   Mat            B = *newmat;
2134dfdc2d9SRichard Tran Mills   Mat_SeqAIJ     *b;
2144dfdc2d9SRichard Tran Mills   Mat_SeqAIJSELL *aijsell;
2154dfdc2d9SRichard Tran Mills   PetscBool      set;
2164dfdc2d9SRichard Tran Mills   PetscBool      sametype;
2174dfdc2d9SRichard Tran Mills 
2184dfdc2d9SRichard Tran Mills   PetscFunctionBegin;
2194dfdc2d9SRichard Tran Mills   if (reuse == MAT_INITIAL_MATRIX) {
2209566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&B));
2214dfdc2d9SRichard Tran Mills   }
2224dfdc2d9SRichard Tran Mills 
2239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A,type,&sametype));
2244dfdc2d9SRichard Tran Mills   if (sametype) PetscFunctionReturn(0);
2254dfdc2d9SRichard Tran Mills 
2269566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&aijsell));
2274dfdc2d9SRichard Tran Mills   b        = (Mat_SeqAIJ*) B->data;
2284dfdc2d9SRichard Tran Mills   B->spptr = (void*) aijsell;
2294dfdc2d9SRichard Tran Mills 
2304dfdc2d9SRichard Tran Mills   /* Disable use of the inode routines so that the AIJSELL ones will be used instead.
2314dfdc2d9SRichard Tran Mills    * This happens in MatAssemblyEnd_SeqAIJSELL as well, but the assembly end may not be called, so set it here, too.
2324dfdc2d9SRichard Tran Mills    * As noted elsewhere, I wonder if it might make sense and be feasible to use some of the inode routines. */
2334dfdc2d9SRichard Tran Mills   b->inode.use = PETSC_FALSE;
2344dfdc2d9SRichard Tran Mills 
2354dfdc2d9SRichard Tran Mills   /* Set function pointers for methods that we inherit from AIJ but override.
2364dfdc2d9SRichard Tran Mills    * We also parse some command line options below, since those determine some of the methods we point to. */
2374dfdc2d9SRichard Tran Mills   B->ops->duplicate        = MatDuplicate_SeqAIJSELL;
2384dfdc2d9SRichard Tran Mills   B->ops->assemblyend      = MatAssemblyEnd_SeqAIJSELL;
2394dfdc2d9SRichard Tran Mills   B->ops->destroy          = MatDestroy_SeqAIJSELL;
2404dfdc2d9SRichard Tran Mills 
2414dfdc2d9SRichard Tran Mills   aijsell->S = NULL;
2424dfdc2d9SRichard Tran Mills   aijsell->eager_shadow = PETSC_FALSE;
2434dfdc2d9SRichard Tran Mills 
2444dfdc2d9SRichard Tran Mills   /* Parse command line options. */
245d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"AIJSELL Options","Mat");
2469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_aijsell_eager_shadow","Eager Shadowing","None",(PetscBool)aijsell->eager_shadow,(PetscBool*)&aijsell->eager_shadow,&set));
247d0609cedSBarry Smith   PetscOptionsEnd();
2484dfdc2d9SRichard Tran Mills 
2494dfdc2d9SRichard Tran Mills   /* If A has already been assembled and eager shadowing is specified, build the shadow matrix. */
25063663694SRichard Tran Mills   if (A->assembled && aijsell->eager_shadow) {
2519566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSELL_build_shadow(A));
2524dfdc2d9SRichard Tran Mills   }
2534dfdc2d9SRichard Tran Mills 
254b0e5de86SRichard Tran Mills   B->ops->mult             = MatMult_SeqAIJSELL;
255b0e5de86SRichard Tran Mills   B->ops->multtranspose    = MatMultTranspose_SeqAIJSELL;
256b0e5de86SRichard Tran Mills   B->ops->multadd          = MatMultAdd_SeqAIJSELL;
257b0e5de86SRichard Tran Mills   B->ops->multtransposeadd = MatMultTransposeAdd_SeqAIJSELL;
258af22a668SRichard Tran Mills   B->ops->sor              = MatSOR_SeqAIJSELL;
2594dfdc2d9SRichard Tran Mills 
2609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaijsell_seqaij_C",MatConvert_SeqAIJSELL_SeqAIJ));
2614dfdc2d9SRichard Tran Mills 
2629566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJSELL));
2634dfdc2d9SRichard Tran Mills   *newmat = B;
2644dfdc2d9SRichard Tran Mills   PetscFunctionReturn(0);
2654dfdc2d9SRichard Tran Mills }
2664dfdc2d9SRichard Tran Mills 
2674dfdc2d9SRichard Tran Mills /*@C
2684dfdc2d9SRichard Tran Mills    MatCreateSeqAIJSELL - Creates a sparse matrix of type SEQAIJSELL.
2694dfdc2d9SRichard Tran Mills    This type inherits from AIJ and is largely identical, but keeps a "shadow"
2708197ac24SRichard Tran Mills    copy of the matrix in SEQSELL format, which is used when this format
2718197ac24SRichard Tran Mills    may be more suitable for a requested operation. Currently, SEQSELL format
2728197ac24SRichard Tran Mills    is used for MatMult, MatMultTranspose, MatMultAdd, MatMultTransposeAdd,
2738197ac24SRichard Tran Mills    and MatSOR operations.
274ca9cdca7SRichard Tran Mills    Because SEQAIJSELL is a subtype of SEQAIJ, the option "-mat_seqaij_type seqaijsell" can be used to make
275ca9cdca7SRichard Tran Mills    sequential AIJ matrices default to being instances of MATSEQAIJSELL.
2764dfdc2d9SRichard Tran Mills 
277d083f849SBarry Smith    Collective
2784dfdc2d9SRichard Tran Mills 
2794dfdc2d9SRichard Tran Mills    Input Parameters:
2804dfdc2d9SRichard Tran Mills +  comm - MPI communicator, set to PETSC_COMM_SELF
2814dfdc2d9SRichard Tran Mills .  m - number of rows
2824dfdc2d9SRichard Tran Mills .  n - number of columns
2834dfdc2d9SRichard Tran Mills .  nz - number of nonzeros per row (same for all rows)
2844dfdc2d9SRichard Tran Mills -  nnz - array containing the number of nonzeros in the various rows
2854dfdc2d9SRichard Tran Mills          (possibly different for each row) or NULL
2864dfdc2d9SRichard Tran Mills 
2874dfdc2d9SRichard Tran Mills    Output Parameter:
2884dfdc2d9SRichard Tran Mills .  A - the matrix
2894dfdc2d9SRichard Tran Mills 
2904dfdc2d9SRichard Tran Mills    Options Database Keys:
2914dfdc2d9SRichard 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
2924dfdc2d9SRichard Tran Mills 
2934dfdc2d9SRichard Tran Mills    Notes:
2944dfdc2d9SRichard Tran Mills    If nnz is given then nz is ignored
2954dfdc2d9SRichard Tran Mills 
2964dfdc2d9SRichard Tran Mills    Level: intermediate
2974dfdc2d9SRichard Tran Mills 
298db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateMPIAIJSELL()`, `MatSetValues()`
2994dfdc2d9SRichard Tran Mills @*/
3004dfdc2d9SRichard Tran Mills PetscErrorCode  MatCreateSeqAIJSELL(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
3014dfdc2d9SRichard Tran Mills {
3024dfdc2d9SRichard Tran Mills   PetscFunctionBegin;
3039566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,A));
3049566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A,m,n,m,n));
3059566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A,MATSEQAIJSELL));
3069566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz));
3074dfdc2d9SRichard Tran Mills   PetscFunctionReturn(0);
3084dfdc2d9SRichard Tran Mills }
3094dfdc2d9SRichard Tran Mills 
3104dfdc2d9SRichard Tran Mills PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJSELL(Mat A)
3114dfdc2d9SRichard Tran Mills {
3124dfdc2d9SRichard Tran Mills   PetscFunctionBegin;
3139566063dSJacob Faibussowitsch   PetscCall(MatSetType(A,MATSEQAIJ));
3149566063dSJacob Faibussowitsch   PetscCall(MatConvert_SeqAIJ_SeqAIJSELL(A,MATSEQAIJSELL,MAT_INPLACE_MATRIX,&A));
3154dfdc2d9SRichard Tran Mills   PetscFunctionReturn(0);
3164dfdc2d9SRichard Tran Mills }
317