xref: /petsc/src/mat/impls/kaij/kaij.c (revision 1cc06b555e92f8ec64db10330b8bbd830e5bc876)
149bd79ccSDebojyoti Ghosh 
249bd79ccSDebojyoti Ghosh /*
349bd79ccSDebojyoti Ghosh   Defines the basic matrix operations for the KAIJ  matrix storage format.
449bd79ccSDebojyoti Ghosh   This format is used to evaluate matrices of the form:
549bd79ccSDebojyoti Ghosh 
649bd79ccSDebojyoti Ghosh     [I \otimes S + A \otimes T]
749bd79ccSDebojyoti Ghosh 
849bd79ccSDebojyoti Ghosh   where
949bd79ccSDebojyoti Ghosh     S is a dense (p \times q) matrix
1049bd79ccSDebojyoti Ghosh     T is a dense (p \times q) matrix
1149bd79ccSDebojyoti Ghosh     A is an AIJ  (n \times n) matrix
1249bd79ccSDebojyoti Ghosh     I is the identity matrix
1349bd79ccSDebojyoti Ghosh 
1449bd79ccSDebojyoti Ghosh   The resulting matrix is (np \times nq)
1549bd79ccSDebojyoti Ghosh 
1649bd79ccSDebojyoti Ghosh   We provide:
1749bd79ccSDebojyoti Ghosh      MatMult()
1849bd79ccSDebojyoti Ghosh      MatMultAdd()
1949bd79ccSDebojyoti Ghosh      MatInvertBlockDiagonal()
2049bd79ccSDebojyoti Ghosh   and
2149bd79ccSDebojyoti Ghosh      MatCreateKAIJ(Mat,PetscInt,PetscInt,const PetscScalar[],const PetscScalar[],Mat*)
2249bd79ccSDebojyoti Ghosh 
2349bd79ccSDebojyoti Ghosh   This single directory handles both the sequential and parallel codes
2449bd79ccSDebojyoti Ghosh */
2549bd79ccSDebojyoti Ghosh 
2649bd79ccSDebojyoti Ghosh #include <../src/mat/impls/kaij/kaij.h> /*I "petscmat.h" I*/
2749bd79ccSDebojyoti Ghosh #include <../src/mat/utils/freespace.h>
2849bd79ccSDebojyoti Ghosh #include <petsc/private/vecimpl.h>
2949bd79ccSDebojyoti Ghosh 
3049bd79ccSDebojyoti Ghosh /*@C
3111a5261eSBarry Smith    MatKAIJGetAIJ - Get the `MATAIJ` matrix describing the blockwise action of the `MATKAIJ` matrix
3249bd79ccSDebojyoti Ghosh 
3311a5261eSBarry Smith    Not Collective, but if the `MATKAIJ` matrix is parallel, the `MATAIJ` matrix is also parallel
3449bd79ccSDebojyoti Ghosh 
3549bd79ccSDebojyoti Ghosh    Input Parameter:
3611a5261eSBarry Smith .  A - the `MATKAIJ` matrix
3749bd79ccSDebojyoti Ghosh 
3849bd79ccSDebojyoti Ghosh    Output Parameter:
3911a5261eSBarry Smith .  B - the `MATAIJ` matrix
4049bd79ccSDebojyoti Ghosh 
4149bd79ccSDebojyoti Ghosh    Level: advanced
4249bd79ccSDebojyoti Ghosh 
4311a5261eSBarry Smith    Note:
4411a5261eSBarry Smith    The reference count on the `MATAIJ` matrix is not increased so you should not destroy it.
4549bd79ccSDebojyoti Ghosh 
46*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateKAIJ()`, `MATKAIJ`, `MATAIJ`
4749bd79ccSDebojyoti Ghosh @*/
48d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJGetAIJ(Mat A, Mat *B)
49d71ae5a4SJacob Faibussowitsch {
5049bd79ccSDebojyoti Ghosh   PetscBool ismpikaij, isseqkaij;
5149bd79ccSDebojyoti Ghosh 
5249bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
539566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIKAIJ, &ismpikaij));
549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQKAIJ, &isseqkaij));
5549bd79ccSDebojyoti Ghosh   if (ismpikaij) {
5649bd79ccSDebojyoti Ghosh     Mat_MPIKAIJ *b = (Mat_MPIKAIJ *)A->data;
5749bd79ccSDebojyoti Ghosh 
5849bd79ccSDebojyoti Ghosh     *B = b->A;
5949bd79ccSDebojyoti Ghosh   } else if (isseqkaij) {
6049bd79ccSDebojyoti Ghosh     Mat_SeqKAIJ *b = (Mat_SeqKAIJ *)A->data;
6149bd79ccSDebojyoti Ghosh 
6249bd79ccSDebojyoti Ghosh     *B = b->AIJ;
63b04351cbSRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix passed in is not of type KAIJ");
643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6549bd79ccSDebojyoti Ghosh }
6649bd79ccSDebojyoti Ghosh 
6749bd79ccSDebojyoti Ghosh /*@C
682ef1f0ffSBarry Smith    MatKAIJGetS - Get the `S` matrix describing the shift action of the `MATKAIJ` matrix
6949bd79ccSDebojyoti Ghosh 
702ef1f0ffSBarry Smith    Not Collective; the entire `S` is stored and returned independently on all processes.
7149bd79ccSDebojyoti Ghosh 
7249bd79ccSDebojyoti Ghosh    Input Parameter:
7311a5261eSBarry Smith .  A - the `MATKAIJ` matrix
7449bd79ccSDebojyoti Ghosh 
75a5b5c723SRichard Tran Mills    Output Parameters:
762ef1f0ffSBarry Smith +  m - the number of rows in `S`
772ef1f0ffSBarry Smith .  n - the number of columns in `S`
78a5b5c723SRichard Tran Mills -  S - the S matrix, in form of a scalar array in column-major format
7949bd79ccSDebojyoti Ghosh 
8049bd79ccSDebojyoti Ghosh    Level: advanced
8149bd79ccSDebojyoti Ghosh 
822ef1f0ffSBarry Smith    Note:
832ef1f0ffSBarry Smith    All output parameters are optional (pass `NULL` if not desired)
842ef1f0ffSBarry Smith 
85*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatCreateKAIJ()`, `MatGetBlockSizes()`
8649bd79ccSDebojyoti Ghosh @*/
87d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJGetS(Mat A, PetscInt *m, PetscInt *n, PetscScalar **S)
88d71ae5a4SJacob Faibussowitsch {
8949bd79ccSDebojyoti Ghosh   Mat_SeqKAIJ *b = (Mat_SeqKAIJ *)A->data;
9049bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
91a5b5c723SRichard Tran Mills   if (m) *m = b->p;
92a5b5c723SRichard Tran Mills   if (n) *n = b->q;
93a5b5c723SRichard Tran Mills   if (S) *S = b->S;
943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95a5b5c723SRichard Tran Mills }
96a5b5c723SRichard Tran Mills 
97a5b5c723SRichard Tran Mills /*@C
982ef1f0ffSBarry Smith    MatKAIJGetSRead - Get a read-only pointer to the `S` matrix describing the shift action of the `MATKAIJ` matrix
99a5b5c723SRichard Tran Mills 
1002ef1f0ffSBarry Smith    Not Collective; the entire `S` is stored and returned independently on all processes.
101a5b5c723SRichard Tran Mills 
102a5b5c723SRichard Tran Mills    Input Parameter:
10311a5261eSBarry Smith .  A - the `MATKAIJ` matrix
104a5b5c723SRichard Tran Mills 
105a5b5c723SRichard Tran Mills    Output Parameters:
1062ef1f0ffSBarry Smith +  m - the number of rows in `S`
1072ef1f0ffSBarry Smith .  n - the number of columns in `S`
108a5b5c723SRichard Tran Mills -  S - the S matrix, in form of a scalar array in column-major format
109a5b5c723SRichard Tran Mills 
110a5b5c723SRichard Tran Mills    Level: advanced
111a5b5c723SRichard Tran Mills 
1122ef1f0ffSBarry Smith    Note:
1132ef1f0ffSBarry Smith    All output parameters are optional (pass `NULL` if not desired)
1142ef1f0ffSBarry Smith 
115*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatCreateKAIJ()`, `MatGetBlockSizes()`
116a5b5c723SRichard Tran Mills @*/
117d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJGetSRead(Mat A, PetscInt *m, PetscInt *n, const PetscScalar **S)
118d71ae5a4SJacob Faibussowitsch {
119a5b5c723SRichard Tran Mills   Mat_SeqKAIJ *b = (Mat_SeqKAIJ *)A->data;
120a5b5c723SRichard Tran Mills   PetscFunctionBegin;
121a5b5c723SRichard Tran Mills   if (m) *m = b->p;
122a5b5c723SRichard Tran Mills   if (n) *n = b->q;
123a5b5c723SRichard Tran Mills   if (S) *S = b->S;
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
125a5b5c723SRichard Tran Mills }
126a5b5c723SRichard Tran Mills 
127a5b5c723SRichard Tran Mills /*@C
12811a5261eSBarry Smith   MatKAIJRestoreS - Restore array obtained with `MatKAIJGetS()`
129a5b5c723SRichard Tran Mills 
1302ef1f0ffSBarry Smith   Not Collective
131a5b5c723SRichard Tran Mills 
1322ef1f0ffSBarry Smith   Input Parameters:
1332ef1f0ffSBarry Smith + A - the `MATKAIJ` matrix
1342ef1f0ffSBarry Smith - S - location of pointer to array obtained with `MatKAIJGetS()`
135a5b5c723SRichard Tran Mills 
136a5b5c723SRichard Tran Mills   Level: advanced
13711a5261eSBarry Smith 
1382ef1f0ffSBarry Smith   Note:
1392ef1f0ffSBarry Smith   This routine zeros the array pointer to prevent accidental reuse after it has been restored.
1402ef1f0ffSBarry Smith   If `NULL` is passed, it will not attempt to zero the array pointer.
1412ef1f0ffSBarry Smith 
142*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatKAIJGetS()`, `MatKAIJGetSRead()`, `MatKAIJRestoreSRead()`
143a5b5c723SRichard Tran Mills @*/
144d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJRestoreS(Mat A, PetscScalar **S)
145d71ae5a4SJacob Faibussowitsch {
146a5b5c723SRichard Tran Mills   PetscFunctionBegin;
147a5b5c723SRichard Tran Mills   if (S) *S = NULL;
1489566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
1493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
150a5b5c723SRichard Tran Mills }
151a5b5c723SRichard Tran Mills 
152a5b5c723SRichard Tran Mills /*@C
15311a5261eSBarry Smith   MatKAIJRestoreSRead - Restore array obtained with `MatKAIJGetSRead()`
154a5b5c723SRichard Tran Mills 
1552ef1f0ffSBarry Smith   Not Collective
156a5b5c723SRichard Tran Mills 
1572ef1f0ffSBarry Smith   Input Parameters:
1582ef1f0ffSBarry Smith + A - the `MATKAIJ` matrix
1592ef1f0ffSBarry Smith - S - location of pointer to array obtained with `MatKAIJGetS()`
160a5b5c723SRichard Tran Mills 
161a5b5c723SRichard Tran Mills   Level: advanced
16211a5261eSBarry Smith 
1632ef1f0ffSBarry Smith   Note:
1642ef1f0ffSBarry Smith   This routine zeros the array pointer to prevent accidental reuse after it has been restored.
1652ef1f0ffSBarry Smith   If `NULL` is passed, it will not attempt to zero the array pointer.
1662ef1f0ffSBarry Smith 
167*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatKAIJGetS()`, `MatKAIJGetSRead()`, `MatKAIJRestoreSRead()`
168a5b5c723SRichard Tran Mills @*/
169d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJRestoreSRead(Mat A, const PetscScalar **S)
170d71ae5a4SJacob Faibussowitsch {
171a5b5c723SRichard Tran Mills   PetscFunctionBegin;
172a5b5c723SRichard Tran Mills   if (S) *S = NULL;
1733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17449bd79ccSDebojyoti Ghosh }
17549bd79ccSDebojyoti Ghosh 
17649bd79ccSDebojyoti Ghosh /*@C
1772ef1f0ffSBarry Smith    MatKAIJGetT - Get the transformation matrix `T` associated with the `MATKAIJ` matrix
17849bd79ccSDebojyoti Ghosh 
1792ef1f0ffSBarry Smith    Not Collective; the entire `T` is stored and returned independently on all processes
18049bd79ccSDebojyoti Ghosh 
18149bd79ccSDebojyoti Ghosh    Input Parameter:
18211a5261eSBarry Smith .  A - the `MATKAIJ` matrix
18349bd79ccSDebojyoti Ghosh 
184d8d19677SJose E. Roman    Output Parameters:
1852ef1f0ffSBarry Smith +  m - the number of rows in `T`
1862ef1f0ffSBarry Smith .  n - the number of columns in `T`
187a5b5c723SRichard Tran Mills -  T - the T matrix, in form of a scalar array in column-major format
18849bd79ccSDebojyoti Ghosh 
18949bd79ccSDebojyoti Ghosh    Level: advanced
19049bd79ccSDebojyoti Ghosh 
1912ef1f0ffSBarry Smith    Note:
1922ef1f0ffSBarry Smith    All output parameters are optional (pass `NULL` if not desired)
1932ef1f0ffSBarry Smith 
194*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatCreateKAIJ()`, `MatGetBlockSizes()`
19549bd79ccSDebojyoti Ghosh @*/
196d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJGetT(Mat A, PetscInt *m, PetscInt *n, PetscScalar **T)
197d71ae5a4SJacob Faibussowitsch {
19849bd79ccSDebojyoti Ghosh   Mat_SeqKAIJ *b = (Mat_SeqKAIJ *)A->data;
19949bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
200a5b5c723SRichard Tran Mills   if (m) *m = b->p;
201a5b5c723SRichard Tran Mills   if (n) *n = b->q;
202a5b5c723SRichard Tran Mills   if (T) *T = b->T;
2033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
204a5b5c723SRichard Tran Mills }
205a5b5c723SRichard Tran Mills 
206a5b5c723SRichard Tran Mills /*@C
2072ef1f0ffSBarry Smith    MatKAIJGetTRead - Get a read-only pointer to the transformation matrix `T` associated with the `MATKAIJ` matrix
208a5b5c723SRichard Tran Mills 
2092ef1f0ffSBarry Smith    Not Collective; the entire `T` is stored and returned independently on all processes
210a5b5c723SRichard Tran Mills 
211a5b5c723SRichard Tran Mills    Input Parameter:
21211a5261eSBarry Smith .  A - the `MATKAIJ` matrix
213a5b5c723SRichard Tran Mills 
214d8d19677SJose E. Roman    Output Parameters:
2152ef1f0ffSBarry Smith +  m - the number of rows in `T`
2162ef1f0ffSBarry Smith .  n - the number of columns in `T`
217a5b5c723SRichard Tran Mills -  T - the T matrix, in form of a scalar array in column-major format
218a5b5c723SRichard Tran Mills 
219a5b5c723SRichard Tran Mills    Level: advanced
220a5b5c723SRichard Tran Mills 
2212ef1f0ffSBarry Smith    Note:
2222ef1f0ffSBarry Smith    All output parameters are optional (pass `NULL` if not desired)
2232ef1f0ffSBarry Smith 
224*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatCreateKAIJ()`, `MatGetBlockSizes()`
225a5b5c723SRichard Tran Mills @*/
226d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJGetTRead(Mat A, PetscInt *m, PetscInt *n, const PetscScalar **T)
227d71ae5a4SJacob Faibussowitsch {
228a5b5c723SRichard Tran Mills   Mat_SeqKAIJ *b = (Mat_SeqKAIJ *)A->data;
229a5b5c723SRichard Tran Mills   PetscFunctionBegin;
230a5b5c723SRichard Tran Mills   if (m) *m = b->p;
231a5b5c723SRichard Tran Mills   if (n) *n = b->q;
232a5b5c723SRichard Tran Mills   if (T) *T = b->T;
2333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
234a5b5c723SRichard Tran Mills }
235a5b5c723SRichard Tran Mills 
236a5b5c723SRichard Tran Mills /*@C
23711a5261eSBarry Smith   MatKAIJRestoreT - Restore array obtained with `MatKAIJGetT()`
238a5b5c723SRichard Tran Mills 
2392ef1f0ffSBarry Smith   Not Collective
240a5b5c723SRichard Tran Mills 
2412ef1f0ffSBarry Smith   Input Parameters:
2422ef1f0ffSBarry Smith + A - the `MATKAIJ` matrix
2432ef1f0ffSBarry Smith - T - location of pointer to array obtained with `MatKAIJGetS()`
244a5b5c723SRichard Tran Mills 
245a5b5c723SRichard Tran Mills   Level: advanced
24611a5261eSBarry Smith 
2472ef1f0ffSBarry Smith   Note:
2482ef1f0ffSBarry Smith   This routine zeros the array pointer to prevent accidental reuse after it has been restored.
2492ef1f0ffSBarry Smith   If `NULL` is passed, it will not attempt to zero the array pointer.
2502ef1f0ffSBarry Smith 
251*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatKAIJGetT()`, `MatKAIJGetTRead()`, `MatKAIJRestoreTRead()`
252a5b5c723SRichard Tran Mills @*/
253d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJRestoreT(Mat A, PetscScalar **T)
254d71ae5a4SJacob Faibussowitsch {
255a5b5c723SRichard Tran Mills   PetscFunctionBegin;
256a5b5c723SRichard Tran Mills   if (T) *T = NULL;
2579566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
2583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
259a5b5c723SRichard Tran Mills }
260a5b5c723SRichard Tran Mills 
261a5b5c723SRichard Tran Mills /*@C
26211a5261eSBarry Smith   MatKAIJRestoreTRead - Restore array obtained with `MatKAIJGetTRead()`
263a5b5c723SRichard Tran Mills 
2642ef1f0ffSBarry Smith   Not Collective
265a5b5c723SRichard Tran Mills 
2662ef1f0ffSBarry Smith   Input Parameters:
2672ef1f0ffSBarry Smith + A - the `MATKAIJ` matrix
2682ef1f0ffSBarry Smith - T - location of pointer to array obtained with `MatKAIJGetS()`
269a5b5c723SRichard Tran Mills 
270a5b5c723SRichard Tran Mills   Level: advanced
27111a5261eSBarry Smith 
2722ef1f0ffSBarry Smith   Note:
2732ef1f0ffSBarry Smith   This routine zeros the array pointer to prevent accidental reuse after it has been restored.
2742ef1f0ffSBarry Smith   If `NULL` is passed, it will not attempt to zero the array pointer.
2752ef1f0ffSBarry Smith 
276*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatKAIJGetT()`, `MatKAIJGetTRead()`, `MatKAIJRestoreTRead()`
277a5b5c723SRichard Tran Mills @*/
278d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJRestoreTRead(Mat A, const PetscScalar **T)
279d71ae5a4SJacob Faibussowitsch {
280a5b5c723SRichard Tran Mills   PetscFunctionBegin;
281a5b5c723SRichard Tran Mills   if (T) *T = NULL;
2823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28349bd79ccSDebojyoti Ghosh }
28449bd79ccSDebojyoti Ghosh 
2850567c835SRichard Tran Mills /*@
28611a5261eSBarry Smith    MatKAIJSetAIJ - Set the `MATAIJ` matrix describing the blockwise action of the `MATKAIJ` matrix
2870567c835SRichard Tran Mills 
28811a5261eSBarry Smith    Logically Collective; if the `MATAIJ` matrix is parallel, the `MATKAIJ` matrix is also parallel
2890567c835SRichard Tran Mills 
2900567c835SRichard Tran Mills    Input Parameters:
29111a5261eSBarry Smith +  A - the `MATKAIJ` matrix
29211a5261eSBarry Smith -  B - the `MATAIJ` matrix
2930567c835SRichard Tran Mills 
2942ef1f0ffSBarry Smith    Level: advanced
2952ef1f0ffSBarry Smith 
29615b9d025SRichard Tran Mills    Notes:
29711a5261eSBarry Smith    This function increases the reference count on the `MATAIJ` matrix, so the user is free to destroy the matrix if it is not needed.
29811a5261eSBarry Smith 
29911a5261eSBarry Smith    Changes to the entries of the `MATAIJ` matrix will immediately affect the `MATKAIJ` matrix.
30015b9d025SRichard Tran Mills 
301*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatKAIJGetAIJ()`, `MatKAIJSetS()`, `MatKAIJSetT()`
3020567c835SRichard Tran Mills @*/
303d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJSetAIJ(Mat A, Mat B)
304d71ae5a4SJacob Faibussowitsch {
3050567c835SRichard Tran Mills   PetscMPIInt size;
30606d61a37SPierre Jolivet   PetscBool   flg;
3070567c835SRichard Tran Mills 
3080567c835SRichard Tran Mills   PetscFunctionBegin;
3099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3100567c835SRichard Tran Mills   if (size == 1) {
3119566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, MATSEQAIJ, &flg));
31228b400f6SJacob Faibussowitsch     PetscCheck(flg, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "MatKAIJSetAIJ() with MATSEQKAIJ does not support %s as the AIJ mat", ((PetscObject)B)->type_name);
3130567c835SRichard Tran Mills     Mat_SeqKAIJ *a = (Mat_SeqKAIJ *)A->data;
3140567c835SRichard Tran Mills     a->AIJ         = B;
3150567c835SRichard Tran Mills   } else {
3160567c835SRichard Tran Mills     Mat_MPIKAIJ *a = (Mat_MPIKAIJ *)A->data;
3170567c835SRichard Tran Mills     a->A           = B;
3180567c835SRichard Tran Mills   }
3199566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)B));
3203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3210567c835SRichard Tran Mills }
3220567c835SRichard Tran Mills 
3230567c835SRichard Tran Mills /*@C
3242ef1f0ffSBarry Smith    MatKAIJSetS - Set the `S` matrix describing the shift action of the `MATKAIJ` matrix
3250567c835SRichard Tran Mills 
3262ef1f0ffSBarry Smith    Logically Collective; the entire `S` is stored independently on all processes.
3270567c835SRichard Tran Mills 
3280567c835SRichard Tran Mills    Input Parameters:
32911a5261eSBarry Smith +  A - the `MATKAIJ` matrix
3302ef1f0ffSBarry Smith .  p - the number of rows in `S`
3312ef1f0ffSBarry Smith .  q - the number of columns in `S`
3320567c835SRichard Tran Mills -  S - the S matrix, in form of a scalar array in column-major format
3330567c835SRichard Tran Mills 
33411a5261eSBarry Smith    Level: advanced
3350567c835SRichard Tran Mills 
3362ef1f0ffSBarry Smith    Notes:
3372ef1f0ffSBarry Smith    The dimensions `p` and `q` must match those of the transformation matrix `T` associated with the `MATKAIJ` matrix.
3382ef1f0ffSBarry Smith 
3392ef1f0ffSBarry Smith    The `S` matrix is copied, so the user can destroy this array.
3402ef1f0ffSBarry Smith 
341*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatKAIJGetS()`, `MatKAIJSetT()`, `MatKAIJSetAIJ()`
3420567c835SRichard Tran Mills @*/
343d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJSetS(Mat A, PetscInt p, PetscInt q, const PetscScalar S[])
344d71ae5a4SJacob Faibussowitsch {
3450567c835SRichard Tran Mills   Mat_SeqKAIJ *a = (Mat_SeqKAIJ *)A->data;
3460567c835SRichard Tran Mills 
3470567c835SRichard Tran Mills   PetscFunctionBegin;
3489566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->S));
3490567c835SRichard Tran Mills   if (S) {
3509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(p * q, &a->S));
3519566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(a->S, S, p * q * sizeof(PetscScalar)));
3520567c835SRichard Tran Mills   } else a->S = NULL;
3530567c835SRichard Tran Mills 
3540567c835SRichard Tran Mills   a->p = p;
3550567c835SRichard Tran Mills   a->q = q;
3563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3570567c835SRichard Tran Mills }
3580567c835SRichard Tran Mills 
3590567c835SRichard Tran Mills /*@C
3602ef1f0ffSBarry Smith    MatKAIJGetScaledIdentity - Check if both `S` and `T` are scaled identities.
361910cf402Sprj- 
362910cf402Sprj-    Logically Collective.
363910cf402Sprj- 
364910cf402Sprj-    Input Parameter:
36511a5261eSBarry Smith .  A - the `MATKAIJ` matrix
366910cf402Sprj- 
367910cf402Sprj-   Output Parameter:
368910cf402Sprj- .  identity - the Boolean value
369910cf402Sprj- 
370910cf402Sprj-    Level: Advanced
371910cf402Sprj- 
372*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatKAIJGetS()`, `MatKAIJGetT()`
373910cf402Sprj- @*/
374d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJGetScaledIdentity(Mat A, PetscBool *identity)
375d71ae5a4SJacob Faibussowitsch {
376910cf402Sprj-   Mat_SeqKAIJ *a = (Mat_SeqKAIJ *)A->data;
377910cf402Sprj-   PetscInt     i, j;
378910cf402Sprj- 
379910cf402Sprj-   PetscFunctionBegin;
380910cf402Sprj-   if (a->p != a->q) {
381910cf402Sprj-     *identity = PETSC_FALSE;
3823ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
383910cf402Sprj-   } else *identity = PETSC_TRUE;
384910cf402Sprj-   if (!a->isTI || a->S) {
385910cf402Sprj-     for (i = 0; i < a->p && *identity; i++) {
386910cf402Sprj-       for (j = 0; j < a->p && *identity; j++) {
387910cf402Sprj-         if (i != j) {
388910cf402Sprj-           if (a->S && PetscAbsScalar(a->S[i + j * a->p]) > PETSC_SMALL) *identity = PETSC_FALSE;
389910cf402Sprj-           if (a->T && PetscAbsScalar(a->T[i + j * a->p]) > PETSC_SMALL) *identity = PETSC_FALSE;
390910cf402Sprj-         } else {
391910cf402Sprj-           if (a->S && PetscAbsScalar(a->S[i * (a->p + 1)] - a->S[0]) > PETSC_SMALL) *identity = PETSC_FALSE;
392910cf402Sprj-           if (a->T && PetscAbsScalar(a->T[i * (a->p + 1)] - a->T[0]) > PETSC_SMALL) *identity = PETSC_FALSE;
393910cf402Sprj-         }
394910cf402Sprj-       }
395910cf402Sprj-     }
396910cf402Sprj-   }
3973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
398910cf402Sprj- }
399910cf402Sprj- 
400910cf402Sprj- /*@C
4012ef1f0ffSBarry Smith    MatKAIJSetT - Set the transformation matrix `T` associated with the `MATKAIJ` matrix
4020567c835SRichard Tran Mills 
4032ef1f0ffSBarry Smith    Logically Collective; the entire `T` is stored independently on all processes.
4040567c835SRichard Tran Mills 
4050567c835SRichard Tran Mills    Input Parameters:
40611a5261eSBarry Smith +  A - the `MATKAIJ` matrix
4072ef1f0ffSBarry Smith .  p - the number of rows in `S`
4082ef1f0ffSBarry Smith .  q - the number of columns in `S`
4092ef1f0ffSBarry Smith -  T - the `T` matrix, in form of a scalar array in column-major format
4100567c835SRichard Tran Mills 
4110567c835SRichard Tran Mills    Level: Advanced
4120567c835SRichard Tran Mills 
4132ef1f0ffSBarry Smith    Notes:
4142ef1f0ffSBarry Smith    The dimensions `p` and `q` must match those of the shift matrix `S` associated with the `MATKAIJ` matrix.
4152ef1f0ffSBarry Smith 
4162ef1f0ffSBarry Smith    The `T` matrix is copied, so the user can destroy this array.
4172ef1f0ffSBarry Smith 
418*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATKAIJ`, `MatKAIJGetT()`, `MatKAIJSetS()`, `MatKAIJSetAIJ()`
4190567c835SRichard Tran Mills @*/
420d71ae5a4SJacob Faibussowitsch PetscErrorCode MatKAIJSetT(Mat A, PetscInt p, PetscInt q, const PetscScalar T[])
421d71ae5a4SJacob Faibussowitsch {
4220567c835SRichard Tran Mills   PetscInt     i, j;
4230567c835SRichard Tran Mills   Mat_SeqKAIJ *a    = (Mat_SeqKAIJ *)A->data;
4240567c835SRichard Tran Mills   PetscBool    isTI = PETSC_FALSE;
4250567c835SRichard Tran Mills 
4260567c835SRichard Tran Mills   PetscFunctionBegin;
4270567c835SRichard Tran Mills   /* check if T is an identity matrix */
4280567c835SRichard Tran Mills   if (T && (p == q)) {
4290567c835SRichard Tran Mills     isTI = PETSC_TRUE;
4300567c835SRichard Tran Mills     for (i = 0; i < p; i++) {
4310567c835SRichard Tran Mills       for (j = 0; j < q; j++) {
4320567c835SRichard Tran Mills         if (i == j) {
4330567c835SRichard Tran Mills           /* diagonal term must be 1 */
4340567c835SRichard Tran Mills           if (T[i + j * p] != 1.0) isTI = PETSC_FALSE;
4350567c835SRichard Tran Mills         } else {
4360567c835SRichard Tran Mills           /* off-diagonal term must be 0 */
4370567c835SRichard Tran Mills           if (T[i + j * p] != 0.0) isTI = PETSC_FALSE;
4380567c835SRichard Tran Mills         }
4390567c835SRichard Tran Mills       }
4400567c835SRichard Tran Mills     }
4410567c835SRichard Tran Mills   }
4420567c835SRichard Tran Mills   a->isTI = isTI;
4430567c835SRichard Tran Mills 
4449566063dSJacob Faibussowitsch   PetscCall(PetscFree(a->T));
4450567c835SRichard Tran Mills   if (T && (!isTI)) {
4469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(p * q, &a->T));
4479566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(a->T, T, p * q * sizeof(PetscScalar)));
44850d19d74SRichard Tran Mills   } else a->T = NULL;
4490567c835SRichard Tran Mills 
4500567c835SRichard Tran Mills   a->p = p;
4510567c835SRichard Tran Mills   a->q = q;
4523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4530567c835SRichard Tran Mills }
4540567c835SRichard Tran Mills 
455ff6a9541SJacob Faibussowitsch static PetscErrorCode MatDestroy_SeqKAIJ(Mat A)
456d71ae5a4SJacob Faibussowitsch {
45749bd79ccSDebojyoti Ghosh   Mat_SeqKAIJ *b = (Mat_SeqKAIJ *)A->data;
45849bd79ccSDebojyoti Ghosh 
45949bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
4609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&b->AIJ));
4619566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->S));
4629566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->T));
4639566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->ibdiag));
4649566063dSJacob Faibussowitsch   PetscCall(PetscFree5(b->sor.w, b->sor.y, b->sor.work, b->sor.t, b->sor.arr));
4659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqkaij_seqaij_C", NULL));
4669566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
4673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46849bd79ccSDebojyoti Ghosh }
46949bd79ccSDebojyoti Ghosh 
470ff6a9541SJacob Faibussowitsch static PetscErrorCode MatKAIJ_build_AIJ_OAIJ(Mat A)
471d71ae5a4SJacob Faibussowitsch {
472e0e5a793SRichard Tran Mills   Mat_MPIKAIJ     *a;
473e0e5a793SRichard Tran Mills   Mat_MPIAIJ      *mpiaij;
474e0e5a793SRichard Tran Mills   PetscScalar     *T;
475e0e5a793SRichard Tran Mills   PetscInt         i, j;
476e0e5a793SRichard Tran Mills   PetscObjectState state;
477e0e5a793SRichard Tran Mills 
478e0e5a793SRichard Tran Mills   PetscFunctionBegin;
479e0e5a793SRichard Tran Mills   a      = (Mat_MPIKAIJ *)A->data;
480e0e5a793SRichard Tran Mills   mpiaij = (Mat_MPIAIJ *)a->A->data;
481e0e5a793SRichard Tran Mills 
4829566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)a->A, &state));
483e0e5a793SRichard Tran Mills   if (state == a->state) {
484e0e5a793SRichard Tran Mills     /* The existing AIJ and KAIJ members are up-to-date, so simply exit. */
4853ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
486e0e5a793SRichard Tran Mills   } else {
4879566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&a->AIJ));
4889566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&a->OAIJ));
489e0e5a793SRichard Tran Mills     if (a->isTI) {
490e0e5a793SRichard Tran Mills       /* If the transformation matrix associated with the parallel matrix A is the identity matrix, then a->T will be NULL.
491e0e5a793SRichard Tran Mills        * In this case, if we pass a->T directly to the MatCreateKAIJ() calls to create the sequential submatrices, the routine will
492e0e5a793SRichard Tran Mills        * not be able to tell that transformation matrix should be set to the identity; thus we create a temporary identity matrix
493e0e5a793SRichard Tran Mills        * to pass in. */
4949566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(a->p * a->q, &T));
495e0e5a793SRichard Tran Mills       for (i = 0; i < a->p; i++) {
496e0e5a793SRichard Tran Mills         for (j = 0; j < a->q; j++) {
497e0e5a793SRichard Tran Mills           if (i == j) T[i + j * a->p] = 1.0;
498e0e5a793SRichard Tran Mills           else T[i + j * a->p] = 0.0;
499e0e5a793SRichard Tran Mills         }
500e0e5a793SRichard Tran Mills       }
501e0e5a793SRichard Tran Mills     } else T = a->T;
5029566063dSJacob Faibussowitsch     PetscCall(MatCreateKAIJ(mpiaij->A, a->p, a->q, a->S, T, &a->AIJ));
5039566063dSJacob Faibussowitsch     PetscCall(MatCreateKAIJ(mpiaij->B, a->p, a->q, NULL, T, &a->OAIJ));
5041baa6e33SBarry Smith     if (a->isTI) PetscCall(PetscFree(T));
505e0e5a793SRichard Tran Mills     a->state = state;
506e0e5a793SRichard Tran Mills   }
507e0e5a793SRichard Tran Mills 
5083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
509e0e5a793SRichard Tran Mills }
510e0e5a793SRichard Tran Mills 
511ff6a9541SJacob Faibussowitsch static PetscErrorCode MatSetUp_KAIJ(Mat A)
512d71ae5a4SJacob Faibussowitsch {
5130567c835SRichard Tran Mills   PetscInt     n;
5140567c835SRichard Tran Mills   PetscMPIInt  size;
5150567c835SRichard Tran Mills   Mat_SeqKAIJ *seqkaij = (Mat_SeqKAIJ *)A->data;
5160567c835SRichard Tran Mills 
51749bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
5189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
5190567c835SRichard Tran Mills   if (size == 1) {
5209566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(A, seqkaij->p * seqkaij->AIJ->rmap->n, seqkaij->q * seqkaij->AIJ->cmap->n, seqkaij->p * seqkaij->AIJ->rmap->N, seqkaij->q * seqkaij->AIJ->cmap->N));
5219566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetBlockSize(A->rmap, seqkaij->p));
5229566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetBlockSize(A->cmap, seqkaij->q));
5239566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp(A->rmap));
5249566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp(A->cmap));
5250567c835SRichard Tran Mills   } else {
5260567c835SRichard Tran Mills     Mat_MPIKAIJ *a;
5270567c835SRichard Tran Mills     Mat_MPIAIJ  *mpiaij;
5280567c835SRichard Tran Mills     IS           from, to;
5290567c835SRichard Tran Mills     Vec          gvec;
5300567c835SRichard Tran Mills 
5310567c835SRichard Tran Mills     a      = (Mat_MPIKAIJ *)A->data;
532d3f912faSRichard Tran Mills     mpiaij = (Mat_MPIAIJ *)a->A->data;
5339566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(A, a->p * a->A->rmap->n, a->q * a->A->cmap->n, a->p * a->A->rmap->N, a->q * a->A->cmap->N));
5349566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetBlockSize(A->rmap, seqkaij->p));
5359566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetBlockSize(A->cmap, seqkaij->q));
5369566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp(A->rmap));
5379566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp(A->cmap));
5380567c835SRichard Tran Mills 
5399566063dSJacob Faibussowitsch     PetscCall(MatKAIJ_build_AIJ_OAIJ(A));
5400567c835SRichard Tran Mills 
5419566063dSJacob Faibussowitsch     PetscCall(VecGetSize(mpiaij->lvec, &n));
5429566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &a->w));
5439566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(a->w, n * a->q, n * a->q));
5449566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(a->w, a->q));
5459566063dSJacob Faibussowitsch     PetscCall(VecSetType(a->w, VECSEQ));
5460567c835SRichard Tran Mills 
5470567c835SRichard Tran Mills     /* create two temporary Index sets for build scatter gather */
5489566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)a->A), a->q, n, mpiaij->garray, PETSC_COPY_VALUES, &from));
5499566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, n * a->q, 0, 1, &to));
5500567c835SRichard Tran Mills 
5510567c835SRichard Tran Mills     /* create temporary global vector to generate scatter context */
5529566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)a->A), a->q, a->q * a->A->cmap->n, a->q * a->A->cmap->N, NULL, &gvec));
5530567c835SRichard Tran Mills 
5540567c835SRichard Tran Mills     /* generate the scatter context */
5559566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(gvec, from, a->w, to, &a->ctx));
5560567c835SRichard Tran Mills 
5579566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&from));
5589566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&to));
5599566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&gvec));
5600567c835SRichard Tran Mills   }
5610567c835SRichard Tran Mills 
5620567c835SRichard Tran Mills   A->assembled = PETSC_TRUE;
5633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56449bd79ccSDebojyoti Ghosh }
56549bd79ccSDebojyoti Ghosh 
566ff6a9541SJacob Faibussowitsch static PetscErrorCode MatView_KAIJ(Mat A, PetscViewer viewer)
567d71ae5a4SJacob Faibussowitsch {
568e6985dafSRichard Tran Mills   PetscViewerFormat format;
569e6985dafSRichard Tran Mills   Mat_SeqKAIJ      *a = (Mat_SeqKAIJ *)A->data;
57049bd79ccSDebojyoti Ghosh   Mat               B;
571e6985dafSRichard Tran Mills   PetscInt          i;
572e6985dafSRichard Tran Mills   PetscBool         ismpikaij;
57349bd79ccSDebojyoti Ghosh 
57449bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
5759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIKAIJ, &ismpikaij));
5769566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
577e6985dafSRichard Tran Mills   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL || format == PETSC_VIEWER_ASCII_IMPL) {
5789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "S and T have %" PetscInt_FMT " rows and %" PetscInt_FMT " columns\n", a->p, a->q));
579e6985dafSRichard Tran Mills 
580e6985dafSRichard Tran Mills     /* Print appropriate details for S. */
581e6985dafSRichard Tran Mills     if (!a->S) {
5829566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "S is NULL\n"));
583e6985dafSRichard Tran Mills     } else if (format == PETSC_VIEWER_ASCII_IMPL) {
5849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "Entries of S are "));
585e6985dafSRichard Tran Mills       for (i = 0; i < (a->p * a->q); i++) {
586e6985dafSRichard Tran Mills #if defined(PETSC_USE_COMPLEX)
5879566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e %18.16e ", (double)PetscRealPart(a->S[i]), (double)PetscImaginaryPart(a->S[i])));
588e6985dafSRichard Tran Mills #else
5899566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(a->S[i])));
590e6985dafSRichard Tran Mills #endif
591e6985dafSRichard Tran Mills       }
5929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
59349bd79ccSDebojyoti Ghosh     }
59449bd79ccSDebojyoti Ghosh 
595e6985dafSRichard Tran Mills     /* Print appropriate details for T. */
596e6985dafSRichard Tran Mills     if (a->isTI) {
5979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "T is the identity matrix\n"));
598e6985dafSRichard Tran Mills     } else if (!a->T) {
5999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "T is NULL\n"));
600e6985dafSRichard Tran Mills     } else if (format == PETSC_VIEWER_ASCII_IMPL) {
6019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "Entries of T are "));
602e6985dafSRichard Tran Mills       for (i = 0; i < (a->p * a->q); i++) {
603e6985dafSRichard Tran Mills #if defined(PETSC_USE_COMPLEX)
6049566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e %18.16e ", (double)PetscRealPart(a->T[i]), (double)PetscImaginaryPart(a->T[i])));
605e6985dafSRichard Tran Mills #else
6069566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(a->T[i])));
607e6985dafSRichard Tran Mills #endif
608e6985dafSRichard Tran Mills       }
6099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
610e6985dafSRichard Tran Mills     }
61149bd79ccSDebojyoti Ghosh 
612e6985dafSRichard Tran Mills     /* Now print details for the AIJ matrix, using the AIJ viewer. */
6139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Now viewing the associated AIJ matrix:\n"));
614e6985dafSRichard Tran Mills     if (ismpikaij) {
615e6985dafSRichard Tran Mills       Mat_MPIKAIJ *b = (Mat_MPIKAIJ *)A->data;
6169566063dSJacob Faibussowitsch       PetscCall(MatView(b->A, viewer));
617e6985dafSRichard Tran Mills     } else {
6189566063dSJacob Faibussowitsch       PetscCall(MatView(a->AIJ, viewer));
619e6985dafSRichard Tran Mills     }
620e6985dafSRichard Tran Mills 
621e6985dafSRichard Tran Mills   } else {
622e6985dafSRichard Tran Mills     /* For all other matrix viewer output formats, simply convert to an AIJ matrix and call MatView() on that. */
6239566063dSJacob Faibussowitsch     PetscCall(MatConvert(A, MATAIJ, MAT_INITIAL_MATRIX, &B));
6249566063dSJacob Faibussowitsch     PetscCall(MatView(B, viewer));
6259566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
626e6985dafSRichard Tran Mills   }
6273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62849bd79ccSDebojyoti Ghosh }
62949bd79ccSDebojyoti Ghosh 
630ff6a9541SJacob Faibussowitsch static PetscErrorCode MatDestroy_MPIKAIJ(Mat A)
631d71ae5a4SJacob Faibussowitsch {
63249bd79ccSDebojyoti Ghosh   Mat_MPIKAIJ *b = (Mat_MPIKAIJ *)A->data;
63349bd79ccSDebojyoti Ghosh 
63449bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
6359566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&b->AIJ));
6369566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&b->OAIJ));
6379566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&b->A));
6389566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&b->ctx));
6399566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->w));
6409566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->S));
6419566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->T));
6429566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->ibdiag));
6439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatGetDiagonalBlock_C", NULL));
6449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_mpikaij_mpiaij_C", NULL));
6459566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
6463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64749bd79ccSDebojyoti Ghosh }
64849bd79ccSDebojyoti Ghosh 
64949bd79ccSDebojyoti Ghosh /* zz = yy + Axx */
650ff6a9541SJacob Faibussowitsch static PetscErrorCode MatMultAdd_SeqKAIJ(Mat A, Vec xx, Vec yy, Vec zz)
651d71ae5a4SJacob Faibussowitsch {
65249bd79ccSDebojyoti Ghosh   Mat_SeqKAIJ       *b = (Mat_SeqKAIJ *)A->data;
65349bd79ccSDebojyoti Ghosh   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)b->AIJ->data;
65449bd79ccSDebojyoti Ghosh   const PetscScalar *s = b->S, *t = b->T;
65549bd79ccSDebojyoti Ghosh   const PetscScalar *x, *v, *bx;
65649bd79ccSDebojyoti Ghosh   PetscScalar       *y, *sums;
65749bd79ccSDebojyoti Ghosh   const PetscInt     m = b->AIJ->rmap->n, *idx, *ii;
65849bd79ccSDebojyoti Ghosh   PetscInt           n, i, jrow, j, l, p = b->p, q = b->q, k;
65949bd79ccSDebojyoti Ghosh 
66049bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
66149bd79ccSDebojyoti Ghosh   if (!yy) {
6629566063dSJacob Faibussowitsch     PetscCall(VecSet(zz, 0.0));
66349bd79ccSDebojyoti Ghosh   } else {
6649566063dSJacob Faibussowitsch     PetscCall(VecCopy(yy, zz));
66549bd79ccSDebojyoti Ghosh   }
6663ba16761SJacob Faibussowitsch   if ((!s) && (!t) && (!b->isTI)) PetscFunctionReturn(PETSC_SUCCESS);
66749bd79ccSDebojyoti Ghosh 
6689566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
6699566063dSJacob Faibussowitsch   PetscCall(VecGetArray(zz, &y));
67049bd79ccSDebojyoti Ghosh   idx = a->j;
67149bd79ccSDebojyoti Ghosh   v   = a->a;
67249bd79ccSDebojyoti Ghosh   ii  = a->i;
67349bd79ccSDebojyoti Ghosh 
67449bd79ccSDebojyoti Ghosh   if (b->isTI) {
67549bd79ccSDebojyoti Ghosh     for (i = 0; i < m; i++) {
67649bd79ccSDebojyoti Ghosh       jrow = ii[i];
67749bd79ccSDebojyoti Ghosh       n    = ii[i + 1] - jrow;
67849bd79ccSDebojyoti Ghosh       sums = y + p * i;
67949bd79ccSDebojyoti Ghosh       for (j = 0; j < n; j++) {
680ad540459SPierre Jolivet         for (k = 0; k < p; k++) sums[k] += v[jrow + j] * x[q * idx[jrow + j] + k];
68149bd79ccSDebojyoti Ghosh       }
68249bd79ccSDebojyoti Ghosh     }
6839566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(3.0 * (a->nz) * p));
68449bd79ccSDebojyoti Ghosh   } else if (t) {
68549bd79ccSDebojyoti Ghosh     for (i = 0; i < m; i++) {
68649bd79ccSDebojyoti Ghosh       jrow = ii[i];
68749bd79ccSDebojyoti Ghosh       n    = ii[i + 1] - jrow;
68849bd79ccSDebojyoti Ghosh       sums = y + p * i;
68949bd79ccSDebojyoti Ghosh       for (j = 0; j < n; j++) {
69049bd79ccSDebojyoti Ghosh         for (k = 0; k < p; k++) {
691ad540459SPierre Jolivet           for (l = 0; l < q; l++) sums[k] += v[jrow + j] * t[k + l * p] * x[q * idx[jrow + j] + l];
69249bd79ccSDebojyoti Ghosh         }
69349bd79ccSDebojyoti Ghosh       }
69449bd79ccSDebojyoti Ghosh     }
695234d9204SRichard Tran Mills     /* The flop count below assumes that v[jrow+j] is hoisted out (which an optimizing compiler is likely to do),
696234d9204SRichard Tran Mills      * and also that T part is hoisted outside this loop (in exchange for temporary storage) as (A \otimes I) (I \otimes T),
697234d9204SRichard Tran Mills      * so that this multiply doesn't have to be redone for each matrix entry, but just once per column. The latter
698234d9204SRichard Tran Mills      * transformation is much less likely to be applied, but we nonetheless count the minimum flops required. */
6999566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((2.0 * p * q - p) * m + 2.0 * p * a->nz));
70049bd79ccSDebojyoti Ghosh   }
70149bd79ccSDebojyoti Ghosh   if (s) {
70249bd79ccSDebojyoti Ghosh     for (i = 0; i < m; i++) {
70349bd79ccSDebojyoti Ghosh       sums = y + p * i;
70449bd79ccSDebojyoti Ghosh       bx   = x + q * i;
70549bd79ccSDebojyoti Ghosh       if (i < b->AIJ->cmap->n) {
70649bd79ccSDebojyoti Ghosh         for (j = 0; j < q; j++) {
707ad540459SPierre Jolivet           for (k = 0; k < p; k++) sums[k] += s[k + j * p] * bx[j];
70849bd79ccSDebojyoti Ghosh         }
70949bd79ccSDebojyoti Ghosh       }
71049bd79ccSDebojyoti Ghosh     }
7119566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * m * p * q));
71249bd79ccSDebojyoti Ghosh   }
71349bd79ccSDebojyoti Ghosh 
7149566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
7159566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(zz, &y));
7163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71749bd79ccSDebojyoti Ghosh }
71849bd79ccSDebojyoti Ghosh 
719ff6a9541SJacob Faibussowitsch static PetscErrorCode MatMult_SeqKAIJ(Mat A, Vec xx, Vec yy)
720d71ae5a4SJacob Faibussowitsch {
72149bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
722f3fa974cSJacob Faibussowitsch   PetscCall(MatMultAdd_SeqKAIJ(A, xx, NULL, yy));
7233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72449bd79ccSDebojyoti Ghosh }
72549bd79ccSDebojyoti Ghosh 
72649bd79ccSDebojyoti Ghosh #include <petsc/private/kernels/blockinvert.h>
72749bd79ccSDebojyoti Ghosh 
728ff6a9541SJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_SeqKAIJ(Mat A, const PetscScalar **values)
729d71ae5a4SJacob Faibussowitsch {
73049bd79ccSDebojyoti Ghosh   Mat_SeqKAIJ       *b = (Mat_SeqKAIJ *)A->data;
73149bd79ccSDebojyoti Ghosh   Mat_SeqAIJ        *a = (Mat_SeqAIJ *)b->AIJ->data;
73249bd79ccSDebojyoti Ghosh   const PetscScalar *S = b->S;
73349bd79ccSDebojyoti Ghosh   const PetscScalar *T = b->T;
73449bd79ccSDebojyoti Ghosh   const PetscScalar *v = a->a;
73549bd79ccSDebojyoti Ghosh   const PetscInt     p = b->p, q = b->q, m = b->AIJ->rmap->n, *idx = a->j, *ii = a->i;
73649bd79ccSDebojyoti Ghosh   PetscInt           i, j, *v_pivots, dof, dof2;
73749bd79ccSDebojyoti Ghosh   PetscScalar       *diag, aval, *v_work;
73849bd79ccSDebojyoti Ghosh 
73949bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
74008401ef6SPierre Jolivet   PetscCheck(p == q, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MATKAIJ: Block size must be square to calculate inverse.");
741aed4548fSBarry Smith   PetscCheck(S || T || b->isTI, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MATKAIJ: Cannot invert a zero matrix.");
74249bd79ccSDebojyoti Ghosh 
74349bd79ccSDebojyoti Ghosh   dof  = p;
74449bd79ccSDebojyoti Ghosh   dof2 = dof * dof;
74549bd79ccSDebojyoti Ghosh 
74649bd79ccSDebojyoti Ghosh   if (b->ibdiagvalid) {
74749bd79ccSDebojyoti Ghosh     if (values) *values = b->ibdiag;
7483ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
74949bd79ccSDebojyoti Ghosh   }
750aa624791SPierre Jolivet   if (!b->ibdiag) PetscCall(PetscMalloc1(dof2 * m, &b->ibdiag));
75149bd79ccSDebojyoti Ghosh   if (values) *values = b->ibdiag;
75249bd79ccSDebojyoti Ghosh   diag = b->ibdiag;
75349bd79ccSDebojyoti Ghosh 
7549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(dof, &v_work, dof, &v_pivots));
75549bd79ccSDebojyoti Ghosh   for (i = 0; i < m; i++) {
75649bd79ccSDebojyoti Ghosh     if (S) {
7579566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(diag, S, dof2 * sizeof(PetscScalar)));
75849bd79ccSDebojyoti Ghosh     } else {
7599566063dSJacob Faibussowitsch       PetscCall(PetscMemzero(diag, dof2 * sizeof(PetscScalar)));
76049bd79ccSDebojyoti Ghosh     }
76149bd79ccSDebojyoti Ghosh     if (b->isTI) {
76249bd79ccSDebojyoti Ghosh       aval = 0;
7639371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1]; j++)
7649371c9d4SSatish Balay         if (idx[j] == i) aval = v[j];
76549bd79ccSDebojyoti Ghosh       for (j = 0; j < dof; j++) diag[j + dof * j] += aval;
76649bd79ccSDebojyoti Ghosh     } else if (T) {
76749bd79ccSDebojyoti Ghosh       aval = 0;
7689371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1]; j++)
7699371c9d4SSatish Balay         if (idx[j] == i) aval = v[j];
77049bd79ccSDebojyoti Ghosh       for (j = 0; j < dof2; j++) diag[j] += aval * T[j];
77149bd79ccSDebojyoti Ghosh     }
7729566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(dof, diag, v_pivots, v_work, PETSC_FALSE, NULL));
77349bd79ccSDebojyoti Ghosh     diag += dof2;
77449bd79ccSDebojyoti Ghosh   }
7759566063dSJacob Faibussowitsch   PetscCall(PetscFree2(v_work, v_pivots));
77649bd79ccSDebojyoti Ghosh 
77749bd79ccSDebojyoti Ghosh   b->ibdiagvalid = PETSC_TRUE;
7783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77949bd79ccSDebojyoti Ghosh }
78049bd79ccSDebojyoti Ghosh 
781d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonalBlock_MPIKAIJ(Mat A, Mat *B)
782d71ae5a4SJacob Faibussowitsch {
78349bd79ccSDebojyoti Ghosh   Mat_MPIKAIJ *kaij = (Mat_MPIKAIJ *)A->data;
78449bd79ccSDebojyoti Ghosh 
78549bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
78649bd79ccSDebojyoti Ghosh   *B = kaij->AIJ;
7873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78849bd79ccSDebojyoti Ghosh }
78949bd79ccSDebojyoti Ghosh 
790d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_KAIJ_AIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
791d71ae5a4SJacob Faibussowitsch {
792fac53fa1SPierre Jolivet   Mat_SeqKAIJ   *a = (Mat_SeqKAIJ *)A->data;
793fac53fa1SPierre Jolivet   Mat            AIJ, OAIJ, B;
794fac53fa1SPierre Jolivet   PetscInt      *d_nnz, *o_nnz = NULL, nz, i, j, m, d;
795fac53fa1SPierre Jolivet   const PetscInt p = a->p, q = a->q;
796fac53fa1SPierre Jolivet   PetscBool      ismpikaij, missing;
797fac53fa1SPierre Jolivet 
798fac53fa1SPierre Jolivet   PetscFunctionBegin;
799fac53fa1SPierre Jolivet   if (reuse != MAT_REUSE_MATRIX) {
8009566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIKAIJ, &ismpikaij));
801fac53fa1SPierre Jolivet     if (ismpikaij) {
802fac53fa1SPierre Jolivet       Mat_MPIKAIJ *b = (Mat_MPIKAIJ *)A->data;
803fac53fa1SPierre Jolivet       AIJ            = ((Mat_SeqKAIJ *)b->AIJ->data)->AIJ;
804fac53fa1SPierre Jolivet       OAIJ           = ((Mat_SeqKAIJ *)b->OAIJ->data)->AIJ;
805fac53fa1SPierre Jolivet     } else {
806fac53fa1SPierre Jolivet       AIJ  = a->AIJ;
807fac53fa1SPierre Jolivet       OAIJ = NULL;
808fac53fa1SPierre Jolivet     }
8099566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
8109566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
8119566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATAIJ));
8129566063dSJacob Faibussowitsch     PetscCall(MatGetSize(AIJ, &m, NULL));
8139566063dSJacob Faibussowitsch     PetscCall(MatMissingDiagonal(AIJ, &missing, &d)); /* assumption that all successive rows will have a missing diagonal */
814fac53fa1SPierre Jolivet     if (!missing || !a->S) d = m;
8159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m * p, &d_nnz));
816fac53fa1SPierre Jolivet     for (i = 0; i < m; ++i) {
8179566063dSJacob Faibussowitsch       PetscCall(MatGetRow_SeqAIJ(AIJ, i, &nz, NULL, NULL));
818fac53fa1SPierre Jolivet       for (j = 0; j < p; ++j) d_nnz[i * p + j] = nz * q + (i >= d) * q;
8199566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow_SeqAIJ(AIJ, i, &nz, NULL, NULL));
820fac53fa1SPierre Jolivet     }
821fac53fa1SPierre Jolivet     if (OAIJ) {
8229566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m * p, &o_nnz));
823fac53fa1SPierre Jolivet       for (i = 0; i < m; ++i) {
8249566063dSJacob Faibussowitsch         PetscCall(MatGetRow_SeqAIJ(OAIJ, i, &nz, NULL, NULL));
825fac53fa1SPierre Jolivet         for (j = 0; j < p; ++j) o_nnz[i * p + j] = nz * q;
8269566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow_SeqAIJ(OAIJ, i, &nz, NULL, NULL));
827fac53fa1SPierre Jolivet       }
8289566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(B, 0, d_nnz, 0, o_nnz));
829fac53fa1SPierre Jolivet     } else {
8309566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(B, 0, d_nnz));
831fac53fa1SPierre Jolivet     }
8329566063dSJacob Faibussowitsch     PetscCall(PetscFree(d_nnz));
8339566063dSJacob Faibussowitsch     PetscCall(PetscFree(o_nnz));
834fac53fa1SPierre Jolivet   } else B = *newmat;
8359566063dSJacob Faibussowitsch   PetscCall(MatConvert_Basic(A, newtype, MAT_REUSE_MATRIX, &B));
836fac53fa1SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) {
8379566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
838fac53fa1SPierre Jolivet   } else *newmat = B;
8393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
840fac53fa1SPierre Jolivet }
841fac53fa1SPierre Jolivet 
842ff6a9541SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqKAIJ(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal fshift, PetscInt its, PetscInt lits, Vec xx)
843d71ae5a4SJacob Faibussowitsch {
84449bd79ccSDebojyoti Ghosh   Mat_SeqKAIJ       *kaij = (Mat_SeqKAIJ *)A->data;
84549bd79ccSDebojyoti Ghosh   Mat_SeqAIJ        *a    = (Mat_SeqAIJ *)kaij->AIJ->data;
84649bd79ccSDebojyoti Ghosh   const PetscScalar *aa = a->a, *T = kaij->T, *v;
84749bd79ccSDebojyoti Ghosh   const PetscInt     m = kaij->AIJ->rmap->n, *ai = a->i, *aj = a->j, p = kaij->p, q = kaij->q, *diag, *vi;
84849bd79ccSDebojyoti Ghosh   const PetscScalar *b, *xb, *idiag;
84949bd79ccSDebojyoti Ghosh   PetscScalar       *x, *work, *workt, *w, *y, *arr, *t, *arrt;
85049bd79ccSDebojyoti Ghosh   PetscInt           i, j, k, i2, bs, bs2, nz;
85149bd79ccSDebojyoti Ghosh 
85249bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
85349bd79ccSDebojyoti Ghosh   its = its * lits;
854aed4548fSBarry Smith   PetscCheck(!(flag & SOR_EISENSTAT), PETSC_COMM_SELF, PETSC_ERR_SUP, "No support yet for Eisenstat");
85508401ef6SPierre Jolivet   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " and local its %" PetscInt_FMT " both positive", its, lits);
85628b400f6SJacob Faibussowitsch   PetscCheck(!fshift, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for diagonal shift");
85708401ef6SPierre Jolivet   PetscCheck(!(flag & SOR_APPLY_UPPER) && !(flag & SOR_APPLY_LOWER), PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for applying upper or lower triangular parts");
85808401ef6SPierre Jolivet   PetscCheck(p == q, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatSOR for KAIJ: No support for non-square dense blocks");
859f7d195e4SLawrence Mitchell   bs  = p;
860f7d195e4SLawrence Mitchell   bs2 = bs * bs;
86149bd79ccSDebojyoti Ghosh 
8623ba16761SJacob Faibussowitsch   if (!m) PetscFunctionReturn(PETSC_SUCCESS);
86349bd79ccSDebojyoti Ghosh 
8649566063dSJacob Faibussowitsch   if (!kaij->ibdiagvalid) PetscCall(MatInvertBlockDiagonal_SeqKAIJ(A, NULL));
86549bd79ccSDebojyoti Ghosh   idiag = kaij->ibdiag;
86649bd79ccSDebojyoti Ghosh   diag  = a->diag;
86749bd79ccSDebojyoti Ghosh 
86849bd79ccSDebojyoti Ghosh   if (!kaij->sor.setup) {
8699566063dSJacob Faibussowitsch     PetscCall(PetscMalloc5(bs, &kaij->sor.w, bs, &kaij->sor.y, m * bs, &kaij->sor.work, m * bs, &kaij->sor.t, m * bs2, &kaij->sor.arr));
87049bd79ccSDebojyoti Ghosh     kaij->sor.setup = PETSC_TRUE;
87149bd79ccSDebojyoti Ghosh   }
87249bd79ccSDebojyoti Ghosh   y    = kaij->sor.y;
87349bd79ccSDebojyoti Ghosh   w    = kaij->sor.w;
87449bd79ccSDebojyoti Ghosh   work = kaij->sor.work;
87549bd79ccSDebojyoti Ghosh   t    = kaij->sor.t;
87649bd79ccSDebojyoti Ghosh   arr  = kaij->sor.arr;
87749bd79ccSDebojyoti Ghosh 
878d0609cedSBarry Smith   PetscCall(VecGetArray(xx, &x));
8799566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
88049bd79ccSDebojyoti Ghosh 
88149bd79ccSDebojyoti Ghosh   if (flag & SOR_ZERO_INITIAL_GUESS) {
88249bd79ccSDebojyoti Ghosh     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
88349bd79ccSDebojyoti Ghosh       PetscKernel_w_gets_Ar_times_v(bs, bs, b, idiag, x); /* x[0:bs] <- D^{-1} b[0:bs] */
8849566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(t, b, bs * sizeof(PetscScalar)));
88549bd79ccSDebojyoti Ghosh       i2 = bs;
88649bd79ccSDebojyoti Ghosh       idiag += bs2;
88749bd79ccSDebojyoti Ghosh       for (i = 1; i < m; i++) {
88849bd79ccSDebojyoti Ghosh         v  = aa + ai[i];
88949bd79ccSDebojyoti Ghosh         vi = aj + ai[i];
89049bd79ccSDebojyoti Ghosh         nz = diag[i] - ai[i];
89149bd79ccSDebojyoti Ghosh 
89249bd79ccSDebojyoti Ghosh         if (T) { /* b - T (Arow * x) */
8939566063dSJacob Faibussowitsch           PetscCall(PetscMemzero(w, bs * sizeof(PetscScalar)));
89449bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
89549bd79ccSDebojyoti Ghosh             for (k = 0; k < bs; k++) w[k] -= v[j] * x[vi[j] * bs + k];
89649bd79ccSDebojyoti Ghosh           }
89749bd79ccSDebojyoti Ghosh           PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs, w, T, &t[i2]);
89849bd79ccSDebojyoti Ghosh           for (k = 0; k < bs; k++) t[i2 + k] += b[i2 + k];
89949bd79ccSDebojyoti Ghosh         } else if (kaij->isTI) {
9009566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(t + i2, b + i2, bs * sizeof(PetscScalar)));
90149bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
90249bd79ccSDebojyoti Ghosh             for (k = 0; k < bs; k++) t[i2 + k] -= v[j] * x[vi[j] * bs + k];
90349bd79ccSDebojyoti Ghosh           }
90449bd79ccSDebojyoti Ghosh         } else {
9059566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(t + i2, b + i2, bs * sizeof(PetscScalar)));
90649bd79ccSDebojyoti Ghosh         }
90749bd79ccSDebojyoti Ghosh 
90849bd79ccSDebojyoti Ghosh         PetscKernel_w_gets_Ar_times_v(bs, bs, t + i2, idiag, y);
90949bd79ccSDebojyoti Ghosh         for (j = 0; j < bs; j++) x[i2 + j] = omega * y[j];
91049bd79ccSDebojyoti Ghosh 
91149bd79ccSDebojyoti Ghosh         idiag += bs2;
91249bd79ccSDebojyoti Ghosh         i2 += bs;
91349bd79ccSDebojyoti Ghosh       }
91449bd79ccSDebojyoti Ghosh       /* for logging purposes assume number of nonzero in lower half is 1/2 of total */
9159566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(1.0 * bs2 * a->nz));
91649bd79ccSDebojyoti Ghosh       xb = t;
91749bd79ccSDebojyoti Ghosh     } else xb = b;
91849bd79ccSDebojyoti Ghosh     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
91949bd79ccSDebojyoti Ghosh       idiag = kaij->ibdiag + bs2 * (m - 1);
92049bd79ccSDebojyoti Ghosh       i2    = bs * (m - 1);
9219566063dSJacob Faibussowitsch       PetscCall(PetscMemcpy(w, xb + i2, bs * sizeof(PetscScalar)));
92249bd79ccSDebojyoti Ghosh       PetscKernel_w_gets_Ar_times_v(bs, bs, w, idiag, x + i2);
92349bd79ccSDebojyoti Ghosh       i2 -= bs;
92449bd79ccSDebojyoti Ghosh       idiag -= bs2;
92549bd79ccSDebojyoti Ghosh       for (i = m - 2; i >= 0; i--) {
92649bd79ccSDebojyoti Ghosh         v  = aa + diag[i] + 1;
92749bd79ccSDebojyoti Ghosh         vi = aj + diag[i] + 1;
92849bd79ccSDebojyoti Ghosh         nz = ai[i + 1] - diag[i] - 1;
92949bd79ccSDebojyoti Ghosh 
93049bd79ccSDebojyoti Ghosh         if (T) { /* FIXME: This branch untested */
9319566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(w, xb + i2, bs * sizeof(PetscScalar)));
93249bd79ccSDebojyoti Ghosh           /* copy all rows of x that are needed into contiguous space */
93349bd79ccSDebojyoti Ghosh           workt = work;
93449bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
9359566063dSJacob Faibussowitsch             PetscCall(PetscMemcpy(workt, x + bs * (*vi++), bs * sizeof(PetscScalar)));
93649bd79ccSDebojyoti Ghosh             workt += bs;
93749bd79ccSDebojyoti Ghosh           }
93849bd79ccSDebojyoti Ghosh           arrt = arr;
93949bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
9409566063dSJacob Faibussowitsch             PetscCall(PetscMemcpy(arrt, T, bs2 * sizeof(PetscScalar)));
94149bd79ccSDebojyoti Ghosh             for (k = 0; k < bs2; k++) arrt[k] *= v[j];
94249bd79ccSDebojyoti Ghosh             arrt += bs2;
94349bd79ccSDebojyoti Ghosh           }
94449bd79ccSDebojyoti Ghosh           PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
94549bd79ccSDebojyoti Ghosh         } else if (kaij->isTI) {
9469566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(w, t + i2, bs * sizeof(PetscScalar)));
94749bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
94849bd79ccSDebojyoti Ghosh             for (k = 0; k < bs; k++) w[k] -= v[j] * x[vi[j] * bs + k];
94949bd79ccSDebojyoti Ghosh           }
95049bd79ccSDebojyoti Ghosh         }
95149bd79ccSDebojyoti Ghosh 
95249bd79ccSDebojyoti Ghosh         PetscKernel_w_gets_Ar_times_v(bs, bs, w, idiag, y); /* RHS incorrect for omega != 1.0 */
95349bd79ccSDebojyoti Ghosh         for (j = 0; j < bs; j++) x[i2 + j] = (1.0 - omega) * x[i2 + j] + omega * y[j];
95449bd79ccSDebojyoti Ghosh 
95549bd79ccSDebojyoti Ghosh         idiag -= bs2;
95649bd79ccSDebojyoti Ghosh         i2 -= bs;
95749bd79ccSDebojyoti Ghosh       }
9589566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(1.0 * bs2 * (a->nz)));
95949bd79ccSDebojyoti Ghosh     }
96049bd79ccSDebojyoti Ghosh     its--;
96149bd79ccSDebojyoti Ghosh   }
96249bd79ccSDebojyoti Ghosh   while (its--) { /* FIXME: This branch not updated */
96349bd79ccSDebojyoti Ghosh     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
96449bd79ccSDebojyoti Ghosh       i2    = 0;
96549bd79ccSDebojyoti Ghosh       idiag = kaij->ibdiag;
96649bd79ccSDebojyoti Ghosh       for (i = 0; i < m; i++) {
9679566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(w, b + i2, bs * sizeof(PetscScalar)));
96849bd79ccSDebojyoti Ghosh 
96949bd79ccSDebojyoti Ghosh         v     = aa + ai[i];
97049bd79ccSDebojyoti Ghosh         vi    = aj + ai[i];
97149bd79ccSDebojyoti Ghosh         nz    = diag[i] - ai[i];
97249bd79ccSDebojyoti Ghosh         workt = work;
97349bd79ccSDebojyoti Ghosh         for (j = 0; j < nz; j++) {
9749566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(workt, x + bs * (*vi++), bs * sizeof(PetscScalar)));
97549bd79ccSDebojyoti Ghosh           workt += bs;
97649bd79ccSDebojyoti Ghosh         }
97749bd79ccSDebojyoti Ghosh         arrt = arr;
97849bd79ccSDebojyoti Ghosh         if (T) {
97949bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
9809566063dSJacob Faibussowitsch             PetscCall(PetscMemcpy(arrt, T, bs2 * sizeof(PetscScalar)));
98149bd79ccSDebojyoti Ghosh             for (k = 0; k < bs2; k++) arrt[k] *= v[j];
98249bd79ccSDebojyoti Ghosh             arrt += bs2;
98349bd79ccSDebojyoti Ghosh           }
98449bd79ccSDebojyoti Ghosh           PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
98549bd79ccSDebojyoti Ghosh         } else if (kaij->isTI) {
98649bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
9879566063dSJacob Faibussowitsch             PetscCall(PetscMemzero(arrt, bs2 * sizeof(PetscScalar)));
98849bd79ccSDebojyoti Ghosh             for (k = 0; k < bs; k++) arrt[k + bs * k] = v[j];
98949bd79ccSDebojyoti Ghosh             arrt += bs2;
99049bd79ccSDebojyoti Ghosh           }
99149bd79ccSDebojyoti Ghosh           PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
99249bd79ccSDebojyoti Ghosh         }
9939566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(t + i2, w, bs * sizeof(PetscScalar)));
99449bd79ccSDebojyoti Ghosh 
99549bd79ccSDebojyoti Ghosh         v     = aa + diag[i] + 1;
99649bd79ccSDebojyoti Ghosh         vi    = aj + diag[i] + 1;
99749bd79ccSDebojyoti Ghosh         nz    = ai[i + 1] - diag[i] - 1;
99849bd79ccSDebojyoti Ghosh         workt = work;
99949bd79ccSDebojyoti Ghosh         for (j = 0; j < nz; j++) {
10009566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(workt, x + bs * (*vi++), bs * sizeof(PetscScalar)));
100149bd79ccSDebojyoti Ghosh           workt += bs;
100249bd79ccSDebojyoti Ghosh         }
100349bd79ccSDebojyoti Ghosh         arrt = arr;
100449bd79ccSDebojyoti Ghosh         if (T) {
100549bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
10069566063dSJacob Faibussowitsch             PetscCall(PetscMemcpy(arrt, T, bs2 * sizeof(PetscScalar)));
100749bd79ccSDebojyoti Ghosh             for (k = 0; k < bs2; k++) arrt[k] *= v[j];
100849bd79ccSDebojyoti Ghosh             arrt += bs2;
100949bd79ccSDebojyoti Ghosh           }
101049bd79ccSDebojyoti Ghosh           PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
101149bd79ccSDebojyoti Ghosh         } else if (kaij->isTI) {
101249bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
10139566063dSJacob Faibussowitsch             PetscCall(PetscMemzero(arrt, bs2 * sizeof(PetscScalar)));
101449bd79ccSDebojyoti Ghosh             for (k = 0; k < bs; k++) arrt[k + bs * k] = v[j];
101549bd79ccSDebojyoti Ghosh             arrt += bs2;
101649bd79ccSDebojyoti Ghosh           }
101749bd79ccSDebojyoti Ghosh           PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
101849bd79ccSDebojyoti Ghosh         }
101949bd79ccSDebojyoti Ghosh 
102049bd79ccSDebojyoti Ghosh         PetscKernel_w_gets_Ar_times_v(bs, bs, w, idiag, y);
102149bd79ccSDebojyoti Ghosh         for (j = 0; j < bs; j++) *(x + i2 + j) = (1.0 - omega) * *(x + i2 + j) + omega * *(y + j);
102249bd79ccSDebojyoti Ghosh 
102349bd79ccSDebojyoti Ghosh         idiag += bs2;
102449bd79ccSDebojyoti Ghosh         i2 += bs;
102549bd79ccSDebojyoti Ghosh       }
102649bd79ccSDebojyoti Ghosh       xb = t;
10279371c9d4SSatish Balay     } else xb = b;
102849bd79ccSDebojyoti Ghosh     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
102949bd79ccSDebojyoti Ghosh       idiag = kaij->ibdiag + bs2 * (m - 1);
103049bd79ccSDebojyoti Ghosh       i2    = bs * (m - 1);
103149bd79ccSDebojyoti Ghosh       if (xb == b) {
103249bd79ccSDebojyoti Ghosh         for (i = m - 1; i >= 0; i--) {
10339566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(w, b + i2, bs * sizeof(PetscScalar)));
103449bd79ccSDebojyoti Ghosh 
103549bd79ccSDebojyoti Ghosh           v     = aa + ai[i];
103649bd79ccSDebojyoti Ghosh           vi    = aj + ai[i];
103749bd79ccSDebojyoti Ghosh           nz    = diag[i] - ai[i];
103849bd79ccSDebojyoti Ghosh           workt = work;
103949bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
10409566063dSJacob Faibussowitsch             PetscCall(PetscMemcpy(workt, x + bs * (*vi++), bs * sizeof(PetscScalar)));
104149bd79ccSDebojyoti Ghosh             workt += bs;
104249bd79ccSDebojyoti Ghosh           }
104349bd79ccSDebojyoti Ghosh           arrt = arr;
104449bd79ccSDebojyoti Ghosh           if (T) {
104549bd79ccSDebojyoti Ghosh             for (j = 0; j < nz; j++) {
10469566063dSJacob Faibussowitsch               PetscCall(PetscMemcpy(arrt, T, bs2 * sizeof(PetscScalar)));
104749bd79ccSDebojyoti Ghosh               for (k = 0; k < bs2; k++) arrt[k] *= v[j];
104849bd79ccSDebojyoti Ghosh               arrt += bs2;
104949bd79ccSDebojyoti Ghosh             }
105049bd79ccSDebojyoti Ghosh             PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
105149bd79ccSDebojyoti Ghosh           } else if (kaij->isTI) {
105249bd79ccSDebojyoti Ghosh             for (j = 0; j < nz; j++) {
10539566063dSJacob Faibussowitsch               PetscCall(PetscMemzero(arrt, bs2 * sizeof(PetscScalar)));
105449bd79ccSDebojyoti Ghosh               for (k = 0; k < bs; k++) arrt[k + bs * k] = v[j];
105549bd79ccSDebojyoti Ghosh               arrt += bs2;
105649bd79ccSDebojyoti Ghosh             }
105749bd79ccSDebojyoti Ghosh             PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
105849bd79ccSDebojyoti Ghosh           }
105949bd79ccSDebojyoti Ghosh 
106049bd79ccSDebojyoti Ghosh           v     = aa + diag[i] + 1;
106149bd79ccSDebojyoti Ghosh           vi    = aj + diag[i] + 1;
106249bd79ccSDebojyoti Ghosh           nz    = ai[i + 1] - diag[i] - 1;
106349bd79ccSDebojyoti Ghosh           workt = work;
106449bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
10659566063dSJacob Faibussowitsch             PetscCall(PetscMemcpy(workt, x + bs * (*vi++), bs * sizeof(PetscScalar)));
106649bd79ccSDebojyoti Ghosh             workt += bs;
106749bd79ccSDebojyoti Ghosh           }
106849bd79ccSDebojyoti Ghosh           arrt = arr;
106949bd79ccSDebojyoti Ghosh           if (T) {
107049bd79ccSDebojyoti Ghosh             for (j = 0; j < nz; j++) {
10719566063dSJacob Faibussowitsch               PetscCall(PetscMemcpy(arrt, T, bs2 * sizeof(PetscScalar)));
107249bd79ccSDebojyoti Ghosh               for (k = 0; k < bs2; k++) arrt[k] *= v[j];
107349bd79ccSDebojyoti Ghosh               arrt += bs2;
107449bd79ccSDebojyoti Ghosh             }
107549bd79ccSDebojyoti Ghosh             PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
107649bd79ccSDebojyoti Ghosh           } else if (kaij->isTI) {
107749bd79ccSDebojyoti Ghosh             for (j = 0; j < nz; j++) {
10789566063dSJacob Faibussowitsch               PetscCall(PetscMemzero(arrt, bs2 * sizeof(PetscScalar)));
107949bd79ccSDebojyoti Ghosh               for (k = 0; k < bs; k++) arrt[k + bs * k] = v[j];
108049bd79ccSDebojyoti Ghosh               arrt += bs2;
108149bd79ccSDebojyoti Ghosh             }
108249bd79ccSDebojyoti Ghosh             PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
108349bd79ccSDebojyoti Ghosh           }
108449bd79ccSDebojyoti Ghosh 
108549bd79ccSDebojyoti Ghosh           PetscKernel_w_gets_Ar_times_v(bs, bs, w, idiag, y);
108649bd79ccSDebojyoti Ghosh           for (j = 0; j < bs; j++) *(x + i2 + j) = (1.0 - omega) * *(x + i2 + j) + omega * *(y + j);
108749bd79ccSDebojyoti Ghosh         }
108849bd79ccSDebojyoti Ghosh       } else {
108949bd79ccSDebojyoti Ghosh         for (i = m - 1; i >= 0; i--) {
10909566063dSJacob Faibussowitsch           PetscCall(PetscMemcpy(w, xb + i2, bs * sizeof(PetscScalar)));
109149bd79ccSDebojyoti Ghosh           v     = aa + diag[i] + 1;
109249bd79ccSDebojyoti Ghosh           vi    = aj + diag[i] + 1;
109349bd79ccSDebojyoti Ghosh           nz    = ai[i + 1] - diag[i] - 1;
109449bd79ccSDebojyoti Ghosh           workt = work;
109549bd79ccSDebojyoti Ghosh           for (j = 0; j < nz; j++) {
10969566063dSJacob Faibussowitsch             PetscCall(PetscMemcpy(workt, x + bs * (*vi++), bs * sizeof(PetscScalar)));
109749bd79ccSDebojyoti Ghosh             workt += bs;
109849bd79ccSDebojyoti Ghosh           }
109949bd79ccSDebojyoti Ghosh           arrt = arr;
110049bd79ccSDebojyoti Ghosh           if (T) {
110149bd79ccSDebojyoti Ghosh             for (j = 0; j < nz; j++) {
11029566063dSJacob Faibussowitsch               PetscCall(PetscMemcpy(arrt, T, bs2 * sizeof(PetscScalar)));
110349bd79ccSDebojyoti Ghosh               for (k = 0; k < bs2; k++) arrt[k] *= v[j];
110449bd79ccSDebojyoti Ghosh               arrt += bs2;
110549bd79ccSDebojyoti Ghosh             }
110649bd79ccSDebojyoti Ghosh             PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
110749bd79ccSDebojyoti Ghosh           } else if (kaij->isTI) {
110849bd79ccSDebojyoti Ghosh             for (j = 0; j < nz; j++) {
11099566063dSJacob Faibussowitsch               PetscCall(PetscMemzero(arrt, bs2 * sizeof(PetscScalar)));
111049bd79ccSDebojyoti Ghosh               for (k = 0; k < bs; k++) arrt[k + bs * k] = v[j];
111149bd79ccSDebojyoti Ghosh               arrt += bs2;
111249bd79ccSDebojyoti Ghosh             }
111349bd79ccSDebojyoti Ghosh             PetscKernel_w_gets_w_minus_Ar_times_v(bs, bs * nz, w, arr, work);
111449bd79ccSDebojyoti Ghosh           }
111549bd79ccSDebojyoti Ghosh           PetscKernel_w_gets_Ar_times_v(bs, bs, w, idiag, y);
111649bd79ccSDebojyoti Ghosh           for (j = 0; j < bs; j++) *(x + i2 + j) = (1.0 - omega) * *(x + i2 + j) + omega * *(y + j);
111749bd79ccSDebojyoti Ghosh         }
111849bd79ccSDebojyoti Ghosh       }
11199566063dSJacob Faibussowitsch       PetscCall(PetscLogFlops(1.0 * bs2 * (a->nz)));
112049bd79ccSDebojyoti Ghosh     }
112149bd79ccSDebojyoti Ghosh   }
112249bd79ccSDebojyoti Ghosh 
1123d0609cedSBarry Smith   PetscCall(VecRestoreArray(xx, &x));
11249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
11253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
112649bd79ccSDebojyoti Ghosh }
112749bd79ccSDebojyoti Ghosh 
112849bd79ccSDebojyoti Ghosh /*===================================================================================*/
112949bd79ccSDebojyoti Ghosh 
1130ff6a9541SJacob Faibussowitsch static PetscErrorCode MatMultAdd_MPIKAIJ(Mat A, Vec xx, Vec yy, Vec zz)
1131d71ae5a4SJacob Faibussowitsch {
113249bd79ccSDebojyoti Ghosh   Mat_MPIKAIJ *b = (Mat_MPIKAIJ *)A->data;
113349bd79ccSDebojyoti Ghosh 
113449bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
113549bd79ccSDebojyoti Ghosh   if (!yy) {
11369566063dSJacob Faibussowitsch     PetscCall(VecSet(zz, 0.0));
113749bd79ccSDebojyoti Ghosh   } else {
11389566063dSJacob Faibussowitsch     PetscCall(VecCopy(yy, zz));
113949bd79ccSDebojyoti Ghosh   }
11409566063dSJacob Faibussowitsch   PetscCall(MatKAIJ_build_AIJ_OAIJ(A)); /* Ensure b->AIJ and b->OAIJ are up to date. */
114149bd79ccSDebojyoti Ghosh   /* start the scatter */
11429566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(b->ctx, xx, b->w, INSERT_VALUES, SCATTER_FORWARD));
11439566063dSJacob Faibussowitsch   PetscCall((*b->AIJ->ops->multadd)(b->AIJ, xx, zz, zz));
11449566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(b->ctx, xx, b->w, INSERT_VALUES, SCATTER_FORWARD));
11459566063dSJacob Faibussowitsch   PetscCall((*b->OAIJ->ops->multadd)(b->OAIJ, b->w, zz, zz));
11463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
114749bd79ccSDebojyoti Ghosh }
114849bd79ccSDebojyoti Ghosh 
1149ff6a9541SJacob Faibussowitsch static PetscErrorCode MatMult_MPIKAIJ(Mat A, Vec xx, Vec yy)
1150d71ae5a4SJacob Faibussowitsch {
115149bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
1152f3fa974cSJacob Faibussowitsch   PetscCall(MatMultAdd_MPIKAIJ(A, xx, NULL, yy));
11533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
115449bd79ccSDebojyoti Ghosh }
115549bd79ccSDebojyoti Ghosh 
1156ff6a9541SJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_MPIKAIJ(Mat A, const PetscScalar **values)
1157d71ae5a4SJacob Faibussowitsch {
115849bd79ccSDebojyoti Ghosh   Mat_MPIKAIJ *b = (Mat_MPIKAIJ *)A->data;
115949bd79ccSDebojyoti Ghosh 
116049bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
11619566063dSJacob Faibussowitsch   PetscCall(MatKAIJ_build_AIJ_OAIJ(A)); /* Ensure b->AIJ is up to date. */
11629566063dSJacob Faibussowitsch   PetscCall((*b->AIJ->ops->invertblockdiagonal)(b->AIJ, values));
11633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
116449bd79ccSDebojyoti Ghosh }
116549bd79ccSDebojyoti Ghosh 
1166ff6a9541SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqKAIJ(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **values)
1167d71ae5a4SJacob Faibussowitsch {
116849bd79ccSDebojyoti Ghosh   Mat_SeqKAIJ *b    = (Mat_SeqKAIJ *)A->data;
11693ba16761SJacob Faibussowitsch   PetscBool    diag = PETSC_FALSE;
117049bd79ccSDebojyoti Ghosh   PetscInt     nzaij, nz, *colsaij, *idx, i, j, p = b->p, q = b->q, r = row / p, s = row % p, c;
117149bd79ccSDebojyoti Ghosh   PetscScalar *vaij, *v, *S = b->S, *T = b->T;
117249bd79ccSDebojyoti Ghosh 
117349bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
117428b400f6SJacob Faibussowitsch   PetscCheck(!b->getrowactive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Already active");
117549bd79ccSDebojyoti Ghosh   b->getrowactive = PETSC_TRUE;
1176aed4548fSBarry Smith   PetscCheck(row >= 0 && row < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " out of range", row);
117749bd79ccSDebojyoti Ghosh 
117849bd79ccSDebojyoti Ghosh   if ((!S) && (!T) && (!b->isTI)) {
117949bd79ccSDebojyoti Ghosh     if (ncols) *ncols = 0;
118049bd79ccSDebojyoti Ghosh     if (cols) *cols = NULL;
118149bd79ccSDebojyoti Ghosh     if (values) *values = NULL;
11823ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
118349bd79ccSDebojyoti Ghosh   }
118449bd79ccSDebojyoti Ghosh 
118549bd79ccSDebojyoti Ghosh   if (T || b->isTI) {
11869566063dSJacob Faibussowitsch     PetscCall(MatGetRow_SeqAIJ(b->AIJ, r, &nzaij, &colsaij, &vaij));
118749bd79ccSDebojyoti Ghosh     c = nzaij;
118849bd79ccSDebojyoti Ghosh     for (i = 0; i < nzaij; i++) {
118949bd79ccSDebojyoti Ghosh       /* check if this row contains a diagonal entry */
119049bd79ccSDebojyoti Ghosh       if (colsaij[i] == r) {
119149bd79ccSDebojyoti Ghosh         diag = PETSC_TRUE;
119249bd79ccSDebojyoti Ghosh         c    = i;
119349bd79ccSDebojyoti Ghosh       }
119449bd79ccSDebojyoti Ghosh     }
119549bd79ccSDebojyoti Ghosh   } else nzaij = c = 0;
119649bd79ccSDebojyoti Ghosh 
119749bd79ccSDebojyoti Ghosh   /* calculate size of row */
119849bd79ccSDebojyoti Ghosh   nz = 0;
119949bd79ccSDebojyoti Ghosh   if (S) nz += q;
120049bd79ccSDebojyoti Ghosh   if (T || b->isTI) nz += (diag && S ? (nzaij - 1) * q : nzaij * q);
120149bd79ccSDebojyoti Ghosh 
120249bd79ccSDebojyoti Ghosh   if (cols || values) {
12039566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nz, &idx, nz, &v));
120438822f9dSRichard Tran Mills     for (i = 0; i < q; i++) {
120538822f9dSRichard Tran Mills       /* We need to initialize the v[i] to zero to handle the case in which T is NULL (not the identity matrix). */
120638822f9dSRichard Tran Mills       v[i] = 0.0;
120738822f9dSRichard Tran Mills     }
120849bd79ccSDebojyoti Ghosh     if (b->isTI) {
120949bd79ccSDebojyoti Ghosh       for (i = 0; i < nzaij; i++) {
121049bd79ccSDebojyoti Ghosh         for (j = 0; j < q; j++) {
121149bd79ccSDebojyoti Ghosh           idx[i * q + j] = colsaij[i] * q + j;
121249bd79ccSDebojyoti Ghosh           v[i * q + j]   = (j == s ? vaij[i] : 0);
121349bd79ccSDebojyoti Ghosh         }
121449bd79ccSDebojyoti Ghosh       }
121549bd79ccSDebojyoti Ghosh     } else if (T) {
121649bd79ccSDebojyoti Ghosh       for (i = 0; i < nzaij; i++) {
121749bd79ccSDebojyoti Ghosh         for (j = 0; j < q; j++) {
121849bd79ccSDebojyoti Ghosh           idx[i * q + j] = colsaij[i] * q + j;
121949bd79ccSDebojyoti Ghosh           v[i * q + j]   = vaij[i] * T[s + j * p];
122049bd79ccSDebojyoti Ghosh         }
122149bd79ccSDebojyoti Ghosh       }
122249bd79ccSDebojyoti Ghosh     }
122349bd79ccSDebojyoti Ghosh     if (S) {
122449bd79ccSDebojyoti Ghosh       for (j = 0; j < q; j++) {
122549bd79ccSDebojyoti Ghosh         idx[c * q + j] = r * q + j;
122649bd79ccSDebojyoti Ghosh         v[c * q + j] += S[s + j * p];
122749bd79ccSDebojyoti Ghosh       }
122849bd79ccSDebojyoti Ghosh     }
122949bd79ccSDebojyoti Ghosh   }
123049bd79ccSDebojyoti Ghosh 
123149bd79ccSDebojyoti Ghosh   if (ncols) *ncols = nz;
123249bd79ccSDebojyoti Ghosh   if (cols) *cols = idx;
123349bd79ccSDebojyoti Ghosh   if (values) *values = v;
12343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
123549bd79ccSDebojyoti Ghosh }
123649bd79ccSDebojyoti Ghosh 
1237ff6a9541SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqKAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
1238d71ae5a4SJacob Faibussowitsch {
123949bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
1240cb4a9cd9SHong Zhang   if (nz) *nz = 0;
12419566063dSJacob Faibussowitsch   PetscCall(PetscFree2(*idx, *v));
124249bd79ccSDebojyoti Ghosh   ((Mat_SeqKAIJ *)A->data)->getrowactive = PETSC_FALSE;
12433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
124449bd79ccSDebojyoti Ghosh }
124549bd79ccSDebojyoti Ghosh 
1246ff6a9541SJacob Faibussowitsch static PetscErrorCode MatGetRow_MPIKAIJ(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **values)
1247d71ae5a4SJacob Faibussowitsch {
124849bd79ccSDebojyoti Ghosh   Mat_MPIKAIJ   *b    = (Mat_MPIKAIJ *)A->data;
124949bd79ccSDebojyoti Ghosh   Mat            AIJ  = b->A;
1250fc64b2cfSRichard Tran Mills   PetscBool      diag = PETSC_FALSE;
1251761d359dSRichard Tran Mills   Mat            MatAIJ, MatOAIJ;
125249bd79ccSDebojyoti Ghosh   const PetscInt rstart = A->rmap->rstart, rend = A->rmap->rend, p = b->p, q = b->q, *garray;
1253389eba51SJed Brown   PetscInt       nz, *idx, ncolsaij = 0, ncolsoaij = 0, *colsaij, *colsoaij, r, s, c, i, j, lrow;
125449bd79ccSDebojyoti Ghosh   PetscScalar   *v, *vals, *ovals, *S = b->S, *T = b->T;
125549bd79ccSDebojyoti Ghosh 
125649bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
12579566063dSJacob Faibussowitsch   PetscCall(MatKAIJ_build_AIJ_OAIJ(A)); /* Ensure b->AIJ and b->OAIJ are up to date. */
1258761d359dSRichard Tran Mills   MatAIJ  = ((Mat_SeqKAIJ *)b->AIJ->data)->AIJ;
1259761d359dSRichard Tran Mills   MatOAIJ = ((Mat_SeqKAIJ *)b->OAIJ->data)->AIJ;
126028b400f6SJacob Faibussowitsch   PetscCheck(!b->getrowactive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Already active");
126149bd79ccSDebojyoti Ghosh   b->getrowactive = PETSC_TRUE;
1262aed4548fSBarry Smith   PetscCheck(row >= rstart && row < rend, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only local rows");
126349bd79ccSDebojyoti Ghosh   lrow = row - rstart;
126449bd79ccSDebojyoti Ghosh 
126549bd79ccSDebojyoti Ghosh   if ((!S) && (!T) && (!b->isTI)) {
126649bd79ccSDebojyoti Ghosh     if (ncols) *ncols = 0;
126749bd79ccSDebojyoti Ghosh     if (cols) *cols = NULL;
126849bd79ccSDebojyoti Ghosh     if (values) *values = NULL;
12693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
127049bd79ccSDebojyoti Ghosh   }
127149bd79ccSDebojyoti Ghosh 
127249bd79ccSDebojyoti Ghosh   r = lrow / p;
127349bd79ccSDebojyoti Ghosh   s = lrow % p;
127449bd79ccSDebojyoti Ghosh 
127549bd79ccSDebojyoti Ghosh   if (T || b->isTI) {
12769566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJGetSeqAIJ(AIJ, NULL, NULL, &garray));
12779566063dSJacob Faibussowitsch     PetscCall(MatGetRow_SeqAIJ(MatAIJ, lrow / p, &ncolsaij, &colsaij, &vals));
12789566063dSJacob Faibussowitsch     PetscCall(MatGetRow_SeqAIJ(MatOAIJ, lrow / p, &ncolsoaij, &colsoaij, &ovals));
127949bd79ccSDebojyoti Ghosh 
128049bd79ccSDebojyoti Ghosh     c = ncolsaij + ncolsoaij;
128149bd79ccSDebojyoti Ghosh     for (i = 0; i < ncolsaij; i++) {
128249bd79ccSDebojyoti Ghosh       /* check if this row contains a diagonal entry */
128349bd79ccSDebojyoti Ghosh       if (colsaij[i] == r) {
128449bd79ccSDebojyoti Ghosh         diag = PETSC_TRUE;
128549bd79ccSDebojyoti Ghosh         c    = i;
128649bd79ccSDebojyoti Ghosh       }
128749bd79ccSDebojyoti Ghosh     }
128849bd79ccSDebojyoti Ghosh   } else c = 0;
128949bd79ccSDebojyoti Ghosh 
129049bd79ccSDebojyoti Ghosh   /* calculate size of row */
129149bd79ccSDebojyoti Ghosh   nz = 0;
129249bd79ccSDebojyoti Ghosh   if (S) nz += q;
129349bd79ccSDebojyoti Ghosh   if (T || b->isTI) nz += (diag && S ? (ncolsaij + ncolsoaij - 1) * q : (ncolsaij + ncolsoaij) * q);
129449bd79ccSDebojyoti Ghosh 
129549bd79ccSDebojyoti Ghosh   if (cols || values) {
12969566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nz, &idx, nz, &v));
1297a437a796SRichard Tran Mills     for (i = 0; i < q; i++) {
1298a437a796SRichard Tran Mills       /* We need to initialize the v[i] to zero to handle the case in which T is NULL (not the identity matrix). */
1299a437a796SRichard Tran Mills       v[i] = 0.0;
1300a437a796SRichard Tran Mills     }
130149bd79ccSDebojyoti Ghosh     if (b->isTI) {
130249bd79ccSDebojyoti Ghosh       for (i = 0; i < ncolsaij; i++) {
130349bd79ccSDebojyoti Ghosh         for (j = 0; j < q; j++) {
130449bd79ccSDebojyoti Ghosh           idx[i * q + j] = (colsaij[i] + rstart / p) * q + j;
130549bd79ccSDebojyoti Ghosh           v[i * q + j]   = (j == s ? vals[i] : 0.0);
130649bd79ccSDebojyoti Ghosh         }
130749bd79ccSDebojyoti Ghosh       }
130849bd79ccSDebojyoti Ghosh       for (i = 0; i < ncolsoaij; i++) {
130949bd79ccSDebojyoti Ghosh         for (j = 0; j < q; j++) {
131049bd79ccSDebojyoti Ghosh           idx[(i + ncolsaij) * q + j] = garray[colsoaij[i]] * q + j;
131149bd79ccSDebojyoti Ghosh           v[(i + ncolsaij) * q + j]   = (j == s ? ovals[i] : 0.0);
131249bd79ccSDebojyoti Ghosh         }
131349bd79ccSDebojyoti Ghosh       }
131449bd79ccSDebojyoti Ghosh     } else if (T) {
131549bd79ccSDebojyoti Ghosh       for (i = 0; i < ncolsaij; i++) {
131649bd79ccSDebojyoti Ghosh         for (j = 0; j < q; j++) {
131749bd79ccSDebojyoti Ghosh           idx[i * q + j] = (colsaij[i] + rstart / p) * q + j;
131849bd79ccSDebojyoti Ghosh           v[i * q + j]   = vals[i] * T[s + j * p];
131949bd79ccSDebojyoti Ghosh         }
132049bd79ccSDebojyoti Ghosh       }
132149bd79ccSDebojyoti Ghosh       for (i = 0; i < ncolsoaij; i++) {
132249bd79ccSDebojyoti Ghosh         for (j = 0; j < q; j++) {
132349bd79ccSDebojyoti Ghosh           idx[(i + ncolsaij) * q + j] = garray[colsoaij[i]] * q + j;
132449bd79ccSDebojyoti Ghosh           v[(i + ncolsaij) * q + j]   = ovals[i] * T[s + j * p];
132549bd79ccSDebojyoti Ghosh         }
132649bd79ccSDebojyoti Ghosh       }
132749bd79ccSDebojyoti Ghosh     }
132849bd79ccSDebojyoti Ghosh     if (S) {
132949bd79ccSDebojyoti Ghosh       for (j = 0; j < q; j++) {
133049bd79ccSDebojyoti Ghosh         idx[c * q + j] = (r + rstart / p) * q + j;
133149bd79ccSDebojyoti Ghosh         v[c * q + j] += S[s + j * p];
133249bd79ccSDebojyoti Ghosh       }
133349bd79ccSDebojyoti Ghosh     }
133449bd79ccSDebojyoti Ghosh   }
133549bd79ccSDebojyoti Ghosh 
133649bd79ccSDebojyoti Ghosh   if (ncols) *ncols = nz;
133749bd79ccSDebojyoti Ghosh   if (cols) *cols = idx;
133849bd79ccSDebojyoti Ghosh   if (values) *values = v;
13393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134049bd79ccSDebojyoti Ghosh }
134149bd79ccSDebojyoti Ghosh 
1342ff6a9541SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_MPIKAIJ(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
1343d71ae5a4SJacob Faibussowitsch {
134449bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
13459566063dSJacob Faibussowitsch   PetscCall(PetscFree2(*idx, *v));
134649bd79ccSDebojyoti Ghosh   ((Mat_SeqKAIJ *)A->data)->getrowactive = PETSC_FALSE;
13473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134849bd79ccSDebojyoti Ghosh }
134949bd79ccSDebojyoti Ghosh 
1350ff6a9541SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_KAIJ(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
1351d71ae5a4SJacob Faibussowitsch {
135249bd79ccSDebojyoti Ghosh   Mat A;
135349bd79ccSDebojyoti Ghosh 
135449bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
13559566063dSJacob Faibussowitsch   PetscCall(MatConvert(mat, MATAIJ, MAT_INITIAL_MATRIX, &A));
13569566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(A, isrow, iscol, cll, newmat));
13579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
13583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
135949bd79ccSDebojyoti Ghosh }
136049bd79ccSDebojyoti Ghosh 
136149bd79ccSDebojyoti Ghosh /*@C
136220f4b53cSBarry Smith   MatCreateKAIJ - Creates a matrix of type `MATKAIJ` to be used for matrices of the following form
136320f4b53cSBarry Smith .vb
136449bd79ccSDebojyoti Ghosh     [I \otimes S + A \otimes T]
136520f4b53cSBarry Smith .ve
136649bd79ccSDebojyoti Ghosh   where
136720f4b53cSBarry Smith .vb
136849bd79ccSDebojyoti Ghosh     S is a dense (p \times q) matrix
136949bd79ccSDebojyoti Ghosh     T is a dense (p \times q) matrix
137020f4b53cSBarry Smith     A is a `MATAIJ`  (n \times n) matrix
137149bd79ccSDebojyoti Ghosh     I is the identity matrix
137220f4b53cSBarry Smith .ve
137349bd79ccSDebojyoti Ghosh   The resulting matrix is (np \times nq)
137449bd79ccSDebojyoti Ghosh 
13752ef1f0ffSBarry Smith   `S` and `T` are always stored independently on all processes as `PetscScalar` arrays in column-major format.
137649bd79ccSDebojyoti Ghosh 
137749bd79ccSDebojyoti Ghosh   Collective
137849bd79ccSDebojyoti Ghosh 
137949bd79ccSDebojyoti Ghosh   Input Parameters:
138011a5261eSBarry Smith + A - the `MATAIJ` matrix
13812ef1f0ffSBarry Smith . p - number of rows in `S` and `T`
13822ef1f0ffSBarry Smith . q - number of columns in `S` and `T`
13832ef1f0ffSBarry Smith . S - the `S` matrix (can be `NULL`), stored as a `PetscScalar` array (column-major)
13842ef1f0ffSBarry Smith - T - the `T` matrix (can be `NULL`), stored as a `PetscScalar` array (column-major)
138549bd79ccSDebojyoti Ghosh 
138649bd79ccSDebojyoti Ghosh   Output Parameter:
138711a5261eSBarry Smith . kaij - the new `MATKAIJ` matrix
138849bd79ccSDebojyoti Ghosh 
13892ef1f0ffSBarry Smith   Level: advanced
13902ef1f0ffSBarry Smith 
1391d3b90ce1SRichard Tran Mills   Notes:
139211a5261eSBarry Smith   This function increases the reference count on the `MATAIJ` matrix, so the user is free to destroy the matrix if it is not needed.
139349bd79ccSDebojyoti Ghosh 
139411a5261eSBarry Smith   Changes to the entries of the `MATAIJ` matrix will immediately affect the `MATKAIJ` matrix.
139511a5261eSBarry Smith 
139611a5261eSBarry Smith   Developer Note:
139711a5261eSBarry Smith   In the `MATMPIKAIJ` case, the internal 'AIJ' and 'OAIJ' sequential KAIJ matrices are kept up to date by tracking the object state
13982ef1f0ffSBarry Smith   of the AIJ matrix 'A' that describes the blockwise action of the `MATMPIKAIJ` matrix and, if the object state has changed, lazily
13992ef1f0ffSBarry Smith   rebuilding 'AIJ' and 'OAIJ' just before executing operations with the `MATMPIKAIJ` matrix. If new types of operations are added,
1400761d359dSRichard Tran Mills   routines implementing those must also ensure these are rebuilt when needed (by calling the internal MatKAIJ_build_AIJ_OAIJ() routine).
1401761d359dSRichard Tran Mills 
1402*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatKAIJSetAIJ()`, `MatKAIJSetS()`, `MatKAIJSetT()`, `MatKAIJGetAIJ()`, `MatKAIJGetS()`, `MatKAIJGetT()`, `MATKAIJ`
140349bd79ccSDebojyoti Ghosh @*/
1404d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateKAIJ(Mat A, PetscInt p, PetscInt q, const PetscScalar S[], const PetscScalar T[], Mat *kaij)
1405d71ae5a4SJacob Faibussowitsch {
140649bd79ccSDebojyoti Ghosh   PetscFunctionBegin;
14079566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), kaij));
14089566063dSJacob Faibussowitsch   PetscCall(MatSetType(*kaij, MATKAIJ));
14099566063dSJacob Faibussowitsch   PetscCall(MatKAIJSetAIJ(*kaij, A));
14109566063dSJacob Faibussowitsch   PetscCall(MatKAIJSetS(*kaij, p, q, S));
14119566063dSJacob Faibussowitsch   PetscCall(MatKAIJSetT(*kaij, p, q, T));
14129566063dSJacob Faibussowitsch   PetscCall(MatSetUp(*kaij));
14133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14140567c835SRichard Tran Mills }
141549bd79ccSDebojyoti Ghosh 
14160567c835SRichard Tran Mills /*MC
14175881e567SRichard Tran Mills   MATKAIJ - MATKAIJ = "kaij" - A matrix type to be used to evaluate matrices of form
14185881e567SRichard Tran Mills     [I \otimes S + A \otimes T],
14190567c835SRichard Tran Mills   where
14202ef1f0ffSBarry Smith .vb
14215881e567SRichard Tran Mills     S is a dense (p \times q) matrix,
14225881e567SRichard Tran Mills     T is a dense (p \times q) matrix,
14235881e567SRichard Tran Mills     A is an AIJ  (n \times n) matrix,
14245881e567SRichard Tran Mills     and I is the identity matrix.
14252ef1f0ffSBarry Smith .ve
14265881e567SRichard Tran Mills   The resulting matrix is (np \times nq).
14270567c835SRichard Tran Mills 
142811a5261eSBarry Smith   S and T are always stored independently on all processes as `PetscScalar` arrays in column-major format.
14290567c835SRichard Tran Mills 
14302ef1f0ffSBarry Smith   Level: advanced
14312ef1f0ffSBarry Smith 
143211a5261eSBarry Smith   Note:
14335881e567SRichard Tran Mills   A linear system with multiple right-hand sides, AX = B, can be expressed in the KAIJ-friendly form of (A \otimes I) x = b,
14345881e567SRichard Tran Mills   where x and b are column vectors containing the row-major representations of X and B.
14355881e567SRichard Tran Mills 
1436*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatKAIJSetAIJ()`, `MatKAIJSetS()`, `MatKAIJSetT()`, `MatKAIJGetAIJ()`, `MatKAIJGetS()`, `MatKAIJGetT()`, `MatCreateKAIJ()`
14370567c835SRichard Tran Mills M*/
14380567c835SRichard Tran Mills 
1439d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_KAIJ(Mat A)
1440d71ae5a4SJacob Faibussowitsch {
14410567c835SRichard Tran Mills   Mat_MPIKAIJ *b;
14420567c835SRichard Tran Mills   PetscMPIInt  size;
14430567c835SRichard Tran Mills 
14440567c835SRichard Tran Mills   PetscFunctionBegin;
14454dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
14460567c835SRichard Tran Mills   A->data = (void *)b;
14470567c835SRichard Tran Mills 
14489566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(A->ops, sizeof(struct _MatOps)));
14490567c835SRichard Tran Mills 
1450f4259b30SLisandro Dalcin   b->w = NULL;
14519566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
14520567c835SRichard Tran Mills   if (size == 1) {
14539566063dSJacob Faibussowitsch     PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATSEQKAIJ));
14540567c835SRichard Tran Mills     A->ops->destroy             = MatDestroy_SeqKAIJ;
1455bb6fb833SRichard Tran Mills     A->ops->mult                = MatMult_SeqKAIJ;
1456bb6fb833SRichard Tran Mills     A->ops->multadd             = MatMultAdd_SeqKAIJ;
1457bb6fb833SRichard Tran Mills     A->ops->invertblockdiagonal = MatInvertBlockDiagonal_SeqKAIJ;
14580567c835SRichard Tran Mills     A->ops->getrow              = MatGetRow_SeqKAIJ;
14590567c835SRichard Tran Mills     A->ops->restorerow          = MatRestoreRow_SeqKAIJ;
14600567c835SRichard Tran Mills     A->ops->sor                 = MatSOR_SeqKAIJ;
14619566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_seqkaij_seqaij_C", MatConvert_KAIJ_AIJ));
14620567c835SRichard Tran Mills   } else {
14639566063dSJacob Faibussowitsch     PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATMPIKAIJ));
14640567c835SRichard Tran Mills     A->ops->destroy             = MatDestroy_MPIKAIJ;
1465bb6fb833SRichard Tran Mills     A->ops->mult                = MatMult_MPIKAIJ;
1466bb6fb833SRichard Tran Mills     A->ops->multadd             = MatMultAdd_MPIKAIJ;
1467bb6fb833SRichard Tran Mills     A->ops->invertblockdiagonal = MatInvertBlockDiagonal_MPIKAIJ;
14680567c835SRichard Tran Mills     A->ops->getrow              = MatGetRow_MPIKAIJ;
14690567c835SRichard Tran Mills     A->ops->restorerow          = MatRestoreRow_MPIKAIJ;
14709566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatGetDiagonalBlock_C", MatGetDiagonalBlock_MPIKAIJ));
14719566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_mpikaij_mpiaij_C", MatConvert_KAIJ_AIJ));
14720567c835SRichard Tran Mills   }
147306d61a37SPierre Jolivet   A->ops->setup           = MatSetUp_KAIJ;
147406d61a37SPierre Jolivet   A->ops->view            = MatView_KAIJ;
14750567c835SRichard Tran Mills   A->ops->createsubmatrix = MatCreateSubMatrix_KAIJ;
14763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147749bd79ccSDebojyoti Ghosh }
1478