xref: /petsc/src/mat/utils/gcreate.c (revision 1690c2ae071c7584458d4e437df7b47bc4686b3c)
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 
69de2952eSStefano Zampini 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 
159de2952eSStefano Zampini 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) {
37f4f49eeaSPierre Jolivet     oldValA                        = ((Mat_SeqAIJ *)A->data)->nonew;
38f4f49eeaSPierre Jolivet     ((Mat_SeqAIJ *)A->data)->nonew = 0; // so that new nonzero locations are allowed
39cc1836a6SJunchao Zhang   }
40cc1836a6SJunchao Zhang   if (B) {
41f4f49eeaSPierre Jolivet     oldValB                        = ((Mat_SeqAIJ *)B->data)->nonew;
42f4f49eeaSPierre 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));
52f4f49eeaSPierre Jolivet   if (A) ((Mat_SeqAIJ *)A->data)->nonew = oldValA;
53f4f49eeaSPierre 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);
1019566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
1028ba1e511SMatthew Knepley 
1039566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(B, MAT_CLASSID, "Mat", "Matrix", "Mat", comm, MatDestroy, MatView));
1049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->rmap));
1059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->cmap));
1069566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(VECSTANDARD, &B->defaultvectype));
1073faff063SStefano Zampini   PetscCall(PetscStrallocpy(PETSCRANDER48, &B->defaultrandtype));
10826fbe8dcSKarl Rupp 
109b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_UNKNOWN;
110b94d7dedSBarry Smith   B->hermitian                   = PETSC_BOOL3_UNKNOWN;
111b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_UNKNOWN;
112b94d7dedSBarry Smith   B->spd                         = PETSC_BOOL3_UNKNOWN;
113b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_FALSE;
114b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_FALSE;
115b94d7dedSBarry Smith 
11694342113SStefano Zampini   B->congruentlayouts = PETSC_DECIDE;
117273d9f13SBarry Smith   B->preallocated     = PETSC_FALSE;
1186f3d89d0SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
1196f3d89d0SStefano Zampini   B->boundtocpu = PETSC_TRUE;
1206f3d89d0SStefano Zampini #endif
121273d9f13SBarry Smith   *A = B;
1223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
123273d9f13SBarry Smith }
124273d9f13SBarry Smith 
125cc4c1da9SBarry Smith /*@
12677433607SBarry Smith   MatCreateFromOptions - Creates a matrix whose type is set from the options database
12777433607SBarry Smith 
12877433607SBarry Smith   Collective
12977433607SBarry Smith 
13077433607SBarry Smith   Input Parameters:
13177433607SBarry Smith + comm   - MPI communicator
13277433607SBarry Smith . prefix - [optional] prefix for the options database
13377433607SBarry Smith . bs     - the blocksize (commonly 1)
13477433607SBarry Smith . m      - the local number of rows (or `PETSC_DECIDE`)
13577433607SBarry Smith . n      - the local number of columns (or `PETSC_DECIDE` or `PETSC_DETERMINE`)
13677433607SBarry Smith . M      - the global number of rows (or `PETSC_DETERMINE`)
13777433607SBarry Smith - N      - the global number of columns (or `PETSC_DETERMINE`)
13877433607SBarry Smith 
13977433607SBarry Smith   Output Parameter:
14077433607SBarry Smith . A - the matrix
14177433607SBarry Smith 
14277433607SBarry Smith   Options Database Key:
14377433607SBarry Smith . -mat_type - see `MatType`, for example `aij`, `aijcusparse`, `baij`, `sbaij`, dense, defaults to `aij`
14477433607SBarry Smith 
14577433607SBarry Smith   Level: beginner
14677433607SBarry Smith 
14777433607SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
14877433607SBarry Smith           `MatCreateSeqDense()`, `MatCreateDense()`,
14977433607SBarry Smith           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
15077433607SBarry Smith           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
15177433607SBarry Smith           `MatConvert()`, `MatCreate()`
15277433607SBarry Smith @*/
15377433607SBarry Smith PetscErrorCode MatCreateFromOptions(MPI_Comm comm, const char *prefix, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, Mat *A)
15477433607SBarry Smith {
15577433607SBarry Smith   PetscFunctionBegin;
15677433607SBarry Smith   PetscAssertPointer(A, 8);
15777433607SBarry Smith   PetscCall(MatCreate(comm, A));
15877433607SBarry Smith   if (prefix) PetscCall(MatSetOptionsPrefix(*A, prefix));
15977433607SBarry Smith   PetscCall(MatSetBlockSize(*A, bs));
16077433607SBarry Smith   PetscCall(MatSetSizes(*A, m, n, M, N));
16177433607SBarry Smith   PetscCall(MatSetFromOptions(*A));
16277433607SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
16377433607SBarry Smith }
16477433607SBarry Smith 
165422a814eSBarry Smith /*@
16611a5261eSBarry Smith   MatSetErrorIfFailure - Causes `Mat` to generate an immediate error, for example a zero pivot, is detected.
167422a814eSBarry Smith 
168c3339decSBarry Smith   Logically Collective
169422a814eSBarry Smith 
170422a814eSBarry Smith   Input Parameters:
17111a5261eSBarry Smith + mat - matrix obtained from `MatCreate()`
17211a5261eSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated
173422a814eSBarry Smith 
174422a814eSBarry Smith   Level: advanced
175422a814eSBarry Smith 
17611a5261eSBarry Smith   Note:
17711a5261eSBarry 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
17811a5261eSBarry Smith   or result in a `KSPConvergedReason` indicating the method did not converge.
17911a5261eSBarry Smith 
1801cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCSetErrorIfFailure()`, `KSPConvergedReason`, `SNESConvergedReason`
181422a814eSBarry Smith @*/
182d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetErrorIfFailure(Mat mat, PetscBool flg)
183d71ae5a4SJacob Faibussowitsch {
184422a814eSBarry Smith   PetscFunctionBegin;
185422a814eSBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
186422a814eSBarry Smith   PetscValidLogicalCollectiveBool(mat, flg, 2);
18784d44b13SHong Zhang   mat->erroriffailure = flg;
1883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
189422a814eSBarry Smith }
190422a814eSBarry Smith 
191f69a0ea3SMatthew Knepley /*@
192f69a0ea3SMatthew Knepley   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
193f69a0ea3SMatthew Knepley 
194c3339decSBarry Smith   Collective
195f69a0ea3SMatthew Knepley 
196f69a0ea3SMatthew Knepley   Input Parameters:
197f69a0ea3SMatthew Knepley + A - the matrix
19811a5261eSBarry Smith . m - number of local rows (or `PETSC_DECIDE`)
19911a5261eSBarry Smith . n - number of local columns (or `PETSC_DECIDE`)
20011a5261eSBarry Smith . M - number of global rows (or `PETSC_DETERMINE`)
20111a5261eSBarry Smith - N - number of global columns (or `PETSC_DETERMINE`)
202f69a0ea3SMatthew Knepley 
2032fe279fdSBarry Smith   Level: beginner
2042fe279fdSBarry Smith 
205f69a0ea3SMatthew Knepley   Notes:
2062ef1f0ffSBarry Smith   `m` (`n`) and `M` (`N`) cannot be both `PETSC_DECIDE`
2072ef1f0ffSBarry Smith   If one processor calls this with `M` (`N`) of `PETSC_DECIDE` then all processors must, otherwise the program will hang.
208f69a0ea3SMatthew Knepley 
20911a5261eSBarry Smith   If `PETSC_DECIDE` is not used for the arguments 'm' and 'n', then the
210f69a0ea3SMatthew Knepley   user must ensure that they are chosen to be compatible with the
211f69a0ea3SMatthew Knepley   vectors. To do this, one first considers the matrix-vector product
2122ef1f0ffSBarry Smith   'y = A x'. The `m` that is used in the above routine must match the
2132ef1f0ffSBarry Smith   local size used in the vector creation routine `VecCreateMPI()` for 'y'.
2142ef1f0ffSBarry Smith   Likewise, the `n` used must match that used as the local size in
21511a5261eSBarry Smith   `VecCreateMPI()` for 'x'.
216f69a0ea3SMatthew Knepley 
217727bdf9bSBarry Smith   If `m` and `n` are not `PETSC_DECIDE`, then the values determine the `PetscLayout` of the matrix and the ranges returned by
218727bdf9bSBarry Smith   `MatGetOwnershipRange()`,  `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, and `MatGetOwnershipRangesColumn()`.
219727bdf9bSBarry Smith 
220f73d5cc4SBarry Smith   You cannot change the sizes once they have been set.
221f73d5cc4SBarry Smith 
22211a5261eSBarry Smith   The sizes must be set before `MatSetUp()` or MatXXXSetPreallocation() is called.
223f73d5cc4SBarry Smith 
224727bdf9bSBarry Smith .seealso: [](ch_matrices), `Mat`, `MatGetSize()`, `PetscSplitOwnership()`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`,
225727bdf9bSBarry Smith           `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, `VecSetSizes()`
226f69a0ea3SMatthew Knepley @*/
227d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
228d71ae5a4SJacob Faibussowitsch {
229f69a0ea3SMatthew Knepley   PetscFunctionBegin;
2300700a824SBarry Smith   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
231a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, M, 4);
232a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, N, 5);
233aed4548fSBarry 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);
234aed4548fSBarry 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);
2359371c9d4SSatish 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,
2369371c9d4SSatish Balay              A->rmap->n, A->rmap->N);
2379371c9d4SSatish 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,
2389371c9d4SSatish Balay              A->cmap->n, A->cmap->N);
239d0f46423SBarry Smith   A->rmap->n = m;
240d0f46423SBarry Smith   A->cmap->n = n;
24159cb773eSBarry Smith   A->rmap->N = M > -1 ? M : A->rmap->N;
24259cb773eSBarry Smith   A->cmap->N = N > -1 ? N : A->cmap->N;
2433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
244f69a0ea3SMatthew Knepley }
245f69a0ea3SMatthew Knepley 
24605869f15SSatish Balay /*@
247273d9f13SBarry Smith   MatSetFromOptions - Creates a matrix where the type is determined
2482920cce0SJacob Faibussowitsch   from the options database.
249273d9f13SBarry Smith 
250c3339decSBarry Smith   Collective
251273d9f13SBarry Smith 
252273d9f13SBarry Smith   Input Parameter:
253fe59aa6dSJacob Faibussowitsch . B - the matrix
254273d9f13SBarry Smith 
255273d9f13SBarry Smith   Options Database Keys:
25611a5261eSBarry Smith + -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
25711a5261eSBarry Smith . -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
25811a5261eSBarry Smith . -mat_type seqdense - `MATSEQDENSE` type, uses `MatCreateSeqDense()`
25911a5261eSBarry Smith . -mat_type mpidense - `MATMPIDENSE`, uses `MatCreateDense()`
26011a5261eSBarry Smith . -mat_type seqbaij  - `MATSEQBAIJ`, uses `MatCreateSeqBAIJ()`
26111a5261eSBarry Smith - -mat_type mpibaij  - `MATMPIBAIJ`, uses `MatCreateBAIJ()`
262273d9f13SBarry Smith 
2632ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
264273d9f13SBarry Smith    for additional format-specific options.
265bd9ce289SLois Curfman McInnes 
2661d69843bSLois Curfman McInnes   Level: beginner
2671d69843bSLois Curfman McInnes 
2682920cce0SJacob Faibussowitsch   Notes:
2692920cce0SJacob Faibussowitsch   Generates a parallel MPI matrix if the communicator has more than one processor.  The default
2702920cce0SJacob Faibussowitsch   matrix type is `MATAIJ`, using the routines `MatCreateSeqAIJ()` and `MatCreateAIJ()` if you
2712920cce0SJacob Faibussowitsch   do not select a type in the options database.
2722920cce0SJacob Faibussowitsch 
2731cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
274db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
275db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
276db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
277db781477SPatrick Sanan           `MatConvert()`
2787807a1faSBarry Smith @*/
279d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetFromOptions(Mat B)
280d71ae5a4SJacob Faibussowitsch {
281f3be49caSLisandro Dalcin   const char *deft = MATAIJ;
282f3be49caSLisandro Dalcin   char        type[256];
28369df5c0cSJed Brown   PetscBool   flg, set;
28416e04d98SRichard Tran Mills   PetscInt    bind_below = 0;
285dbb450caSBarry Smith 
2863a40ed3dSBarry Smith   PetscFunctionBegin;
2870700a824SBarry Smith   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
288f3be49caSLisandro Dalcin 
289d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)B);
290535b19f3SBarry Smith 
291535b19f3SBarry Smith   if (B->rmap->bs < 0) {
292535b19f3SBarry Smith     PetscInt newbs = -1;
2939566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-mat_block_size", "Set the blocksize used to store the matrix", "MatSetBlockSize", newbs, &newbs, &flg));
294535b19f3SBarry Smith     if (flg) {
2959566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->rmap, newbs));
2969566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->cmap, newbs));
297535b19f3SBarry Smith     }
298535b19f3SBarry Smith   }
299535b19f3SBarry Smith 
3009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-mat_type", "Matrix type", "MatSetType", MatList, deft, type, 256, &flg));
301273d9f13SBarry Smith   if (flg) {
3029566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, type));
303f3be49caSLisandro Dalcin   } else if (!((PetscObject)B)->type_name) {
3049566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, deft));
305273d9f13SBarry Smith   }
306f3be49caSLisandro Dalcin 
3079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", &B->checksymmetryonassembly));
3089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", B->checksymmetrytol, &B->checksymmetrytol, NULL));
3099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_null_space_test", "Checks if provided null space is correct in MatAssemblyEnd()", "MatSetNullSpaceTest", B->checknullspaceonassembly, &B->checknullspaceonassembly, NULL));
3109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_error_if_failure", "Generate an error if an error occurs when factoring the matrix", "MatSetErrorIfFailure", B->erroriffailure, &B->erroriffailure, NULL));
311840d65ccSBarry Smith 
312dbbe0bcdSBarry Smith   PetscTryTypeMethod(B, setfromoptions, PetscOptionsObject);
313f3be49caSLisandro Dalcin 
31469df5c0cSJed Brown   flg = PETSC_FALSE;
3159566063dSJacob 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));
3169566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, flg));
31769df5c0cSJed Brown   flg = PETSC_FALSE;
3189566063dSJacob 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));
3199566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, flg));
320478db826SMatthew G. Knepley   flg = PETSC_FALSE;
3219566063dSJacob 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));
3229566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_IGNORE_ZERO_ENTRIES, flg));
32369df5c0cSJed Brown 
3241a2c6b5cSJunchao Zhang   flg = PETSC_FALSE;
3259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_form_explicit_transpose", "Hint to form an explicit transpose for operations like MatMultTranspose", "MatSetOption", flg, &flg, &set));
3269566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_FORM_EXPLICIT_TRANSPOSE, flg));
3271a2c6b5cSJunchao Zhang 
32816e04d98SRichard Tran Mills   /* Bind to CPU if below a user-specified size threshold.
32916e04d98SRichard Tran Mills    * This perhaps belongs in the options for the GPU Mat types, but MatBindToCPU() does nothing when called on non-GPU types,
33016e04d98SRichard Tran Mills    * and putting it here makes is more maintainable than duplicating this for all. */
3319566063dSJacob 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));
33248a46eb9SPierre Jolivet   if (flg && B->rmap->n < bind_below) PetscCall(MatBindToCPU(B, PETSC_TRUE));
33316e04d98SRichard Tran Mills 
3345d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
335dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)B, PetscOptionsObject));
336d0609cedSBarry Smith   PetscOptionsEnd();
3373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3387807a1faSBarry Smith }
3397807a1faSBarry Smith 
3405d83a8b1SBarry Smith /*@
34111a5261eSBarry Smith   MatXAIJSetPreallocation - set preallocation for serial and parallel `MATAIJ`, `MATBAIJ`, and `MATSBAIJ` matrices and their unassembled versions.
34263562e91SJed Brown 
343c3339decSBarry Smith   Collective
34463562e91SJed Brown 
3454165533cSJose E. Roman   Input Parameters:
34663562e91SJed Brown + A     - matrix being preallocated
34763562e91SJed Brown . bs    - block size
34841319c1dSStefano Zampini . dnnz  - number of nonzero column blocks per block row of diagonal part of parallel matrix
34941319c1dSStefano Zampini . onnz  - number of nonzero column blocks per block row of off-diagonal part of parallel matrix
35041319c1dSStefano Zampini . dnnzu - number of nonzero column blocks per block row of upper-triangular part of diagonal part of parallel matrix
35141319c1dSStefano Zampini - onnzu - number of nonzero column blocks per block row of upper-triangular part of off-diagonal part of parallel matrix
35263562e91SJed Brown 
35363562e91SJed Brown   Level: beginner
35463562e91SJed Brown 
3551cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`,
3562fe279fdSBarry Smith           `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`,
357db781477SPatrick Sanan           `PetscSplitOwnership()`
35863562e91SJed Brown @*/
359d71ae5a4SJacob Faibussowitsch PetscErrorCode MatXAIJSetPreallocation(Mat A, PetscInt bs, const PetscInt dnnz[], const PetscInt onnz[], const PetscInt dnnzu[], const PetscInt onnzu[])
360d71ae5a4SJacob Faibussowitsch {
36141319c1dSStefano Zampini   PetscInt cbs;
36263562e91SJed Brown   void (*aij)(void);
363e8bd9bafSStefano Zampini   void (*is)(void);
364990279feSStefano Zampini   void (*hyp)(void) = NULL;
36563562e91SJed Brown 
36663562e91SJed Brown   PetscFunctionBegin;
36741319c1dSStefano Zampini   if (bs != PETSC_DECIDE) { /* don't mess with an already set block size */
3689566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(A, bs));
36941319c1dSStefano Zampini   }
3709566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
3719566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
3729566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(A, &bs, &cbs));
37341319c1dSStefano Zampini   /* these routines assumes bs == cbs, this should be checked somehow */
3749566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(A, bs, 0, dnnz));
3759566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(A, bs, 0, dnnz, 0, onnz));
3769566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(A, bs, 0, dnnzu));
3779566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(A, bs, 0, dnnzu, 0, onnzu));
37863562e91SJed Brown   /*
379e8bd9bafSStefano 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
38063562e91SJed Brown     good before going on with it.
38163562e91SJed Brown   */
3829566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIAIJSetPreallocation_C", &aij));
3839566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatISSetPreallocation_C", &is));
384990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3859566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatHYPRESetPreallocation_C", &hyp));
386990279feSStefano Zampini #endif
38748a46eb9SPierre Jolivet   if (!aij && !is && !hyp) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", &aij));
388990279feSStefano Zampini   if (aij || is || hyp) {
38941319c1dSStefano Zampini     if (bs == cbs && bs == 1) {
3909566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz));
3919566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz, 0, onnz));
3929566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz, 0, onnz));
393990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3949566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz, 0, onnz));
395990279feSStefano Zampini #endif
3963e5f4774SJed Brown     } else { /* Convert block-row precallocation to scalar-row */
39763562e91SJed Brown       PetscInt i, m, *sdnnz, *sonnz;
3989566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(A, &m, NULL));
3999566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2((!!dnnz) * m, &sdnnz, (!!onnz) * m, &sonnz));
400dec54756SJed Brown       for (i = 0; i < m; i++) {
40141319c1dSStefano Zampini         if (dnnz) sdnnz[i] = dnnz[i / bs] * cbs;
40241319c1dSStefano Zampini         if (onnz) sonnz[i] = onnz[i / bs] * cbs;
40363562e91SJed Brown       }
4049566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL));
4059566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
4069566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
407990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
4089566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
409990279feSStefano Zampini #endif
4109566063dSJacob Faibussowitsch       PetscCall(PetscFree2(sdnnz, sonnz));
41163562e91SJed Brown     }
41263562e91SJed Brown   }
4133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41463562e91SJed Brown }
41563562e91SJed Brown 
41602218ef1SBarry Smith /*@C
41702218ef1SBarry Smith   MatHeaderMerge - Merges some information from the header of `C` to `A`; the `C` object is then destroyed
418d0f46423SBarry Smith 
41902218ef1SBarry Smith   Collective, No Fortran Support
42002218ef1SBarry Smith 
42102218ef1SBarry Smith   Input Parameters:
42202218ef1SBarry Smith + A - a `Mat` being merged into
42302218ef1SBarry Smith - C - the `Mat` providing the merge information
42402218ef1SBarry Smith 
42502218ef1SBarry Smith   Level: developer
42602218ef1SBarry Smith 
427f2e50d50SStefano Zampini   Notes:
428f2e50d50SStefano Zampini   `A` and `C` must be of the same type.
429f2e50d50SStefano Zampini   The object list and query function list in `A` are retained, as well as the object name, and prefix.
430f2e50d50SStefano Zampini   The object state of `A` is increased by 1.
431f2e50d50SStefano Zampini 
43202218ef1SBarry Smith   Developer Note:
43302218ef1SBarry Smith   This is somewhat different from `MatHeaderReplace()`, it would be nice to merge the code
43402218ef1SBarry Smith 
43502218ef1SBarry Smith .seealso: `Mat`, `MatHeaderReplace()`
43602218ef1SBarry Smith  @*/
437d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHeaderMerge(Mat A, Mat *C)
438d71ae5a4SJacob Faibussowitsch {
439d44834fbSBarry Smith   PetscInt          refct;
44073107ff1SLisandro Dalcin   PetscOps          Abops;
44173107ff1SLisandro Dalcin   struct _MatOps    Aops;
4424768301cSVaclav Hapla   char             *mtype, *mname, *mprefix;
4434222ddf1SHong Zhang   Mat_Product      *product;
44433e6eea4SJose E. Roman   Mat_Redundant    *redundant;
445d4a972cbSStefano Zampini   PetscObjectState  state;
446f2e50d50SStefano Zampini   PetscObjectList   olist;
447f2e50d50SStefano Zampini   PetscFunctionList qlist;
448273d9f13SBarry Smith 
449273d9f13SBarry Smith   PetscFunctionBegin;
4501dc04de0SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4511dc04de0SStefano Zampini   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
4523ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
453f2e50d50SStefano Zampini   PetscCheckSameTypeAndComm(A, 1, *C, 2);
454273d9f13SBarry Smith   /* save the parts of A we need */
45573107ff1SLisandro Dalcin   Abops     = ((PetscObject)A)->bops[0];
45673107ff1SLisandro Dalcin   Aops      = A->ops[0];
4577adad957SLisandro Dalcin   refct     = ((PetscObject)A)->refct;
4585c9eb25fSBarry Smith   mtype     = ((PetscObject)A)->type_name;
4595c9eb25fSBarry Smith   mname     = ((PetscObject)A)->name;
460d4a972cbSStefano Zampini   state     = ((PetscObject)A)->state;
4614768301cSVaclav Hapla   mprefix   = ((PetscObject)A)->prefix;
4624222ddf1SHong Zhang   product   = A->product;
46333e6eea4SJose E. Roman   redundant = A->redundant;
464f2e50d50SStefano Zampini   qlist     = ((PetscObject)A)->qlist;
465f2e50d50SStefano Zampini   olist     = ((PetscObject)A)->olist;
46630735b05SKris Buschelman 
4675c9eb25fSBarry Smith   /* zero these so the destroy below does not free them */
468f4259b30SLisandro Dalcin   ((PetscObject)A)->type_name = NULL;
469f4259b30SLisandro Dalcin   ((PetscObject)A)->name      = NULL;
470f2e50d50SStefano Zampini   ((PetscObject)A)->qlist     = NULL;
471f2e50d50SStefano Zampini   ((PetscObject)A)->olist     = NULL;
4725c9eb25fSBarry Smith 
473dbbe0bcdSBarry Smith   /*
474dbbe0bcdSBarry Smith      free all the interior data structures from mat
475dbbe0bcdSBarry Smith      cannot use PetscUseTypeMethod(A,destroy); because compiler
476dbbe0bcdSBarry Smith      thinks it may print NULL type_name and name
477dbbe0bcdSBarry Smith   */
478dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, destroy);
4797c99f97cSSatish Balay 
4809566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->defaultvectype));
4813faff063SStefano Zampini   PetscCall(PetscFree(A->defaultrandtype));
4829566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->rmap));
4839566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->cmap));
4849566063dSJacob Faibussowitsch   PetscCall(PetscComposedQuantitiesDestroy((PetscObject)A));
485273d9f13SBarry Smith 
486273d9f13SBarry Smith   /* copy C over to A */
48726cc229bSBarry Smith   PetscCall(PetscFree(A->factorprefix));
4889566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
489273d9f13SBarry Smith 
490273d9f13SBarry Smith   /* return the parts of A we saved */
49173107ff1SLisandro Dalcin   ((PetscObject)A)->bops[0]   = Abops;
49273107ff1SLisandro Dalcin   A->ops[0]                   = Aops;
4937adad957SLisandro Dalcin   ((PetscObject)A)->refct     = refct;
4947adad957SLisandro Dalcin   ((PetscObject)A)->type_name = mtype;
4957adad957SLisandro Dalcin   ((PetscObject)A)->name      = mname;
4964768301cSVaclav Hapla   ((PetscObject)A)->prefix    = mprefix;
497d4a972cbSStefano Zampini   ((PetscObject)A)->state     = state + 1;
4984222ddf1SHong Zhang   A->product                  = product;
49933e6eea4SJose E. Roman   A->redundant                = redundant;
500273d9f13SBarry Smith 
501f2e50d50SStefano Zampini   /* Append the saved lists */
502f2e50d50SStefano Zampini   PetscCall(PetscFunctionListDuplicate(qlist, &((PetscObject)A)->qlist));
503f2e50d50SStefano Zampini   PetscCall(PetscObjectListDuplicate(olist, &((PetscObject)A)->olist));
504f2e50d50SStefano Zampini   PetscCall(PetscFunctionListDestroy(&qlist));
505f2e50d50SStefano Zampini   PetscCall(PetscObjectListDestroy(&olist));
506f2e50d50SStefano Zampini 
5075c9eb25fSBarry Smith   /* since these two are copied into A we do not want them destroyed in C */
508f4259b30SLisandro Dalcin   ((PetscObject)*C)->qlist = NULL;
509f4259b30SLisandro Dalcin   ((PetscObject)*C)->olist = NULL;
5109566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(C));
5113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
512273d9f13SBarry Smith }
513d0f46423SBarry Smith 
51402218ef1SBarry Smith /*@
51502218ef1SBarry Smith   MatHeaderReplace - Replaces the internal data of matrix `A` by the internal data of matrix `C` while deleting the outer wrapper of `C`
516eb6b5d47SBarry Smith 
51702218ef1SBarry Smith   Input Parameters:
51802218ef1SBarry Smith + A - a `Mat` whose internal data is to be replaced
51902218ef1SBarry Smith - C - the `Mat` providing new internal data for `A`
520b30237c6SBarry Smith 
52102218ef1SBarry Smith   Level: advanced
52202218ef1SBarry Smith 
52302218ef1SBarry Smith   Example Usage\:
52402218ef1SBarry Smith .vb
52502218ef1SBarry Smith   Mat C;
52602218ef1SBarry Smith   MatCreateSeqAIJWithArrays(..., &C);
52702218ef1SBarry Smith   MatHeaderReplace(A, &C);
52802218ef1SBarry Smith   // C has been destroyed and A contains the matrix entries of C
52902218ef1SBarry Smith .ve
53002218ef1SBarry Smith 
53102218ef1SBarry Smith   Note:
53202218ef1SBarry 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
53302218ef1SBarry 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.
53402218ef1SBarry Smith 
53502218ef1SBarry Smith   Developer Note:
53602218ef1SBarry Smith   This is somewhat different from `MatHeaderMerge()` it would be nice to merge the code
53702218ef1SBarry Smith 
53802218ef1SBarry Smith .seealso: `Mat`, `MatHeaderMerge()`
53902218ef1SBarry Smith  @*/
54002218ef1SBarry Smith PetscErrorCode MatHeaderReplace(Mat A, Mat *C)
541d71ae5a4SJacob Faibussowitsch {
54227b31e29SJed Brown   PetscInt         refct;
543fefd9316SJose E. Roman   PetscObjectState state;
54428be2f97SBarry Smith   struct _p_Mat    buffer;
54581fa06acSBarry Smith   MatStencilInfo   stencil;
5468ab5b326SKris Buschelman 
5478ab5b326SKris Buschelman   PetscFunctionBegin;
54827b31e29SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
54928be2f97SBarry Smith   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
5503ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
55128be2f97SBarry Smith   PetscCheckSameComm(A, 1, *C, 2);
552aed4548fSBarry 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);
5536d7c1e57SBarry Smith 
55428be2f97SBarry Smith   /* swap C and A */
55527b31e29SJed Brown   refct   = ((PetscObject)A)->refct;
556fefd9316SJose E. Roman   state   = ((PetscObject)A)->state;
55781fa06acSBarry Smith   stencil = A->stencil;
5589566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(&buffer, A, sizeof(struct _p_Mat)));
5599566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
5609566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(*C, &buffer, sizeof(struct _p_Mat)));
56127b31e29SJed Brown   ((PetscObject)A)->refct = refct;
562fefd9316SJose E. Roman   ((PetscObject)A)->state = state + 1;
56381fa06acSBarry Smith   A->stencil              = stencil;
56426fbe8dcSKarl Rupp 
565c32d4117SBarry Smith   ((PetscObject)*C)->refct = 1;
5669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(C));
5673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5688ab5b326SKris Buschelman }
569e7e92044SBarry Smith 
570e7e92044SBarry Smith /*@
571b470e4b4SRichard Tran Mills   MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU
572e7e92044SBarry Smith 
5732ef1f0ffSBarry Smith   Logically Collective
5742216c58aSStefano Zampini 
575e7e92044SBarry Smith   Input Parameters:
576e7e92044SBarry Smith + A   - the matrix
57711a5261eSBarry Smith - flg - bind to the CPU if value of `PETSC_TRUE`
578e7e92044SBarry Smith 
57990ea27d8SSatish Balay   Level: intermediate
5802216c58aSStefano Zampini 
5811cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBoundToCPU()`
582e7e92044SBarry Smith @*/
583d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBindToCPU(Mat A, PetscBool flg)
584d71ae5a4SJacob Faibussowitsch {
5857d871021SStefano Zampini   PetscFunctionBegin;
5862ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5872ffa8ee7SStefano Zampini   PetscValidLogicalCollectiveBool(A, flg, 2);
5882216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
5893ba16761SJacob Faibussowitsch   if (A->boundtocpu == flg) PetscFunctionReturn(PETSC_SUCCESS);
590b470e4b4SRichard Tran Mills   A->boundtocpu = flg;
591dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, bindtocpu, flg);
5922216c58aSStefano Zampini #endif
5933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5942216c58aSStefano Zampini }
5952216c58aSStefano Zampini 
5962216c58aSStefano Zampini /*@
5972216c58aSStefano Zampini   MatBoundToCPU - query if a matrix is bound to the CPU
5982216c58aSStefano Zampini 
5992216c58aSStefano Zampini   Input Parameter:
6002216c58aSStefano Zampini . A - the matrix
6012216c58aSStefano Zampini 
6022216c58aSStefano Zampini   Output Parameter:
6032216c58aSStefano Zampini . flg - the logical flag
6042216c58aSStefano Zampini 
6052216c58aSStefano Zampini   Level: intermediate
6062216c58aSStefano Zampini 
6071cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBindToCPU()`
6082216c58aSStefano Zampini @*/
609d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBoundToCPU(Mat A, PetscBool *flg)
610d71ae5a4SJacob Faibussowitsch {
6112ffa8ee7SStefano Zampini   PetscFunctionBegin;
6122ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
6134f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
6142216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
6152216c58aSStefano Zampini   *flg = A->boundtocpu;
6162216c58aSStefano Zampini #else
6172216c58aSStefano Zampini   *flg = PETSC_TRUE;
6187d871021SStefano Zampini #endif
6193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
620e7e92044SBarry Smith }
6217e8381f9SStefano Zampini 
622d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO_Basic(Mat A, const PetscScalar coo_v[], InsertMode imode)
623d71ae5a4SJacob Faibussowitsch {
6247e8381f9SStefano Zampini   IS              is_coo_i, is_coo_j;
6257e8381f9SStefano Zampini   const PetscInt *coo_i, *coo_j;
6267e8381f9SStefano Zampini   PetscInt        n, n_i, n_j;
6277e8381f9SStefano Zampini   PetscScalar     zero = 0.;
6287e8381f9SStefano Zampini 
6297e8381f9SStefano Zampini   PetscFunctionBegin;
6309566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_i", (PetscObject *)&is_coo_i));
6319566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_j", (PetscObject *)&is_coo_j));
63228b400f6SJacob Faibussowitsch   PetscCheck(is_coo_i, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_i IS");
63328b400f6SJacob Faibussowitsch   PetscCheck(is_coo_j, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_j IS");
6349566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_i, &n_i));
6359566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_j, &n_j));
63608401ef6SPierre Jolivet   PetscCheck(n_i == n_j, PETSC_COMM_SELF, PETSC_ERR_COR, "Wrong local size %" PetscInt_FMT " != %" PetscInt_FMT, n_i, n_j);
6379566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_i, &coo_i));
6389566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_j, &coo_j));
63948a46eb9SPierre Jolivet   if (imode != ADD_VALUES) PetscCall(MatZeroEntries(A));
64048a46eb9SPierre 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));
6419566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_i, &coo_i));
6429566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_j, &coo_j));
6433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6447e8381f9SStefano Zampini }
6457e8381f9SStefano Zampini 
6468063e3c8SPierre Jolivet PetscErrorCode MatSetPreallocationCOO_Basic(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
647d71ae5a4SJacob Faibussowitsch {
6487e8381f9SStefano Zampini   Mat         preallocator;
6497e8381f9SStefano Zampini   IS          is_coo_i, is_coo_j;
6507e8381f9SStefano Zampini   PetscScalar zero = 0.0;
6517e8381f9SStefano Zampini 
6527e8381f9SStefano Zampini   PetscFunctionBegin;
653*1690c2aeSBarry Smith   PetscCheck(ncoo <= PETSC_INT_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support", ncoo);
6549566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
6569566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &preallocator));
6579566063dSJacob Faibussowitsch   PetscCall(MatSetType(preallocator, MATPREALLOCATOR));
6589566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(preallocator, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
6599566063dSJacob Faibussowitsch   PetscCall(MatSetLayouts(preallocator, A->rmap, A->cmap));
6609566063dSJacob Faibussowitsch   PetscCall(MatSetUp(preallocator));
66148a46eb9SPierre Jolivet   for (PetscCount n = 0; n < ncoo; n++) PetscCall(MatSetValue(preallocator, coo_i[n], coo_j[n], zero, INSERT_VALUES));
6629566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY));
6639566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY));
6649566063dSJacob Faibussowitsch   PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_TRUE, A));
6659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&preallocator));
6666497c311SBarry Smith   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (PetscInt)ncoo, coo_i, PETSC_COPY_VALUES, &is_coo_i));
6676497c311SBarry Smith   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, (PetscInt)ncoo, coo_j, PETSC_COPY_VALUES, &is_coo_j));
6689566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_i", (PetscObject)is_coo_i));
6699566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_j", (PetscObject)is_coo_j));
6709566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_i));
6719566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_j));
6723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6737e8381f9SStefano Zampini }
6747e8381f9SStefano Zampini 
67556856777SBarry Smith /*@C
676c3dd2894SJed Brown   MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries with global indices
6777e8381f9SStefano Zampini 
678c3339decSBarry Smith   Collective
6797e8381f9SStefano Zampini 
6804165533cSJose E. Roman   Input Parameters:
6817e8381f9SStefano Zampini + A     - matrix being preallocated
68242550becSJunchao Zhang . ncoo  - number of entries
6837e8381f9SStefano Zampini . coo_i - row indices
6847e8381f9SStefano Zampini - coo_j - column indices
6857e8381f9SStefano Zampini 
6867e8381f9SStefano Zampini   Level: beginner
6877e8381f9SStefano Zampini 
688394ed5ebSJunchao Zhang   Notes:
689f13dfd9eSBarry Smith   The indices within `coo_i` and `coo_j` may be modified within this function. The caller should not rely on them
690e8729f6fSJunchao Zhang   having any specific value after this function returns. The arrays can be freed or reused immediately
691e8729f6fSJunchao Zhang   after this function returns.
692e8729f6fSJunchao Zhang 
69311a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
69411a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
695d7547e51SJunchao Zhang   are allowed and will be properly added or inserted to the matrix, unless the matrix option `MAT_IGNORE_OFF_PROC_ENTRIES`
69611a5261eSBarry 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.
6977e8381f9SStefano Zampini 
698d7547e51SJunchao 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
699d7547e51SJunchao Zhang   `MatCreateSeqAIJFromTriple()`. But that is not recommended for iterative applications.
700d7547e51SJunchao Zhang 
7011cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
7022ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOOLocal()`,
7032ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`, `MatCreateSeqAIJFromTriple()`
7047e8381f9SStefano Zampini @*/
705d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
706d71ae5a4SJacob Faibussowitsch {
7078063e3c8SPierre Jolivet   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
7087e8381f9SStefano Zampini 
7097e8381f9SStefano Zampini   PetscFunctionBegin;
7107e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7117e8381f9SStefano Zampini   PetscValidType(A, 1);
7124f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_i, 3);
7134f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_j, 4);
7149566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
7159566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
7169566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOO_C", &f));
717cbc6b225SStefano Zampini 
7189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_PreallCOO, A, 0, 0, 0));
7197e8381f9SStefano Zampini   if (f) {
7209566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
7217e8381f9SStefano Zampini   } else { /* allow fallback, very slow */
7229566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO_Basic(A, ncoo, coo_i, coo_j));
7237e8381f9SStefano Zampini   }
7249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(MAT_PreallCOO, A, 0, 0, 0));
7256834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
726cbc6b225SStefano Zampini   A->nonzerostate++;
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7287e8381f9SStefano Zampini }
7297e8381f9SStefano Zampini 
73056856777SBarry Smith /*@C
731c3dd2894SJed Brown   MatSetPreallocationCOOLocal - set preallocation for matrices using a coordinate format of the entries with local indices
732c3dd2894SJed Brown 
733c3339decSBarry Smith   Collective
734c3dd2894SJed Brown 
735c3dd2894SJed Brown   Input Parameters:
736c3dd2894SJed Brown + A     - matrix being preallocated
737c3dd2894SJed Brown . ncoo  - number of entries
738c3dd2894SJed Brown . coo_i - row indices (local numbering; may be modified)
739c3dd2894SJed Brown - coo_j - column indices (local numbering; may be modified)
740c3dd2894SJed Brown 
741c3dd2894SJed Brown   Level: beginner
742c3dd2894SJed Brown 
743c3dd2894SJed Brown   Notes:
74411a5261eSBarry Smith   The local indices are translated using the local to global mapping, thus `MatSetLocalToGlobalMapping()` must have been
74511a5261eSBarry Smith   called prior to this function. For matrices created with `DMCreateMatrix()` the local to global mapping is often already provided.
746c3dd2894SJed Brown 
7472ef1f0ffSBarry Smith   The indices `coo_i` and `coo_j` may be modified within this function. They might be translated to corresponding global
748735d7f90SBarry Smith   indices, but the caller should not rely on them having any specific value after this function returns. The arrays
749735d7f90SBarry Smith   can be freed or reused immediately after this function returns.
750c3dd2894SJed Brown 
75111a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
75211a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
753394ed5ebSJunchao Zhang   are allowed and will be properly added or inserted to the matrix.
754c3dd2894SJed Brown 
7551cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
7562ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOO()`,
7572ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`
758c3dd2894SJed Brown @*/
759d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOOLocal(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
760d71ae5a4SJacob Faibussowitsch {
7616834774dSStefano Zampini   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
762c3dd2894SJed Brown 
763c3dd2894SJed Brown   PetscFunctionBegin;
764c3dd2894SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
765c3dd2894SJed Brown   PetscValidType(A, 1);
7664f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_i, 3);
7674f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_j, 4);
768*1690c2aeSBarry Smith   PetscCheck(ncoo <= PETSC_INT_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support", ncoo);
7699566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
7709566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
771cbc6b225SStefano Zampini 
7729566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", &f));
7736834774dSStefano Zampini   if (f) {
7749566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
775cbc6b225SStefano Zampini     A->nonzerostate++;
7766834774dSStefano Zampini   } else {
777cbc6b225SStefano Zampini     ISLocalToGlobalMapping ltog_row, ltog_col;
7786497c311SBarry Smith 
7799566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A, &ltog_row, &ltog_col));
7806497c311SBarry Smith     if (ltog_row) PetscCall(ISLocalToGlobalMappingApply(ltog_row, (PetscInt)ncoo, coo_i, coo_i));
7816497c311SBarry Smith     if (ltog_col) PetscCall(ISLocalToGlobalMappingApply(ltog_col, (PetscInt)ncoo, coo_j, coo_j));
7829566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO(A, ncoo, coo_i, coo_j));
7836834774dSStefano Zampini   }
7846834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
7853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
786c3dd2894SJed Brown }
787c3dd2894SJed Brown 
788c3dd2894SJed Brown /*@
78911a5261eSBarry Smith   MatSetValuesCOO - set values at once in a matrix preallocated using `MatSetPreallocationCOO()`
7907e8381f9SStefano Zampini 
791c3339decSBarry Smith   Collective
7927e8381f9SStefano Zampini 
7934165533cSJose E. Roman   Input Parameters:
7947e8381f9SStefano Zampini + A     - matrix being preallocated
7952ef1f0ffSBarry Smith . coo_v - the matrix values (can be `NULL`)
7967e8381f9SStefano Zampini - imode - the insert mode
7977e8381f9SStefano Zampini 
7987e8381f9SStefano Zampini   Level: beginner
7997e8381f9SStefano Zampini 
80011a5261eSBarry Smith   Notes:
80111a5261eSBarry Smith   The values must follow the order of the indices prescribed with `MatSetPreallocationCOO()` or `MatSetPreallocationCOOLocal()`.
80211a5261eSBarry Smith 
8032ef1f0ffSBarry Smith   When repeated entries are specified in the COO indices the `coo_v` values are first properly summed, regardless of the value of imode.
80411a5261eSBarry Smith   The imode flag indicates if coo_v must be added to the current values of the matrix (`ADD_VALUES`) or overwritten (`INSERT_VALUES`).
80511a5261eSBarry Smith 
80611a5261eSBarry Smith   `MatAssemblyBegin()` and `MatAssemblyEnd()` do not need to be called after this routine. It automatically handles the assembly process.
8077e8381f9SStefano Zampini 
8081cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetPreallocationCOO()`, `MatSetPreallocationCOOLocal()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
8097e8381f9SStefano Zampini @*/
810d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode)
811d71ae5a4SJacob Faibussowitsch {
8127e8381f9SStefano Zampini   PetscErrorCode (*f)(Mat, const PetscScalar[], InsertMode) = NULL;
81335cef55dSJunchao Zhang   PetscBool oldFlg;
8147e8381f9SStefano Zampini 
8157e8381f9SStefano Zampini   PetscFunctionBegin;
8167e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8177e8381f9SStefano Zampini   PetscValidType(A, 1);
8187e8381f9SStefano Zampini   MatCheckPreallocated(A, 1);
819bfcc3627SStefano Zampini   PetscValidLogicalCollectiveEnum(A, imode, 3);
8209566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetValuesCOO_C", &f));
8219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_SetVCOO, A, 0, 0, 0));
8227e8381f9SStefano Zampini   if (f) {
82335cef55dSJunchao Zhang     PetscCall((*f)(A, coo_v, imode)); // all known COO implementations do not use MatStash. They do their own off-proc communication
82435cef55dSJunchao Zhang     PetscCall(MatGetOption(A, MAT_NO_OFF_PROC_ENTRIES, &oldFlg));
82535cef55dSJunchao Zhang     PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); // set A->nooffprocentries to avoid costly MatStash scatter in MatAssembly
82635cef55dSJunchao Zhang   } else {
82735cef55dSJunchao Zhang     PetscCall(MatSetValuesCOO_Basic(A, coo_v, imode)); // fall back to MatSetValues, which might use MatStash
8287e8381f9SStefano Zampini   }
8299566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
8309566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
83135cef55dSJunchao Zhang   if (f) PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, oldFlg));
83235cef55dSJunchao Zhang   PetscCall(PetscLogEventEnd(MAT_SetVCOO, A, 0, 0, 0));
8333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8347e8381f9SStefano Zampini }
83565a9ecf2SRichard Tran Mills 
83665a9ecf2SRichard Tran Mills /*@
83765a9ecf2SRichard 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
83865a9ecf2SRichard Tran Mills 
83965a9ecf2SRichard Tran Mills   Input Parameters:
84065a9ecf2SRichard Tran Mills + A   - the matrix
84165a9ecf2SRichard Tran Mills - flg - flag indicating whether the boundtocpu flag should be propagated
84265a9ecf2SRichard Tran Mills 
84365a9ecf2SRichard Tran Mills   Level: developer
84465a9ecf2SRichard Tran Mills 
84565a9ecf2SRichard Tran Mills   Notes:
8462fe279fdSBarry Smith   If the value of flg is set to true, the following will occur
8472fe279fdSBarry Smith +   `MatCreateSubMatrices()` and `MatCreateRedundantMatrix()` - bind created matrices to CPU if the input matrix is bound to the CPU.
8482fe279fdSBarry Smith -   `MatCreateVecs()` - bind created vectors to CPU if the input matrix is bound to the CPU.
84965a9ecf2SRichard Tran Mills 
85065a9ecf2SRichard Tran Mills   The bindingpropagates flag itself is also propagated by the above routines.
85165a9ecf2SRichard Tran Mills 
852fe59aa6dSJacob Faibussowitsch   Developer Notes:
853aa624791SPierre Jolivet   If the fine-scale `DMDA` has the `-dm_bind_below` option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
85465a9ecf2SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
85565a9ecf2SRichard Tran Mills 
8561cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `VecSetBindingPropagates()`, `MatGetBindingPropagates()`
85765a9ecf2SRichard Tran Mills @*/
858d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetBindingPropagates(Mat A, PetscBool flg)
859d71ae5a4SJacob Faibussowitsch {
86065a9ecf2SRichard Tran Mills   PetscFunctionBegin;
86165a9ecf2SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
862d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
86365a9ecf2SRichard Tran Mills   A->bindingpropagates = flg;
86465a9ecf2SRichard Tran Mills #endif
8653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86665a9ecf2SRichard Tran Mills }
867e9c74fd6SRichard Tran Mills 
868e9c74fd6SRichard Tran Mills /*@
869e9c74fd6SRichard 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
870e9c74fd6SRichard Tran Mills 
871e9c74fd6SRichard Tran Mills   Input Parameter:
872e9c74fd6SRichard Tran Mills . A - the matrix
873e9c74fd6SRichard Tran Mills 
874e9c74fd6SRichard Tran Mills   Output Parameter:
875e9c74fd6SRichard Tran Mills . flg - flag indicating whether the boundtocpu flag will be propagated
876e9c74fd6SRichard Tran Mills 
877e9c74fd6SRichard Tran Mills   Level: developer
878e9c74fd6SRichard Tran Mills 
8791cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetBindingPropagates()`
880e9c74fd6SRichard Tran Mills @*/
881d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetBindingPropagates(Mat A, PetscBool *flg)
882d71ae5a4SJacob Faibussowitsch {
883e9c74fd6SRichard Tran Mills   PetscFunctionBegin;
884e9c74fd6SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8854f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
886d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
887e9c74fd6SRichard Tran Mills   *flg = A->bindingpropagates;
888e9c74fd6SRichard Tran Mills #else
889e9c74fd6SRichard Tran Mills   *flg = PETSC_FALSE;
890e9c74fd6SRichard Tran Mills #endif
8913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
892e9c74fd6SRichard Tran Mills }
893