xref: /petsc/src/mat/utils/gcreate.c (revision 02218ef1a666c229ec6162e5b10b8a871f6ca6d9)
1af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h"  I*/
27807a1faSBarry Smith 
3d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatSetBlockSizes_Default(Mat mat, PetscInt rbs, PetscInt cbs)
4d71ae5a4SJacob Faibussowitsch {
546533700Sstefano_zampini   PetscFunctionBegin;
63ba16761SJacob Faibussowitsch   if (!mat->preallocated) PetscFunctionReturn(PETSC_SUCCESS);
7aed4548fSBarry 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);
8aed4548fSBarry 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);
93ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1046533700Sstefano_zampini }
1146533700Sstefano_zampini 
12d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatShift_Basic(Mat Y, PetscScalar a)
13d71ae5a4SJacob Faibussowitsch {
147d68702bSBarry Smith   PetscInt    i, start, end;
157d68702bSBarry Smith   PetscScalar alpha = a;
167d68702bSBarry Smith   PetscBool   prevoption;
177d68702bSBarry Smith 
187d68702bSBarry Smith   PetscFunctionBegin;
199566063dSJacob Faibussowitsch   PetscCall(MatGetOption(Y, MAT_NO_OFF_PROC_ENTRIES, &prevoption));
209566063dSJacob Faibussowitsch   PetscCall(MatSetOption(Y, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
219566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(Y, &start, &end));
227d68702bSBarry Smith   for (i = start; i < end; i++) {
2348a46eb9SPierre Jolivet     if (i < Y->cmap->N) PetscCall(MatSetValues(Y, 1, &i, 1, &i, &alpha, ADD_VALUES));
24ab6153dcSStefano Zampini   }
259566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(Y, MAT_FINAL_ASSEMBLY));
269566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(Y, MAT_FINAL_ASSEMBLY));
279566063dSJacob Faibussowitsch   PetscCall(MatSetOption(Y, MAT_NO_OFF_PROC_ENTRIES, prevoption));
283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
297d68702bSBarry Smith }
307d68702bSBarry Smith 
3105869f15SSatish Balay /*@
3269dd0797SLois Curfman McInnes   MatCreate - Creates a matrix where the type is determined
3311a5261eSBarry Smith   from either a call to `MatSetType()` or from the options database
342920cce0SJacob Faibussowitsch   with a call to `MatSetFromOptions()`.
3583e1b59cSLois Curfman McInnes 
36d083f849SBarry Smith   Collective
37cb13003dSBarry Smith 
38f69a0ea3SMatthew Knepley   Input Parameter:
39f69a0ea3SMatthew Knepley . comm - MPI communicator
407807a1faSBarry Smith 
417807a1faSBarry Smith   Output Parameter:
42dc401e71SLois Curfman McInnes . A - the matrix
43e0b365e2SLois Curfman McInnes 
44273d9f13SBarry Smith   Options Database Keys:
4511a5261eSBarry Smith + -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
4611a5261eSBarry Smith . -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
4711a5261eSBarry Smith . -mat_type seqdense - `MATSEQDENSE`, uses `MatCreateSeqDense()`
4811a5261eSBarry Smith . -mat_type mpidense - `MATMPIDENSE` type, uses `MatCreateDense()`
4911a5261eSBarry Smith . -mat_type seqbaij  - `MATSEQBAIJ` type, uses `MatCreateSeqBAIJ()`
5011a5261eSBarry Smith - -mat_type mpibaij  - `MATMPIBAIJ` type, uses `MatCreateBAIJ()`
51e0b365e2SLois Curfman McInnes 
522ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
5383e1b59cSLois Curfman McInnes    for additional format-specific options.
54e0b365e2SLois Curfman McInnes 
55273d9f13SBarry Smith   Level: beginner
56273d9f13SBarry Smith 
572920cce0SJacob Faibussowitsch   Notes:
582920cce0SJacob Faibussowitsch   The default matrix type is `MATAIJ`, using the routines `MatCreateSeqAIJ()` or
592920cce0SJacob Faibussowitsch   `MatCreateAIJ()` if you do not set a type in the options database. If you never call
602920cce0SJacob Faibussowitsch   `MatSetType()` or `MatSetFromOptions()` it will generate an error when you try to use the
612920cce0SJacob Faibussowitsch   matrix.
622920cce0SJacob Faibussowitsch 
631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
64db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
65db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
66db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
67db781477SPatrick Sanan           `MatConvert()`
68273d9f13SBarry Smith @*/
69d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate(MPI_Comm comm, Mat *A)
70d71ae5a4SJacob Faibussowitsch {
71273d9f13SBarry Smith   Mat B;
72273d9f13SBarry Smith 
73273d9f13SBarry Smith   PetscFunctionBegin;
744f572ea9SToby Isaac   PetscAssertPointer(A, 2);
7597f1f81fSBarry Smith 
760298fd71SBarry Smith   *A = NULL;
779566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
788ba1e511SMatthew Knepley 
799566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(B, MAT_CLASSID, "Mat", "Matrix", "Mat", comm, MatDestroy, MatView));
809566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->rmap));
819566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->cmap));
829566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(VECSTANDARD, &B->defaultvectype));
833faff063SStefano Zampini   PetscCall(PetscStrallocpy(PETSCRANDER48, &B->defaultrandtype));
8426fbe8dcSKarl Rupp 
85b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_UNKNOWN;
86b94d7dedSBarry Smith   B->hermitian                   = PETSC_BOOL3_UNKNOWN;
87b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_UNKNOWN;
88b94d7dedSBarry Smith   B->spd                         = PETSC_BOOL3_UNKNOWN;
89b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_FALSE;
90b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_FALSE;
91b94d7dedSBarry Smith 
9294342113SStefano Zampini   B->congruentlayouts = PETSC_DECIDE;
93273d9f13SBarry Smith   B->preallocated     = PETSC_FALSE;
946f3d89d0SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
956f3d89d0SStefano Zampini   B->boundtocpu = PETSC_TRUE;
966f3d89d0SStefano Zampini #endif
97273d9f13SBarry Smith   *A = B;
983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99273d9f13SBarry Smith }
100273d9f13SBarry Smith 
10177433607SBarry Smith /*@C
10277433607SBarry Smith   MatCreateFromOptions - Creates a matrix whose type is set from the options database
10377433607SBarry Smith 
10477433607SBarry Smith   Collective
10577433607SBarry Smith 
10677433607SBarry Smith   Input Parameters:
10777433607SBarry Smith + comm   - MPI communicator
10877433607SBarry Smith . prefix - [optional] prefix for the options database
10977433607SBarry Smith . bs     - the blocksize (commonly 1)
11077433607SBarry Smith . m      - the local number of rows (or `PETSC_DECIDE`)
11177433607SBarry Smith . n      - the local number of columns (or `PETSC_DECIDE` or `PETSC_DETERMINE`)
11277433607SBarry Smith . M      - the global number of rows (or `PETSC_DETERMINE`)
11377433607SBarry Smith - N      - the global number of columns (or `PETSC_DETERMINE`)
11477433607SBarry Smith 
11577433607SBarry Smith   Output Parameter:
11677433607SBarry Smith . A - the matrix
11777433607SBarry Smith 
11877433607SBarry Smith   Options Database Key:
11977433607SBarry Smith . -mat_type - see `MatType`, for example `aij`, `aijcusparse`, `baij`, `sbaij`, dense, defaults to `aij`
12077433607SBarry Smith 
12177433607SBarry Smith   Level: beginner
12277433607SBarry Smith 
12377433607SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
12477433607SBarry Smith           `MatCreateSeqDense()`, `MatCreateDense()`,
12577433607SBarry Smith           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
12677433607SBarry Smith           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
12777433607SBarry Smith           `MatConvert()`, `MatCreate()`
12877433607SBarry Smith @*/
12977433607SBarry Smith PetscErrorCode MatCreateFromOptions(MPI_Comm comm, const char *prefix, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, Mat *A)
13077433607SBarry Smith {
13177433607SBarry Smith   PetscFunctionBegin;
13277433607SBarry Smith   PetscAssertPointer(A, 8);
13377433607SBarry Smith   PetscCall(MatCreate(comm, A));
13477433607SBarry Smith   if (prefix) PetscCall(MatSetOptionsPrefix(*A, prefix));
13577433607SBarry Smith   PetscCall(MatSetBlockSize(*A, bs));
13677433607SBarry Smith   PetscCall(MatSetSizes(*A, m, n, M, N));
13777433607SBarry Smith   PetscCall(MatSetFromOptions(*A));
13877433607SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
13977433607SBarry Smith }
14077433607SBarry Smith 
141422a814eSBarry Smith /*@
14211a5261eSBarry Smith   MatSetErrorIfFailure - Causes `Mat` to generate an immediate error, for example a zero pivot, is detected.
143422a814eSBarry Smith 
144c3339decSBarry Smith   Logically Collective
145422a814eSBarry Smith 
146422a814eSBarry Smith   Input Parameters:
14711a5261eSBarry Smith + mat - matrix obtained from `MatCreate()`
14811a5261eSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated
149422a814eSBarry Smith 
150422a814eSBarry Smith   Level: advanced
151422a814eSBarry Smith 
15211a5261eSBarry Smith   Note:
15311a5261eSBarry 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
15411a5261eSBarry Smith   or result in a `KSPConvergedReason` indicating the method did not converge.
15511a5261eSBarry Smith 
1561cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCSetErrorIfFailure()`, `KSPConvergedReason`, `SNESConvergedReason`
157422a814eSBarry Smith @*/
158d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetErrorIfFailure(Mat mat, PetscBool flg)
159d71ae5a4SJacob Faibussowitsch {
160422a814eSBarry Smith   PetscFunctionBegin;
161422a814eSBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
162422a814eSBarry Smith   PetscValidLogicalCollectiveBool(mat, flg, 2);
16384d44b13SHong Zhang   mat->erroriffailure = flg;
1643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
165422a814eSBarry Smith }
166422a814eSBarry Smith 
167f69a0ea3SMatthew Knepley /*@
168f69a0ea3SMatthew Knepley   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
169f69a0ea3SMatthew Knepley 
170c3339decSBarry Smith   Collective
171f69a0ea3SMatthew Knepley 
172f69a0ea3SMatthew Knepley   Input Parameters:
173f69a0ea3SMatthew Knepley + A - the matrix
17411a5261eSBarry Smith . m - number of local rows (or `PETSC_DECIDE`)
17511a5261eSBarry Smith . n - number of local columns (or `PETSC_DECIDE`)
17611a5261eSBarry Smith . M - number of global rows (or `PETSC_DETERMINE`)
17711a5261eSBarry Smith - N - number of global columns (or `PETSC_DETERMINE`)
178f69a0ea3SMatthew Knepley 
1792fe279fdSBarry Smith   Level: beginner
1802fe279fdSBarry Smith 
181f69a0ea3SMatthew Knepley   Notes:
1822ef1f0ffSBarry Smith   `m` (`n`) and `M` (`N`) cannot be both `PETSC_DECIDE`
1832ef1f0ffSBarry Smith   If one processor calls this with `M` (`N`) of `PETSC_DECIDE` then all processors must, otherwise the program will hang.
184f69a0ea3SMatthew Knepley 
18511a5261eSBarry Smith   If `PETSC_DECIDE` is not used for the arguments 'm' and 'n', then the
186f69a0ea3SMatthew Knepley   user must ensure that they are chosen to be compatible with the
187f69a0ea3SMatthew Knepley   vectors. To do this, one first considers the matrix-vector product
1882ef1f0ffSBarry Smith   'y = A x'. The `m` that is used in the above routine must match the
1892ef1f0ffSBarry Smith   local size used in the vector creation routine `VecCreateMPI()` for 'y'.
1902ef1f0ffSBarry Smith   Likewise, the `n` used must match that used as the local size in
19111a5261eSBarry Smith   `VecCreateMPI()` for 'x'.
192f69a0ea3SMatthew Knepley 
193f73d5cc4SBarry Smith   You cannot change the sizes once they have been set.
194f73d5cc4SBarry Smith 
19511a5261eSBarry Smith   The sizes must be set before `MatSetUp()` or MatXXXSetPreallocation() is called.
196f73d5cc4SBarry Smith 
1971cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatGetSize()`, `PetscSplitOwnership()`
198f69a0ea3SMatthew Knepley @*/
199d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
200d71ae5a4SJacob Faibussowitsch {
201f69a0ea3SMatthew Knepley   PetscFunctionBegin;
2020700a824SBarry Smith   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
203a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, M, 4);
204a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, N, 5);
205aed4548fSBarry 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);
206aed4548fSBarry 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);
2079371c9d4SSatish 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,
2089371c9d4SSatish Balay              A->rmap->n, A->rmap->N);
2099371c9d4SSatish 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,
2109371c9d4SSatish Balay              A->cmap->n, A->cmap->N);
211d0f46423SBarry Smith   A->rmap->n = m;
212d0f46423SBarry Smith   A->cmap->n = n;
21359cb773eSBarry Smith   A->rmap->N = M > -1 ? M : A->rmap->N;
21459cb773eSBarry Smith   A->cmap->N = N > -1 ? N : A->cmap->N;
2153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216f69a0ea3SMatthew Knepley }
217f69a0ea3SMatthew Knepley 
21805869f15SSatish Balay /*@
219273d9f13SBarry Smith   MatSetFromOptions - Creates a matrix where the type is determined
2202920cce0SJacob Faibussowitsch   from the options database.
221273d9f13SBarry Smith 
222c3339decSBarry Smith   Collective
223273d9f13SBarry Smith 
224273d9f13SBarry Smith   Input Parameter:
225fe59aa6dSJacob Faibussowitsch . B - the matrix
226273d9f13SBarry Smith 
227273d9f13SBarry Smith   Options Database Keys:
22811a5261eSBarry Smith + -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
22911a5261eSBarry Smith . -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
23011a5261eSBarry Smith . -mat_type seqdense - `MATSEQDENSE` type, uses `MatCreateSeqDense()`
23111a5261eSBarry Smith . -mat_type mpidense - `MATMPIDENSE`, uses `MatCreateDense()`
23211a5261eSBarry Smith . -mat_type seqbaij  - `MATSEQBAIJ`, uses `MatCreateSeqBAIJ()`
23311a5261eSBarry Smith - -mat_type mpibaij  - `MATMPIBAIJ`, uses `MatCreateBAIJ()`
234273d9f13SBarry Smith 
2352ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
236273d9f13SBarry Smith    for additional format-specific options.
237bd9ce289SLois Curfman McInnes 
2381d69843bSLois Curfman McInnes   Level: beginner
2391d69843bSLois Curfman McInnes 
2402920cce0SJacob Faibussowitsch   Notes:
2412920cce0SJacob Faibussowitsch   Generates a parallel MPI matrix if the communicator has more than one processor.  The default
2422920cce0SJacob Faibussowitsch   matrix type is `MATAIJ`, using the routines `MatCreateSeqAIJ()` and `MatCreateAIJ()` if you
2432920cce0SJacob Faibussowitsch   do not select a type in the options database.
2442920cce0SJacob Faibussowitsch 
2451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
246db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
247db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
248db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
249db781477SPatrick Sanan           `MatConvert()`
2507807a1faSBarry Smith @*/
251d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetFromOptions(Mat B)
252d71ae5a4SJacob Faibussowitsch {
253f3be49caSLisandro Dalcin   const char *deft = MATAIJ;
254f3be49caSLisandro Dalcin   char        type[256];
25569df5c0cSJed Brown   PetscBool   flg, set;
25616e04d98SRichard Tran Mills   PetscInt    bind_below = 0;
257dbb450caSBarry Smith 
2583a40ed3dSBarry Smith   PetscFunctionBegin;
2590700a824SBarry Smith   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
260f3be49caSLisandro Dalcin 
261d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)B);
262535b19f3SBarry Smith 
263535b19f3SBarry Smith   if (B->rmap->bs < 0) {
264535b19f3SBarry Smith     PetscInt newbs = -1;
2659566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-mat_block_size", "Set the blocksize used to store the matrix", "MatSetBlockSize", newbs, &newbs, &flg));
266535b19f3SBarry Smith     if (flg) {
2679566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->rmap, newbs));
2689566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->cmap, newbs));
269535b19f3SBarry Smith     }
270535b19f3SBarry Smith   }
271535b19f3SBarry Smith 
2729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-mat_type", "Matrix type", "MatSetType", MatList, deft, type, 256, &flg));
273273d9f13SBarry Smith   if (flg) {
2749566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, type));
275f3be49caSLisandro Dalcin   } else if (!((PetscObject)B)->type_name) {
2769566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, deft));
277273d9f13SBarry Smith   }
278f3be49caSLisandro Dalcin 
2799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", &B->checksymmetryonassembly));
2809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", B->checksymmetrytol, &B->checksymmetrytol, NULL));
2819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_null_space_test", "Checks if provided null space is correct in MatAssemblyEnd()", "MatSetNullSpaceTest", B->checknullspaceonassembly, &B->checknullspaceonassembly, NULL));
2829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_error_if_failure", "Generate an error if an error occurs when factoring the matrix", "MatSetErrorIfFailure", B->erroriffailure, &B->erroriffailure, NULL));
283840d65ccSBarry Smith 
284dbbe0bcdSBarry Smith   PetscTryTypeMethod(B, setfromoptions, PetscOptionsObject);
285f3be49caSLisandro Dalcin 
28669df5c0cSJed Brown   flg = PETSC_FALSE;
2879566063dSJacob 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));
2889566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, flg));
28969df5c0cSJed Brown   flg = PETSC_FALSE;
2909566063dSJacob 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));
2919566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, flg));
292478db826SMatthew G. Knepley   flg = PETSC_FALSE;
2939566063dSJacob 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));
2949566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_IGNORE_ZERO_ENTRIES, flg));
29569df5c0cSJed Brown 
2961a2c6b5cSJunchao Zhang   flg = PETSC_FALSE;
2979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_form_explicit_transpose", "Hint to form an explicit transpose for operations like MatMultTranspose", "MatSetOption", flg, &flg, &set));
2989566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_FORM_EXPLICIT_TRANSPOSE, flg));
2991a2c6b5cSJunchao Zhang 
30016e04d98SRichard Tran Mills   /* Bind to CPU if below a user-specified size threshold.
30116e04d98SRichard Tran Mills    * This perhaps belongs in the options for the GPU Mat types, but MatBindToCPU() does nothing when called on non-GPU types,
30216e04d98SRichard Tran Mills    * and putting it here makes is more maintainable than duplicating this for all. */
3039566063dSJacob 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));
30448a46eb9SPierre Jolivet   if (flg && B->rmap->n < bind_below) PetscCall(MatBindToCPU(B, PETSC_TRUE));
30516e04d98SRichard Tran Mills 
3065d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
307dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)B, PetscOptionsObject));
308d0609cedSBarry Smith   PetscOptionsEnd();
3093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3107807a1faSBarry Smith }
3117807a1faSBarry Smith 
312987010e7SBarry Smith /*@C
31311a5261eSBarry Smith   MatXAIJSetPreallocation - set preallocation for serial and parallel `MATAIJ`, `MATBAIJ`, and `MATSBAIJ` matrices and their unassembled versions.
31463562e91SJed Brown 
315c3339decSBarry Smith   Collective
31663562e91SJed Brown 
3174165533cSJose E. Roman   Input Parameters:
31863562e91SJed Brown + A     - matrix being preallocated
31963562e91SJed Brown . bs    - block size
32041319c1dSStefano Zampini . dnnz  - number of nonzero column blocks per block row of diagonal part of parallel matrix
32141319c1dSStefano Zampini . onnz  - number of nonzero column blocks per block row of off-diagonal part of parallel matrix
32241319c1dSStefano Zampini . dnnzu - number of nonzero column blocks per block row of upper-triangular part of diagonal part of parallel matrix
32341319c1dSStefano Zampini - onnzu - number of nonzero column blocks per block row of upper-triangular part of off-diagonal part of parallel matrix
32463562e91SJed Brown 
32563562e91SJed Brown   Level: beginner
32663562e91SJed Brown 
3271cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`,
3282fe279fdSBarry Smith           `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`,
329db781477SPatrick Sanan           `PetscSplitOwnership()`
33063562e91SJed Brown @*/
331d71ae5a4SJacob Faibussowitsch PetscErrorCode MatXAIJSetPreallocation(Mat A, PetscInt bs, const PetscInt dnnz[], const PetscInt onnz[], const PetscInt dnnzu[], const PetscInt onnzu[])
332d71ae5a4SJacob Faibussowitsch {
33341319c1dSStefano Zampini   PetscInt cbs;
33463562e91SJed Brown   void (*aij)(void);
335e8bd9bafSStefano Zampini   void (*is)(void);
336990279feSStefano Zampini   void (*hyp)(void) = NULL;
33763562e91SJed Brown 
33863562e91SJed Brown   PetscFunctionBegin;
33941319c1dSStefano Zampini   if (bs != PETSC_DECIDE) { /* don't mess with an already set block size */
3409566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(A, bs));
34141319c1dSStefano Zampini   }
3429566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
3439566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
3449566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(A, &bs, &cbs));
34541319c1dSStefano Zampini   /* these routines assumes bs == cbs, this should be checked somehow */
3469566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(A, bs, 0, dnnz));
3479566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(A, bs, 0, dnnz, 0, onnz));
3489566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(A, bs, 0, dnnzu));
3499566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(A, bs, 0, dnnzu, 0, onnzu));
35063562e91SJed Brown   /*
351e8bd9bafSStefano 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
35263562e91SJed Brown     good before going on with it.
35363562e91SJed Brown   */
3549566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIAIJSetPreallocation_C", &aij));
3559566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatISSetPreallocation_C", &is));
356990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3579566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatHYPRESetPreallocation_C", &hyp));
358990279feSStefano Zampini #endif
35948a46eb9SPierre Jolivet   if (!aij && !is && !hyp) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", &aij));
360990279feSStefano Zampini   if (aij || is || hyp) {
36141319c1dSStefano Zampini     if (bs == cbs && bs == 1) {
3629566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz));
3639566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz, 0, onnz));
3649566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz, 0, onnz));
365990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3669566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz, 0, onnz));
367990279feSStefano Zampini #endif
3683e5f4774SJed Brown     } else { /* Convert block-row precallocation to scalar-row */
36963562e91SJed Brown       PetscInt i, m, *sdnnz, *sonnz;
3709566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(A, &m, NULL));
3719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2((!!dnnz) * m, &sdnnz, (!!onnz) * m, &sonnz));
372dec54756SJed Brown       for (i = 0; i < m; i++) {
37341319c1dSStefano Zampini         if (dnnz) sdnnz[i] = dnnz[i / bs] * cbs;
37441319c1dSStefano Zampini         if (onnz) sonnz[i] = onnz[i / bs] * cbs;
37563562e91SJed Brown       }
3769566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL));
3779566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
3789566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
379990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3809566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
381990279feSStefano Zampini #endif
3829566063dSJacob Faibussowitsch       PetscCall(PetscFree2(sdnnz, sonnz));
38363562e91SJed Brown     }
38463562e91SJed Brown   }
3853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38663562e91SJed Brown }
38763562e91SJed Brown 
388*02218ef1SBarry Smith /*@C
389*02218ef1SBarry Smith   MatHeaderMerge - Merges some information from the header of `C` to `A`; the `C` object is then destroyed
390d0f46423SBarry Smith 
391*02218ef1SBarry Smith   Collective, No Fortran Support
392*02218ef1SBarry Smith 
393*02218ef1SBarry Smith   Input Parameters:
394*02218ef1SBarry Smith + A - a `Mat` being merged into
395*02218ef1SBarry Smith - C - the `Mat` providing the merge information
396*02218ef1SBarry Smith 
397*02218ef1SBarry Smith   Level: developer
398*02218ef1SBarry Smith 
399*02218ef1SBarry Smith   Developer Note:
400*02218ef1SBarry Smith   This is somewhat different from `MatHeaderReplace()`, it would be nice to merge the code
401*02218ef1SBarry Smith 
402*02218ef1SBarry Smith .seealso: `Mat`, `MatHeaderReplace()`
403*02218ef1SBarry Smith  @*/
404d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHeaderMerge(Mat A, Mat *C)
405d71ae5a4SJacob Faibussowitsch {
406d44834fbSBarry Smith   PetscInt         refct;
40773107ff1SLisandro Dalcin   PetscOps         Abops;
40873107ff1SLisandro Dalcin   struct _MatOps   Aops;
4094768301cSVaclav Hapla   char            *mtype, *mname, *mprefix;
4104222ddf1SHong Zhang   Mat_Product     *product;
41133e6eea4SJose E. Roman   Mat_Redundant   *redundant;
412d4a972cbSStefano Zampini   PetscObjectState state;
413273d9f13SBarry Smith 
414273d9f13SBarry Smith   PetscFunctionBegin;
4151dc04de0SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4161dc04de0SStefano Zampini   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
4173ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
4181dc04de0SStefano Zampini   PetscCheckSameComm(A, 1, *C, 2);
419273d9f13SBarry Smith   /* save the parts of A we need */
42073107ff1SLisandro Dalcin   Abops     = ((PetscObject)A)->bops[0];
42173107ff1SLisandro Dalcin   Aops      = A->ops[0];
4227adad957SLisandro Dalcin   refct     = ((PetscObject)A)->refct;
4235c9eb25fSBarry Smith   mtype     = ((PetscObject)A)->type_name;
4245c9eb25fSBarry Smith   mname     = ((PetscObject)A)->name;
425d4a972cbSStefano Zampini   state     = ((PetscObject)A)->state;
4264768301cSVaclav Hapla   mprefix   = ((PetscObject)A)->prefix;
4274222ddf1SHong Zhang   product   = A->product;
42833e6eea4SJose E. Roman   redundant = A->redundant;
42930735b05SKris Buschelman 
4305c9eb25fSBarry Smith   /* zero these so the destroy below does not free them */
431f4259b30SLisandro Dalcin   ((PetscObject)A)->type_name = NULL;
432f4259b30SLisandro Dalcin   ((PetscObject)A)->name      = NULL;
4335c9eb25fSBarry Smith 
434dbbe0bcdSBarry Smith   /*
435dbbe0bcdSBarry Smith      free all the interior data structures from mat
436dbbe0bcdSBarry Smith      cannot use PetscUseTypeMethod(A,destroy); because compiler
437dbbe0bcdSBarry Smith      thinks it may print NULL type_name and name
438dbbe0bcdSBarry Smith   */
439dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, destroy);
4407c99f97cSSatish Balay 
4419566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->defaultvectype));
4423faff063SStefano Zampini   PetscCall(PetscFree(A->defaultrandtype));
4439566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->rmap));
4449566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->cmap));
4459566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDestroy(&((PetscObject)A)->qlist));
4469566063dSJacob Faibussowitsch   PetscCall(PetscObjectListDestroy(&((PetscObject)A)->olist));
4479566063dSJacob Faibussowitsch   PetscCall(PetscComposedQuantitiesDestroy((PetscObject)A));
448273d9f13SBarry Smith 
449273d9f13SBarry Smith   /* copy C over to A */
45026cc229bSBarry Smith   PetscCall(PetscFree(A->factorprefix));
4519566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
452273d9f13SBarry Smith 
453273d9f13SBarry Smith   /* return the parts of A we saved */
45473107ff1SLisandro Dalcin   ((PetscObject)A)->bops[0]   = Abops;
45573107ff1SLisandro Dalcin   A->ops[0]                   = Aops;
4567adad957SLisandro Dalcin   ((PetscObject)A)->refct     = refct;
4577adad957SLisandro Dalcin   ((PetscObject)A)->type_name = mtype;
4587adad957SLisandro Dalcin   ((PetscObject)A)->name      = mname;
4594768301cSVaclav Hapla   ((PetscObject)A)->prefix    = mprefix;
460d4a972cbSStefano Zampini   ((PetscObject)A)->state     = state + 1;
4614222ddf1SHong Zhang   A->product                  = product;
46233e6eea4SJose E. Roman   A->redundant                = redundant;
463273d9f13SBarry Smith 
4645c9eb25fSBarry Smith   /* since these two are copied into A we do not want them destroyed in C */
465f4259b30SLisandro Dalcin   ((PetscObject)*C)->qlist = NULL;
466f4259b30SLisandro Dalcin   ((PetscObject)*C)->olist = NULL;
46726fbe8dcSKarl Rupp 
4689566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(C));
4693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
470273d9f13SBarry Smith }
471d0f46423SBarry Smith 
472*02218ef1SBarry Smith /*@
473*02218ef1SBarry Smith   MatHeaderReplace - Replaces the internal data of matrix `A` by the internal data of matrix `C` while deleting the outer wrapper of `C`
474eb6b5d47SBarry Smith 
475*02218ef1SBarry Smith   Input Parameters:
476*02218ef1SBarry Smith + A - a `Mat` whose internal data is to be replaced
477*02218ef1SBarry Smith - C - the `Mat` providing new internal data for `A`
478b30237c6SBarry Smith 
479*02218ef1SBarry Smith   Level: advanced
480*02218ef1SBarry Smith 
481*02218ef1SBarry Smith   Example Usage\:
482*02218ef1SBarry Smith .vb
483*02218ef1SBarry Smith   Mat C;
484*02218ef1SBarry Smith   MatCreateSeqAIJWithArrays(..., &C);
485*02218ef1SBarry Smith   MatHeaderReplace(A, &C);
486*02218ef1SBarry Smith   // C has been destroyed and A contains the matrix entries of C
487*02218ef1SBarry Smith .ve
488*02218ef1SBarry Smith 
489*02218ef1SBarry Smith   Note:
490*02218ef1SBarry 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
491*02218ef1SBarry 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.
492*02218ef1SBarry Smith 
493*02218ef1SBarry Smith   Developer Note:
494*02218ef1SBarry Smith   This is somewhat different from `MatHeaderMerge()` it would be nice to merge the code
495*02218ef1SBarry Smith 
496*02218ef1SBarry Smith .seealso: `Mat`, `MatHeaderMerge()`
497*02218ef1SBarry Smith  @*/
498*02218ef1SBarry Smith PetscErrorCode MatHeaderReplace(Mat A, Mat *C)
499d71ae5a4SJacob Faibussowitsch {
50027b31e29SJed Brown   PetscInt         refct;
501fefd9316SJose E. Roman   PetscObjectState state;
50228be2f97SBarry Smith   struct _p_Mat    buffer;
50381fa06acSBarry Smith   MatStencilInfo   stencil;
5048ab5b326SKris Buschelman 
5058ab5b326SKris Buschelman   PetscFunctionBegin;
50627b31e29SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
50728be2f97SBarry Smith   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
5083ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
50928be2f97SBarry Smith   PetscCheckSameComm(A, 1, *C, 2);
510aed4548fSBarry 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);
5116d7c1e57SBarry Smith 
51228be2f97SBarry Smith   /* swap C and A */
51327b31e29SJed Brown   refct   = ((PetscObject)A)->refct;
514fefd9316SJose E. Roman   state   = ((PetscObject)A)->state;
51581fa06acSBarry Smith   stencil = A->stencil;
5169566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(&buffer, A, sizeof(struct _p_Mat)));
5179566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
5189566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(*C, &buffer, sizeof(struct _p_Mat)));
51927b31e29SJed Brown   ((PetscObject)A)->refct = refct;
520fefd9316SJose E. Roman   ((PetscObject)A)->state = state + 1;
52181fa06acSBarry Smith   A->stencil              = stencil;
52226fbe8dcSKarl Rupp 
523c32d4117SBarry Smith   ((PetscObject)*C)->refct = 1;
5249566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(*C, MATOP_DESTROY, (void (*)(void))NULL));
5259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(C));
5263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5278ab5b326SKris Buschelman }
528e7e92044SBarry Smith 
529e7e92044SBarry Smith /*@
530b470e4b4SRichard Tran Mills   MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU
531e7e92044SBarry Smith 
5322ef1f0ffSBarry Smith   Logically Collective
5332216c58aSStefano Zampini 
534e7e92044SBarry Smith   Input Parameters:
535e7e92044SBarry Smith + A   - the matrix
53611a5261eSBarry Smith - flg - bind to the CPU if value of `PETSC_TRUE`
537e7e92044SBarry Smith 
53890ea27d8SSatish Balay   Level: intermediate
5392216c58aSStefano Zampini 
5401cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBoundToCPU()`
541e7e92044SBarry Smith @*/
542d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBindToCPU(Mat A, PetscBool flg)
543d71ae5a4SJacob Faibussowitsch {
5447d871021SStefano Zampini   PetscFunctionBegin;
5452ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5462ffa8ee7SStefano Zampini   PetscValidLogicalCollectiveBool(A, flg, 2);
5472216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
5483ba16761SJacob Faibussowitsch   if (A->boundtocpu == flg) PetscFunctionReturn(PETSC_SUCCESS);
549b470e4b4SRichard Tran Mills   A->boundtocpu = flg;
550dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, bindtocpu, flg);
5512216c58aSStefano Zampini #endif
5523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5532216c58aSStefano Zampini }
5542216c58aSStefano Zampini 
5552216c58aSStefano Zampini /*@
5562216c58aSStefano Zampini   MatBoundToCPU - query if a matrix is bound to the CPU
5572216c58aSStefano Zampini 
5582216c58aSStefano Zampini   Input Parameter:
5592216c58aSStefano Zampini . A - the matrix
5602216c58aSStefano Zampini 
5612216c58aSStefano Zampini   Output Parameter:
5622216c58aSStefano Zampini . flg - the logical flag
5632216c58aSStefano Zampini 
5642216c58aSStefano Zampini   Level: intermediate
5652216c58aSStefano Zampini 
5661cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBindToCPU()`
5672216c58aSStefano Zampini @*/
568d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBoundToCPU(Mat A, PetscBool *flg)
569d71ae5a4SJacob Faibussowitsch {
5702ffa8ee7SStefano Zampini   PetscFunctionBegin;
5712ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5724f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
5732216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
5742216c58aSStefano Zampini   *flg = A->boundtocpu;
5752216c58aSStefano Zampini #else
5762216c58aSStefano Zampini   *flg = PETSC_TRUE;
5777d871021SStefano Zampini #endif
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
579e7e92044SBarry Smith }
5807e8381f9SStefano Zampini 
581d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO_Basic(Mat A, const PetscScalar coo_v[], InsertMode imode)
582d71ae5a4SJacob Faibussowitsch {
5837e8381f9SStefano Zampini   IS              is_coo_i, is_coo_j;
5847e8381f9SStefano Zampini   const PetscInt *coo_i, *coo_j;
5857e8381f9SStefano Zampini   PetscInt        n, n_i, n_j;
5867e8381f9SStefano Zampini   PetscScalar     zero = 0.;
5877e8381f9SStefano Zampini 
5887e8381f9SStefano Zampini   PetscFunctionBegin;
5899566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_i", (PetscObject *)&is_coo_i));
5909566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_j", (PetscObject *)&is_coo_j));
59128b400f6SJacob Faibussowitsch   PetscCheck(is_coo_i, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_i IS");
59228b400f6SJacob Faibussowitsch   PetscCheck(is_coo_j, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_j IS");
5939566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_i, &n_i));
5949566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_j, &n_j));
59508401ef6SPierre Jolivet   PetscCheck(n_i == n_j, PETSC_COMM_SELF, PETSC_ERR_COR, "Wrong local size %" PetscInt_FMT " != %" PetscInt_FMT, n_i, n_j);
5969566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_i, &coo_i));
5979566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_j, &coo_j));
59848a46eb9SPierre Jolivet   if (imode != ADD_VALUES) PetscCall(MatZeroEntries(A));
59948a46eb9SPierre 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));
6009566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_i, &coo_i));
6019566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_j, &coo_j));
6023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6037e8381f9SStefano Zampini }
6047e8381f9SStefano Zampini 
6058063e3c8SPierre Jolivet PetscErrorCode MatSetPreallocationCOO_Basic(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
606d71ae5a4SJacob Faibussowitsch {
6077e8381f9SStefano Zampini   Mat         preallocator;
6087e8381f9SStefano Zampini   IS          is_coo_i, is_coo_j;
6097e8381f9SStefano Zampini   PetscScalar zero = 0.0;
6107e8381f9SStefano Zampini 
6117e8381f9SStefano Zampini   PetscFunctionBegin;
6129566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6139566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
6149566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &preallocator));
6159566063dSJacob Faibussowitsch   PetscCall(MatSetType(preallocator, MATPREALLOCATOR));
6169566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(preallocator, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
6179566063dSJacob Faibussowitsch   PetscCall(MatSetLayouts(preallocator, A->rmap, A->cmap));
6189566063dSJacob Faibussowitsch   PetscCall(MatSetUp(preallocator));
61948a46eb9SPierre Jolivet   for (PetscCount n = 0; n < ncoo; n++) PetscCall(MatSetValue(preallocator, coo_i[n], coo_j[n], zero, INSERT_VALUES));
6209566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY));
6219566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY));
6229566063dSJacob Faibussowitsch   PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_TRUE, A));
6239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&preallocator));
6242c71b3e2SJacob 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);
6259566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_i, PETSC_COPY_VALUES, &is_coo_i));
6269566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_j, PETSC_COPY_VALUES, &is_coo_j));
6279566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_i", (PetscObject)is_coo_i));
6289566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_j", (PetscObject)is_coo_j));
6299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_i));
6309566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_j));
6313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6327e8381f9SStefano Zampini }
6337e8381f9SStefano Zampini 
63456856777SBarry Smith /*@C
635c3dd2894SJed Brown   MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries with global indices
6367e8381f9SStefano Zampini 
637c3339decSBarry Smith   Collective
6387e8381f9SStefano Zampini 
6394165533cSJose E. Roman   Input Parameters:
6407e8381f9SStefano Zampini + A     - matrix being preallocated
64142550becSJunchao Zhang . ncoo  - number of entries
6427e8381f9SStefano Zampini . coo_i - row indices
6437e8381f9SStefano Zampini - coo_j - column indices
6447e8381f9SStefano Zampini 
6457e8381f9SStefano Zampini   Level: beginner
6467e8381f9SStefano Zampini 
647394ed5ebSJunchao Zhang   Notes:
6482ef1f0ffSBarry Smith   The indices `coo_i` and `coo_j` may be modified within this function. The caller should not rely on them
649e8729f6fSJunchao Zhang   having any specific value after this function returns. The arrays can be freed or reused immediately
650e8729f6fSJunchao Zhang   after this function returns.
651e8729f6fSJunchao Zhang 
65211a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
65311a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
654d7547e51SJunchao Zhang   are allowed and will be properly added or inserted to the matrix, unless the matrix option `MAT_IGNORE_OFF_PROC_ENTRIES`
65511a5261eSBarry 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.
6567e8381f9SStefano Zampini 
657d7547e51SJunchao 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
658d7547e51SJunchao Zhang   `MatCreateSeqAIJFromTriple()`. But that is not recommended for iterative applications.
659d7547e51SJunchao Zhang 
6601cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
6612ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOOLocal()`,
6622ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`, `MatCreateSeqAIJFromTriple()`
6637e8381f9SStefano Zampini @*/
664d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
665d71ae5a4SJacob Faibussowitsch {
6668063e3c8SPierre Jolivet   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
6677e8381f9SStefano Zampini 
6687e8381f9SStefano Zampini   PetscFunctionBegin;
6697e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
6707e8381f9SStefano Zampini   PetscValidType(A, 1);
6714f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_i, 3);
6724f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_j, 4);
6739566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6749566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
6759566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOO_C", &f));
676cbc6b225SStefano Zampini 
6779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_PreallCOO, A, 0, 0, 0));
6787e8381f9SStefano Zampini   if (f) {
6799566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
6807e8381f9SStefano Zampini   } else { /* allow fallback, very slow */
6819566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO_Basic(A, ncoo, coo_i, coo_j));
6827e8381f9SStefano Zampini   }
6839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(MAT_PreallCOO, A, 0, 0, 0));
6846834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
685cbc6b225SStefano Zampini   A->nonzerostate++;
6863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6877e8381f9SStefano Zampini }
6887e8381f9SStefano Zampini 
68956856777SBarry Smith /*@C
690c3dd2894SJed Brown   MatSetPreallocationCOOLocal - set preallocation for matrices using a coordinate format of the entries with local indices
691c3dd2894SJed Brown 
692c3339decSBarry Smith   Collective
693c3dd2894SJed Brown 
694c3dd2894SJed Brown   Input Parameters:
695c3dd2894SJed Brown + A     - matrix being preallocated
696c3dd2894SJed Brown . ncoo  - number of entries
697c3dd2894SJed Brown . coo_i - row indices (local numbering; may be modified)
698c3dd2894SJed Brown - coo_j - column indices (local numbering; may be modified)
699c3dd2894SJed Brown 
700c3dd2894SJed Brown   Level: beginner
701c3dd2894SJed Brown 
702c3dd2894SJed Brown   Notes:
70311a5261eSBarry Smith   The local indices are translated using the local to global mapping, thus `MatSetLocalToGlobalMapping()` must have been
70411a5261eSBarry Smith   called prior to this function. For matrices created with `DMCreateMatrix()` the local to global mapping is often already provided.
705c3dd2894SJed Brown 
7062ef1f0ffSBarry Smith   The indices `coo_i` and `coo_j` may be modified within this function. They might be translated to corresponding global
707735d7f90SBarry Smith   indices, but the caller should not rely on them having any specific value after this function returns. The arrays
708735d7f90SBarry Smith   can be freed or reused immediately after this function returns.
709c3dd2894SJed Brown 
71011a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
71111a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
712394ed5ebSJunchao Zhang   are allowed and will be properly added or inserted to the matrix.
713c3dd2894SJed Brown 
7141cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
7152ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOO()`,
7162ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`
717c3dd2894SJed Brown @*/
718d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOOLocal(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
719d71ae5a4SJacob Faibussowitsch {
7206834774dSStefano Zampini   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
721c3dd2894SJed Brown 
722c3dd2894SJed Brown   PetscFunctionBegin;
723c3dd2894SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
724c3dd2894SJed Brown   PetscValidType(A, 1);
7254f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_i, 3);
7264f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_j, 4);
7276834774dSStefano 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);
7289566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
7299566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
730cbc6b225SStefano Zampini 
7319566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", &f));
7326834774dSStefano Zampini   if (f) {
7339566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
734cbc6b225SStefano Zampini     A->nonzerostate++;
7356834774dSStefano Zampini   } else {
736cbc6b225SStefano Zampini     ISLocalToGlobalMapping ltog_row, ltog_col;
7379566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A, &ltog_row, &ltog_col));
7389566063dSJacob Faibussowitsch     if (ltog_row) PetscCall(ISLocalToGlobalMappingApply(ltog_row, ncoo, coo_i, coo_i));
7399566063dSJacob Faibussowitsch     if (ltog_col) PetscCall(ISLocalToGlobalMappingApply(ltog_col, ncoo, coo_j, coo_j));
7409566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO(A, ncoo, coo_i, coo_j));
7416834774dSStefano Zampini   }
7426834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
7433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
744c3dd2894SJed Brown }
745c3dd2894SJed Brown 
746c3dd2894SJed Brown /*@
74711a5261eSBarry Smith   MatSetValuesCOO - set values at once in a matrix preallocated using `MatSetPreallocationCOO()`
7487e8381f9SStefano Zampini 
749c3339decSBarry Smith   Collective
7507e8381f9SStefano Zampini 
7514165533cSJose E. Roman   Input Parameters:
7527e8381f9SStefano Zampini + A     - matrix being preallocated
7532ef1f0ffSBarry Smith . coo_v - the matrix values (can be `NULL`)
7547e8381f9SStefano Zampini - imode - the insert mode
7557e8381f9SStefano Zampini 
7567e8381f9SStefano Zampini   Level: beginner
7577e8381f9SStefano Zampini 
75811a5261eSBarry Smith   Notes:
75911a5261eSBarry Smith   The values must follow the order of the indices prescribed with `MatSetPreallocationCOO()` or `MatSetPreallocationCOOLocal()`.
76011a5261eSBarry Smith 
7612ef1f0ffSBarry Smith   When repeated entries are specified in the COO indices the `coo_v` values are first properly summed, regardless of the value of imode.
76211a5261eSBarry Smith   The imode flag indicates if coo_v must be added to the current values of the matrix (`ADD_VALUES`) or overwritten (`INSERT_VALUES`).
76311a5261eSBarry Smith 
76411a5261eSBarry Smith   `MatAssemblyBegin()` and `MatAssemblyEnd()` do not need to be called after this routine. It automatically handles the assembly process.
7657e8381f9SStefano Zampini 
7661cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetPreallocationCOO()`, `MatSetPreallocationCOOLocal()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
7677e8381f9SStefano Zampini @*/
768d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode)
769d71ae5a4SJacob Faibussowitsch {
7707e8381f9SStefano Zampini   PetscErrorCode (*f)(Mat, const PetscScalar[], InsertMode) = NULL;
77135cef55dSJunchao Zhang   PetscBool oldFlg;
7727e8381f9SStefano Zampini 
7737e8381f9SStefano Zampini   PetscFunctionBegin;
7747e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7757e8381f9SStefano Zampini   PetscValidType(A, 1);
7767e8381f9SStefano Zampini   MatCheckPreallocated(A, 1);
777bfcc3627SStefano Zampini   PetscValidLogicalCollectiveEnum(A, imode, 3);
7789566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetValuesCOO_C", &f));
7799566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_SetVCOO, A, 0, 0, 0));
7807e8381f9SStefano Zampini   if (f) {
78135cef55dSJunchao Zhang     PetscCall((*f)(A, coo_v, imode)); // all known COO implementations do not use MatStash. They do their own off-proc communication
78235cef55dSJunchao Zhang     PetscCall(MatGetOption(A, MAT_NO_OFF_PROC_ENTRIES, &oldFlg));
78335cef55dSJunchao Zhang     PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); // set A->nooffprocentries to avoid costly MatStash scatter in MatAssembly
78435cef55dSJunchao Zhang   } else {
78535cef55dSJunchao Zhang     PetscCall(MatSetValuesCOO_Basic(A, coo_v, imode)); // fall back to MatSetValues, which might use MatStash
7867e8381f9SStefano Zampini   }
7879566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
7889566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
78935cef55dSJunchao Zhang   if (f) PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, oldFlg));
79035cef55dSJunchao Zhang   PetscCall(PetscLogEventEnd(MAT_SetVCOO, A, 0, 0, 0));
7913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7927e8381f9SStefano Zampini }
79365a9ecf2SRichard Tran Mills 
79465a9ecf2SRichard Tran Mills /*@
79565a9ecf2SRichard 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
79665a9ecf2SRichard Tran Mills 
79765a9ecf2SRichard Tran Mills   Input Parameters:
79865a9ecf2SRichard Tran Mills + A   - the matrix
79965a9ecf2SRichard Tran Mills - flg - flag indicating whether the boundtocpu flag should be propagated
80065a9ecf2SRichard Tran Mills 
80165a9ecf2SRichard Tran Mills   Level: developer
80265a9ecf2SRichard Tran Mills 
80365a9ecf2SRichard Tran Mills   Notes:
8042fe279fdSBarry Smith   If the value of flg is set to true, the following will occur
8052fe279fdSBarry Smith +   `MatCreateSubMatrices()` and `MatCreateRedundantMatrix()` - bind created matrices to CPU if the input matrix is bound to the CPU.
8062fe279fdSBarry Smith -   `MatCreateVecs()` - bind created vectors to CPU if the input matrix is bound to the CPU.
80765a9ecf2SRichard Tran Mills 
80865a9ecf2SRichard Tran Mills   The bindingpropagates flag itself is also propagated by the above routines.
80965a9ecf2SRichard Tran Mills 
810fe59aa6dSJacob Faibussowitsch   Developer Notes:
811aa624791SPierre Jolivet   If the fine-scale `DMDA` has the `-dm_bind_below` option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
81265a9ecf2SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
81365a9ecf2SRichard Tran Mills 
8141cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `VecSetBindingPropagates()`, `MatGetBindingPropagates()`
81565a9ecf2SRichard Tran Mills @*/
816d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetBindingPropagates(Mat A, PetscBool flg)
817d71ae5a4SJacob Faibussowitsch {
81865a9ecf2SRichard Tran Mills   PetscFunctionBegin;
81965a9ecf2SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
820d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
82165a9ecf2SRichard Tran Mills   A->bindingpropagates = flg;
82265a9ecf2SRichard Tran Mills #endif
8233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82465a9ecf2SRichard Tran Mills }
825e9c74fd6SRichard Tran Mills 
826e9c74fd6SRichard Tran Mills /*@
827e9c74fd6SRichard 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
828e9c74fd6SRichard Tran Mills 
829e9c74fd6SRichard Tran Mills   Input Parameter:
830e9c74fd6SRichard Tran Mills . A - the matrix
831e9c74fd6SRichard Tran Mills 
832e9c74fd6SRichard Tran Mills   Output Parameter:
833e9c74fd6SRichard Tran Mills . flg - flag indicating whether the boundtocpu flag will be propagated
834e9c74fd6SRichard Tran Mills 
835e9c74fd6SRichard Tran Mills   Level: developer
836e9c74fd6SRichard Tran Mills 
8371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetBindingPropagates()`
838e9c74fd6SRichard Tran Mills @*/
839d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetBindingPropagates(Mat A, PetscBool *flg)
840d71ae5a4SJacob Faibussowitsch {
841e9c74fd6SRichard Tran Mills   PetscFunctionBegin;
842e9c74fd6SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8434f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
844d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
845e9c74fd6SRichard Tran Mills   *flg = A->bindingpropagates;
846e9c74fd6SRichard Tran Mills #else
847e9c74fd6SRichard Tran Mills   *flg = PETSC_FALSE;
848e9c74fd6SRichard Tran Mills #endif
8493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
850e9c74fd6SRichard Tran Mills }
851