xref: /petsc/src/mat/utils/gcreate.c (revision f4f49eeac7efa77fffa46b7ff95a3ed169f659ed)
1af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h"  I*/
27807a1faSBarry Smith 
3cc1836a6SJunchao Zhang #include <../src/mat/impls/aij/seq/aij.h>
4cc1836a6SJunchao Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h>
5cc1836a6SJunchao Zhang 
6d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatSetBlockSizes_Default(Mat mat, PetscInt rbs, PetscInt cbs)
7d71ae5a4SJacob Faibussowitsch {
846533700Sstefano_zampini   PetscFunctionBegin;
93ba16761SJacob Faibussowitsch   if (!mat->preallocated) PetscFunctionReturn(PETSC_SUCCESS);
10aed4548fSBarry Smith   PetscCheck(mat->rmap->bs <= 0 || mat->rmap->bs == rbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot change row block size %" PetscInt_FMT " to %" PetscInt_FMT, mat->rmap->bs, rbs);
11aed4548fSBarry Smith   PetscCheck(mat->cmap->bs <= 0 || mat->cmap->bs == cbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot change column block size %" PetscInt_FMT " to %" PetscInt_FMT, mat->cmap->bs, cbs);
123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1346533700Sstefano_zampini }
1446533700Sstefano_zampini 
15d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatShift_Basic(Mat Y, PetscScalar a)
16d71ae5a4SJacob Faibussowitsch {
17cc1836a6SJunchao Zhang   PetscInt    i, start, end, oldValA = 0, oldValB = 0;
187d68702bSBarry Smith   PetscScalar alpha = a;
197d68702bSBarry Smith   PetscBool   prevoption;
20cc1836a6SJunchao Zhang   PetscBool   isSeqAIJDerived, isMPIAIJDerived; // all classes sharing SEQAIJHEADER or MPIAIJHEADER
21cc1836a6SJunchao Zhang   Mat         A = NULL, B = NULL;
227d68702bSBarry Smith 
237d68702bSBarry Smith   PetscFunctionBegin;
249566063dSJacob Faibussowitsch   PetscCall(MatGetOption(Y, MAT_NO_OFF_PROC_ENTRIES, &prevoption));
259566063dSJacob Faibussowitsch   PetscCall(MatSetOption(Y, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
26cc1836a6SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)Y, &isSeqAIJDerived, MATSEQAIJ, MATSEQBAIJ, MATSEQSBAIJ, ""));
27cc1836a6SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)Y, &isMPIAIJDerived, MATMPIAIJ, MATMPIBAIJ, MATMPISBAIJ, ""));
28cc1836a6SJunchao Zhang 
29cc1836a6SJunchao Zhang   if (isSeqAIJDerived) A = Y;
30cc1836a6SJunchao Zhang   else if (isMPIAIJDerived) {
31cc1836a6SJunchao Zhang     Mat_MPIAIJ *mpiaij = (Mat_MPIAIJ *)Y->data;
32cc1836a6SJunchao Zhang     A                  = mpiaij->A;
33cc1836a6SJunchao Zhang     B                  = mpiaij->B;
34cc1836a6SJunchao Zhang   }
35cc1836a6SJunchao Zhang 
36cc1836a6SJunchao Zhang   if (A) {
37*f4f49eeaSPierre Jolivet     oldValA                        = ((Mat_SeqAIJ *)A->data)->nonew;
38*f4f49eeaSPierre Jolivet     ((Mat_SeqAIJ *)A->data)->nonew = 0; // so that new nonzero locations are allowed
39cc1836a6SJunchao Zhang   }
40cc1836a6SJunchao Zhang   if (B) {
41*f4f49eeaSPierre Jolivet     oldValB                        = ((Mat_SeqAIJ *)B->data)->nonew;
42*f4f49eeaSPierre Jolivet     ((Mat_SeqAIJ *)B->data)->nonew = 0;
43cc1836a6SJunchao Zhang   }
44cc1836a6SJunchao Zhang 
459566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(Y, &start, &end));
467d68702bSBarry Smith   for (i = start; i < end; i++) {
4748a46eb9SPierre Jolivet     if (i < Y->cmap->N) PetscCall(MatSetValues(Y, 1, &i, 1, &i, &alpha, ADD_VALUES));
48ab6153dcSStefano Zampini   }
499566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(Y, MAT_FINAL_ASSEMBLY));
509566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(Y, MAT_FINAL_ASSEMBLY));
519566063dSJacob Faibussowitsch   PetscCall(MatSetOption(Y, MAT_NO_OFF_PROC_ENTRIES, prevoption));
52*f4f49eeaSPierre Jolivet   if (A) ((Mat_SeqAIJ *)A->data)->nonew = oldValA;
53*f4f49eeaSPierre Jolivet   if (B) ((Mat_SeqAIJ *)B->data)->nonew = oldValB;
543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
557d68702bSBarry Smith }
567d68702bSBarry Smith 
5705869f15SSatish Balay /*@
5869dd0797SLois Curfman McInnes   MatCreate - Creates a matrix where the type is determined
5911a5261eSBarry Smith   from either a call to `MatSetType()` or from the options database
602920cce0SJacob Faibussowitsch   with a call to `MatSetFromOptions()`.
6183e1b59cSLois Curfman McInnes 
62d083f849SBarry Smith   Collective
63cb13003dSBarry Smith 
64f69a0ea3SMatthew Knepley   Input Parameter:
65f69a0ea3SMatthew Knepley . comm - MPI communicator
667807a1faSBarry Smith 
677807a1faSBarry Smith   Output Parameter:
68dc401e71SLois Curfman McInnes . A - the matrix
69e0b365e2SLois Curfman McInnes 
70273d9f13SBarry Smith   Options Database Keys:
7111a5261eSBarry Smith + -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
7211a5261eSBarry Smith . -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
7311a5261eSBarry Smith . -mat_type seqdense - `MATSEQDENSE`, uses `MatCreateSeqDense()`
7411a5261eSBarry Smith . -mat_type mpidense - `MATMPIDENSE` type, uses `MatCreateDense()`
7511a5261eSBarry Smith . -mat_type seqbaij  - `MATSEQBAIJ` type, uses `MatCreateSeqBAIJ()`
7611a5261eSBarry Smith - -mat_type mpibaij  - `MATMPIBAIJ` type, uses `MatCreateBAIJ()`
77e0b365e2SLois Curfman McInnes 
782ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
7983e1b59cSLois Curfman McInnes    for additional format-specific options.
80e0b365e2SLois Curfman McInnes 
81273d9f13SBarry Smith   Level: beginner
82273d9f13SBarry Smith 
832920cce0SJacob Faibussowitsch   Notes:
842920cce0SJacob Faibussowitsch   The default matrix type is `MATAIJ`, using the routines `MatCreateSeqAIJ()` or
852920cce0SJacob Faibussowitsch   `MatCreateAIJ()` if you do not set a type in the options database. If you never call
862920cce0SJacob Faibussowitsch   `MatSetType()` or `MatSetFromOptions()` it will generate an error when you try to use the
872920cce0SJacob Faibussowitsch   matrix.
882920cce0SJacob Faibussowitsch 
891cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
90db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
91db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
92db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
93db781477SPatrick Sanan           `MatConvert()`
94273d9f13SBarry Smith @*/
95d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate(MPI_Comm comm, Mat *A)
96d71ae5a4SJacob Faibussowitsch {
97273d9f13SBarry Smith   Mat B;
98273d9f13SBarry Smith 
99273d9f13SBarry Smith   PetscFunctionBegin;
1004f572ea9SToby Isaac   PetscAssertPointer(A, 2);
10197f1f81fSBarry Smith 
1020298fd71SBarry Smith   *A = NULL;
1039566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
1048ba1e511SMatthew Knepley 
1059566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(B, MAT_CLASSID, "Mat", "Matrix", "Mat", comm, MatDestroy, MatView));
1069566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->rmap));
1079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->cmap));
1089566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(VECSTANDARD, &B->defaultvectype));
1093faff063SStefano Zampini   PetscCall(PetscStrallocpy(PETSCRANDER48, &B->defaultrandtype));
11026fbe8dcSKarl Rupp 
111b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_UNKNOWN;
112b94d7dedSBarry Smith   B->hermitian                   = PETSC_BOOL3_UNKNOWN;
113b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_UNKNOWN;
114b94d7dedSBarry Smith   B->spd                         = PETSC_BOOL3_UNKNOWN;
115b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_FALSE;
116b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_FALSE;
117b94d7dedSBarry Smith 
11894342113SStefano Zampini   B->congruentlayouts = PETSC_DECIDE;
119273d9f13SBarry Smith   B->preallocated     = PETSC_FALSE;
1206f3d89d0SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
1216f3d89d0SStefano Zampini   B->boundtocpu = PETSC_TRUE;
1226f3d89d0SStefano Zampini #endif
123273d9f13SBarry Smith   *A = B;
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
125273d9f13SBarry Smith }
126273d9f13SBarry Smith 
12777433607SBarry Smith /*@C
12877433607SBarry Smith   MatCreateFromOptions - Creates a matrix whose type is set from the options database
12977433607SBarry Smith 
13077433607SBarry Smith   Collective
13177433607SBarry Smith 
13277433607SBarry Smith   Input Parameters:
13377433607SBarry Smith + comm   - MPI communicator
13477433607SBarry Smith . prefix - [optional] prefix for the options database
13577433607SBarry Smith . bs     - the blocksize (commonly 1)
13677433607SBarry Smith . m      - the local number of rows (or `PETSC_DECIDE`)
13777433607SBarry Smith . n      - the local number of columns (or `PETSC_DECIDE` or `PETSC_DETERMINE`)
13877433607SBarry Smith . M      - the global number of rows (or `PETSC_DETERMINE`)
13977433607SBarry Smith - N      - the global number of columns (or `PETSC_DETERMINE`)
14077433607SBarry Smith 
14177433607SBarry Smith   Output Parameter:
14277433607SBarry Smith . A - the matrix
14377433607SBarry Smith 
14477433607SBarry Smith   Options Database Key:
14577433607SBarry Smith . -mat_type - see `MatType`, for example `aij`, `aijcusparse`, `baij`, `sbaij`, dense, defaults to `aij`
14677433607SBarry Smith 
14777433607SBarry Smith   Level: beginner
14877433607SBarry Smith 
14977433607SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
15077433607SBarry Smith           `MatCreateSeqDense()`, `MatCreateDense()`,
15177433607SBarry Smith           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
15277433607SBarry Smith           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
15377433607SBarry Smith           `MatConvert()`, `MatCreate()`
15477433607SBarry Smith @*/
15577433607SBarry Smith PetscErrorCode MatCreateFromOptions(MPI_Comm comm, const char *prefix, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, Mat *A)
15677433607SBarry Smith {
15777433607SBarry Smith   PetscFunctionBegin;
15877433607SBarry Smith   PetscAssertPointer(A, 8);
15977433607SBarry Smith   PetscCall(MatCreate(comm, A));
16077433607SBarry Smith   if (prefix) PetscCall(MatSetOptionsPrefix(*A, prefix));
16177433607SBarry Smith   PetscCall(MatSetBlockSize(*A, bs));
16277433607SBarry Smith   PetscCall(MatSetSizes(*A, m, n, M, N));
16377433607SBarry Smith   PetscCall(MatSetFromOptions(*A));
16477433607SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
16577433607SBarry Smith }
16677433607SBarry Smith 
167422a814eSBarry Smith /*@
16811a5261eSBarry Smith   MatSetErrorIfFailure - Causes `Mat` to generate an immediate error, for example a zero pivot, is detected.
169422a814eSBarry Smith 
170c3339decSBarry Smith   Logically Collective
171422a814eSBarry Smith 
172422a814eSBarry Smith   Input Parameters:
17311a5261eSBarry Smith + mat - matrix obtained from `MatCreate()`
17411a5261eSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated
175422a814eSBarry Smith 
176422a814eSBarry Smith   Level: advanced
177422a814eSBarry Smith 
17811a5261eSBarry Smith   Note:
17911a5261eSBarry Smith   If this flag is not set then the matrix operation will note the error and continue. The error may cause a later `PC` or `KSP` error
18011a5261eSBarry Smith   or result in a `KSPConvergedReason` indicating the method did not converge.
18111a5261eSBarry Smith 
1821cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCSetErrorIfFailure()`, `KSPConvergedReason`, `SNESConvergedReason`
183422a814eSBarry Smith @*/
184d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetErrorIfFailure(Mat mat, PetscBool flg)
185d71ae5a4SJacob Faibussowitsch {
186422a814eSBarry Smith   PetscFunctionBegin;
187422a814eSBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
188422a814eSBarry Smith   PetscValidLogicalCollectiveBool(mat, flg, 2);
18984d44b13SHong Zhang   mat->erroriffailure = flg;
1903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
191422a814eSBarry Smith }
192422a814eSBarry Smith 
193f69a0ea3SMatthew Knepley /*@
194f69a0ea3SMatthew Knepley   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
195f69a0ea3SMatthew Knepley 
196c3339decSBarry Smith   Collective
197f69a0ea3SMatthew Knepley 
198f69a0ea3SMatthew Knepley   Input Parameters:
199f69a0ea3SMatthew Knepley + A - the matrix
20011a5261eSBarry Smith . m - number of local rows (or `PETSC_DECIDE`)
20111a5261eSBarry Smith . n - number of local columns (or `PETSC_DECIDE`)
20211a5261eSBarry Smith . M - number of global rows (or `PETSC_DETERMINE`)
20311a5261eSBarry Smith - N - number of global columns (or `PETSC_DETERMINE`)
204f69a0ea3SMatthew Knepley 
2052fe279fdSBarry Smith   Level: beginner
2062fe279fdSBarry Smith 
207f69a0ea3SMatthew Knepley   Notes:
2082ef1f0ffSBarry Smith   `m` (`n`) and `M` (`N`) cannot be both `PETSC_DECIDE`
2092ef1f0ffSBarry Smith   If one processor calls this with `M` (`N`) of `PETSC_DECIDE` then all processors must, otherwise the program will hang.
210f69a0ea3SMatthew Knepley 
21111a5261eSBarry Smith   If `PETSC_DECIDE` is not used for the arguments 'm' and 'n', then the
212f69a0ea3SMatthew Knepley   user must ensure that they are chosen to be compatible with the
213f69a0ea3SMatthew Knepley   vectors. To do this, one first considers the matrix-vector product
2142ef1f0ffSBarry Smith   'y = A x'. The `m` that is used in the above routine must match the
2152ef1f0ffSBarry Smith   local size used in the vector creation routine `VecCreateMPI()` for 'y'.
2162ef1f0ffSBarry Smith   Likewise, the `n` used must match that used as the local size in
21711a5261eSBarry Smith   `VecCreateMPI()` for 'x'.
218f69a0ea3SMatthew Knepley 
219f73d5cc4SBarry Smith   You cannot change the sizes once they have been set.
220f73d5cc4SBarry Smith 
22111a5261eSBarry Smith   The sizes must be set before `MatSetUp()` or MatXXXSetPreallocation() is called.
222f73d5cc4SBarry Smith 
2231cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatGetSize()`, `PetscSplitOwnership()`
224f69a0ea3SMatthew Knepley @*/
225d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
226d71ae5a4SJacob Faibussowitsch {
227f69a0ea3SMatthew Knepley   PetscFunctionBegin;
2280700a824SBarry Smith   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
229a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, M, 4);
230a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, N, 5);
231aed4548fSBarry Smith   PetscCheck(M <= 0 || m <= M, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local row size %" PetscInt_FMT " cannot be larger than global row size %" PetscInt_FMT, m, M);
232aed4548fSBarry Smith   PetscCheck(N <= 0 || n <= N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local column size %" PetscInt_FMT " cannot be larger than global column size %" PetscInt_FMT, n, N);
2339371c9d4SSatish Balay   PetscCheck((A->rmap->n < 0 || A->rmap->N < 0) || (A->rmap->n == m && (M <= 0 || A->rmap->N == M)), PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot change/reset row sizes to %" PetscInt_FMT " local %" PetscInt_FMT " global after previously setting them to %" PetscInt_FMT " local %" PetscInt_FMT " global", m, M,
2349371c9d4SSatish Balay              A->rmap->n, A->rmap->N);
2359371c9d4SSatish Balay   PetscCheck((A->cmap->n < 0 || A->cmap->N < 0) || (A->cmap->n == n && (N <= 0 || A->cmap->N == N)), PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot change/reset column sizes to %" PetscInt_FMT " local %" PetscInt_FMT " global after previously setting them to %" PetscInt_FMT " local %" PetscInt_FMT " global", n, N,
2369371c9d4SSatish Balay              A->cmap->n, A->cmap->N);
237d0f46423SBarry Smith   A->rmap->n = m;
238d0f46423SBarry Smith   A->cmap->n = n;
23959cb773eSBarry Smith   A->rmap->N = M > -1 ? M : A->rmap->N;
24059cb773eSBarry Smith   A->cmap->N = N > -1 ? N : A->cmap->N;
2413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
242f69a0ea3SMatthew Knepley }
243f69a0ea3SMatthew Knepley 
24405869f15SSatish Balay /*@
245273d9f13SBarry Smith   MatSetFromOptions - Creates a matrix where the type is determined
2462920cce0SJacob Faibussowitsch   from the options database.
247273d9f13SBarry Smith 
248c3339decSBarry Smith   Collective
249273d9f13SBarry Smith 
250273d9f13SBarry Smith   Input Parameter:
251fe59aa6dSJacob Faibussowitsch . B - the matrix
252273d9f13SBarry Smith 
253273d9f13SBarry Smith   Options Database Keys:
25411a5261eSBarry Smith + -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
25511a5261eSBarry Smith . -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
25611a5261eSBarry Smith . -mat_type seqdense - `MATSEQDENSE` type, uses `MatCreateSeqDense()`
25711a5261eSBarry Smith . -mat_type mpidense - `MATMPIDENSE`, uses `MatCreateDense()`
25811a5261eSBarry Smith . -mat_type seqbaij  - `MATSEQBAIJ`, uses `MatCreateSeqBAIJ()`
25911a5261eSBarry Smith - -mat_type mpibaij  - `MATMPIBAIJ`, uses `MatCreateBAIJ()`
260273d9f13SBarry Smith 
2612ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
262273d9f13SBarry Smith    for additional format-specific options.
263bd9ce289SLois Curfman McInnes 
2641d69843bSLois Curfman McInnes   Level: beginner
2651d69843bSLois Curfman McInnes 
2662920cce0SJacob Faibussowitsch   Notes:
2672920cce0SJacob Faibussowitsch   Generates a parallel MPI matrix if the communicator has more than one processor.  The default
2682920cce0SJacob Faibussowitsch   matrix type is `MATAIJ`, using the routines `MatCreateSeqAIJ()` and `MatCreateAIJ()` if you
2692920cce0SJacob Faibussowitsch   do not select a type in the options database.
2702920cce0SJacob Faibussowitsch 
2711cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
272db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
273db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
274db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
275db781477SPatrick Sanan           `MatConvert()`
2767807a1faSBarry Smith @*/
277d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetFromOptions(Mat B)
278d71ae5a4SJacob Faibussowitsch {
279f3be49caSLisandro Dalcin   const char *deft = MATAIJ;
280f3be49caSLisandro Dalcin   char        type[256];
28169df5c0cSJed Brown   PetscBool   flg, set;
28216e04d98SRichard Tran Mills   PetscInt    bind_below = 0;
283dbb450caSBarry Smith 
2843a40ed3dSBarry Smith   PetscFunctionBegin;
2850700a824SBarry Smith   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
286f3be49caSLisandro Dalcin 
287d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)B);
288535b19f3SBarry Smith 
289535b19f3SBarry Smith   if (B->rmap->bs < 0) {
290535b19f3SBarry Smith     PetscInt newbs = -1;
2919566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-mat_block_size", "Set the blocksize used to store the matrix", "MatSetBlockSize", newbs, &newbs, &flg));
292535b19f3SBarry Smith     if (flg) {
2939566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->rmap, newbs));
2949566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->cmap, newbs));
295535b19f3SBarry Smith     }
296535b19f3SBarry Smith   }
297535b19f3SBarry Smith 
2989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-mat_type", "Matrix type", "MatSetType", MatList, deft, type, 256, &flg));
299273d9f13SBarry Smith   if (flg) {
3009566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, type));
301f3be49caSLisandro Dalcin   } else if (!((PetscObject)B)->type_name) {
3029566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, deft));
303273d9f13SBarry Smith   }
304f3be49caSLisandro Dalcin 
3059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", &B->checksymmetryonassembly));
3069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", B->checksymmetrytol, &B->checksymmetrytol, NULL));
3079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_null_space_test", "Checks if provided null space is correct in MatAssemblyEnd()", "MatSetNullSpaceTest", B->checknullspaceonassembly, &B->checknullspaceonassembly, NULL));
3089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_error_if_failure", "Generate an error if an error occurs when factoring the matrix", "MatSetErrorIfFailure", B->erroriffailure, &B->erroriffailure, NULL));
309840d65ccSBarry Smith 
310dbbe0bcdSBarry Smith   PetscTryTypeMethod(B, setfromoptions, PetscOptionsObject);
311f3be49caSLisandro Dalcin 
31269df5c0cSJed Brown   flg = PETSC_FALSE;
3139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_new_nonzero_location_err", "Generate an error if new nonzeros are created in the matrix structure (useful to test preallocation)", "MatSetOption", flg, &flg, &set));
3149566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, flg));
31569df5c0cSJed Brown   flg = PETSC_FALSE;
3169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_new_nonzero_allocation_err", "Generate an error if new nonzeros are allocated in the matrix structure (useful to test preallocation)", "MatSetOption", flg, &flg, &set));
3179566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, flg));
318478db826SMatthew G. Knepley   flg = PETSC_FALSE;
3199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_ignore_zero_entries", "For AIJ/IS matrices this will stop zero values from creating a zero location in the matrix", "MatSetOption", flg, &flg, &set));
3209566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_IGNORE_ZERO_ENTRIES, flg));
32169df5c0cSJed Brown 
3221a2c6b5cSJunchao Zhang   flg = PETSC_FALSE;
3239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_form_explicit_transpose", "Hint to form an explicit transpose for operations like MatMultTranspose", "MatSetOption", flg, &flg, &set));
3249566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_FORM_EXPLICIT_TRANSPOSE, flg));
3251a2c6b5cSJunchao Zhang 
32616e04d98SRichard Tran Mills   /* Bind to CPU if below a user-specified size threshold.
32716e04d98SRichard Tran Mills    * This perhaps belongs in the options for the GPU Mat types, but MatBindToCPU() does nothing when called on non-GPU types,
32816e04d98SRichard Tran Mills    * and putting it here makes is more maintainable than duplicating this for all. */
3299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-mat_bind_below", "Set the size threshold (in local rows) below which the Mat is bound to the CPU", "MatBindToCPU", bind_below, &bind_below, &flg));
33048a46eb9SPierre Jolivet   if (flg && B->rmap->n < bind_below) PetscCall(MatBindToCPU(B, PETSC_TRUE));
33116e04d98SRichard Tran Mills 
3325d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
333dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)B, PetscOptionsObject));
334d0609cedSBarry Smith   PetscOptionsEnd();
3353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3367807a1faSBarry Smith }
3377807a1faSBarry Smith 
338987010e7SBarry Smith /*@C
33911a5261eSBarry Smith   MatXAIJSetPreallocation - set preallocation for serial and parallel `MATAIJ`, `MATBAIJ`, and `MATSBAIJ` matrices and their unassembled versions.
34063562e91SJed Brown 
341c3339decSBarry Smith   Collective
34263562e91SJed Brown 
3434165533cSJose E. Roman   Input Parameters:
34463562e91SJed Brown + A     - matrix being preallocated
34563562e91SJed Brown . bs    - block size
34641319c1dSStefano Zampini . dnnz  - number of nonzero column blocks per block row of diagonal part of parallel matrix
34741319c1dSStefano Zampini . onnz  - number of nonzero column blocks per block row of off-diagonal part of parallel matrix
34841319c1dSStefano Zampini . dnnzu - number of nonzero column blocks per block row of upper-triangular part of diagonal part of parallel matrix
34941319c1dSStefano Zampini - onnzu - number of nonzero column blocks per block row of upper-triangular part of off-diagonal part of parallel matrix
35063562e91SJed Brown 
35163562e91SJed Brown   Level: beginner
35263562e91SJed Brown 
3531cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`,
3542fe279fdSBarry Smith           `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`,
355db781477SPatrick Sanan           `PetscSplitOwnership()`
35663562e91SJed Brown @*/
357d71ae5a4SJacob Faibussowitsch PetscErrorCode MatXAIJSetPreallocation(Mat A, PetscInt bs, const PetscInt dnnz[], const PetscInt onnz[], const PetscInt dnnzu[], const PetscInt onnzu[])
358d71ae5a4SJacob Faibussowitsch {
35941319c1dSStefano Zampini   PetscInt cbs;
36063562e91SJed Brown   void (*aij)(void);
361e8bd9bafSStefano Zampini   void (*is)(void);
362990279feSStefano Zampini   void (*hyp)(void) = NULL;
36363562e91SJed Brown 
36463562e91SJed Brown   PetscFunctionBegin;
36541319c1dSStefano Zampini   if (bs != PETSC_DECIDE) { /* don't mess with an already set block size */
3669566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(A, bs));
36741319c1dSStefano Zampini   }
3689566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
3699566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
3709566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(A, &bs, &cbs));
37141319c1dSStefano Zampini   /* these routines assumes bs == cbs, this should be checked somehow */
3729566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(A, bs, 0, dnnz));
3739566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(A, bs, 0, dnnz, 0, onnz));
3749566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(A, bs, 0, dnnzu));
3759566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(A, bs, 0, dnnzu, 0, onnzu));
37663562e91SJed Brown   /*
377e8bd9bafSStefano Zampini     In general, we have to do extra work to preallocate for scalar (AIJ) or unassembled (IS) matrices so we check whether it will do any
37863562e91SJed Brown     good before going on with it.
37963562e91SJed Brown   */
3809566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIAIJSetPreallocation_C", &aij));
3819566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatISSetPreallocation_C", &is));
382990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3839566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatHYPRESetPreallocation_C", &hyp));
384990279feSStefano Zampini #endif
38548a46eb9SPierre Jolivet   if (!aij && !is && !hyp) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", &aij));
386990279feSStefano Zampini   if (aij || is || hyp) {
38741319c1dSStefano Zampini     if (bs == cbs && bs == 1) {
3889566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz));
3899566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz, 0, onnz));
3909566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz, 0, onnz));
391990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3929566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz, 0, onnz));
393990279feSStefano Zampini #endif
3943e5f4774SJed Brown     } else { /* Convert block-row precallocation to scalar-row */
39563562e91SJed Brown       PetscInt i, m, *sdnnz, *sonnz;
3969566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(A, &m, NULL));
3979566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2((!!dnnz) * m, &sdnnz, (!!onnz) * m, &sonnz));
398dec54756SJed Brown       for (i = 0; i < m; i++) {
39941319c1dSStefano Zampini         if (dnnz) sdnnz[i] = dnnz[i / bs] * cbs;
40041319c1dSStefano Zampini         if (onnz) sonnz[i] = onnz[i / bs] * cbs;
40163562e91SJed Brown       }
4029566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL));
4039566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
4049566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
405990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
4069566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
407990279feSStefano Zampini #endif
4089566063dSJacob Faibussowitsch       PetscCall(PetscFree2(sdnnz, sonnz));
40963562e91SJed Brown     }
41063562e91SJed Brown   }
4113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41263562e91SJed Brown }
41363562e91SJed Brown 
41402218ef1SBarry Smith /*@C
41502218ef1SBarry Smith   MatHeaderMerge - Merges some information from the header of `C` to `A`; the `C` object is then destroyed
416d0f46423SBarry Smith 
41702218ef1SBarry Smith   Collective, No Fortran Support
41802218ef1SBarry Smith 
41902218ef1SBarry Smith   Input Parameters:
42002218ef1SBarry Smith + A - a `Mat` being merged into
42102218ef1SBarry Smith - C - the `Mat` providing the merge information
42202218ef1SBarry Smith 
42302218ef1SBarry Smith   Level: developer
42402218ef1SBarry Smith 
42502218ef1SBarry Smith   Developer Note:
42602218ef1SBarry Smith   This is somewhat different from `MatHeaderReplace()`, it would be nice to merge the code
42702218ef1SBarry Smith 
42802218ef1SBarry Smith .seealso: `Mat`, `MatHeaderReplace()`
42902218ef1SBarry Smith  @*/
430d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHeaderMerge(Mat A, Mat *C)
431d71ae5a4SJacob Faibussowitsch {
432d44834fbSBarry Smith   PetscInt         refct;
43373107ff1SLisandro Dalcin   PetscOps         Abops;
43473107ff1SLisandro Dalcin   struct _MatOps   Aops;
4354768301cSVaclav Hapla   char            *mtype, *mname, *mprefix;
4364222ddf1SHong Zhang   Mat_Product     *product;
43733e6eea4SJose E. Roman   Mat_Redundant   *redundant;
438d4a972cbSStefano Zampini   PetscObjectState state;
439273d9f13SBarry Smith 
440273d9f13SBarry Smith   PetscFunctionBegin;
4411dc04de0SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4421dc04de0SStefano Zampini   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
4433ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
4441dc04de0SStefano Zampini   PetscCheckSameComm(A, 1, *C, 2);
445273d9f13SBarry Smith   /* save the parts of A we need */
44673107ff1SLisandro Dalcin   Abops     = ((PetscObject)A)->bops[0];
44773107ff1SLisandro Dalcin   Aops      = A->ops[0];
4487adad957SLisandro Dalcin   refct     = ((PetscObject)A)->refct;
4495c9eb25fSBarry Smith   mtype     = ((PetscObject)A)->type_name;
4505c9eb25fSBarry Smith   mname     = ((PetscObject)A)->name;
451d4a972cbSStefano Zampini   state     = ((PetscObject)A)->state;
4524768301cSVaclav Hapla   mprefix   = ((PetscObject)A)->prefix;
4534222ddf1SHong Zhang   product   = A->product;
45433e6eea4SJose E. Roman   redundant = A->redundant;
45530735b05SKris Buschelman 
4565c9eb25fSBarry Smith   /* zero these so the destroy below does not free them */
457f4259b30SLisandro Dalcin   ((PetscObject)A)->type_name = NULL;
458f4259b30SLisandro Dalcin   ((PetscObject)A)->name      = NULL;
4595c9eb25fSBarry Smith 
460dbbe0bcdSBarry Smith   /*
461dbbe0bcdSBarry Smith      free all the interior data structures from mat
462dbbe0bcdSBarry Smith      cannot use PetscUseTypeMethod(A,destroy); because compiler
463dbbe0bcdSBarry Smith      thinks it may print NULL type_name and name
464dbbe0bcdSBarry Smith   */
465dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, destroy);
4667c99f97cSSatish Balay 
4679566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->defaultvectype));
4683faff063SStefano Zampini   PetscCall(PetscFree(A->defaultrandtype));
4699566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->rmap));
4709566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->cmap));
4719566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDestroy(&((PetscObject)A)->qlist));
4729566063dSJacob Faibussowitsch   PetscCall(PetscObjectListDestroy(&((PetscObject)A)->olist));
4739566063dSJacob Faibussowitsch   PetscCall(PetscComposedQuantitiesDestroy((PetscObject)A));
474273d9f13SBarry Smith 
475273d9f13SBarry Smith   /* copy C over to A */
47626cc229bSBarry Smith   PetscCall(PetscFree(A->factorprefix));
4779566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
478273d9f13SBarry Smith 
479273d9f13SBarry Smith   /* return the parts of A we saved */
48073107ff1SLisandro Dalcin   ((PetscObject)A)->bops[0]   = Abops;
48173107ff1SLisandro Dalcin   A->ops[0]                   = Aops;
4827adad957SLisandro Dalcin   ((PetscObject)A)->refct     = refct;
4837adad957SLisandro Dalcin   ((PetscObject)A)->type_name = mtype;
4847adad957SLisandro Dalcin   ((PetscObject)A)->name      = mname;
4854768301cSVaclav Hapla   ((PetscObject)A)->prefix    = mprefix;
486d4a972cbSStefano Zampini   ((PetscObject)A)->state     = state + 1;
4874222ddf1SHong Zhang   A->product                  = product;
48833e6eea4SJose E. Roman   A->redundant                = redundant;
489273d9f13SBarry Smith 
4905c9eb25fSBarry Smith   /* since these two are copied into A we do not want them destroyed in C */
491f4259b30SLisandro Dalcin   ((PetscObject)*C)->qlist = NULL;
492f4259b30SLisandro Dalcin   ((PetscObject)*C)->olist = NULL;
49326fbe8dcSKarl Rupp 
4949566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(C));
4953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
496273d9f13SBarry Smith }
497d0f46423SBarry Smith 
49802218ef1SBarry Smith /*@
49902218ef1SBarry Smith   MatHeaderReplace - Replaces the internal data of matrix `A` by the internal data of matrix `C` while deleting the outer wrapper of `C`
500eb6b5d47SBarry Smith 
50102218ef1SBarry Smith   Input Parameters:
50202218ef1SBarry Smith + A - a `Mat` whose internal data is to be replaced
50302218ef1SBarry Smith - C - the `Mat` providing new internal data for `A`
504b30237c6SBarry Smith 
50502218ef1SBarry Smith   Level: advanced
50602218ef1SBarry Smith 
50702218ef1SBarry Smith   Example Usage\:
50802218ef1SBarry Smith .vb
50902218ef1SBarry Smith   Mat C;
51002218ef1SBarry Smith   MatCreateSeqAIJWithArrays(..., &C);
51102218ef1SBarry Smith   MatHeaderReplace(A, &C);
51202218ef1SBarry Smith   // C has been destroyed and A contains the matrix entries of C
51302218ef1SBarry Smith .ve
51402218ef1SBarry Smith 
51502218ef1SBarry Smith   Note:
51602218ef1SBarry Smith   This can be used inside a function provided to `SNESSetJacobian()`, `TSSetRHSJacobian()`, or `TSSetIJacobian()` in cases where the user code computes an entirely new sparse matrix
51702218ef1SBarry Smith   (generally with a different nonzero pattern) for each Newton update. It is usually better to reuse the matrix structure of `A` instead of constructing an entirely new one.
51802218ef1SBarry Smith 
51902218ef1SBarry Smith   Developer Note:
52002218ef1SBarry Smith   This is somewhat different from `MatHeaderMerge()` it would be nice to merge the code
52102218ef1SBarry Smith 
52202218ef1SBarry Smith .seealso: `Mat`, `MatHeaderMerge()`
52302218ef1SBarry Smith  @*/
52402218ef1SBarry Smith PetscErrorCode MatHeaderReplace(Mat A, Mat *C)
525d71ae5a4SJacob Faibussowitsch {
52627b31e29SJed Brown   PetscInt         refct;
527fefd9316SJose E. Roman   PetscObjectState state;
52828be2f97SBarry Smith   struct _p_Mat    buffer;
52981fa06acSBarry Smith   MatStencilInfo   stencil;
5308ab5b326SKris Buschelman 
5318ab5b326SKris Buschelman   PetscFunctionBegin;
53227b31e29SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
53328be2f97SBarry Smith   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
5343ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
53528be2f97SBarry Smith   PetscCheckSameComm(A, 1, *C, 2);
536aed4548fSBarry Smith   PetscCheck(((PetscObject)*C)->refct == 1, PetscObjectComm((PetscObject)C), PETSC_ERR_ARG_WRONGSTATE, "Object C has refct %" PetscInt_FMT " > 1, would leave hanging reference", ((PetscObject)*C)->refct);
5376d7c1e57SBarry Smith 
53828be2f97SBarry Smith   /* swap C and A */
53927b31e29SJed Brown   refct   = ((PetscObject)A)->refct;
540fefd9316SJose E. Roman   state   = ((PetscObject)A)->state;
54181fa06acSBarry Smith   stencil = A->stencil;
5429566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(&buffer, A, sizeof(struct _p_Mat)));
5439566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
5449566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(*C, &buffer, sizeof(struct _p_Mat)));
54527b31e29SJed Brown   ((PetscObject)A)->refct = refct;
546fefd9316SJose E. Roman   ((PetscObject)A)->state = state + 1;
54781fa06acSBarry Smith   A->stencil              = stencil;
54826fbe8dcSKarl Rupp 
549c32d4117SBarry Smith   ((PetscObject)*C)->refct = 1;
5509566063dSJacob Faibussowitsch   PetscCall(MatDestroy(C));
5513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5528ab5b326SKris Buschelman }
553e7e92044SBarry Smith 
554e7e92044SBarry Smith /*@
555b470e4b4SRichard Tran Mills   MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU
556e7e92044SBarry Smith 
5572ef1f0ffSBarry Smith   Logically Collective
5582216c58aSStefano Zampini 
559e7e92044SBarry Smith   Input Parameters:
560e7e92044SBarry Smith + A   - the matrix
56111a5261eSBarry Smith - flg - bind to the CPU if value of `PETSC_TRUE`
562e7e92044SBarry Smith 
56390ea27d8SSatish Balay   Level: intermediate
5642216c58aSStefano Zampini 
5651cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBoundToCPU()`
566e7e92044SBarry Smith @*/
567d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBindToCPU(Mat A, PetscBool flg)
568d71ae5a4SJacob Faibussowitsch {
5697d871021SStefano Zampini   PetscFunctionBegin;
5702ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5712ffa8ee7SStefano Zampini   PetscValidLogicalCollectiveBool(A, flg, 2);
5722216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
5733ba16761SJacob Faibussowitsch   if (A->boundtocpu == flg) PetscFunctionReturn(PETSC_SUCCESS);
574b470e4b4SRichard Tran Mills   A->boundtocpu = flg;
575dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, bindtocpu, flg);
5762216c58aSStefano Zampini #endif
5773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5782216c58aSStefano Zampini }
5792216c58aSStefano Zampini 
5802216c58aSStefano Zampini /*@
5812216c58aSStefano Zampini   MatBoundToCPU - query if a matrix is bound to the CPU
5822216c58aSStefano Zampini 
5832216c58aSStefano Zampini   Input Parameter:
5842216c58aSStefano Zampini . A - the matrix
5852216c58aSStefano Zampini 
5862216c58aSStefano Zampini   Output Parameter:
5872216c58aSStefano Zampini . flg - the logical flag
5882216c58aSStefano Zampini 
5892216c58aSStefano Zampini   Level: intermediate
5902216c58aSStefano Zampini 
5911cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBindToCPU()`
5922216c58aSStefano Zampini @*/
593d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBoundToCPU(Mat A, PetscBool *flg)
594d71ae5a4SJacob Faibussowitsch {
5952ffa8ee7SStefano Zampini   PetscFunctionBegin;
5962ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5974f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
5982216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
5992216c58aSStefano Zampini   *flg = A->boundtocpu;
6002216c58aSStefano Zampini #else
6012216c58aSStefano Zampini   *flg = PETSC_TRUE;
6027d871021SStefano Zampini #endif
6033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
604e7e92044SBarry Smith }
6057e8381f9SStefano Zampini 
606d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO_Basic(Mat A, const PetscScalar coo_v[], InsertMode imode)
607d71ae5a4SJacob Faibussowitsch {
6087e8381f9SStefano Zampini   IS              is_coo_i, is_coo_j;
6097e8381f9SStefano Zampini   const PetscInt *coo_i, *coo_j;
6107e8381f9SStefano Zampini   PetscInt        n, n_i, n_j;
6117e8381f9SStefano Zampini   PetscScalar     zero = 0.;
6127e8381f9SStefano Zampini 
6137e8381f9SStefano Zampini   PetscFunctionBegin;
6149566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_i", (PetscObject *)&is_coo_i));
6159566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_j", (PetscObject *)&is_coo_j));
61628b400f6SJacob Faibussowitsch   PetscCheck(is_coo_i, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_i IS");
61728b400f6SJacob Faibussowitsch   PetscCheck(is_coo_j, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_j IS");
6189566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_i, &n_i));
6199566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_j, &n_j));
62008401ef6SPierre Jolivet   PetscCheck(n_i == n_j, PETSC_COMM_SELF, PETSC_ERR_COR, "Wrong local size %" PetscInt_FMT " != %" PetscInt_FMT, n_i, n_j);
6219566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_i, &coo_i));
6229566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_j, &coo_j));
62348a46eb9SPierre Jolivet   if (imode != ADD_VALUES) PetscCall(MatZeroEntries(A));
62448a46eb9SPierre Jolivet   for (n = 0; n < n_i; n++) PetscCall(MatSetValue(A, coo_i[n], coo_j[n], coo_v ? coo_v[n] : zero, ADD_VALUES));
6259566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_i, &coo_i));
6269566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_j, &coo_j));
6273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6287e8381f9SStefano Zampini }
6297e8381f9SStefano Zampini 
6308063e3c8SPierre Jolivet PetscErrorCode MatSetPreallocationCOO_Basic(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
631d71ae5a4SJacob Faibussowitsch {
6327e8381f9SStefano Zampini   Mat         preallocator;
6337e8381f9SStefano Zampini   IS          is_coo_i, is_coo_j;
6347e8381f9SStefano Zampini   PetscScalar zero = 0.0;
6357e8381f9SStefano Zampini 
6367e8381f9SStefano Zampini   PetscFunctionBegin;
6379566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6389566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
6399566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &preallocator));
6409566063dSJacob Faibussowitsch   PetscCall(MatSetType(preallocator, MATPREALLOCATOR));
6419566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(preallocator, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
6429566063dSJacob Faibussowitsch   PetscCall(MatSetLayouts(preallocator, A->rmap, A->cmap));
6439566063dSJacob Faibussowitsch   PetscCall(MatSetUp(preallocator));
64448a46eb9SPierre Jolivet   for (PetscCount n = 0; n < ncoo; n++) PetscCall(MatSetValue(preallocator, coo_i[n], coo_j[n], zero, INSERT_VALUES));
6459566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY));
6469566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY));
6479566063dSJacob Faibussowitsch   PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_TRUE, A));
6489566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&preallocator));
6492c71b3e2SJacob Faibussowitsch   PetscCheck(ncoo <= PETSC_MAX_INT, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support", ncoo);
6509566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_i, PETSC_COPY_VALUES, &is_coo_i));
6519566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_j, PETSC_COPY_VALUES, &is_coo_j));
6529566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_i", (PetscObject)is_coo_i));
6539566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_j", (PetscObject)is_coo_j));
6549566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_i));
6559566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_j));
6563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6577e8381f9SStefano Zampini }
6587e8381f9SStefano Zampini 
65956856777SBarry Smith /*@C
660c3dd2894SJed Brown   MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries with global indices
6617e8381f9SStefano Zampini 
662c3339decSBarry Smith   Collective
6637e8381f9SStefano Zampini 
6644165533cSJose E. Roman   Input Parameters:
6657e8381f9SStefano Zampini + A     - matrix being preallocated
66642550becSJunchao Zhang . ncoo  - number of entries
6677e8381f9SStefano Zampini . coo_i - row indices
6687e8381f9SStefano Zampini - coo_j - column indices
6697e8381f9SStefano Zampini 
6707e8381f9SStefano Zampini   Level: beginner
6717e8381f9SStefano Zampini 
672394ed5ebSJunchao Zhang   Notes:
6732ef1f0ffSBarry Smith   The indices `coo_i` and `coo_j` may be modified within this function. The caller should not rely on them
674e8729f6fSJunchao Zhang   having any specific value after this function returns. The arrays can be freed or reused immediately
675e8729f6fSJunchao Zhang   after this function returns.
676e8729f6fSJunchao Zhang 
67711a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
67811a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
679d7547e51SJunchao Zhang   are allowed and will be properly added or inserted to the matrix, unless the matrix option `MAT_IGNORE_OFF_PROC_ENTRIES`
68011a5261eSBarry Smith   is set, in which case remote entries are ignored, or `MAT_NO_OFF_PROC_ENTRIES` is set, in which case an error will be generated.
6817e8381f9SStefano Zampini 
682d7547e51SJunchao Zhang   If you just want to create a sequential AIJ matrix (`MATSEQAIJ`), and your matrix entries in COO format are unique, you can also use
683d7547e51SJunchao Zhang   `MatCreateSeqAIJFromTriple()`. But that is not recommended for iterative applications.
684d7547e51SJunchao Zhang 
6851cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
6862ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOOLocal()`,
6872ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`, `MatCreateSeqAIJFromTriple()`
6887e8381f9SStefano Zampini @*/
689d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
690d71ae5a4SJacob Faibussowitsch {
6918063e3c8SPierre Jolivet   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
6927e8381f9SStefano Zampini 
6937e8381f9SStefano Zampini   PetscFunctionBegin;
6947e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
6957e8381f9SStefano Zampini   PetscValidType(A, 1);
6964f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_i, 3);
6974f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_j, 4);
6989566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6999566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
7009566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOO_C", &f));
701cbc6b225SStefano Zampini 
7029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_PreallCOO, A, 0, 0, 0));
7037e8381f9SStefano Zampini   if (f) {
7049566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
7057e8381f9SStefano Zampini   } else { /* allow fallback, very slow */
7069566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO_Basic(A, ncoo, coo_i, coo_j));
7077e8381f9SStefano Zampini   }
7089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(MAT_PreallCOO, A, 0, 0, 0));
7096834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
710cbc6b225SStefano Zampini   A->nonzerostate++;
7113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7127e8381f9SStefano Zampini }
7137e8381f9SStefano Zampini 
71456856777SBarry Smith /*@C
715c3dd2894SJed Brown   MatSetPreallocationCOOLocal - set preallocation for matrices using a coordinate format of the entries with local indices
716c3dd2894SJed Brown 
717c3339decSBarry Smith   Collective
718c3dd2894SJed Brown 
719c3dd2894SJed Brown   Input Parameters:
720c3dd2894SJed Brown + A     - matrix being preallocated
721c3dd2894SJed Brown . ncoo  - number of entries
722c3dd2894SJed Brown . coo_i - row indices (local numbering; may be modified)
723c3dd2894SJed Brown - coo_j - column indices (local numbering; may be modified)
724c3dd2894SJed Brown 
725c3dd2894SJed Brown   Level: beginner
726c3dd2894SJed Brown 
727c3dd2894SJed Brown   Notes:
72811a5261eSBarry Smith   The local indices are translated using the local to global mapping, thus `MatSetLocalToGlobalMapping()` must have been
72911a5261eSBarry Smith   called prior to this function. For matrices created with `DMCreateMatrix()` the local to global mapping is often already provided.
730c3dd2894SJed Brown 
7312ef1f0ffSBarry Smith   The indices `coo_i` and `coo_j` may be modified within this function. They might be translated to corresponding global
732735d7f90SBarry Smith   indices, but the caller should not rely on them having any specific value after this function returns. The arrays
733735d7f90SBarry Smith   can be freed or reused immediately after this function returns.
734c3dd2894SJed Brown 
73511a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
73611a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
737394ed5ebSJunchao Zhang   are allowed and will be properly added or inserted to the matrix.
738c3dd2894SJed Brown 
7391cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
7402ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOO()`,
7412ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`
742c3dd2894SJed Brown @*/
743d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOOLocal(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
744d71ae5a4SJacob Faibussowitsch {
7456834774dSStefano Zampini   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
746c3dd2894SJed Brown 
747c3dd2894SJed Brown   PetscFunctionBegin;
748c3dd2894SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
749c3dd2894SJed Brown   PetscValidType(A, 1);
7504f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_i, 3);
7514f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_j, 4);
7526834774dSStefano Zampini   PetscCheck(ncoo <= PETSC_MAX_INT, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support", ncoo);
7539566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
7549566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
755cbc6b225SStefano Zampini 
7569566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", &f));
7576834774dSStefano Zampini   if (f) {
7589566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
759cbc6b225SStefano Zampini     A->nonzerostate++;
7606834774dSStefano Zampini   } else {
761cbc6b225SStefano Zampini     ISLocalToGlobalMapping ltog_row, ltog_col;
7629566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A, &ltog_row, &ltog_col));
7639566063dSJacob Faibussowitsch     if (ltog_row) PetscCall(ISLocalToGlobalMappingApply(ltog_row, ncoo, coo_i, coo_i));
7649566063dSJacob Faibussowitsch     if (ltog_col) PetscCall(ISLocalToGlobalMappingApply(ltog_col, ncoo, coo_j, coo_j));
7659566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO(A, ncoo, coo_i, coo_j));
7666834774dSStefano Zampini   }
7676834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
7683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
769c3dd2894SJed Brown }
770c3dd2894SJed Brown 
771c3dd2894SJed Brown /*@
77211a5261eSBarry Smith   MatSetValuesCOO - set values at once in a matrix preallocated using `MatSetPreallocationCOO()`
7737e8381f9SStefano Zampini 
774c3339decSBarry Smith   Collective
7757e8381f9SStefano Zampini 
7764165533cSJose E. Roman   Input Parameters:
7777e8381f9SStefano Zampini + A     - matrix being preallocated
7782ef1f0ffSBarry Smith . coo_v - the matrix values (can be `NULL`)
7797e8381f9SStefano Zampini - imode - the insert mode
7807e8381f9SStefano Zampini 
7817e8381f9SStefano Zampini   Level: beginner
7827e8381f9SStefano Zampini 
78311a5261eSBarry Smith   Notes:
78411a5261eSBarry Smith   The values must follow the order of the indices prescribed with `MatSetPreallocationCOO()` or `MatSetPreallocationCOOLocal()`.
78511a5261eSBarry Smith 
7862ef1f0ffSBarry Smith   When repeated entries are specified in the COO indices the `coo_v` values are first properly summed, regardless of the value of imode.
78711a5261eSBarry Smith   The imode flag indicates if coo_v must be added to the current values of the matrix (`ADD_VALUES`) or overwritten (`INSERT_VALUES`).
78811a5261eSBarry Smith 
78911a5261eSBarry Smith   `MatAssemblyBegin()` and `MatAssemblyEnd()` do not need to be called after this routine. It automatically handles the assembly process.
7907e8381f9SStefano Zampini 
7911cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetPreallocationCOO()`, `MatSetPreallocationCOOLocal()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
7927e8381f9SStefano Zampini @*/
793d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode)
794d71ae5a4SJacob Faibussowitsch {
7957e8381f9SStefano Zampini   PetscErrorCode (*f)(Mat, const PetscScalar[], InsertMode) = NULL;
79635cef55dSJunchao Zhang   PetscBool oldFlg;
7977e8381f9SStefano Zampini 
7987e8381f9SStefano Zampini   PetscFunctionBegin;
7997e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8007e8381f9SStefano Zampini   PetscValidType(A, 1);
8017e8381f9SStefano Zampini   MatCheckPreallocated(A, 1);
802bfcc3627SStefano Zampini   PetscValidLogicalCollectiveEnum(A, imode, 3);
8039566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetValuesCOO_C", &f));
8049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_SetVCOO, A, 0, 0, 0));
8057e8381f9SStefano Zampini   if (f) {
80635cef55dSJunchao Zhang     PetscCall((*f)(A, coo_v, imode)); // all known COO implementations do not use MatStash. They do their own off-proc communication
80735cef55dSJunchao Zhang     PetscCall(MatGetOption(A, MAT_NO_OFF_PROC_ENTRIES, &oldFlg));
80835cef55dSJunchao Zhang     PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); // set A->nooffprocentries to avoid costly MatStash scatter in MatAssembly
80935cef55dSJunchao Zhang   } else {
81035cef55dSJunchao Zhang     PetscCall(MatSetValuesCOO_Basic(A, coo_v, imode)); // fall back to MatSetValues, which might use MatStash
8117e8381f9SStefano Zampini   }
8129566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
8139566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
81435cef55dSJunchao Zhang   if (f) PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, oldFlg));
81535cef55dSJunchao Zhang   PetscCall(PetscLogEventEnd(MAT_SetVCOO, A, 0, 0, 0));
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8177e8381f9SStefano Zampini }
81865a9ecf2SRichard Tran Mills 
81965a9ecf2SRichard Tran Mills /*@
82065a9ecf2SRichard Tran Mills   MatSetBindingPropagates - Sets whether the state of being bound to the CPU for a GPU matrix type propagates to child and some other associated objects
82165a9ecf2SRichard Tran Mills 
82265a9ecf2SRichard Tran Mills   Input Parameters:
82365a9ecf2SRichard Tran Mills + A   - the matrix
82465a9ecf2SRichard Tran Mills - flg - flag indicating whether the boundtocpu flag should be propagated
82565a9ecf2SRichard Tran Mills 
82665a9ecf2SRichard Tran Mills   Level: developer
82765a9ecf2SRichard Tran Mills 
82865a9ecf2SRichard Tran Mills   Notes:
8292fe279fdSBarry Smith   If the value of flg is set to true, the following will occur
8302fe279fdSBarry Smith +   `MatCreateSubMatrices()` and `MatCreateRedundantMatrix()` - bind created matrices to CPU if the input matrix is bound to the CPU.
8312fe279fdSBarry Smith -   `MatCreateVecs()` - bind created vectors to CPU if the input matrix is bound to the CPU.
83265a9ecf2SRichard Tran Mills 
83365a9ecf2SRichard Tran Mills   The bindingpropagates flag itself is also propagated by the above routines.
83465a9ecf2SRichard Tran Mills 
835fe59aa6dSJacob Faibussowitsch   Developer Notes:
836aa624791SPierre Jolivet   If the fine-scale `DMDA` has the `-dm_bind_below` option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
83765a9ecf2SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
83865a9ecf2SRichard Tran Mills 
8391cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `VecSetBindingPropagates()`, `MatGetBindingPropagates()`
84065a9ecf2SRichard Tran Mills @*/
841d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetBindingPropagates(Mat A, PetscBool flg)
842d71ae5a4SJacob Faibussowitsch {
84365a9ecf2SRichard Tran Mills   PetscFunctionBegin;
84465a9ecf2SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
845d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
84665a9ecf2SRichard Tran Mills   A->bindingpropagates = flg;
84765a9ecf2SRichard Tran Mills #endif
8483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84965a9ecf2SRichard Tran Mills }
850e9c74fd6SRichard Tran Mills 
851e9c74fd6SRichard Tran Mills /*@
852e9c74fd6SRichard Tran Mills   MatGetBindingPropagates - Gets whether the state of being bound to the CPU for a GPU matrix type propagates to child and some other associated objects
853e9c74fd6SRichard Tran Mills 
854e9c74fd6SRichard Tran Mills   Input Parameter:
855e9c74fd6SRichard Tran Mills . A - the matrix
856e9c74fd6SRichard Tran Mills 
857e9c74fd6SRichard Tran Mills   Output Parameter:
858e9c74fd6SRichard Tran Mills . flg - flag indicating whether the boundtocpu flag will be propagated
859e9c74fd6SRichard Tran Mills 
860e9c74fd6SRichard Tran Mills   Level: developer
861e9c74fd6SRichard Tran Mills 
8621cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetBindingPropagates()`
863e9c74fd6SRichard Tran Mills @*/
864d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetBindingPropagates(Mat A, PetscBool *flg)
865d71ae5a4SJacob Faibussowitsch {
866e9c74fd6SRichard Tran Mills   PetscFunctionBegin;
867e9c74fd6SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8684f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
869d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
870e9c74fd6SRichard Tran Mills   *flg = A->bindingpropagates;
871e9c74fd6SRichard Tran Mills #else
872e9c74fd6SRichard Tran Mills   *flg = PETSC_FALSE;
873e9c74fd6SRichard Tran Mills #endif
8743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
875e9c74fd6SRichard Tran Mills }
876