xref: /petsc/src/mat/utils/gcreate.c (revision f13dfd9ea68e0ddeee984e65c377a1819eab8a8a)
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);
10197f1f81fSBarry Smith 
1020298fd71SBarry Smith   *A = NULL;
1039566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
1048ba1e511SMatthew Knepley 
1059566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(B, MAT_CLASSID, "Mat", "Matrix", "Mat", comm, MatDestroy, MatView));
1069566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->rmap));
1079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &B->cmap));
1089566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(VECSTANDARD, &B->defaultvectype));
1093faff063SStefano Zampini   PetscCall(PetscStrallocpy(PETSCRANDER48, &B->defaultrandtype));
11026fbe8dcSKarl Rupp 
111b94d7dedSBarry Smith   B->symmetric                   = PETSC_BOOL3_UNKNOWN;
112b94d7dedSBarry Smith   B->hermitian                   = PETSC_BOOL3_UNKNOWN;
113b94d7dedSBarry Smith   B->structurally_symmetric      = PETSC_BOOL3_UNKNOWN;
114b94d7dedSBarry Smith   B->spd                         = PETSC_BOOL3_UNKNOWN;
115b94d7dedSBarry Smith   B->symmetry_eternal            = PETSC_FALSE;
116b94d7dedSBarry Smith   B->structural_symmetry_eternal = PETSC_FALSE;
117b94d7dedSBarry Smith 
11894342113SStefano Zampini   B->congruentlayouts = PETSC_DECIDE;
119273d9f13SBarry Smith   B->preallocated     = PETSC_FALSE;
1206f3d89d0SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
1216f3d89d0SStefano Zampini   B->boundtocpu = PETSC_TRUE;
1226f3d89d0SStefano Zampini #endif
123273d9f13SBarry Smith   *A = B;
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
125273d9f13SBarry Smith }
126273d9f13SBarry Smith 
12777433607SBarry Smith /*@C
12877433607SBarry Smith   MatCreateFromOptions - Creates a matrix whose type is set from the options database
12977433607SBarry Smith 
13077433607SBarry Smith   Collective
13177433607SBarry Smith 
13277433607SBarry Smith   Input Parameters:
13377433607SBarry Smith + comm   - MPI communicator
13477433607SBarry Smith . prefix - [optional] prefix for the options database
13577433607SBarry Smith . bs     - the blocksize (commonly 1)
13677433607SBarry Smith . m      - the local number of rows (or `PETSC_DECIDE`)
13777433607SBarry Smith . n      - the local number of columns (or `PETSC_DECIDE` or `PETSC_DETERMINE`)
13877433607SBarry Smith . M      - the global number of rows (or `PETSC_DETERMINE`)
13977433607SBarry Smith - N      - the global number of columns (or `PETSC_DETERMINE`)
14077433607SBarry Smith 
14177433607SBarry Smith   Output Parameter:
14277433607SBarry Smith . A - the matrix
14377433607SBarry Smith 
14477433607SBarry Smith   Options Database Key:
14577433607SBarry Smith . -mat_type - see `MatType`, for example `aij`, `aijcusparse`, `baij`, `sbaij`, dense, defaults to `aij`
14677433607SBarry Smith 
14777433607SBarry Smith   Level: beginner
14877433607SBarry Smith 
14977433607SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
15077433607SBarry Smith           `MatCreateSeqDense()`, `MatCreateDense()`,
15177433607SBarry Smith           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
15277433607SBarry Smith           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
15377433607SBarry Smith           `MatConvert()`, `MatCreate()`
15477433607SBarry Smith @*/
15577433607SBarry Smith PetscErrorCode MatCreateFromOptions(MPI_Comm comm, const char *prefix, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, Mat *A)
15677433607SBarry Smith {
15777433607SBarry Smith   PetscFunctionBegin;
15877433607SBarry Smith   PetscAssertPointer(A, 8);
15977433607SBarry Smith   PetscCall(MatCreate(comm, A));
16077433607SBarry Smith   if (prefix) PetscCall(MatSetOptionsPrefix(*A, prefix));
16177433607SBarry Smith   PetscCall(MatSetBlockSize(*A, bs));
16277433607SBarry Smith   PetscCall(MatSetSizes(*A, m, n, M, N));
16377433607SBarry Smith   PetscCall(MatSetFromOptions(*A));
16477433607SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
16577433607SBarry Smith }
16677433607SBarry Smith 
167422a814eSBarry Smith /*@
16811a5261eSBarry Smith   MatSetErrorIfFailure - Causes `Mat` to generate an immediate error, for example a zero pivot, is detected.
169422a814eSBarry Smith 
170c3339decSBarry Smith   Logically Collective
171422a814eSBarry Smith 
172422a814eSBarry Smith   Input Parameters:
17311a5261eSBarry Smith + mat - matrix obtained from `MatCreate()`
17411a5261eSBarry Smith - flg - `PETSC_TRUE` indicates you want the error generated
175422a814eSBarry Smith 
176422a814eSBarry Smith   Level: advanced
177422a814eSBarry Smith 
17811a5261eSBarry Smith   Note:
17911a5261eSBarry Smith   If this flag is not set then the matrix operation will note the error and continue. The error may cause a later `PC` or `KSP` error
18011a5261eSBarry Smith   or result in a `KSPConvergedReason` indicating the method did not converge.
18111a5261eSBarry Smith 
1821cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `PCSetErrorIfFailure()`, `KSPConvergedReason`, `SNESConvergedReason`
183422a814eSBarry Smith @*/
184d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetErrorIfFailure(Mat mat, PetscBool flg)
185d71ae5a4SJacob Faibussowitsch {
186422a814eSBarry Smith   PetscFunctionBegin;
187422a814eSBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
188422a814eSBarry Smith   PetscValidLogicalCollectiveBool(mat, flg, 2);
18984d44b13SHong Zhang   mat->erroriffailure = flg;
1903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
191422a814eSBarry Smith }
192422a814eSBarry Smith 
193f69a0ea3SMatthew Knepley /*@
194f69a0ea3SMatthew Knepley   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
195f69a0ea3SMatthew Knepley 
196c3339decSBarry Smith   Collective
197f69a0ea3SMatthew Knepley 
198f69a0ea3SMatthew Knepley   Input Parameters:
199f69a0ea3SMatthew Knepley + A - the matrix
20011a5261eSBarry Smith . m - number of local rows (or `PETSC_DECIDE`)
20111a5261eSBarry Smith . n - number of local columns (or `PETSC_DECIDE`)
20211a5261eSBarry Smith . M - number of global rows (or `PETSC_DETERMINE`)
20311a5261eSBarry Smith - N - number of global columns (or `PETSC_DETERMINE`)
204f69a0ea3SMatthew Knepley 
2052fe279fdSBarry Smith   Level: beginner
2062fe279fdSBarry Smith 
207f69a0ea3SMatthew Knepley   Notes:
2082ef1f0ffSBarry Smith   `m` (`n`) and `M` (`N`) cannot be both `PETSC_DECIDE`
2092ef1f0ffSBarry Smith   If one processor calls this with `M` (`N`) of `PETSC_DECIDE` then all processors must, otherwise the program will hang.
210f69a0ea3SMatthew Knepley 
21111a5261eSBarry Smith   If `PETSC_DECIDE` is not used for the arguments 'm' and 'n', then the
212f69a0ea3SMatthew Knepley   user must ensure that they are chosen to be compatible with the
213f69a0ea3SMatthew Knepley   vectors. To do this, one first considers the matrix-vector product
2142ef1f0ffSBarry Smith   'y = A x'. The `m` that is used in the above routine must match the
2152ef1f0ffSBarry Smith   local size used in the vector creation routine `VecCreateMPI()` for 'y'.
2162ef1f0ffSBarry Smith   Likewise, the `n` used must match that used as the local size in
21711a5261eSBarry Smith   `VecCreateMPI()` for 'x'.
218f69a0ea3SMatthew Knepley 
219727bdf9bSBarry Smith   If `m` and `n` are not `PETSC_DECIDE`, then the values determine the `PetscLayout` of the matrix and the ranges returned by
220727bdf9bSBarry Smith   `MatGetOwnershipRange()`,  `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, and `MatGetOwnershipRangesColumn()`.
221727bdf9bSBarry Smith 
222f73d5cc4SBarry Smith   You cannot change the sizes once they have been set.
223f73d5cc4SBarry Smith 
22411a5261eSBarry Smith   The sizes must be set before `MatSetUp()` or MatXXXSetPreallocation() is called.
225f73d5cc4SBarry Smith 
226727bdf9bSBarry Smith .seealso: [](ch_matrices), `Mat`, `MatGetSize()`, `PetscSplitOwnership()`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`,
227727bdf9bSBarry Smith           `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, `VecSetSizes()`
228f69a0ea3SMatthew Knepley @*/
229d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
230d71ae5a4SJacob Faibussowitsch {
231f69a0ea3SMatthew Knepley   PetscFunctionBegin;
2320700a824SBarry Smith   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
233a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, M, 4);
234a69c7061SStefano Zampini   PetscValidLogicalCollectiveInt(A, N, 5);
235aed4548fSBarry 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);
236aed4548fSBarry 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);
2379371c9d4SSatish 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,
2389371c9d4SSatish Balay              A->rmap->n, A->rmap->N);
2399371c9d4SSatish 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,
2409371c9d4SSatish Balay              A->cmap->n, A->cmap->N);
241d0f46423SBarry Smith   A->rmap->n = m;
242d0f46423SBarry Smith   A->cmap->n = n;
24359cb773eSBarry Smith   A->rmap->N = M > -1 ? M : A->rmap->N;
24459cb773eSBarry Smith   A->cmap->N = N > -1 ? N : A->cmap->N;
2453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
246f69a0ea3SMatthew Knepley }
247f69a0ea3SMatthew Knepley 
24805869f15SSatish Balay /*@
249273d9f13SBarry Smith   MatSetFromOptions - Creates a matrix where the type is determined
2502920cce0SJacob Faibussowitsch   from the options database.
251273d9f13SBarry Smith 
252c3339decSBarry Smith   Collective
253273d9f13SBarry Smith 
254273d9f13SBarry Smith   Input Parameter:
255fe59aa6dSJacob Faibussowitsch . B - the matrix
256273d9f13SBarry Smith 
257273d9f13SBarry Smith   Options Database Keys:
25811a5261eSBarry Smith + -mat_type seqaij   - `MATSEQAIJ` type, uses `MatCreateSeqAIJ()`
25911a5261eSBarry Smith . -mat_type mpiaij   - `MATMPIAIJ` type, uses `MatCreateAIJ()`
26011a5261eSBarry Smith . -mat_type seqdense - `MATSEQDENSE` type, uses `MatCreateSeqDense()`
26111a5261eSBarry Smith . -mat_type mpidense - `MATMPIDENSE`, uses `MatCreateDense()`
26211a5261eSBarry Smith . -mat_type seqbaij  - `MATSEQBAIJ`, uses `MatCreateSeqBAIJ()`
26311a5261eSBarry Smith - -mat_type mpibaij  - `MATMPIBAIJ`, uses `MatCreateBAIJ()`
264273d9f13SBarry Smith 
2652ef1f0ffSBarry Smith    See the manpages for particular formats (e.g., `MATSEQAIJ`)
266273d9f13SBarry Smith    for additional format-specific options.
267bd9ce289SLois Curfman McInnes 
2681d69843bSLois Curfman McInnes   Level: beginner
2691d69843bSLois Curfman McInnes 
2702920cce0SJacob Faibussowitsch   Notes:
2712920cce0SJacob Faibussowitsch   Generates a parallel MPI matrix if the communicator has more than one processor.  The default
2722920cce0SJacob Faibussowitsch   matrix type is `MATAIJ`, using the routines `MatCreateSeqAIJ()` and `MatCreateAIJ()` if you
2732920cce0SJacob Faibussowitsch   do not select a type in the options database.
2742920cce0SJacob Faibussowitsch 
2751cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSeqAIJ()`, `MatCreateAIJ()`,
276db781477SPatrick Sanan           `MatCreateSeqDense()`, `MatCreateDense()`,
277db781477SPatrick Sanan           `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`,
278db781477SPatrick Sanan           `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`,
279db781477SPatrick Sanan           `MatConvert()`
2807807a1faSBarry Smith @*/
281d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetFromOptions(Mat B)
282d71ae5a4SJacob Faibussowitsch {
283f3be49caSLisandro Dalcin   const char *deft = MATAIJ;
284f3be49caSLisandro Dalcin   char        type[256];
28569df5c0cSJed Brown   PetscBool   flg, set;
28616e04d98SRichard Tran Mills   PetscInt    bind_below = 0;
287dbb450caSBarry Smith 
2883a40ed3dSBarry Smith   PetscFunctionBegin;
2890700a824SBarry Smith   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
290f3be49caSLisandro Dalcin 
291d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)B);
292535b19f3SBarry Smith 
293535b19f3SBarry Smith   if (B->rmap->bs < 0) {
294535b19f3SBarry Smith     PetscInt newbs = -1;
2959566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-mat_block_size", "Set the blocksize used to store the matrix", "MatSetBlockSize", newbs, &newbs, &flg));
296535b19f3SBarry Smith     if (flg) {
2979566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->rmap, newbs));
2989566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetBlockSize(B->cmap, newbs));
299535b19f3SBarry Smith     }
300535b19f3SBarry Smith   }
301535b19f3SBarry Smith 
3029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-mat_type", "Matrix type", "MatSetType", MatList, deft, type, 256, &flg));
303273d9f13SBarry Smith   if (flg) {
3049566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, type));
305f3be49caSLisandro Dalcin   } else if (!((PetscObject)B)->type_name) {
3069566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, deft));
307273d9f13SBarry Smith   }
308f3be49caSLisandro Dalcin 
3099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", &B->checksymmetryonassembly));
3109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-mat_is_symmetric", "Checks if mat is symmetric on MatAssemblyEnd()", "MatIsSymmetric", B->checksymmetrytol, &B->checksymmetrytol, NULL));
3119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_null_space_test", "Checks if provided null space is correct in MatAssemblyEnd()", "MatSetNullSpaceTest", B->checknullspaceonassembly, &B->checknullspaceonassembly, NULL));
3129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_error_if_failure", "Generate an error if an error occurs when factoring the matrix", "MatSetErrorIfFailure", B->erroriffailure, &B->erroriffailure, NULL));
313840d65ccSBarry Smith 
314dbbe0bcdSBarry Smith   PetscTryTypeMethod(B, setfromoptions, PetscOptionsObject);
315f3be49caSLisandro Dalcin 
31669df5c0cSJed Brown   flg = PETSC_FALSE;
3179566063dSJacob 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));
3189566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_LOCATION_ERR, flg));
31969df5c0cSJed Brown   flg = PETSC_FALSE;
3209566063dSJacob 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));
3219566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, flg));
322478db826SMatthew G. Knepley   flg = PETSC_FALSE;
3239566063dSJacob 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));
3249566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_IGNORE_ZERO_ENTRIES, flg));
32569df5c0cSJed Brown 
3261a2c6b5cSJunchao Zhang   flg = PETSC_FALSE;
3279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-mat_form_explicit_transpose", "Hint to form an explicit transpose for operations like MatMultTranspose", "MatSetOption", flg, &flg, &set));
3289566063dSJacob Faibussowitsch   if (set) PetscCall(MatSetOption(B, MAT_FORM_EXPLICIT_TRANSPOSE, flg));
3291a2c6b5cSJunchao Zhang 
33016e04d98SRichard Tran Mills   /* Bind to CPU if below a user-specified size threshold.
33116e04d98SRichard Tran Mills    * This perhaps belongs in the options for the GPU Mat types, but MatBindToCPU() does nothing when called on non-GPU types,
33216e04d98SRichard Tran Mills    * and putting it here makes is more maintainable than duplicating this for all. */
3339566063dSJacob 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));
33448a46eb9SPierre Jolivet   if (flg && B->rmap->n < bind_below) PetscCall(MatBindToCPU(B, PETSC_TRUE));
33516e04d98SRichard Tran Mills 
3365d973c19SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
337dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)B, PetscOptionsObject));
338d0609cedSBarry Smith   PetscOptionsEnd();
3393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3407807a1faSBarry Smith }
3417807a1faSBarry Smith 
342987010e7SBarry Smith /*@C
34311a5261eSBarry Smith   MatXAIJSetPreallocation - set preallocation for serial and parallel `MATAIJ`, `MATBAIJ`, and `MATSBAIJ` matrices and their unassembled versions.
34463562e91SJed Brown 
345c3339decSBarry Smith   Collective
34663562e91SJed Brown 
3474165533cSJose E. Roman   Input Parameters:
34863562e91SJed Brown + A     - matrix being preallocated
34963562e91SJed Brown . bs    - block size
35041319c1dSStefano Zampini . dnnz  - number of nonzero column blocks per block row of diagonal part of parallel matrix
35141319c1dSStefano Zampini . onnz  - number of nonzero column blocks per block row of off-diagonal part of parallel matrix
35241319c1dSStefano Zampini . dnnzu - number of nonzero column blocks per block row of upper-triangular part of diagonal part of parallel matrix
35341319c1dSStefano Zampini - onnzu - number of nonzero column blocks per block row of upper-triangular part of off-diagonal part of parallel matrix
35463562e91SJed Brown 
35563562e91SJed Brown   Level: beginner
35663562e91SJed Brown 
3571cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`,
3582fe279fdSBarry Smith           `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`,
359db781477SPatrick Sanan           `PetscSplitOwnership()`
36063562e91SJed Brown @*/
361d71ae5a4SJacob Faibussowitsch PetscErrorCode MatXAIJSetPreallocation(Mat A, PetscInt bs, const PetscInt dnnz[], const PetscInt onnz[], const PetscInt dnnzu[], const PetscInt onnzu[])
362d71ae5a4SJacob Faibussowitsch {
36341319c1dSStefano Zampini   PetscInt cbs;
36463562e91SJed Brown   void (*aij)(void);
365e8bd9bafSStefano Zampini   void (*is)(void);
366990279feSStefano Zampini   void (*hyp)(void) = NULL;
36763562e91SJed Brown 
36863562e91SJed Brown   PetscFunctionBegin;
36941319c1dSStefano Zampini   if (bs != PETSC_DECIDE) { /* don't mess with an already set block size */
3709566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(A, bs));
37141319c1dSStefano Zampini   }
3729566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
3739566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
3749566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(A, &bs, &cbs));
37541319c1dSStefano Zampini   /* these routines assumes bs == cbs, this should be checked somehow */
3769566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(A, bs, 0, dnnz));
3779566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(A, bs, 0, dnnz, 0, onnz));
3789566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(A, bs, 0, dnnzu));
3799566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(A, bs, 0, dnnzu, 0, onnzu));
38063562e91SJed Brown   /*
381e8bd9bafSStefano 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
38263562e91SJed Brown     good before going on with it.
38363562e91SJed Brown   */
3849566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatMPIAIJSetPreallocation_C", &aij));
3859566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatISSetPreallocation_C", &is));
386990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3879566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatHYPRESetPreallocation_C", &hyp));
388990279feSStefano Zampini #endif
38948a46eb9SPierre Jolivet   if (!aij && !is && !hyp) PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSeqAIJSetPreallocation_C", &aij));
390990279feSStefano Zampini   if (aij || is || hyp) {
39141319c1dSStefano Zampini     if (bs == cbs && bs == 1) {
3929566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz));
3939566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz, 0, onnz));
3949566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz, 0, onnz));
395990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
3969566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz, 0, onnz));
397990279feSStefano Zampini #endif
3983e5f4774SJed Brown     } else { /* Convert block-row precallocation to scalar-row */
39963562e91SJed Brown       PetscInt i, m, *sdnnz, *sonnz;
4009566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(A, &m, NULL));
4019566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2((!!dnnz) * m, &sdnnz, (!!onnz) * m, &sonnz));
402dec54756SJed Brown       for (i = 0; i < m; i++) {
40341319c1dSStefano Zampini         if (dnnz) sdnnz[i] = dnnz[i / bs] * cbs;
40441319c1dSStefano Zampini         if (onnz) sonnz[i] = onnz[i / bs] * cbs;
40563562e91SJed Brown       }
4069566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL));
4079566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
4089566063dSJacob Faibussowitsch       PetscCall(MatISSetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
409990279feSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
4109566063dSJacob Faibussowitsch       PetscCall(MatHYPRESetPreallocation(A, 0, dnnz ? sdnnz : NULL, 0, onnz ? sonnz : NULL));
411990279feSStefano Zampini #endif
4129566063dSJacob Faibussowitsch       PetscCall(PetscFree2(sdnnz, sonnz));
41363562e91SJed Brown     }
41463562e91SJed Brown   }
4153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41663562e91SJed Brown }
41763562e91SJed Brown 
41802218ef1SBarry Smith /*@C
41902218ef1SBarry Smith   MatHeaderMerge - Merges some information from the header of `C` to `A`; the `C` object is then destroyed
420d0f46423SBarry Smith 
42102218ef1SBarry Smith   Collective, No Fortran Support
42202218ef1SBarry Smith 
42302218ef1SBarry Smith   Input Parameters:
42402218ef1SBarry Smith + A - a `Mat` being merged into
42502218ef1SBarry Smith - C - the `Mat` providing the merge information
42602218ef1SBarry Smith 
42702218ef1SBarry Smith   Level: developer
42802218ef1SBarry Smith 
429f2e50d50SStefano Zampini   Notes:
430f2e50d50SStefano Zampini   `A` and `C` must be of the same type.
431f2e50d50SStefano Zampini   The object list and query function list in `A` are retained, as well as the object name, and prefix.
432f2e50d50SStefano Zampini   The object state of `A` is increased by 1.
433f2e50d50SStefano Zampini 
43402218ef1SBarry Smith   Developer Note:
43502218ef1SBarry Smith   This is somewhat different from `MatHeaderReplace()`, it would be nice to merge the code
43602218ef1SBarry Smith 
43702218ef1SBarry Smith .seealso: `Mat`, `MatHeaderReplace()`
43802218ef1SBarry Smith  @*/
439d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHeaderMerge(Mat A, Mat *C)
440d71ae5a4SJacob Faibussowitsch {
441d44834fbSBarry Smith   PetscInt          refct;
44273107ff1SLisandro Dalcin   PetscOps          Abops;
44373107ff1SLisandro Dalcin   struct _MatOps    Aops;
4444768301cSVaclav Hapla   char             *mtype, *mname, *mprefix;
4454222ddf1SHong Zhang   Mat_Product      *product;
44633e6eea4SJose E. Roman   Mat_Redundant    *redundant;
447d4a972cbSStefano Zampini   PetscObjectState  state;
448f2e50d50SStefano Zampini   PetscObjectList   olist;
449f2e50d50SStefano Zampini   PetscFunctionList qlist;
450273d9f13SBarry Smith 
451273d9f13SBarry Smith   PetscFunctionBegin;
4521dc04de0SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4531dc04de0SStefano Zampini   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
4543ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
455f2e50d50SStefano Zampini   PetscCheckSameTypeAndComm(A, 1, *C, 2);
456273d9f13SBarry Smith   /* save the parts of A we need */
45773107ff1SLisandro Dalcin   Abops     = ((PetscObject)A)->bops[0];
45873107ff1SLisandro Dalcin   Aops      = A->ops[0];
4597adad957SLisandro Dalcin   refct     = ((PetscObject)A)->refct;
4605c9eb25fSBarry Smith   mtype     = ((PetscObject)A)->type_name;
4615c9eb25fSBarry Smith   mname     = ((PetscObject)A)->name;
462d4a972cbSStefano Zampini   state     = ((PetscObject)A)->state;
4634768301cSVaclav Hapla   mprefix   = ((PetscObject)A)->prefix;
4644222ddf1SHong Zhang   product   = A->product;
46533e6eea4SJose E. Roman   redundant = A->redundant;
466f2e50d50SStefano Zampini   qlist     = ((PetscObject)A)->qlist;
467f2e50d50SStefano Zampini   olist     = ((PetscObject)A)->olist;
46830735b05SKris Buschelman 
4695c9eb25fSBarry Smith   /* zero these so the destroy below does not free them */
470f4259b30SLisandro Dalcin   ((PetscObject)A)->type_name = NULL;
471f4259b30SLisandro Dalcin   ((PetscObject)A)->name      = NULL;
472f2e50d50SStefano Zampini   ((PetscObject)A)->qlist     = NULL;
473f2e50d50SStefano Zampini   ((PetscObject)A)->olist     = NULL;
4745c9eb25fSBarry Smith 
475dbbe0bcdSBarry Smith   /*
476dbbe0bcdSBarry Smith      free all the interior data structures from mat
477dbbe0bcdSBarry Smith      cannot use PetscUseTypeMethod(A,destroy); because compiler
478dbbe0bcdSBarry Smith      thinks it may print NULL type_name and name
479dbbe0bcdSBarry Smith   */
480dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, destroy);
4817c99f97cSSatish Balay 
4829566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->defaultvectype));
4833faff063SStefano Zampini   PetscCall(PetscFree(A->defaultrandtype));
4849566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->rmap));
4859566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&A->cmap));
4869566063dSJacob Faibussowitsch   PetscCall(PetscComposedQuantitiesDestroy((PetscObject)A));
487273d9f13SBarry Smith 
488273d9f13SBarry Smith   /* copy C over to A */
48926cc229bSBarry Smith   PetscCall(PetscFree(A->factorprefix));
4909566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
491273d9f13SBarry Smith 
492273d9f13SBarry Smith   /* return the parts of A we saved */
49373107ff1SLisandro Dalcin   ((PetscObject)A)->bops[0]   = Abops;
49473107ff1SLisandro Dalcin   A->ops[0]                   = Aops;
4957adad957SLisandro Dalcin   ((PetscObject)A)->refct     = refct;
4967adad957SLisandro Dalcin   ((PetscObject)A)->type_name = mtype;
4977adad957SLisandro Dalcin   ((PetscObject)A)->name      = mname;
4984768301cSVaclav Hapla   ((PetscObject)A)->prefix    = mprefix;
499d4a972cbSStefano Zampini   ((PetscObject)A)->state     = state + 1;
5004222ddf1SHong Zhang   A->product                  = product;
50133e6eea4SJose E. Roman   A->redundant                = redundant;
502273d9f13SBarry Smith 
503f2e50d50SStefano Zampini   /* Append the saved lists */
504f2e50d50SStefano Zampini   PetscCall(PetscFunctionListDuplicate(qlist, &((PetscObject)A)->qlist));
505f2e50d50SStefano Zampini   PetscCall(PetscObjectListDuplicate(olist, &((PetscObject)A)->olist));
506f2e50d50SStefano Zampini   PetscCall(PetscFunctionListDestroy(&qlist));
507f2e50d50SStefano Zampini   PetscCall(PetscObjectListDestroy(&olist));
508f2e50d50SStefano Zampini 
5095c9eb25fSBarry Smith   /* since these two are copied into A we do not want them destroyed in C */
510f4259b30SLisandro Dalcin   ((PetscObject)*C)->qlist = NULL;
511f4259b30SLisandro Dalcin   ((PetscObject)*C)->olist = NULL;
5129566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(C));
5133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
514273d9f13SBarry Smith }
515d0f46423SBarry Smith 
51602218ef1SBarry Smith /*@
51702218ef1SBarry Smith   MatHeaderReplace - Replaces the internal data of matrix `A` by the internal data of matrix `C` while deleting the outer wrapper of `C`
518eb6b5d47SBarry Smith 
51902218ef1SBarry Smith   Input Parameters:
52002218ef1SBarry Smith + A - a `Mat` whose internal data is to be replaced
52102218ef1SBarry Smith - C - the `Mat` providing new internal data for `A`
522b30237c6SBarry Smith 
52302218ef1SBarry Smith   Level: advanced
52402218ef1SBarry Smith 
52502218ef1SBarry Smith   Example Usage\:
52602218ef1SBarry Smith .vb
52702218ef1SBarry Smith   Mat C;
52802218ef1SBarry Smith   MatCreateSeqAIJWithArrays(..., &C);
52902218ef1SBarry Smith   MatHeaderReplace(A, &C);
53002218ef1SBarry Smith   // C has been destroyed and A contains the matrix entries of C
53102218ef1SBarry Smith .ve
53202218ef1SBarry Smith 
53302218ef1SBarry Smith   Note:
53402218ef1SBarry 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
53502218ef1SBarry 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.
53602218ef1SBarry Smith 
53702218ef1SBarry Smith   Developer Note:
53802218ef1SBarry Smith   This is somewhat different from `MatHeaderMerge()` it would be nice to merge the code
53902218ef1SBarry Smith 
54002218ef1SBarry Smith .seealso: `Mat`, `MatHeaderMerge()`
54102218ef1SBarry Smith  @*/
54202218ef1SBarry Smith PetscErrorCode MatHeaderReplace(Mat A, Mat *C)
543d71ae5a4SJacob Faibussowitsch {
54427b31e29SJed Brown   PetscInt         refct;
545fefd9316SJose E. Roman   PetscObjectState state;
54628be2f97SBarry Smith   struct _p_Mat    buffer;
54781fa06acSBarry Smith   MatStencilInfo   stencil;
5488ab5b326SKris Buschelman 
5498ab5b326SKris Buschelman   PetscFunctionBegin;
55027b31e29SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
55128be2f97SBarry Smith   PetscValidHeaderSpecific(*C, MAT_CLASSID, 2);
5523ba16761SJacob Faibussowitsch   if (A == *C) PetscFunctionReturn(PETSC_SUCCESS);
55328be2f97SBarry Smith   PetscCheckSameComm(A, 1, *C, 2);
554aed4548fSBarry 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);
5556d7c1e57SBarry Smith 
55628be2f97SBarry Smith   /* swap C and A */
55727b31e29SJed Brown   refct   = ((PetscObject)A)->refct;
558fefd9316SJose E. Roman   state   = ((PetscObject)A)->state;
55981fa06acSBarry Smith   stencil = A->stencil;
5609566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(&buffer, A, sizeof(struct _p_Mat)));
5619566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(A, *C, sizeof(struct _p_Mat)));
5629566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(*C, &buffer, sizeof(struct _p_Mat)));
56327b31e29SJed Brown   ((PetscObject)A)->refct = refct;
564fefd9316SJose E. Roman   ((PetscObject)A)->state = state + 1;
56581fa06acSBarry Smith   A->stencil              = stencil;
56626fbe8dcSKarl Rupp 
567c32d4117SBarry Smith   ((PetscObject)*C)->refct = 1;
5689566063dSJacob Faibussowitsch   PetscCall(MatDestroy(C));
5693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5708ab5b326SKris Buschelman }
571e7e92044SBarry Smith 
572e7e92044SBarry Smith /*@
573b470e4b4SRichard Tran Mills   MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU
574e7e92044SBarry Smith 
5752ef1f0ffSBarry Smith   Logically Collective
5762216c58aSStefano Zampini 
577e7e92044SBarry Smith   Input Parameters:
578e7e92044SBarry Smith + A   - the matrix
57911a5261eSBarry Smith - flg - bind to the CPU if value of `PETSC_TRUE`
580e7e92044SBarry Smith 
58190ea27d8SSatish Balay   Level: intermediate
5822216c58aSStefano Zampini 
5831cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBoundToCPU()`
584e7e92044SBarry Smith @*/
585d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBindToCPU(Mat A, PetscBool flg)
586d71ae5a4SJacob Faibussowitsch {
5877d871021SStefano Zampini   PetscFunctionBegin;
5882ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5892ffa8ee7SStefano Zampini   PetscValidLogicalCollectiveBool(A, flg, 2);
5902216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
5913ba16761SJacob Faibussowitsch   if (A->boundtocpu == flg) PetscFunctionReturn(PETSC_SUCCESS);
592b470e4b4SRichard Tran Mills   A->boundtocpu = flg;
593dbbe0bcdSBarry Smith   PetscTryTypeMethod(A, bindtocpu, flg);
5942216c58aSStefano Zampini #endif
5953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5962216c58aSStefano Zampini }
5972216c58aSStefano Zampini 
5982216c58aSStefano Zampini /*@
5992216c58aSStefano Zampini   MatBoundToCPU - query if a matrix is bound to the CPU
6002216c58aSStefano Zampini 
6012216c58aSStefano Zampini   Input Parameter:
6022216c58aSStefano Zampini . A - the matrix
6032216c58aSStefano Zampini 
6042216c58aSStefano Zampini   Output Parameter:
6052216c58aSStefano Zampini . flg - the logical flag
6062216c58aSStefano Zampini 
6072216c58aSStefano Zampini   Level: intermediate
6082216c58aSStefano Zampini 
6091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatBindToCPU()`
6102216c58aSStefano Zampini @*/
611d71ae5a4SJacob Faibussowitsch PetscErrorCode MatBoundToCPU(Mat A, PetscBool *flg)
612d71ae5a4SJacob Faibussowitsch {
6132ffa8ee7SStefano Zampini   PetscFunctionBegin;
6142ffa8ee7SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
6154f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
6162216c58aSStefano Zampini #if defined(PETSC_HAVE_DEVICE)
6172216c58aSStefano Zampini   *flg = A->boundtocpu;
6182216c58aSStefano Zampini #else
6192216c58aSStefano Zampini   *flg = PETSC_TRUE;
6207d871021SStefano Zampini #endif
6213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
622e7e92044SBarry Smith }
6237e8381f9SStefano Zampini 
624d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO_Basic(Mat A, const PetscScalar coo_v[], InsertMode imode)
625d71ae5a4SJacob Faibussowitsch {
6267e8381f9SStefano Zampini   IS              is_coo_i, is_coo_j;
6277e8381f9SStefano Zampini   const PetscInt *coo_i, *coo_j;
6287e8381f9SStefano Zampini   PetscInt        n, n_i, n_j;
6297e8381f9SStefano Zampini   PetscScalar     zero = 0.;
6307e8381f9SStefano Zampini 
6317e8381f9SStefano Zampini   PetscFunctionBegin;
6329566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_i", (PetscObject *)&is_coo_i));
6339566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_coo_j", (PetscObject *)&is_coo_j));
63428b400f6SJacob Faibussowitsch   PetscCheck(is_coo_i, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_i IS");
63528b400f6SJacob Faibussowitsch   PetscCheck(is_coo_j, PetscObjectComm((PetscObject)A), PETSC_ERR_COR, "Missing coo_j IS");
6369566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_i, &n_i));
6379566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(is_coo_j, &n_j));
63808401ef6SPierre Jolivet   PetscCheck(n_i == n_j, PETSC_COMM_SELF, PETSC_ERR_COR, "Wrong local size %" PetscInt_FMT " != %" PetscInt_FMT, n_i, n_j);
6399566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_i, &coo_i));
6409566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(is_coo_j, &coo_j));
64148a46eb9SPierre Jolivet   if (imode != ADD_VALUES) PetscCall(MatZeroEntries(A));
64248a46eb9SPierre 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));
6439566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_i, &coo_i));
6449566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(is_coo_j, &coo_j));
6453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6467e8381f9SStefano Zampini }
6477e8381f9SStefano Zampini 
6488063e3c8SPierre Jolivet PetscErrorCode MatSetPreallocationCOO_Basic(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
649d71ae5a4SJacob Faibussowitsch {
6507e8381f9SStefano Zampini   Mat         preallocator;
6517e8381f9SStefano Zampini   IS          is_coo_i, is_coo_j;
6527e8381f9SStefano Zampini   PetscScalar zero = 0.0;
6537e8381f9SStefano Zampini 
6547e8381f9SStefano Zampini   PetscFunctionBegin;
6559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
6569566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
6579566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &preallocator));
6589566063dSJacob Faibussowitsch   PetscCall(MatSetType(preallocator, MATPREALLOCATOR));
6599566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(preallocator, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
6609566063dSJacob Faibussowitsch   PetscCall(MatSetLayouts(preallocator, A->rmap, A->cmap));
6619566063dSJacob Faibussowitsch   PetscCall(MatSetUp(preallocator));
66248a46eb9SPierre Jolivet   for (PetscCount n = 0; n < ncoo; n++) PetscCall(MatSetValue(preallocator, coo_i[n], coo_j[n], zero, INSERT_VALUES));
6639566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY));
6649566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY));
6659566063dSJacob Faibussowitsch   PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_TRUE, A));
6669566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&preallocator));
6672c71b3e2SJacob 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);
6689566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_i, PETSC_COPY_VALUES, &is_coo_i));
6699566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncoo, coo_j, PETSC_COPY_VALUES, &is_coo_j));
6709566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_i", (PetscObject)is_coo_i));
6719566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_coo_j", (PetscObject)is_coo_j));
6729566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_i));
6739566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is_coo_j));
6743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6757e8381f9SStefano Zampini }
6767e8381f9SStefano Zampini 
67756856777SBarry Smith /*@C
678c3dd2894SJed Brown   MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries with global indices
6797e8381f9SStefano Zampini 
680c3339decSBarry Smith   Collective
6817e8381f9SStefano Zampini 
6824165533cSJose E. Roman   Input Parameters:
6837e8381f9SStefano Zampini + A     - matrix being preallocated
68442550becSJunchao Zhang . ncoo  - number of entries
6857e8381f9SStefano Zampini . coo_i - row indices
6867e8381f9SStefano Zampini - coo_j - column indices
6877e8381f9SStefano Zampini 
6887e8381f9SStefano Zampini   Level: beginner
6897e8381f9SStefano Zampini 
690394ed5ebSJunchao Zhang   Notes:
691*f13dfd9eSBarry Smith   The indices within `coo_i` and `coo_j` may be modified within this function. The caller should not rely on them
692e8729f6fSJunchao Zhang   having any specific value after this function returns. The arrays can be freed or reused immediately
693e8729f6fSJunchao Zhang   after this function returns.
694e8729f6fSJunchao Zhang 
69511a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
69611a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
697d7547e51SJunchao Zhang   are allowed and will be properly added or inserted to the matrix, unless the matrix option `MAT_IGNORE_OFF_PROC_ENTRIES`
69811a5261eSBarry 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.
6997e8381f9SStefano Zampini 
700d7547e51SJunchao 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
701d7547e51SJunchao Zhang   `MatCreateSeqAIJFromTriple()`. But that is not recommended for iterative applications.
702d7547e51SJunchao Zhang 
7031cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
7042ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOOLocal()`,
7052ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`, `MatCreateSeqAIJFromTriple()`
7067e8381f9SStefano Zampini @*/
707d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOO(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
708d71ae5a4SJacob Faibussowitsch {
7098063e3c8SPierre Jolivet   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
7107e8381f9SStefano Zampini 
7117e8381f9SStefano Zampini   PetscFunctionBegin;
7127e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7137e8381f9SStefano Zampini   PetscValidType(A, 1);
7144f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_i, 3);
7154f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_j, 4);
7169566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
7179566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
7189566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOO_C", &f));
719cbc6b225SStefano Zampini 
7209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_PreallCOO, A, 0, 0, 0));
7217e8381f9SStefano Zampini   if (f) {
7229566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
7237e8381f9SStefano Zampini   } else { /* allow fallback, very slow */
7249566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO_Basic(A, ncoo, coo_i, coo_j));
7257e8381f9SStefano Zampini   }
7269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(MAT_PreallCOO, A, 0, 0, 0));
7276834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
728cbc6b225SStefano Zampini   A->nonzerostate++;
7293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7307e8381f9SStefano Zampini }
7317e8381f9SStefano Zampini 
73256856777SBarry Smith /*@C
733c3dd2894SJed Brown   MatSetPreallocationCOOLocal - set preallocation for matrices using a coordinate format of the entries with local indices
734c3dd2894SJed Brown 
735c3339decSBarry Smith   Collective
736c3dd2894SJed Brown 
737c3dd2894SJed Brown   Input Parameters:
738c3dd2894SJed Brown + A     - matrix being preallocated
739c3dd2894SJed Brown . ncoo  - number of entries
740c3dd2894SJed Brown . coo_i - row indices (local numbering; may be modified)
741c3dd2894SJed Brown - coo_j - column indices (local numbering; may be modified)
742c3dd2894SJed Brown 
743c3dd2894SJed Brown   Level: beginner
744c3dd2894SJed Brown 
745c3dd2894SJed Brown   Notes:
74611a5261eSBarry Smith   The local indices are translated using the local to global mapping, thus `MatSetLocalToGlobalMapping()` must have been
74711a5261eSBarry Smith   called prior to this function. For matrices created with `DMCreateMatrix()` the local to global mapping is often already provided.
748c3dd2894SJed Brown 
7492ef1f0ffSBarry Smith   The indices `coo_i` and `coo_j` may be modified within this function. They might be translated to corresponding global
750735d7f90SBarry Smith   indices, but the caller should not rely on them having any specific value after this function returns. The arrays
751735d7f90SBarry Smith   can be freed or reused immediately after this function returns.
752c3dd2894SJed Brown 
75311a5261eSBarry Smith   Entries can be repeated, see `MatSetValuesCOO()`. Entries with negative row or column indices are allowed
75411a5261eSBarry Smith   but will be ignored. The corresponding entries in `MatSetValuesCOO()` will be ignored too. Remote entries
755394ed5ebSJunchao Zhang   are allowed and will be properly added or inserted to the matrix.
756c3dd2894SJed Brown 
7571cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`,
7582ef1f0ffSBarry Smith           `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOO()`,
7592ef1f0ffSBarry Smith           `DMSetMatrixPreallocateSkip()`
760c3dd2894SJed Brown @*/
761d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetPreallocationCOOLocal(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
762d71ae5a4SJacob Faibussowitsch {
7636834774dSStefano Zampini   PetscErrorCode (*f)(Mat, PetscCount, PetscInt[], PetscInt[]) = NULL;
764c3dd2894SJed Brown 
765c3dd2894SJed Brown   PetscFunctionBegin;
766c3dd2894SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
767c3dd2894SJed Brown   PetscValidType(A, 1);
7684f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_i, 3);
7694f572ea9SToby Isaac   if (ncoo) PetscAssertPointer(coo_j, 4);
7706834774dSStefano 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);
7719566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
7729566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
773cbc6b225SStefano Zampini 
7749566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", &f));
7756834774dSStefano Zampini   if (f) {
7769566063dSJacob Faibussowitsch     PetscCall((*f)(A, ncoo, coo_i, coo_j));
777cbc6b225SStefano Zampini     A->nonzerostate++;
7786834774dSStefano Zampini   } else {
779cbc6b225SStefano Zampini     ISLocalToGlobalMapping ltog_row, ltog_col;
7809566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A, &ltog_row, &ltog_col));
7819566063dSJacob Faibussowitsch     if (ltog_row) PetscCall(ISLocalToGlobalMappingApply(ltog_row, ncoo, coo_i, coo_i));
7829566063dSJacob Faibussowitsch     if (ltog_col) PetscCall(ISLocalToGlobalMappingApply(ltog_col, ncoo, coo_j, coo_j));
7839566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO(A, ncoo, coo_i, coo_j));
7846834774dSStefano Zampini   }
7856834774dSStefano Zampini   A->preallocated = PETSC_TRUE;
7863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
787c3dd2894SJed Brown }
788c3dd2894SJed Brown 
789c3dd2894SJed Brown /*@
79011a5261eSBarry Smith   MatSetValuesCOO - set values at once in a matrix preallocated using `MatSetPreallocationCOO()`
7917e8381f9SStefano Zampini 
792c3339decSBarry Smith   Collective
7937e8381f9SStefano Zampini 
7944165533cSJose E. Roman   Input Parameters:
7957e8381f9SStefano Zampini + A     - matrix being preallocated
7962ef1f0ffSBarry Smith . coo_v - the matrix values (can be `NULL`)
7977e8381f9SStefano Zampini - imode - the insert mode
7987e8381f9SStefano Zampini 
7997e8381f9SStefano Zampini   Level: beginner
8007e8381f9SStefano Zampini 
80111a5261eSBarry Smith   Notes:
80211a5261eSBarry Smith   The values must follow the order of the indices prescribed with `MatSetPreallocationCOO()` or `MatSetPreallocationCOOLocal()`.
80311a5261eSBarry Smith 
8042ef1f0ffSBarry Smith   When repeated entries are specified in the COO indices the `coo_v` values are first properly summed, regardless of the value of imode.
80511a5261eSBarry Smith   The imode flag indicates if coo_v must be added to the current values of the matrix (`ADD_VALUES`) or overwritten (`INSERT_VALUES`).
80611a5261eSBarry Smith 
80711a5261eSBarry Smith   `MatAssemblyBegin()` and `MatAssemblyEnd()` do not need to be called after this routine. It automatically handles the assembly process.
8087e8381f9SStefano Zampini 
8091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetPreallocationCOO()`, `MatSetPreallocationCOOLocal()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
8107e8381f9SStefano Zampini @*/
811d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode)
812d71ae5a4SJacob Faibussowitsch {
8137e8381f9SStefano Zampini   PetscErrorCode (*f)(Mat, const PetscScalar[], InsertMode) = NULL;
81435cef55dSJunchao Zhang   PetscBool oldFlg;
8157e8381f9SStefano Zampini 
8167e8381f9SStefano Zampini   PetscFunctionBegin;
8177e8381f9SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8187e8381f9SStefano Zampini   PetscValidType(A, 1);
8197e8381f9SStefano Zampini   MatCheckPreallocated(A, 1);
820bfcc3627SStefano Zampini   PetscValidLogicalCollectiveEnum(A, imode, 3);
8219566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatSetValuesCOO_C", &f));
8229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(MAT_SetVCOO, A, 0, 0, 0));
8237e8381f9SStefano Zampini   if (f) {
82435cef55dSJunchao Zhang     PetscCall((*f)(A, coo_v, imode)); // all known COO implementations do not use MatStash. They do their own off-proc communication
82535cef55dSJunchao Zhang     PetscCall(MatGetOption(A, MAT_NO_OFF_PROC_ENTRIES, &oldFlg));
82635cef55dSJunchao Zhang     PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); // set A->nooffprocentries to avoid costly MatStash scatter in MatAssembly
82735cef55dSJunchao Zhang   } else {
82835cef55dSJunchao Zhang     PetscCall(MatSetValuesCOO_Basic(A, coo_v, imode)); // fall back to MatSetValues, which might use MatStash
8297e8381f9SStefano Zampini   }
8309566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
8319566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
83235cef55dSJunchao Zhang   if (f) PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, oldFlg));
83335cef55dSJunchao Zhang   PetscCall(PetscLogEventEnd(MAT_SetVCOO, A, 0, 0, 0));
8343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8357e8381f9SStefano Zampini }
83665a9ecf2SRichard Tran Mills 
83765a9ecf2SRichard Tran Mills /*@
83865a9ecf2SRichard 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
83965a9ecf2SRichard Tran Mills 
84065a9ecf2SRichard Tran Mills   Input Parameters:
84165a9ecf2SRichard Tran Mills + A   - the matrix
84265a9ecf2SRichard Tran Mills - flg - flag indicating whether the boundtocpu flag should be propagated
84365a9ecf2SRichard Tran Mills 
84465a9ecf2SRichard Tran Mills   Level: developer
84565a9ecf2SRichard Tran Mills 
84665a9ecf2SRichard Tran Mills   Notes:
8472fe279fdSBarry Smith   If the value of flg is set to true, the following will occur
8482fe279fdSBarry Smith +   `MatCreateSubMatrices()` and `MatCreateRedundantMatrix()` - bind created matrices to CPU if the input matrix is bound to the CPU.
8492fe279fdSBarry Smith -   `MatCreateVecs()` - bind created vectors to CPU if the input matrix is bound to the CPU.
85065a9ecf2SRichard Tran Mills 
85165a9ecf2SRichard Tran Mills   The bindingpropagates flag itself is also propagated by the above routines.
85265a9ecf2SRichard Tran Mills 
853fe59aa6dSJacob Faibussowitsch   Developer Notes:
854aa624791SPierre Jolivet   If the fine-scale `DMDA` has the `-dm_bind_below` option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
85565a9ecf2SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
85665a9ecf2SRichard Tran Mills 
8571cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `VecSetBindingPropagates()`, `MatGetBindingPropagates()`
85865a9ecf2SRichard Tran Mills @*/
859d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetBindingPropagates(Mat A, PetscBool flg)
860d71ae5a4SJacob Faibussowitsch {
86165a9ecf2SRichard Tran Mills   PetscFunctionBegin;
86265a9ecf2SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
863d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
86465a9ecf2SRichard Tran Mills   A->bindingpropagates = flg;
86565a9ecf2SRichard Tran Mills #endif
8663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86765a9ecf2SRichard Tran Mills }
868e9c74fd6SRichard Tran Mills 
869e9c74fd6SRichard Tran Mills /*@
870e9c74fd6SRichard 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
871e9c74fd6SRichard Tran Mills 
872e9c74fd6SRichard Tran Mills   Input Parameter:
873e9c74fd6SRichard Tran Mills . A - the matrix
874e9c74fd6SRichard Tran Mills 
875e9c74fd6SRichard Tran Mills   Output Parameter:
876e9c74fd6SRichard Tran Mills . flg - flag indicating whether the boundtocpu flag will be propagated
877e9c74fd6SRichard Tran Mills 
878e9c74fd6SRichard Tran Mills   Level: developer
879e9c74fd6SRichard Tran Mills 
8801cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatSetBindingPropagates()`
881e9c74fd6SRichard Tran Mills @*/
882d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetBindingPropagates(Mat A, PetscBool *flg)
883d71ae5a4SJacob Faibussowitsch {
884e9c74fd6SRichard Tran Mills   PetscFunctionBegin;
885e9c74fd6SRichard Tran Mills   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8864f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
887d5e393b6SSuyash Tandon #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
888e9c74fd6SRichard Tran Mills   *flg = A->bindingpropagates;
889e9c74fd6SRichard Tran Mills #else
890e9c74fd6SRichard Tran Mills   *flg = PETSC_FALSE;
891e9c74fd6SRichard Tran Mills #endif
8923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
893e9c74fd6SRichard Tran Mills }
894